作者:微信小助手
<h1 data-track="2" style="box-sizing: border-box;font-size: 1.056em;margin: 20px 0px;padding: 0px;font-weight: 700;border: 0px;line-height: 1.579;color: rgb(0, 0, 0);font-family: " pingfang sc, hiragino sans gb, microsoft yahei, wenquanyi micro hei, helvetica neue, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial; data-pm-slice="0 0 []"><span leaf="">了解ReRank模型前先回顾一下RAG的流程</span></h1> <h1 data-track="2" style="box-sizing: border-box;font-size: 1.056em;margin: 20px 0px;padding: 0px;font-weight: 700;border: 0px;line-height: 1.579;color: rgb(0, 0, 0);font-family: " pingfang sc, hiragino sans gb, microsoft yahei, wenquanyi micro hei, helvetica neue, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial; data-pm-slice="0 0 []"><span leaf=""><img src="/upload/d47a84c048271ead6f70f7d5e5f5b49f.png" alt="在这里插入图片描述" class="rich_pages wxw-img" data-ratio="0.6324074074074074" data-type="png" data-w="1080" data-imgfileid="100001567"></span></h1> <h1 data-track="2" style="box-sizing: border-box;font-size: 1.056em;margin: 20px 0px;padding: 0px;font-weight: 700;border: 0px;line-height: 1.579;color: rgb(0, 0, 0);font-family: " pingfang sc, hiragino sans gb, microsoft yahei, wenquanyi micro hei, helvetica neue, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial; data-pm-slice="0 0 []"><span leaf=""><span textstyle="" style="font-size: 18px;">什么是Rerank模型?</span></span></h1> <p data-track="3" style="box-sizing: border-box;margin: 20px 0px;padding: 0px;border: 0px;color: rgb(34, 34, 34);font-family: " pingfang sc, hiragino sans gb, microsoft yahei, wenquanyi micro hei, helvetica neue, arial, sans-serif;font-size: 18px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(51, 51, 51);"><span leaf=""><span textstyle="" style="font-size: 18px;"> Rerank模型是一种用于优化信息检索结果排序的机器学习模型,通过精细化评估文档与查询的相关性,提升最终结果的准确性和语义匹配度。以下是其核心要点:</span></span></span></p> <section> <strong style="box-sizing: border-box;font-weight: 700;margin: 0px;padding: 0px;border: 0px;"><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(51, 51, 51);"><span leaf=""><span textstyle="" style="font-size: 18px;">定义与定位</span></span></span></strong><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(51, 51, 51);"><span leaf=""><br></span></span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(51, 51, 51);"><span leaf=""><br></span></span> </section> <section> <span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(51, 51, 51);"><span leaf=""><span textstyle="" style="font-size: 18px;"> 属于重排序算法,作用于初步检索(如关键词匹配或向量相似度检索)之后,对候选文档进行二次筛选和排序。</span></span></span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(51, 51, 51);"><span leaf=""><span textstyle="" style="font-size: 18px;">在RAG(检索增强生成)流程中,与Embedding模型配合使用,形成“粗筛+精排”的协同机制。</span></span></span> </section> <section> <strong style="box-sizing: border-box;font-weight: 700;margin: 0px;padding: 0px;border: 0px;"><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(51, 51, 51);"><span leaf=""><span textstyle="" style="font-size: 18px;">核心作用</span></span></span></strong> </section> <ul style="list-style-type: disc;" class="list-paddingleft-1"> <li> <section> <span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(51, 51, 51);"><span leaf="" data-pm-slice="1 1 [" para,null,node,{tagname:span,attributes:{style:box-sizing: border-box; margin: 0px; padding: border: color: rgb(51, 51, 51); --tt-darkmode-color: #a3a3a3;},namespaceuri:http: www.w3.org 1999 xhtml}]><span textstyle="" style="font-size: 18px;font-weight: bold;">解决初步检索的局限性</span></span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(51, 51, 51);"><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(51, 51, 51);"><span leaf=""><span textstyle="" style="font-size: 18px;font-weight: bold;">:</span><span textstyle="" style="font-size: 18px;">弥补传统检索方法(如倒排索引或Embedding相似度计算)在语义理解深度上的不足。</span></span></span></span></span> </section></li> <li> <section> <span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(51, 51, 51);"><span leaf="" data-pm-slice="1 1 [" para,null,node,{tagname:span,attributes:{style:box-sizing: border-box; margin: 0px; padding: border: color: rgb(51, 51, 51); --tt-darkmode-color: #a3a3a3;},namespaceuri:http: www.w3.org 1999 xhtml}]><span textstyle="" style="font-size: 18px;font-weight: bold;">提升结果质量</span></span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(51, 51, 51);"><span leaf=""><span textstyle="" style="font-size: 18px;font-weight: bold;">:</span><span textstyle="" style="font-size: 18px;">通过多维度评估(如语义一致性、上下文关联性)对文档重新打分,确保高相关性的内容优先展示。</span></span></span></span> </section> <section> <span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(51, 51, 51);"><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(51, 51, 51);"><span leaf=""><br></span></span></span> </section></li> </ul> <section> <strong style="box-sizing: border-box;font-weight: 700;margin: 0px;padding: 0px;border: 0px;"><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(51, 51, 51);"><span leaf=""><span textstyle="" style="font-size: 18px;">工作原理</span></span></span></strong> </section> <ul style="list-style-type: disc;" class="list-paddingleft-1"> <li> <section> <span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(51, 51, 51);"><span leaf="" data-pm-slice="1 1 [" para,null,node,{tagname:span,attributes:{style:box-sizing: border-box; margin: 0px; padding: border: color: rgb(51, 51, 51); --tt-darkmode-color: #a3a3a3;},namespaceuri:http: www.w3.org 1999 xhtml}]><span textstyle="" style="font-size: 18px;font-weight: bold;">监督学习训练</span></span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(51, 51, 51);"><span leaf=""><span textstyle="" style="font-size: 18px;font-weight: bold;">:</span><span textstyle="" style="font-size: 18px;">基于大量正确与不正确的查询-文档对,模型学习最大化正确对的分数、最小化错误对的分数。</span></span></span></span> </section></li> <li> <section> <span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(51, 51, 51);"><span leaf="" data-pm-slice="1 1 [" para,null,node,{tagname:span,attributes:{style:box-sizing: border-box; margin: 0px; padding: border: color: rgb(51, 51, 51); --tt-darkmode-color: #a3a3a3;},namespaceuri:http: www.w3.org 1999 xhtml}]><span textstyle="" style="font-size: 18px;font-weight: bold;">相关性评分</span></span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(51, 51, 51);"><span leaf=""><span textstyle="" style="font-size: 18px;font-weight: bold;">:</span><span textstyle="" style="font-size: 18px;">输入查询和文档,直接输出两者的匹配分数,并依此排序。</span></span></span></span> </section> <section> <span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(51, 51, 51);"><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(51, 51, 51);"><span leaf=""><br></span></span></span> </section></li> </ul> <section> <strong style="box-sizing: border-box;font-weight: 700;margin: 0px;padding: 0px;border: 0px;"><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(51, 51, 51);"><span leaf=""><span textstyle="" style="font-size: 18px;">典型应用场景</span></span></span></strong> </section> <ul style="list-style-type: disc;" class="list-paddingleft-1"> <li> <section> <strong style="box-sizing: border-box;font-weight: 700;margin: 0px;padding: 0px;border: 0px;"><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(51, 51, 51);"><span leaf=""><span textstyle="" style="font-size: 18px;">RAG系统</span></span></span></strong><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(51, 51, 51);"><span leaf=""><span textstyle="" style="font-size: 18px;">:优化检索文档的排序,提升大模型生成回答的准确性。</span></span></span> </section></li> <li> <section> <span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(51, 51, 51);"><span leaf=""><span textstyle="" style="font-size: 18px;font-weight: bold;">搜索引擎/推荐系统</span></span></span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(51, 51, 51);"><span leaf=""><span textstyle="" style="font-size: 18px;font-weight: bold;">:</span><span textstyle="" style="font-size: 18px;">精细化调整结果顺序,增强用户满意度。</span></span></span> </section></li> </ul> <h1 data-track="279" style="box-sizing: border-box;font-size: 1.056em;margin: 20px 0px;padding: 0px;font-weight: 700;border: 0px;line-height: 1.579;color: rgb(0, 0, 0);font-family: " pingfang sc, hiragino sans gb, microsoft yahei, wenquanyi micro hei, helvetica neue, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial; data-pm-slice="0 0 []"><span leaf="">排序的关键维度</span></h1> <h1 data-track="280" style="box-sizing: border-box;font-size: 1.056em;margin: 20px 0px;padding: 0px;font-weight: 700;border: 0px;line-height: 1.579;color: rgb(0, 0, 0);font-family: " pingfang sc, hiragino sans gb, microsoft yahei, wenquanyi micro hei, helvetica neue, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial; data-pm-slice="0 0 []"><span leaf="">语义相关性</span></h1> <pre style="box-sizing: border-box;font-family: Monaco;font-size: 18px;margin: 20px 0px;padding: 15px;border: 0px;background: rgb(250, 250, 250);white-space: pre-wrap;word-break: break-all;display: block;overflow-x: auto;border-radius: 3px;text-align: left;color: rgb(34, 34, 34);box-shadow: rgba(216, 216, 216, 0.5) 0px 0px 0px 1px inset;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><code style="white-space:pre-wrap;box-sizing: border-box;font-family: inherit;font-size: 14px;margin: 0px;padding: 0px;border: 0px;overflow-wrap: normal;word-break: normal;overflow-x: auto;line-height: 24px;"><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(0, 117, 59);"><span leaf="">#</span></span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;"><span leaf=""> 用户问题:</span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(0, 117, 59);"><span leaf="">"糖尿病患者的饮食禁忌有哪些?"</span></span></span><span leaf=""><br></span><span leaf="">候选文档1:详细列举12种糖尿病饮食禁忌(相关度高)</span><span leaf=""><br></span><span leaf="">候选文档2:讲解胰岛素注射方法(相关度低)</span></code></pre> <h1 data-track="282" style="box-sizing: border-box;font-size: 1.056em;margin: 20px 0px;padding: 0px;font-weight: 700;border: 0px;line-height: 1.579;color: rgb(0, 0, 0);font-family: " pingfang sc, hiragino sans gb, microsoft yahei, wenquanyi micro hei, helvetica neue, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial; data-pm-slice="0 0 []"><span leaf="">时效性权重</span></h1> <pre style="box-sizing: border-box;font-family: Monaco;font-size: 18px;margin: 20px 0px;padding: 15px;border: 0px;background: rgb(250, 250, 250);white-space: pre-wrap;word-break: break-all;display: block;overflow-x: auto;border-radius: 3px;text-align: left;color: rgb(34, 34, 34);box-shadow: rgba(216, 216, 216, 0.5) 0px 0px 0px 1px inset;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><code style="white-space:pre-wrap;box-sizing: border-box;font-family: inherit;font-size: 14px;margin: 0px;padding: 0px;border: 0px;overflow-wrap: normal;word-break: normal;overflow-x: auto;line-height: 24px;"><span leaf="">文档A:2023年《中国糖尿病防治指南》(权重+20%)</span><span leaf=""><br></span><span leaf="">文档B:2010年某医院内部资料(权重-30%)</span></code></pre> <h1 data-track="286" style="box-sizing: border-box;font-size: 1.056em;margin: 20px 0px;padding: 0px;font-weight: 700;border: 0px;line-height: 1.579;color: rgb(0, 0, 0);font-family: " pingfang sc, hiragino sans gb, microsoft yahei, wenquanyi micro hei, helvetica neue, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial; data-pm-slice="0 0 []"><span leaf="">多样性控制</span></h1> <pre style="box-sizing: border-box;font-family: Monaco;font-size: 18px;margin: 20px 0px;padding: 15px;border: 0px;background: rgb(250, 250, 250);white-space: pre-wrap;word-break: break-all;display: block;overflow-x: auto;border-radius: 3px;text-align: left;color: rgb(34, 34, 34);box-shadow: rgba(216, 216, 216, 0.5) 0px 0px 0px 1px inset;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><code style="white-space:pre-wrap;box-sizing: border-box;font-family: inherit;font-size: 14px;margin: 0px;padding: 0px;border: 0px;overflow-wrap: normal;word-break: normal;overflow-x: auto;line-height: 24px;"><span leaf="">避免返回3篇都讲</span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(0, 117, 59);"><span leaf="">"糖分控制"</span></span><span leaf="">的文章</span><span leaf=""><br></span><span leaf="">保留1篇</span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(0, 117, 59);"><span leaf="">"运动管理"</span></span><span leaf="">的补充内容</span></code></pre> <h1 data-track="119" style="box-sizing: border-box;font-size: 1.056em;margin: 20px 0px;padding: 0px;font-weight: 700;border: 0px;line-height: 1.579;color: rgb(0, 0, 0);font-family: " pingfang sc, hiragino sans gb, microsoft yahei, wenquanyi micro hei, helvetica neue, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial; data-pm-slice="0 0 []"><span leaf="">排序面临的挑战</span></h1> <section> <span leaf=""><img src="/upload/8577432d63a64c2377780254be5599e7.jpg" class="rich_pages wxw-img" data-ratio="0.8481481481481481" data-type="jpeg" data-w="1080" data-imgfileid="100001565"></span> </section> <p><span leaf=""><span textstyle="" style="font-size: 18px;font-weight: bold;">长尾问题</span></span></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang=""><code><span leaf="">用户提问:“如何训练导盲犬AI机器人?” </span></code><code><span leaf="">检索结果: 前10篇:通用机器人训练方法(未命中) </span></code><code><span leaf=""> 仅1篇:《基于多模态感知的导盲犬机器人训练指南》(命中但排名靠后)</span></code></pre> </section> <p><span leaf=""><span textstyle="" style="font-size: 18px;font-weight: bold;">解决策略:</span></span></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="javascript"><code><span leaf="">数据增强:合成<span class="code-snippet__string">"导盲犬+机器人"</span>的伪数据微调模型</span></code><code><span leaf="">混合检索:结合关键词(“导盲犬”+“<span class="code-snippet__variable">AI</span>”)与语义检索</span></code><code><span leaf="">主动学习:标注低置信度结果,迭代优化模型</span></code></pre> </section> <h1 data-track="290" style="box-sizing: border-box;font-size: 1.056em;margin: 20px 0px;padding: 0px;font-weight: 700;border: 0px;line-height: 1.579;color: rgb(0, 0, 0);font-family: " pingfang sc, hiragino sans gb, microsoft yahei, wenquanyi micro hei, helvetica neue, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial; data-pm-slice="0 0 []"><span leaf="">语义鸿沟</span></h1> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="makefile"><code><span leaf=""><span class="code-snippet__section">用户问:“手机发热严重怎么降温?</span></span></code><code><span leaf="">检索结果:《移动设备SoC功耗管理与散热优化方案》(语义相关)</span></code><code><span leaf=""> 《智能手机电池保养技巧》(字面相关但非核心)</span></code></pre> </section> <h1 data-track="290" style="box-sizing: border-box;font-size: 1.056em;margin: 20px 0px;padding: 0px;font-weight: 700;border: 0px;line-height: 1.579;color: rgb(0, 0, 0);font-family: " pingfang sc, hiragino sans gb, microsoft yahei, wenquanyi micro hei, helvetica neue, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial; data-pm-slice="0 0 []"><span leaf=""><span textstyle="" style="font-size: 18px;font-weight: bold;">解决策略:</span></span></h1> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="javascript"><code><span leaf=""><span class="code-snippet__number">1.</span> 查询扩展:用<span class="code-snippet__variable">LLM</span>生成同义表述(如<span class="code-snippet__string">"发热"</span>→<span class="code-snippet__string">"散热"</span>、“降温<span class="code-snippet__string">"→"</span>温度控制”) </span></code><code><span leaf=""><span class="code-snippet__number">2.</span> 上下文增强:提取文档中<span class="code-snippet__string">"发热"</span>相关段落提升权重 </span></code><code><span leaf=""><span class="code-snippet__number">3.</span> 用户反馈:记录用户最终点击的文档,反向优化模型</span></code></pre> </section> <section> <span data-lark-record-data="{" rootid:mqlddkkfaoarumxq5ljcpyi6nuf,text:{initialattributedtexts:{text:{0:文档标题: ◦ 《移动设备soc功耗管理与散热优化方案》(语义相关) 《智能手机电池保养技巧》(字面相关但非核心)},attribs:{0:*0+1n}},apool:{numtoattrib:{0:[author,7480500817733943298]},nextnum:1}},type:text,referencerecordmap:{},extra:{channel:saas,isequalblockselection:false,pasterandomid:ff8946af-a32f-44e1-8702-5831e87eca76,mention_page_title:{},external_mention_url:{}},iskeepquotecontainer:false,isfromcode:false,selection:[{id:69,type:text,selection:{start:477,end:536},recordid:rddldkhonovtizxkww7cmlhunvh}],payloadmap:{lingoclipboardpayload:{spacesubextrainfo:[{spacesubid:rddldkhonovtizxkww7cmlhunvh,word:soc}],spaceid:mqlddkkfaoarumxq5ljcpyi6nuf,spacetype:1}},iscut:false} data-lark-record-format="docx/text"></span> </section> <h1 data-track="292" style="box-sizing: border-box;font-size: 1.056em;margin: 20px 0px;padding: 0px;font-weight: 700;border: 0px;line-height: 1.579;color: rgb(0, 0, 0);font-family: " pingfang sc, hiragino sans gb, microsoft yahei, wenquanyi micro hei, helvetica neue, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial; data-pm-slice="0 0 []"><span leaf="">多语言混合</span></h1> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang=""><code><span leaf="">中文提问:“量子纠缠的实际应用有哪些?</span></code><code><span leaf="">检索结果: 中文文档:《里子通信技术白皮书》(匹配度一般)</span></code><code><span leaf=""> 英文论文:《Quantum Entanglement inCommercial Systems》(Nature 2023,高相关)</span></code></pre> </section> <p data-pm-slice="0 0 []"><span leaf="" data-pm-slice="1 1 [" para,{tagname:p,attributes:{data-pm-slice:0 0 []},namespaceuri:http: www.w3.org 1999 xhtml}]><span textstyle="" style="font-size: 18px;font-weight: bold;">解决策略:</span></span></p> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="markdown"><code><span leaf=""><span class="code-snippet__bullet">1.</span> 实时翻译对齐:将英文论文摘要翻译后参与排序 </span></code><code><span leaf=""><span class="code-snippet__bullet">2.</span> 跨语言模型:使用mBERT等模型直接计算中英文相似度 </span></code><code><span leaf=""><span class="code-snippet__bullet">3.</span> 多语言标签:为文档添加语言/领域元数据辅助过滤</span></code></pre> </section> <section> <span data-lark-record-data="{" rootid:mqlddkkfaoarumxq5ljcpyi6nuf,text:{initialattributedtexts:{text:{0: 知识库内容: ◦ 中文文档:《量子通信技术白皮书》(匹配度一般) 英文论文:《quantum entanglement in commercial systems》(nature 2023, 高相关)},attribs:{0:*0+2v}},apool:{numtoattrib:{0:[author,7480500817733943298]},nextnum:1}},type:text,referencerecordmap:{},extra:{channel:saas,isequalblockselection:false,pasterandomid:d6132f08-ab71-4830-b5f9-0d88539e73b9,mention_page_title:{},external_mention_url:{}},iskeepquotecontainer:false,isfromcode:false,selection:[{id:69,type:text,selection:{start:676,end:779},recordid:rddldkhonovtizxkww7cmlhunvh}],payloadmap:{},iscut:false} data-lark-record-format="docx/text"></span> </section> <h1 data-track="294" style="box-sizing: border-box;font-size: 1.056em;margin: 20px 0px;padding: 0px;font-weight: 700;border: 0px;line-height: 1.579;color: rgb(0, 0, 0);font-family: " pingfang sc, hiragino sans gb, microsoft yahei, wenquanyi micro hei, helvetica neue, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial; data-pm-slice="0 0 []"><span leaf="">计算效率</span></h1> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="javascript"><code><span leaf="">数据规模:<span class="code-snippet__number">100</span>万篇医疗文献库</span></code><code><span leaf="">查询需求:实时返回<span class="code-snippet__string">"阿尔茨海默症新药研发进展"</span><span class="code-snippet__title">Top5</span>结果(<500ms)</span></code></pre> </section> <h1 data-track="294" style="box-sizing: border-box;font-size: 1.056em;margin: 20px 0px;padding: 0px;font-weight: 700;border: 0px;line-height: 1.579;color: rgb(0, 0, 0);font-family: " pingfang sc, hiragino sans gb, microsoft yahei, wenquanyi micro hei, helvetica neue, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial; data-pm-slice="0 0 []"><span leaf="" data-pm-slice="1 1 [" para,{tagname:p,attributes:{data-pm-slice:0 0 []},namespaceuri:http: www.w3.org 1999 xhtml}]><span textstyle="" style="font-size: 18px;font-weight: bold;">解决策略:</span></span></h1> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="markdown"><code><span leaf=""><span class="code-snippet__bullet">1.</span> 两阶段排序: </span></code><code><span leaf=""> 第一阶段:BM25快速筛选1000篇(耗时50ms) </span></code><code><span leaf=""> 第二阶段:Reranker精排Top100(耗时400ms) </span></code><code><span leaf=""><span class="code-snippet__bullet">2.</span> 模型蒸馏:将BERT-large蒸馏为Tiny版,速度提升5倍 </span></code><code><span leaf=""><span class="code-snippet__bullet">3.</span> 硬件加速:使用TensorRT部署模型,GPU推理吞吐量提升10倍</span></code></pre> </section> <section> <span data-lark-record-data="{" rootid:mqlddkkfaoarumxq5ljcpyi6nuf,text:{initialattributedtexts:{text:{0:数据规模:100万篇医疗文献库 • 查询需求:实时返回\阿尔茨海默症新药研发进展\top5结果(<500ms)},attribs:{0:*0+1j}},apool:{numtoattrib:{0:[author,7480500817733943298]},nextnum:1}},type:text,referencerecordmap:{},extra:{channel:saas,isequalblockselection:false,pasterandomid:632f18ae-3ccb-4633-b8dd-75d5b07a7de9,mention_page_title:{},external_mention_url:{}},iskeepquotecontainer:false,isfromcode:false,selection:[{id:69,type:text,selection:{start:881,end:936},recordid:rddldkhonovtizxkww7cmlhunvh}],payloadmap:{lingoclipboardpayload:{spacesubextrainfo:[{spacesubid:rddldkhonovtizxkww7cmlhunvh,word:ms}],spaceid:mqlddkkfaoarumxq5ljcpyi6nuf,spacetype:1}},iscut:false} data-lark-record-format="docx/text"></span> </section> <h1 data-track="119" style="box-sizing: border-box;font-size: 1.056em;margin: 20px 0px;padding: 0px;font-weight: 700;border: 0px;line-height: 1.579;color: rgb(0, 0, 0);font-family: " pingfang sc, hiragino sans gb, microsoft yahei, wenquanyi micro hei, helvetica neue, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial; data-pm-slice="0 0 []"><span leaf="">主流模型选型</span></h1> <table style="box-sizing: border-box;margin: 0px auto;padding: 0px;border-collapse: collapse;border-spacing: 0px;border: 0px;table-layout: fixed;word-break: normal;color: rgb(34, 34, 34);min-width: 168px;"> <tbody> <tr style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;"> <td style="box-sizing: border-box;margin: 0px;padding: 8px 12px;border: 1px solid rgb(232, 232, 232);vertical-align: top;font-weight: 400;text-align: left;font-size: 16px;line-height: 28px;min-height: 44px;"><p data-track="120" style="box-sizing: border-box;margin-top: 0px !important;margin-right: 0px;margin-bottom: 0px !important;margin-left: 0px;padding: 0px;border: 0px;"><span leaf="">模型</span></p></td> <td style="box-sizing: border-box;margin: 0px;padding: 8px 12px;border: 1px solid rgb(232, 232, 232);vertical-align: top;font-weight: 400;text-align: left;font-size: 16px;line-height: 28px;min-height: 44px;"><p data-track="121" style="box-sizing: border-box;margin-top: 0px !important;margin-right: 0px;margin-bottom: 0px !important;margin-left: 0px;padding: 0px;border: 0px;"><span leaf="">特点</span></p></td> <td style="box-sizing: border-box;margin: 0px;padding: 8px 12px;border: 1px solid rgb(232, 232, 232);vertical-align: top;font-weight: 400;text-align: left;font-size: 16px;line-height: 28px;min-height: 44px;"><p data-track="122" style="box-sizing: border-box;margin-top: 0px !important;margin-right: 0px;margin-bottom: 0px !important;margin-left: 0px;padding: 0px;border: 0px;"><span leaf="">性能优势</span></p></td> </tr> <tr style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;"> <td style="box-sizing: border-box;margin: 0px;padding: 8px 12px;border: 1px solid rgb(232, 232, 232);vertical-align: top;font-weight: 400;text-align: left;font-size: 16px;line-height: 28px;min-height: 44px;"><p data-track="123" style="box-sizing: border-box;margin-top: 0px !important;margin-right: 0px;margin-bottom: 0px !important;margin-left: 0px;padding: 0px;border: 0px;text-align: left;"><strong style="box-sizing: border-box;font-weight: 700;margin: 0px;padding: 0px;border: 0px;"><span leaf="">BGE ReRanker</span></strong></p></td> <td style="box-sizing: border-box;margin: 0px;padding: 8px 12px;border: 1px solid rgb(232, 232, 232);vertical-align: top;font-weight: 400;text-align: left;font-size: 16px;line-height: 28px;min-height: 44px;"><p data-track="124" style="box-sizing: border-box;margin-top: 0px !important;margin-right: 0px;margin-bottom: 0px !important;margin-left: 0px;padding: 0px;border: 0px;"><span leaf="">支持多语言</span></p></td> <td style="box-sizing: border-box;margin: 0px;padding: 8px 12px;border: 1px solid rgb(232, 232, 232);vertical-align: top;font-weight: 400;text-align: left;font-size: 16px;line-height: 28px;min-height: 44px;"><p data-track="125" style="box-sizing: border-box;margin-top: 0px !important;margin-right: 0px;margin-bottom: 0px !important;margin-left: 0px;padding: 0px;border: 0px;"><span leaf="">多语言场景、高精度需求</span></p></td> </tr> <tr style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;"> <td style="box-sizing: border-box;margin: 0px;padding: 8px 12px;border: 1px solid rgb(232, 232, 232);vertical-align: top;font-weight: 400;text-align: left;font-size: 16px;line-height: 28px;min-height: 44px;"><p data-track="126" style="box-sizing: border-box;margin-top: 0px !important;margin-right: 0px;margin-bottom: 0px !important;margin-left: 0px;padding: 0px;border: 0px;text-align: left;"><strong style="box-sizing: border-box;font-weight: 700;margin: 0px;padding: 0px;border: 0px;"><span leaf="">Jina Reranker</span></strong></p></td> <td style="box-sizing: border-box;margin: 0px;padding: 8px 12px;border: 1px solid rgb(232, 232, 232);vertical-align: top;font-weight: 400;text-align: left;font-size: 16px;line-height: 28px;min-height: 44px;"><p data-track="127" style="box-sizing: border-box;margin-top: 0px !important;margin-right: 0px;margin-bottom: 0px !important;margin-left: 0px;padding: 0px;border: 0px;"><span leaf="">8k上下文支持</span></p></td> <td style="box-sizing: border-box;margin: 0px;padding: 8px 12px;border: 1px solid rgb(232, 232, 232);vertical-align: top;font-weight: 400;text-align: left;font-size: 16px;line-height: 28px;min-height: 44px;"><p data-track="128" style="box-sizing: border-box;margin-top: 0px !important;margin-right: 0px;margin-bottom: 0px !important;margin-left: 0px;padding: 0px;border: 0px;"><span leaf="">长文本排序、低延迟场景</span></p></td> </tr> <tr style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;"> <td style="box-sizing: border-box;margin: 0px;padding: 8px 12px;border: 1px solid rgb(232, 232, 232);vertical-align: top;font-weight: 400;text-align: left;font-size: 16px;line-height: 28px;min-height: 44px;"><p data-track="129" style="box-sizing: border-box;margin-top: 0px !important;margin-right: 0px;margin-bottom: 0px !important;margin-left: 0px;padding: 0px;border: 0px;text-align: left;"><strong style="box-sizing: border-box;font-weight: 700;margin: 0px;padding: 0px;border: 0px;"><span leaf="">BCE-Reranker</span></strong></p></td> <td style="box-sizing: border-box;margin: 0px;padding: 8px 12px;border: 1px solid rgb(232, 232, 232);vertical-align: top;font-weight: 400;text-align: left;font-size: 16px;line-height: 28px;min-height: 44px;"><p data-track="130" style="box-sizing: border-box;margin-top: 0px !important;margin-right: 0px;margin-bottom: 0px !important;margin-left: 0px;padding: 0px;border: 0px;"><span leaf="">网易有道开源,中英跨语言优化</span></p></td> <td style="box-sizing: border-box;margin: 0px;padding: 8px 12px;border: 1px solid rgb(232, 232, 232);vertical-align: top;font-weight: 400;text-align: left;font-size: 16px;line-height: 28px;min-height: 44px;"><p data-track="131" style="box-sizing: border-box;margin-top: 0px !important;margin-right: 0px;margin-bottom: 0px !important;margin-left: 0px;padding: 0px;border: 0px;"><span leaf="">中英混合场景、高召回率需求</span></p></td> </tr> </tbody> </table> <h1 data-track="232" style="box-sizing: border-box;font-size: 1.056em;margin: 20px 0px;padding: 0px;font-weight: 700;border: 0px;line-height: 1.579;color: rgb(0, 0, 0);font-family: " pingfang sc, hiragino sans gb, microsoft yahei, wenquanyi micro hei, helvetica neue, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial; data-pm-slice="0 0 []"><span leaf="">完整排序流程示例</span></h1> <p data-track="240" style="box-sizing: border-box;margin: 20px 0px;padding: 0px;border: 0px;color: rgb(34, 34, 34);font-family: " pingfang sc, hiragino sans gb, microsoft yahei, wenquanyi micro hei, helvetica neue, arial, sans-serif;font-size: 18px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;><strong style="box-sizing: border-box;font-weight: 700;margin: 0px;padding: 0px;border: 0px;"><span leaf="">用户问题</span></strong><span leaf="">:"美联储加息对A股的影响"</span></p> <ol style="box-sizing: border-box;margin: 20px 30px;padding: 0px;border: 0px;counter-reset: ol_list 0;color: rgb(34, 34, 34);font-family: " pingfang sc, hiragino sans gb, microsoft yahei, wenquanyi micro hei, helvetica neue, arial, sans-serif;font-size: 18px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial; class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;padding: 0px;list-style: decimal;border: 0px;"> <section> <span leaf="">初步检索(Retriever):</span> </section></li> </ol> <pre style="box-sizing: border-box;font-family: Monaco;font-size: 18px;margin: 20px 0px;padding: 15px;border: 0px;background: rgb(250, 250, 250);white-space: pre-wrap;word-break: break-all;display: block;overflow-x: auto;border-radius: 3px;text-align: left;color: rgb(34, 34, 34);box-shadow: rgba(216, 216, 216, 0.5) 0px 0px 0px 1px inset;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><code style="white-space:pre-wrap;box-sizing: border-box;font-family: inherit;font-size: 14px;margin: 0px;padding: 0px;border: 0px;overflow-wrap: normal;word-break: normal;overflow-x: auto;line-height: 24px;"><span leaf="">返回50篇文档:</span><span leaf=""><br></span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(168, 46, 46);"><span leaf="">- 10篇关于美国货币政策</span></span><span leaf=""><br></span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(168, 46, 46);"><span leaf="">- 15篇A股市场分析</span></span><span leaf=""><br></span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(168, 46, 46);"><span leaf="">- 20篇历史加息案例</span></span><span leaf=""><br></span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(168, 46, 46);"><span leaf="">- 5篇无关内容</span></span><span leaf=""><br></span></code></pre> <section> <span leaf="">2. Reranker工作流:</span> </section> <pre style="box-sizing: border-box;font-family: Monaco;font-size: 18px;margin: 20px 0px;padding: 15px;border: 0px;background: rgb(250, 250, 250);white-space: pre-wrap;word-break: break-all;display: block;overflow-x: auto;border-radius: 3px;text-align: left;color: rgb(34, 34, 34);box-shadow: rgba(216, 216, 216, 0.5) 0px 0px 0px 1px inset;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;"><code style="white-space:pre-wrap;box-sizing: border-box;font-family: inherit;font-size: 14px;margin: 0px;padding: 0px;border: 0px;overflow-wrap: normal;word-break: normal;overflow-x: auto;line-height: 24px;"><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(0, 117, 59);"><span leaf="">for</span></span><span leaf=""> </span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(0, 117, 59);"><span leaf="">文档</span></span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(0, 117, 59);"><span leaf="">in</span></span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(168, 46, 46);"><span leaf="">50</span></span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(0, 117, 59);"><span leaf="">篇:</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(0, 117, 59);"><span leaf="">计算语义相关性(BERT模型)→</span></span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(0, 117, 59);"><span leaf="">得分0.6-0.95</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(0, 117, 59);"><span leaf="">叠加时效性权重(2023年文档×1.2)</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(0, 117, 59);"><span leaf="">扣除低权威惩罚(自媒体文章×0.7)</span></span><span leaf=""><br></span><span leaf=""> </span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(0, 117, 59);"><span leaf="">最终得分</span></span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(0, 117, 59);"><span leaf="">=</span></span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(0, 117, 59);"><span leaf="">语义分×时效权重×权威系数</span></span><span leaf=""><br></span><span leaf=""><br></span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(0, 117, 59);"><span leaf="">排序后Top3:</span></span><span leaf=""><br></span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(168, 46, 46);"><span leaf="">1</span></span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(0, 117, 59);"><span leaf="">.</span></span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(0, 117, 59);"><span leaf="">《2023年美联储政策与新兴市场联动分析》(0.94)</span></span><span leaf=""><br></span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(168, 46, 46);"><span leaf="">2</span></span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(0, 117, 59);"><span leaf="">.</span></span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(0, 117, 59);"><span leaf="">《跨境资本流动对A股的影响机制》(0.91)</span></span><span leaf=""><br></span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(168, 46, 46);"><span leaf="">3</span></span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(0, 117, 59);"><span leaf="">.</span></span><span leaf=""> </span><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(0, 117, 59);"><span leaf="">《历史六轮加息周期中的板块表现》(0.89)</span></span></code></pre> <h1 data-track="107" style="box-sizing: border-box;font-size: 1.056em;margin: 20px 0px;padding: 0px;font-weight: 700;border: 0px;line-height: 1.579;color: rgb(0, 0, 0);font-family: " pingfang sc, hiragino sans gb, microsoft yahei, wenquanyi micro hei, helvetica neue, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial; data-pm-slice="0 0 []"><span leaf="">Reranker本质</span></h1> <p data-track="107" style="box-sizing: border-box;margin: 20px 0px;padding: 0px;border: 0px;color: rgb(34, 34, 34);font-family: " pingfang sc, hiragino sans gb, microsoft yahei, wenquanyi micro hei, helvetica neue, arial, sans-serif;font-size: 18px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;><span leaf=""> Reranker是知识库的"</span><strong style="box-sizing: border-box;font-weight: 700;margin: 0px;padding: 0px;border: 0px;"><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(26, 116, 255);"><span leaf="">智能质检员</span></span></strong><span leaf="">",假设你在图书馆找书,先用关键词检索到100本书,但需要找出</span><strong style="box-sizing: border-box;font-weight: 700;margin: 0px;padding: 0px;border: 0px;"><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(26, 116, 255);"><span leaf="">最相关</span></span></strong><span leaf="">的3本才行。</span></p> <p data-track="278" style="box-sizing: border-box;margin: 20px 0px;padding: 0px;border: 0px;color: rgb(34, 34, 34);font-family: " pingfang sc, hiragino sans gb, microsoft yahei, wenquanyi micro hei, helvetica neue, arial, sans-serif;font-size: 18px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;><span leaf="" data-pm-slice="1 1 [" para,{tagname:p,attributes:{data-track:107,style:box-sizing: border-box; margin: 20px 0px; padding: border: color: rgb(34, 34, 34); font-family: \pingfang sc\, \hiragino sans gb\, \microsoft yahei\, \wenquanyi micro hei\, \helvetica neue\, arial, sans-serif; font-size: 18px; font-style: normal; font-variant-ligatures: font-variant-caps: font-weight: 400; letter-spacing: orphans: 2; text-align: justify; text-indent: text-transform: none; widows: word-spacing: -webkit-text-stroke-width: white-space: background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: text-decoration-color: initial;},namespaceuri:http: www.w3.org 1999 xhtml}]> 图书管理员</span><span leaf="">(Reranker)会综合评估书籍内容、出版时间、作者权威性等维度进行二次筛选。</span></p> <p data-track="277" style="box-sizing: border-box;margin: 20px 0px;padding: 0px;border: 0px;color: rgb(34, 34, 34);font-family: " pingfang sc, hiragino sans gb, microsoft yahei, wenquanyi micro hei, helvetica neue, arial, sans-serif;font-size: 18px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: justify;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;white-space: normal;background-color: rgb(255, 255, 255);text-decoration-thickness: initial;text-decoration-style: initial;text-decoration-color: initial;><span leaf="" data-pm-slice="1 1 [" para,{tagname:p,attributes:{data-track:107,style:box-sizing: border-box; margin: 20px 0px; padding: border: color: rgb(34, 34, 34); font-family: \pingfang sc\, \hiragino sans gb\, \microsoft yahei\, \wenquanyi micro hei\, \helvetica neue\, arial, sans-serif; font-size: 18px; font-style: normal; font-variant-ligatures: font-variant-caps: font-weight: 400; letter-spacing: orphans: 2; text-align: justify; text-indent: text-transform: none; widows: word-spacing: -webkit-text-stroke-width: white-space: background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: text-decoration-color: initial;},namespaceuri:http: www.w3.org 1999 xhtml}]> 将检索到的候选文档(如100条)按照与问题的</span><strong style="box-sizing: border-box;font-weight: 700;margin: 0px;padding: 0px;border: 0px;"><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(26, 116, 255);"><span leaf="">相关度</span></span></strong><span leaf="">重新排序,把</span><strong style="box-sizing: border-box;font-weight: 700;margin: 0px;padding: 0px;border: 0px;"><span style="box-sizing: border-box;margin: 0px;padding: 0px;border: 0px;color: rgb(26, 116, 255);"><span leaf="">最匹配</span></span></strong><span leaf="">的结果提升到Top位置。</span></p> <p><span leaf=""><span textstyle="" style="font-size: 18px;"> Reranker模型是RAG系统中的智能排序引擎, 在知识库检索流程中承担着关键的优化角色。它通过多维度智能分析,对初步检索结果进行精细化处理,将最符合用户真实需求的信息精准呈现在前列。</span></span></p> <p><span leaf=""><span textstyle="" style="font-size: 18px;"> 不同于初检阶段的粗粒度筛选,Reranker会综合评估语义相关度(如问题与内容的深层匹配)、时效性(优先最新资料)、权威性(区分专家论述与普通观点)以及内容完整性(覆盖关键要素的程度)等多个核心维度,通过算法加权计算出每个结果的最终排序得分。</span></span></p> <p><span leaf=""><span textstyle="" style="font-size: 18px;"> 在企业级应用中, 这种智能排序机制有效解决了传统检索中面临的长尾问题、语义鸿沟等挑战,大幅提升了知识库的可用性和准确性,是确保专业用户获得高价值信息的关键技术保障。</span></span></p>
作者:微信小助手
<section style="text-indent: 0em;text-align: center;" data-mpa-powered-by="yiban.io"> <span style="font-size: 18px;">在人工智能飞速发展的当下</span> </section> <section style="text-indent: 0em;text-align: center;"> <span style="font-size: 18px;">对于广大学生和科研工作者而言</span> </section> <section style="text-indent: 0em;text-align: center;"> <span style="font-size: 18px;">一个关键问题随之而来</span> </section> <section style="text-indent: 0em;text-align: center;"> <span style="font-size: 18px;"><strong><span style="color: rgb(0, 122, 170);">借助这些前沿大模型写论文</span></strong></span> </section> <section style="text-indent: 0em;text-align: center;"> <span style="font-size: 18px;"><strong><span style="color: rgb(0, 122, 170);">真的靠谱吗?</span></strong></span> </section> <p style="text-indent: 2em;"><span style="font-size: 18px;"><br></span></p> <p><img class="rich_pages wxw-img" data-backh="201.822086" data-backw="576.822086" data-galleryid="" data-imgfileid="519447756" data-ratio="0.3490740740740741" data-s="300,640" src="/upload/18c314b057cbbcf79ac9bd0cb3164057.jpg" data-type="png" data-w="1080" style="letter-spacing: 0.578px;text-align: center;border-style: solid;border-width: 1px;border-color: rgb(0, 0, 0);width: 100%;height: auto;"></p> <p><br></p> <section style="text-indent: 0em;text-align: center;"> <span style="font-size: 18px;">不久前</span> </section> <section style="text-indent: 0em;text-align: center;"> <span style="font-size: 18px;">#防止DeepSeek乱编文献的方法#</span> </section> <section style="text-indent: 0em;text-align: center;"> <span style="font-size: 18px;">冲上热搜</span> </section> <section style="text-indent: 0em;text-align: center;"> <span style="font-size: 18px;">记者注意到</span> </section> <section style="text-indent: 0em;text-align: center;"> <span style="font-size: 18px;"><strong><span style="color: rgb(0, 122, 170);">用AI工具写论文“被坑”的经历</span></strong></span> </section> <section style="text-indent: 0em;text-align: center;"> <span style="font-size: 18px;"><strong><span style="color: rgb(0, 122, 170);">并非鲜见</span></strong></span> </section> <p style="text-indent: 2em;"><br></p> <section> <img class="rich_pages wxw-img" data-backh="841.822086" data-backw="576.822086" data-galleryid="" data-imgfileid="519447759" data-ratio="1.4592592592592593" data-s="300,640" src="/upload/375e4cd9ddb8235e63259f7f968e97a5.jpg" data-type="png" data-w="1080" style="letter-spacing: 0.578px;text-align: center;border-style: solid;border-width: 1px;width: 100%;height: auto;"> </section> <section> <br> </section> <section style="text-align: center;"> <span style="font-size: 18px;">有网友列出了自己的亲身经历</span> </section> <section style="text-align: center;"> <span style="font-size: 18px;">除了编造论文文献</span> </section> <section style="text-align: center;"> <span style="font-size: 18px;">AI还会编造法律条文<br></span> </section> <section style="text-align: center;"> <strong><span style="font-size: 18px;color: rgb(0, 122, 170);">甚至教人做菜还跑偏了</span></strong> </section> <section> <br> </section> <section style="font-size: 16px;color: rgb(62, 62, 62);"> <section style="margin-top: 10px;margin-bottom: 10px;display: inline-block;width: 100%;border-width: 1px;border-style: solid;border-color: rgb(192, 200, 209);padding: 10px;background-color: rgb(250, 250, 239);box-shadow: rgb(170, 170, 170) 0px 0px 10px;"> <section style="color: rgb(51, 51, 51);width: 100%;"> <section style="margin-bottom: 0px;letter-spacing: 0.578px;"> <img class="rich_pages wxw-img" data-galleryid="" data-imgfileid="519447758" data-ratio="0.20925925925925926" data-s="300,640" src="/upload/3e3c5f62eef8a402a54b413fceb9f768.png" data-type="png" data-w="1080" style="letter-spacing: 0.578px;text-align: center;"> </section> <p style="margin-bottom: 0px;letter-spacing: 0.578px;text-align: center;"><img class="rich_pages wxw-img" data-galleryid="" data-imgfileid="519447755" data-ratio="0.29074074074074074" data-s="300,640" src="/upload/4e778de885d4869e6a3968e1e9c0f17a.png" data-type="png" data-w="1080"></p> </section> </section> </section> <p style="text-align: center;"><br></p> <p style="text-indent: 2em;"><span style="font-size: 18px;">问AI一个问题,它给了你一个特别详细、丰富,看上去好有逻辑的答案。但当我们去核实时,却发现这些信息完全是虚构的。<strong><span style="color: rgb(0, 122, 170);">这就是著名的“AI幻觉”现象。</span></strong></span></p> <p style="text-indent: 2em;"><span style="font-size: 18px;"><br></span></p> <p style="text-indent: 2em;"><span style="font-size: 18px;">“AI幻觉”指的是AI会生成看似合理但实际确实错误的信息,最常见的表现就是会编造一些不存在的事实或者细节。</span></p> <section> <br> </section> <section style="text-indent: 2em;"> <span style="font-size: 18px;">造成“AI幻觉”的成因很多,例如:基于统计关系的预测;训练数据的局限性;过拟合问题,即因为记住了太多错误或者无关紧要的东西,从而让AI对训练数据中的噪声过于敏感;有限的上下文窗口;生成流畅回答的设计等等。</span> </section> <section style="text-indent: 2em;"> <br> </section> <p style="text-align: center;"><img class="rich_pages wxw-img" data-backh="962.822086" data-backw="576.822086" data-galleryid="" data-imgfileid="519447757" data-ratio="1.6685185185185185" data-s="300,640" src="/upload/fea8a81fcc7c90b756be23742fcb4f79.jpg" data-type="png" data-w="1080" style="letter-spacing: 0.578px;border-style: solid;border-width: 1px;width: 100%;height: auto;"></p> <section> <br> </section> <p style="text-indent: 2em;"><strong><span style="font-size: 18px;color: rgb(0, 122, 170);">那么,当AI会说谎,大家如何避免被“带偏”?</span></strong><strong><span style="font-size: 18px;text-indent: 2em;letter-spacing: 0.034em;color: rgb(0, 122, 170);">技术浪潮中,我们如何守护自己的思辨能力?</span></strong></p> <p style="text-indent: 2em;"><span style="font-size: 18px;"><br></span></p> <p style="text-indent: 2em;"><span style="font-size: 18px;">中国人民大学新闻学院教授卢家银指出,在知识建构上,AI生成的虚假学术成果,可能扭曲青年对科学方法论的理解,削弱其“假设-验证”的科研逻辑训练。在思维发展上,AI谣言通过算法推荐的“信息茧房”形成逻辑闭环,不利于批判性思维的培养。</span></p> <section style="text-indent: 2em;"> <br> </section> <section style="text-indent: 2em;"> <span style="font-size: 18px;">北京师范大学教育学部教授、教育技术学北京市重点实验室副主任李艳燕建议,<strong><span style="color: rgb(0, 122, 170);">可以把AI看作一位平等对话的智者</span></strong>,通过引导与AI的对话互动,促进个体思维链的形成,并校准认知偏差。这种去权威化的思辨训练,可以帮助我们在与AI的对话中保持独立判断,实现认知跃迁。</span> </section> <section style="text-indent: 2em;"> <span style="font-size: 18px;"><br></span> </section> <section style="text-indent: 2em;"> <span style="font-size: 18px;">北京邮电大学马克思主义学院副教授宋林泽认为,<strong><span style="color: rgb(0, 122, 170);">AI输出的内容只是一个认知起点,而不是终点</span></strong>。大学生需要主动去验证它的内容,比如查阅权威来源、对比不同观点,甚至直接与领域专家交流。这种验证过程,不仅能帮助我们更全面地理解问题,还能让我们在面对复杂信息时更有判断力。</span> </section> <section style="text-indent: 2em;"> <span style="font-size: 18px;"><br></span> </section> <p style="text-align: center;"><img class="rich_pages wxw-img js_insertlocalimg" data-backh="434" data-backw="578" data-imgfileid="519447761" data-ratio="0.75" data-s="300,640" src="/upload/1a997f17f14940fde233cec9b3bfb2eb.jpg" data-type="jpeg" data-w="1080" style="width: 100%;height: auto;"></p> <section style="text-indent: 2em;"> <span style="font-size: 18px;"><br></span> </section> <section style="text-indent: 2em;"> <span style="font-size: 18px;">如何应对AI幻觉呢?</span> </section> <section style="text-indent: 2em;"> <span style="font-size: 18px;"><br></span> </section> <section style="text-indent: 2em;"> <span style="font-size: 18px;">AI工具研究者田威提到,<strong><span style="color: rgb(0, 122, 170);">想要获得准确答案,提问方式很关键。</span></strong>与AI交流也需要明确和具体,避免模糊或开放性的问题,提问越具体、清晰,AI的回答越准确。</span> </section> <section style="text-indent: 2em;"> <span style="font-size: 18px;"><br></span> </section> <section style="text-indent: 2em;"> <span style="font-size: 18px;">总结成提示词技巧就是下面四种问法:</span> </section> <section> <br> </section> <section data-mpa-template="t" mpa-from-tpl="t"> <section> <section data-style-type="2" data-tools="新媒体排版" data-id="9155" style="color: rgb(51, 51, 51);letter-spacing: 0.544px;" mpa-from-tpl="t"> <section powered-by="xiumi.us" mpa-from-tpl="t"> <section style="margin-top: 0.5em;margin-bottom: 0.5em;text-align: center;" mpa-from-tpl="t"> <section style="padding: 10px;border-width: 3px;border-style: solid;border-color: rgb(204, 204, 204);box-shadow: rgb(102, 102, 102) 2.82843px 2.82843px 7px;" mpa-from-tpl="t"> <section powered-by="xiumi.us" mpa-from-tpl="t"> <section mpa-from-tpl="t"> <section style="text-align: left;" mpa-from-tpl="t"> <section style="text-align: justify;text-indent: 2em;"> <strong><span style="font-size: 18px;letter-spacing: 0.578px;color: rgb(0, 122, 170);">1.设定边界</span></strong><span style="color: rgb(0, 0, 0);font-size: 18px;letter-spacing: 0.578px;">:“请严格限定在xx年xx期刊发表的研究范围内”;</span> </section> <section style="text-align: center;text-indent: 2em;"> <br> </section> </section> </section> </section> <section style="letter-spacing: 0.578px;text-align: justify;margin-bottom: 24px;text-indent: 2em;"> <span style="color: rgb(0, 0, 0);font-size: 18px;">示例:“介绍ChatGPT的发展历程”→“请仅基于OpenAI官方2022-2023年的公开文档,介绍ChatGPT的发展历程”</span><o:p></o:p> </section> <section style="letter-spacing: 0.578px;text-align: justify;margin-bottom: 24px;text-indent: 2em;"> <strong><span style="font-size: 18px;color: rgb(0, 122, 170);">2.标注不确定</span></strong><span style="color: rgb(0, 0, 0);font-size: 18px;">:“对于模糊信息,需要标注‘此处为推测内容’”;</span><o:p></o:p> </section> <section style="letter-spacing: 0.578px;text-align: justify;margin-bottom: 24px;text-indent: 2em;"> <span style="color: rgb(0, 0, 0);font-size: 18px;">示例:“分析特斯拉2025年的市场份额”→“分析特斯拉2025年的市场份额,对于非官方数据或预测性内容,请标注[推测内容]”</span><o:p></o:p> </section> <section style="letter-spacing: 0.578px;text-align: justify;margin-bottom: 24px;text-indent: 2em;"> <strong><span style="font-size: 18px;color: rgb(0, 122, 170);">3.步骤拆解</span></strong><span style="color: rgb(0, 0, 0);font-size: 18px;">:“第一步列举确定的事实依据,第二步展开详细分析”;</span><o:p></o:p> </section> <section style="letter-spacing: 0.578px;text-align: justify;margin-bottom: 24px;text-indent: 2em;"> <span style="color: rgb(0, 0, 0);font-size: 18px;">示例:“评估人工智能对就业的影响”→“请分两步评估AI对就业的影响:</span><o:p></o:p> </section> <section style="letter-spacing: 0.578px;text-align: justify;margin-bottom: 24px;text-indent: 2em;"> <span style="color: rgb(0, 0, 0);font-size: 18px;">1)先列出目前已发生的具体影响案例;</span><o:p></o:p> </section> <section style="letter-spacing: 0.578px;text-align: justify;margin-bottom: 24px;text-indent: 2em;"> <span style="color: rgb(0, 0, 0);font-size: 18px;">2)基于这些案例进行未来趋势分析”。</span><o:p></o:p> </section> <section style="letter-spacing: 0.578px;text-align: justify;margin-bottom: 24px;text-indent: 2em;"> <strong><span style="font-size: 18px;color: rgb(0, 122, 170);">4.明确约束</span></strong><span style="color: rgb(0, 0, 0);font-size: 18px;">:明确告诉AI要基于已有事实回答,不要进行推测。</span><o:p></o:p> </section> <p style="letter-spacing: 0.578px;text-align: justify;text-indent: 2em;margin-bottom: 0px;"><span style="color: rgb(0, 0, 0);font-size: 18px;">示例:“预测2025年房地产市场走势”→“请仅基于2024年的实际房地产数据和已出台的相关政策进行分析,不要加入任何推测性内容”。</span></p> </section> </section> </section> </section> </section> </section> <section data-mpa-template="t" mpa-from-tpl="t"> <section> <section style="text-indent: 2em;"> <span style="font-size: 18px;"><br></span> </section> <section style="text-indent: 2em;"> <span style="font-size: 18px;">针对如何获得准确答案,AI自己的答案是,可以通过指令约束、工具验证和人工审核三重保障,大幅降低AI虚构文献的风险。值得注意的是,<strong><span style="color: rgb(0, 122, 170);">“人工审核”被AI自己认为是“最后防线”</span></strong>。</span> </section> <section style="text-indent: 2em;"> <br> </section> <section> <img class="rich_pages wxw-img" data-backh="391.822086" data-backw="576.822086" data-galleryid="" data-imgfileid="519447760" data-ratio="0.6791277258566978" data-s="300,640" src="/upload/6517d97da6c3f98887fcd51bb40f4741.png" data-type="png" data-w="642" style="border-style: solid;border-width: 1px;width: 100%;height: auto;"> </section> <section style="text-indent: 2em;"> <br> </section> <section style="text-indent: 2em;"> <span style="font-size: 18px;">专家提醒,“AI幻觉”并非没有好处,有时候与其把它当成缺陷,<span style="color: rgb(0, 122, 170);"><strong>不如把它看作创意的源泉</strong></span>。在写作、艺术创作或头脑风暴时,这些“跳跃性思维”反而可能帮我们打开新世界的大门。</span> </section> <p><br></p> </section> </section> <section style="text-indent: 2em;"> <span style="font-size: 18px;">“AI幻觉”的本质是,AI在知识的迷雾中,有时会创造出看似真实,实则虚幻的“影子”。但就像任何工具一样,关键在于如何使用。</span> </section> <section style="text-indent: 2em;"> <span style="font-size: 18px;"><br></span> </section> <section style="text-indent: 2em;"> <span style="font-size: 18px;">归根结底,在这个AI与人类共同进步的时代,<strong><span style="color: rgb(0, 122, 170);">重要的不是责备AI的不完美,而是学会与之更好地协作。</span></strong></span> </section>
作者:微信小助手
<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="margin-bottom: 0px;padding-left: 10px;padding-right: 10px;background-attachment: scroll;background-clip: border-box;background-image: linear-gradient(90deg, rgba(50, 0, 0, 0.05) 0%, rgba(0, 0, 0, 0) 6.76%), linear-gradient(360deg, rgba(50, 0, 0, 0.05) 0%, rgba(249, 247, 252, 0) 9.46%);background-origin: padding-box;background-position: 0% 0%;background-repeat: repeat, repeat;background-size: 20px 20px, 20px 20px;width: auto;font-family: Optima, " microsoft yahei, pingfangsc-regular, serif;font-size: 16px;color: rgb(0, 0, 0);line-height: 1.5em;word-spacing: 0em;letter-spacing: 0em;word-break: break-word;text-align: left; data-pm-slice="0 0 []"> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="padding-left: 3px;padding-right: 3px;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position: 0% 0%;background-repeat: no-repeat;background-size: auto;width: auto;font-family: PingFangSC-regular, sans-serif;line-height: 1.5em;word-spacing: 0em;letter-spacing: 0em;word-break: break-word;"> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><br></span> </figure> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 3px;padding-right: 3px;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;font-family: PingFangSC-regular, sans-serif;font-size: 16px;color: rgb(0, 0, 0);line-height: 1.5em;word-spacing: 0em;letter-spacing: 0em;word-break: break-word;overflow-wrap: break-word;text-align: left;" data-pm-slice="0 0 []"> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img src="/upload/92669e7a0436457d32c945ea1130081d.png" class="rich_pages wxw-img" data-ratio="0.6" data-type="png" data-w="1080" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;" data-imgfileid="100006382"></span> </figure> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">在当今信息爆炸的时代,如何从海量数据中快速准确地获取所需信息,是人工智能领域的一大挑战。Retrieval-Augmented Generation(RAG,检索增强生成)技术应运而生,它结合了检索和生成的优势,通过从大量文档中检索相关信息,再利用这些信息生成高质量的回答。然而,RAG 的实现方式多种多样,不同的技术路径有着不同的优势和局限。今天,我们就来深入探讨一下这些 RAG 技术,看看谁才是真正的“最佳选手”。</span></p> <h2 data-tool="mdnice编辑器" style="background-color: rgb(251, 251, 251);margin-top: 50px;margin-bottom: 20px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(255, 255, 255);background-color: rgb(33, 33, 34);line-height: 1.5em;letter-spacing: 0em;padding-top: 8px;padding-bottom: 8px;padding-left: 15px;padding-right: 30px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 40px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">1. Simple RAG:基础而不失经典</span></span><span style="display: none;"></span></h2> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img src="/upload/eb4ffebdfc5ca69ff8685c64fea880a4.png" class="rich_pages wxw-img" data-ratio="0.33714285714285713" data-type="png" data-w="700" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;" data-imgfileid="100006381"></span> </figure> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">在探索各种复杂的 RAG 技术之前,我们先从最简单的 RAG 方法说起。**简单 RAG **的工作流程非常直观:从 PDF 文档中提取文本,将其分割成小块(chunks),将这些文本块转换为数值化的嵌入向量(embeddings),根据查询(query)搜索最相关的文本块,最后利用检索到的文本块生成回答。</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg ijdpq631cvfpzevp7c96gnruqn0u3fiancwzhdxoqs1pvknfalxbssriccrluvnayrvtcp9zwfopqiaotazjtnke4qtwezjoiczs 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf=""># 定义 PDF 文件路径</span></span><span leaf=""><br></span><span leaf="">pdf_path = </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"data/AI_information.pdf"</span></span><span leaf=""><br></span><span leaf=""><br></span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf=""># 提取文本并分割成文本块</span></span><span leaf=""><br></span><span leaf="">extracted_text = extract_text_from_pdf(pdf_path)</span><span leaf=""><br></span><span leaf="">text_chunks = chunk_text(extracted_text, chunk_size=</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">1000</span></span><span leaf="">, overlap=</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">200</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf=""><br></span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf=""># 打印文本块数量</span></span><span leaf=""><br></span><span leaf="">print(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"Number of text chunks:"</span></span><span leaf="">, len(text_chunks))</span><span leaf=""><br></span></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">这种方法虽然简单,但却为后续更复杂的技术奠定了基础。它就像是一个“新手村”,让我们能够初步了解 RAG 的工作原理。然而,简单 RAG 也有它的局限性。由于文本块是按照固定大小分割的,可能会导致一些句子被拆分开,或者将不相关的句子组合在一起,从而影响检索的准确性。</span></p> <h2 data-tool="mdnice编辑器" style="background-color: rgb(251, 251, 251);margin-top: 50px;margin-bottom: 20px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(255, 255, 255);background-color: rgb(33, 33, 34);line-height: 1.5em;letter-spacing: 0em;padding-top: 8px;padding-bottom: 8px;padding-left: 15px;padding-right: 30px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 40px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">2. Semantic Chunking语义分块:让文本块更有意义</span></span><span style="display: none;"></span></h2> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img src="/upload/257fc429af0834315b95bc9b4a4412f7.png" class="rich_pages wxw-img" data-ratio="0.3842857142857143" data-type="png" data-w="700" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;" data-imgfileid="100006380"></span> </figure> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">为了解决简单 RAG 中文本块分割不够合理的问题,</span><strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">语义分块(Semantic Chunking)</span></strong><span leaf="">应运而生。与简单 RAG 不同,语义分块不再是按照固定大小来分割文本,而是尝试根据文本的语义来划分,将语义相关的句子组合在一起形成文本块。</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg ijdpq631cvfpzevp7c96gnruqn0u3fiancwzhdxoqs1pvknfalxbssriccrluvnayrvtcp9zwfopqiaotazjtnke4qtwezjoiczs 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf=""># 将提取的文本分割成句子</span></span><span leaf=""><br></span><span leaf="">sentences = extracted_text.split(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">". "</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf=""><br></span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf=""># 为每个句子生成嵌入向量</span></span><span leaf=""><br></span><span leaf="">embeddings = [get_embedding(sentence) </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">for</span></span><span leaf=""> sentence </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">in</span></span><span leaf=""> sentences]</span><span leaf=""><br></span><span leaf=""><br></span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf=""># 计算连续句子之间的相似度</span></span><span leaf=""><br></span><span leaf="">similarities = [cosine_similarity(embeddings[i], embeddings[i + </span><span style="color: #d19a66;line-height: 26px;"><span leaf="">1</span></span><span leaf="">]) </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">for</span></span><span leaf=""> i </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">in</span></span><span leaf=""> range(len(embeddings) - </span><span style="color: #d19a66;line-height: 26px;"><span leaf="">1</span></span><span leaf="">)]</span><span leaf=""><br></span><span leaf=""><br></span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf=""># 使用百分位法计算断点</span></span><span leaf=""><br></span><span leaf="">breakpoints = compute_breakpoints(similarities, method=</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"percentile"</span></span><span leaf="">, threshold=</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">90</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf=""><br></span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf=""># 根据断点将句子分组成语义块</span></span><span leaf=""><br></span><span leaf="">text_chunks = split_into_chunks(sentences, breakpoints)</span><span leaf=""><br></span></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">这种方法听起来很完美,但在实际测试中,它的表现却不尽如人意。语义分块的评分甚至低于简单 RAG,这说明仅仅改变文本块的分割策略,并不能保证检索效果的提升。这也提醒我们,技术的改进并非一蹴而就,需要更多的思考和尝试。</span></p> <h2 data-tool="mdnice编辑器" style="background-color: rgb(251, 251, 251);margin-top: 50px;margin-bottom: 20px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(255, 255, 255);background-color: rgb(33, 33, 34);line-height: 1.5em;letter-spacing: 0em;padding-top: 8px;padding-bottom: 8px;padding-left: 15px;padding-right: 30px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 40px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">3. 上下文增强检索:邻居也能提供帮助</span></span><span style="display: none;"></span></h2> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img src="/upload/d3fb570dca54bcbfc3060bc62cee0e05.png" class="rich_pages wxw-img" data-ratio="0.2985714285714286" data-type="png" data-w="700" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;" data-imgfileid="100006379"></span> </figure> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">既然语义分块没有达到预期的效果,我们不妨换个思路。简单 RAG 的问题在于文本块过于孤立,缺乏上下文信息。那么,如果我们能够为每个文本块添加一些上下文信息,是不是就能提高检索的准确性呢?</span><strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">上下文增强检索(Context Enriched Retrieval)</span></strong><span leaf="">正是基于这样的想法。</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg ijdpq631cvfpzevp7c96gnruqn0u3fiancwzhdxoqs1pvknfalxbssriccrluvnayrvtcp9zwfopqiaotazjtnke4qtwezjoiczs 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf=""># 定义上下文增强检索函数</span></span><span leaf=""><br></span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">def</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">context_enriched_search</span></span><span style="line-height: 26px;"><span leaf="">(query, text_chunks, embeddings, k=</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">1</span></span><span leaf="">, context_size=</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">1</span></span><span leaf="">)</span></span><span leaf="">:</span></span><span leaf=""><br></span><span leaf=""> query_embedding = create_embeddings(query).data[</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">0</span></span><span leaf="">].embedding</span><span leaf=""><br></span><span leaf=""> similarity_scores = []</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">for</span></span><span leaf=""> i, chunk_embedding </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">in</span></span><span leaf=""> enumerate(embeddings):</span><span leaf=""><br></span><span leaf=""> similarity_score = cosine_similarity(np.array(query_embedding), np.array(chunk_embedding.embedding))</span><span leaf=""><br></span><span leaf=""> similarity_scores.append((i, similarity_score))</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> similarity_scores.sort(key=</span><span style="color: #c678dd;line-height: 26px;"><span leaf="">lambda</span></span><span leaf=""> x: x[</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">1</span></span><span leaf="">], reverse=</span><span style="color: #56b6c2;line-height: 26px;"><span leaf="">True</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf=""> top_index = similarity_scores[</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">0</span></span><span leaf="">][</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">0</span></span><span leaf="">]</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> start = max(</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">0</span></span><span leaf="">, top_index - context_size)</span><span leaf=""><br></span><span leaf=""> end = min(len(text_chunks), top_index + context_size + </span><span style="color: #d19a66;line-height: 26px;"><span leaf="">1</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">return</span></span><span leaf=""> [text_chunks[i] </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">for</span></span><span leaf=""> i </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">in</span></span><span leaf=""> range(start, end)]</span><span leaf=""><br></span></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">在上下文增强检索中,我们不仅检索与查询最相关的文本块,还会检索其周围的文本块作为上下文信息。这些“邻居”文本块能够为检索提供更多的背景信息,帮助生成更准确的回答。经过测试,上下文增强检索的评分达到了 0.6,相较于简单 RAG 和语义分块有了显著的提升。这表明,上下文信息在检索过程中确实起到了关键作用。</span></p> <h2 data-tool="mdnice编辑器" style="background-color: rgb(251, 251, 251);margin-top: 50px;margin-bottom: 20px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(255, 255, 255);background-color: rgb(33, 33, 34);line-height: 1.5em;letter-spacing: 0em;padding-top: 8px;padding-bottom: 8px;padding-left: 15px;padding-right: 30px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 40px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">4. 上下文块头:给文本块加上“标签”</span></span><span style="display: none;"></span></h2> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img src="/upload/60342a9ccdaae79f804d5568a2fcf27a.png" class="rich_pages wxw-img" data-ratio="0.24285714285714285" data-type="png" data-w="700" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;" data-imgfileid="100006378"></span> </figure> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">上下文增强检索虽然有效,但仍然存在一个问题:即使有了上下文信息,文本块本身可能仍然缺乏足够的语义信息。例如,一个文档可能包含多个主题,每个主题都对应着不同的文本块。在这种情况下,如何快速准确地找到与查询最相关的文本块呢?</span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">上下文块头(Contextual Chunk Headers)</span></strong><span leaf="">技术为我们提供了一个解决方案。它在每个文本块的前面添加了一个描述性的标题(header),这个标题就像是一个“标签”,能够概括文本块的主要内容。</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg ijdpq631cvfpzevp7c96gnruqn0u3fiancwzhdxoqs1pvknfalxbssriccrluvnayrvtcp9zwfopqiaotazjtnke4qtwezjoiczs 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf=""># 为每个文本块生成描述性标题</span></span><span leaf=""><br></span><span leaf="">text_chunks_with_headers = chunk_text_with_headers(extracted_text, chunk_size=</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">1000</span></span><span leaf="">, overlap=</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">200</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf=""><br></span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf=""># 打印一个样本以查看效果</span></span><span leaf=""><br></span><span leaf="">print(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"Sample Chunk with Header:"</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf="">print(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"Header:"</span></span><span leaf="">, text_chunks_with_headers[</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">0</span></span><span leaf="">][</span><span style="color: #98c379;line-height: 26px;"><span leaf="">'header'</span></span><span leaf="">])</span><span leaf=""><br></span><span leaf="">print(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"Content:"</span></span><span leaf="">, text_chunks_with_headers[</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">0</span></span><span leaf="">][</span><span style="color: #98c379;line-height: 26px;"><span leaf="">'text'</span></span><span leaf="">])</span><span leaf=""><br></span></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">在检索过程中,系统不仅会考虑文本块的内容,还会参考其标题,从而更准确地找到与查询相关的文本块。经过测试,上下文块头的评分达到了 0.5,虽然没有上下文增强检索高,但也比简单 RAG 和语义分块有了明显的提升。这说明,通过给文本块添加标题,我们能够为检索提供更多的语义信息,从而提高检索的准确性。</span></p> <h2 data-tool="mdnice编辑器" style="background-color: rgb(251, 251, 251);margin-top: 50px;margin-bottom: 20px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(255, 255, 255);background-color: rgb(33, 33, 34);line-height: 1.5em;letter-spacing: 0em;padding-top: 8px;padding-bottom: 8px;padding-left: 15px;padding-right: 30px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 40px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">5. 文档增强:从文本块到问题</span></span><span style="display: none;"></span></h2> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img src="/upload/882d116dc45be0b2f072b1f49aa1efd6.png" class="rich_pages wxw-img" data-ratio="0.33285714285714285" data-type="png" data-w="700" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;" data-imgfileid="100006383"></span> </figure> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">上下文块头虽然能够提供更多的语义信息,但仍然存在局限性。在某些情况下,文本块的内容可能过于复杂,难以用一个简单的标题来概括。那么,有没有一种方法能够让文本块更容易被检索到呢?</span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">文档增强(Document Augmentation)技术为我们提供了一个新的思路。它不仅将文本块转换为嵌入向量,还会为每个文本块生成一些相关的问题,并将这些问题也转换为嵌入向量。</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg ijdpq631cvfpzevp7c96gnruqn0u3fiancwzhdxoqs1pvknfalxbssriccrluvnayrvtcp9zwfopqiaotazjtnke4qtwezjoiczs 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf=""># 处理文档,提取文本、创建文本块、生成问题并构建向量库</span></span><span leaf=""><br></span><span leaf="">text_chunks, vector_store = process_document(</span><span leaf=""><br></span><span leaf=""> pdf_path,</span><span leaf=""><br></span><span leaf=""> chunk_size=</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">1000</span></span><span leaf="">,</span><span leaf=""><br></span><span leaf=""> chunk_overlap=</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">200</span></span><span leaf="">,</span><span leaf=""><br></span><span leaf=""> questions_per_chunk=</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">3</span></span><span leaf=""><br></span><span leaf="">)</span><span leaf=""><br></span></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">这样一来,在检索过程中,系统不仅能够匹配文本块的内容,还能够匹配与查询相关的问题,从而提高检索的准确性。经过测试,文档增强的评分达到了 0.8,这是一个非常高的分数,表明文档增强技术能够显著提高检索的准确性。这也说明,通过为文本块生成相关问题,我们能够为检索提供更多的入口,从而更容易找到与查询相关的文本块。</span></p> <h2 data-tool="mdnice编辑器" style="background-color: rgb(251, 251, 251);margin-top: 50px;margin-bottom: 20px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(255, 255, 255);background-color: rgb(33, 33, 34);line-height: 1.5em;letter-spacing: 0em;padding-top: 8px;padding-bottom: 8px;padding-left: 15px;padding-right: 30px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 40px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">6. 查询转换:让查询更“友好”</span></span><span style="display: none;"></span></h2> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img src="/upload/c50e221d17087dce22c9aab59c41bbaa.png" class="rich_pages wxw-img" data-ratio="0.39571428571428574" data-type="png" data-w="700" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;" data-imgfileid="100006385"></span> </figure> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">在前面的讨论中,我们主要关注了如何改进文本块的表示和检索策略。然而,我们忽略了一个重要的因素:用户提出的查询可能并不总是能够很好地匹配文档中的内容,这可能会导致检索结果不准确。那么,有没有一种方法能够让查询更“友好”,更容易被检索到呢?</span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">查询转换(Query Transformation)</span></strong><span leaf="">技术为我们提供了一个解决方案。它通过三种不同的方法来改进查询:查询重写(Query Rewriting)、后退提示(Step-back Prompting)和子查询分解(Sub-query Decomposition)。</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg ijdpq631cvfpzevp7c96gnruqn0u3fiancwzhdxoqs1pvknfalxbssriccrluvnayrvtcp9zwfopqiaotazjtnke4qtwezjoiczs 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf=""># 查询重写</span></span><span leaf=""><br></span><span leaf="">rewritten_query = rewrite_query(query)</span><span leaf=""><br></span><span leaf=""><br></span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf=""># 后退提示</span></span><span leaf=""><br></span><span leaf="">step_back_query = generate_step_back_query(query)</span><span leaf=""><br></span><span leaf=""><br></span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf=""># 子查询分解</span></span><span leaf=""><br></span><span leaf="">sub_queries = decompose_query(query, num_subqueries=</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">4</span></span><span leaf="">)</span><span leaf=""><br></span></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">查询重写是将查询变得更加具体和详细;后退提示是创建一个更广泛的查询,以检索有用的背景信息;子查询分解则是将一个复杂的查询分解为多个简单的子查询。经过测试,查询转换的评分达到了 0.5。虽然这个分数并不高,但它仍然表明查询转换技术在某些情况下能够提高检索的准确性。这也提醒我们,在 RAG 系统中,不仅需要关注文本块的表示和检索策略,还需要关注查询的质量。</span></p> <h2 data-tool="mdnice编辑器" style="background-color: rgb(251, 251, 251);margin-top: 50px;margin-bottom: 20px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(255, 255, 255);background-color: rgb(33, 33, 34);line-height: 1.5em;letter-spacing: 0em;padding-top: 8px;padding-bottom: 8px;padding-left: 15px;padding-right: 30px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 40px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">7. 重排序:让检索结果更有条理</span></span><span style="display: none;"></span></h2> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img src="/upload/b1549b8b3df0dc7398cc23cc3ca35bf5.png" class="rich_pages wxw-img" data-ratio="0.2957142857142857" data-type="png" data-w="700" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;" data-imgfileid="100006386"></span> </figure> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">在前面的讨论中,我们主要关注了如何改进文本块的表示和检索策略,以及如何改进查询的质量。然而,我们忽略了一个重要的环节:检索结果的排序。简单相似性搜索通常会返回一组相关性和不相关性混杂的结果,这可能会导致生成的回答不够准确。那么,有没有一种方法能够让检索结果更有条理,更容易被利用呢?</span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">重排序(Reranker)</span></strong><span leaf="">技术为我们提供了一个解决方案。它在初始检索的基础上,通过一个额外的步骤对检索结果进行重新排序,将最相关的文本块放在最前面。重排序可以使用不同的方法,例如基于关键词的重排序或基于 LLM 的重排序。</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg ijdpq631cvfpzevp7c96gnruqn0u3fiancwzhdxoqs1pvknfalxbssriccrluvnayrvtcp9zwfopqiaotazjtnke4qtwezjoiczs 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf=""># 定义重排序函数</span></span><span leaf=""><br></span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">def</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">rag_with_reranking</span></span><span style="line-height: 26px;"><span leaf="">(query, vector_store, reranking_method=</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"llm"</span></span><span leaf="">, top_n=</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">3</span></span><span leaf="">, model=</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"meta-llama/Llama-3.2-3B-Instruct"</span></span><span leaf="">)</span></span><span leaf="">:</span></span><span leaf=""><br></span><span leaf=""> query_embedding = create_embeddings(query)</span><span leaf=""><br></span><span leaf=""> initial_results = vector_store.similarity_search(query_embedding, k=</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">10</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">if</span></span><span leaf=""> reranking_method == </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"llm"</span></span><span leaf="">:</span><span leaf=""><br></span><span leaf=""> reranked_results = rerank_with_llm(query, initial_results, top_n=top_n)</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">else</span></span><span leaf="">:</span><span leaf=""><br></span><span leaf=""> reranked_results = initial_results[:top_n]</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> context = </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"\n\n===\n\n"</span></span><span leaf="">.join([result[</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"text"</span></span><span leaf="">] </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">for</span></span><span leaf=""> result </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">in</span></span><span leaf=""> reranked_results])</span><span leaf=""><br></span><span leaf=""> response = generate_response(query, context, model)</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">return</span></span><span leaf=""> {</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"query"</span></span><span leaf="">: query,</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"reranking_method"</span></span><span leaf="">: reranking_method,</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"initial_results"</span></span><span leaf="">: initial_results[:top_n],</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"reranked_results"</span></span><span leaf="">: reranked_results,</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"context"</span></span><span leaf="">: context,</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"response"</span></span><span leaf="">: response</span><span leaf=""><br></span><span leaf=""> }</span><span leaf=""><br></span></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">这种方法的效果如何呢?经过测试,重排序的评分达到了 0.7。这个分数表明,重排序技术能够显著提高检索结果的质量,从而提高生成回答的准确性。这也说明,对检索结果进行重新排序是一个非常重要的步骤,能够帮助我们更好地利用检索到的信息。</span></p> <h2 data-tool="mdnice编辑器" style="background-color: rgb(251, 251, 251);margin-top: 50px;margin-bottom: 20px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(255, 255, 255);background-color: rgb(33, 33, 34);line-height: 1.5em;letter-spacing: 0em;padding-top: 8px;padding-bottom: 8px;padding-left: 15px;padding-right: 30px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 40px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">8. 相关段落提取(RSE):寻找连续的相关文本</span></span><span style="display: none;"></span></h2> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img src="/upload/dbcb9c17b4b49d888e7ce87cef82bcd5.png" class="rich_pages wxw-img" data-ratio="0.26857142857142857" data-type="png" data-w="700" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;" data-imgfileid="100006387"></span> </figure> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">在前面的讨论中,我们主要关注了如何改进文本块的表示和检索策略,以及如何改进查询的质量和检索结果的排序。然而,我们忽略了一个重要的问题:有时候,最佳的信息可能分散在多个连续的文本块中。那么,有没有一种方法能够让系统自动识别并提取这些连续的相关文本呢?</span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">相关段落提取(Relevant Segment Extraction,RSE)</span></strong><span leaf="">技术为我们提供了一个解决方案。它不是简单地检索最相关的文本块,而是尝试识别并提取整个相关段落。</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg ijdpq631cvfpzevp7c96gnruqn0u3fiancwzhdxoqs1pvknfalxbssriccrluvnayrvtcp9zwfopqiaotazjtnke4qtwezjoiczs 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf=""># 运行 RAG 并应用相关段落提取</span></span><span leaf=""><br></span><span leaf="">rse_result = rag_with_rse(pdf_path, query)</span><span leaf=""><br></span></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">这种方法能够为生成回答提供更连贯和完整的上下文信息,从而提高回答的质量。经过测试,相关段落提取的评分达到了 0.8。这个分数表明,相关段落提取技术能够显著提高检索结果的质量,从而提高生成回答的准确性。这也说明,识别并提取连续的相关文本是一个非常重要的步骤,能够帮助我们更好地利用检索到的信息。</span></p> <h2 data-tool="mdnice编辑器" style="background-color: rgb(251, 251, 251);margin-top: 50px;margin-bottom: 20px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(255, 255, 255);background-color: rgb(33, 33, 34);line-height: 1.5em;letter-spacing: 0em;padding-top: 8px;padding-bottom: 8px;padding-left: 15px;padding-right: 30px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 40px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">9. 上下文压缩:让信息更精炼</span></span><span style="display: none;"></span></h2> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img src="/upload/43316efaee43bec113d5124d2034e0f8.png" class="rich_pages wxw-img" data-ratio="0.2957142857142857" data-type="png" data-w="700" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;" data-imgfileid="100006384"></span> </figure> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">在前面的讨论中,我们主要关注了如何改进文本块的表示和检索策略,以及如何改进查询的质量和检索结果的排序,以及如何识别并提取连续的相关文本。然而,我们忽略了一个重要的问题:有时候,检索到的信息可能过于冗长,包含了大量与查询不相关的内容。这不仅会浪费计算资源,还可能会影响生成回答的质量。那么,有没有一种方法能够让检索到的信息更精炼,只保留与查询最相关的内容呢?</span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">上下文压缩(Contextual Compression)</span></strong><span leaf="">技术为我们提供了一个解决方案。它在检索到文本块之后,通过一个额外的步骤对文本块进行压缩,只保留与查询最相关的内容。</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg ijdpq631cvfpzevp7c96gnruqn0u3fiancwzhdxoqs1pvknfalxbssriccrluvnayrvtcp9zwfopqiaotazjtnke4qtwezjoiczs 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf=""># 定义上下文压缩函数</span></span><span leaf=""><br></span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">def</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">rag_with_compression</span></span><span style="line-height: 26px;"><span leaf="">(pdf_path, query, k=</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">10</span></span><span leaf="">, compression_type=</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"selective"</span></span><span leaf="">, model=</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"meta-llama/Llama-3.2-3B-Instruct"</span></span><span leaf="">)</span></span><span leaf="">:</span></span><span leaf=""><br></span><span leaf=""> vector_store = process_document(pdf_path)</span><span leaf=""><br></span><span leaf=""> results = vector_store.similarity_search(create_embeddings(query), k=k)</span><span leaf=""><br></span><span leaf=""> retrieved_chunks = [r[</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"text"</span></span><span leaf="">] </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">for</span></span><span leaf=""> r </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">in</span></span><span leaf=""> results]</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> compressed = batch_compress_chunks(retrieved_chunks, query, compression_type, model)</span><span leaf=""><br></span><span leaf=""> compressed_chunks, compression_ratios = zip([(c, r) </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">for</span></span><span leaf=""> c, r </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">in</span></span><span leaf=""> compressed </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">if</span></span><span leaf=""> c.strip()] </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">or</span></span><span leaf=""> [(chunk, </span><span style="color: #d19a66;line-height: 26px;"><span leaf="">0.0</span></span><span leaf="">) </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">for</span></span><span leaf=""> chunk </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">in</span></span><span leaf=""> retrieved_chunks])</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> context = </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"\n\n---\n\n"</span></span><span leaf="">.join(compressed_chunks)</span><span leaf=""><br></span><span leaf=""> response = generate_response(query, context, model)</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">return</span></span><span leaf=""> {</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"query"</span></span><span leaf="">: query,</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"original_chunks"</span></span><span leaf="">: retrieved_chunks,</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"compressed_chunks"</span></span><span leaf="">: compressed_chunks,</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"compression_ratios"</span></span><span leaf="">: compression_ratios,</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"context_length_reduction"</span></span><span leaf="">: </span><span style="color: #98c379;line-height: 26px;"><span leaf="">f"</span><span style="color: #e06c75;line-height: 26px;"><span leaf="">{sum(compression_ratios)/len(compression_ratios):</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">.2</span></span><span leaf="">f}</span></span><span leaf="">%"</span></span><span leaf="">,</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"response"</span></span><span leaf="">: response</span><span leaf=""><br></span><span leaf=""> }</span><span leaf=""><br></span></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">这种方法的效果如何呢?经过测试,上下文压缩的评分达到了 0.75。这个分数表明,上下文压缩技术能够显著提高检索结果的质量,从而提高生成回答的准确性。这也说明,对检索到的信息进行压缩是一个非常重要的步骤,能够帮助我们更好地利用检索到的信息。</span></p> <h2 data-tool="mdnice编辑器" style="background-color: rgb(251, 251, 251);margin-top: 50px;margin-bottom: 20px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(255, 255, 255);background-color: rgb(33, 33, 34);line-height: 1.5em;letter-spacing: 0em;padding-top: 8px;padding-bottom: 8px;padding-left: 15px;padding-right: 30px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 40px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">10. 反馈循环:让系统不断学习</span></span><span style="display: none;"></span></h2> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img src="/upload/0c26df49063e39b6616622fac3934d20.png" class="rich_pages wxw-img" data-ratio="0.3271428571428571" data-type="png" data-w="700" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;" data-imgfileid="100006389"></span> </figure> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">在前面的讨论中,我们主要关注了如何改进文本块的表示和检索策略,以及如何改进查询的质量和检索结果的排序,以及如何识别并提取连续的相关文本,以及如何对检索到的信息进行压缩。然而,我们忽略了一个重要的问题:这些改进都是基于预先设定的策略,系统无法根据实际的使用情况进行自我调整。那么,有没有一种方法能够让系统根据用户的反馈不断学习和调整呢?</span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">反馈循环(Feedback Loop)</span></strong><span leaf="">技术为我们提供了一个解决方案。它允许用户对系统的回答进行评价,并将这些评价作为反馈信息存储起来。在后续的检索过程中,系统会根据这些反馈信息对检索策略进行调整,从而提高检索结果的质量。</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg ijdpq631cvfpzevp7c96gnruqn0u3fiancwzhdxoqs1pvknfalxbssriccrluvnayrvtcp9zwfopqiaotazjtnke4qtwezjoiczs 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf=""># 定义完整的 RAG 流程,包含反馈机制</span></span><span leaf=""><br></span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">def</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">full_rag_workflow</span></span><span style="line-height: 26px;"><span leaf="">(pdf_path, query, feedback_data=None, feedback_file=</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"feedback_data.json"</span></span><span leaf="">, fine_tune=False)</span></span><span leaf="">:</span></span><span leaf=""><br></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">if</span></span><span leaf=""> feedback_data </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">is</span></span><span style="color: #56b6c2;line-height: 26px;"><span leaf="">None</span></span><span leaf="">:</span><span leaf=""><br></span><span leaf=""> feedback_data = load_feedback_data(feedback_file)</span><span leaf=""><br></span><span leaf=""> print(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">f"Loaded </span><span style="color: #e06c75;line-height: 26px;"><span leaf="">{len(feedback_data)}</span></span><span leaf=""> feedback entries from </span><span style="color: #e06c75;line-height: 26px;"><span leaf="">{feedback_file}</span></span><span leaf="">"</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> chunks, vector_store = process_document(pdf_path)</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">if</span></span><span leaf=""> fine_tune </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">and</span></span><span leaf=""> feedback_data:</span><span leaf=""><br></span><span leaf=""> vector_store = fine_tune_index(vector_store, chunks, feedback_data)</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> result = rag_with_feedback_loop(query, vector_store, feedback_data)</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> print(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"\n=== Would you like to provide feedback on this response? ==="</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf=""> print(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"Rate relevance (1-5, with 5 being most relevant):"</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf=""> relevance = input()</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> print(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"Rate quality (1-5, with 5 being highest quality):"</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf=""> quality = input()</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> print(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"Any comments? (optional, press Enter to skip)"</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf=""> comments = input()</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> feedback = get_user_feedback(</span><span leaf=""><br></span><span leaf=""> query=query,</span><span leaf=""><br></span><span leaf=""> response=result[</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"response"</span></span><span leaf="">],</span><span leaf=""><br></span><span leaf=""> relevance=int(relevance),</span><span leaf=""><br></span><span leaf=""> quality=int(quality),</span><span leaf=""><br></span><span leaf=""> comments=comments</span><span leaf=""><br></span><span leaf=""> )</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> store_feedback(feedback, feedback_file)</span><span leaf=""><br></span><span leaf=""> print(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"Feedback recorded. Thank you!"</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">return</span></span><span leaf=""> result</span><span leaf=""><br></span></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">这种方法的效果如何呢?经过测试,反馈循环的评分达到了 0.7。虽然这个分数并不高,但它仍然表明反馈循环技术能够让系统不断学习和调整,从而提高检索结果的质量。这也说明,用户反馈是一个非常重要的资源,能够帮助系统更好地满足用户的需求。</span></p> <h2 data-tool="mdnice编辑器" style="background-color: rgb(251, 251, 251);margin-top: 50px;margin-bottom: 20px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(255, 255, 255);background-color: rgb(33, 33, 34);line-height: 1.5em;letter-spacing: 0em;padding-top: 8px;padding-bottom: 8px;padding-left: 15px;padding-right: 30px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 40px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">11. Adaptive RAG:智能选择检索策略</span></span><span style="display: none;"></span></h2> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img src="/upload/a96661311c6fe3c024702551348dae9b.png" class="rich_pages wxw-img" data-ratio="0.58" data-type="png" data-w="700" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;" data-imgfileid="100006391"></span> </figure> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">在前面的讨论中,我们主要关注了如何改进文本块的表示和检索策略,以及如何改进查询的质量和检索结果的排序,以及如何识别并提取连续的相关文本,以及如何对检索到的信息进行压缩,以及如何根据用户的反馈不断学习和调整。然而,我们忽略了一个重要的问题:不同的查询可能需要不同的检索策略。那么,有没有一种方法能够让系统根据查询的类型自动选择最合适的检索策略呢?</span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">自适应 RAG(Adaptive RAG)</span></strong><span leaf="">技术为我们提供了一个解决方案。它根据查询的类型,自动选择最合适的检索策略。例如,对于事实性查询,系统会选择事实检索策略;对于分析性查询,系统会选择分析检索策略;对于观点性查询,系统会选择观点检索策略;对于上下文相关查询,系统会选择上下文检索策略。</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg ijdpq631cvfpzevp7c96gnruqn0u3fiancwzhdxoqs1pvknfalxbssriccrluvnayrvtcp9zwfopqiaotazjtnke4qtwezjoiczs 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf=""># 定义自适应 RAG 函数</span></span><span leaf=""><br></span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">def</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">rag_with_adaptive_retrieval</span></span><span style="line-height: 26px;"><span leaf="">(pdf_path, query, k=</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">4</span></span><span leaf="">, user_context=None)</span></span><span leaf="">:</span></span><span leaf=""><br></span><span leaf=""> chunks, vector_store = process_document(pdf_path)</span><span leaf=""><br></span><span leaf=""> query_type = classify_query(query)</span><span leaf=""><br></span><span leaf=""> print(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">f"Query classified as: </span><span style="color: #e06c75;line-height: 26px;"><span leaf="">{query_type}</span></span><span leaf="">"</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> retrieved_docs = adaptive_retrieval(query, vector_store, k, user_context)</span><span leaf=""><br></span><span leaf=""> response = generate_response(query, retrieved_docs, query_type)</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">return</span></span><span leaf=""> {</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"query"</span></span><span leaf="">: query,</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"query_type"</span></span><span leaf="">: query_type,</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"retrieved_documents"</span></span><span leaf="">: retrieved_docs,</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"response"</span></span><span leaf="">: response</span><span leaf=""><br></span><span leaf=""> }</span><span leaf=""><br></span></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">这种方法的效果如何呢?经过测试,自适应 RAG 的评分达到了 0.86,这是所有方法中最高的分数。这个分数表明,自适应 RAG 技术能够显著提高检索结果的质量,从而提高生成回答的准确性。这也说明,根据查询的类型自动选择检索策略是一个非常重要的步骤,能够帮助我们更好地利用检索到的信息。</span></p> <h2 data-tool="mdnice编辑器" style="background-color: rgb(251, 251, 251);margin-top: 50px;margin-bottom: 20px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(255, 255, 255);background-color: rgb(33, 33, 34);line-height: 1.5em;letter-spacing: 0em;padding-top: 8px;padding-bottom: 8px;padding-left: 15px;padding-right: 30px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 40px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">12. Self RAG:让系统自我反思</span></span><span style="display: none;"></span></h2> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img src="/upload/5aa021b0cf568fc88dd4f1b6e216e697.png" class="rich_pages wxw-img" data-ratio="0.23857142857142857" data-type="png" data-w="700" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;" data-imgfileid="100006390"></span> </figure> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">在前面的讨论中,我们主要关注了如何改进文本块的表示和检索策略,以及如何改进查询的质量和检索结果的排序,以及如何识别并提取连续的相关文本,以及如何对检索到的信息进行压缩,以及如何根据用户的反馈不断学习和调整,以及如何根据查询的类型自动选择检索策略。然而,我们忽略了一个重要的问题:系统是否能够自我反思,判断是否需要检索,以及如何利用检索到的信息呢?</span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">自我 RAG(Self RAG)</span></strong><span leaf="">技术为我们提供了一个解决方案。它不仅能够检索和生成回答,还能够自我反思,判断是否需要检索,以及如何利用检索到的信息。</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg ijdpq631cvfpzevp7c96gnruqn0u3fiancwzhdxoqs1pvknfalxbssriccrluvnayrvtcp9zwfopqiaotazjtnke4qtwezjoiczs 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf=""># 运行自我 RAG</span></span><span leaf=""><br></span><span leaf="">result = self_rag(query, vector_store)</span><span leaf=""><br></span></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">这种方法的效果如何呢?经过测试,自我 RAG 的评分达到了 0.65。虽然这个分数并不高,但它仍然表明自我 RAG 技术能够让系统更加智能和灵活。这也说明,自我反思是一个非常重要的能力,能够帮助系统更好地适应不同的查询需求。</span></p> <h2 data-tool="mdnice编辑器" style="background-color: rgb(251, 251, 251);margin-top: 50px;margin-bottom: 20px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(255, 255, 255);background-color: rgb(33, 33, 34);line-height: 1.5em;letter-spacing: 0em;padding-top: 8px;padding-bottom: 8px;padding-left: 15px;padding-right: 30px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 40px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">13. Knowledge Graph:构建知识网络</span></span><span style="display: none;"></span></h2> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img src="/upload/dcdb4e989849cb304b701a82c1433dd3.png" class="rich_pages wxw-img" data-ratio="0.4442857142857143" data-type="png" data-w="700" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;" data-imgfileid="100006388"></span> </figure> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">在前面的讨论中,我们主要关注了如何改进文本块的表示和检索策略,以及如何改进查询的质量和检索结果的排序,以及如何识别并提取连续的相关文本,以及如何对检索到的信息进行压缩,以及如何根据用户的反馈不断学习和调整,以及如何根据查询的类型自动选择检索策略,以及如何让系统自我反思。然而,我们忽略了一个重要的问题:文档中的信息可能是相互关联的,如何构建一个知识网络,将这些信息有机地结合起来呢?</span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">知识图谱 RAG(Knowledge Graph RAG)</span></strong><span leaf="">技术为我们提供了一个解决方案。它将文档中的信息构建成一个知识图谱,其中节点代表概念、实体或信息片段,边代表这些节点之间的关系。</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg ijdpq631cvfpzevp7c96gnruqn0u3fiancwzhdxoqs1pvknfalxbssriccrluvnayrvtcp9zwfopqiaotazjtnke4qtwezjoiczs 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf=""># 构建知识图谱</span></span><span leaf=""><br></span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">def</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">build_knowledge_graph</span></span><span style="line-height: 26px;"><span leaf="">(chunks)</span></span><span leaf="">:</span></span><span leaf=""><br></span><span leaf=""> graph, texts = nx.Graph(), [c[</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"text"</span></span><span leaf="">] </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">for</span></span><span leaf=""> c </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">in</span></span><span leaf=""> chunks]</span><span leaf=""><br></span><span leaf=""> embeddings = create_embeddings(texts)</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">for</span></span><span leaf=""> i, (chunk, emb) </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">in</span></span><span leaf=""> enumerate(zip(chunks, embeddings)):</span><span leaf=""><br></span><span leaf=""> graph.add_node(i, text=chunk[</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"text"</span></span><span leaf="">], concepts=extract_concepts(chunk[</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"text"</span></span><span leaf="">]), embedding=emb)</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">for</span></span><span leaf=""> i, j </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">in</span></span><span leaf=""> ((i, j) </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">for</span></span><span leaf=""> i </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">in</span></span><span leaf=""> range(len(chunks)) </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">for</span></span><span leaf=""> j </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">in</span></span><span leaf=""> range(i + </span><span style="color: #d19a66;line-height: 26px;"><span leaf="">1</span></span><span leaf="">, len(chunks))):</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">if</span></span><span leaf=""> shared_concepts := set(graph.nodes[i][</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"concepts"</span></span><span leaf="">]) & set(graph.nodes[j][</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"concepts"</span></span><span leaf="">]):</span><span leaf=""><br></span><span leaf=""> sim = np.dot(embeddings[i], embeddings[j]) / (np.linalg.norm(embeddings[i]) * np.linalg.norm(embeddings[j]))</span><span leaf=""><br></span><span leaf=""> weight = </span><span style="color: #d19a66;line-height: 26px;"><span leaf="">0.7</span></span><span leaf=""> * sim + </span><span style="color: #d19a66;line-height: 26px;"><span leaf="">0.3</span></span><span leaf=""> * (len(shared_concepts) / min(len(graph.nodes[i][</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"concepts"</span></span><span leaf="">]), len(graph.nodes[j][</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"concepts"</span></span><span leaf="">])))</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">if</span></span><span leaf=""> weight > </span><span style="color: #d19a66;line-height: 26px;"><span leaf="">0.6</span></span><span leaf="">:</span><span leaf=""><br></span><span leaf=""> graph.add_edge(i, j, weight=weight, similarity=sim, shared_concepts=list(shared_concepts))</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> print(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">f"Graph built: </span><span style="color: #e06c75;line-height: 26px;"><span leaf="">{graph.number_of_nodes()}</span></span><span leaf=""> nodes, </span><span style="color: #e06c75;line-height: 26px;"><span leaf="">{graph.number_of_edges()}</span></span><span leaf=""> edges"</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">return</span></span><span leaf=""> graph, embeddings</span><span leaf=""><br></span></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">在检索过程中,系统不仅能够检索与查询直接相关的节点,还能够通过遍历知识图谱找到间接相关的节点,从而为生成回答提供更全面的上下文信息。经过测试,知识图谱 RAG 的评分达到了 0.78。这个分数表明,知识图谱 RAG 技术能够显著提高检索结果的质量,从而提高生成回答的准确性。这也说明,构建知识图谱是一个非常重要的步骤,能够帮助我们更好地利用文档中的信息。</span></p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img src="/upload/a173c42435d8321bab493377c55697b3.png" class="rich_pages wxw-img" data-ratio="0.8314285714285714" data-type="png" data-w="700" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;" data-imgfileid="100006392"></span> </figure> <h2 data-tool="mdnice编辑器" style="background-color: rgb(251, 251, 251);margin-top: 50px;margin-bottom: 20px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(255, 255, 255);background-color: rgb(33, 33, 34);line-height: 1.5em;letter-spacing: 0em;padding-top: 8px;padding-bottom: 8px;padding-left: 15px;padding-right: 30px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 40px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">14. 层次化索引:平衡上下文和精确性</span></span><span style="display: none;"></span></h2> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img src="/upload/42af1c2e6e43a1f7c493466c7727291b.png" class="rich_pages wxw-img" data-ratio="0.3314285714285714" data-type="png" data-w="700" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;" data-imgfileid="100006395"></span> </figure> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">在前面的讨论中,我们主要关注了如何改进文本块的表示和检索策略,以及如何改进查询的质量和检索结果的排序,以及如何识别并提取连续的相关文本,以及如何对检索到的信息进行压缩,以及如何根据用户的反馈不断学习和调整,以及如何根据查询的类型自动选择检索策略,以及如何让系统自我反思,以及如何构建知识图谱。然而,我们忽略了一个重要的问题:如何平衡上下文信息和检索的精确性呢?</span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">层次化索引(Hierarchical Indices)</span></strong><span leaf="">技术为我们提供了一个解决方案。它创建了两个层次的表示:摘要和详细文本块。首先,系统在摘要层次进行检索,快速缩小相关文档的范围;然后,在详细文本块层次进行检索,提供精确的检索结果。</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg ijdpq631cvfpzevp7c96gnruqn0u3fiancwzhdxoqs1pvknfalxbssriccrluvnayrvtcp9zwfopqiaotazjtnke4qtwezjoiczs 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf=""># 定义层次化 RAG 函数</span></span><span leaf=""><br></span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">def</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">hierarchical_rag</span></span><span style="line-height: 26px;"><span leaf="">(query, pdf_path, chunk_size=</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">1000</span></span><span leaf="">, chunk_overlap=</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">200</span></span><span leaf="">, k_summaries=</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">3</span></span><span leaf="">, k_chunks=</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">5</span></span><span leaf="">, regenerate=False)</span></span><span leaf="">:</span></span><span leaf=""><br></span><span leaf=""> summary_store_file = </span><span style="color: #98c379;line-height: 26px;"><span leaf="">f"</span><span style="color: #e06c75;line-height: 26px;"><span leaf="">{os.path.basename(pdf_path)}</span></span><span leaf="">_summary_store.pkl"</span></span><span leaf=""><br></span><span leaf=""> detailed_store_file = </span><span style="color: #98c379;line-height: 26px;"><span leaf="">f"</span><span style="color: #e06c75;line-height: 26px;"><span leaf="">{os.path.basename(pdf_path)}</span></span><span leaf="">_detailed_store.pkl"</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">if</span></span><span leaf=""> regenerate </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">or</span></span><span style="color: #c678dd;line-height: 26px;"><span leaf="">not</span></span><span leaf=""> os.path.exists(summary_store_file) </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">or</span></span><span style="color: #c678dd;line-height: 26px;"><span leaf="">not</span></span><span leaf=""> os.path.exists(detailed_store_file):</span><span leaf=""><br></span><span leaf=""> print(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"Processing document and creating vector stores..."</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf=""> summary_store, detailed_store = process_document_hierarchically(pdf_path, chunk_size, chunk_overlap)</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">with</span></span><span leaf=""> open(summary_store_file, </span><span style="color: #98c379;line-height: 26px;"><span leaf="">'wb'</span></span><span leaf="">) </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">as</span></span><span leaf=""> f:</span><span leaf=""><br></span><span leaf=""> pickle.dump(summary_store, f)</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">with</span></span><span leaf=""> open(detailed_store_file, </span><span style="color: #98c379;line-height: 26px;"><span leaf="">'wb'</span></span><span leaf="">) </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">as</span></span><span leaf=""> f:</span><span leaf=""><br></span><span leaf=""> pickle.dump(detailed_store, f)</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">else</span></span><span leaf="">:</span><span leaf=""><br></span><span leaf=""> print(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"Loading existing vector stores..."</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">with</span></span><span leaf=""> open(summary_store_file, </span><span style="color: #98c379;line-height: 26px;"><span leaf="">'rb'</span></span><span leaf="">) </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">as</span></span><span leaf=""> f:</span><span leaf=""><br></span><span leaf=""> summary_store = pickle.load(f)</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">with</span></span><span leaf=""> open(detailed_store_file, </span><span style="color: #98c379;line-height: 26px;"><span leaf="">'rb'</span></span><span leaf="">) </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">as</span></span><span leaf=""> f:</span><span leaf=""><br></span><span leaf=""> detailed_store = pickle.load(f)</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> retrieved_chunks = retrieve_hierarchically(query, summary_store, detailed_store, k_summaries, k_chunks)</span><span leaf=""><br></span><span leaf=""> response = generate_response(query, retrieved_chunks)</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">return</span></span><span leaf=""> {</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"query"</span></span><span leaf="">: query,</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"response"</span></span><span leaf="">: response,</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"retrieved_chunks"</span></span><span leaf="">: retrieved_chunks,</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"summary_count"</span></span><span leaf="">: len(summary_store.texts),</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"detailed_count"</span></span><span leaf="">: len(detailed_store.texts)</span><span leaf=""><br></span><span leaf=""> }</span><span leaf=""><br></span></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">这种方法既保留了上下文信息,又提高了检索的精确性。经过测试,层次化索引的评分达到了 0.84。这个分数表明,层次化索引技术能够显著提高检索结果的质量,从而提高生成回答的准确性。这也说明,平衡上下文信息和检索精确性是一个非常重要的步骤,能够帮助我们更好地利用检索到的信息。</span></p> <h2 data-tool="mdnice编辑器" style="background-color: rgb(251, 251, 251);margin-top: 50px;margin-bottom: 20px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(255, 255, 255);background-color: rgb(33, 33, 34);line-height: 1.5em;letter-spacing: 0em;padding-top: 8px;padding-bottom: 8px;padding-left: 15px;padding-right: 30px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 40px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">15. HyDE:从假设文档出发</span></span><span style="display: none;"></span></h2> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img src="/upload/3bc7dc98dbade013dad27c07d74d8d44.png" class="rich_pages wxw-img" data-ratio="0.29" data-type="png" data-w="700" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;" data-imgfileid="100006396"></span> </figure> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">在前面的讨论中,我们主要关注了如何改进文本块的表示和检索策略,以及如何改进查询的质量和检索结果的排序,以及如何识别并提取连续的相关文本,以及如何对检索到的信息进行压缩,以及如何根据用户的反馈不断学习和调整,以及如何根据查询的类型自动选择检索策略,以及如何让系统自我反思,以及如何构建知识图谱,以及如何平衡上下文信息和检索精确性。然而,我们忽略了一个重要的问题:如何更好地表示查询,以便更准确地检索到相关信息呢?</span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">HyDE(Hypothetical Document Embedding)</span></strong><span leaf="">技术为我们提供了一个解决方案。它不是直接对查询进行嵌入,而是先生成一个假设文档,这个文档是查询的理想答案。然后,系统对这个假设文档进行嵌入,并利用这个嵌入进行检索。</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg ijdpq631cvfpzevp7c96gnruqn0u3fiancwzhdxoqs1pvknfalxbssriccrluvnayrvtcp9zwfopqiaotazjtnke4qtwezjoiczs 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf=""># 定义 HyDE RAG 函数</span></span><span leaf=""><br></span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">def</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">hyde_rag</span></span><span style="line-height: 26px;"><span leaf="">(query, vector_store, k=</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">5</span></span><span leaf="">, should_generate_response=True)</span></span><span leaf="">:</span></span><span leaf=""><br></span><span leaf=""> print(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">f"\n=== Processing query with HyDE: </span><span style="color: #e06c75;line-height: 26px;"><span leaf="">{query}</span></span><span leaf=""> ===\n"</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> print(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"Generating hypothetical document..."</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf=""> hypothetical_doc = generate_hypothetical_document(query)</span><span leaf=""><br></span><span leaf=""> print(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">f"Generated hypothetical document of </span><span style="color: #e06c75;line-height: 26px;"><span leaf="">{len(hypothetical_doc)}</span></span><span leaf=""> characters"</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> print(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"Creating embedding for hypothetical document..."</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf=""> hypothetical_embedding = create_embeddings([hypothetical_doc])[</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">0</span></span><span leaf="">]</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> print(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">f"Retrieving </span><span style="color: #e06c75;line-height: 26px;"><span leaf="">{k}</span></span><span leaf=""> most similar chunks..."</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf=""> retrieved_chunks = vector_store.similarity_search(hypothetical_embedding, k=k)</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> results = {</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"query"</span></span><span leaf="">: query,</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"hypothetical_document"</span></span><span leaf="">: hypothetical_doc,</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"retrieved_chunks"</span></span><span leaf="">: retrieved_chunks</span><span leaf=""><br></span><span leaf=""> }</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">if</span></span><span leaf=""> should_generate_response:</span><span leaf=""><br></span><span leaf=""> print(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"Generating final response..."</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf=""> response = generate_response(query, retrieved_chunks)</span><span leaf=""><br></span><span leaf=""> results[</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"response"</span></span><span leaf="">] = response</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">return</span></span><span leaf=""> results</span><span leaf=""><br></span></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">这种方法能够更好地捕捉查询的语义信息,从而提高检索的准确性。经过测试,HyDE 的评分达到了 0.5。虽然这个分数并不高,但它仍然表明 HyDE 技术在某些情况下能够提高检索的准确性。这也说明,从假设文档出发是一个非常有趣的思路,能够帮助我们更好地表示查询。</span></p> <h2 data-tool="mdnice编辑器" style="background-color: rgb(251, 251, 251);margin-top: 50px;margin-bottom: 20px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(255, 255, 255);background-color: rgb(33, 33, 34);line-height: 1.5em;letter-spacing: 0em;padding-top: 8px;padding-bottom: 8px;padding-left: 15px;padding-right: 30px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 40px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">16. 融合 RAG:结合多种检索方法</span></span><span style="display: none;"></span></h2> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img src="/upload/fcb36af1fc6d0c0c5f3aeabfb154551a.png" class="rich_pages wxw-img" data-ratio="0.22" data-type="png" data-w="700" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;" data-imgfileid="100006397"></span> </figure> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">在前面的讨论中,我们主要关注了如何改进文本块的表示和检索策略,以及如何改进查询的质量和检索结果的排序,以及如何识别并提取连续的相关文本,以及如何对检索到的信息进行压缩,以及如何根据用户的反馈不断学习和调整,以及如何根据查询的类型自动选择检索策略,以及如何让系统自我反思,以及如何构建知识图谱,以及如何平衡上下文信息和检索精确性,以及如何从假设文档出发。然而,我们忽略了一个重要的问题:不同的检索方法有各自的优缺点,如何将它们结合起来,发挥各自的优点呢?</span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">融合 RAG(Fusion RAG)</span></strong><span leaf="">技术为我们提供了一个解决方案。它结合了向量检索和关键词检索两种方法,取两者的优点,为检索结果提供更全面的语义信息和精确的关键词匹配。</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg ijdpq631cvfpzevp7c96gnruqn0u3fiancwzhdxoqs1pvknfalxbssriccrluvnayrvtcp9zwfopqiaotazjtnke4qtwezjoiczs 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf=""># 定义融合检索函数</span></span><span leaf=""><br></span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">def</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">fusion_retrieval</span></span><span style="line-height: 26px;"><span leaf="">(query, chunks, vector_store, bm25_index, k=</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">5</span></span><span leaf="">, alpha=</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">0.5</span></span><span leaf="">)</span></span><span leaf="">:</span></span><span leaf=""><br></span><span leaf=""> query_embedding = create_embeddings(query)</span><span leaf=""><br></span><span leaf=""> vector_results = {r[</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"metadata"</span></span><span leaf="">][</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"index"</span></span><span leaf="">]: r[</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"similarity"</span></span><span leaf="">] </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">for</span></span><span leaf=""> r </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">in</span></span><span leaf=""> vector_store.similarity_search_with_scores(query_embedding, len(chunks))}</span><span leaf=""><br></span><span leaf=""> bm25_results = {r[</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"metadata"</span></span><span leaf="">][</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"index"</span></span><span leaf="">]: r[</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"bm25_score"</span></span><span leaf="">] </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">for</span></span><span leaf=""> r </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">in</span></span><span leaf=""> bm25_search(bm25_index, chunks, query, len(chunks))}</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> all_docs = vector_store.get_all_documents()</span><span leaf=""><br></span><span leaf=""> scores = [(i, alpha * vector_results.get(i, </span><span style="color: #d19a66;line-height: 26px;"><span leaf="">0</span></span><span leaf="">) + (</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">1</span></span><span leaf=""> - alpha) * bm25_results.get(i, </span><span style="color: #d19a66;line-height: 26px;"><span leaf="">0</span></span><span leaf="">)) </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">for</span></span><span leaf=""> i </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">in</span></span><span leaf=""> range(len(all_docs))]</span><span leaf=""><br></span><span leaf=""> top_docs = sorted(scores, key=</span><span style="color: #c678dd;line-height: 26px;"><span leaf="">lambda</span></span><span leaf=""> x: x[</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">1</span></span><span leaf="">], reverse=</span><span style="color: #56b6c2;line-height: 26px;"><span leaf="">True</span></span><span leaf="">)[:k]</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">return</span></span><span leaf=""> [{</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"text"</span></span><span leaf="">: all_docs[i][</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"text"</span></span><span leaf="">], </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"metadata"</span></span><span leaf="">: all_docs[i][</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"metadata"</span></span><span leaf="">], </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"score"</span></span><span leaf="">: s} </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">for</span></span><span leaf=""> i, s </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">in</span></span><span leaf=""> top_docs]</span><span leaf=""><br></span></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">这种方法能够更好地满足不同查询的需求,提高检索的准确性。经过测试,融合 RAG 的评分达到了 0.83。这个分数表明,融合 RAG 技术能够显著提高检索结果的质量,从而提高生成回答的准确性。这也说明,结合多种检索方法是一个非常有效的策略,能够帮助我们更好地利用检索到的信息。</span></p> <h2 data-tool="mdnice编辑器" style="background-color: rgb(251, 251, 251);margin-top: 50px;margin-bottom: 20px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(255, 255, 255);background-color: rgb(33, 33, 34);line-height: 1.5em;letter-spacing: 0em;padding-top: 8px;padding-bottom: 8px;padding-left: 15px;padding-right: 30px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 40px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">17. 多模态RAG:解锁图像信息</span></span><span style="display: none;"></span></h2> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img src="/upload/4d821ac017ec79184f47d21cee888cf4.png" class="rich_pages wxw-img" data-ratio="0.31142857142857144" data-type="png" data-w="700" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;" data-imgfileid="100006394"></span> </figure> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">在前面的讨论中,我们主要关注了如何改进文本块的表示和检索策略,以及如何改进查询的质量和检索结果的排序,以及如何识别并提取连续的相关文本,以及如何对检索到的信息进行压缩,以及如何根据用户的反馈不断学习和调整,以及如何根据查询的类型自动选择检索策略,以及如何让系统自我反思,以及如何构建知识图谱,以及如何平衡上下文信息和检索精确性,以及如何从假设文档出发,以及如何结合多种检索方法。然而,我们忽略了一个重要的问题:文档中的信息不仅包含文本,还可能包含图像、图表等其他形式的信息,如何将这些信息也纳入检索范围呢?</span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">多模态 RAG(Multi Model RAG)</span></strong><span leaf="">技术为我们提供了一个解决方案。它不仅从文档中提取文本,还会提取图像,并为图像生成描述性的标题。然后,系统将文本和图像的嵌入向量一起存储在向量库中,从而实现对文本和图像的联合检索。</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg ijdpq631cvfpzevp7c96gnruqn0u3fiancwzhdxoqs1pvknfalxbssriccrluvnayrvtcp9zwfopqiaotazjtnke4qtwezjoiczs 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf=""># 处理多模态文档</span></span><span leaf=""><br></span><span style="line-height: 26px;"><span style="color: #c678dd;line-height: 26px;"><span leaf="">def</span></span><span leaf=""> </span><span style="color: #61aeee;line-height: 26px;"><span leaf="">process_document</span></span><span style="line-height: 26px;"><span leaf="">(pdf_path, chunk_size=</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">1000</span></span><span leaf="">, chunk_overlap=</span><span style="color: #d19a66;line-height: 26px;"><span leaf="">200</span></span><span leaf="">)</span></span><span leaf="">:</span></span><span leaf=""><br></span><span leaf=""> image_dir = </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"extracted_images"</span></span><span leaf=""><br></span><span leaf=""> os.makedirs(image_dir, exist_ok=</span><span style="color: #56b6c2;line-height: 26px;"><span leaf="">True</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> text_data, image_paths = extract_content_from_pdf(pdf_path, image_dir)</span><span leaf=""><br></span><span leaf=""> chunked_text = chunk_text(text_data, chunk_size, chunk_overlap)</span><span leaf=""><br></span><span leaf=""> image_data = process_images(image_paths)</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> all_items = chunked_text + image_data</span><span leaf=""><br></span><span leaf=""> contents = [item[</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"content"</span></span><span leaf="">] </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">for</span></span><span leaf=""> item </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">in</span></span><span leaf=""> all_items]</span><span leaf=""><br></span><span leaf=""> embeddings = create_embeddings(contents)</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> vector_store = MultiModalVectorStore()</span><span leaf=""><br></span><span leaf=""> vector_store.add_items(all_items, embeddings)</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> doc_info = {</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"text_count"</span></span><span leaf="">: len(chunked_text),</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"image_count"</span></span><span leaf="">: len(image_data),</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"total_items"</span></span><span leaf="">: len(all_items),</span><span leaf=""><br></span><span leaf=""> }</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> print(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">f"Added </span><span style="color: #e06c75;line-height: 26px;"><span leaf="">{len(all_items)}</span></span><span leaf=""> items to vector store (</span><span style="color: #e06c75;line-height: 26px;"><span leaf="">{len(chunked_text)}</span></span><span leaf=""> text chunks, </span><span style="color: #e06c75;line-height: 26px;"><span leaf="">{len(image_data)}</span></span><span leaf=""> image captions)"</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">return</span></span><span leaf=""> vector_store, doc_info</span><span leaf=""><br></span></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">这种方法能够更好地利用文档中的信息,提高检索的准确性。经过测试,多模态 RAG 的评分达到了 0.79。这个分数表明,多模态 RAG 技术能够显著提高检索结果的质量,从而提高生成回答的准确性。这也说明,将图像信息纳入检索范围是一个非常重要的步骤,能够帮助我们更好地利用文档中的信息。</span></p> <h2 data-tool="mdnice编辑器" style="background-color: rgb(251, 251, 251);margin-top: 50px;margin-bottom: 20px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(255, 255, 255);background-color: rgb(33, 33, 34);line-height: 1.5em;letter-spacing: 0em;padding-top: 8px;padding-bottom: 8px;padding-left: 15px;padding-right: 30px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 40px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">18. CRAG:动态调整检索策略</span></span><span style="display: none;"></span></h2> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img src="/upload/133b7bd5cfbdd01cb059378d5497d935.png" class="rich_pages wxw-img" data-ratio="0.28714285714285714" data-type="png" data-w="700" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;" data-imgfileid="100006398"></span> </figure> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">在前面的讨论中,我们主要关注了如何改进文本块的表示和检索策略,以及如何改进查询的质量和检索结果的排序,以及如何识别并提取连续的相关文本,以及如何对检索到的信息进行压缩,以及如何根据用户的反馈不断学习和调整,以及如何根据查询的类型自动选择检索策略,以及如何让系统自我反思,以及如何构建知识图谱,以及如何平衡上下文信息和检索精确性,以及如何从假设文档出发,以及如何结合多种检索方法,以及如何将图像信息纳入检索范围。然而,我们忽略了一个重要的问题:检索到的信息可能并不总是理想的,如何动态调整检索策略,以应对不同的情况呢?</span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">纠正性 RAG(Corrective RAG,CRAG)</span></strong><span leaf="">技术为我们提供了一个解决方案。它在检索之后,对检索到的信息进行评估,根据评估结果动态调整检索策略。如果检索到的信息质量高,系统会直接利用这些信息生成回答;如果检索到的信息质量低,系统会转而进行网络搜索;如果检索到的信息质量中等,系统会结合文档信息和网络搜索结果生成回答。</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg ijdpq631cvfpzevp7c96gnruqn0u3fiancwzhdxoqs1pvknfalxbssriccrluvnayrvtcp9zwfopqiaotazjtnke4qtwezjoiczs 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf=""># 运行纠正性 RAG</span></span><span leaf=""><br></span><span leaf="">crag_result = rag_with_compression(pdf_path, query, compression_type=</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"selective"</span></span><span leaf="">)</span><span leaf=""><br></span></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">这种方法能够更好地应对不同的情况,提高检索的准确性和可靠性。经过测试,纠正性 RAG 的评分达到了 0.824。这个分数表明,纠正性 RAG 技术能够显著提高检索结果的质量,从而提高生成回答的准确性。这也说明,动态调整检索策略是一个非常重要的步骤,能够帮助我们更好地利用检索到的信息。</span></p> <h2 data-tool="mdnice编辑器" style="background-color: rgb(251, 251, 251);margin-top: 50px;margin-bottom: 20px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 20px;color: rgb(255, 255, 255);background-color: rgb(33, 33, 34);line-height: 1.5em;letter-spacing: 0em;padding-top: 8px;padding-bottom: 8px;padding-left: 15px;padding-right: 30px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 40px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">结论:选择最适合的 RAG 技术</span></span><span style="display: none;"></span></h2> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">通过上述对 18 种 RAG 技术的测试和分析,我们可以看到,不同的技术有各自的优缺点,适用于不同的场景和需求。简单 RAG 提供了一个基础的框架,但其检索效果有限;语义分块、上下文增强检索、上下文块头、文档增强等技术通过改进文本块的表示和检索策略,提高了检索的准确性;查询转换、重排序、相关段落提取、上下文压缩等技术通过改进查询的质量和检索结果的排序,进一步提高了检索的效果;反馈循环、自适应 RAG、自我 RAG 等技术通过引入反馈机制和动态调整检索策略,让系统能够更好地适应不同的查询需求;知识图谱 RAG、层次化索引、HyDE、融合 RAG、多模态 RAG、纠正性 RAG 等技术通过结合多种方法和信息源,显著提高了检索的准确性和可靠性。</span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">在这些技术中,自适应 RAG 以 0.86 的评分脱颖而出,成为表现最佳的 RAG 技术。它通过根据查询的类型自动选择最合适的检索策略,能够更好地满足不同用户的需求,生成更准确的回答。然而,这并不意味着其他技术没有价值。实际上,不同的技术可以在不同的场景下发挥重要作用,关键在于根据具体的需求和场景选择最适合的技术。</span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">未来,随着人工智能技术的不断发展,RAG 技术也将不断进化。我们可以预见,结合多种技术的优点,开发出更加智能、高效、可靠的 RAG 系统,将为信息检索和自然语言处理领域带来更多的可能性和突破。</span></p> <hr style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: solid;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: 1px;"> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">以上就是对 18 种 RAG 技术的详细分析和代码示例。希望这篇文章能够帮助你更好地了解 RAG 技术的多样性和潜力。如果你对某一种技术特别感兴趣,或者有其他问题,欢迎在评论区留言,我们一起探讨!</span></p> </section> </section> </section>
作者:微信小助手
<section style="text-indent: 2em;"> <span data-pm-slice="0 0 []"><span leaf="" style="color:rgba(0, 0, 0, 0.9);font-size:17px;font-family:" mp-quote, -apple-system-font, blinkmacsystemfont, helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;line-height:1.6;letter-spacing:0.034em;font-style:normal;font-weight:normal; data-pm-slice="1 1 [" para,{tagname:section,attributes:{},namespaceuri:},node,{tagname:span,attributes:{data-pm-slice:0 0 [],style:null},namespaceuri:http: www.w3.org 1999 xhtml}]><span textstyle="" style="font-size: 16px;">上周,百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。</span><span textstyle="" style="font-size: 16px;background-color: #fffb00;">目前提供的MCP工具列表包含8个核心API接口和MCP协议的对接, 涵盖逆地理编码、地点检索、路线规划等</span><span textstyle="" style="font-size: 16px;">。</span></span></span> </section> <section style="text-align: center;" nodeleaf=""> <img class="rich_pages wxw-img js_insertlocalimg" data-imgfileid="100000799" data-ratio="0.937962962962963" data-s="300,640" src="/upload/7b5201b2f25366bd07b61d8b8e750d5d.png" data-type="png" data-w="1080" type="block"> </section> <section style="text-indent: 2em;"> <span leaf="" style="color:rgba(0, 0, 0, 0.9);font-size:17px;font-family:" mp-quote, -apple-system-font, blinkmacsystemfont, helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;line-height:1.6;letter-spacing:0.034em;font-style:normal;font-weight:normal;><span textstyle="" style="font-size: 16px;">我们来实践一下,怎么使用</span></span><span data-pm-slice="0 0 []"><span leaf="" style="color:rgba(0, 0, 0, 0.9);font-size:17px;font-family:" mp-quote, -apple-system-font, blinkmacsystemfont, helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;line-height:1.6;letter-spacing:0.034em;font-style:normal;font-weight:normal;><span textstyle="" style="font-size: 16px;">百度地图MCP Server。</span></span></span> </section> <section> <span leaf="" style="color:rgba(0, 0, 0, 0.9);font-size:17px;font-family:" mp-quote, -apple-system-font, blinkmacsystemfont, helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;line-height:1.6;letter-spacing:0.034em;font-style:normal;font-weight:normal;><span textstyle="" style="font-size: 16px;">一.在百度地图开放平台的控制台中创建一个服务端AK</span></span> </section> <section> <span leaf="" data-pm-slice="1 1 [" para,null] style="color:rgba(0, 0, 0, 0.9);font-size:17px;font-family:" mp-quote, -apple-system-font, blinkmacsystemfont, helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;line-height:1.6;letter-spacing:0.034em;font-style:normal;font-weight:normal;><span textstyle="" style="font-size: 16px;">通过AK你才能够调用百度地图API能力</span></span> </section> <section style="color:rgba(0, 0, 0, 0.9);font-size:17px;font-family:" mp-quote, -apple-system-font, blinkmacsystemfont, helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;line-height:1.6;letter-spacing:0.034em;font-style:normal;font-weight:normal; nodeleaf=""> <img class="rich_pages wxw-img js_insertlocalimg" data-imgfileid="100000795" data-ratio="0.48333333333333334" data-s="300,640" src="/upload/9741e5eaef17186dd9df761341aad1d1.png" data-type="png" data-w="1080" type="block"> </section> <section> <span leaf="" data-pm-slice="1 1 [" para,null] style="color:rgba(0, 0, 0, 0.9);font-size:17px;font-family:" mp-quote, -apple-system-font, blinkmacsystemfont, helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;line-height:1.6;letter-spacing:0.034em;font-style:normal;font-weight:normal;><span textstyle="" style="font-size: 16px;">二.打开 windsurf编辑器</span></span> </section> <section style="text-indent: 2em;"> <span data-pm-slice="0 0 []"><span leaf="" style="color:rgba(0, 0, 0, 0.9);font-size:17px;font-family:" mp-quote, -apple-system-font, blinkmacsystemfont, helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;line-height:1.6;letter-spacing:0.034em;font-style:normal;font-weight:normal;><span textstyle="" style="font-size: 16px;">将以下配置添加到配置文件中,BAIDU_MAP_API_KEY 是访问百度地图开放平台API的AK。</span></span></span> </section> <section style="color:rgba(0, 0, 0, 0.9);font-size:17px;font-family:" mp-quote, -apple-system-font, blinkmacsystemfont, helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;line-height:1.6;letter-spacing:0.034em;font-style:normal;font-weight:normal; nodeleaf=""> <img class="rich_pages wxw-img js_insertlocalimg" data-imgfileid="100000796" data-ratio="0.5712962962962963" data-s="300,640" src="/upload/888e4ec2ecf37542301a478f11e8d768.jpg" data-type="jpeg" data-w="1080" type="block"> </section> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="perl"><code><span leaf="">{</span></code><code><span leaf=""> <span class="code-snippet__string">"mcpServers"</span>: {</span></code><code><span leaf=""> <span class="code-snippet__string">"baidu-map"</span>: {</span></code><code><span leaf=""> <span class="code-snippet__string">"command"</span>: <span class="code-snippet__string">"npx"</span>,</span></code><code><span leaf=""> <span class="code-snippet__string">"args"</span>: [</span></code><code><span leaf=""> <span class="code-snippet__string">"-y"</span>,</span></code><code><span leaf=""> <span class="code-snippet__string">"@baidumap/mcp-server-baidu-map"</span></span></code><code><span leaf=""> ],</span></code><code><span leaf=""> <span class="code-snippet__string">"env"</span>: {</span></code><code><span leaf=""> <span class="code-snippet__string">"BAIDU_MAP_API_KEY"</span>: <span class="code-snippet__string">"xxx"</span></span></code><code><span leaf=""> }</span></code><code><span leaf=""> }</span></code><code><span leaf=""> }</span></code><code><span leaf="">}</span></code></pre> </section> <section style="text-indent: 2em;"> <span data-pm-slice="0 0 []"><span leaf="" style="color:rgba(0, 0, 0, 0.9);font-size:17px;font-family:" mp-quote, -apple-system-font, blinkmacsystemfont, helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;line-height:1.6;letter-spacing:0.034em;font-style:normal;font-weight:normal;><span textstyle="" style="font-size: 16px;">重启windsurf,此时设置面板已经成功加载了百度地图MCP Server。</span></span><span data-pm-slice="0 0 []"><span leaf="" style="color:rgba(0, 0, 0, 0.9);font-size:17px;font-family:" mp-quote, -apple-system-font, blinkmacsystemfont, helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;line-height:1.6;letter-spacing:0.034em;font-style:normal;font-weight:normal;><span textstyle="" style="font-size: 16px;">可以看到有8个可用的MCP工具,点击可以查看详情。</span></span></span></span> </section> <section style="color:rgba(0, 0, 0, 0.9);font-size:17px;font-family:" mp-quote, -apple-system-font, blinkmacsystemfont, helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;line-height:1.6;letter-spacing:0.034em;font-style:normal;font-weight:normal; nodeleaf=""> <img class="rich_pages wxw-img js_insertlocalimg" data-imgfileid="100000797" data-ratio="1.102880658436214" data-s="300,640" src="/upload/e5bf23b9b2a67dfef710978b978c0273.png" data-type="png" data-w="972" type="block"> </section> <section style="text-indent: 2em;"> <span data-pm-slice="0 0 []"><span data-pm-slice="0 0 []"><span leaf="" style="color:rgba(0, 0, 0, 0.9);font-size:17px;font-family:" mp-quote, -apple-system-font, blinkmacsystemfont, helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;line-height:1.6;letter-spacing:0.034em;font-style:normal;font-weight:normal;><span textstyle="" style="font-size: 16px;">接下来就可以进行提问,验证一下,百度mcp的使用。</span></span></span></span> </section> <section style="color:rgba(0, 0, 0, 0.9);font-size:17px;font-family:" mp-quote, -apple-system-font, blinkmacsystemfont, helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;line-height:1.6;letter-spacing:0.034em;font-style:normal;font-weight:normal; nodeleaf=""> <img class="rich_pages wxw-img js_insertlocalimg" data-imgfileid="100000798" data-ratio="1.4346153846153846" data-s="300,640" src="/upload/10283fd450138b7ba04333db97713cb8.png" data-type="png" data-w="1040" type="block"> </section> <section> <span data-pm-slice="0 0 []"><span data-pm-slice="0 0 []"><span leaf="" style="color:rgba(0, 0, 0, 0.9);font-size:17px;font-family:" mp-quote, -apple-system-font, blinkmacsystemfont, helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;line-height:1.6;letter-spacing:0.034em;font-style:normal;font-weight:normal;><br></span></span></span> </section> <p style="display: none;"> <mp-style-type data-value="3"></mp-style-type></p>
作者:微信小助手
<p cid="n0" mdtype="paragraph" style="margin-bottom: 24px;" data-pm-slice="0 0 []"><span md-inline="plain"><span leaf="" style="color:rgba(0, 0, 0, 0.9);font-size:17px;font-family:" mp-quote, -apple-system-font, blinkmacsystemfont, helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;line-height:1.6;letter-spacing:0.034em;font-style:normal;font-weight:normal;>兄弟们,前几天在技术群里看到一个令人窒息的代码片段:</span></span></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t" data-mpa-action-id="m8x51biryow"> <pre style="margin: 0px;padding: 0px;background: none;font-family: none;"><code style="border-radius: 4px;font-size: 0.85em;font-family: none;margin: 0px 0.15em;background: rgb(248, 248, 248);color: rgb(51, 51, 51);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">List</span></span><span leaf=""> <user> users = ...; </user></span><span leaf=""><br></span><span leaf="">Map <long, ></long, ></span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">List</span></span><span leaf=""> <order>> result = users.stream() </order></span><span leaf=""><br></span><span leaf=""> .filter(u -> u.getStatus() == UserStatus.ACTIVE)</span><span leaf=""><br></span><span leaf=""> .filter(u -> u.getAge() > </span><span style="color: rgb(0, 128, 128);background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration: none solid rgb(0, 128, 128);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">18</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf=""> .filter(u -> u.getOrders().size() > </span><span style="color: rgb(0, 128, 128);background: rgba(0, 0, 0, 0);display: inline;width: 7px;text-decoration: none solid rgb(0, 128, 128);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">0</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf=""> .flatMap(u -> u.getOrders().stream())</span><span leaf=""><br></span><span leaf=""> .collect(Collectors.groupingBy(Order::getUserId,</span><span leaf=""><br></span><span leaf=""> Collectors.mapping(Order::getId, Collectors.toList())));</span></code></pre> </section> <p cid="n3" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 0.8em 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">这段代码乍一看很“流式”,但仔细分析就会发现:</span></span></span></p> <ul style="box-sizing: border-box;margin: 0.8em 0px;padding-left: 30px;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial; class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n6" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">连续三个filter像俄罗斯套娃</span></span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n8" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">flatMap后的collect嵌套层数堪比俄罗斯方块</span></span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n10" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">最终结果类型Map>与实际需求完全不符 </span></span></span></p></li> </ul> <p cid="n10" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="plain" style="background-color: transparent;"><span leaf=""><span textstyle="" style="font-size: 17px;">这让我想起最近流行的一句话:</span></span></span><span md-inline="strong" style="background-color: transparent;"><strong><span md-inline="plain"><span leaf=""><span textstyle="" style="font-size: 17px;">“Stream用得好是瑞士军刀,用不好就是小李飞刀——刀刀见血,但扎的是自己。”</span></span></span></strong></span></p> <section mpa-from-tpl="t" data-mpa-action-id="m8x4c4fm1p5w" data-pm-slice="0 0 []"> <span leaf=""><br></span> </section> <section data-mpa-template="t" mpa-from-tpl="t" data-mpa-action-id="m8x4c4fm17nt"> <section data-mpa-template="t" mpa-from-tpl="t"> <h4 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: 400;font-size: 16px;text-align: justify;outline: 0px;color: rgb(34, 34, 34);letter-spacing: 0.544px;caret-color: rgb(51, 51, 51);line-height: 2em;"><span style="font-size: 20px;"><strong mpa-from-tpl="t" style="outline: 0px;"><span mpa-is-content="t" style="font-size: 20px;outline: 0px;color: rgb(0, 122, 170);"><span leaf="">一、Stream变丑的四大“毁容级”操作</span></span></strong></span></h4> </section> </section> <h4 cid="n12" mdtype="heading" style="box-sizing: border-box;break-after: avoid-page;break-inside: avoid;orphans: 2;font-size: 1.25em;margin-top: 1rem;margin-bottom: 1rem;font-weight: bold;line-height: 2em;cursor: text;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">1. 链式调用七龙珠</span></span></span></h4> <p cid="n13" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 0.8em 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">有些同学对链式调用有一种迷之执着,恨不得把所有操作塞进一条流里:</span></span></span></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t" data-mpa-action-id="m8x51twh1sdc"> <pre style="margin: 0px;padding: 0px;background: none;font-family: none;"><code style="border-radius: 4px;font-size: 0.85em;font-family: none;margin: 0px 0.15em;background: rgb(248, 248, 248);color: rgb(51, 51, 51);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">List</span></span><span leaf=""> <string> result = </string></span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">list</span></span><span leaf="">.stream()</span><span leaf=""><br></span><span leaf=""> .filter(...).map(...).flatMap(...).distinct()</span><span leaf=""><br></span><span leaf=""> .sorted(...).limit(...).skip(...).collect(...);</span></code></pre> </section> <p cid="n15" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 24px 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">危害</span></span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">:超过5个操作的链式调用会让代码可读性直线下降,调试时根本分不清问题出在哪一环。</span></span></span><span md-inline="softbreak" style="box-sizing: border-box;"></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><br></span></span></p> <p cid="n15" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 24px 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">解药</span></span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">:</span></span></span></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t" data-mpa-action-id="m8x5279fkiw"> <pre style="margin: 0px;padding: 0px;background: none;font-family: none;"><code style="border-radius: 4px;font-size: 0.85em;font-family: none;margin: 0px 0.15em;background: rgb(248, 248, 248);color: rgb(51, 51, 51);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span style="color: rgb(153, 153, 136);background: rgba(0, 0, 0, 0);display: inline;width: 173px;text-decoration: none solid rgb(153, 153, 136);font-weight: 400;font-style: italic;font-family: none;"><span leaf="">// 分段处理,用中间变量过渡</span></span><span leaf=""><br></span><span leaf="">Stream<</span><span style="color: rgb(0, 134, 179);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(0, 134, 179);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">String</span></span><span leaf="">> filtered = list.stream().filter(...);</span><span leaf=""><br></span><span leaf="">Stream<</span><span style="color: rgb(0, 134, 179);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(0, 134, 179);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">String</span></span><span leaf="">> mapped = filtered.map(...);</span><span leaf=""><br></span><span leaf="">List<</span><span style="color: rgb(0, 134, 179);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(0, 134, 179);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">String</span></span><span leaf="">> result = mapped.collect(...);</span></code></pre> </section> <h4 cid="n17" mdtype="heading" style="box-sizing: border-box;break-after: avoid-page;break-inside: avoid;orphans: 2;font-size: 1.25em;margin-top: 24px;margin-bottom: 24px;font-weight: bold;line-height: 2em;cursor: text;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">2. 滥用Collectors.joining</span></span></span></h4> <p cid="n18" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 24px 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">在某个电商项目里,我见过这样的代码:</span></span></span></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t" data-mpa-action-id="m8x52p7ejsj"> <pre style="margin: 0px;padding: 0px;background: none;font-family: none;"><code style="border-radius: 4px;font-size: 0.85em;font-family: none;margin: 0px 0.15em;background: rgb(248, 248, 248);color: rgb(51, 51, 51);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span leaf="">String skuIds = order.getItems().stream()</span><span leaf=""><br></span><span leaf=""> .</span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">map</span></span><span leaf="">(Item::getSkuId)</span><span leaf=""><br></span><span leaf=""> .collect(Collectors.joining(</span><span style="color: rgb(221, 17, 68);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(221, 17, 68);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">","</span></span><span leaf="">));</span></code></pre> </section> <p cid="n20" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 24px 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">问题</span></span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">:如果订单没有商品,会得到空字符串,而空字符串和null在业务逻辑中是不同的概念。</span></span></span><span md-inline="softbreak" style="box-sizing: border-box;"></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;"> </span></span></span><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><br></span></span></strong></span></p> <p cid="n20" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 24px 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">改进方案</span></span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">:</span></span></span></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t" data-mpa-action-id="m8x534jpknd"> <pre style="margin: 0px;padding: 0px;background: none;font-family: none;"><code style="border-radius: 4px;font-size: 0.85em;font-family: none;margin: 0px 0.15em;background: rgb(248, 248, 248);color: rgb(51, 51, 51);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span leaf="">Optional <string> skuIdsOpt = order.getItems().stream() </string></span><span leaf=""><br></span><span leaf=""> .map(Item::getSkuId)</span><span leaf=""><br></span><span leaf=""> .collect(Collectors.joining(</span><span style="color: rgb(221, 17, 68);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(221, 17, 68);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">","</span></span><span leaf="">))</span><span leaf=""><br></span><span leaf=""> .</span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">empty</span></span><span leaf="">() ? Optional.</span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">empty</span></span><span leaf="">() : Optional.of(skuIds);</span></code></pre> </section> <h4 cid="n22" mdtype="heading" style="box-sizing: border-box;break-after: avoid-page;break-inside: avoid;orphans: 2;font-size: 1.25em;margin-top: 24px;margin-bottom: 24px;font-weight: bold;line-height: 2em;cursor: text;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">3. 忽略性能的Collectors.toList()</span></span></span></h4> <p cid="n23" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 24px 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">某支付系统的关键路径上有这样的代码:</span></span></span></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t" data-mpa-action-id="m8x53rsq1oyw"> <pre style="margin: 0px;padding: 0px;background: none;font-family: none;"><code style="border-radius: 4px;font-size: 0.85em;font-family: none;margin: 0px 0.15em;background: rgb(248, 248, 248);color: rgb(51, 51, 51);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">List</span></span><span leaf=""> <transaction> transactions = db.query(...).stream() </transaction></span><span leaf=""><br></span><span leaf=""> .filter(t -> t.getAmount() > </span><span style="color: rgb(0, 128, 128);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(0, 128, 128);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">1000</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf=""> .collect(Collectors.toList());</span></code></pre> </section> <p cid="n25" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 24px 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">隐患</span></span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">:当数据量达到百万级时,toList()会导致内存溢出。</span></span></span><span md-inline="softbreak" style="box-sizing: border-box;"></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;"> </span></span></span><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><br></span></span></strong></span></p> <p cid="n25" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 24px 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">优化方法</span></span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;font-weight: normal;">:</span></span></span></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t" data-mpa-action-id="m8x54akukwd"> <pre style="margin: 0px;padding: 0px;background: none;font-family: none;"><code style="border-radius: 4px;font-size: 0.85em;font-family: none;margin: 0px 0.15em;background: rgb(248, 248, 248);color: rgb(51, 51, 51);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span style="color: rgb(153, 153, 136);background: rgba(0, 0, 0, 0);display: inline;width: 141px;text-decoration: none solid rgb(153, 153, 136);font-weight: 400;font-style: italic;font-family: none;"><span leaf="">// 使用并行流+分批处理</span></span><span leaf=""><br></span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">List</span></span><span leaf=""> <transaction> result = </transaction></span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">new</span></span><span leaf=""> ArrayList<>();</span><span leaf=""><br></span><span leaf="">db.query(...).stream()</span><span leaf=""><br></span><span leaf=""> .parallel()</span><span leaf=""><br></span><span leaf=""> .filter(t -> t.getAmount() > </span><span style="color: rgb(0, 128, 128);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(0, 128, 128);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">1000</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf=""> .forEachOrdered(result::add);</span></code></pre> </section> <h4 cid="n27" mdtype="heading" style="box-sizing: border-box;break-after: avoid-page;break-inside: avoid;orphans: 2;font-size: 1.25em;margin-top: 24px;margin-bottom: 24px;font-weight: bold;line-height: 2em;cursor: text;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">4. 错误使用boxed()</span></span></span></h4> <p cid="n28" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 24px 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">在某个金融计算场景中:</span></span></span></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t" data-mpa-action-id="m8x54wkd1q5t"> <pre style="margin: 0px;padding: 0px;background: none;font-family: none;"><code style="border-radius: 4px;font-size: 0.85em;font-family: none;margin: 0px 0.15em;background: rgb(248, 248, 248);color: rgb(51, 51, 51);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span leaf="">double sum = numbers.stream()</span><span leaf=""><br></span><span leaf=""> .boxed()</span><span leaf=""><br></span><span leaf=""> .mapToDouble(Number::doubleValue)</span><span leaf=""><br></span><span leaf=""> .sum();</span></code></pre> </section> <p cid="n28" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 24px 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-weight: bold;">误区</span></span></span><span md-inline="plain"><span leaf="" style="color:rgba(0, 0, 0, 0.9);font-size:17px;font-family:" mp-quote, -apple-system-font, blinkmacsystemfont, helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;line-height:1.6;letter-spacing:0.034em;font-style:normal;font-weight:normal;>:boxed()会将原始类型转换为包装类型,导致性能下降。</span></span><span md-inline="softbreak" style="box-sizing: border-box;"></span><span md-inline="plain"><span leaf="" style="color:rgba(0, 0, 0, 0.9);font-size:17px;font-family:" mp-quote, -apple-system-font, blinkmacsystemfont, helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;line-height:1.6;letter-spacing:0.034em;font-style:normal;font-weight:normal;> </span></span><span md-inline="strong"><strong><span md-inline="plain"><span leaf="" style="color:rgba(0, 0, 0, 0.9);font-size:17px;font-family:" mp-quote, -apple-system-font, blinkmacsystemfont, helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;line-height:1.6;letter-spacing:0.034em;font-style:normal;font-weight:normal;><br></span></span></strong></span></p> <p cid="n30" mdtype="paragraph" style="margin-top: 24px;margin-bottom: 24px;"><span md-inline="strong"><strong><span md-inline="plain"><span leaf="" style="color:rgba(0, 0, 0, 0.9);font-size:17px;font-family:" mp-quote, -apple-system-font, blinkmacsystemfont, helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;line-height:1.6;letter-spacing:0.034em;font-style:normal;font-weight:normal;><span textstyle="" style="font-weight: bold;">正确姿势</span></span></span></strong></span><span md-inline="plain"><span leaf="" style="color:rgba(0, 0, 0, 0.9);font-size:17px;font-family:" mp-quote, -apple-system-font, blinkmacsystemfont, helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;line-height:1.6;letter-spacing:0.034em;font-style:normal;font-weight:normal;>:</span></span></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t" data-mpa-action-id="m8x55bgmyw8"> <pre style="margin: 0px;padding: 0px;background: none;font-family: none;"><code style="border-radius: 4px;font-size: 0.85em;font-family: none;margin: 0px 0.15em;background: rgb(248, 248, 248);color: rgb(51, 51, 51);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span leaf="">double sum = numbers.stream()</span><span leaf=""><br></span><span leaf=""> .mapToDouble(Number::doubleValue)</span><span leaf=""><br></span><span leaf=""> .sum();</span></code></pre> </section> <section mpa-from-tpl="t" data-mpa-action-id="m8x4exn21m7h" data-pm-slice="0 0 []"> <span leaf=""><br></span> </section> <section data-mpa-template="t" mpa-from-tpl="t" data-mpa-action-id="m8x4exn2hv4"> <section data-mpa-template="t" mpa-from-tpl="t"> <h4 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: 400;font-size: 16px;text-align: justify;outline: 0px;color: rgb(34, 34, 34);letter-spacing: 0.544px;caret-color: rgb(51, 51, 51);line-height: 2em;"><span style="font-size: 20px;"><strong mpa-from-tpl="t" style="outline: 0px;"><span mpa-is-content="t" style="font-size: 20px;outline: 0px;color: rgb(0, 122, 170);"><span leaf="">二、Stream优雅编程的五大黄金法则</span></span></strong></span></h4> </section> </section> <h4 cid="n33" mdtype="heading" style="margin-top: 24px;margin-bottom: 24px;line-height: 2em;"><span md-inline="plain"><span leaf="" style="color:rgba(0, 0, 0, 0.9);font-size:17px;font-family:" mp-quote, -apple-system-font, blinkmacsystemfont, helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;line-height:1.6;letter-spacing:0.034em;font-style:normal;font-weight:normal;><span textstyle="" style="font-weight: bold;">1. 保持流操作的原子性</span></span></span></h4> <p cid="n34" mdtype="paragraph" style="margin-top: 24px;margin-bottom: 24px;line-height: 2em;"><span md-inline="strong"><strong><span md-inline="plain"><span leaf="" style="color:rgba(0, 0, 0, 0.9);font-size:17px;font-family:" mp-quote, -apple-system-font, blinkmacsystemfont, helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;line-height:1.6;letter-spacing:0.034em;font-style:normal;font-weight:normal;>反模式</span></span></strong></span><span md-inline="plain"><span leaf="" style="color:rgba(0, 0, 0, 0.9);font-size:17px;font-family:" mp-quote, -apple-system-font, blinkmacsystemfont, helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;line-height:1.6;letter-spacing:0.034em;font-style:normal;font-weight:normal;>:</span></span></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t" data-mpa-action-id="m8x4ml75yn6"> <pre style="margin: 0px;padding: 0px;background: none;font-family: none;"><code style="border-radius: 4px;font-size: 0.85em;font-family: none;margin: 0px 0.15em;background: rgb(248, 248, 248);color: rgb(51, 51, 51);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">List</span></span><span leaf=""> <product> products = productList.stream() </product></span><span leaf=""><br></span><span leaf=""> .filter(p -> p.getPrice() > </span><span style="color: rgb(0, 128, 128);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(0, 128, 128);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">100</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf=""> .filter(p -> p.getStock() > </span><span style="color: rgb(0, 128, 128);background: rgba(0, 0, 0, 0);display: inline;width: 7px;text-decoration: none solid rgb(0, 128, 128);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">0</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf=""> .collect(Collectors.toList());</span></code></pre> </section> <p cid="n34" mdtype="paragraph" style="margin-top: 24px;margin-bottom: 24px;line-height: 2em;"><span md-inline="plain"><span leaf="" style="color:rgba(0, 0, 0, 0.9);font-size:17px;font-family:" mp-quote, -apple-system-font, blinkmacsystemfont, helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;line-height:1.6;letter-spacing:0.034em;font-style:normal;font-weight:normal;><span textstyle="" style="font-size: 17px;">重构方案</span></span></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">:</span></span></span></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t" data-mpa-action-id="m8x4ncip3xj"> <pre style="margin: 0px;padding: 0px;background: none;font-family: none;"><code style="border-radius: 4px;font-size: 0.85em;font-family: none;margin: 0px 0.15em;background: rgb(248, 248, 248);color: rgb(51, 51, 51);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span style="color: rgb(153, 153, 136);background: rgba(0, 0, 0, 0);display: inline;width: 142px;text-decoration: none solid rgb(153, 153, 136);font-weight: 400;font-style: italic;font-family: none;"><span leaf="">// 定义独立的Predicate</span></span><span leaf=""><br></span><span leaf="">Predicate <product> isExpensive = p -> p.getPrice() > </product></span><span style="color: rgb(0, 128, 128);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(0, 128, 128);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">100</span></span><span leaf="">;</span><span leaf=""><br></span><span leaf="">Predicate <product> isInStock = p -> p.getStock() > </product></span><span style="color: rgb(0, 128, 128);background: rgba(0, 0, 0, 0);display: inline;width: 7px;text-decoration: none solid rgb(0, 128, 128);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">0</span></span><span leaf="">;</span><span leaf=""><br></span><span leaf=""><br></span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">List</span></span><span leaf=""> <product> products = productList.stream() </product></span><span leaf=""><br></span><span leaf=""> .filter(isExpensive.</span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">and</span></span><span leaf="">(isInStock))</span><span leaf=""><br></span><span leaf=""> .collect(Collectors.toList());</span></code></pre> </section> <h4 cid="n38" mdtype="heading" style="box-sizing: border-box;break-after: avoid-page;break-inside: avoid;orphans: 2;font-size: 1.25em;margin-top: 24px;margin-bottom: 24px;font-weight: bold;line-height: 2em;cursor: text;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">2. 合理使用peek()</span></span></span></h4> <p cid="n39" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 24px 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">在监控日志场景中:</span></span></span></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t" data-mpa-action-id="m8x4nxvw20a"> <pre style="margin: 0px;padding: 0px;background: none;font-family: none;"><code style="border-radius: 4px;font-size: 0.85em;font-family: none;margin: 0px 0.15em;background: rgb(248, 248, 248);color: rgb(51, 51, 51);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">List</span></span><span leaf=""> <order> orders = orderList.stream() </order></span><span leaf=""><br></span><span leaf=""> .peek(o -> log.info(</span><span style="color: rgb(221, 17, 68);background: rgba(0, 0, 0, 0);display: inline;width: 144px;text-decoration: none solid rgb(221, 17, 68);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">"Processing order: {}"</span></span><span leaf="">, o.getId()))</span><span leaf=""><br></span><span leaf=""> .filter(o -> o.getStatus() == COMPLETED)</span><span leaf=""><br></span><span leaf=""> .collect(Collectors.toList());</span></code></pre> </section> <p cid="n41" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0.8em 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">注意事项</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">:</span></span></p> <ul style="box-sizing: border-box;margin: 0.8em 0px;padding-left: 30px;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial; class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n44" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">peek()只能用于调试或副作用操作</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n46" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">避免在peek中修改流元素</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n48" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">并行流中慎用peek()</span></span></p></li> </ul> <h4 cid="n49" mdtype="heading" style="box-sizing: border-box;break-after: avoid-page;break-inside: avoid;orphans: 2;font-size: 1.25em;margin-top: 24px;margin-bottom: 24px;font-weight: bold;line-height: 2em;cursor: text;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">3. 自定义Collectors</span></span></span></h4> <p cid="n50" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 24px 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">在权限系统中,我们需要将用户角色收集为枚举集合:</span></span></span></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t" data-mpa-action-id="m8x4oja61f7j"> <pre style="margin: 0px;padding: 0px;background: none;font-family: none;"><code style="border-radius: 4px;font-size: 0.85em;font-family: none;margin: 0px 0.15em;background: rgb(248, 248, 248);color: rgb(51, 51, 51);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span leaf="">public </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 144px;text-decoration: none solid rgb(51, 51, 51);font-weight: 400;font-style: normal;font-family: none;"><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">class</span></span><span leaf=""> </span><span style="color: rgb(68, 85, 136);background: rgba(0, 0, 0, 0);display: inline;width: 92px;text-decoration: none solid rgb(68, 85, 136);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">RoleCollectors</span></span><span leaf=""> {</span></span><span leaf=""><br></span><span leaf=""> public static Collector <user, ?, set<role>> rolesToSet() { </user,></span><span leaf=""><br></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">return</span></span><span leaf=""> Collector.</span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">of</span></span><span leaf="">(</span><span leaf=""><br></span><span leaf=""> HashSet::</span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">new</span></span><span leaf="">,</span><span leaf=""><br></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 92px;text-decoration: none solid rgb(51, 51, 51);font-weight: 400;font-style: normal;font-family: none;"><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 72px;text-decoration: none solid rgb(51, 51, 51);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">(set, user)</span></span><span leaf=""> -></span></span><span leaf=""> set.add(user.getRole()),</span><span leaf=""><br></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 105px;text-decoration: none solid rgb(51, 51, 51);font-weight: 400;font-style: normal;font-family: none;"><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 85px;text-decoration: none solid rgb(51, 51, 51);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">(left, right)</span></span><span leaf=""> -></span></span><span leaf=""> { left.addAll(right); </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">return</span></span><span leaf=""> left; },</span><span leaf=""><br></span><span leaf=""> Collector.Characteristics.UNORDERED</span><span leaf=""><br></span><span leaf=""> );</span><span leaf=""><br></span><span leaf=""> }</span><span leaf=""><br></span><span leaf="">}</span><span leaf=""><br></span><span leaf=""><br></span><span style="color: rgb(0, 153, 38);background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration: none solid rgb(0, 153, 38);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">//</span></span><span leaf=""> 使用示例</span><span leaf=""><br></span><span leaf="">Set <role> roles = users.stream() </role></span><span leaf=""><br></span><span leaf=""> .collect(RoleCollectors.rolesToSet());</span></code></pre> </section> <h4 cid="n52" mdtype="heading" style="box-sizing: border-box;break-after: avoid-page;break-inside: avoid;orphans: 2;font-size: 1.25em;margin-top: 24px;margin-bottom: 24px;font-weight: bold;line-height: 2em;cursor: text;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">4. 处理空流的正确姿势</span></span></span></h4> <p cid="n53" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 24px 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">在商品推荐场景中:</span></span></span></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t" data-mpa-action-id="m8x4p1dplw2"> <pre style="margin: 0px;padding: 0px;background: none;font-family: none;"><code style="border-radius: 4px;font-size: 0.85em;font-family: none;margin: 0px 0.15em;background: rgb(248, 248, 248);color: rgb(51, 51, 51);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">List</span></span><span leaf=""> <product> recommendations = productList.stream() </product></span><span leaf=""><br></span><span leaf=""> .filter(p -> p.getCategory().equals(</span><span style="color: rgb(221, 17, 68);background: rgba(0, 0, 0, 0);display: inline;width: 85px;text-decoration: none solid rgb(221, 17, 68);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">"electronics"</span></span><span leaf="">))</span><span leaf=""><br></span><span leaf=""> .findFirst()</span><span leaf=""><br></span><span leaf=""> .map(Collections::singletonList)</span><span leaf=""><br></span><span leaf=""> .orElse(Collections.emptyList());</span></code></pre> </section> <p cid="n55" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 24px 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">更优雅的方式</span></span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">:</span></span></span></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t" data-mpa-action-id="m8x4pqb5pur"> <pre style="margin: 0px;padding: 0px;background: none;font-family: none;"><code style="border-radius: 4px;font-size: 0.85em;font-family: none;margin: 0px 0.15em;background: rgb(248, 248, 248);color: rgb(51, 51, 51);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">List</span></span><span leaf=""> <product> recommendations = productList.stream() </product></span><span leaf=""><br></span><span leaf=""> .filter(p -> p.getCategory().equals(</span><span style="color: rgb(221, 17, 68);background: rgba(0, 0, 0, 0);display: inline;width: 85px;text-decoration: none solid rgb(221, 17, 68);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">"electronics"</span></span><span leaf="">))</span><span leaf=""><br></span><span leaf=""> .collect(Collectors.collectingAndThen(</span><span leaf=""><br></span><span leaf=""> Collectors.toList(),</span><span leaf=""><br></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">list</span></span><span leaf=""> -> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">list</span></span><span leaf="">.isEmpty() ? Collections.singletonList(defaultProduct) : </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">list</span></span><span leaf=""><br></span><span leaf=""> ));</span></code></pre> </section> <h4 cid="n57" mdtype="heading" style="box-sizing: border-box;break-after: avoid-page;break-inside: avoid;orphans: 2;font-size: 1.25em;margin-top: 24px;margin-bottom: 24px;font-weight: bold;line-height: 2em;cursor: text;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">5. 结合Optional使用</span></span></span></h4> <p cid="n58" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 24px 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">在用户服务中:</span></span></span></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t" data-mpa-action-id="m8x4qb3dgn6"> <pre style="margin: 0px;padding: 0px;background: none;font-family: none;"><code style="border-radius: 4px;font-size: 0.85em;font-family: none;margin: 0px 0.15em;background: rgb(248, 248, 248);color: rgb(51, 51, 51);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span leaf="">User user = userRepository.findById(userId)</span><span leaf=""><br></span><span leaf=""> .orElseThrow(</span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(51, 51, 51);font-weight: 400;font-style: normal;font-family: none;"><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration: none solid rgb(51, 51, 51);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">()</span></span><span leaf=""> -></span></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">new</span></span><span leaf=""> UserNotFoundException(userId));</span><span leaf=""><br></span><span leaf=""><br></span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">return</span></span><span leaf=""> user.getEmail();</span></code></pre> </section> <p cid="n60" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 24px 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">Stream优化版</span></span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">:</span></span></span></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t" data-mpa-action-id="m8x4qqa5sq0"> <pre style="margin: 0px;padding: 0px;background: none;font-family: none;"><code style="border-radius: 4px;font-size: 0.85em;font-family: none;margin: 0px 0.15em;background: rgb(248, 248, 248);color: rgb(51, 51, 51);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">return</span></span><span leaf=""> userRepository.findById(userId)</span><span leaf=""><br></span><span leaf=""> .map(User::getEmail)</span><span leaf=""><br></span><span leaf=""> .orElseThrow(</span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(51, 51, 51);font-weight: 400;font-style: normal;font-family: none;"><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration: none solid rgb(51, 51, 51);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">()</span></span><span leaf=""> -></span></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">new</span></span><span leaf=""> UserNotFoundException(userId));</span></code></pre> </section> <section mpa-from-tpl="t" data-mpa-action-id="m8x4rz6yjxt" data-pm-slice="0 0 []"> <span leaf=""><br></span> </section> <section data-mpa-template="t" mpa-from-tpl="t" data-mpa-action-id="m8x4rz6y1cay"> <section data-mpa-template="t" mpa-from-tpl="t"> <h4 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: 400;font-size: 16px;text-align: justify;outline: 0px;color: rgb(34, 34, 34);letter-spacing: 0.544px;caret-color: rgb(51, 51, 51);line-height: 2em;"><span style="font-size: 20px;"><strong mpa-from-tpl="t" style="outline: 0px;"><span mpa-is-content="t" style="font-size: 20px;outline: 0px;color: rgb(0, 122, 170);"><span leaf="">三、Stream高级技巧:让代码会“呼吸”</span></span></strong></span></h4> </section> </section> <h4 cid="n63" mdtype="heading" style="box-sizing: border-box;break-after: avoid-page;break-inside: avoid;orphans: 2;font-size: 1.25em;margin-top: 24px;margin-bottom: 24px;font-weight: bold;line-height: 2em;cursor: text;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">1. 分阶段处理流</span></span></span></h4> <p cid="n64" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 24px 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">在物流系统中,订单处理分为三个阶段:</span></span></span></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t" data-mpa-action-id="m8x4ug6q8m1"> <pre style="margin: 0px;padding: 0px;background: none;font-family: none;"><code style="border-radius: 4px;font-size: 0.85em;font-family: none;margin: 0px 0.15em;background: rgb(248, 248, 248);color: rgb(51, 51, 51);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span leaf="">Stream <order> orderStream = orderRepository.findAll().stream(); </order></span><span leaf=""><br></span><span leaf=""><br></span><span style="color: rgb(153, 153, 136);background: rgba(0, 0, 0, 0);display: inline;width: 141px;text-decoration: none solid rgb(153, 153, 136);font-weight: 400;font-style: italic;font-family: none;"><span leaf="">// 阶段1:过滤有效订单</span></span><span leaf=""><br></span><span leaf="">Stream <order> validOrders = orderStream </order></span><span leaf=""><br></span><span leaf=""> .filter(Order::isValid)</span><span leaf=""><br></span><span leaf=""> .peek(o -> auditLogService.logValidation(o));</span><span leaf=""><br></span><span leaf=""><br></span><span style="color: rgb(153, 153, 136);background: rgba(0, 0, 0, 0);display: inline;width: 116px;text-decoration: none solid rgb(153, 153, 136);font-weight: 400;font-style: italic;font-family: none;"><span leaf="">// 阶段2:计算运费</span></span><span leaf=""><br></span><span leaf="">Map <long, double> shippingFees = validOrders </long,></span><span leaf=""><br></span><span leaf=""> .collect(Collectors.toMap(</span><span leaf=""><br></span><span leaf=""> Order::getId,</span><span leaf=""><br></span><span leaf=""> this::calculateShippingFee</span><span leaf=""><br></span><span leaf=""> ));</span><span leaf=""><br></span><span leaf=""><br></span><span style="color: rgb(153, 153, 136);background: rgba(0, 0, 0, 0);display: inline;width: 141px;text-decoration: none solid rgb(153, 153, 136);font-weight: 400;font-style: italic;font-family: none;"><span leaf="">// 阶段3:更新订单状态</span></span><span leaf=""><br></span><span leaf="">validOrders.</span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">forEach</span></span><span leaf="">(o -> orderService.updateStatus(o, SHIPPING));</span></code></pre> </section> <h4 cid="n66" mdtype="heading" style="box-sizing: border-box;break-after: avoid-page;break-inside: avoid;orphans: 2;font-size: 1.25em;margin-top: 24px;margin-bottom: 24px;font-weight: bold;line-height: 2em;cursor: text;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">2. 使用Collectors.teeing()</span></span></span></h4> <p cid="n67" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 24px 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">在统计用户画像时:</span></span></span></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t" data-mpa-action-id="m8x4v43013ll"> <pre style="margin: 0px;padding: 0px;background: none;font-family: none;"><code style="border-radius: 4px;font-size: 0.85em;font-family: none;margin: 0px 0.15em;background: rgb(248, 248, 248);color: rgb(51, 51, 51);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span leaf="">UserProfile profile = users.stream()</span><span leaf=""><br></span><span leaf=""> .collect(Collectors.teeing(</span><span leaf=""><br></span><span leaf=""> Collectors.averagingInt(User::getAge),</span><span leaf=""><br></span><span leaf=""> Collectors.summingDouble(User::getSpending),</span><span leaf=""><br></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 170px;text-decoration: none solid rgb(51, 51, 51);font-weight: 400;font-style: normal;font-family: none;"><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 150px;text-decoration: none solid rgb(51, 51, 51);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">(avgAge, totalSpending)</span></span><span leaf=""> -></span></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">new</span></span><span leaf=""> UserProfile(avgAge, totalSpending)</span><span leaf=""><br></span><span leaf=""> ));</span></code></pre> </section> <h4 cid="n69" mdtype="heading" style="box-sizing: border-box;break-after: avoid-page;break-inside: avoid;orphans: 2;font-size: 1.25em;margin-top: 24px;margin-bottom: 24px;font-weight: bold;line-height: 2em;cursor: text;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">3. 处理并行流的陷阱</span></span></span></h4> <p cid="n70" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 24px 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">在文件处理场景中:</span></span></span></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t" data-mpa-action-id="m8x4w0szunk"> <pre style="margin: 0px;padding: 0px;background: none;font-family: none;"><code style="border-radius: 4px;font-size: 0.85em;font-family: none;margin: 0px 0.15em;background: rgb(248, 248, 248);color: rgb(51, 51, 51);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">List</span></span><span leaf=""> <string> lines = Files.readAllLines(Paths.get( </string></span><span style="color: rgb(221, 17, 68);background: rgba(0, 0, 0, 0);display: inline;width: 65px;text-decoration: none solid rgb(221, 17, 68);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">"data.txt"</span></span><span leaf="">));</span><span leaf=""><br></span><span leaf=""><br></span><span leaf="">lines.parallelStream()</span><span leaf=""><br></span><span leaf=""> .map(this::processLine)</span><span leaf=""><br></span><span leaf=""> .forEachOrdered(System.out::println);</span></code></pre> </section> <p cid="n72" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0.8em 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">关键点</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">:</span></span></p> <ul style="box-sizing: border-box;margin: 0.8em 0px;padding-left: 30px;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial; class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n75" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">顺序敏感操作必须使用forEachOrdered()</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n77" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">共享资源需要线程安全处理</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n79" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">避免过度使用并行流</span></span></p></li> </ul> <h4 cid="n80" mdtype="heading" style="box-sizing: border-box;break-after: avoid-page;break-inside: avoid;orphans: 2;font-size: 1.25em;margin-top: 24px;margin-bottom: 24px;font-weight: bold;line-height: 2em;cursor: text;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">4. 自定义Spliterator</span></span></span></h4> <p cid="n81" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 24px 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">在处理海量日志时:</span></span></span></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t" data-mpa-action-id="m8x4xcc21t9x"> <pre style="margin: 0px;padding: 0px;background: none;font-family: none;"><code style="border-radius: 4px;font-size: 0.85em;font-family: none;margin: 0px 0.15em;background: rgb(248, 248, 248);color: rgb(51, 51, 51);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">public</span></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 353px;text-decoration: none solid rgb(51, 51, 51);font-weight: 400;font-style: normal;font-family: none;"><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">class</span></span><span leaf=""> </span><span style="color: rgb(68, 85, 136);background: rgba(0, 0, 0, 0);display: inline;width: 92px;text-decoration: none solid rgb(68, 85, 136);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">LogSpliterator</span></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 65px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">implements</span></span><span leaf=""> </span><span style="color: rgb(68, 85, 136);background: rgba(0, 0, 0, 0);display: inline;width: 72px;text-decoration: none solid rgb(68, 85, 136);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">Spliterator</span></span><span leaf=""><</span><span style="color: rgb(68, 85, 136);background: rgba(0, 0, 0, 0);display: inline;width: 52px;text-decoration: none solid rgb(68, 85, 136);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">LogEntry</span></span><span leaf="">> </span></span><span leaf="">{</span><span leaf=""><br></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">private</span></span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">final</span></span><span leaf=""> List <logentry> logs; </logentry></span><span leaf=""><br></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">private</span></span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">int</span></span><span leaf=""> currentIndex;</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 281px;text-decoration: none solid rgb(51, 51, 51);font-weight: 400;font-style: normal;font-family: none;"><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">public</span></span><span leaf=""> </span><span style="color: rgb(153, 0, 0);background: rgba(0, 0, 0, 0);display: inline;width: 92px;text-decoration: none solid rgb(153, 0, 0);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">LogSpliterator</span></span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 137px;text-decoration: none solid rgb(51, 51, 51);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">(List <logentry> logs) </logentry></span></span><span leaf=""> </span></span><span leaf="">{</span><span leaf=""><br></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">this</span></span><span leaf="">.logs = logs;</span><span leaf=""><br></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">this</span></span><span leaf="">.currentIndex = </span><span style="color: rgb(0, 128, 128);background: rgba(0, 0, 0, 0);display: inline;width: 7px;text-decoration: none solid rgb(0, 128, 128);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">0</span></span><span leaf="">;</span><span leaf=""><br></span><span leaf=""> }</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="color: rgb(153, 153, 153);background: rgba(0, 0, 0, 0);display: inline;width: 59px;text-decoration: none solid rgb(153, 153, 153);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">@Override</span></span><span leaf=""><br></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 399px;text-decoration: none solid rgb(51, 51, 51);font-weight: 400;font-style: normal;font-family: none;"><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">public</span></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">boolean</span></span><span leaf=""> </span><span style="color: rgb(153, 0, 0);background: rgba(0, 0, 0, 0);display: inline;width: 65px;text-decoration: none solid rgb(153, 0, 0);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">tryAdvance</span></span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 229px;text-decoration: none solid rgb(51, 51, 51);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">(Consumer<!--? </span--><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">super</span></span><span leaf=""> LogEntry> action)</span></span><span leaf=""> </span></span><span leaf="">{</span><span leaf=""><br></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">if</span></span><span leaf=""> (currentIndex < logs.size()) {</span><span leaf=""><br></span><span leaf=""> action.accept(logs.get(currentIndex++));</span><span leaf=""><br></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">return</span></span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">true</span></span><span leaf="">;</span><span leaf=""><br></span><span leaf=""> }</span><span leaf=""><br></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">return</span></span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">false</span></span><span leaf="">;</span><span leaf=""><br></span><span leaf=""> }</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="color: rgb(153, 153, 153);background: rgba(0, 0, 0, 0);display: inline;width: 59px;text-decoration: none solid rgb(153, 153, 153);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">@Override</span></span><span leaf=""><br></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 262px;text-decoration: none solid rgb(51, 51, 51);font-weight: 400;font-style: normal;font-family: none;"><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">public</span></span><span leaf=""> Spliterator <logentry> </logentry></span><span style="color: rgb(153, 0, 0);background: rgba(0, 0, 0, 0);display: inline;width: 52px;text-decoration: none solid rgb(153, 0, 0);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">trySplit</span></span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration: none solid rgb(51, 51, 51);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">()</span></span><span leaf=""> </span></span><span leaf="">{</span><span leaf=""><br></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">int</span></span><span leaf=""> currentSize = logs.size() - currentIndex;</span><span leaf=""><br></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">if</span></span><span leaf=""> (currentSize < </span><span style="color: rgb(0, 128, 128);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(0, 128, 128);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">1000</span></span><span leaf="">) </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">return</span></span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">null</span></span><span leaf="">; </span><span style="color: rgb(153, 153, 136);background: rgba(0, 0, 0, 0);display: inline;width: 71px;text-decoration: none solid rgb(153, 153, 136);font-weight: 400;font-style: italic;font-family: none;"><span leaf="">// 阈值设定</span></span><span leaf=""><br></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">int</span></span><span leaf=""> splitPos = currentIndex + currentSize / </span><span style="color: rgb(0, 128, 128);background: rgba(0, 0, 0, 0);display: inline;width: 7px;text-decoration: none solid rgb(0, 128, 128);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">2</span></span><span leaf="">;</span><span leaf=""><br></span><span leaf=""> Spliterator <logentry> split = </logentry></span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">new</span></span><span leaf=""> LogSpliterator(logs.subList(currentIndex, splitPos));</span><span leaf=""><br></span><span leaf=""> currentIndex = splitPos;</span><span leaf=""><br></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">return</span></span><span leaf=""> split;</span><span leaf=""><br></span><span leaf=""> }</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="color: rgb(153, 153, 153);background: rgba(0, 0, 0, 0);display: inline;width: 59px;text-decoration: none solid rgb(153, 153, 153);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">@Override</span></span><span leaf=""><br></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 177px;text-decoration: none solid rgb(51, 51, 51);font-weight: 400;font-style: normal;font-family: none;"><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">public</span></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">long</span></span><span leaf=""> </span><span style="color: rgb(153, 0, 0);background: rgba(0, 0, 0, 0);display: inline;width: 78px;text-decoration: none solid rgb(153, 0, 0);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">estimateSize</span></span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration: none solid rgb(51, 51, 51);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">()</span></span><span leaf=""> </span></span><span leaf="">{</span><span leaf=""><br></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">return</span></span><span leaf=""> logs.size() - currentIndex;</span><span leaf=""><br></span><span leaf=""> }</span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""> </span><span style="color: rgb(153, 153, 153);background: rgba(0, 0, 0, 0);display: inline;width: 59px;text-decoration: none solid rgb(153, 153, 153);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">@Override</span></span><span leaf=""><br></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 190px;text-decoration: none solid rgb(51, 51, 51);font-weight: 400;font-style: normal;font-family: none;"><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">public</span></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">int</span></span><span leaf=""> </span><span style="color: rgb(153, 0, 0);background: rgba(0, 0, 0, 0);display: inline;width: 98px;text-decoration: none solid rgb(153, 0, 0);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">characteristics</span></span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration: none solid rgb(51, 51, 51);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">()</span></span><span leaf=""> </span></span><span leaf="">{</span><span leaf=""><br></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">return</span></span><span leaf=""> Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;</span><span leaf=""><br></span><span leaf=""> }</span><span leaf=""><br></span><span leaf="">}</span><span leaf=""><br></span><span leaf=""><br></span><span style="color: rgb(153, 153, 136);background: rgba(0, 0, 0, 0);display: inline;width: 71px;text-decoration: none solid rgb(153, 153, 136);font-weight: 400;font-style: italic;font-family: none;"><span leaf="">// 使用示例</span></span><span leaf=""><br></span><span leaf="">StreamSupport.stream(</span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">new</span></span><span leaf=""> LogSpliterator(logs), </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">true</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf=""> .parallel()</span><span leaf=""><br></span><span leaf=""> .forEach(</span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">this</span></span><span leaf="">::processLog);</span></span></code></pre> </section> <section mpa-from-tpl="t" data-mpa-action-id="m8x4xpy01p0e" data-pm-slice="0 0 []"> <span leaf=""><br></span> </section> <section data-mpa-template="t" mpa-from-tpl="t" data-mpa-action-id="m8x4xpy0iqe"> <section data-mpa-template="t" mpa-from-tpl="t"> <h4 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: 400;font-size: 16px;text-align: justify;outline: 0px;color: rgb(34, 34, 34);letter-spacing: 0.544px;caret-color: rgb(51, 51, 51);line-height: 2em;"><span style="font-size: 20px;"><strong mpa-from-tpl="t" style="outline: 0px;"><span mpa-is-content="t" style="font-size: 20px;outline: 0px;color: rgb(0, 122, 170);"><span leaf="">四、Stream代码质量检查清单</span></span></strong></span></h4> </section> </section> <ol style="box-sizing: border-box;margin: 0.8em 0px;padding-left: 30px;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial; class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n86" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">可读性检查</span></span></strong></span></p></li> <ol style="box-sizing: border-box;margin: 0px;padding-left: 30px;" class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n89" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">每个流操作是否有明确的业务含义</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n91" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">链式调用是否超过5层</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n93" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">是否使用了有意义的中间变量</span></span></p></li> </ol> <li style="box-sizing: border-box;margin: 0px;"><p cid="n95" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">性能检查</span></span></strong></span></p></li> <ol style="box-sizing: border-box;margin: 0px;padding-left: 30px;" class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n98" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">是否在不必要的情况下使用了boxed()</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n100" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">并行流是否适用于当前场景</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n102" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">收集操作是否考虑了数据规模</span></span></p></li> </ol> <li style="box-sizing: border-box;margin: 0px;"><p cid="n104" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">异常处理</span></span></strong></span></p></li> <ol style="box-sizing: border-box;margin: 0px;padding-left: 30px;" class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n107" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">是否处理了空流情况</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n109" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">是否合理使用了Optional</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n111" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">错误处理是否符合业务需求</span></span></p></li> </ol> <li style="box-sizing: border-box;margin: 0px;"><p cid="n113" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">可维护性</span></span></strong></span></p></li> <ol style="box-sizing: border-box;margin: 0px;padding-left: 30px;" class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n116" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">是否将复杂逻辑拆分为独立的方法</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n118" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">是否使用了自定义Collectors</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n120" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">是否考虑了未来的扩展需求</span></span></p></li> </ol> </ol> <section mpa-from-tpl="t" data-mpa-action-id="m8x50hz624mu" data-pm-slice="0 0 []"> <span leaf=""><br></span> </section> <section data-mpa-template="t" mpa-from-tpl="t" data-mpa-action-id="m8x50hz61dtp"> <section data-mpa-template="t" mpa-from-tpl="t"> <h4 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: 400;font-size: 16px;text-align: justify;outline: 0px;color: rgb(34, 34, 34);letter-spacing: 0.544px;caret-color: rgb(51, 51, 51);line-height: 2em;"><span style="font-size: 20px;"><strong mpa-from-tpl="t" style="outline: 0px;"><span mpa-is-content="t" style="font-size: 20px;outline: 0px;color: rgb(0, 122, 170);"><span leaf="">五、终极心法:流的本质是思维方式</span></span></strong></span></h4> </section> </section> <p cid="n122" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 24px 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">最后分享一个真实案例:某电商平台通过重构Stream代码,使核心订单处理流程的代码量减少40%,同时性能提升30%。他们的秘诀在于:</span></span></span></p> <ol style="box-sizing: border-box;margin: 0.8em 0px;padding-left: 30px;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial; class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n125" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">将流操作与业务逻辑解耦</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n127" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">建立Stream最佳实践库</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n129" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">使用IDE插件(如StreamRefactor)进行代码检查 </span></span></p></li> </ol> <p cid="n129" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 24px 0px;white-space: pre-wrap;"><span style="background-color: transparent;"><span leaf="">记住:Stream不是代码竞赛的工具,而是提升代码质量的手段</span></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">。当你开始思考如何让Stream代码更易读、易维护、易扩展时,你就真正掌握了它的精髓。 </span></span></p> <p style="display: none;"> <mp-style-type data-value="3"></mp-style-type></p>
作者:微信小助手
<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;font-family: Optima, 'Microsoft YaHei', PingFangSC-regular, serif;font-size: 16px;color: rgb(0, 0, 0);line-height: 1.5em;word-spacing: 0em;letter-spacing: 0em;word-break: break-word;overflow-wrap: break-word;text-align: left;" data-pm-slice="0 0 []"> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">就体验而言,笔者用的最多的当属:</span><code style="color: rgb(145, 109, 213);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">edge-tts</span></code><span leaf=""> </span><code style="color: rgb(145, 109, 213);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">FishSpeech</span></code><span leaf=""> 和 </span><code style="color: rgb(145, 109, 213);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">CosyVoice</span></code></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">其中,</span><code style="color: rgb(145, 109, 213);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">edge-tts</span></code><span leaf=""> 需联网,而 </span><code style="color: rgb(145, 109, 213);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">FishSpeech</span></code><span leaf=""> 和 </span><code style="color: rgb(145, 109, 213);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">CosyVoice</span></code><span leaf=""> 则需显卡。</span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">有没有端侧可运行的轻量级 TTS 模型?</span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">之前还真发现过一个潜力股:</span><code style="color: rgb(145, 109, 213);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Kokoro</span></code><span leaf="">,不过当时对中文不太友好,暂且搁置。</span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">最近,</span><code style="color: rgb(145, 109, 213);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Kokoro</span></code><span leaf=""> 上新了,新增 100 种中文音色,且支持中英混合。</span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">这就有必要来聊聊了,希望能为您 TTS 选型提供一个参考。</span></p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(34, 34, 34);line-height: 1.8em;letter-spacing: 0em;padding-top: 0px;padding-bottom: 0px;padding-left: 10px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: solid;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 5px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(145, 109, 213);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">1. Kokoro 简介</span></span><span style="display: none;"></span></h2> <blockquote style="margin-top: 20px;margin-bottom: 20px;margin-left: 0px;margin-right: 0px;padding-top: 10px;padding-bottom: 10px;padding-left: 20px;padding-right: 10px;border-top-style: none;border-bottom-style: none;border-left-style: solid;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgb(216, 156, 246);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;background-attachment: scroll;background-clip: border-box;background-color: rgb(244, 238, 255);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;display: block;overflow-x: auto;overflow-y: auto;"> <span style="display: none;color: rgb(0, 0, 0);font-size: 16px;line-height: 1.5em;letter-spacing: 0em;text-align: left;font-weight: normal;"></span> <p style="text-indent: 0em;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;color: rgb(0, 0, 0);font-size: 15px;line-height: 1.8em;letter-spacing: 0em;text-align: left;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0px;margin-left: 0px;"><span leaf="">项目地址:</span><span leaf="">https://github.com/hexgrad/kokoro</span></p> </blockquote> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">一款超轻量级的 TTS 模型,只有 </span><strong style="color: rgb(145, 109, 213);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">82M</span></strong><span leaf=""> 参数。</span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">别看它架构轻巧,音质仍可媲美动辄 0.5B 的大模型。</span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">且看语音合成领域的 TTS Arena 排行榜,荣登榜一,且遥遥领先!</span></p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img class="rich_pages wxw-img" data-imgfileid="100005247" data-ratio="0.362962962962963" src="/upload/1364b2ff170d7c30785e2f71fe56a69b.png" data-type="png" data-w="1080" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 8px;border-top-right-radius: 8px;border-bottom-right-radius: 8px;border-bottom-left-radius: 8px;object-fit: fill;box-shadow: rgba(153, 153, 153, 0.3) 2px 4px 8px 0px;"></span> </figure> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">相比 v0.19,v1.0 训练数据规模增加了,支持的音色更多:</span></p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img class="rich_pages wxw-img" data-imgfileid="100005246" data-ratio="0.2851851851851852" src="/upload/ec97a456a79c923b363d60d7c55f1f1d.png" data-type="png" data-w="1080" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 8px;border-top-right-radius: 8px;border-bottom-right-radius: 8px;border-bottom-left-radius: 8px;object-fit: fill;box-shadow: rgba(153, 153, 153, 0.3) 2px 4px 8px 0px;"></span> </figure> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><strong style="color: rgb(145, 109, 213);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">老规矩,简短介绍下亮点:</span></strong></p> <ul style="list-style-type: circle;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 25px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;font-weight: normal;"> <strong style="color: rgb(145, 109, 213);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">多语言支持</span></strong><span leaf="">:支持中、英、日、法、意大利、葡萄牙、西班牙、印地语共 </span><strong style="color: rgb(145, 109, 213);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">8</span></strong><span leaf=""> 种语言。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;font-weight: normal;"> <strong style="color: rgb(145, 109, 213);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">多音色支持</span></strong><span leaf="">:提供了多种男女人物音色,不断更新中。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;font-weight: normal;"> <strong style="color: rgb(145, 109, 213);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">实时语音生成</span></strong><span leaf="">:CPU上可近乎实时,而在GPU上,则达到了50倍实时速度。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;text-align: left;font-weight: normal;"> <strong style="color: rgb(145, 109, 213);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">自然语音生成</span></strong><span leaf="">:不只是快,还超逼真。</span> </section></li> </ul> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;height: auto;justify-content: center;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 17px;color: rgb(0, 0, 0);border-bottom-color: rgb(216, 156, 246);line-height: 1.5em;letter-spacing: 0em;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: solid;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 2px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: inline;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">1.1 音色地址</span></span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><code style="color: rgb(145, 109, 213);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">Kokoro</span></code><span leaf=""> 的所有音色均以 pt 文件,存放在 huggingface,国内用户可通过以下地址下载:</span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">v1.0:</span><span leaf="">https://hf-mirror.com/hexgrad/Kokoro-82M</span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">v1.1 </span><span leaf="">https://hf-mirror.com/hexgrad/Kokoro-82M-v1.1-zh</span><span leaf="">,新增更多中文音色。</span></p> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(34, 34, 34);line-height: 1.8em;letter-spacing: 0em;padding-top: 0px;padding-bottom: 0px;padding-left: 10px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: solid;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 5px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(145, 109, 213);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">2. Kokoro 实测</span></span><span style="display: none;"></span></h2> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;height: auto;justify-content: center;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 17px;color: rgb(0, 0, 0);border-bottom-color: rgb(216, 156, 246);line-height: 1.5em;letter-spacing: 0em;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: solid;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 2px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: inline;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">2.1 安装依赖</span></span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">需安装如下依赖:</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg kbcyznggu08mg3qlheiamqpnoe69vqcjcf2ostdygj4mweseihpl1klmxmmdoik8zozhyivhvibf4ch4dgynw55jjxok0wf6via 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span leaf="">pip install kokoro</span><span leaf=""><br></span><span leaf="">pip install ordered-set</span><span leaf=""><br></span><span leaf="">pip install cn2an</span><span leaf=""><br></span><span leaf="">pip install pypinyin_dict</span><span leaf=""><br></span></code></pre> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;height: auto;justify-content: center;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 17px;color: rgb(0, 0, 0);border-bottom-color: rgb(216, 156, 246);line-height: 1.5em;letter-spacing: 0em;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: solid;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 2px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: inline;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">2.2 模型和音色下载</span></span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">从 huggingface 上拉取模型权重,以及音色文件:</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg kbcyznggu08mg3qlheiamqpnoe69vqcjcf2ostdygj4mweseihpl1klmxmmdoik8zozhyivhvibf4ch4dgynw55jjxok0wf6via 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #e6c07b;line-height: 26px;"><span leaf="">export</span></span><span leaf=""> HF_ENDPOINT=https://hf-mirror.com </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf=""># 引入镜像地址</span></span><span leaf=""><br></span><span leaf="">huggingface-cli download --resume-download hexgrad/Kokoro-82M --</span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">local</span></span><span leaf="">-dir ./ckpts/kokoro-v1.0</span><span leaf=""><br></span><span leaf="">huggingface-cli download --resume-download hexgrad/Kokoro-82M-v1.1-zh --</span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">local</span></span><span leaf="">-dir ./ckpts/kokoro-v1.1</span><span leaf=""><br></span></code></pre> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;height: auto;justify-content: center;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 17px;color: rgb(0, 0, 0);border-bottom-color: rgb(216, 156, 246);line-height: 1.5em;letter-spacing: 0em;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: solid;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 2px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: inline;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">2.3 模型推理</span></span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">下面以中文语音合成为例,进行演示。</span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><code style="color: rgb(145, 109, 213);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">kokoro</span></code><span leaf=""> 模型推理,只需以下 4 步~</span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><strong style="color: rgb(145, 109, 213);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">step 1:引入依赖</span></strong></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg kbcyznggu08mg3qlheiamqpnoe69vqcjcf2ostdygj4mweseihpl1klmxmmdoik8zozhyivhvibf4ch4dgynw55jjxok0wf6via 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span leaf="">import torch</span><span leaf=""><br></span><span leaf="">import time</span><span leaf=""><br></span><span leaf="">from kokoro import KPipeline, KModel</span><span leaf=""><br></span><span leaf="">import soundfile as sf</span><span leaf=""><br></span></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><strong style="color: rgb(145, 109, 213);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">step 2:加载音色</span></strong></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">尽管 </span><code style="color: rgb(145, 109, 213);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">kokoro</span></code><span leaf=""> 支持运行时下载音色,不过在 2.2 部分,我们已将音色文件下载到本地,这里直接 load 进来:</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg kbcyznggu08mg3qlheiamqpnoe69vqcjcf2ostdygj4mweseihpl1klmxmmdoik8zozhyivhvibf4ch4dgynw55jjxok0wf6via 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span leaf="">voice_zf = </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"zf_001"</span></span><span leaf=""><br></span><span leaf="">voice_zf_tensor = torch.load(f</span><span style="color: #98c379;line-height: 26px;"><span leaf="">'ckpts/kokoro-v1.1/voices/{voice_zf}.pt'</span></span><span leaf="">, weights_only=True)</span><span leaf=""><br></span><span leaf="">voice_af = </span><span style="color: #98c379;line-height: 26px;"><span leaf="">'af_maple'</span></span><span leaf=""><br></span><span leaf="">voice_af_tensor = torch.load(f</span><span style="color: #98c379;line-height: 26px;"><span leaf="">'ckpts/kokoro-v1.1/voices/{voice_af}.pt'</span></span><span leaf="">, weights_only=True)</span><span leaf=""><br></span></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><strong style="color: rgb(145, 109, 213);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">step 3:加载模型</span></strong></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg kbcyznggu08mg3qlheiamqpnoe69vqcjcf2ostdygj4mweseihpl1klmxmmdoik8zozhyivhvibf4ch4dgynw55jjxok0wf6via 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span leaf="">repo_id = </span><span style="color: #98c379;line-height: 26px;"><span leaf="">'hexgrad/Kokoro-82M-v1.1-zh'</span></span><span leaf=""><br></span><span leaf="">device = </span><span style="color: #98c379;line-height: 26px;"><span leaf="">'cuda'</span></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">if</span></span><span leaf=""> torch.cuda.is_available() </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">else</span></span><span leaf=""> </span><span style="color: #98c379;line-height: 26px;"><span leaf="">'cpu'</span></span><span leaf=""><br></span><span leaf="">model_path = </span><span style="color: #98c379;line-height: 26px;"><span leaf="">'ckpts/kokoro-v1.1/kokoro-v1_1-zh.pth'</span></span><span leaf=""><br></span><span leaf="">config_path = </span><span style="color: #98c379;line-height: 26px;"><span leaf="">'ckpts/kokoro-v1.1/config.json'</span></span><span leaf=""><br></span><span leaf="">model = KModel(model=model_path, config=config_path, repo_id=repo_id).to(device).</span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">eval</span></span><span leaf="">()</span><span leaf=""><br></span></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><strong style="color: rgb(145, 109, 213);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">step 4:开始推理</span></strong></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg kbcyznggu08mg3qlheiamqpnoe69vqcjcf2ostdygj4mweseihpl1klmxmmdoik8zozhyivhvibf4ch4dgynw55jjxok0wf6via 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span leaf="">zh_pipeline = KPipeline(lang_code=</span><span style="color: #98c379;line-height: 26px;"><span leaf="">'z'</span></span><span leaf="">, repo_id=repo_id, model=model)</span><span leaf=""><br></span><span leaf="">sentence = </span><span style="color: #98c379;line-height: 26px;"><span leaf="">'如果您愿意帮助进一步完成这一使命,请考虑为此贡献许可的音频数据。'</span></span><span leaf=""><br></span><span leaf="">start_time = time.time()</span><span leaf=""><br></span><span leaf="">generator = zh_pipeline(sentence, voice=voice_zf_tensor, speed=speed_callable)</span><span leaf=""><br></span><span leaf="">result = next(generator)</span><span leaf=""><br></span><span leaf="">wav = result.audio</span><span leaf=""><br></span><span leaf="">speech_len = len(wav) / 24000</span><span leaf=""><br></span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">print</span></span><span leaf="">(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">'yield speech len {}, rtf {}'</span></span><span leaf="">.format(speech_len, (time.time() - start_time) / speech_len)) </span><span leaf=""><br></span><span leaf="">sf.write(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">'output.wav'</span></span><span leaf="">, wav, 24000)</span><span leaf=""><br></span></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">其中,</span><code style="color: rgb(145, 109, 213);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">speed</span></code><span leaf=""> 支持 float 类型的语速控制,</span><code style="color: rgb(145, 109, 213);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">speed_callable</span></code><span leaf="">为官方提供的默认回调函数(主要和训练数据有关):</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg kbcyznggu08mg3qlheiamqpnoe69vqcjcf2ostdygj4mweseihpl1klmxmmdoik8zozhyivhvibf4ch4dgynw55jjxok0wf6via 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span leaf="">def speed_callable(len_ps):</span><span leaf=""><br></span><span leaf=""> speed = 0.8</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">if</span></span><span leaf=""> len_ps <= 83:</span><span leaf=""><br></span><span leaf=""> speed = 1</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">elif</span></span><span leaf=""> len_ps < 183:</span><span leaf=""><br></span><span leaf=""> speed = 1 - (len_ps - 83) / 500</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">return</span></span><span leaf=""> speed * 1.1</span><span leaf=""><br></span></code></pre> <hr style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: solid;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 2px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(217, 184, 250);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: 1px;"> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">对于</span><strong style="color: rgb(145, 109, 213);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">中英混杂</span></strong><span leaf="">的文本,需要在 </span><code style="color: rgb(145, 109, 213);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">KPipeline</span></code><span leaf=""> 中增加 </span><code style="color: rgb(145, 109, 213);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">en_callable</span></code><span leaf=""> 回调函数,并传入英文音色,如下:</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg kbcyznggu08mg3qlheiamqpnoe69vqcjcf2ostdygj4mweseihpl1klmxmmdoik8zozhyivhvibf4ch4dgynw55jjxok0wf6via 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span leaf="">en_pipeline = KPipeline(lang_code=</span><span style="color: #98c379;line-height: 26px;"><span leaf="">'a'</span></span><span leaf="">, repo_id=repo_id, model=model)</span><span leaf=""><br></span><span leaf="">def en_callable(text):</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">if</span></span><span leaf=""> text == </span><span style="color: #98c379;line-height: 26px;"><span leaf="">'Kokoro'</span></span><span leaf="">:</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">return</span></span><span leaf=""> </span><span style="color: #98c379;line-height: 26px;"><span leaf="">'kˈOkəɹO'</span></span><span leaf=""><br></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">elif</span></span><span leaf=""> text == </span><span style="color: #98c379;line-height: 26px;"><span leaf="">'Sol'</span></span><span leaf="">:</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">return</span></span><span leaf=""> </span><span style="color: #98c379;line-height: 26px;"><span leaf="">'sˈOl'</span></span><span leaf=""><br></span><span leaf=""> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">return</span></span><span leaf=""> next(en_pipeline(text, voice=voice_zf_tensor)).phonemes</span><span leaf=""><br></span><span leaf="">zh_pipeline = KPipeline(lang_code=</span><span style="color: #98c379;line-height: 26px;"><span leaf="">'z'</span></span><span leaf="">, repo_id=repo_id, model=model, en_callable=en_callable)</span><span leaf=""><br></span></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">最后,来听听合成效果:</span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><strong style="color: rgb(145, 109, 213);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">中英混语合成:</span></strong></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg kbcyznggu08mg3qlheiamqpnoe69vqcjcf2ostdygj4mweseihpl1klmxmmdoik8zozhyivhvibf4ch4dgynw55jjxok0wf6via 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span leaf="">该 Apache 许可模式也符合 OpenAI 所宣称的广泛传播 AI 优势的使命。</span><span leaf=""><br></span></code></pre> <section nodeleaf=""> <mp-common-mpaudio class="js_editor_audio res_iframe js_uneditable custom_select_card" data-pluginname="insertaudio" name="kokoro-mixed" author="猴哥的AI知识库" src="/cgi-bin/readtemplate?t=tmpl/audio_tmpl&name=kokoro-mixed&play_length=6%E7%A7%92" isaac2="1" low_size="11.43" source_size="11.4" high_size="25.17" play_length="6000" data-trans_state="1" data-verify_state="3" voice_encode_fileid="MzkzMzY2MTkyN18yMjQ3NDg4OTEz" cover="https://wx.qlogo.cn/mmopen/l1BlcrnOO6TnMmibUYUfACWLNcCficWzsYGKqK3DN2dYKTF9jVRKcB2k9bpCk2I8u63dTdKicITKwoSEmF4QEWNtTk1icX4nARQFGzLOXtXdic4DBumSPOy1R0oibKhicGCmuwv/0"></mp-common-mpaudio> </section> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;height: auto;justify-content: center;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 17px;color: rgb(0, 0, 0);border-bottom-color: rgb(216, 156, 246);line-height: 1.5em;letter-spacing: 0em;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: solid;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 2px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: inline;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">2.4 速度测试</span></span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">GPU 推理显存占用:</span></p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img class="rich_pages wxw-img" data-imgfileid="100005245" data-ratio="0.2111111111111111" src="/upload/032adddcb2799ef9e1eb1c6bec8f4bf9.png" data-type="png" data-w="1080" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 8px;border-top-right-radius: 8px;border-bottom-right-radius: 8px;border-bottom-left-radius: 8px;object-fit: fill;box-shadow: rgba(153, 153, 153, 0.3) 2px 4px 8px 0px;"></span> </figure> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">TTS 通用的速度评估指标为 </span><code style="color: rgb(145, 109, 213);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">rtf</span></code><span leaf="">,也即 </span><code style="color: rgb(145, 109, 213);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">推理耗时/生成音频耗时</span></code><span leaf="">,指标越低,代表推理速度越快!</span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><code style="color: rgb(145, 109, 213);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">kokoro</span></code><span leaf=""> GPU 推理:</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg kbcyznggu08mg3qlheiamqpnoe69vqcjcf2ostdygj4mweseihpl1klmxmmdoik8zozhyivhvibf4ch4dgynw55jjxok0wf6via 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span leaf="">yield speech len 6.825, rtf 0.2680429521497789</span><span leaf=""><br></span></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><code style="color: rgb(145, 109, 213);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">kokoro</span></code><span leaf=""> CPU 推理:</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg kbcyznggu08mg3qlheiamqpnoe69vqcjcf2ostdygj4mweseihpl1klmxmmdoik8zozhyivhvibf4ch4dgynw55jjxok0wf6via 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span leaf="">yield speech len 6.825, rtf 0.4242438012427026</span><span leaf=""><br></span></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><strong style="color: rgb(145, 109, 213);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">可以发现,即便是 CPU 推理,rtf 依然远小于 1,强啊!</span></strong></p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;height: auto;justify-content: center;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 17px;color: rgb(0, 0, 0);border-bottom-color: rgb(216, 156, 246);line-height: 1.5em;letter-spacing: 0em;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: solid;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 2px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: inline;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">2.5 服务端部署</span></span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">下面我们采用 FastAPI 完成服务部署。</span><em style="color: rgb(145, 109, 213);font-style: italic;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">(完整代码,可在文末自取)</span></em></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">首先,定义数据模型,用于接收POST请求中的数据:</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg kbcyznggu08mg3qlheiamqpnoe69vqcjcf2ostdygj4mweseihpl1klmxmmdoik8zozhyivhvibf4ch4dgynw55jjxok0wf6via 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span leaf="">class TTSRequest(BaseModel):</span><span leaf=""><br></span><span leaf=""> tts_text: str </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf=""># 待合成的文本</span></span><span leaf=""><br></span><span leaf=""> voice_id: Optional[str] = </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"zf_001"</span></span><span leaf=""> </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf=""># 参考语音的id</span></span><span leaf=""><br></span><span leaf=""> speed: Optional[</span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">float</span></span><span leaf="">] = None </span><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf=""># 语速</span></span><span leaf=""><br></span></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">接口功能函数:</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg kbcyznggu08mg3qlheiamqpnoe69vqcjcf2ostdygj4mweseihpl1klmxmmdoik8zozhyivhvibf4ch4dgynw55jjxok0wf6via 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span leaf="">@app.post(</span><span style="color: #98c379;line-height: 26px;"><span leaf="">'/tts'</span></span><span leaf="">)</span><span leaf=""><br></span><span leaf="">def tts(request: TTSRequest):</span><span leaf=""><br></span><span leaf=""> voice_path = f</span><span style="color: #98c379;line-height: 26px;"><span leaf="">'ckpts/kokoro-v1.1/voices/{request.voice_id}.pt'</span></span><span leaf=""><br></span><span leaf=""> </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">if</span></span><span leaf=""> not os.path.exists(voice_path):</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">return</span></span><span leaf=""> JSONResponse(status_code=400, content={</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"error"</span></span><span leaf="">: </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"voice_id not found"</span></span><span leaf="">})</span><span leaf=""><br></span><span leaf=""> voice_tensor = torch.load(voice_path, weights_only=True)</span><span leaf=""><br></span><span leaf=""> speed = speed_callable </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">if</span></span><span leaf=""> request.speed is None </span><span style="color: #c678dd;line-height: 26px;"><span leaf="">else</span></span><span leaf=""> request.speed</span><span leaf=""><br></span><span leaf=""> generator = zh_pipeline(request.tts_text, voice=voice_tensor, speed=speed)</span><span leaf=""><br></span><span leaf=""> result = next(generator)</span><span leaf=""><br></span><span leaf=""> wav = result.audio.cpu().numpy()</span><span leaf=""><br></span><span leaf=""> wav = (wav * 32767).astype(np.int16)</span><span leaf=""><br></span><span leaf=""> wav_bytes = io.BytesIO()</span><span leaf=""><br></span><span leaf=""> wav_bytes.write(wav.tobytes())</span><span leaf=""><br></span><span leaf=""> wav_bytes.seek(0)</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">return</span></span><span leaf=""> StreamingResponse(wav_bytes, media_type=</span><span style="color: #98c379;line-height: 26px;"><span leaf="">'audio/pcm'</span></span><span leaf="">, headers=headers)</span><span leaf=""><br></span></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><strong style="color: rgb(145, 109, 213);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">注意:模型原始输出为 torch.tensor,可转成 int16 以 pcm 格式输出。</span></strong></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">最后,启动服务:</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg kbcyznggu08mg3qlheiamqpnoe69vqcjcf2ostdygj4mweseihpl1klmxmmdoik8zozhyivhvibf4ch4dgynw55jjxok0wf6via 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span leaf="">nohup uvicorn server:app --host 0.0.0.0 --port 3008 > server.log 2>&1 &</span><span leaf=""><br></span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">echo</span></span><span leaf=""> </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"Server started"</span></span><span leaf=""><br></span></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">客户端测试代码:</span></p> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg kbcyznggu08mg3qlheiamqpnoe69vqcjcf2ostdygj4mweseihpl1klmxmmdoik8zozhyivhvibf4ch4dgynw55jjxok0wf6via 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span leaf="">def </span><span style="color: #e6c07b;line-height: 26px;"><span leaf="">test</span></span><span leaf="">():</span><span leaf=""><br></span><span leaf=""> data = {</span><span leaf=""><br></span><span leaf=""> </span><span style="color: #98c379;line-height: 26px;"><span leaf="">'tts_text'</span></span><span leaf="">: </span><span style="color: #98c379;line-height: 26px;"><span leaf="">'2024年12月21日,你好,欢迎使用语音合成服务,共收录2000余种语言。'</span></span><span leaf="">,</span><span leaf=""><br></span><span leaf=""> }</span><span leaf=""><br></span><span leaf=""> response = requests.post(f</span><span style="color: #98c379;line-height: 26px;"><span leaf="">"{url}/tts"</span></span><span leaf="">, json=data)</span><span leaf=""><br></span><span leaf=""> pcm2wav(response.content)</span><span leaf=""><br></span></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">对于</span><code style="color: rgb(145, 109, 213);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">数字播报</span></code><span leaf="">这一老大难问题,</span><code style="color: rgb(145, 109, 213);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">kokoro</span></code><span leaf=""> 也能轻松拿捏,来听效果:</span></p> <section nodeleaf=""> <mp-common-mpaudio class="js_editor_audio res_iframe js_uneditable custom_select_card" data-pluginname="insertaudio" name="kokoro-num" author="猴哥的AI知识库" src="/cgi-bin/readtemplate?t=tmpl/audio_tmpl&name=kokoro-num&play_length=7%E7%A7%92" isaac2="1" low_size="12.93" source_size="12.9" high_size="29.29" play_length="7000" data-trans_state="1" data-verify_state="3" voice_encode_fileid="MzkzMzY2MTkyN18yMjQ3NDg4OTEy" cover="https://wx.qlogo.cn/mmopen/l1BlcrnOO6TnMmibUYUfACWLNcCficWzsYGKqK3DN2dYKTF9jVRKcB2k9bpCk2I8u63dTdKicITKwoSEmF4QEWNtTk1icX4nARQFGzLOXtXdic4DBumSPOy1R0oibKhicGCmuwv/0"></mp-common-mpaudio> </section> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">就凭这,</span><code style="color: rgb(145, 109, 213);font-size: 16px;line-height: 1.8em;letter-spacing: 0em;background-attachment: scroll;background-clip: border-box;background-color: rgba(27, 31, 35, 0.05);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 2px;margin-right: 2px;padding-top: 2px;padding-bottom: 2px;padding-left: 4px;padding-right: 4px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;overflow-wrap: break-word;font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;"><span leaf="">kokoro</span></code><span leaf=""> 吊打一众 TTS 巨无霸模型!</span></p> </section>
作者:微信小助手
<section style="letter-spacing: 1.3px;padding: 0px;box-sizing: border-box;font-style: normal;font-weight: 400;text-align: justify;font-size: 16px;color: rgb(62, 62, 62);"> <section style="text-align: left;box-sizing: border-box;"> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 22px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf="">一、SEO的核心逻辑:理解搜索引擎如何工作</span></span></strong></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span style="font-size: 18px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf="">1. 搜索引擎的三大目标</span></span></strong></span></p> <ul style="list-style-type: disc;box-sizing: border-box;padding-left: 40px;list-style-position: outside;" class="list-paddingleft-2"> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">理解内容:通过爬虫抓取和分析网页内容</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">评估质量:基于E-E-A-T原则(专业性、权威性、可信度)</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">匹配意图:判断内容是否解决用户真实需求</span></p></li> </ul> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 18px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf=""><br></span></span></strong></p> <p style="margin: 0px;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 18px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf="">2. 谷歌算法核心关注点</span></span></strong></p> </section> <section style="line-height: 0;box-sizing: border-box;"> <section style="max-width: 100%;vertical-align: middle;display: inline-block;line-height: 0;box-sizing: border-box;" nodeleaf=""> <img src="/upload/a006c6a1f028034826e09e7cebd70cb4.png" class="rich_pages wxw-img" data-ratio="0.32355723746452225" data-s="300,640" data-type="png" data-w="1057" style="vertical-align: middle;max-width: 100%;width: 100%;box-sizing: border-box;" data-imgfileid="100013465"> </section> </section> <section style="text-align: left;box-sizing: border-box;"> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 22px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf=""> </span></span></strong></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 22px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf="">二、四步构建SEO基础框架</span></span></strong></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 18px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf="">1. 关键词研究:找到用户的搜索语言</span></span></strong></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">(1)工具与步骤</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">免费工具:Google Keyword Planner、AnswerThePublic</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">付费工具:SEMrush、Ahrefs(试用期可申请)</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">操作流程:</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">输入5个种子词(如"咖啡机")</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">筛选搜索量≥300、竞争度≤40的词</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">按意图分类(信息/商业/导航/交易型)</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">(2)实战案例:咖啡馆长尾词优化</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">成功案例</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">背景:某咖啡馆网站流量停滞,核心词"咖啡"竞争度过高(KD=85)</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">操作:</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">用AnswerThePublic挖掘疑问词:"如何在家制作拿铁"、"咖啡豆保存方法"</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">筛选出20个搜索量200-500的长尾词</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">结果:</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">3个月内"咖啡豆保存方法"排名第1,带来月均1500次点击</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">相关页面用户停留时间达4分钟(高于全站均值2倍)</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 18px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf="">2. 网站技术优化:让谷歌爬虫畅通无阻</span></span></strong></p> <p style="margin: 0px;padding: 0px;box-sizing: border-box;"><span leaf="">(1)必做技术项清单</span></p> </section> <section style="line-height: 0;box-sizing: border-box;"> <section style="max-width: 100%;vertical-align: middle;display: inline-block;line-height: 0;box-sizing: border-box;" nodeleaf=""> <img src="/upload/9090d08c0882e393704b498d4422e8f8.png" class="rich_pages wxw-img" data-ratio="0.36644798500468606" data-s="300,640" data-type="png" data-w="1067" style="vertical-align: middle;max-width: 100%;width: 100%;box-sizing: border-box;" data-imgfileid="100013466"> </section> </section> <section style="text-align: left;box-sizing: border-box;"> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""> </span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 18px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf="">3. 内容策略:打造用户与搜索引擎都爱的内容</span></span></strong></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">(1)内容创作黄金公式</span></p> <p style="text-align: justify;margin: 0px 0px 13px;white-space: normal;padding: 0px;box-sizing: border-box;"><span style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf="">标题:核心词+解决方案+附加值 </span></span></strong></span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">✅ 正例:“2023咖啡机选购指南|5步避开智商税” </span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">❌ 反例:“咖啡机推荐|点击查看详情”</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">正文结构:</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">用户痛点(前100字明确问题)</span></p> <ul style="list-style-type: disc;box-sizing: border-box;padding-left: 40px;list-style-position: outside;" class="list-paddingleft-2"> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">案例:某健身器材页以“90%健身者忽视的5个错误姿势”开篇,跳出率降低40%</span></p></li> </ul> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">解决方案(分步骤/场景化说明)</span></p> <ul style="list-style-type: disc;box-sizing: border-box;padding-left: 40px;list-style-position: outside;" class="list-paddingleft-2"> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">案例:某母婴用品站用视频+图文展示婴儿车折叠步骤,页面分享率提高3倍</span></p></li> </ul> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">权威背书(数据/证书/用户评价)</span></p> <ul style="list-style-type: disc;box-sizing: border-box;padding-left: 40px;list-style-position: outside;" class="list-paddingleft-2"> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">案例:某保健品页添加“FDA认证”图标,转化率提升18%</span></p></li> </ul> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="margin: 0px;padding: 0px;box-sizing: border-box;"><span leaf="">(</span><span style="letter-spacing: 1.3px;box-sizing: border-box;"><span leaf="">2)内容更新周期</span></span></p> </section> <section style="line-height: 0;box-sizing: border-box;"> <section style="max-width: 100%;vertical-align: middle;display: inline-block;line-height: 0;box-sizing: border-box;" nodeleaf=""> <img src="/upload/53464dce6d6da5d7da8ba708bb1f400f.png" class="rich_pages wxw-img" data-ratio="0.2706855791962175" data-s="300,640" data-type="png" data-w="846" style="vertical-align: middle;max-width: 100%;width: 100%;box-sizing: border-box;" data-imgfileid="100013463"> </section> </section> <section style="text-align: left;box-sizing: border-box;"> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 18px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf="">4. 权威信号建设:获取高质量外链</span></span></strong></p> <p style="margin: 0px;padding: 0px;box-sizing: border-box;"><span style="letter-spacing: 1.3px;box-sizing: border-box;"><span leaf="">(</span></span><span style="letter-spacing: 1.3px;box-sizing: border-box;"><span leaf="">1)安全外链获取策略</span></span></p> </section> <section style="line-height: 0;box-sizing: border-box;"> <section style="max-width: 100%;vertical-align: middle;display: inline-block;line-height: 0;box-sizing: border-box;" nodeleaf=""> <img src="/upload/2d2f15ef6158e31dbd2f54f2fefc5af3.png" class="rich_pages wxw-img" data-ratio="0.3113207547169811" data-s="300,640" data-type="png" data-w="1060" style="vertical-align: middle;max-width: 100%;width: 100%;box-sizing: border-box;" data-imgfileid="100013462"> </section> </section> <section style="text-align: left;box-sizing: border-box;"> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">(2)高危操作黑名单</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">❌ 购买PBN(私有博客网络)外链 案例:某电商站因购买PBN链接被谷歌降权,流量暴跌70%</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">❌ 群发垃圾评论获取链接 案例:某教育机构在论坛群发链接,域名被标记为SPAM</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">❌ 使用完全匹配锚文本超50% 案例:某金融站过度优化“贷款计算器”锚文本,排名不升反降</span></p> <p style="margin: 0px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> </section> <section style="text-align: left;box-sizing: border-box;"> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 22px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf="">三、执行SEO方案的六大禁忌与真实教训</span></span></strong></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">禁忌1:关键词堆砌</span></p> <ul style="list-style-type: disc;box-sizing: border-box;padding-left: 40px;list-style-position: outside;" class="list-paddingleft-2"> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">案例:某旅游站重复堆砌"巴厘岛酒店"15次,被算法判定过度优化,排名消失</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">解决方案:自然分布核心词(密度1.2%-1.8%),用LSI词替代</span></p></li> </ul> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">禁忌2:忽视移动端</span></p> <ul style="list-style-type: disc;box-sizing: border-box;padding-left: 40px;list-style-position: outside;" class="list-paddingleft-2"> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">案例:某餐厅网站未适配移动端,60%用户3秒内跳出,谷歌排名持续下滑</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">解决方案:用Google移动友好测试工具修复问题</span></p></li> </ul> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">禁忌3:抄袭内容</span></p> <ul style="list-style-type: disc;box-sizing: border-box;padding-left: 40px;list-style-position: outside;" class="list-paddingleft-2"> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">案例:某健康站复制维基百科内容,Copyscape检测重复率62%,索引被删除</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">解决方案:原创内容+AI改写检测</span></p></li> </ul> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">禁忌4:忽略数据反馈</span></p> <ul style="list-style-type: disc;box-sizing: border-box;padding-left: 40px;list-style-position: outside;" class="list-paddingleft-2"> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">案例:某电商站半年未查看Search Console,后续觉得奇怪才发现500个页面未被索引</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">解决方案:设置每周数据巡检制度</span></p></li> </ul> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">禁忌5:闭门造车</span></p> <ul style="list-style-type: disc;box-sizing: border-box;padding-left: 40px;list-style-position: outside;" class="list-paddingleft-2"> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">案例:某工具站未分析竞品,错失"PDF转Word"等高价值词</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">解决方案:用SEMrush分析3个竞品策略</span></p></li> </ul> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">禁忌6:急功近利</span></p> <ul style="list-style-type: disc;box-sizing: border-box;padding-left: 40px;list-style-position: outside;" class="list-paddingleft-2"> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">案例:某新站1个月内发布200篇AI生成内容,被算法惩罚降权</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">解决方案:保持自然增长节奏(每周发布2-3篇优质内容)</span></p></li> </ul> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="text-align: justify;white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 18px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf="">四、新手必备工具包与使用场景</span></span></strong></p> </section> <section style="line-height: 0;box-sizing: border-box;"> <section style="max-width: 100%;vertical-align: middle;display: inline-block;line-height: 0;box-sizing: border-box;" nodeleaf=""> <img src="/upload/62a152c68bef386a208d30e3a94c831a.png" class="rich_pages wxw-img" data-ratio="0.3242603550295858" data-s="300,640" data-type="png" data-w="845" style="vertical-align: middle;max-width: 100%;width: 100%;box-sizing: border-box;" data-imgfileid="100013464"> </section> </section> <section style="text-align: left;box-sizing: border-box;"> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="text-align: justify;white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 18px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf="">五、30天快速启动计划与成果预期</span></span></strong></p> </section> <section style="line-height: 0;box-sizing: border-box;"> <section style="max-width: 100%;vertical-align: middle;display: inline-block;line-height: 0;width: 100%;height: auto;box-sizing: border-box;" nodeleaf=""> <img src="/upload/b378fe1443b285ebf076b97a5d9f3704.png" class="rich_pages wxw-img" data-ratio="0.2964930924548353" data-s="300,640" data-type="png" data-w="941" style="vertical-align: middle;max-width: 100%;width: 100%;box-sizing: border-box;" data-imgfileid="100013469"> </section> </section> <section style="text-align: left;box-sizing: border-box;"> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="text-align: justify;margin: 0px 0px 13px;white-space: normal;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 22px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf=""><br></span></span></strong></p> <p style="text-align: justify;margin: 0px 0px 13px;white-space: normal;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 22px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf="">如何利用DeepSeek深度赋能SEO优化全流程</span></span></strong></p> <p style="text-align: justify;margin: 0px 0px 13px;white-space: normal;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 18px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf="">一、DeepSeek在SEO中的核心价值</span></span></strong></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">DeepSeek的核心优势:通过AI大模型的语义理解与生成能力,突破传统工具瓶颈,实现效率倍增+效果突破。以下为全流程整合方案:</span></p> <p style="text-align: justify;margin: 0px 0px 13px;white-space: normal;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 18px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf=""><br></span></span></strong></p> <p style="text-align: justify;margin: 0px 0px 13px;white-space: normal;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 18px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf=""><br></span></span></strong></p> <p style="text-align: justify;margin: 0px 0px 13px;white-space: normal;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 18px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf="">二、分阶段深度应用指南</span></span></strong></p> <p style="text-align: justify;margin: 0px 0px 13px;white-space: normal;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 18px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf="">1. 关键词研究:智能语义挖掘</span></span></strong></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">(1)长尾词矩阵</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">基于'咖啡机'找到4个包含场景、地域、疑问结构的搜索词 "咖啡机清洁方法 视频教程", "深圳南山咖啡机租赁服务", "如何选择适合小户型的咖啡机", "咖啡机不出蒸汽故障排查"</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">验证操作方式:</span></p> <ol style="list-style-type: decimal;box-sizing: border-box;padding-left: 40px;list-style-position: outside;" class="list-paddingleft-2"> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">输入核心词+需求描述(如“带地域限定”“疑问句式”)</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">导出JSON格式词表,导入SEMrush验证搜索量</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">筛选KD<40且搜索量>200的词</span></p></li> </ol> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">(2)搜索意图深度解析</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">案例:分析“咖啡机推荐”的搜索意图演变:</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">DeepSeek通过分析TOP100搜索结果,发现2024年用户更关注“节能参数”(提及率+35%)</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">建议内容增加“每月耗电量对比”模块</span></p> <p style="text-align: justify;margin: 0px 0px 13px;white-space: normal;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 18px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf=""><br></span></span></strong></p> <p style="text-align: justify;margin: 0px 0px 13px;white-space: normal;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 18px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf="">2. 内容优化:AI驱动的高效创作</span></span></strong></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">(1)E-E-A-T增强内容生成</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">操作流程:</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">输入核心词+优化指令:</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">"生成关于'咖啡机清洗'的专家级指南</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">要求:</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">- 包含5个常见错误清洗方法</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">- 引用SCA(精品咖啡协会)标准</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">- 插入分步骤视频脚本"</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">输出内容经人工审核后发布</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">用Copyscape检测原创性(重复率<3%)</span></p> <p style="margin: 0px;padding: 0px;box-sizing: border-box;"><span leaf="">效率对比:</span></p> </section> <section style="line-height: 0;box-sizing: border-box;"> <section style="max-width: 100%;vertical-align: middle;display: inline-block;line-height: 0;box-sizing: border-box;" nodeleaf=""> <img src="/upload/b3426586b859ea56e9dda9cb3bab4b8a.png" class="rich_pages wxw-img" data-ratio="0.2727272727272727" data-s="300,640" data-type="png" data-w="429" style="vertical-align: middle;max-width: 100%;width: 100%;box-sizing: border-box;" data-imgfileid="100013468"> </section> </section> <section style="text-align: left;box-sizing: border-box;"> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="text-align: justify;margin: 0px 0px 13px;white-space: normal;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 18px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf="">3. 技术SEO:智能化诊断与修复</span></span></strong></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">(1)自动化代码优化</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">批量生成页面结构化数据</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">自动检测标记错误(如价格单位缺失)</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">(2)智能异常监测</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">实时预警系统:</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">监控Search Console数据,当出现以下情况时触发警报:</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">✅ 核心词排名下跌>5位 </span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">✅ 索引覆盖率下降>10%</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">✅ 移动可用性评分<90</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">自动生成诊断报告与修复建议</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="text-align: justify;margin: 0px 0px 13px;white-space: normal;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 18px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf="">4. 外链建设:AI驱动的资源获取</span></span></strong></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">(1)高权重媒体挖掘</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">操作流程:</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">输入行业关键词(如“咖啡器具评测”)</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">DeepSeek分析TOP100文章,提取高DR媒体列表</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">生成个性化投稿邮件模板:</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""> "您好[编辑姓名], </span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""> 我是[品牌]的咖啡设备专家,基于SCA标准撰写了《2024咖啡机清洁白皮书》,包含行业首创的[具体技术点]。此文已被[某协会]推荐,希望能为贵站读者提供价值..."</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">(2)外链质量评估</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">AI评分模型:</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">外链质量评估维度评估指标 = </span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">"域名权威性": 0.8, # DR>60为优质 </span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">"内容相关性": 0.9, # 与本站主题匹配度 </span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">"锚文本自然度": 0.7 # 商业关键词占比<30%</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">总评分 = sum(评估指标.values()) / len(评估指标) # 0.8</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">应用场景:</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">自动过滤毒性外链(评分<0.6)</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">优先获取评分>0.85的优质外链</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="text-align: justify;margin: 0px 0px 13px;white-space: normal;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 18px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf="">三、高阶应用:预测与策略优化</span></span></strong></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">1. 流量预测模型</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">操作示例:输入历史数据(关键词排名/流量),DeepSeek预测:</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">"优化'家用咖啡机推荐'至TOP3后: - 预计月流量增长:1200-1500 - 转化率提升范围:1.8%-2.5% - 需新增3个DR>50的外链支撑"</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">2. 算法更新应对</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">实时监控与策略调整:</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">当检测到HCU(Helpful Content Update)算法更新时:</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">自动扫描低质量内容(用户停留时间<1分钟)</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">生成重写建议(增加实操案例/专家问答)</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">优先更新流量下降>20%的页面</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="text-align: justify;white-space: normal;margin: 0px;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 18px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf="">四、实施工具链配置建议</span></span></strong></p> </section> <section style="line-height: 0;box-sizing: border-box;"> <section style="max-width: 100%;vertical-align: middle;display: inline-block;line-height: 0;box-sizing: border-box;" nodeleaf=""> <img src="/upload/a28a9f741e3fc89b09c240dfd4a9774d.png" class="rich_pages wxw-img" data-ratio="0.47586206896551725" data-s="300,640" data-type="png" data-w="580" style="vertical-align: middle;max-width: 100%;width: 100%;box-sizing: border-box;" data-imgfileid="100013470"> </section> </section> <section style="text-align: left;box-sizing: border-box;"> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="text-align: justify;margin: 0px 0px 13px;white-space: normal;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 18px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf="">五、风险控制与最佳实践</span></span></strong></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">1. 人工审核是必须项</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">AI生成内容需通过Copyscape+人工校验</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">外链建设策略需手动确认媒体相关性</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="margin: 0px;padding: 0px;box-sizing: border-box;"><span leaf="">2. 效果对比案例</span></p> </section> <section style="line-height: 0;box-sizing: border-box;"> <section style="max-width: 100%;vertical-align: middle;display: inline-block;line-height: 0;box-sizing: border-box;" nodeleaf=""> <img src="/upload/7eef5b277a51a807f00d045b2c2dd93f.png" class="rich_pages wxw-img" data-ratio="0.3445121951219512" data-s="300,640" data-type="png" data-w="656" style="vertical-align: middle;max-width: 100%;width: 100%;box-sizing: border-box;" data-imgfileid="100013471"> </section> </section> <section style="text-align: left;box-sizing: border-box;"> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">立即行动清单:</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">使用DeepSeek生成首个长尾词库(50词起步)</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">选择3个产品页测试AI生成Schema标记</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">配置核心词排名监控预警规则</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">通过DeepSeek的深度整合,SEO团队效率可提升3-5倍,同时内容质量评分提升40%+。建议从关键词挖掘和内容生成模块优先切入,逐步构建智能化工作流。</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="text-align: justify;margin: 0px 0px 13px;white-space: normal;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 22px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf="">DeepSeek多语言SEO优化方案</span></span></strong></p> <p style="text-align: justify;margin: 0px 0px 13px;white-space: normal;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 18px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf="">一、突破语言边界的智能策略</span></span></strong></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">1. 语义精准适配</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">语境感知翻译系统自动识别不同语种的表达习惯,例如:</span></p> <ul style="list-style-type: disc;box-sizing: border-box;padding-left: 40px;list-style-position: outside;" class="list-paddingleft-2"> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">英语用户搜索"best budget coffee maker"时,侧重性价比参数对比</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">日本用户查询"コーヒーメーカー 省エネ"(节能咖啡机)时,强化能耗认证信息</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">阿拉伯语场景下"ماكينة قهوة بدون صوت"(静音咖啡机)需突出降噪技术说明</span></p></li> </ul> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">文化敏感度检测自动预警宗教禁忌与敏感历史关联词,例如:</span></p> <ul style="list-style-type: disc;box-sizing: border-box;padding-left: 40px;list-style-position: outside;" class="list-paddingleft-2"> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">中东地区规避含有酒精成分的食品描述</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">东南亚市场避免使用特定动物形象图标</span></p></li> </ul> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">2. 多维度关键词体系</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">本地化长尾词矩阵基于地理特征生成适配词库:</span></p> <ul style="list-style-type: disc;box-sizing: border-box;padding-left: 40px;list-style-position: outside;" class="list-paddingleft-2"> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">德国用户偏好技术参数:"Kaffeevollautomat mit 15 Bar Druck"(15巴压力咖啡机)</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">巴西市场关注促销信息:"cafeteira automática com desconto"(自动咖啡机折扣)</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">韩国流行趋势词:"커피메이커 신제품 리뷰"(咖啡机新品评测)</span></p></li> </ul> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">动态搜索趋势追踪实时监控各语言区热搜变化,例如:</span></p> <ul style="list-style-type: disc;box-sizing: border-box;padding-left: 40px;list-style-position: outside;" class="list-paddingleft-2"> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">发现法语区"machine à café écologique"(环保咖啡机)搜索量月增45%</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">及时生成《欧盟环保认证咖啡机选购指南》法文版</span></p></li> </ul> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="text-align: justify;margin: 0px 0px 13px;white-space: normal;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 22px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf="">二、全流程技术适配方案</span></span></strong></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">1. 地理智能识别系统</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">IP定位优化自动推送地域适配内容:</span></p> <ul style="list-style-type: disc;box-sizing: border-box;padding-left: 40px;list-style-position: outside;" class="list-paddingleft-2"> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">墨西哥用户访问时优先展示西班牙语内容</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">加拿大法语区用户获取魁北克方言优化版本</span></p></li> </ul> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">多语言站群架构智能配置技术要素:</span></p> <ul style="list-style-type: disc;box-sizing: border-box;padding-left: 40px;list-style-position: outside;" class="list-paddingleft-2"> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">自动生成hreflang标签关联各语言版本</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">动态调整服务器响应时间(欧洲节点<0.8秒,亚洲节点<1.2秒)</span></p></li> </ul> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">2. 跨平台内容管理</span></p> <ul style="list-style-type: disc;box-sizing: border-box;padding-left: 40px;list-style-position: outside;" class="list-paddingleft-2"> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">统一内容枢纽中央控制台实现:</span></p><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">多语言内容版本对比</span></p><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">自动同步产品数据更新</span></p><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">批量管理50+语言元标签</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">智能翻译记忆库积累行业专属术语库:</span></p><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">医疗设备领域精准对应"MRI"与"磁共振成像"</span></p><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">法律文件保持条款表述一致性</span></p></li> </ul> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="text-align: justify;margin: 0px 0px 13px;white-space: normal;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 18px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf="">三、本地化权威建设体系</span></span></strong></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">1. 区域化外联网络</span></p> <ul style="list-style-type: disc;box-sizing: border-box;padding-left: 40px;list-style-position: outside;" class="list-paddingleft-2"> <li style="box-sizing: border-box;"><p style="margin: 0px;padding: 0px;box-sizing: border-box;"><span leaf="">高权重平台智能匹配自动推荐各语种优质资源:</span></p></li> </ul> </section> <section style="line-height: 0;box-sizing: border-box;"> <section style="max-width: 100%;vertical-align: middle;display: inline-block;line-height: 0;box-sizing: border-box;" nodeleaf=""> <img src="/upload/5697d809dc17755682e75fe55c4de0a5.png" class="rich_pages wxw-img" data-ratio="0.4444444444444444" data-s="300,640" data-type="png" data-w="432" style="vertical-align: middle;max-width: 100%;width: 100%;box-sizing: border-box;" data-imgfileid="100013467"> </section> </section> <section style="text-align: left;box-sizing: border-box;"> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""> </span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">本地KOL合作管理建立跨国红人数据库:</span></p> <ul style="list-style-type: disc;box-sizing: border-box;padding-left: 40px;list-style-position: outside;" class="list-paddingleft-2"> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">自动分析红人领域匹配度</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">生成个性化合作邀约模板</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">追踪合作内容传播效果</span></p></li> </ul> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">2. 区域性信任背书</span></p> <ul style="list-style-type: disc;box-sizing: border-box;padding-left: 40px;list-style-position: outside;" class="list-paddingleft-2"> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">自动生成合规文档适配各地法规要求:</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">欧盟CE认证多语言说明书</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">北美UL安全认证指南</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">中国GB国家标准解读</span></p></li> </ul> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">本地客户证言系统智能收集展示案例:</span></p> <ul style="list-style-type: disc;box-sizing: border-box;padding-left: 40px;list-style-position: outside;" class="list-paddingleft-2"> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">自动抓取Google My Business多语言评价</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">生成带地理标签的成功案例库</span></p></li> </ul> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="text-align: justify;margin: 0px 0px 13px;white-space: normal;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 18px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf="">四、智能监测与持续优化</span></span></strong></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">1. 多维度数据看板</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">实时流量追踪可视化展示:</span></p> <ul style="list-style-type: disc;box-sizing: border-box;padding-left: 40px;list-style-position: outside;" class="list-paddingleft-2"> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">各语言版本流量占比</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">本地搜索词排名波动</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">跨语言内容转化对比</span></p></li> </ul> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">智能预警系统自动识别风险:</span></p> <ul style="list-style-type: disc;box-sizing: border-box;padding-left: 40px;list-style-position: outside;" class="list-paddingleft-2"> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">某语种跳出率突增20%</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">特定地区索引页面异常减少</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">重要关键词排名连续下降</span></p></li> </ul> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">2. 动态优化建议</span></p> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">内容迭代提示基于用户行为分析:</span></p> <ul style="list-style-type: disc;box-sizing: border-box;padding-left: 40px;list-style-position: outside;" class="list-paddingleft-2"> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">发现西班牙语用户偏爱视频教程</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">建议将图文指南转化为短视频</span></p></li> </ul> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">竞品策略透视跨国竞品监控:</span></p> <ul style="list-style-type: disc;box-sizing: border-box;padding-left: 40px;list-style-position: outside;" class="list-paddingleft-2"> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">分析德国竞品的技术文档结构</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">比对中国竞品的促销话术设计</span></p></li> </ul> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="text-align: justify;margin: 0px 0px 13px;white-space: normal;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 18px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf=""><br></span></span></strong></p> <p style="text-align: justify;margin: 0px 0px 13px;white-space: normal;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 18px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf="">五、实施路径与效果预测</span></span></strong></p> <p style="margin: 0px;padding: 0px;box-sizing: border-box;"><span leaf="">1. 三阶段实施计划</span></p> </section> <section style="line-height: 0;box-sizing: border-box;"> <section style="max-width: 100%;vertical-align: middle;display: inline-block;line-height: 0;box-sizing: border-box;" nodeleaf=""> <img src="/upload/6e95da0d468bd09c929d69260871ed44.png" class="rich_pages wxw-img" data-ratio="0.36217948717948717" data-s="300,640" data-type="png" data-w="624" style="vertical-align: middle;max-width: 100%;width: 100%;box-sizing: border-box;" data-imgfileid="100013473"> </section> </section> <section style="text-align: left;box-sizing: border-box;"> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="margin: 0px;padding: 0px;box-sizing: border-box;"><span leaf="">2. 成本效率对比</span></p> </section> <section style="line-height: 0;box-sizing: border-box;"> <section style="max-width: 100%;vertical-align: middle;display: inline-block;line-height: 0;box-sizing: border-box;" nodeleaf=""> <img src="/upload/3a256f89041dee48500f2005a6320ea4.png" class="rich_pages wxw-img" data-ratio="0.3729641693811075" data-s="300,640" data-type="png" data-w="614" style="vertical-align: middle;max-width: 100%;width: 100%;box-sizing: border-box;" data-imgfileid="100013472"> </section> </section> <section style="text-align: left;box-sizing: border-box;"> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf=""><br></span></p> <p style="text-align: justify;margin: 0px 0px 13px;white-space: normal;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 18px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf=""><br></span></span></strong></p> <p style="text-align: justify;margin: 0px 0px 13px;white-space: normal;padding: 0px;box-sizing: border-box;"><strong style="box-sizing: border-box;"><span style="font-size: 18px;color: rgb(0, 0, 0);box-sizing: border-box;"><span leaf="">六、成功案例实证</span></span></strong></p> <ul style="list-style-type: disc;box-sizing: border-box;padding-left: 40px;list-style-position: outside;" class="list-paddingleft-2"> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">案例:智能家电品牌全球化突围</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">挑战:需在6个月内实现8种语言的SEO覆盖,目标进入20国市场Top3</span></p></li> </ul> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">解决方案:</span></p> <ul style="list-style-type: disc;box-sizing: border-box;padding-left: 40px;list-style-position: outside;" class="list-paddingleft-2"> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">生成8000+本地化长尾词库</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">自动创建适配各区域的环保认证文档</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">建立跨语言客户案例库</span></p></li> </ul> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">成果:</span></p> <ul style="list-style-type: disc;box-sizing: border-box;padding-left: 40px;list-style-position: outside;" class="list-paddingleft-2"> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">德语区核心词排名6周进入Top5</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">阿拉伯语版本转化率超本地品牌40%</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">整体优化成本降低67%</span></p></li> </ul> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">行动建议:</span></p> <ul style="list-style-type: disc;box-sizing: border-box;padding-left: 40px;list-style-position: outside;" class="list-paddingleft-2"> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">启动多语言SEO智能诊断(免费生成风险报告)</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">选择3个战略市场试点AI优化方案</span></p></li> <li style="box-sizing: border-box;"><p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">预约跨国SEO架构师定制路线图</span></p></li> </ul> <p style="margin: 0px 0px 13px;padding: 0px;box-sizing: border-box;"><span leaf="">通过DeepSeek的智能系统,可突破传统多语言管理的资源瓶颈,实现全球化精准获客。从关键词到内容,从技术到运营,全方位提升。</span></p> </section> </section>
作者:微信小助手
<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 10px;padding-right: 10px;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;font-family: Optima, 'Microsoft YaHei', PingFangSC-regular, serif;font-size: 16px;color: rgb(0, 0, 0);line-height: 1.5em;word-spacing: 0em;letter-spacing: 0em;word-break: break-word;overflow-wrap: break-word;text-align: left;" data-pm-slice="0 0 []"> <blockquote style="margin-top: 20px;margin-bottom: 20px;margin-left: 0px;margin-right: 0px;padding-top: 10px;padding-bottom: 10px;padding-left: 20px;padding-right: 10px;border-top-style: none;border-bottom-style: none;border-left-style: solid;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgb(53, 179, 120);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;background-attachment: scroll;background-clip: border-box;background-color: rgb(251, 249, 253);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;display: block;overflow-x: auto;overflow-y: auto;"> <span style="display: none;color: rgb(0, 0, 0);font-size: 16px;line-height: 1.5em;letter-spacing: 0em;text-align: left;font-weight: normal;"></span> <p style="text-indent: 0em;padding-top: 16px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;color: rgb(63, 63, 63);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;margin-top: 0px;margin-right: 0px;margin-bottom: 0px;margin-left: 0px;"><strong style="color: rgb(74, 74, 74);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">RAGFlow</span></strong><span leaf=""> 是基于深度文档理解的开源RAG引擎,通过与LLM结合提供带精准引用的问答能力。支持20+文档格式解析,提供智能分块策略和混合检索方案,具备可视化干预界面,支持Docker快速部署,是企业级知识库构建的利器!</span></p> </blockquote> <h2 data-cacheurl="" data-remoteid="" data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-left: 0px;padding-right: 0px;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-origin: padding-box;background-position-x: 50%;background-position-y: 50%;background-repeat: no-repeat;background-size: 63px;width: auto;height: auto;align-items: unset;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;justify-content: center;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;text-align: left;text-shadow: none;transform: none;-webkit-box-reflect: unset;background-image: url(" https: mmbiz.qpic.cn mmbiz_png mrgvnruiwydfpgqx7myyyzbimhibrggljxzjk51k5r0aedpwtfeoyvichjplcca76mmvuud5wbkg30er9sajpgng 640?wx_fmt="png&from=appmsg");""><span style="display: none;"></span><span style="font-size: 18px;color: rgb(72, 179, 120);line-height: 2.4em;letter-spacing: 0em;margin-top: 38px;margin-bottom: 10px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: 38px;justify-content: unset;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: center;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">为什么你需要这个神器?</span></span><span style="display: none;"></span></h2> <p data-tool="mdnice编辑器" style="color: rgb(63, 63, 63);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 16px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">在企业知识管理、法律文书分析、学术研究等场景中,我们常面临三大痛点:</span></p> <ol style="list-style-type: decimal;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 25px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">多格式文档解析困难(合同/论文/报表等)</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">传统检索方式准确率低</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">AI问答存在"幻觉"风险</span> </section></li> </ol> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img src="/upload/f79b049d88d0a69c31e2ed3aaad89462.jpg" class="rich_pages wxw-img" data-ratio="0.562962962962963" data-type="jpeg" data-w="1080" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;" data-imgfileid="100007162"></span> </figure> <p data-tool="mdnice编辑器" style="color: rgb(63, 63, 63);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 16px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">RAGFlow 正是为解决这些问题而生!</span></p> <h2 data-cacheurl="" data-remoteid="" data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-left: 0px;padding-right: 0px;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-origin: padding-box;background-position-x: 50%;background-position-y: 50%;background-repeat: no-repeat;background-size: 63px;width: auto;height: auto;align-items: unset;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;justify-content: center;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;text-align: left;text-shadow: none;transform: none;-webkit-box-reflect: unset;background-image: url(" https: mmbiz.qpic.cn mmbiz_png mrgvnruiwydfpgqx7myyyzbimhibrggljxzjk51k5r0aedpwtfeoyvichjplcca76mmvuud5wbkg30er9sajpgng 640?wx_fmt="png&from=appmsg");""><span style="display: none;"></span><span style="font-size: 18px;color: rgb(72, 179, 120);line-height: 2.4em;letter-spacing: 0em;margin-top: 38px;margin-bottom: 10px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: 38px;justify-content: unset;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: center;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">五大核心功能亮剑</span></span><span style="display: none;"></span></h2> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span data-cacheurl="" data-remoteid="" style="background-attachment: scroll;background-clip: border-box;background-color: transparent;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: 15px 15px;width: 15px;height: 15px;align-items: unset;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;color: rgb(0, 0, 0);display: inline-block;font-size: 22px;font-weight: bold;flex-direction: unset;float: unset;justify-content: unset;letter-spacing: 0px;line-height: 1.5em;margin-top: 0px;margin-bottom: -2px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-indent: 0em;text-shadow: none;transform: none;-webkit-box-reflect: unset;background-image: url(" https: mmbiz.qpic.cn mmbiz_png mrgvnruiwydfpgqx7myyyzbimhibrggljiicg8iccbcdl8vbgcoeokkwc2p3jq31drvgjvzyf0fhvwkrybyv7peqg 640?wx_fmt="png&from=appmsg");""></span><span style="display: none;"></span><span style="font-size: 16px;color: rgb(72, 179, 120);line-height: 1.5em;letter-spacing: 0em;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 8px;margin-right: 0px;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">深度文档理解</span></span><span style="display: none;"></span></h3> <ul style="list-style-type: disc;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 25px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">支持格式:PDF/DOCX/PPT/XLSX/JPG等20+常见格式</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">特色解析:</span><span leaf=""><br></span><span leaf="">✅ 表格数据结构化提取</span><span leaf=""><br></span><span leaf="">✅ 数学公式Latex格式保留</span><span leaf=""><br></span><span leaf="">✅ 图片OCR文字识别</span><span leaf=""><br></span><span leaf="">✅ 多栏排版智能重组</span> </section></li> </ul> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span data-cacheurl="" data-remoteid="" style="background-attachment: scroll;background-clip: border-box;background-color: transparent;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: 15px 15px;width: 15px;height: 15px;align-items: unset;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;color: rgb(0, 0, 0);display: inline-block;font-size: 22px;font-weight: bold;flex-direction: unset;float: unset;justify-content: unset;letter-spacing: 0px;line-height: 1.5em;margin-top: 0px;margin-bottom: -2px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-indent: 0em;text-shadow: none;transform: none;-webkit-box-reflect: unset;background-image: url(" https: mmbiz.qpic.cn mmbiz_png mrgvnruiwydfpgqx7myyyzbimhibrggljiicg8iccbcdl8vbgcoeokkwc2p3jq31drvgjvzyf0fhvwkrybyv7peqg 640?wx_fmt="png&from=appmsg");""></span><span style="display: none;"></span><span style="font-size: 16px;color: rgb(72, 179, 120);line-height: 1.5em;letter-spacing: 0em;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 8px;margin-right: 0px;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">智能分块策略</span></span><span style="display: none;"></span></h3> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg wzjhlvpsrd3ef7sqnh3uco6zmibsqgacdibndmqyq0wsy2p7k3aseainqjjiqli4tf4mic0nhvrnt5acljmblnjflsxotf9tckh 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf=""># 分块配置示例(yaml格式)</span></span><span leaf=""><br></span><span leaf="">chunk:</span><span leaf=""><br></span><span leaf=""> splitter: </span><span style="color: #98c379;line-height: 26px;"><span leaf="">"smart"</span></span><span leaf=""><br></span><span leaf=""> max_length: </span><span style="color: #d19a66;line-height: 26px;"><span leaf="">512</span></span><span leaf=""><br></span><span leaf=""> overlap: </span><span style="color: #d19a66;line-height: 26px;"><span leaf="">64</span></span><span leaf=""><br></span><span leaf=""> image_caption: true</span><span leaf=""><br></span></code></pre> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span data-cacheurl="" data-remoteid="" style="background-attachment: scroll;background-clip: border-box;background-color: transparent;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: 15px 15px;width: 15px;height: 15px;align-items: unset;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;color: rgb(0, 0, 0);display: inline-block;font-size: 22px;font-weight: bold;flex-direction: unset;float: unset;justify-content: unset;letter-spacing: 0px;line-height: 1.5em;margin-top: 0px;margin-bottom: -2px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-indent: 0em;text-shadow: none;transform: none;-webkit-box-reflect: unset;background-image: url(" https: mmbiz.qpic.cn mmbiz_png mrgvnruiwydfpgqx7myyyzbimhibrggljiicg8iccbcdl8vbgcoeokkwc2p3jq31drvgjvzyf0fhvwkrybyv7peqg 640?wx_fmt="png&from=appmsg");""></span><span style="display: none;"></span><span style="font-size: 16px;color: rgb(72, 179, 120);line-height: 1.5em;letter-spacing: 0em;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 8px;margin-right: 0px;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">混合检索方案</span></span><span style="display: none;"></span></h3> <ol style="list-style-type: decimal;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 25px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">语义检索(Embedding模型)</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">关键词检索(BM25算法)</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">多路召回结果融合排序</span> </section></li> </ol> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span data-cacheurl="" data-remoteid="" style="background-attachment: scroll;background-clip: border-box;background-color: transparent;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: 15px 15px;width: 15px;height: 15px;align-items: unset;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;color: rgb(0, 0, 0);display: inline-block;font-size: 22px;font-weight: bold;flex-direction: unset;float: unset;justify-content: unset;letter-spacing: 0px;line-height: 1.5em;margin-top: 0px;margin-bottom: -2px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-indent: 0em;text-shadow: none;transform: none;-webkit-box-reflect: unset;background-image: url(" https: mmbiz.qpic.cn mmbiz_png mrgvnruiwydfpgqx7myyyzbimhibrggljiicg8iccbcdl8vbgcoeokkwc2p3jq31drvgjvzyf0fhvwkrybyv7peqg 640?wx_fmt="png&from=appmsg");""></span><span style="display: none;"></span><span style="font-size: 16px;color: rgb(72, 179, 120);line-height: 1.5em;letter-spacing: 0em;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 8px;margin-right: 0px;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">灵活部署方案</span></span><span style="display: none;"></span></h3> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg wzjhlvpsrd3ef7sqnh3uco6zmibsqgacdibndmqyq0wsy2p7k3aseainqjjiqli4tf4mic0nhvrnt5acljmblnjflsxotf9tckh 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span style="color: #5c6370;font-style: italic;line-height: 26px;"><span leaf=""># 一键启动命令</span></span><span leaf=""><br></span><span leaf="">docker compose -f docker/docker-compose.yml up -d</span><span leaf=""><br></span></code></pre> <p data-tool="mdnice编辑器" style="color: rgb(63, 63, 63);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 16px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">支持CPU/GPU环境,最小4核CPU+16GB内存即可运行</span></p> <h2 data-cacheurl="" data-remoteid="" data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-left: 0px;padding-right: 0px;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-origin: padding-box;background-position-x: 50%;background-position-y: 50%;background-repeat: no-repeat;background-size: 63px;width: auto;height: auto;align-items: unset;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;justify-content: center;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;text-align: left;text-shadow: none;transform: none;-webkit-box-reflect: unset;background-image: url(" https: mmbiz.qpic.cn mmbiz_png mrgvnruiwydfpgqx7myyyzbimhibrggljxzjk51k5r0aedpwtfeoyvichjplcca76mmvuud5wbkg30er9sajpgng 640?wx_fmt="png&from=appmsg");""><span style="display: none;"></span><span style="font-size: 18px;color: rgb(72, 179, 120);line-height: 2.4em;letter-spacing: 0em;margin-top: 38px;margin-bottom: 10px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: 38px;justify-content: unset;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: center;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">技术架构解密</span></span><span style="display: none;"></span></h2> <section data-tool="mdnice编辑器" style="margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;overflow-x: auto;"> <table style="display: table;text-align: left;"> <thead> <tr> <th style="color: rgb(63, 63, 63);font-size: 16px;line-height: 1.5em;letter-spacing: 0.02em;text-align: left;font-weight: bold;background: none 0% 0% / auto no-repeat scroll padding-box border-box rgb(240, 240, 240);height: auto;border-style: solid;border-width: 1px;border-color: rgba(204, 204, 204, 0.4);border-radius: 0px;padding: 5px 10px;min-width: 85px;"> <section> <span leaf="">组件</span> </section></th> <th style="color: rgb(63, 63, 63);font-size: 16px;line-height: 1.5em;letter-spacing: 0.02em;text-align: left;font-weight: bold;background: none 0% 0% / auto no-repeat scroll padding-box border-box rgb(240, 240, 240);height: auto;border-style: solid;border-width: 1px;border-color: rgba(204, 204, 204, 0.4);border-radius: 0px;padding: 5px 10px;min-width: 85px;"> <section> <span leaf="">技术选型</span> </section></th> <th style="color: rgb(63, 63, 63);font-size: 16px;line-height: 1.5em;letter-spacing: 0.02em;text-align: left;font-weight: bold;background: none 0% 0% / auto no-repeat scroll padding-box border-box rgb(240, 240, 240);height: auto;border-style: solid;border-width: 1px;border-color: rgba(204, 204, 204, 0.4);border-radius: 0px;padding: 5px 10px;min-width: 85px;"> <section> <span leaf="">核心作用</span> </section></th> </tr> </thead> <tbody> <tr style="color: rgb(63, 63, 63);background-attachment: scroll;background-clip: border-box;background-color: rgb(255, 255, 255);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;"> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">文档解析引擎</span> </section></td> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">Apache Tika+自定义解析器</span> </section></td> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">多格式文档内容提取</span> </section></td> </tr> <tr style="color: rgb(0, 0, 0);background-attachment: scroll;background-clip: border-box;background-color: rgb(248, 248, 248);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;"> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">向量数据库</span> </section></td> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">Elasticsearch 8.x</span> </section></td> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">支持混合检索方案</span> </section></td> </tr> <tr style="color: rgb(63, 63, 63);background-attachment: scroll;background-clip: border-box;background-color: rgb(255, 255, 255);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;"> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">对象存储</span> </section></td> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">MinIO</span> </section></td> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">原始文件存储管理</span> </section></td> </tr> <tr style="color: rgb(0, 0, 0);background-attachment: scroll;background-clip: border-box;background-color: rgb(248, 248, 248);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;"> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">任务调度</span> </section></td> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">Celery</span> </section></td> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">分布式文档解析任务处理</span> </section></td> </tr> <tr style="color: rgb(63, 63, 63);background-attachment: scroll;background-clip: border-box;background-color: rgb(255, 255, 255);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;"> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">前端框架</span> </section></td> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">React+Ant Design</span> </section></td> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">可视化操作界面</span> </section></td> </tr> </tbody> </table> </section> <h2 data-cacheurl="" data-remoteid="" data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-left: 0px;padding-right: 0px;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-origin: padding-box;background-position-x: 50%;background-position-y: 50%;background-repeat: no-repeat;background-size: 63px;width: auto;height: auto;align-items: unset;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;justify-content: center;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;text-align: left;text-shadow: none;transform: none;-webkit-box-reflect: unset;background-image: url(" https: mmbiz.qpic.cn mmbiz_png mrgvnruiwydfpgqx7myyyzbimhibrggljxzjk51k5r0aedpwtfeoyvichjplcca76mmvuud5wbkg30er9sajpgng 640?wx_fmt="png&from=appmsg");""><span style="display: none;"></span><span style="font-size: 18px;color: rgb(72, 179, 120);line-height: 2.4em;letter-spacing: 0em;margin-top: 38px;margin-bottom: 10px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: 38px;justify-content: unset;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: center;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">五大独特优势</span></span><span style="display: none;"></span></h2> <p data-tool="mdnice编辑器" style="color: rgb(63, 63, 63);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 16px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">相较于同类项目,RAGFlow 具备以下优势:</span></p> <section data-tool="mdnice编辑器" style="margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;overflow-x: auto;"> <table style="display: table;text-align: left;"> <thead> <tr> <th style="color: rgb(63, 63, 63);font-size: 16px;line-height: 1.5em;letter-spacing: 0.02em;text-align: left;font-weight: bold;background: none 0% 0% / auto no-repeat scroll padding-box border-box rgb(240, 240, 240);height: auto;border-style: solid;border-width: 1px;border-color: rgba(204, 204, 204, 0.4);border-radius: 0px;padding: 5px 10px;min-width: 85px;"> <section> <span leaf="">对比维度</span> </section></th> <th style="color: rgb(63, 63, 63);font-size: 16px;line-height: 1.5em;letter-spacing: 0.02em;text-align: left;font-weight: bold;background: none 0% 0% / auto no-repeat scroll padding-box border-box rgb(240, 240, 240);height: auto;border-style: solid;border-width: 1px;border-color: rgba(204, 204, 204, 0.4);border-radius: 0px;padding: 5px 10px;min-width: 85px;"> <section> <span leaf="">RAGFlow</span> </section></th> <th style="color: rgb(63, 63, 63);font-size: 16px;line-height: 1.5em;letter-spacing: 0.02em;text-align: left;font-weight: bold;background: none 0% 0% / auto no-repeat scroll padding-box border-box rgb(240, 240, 240);height: auto;border-style: solid;border-width: 1px;border-color: rgba(204, 204, 204, 0.4);border-radius: 0px;padding: 5px 10px;min-width: 85px;"> <section> <span leaf="">LangChain</span> </section></th> <th style="color: rgb(63, 63, 63);font-size: 16px;line-height: 1.5em;letter-spacing: 0.02em;text-align: left;font-weight: bold;background: none 0% 0% / auto no-repeat scroll padding-box border-box rgb(240, 240, 240);height: auto;border-style: solid;border-width: 1px;border-color: rgba(204, 204, 204, 0.4);border-radius: 0px;padding: 5px 10px;min-width: 85px;"> <section> <span leaf="">LlamaIndex</span> </section></th> </tr> </thead> <tbody> <tr style="color: rgb(63, 63, 63);background-attachment: scroll;background-clip: border-box;background-color: rgb(255, 255, 255);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;"> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">文档解析能力</span> </section></td> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">✅ 20+格式深度解析</span> </section></td> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">⚠️ 基础文本解析</span> </section></td> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">⚠️ 基础文本解析</span> </section></td> </tr> <tr style="color: rgb(0, 0, 0);background-attachment: scroll;background-clip: border-box;background-color: rgb(248, 248, 248);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;"> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">分块策略</span> </section></td> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">✅ 智能布局分析</span> </section></td> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">⚠️ 固定窗口分块</span> </section></td> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">✅ 基础语义分块</span> </section></td> </tr> <tr style="color: rgb(63, 63, 63);background-attachment: scroll;background-clip: border-box;background-color: rgb(255, 255, 255);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;"> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">检索方案</span> </section></td> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">✅ 混合检索</span> </section></td> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">✅ 向量检索</span> </section></td> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">⚠️ 单一检索方式</span> </section></td> </tr> <tr style="color: rgb(0, 0, 0);background-attachment: scroll;background-clip: border-box;background-color: rgb(248, 248, 248);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;"> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">可视化干预</span> </section></td> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">✅ 完整干预流程</span> </section></td> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">❌ 无</span> </section></td> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">❌ 无</span> </section></td> </tr> <tr style="color: rgb(63, 63, 63);background-attachment: scroll;background-clip: border-box;background-color: rgb(255, 255, 255);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;"> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">企业级特性</span> </section></td> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">✅ 用户权限/审计日志</span> </section></td> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">⚠️ 需二次开发</span> </section></td> <td style="padding-top: 5px;padding-right: 10px;padding-bottom: 5px;padding-left: 10px;min-width: 85px;border-top-style: solid;border-bottom-style: solid;border-left-style: solid;border-right-style: solid;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgba(204, 204, 204, 0.4);border-bottom-color: rgba(204, 204, 204, 0.4);border-left-color: rgba(204, 204, 204, 0.4);border-right-color: rgba(204, 204, 204, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"> <section> <span leaf="">⚠️ 需二次开发</span> </section></td> </tr> </tbody> </table> </section> <h2 data-cacheurl="" data-remoteid="" data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-left: 0px;padding-right: 0px;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-origin: padding-box;background-position-x: 50%;background-position-y: 50%;background-repeat: no-repeat;background-size: 63px;width: auto;height: auto;align-items: unset;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;justify-content: center;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;text-align: left;text-shadow: none;transform: none;-webkit-box-reflect: unset;background-image: url(" https: mmbiz.qpic.cn mmbiz_png mrgvnruiwydfpgqx7myyyzbimhibrggljxzjk51k5r0aedpwtfeoyvichjplcca76mmvuud5wbkg30er9sajpgng 640?wx_fmt="png&from=appmsg");""><span style="display: none;"></span><span style="font-size: 18px;color: rgb(72, 179, 120);line-height: 2.4em;letter-spacing: 0em;margin-top: 38px;margin-bottom: 10px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: 38px;justify-content: unset;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: center;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">同类项目推荐</span></span><span style="display: none;"></span></h2> <ol style="list-style-type: decimal;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 25px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(74, 74, 74);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">LangChain</span></strong><span leaf="">:适合需要高度定制的开发者,提供灵活的工具链</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(74, 74, 74);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">LlamaIndex</span></strong><span leaf="">:专注数据连接器的轻量级解决方案</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(74, 74, 74);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">Haystack</span></strong><span leaf="">:工业级NLP管道框架,适合复杂业务场景</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(63, 63, 63);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(74, 74, 74);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">Milvus</span></strong><span leaf="">:专业向量数据库,适合超大规模向量检索</span> </section></li> </ol> <h2 data-cacheurl="" data-remoteid="" data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-left: 0px;padding-right: 0px;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-origin: padding-box;background-position-x: 50%;background-position-y: 50%;background-repeat: no-repeat;background-size: 63px;width: auto;height: auto;align-items: unset;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;justify-content: center;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;text-align: left;text-shadow: none;transform: none;-webkit-box-reflect: unset;background-image: url(" https: mmbiz.qpic.cn mmbiz_png mrgvnruiwydfpgqx7myyyzbimhibrggljxzjk51k5r0aedpwtfeoyvichjplcca76mmvuud5wbkg30er9sajpgng 640?wx_fmt="png&from=appmsg");""><span style="display: none;"></span><span style="font-size: 18px;color: rgb(72, 179, 120);line-height: 2.4em;letter-spacing: 0em;margin-top: 38px;margin-bottom: 10px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: 38px;justify-content: unset;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: center;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">界面效果</span></span><span style="display: none;"></span></h2> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img src="/upload/e8ef8e26adcef33c7ca70b283f5d9e00.png" class="rich_pages wxw-img" data-ratio="0.5509259259259259" data-type="png" data-w="1080" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;" data-imgfileid="100007158"></span> </figure> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img src="/upload/a2776b3d8a660cad1a22af5db5454c40.png" class="rich_pages wxw-img" data-ratio="0.5472222222222223" data-type="png" data-w="1080" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;" data-imgfileid="100007159"></span> </figure> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img src="/upload/697fc889afc83c92f86fda63ec81a8ee.png" class="rich_pages wxw-img" data-ratio="0.5453703703703704" data-type="png" data-w="1080" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;" data-imgfileid="100007160"></span> </figure> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img src="/upload/42ee2843d97612c2bf02d05d5e7ef6be.png" class="rich_pages wxw-img" data-ratio="0.5462962962962963" data-type="png" data-w="1080" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;" data-imgfileid="100007167"></span> </figure> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img src="/upload/ae1eb9b1e7caad61392c9f2fea608dda.png" class="rich_pages wxw-img" data-ratio="0.5444444444444444" data-type="png" data-w="1080" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;" data-imgfileid="100007166"></span> </figure> <h2 data-cacheurl="" data-remoteid="" data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-left: 0px;padding-right: 0px;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-origin: padding-box;background-position-x: 50%;background-position-y: 50%;background-repeat: no-repeat;background-size: 63px;width: auto;height: auto;align-items: unset;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;justify-content: center;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;text-align: left;text-shadow: none;transform: none;-webkit-box-reflect: unset;background-image: url(" https: mmbiz.qpic.cn mmbiz_png mrgvnruiwydfpgqx7myyyzbimhibrggljxzjk51k5r0aedpwtfeoyvichjplcca76mmvuud5wbkg30er9sajpgng 640?wx_fmt="png&from=appmsg");""><span style="display: none;"></span><span style="font-size: 18px;color: rgb(72, 179, 120);line-height: 2.4em;letter-spacing: 0em;margin-top: 38px;margin-bottom: 10px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: 38px;justify-content: unset;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: center;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">总结</span></span><span style="display: none;"></span></h2> <p data-tool="mdnice编辑器" style="color: rgb(63, 63, 63);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 16px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">"当大模型遇上深度文档解析,RAGFlow 用结构化思维重新定义知识管理——支持20+格式智能解析、混合检索增强、可视化干预,让企业级知识库搭建像搭积木一样简单!"</span></p> <h2 data-cacheurl="" data-remoteid="" data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;padding-left: 0px;padding-right: 0px;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-origin: padding-box;background-position-x: 50%;background-position-y: 50%;background-repeat: no-repeat;background-size: 63px;width: auto;height: auto;align-items: unset;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;justify-content: center;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;text-align: left;text-shadow: none;transform: none;-webkit-box-reflect: unset;background-image: url(" https: mmbiz.qpic.cn mmbiz_png mrgvnruiwydfpgqx7myyyzbimhibrggljxzjk51k5r0aedpwtfeoyvichjplcca76mmvuud5wbkg30er9sajpgng 640?wx_fmt="png&from=appmsg");""><span style="display: none;"></span><span style="font-size: 18px;color: rgb(72, 179, 120);line-height: 2.4em;letter-spacing: 0em;margin-top: 38px;margin-bottom: 10px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: transparent;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;box-shadow: none;display: inline-block;font-weight: bold;flex-direction: unset;float: unset;height: 38px;justify-content: unset;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: center;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">项目地址</span></span><span style="display: none;"></span></h2> <p data-tool="mdnice编辑器" style="color: rgb(63, 63, 63);font-size: 16px;line-height: 1.8em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 16px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">https://github.com/infiniflow/ragflow</span></p> </section>
作者:微信小助手
<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="margin-bottom: 0px;padding-left: 10px;padding-right: 10px;background-attachment: scroll;background-clip: border-box;background-image: linear-gradient(90deg, rgba(50, 0, 0, 0.05) 0%, rgba(0, 0, 0, 0) 6.76%), linear-gradient(360deg, rgba(50, 0, 0, 0.05) 0%, rgba(249, 247, 252, 0) 9.46%);background-origin: padding-box;background-position: 0% 0%;background-repeat: repeat, repeat;background-size: 20px 20px, 20px 20px;width: auto;font-family: Optima, " microsoft yahei, pingfangsc-regular, serif;font-size: 16px;color: rgb(0, 0, 0);line-height: 1.5em;word-spacing: 0em;letter-spacing: 0em;word-break: break-word;text-align: left; data-pm-slice="0 0 []"> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="padding-left: 3px;padding-right: 3px;background-attachment: scroll;background-clip: border-box;background-image: none;background-origin: padding-box;background-position: 0% 0%;background-repeat: no-repeat;background-size: auto;width: auto;font-family: PingFangSC-regular, sans-serif;line-height: 1.5em;word-spacing: 0em;letter-spacing: 0em;word-break: break-word;"> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><br></span> </figure> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 3px;padding-right: 3px;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;font-family: PingFangSC-regular, sans-serif;font-size: 16px;color: rgb(0, 0, 0);line-height: 1.5em;word-spacing: 0em;letter-spacing: 0em;word-break: break-word;overflow-wrap: break-word;text-align: left;" data-pm-slice="0 0 []"> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img class="rich_pages wxw-img" data-imgfileid="100006653" data-ratio="0.4398148148148148" src="/upload/4380045967d6dfff690d442eb8aa5c48.png" data-type="png" data-w="1080" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;"></span> </figure> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">在当今数字化时代,AI技术已经渗透到我们生活的方方面面,无论是内容创作、教育学习,还是市场营销,AI都发挥着巨大的作用。然而,对于许多AI使用者来说,如何高效地管理、优化和分享AI提示词,一直是一个令人头疼的问题。今天,我要给大家介绍一款专为AI提示词管理设计的工具——PromptPro。它不仅能帮助你高效管理提示词,还能让你的AI创作更加得心应手。</span></p> <h3 data-tool="mdnice编辑器" style="border-top-color: rgb(33, 33, 34);margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: solid;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 2px;border-left-width: 1px;border-right-width: 1px;border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(13, 13, 13);border-top-color: rgb(34, 34, 34);line-height: 1.8em;letter-spacing: 0em;padding-top: 4px;padding-bottom: 0px;padding-left: 6px;padding-right: 6px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: solid;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 2px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">PromptPro:AI创作的得力助手</span></span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">PromptPro是一款专为AI提示词管理设计的工具,它的使命是通过简化提示词管理流程,让AI创作更加高效、直观和易于使用。</span></strong><span leaf="">无论你是AI创作爱好者,还是专业的内容创作者,PromptPro都能帮助你将创意转化为高质量的AI输出。它提供了本地存储和云端备份功能,支持文件夹和标签系统进行分类管理,版本控制记录每次修改,确保你的提示词库井井有条且随时可用。</span></p> <h3 data-tool="mdnice编辑器" style="border-top-color: rgb(33, 33, 34);margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: solid;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 2px;border-left-width: 1px;border-right-width: 1px;border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(13, 13, 13);border-top-color: rgb(34, 34, 34);line-height: 1.8em;letter-spacing: 0em;padding-top: 4px;padding-bottom: 0px;padding-left: 6px;padding-right: 6px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: solid;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 2px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">系统架构:前后端分离的高效设计</span></span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">PromptPro采用前后端分离架构,这种架构设计不仅提高了系统的灵活性和可扩展性,还为用户带来了更流畅的使用体验。</span></p> <ul style="list-style-type: disc;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 20px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">前端</span></strong><span leaf="">:基于Vue 3 + TypeScript的单页应用,使用IndexedDB实现本地数据存储。这种设计不仅保证了数据的安全性,还让应用能够在离线状态下正常运行。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">后端</span></strong><span leaf="">:Node.js + Express构建的RESTful API服务,提供云备份和提示词共享功能。后端使用MySQL作为数据库,确保数据的持久化存储。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">第三方服务</span></strong><span leaf="">:集成OpenAI API实现提示词测试和优化,让你能够实时测试和优化你的提示词,确保它们能够产生最佳的AI输出。</span> </section></li> </ul> <h3 data-tool="mdnice编辑器" style="border-top-color: rgb(33, 33, 34);margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: solid;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 2px;border-left-width: 1px;border-right-width: 1px;border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(13, 13, 13);border-top-color: rgb(34, 34, 34);line-height: 1.8em;letter-spacing: 0em;padding-top: 4px;padding-bottom: 0px;padding-left: 6px;padding-right: 6px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: solid;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 2px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">数据流程:安全高效的管理机制</span></span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">PromptPro的数据管理流程非常严谨,无论是本地数据管理还是云备份,都经过精心设计,确保数据的安全性和一致性。</span></p> <ul style="list-style-type: disc;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 20px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <p style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">本地数据管理</span></strong><span leaf="">:数据通过Pinia状态管理,Vue3组件响应式更新,确保用户界面的实时性和准确性。创建、编辑提示词的操作都会经过严格的本地存储流程,确保数据的完整性和安全性。<img class="rich_pages wxw-img" data-imgfileid="100006651" data-ratio="0.7916666666666666" src="/upload/df5dc4af50b5c31bf5c68fad492e9b9a.png" data-type="png" data-w="1080" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;"></span></p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <p style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">云备份流程</span></strong><span leaf="">:数据通过HTTPS加密传输,使用预处理语句防止SQL注入,确保数据在传输和存储过程中的安全性。用户可以随时请求云备份,备份数据会存储在MySQL数据库中,并返回备份ID,方便用户随时恢复数据。<img src="/upload/c37a45966165fdd98d7f1aee01d69f21.png" class="rich_pages wxw-img" data-ratio="0.6583333333333333" data-type="png" data-w="1080" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;" data-imgfileid="100006652"></span></p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <p style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">提示词分享流程</span></strong><span leaf="">:生成唯一的32位分享码,用户可以通过复制分享链接或二维码,将提示词分享给他人。分享的提示词会存储在MySQL数据库中,并返回分享码,确保分享过程的安全性和便捷性。<img src="/upload/7bda5c590a51ea85452a49d72801ba27.png" class="rich_pages wxw-img" data-ratio="0.7138888888888889" data-type="png" data-w="1080" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;" data-imgfileid="100006650"></span></p> </section></li> </ul> <h3 data-tool="mdnice编辑器" style="border-top-color: rgb(33, 33, 34);margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: solid;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 2px;border-left-width: 1px;border-right-width: 1px;border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(13, 13, 13);border-top-color: rgb(34, 34, 34);line-height: 1.8em;letter-spacing: 0em;padding-top: 4px;padding-bottom: 0px;padding-left: 6px;padding-right: 6px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: solid;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 2px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">前端架构:现代化的技术栈</span></span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">PromptPro的前端采用了现代化的技术栈,确保了应用的高性能和良好的用户体验。</span></p> <ul style="list-style-type: disc;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 20px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">技术栈</span></strong><span leaf="">:</span> </section></li> <ul style="list-style-type: disc;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 20px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">框架:Vue 3 + TypeScript</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">UI库:Arco Design</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">状态管理:Pinia</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">本地存储:IndexedDB</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">路由:Vue Router</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">HTTP客户端:Axios</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">PWA支持:Vite PWA插件</span> </section></li> </ul> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">目录结构</span></strong><span leaf="">:清晰的目录结构让开发和维护变得更加容易。从静态资源到通用组件,从状态管理到页面组件,每个部分都井井有条。</span> </section></li> </ul> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg ijdpq631cvfpzevp7c96gfmjqygv5gmedjbvbunfkezfs4jpypiaufeo4ferun1nl7e13p1etekfxobsfngexn7folibrpfoian 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span leaf="">src/</span><span leaf=""><br></span><span leaf="">├── assets/ # 静态资源</span><span leaf=""><br></span><span leaf="">├── components/ # 通用组件</span><span leaf=""><br></span><span leaf="">├── composables/ # 可复用逻辑</span><span leaf=""><br></span><span leaf="">├── config/ # 配置文件</span><span leaf=""><br></span><span leaf="">├── db/ # IndexedDB管理</span><span leaf=""><br></span><span leaf="">├── router/ # 路由配置</span><span leaf=""><br></span><span leaf="">├── store/ # 状态管理</span><span leaf=""><br></span><span leaf="">├── utils/ # 工具函数</span><span leaf=""><br></span><span leaf="">├── views/ # 页面组件</span><span leaf=""><br></span><span leaf="">└── App.vue # 根组件</span><span leaf=""><br></span></code></pre> <h3 data-tool="mdnice编辑器" style="border-top-color: rgb(33, 33, 34);margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: solid;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 2px;border-left-width: 1px;border-right-width: 1px;border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(13, 13, 13);border-top-color: rgb(34, 34, 34);line-height: 1.8em;letter-spacing: 0em;padding-top: 4px;padding-bottom: 0px;padding-left: 6px;padding-right: 6px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: solid;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 2px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">后端架构:稳定可靠的云服务</span></span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">后端架构同样采用了成熟的技术栈,确保了云服务的稳定性和可靠性。</span></p> <ul style="list-style-type: disc;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 20px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">技术栈</span></strong><span leaf="">:</span> </section></li> <ul style="list-style-type: disc;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 20px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">运行环境:Node.js</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">Web框架:Express</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">数据库:MySQL</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">ORM:原生SQL (mysql2/promise)</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">身份验证:简单的邮箱+密钥认证</span> </section></li> </ul> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">目录结构</span></strong><span leaf="">:简洁明了的目录结构让后端开发更加高效。从入口文件到数据库连接,从路由定义到环境变量,每个部分都清晰可辨。</span> </section></li> </ul> <pre data-tool="mdnice编辑器" style="border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;text-align: left;margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;"><span data-cacheurl="" data-remoteid="" style="display: block;background: none;height: 30px;width: 100%;background-size: 40px;background-repeat: no-repeat;background-color: #282c34;margin-bottom: -7px;border-radius: 5px;background-position: 10px 10px;background-image: url(" https: mmbiz.qpic.cn mmbiz_svg ijdpq631cvfpzevp7c96gfmjqygv5gmedjbvbunfkezfs4jpypiaufeo4ferun1nl7e13p1etekfxobsfngexn7folibrpfoian 640?wx_fmt="svg&from=appmsg");""></span><code style="overflow-x: auto;padding: 16px;color: #abb2bf;padding-top: 15px;background: #282c34;border-radius: 5px;display: -webkit-box;font-family: Consolas, Monaco, Menlo, monospace;font-size: 12px;"><span leaf="">server/</span><span leaf=""><br></span><span leaf="">├── index.js # 入口文件</span><span leaf=""><br></span><span leaf="">├── db.js # 数据库连接</span><span leaf=""><br></span><span leaf="">├── routes/ # 路由定义</span><span leaf=""><br></span><span leaf="">│ ├── backups.js # 备份相关路由</span><span leaf=""><br></span><span leaf="">│ └── prompts.js # 提示词相关路由</span><span leaf=""><br></span><span leaf="">└── .env # 环境变量</span><span leaf=""><br></span></code></pre> <ul style="list-style-type: disc;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 20px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">API路由</span></strong><span leaf="">:提供了丰富的API接口,支持提示词的创建、获取、更新和删除操作,以及备份的管理功能。</span> </section></li> </ul> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img src="/upload/f09c052a6b05eca4c0825f9c25cf3b7a.png" class="rich_pages wxw-img" data-ratio="0.15" data-type="png" data-w="1080" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;" data-imgfileid="100006649"></span> </figure> <h3 data-tool="mdnice编辑器" style="border-top-color: rgb(33, 33, 34);margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: solid;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 2px;border-left-width: 1px;border-right-width: 1px;border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(13, 13, 13);border-top-color: rgb(34, 34, 34);line-height: 1.8em;letter-spacing: 0em;padding-top: 4px;padding-bottom: 0px;padding-left: 6px;padding-right: 6px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: solid;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 2px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">数据模型:清晰的结构设计</span></span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">PromptPro的数据模型设计非常清晰,无论是前端的IndexedDB还是后端的MySQL,都为数据的存储和管理提供了强大的支持。</span></p> <ul style="list-style-type: disc;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 20px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">前端数据模型</span></strong><span leaf="">:</span> </section></li> <ul style="list-style-type: disc;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 20px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">PROMPT:存储用户创建的所有提示词模板。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">FOLDER:提供分类管理提示词的结构。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">VERSION:记录提示词的修改历史。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">TAG:用于快速检索和分类提示词。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">SETTINGS:用户偏好设置,如界面主题、显示选项等。</span> </section></li> </ul> </ul> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img src="/upload/899df2585662d0c4c9acb63876b1f47d.jpg" class="rich_pages wxw-img" data-ratio="1.0157407407407408" data-type="jpeg" data-w="1080" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;" data-imgfileid="100006656"></span> </figure> <ul style="list-style-type: disc;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 20px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">后端数据模型</span></strong><span leaf="">:</span> </section></li> <ul style="list-style-type: disc;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 20px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">CLOUD_BACKUPS:存储用户的备份数据,通过email和access_key进行身份验证。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">SHARED_PROMPTS:存储用户分享的提示词,可通过share_code进行访问。</span> </section></li> </ul> </ul> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img src="/upload/2d6c942f7c8c7810fb8344b1bb61466f.jpg" class="rich_pages wxw-img" data-ratio="0.9583333333333334" data-type="jpeg" data-w="1080" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;" data-imgfileid="100006657"></span> </figure> <h3 data-tool="mdnice编辑器" style="border-top-color: rgb(33, 33, 34);margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: solid;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 2px;border-left-width: 1px;border-right-width: 1px;border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(13, 13, 13);border-top-color: rgb(34, 34, 34);line-height: 1.8em;letter-spacing: 0em;padding-top: 4px;padding-bottom: 0px;padding-left: 6px;padding-right: 6px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: solid;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 2px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">认证与安全:保护你的数据安全</span></span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">PromptPro非常注重数据的安全性,无论是云备份还是提示词分享,都采用了严格的安全措施。</span></p> <ul style="list-style-type: disc;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 20px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">云备份认证流程</span></strong><span leaf="">:通过邮箱和密钥进行身份验证,确保只有授权用户才能访问备份数据。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">数据加密</span></strong><span leaf="">:所有数据通过HTTPS加密传输,确保数据在传输过程中的安全性。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">SQL注入防护</span></strong><span leaf="">:使用预处理语句防止SQL注入,确保数据库的安全性。</span> </section></li> </ul> <h3 data-tool="mdnice编辑器" style="border-top-color: rgb(33, 33, 34);margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: solid;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 2px;border-left-width: 1px;border-right-width: 1px;border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(13, 13, 13);border-top-color: rgb(34, 34, 34);line-height: 1.8em;letter-spacing: 0em;padding-top: 4px;padding-bottom: 0px;padding-left: 6px;padding-right: 6px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: solid;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 2px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">部署架构:灵活的部署选项</span></span><span style="display: none;"></span></h3> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img src="/upload/4847e4f901cc0d60c0d51555f2ebcf92.png" class="rich_pages wxw-img" data-ratio="0.8314814814814815" data-type="png" data-w="1080" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;" data-imgfileid="100006658"></span> </figure> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">PromptPro提供了多种部署选项,无论是个人用户还是团队用户,都能找到适合自己的部署方案。</span></p> <ul style="list-style-type: disc;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 20px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">单服务器部署</span></strong><span leaf="">:适合个人或小型团队使用,前端和后端部署在同一服务器上,简单易用。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">前后端分离部署</span></strong><span leaf="">:适合生产环境,前端静态资源部署在CDN或静态文件服务器,后端API服务部署在独立服务器集群,数据库部署在专用数据库服务器或使用云数据库服务。</span> </section></li> </ul> <h3 data-tool="mdnice编辑器" style="border-top-color: rgb(33, 33, 34);margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: solid;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 2px;border-left-width: 1px;border-right-width: 1px;border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(13, 13, 13);border-top-color: rgb(34, 34, 34);line-height: 1.8em;letter-spacing: 0em;padding-top: 4px;padding-bottom: 0px;padding-left: 6px;padding-right: 6px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: solid;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 2px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">数据同步机制:无缝的数据管理</span></span><span style="display: none;"></span></h3> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <span leaf=""><img src="/upload/5cba9200f47cac3ff82716963d770c4c.png" class="rich_pages wxw-img" data-ratio="0.46296296296296297" data-type="png" data-w="1080" style="display: block;margin-top: 0px;margin-right: auto;margin-bottom: 0px;margin-left: auto;max-width: 100%;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;object-fit: fill;box-shadow: rgba(0, 0, 0, 0) 0px 0px 0px 0px;" data-imgfileid="100006655"></span> </figure> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">PromptPro提供了多种数据同步选项,确保用户能够在不同设备上无缝使用提示词库。</span></p> <ul style="list-style-type: disc;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 20px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">全量备份</span></strong><span leaf="">:备份所有本地数据,确保数据的完整性。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">增量备份</span></strong><span leaf="">:仅备份自上次备份以来的更改,提高备份效率。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">选择性恢复</span></strong><span leaf="">:用户可以选择恢复特定的数据,方便灵活。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">合并恢复</span></strong><span leaf="">:将本地数据与云端数据合并,确保数据的一致性。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">完全覆盖</span></strong><span leaf="">:用户可以选择完全覆盖本地数据,以恢复云端的最新状态。</span> </section></li> </ul> <h3 data-tool="mdnice编辑器" style="border-top-color: rgb(33, 33, 34);margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: solid;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 2px;border-left-width: 1px;border-right-width: 1px;border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(13, 13, 13);border-top-color: rgb(34, 34, 34);line-height: 1.8em;letter-spacing: 0em;padding-top: 4px;padding-bottom: 0px;padding-left: 6px;padding-right: 6px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: solid;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 2px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">PWA支持:类原生应用体验</span></span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">PromptPro支持PWA(Progressive Web Apps),通过Workbox实现了一系列强大的功能。</span></p> <ul style="list-style-type: disc;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 20px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">离线使用</span></strong><span leaf="">:缓存核心资源,确保无网络时也能使用。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">安装到设备</span></strong><span leaf="">:可直接添加到主屏幕,提供类似原生应用的体验。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">后台同步</span></strong><span leaf="">:当网络恢复时自动同步云备份。</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">推送通知</span></strong><span leaf="">:重要更新或备份完成时提醒用户。</span> </section></li> </ul> <h3 data-tool="mdnice编辑器" style="border-top-color: rgb(33, 33, 34);margin-top: 30px;margin-bottom: 15px;margin-left: 0px;margin-right: 0px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: solid;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 2px;border-left-width: 1px;border-right-width: 1px;border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: flex;flex-direction: unset;float: unset;height: auto;justify-content: unset;line-height: 1.5em;overflow-x: unset;overflow-y: unset;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;text-align: left;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(13, 13, 13);border-top-color: rgb(34, 34, 34);line-height: 1.8em;letter-spacing: 0em;padding-top: 4px;padding-bottom: 0px;padding-left: 6px;padding-right: 6px;align-items: unset;background-attachment: scroll;background-clip: border-box;background-color: unset;background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;border-top-style: solid;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 2px;border-bottom-width: 1px;border-left-width: 1px;border-right-width: 1px;border-bottom-color: rgb(0, 0, 0);border-left-color: rgb(0, 0, 0);border-right-color: rgb(0, 0, 0);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-left-radius: 0px;border-bottom-right-radius: 0px;box-shadow: none;display: block;font-weight: bold;flex-direction: unset;float: unset;height: auto;justify-content: unset;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;overflow-x: unset;overflow-y: unset;text-align: left;text-indent: 0em;text-shadow: none;transform: none;width: auto;-webkit-box-reflect: unset;"><span leaf="">总结:高效、灵活、安全的AI提示词管理工具</span></span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">PromptPro是一款高效、灵活且安全的AI提示词管理工具。它通过现代化的前后端分离架构、严谨的数据管理流程、强大的PWA支持和灵活的部署选项,为用户带来了前所未有的AI创作体验。PromptPro不仅能够帮助你高效管理提示词,还能让你的AI创作更加得心应手。</span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">无论是个人用户还是团队用户,PromptPro都能满足你的需求。它支持多端使用,让你能够在不同设备上同步和使用提示词库;它保障数据安全,通过简单高效的认证机制保护你的个人数据;它共建提示词生态,通过公开分享功能让用户之间交流优质提示词。</span></p> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><span leaf="">PromptPro,是你AI创作的得力助手,快来体验一下吧!</span></p> <hr style="margin-top: 10px;margin-bottom: 10px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: solid;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 1px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgb(0, 0, 0);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: 1px;"> <p data-tool="mdnice编辑器" style="color: rgb(0, 0, 0);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;text-indent: 0em;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 8px;padding-bottom: 8px;padding-left: 0px;padding-right: 0px;"><strong style="color: rgb(239, 112, 96);font-weight: bold;background-attachment: scroll;background-clip: border-box;background-color: rgba(0, 0, 0, 0);background-image: none;background-origin: padding-box;background-position-x: 0%;background-position-y: 0%;background-repeat: no-repeat;background-size: auto;width: auto;height: auto;margin-top: 0px;margin-bottom: 0px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 0px;padding-right: 0px;border-top-style: none;border-bottom-style: none;border-left-style: none;border-right-style: none;border-top-width: 3px;border-bottom-width: 3px;border-left-width: 3px;border-right-width: 3px;border-top-color: rgba(0, 0, 0, 0.4);border-bottom-color: rgba(0, 0, 0, 0.4);border-left-color: rgba(0, 0, 0, 0.4);border-right-color: rgba(0, 0, 0, 0.4);border-top-left-radius: 0px;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-bottom-left-radius: 0px;"><span leaf="">参考:</span></strong></p> <ul style="list-style-type: disc;margin-top: 8px;margin-bottom: 8px;margin-left: 0px;margin-right: 0px;padding-top: 0px;padding-bottom: 0px;padding-left: 20px;padding-right: 0px;color: rgb(0, 0, 0);" class="list-paddingleft-1"> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">https://prompt.orence.net/welcome</span> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;color: rgb(1, 1, 1);font-size: 15px;line-height: 2.1em;letter-spacing: 0.02em;text-align: left;font-weight: normal;"> <span leaf="">https://prompt.orence.net/app</span> </section></li> </ul> </section> </section>
作者:微信小助手
<p cid="n0" mdtype="paragraph" style="margin-top: 16px;margin-bottom: 24px;line-height: 2em;" data-pm-slice="0 0 []"><span md-inline="plain"><span leaf="" style="color: rgba(0, 0, 0, 0.9);font-size: 17px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;letter-spacing: 0.034em;font-style: normal;font-weight: normal;>兄弟们,有没有遇到过这种情况:凌晨三点在某东抢购显卡,刚提交订单就提示"系统繁忙",转头发现黄牛已经在海鲜市场挂出同款;扫码支付时突然弹出风险提示,非要验证人脸识别;更绝的是某银行APP,刚输完密码就收到短信提醒:"检测到您的账户存在异常操作"——但此时您根本没动过手机。</span></span></p> <p cid="n2" mdtype="paragraph" style="margin-top: 24px;margin-bottom: 24px;line-height: 2em;"><span md-inline="plain"><span leaf="" style="color: rgba(0, 0, 0, 0.9);font-size: 17px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;letter-spacing: 0.034em;font-style: normal;font-weight: normal;>这些让人又爱又恨的操作背后,都藏着一个叫"实时风控"的技术妖怪。今天咱们就来扒一扒,这个妖怪是如何用 Redis 和 AI 模型在 0.1 秒内完成逆天操作的。</span></span></p> <p cid="n2" mdtype="paragraph" style="margin-top: 24px;margin-bottom: 24px;line-height: 2em;"><span md-inline="plain"><span leaf="" style="color: rgba(0, 0, 0, 0.9);font-size: 17px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;letter-spacing: 0.034em;font-style: normal;font-weight: normal;><br></span></span></p> <section data-mpa-template="t" mpa-from-tpl="t" data-mpa-action-id="m8zww6721txr"> <section data-mpa-template="t" mpa-from-tpl="t"> <h4 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: 400;font-size: 16px;text-align: justify;outline: 0px;color: rgb(34, 34, 34);letter-spacing: 0.544px;caret-color: rgb(51, 51, 51);line-height: 2em;"><span style="font-size: 20px;"><strong mpa-from-tpl="t" style="outline: 0px;"><span mpa-is-content="t" style="font-size: 20px;outline: 0px;color: rgb(0, 122, 170);"><span leaf="">一、传统风控系统的"慢动作"人生</span></span></strong></span></h4> </section> </section> <p cid="n4" mdtype="paragraph" style="margin-top: 24px;margin-bottom: 24px;line-height: 2em;"><span md-inline="plain"><span leaf="" style="color: rgba(0, 0, 0, 0.9);font-size: 17px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, " helvetica neue, pingfang sc, hiragino sans gb, microsoft yahei ui, yahei, arial, sans-serif;letter-spacing: 0.034em;font-style: normal;font-weight: normal;>先带大家看看传统风控系统是怎么工作的。假设你要在电商平台买东西,风控流程大概是这样:</span></span></p> <ol style="box-sizing: border-box;margin: 0.8em 0px;padding-left: 30px;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial; class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n7" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">数据采集</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">:收集你的 IP 地址、设备指纹、行为轨迹等信息</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n9" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">特征提取</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">:把这些信息转换成"用户画像"特征</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n11" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">规则匹配</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">:用预先设定的风控规则进行判断(比如"同一 IP 10 分钟内下单 3 次触发警报")</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n13" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">人工审核</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">:如果规则命中,进入漫长的人工复核流程 </span></span></p></li> </ol> <p cid="n14" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 24px 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">但问题来了:</span></span></span></p> <ul style="box-sizing: border-box;margin: 0.8em 0px;padding-left: 30px;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial; class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n17" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">延迟高</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">:从数据采集到最终决策可能需要几分钟甚至几十分钟</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n19" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">规则僵化</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">:道高一尺魔高一丈,规则永远追不上黑产的创新速度</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n21" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">成本爆炸</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">:每增加一条规则都需要大量人力维护 </span></span></p></li> </ul> <p cid="n22" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 24px 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">举个栗子:某支付公司曾因为风控规则更新不及时,被羊毛党用"0.01元拼团"活动薅走 3000 万。等风控团队发现时,黑产已经换了三个作案手法。</span></span></span></p> <section mpa-from-tpl="t" data-mpa-action-id="m8zwxir7ofp" data-pm-slice="0 0 []"> <span leaf=""><br></span> </section> <section data-mpa-template="t" mpa-from-tpl="t" data-mpa-action-id="m8zwxir7jni"> <section data-mpa-template="t" mpa-from-tpl="t"> <h4 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: 400;font-size: 16px;text-align: justify;outline: 0px;color: rgb(34, 34, 34);letter-spacing: 0.544px;caret-color: rgb(51, 51, 51);line-height: 2em;"><span style="font-size: 20px;"><strong mpa-from-tpl="t" style="outline: 0px;"><span mpa-is-content="t" style="font-size: 20px;outline: 0px;color: rgb(0, 122, 170);"><span leaf="">二、Redis+AI 组合拳:给风控装上"超跑引擎"</span></span></strong></span></h4> </section> </section> <p cid="n25" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 24px 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">现在轮到我们的主角闪亮登场了:</span></span></span></p> <h3 cid="n26" mdtype="heading" style="box-sizing: border-box;break-after: avoid-page;break-inside: avoid;orphans: 2;font-size: 1.5em;margin-top: 24px;margin-bottom: 24px;font-weight: bold;line-height: 2em;cursor: text;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">(一)Redis:内存界的"闪电侠"</span></span></span></h3> <ul style="box-sizing: border-box;margin: 0.8em 0px;padding-left: 30px;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial; class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n29" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">速度快</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">:读写速度可达 10 万次/秒,延迟低至 0.1 毫秒</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n31" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">数据结构丰富</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">:支持哈希、列表、位图等 10 种数据结构</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n33" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">持久化机制</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">:RDB+AOF 双重保障,数据安全不丢失</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n35" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">分布式特性</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">:轻松支撑每秒百万级请求 </span></span></p></li> </ul> <p cid="n36" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 24px 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">想象一下,把用户行为数据比作快递包裹,Redis 就是 24 小时营业的智能快递柜,能瞬间完成包裹的存取和分拣。</span></span></span></p> <h3 cid="n37" mdtype="heading" style="box-sizing: border-box;break-after: avoid-page;break-inside: avoid;orphans: 2;font-size: 1.5em;margin-top: 24px;margin-bottom: 24px;font-weight: bold;line-height: 2em;cursor: text;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">(二)AI 模型:风控界的"福尔摩斯"</span></span></span></h3> <ul style="box-sizing: border-box;margin: 0.8em 0px;padding-left: 30px;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial; class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n40" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">机器学习</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">:通过历史数据训练模型,自动识别异常行为模式</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n42" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">深度学习</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">:处理高维复杂数据(比如设备指纹、行为轨迹)</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n44" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">实时更新</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">:模型可在线增量学习,动态调整风控策略 </span></span></p></li> </ul> <p cid="n45" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 24px 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">传统规则是"看见红灯就停车",而 AI 模型是"分析路况、车流量、行人状态后智能决策"。</span></span></span></p> <h3 cid="n46" mdtype="heading" style="box-sizing: border-box;break-after: avoid-page;break-inside: avoid;orphans: 2;font-size: 1.5em;margin-top: 24px;margin-bottom: 24px;font-weight: bold;line-height: 2em;cursor: text;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">(三)组合后的化学反应</span></span></span></h3> <p cid="n47" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 24px 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">当 Redis 遇到 AI,就像给赛车装上了核动力引擎:</span></span></span></p> <ol style="box-sizing: border-box;margin: 0.8em 0px;padding-left: 30px;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial; class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n50" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">实时数据采集</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">:用户行为数据毫秒级写入 Redis</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n52" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">特征实时计算</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">:利用 Redis 的计算能力预处理数据</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n54" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">模型在线推理</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">:AI 模型在 Redis 集群中并行运算</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n56" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">决策实时反馈</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">:结果直接返回业务系统 </span></span></p></li> </ol> <p cid="n57" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 24px 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">某头部支付公司实测:通过这种组合,风控决策时间从 800ms 降至 70ms,误报率下降 65%。</span></span></span></p> <section mpa-from-tpl="t" data-mpa-action-id="m8zwylxi1tor" data-pm-slice="0 0 []"> <span leaf=""><br></span> </section> <section data-mpa-template="t" mpa-from-tpl="t" data-mpa-action-id="m8zwylxi2109"> <section data-mpa-template="t" mpa-from-tpl="t"> <h4 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: 400;font-size: 16px;text-align: justify;outline: 0px;color: rgb(34, 34, 34);letter-spacing: 0.544px;caret-color: rgb(51, 51, 51);line-height: 2em;"><span style="font-size: 20px;"><strong mpa-from-tpl="t" style="outline: 0px;"><span mpa-is-content="t" style="font-size: 20px;outline: 0px;color: rgb(0, 122, 170);"><span leaf="">三、实战指南:如何用 Redis+AI 实现实时风控</span></span></strong></span></h4> </section> </section> <p cid="n59" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 24px 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">接下来进入硬核环节,咱们一步步拆解实现过程。为了方便理解,这里用电商场景举例。</span></span></span></p> <h3 cid="n60" mdtype="heading" style="box-sizing: border-box;break-after: avoid-page;break-inside: avoid;orphans: 2;font-size: 1.5em;margin-top: 24px;margin-bottom: 24px;font-weight: bold;line-height: 2em;cursor: text;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">(一)系统架构设计</span></span></span></h3> <pre spellcheck="false" lang="plain" cid="n61" mdtype="fences" style="box-sizing: border-box;overflow: visible;font-family: var(--monospace);font-size: 0.9em;display: block;break-inside: avoid;text-align: left;white-space: normal;background-image: inherit;background-position: inherit;background-size: inherit;background-repeat: inherit;background-attachment: inherit;background-origin: inherit;background-clip: inherit;background-color: rgb(248, 248, 248);border: 1px solid rgb(231, 234, 237);border-radius: 3px;padding: 8px 4px 6px;margin-bottom: 15px;margin-top: 15px;width: inherit;color: rgb(51, 51, 51);font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;"><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf="">用户行为 → 实时采集 → Redis 集群 → 特征工程 → AI 模型 → 决策引擎 → 业务系统</span></span></pre> <p cid="n62" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 24px 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">关键点:</span></span></span></p> <ul style="box-sizing: border-box;margin: 0.8em 0px;padding-left: 30px;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial; class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n65" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">数据管道</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">:使用 Redis Streams 构建实时数据流</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n67" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">特征存储</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">:用 Redis Hash 存储用户画像特征</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n69" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">模型部署</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">:通过 Redis AI 模块加载 TensorFlow/PyTorch 模型</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n71" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">决策缓存</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">:用 Redis Sorted Set 缓存高频决策结果</span></span></p></li> </ul> <h3 cid="n72" mdtype="heading" style="box-sizing: border-box;break-after: avoid-page;break-inside: avoid;orphans: 2;font-size: 1.5em;margin-top: 24px;margin-bottom: 24px;font-weight: bold;line-height: 2em;cursor: text;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">(二)数据采集与预处理</span></span></span></h3> <ol style="box-sizing: border-box;margin: 0.8em 0px;padding-left: 30px;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial; class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n75" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">埋点设计</span></span></strong></span></p></li> </ol> <pre spellcheck="false" lang="java" cid="n76" mdtype="fences" style="box-sizing: border-box;overflow: visible;font-family: var(--monospace);font-size: 0.9em;display: block;break-inside: avoid;text-align: left;white-space: normal;background-image: inherit;background-position: inherit;background-size: inherit;background-repeat: inherit;background-attachment: inherit;background-origin: inherit;background-clip: inherit;background-color: rgb(248, 248, 248);border: 1px solid rgb(231, 234, 237);border-radius: 3px;padding: 8px 4px 6px;margin-bottom: 15px;margin-top: 15px;width: inherit;color: rgb(51, 51, 51);font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;"><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(170, 85, 0);"><span leaf="">// 伪代码:用户下单行为埋点</span></span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 136, 85);"><span leaf="">void</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 255);"><span leaf="">onOrderSubmit</span></span><span leaf="">(</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">User</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">user</span></span><span leaf="">, </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">Order</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">order</span></span><span leaf="">) {</span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(170, 85, 0);"><span leaf="">// 采集基础信息</span></span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 136, 85);"><span leaf="">String</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">deviceId</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(152, 26, 26);"><span leaf="">=</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">user</span></span><span leaf="">.</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">getDeviceId</span></span><span leaf="">();</span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 136, 85);"><span leaf="">String</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">ip</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(152, 26, 26);"><span leaf="">=</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">user</span></span><span leaf="">.</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">getIp</span></span><span leaf="">();</span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 136, 85);"><span leaf="">long</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">timestamp</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(152, 26, 26);"><span leaf="">=</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">System</span></span><span leaf="">.</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">currentTimeMillis</span></span><span leaf="">();</span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span cm-text="" style="box-sizing: border-box;"></span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span cm-text="" style="box-sizing: border-box;"></span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(170, 85, 0);"><span leaf="">// 写入 Redis Stream</span></span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">redis</span></span><span leaf="">.</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">xadd</span></span><span leaf="">(</span><span style="box-sizing: border-box;color: rgb(170, 17, 17);"><span leaf="">"user_events:"</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(152, 26, 26);"><span leaf="">+</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">deviceId</span></span><span leaf="">, </span><span style="box-sizing: border-box;color: rgb(170, 17, 17);"><span leaf="">"*"</span></span><span leaf="">, </span><span style="box-sizing: border-box;color: rgb(170, 17, 17);"><span leaf="">"type"</span></span><span leaf="">, </span><span style="box-sizing: border-box;color: rgb(170, 17, 17);"><span leaf="">"order"</span></span><span leaf="">, </span><span style="box-sizing: border-box;color: rgb(170, 17, 17);"><span leaf="">"amount"</span></span><span leaf="">, </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">order</span></span><span leaf="">.</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">getAmount</span></span><span leaf="">());</span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> }</span></span></pre> <ol style="box-sizing: border-box;margin: 0.8em 0px;padding-left: 30px;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial; class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n79" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">实时特征计算</span></span></strong></span></p></li> </ol> <pre spellcheck="false" lang="python" cid="n80" mdtype="fences" style="box-sizing: border-box;overflow: visible;font-family: var(--monospace);font-size: 0.9em;display: block;break-inside: avoid;text-align: left;white-space: normal;background-image: inherit;background-position: inherit;background-size: inherit;background-repeat: inherit;background-attachment: inherit;background-origin: inherit;background-clip: inherit;background-color: rgb(248, 248, 248);border: 1px solid rgb(231, 234, 237);border-radius: 3px;padding: 8px 4px 6px;margin-bottom: 15px;margin-top: 15px;width: inherit;color: rgb(51, 51, 51);font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;"><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(170, 85, 0);"><span leaf=""># 示例:计算最近 5 分钟订单量</span></span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(119, 0, 136);"><span leaf="">def</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 255);"><span leaf="">calculate_recent_orders</span></span><span leaf="">(</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">device_id</span></span><span leaf="">):</span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(170, 85, 0);"><span leaf=""># 获取最近 5 分钟的事件</span></span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">events</span></span><span leaf=""> = </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">redis</span></span><span leaf="">.</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">xrange</span></span><span leaf="">(</span><span style="box-sizing: border-box;color: rgb(170, 17, 17);"><span leaf="">"user_events:"</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(152, 26, 26);"><span leaf="">+</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">device_id</span></span><span leaf="">, </span><span style="box-sizing: border-box;color: rgb(170, 17, 17);"><span leaf="">"-"</span></span><span leaf="">, </span><span style="box-sizing: border-box;color: rgb(170, 17, 17);"><span leaf="">"+"</span></span><span leaf="">)</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(170, 85, 0);"><span leaf=""># 过滤出订单事件</span></span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">orders</span></span><span leaf=""> = [</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">e</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(119, 0, 136);"><span leaf="">for</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">e</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(119, 0, 136);"><span leaf="">in</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">events</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(119, 0, 136);"><span leaf="">if</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">e</span></span><span leaf="">[</span><span style="box-sizing: border-box;color: rgb(170, 17, 17);"><span leaf="">'type'</span></span><span leaf="">] == </span><span style="box-sizing: border-box;color: rgb(170, 17, 17);"><span leaf="">'order'</span></span><span leaf="">]</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(170, 85, 0);"><span leaf=""># 按时间倒序排序</span></span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">orders</span></span><span leaf="">.</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">sort</span></span><span leaf="">(</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">key</span></span><span leaf="">=</span><span style="box-sizing: border-box;color: rgb(119, 0, 136);"><span leaf="">lambda</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">x</span></span><span leaf="">: </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">x</span></span><span leaf="">[</span><span style="box-sizing: border-box;color: rgb(170, 17, 17);"><span leaf="">'timestamp'</span></span><span leaf="">], </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">reverse</span></span><span leaf="">=</span><span style="box-sizing: border-box;color: rgb(119, 0, 136);"><span leaf="">True</span></span><span leaf="">)</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(170, 85, 0);"><span leaf=""># 取最近 5 分钟的订单</span></span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">recent_orders</span></span><span leaf=""> = [</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">o</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(119, 0, 136);"><span leaf="">for</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">o</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(119, 0, 136);"><span leaf="">in</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">orders</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(119, 0, 136);"><span leaf="">if</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">o</span></span><span leaf="">[</span><span style="box-sizing: border-box;color: rgb(170, 17, 17);"><span leaf="">'timestamp'</span></span><span leaf="">] </span><span style="box-sizing: border-box;color: rgb(152, 26, 26);"><span leaf="">></span></span><span leaf=""> (</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">now</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(152, 26, 26);"><span leaf="">-</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(17, 102, 68);"><span leaf="">300000</span></span><span leaf="">)]</span></span><span leaf=""><br></span><span leaf=""><br></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(119, 0, 136);"><span leaf="">return</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(51, 0, 170);"><span leaf="">len</span></span><span leaf="">(</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">recent_orders</span></span><span leaf="">)</span></span></pre> <h3 cid="n81" mdtype="heading" style="box-sizing: border-box;break-after: avoid-page;break-inside: avoid;orphans: 2;font-size: 1.5em;margin-top: 24px;margin-bottom: 24px;font-weight: bold;line-height: 2em;cursor: text;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">(三)AI 模型构建与部署</span></span></span></h3> <ol style="box-sizing: border-box;margin: 0.8em 0px;padding-left: 30px;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial; class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n84" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">模型选择</span></span></strong></span></p></li> <ol style="box-sizing: border-box;margin: 0px;padding-left: 30px;" class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n87" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">二分类问题:逻辑回归、XGBoost、LightGBM</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n89" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">序列数据:LSTM、Transformer</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n91" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">高维稀疏数据:DeepFM、Wide & Deep</span></span></p></li> </ol> <li style="box-sizing: border-box;margin: 0px;"><p cid="n93" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">模型训练(示例)</span></span></strong></span></p></li> </ol> <pre spellcheck="false" lang="python" cid="n94" mdtype="fences" style="box-sizing: border-box;overflow: visible;font-family: var(--monospace);font-size: 0.9em;display: block;break-inside: avoid;text-align: left;white-space: normal;background-image: inherit;background-position: inherit;background-size: inherit;background-repeat: inherit;background-attachment: inherit;background-origin: inherit;background-clip: inherit;background-color: rgb(248, 248, 248);border: 1px solid rgb(231, 234, 237);border-radius: 3px;padding: 8px 4px 6px;margin-bottom: 15px;margin-top: 15px;width: inherit;color: rgb(51, 51, 51);font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;"><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(119, 0, 136);"><span leaf="">import</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">xgboost</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(119, 0, 136);"><span leaf="">as</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">xgb</span></span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(119, 0, 136);"><span leaf="">from</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">sklearn</span></span><span leaf="">.</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">model_selection</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(119, 0, 136);"><span leaf="">import</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">train_test_split</span></span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(170, 85, 0);"><span leaf=""># 加载历史数据</span></span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">data</span></span><span leaf=""> = </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">pd</span></span><span leaf="">.</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">read_csv</span></span><span leaf="">(</span><span style="box-sizing: border-box;color: rgb(170, 17, 17);"><span leaf="">'risk_data.csv'</span></span><span leaf="">)</span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">X</span></span><span leaf=""> = </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">data</span></span><span leaf="">.</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">drop</span></span><span leaf="">(</span><span style="box-sizing: border-box;color: rgb(170, 17, 17);"><span leaf="">'label'</span></span><span leaf="">, </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">axis</span></span><span leaf="">=</span><span style="box-sizing: border-box;color: rgb(17, 102, 68);"><span leaf="">1</span></span><span leaf="">)</span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">y</span></span><span leaf=""> = </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">data</span></span><span leaf="">[</span><span style="box-sizing: border-box;color: rgb(170, 17, 17);"><span leaf="">'label'</span></span><span leaf="">]</span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(170, 85, 0);"><span leaf=""># 划分训练集和测试集</span></span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">X_train</span></span><span leaf="">, </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">X_test</span></span><span leaf="">, </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">y_train</span></span><span leaf="">, </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">y_test</span></span><span leaf=""> = </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">train_test_split</span></span><span leaf="">(</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">X</span></span><span leaf="">, </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">y</span></span><span leaf="">, </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">test_size</span></span><span leaf="">=</span><span style="box-sizing: border-box;color: rgb(17, 102, 68);"><span leaf="">0.2</span></span><span leaf="">)</span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(170, 85, 0);"><span leaf=""># 训练 XGBoost 模型</span></span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">model</span></span><span leaf=""> = </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">xgb</span></span><span leaf="">.</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">XGBClassifier</span></span><span leaf="">(</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">objective</span></span><span leaf="">=</span><span style="box-sizing: border-box;color: rgb(170, 17, 17);"><span leaf="">'binary:logistic'</span></span><span leaf="">, </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">learning_rate</span></span><span leaf="">=</span><span style="box-sizing: border-box;color: rgb(17, 102, 68);"><span leaf="">0.1</span></span><span leaf="">, </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">max_depth</span></span><span leaf="">=</span><span style="box-sizing: border-box;color: rgb(17, 102, 68);"><span leaf="">3</span></span><span leaf="">)</span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">model</span></span><span leaf="">.</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">fit</span></span><span leaf="">(</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">X_train</span></span><span leaf="">, </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">y_train</span></span><span leaf="">)</span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(170, 85, 0);"><span leaf=""># 模型评估</span></span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">accuracy</span></span><span leaf=""> = </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">model</span></span><span leaf="">.</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">score</span></span><span leaf="">(</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">X_test</span></span><span leaf="">, </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">y_test</span></span><span leaf="">)</span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(51, 0, 170);"><span leaf="">print</span></span><span leaf="">(</span><span style="box-sizing: border-box;color: rgb(170, 17, 17);"><span leaf="">f"Model accuracy: {accuracy}"</span></span><span leaf="">)</span></span></pre> <ol style="box-sizing: border-box;margin: 0.8em 0px;padding-left: 30px;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial; class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n97" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">模型部署到 Redis AI</span></span></strong></span></p></li> </ol> <pre spellcheck="false" lang="python" cid="n98" mdtype="fences" style="box-sizing: border-box;overflow: visible;font-family: var(--monospace);font-size: 0.9em;display: block;break-inside: avoid;text-align: left;white-space: normal;background-image: inherit;background-position: inherit;background-size: inherit;background-repeat: inherit;background-attachment: inherit;background-origin: inherit;background-clip: inherit;background-color: rgb(248, 248, 248);border: 1px solid rgb(231, 234, 237);border-radius: 3px;padding: 8px 4px 6px;margin-bottom: 15px;margin-top: 15px;width: inherit;color: rgb(51, 51, 51);font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;"><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(170, 85, 0);"><span leaf=""># 保存模型到 Redis</span></span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(119, 0, 136);"><span leaf="">import</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">redisai</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(119, 0, 136);"><span leaf="">as</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">rai</span></span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">r</span></span><span leaf=""> = </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">rai</span></span><span leaf="">.</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">Client</span></span><span leaf="">()</span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">r</span></span><span leaf="">.</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">modelset</span></span><span leaf="">(</span><span style="box-sizing: border-box;color: rgb(170, 17, 17);"><span leaf="">"risk_model"</span></span><span leaf="">, </span><span style="box-sizing: border-box;color: rgb(170, 17, 17);"><span leaf="">"TF"</span></span><span leaf="">, </span><span style="box-sizing: border-box;color: rgb(170, 17, 17);"><span leaf="">"CPU"</span></span><span leaf="">, </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">model_bytes</span></span><span leaf="">)</span></span></pre> <h3 cid="n99" mdtype="heading" style="box-sizing: border-box;break-after: avoid-page;break-inside: avoid;orphans: 2;font-size: 1.5em;margin-top: 24px;margin-bottom: 24px;font-weight: bold;line-height: 2em;cursor: text;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">(四)实时决策流程</span></span></span></h3> <ol style="box-sizing: border-box;margin: 0.8em 0px;padding-left: 30px;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial; class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n102" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">特征提取</span></span></strong></span></p></li> </ol> <pre spellcheck="false" lang="java" cid="n103" mdtype="fences" style="box-sizing: border-box;overflow: visible;font-family: var(--monospace);font-size: 0.9em;display: block;break-inside: avoid;text-align: left;white-space: normal;background-image: inherit;background-position: inherit;background-size: inherit;background-repeat: inherit;background-attachment: inherit;background-origin: inherit;background-clip: inherit;background-color: rgb(248, 248, 248);border: 1px solid rgb(231, 234, 237);border-radius: 3px;padding: 8px 4px 6px;margin-bottom: 15px;margin-top: 15px;width: inherit;color: rgb(51, 51, 51);font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;"><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(170, 85, 0);"><span leaf="">// 从 Redis 获取用户特征</span></span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">Map</span></span><span style="box-sizing: border-box;color: rgb(152, 26, 26);"><span leaf=""><</span></span><span style="box-sizing: border-box;color: rgb(0, 136, 85);"><span leaf="">String</span></span><span leaf="">, </span><span style="box-sizing: border-box;color: rgb(0, 136, 85);"><span leaf="">String</span></span><span style="box-sizing: border-box;color: rgb(152, 26, 26);"><span leaf="">></span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">features</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(152, 26, 26);"><span leaf="">=</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">redis</span></span><span leaf="">.</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">hgetall</span></span><span leaf="">(</span><span style="box-sizing: border-box;color: rgb(170, 17, 17);"><span leaf="">"user_features:"</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(152, 26, 26);"><span leaf="">+</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">userId</span></span><span leaf="">);</span></span></pre> <ol style="box-sizing: border-box;margin: 0.8em 0px;padding-left: 30px;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial; class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n106" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">模型推理</span></span></strong></span></p></li> </ol> <pre spellcheck="false" lang="python" cid="n107" mdtype="fences" style="box-sizing: border-box;overflow: visible;font-family: var(--monospace);font-size: 0.9em;display: block;break-inside: avoid;text-align: left;white-space: normal;background-image: inherit;background-position: inherit;background-size: inherit;background-repeat: inherit;background-attachment: inherit;background-origin: inherit;background-clip: inherit;background-color: rgb(248, 248, 248);border: 1px solid rgb(231, 234, 237);border-radius: 3px;padding: 8px 4px 6px;margin-bottom: 15px;margin-top: 15px;width: inherit;color: rgb(51, 51, 51);font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;"><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(170, 85, 0);"><span leaf=""># 加载模型并进行预测</span></span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(119, 0, 136);"><span leaf="">import</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">numpy</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(119, 0, 136);"><span leaf="">as</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">np</span></span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">input_data</span></span><span leaf=""> = </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">np</span></span><span leaf="">.</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">array</span></span><span leaf="">([[</span><span style="box-sizing: border-box;color: rgb(51, 0, 170);"><span leaf="">float</span></span><span leaf="">(</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">features</span></span><span leaf="">[</span><span style="box-sizing: border-box;color: rgb(170, 17, 17);"><span leaf="">'order_count'</span></span><span leaf="">]), </span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(51, 0, 170);"><span leaf="">float</span></span><span leaf="">(</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">features</span></span><span leaf="">[</span><span style="box-sizing: border-box;color: rgb(170, 17, 17);"><span leaf="">'ip_blacklist_score'</span></span><span leaf="">])]])</span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">result</span></span><span leaf=""> = </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">r</span></span><span leaf="">.</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">modelrun</span></span><span leaf="">(</span><span style="box-sizing: border-box;color: rgb(170, 17, 17);"><span leaf="">"risk_model"</span></span><span leaf="">, </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">inputs</span></span><span leaf="">=[</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">input_data</span></span><span leaf="">])</span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">probability</span></span><span leaf=""> = </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">result</span></span><span leaf="">[</span><span style="box-sizing: border-box;color: rgb(17, 102, 68);"><span leaf="">0</span></span><span leaf="">][</span><span style="box-sizing: border-box;color: rgb(17, 102, 68);"><span leaf="">0</span></span><span leaf="">]</span></span></pre> <ol style="box-sizing: border-box;margin: 0.8em 0px;padding-left: 30px;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial; class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n110" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">决策逻辑</span></span></strong></span></p></li> </ol> <pre spellcheck="false" lang="java" cid="n111" mdtype="fences" style="box-sizing: border-box;overflow: visible;font-family: var(--monospace);font-size: 0.9em;display: block;break-inside: avoid;text-align: left;white-space: normal;background-image: inherit;background-position: inherit;background-size: inherit;background-repeat: inherit;background-attachment: inherit;background-origin: inherit;background-clip: inherit;background-color: rgb(248, 248, 248);border: 1px solid rgb(231, 234, 237);border-radius: 3px;padding: 8px 4px 6px;margin-bottom: 15px;margin-top: 15px;width: inherit;color: rgb(51, 51, 51);font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;"><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(170, 85, 0);"><span leaf="">// 根据模型输出决定是否拦截</span></span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(119, 0, 136);"><span leaf="">if</span></span><span leaf=""> (</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">probability</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(152, 26, 26);"><span leaf="">></span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(17, 102, 68);"><span leaf="">0.9</span></span><span leaf="">) {</span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(170, 85, 0);"><span leaf="">// 高风险:拦截交易</span></span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(119, 0, 136);"><span leaf="">return</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(119, 0, 136);"><span leaf="">new</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">RiskResult</span></span><span leaf="">(</span><span style="box-sizing: border-box;color: rgb(34, 17, 153);"><span leaf="">true</span></span><span leaf="">, </span><span style="box-sizing: border-box;color: rgb(170, 17, 17);"><span leaf="">"高风险交易"</span></span><span leaf="">);</span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> } </span><span style="box-sizing: border-box;color: rgb(119, 0, 136);"><span leaf="">else</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(119, 0, 136);"><span leaf="">if</span></span><span leaf=""> (</span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">probability</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(152, 26, 26);"><span leaf="">></span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(17, 102, 68);"><span leaf="">0.7</span></span><span leaf="">) {</span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(170, 85, 0);"><span leaf="">// 中风险:二次验证</span></span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(119, 0, 136);"><span leaf="">return</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(119, 0, 136);"><span leaf="">new</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">RiskResult</span></span><span leaf="">(</span><span style="box-sizing: border-box;color: rgb(34, 17, 153);"><span leaf="">true</span></span><span leaf="">, </span><span style="box-sizing: border-box;color: rgb(170, 17, 17);"><span leaf="">"需要短信验证"</span></span><span leaf="">);</span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> } </span><span style="box-sizing: border-box;color: rgb(119, 0, 136);"><span leaf="">else</span></span><span leaf=""> {</span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(170, 85, 0);"><span leaf="">// 低风险:正常放行</span></span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(119, 0, 136);"><span leaf="">return</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(119, 0, 136);"><span leaf="">new</span></span><span leaf=""> </span><span style="box-sizing: border-box;color: rgb(0, 0, 0);"><span leaf="">RiskResult</span></span><span leaf="">(</span><span style="box-sizing: border-box;color: rgb(34, 17, 153);"><span leaf="">false</span></span><span leaf="">, </span><span style="box-sizing: border-box;color: rgb(170, 17, 17);"><span leaf="">"交易正常"</span></span><span leaf="">);</span></span><span leaf=""><br></span><span role="presentation" style="box-sizing: border-box;padding-right: 0.1px;"><span leaf=""> }</span></span></pre> <section mpa-from-tpl="t" data-mpa-action-id="m8zx0dwz1y87" data-pm-slice="0 0 []"> <span leaf=""><br></span> </section> <section data-mpa-template="t" mpa-from-tpl="t" data-mpa-action-id="m8zx0dwz3zx"> <section data-mpa-template="t" mpa-from-tpl="t"> <h4 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: 400;font-size: 16px;text-align: justify;outline: 0px;color: rgb(34, 34, 34);letter-spacing: 0.544px;caret-color: rgb(51, 51, 51);line-height: 2em;"><span style="font-size: 20px;"><strong mpa-from-tpl="t" style="outline: 0px;"><span mpa-is-content="t" style="font-size: 20px;outline: 0px;color: rgb(0, 122, 170);"><span leaf="">四、高级技巧:让系统飞起来的"黑科技"</span></span></strong></span></h4> </section> </section> <h3 cid="n113" mdtype="heading" style="box-sizing: border-box;break-after: avoid-page;break-inside: avoid;orphans: 2;font-size: 1.5em;margin-top: 24px;margin-bottom: 24px;font-weight: bold;line-height: 2em;cursor: text;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">(一)特征工程优化</span></span></span></h3> <ol style="box-sizing: border-box;margin: 0.8em 0px;padding-left: 30px;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial; class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n116" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">滑动窗口统计</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""> 使用 Redis HyperLogLog 统计独立用户数,SORTED SET 实现滑动窗口。</span></span></p></li> </ol> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t" data-mpa-action-id="m8zx692u1nu8"> <pre style="margin: 0px;padding: 0px;background: none;font-family: none;"><code style="border-radius: 4px;font-size: 0.85em;font-family: none;margin: 0px 0.15em;background: rgb(248, 248, 248);color: rgb(51, 51, 51);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span style="color: rgb(153, 153, 136);background: rgba(0, 0, 0, 0);display: inline;width: 186px;text-decoration: none solid rgb(153, 153, 136);font-weight: 400;font-style: italic;font-family: none;"><span leaf=""># 计算过去 1 小时的独立设备数</span></span><span leaf=""><br></span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 164px;text-decoration: none solid rgb(51, 51, 51);font-weight: 400;font-style: normal;font-family: none;"><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">def</span></span><span leaf=""> </span><span style="color: rgb(153, 0, 0);background: rgba(0, 0, 0, 0);display: inline;width: 118px;text-decoration: none solid rgb(153, 0, 0);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">get_unique_devices</span></span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration: none solid rgb(51, 51, 51);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">()</span></span><span leaf="">:</span></span><span leaf=""><br></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">return</span></span><span leaf=""> redis.pfcount(</span><span style="color: rgb(221, 17, 68);background: rgba(0, 0, 0, 0);display: inline;width: 65px;text-decoration: none solid rgb(221, 17, 68);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">"devices:"</span></span><span leaf=""> + now.hour)</span></code></pre> </section> <ol style="box-sizing: border-box;margin: 0.8em 0px;padding-left: 30px;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial; class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n120" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">实时特征交叉</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""> 结合用户行为、设备信息、环境特征等多维度数据。</span></span></p></li> </ol> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t" data-mpa-action-id="m8zx791ws32"> <pre style="margin: 0px;padding: 0px;background: none;font-family: none;"><code style="border-radius: 4px;font-size: 0.85em;font-family: none;margin: 0px 0.15em;background: rgb(248, 248, 248);color: rgb(51, 51, 51);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span style="color: rgb(153, 153, 136);background: rgba(0, 0, 0, 0);display: inline;width: 154px;text-decoration: none solid rgb(153, 153, 136);font-weight: 400;font-style: italic;font-family: none;"><span leaf=""># 设备指纹与 IP 关联分析</span></span><span leaf=""><br></span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 268px;text-decoration: none solid rgb(51, 51, 51);font-weight: 400;font-style: normal;font-family: none;"><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">def</span></span><span leaf=""> </span><span style="color: rgb(153, 0, 0);background: rgba(0, 0, 0, 0);display: inline;width: 137px;text-decoration: none solid rgb(153, 0, 0);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">device_ip_correlation</span></span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 98px;text-decoration: none solid rgb(51, 51, 51);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">(device_id, ip)</span></span><span leaf="">:</span></span><span leaf=""><br></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">return</span></span><span leaf=""> redis.hget(</span><span style="color: rgb(221, 17, 68);background: rgba(0, 0, 0, 0);display: inline;width: 98px;text-decoration: none solid rgb(221, 17, 68);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">"ip_device_map"</span></span><span leaf="">, ip) == device_id</span></code></pre> </section> <h3 cid="n122" mdtype="heading" style="box-sizing: border-box;break-after: avoid-page;break-inside: avoid;orphans: 2;font-size: 1.5em;margin-top: 24px;margin-bottom: 24px;font-weight: bold;line-height: 2em;cursor: text;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">(二)模型优化策略</span></span></span></h3> <ol style="box-sizing: border-box;margin: 0.8em 0px;padding-left: 30px;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial; class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n125" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">模型量化</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""> 使用 TensorFlow Lite 或 ONNX Runtime 对模型进行轻量化。</span></span></p></li> </ol> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t" data-mpa-action-id="m8zx4k4q22zp"> <pre style="margin: 0px;padding: 0px;background: none;font-family: none;"><code style="border-radius: 4px;font-size: 0.85em;font-family: none;margin: 0px 0.15em;background: rgb(248, 248, 248);color: rgb(51, 51, 51);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span style="color: rgb(153, 153, 136);background: rgba(0, 0, 0, 0);display: inline;width: 279px;text-decoration: none solid rgb(153, 153, 136);font-weight: 400;font-style: italic;font-family: none;"><span leaf=""># 示例:将 Keras 模型转换为 TensorFlow Lite</span></span><span leaf=""><br></span><span leaf="">converter = tf.lite.TFLiteConverter.from_keras_model(model)</span><span leaf=""><br></span><span leaf="">tflite_model = converter.convert()</span><span leaf=""><br></span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">with</span></span><span leaf=""> open(</span><span style="color: rgb(221, 17, 68);background: rgba(0, 0, 0, 0);display: inline;width: 92px;text-decoration: none solid rgb(221, 17, 68);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">"model.tflite"</span></span><span leaf="">, </span><span style="color: rgb(221, 17, 68);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(221, 17, 68);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">"wb"</span></span><span leaf="">) </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">as</span></span><span leaf=""> f:</span><span leaf=""><br></span><span leaf=""> f.write(tflite_model)</span></code></pre> </section> <ol style="box-sizing: border-box;margin: 0.8em 0px;padding-left: 30px;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial; class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n129" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">在线学习</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""> 用 Redis 存储实时反馈数据,定期触发模型增量训练。</span></span></p></li> </ol> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t" data-mpa-action-id="m8zxd4og1y54"> <pre style="margin: 0px;padding: 0px;background: none;font-family: none;"><code style="border-radius: 4px;font-size: 0.85em;font-family: none;margin: 0px 0.15em;background: rgb(248, 248, 248);color: rgb(51, 51, 51);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span style="color: rgb(153, 153, 136);background: rgba(0, 0, 0, 0);display: inline;width: 128px;text-decoration: none solid rgb(153, 153, 136);font-weight: 400;font-style: italic;font-family: none;"><span leaf=""># 每小时重新训练模型</span></span><span leaf=""><br></span><span leaf="">schedule.every().hour.do(retrain_model)</span></code></pre> </section> <h3 cid="n131" mdtype="heading" style="box-sizing: border-box;break-after: avoid-page;break-inside: avoid;orphans: 2;font-size: 1.5em;margin-top: 24px;margin-bottom: 24px;font-weight: bold;line-height: 1.43;cursor: text;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">(三)性能优化方案</span></span></span></h3> <ol style="box-sizing: border-box;margin: 0.8em 0px;padding-left: 30px;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial; class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n134" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">批量推理</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""> 使用 Redis Pipelining 批量处理多个请求。</span></span></p></li> </ol> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t" data-mpa-action-id="m8zxh68kko5"> <pre style="margin: 0px;padding: 0px;background: none;font-family: none;"><code style="border-radius: 4px;font-size: 0.85em;font-family: none;margin: 0px 0.15em;background: rgb(248, 248, 248);color: rgb(51, 51, 51);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span style="color: rgb(153, 153, 136);background: rgba(0, 0, 0, 0);display: inline;width: 142px;text-decoration: none solid rgb(153, 153, 136);font-weight: 400;font-style: italic;font-family: none;"><span leaf="">// Java 示例:批量推理</span></span><span leaf=""><br></span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">try</span></span><span leaf=""> (RedisPipeline pipeline = redis.pipelined()) {</span><span leaf=""><br></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">for</span></span><span leaf=""> (User user : users) {</span><span leaf=""><br></span><span leaf=""> pipeline.hgetall(</span><span style="color: rgb(221, 17, 68);background: rgba(0, 0, 0, 0);display: inline;width: 105px;text-decoration: none solid rgb(221, 17, 68);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">"user_features:"</span></span><span leaf=""> + user.getId());</span><span leaf=""><br></span><span leaf=""> }</span><span leaf=""><br></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">List</span></span><span leaf=""><object> results = pipeline.syncAndReturnAll();<span leaf=""><br></span><span leaf="">}</span> <ol style="box-sizing: border-box;margin: 0.8em 0px;padding-left: 30px;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial; class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n138" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">缓存热点决策</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""> 用 Redis 缓存高频决策结果,减少模型调用次数。</span></span></p></li> </ol> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" mpa-preserve="t" mpa-from-tpl="t" data-mpa-action-id="m8zxgdpeyrl"> <pre style="margin: 0px;padding: 0px;background: none;font-family: none;"><code style="border-radius: 4px;font-size: 0.85em;font-family: none;margin: 0px 0.15em;background: rgb(248, 248, 248);color: rgb(51, 51, 51);display: block;padding: 5.95px;overflow-x: auto;white-space: nowrap;"><span style="color: rgb(153, 153, 136);background: rgba(0, 0, 0, 0);display: inline;width: 128px;text-decoration: none solid rgb(153, 153, 136);font-weight: 400;font-style: italic;font-family: none;"><span leaf=""># 缓存高置信度的结果</span></span><span leaf=""><br></span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 236px;text-decoration: none solid rgb(51, 51, 51);font-weight: 400;font-style: normal;font-family: none;"><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">def</span></span><span leaf=""> </span><span style="color: rgb(153, 0, 0);background: rgba(0, 0, 0, 0);display: inline;width: 92px;text-decoration: none solid rgb(153, 0, 0);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">cache_decision</span></span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 111px;text-decoration: none solid rgb(51, 51, 51);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">(user_id, result)</span></span><span leaf="">:</span></span><span leaf=""><br></span><span leaf=""> </span><span style="color: rgb(51, 51, 51);background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration: none solid rgb(51, 51, 51);font-weight: 700;font-style: normal;font-family: none;"><span leaf="">if</span></span><span leaf=""> result.confidence > </span><span style="color: rgb(0, 128, 128);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(0, 128, 128);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">0.95</span></span><span leaf="">:</span><span leaf=""><br></span><span leaf=""> redis.setex(</span><span style="color: rgb(221, 17, 68);background: rgba(0, 0, 0, 0);display: inline;width: 52px;text-decoration: none solid rgb(221, 17, 68);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">"cache:"</span></span><span leaf=""> + user_id, </span><span style="color: rgb(0, 128, 128);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration: none solid rgb(0, 128, 128);font-weight: 400;font-style: normal;font-family: none;"><span leaf="">3600</span></span><span leaf="">, result)</span></code></pre> </section> <section mpa-from-tpl="t" data-mpa-action-id="m8zxi7fwbed" data-pm-slice="0 0 []"> <span leaf=""><br></span> </section> <section data-mpa-template="t" mpa-from-tpl="t" data-mpa-action-id="m8zxi7fwb9h"> <section data-mpa-template="t" mpa-from-tpl="t"> <h4 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: 400;font-size: 16px;text-align: justify;outline: 0px;color: rgb(34, 34, 34);letter-spacing: 0.544px;caret-color: rgb(51, 51, 51);line-height: 2em;"><span style="font-size: 20px;"><strong mpa-from-tpl="t" style="outline: 0px;"><span mpa-is-content="t" style="font-size: 20px;outline: 0px;color: rgb(0, 122, 170);"><span leaf="">五、避坑指南:那些你必须知道的细节</span></span></strong></span></h4> </section> </section><h3 cid="n141" mdtype="heading" style="box-sizing: border-box;break-after: avoid-page;break-inside: avoid;orphans: 2;font-size: 1.5em;margin-top: 24px;margin-bottom: 24px;font-weight: bold;line-height: 2em;cursor: text;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">(一)数据一致性问题</span></span></span></h3> <ul style="box-sizing: border-box;margin: 0.8em 0px;padding-left: 30px;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial; class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n144" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">解决方案</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">:使用 Redis 事务(WATCH/MULTI/EXEC)保证数据原子性。</span></span></p></li> </ul><h3 cid="n146" mdtype="heading" style="box-sizing: border-box;break-after: avoid-page;break-inside: avoid;orphans: 2;font-size: 1.5em;margin-top: 24px;margin-bottom: 24px;font-weight: bold;line-height: 1.43;cursor: text;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 18px;">(二)模型漂移问题</span></span></span></h3> <ul style="box-sizing: border-box;margin: 0.8em 0px;padding-left: 30px;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial; class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n149" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">监控指标</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">:AUC、准确率、召回率、F1 值</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n151" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">解决方案</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">:定期重新训练模型,使用模型版本管理工具(如 MLflow)</span></span></p></li> </ul><h3 cid="n152" mdtype="heading" style="box-sizing: border-box;break-after: avoid-page;break-inside: avoid;orphans: 2;font-size: 1.5em;margin-top: 24px;margin-bottom: 24px;font-weight: bold;line-height: 2em;cursor: text;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">(三)Redis 内存管理</span></span></span></h3> <ul style="box-sizing: border-box;margin: 0.8em 0px;padding-left: 30px;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial; class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n155" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">内存监控</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">:定期执行 </span></span><span md-inline="code" spellcheck="false" style="box-sizing: border-box;"><code style="box-sizing: border-box;font-family: var(--monospace);text-align: left;vertical-align: initial;border: 1px solid rgb(231, 234, 237);background-color: rgb(243, 244, 244);border-radius: 3px;padding: 0px 2px;font-size: 0.9em;"><span leaf="">redis-cli info memory</span></code></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n157" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">淘汰策略</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">:设置合理的 </span></span><span md-inline="code" spellcheck="false" style="box-sizing: border-box;"><code style="box-sizing: border-box;font-family: var(--monospace);text-align: left;vertical-align: initial;border: 1px solid rgb(231, 234, 237);background-color: rgb(243, 244, 244);border-radius: 3px;padding: 0px 2px;font-size: 0.9em;"><span leaf="">maxmemory-policy</span></code></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">(如 allkeys-lru)</span></span></p></li> </ul> <section mpa-from-tpl="t" data-mpa-action-id="m8zxkvfxr62" data-pm-slice="0 0 []"> <span leaf=""><br></span> </section> <section data-mpa-template="t" mpa-from-tpl="t" data-mpa-action-id="m8zxkvfxbfu"> <section data-mpa-template="t" mpa-from-tpl="t"> <h4 data-tool="mdnice编辑器" style="margin-bottom: 15px;font-weight: 400;font-size: 16px;text-align: justify;outline: 0px;color: rgb(34, 34, 34);letter-spacing: 0.544px;caret-color: rgb(51, 51, 51);line-height: 2em;"><span style="font-size: 20px;"><strong mpa-from-tpl="t" style="outline: 0px;"><span mpa-is-content="t" style="font-size: 20px;outline: 0px;color: rgb(0, 122, 170);"><span leaf="">六、真实案例:某支付公司的实战经验</span></span></strong></span></h4> </section> </section><p cid="n159" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 24px 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;">某支付公司通过 Redis+AI 风控系统实现了:</span></span></span></p> <ul style="box-sizing: border-box;margin: 0.8em 0px;padding-left: 30px;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial; class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n162" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">响应时间</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">:从 800ms 降至 70ms</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n164" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">拦截准确率</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">:从 72% 提升至 93%</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n166" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">误报率</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">:下降 65%</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n168" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="strong" style="box-sizing: border-box;"><strong style="box-sizing: border-box;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">运维成本</span></span></strong></span><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">:减少 40% 的人工规则维护工作量 </span></span></p></li> </ul><p cid="n169" mdtype="paragraph" style="box-sizing: border-box;line-height: 2em;orphans: 4;margin: 24px 0px;white-space: pre-wrap;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;text-align: start;text-indent: 0px;text-transform: none;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial;><span md-inline="plain" style="box-sizing: border-box;"><span leaf=""><span textstyle="" style="font-size: 17px;font-weight: bold;">具体实施步骤:</span></span></span></p> <ol style="box-sizing: border-box;margin: 0.8em 0px;padding-left: 30px;color: rgb(51, 51, 51);font-family: " open sans, clear helvetica neue, helvetica, arial, sans-serif;font-size: 16px;font-style: normal;font-variant-ligatures: normal;font-variant-caps: normal;font-weight: 400;letter-spacing: normal;orphans: 2;text-align: start;text-indent: 0px;text-transform: none;white-space: normal;widows: 2;word-spacing: 0px;-webkit-text-stroke-width: 0px;text-decoration-style: initial;text-decoration-color: initial; class="list-paddingleft-1"> <li style="box-sizing: border-box;margin: 0px;"><p cid="n172" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">搭建 Redis 集群(3 主 3 从)</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n174" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">使用 Redis Streams 实时采集交易数据</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n176" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">用 Redis AI 部署 XGBoost 模型</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n178" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">开发实时特征计算模块</span></span></p></li> <li style="box-sizing: border-box;margin: 0px;"><p cid="n180" mdtype="paragraph" style="box-sizing: border-box;line-height: inherit;orphans: 4;margin: 0px 0px 0.5rem;white-space: pre-wrap;"><span md-inline="plain" style="box-sizing: border-box;"><span leaf="">接入业务系统进行压力测试</span></span></p></li> </ol><p style="display: none;"> <mp-style-type data-value="3"></mp-style-type></p> <script type="text/javascript" nonce="1989770072" reportloaderror> var first_sceen__time = (+new Date()); if ("" == 1 && document.getElementById('js_content')) { document.getElementById('js_content').addEventListener("selectstart",function(e){ e.preventDefault(); }); } </script> <div id="js_tags_preview_toast" class="article-tag__error-tips" style="display: none;">预览时标签不可点 </div> <div id="content_bottom_area"></div> <div id="js_temp_bottom_area" class="rich_media_tool_area"> <div class="rich_media_tool__wrp"> <div class="rich_media_tool"> <div class="rich_media_info weui-flex "> </div> </div> </div> </div> <div class="rich_media_area_primary sougou" id="sg_tj" style="display:none"></div> <div class="rich_media_area_extra"> <div class="rich_media_area_extra_inner"> <div id="page_bottom_area"></div> </div> </div> <div id="js_pc_qr_code" class="qr_code_pc_outer" style="display:none;"> <div class="qr_code_pc_inner"> <div class="qr_code_pc"><img id="js_pc_qr_code_img" class="qr_code_pc_img"> <p>微信扫一扫<br>关注该公众号</p> </div> </div> </div> <div class="wx_stream_article_slide_tip" id="wx_stream_article_slide_tip"> <div class="wx_stream_article_slide_tip_wrp"> <span class="wx_stream_article_slide_tip_arrow"></span> <span class="wx_stream_article_slide_tip_text">继续滑动看下一个</span> </div> </div> <div class="wx_network_msg_wrp" id="js_network_msg_wrp"></div> <div class="wx_expand_article " id="wx_expand_article"> <div class="wx_expand_article_gradient_background" id="wx_expand_background"></div> <div class="wx_expand_article_bottom_area" id="wx_expand_bottom"> <div class="wx_expand_article_button_wrap" id="wx_expand_article_placeholder"><button class="wx_expand_article_button" id="wx_expand_article_button">轻触阅读原文</button> </div> <div id="js_stream_bottom_bar" class="stream_bottom_bar_wrp"> <div id="js_stream_bottom_bar_placeholder" class="bottom_bar_placeholder"> <div class="wx_follow_context wx_follow_primary wx_follow_smart wx_follow_top wx_follow_bottom"> <div class="function_mod js_function_mod wx_tap_cell"> <div class="function_mod_inner js_function_mod_inner"> <div class="function_bd"> <div class="wx_follow_media weui-flex weui-flex_align-center"> <div class="wx_follow_hd"><span class="wx_follow_avatar"> <img src="/upload/ac7ecb6e296202cc8a75f7993256decd.png" alt="" class="wx_follow_avatar_pic"> </span> </div> <div class="wx_follow_bd weui-flex__item"> <div class="wx_follow_info"> <div role="link" tabindex="0" aria-labelledby="js_wx_follow_nickname" aria-describedby="js_wx_follow_tips" class="wx_follow_nickname"> 石杉的架构笔记 </div> </div> </div> </div> </div> </div> </div> </div> <div class="interaction_bar__wrap" style="opacity: 1;"> <div class="interaction_bar" style="-webkit-text-size-adjust: 100%;"> </div> </div> </div> <div id="stream_article_bottom_area"></div> </div> </div> <div id="wx_expand_slidetip" class="wx_expand_article_slide_tip"> <div class="wx_stream_article_slide_tip"> <div class="wx_stream_article_slide_tip_wrp"><span class="wx_stream_article_slide_tip_arrow"></span> <span class="wx_stream_article_slide_tip_text">向上滑动看下一个</span> </div> </div> </div> </div> <div id="js_ad_control"></div> <div id="audio_panel_area"></div> <div id="js_profile_card_modal"></div> <div class="comment_primary_emotion_panel_wrp" id="js_emotion_panel_pc" style="display: none"> <div class="comment_primary_emotion_panel"> <ul class="comment_primary_emotion_list_pc" id="js_emotion_list_pc"> </ul> </div> </div> <div class="weui-dialog__wrp" id="js_alert_panel" style="display:none;"> <div class="weui-mask"></div> <div class="weui-dialog"> <div class="weui-dialog__bd" id="js_alert_content"></div> <div class="weui-dialog__ft"><a href="javascript:;" class="weui-dialog__btn weui-dialog__btn_default" id="js_alert_confirm">知道了</a> </div> </div> </div> <script type="text/javascript" nonce="1989770072" reportloaderror> window.img_popup = 1; </script> <style>.weui-dialog_link{-webkit-transform:translateY(-75%);transform:translateY(-75%)}</style> <div id="js_pc_weapp_code" class="weui-desktop-popover weui-desktop-popover_pos-up-center weui-desktop-popover_img-text weapp_code_popover" style="display: none;"> <div class="weui-desktop-popover__inner"> <div class="weui-desktop-popover__desc"><img id="js_pc_weapp_code_img"> 微信扫一扫<br>使用小程序<span id="js_pc_weapp_code_des"></span> </div> </div> </div> <div id="js_minipro_dialog" role="dialog" aria-modal="true" tabindex="0" aria-labelledby="js_minipro_dialog_head" style="display:none;"> <div class="weui-mask"></div> <div class="weui-dialog weui-dialog_link"> <div class="weui-dialog__hd"><strong class="weui-dialog__title" id="js_minipro_dialog_head" tabindex="0"></strong> </div> <div class="weui-dialog__bd" id="js_minipro_dialog_body"></div> <div class="weui-dialog__ft"><a role="button" id="js_minipro_dialog_cancel" href="javascript:void(0);" class="weui-dialog__btn weui-dialog__btn_default">取消</a> <a role="button" id="js_minipro_dialog_ok" href="javascript:void(0);" class="weui-dialog__btn weui-dialog__btn_primary">允许</a> </div> </div> </div> <div id="js_link_dialog" role="dialog" aria-modal="true" tabindex="0" aria-labelledby="js_link_dialog_body" style="display:none;"> <div class="weui-mask"></div> <div class="weui-dialog weui-dialog_link"> <div class="weui-dialog__hd"><strong class="weui-dialog__title" id="js_link_dialog_head" tabindex="0"></strong> </div> <div class="weui-dialog__bd" id="js_link_dialog_body" tabindex="0"></div> <div class="weui-dialog__ft"><a role="button" id="js_link_dialog_cancel" href="javascript:void(0);" class="weui-dialog__btn weui-dialog__btn_default">取消</a> <a role="button" id="js_link_dialog_ok" href="javascript:void(0);" class="weui-dialog__btn weui-dialog__btn_primary">允许</a> </div> </div> </div> <div class="analyze_btn_wrap" id="js_analyze_btn" style="display:none"> <button class="close-button">×</button> <button class="go-button wx_tap_card js_wx_tap_highlight">分析</button> </div> <div class="weui-dialog__wrp jump_wx_qrcode_dialog" id="js_jump_wx_qrcode_dialog" role="dialog" style="display:none;"> <div class="weui-mask js_dialog_mask"></div> <div class="weui-dialog"> <div class="weui-dialog__hd"><i class="weui-icon-close-thin js_dialog_close"></i> <div class="qrcode-con"><img class="jump_wx_qrcode_img js_qrcode_img" src="" alt="跳转二维码"> <div class="jump_author_avatar_con"><img class="jump_author_avatar" src="/upload/ac7ecb6e296202cc8a75f7993256decd.png" alt="作者头像"> </div> </div> </div> <div class="weui-dialog__bd"> <p class="jump_wx_qrcode_desc">微信扫一扫可打开此内容,<br>使用完整服务</p> </div> </div> </div> <div id="unlogin_bottom_bar" style="display:none;"> <div id="js_article_bottom_bar" class="bottom_bar_wrp"> <div id="article_bottom_bar_area"></div> </div> <div class="bottom_bar_padding_mask"></div> </div> <script type="text/javascript" nonce="1989770072" reportloaderror> window.logs.pagetime.page_begin = Date.now(); try { var adIframeUrl = localStorage.getItem('__WXLS_ad_iframe_url'); if (window === top) { if (adIframeUrl) { if (navigator.userAgent.indexOf('iPhone') > -1) { var img = new Image(); img.src = adIframeUrl; } else { var link = document.createElement('link'); link.rel = 'prefetch'; link.href = adIframeUrl; document.getElementsByTagName('head')[0].appendChild(link); } } } } catch (err) { } </script> <span aria-hidden="true" class="weui-a11y_ref" style="display:none" id="js_a11y_colon">:</span> <span aria-hidden="true" class="weui-a11y_ref" style="display:none" id="js_a11y_comma">,</span> <span aria-hidden="true" class="weui-a11y_ref" style="display:none" id="js_a11y_comma0">,</span> <span aria-hidden="true" class="weui-a11y_ref" style="display:none" id="js_a11y_comma1">,</span> <span aria-hidden="true" class="weui-a11y_ref" style="display:none" id="js_a11y_comma2">,</span> <span aria-hidden="true" class="weui-a11y_ref" style="display:none" id="js_a11y_comma3">,</span> <span aria-hidden="true" class="weui-a11y_ref" style="display:none" id="js_a11y_comma4">,</span> <span aria-hidden="true" class="weui-a11y_ref" style="display:none" id="js_a11y_comma5">,</span> <span aria-hidden="true" class="weui-a11y_ref" style="display:none" id="js_a11y_comma6">,</span> <span aria-hidden="true" class="weui-a11y_ref" style="display:none" id="js_a11y_comma7">,</span> <span aria-hidden="true" class="weui-a11y_ref" style="display:none" id="js_a11y_comma8">,</span> <span aria-hidden="true" class="weui-a11y_ref" style="display:none" id="js_a11y_comma9">,</span> <span aria-hidden="true" class="weui-a11y_ref" style="display:none" id="js_a11y_comma10">,</span> <span aria-hidden="true" class="weui-a11y_ref" style="display:none" id="js_a11y_period">。</span> <span aria-hidden="true" class="weui-a11y_ref" style="display:none" id="js_a11y_space"> </span> <span aria-hidden="true" class="weui-a11y_ref" style="display:none" id="js_a11y_type_video">视频</span> <span aria-hidden="true" class="weui-a11y_ref" style="display:none" id="js_a11y_type_weapp">小程序</span> <span aria-hidden="true" class="weui-a11y_ref" style="display:none" id="js_a11y_zan_btn_txt">赞</span> <span aria-hidden="true" class="weui-a11y_ref" style="display:none" id="js_a11y_zan_btn_tips">,轻点两下取消赞</span> <span aria-hidden="true" class="weui-a11y_ref" style="display:none" id="js_a11y_like_btn_txt">在看</span> <span aria-hidden="true" class="weui-a11y_ref" style="display:none" id="js_a11y_like_btn_tips">,轻点两下取消在看</span> <span aria-hidden="true" class="weui-a11y_ref" style="display:none" id="js_a11y_share_btn_txt">分享</span> <span aria-hidden="true" class="weui-a11y_ref" style="display:none" id="js_a11y_comment_btn_txt">留言</span> <span aria-hidden="true" class="weui-a11y_ref" style="display:none" id="js_a11y_collect_btn_txt">收藏</span> <span aria-hidden="true" class="weui-a11y_ref" style="display:none" id="js_a11y_op_ting_heard">听过</span> <script type="text/javascript" nonce="1989770072" reportloaderror> (function () { var totalCount = 0, finishCount = 0; function _addScript(uri, cb) { totalCount++; var node = document.createElement('SCRIPT'); node.type = 'text/javascript'; node.src = uri; node.setAttribute('nonce', '1989770072'); if (cb) { node.onload = cb; } document.getElementsByTagName('head')[0].appendChild(node); } if ((document.cookie && document.cookie.indexOf('vconsole_open=1') > -1) || location.href.indexOf('vconsole=1') > -1) { _addScript('https://mp.weixin.qq.com/mmbizappmsg/zh_CN/htmledition/js/scripts/vconsole-3.14.6.js', function () { window.vConsole = new window.VConsole(); }); } if (document.cookie && document.cookie.indexOf('__xweb_remote_debug_device_token__') > -1) { _addScript('https://mp.weixin.qq.com/mmbizappmsg/zh_CN/htmledition/js/scripts/mprdev-0.2.5.js', function () { _addScript('https://mp.weixin.qq.com/mmbizappmsg/zh_CN/htmledition/js/scripts/xwebrd-0.0.2.js'); }); } })(); </script> <script type="text/javascript" h5only nonce="1989770072" reportloaderror>(function () { 'use strict'; function _arrayLikeToArray$1(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray$1(arr); } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } function _unsupportedIterableToArray$1(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray$1(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$1(o, minLen); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray$1(arr) || _nonIterableSpread(); } const A = { web: "common-web", app: "common-app", wechat: "common-webchat" }; function x(t, e) { const o = arguments[1] || window.location.search, n = new RegExp("(^|&)" + t + "=([^&]*)(&|$)"), s = o.substr(o.indexOf("?") + 1).match(n); return s != null ? s[2] : ""; } const f = x("color_scheme", location.href), $ = Number(x("uninteractive", location.href)), j$1 = { props: { platform: { type: String, default: "web" }, extraInfo: { type: Object, default: () => ({}) } }, mounted() { const t = this.$refs.js_custom_element; this.platform !== "wechat" && !f && t.setAttribute("data-weui-theme", "light"), f && f === "light" && t.setAttribute("data-weui-theme", "light"), $ === 1 && t.classList.add("wx_uninteractive"); }, data() { return { platformClassname: A[this.platform] }; } }; function _(t) { const e = {}; return t.attributes && Array.from(t.attributes).forEach((o) => { e[o.nodeName] = o.nodeValue; }), e; } function L$1(t = [], e) { let o = []; return t.childNodes.forEach((n) => { const s = _(n); if ("data-shadow-slot" in s) { if (!s.slot) return; const l = { attrs: s, domProps: { innerHTML: n.innerHTML === "" ? n.innerText : n.innerHTML }, slot: s.slot }; s.slot = void 0; const m = e(n.tagName, l); o.push(m); } else if (s.slot) { const l = e("slot", { attrs: { name: s.slot }, slot: s.slot }); o.push(l); } }), o; } function k({ iframeWindow: t, Component: e, platform: o, customName: n, styleText: s, extraInfo: l = {}, watchAttr: m, beforeRender: b, afterRender: g, selector: E, afterMounted: y, reflowProps: w, getProps: C, eventName: v = [] }) { let d = window; t && (d = t), l.window = d, d.customElements.define(n, class extends d.HTMLElement { constructor() { super(); const i = this.attachShadow({ mode: "open" }); this.shadow = i; } connectedCallback() { if (!e.install) { if (e.props && w && w.length) { const a = { watch: {} }; w.forEach((u) => { a.watch[u] = function() { const p = this.$el.getRootNode().host, T = { compEle: p, compType: n, compIdx: Array.from(document.querySelectorAll(E || n)).indexOf(p) }; b && b(Object.assign({ subCompType: u }, T)), this.$nextTick(() => { g && g(Object.assign({ subCompType: u }, T)); }); }; }), e.mixins.push(a); } typeof e.template == "function" && e.template(e); } const i = v.reduce((a, u) => (a[u] = (p) => { this.dispatchCustomEvent(u, p); }, a), {}), r = new Vue({ render: (a) => a( e, { props: C.call(this, o, l), on: i }, L$1(this, a) ) }); this.wrapper = r; const c = document.createElement("style"); c.textContent = ` :host { all: initial; -webkit-text-size-adjust: inherit; } `, this.shadowRoot.appendChild(c); const h = document.createElement("style"); h.appendChild(document.createTextNode(s)), this.shadowRoot.appendChild(h), this.wrapper.$mount(), this.shadowRoot.appendChild(this.wrapper.$el), this.debounceUpdate = this.debounce(() => { console.log("forceUpdate"), this.wrapper && this.wrapper.$forceUpdate(); }, 500), this.classList.add("mp_common_widget"), y && y.call(this); } debounce(i, r) { let c; return function(...h) { const a = this; clearTimeout(c), c = setTimeout(() => i.apply(a, h), r); }; } dispatchCustomEvent(i, r) { const c = new CustomEvent(i, { detail: r, bubbles: !0, composed: !0 }); this.dispatchEvent(c); } getKeyByDataValue(i) { for (const r in ATTR) if (ATTR[r] === i) return r; return null; } disconnectedCallback() { this.shadowRoot.innerHTML = "", this.wrapper && this.wrapper.$destroy(); } attributeChangedCallback(i, r, c) { this.wrapper && this.wrapper.$forceUpdate(); } static get observedAttributes() { return m; } }); } typeof Number.isFinite == "function" && Number.isFinite.bind(Number); function o$1(n) { const t = {}; return Object.keys(n).forEach((e) => { t[e] = this.getAttribute(n[e]); }), t; } function r$1(B) { const A = {}, E = /[?&]([^=&#]+)=([^&#]*)/g, w = B.match(E); if (w) { for (const i in w) if (Object.prototype.hasOwnProperty.call(w, i)) { const M = w[i].split("="), e = M[0].substr(1), F = M[1]; A[e] ? A[e] = [].concat(A[e], F) : A[e] = F; } } return A; } function T(B, A, E, w, i, M, e, F) { var I = typeof B == "function" ? B.options : B; A && (I.render = A, I.staticRenderFns = E, I._compiled = !0), w && (I.functional = !0), M && (I._scopeId = "data-v-" + M); var g; if (e ? (g = function(Q) { Q = Q || this.vnode.ssrContext || this.parent && this.parent.vnode.ssrContext, !Q && typeof __VUE_SSR_CONTEXT__ < "u" && (Q = __VUE_SSR_CONTEXT__), i && i.call(this, Q), Q && Q._registeredComponents && Q._registeredComponents.add(e); }, I._ssrRegister = g) : i && (g = F ? function() { i.call( this, (I.functional ? this.parent : this).options.shadowRoot ); } : i), g) if (I.functional) { I._injectStyles = g; var Y = I.render; I.render = function(c, t) { return g.call(t), Y(c, t); }; } else { var u = I.beforeCreate; I.beforeCreate = u ? [].concat(u, g) : [g]; } return { exports: B, options: I }; } const D = "https://mp.weixin.qq.com/shop/ssr/wap/business", U = "https://mp.weixin.qq.com/mmec/productcard", l = "https://mp.weixin.qq.com", N = { BIZ_ARTICLE_CSIDE_READ: 1, BIZ_ARTICLE_BSIDE_PREVIEW: 2, BIZ_PRIVATE_MESSAGE_BSIDE: 3, BIZ_PRIVATE_MESSAGE_CSIDE: 4, BIZ_AUTO_REPLY_BSIDE: 5, BIZ_AUTO_REPLY_CSIDE: 6, BIZ_CUSTOM_MENU_BSIDE: 7, BIZ_CUSTOM_MENU_CSIDE: 8 }; function h(B) { const A = B.length; let E = B.indexOf("?"), w = B.indexOf("#"); w = w === -1 ? A : w, E = E === -1 ? w : E; const i = B.substring(0, E), M = B.substring(E + 1, w), e = B.substring(w + 1); return { host: i, queryStr: M, hash: e }; } function C$1(B, A, E = !1) { const w = h(B); let i = w.queryStr; const M = []; if (typeof A == "object") for (const e in A) Object.prototype.hasOwnProperty.call(A, e) && M.push(e + "=" + (E ? A[e] : encodeURIComponent(A[e]))); else M.push(E ? A : encodeURIComponent(A)); return M.length > 0 && (i += (i !== "" ? "&" : "") + M.join("&")), `${w.host}${i !== "" ? "?" + i : ""}${w.hash !== "" ? "#" + w.hash : ""}`; } function L(B) { try { const { action: A, value: E } = JSON.parse(B); return { action: A, value: E }; } catch (A) { console.error(A); } return {}; } function G(B, A, E, w) { try { if (!B) return console.warn("postMessageToIframe: win is null"); B.postMessage( JSON.stringify({ action: A, value: E }), w || "*" ); } catch (i) { console.log("postMessage error", i); } } const d = { name: "mp-common-product", mixins: [j$1], props: { extraInfo: { type: Object, default: () => ({}) }, productInfo: { type: Object, default: () => ({}) }, immutable: { type: Number, default: 0 }, token: { type: String, default: "" }, windowproduct: { type: String, default: "" }, is_hover: { type: Number, default: 0 }, is_selected: { type: Number, default: 0 }, customstyle: { type: String, default: "{}" }, ecsource: { type: String, default: "" }, exportkey: { type: String, default: "" }, wap_export_token: { type: String, default: "" }, loaded: { type: Number, default: 0 }, cardtype: { type: Number, default: 0 }, productImage: { type: String, default: "" }, originPrice: { type: Number, default: 0 }, discountedPrice: { type: Number, default: 0 }, title: { type: String, default: "" }, req_scene: { type: Number, default: 0 }, urlParams: { type: Object, default: () => ({}) }, extInfo: { type: Object, default: () => ({}) }, scrollBlur: { type: Number, default: !1 }, wrpStyle: { type: String, default: "" }, outerclick: { type: Number, default: 0 } }, data() { return { showIframe: !1, iframeUrl: "", transferStyle: "", timeout: null, observer: null, active: !1, hasExpose: !1, iframeLoading: !0, iframeLoadTimeout: null }; }, watch: { loaded: { handler() { this.loaded && (this.showIframe = !0, this.iframeUrl = this.getCIframeUrl()); }, immediate: !0 }, cardtype() { this.isEditor && (this.iframeUrl = this.getBIframeUrl()); }, windowproduct() { this.isEditor && (this.iframeUrl = this.getBIframeUrl()); }, iframeUrl() { this.iframeLoading = !0, this.iframeLoadTimeout && clearTimeout(this.iframeLoadTimeout), this.iframeLoadTimeout = setTimeout(() => { window.WX_BJ_REPORT && window.WX_BJ_REPORT.BadJs && window.WX_BJ_REPORT.BadJs.report("load timeout", this.iframeUrl, { mid: "mmbizwap:product", view: "wap_business", _info: { url: location.href, productCount: document.getElementsByTagName("mp-common-product").length } }); }, 5e3); } }, computed: { isEditor() { return this.platform === "web" || this.platform === "app"; }, iframeStyle() { let B = {}; return this.platform === "web" ? [N.BIZ_CUSTOM_MENU_BSIDE, N.BIZ_AUTO_REPLY_BSIDE, N.BIZ_PRIVATE_MESSAGE_BSIDE].includes( this.req_scene ) ? B.width = "195px" : B.width = "350px" : B.width = "100%", B = Object.assign(B, JSON.parse(this.transferStyle || "{}")), B; } }, created() { this.isEditor && (this.showIframe = !0, this.iframeUrl = this.getBIframeUrl()); }, mounted() { this.extraInfo.window && this.extraInfo.window.addEventListener("message", this.handleMessage), this.extraInfo.window && this.extraInfo.window.addEventListener("click", this.handleDocumentClick), this.scrollBlur && this.extraInfo.window && this.extraInfo.window.addEventListener("scroll", this.handleScroll); }, beforeDestroy() { this.extraInfo.window && this.extraInfo.window.removeEventListener("message", this.handleMessage), this.extraInfo.window && this.extraInfo.window.removeEventListener("click", this.handleDocumentClick), this.scrollBlur && this.extraInfo.window && this.extraInfo.window.removeEventListener("scroll", this.handleScroll), this.observer && this.observer.disconnect(); }, methods: { handleScroll() { this.deActive(); }, handleDocumentClick(B) { this.$refs.js_custom_element.contains(B.target) || (this.deActive(), this.$emit("document-click", B)); }, deActive() { const B = this.$refs.iframeRef; B && B.contentWindow && this.active && (G(B.contentWindow, "webEvent", { type: "unclick" }), this.active = !1); }, exposureReport() { this.observer = new IntersectionObserver( (B) => { B.forEach((A) => { const E = this.$refs.iframeRef; if (A.isIntersecting && A.intersectionRatio >= 0.5) { this.$emit("expose", !this.hasExpose), this.hasExpose = !0; try { E && E.contentWindow && (this.timeout = setTimeout(() => { G(E.contentWindow, "webEvent", { type: "valid_expose" }); }, 500)); } catch (w) { console.error(w); } } else this.timeout && clearTimeout(this.timeout); }); }, { threshold: 0.5 } ), this.observer.observe(this.$refs.js_custom_element); }, handleMessage(B) { if (B.origin !== l) return; const A = this.$refs.iframeRef; if (A && B.source === A.contentWindow) { const { action: E, value: w } = L(B.data); switch (E) { case "changeFrameStyle": this.changeFrameStyle(B, w); break; case "onFrameReady": this.onFrameReady(B, A); break; case "webEvent": w.type === "click" ? this.clickProduct(B) : w.type === "toast" ? window.weui.toast(w.msg, { extClass: "weui-toast_text" }) : w.type === "dialog" && window.weui.dialog(w); break; } this.$emit("iframe-message", B); } }, onFrameReady(B, A) { this.iframeLoadTimeout && clearTimeout(this.iframeLoadTimeout), this.iframeLoading = !1, this.setProductData(B.source, A), this.extraInfo.window && G(this.extraInfo.window, "setPageData", { darkMode: this.extraInfo.window.matchMedia("(prefers-color-scheme: dark)").matches }), this.isEditor || this.exposureReport(); }, clickProduct(B) { this.extraInfo.window && this.extraInfo.window.clickedProductWin && B.source !== this.extraInfo.window.clickedProductWin && G(this.extraInfo.window.clickedProductWin, "webEvent", { type: "unclick" }), this.extraInfo.window && (this.extraInfo.window.clickedProductWin = B.source), this.active = !0; }, setProductData(B) { G(B, "setData", { infos: { scene: "edit" } }), this.immutable && G(B, "setPageData", { scene: "immutable" }); }, changeFrameStyle(B, A) { if (!(!A || typeof A != "object" || this.cardtype === 2)) try { this.transferStyle = JSON.stringify(A); } catch (E) { console.error(E); } }, getBIframeUrl() { const B = { productkey: this.windowproduct, reqScene: this.req_scene, ...this.urlParams }, A = window && window.wx && window.wx.data && window.wx.data.t || r$1(window.location.href).token || this.token; return A && (B.token = A), this.cardtype && (B.cardtype = this.cardtype), C$1(D, B); }, getCIframeUrl() { const B = { productkey: this.windowproduct, reqScene: this.req_scene, ...this.urlParams }; return this.exportkey && (B.exportkey = this.exportkey), this.wap_export_token && (B.wap_export_token = this.wap_export_token), this.ecsource && (B.ecsource = this.ecsource), this.cardtype && (B.cardtype = this.cardtype), typeof window.WX_BJ_REPORT < "u" && window.WX_BJ_REPORT.BadJs && window.WX_BJ_REPORT.BadJs.report(C$1(U, B), "no exportkey" + window.location.href, { mid: window.PAGE_MID, view: "wap_business" }), C$1(U, B); }, openShop() { const B = this.$refs.iframeRef; this.outerclick ? this.$emit("element-click", this.$refs.js_custom_element) : !this.isEditor && B && G(B.contentWindow, "webEvent", { type: "openShop", clickType: 0 }); } } }, z = d; var n = function() { var A = this, E = A._self._c; return A._self._setupProxy, A.cardtype === 2 ? E("span", { ref: "js_custom_element", staticClass: "product_card_text_wrp", style: A.wrpStyle }, [E("a", { staticClass: "product_text_link", style: A.isEditor ? "color: #576B95" : "", attrs: { href: "javascript:void(0);" }, on: { click: A.openShop } }, [A._v(A._s(A.title))]), A.showIframe ? E("iframe", { ref: "iframeRef", staticClass: "iframe_style", style: [A.iframeStyle, { display: "none" }], attrs: { src: A.iframeUrl, scrolling: "no", frameborder: "0" } }) : A._e()]) : A.cardtype === 4 ? E("div", { ref: "js_custom_element", staticClass: "activity_card_wrp", on: { click: A.openShop } }, [E("div", { staticClass: "activity_card_wrp__container" }, [E("img", { staticClass: "product_image", attrs: { src: A.productImage, alt: "" } }), E("transition", { attrs: { name: "fade" } }, [A.discountedPrice ? E("span", { staticClass: "discounted_price" }, [A._v("¥" + A._s(A.discountedPrice))]) : A._e()]), E("span", { key: A.discountedPrice, staticClass: "origin_price", class: { has_discount: A.discountedPrice } }, [A._v("¥" + A._s(A.originPrice))])], 1), A.showIframe ? E("iframe", { ref: "iframeRef", staticClass: "iframe_style", style: [A.iframeStyle, { display: "none" }], attrs: { src: A.iframeUrl, scrolling: "no", frameborder: "0" } }) : A._e()]) : A.cardtype === 5 ? E("div", { ref: "js_custom_element", staticClass: "s1s_card_wrp", on: { click: A.openShop } }, [E("img", { staticClass: "product-image", attrs: { src: A.productInfo.product_info.img_url, alt: "商品图片" } }), E("div", { staticClass: "product-info" }, [E("div", { staticClass: "product-title" }, [A._v(A._s(A.productInfo.product_info.title))]), E("div", { staticClass: "product-centercontainer" }, [E("span", { staticClass: "product-price" }, [A._v("¥" + A._s(A.productInfo.product_info.selling_price / 100))]), A.productInfo.product_info.friend_send_cnt ? E("div", { staticClass: "product-gifts" }, [A._v("朋友送过"), E("span", { staticClass: "product-gifts__num" }, [A._v(A._s(A.productInfo.product_info.friend_send_cnt))]), A._v("次 ")]) : A._e()]), E("div", { staticClass: "product-brand" }, [E("i", { staticClass: "product-logo" }), A._v(A._s(A.productInfo.shop_info.shop_window_profile_name)), E("i", { staticClass: "shop-verify-icon" })])]), A.showIframe ? E("iframe", { ref: "iframeRef", staticClass: "iframe_style", style: [A.iframeStyle, { display: "none" }], attrs: { src: A.iframeUrl, scrolling: "no", frameborder: "0" } }) : A._e()]) : E("div", { ref: "js_custom_element", class: [ "iframe_wrp", "wx_card_root", A.is_hover === 1 ? "wx_hover_card" : "", A.is_selected === 1 ? "wx_selected_card" : "" ], style: A.wrpStyle }, [A.showIframe ? E("iframe", { ref: "iframeRef", staticClass: "iframe_style", style: A.iframeStyle, attrs: { src: A.iframeUrl, scrolling: "no", frameborder: "0" } }) : A._e()]); }, S = [], y = T( z, n, S, !1, null, "bbb26799", null, null ); const j = y.exports, m = `body,.wx-root{--weui-BG-0: #EDEDED;--weui-BG-1: #F7F7F7;--weui-BG-2: #FFFFFF;--weui-BG-3: #F7F7F7;--weui-BG-4: #4C4C4C;--weui-BG-5: #FFFFFF;--weui-BLUE-100: #10AEFF;--weui-BLUE-120: #3FBEFF;--weui-BLUE-170: #B7E6FF;--weui-BLUE-80: #0C8BCC;--weui-BLUE-90: #0E9CE6;--weui-BLUE-BG-100: #48A6E2;--weui-BLUE-BG-110: #5AAFE4;--weui-BLUE-BG-130: #7FC0EA;--weui-BLUE-BG-90: #4095CB;--weui-BRAND-100: #07C160;--weui-BRAND-120: #38CD7F;--weui-BRAND-170: #B4ECCE;--weui-BRAND-80: #059A4C;--weui-BRAND-90: #06AE56;--weui-BRAND-BG-100: #2AAE67;--weui-BRAND-BG-110: #3EB575;--weui-BRAND-BG-130: #69C694;--weui-BRAND-BG-90: #259C5C;--weui-FG-0: rgba(0, 0, 0, .9);--weui-FG-0_5: rgba(0, 0, 0, .9);--weui-FG-1: rgba(0, 0, 0, .55);--weui-FG-2: rgba(0, 0, 0, .3);--weui-FG-3: rgba(0, 0, 0, .1);--weui-FG-4: rgba(0, 0, 0, .15);--weui-GLYPH-0: rgba(0, 0, 0, .9);--weui-GLYPH-1: rgba(0, 0, 0, .55);--weui-GLYPH-2: rgba(0, 0, 0, .3);--weui-GLYPH-WHITE-0: rgba(255, 255, 255, .8);--weui-GLYPH-WHITE-1: rgba(255, 255, 255, .5);--weui-GLYPH-WHITE-2: rgba(255, 255, 255, .3);--weui-GLYPH-WHITE-3: #FFFFFF;--weui-GREEN-100: #91D300;--weui-GREEN-120: #A7DB33;--weui-GREEN-170: #DEF1B3;--weui-GREEN-80: #74A800;--weui-GREEN-90: #82BD00;--weui-GREEN-BG-100: #96BE40;--weui-GREEN-BG-110: #A0C452;--weui-GREEN-BG-130: #B5D179;--weui-GREEN-BG-90: #86AA39;--weui-INDIGO-100: #1485EE;--weui-INDIGO-120: #439DF1;--weui-INDIGO-170: #B8DAF9;--weui-INDIGO-80: #106ABE;--weui-INDIGO-90: #1277D6;--weui-INDIGO-BG-100: #2B77BF;--weui-INDIGO-BG-110: #3F84C5;--weui-INDIGO-BG-130: #6BA0D2;--weui-INDIGO-BG-90: #266AAB;--weui-LIGHTGREEN-100: #95EC69;--weui-LIGHTGREEN-120: #AAEF87;--weui-LIGHTGREEN-170: #DEF9D1;--weui-LIGHTGREEN-80: #77BC54;--weui-LIGHTGREEN-90: #85D35E;--weui-LIGHTGREEN-BG-100: #72CF60;--weui-LIGHTGREEN-BG-110: #80D370;--weui-LIGHTGREEN-BG-130: #9CDD90;--weui-LIGHTGREEN-BG-90: #66B956;--weui-LINK-100: #576B95;--weui-LINK-120: #7888AA;--weui-LINK-170: #CCD2DE;--weui-LINK-80: #455577;--weui-LINK-90: #4E6085;--weui-LINKFINDER-100: #002666;--weui-MATERIAL-ATTACHMENTCOLUMN: rgba(245, 245, 245, .95);--weui-MATERIAL-NAVIGATIONBAR: rgba(237, 237, 237, .94);--weui-MATERIAL-REGULAR: rgba(247, 247, 247, .3);--weui-MATERIAL-THICK: rgba(247, 247, 247, .8);--weui-MATERIAL-THIN: rgba(255, 255, 255, .2);--weui-MATERIAL-TOOLBAR: rgba(246, 246, 246, .82);--weui-ORANGE-100: #FA9D3B;--weui-ORANGE-120: #FBB062;--weui-ORANGE-170: #FDE1C3;--weui-ORANGE-80: #C87D2F;--weui-ORANGE-90: #E08C34;--weui-ORANGE-BG-100: #EA7800;--weui-ORANGE-BG-110: #EC8519;--weui-ORANGE-BG-130: #F0A04D;--weui-ORANGE-BG-90: #D26B00;--weui-ORANGERED-100: #FF6146;--weui-OVERLAY: rgba(0, 0, 0, .5);--weui-OVERLAY-WHITE: rgba(242, 242, 242, .8);--weui-PURPLE-100: #6467F0;--weui-PURPLE-120: #8385F3;--weui-PURPLE-170: #D0D1FA;--weui-PURPLE-80: #5052C0;--weui-PURPLE-90: #595CD7;--weui-PURPLE-BG-100: #6769BA;--weui-PURPLE-BG-110: #7678C1;--weui-PURPLE-BG-130: #9496CE;--weui-PURPLE-BG-90: #5C5EA7;--weui-RED-100: #FA5151;--weui-RED-120: #FB7373;--weui-RED-170: #FDCACA;--weui-RED-80: #C84040;--weui-RED-90: #E14949;--weui-RED-BG-100: #CF5148;--weui-RED-BG-110: #D3625A;--weui-RED-BG-130: #DD847E;--weui-RED-BG-90: #B94840;--weui-SECONDARY-BG: rgba(0, 0, 0, .05);--weui-SEPARATOR-0: rgba(0, 0, 0, .1);--weui-SEPARATOR-1: rgba(0, 0, 0, .15);--weui-STATELAYER-HOVERED: rgba(0, 0, 0, .02);--weui-STATELAYER-PRESSED: rgba(0, 0, 0, .1);--weui-STATELAYER-PRESSEDSTRENGTHENED: rgba(0, 0, 0, .2);--weui-YELLOW-100: #FFC300;--weui-YELLOW-120: #FFCF33;--weui-YELLOW-170: #FFECB2;--weui-YELLOW-80: #CC9C00;--weui-YELLOW-90: #E6AF00;--weui-YELLOW-BG-100: #EFB600;--weui-YELLOW-BG-110: #F0BD19;--weui-YELLOW-BG-130: #F3CC4D;--weui-YELLOW-BG-90: #D7A400;--weui-FG-HALF: rgba(0, 0, 0, .9);--weui-RED: #FA5151;--weui-ORANGERED: #FF6146;--weui-ORANGE: #FA9D3B;--weui-YELLOW: #FFC300;--weui-GREEN: #91D300;--weui-LIGHTGREEN: #95EC69;--weui-TEXTGREEN: #06AE56;--weui-BRAND: #07C160;--weui-BLUE: #10AEFF;--weui-INDIGO: #1485EE;--weui-PURPLE: #6467F0;--weui-LINK: #576B95;--weui-TAG-TEXT-ORANGE: #FA9D3B;--weui-TAG-TEXT-GREEN: #06AE56;--weui-TAG-TEXT-BLUE: #10AEFF;--weui-REDORANGE: #FF6146;--weui-TAG-TEXT-BLACK: rgba(0, 0, 0, .5);--weui-TAG-BACKGROUND-BLACK: rgba(0, 0, 0, .05);--weui-WHITE: #FFFFFF;--weui-BG: #FFFFFF;--weui-FG: #000;--weui-FG-5: rgba(0, 0, 0, .05);--weui-TAG-BACKGROUND-ORANGE: rgba(250, 157, 59, .1);--weui-TAG-BACKGROUND-GREEN: rgba(6, 174, 86, .1);--weui-TAG-TEXT-RED: rgba(250, 81, 81, .6);--weui-TAG-BACKGROUND-RED: rgba(250, 81, 81, .1);--weui-TAG-BACKGROUND-BLUE: rgba(16, 174, 255, .1)}@media (prefers-color-scheme: dark){.wx-root:not([data-weui-theme=light]),body:not([data-weui-theme=light]){--weui-BG-0: #111111;--weui-BG-1: #1E1E1E;--weui-BG-2: #191919;--weui-BG-3: #202020;--weui-BG-4: #404040;--weui-BG-5: #2C2C2C;--weui-BLUE-100: #10AEFF;--weui-BLUE-120: #0C8BCC;--weui-BLUE-170: #04344D;--weui-BLUE-80: #3FBEFF;--weui-BLUE-90: #28B6FF;--weui-BLUE-BG-100: #48A6E2;--weui-BLUE-BG-110: #4095CB;--weui-BLUE-BG-130: #32749E;--weui-BLUE-BG-90: #5AAFE4;--weui-BRAND-100: #07C160;--weui-BRAND-120: #059A4C;--weui-BRAND-170: #023A1C;--weui-BRAND-80: #38CD7F;--weui-BRAND-90: #20C770;--weui-BRAND-BG-100: #2AAE67;--weui-BRAND-BG-110: #259C5C;--weui-BRAND-BG-130: #1D7A48;--weui-BRAND-BG-90: #3EB575;--weui-FG-0: rgba(255, 255, 255, .8);--weui-FG-0_5: rgba(255, 255, 255, .6);--weui-FG-1: rgba(255, 255, 255, .5);--weui-FG-2: rgba(255, 255, 255, .3);--weui-FG-3: rgba(255, 255, 255, .1);--weui-FG-4: rgba(255, 255, 255, .15);--weui-GLYPH-0: rgba(255, 255, 255, .8);--weui-GLYPH-1: rgba(255, 255, 255, .5);--weui-GLYPH-2: rgba(255, 255, 255, .3);--weui-GLYPH-WHITE-0: rgba(255, 255, 255, .8);--weui-GLYPH-WHITE-1: rgba(255, 255, 255, .5);--weui-GLYPH-WHITE-2: rgba(255, 255, 255, .3);--weui-GLYPH-WHITE-3: #FFFFFF;--weui-GREEN-100: #74A800;--weui-GREEN-120: #5C8600;--weui-GREEN-170: #233200;--weui-GREEN-80: #8FB933;--weui-GREEN-90: #82B01A;--weui-GREEN-BG-100: #789833;--weui-GREEN-BG-110: #6B882D;--weui-GREEN-BG-130: #65802B;--weui-GREEN-BG-90: #85A247;--weui-INDIGO-100: #1196FF;--weui-INDIGO-120: #0D78CC;--weui-INDIGO-170: #052D4D;--weui-INDIGO-80: #40ABFF;--weui-INDIGO-90: #28A0FF;--weui-INDIGO-BG-100: #0D78CC;--weui-INDIGO-BG-110: #0B6BB7;--weui-INDIGO-BG-130: #09548F;--weui-INDIGO-BG-90: #2585D1;--weui-LIGHTGREEN-100: #3EB575;--weui-LIGHTGREEN-120: #31905D;--weui-LIGHTGREEN-170: #123522;--weui-LIGHTGREEN-80: #64C390;--weui-LIGHTGREEN-90: #51BC83;--weui-LIGHTGREEN-BG-100: #31905D;--weui-LIGHTGREEN-BG-110: #2C8153;--weui-LIGHTGREEN-BG-130: #226541;--weui-LIGHTGREEN-BG-90: #31905D;--weui-LINK-100: #7D90A9;--weui-LINK-120: #647387;--weui-LINK-170: #252A32;--weui-LINK-80: #97A6BA;--weui-LINK-90: #899AB1;--weui-LINKFINDER-100: #DEE9FF;--weui-MATERIAL-ATTACHMENTCOLUMN: rgba(32, 32, 32, .93);--weui-MATERIAL-NAVIGATIONBAR: rgba(18, 18, 18, .9);--weui-MATERIAL-REGULAR: rgba(37, 37, 37, .6);--weui-MATERIAL-THICK: rgba(34, 34, 34, .9);--weui-MATERIAL-THIN: rgba(95, 95, 95, .4);--weui-MATERIAL-TOOLBAR: rgba(35, 35, 35, .93);--weui-ORANGE-100: #C87D2F;--weui-ORANGE-120: #A06425;--weui-ORANGE-170: #3B250E;--weui-ORANGE-80: #D39758;--weui-ORANGE-90: #CD8943;--weui-ORANGE-BG-100: #BB6000;--weui-ORANGE-BG-110: #A85600;--weui-ORANGE-BG-130: #824300;--weui-ORANGE-BG-90: #C1701A;--weui-ORANGERED-100: #FF6146;--weui-OVERLAY: rgba(0, 0, 0, .8);--weui-OVERLAY-WHITE: rgba(242, 242, 242, .8);--weui-PURPLE-100: #8183FF;--weui-PURPLE-120: #6768CC;--weui-PURPLE-170: #26274C;--weui-PURPLE-80: #9A9BFF;--weui-PURPLE-90: #8D8FFF;--weui-PURPLE-BG-100: #6768CC;--weui-PURPLE-BG-110: #5C5DB7;--weui-PURPLE-BG-130: #48498F;--weui-PURPLE-BG-90: #7677D1;--weui-RED-100: #FA5151;--weui-RED-120: #C84040;--weui-RED-170: #4B1818;--weui-RED-80: #FB7373;--weui-RED-90: #FA6262;--weui-RED-BG-100: #CF5148;--weui-RED-BG-110: #BA4940;--weui-RED-BG-130: #913832;--weui-RED-BG-90: #D3625A;--weui-SECONDARY-BG: rgba(255, 255, 255, .1);--weui-SEPARATOR-0: rgba(255, 255, 255, .05);--weui-SEPARATOR-1: rgba(255, 255, 255, .15);--weui-STATELAYER-HOVERED: rgba(0, 0, 0, .02);--weui-STATELAYER-PRESSED: rgba(255, 255, 255, .1);--weui-STATELAYER-PRESSEDSTRENGTHENED: rgba(255, 255, 255, .2);--weui-YELLOW-100: #CC9C00;--weui-YELLOW-120: #A37C00;--weui-YELLOW-170: #3D2F00;--weui-YELLOW-80: #D6AF33;--weui-YELLOW-90: #D1A519;--weui-YELLOW-BG-100: #BF9100;--weui-YELLOW-BG-110: #AB8200;--weui-YELLOW-BG-130: #866500;--weui-YELLOW-BG-90: #C59C1A;--weui-FG-HALF: rgba(255, 255, 255, .6);--weui-RED: #FA5151;--weui-ORANGERED: #FF6146;--weui-ORANGE: #C87D2F;--weui-YELLOW: #CC9C00;--weui-GREEN: #74A800;--weui-LIGHTGREEN: #3EB575;--weui-TEXTGREEN: #259C5C;--weui-BRAND: #07C160;--weui-BLUE: #10AEFF;--weui-INDIGO: #1196FF;--weui-PURPLE: #8183FF;--weui-LINK: #7D90A9;--weui-REDORANGE: #FF6146;--weui-TAG-TEXT-BLACK: rgba(255, 255, 255, .5);--weui-TAG-BACKGROUND-BLACK: rgba(255, 255, 255, .05);--weui-WHITE: rgba(255, 255, 255, .8);--weui-FG: #fff;--weui-BG: #000;--weui-FG-5: rgba(255, 255, 255, .1);--weui-TAG-BACKGROUND-ORANGE: rgba(250, 157, 59, .1);--weui-TAG-BACKGROUND-GREEN: rgba(6, 174, 86, .1);--weui-TAG-TEXT-RED: rgba(250, 81, 81, .6);--weui-TAG-BACKGROUND-RED: rgba(250, 81, 81, .1);--weui-TAG-BACKGROUND-BLUE: rgba(16, 174, 255, .1);--weui-TAG-TEXT-ORANGE: rgba(250, 157, 59, .6);--weui-TAG-TEXT-GREEN: rgba(6, 174, 86, .6);--weui-TAG-TEXT-BLUE: rgba(16, 174, 255, .6)}}.wx-root[data-weui-theme=dark],body[data-weui-theme=dark]{--weui-BG-0: #111111;--weui-BG-1: #1E1E1E;--weui-BG-2: #191919;--weui-BG-3: #202020;--weui-BG-4: #404040;--weui-BG-5: #2C2C2C;--weui-BLUE-100: #10AEFF;--weui-BLUE-120: #0C8BCC;--weui-BLUE-170: #04344D;--weui-BLUE-80: #3FBEFF;--weui-BLUE-90: #28B6FF;--weui-BLUE-BG-100: #48A6E2;--weui-BLUE-BG-110: #4095CB;--weui-BLUE-BG-130: #32749E;--weui-BLUE-BG-90: #5AAFE4;--weui-BRAND-100: #07C160;--weui-BRAND-120: #059A4C;--weui-BRAND-170: #023A1C;--weui-BRAND-80: #38CD7F;--weui-BRAND-90: #20C770;--weui-BRAND-BG-100: #2AAE67;--weui-BRAND-BG-110: #259C5C;--weui-BRAND-BG-130: #1D7A48;--weui-BRAND-BG-90: #3EB575;--weui-FG-0: rgba(255, 255, 255, .8);--weui-FG-0_5: rgba(255, 255, 255, .6);--weui-FG-1: rgba(255, 255, 255, .5);--weui-FG-2: rgba(255, 255, 255, .3);--weui-FG-3: rgba(255, 255, 255, .1);--weui-FG-4: rgba(255, 255, 255, .15);--weui-GLYPH-0: rgba(255, 255, 255, .8);--weui-GLYPH-1: rgba(255, 255, 255, .5);--weui-GLYPH-2: rgba(255, 255, 255, .3);--weui-GLYPH-WHITE-0: rgba(255, 255, 255, .8);--weui-GLYPH-WHITE-1: rgba(255, 255, 255, .5);--weui-GLYPH-WHITE-2: rgba(255, 255, 255, .3);--weui-GLYPH-WHITE-3: #FFFFFF;--weui-GREEN-100: #74A800;--weui-GREEN-120: #5C8600;--weui-GREEN-170: #233200;--weui-GREEN-80: #8FB933;--weui-GREEN-90: #82B01A;--weui-GREEN-BG-100: #789833;--weui-GREEN-BG-110: #6B882D;--weui-GREEN-BG-130: #65802B;--weui-GREEN-BG-90: #85A247;--weui-INDIGO-100: #1196FF;--weui-INDIGO-120: #0D78CC;--weui-INDIGO-170: #052D4D;--weui-INDIGO-80: #40ABFF;--weui-INDIGO-90: #28A0FF;--weui-INDIGO-BG-100: #0D78CC;--weui-INDIGO-BG-110: #0B6BB7;--weui-INDIGO-BG-130: #09548F;--weui-INDIGO-BG-90: #2585D1;--weui-LIGHTGREEN-100: #3EB575;--weui-LIGHTGREEN-120: #31905D;--weui-LIGHTGREEN-170: #123522;--weui-LIGHTGREEN-80: #64C390;--weui-LIGHTGREEN-90: #51BC83;--weui-LIGHTGREEN-BG-100: #31905D;--weui-LIGHTGREEN-BG-110: #2C8153;--weui-LIGHTGREEN-BG-130: #226541;--weui-LIGHTGREEN-BG-90: #31905D;--weui-LINK-100: #7D90A9;--weui-LINK-120: #647387;--weui-LINK-170: #252A32;--weui-LINK-80: #97A6BA;--weui-LINK-90: #899AB1;--weui-LINKFINDER-100: #DEE9FF;--weui-MATERIAL-ATTACHMENTCOLUMN: rgba(32, 32, 32, .93);--weui-MATERIAL-NAVIGATIONBAR: rgba(18, 18, 18, .9);--weui-MATERIAL-REGULAR: rgba(37, 37, 37, .6);--weui-MATERIAL-THICK: rgba(34, 34, 34, .9);--weui-MATERIAL-THIN: rgba(95, 95, 95, .4);--weui-MATERIAL-TOOLBAR: rgba(35, 35, 35, .93);--weui-ORANGE-100: #C87D2F;--weui-ORANGE-120: #A06425;--weui-ORANGE-170: #3B250E;--weui-ORANGE-80: #D39758;--weui-ORANGE-90: #CD8943;--weui-ORANGE-BG-100: #BB6000;--weui-ORANGE-BG-110: #A85600;--weui-ORANGE-BG-130: #824300;--weui-ORANGE-BG-90: #C1701A;--weui-ORANGERED-100: #FF6146;--weui-OVERLAY: rgba(0, 0, 0, .8);--weui-OVERLAY-WHITE: rgba(242, 242, 242, .8);--weui-PURPLE-100: #8183FF;--weui-PURPLE-120: #6768CC;--weui-PURPLE-170: #26274C;--weui-PURPLE-80: #9A9BFF;--weui-PURPLE-90: #8D8FFF;--weui-PURPLE-BG-100: #6768CC;--weui-PURPLE-BG-110: #5C5DB7;--weui-PURPLE-BG-130: #48498F;--weui-PURPLE-BG-90: #7677D1;--weui-RED-100: #FA5151;--weui-RED-120: #C84040;--weui-RED-170: #4B1818;--weui-RED-80: #FB7373;--weui-RED-90: #FA6262;--weui-RED-BG-100: #CF5148;--weui-RED-BG-110: #BA4940;--weui-RED-BG-130: #913832;--weui-RED-BG-90: #D3625A;--weui-SECONDARY-BG: rgba(255, 255, 255, .1);--weui-SEPARATOR-0: rgba(255, 255, 255, .05);--weui-SEPARATOR-1: rgba(255, 255, 255, .15);--weui-STATELAYER-HOVERED: rgba(0, 0, 0, .02);--weui-STATELAYER-PRESSED: rgba(255, 255, 255, .1);--weui-STATELAYER-PRESSEDSTRENGTHENED: rgba(255, 255, 255, .2);--weui-YELLOW-100: #CC9C00;--weui-YELLOW-120: #A37C00;--weui-YELLOW-170: #3D2F00;--weui-YELLOW-80: #D6AF33;--weui-YELLOW-90: #D1A519;--weui-YELLOW-BG-100: #BF9100;--weui-YELLOW-BG-110: #AB8200;--weui-YELLOW-BG-130: #866500;--weui-YELLOW-BG-90: #C59C1A;--weui-FG-HALF: rgba(255, 255, 255, .6);--weui-RED: #FA5151;--weui-ORANGERED: #FF6146;--weui-ORANGE: #C87D2F;--weui-YELLOW: #CC9C00;--weui-GREEN: #74A800;--weui-LIGHTGREEN: #3EB575;--weui-TEXTGREEN: #259C5C;--weui-BRAND: #07C160;--weui-BLUE: #10AEFF;--weui-INDIGO: #1196FF;--weui-PURPLE: #8183FF;--weui-LINK: #7D90A9;--weui-REDORANGE: #FF6146;--weui-TAG-TEXT-BLACK: rgba(255, 255, 255, .5);--weui-TAG-BACKGROUND-BLACK: rgba(255, 255, 255, .05);--weui-WHITE: rgba(255, 255, 255, .8);--weui-FG: #fff;--weui-BG: #000;--weui-FG-5: rgba(255, 255, 255, .1);--weui-TAG-BACKGROUND-ORANGE: rgba(250, 157, 59, .1);--weui-TAG-BACKGROUND-GREEN: rgba(6, 174, 86, .1);--weui-TAG-TEXT-RED: rgba(250, 81, 81, .6);--weui-TAG-BACKGROUND-RED: rgba(250, 81, 81, .1);--weui-TAG-BACKGROUND-BLUE: rgba(16, 174, 255, .1);--weui-TAG-TEXT-ORANGE: rgba(250, 157, 59, .6);--weui-TAG-TEXT-GREEN: rgba(6, 174, 86, .6);--weui-TAG-TEXT-BLUE: rgba(16, 174, 255, .6)}.wx-root[data-weui-mode=care],body[data-weui-mode=care]{--weui-BG-0: #EDEDED;--weui-BG-1: #F7F7F7;--weui-BG-2: #FFFFFF;--weui-BG-3: #F7F7F7;--weui-BG-4: #4C4C4C;--weui-BG-5: #FFFFFF;--weui-BLUE-100: #007DBB;--weui-BLUE-120: #3FBEFF;--weui-BLUE-170: #B7E6FF;--weui-BLUE-80: #0C8BCC;--weui-BLUE-90: #0E9CE6;--weui-BLUE-BG-100: #48A6E2;--weui-BLUE-BG-110: #5AAFE4;--weui-BLUE-BG-130: #7FC0EA;--weui-BLUE-BG-90: #4095CB;--weui-BRAND-100: #018942;--weui-BRAND-120: #38CD7F;--weui-BRAND-170: #B4ECCE;--weui-BRAND-80: #059A4C;--weui-BRAND-90: #06AE56;--weui-BRAND-BG-100: #2AAE67;--weui-BRAND-BG-110: #3EB575;--weui-BRAND-BG-130: #69C694;--weui-BRAND-BG-90: #259C5C;--weui-FG-0: #000000;--weui-FG-0_5: #000000;--weui-FG-1: rgba(0, 0, 0, .6);--weui-FG-2: rgba(0, 0, 0, .42);--weui-FG-3: rgba(0, 0, 0, .1);--weui-FG-4: rgba(0, 0, 0, .15);--weui-GLYPH-0: #000000;--weui-GLYPH-1: rgba(0, 0, 0, .6);--weui-GLYPH-2: rgba(0, 0, 0, .42);--weui-GLYPH-WHITE-0: rgba(255, 255, 255, .85);--weui-GLYPH-WHITE-1: rgba(255, 255, 255, .55);--weui-GLYPH-WHITE-2: rgba(255, 255, 255, .35);--weui-GLYPH-WHITE-3: #FFFFFF;--weui-GREEN-100: #4F8400;--weui-GREEN-120: #A7DB33;--weui-GREEN-170: #DEF1B3;--weui-GREEN-80: #74A800;--weui-GREEN-90: #82BD00;--weui-GREEN-BG-100: #96BE40;--weui-GREEN-BG-110: #A0C452;--weui-GREEN-BG-130: #B5D179;--weui-GREEN-BG-90: #86AA39;--weui-INDIGO-100: #0075E2;--weui-INDIGO-120: #439DF1;--weui-INDIGO-170: #B8DAF9;--weui-INDIGO-80: #106ABE;--weui-INDIGO-90: #1277D6;--weui-INDIGO-BG-100: #2B77BF;--weui-INDIGO-BG-110: #3F84C5;--weui-INDIGO-BG-130: #6BA0D2;--weui-INDIGO-BG-90: #266AAB;--weui-LIGHTGREEN-100: #2E8800;--weui-LIGHTGREEN-120: #AAEF87;--weui-LIGHTGREEN-170: #DEF9D1;--weui-LIGHTGREEN-80: #77BC54;--weui-LIGHTGREEN-90: #85D35E;--weui-LIGHTGREEN-BG-100: #72CF60;--weui-LIGHTGREEN-BG-110: #80D370;--weui-LIGHTGREEN-BG-130: #9CDD90;--weui-LIGHTGREEN-BG-90: #66B956;--weui-LINK-100: #576B95;--weui-LINK-120: #7888AA;--weui-LINK-170: #CCD2DE;--weui-LINK-80: #455577;--weui-LINK-90: #4E6085;--weui-LINKFINDER-100: #002666;--weui-MATERIAL-ATTACHMENTCOLUMN: rgba(245, 245, 245, .95);--weui-MATERIAL-NAVIGATIONBAR: rgba(237, 237, 237, .94);--weui-MATERIAL-REGULAR: rgba(247, 247, 247, .3);--weui-MATERIAL-THICK: rgba(247, 247, 247, .8);--weui-MATERIAL-THIN: rgba(255, 255, 255, .2);--weui-MATERIAL-TOOLBAR: rgba(246, 246, 246, .82);--weui-ORANGE-100: #E17719;--weui-ORANGE-120: #FBB062;--weui-ORANGE-170: #FDE1C3;--weui-ORANGE-80: #C87D2F;--weui-ORANGE-90: #E08C34;--weui-ORANGE-BG-100: #EA7800;--weui-ORANGE-BG-110: #EC8519;--weui-ORANGE-BG-130: #F0A04D;--weui-ORANGE-BG-90: #D26B00;--weui-ORANGERED-100: #D14730;--weui-OVERLAY: rgba(0, 0, 0, .5);--weui-OVERLAY-WHITE: rgba(242, 242, 242, .8);--weui-PURPLE-100: #6265F1;--weui-PURPLE-120: #8385F3;--weui-PURPLE-170: #D0D1FA;--weui-PURPLE-80: #5052C0;--weui-PURPLE-90: #595CD7;--weui-PURPLE-BG-100: #6769BA;--weui-PURPLE-BG-110: #7678C1;--weui-PURPLE-BG-130: #9496CE;--weui-PURPLE-BG-90: #5C5EA7;--weui-RED-100: #DC3636;--weui-RED-120: #FB7373;--weui-RED-170: #FDCACA;--weui-RED-80: #C84040;--weui-RED-90: #E14949;--weui-RED-BG-100: #CF5148;--weui-RED-BG-110: #D3625A;--weui-RED-BG-130: #DD847E;--weui-RED-BG-90: #B94840;--weui-SECONDARY-BG: rgba(0, 0, 0, .1);--weui-SEPARATOR-0: rgba(0, 0, 0, .1);--weui-SEPARATOR-1: rgba(0, 0, 0, .15);--weui-STATELAYER-HOVERED: rgba(0, 0, 0, .02);--weui-STATELAYER-PRESSED: rgba(0, 0, 0, .1);--weui-STATELAYER-PRESSEDSTRENGTHENED: rgba(0, 0, 0, .2);--weui-YELLOW-100: #BB8E00;--weui-YELLOW-120: #FFCF33;--weui-YELLOW-170: #FFECB2;--weui-YELLOW-80: #CC9C00;--weui-YELLOW-90: #E6AF00;--weui-YELLOW-BG-100: #EFB600;--weui-YELLOW-BG-110: #F0BD19;--weui-YELLOW-BG-130: #F3CC4D;--weui-YELLOW-BG-90: #D7A400;--weui-FG-HALF: #000000;--weui-RED: #DC3636;--weui-ORANGERED: #D14730;--weui-ORANGE: #E17719;--weui-YELLOW: #BB8E00;--weui-GREEN: #4F8400;--weui-LIGHTGREEN: #2E8800;--weui-TEXTGREEN: #06AE56;--weui-BRAND: #018942;--weui-BLUE: #007DBB;--weui-INDIGO: #0075E2;--weui-PURPLE: #6265F1;--weui-LINK: #576B95;--weui-TAG-TEXT-ORANGE: #E17719;--weui-TAG-TEXT-GREEN: #06AE56;--weui-TAG-TEXT-BLUE: #007DBB;--weui-REDORANGE: #D14730;--weui-TAG-TEXT-BLACK: rgba(0, 0, 0, .5);--weui-WHITE: #FFFFFF;--weui-BG: #FFFFFF;--weui-FG: #000;--weui-FG-5: rgba(0, 0, 0, .05);--weui-TAG-BACKGROUND-ORANGE: rgba(225, 119, 25, .1);--weui-TAG-BACKGROUND-GREEN: rgba(6, 174, 86, .1);--weui-TAG-TEXT-RED: rgba(250, 81, 81, .6);--weui-TAG-BACKGROUND-RED: rgba(250, 81, 81, .1);--weui-TAG-BACKGROUND-BLUE: rgba(0, 125, 187, .1);--weui-TAG-BACKGROUND-BLACK: rgba(0, 0, 0, .05)}@media (prefers-color-scheme: dark){.wx-root[data-weui-mode=care]:not([data-weui-theme=light]),body[data-weui-mode=care]:not([data-weui-theme=light]){--weui-BG-0: #111111;--weui-BG-1: #1E1E1E;--weui-BG-2: #191919;--weui-BG-3: #202020;--weui-BG-4: #404040;--weui-BG-5: #2C2C2C;--weui-BLUE-100: #10AEFF;--weui-BLUE-120: #0C8BCC;--weui-BLUE-170: #04344D;--weui-BLUE-80: #3FBEFF;--weui-BLUE-90: #28B6FF;--weui-BLUE-BG-100: #48A6E2;--weui-BLUE-BG-110: #4095CB;--weui-BLUE-BG-130: #32749E;--weui-BLUE-BG-90: #5AAFE4;--weui-BRAND-100: #07C160;--weui-BRAND-120: #059A4C;--weui-BRAND-170: #023A1C;--weui-BRAND-80: #38CD7F;--weui-BRAND-90: #20C770;--weui-BRAND-BG-100: #2AAE67;--weui-BRAND-BG-110: #259C5C;--weui-BRAND-BG-130: #1D7A48;--weui-BRAND-BG-90: #3EB575;--weui-FG-0: rgba(255, 255, 255, .85);--weui-FG-0_5: rgba(255, 255, 255, .65);--weui-FG-1: rgba(255, 255, 255, .55);--weui-FG-2: rgba(255, 255, 255, .35);--weui-FG-3: rgba(255, 255, 255, .1);--weui-FG-4: rgba(255, 255, 255, .15);--weui-GLYPH-0: rgba(255, 255, 255, .85);--weui-GLYPH-1: rgba(255, 255, 255, .55);--weui-GLYPH-2: rgba(255, 255, 255, .35);--weui-GLYPH-WHITE-0: rgba(255, 255, 255, .85);--weui-GLYPH-WHITE-1: rgba(255, 255, 255, .55);--weui-GLYPH-WHITE-2: rgba(255, 255, 255, .35);--weui-GLYPH-WHITE-3: #FFFFFF;--weui-GREEN-100: #74A800;--weui-GREEN-120: #5C8600;--weui-GREEN-170: #233200;--weui-GREEN-80: #8FB933;--weui-GREEN-90: #82B01A;--weui-GREEN-BG-100: #789833;--weui-GREEN-BG-110: #6B882D;--weui-GREEN-BG-130: #65802B;--weui-GREEN-BG-90: #85A247;--weui-INDIGO-100: #1196FF;--weui-INDIGO-120: #0D78CC;--weui-INDIGO-170: #052D4D;--weui-INDIGO-80: #40ABFF;--weui-INDIGO-90: #28A0FF;--weui-INDIGO-BG-100: #0D78CC;--weui-INDIGO-BG-110: #0B6BB7;--weui-INDIGO-BG-130: #09548F;--weui-INDIGO-BG-90: #2585D1;--weui-LIGHTGREEN-100: #3EB575;--weui-LIGHTGREEN-120: #31905D;--weui-LIGHTGREEN-170: #123522;--weui-LIGHTGREEN-80: #64C390;--weui-LIGHTGREEN-90: #51BC83;--weui-LIGHTGREEN-BG-100: #31905D;--weui-LIGHTGREEN-BG-110: #2C8153;--weui-LIGHTGREEN-BG-130: #226541;--weui-LIGHTGREEN-BG-90: #31905D;--weui-LINK-100: #7D90A9;--weui-LINK-120: #647387;--weui-LINK-170: #252A32;--weui-LINK-80: #97A6BA;--weui-LINK-90: #899AB1;--weui-LINKFINDER-100: #DEE9FF;--weui-MATERIAL-ATTACHMENTCOLUMN: rgba(32, 32, 32, .93);--weui-MATERIAL-NAVIGATIONBAR: rgba(18, 18, 18, .9);--weui-MATERIAL-REGULAR: rgba(37, 37, 37, .6);--weui-MATERIAL-THICK: rgba(34, 34, 34, .9);--weui-MATERIAL-THIN: rgba(245, 245, 245, .4);--weui-MATERIAL-TOOLBAR: rgba(35, 35, 35, .93);--weui-ORANGE-100: #C87D2F;--weui-ORANGE-120: #A06425;--weui-ORANGE-170: #3B250E;--weui-ORANGE-80: #D39758;--weui-ORANGE-90: #CD8943;--weui-ORANGE-BG-100: #BB6000;--weui-ORANGE-BG-110: #A85600;--weui-ORANGE-BG-130: #824300;--weui-ORANGE-BG-90: #C1701A;--weui-ORANGERED-100: #FF6146;--weui-OVERLAY: rgba(0, 0, 0, .8);--weui-OVERLAY-WHITE: rgba(242, 242, 242, .8);--weui-PURPLE-100: #8183FF;--weui-PURPLE-120: #6768CC;--weui-PURPLE-170: #26274C;--weui-PURPLE-80: #9A9BFF;--weui-PURPLE-90: #8D8FFF;--weui-PURPLE-BG-100: #6768CC;--weui-PURPLE-BG-110: #5C5DB7;--weui-PURPLE-BG-130: #48498F;--weui-PURPLE-BG-90: #7677D1;--weui-RED-100: #FA5151;--weui-RED-120: #C84040;--weui-RED-170: #4B1818;--weui-RED-80: #FB7373;--weui-RED-90: #FA6262;--weui-RED-BG-100: #CF5148;--weui-RED-BG-110: #BA4940;--weui-RED-BG-130: #913832;--weui-RED-BG-90: #D3625A;--weui-SECONDARY-BG: rgba(255, 255, 255, .15);--weui-SEPARATOR-0: rgba(255, 255, 255, .05);--weui-SEPARATOR-1: rgba(255, 255, 255, .15);--weui-STATELAYER-HOVERED: rgba(0, 0, 0, .02);--weui-STATELAYER-PRESSED: rgba(255, 255, 255, .1);--weui-STATELAYER-PRESSEDSTRENGTHENED: rgba(255, 255, 255, .2);--weui-YELLOW-100: #CC9C00;--weui-YELLOW-120: #A37C00;--weui-YELLOW-170: #3D2F00;--weui-YELLOW-80: #D6AF33;--weui-YELLOW-90: #D1A519;--weui-YELLOW-BG-100: #BF9100;--weui-YELLOW-BG-110: #AB8200;--weui-YELLOW-BG-130: #866500;--weui-YELLOW-BG-90: #C59C1A;--weui-FG-HALF: rgba(255, 255, 255, .65);--weui-RED: #FA5151;--weui-ORANGERED: #FF6146;--weui-ORANGE: #C87D2F;--weui-YELLOW: #CC9C00;--weui-GREEN: #74A800;--weui-LIGHTGREEN: #3EB575;--weui-TEXTGREEN: #259C5C;--weui-BRAND: #07C160;--weui-BLUE: #10AEFF;--weui-INDIGO: #1196FF;--weui-PURPLE: #8183FF;--weui-LINK: #7D90A9;--weui-REDORANGE: #FF6146;--weui-TAG-BACKGROUND-BLACK: rgba(255, 255, 255, .05);--weui-FG: #fff;--weui-WHITE: rgba(255, 255, 255, .8);--weui-FG-5: rgba(255, 255, 255, .1);--weui-TAG-BACKGROUND-ORANGE: rgba(250, 157, 59, .1);--weui-TAG-BACKGROUND-GREEN: rgba(6, 174, 86, .1);--weui-TAG-TEXT-RED: rgba(250, 81, 81, .6);--weui-TAG-BACKGROUND-RED: rgba(250, 81, 81, .1);--weui-TAG-BACKGROUND-BLUE: rgba(16, 174, 255, .1);--weui-TAG-TEXT-ORANGE: rgba(250, 157, 59, .6);--weui-BG: #000;--weui-TAG-TEXT-GREEN: rgba(6, 174, 86, .6);--weui-TAG-TEXT-BLUE: rgba(16, 174, 255, .6);--weui-TAG-TEXT-BLACK: rgba(255, 255, 255, .5)}}.wx-root[data-weui-mode=care][data-weui-theme=dark],body[data-weui-mode=care][data-weui-theme=dark]{--weui-BG-0: #111111;--weui-BG-1: #1E1E1E;--weui-BG-2: #191919;--weui-BG-3: #202020;--weui-BG-4: #404040;--weui-BG-5: #2C2C2C;--weui-BLUE-100: #10AEFF;--weui-BLUE-120: #0C8BCC;--weui-BLUE-170: #04344D;--weui-BLUE-80: #3FBEFF;--weui-BLUE-90: #28B6FF;--weui-BLUE-BG-100: #48A6E2;--weui-BLUE-BG-110: #4095CB;--weui-BLUE-BG-130: #32749E;--weui-BLUE-BG-90: #5AAFE4;--weui-BRAND-100: #07C160;--weui-BRAND-120: #059A4C;--weui-BRAND-170: #023A1C;--weui-BRAND-80: #38CD7F;--weui-BRAND-90: #20C770;--weui-BRAND-BG-100: #2AAE67;--weui-BRAND-BG-110: #259C5C;--weui-BRAND-BG-130: #1D7A48;--weui-BRAND-BG-90: #3EB575;--weui-FG-0: rgba(255, 255, 255, .85);--weui-FG-0_5: rgba(255, 255, 255, .65);--weui-FG-1: rgba(255, 255, 255, .55);--weui-FG-2: rgba(255, 255, 255, .35);--weui-FG-3: rgba(255, 255, 255, .1);--weui-FG-4: rgba(255, 255, 255, .15);--weui-GLYPH-0: rgba(255, 255, 255, .85);--weui-GLYPH-1: rgba(255, 255, 255, .55);--weui-GLYPH-2: rgba(255, 255, 255, .35);--weui-GLYPH-WHITE-0: rgba(255, 255, 255, .85);--weui-GLYPH-WHITE-1: rgba(255, 255, 255, .55);--weui-GLYPH-WHITE-2: rgba(255, 255, 255, .35);--weui-GLYPH-WHITE-3: #FFFFFF;--weui-GREEN-100: #74A800;--weui-GREEN-120: #5C8600;--weui-GREEN-170: #233200;--weui-GREEN-80: #8FB933;--weui-GREEN-90: #82B01A;--weui-GREEN-BG-100: #789833;--weui-GREEN-BG-110: #6B882D;--weui-GREEN-BG-130: #65802B;--weui-GREEN-BG-90: #85A247;--weui-INDIGO-100: #1196FF;--weui-INDIGO-120: #0D78CC;--weui-INDIGO-170: #052D4D;--weui-INDIGO-80: #40ABFF;--weui-INDIGO-90: #28A0FF;--weui-INDIGO-BG-100: #0D78CC;--weui-INDIGO-BG-110: #0B6BB7;--weui-INDIGO-BG-130: #09548F;--weui-INDIGO-BG-90: #2585D1;--weui-LIGHTGREEN-100: #3EB575;--weui-LIGHTGREEN-120: #31905D;--weui-LIGHTGREEN-170: #123522;--weui-LIGHTGREEN-80: #64C390;--weui-LIGHTGREEN-90: #51BC83;--weui-LIGHTGREEN-BG-100: #31905D;--weui-LIGHTGREEN-BG-110: #2C8153;--weui-LIGHTGREEN-BG-130: #226541;--weui-LIGHTGREEN-BG-90: #31905D;--weui-LINK-100: #7D90A9;--weui-LINK-120: #647387;--weui-LINK-170: #252A32;--weui-LINK-80: #97A6BA;--weui-LINK-90: #899AB1;--weui-LINKFINDER-100: #DEE9FF;--weui-MATERIAL-ATTACHMENTCOLUMN: rgba(32, 32, 32, .93);--weui-MATERIAL-NAVIGATIONBAR: rgba(18, 18, 18, .9);--weui-MATERIAL-REGULAR: rgba(37, 37, 37, .6);--weui-MATERIAL-THICK: rgba(34, 34, 34, .9);--weui-MATERIAL-THIN: rgba(245, 245, 245, .4);--weui-MATERIAL-TOOLBAR: rgba(35, 35, 35, .93);--weui-ORANGE-100: #C87D2F;--weui-ORANGE-120: #A06425;--weui-ORANGE-170: #3B250E;--weui-ORANGE-80: #D39758;--weui-ORANGE-90: #CD8943;--weui-ORANGE-BG-100: #BB6000;--weui-ORANGE-BG-110: #A85600;--weui-ORANGE-BG-130: #824300;--weui-ORANGE-BG-90: #C1701A;--weui-ORANGERED-100: #FF6146;--weui-OVERLAY: rgba(0, 0, 0, .8);--weui-OVERLAY-WHITE: rgba(242, 242, 242, .8);--weui-PURPLE-100: #8183FF;--weui-PURPLE-120: #6768CC;--weui-PURPLE-170: #26274C;--weui-PURPLE-80: #9A9BFF;--weui-PURPLE-90: #8D8FFF;--weui-PURPLE-BG-100: #6768CC;--weui-PURPLE-BG-110: #5C5DB7;--weui-PURPLE-BG-130: #48498F;--weui-PURPLE-BG-90: #7677D1;--weui-RED-100: #FA5151;--weui-RED-120: #C84040;--weui-RED-170: #4B1818;--weui-RED-80: #FB7373;--weui-RED-90: #FA6262;--weui-RED-BG-100: #CF5148;--weui-RED-BG-110: #BA4940;--weui-RED-BG-130: #913832;--weui-RED-BG-90: #D3625A;--weui-SECONDARY-BG: rgba(255, 255, 255, .15);--weui-SEPARATOR-0: rgba(255, 255, 255, .05);--weui-SEPARATOR-1: rgba(255, 255, 255, .15);--weui-STATELAYER-HOVERED: rgba(0, 0, 0, .02);--weui-STATELAYER-PRESSED: rgba(255, 255, 255, .1);--weui-STATELAYER-PRESSEDSTRENGTHENED: rgba(255, 255, 255, .2);--weui-YELLOW-100: #CC9C00;--weui-YELLOW-120: #A37C00;--weui-YELLOW-170: #3D2F00;--weui-YELLOW-80: #D6AF33;--weui-YELLOW-90: #D1A519;--weui-YELLOW-BG-100: #BF9100;--weui-YELLOW-BG-110: #AB8200;--weui-YELLOW-BG-130: #866500;--weui-YELLOW-BG-90: #C59C1A;--weui-FG-HALF: rgba(255, 255, 255, .65);--weui-RED: #FA5151;--weui-ORANGERED: #FF6146;--weui-ORANGE: #C87D2F;--weui-YELLOW: #CC9C00;--weui-GREEN: #74A800;--weui-LIGHTGREEN: #3EB575;--weui-TEXTGREEN: #259C5C;--weui-BRAND: #07C160;--weui-BLUE: #10AEFF;--weui-INDIGO: #1196FF;--weui-PURPLE: #8183FF;--weui-LINK: #7D90A9;--weui-REDORANGE: #FF6146;--weui-TAG-BACKGROUND-BLACK: rgba(255, 255, 255, .05);--weui-FG: #fff;--weui-WHITE: rgba(255, 255, 255, .8);--weui-FG-5: rgba(255, 255, 255, .1);--weui-TAG-BACKGROUND-ORANGE: rgba(250, 157, 59, .1);--weui-TAG-BACKGROUND-GREEN: rgba(6, 174, 86, .1);--weui-TAG-TEXT-RED: rgba(250, 81, 81, .6);--weui-TAG-BACKGROUND-RED: rgba(250, 81, 81, .1);--weui-TAG-BACKGROUND-BLUE: rgba(16, 174, 255, .1);--weui-TAG-TEXT-ORANGE: rgba(250, 157, 59, .6);--weui-BG: #000;--weui-TAG-TEXT-GREEN: rgba(6, 174, 86, .6);--weui-TAG-TEXT-BLUE: rgba(16, 174, 255, .6);--weui-TAG-TEXT-BLACK: rgba(255, 255, 255, .5)}.wx_hover_card:before{content:" ";position:absolute;top:0;left:0;right:0;bottom:0;border-radius:8px;box-sizing:border-box;border:1px solid rgba(7,193,96,.3);pointer-events:none;z-index:9}.wx_selected_card:before{content:" ";position:absolute;top:0;left:0;right:0;bottom:0;border-radius:8px;border:1.5px solid #07C160;box-sizing:border-box;background:rgba(7,193,96,.1);pointer-events:none;z-index:9}.product_card_text_wrp{display:inline;-webkit-user-select:none;-moz-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;font-family:PingFang SC}.iframe_wrp{display:flex;flex-direction:column;-webkit-user-select:none;-moz-user-select:none;user-select:none;align-items:center;position:relative}.iframe_style{height:0px}.product_wx_img_placeholder{width:100%;background:var(--weui-BG-3) url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='UTF-8'%3F%3E%3Csvg width='80px' height='80px' viewBox='0 0 80 80' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Ctitle%3E9.元素/加载/Black%3C/title%3E%3Cdefs%3E%3ClinearGradient x1='94.0869141%25' y1='0%25' x2='94.0869141%25' y2='90.559082%25' id='linearGradient-1'%3E%3Cstop stop-color='%23606060' stop-opacity='0' offset='0%25'%3E%3C/stop%3E%3Cstop stop-color='%23606060' stop-opacity='0.3' offset='100%25'%3E%3C/stop%3E%3C/linearGradient%3E%3ClinearGradient x1='100%25' y1='8.67370605%25' x2='100%25' y2='90.6286621%25' id='linearGradient-2'%3E%3Cstop stop-color='%23606060' offset='0%25'%3E%3C/stop%3E%3Cstop stop-color='%23606060' stop-opacity='0.3' offset='100%25'%3E%3C/stop%3E%3C/linearGradient%3E%3C/defs%3E%3Cg id='页面-1' stroke='none' stroke-width='1' fill='none' fill-rule='evenodd' opacity='0.9'%3E%3Cg id='LoadingDefault'%3E%3Cpath d='M40,0 C62.09139,0 80,17.90861 80,40 C80,62.09139 62.09139,80 40,80 L40,73 C58.2253967,73 73,58.2253967 73,40 C73,21.7746033 58.2253967,7 40,7 L40,0 Z' id='路径' fill='url(%23linearGradient-1)'%3E%3C/path%3E%3Cpath d='M40,0 L40,7 C21.7746033,7 7,21.7746033 7,40 C7,58.2253967 21.7746033,73 40,73 L40,80 C17.90861,80 0,62.09139 0,40 C0,17.90861 17.90861,0 40,0 Z' id='路径' fill='url(%23linearGradient-2)'%3E%3C/path%3E%3Ccircle id='Oval' fill='%23606060' cx='40.5' cy='3.5' r='3.5'%3E%3C/circle%3E%3C/g%3E%3CanimateTransform attributeName='transform' begin='0s' dur='1s' type='rotate' values='0 40 40;360 40 40' repeatCount='indefinite'/%3E%3C/g%3E%3C/svg%3E%0A") no-repeat 50% 50%!important;background-size:16px!important;border-radius:8px}:root{--weui-FG-6: rgba(0, 0, 0, .05)}@media (prefers-color-scheme: dark){:root{--weui-FG-6: rgba(255, 255, 255, .05)}}.product_text_link{text-decoration:none;padding:2px 4px;color:var(--weui-LINK);cursor:default;-webkit-user-drag:none;border-radius:4px}.product_text_link:before{content:"";display:inline-block;mask-image:url("data:image/svg+xml,%3Csvg width='25' height='25' viewBox='0 0 25 25' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M5.798 13.728c-.32 0-.636-.032-.942-.096-1.792-.378-3.042-1.754-3.042-3.348 0-.426.088-.84.262-1.232l.008-.02 2.008-4.498a3.696 3.696 0 0 1 3.372-2.186h9.8A3.697 3.697 0 0 1 20.662 4.6l1.984 4.432c.178.402.268.82.268 1.248 0 1.596-1.252 2.974-3.044 3.348a4.63 4.63 0 0 1-2.176-.074c-.816-.23-1.514-.68-2.002-1.268-.798.846-2.018 1.368-3.326 1.368-1.308 0-2.52-.52-3.322-1.364-.488.59-1.188 1.042-2.014 1.274-.394.11-.808.168-1.23.168l-.002-.004zM3.46 9.632l-.01.022c-.09.2-.136.412-.136.63 0 .878.762 1.65 1.85 1.88.47.098.994.082 1.458-.048.766-.214 1.368-.728 1.576-1.34a1.43 1.43 0 0 0 .046-.158.748.748 0 1 1 1.448-.056l.026.07.012.03c.392.892 1.448 1.49 2.634 1.49s2.25-.602 2.636-1.498c.02-.046.034-.082.046-.12a.744.744 0 0 1 .754-.502.75.75 0 0 1 .688.588c.012.056.026.108.042.152.214.62.802 1.118 1.572 1.334.466.132.99.148 1.46.048 1.092-.228 1.852-1.002 1.852-1.88 0-.216-.046-.43-.138-.636l-1.988-4.44-.008-.018-.018-.036a2.19 2.19 0 0 0-1.998-1.296h-9.8c-.864 0-1.648.51-2 1.298-.008.016-.014.032-.022.046L3.46 9.634v-.002zM12.364 21.642c-4.142 0-7.566-2.634-7.794-5.996a.75.75 0 1 1 1.498-.102c.174 2.578 2.94 4.598 6.298 4.598s6.122-2.02 6.296-4.598a.75.75 0 1 1 1.498.102c-.228 3.362-3.652 5.996-7.794 5.996h-.002z' fill='%23576B95'/%3E%3C/svg%3E");-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='25' height='25' viewBox='0 0 25 25' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M5.798 13.728c-.32 0-.636-.032-.942-.096-1.792-.378-3.042-1.754-3.042-3.348 0-.426.088-.84.262-1.232l.008-.02 2.008-4.498a3.696 3.696 0 0 1 3.372-2.186h9.8A3.697 3.697 0 0 1 20.662 4.6l1.984 4.432c.178.402.268.82.268 1.248 0 1.596-1.252 2.974-3.044 3.348a4.63 4.63 0 0 1-2.176-.074c-.816-.23-1.514-.68-2.002-1.268-.798.846-2.018 1.368-3.326 1.368-1.308 0-2.52-.52-3.322-1.364-.488.59-1.188 1.042-2.014 1.274-.394.11-.808.168-1.23.168l-.002-.004zM3.46 9.632l-.01.022c-.09.2-.136.412-.136.63 0 .878.762 1.65 1.85 1.88.47.098.994.082 1.458-.048.766-.214 1.368-.728 1.576-1.34a1.43 1.43 0 0 0 .046-.158.748.748 0 1 1 1.448-.056l.026.07.012.03c.392.892 1.448 1.49 2.634 1.49s2.25-.602 2.636-1.498c.02-.046.034-.082.046-.12a.744.744 0 0 1 .754-.502.75.75 0 0 1 .688.588c.012.056.026.108.042.152.214.62.802 1.118 1.572 1.334.466.132.99.148 1.46.048 1.092-.228 1.852-1.002 1.852-1.88 0-.216-.046-.43-.138-.636l-1.988-4.44-.008-.018-.018-.036a2.19 2.19 0 0 0-1.998-1.296h-9.8c-.864 0-1.648.51-2 1.298-.008.016-.014.032-.022.046L3.46 9.634v-.002zM12.364 21.642c-4.142 0-7.566-2.634-7.794-5.996a.75.75 0 1 1 1.498-.102c.174 2.578 2.94 4.598 6.298 4.598s6.122-2.02 6.296-4.598a.75.75 0 1 1 1.498.102c-.228 3.362-3.652 5.996-7.794 5.996h-.002z' fill='%23576B95'/%3E%3C/svg%3E");background-color:currentColor;-webkit-mask-size:contain;mask-size:contain;vertical-align:middle;height:1.1em;width:1.1em;margin-right:2px;margin-top:-.16em}.product-logo{height:1.1em;width:1.1em;display:inline-block;mask-image:url("data:image/svg+xml,%3Csvg width='25' height='25' viewBox='0 0 25 25' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M5.798 13.728c-.32 0-.636-.032-.942-.096-1.792-.378-3.042-1.754-3.042-3.348 0-.426.088-.84.262-1.232l.008-.02 2.008-4.498a3.696 3.696 0 0 1 3.372-2.186h9.8A3.697 3.697 0 0 1 20.662 4.6l1.984 4.432c.178.402.268.82.268 1.248 0 1.596-1.252 2.974-3.044 3.348a4.63 4.63 0 0 1-2.176-.074c-.816-.23-1.514-.68-2.002-1.268-.798.846-2.018 1.368-3.326 1.368-1.308 0-2.52-.52-3.322-1.364-.488.59-1.188 1.042-2.014 1.274-.394.11-.808.168-1.23.168l-.002-.004zM3.46 9.632l-.01.022c-.09.2-.136.412-.136.63 0 .878.762 1.65 1.85 1.88.47.098.994.082 1.458-.048.766-.214 1.368-.728 1.576-1.34a1.43 1.43 0 0 0 .046-.158.748.748 0 1 1 1.448-.056l.026.07.012.03c.392.892 1.448 1.49 2.634 1.49s2.25-.602 2.636-1.498c.02-.046.034-.082.046-.12a.744.744 0 0 1 .754-.502.75.75 0 0 1 .688.588c.012.056.026.108.042.152.214.62.802 1.118 1.572 1.334.466.132.99.148 1.46.048 1.092-.228 1.852-1.002 1.852-1.88 0-.216-.046-.43-.138-.636l-1.988-4.44-.008-.018-.018-.036a2.19 2.19 0 0 0-1.998-1.296h-9.8c-.864 0-1.648.51-2 1.298-.008.016-.014.032-.022.046L3.46 9.634v-.002zM12.364 21.642c-4.142 0-7.566-2.634-7.794-5.996a.75.75 0 1 1 1.498-.102c.174 2.578 2.94 4.598 6.298 4.598s6.122-2.02 6.296-4.598a.75.75 0 1 1 1.498.102c-.228 3.362-3.652 5.996-7.794 5.996h-.002z' fill='%23576B95'/%3E%3C/svg%3E");-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='25' height='25' viewBox='0 0 25 25' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M5.798 13.728c-.32 0-.636-.032-.942-.096-1.792-.378-3.042-1.754-3.042-3.348 0-.426.088-.84.262-1.232l.008-.02 2.008-4.498a3.696 3.696 0 0 1 3.372-2.186h9.8A3.697 3.697 0 0 1 20.662 4.6l1.984 4.432c.178.402.268.82.268 1.248 0 1.596-1.252 2.974-3.044 3.348a4.63 4.63 0 0 1-2.176-.074c-.816-.23-1.514-.68-2.002-1.268-.798.846-2.018 1.368-3.326 1.368-1.308 0-2.52-.52-3.322-1.364-.488.59-1.188 1.042-2.014 1.274-.394.11-.808.168-1.23.168l-.002-.004zM3.46 9.632l-.01.022c-.09.2-.136.412-.136.63 0 .878.762 1.65 1.85 1.88.47.098.994.082 1.458-.048.766-.214 1.368-.728 1.576-1.34a1.43 1.43 0 0 0 .046-.158.748.748 0 1 1 1.448-.056l.026.07.012.03c.392.892 1.448 1.49 2.634 1.49s2.25-.602 2.636-1.498c.02-.046.034-.082.046-.12a.744.744 0 0 1 .754-.502.75.75 0 0 1 .688.588c.012.056.026.108.042.152.214.62.802 1.118 1.572 1.334.466.132.99.148 1.46.048 1.092-.228 1.852-1.002 1.852-1.88 0-.216-.046-.43-.138-.636l-1.988-4.44-.008-.018-.018-.036a2.19 2.19 0 0 0-1.998-1.296h-9.8c-.864 0-1.648.51-2 1.298-.008.016-.014.032-.022.046L3.46 9.634v-.002zM12.364 21.642c-4.142 0-7.566-2.634-7.794-5.996a.75.75 0 1 1 1.498-.102c.174 2.578 2.94 4.598 6.298 4.598s6.122-2.02 6.296-4.598a.75.75 0 1 1 1.498.102c-.228 3.362-3.652 5.996-7.794 5.996h-.002z' fill='%23576B95'/%3E%3C/svg%3E");background-color:currentColor;-webkit-mask-size:contain;mask-size:contain}.shop-verify-icon{height:1em;width:1em;display:inline-block;background-image:url("data:image/svg+xml,%3Csvg width='12' height='13' viewBox='0 0 12 13' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M8.913 3.789l-.718-1.732a.352.352 0 0 0-.46-.19l-1.732.717-1.731-.718a.352.352 0 0 0-.46.191l-.718 1.732-1.732.717a.352.352 0 0 0-.19.46l.717 1.732-.717 1.732c-.074.18.01.386.19.46l1.732.717.718 1.732c.074.18.28.265.46.19l1.731-.717 1.732.718c.18.074.386-.011.46-.19l.718-1.733 1.732-.717a.352.352 0 0 0 .19-.46l-.717-1.732.717-1.732a.352.352 0 0 0-.19-.46L8.913 3.79z' fill='%23E0B584'/%3E%3Cpath d='M7.082 8.904l-1.496-1.8 1.496 1.8zm0 0l.009.01c.014.017.031.038.053.054.03.02.064.03.11.03h.526c.057 0 .11-.03.133-.081.024-.054.008-.116-.04-.167L6.306 7.004m.776 1.9l-.776-1.9m0 0c.382-.07.686-.21.9-.413.23-.221.351-.515.351-.87 0-.422-.153-.756-.446-.983-.292-.226-.716-.34-1.252-.34h-.97a.37.37 0 0 0-.27.096.37.37 0 0 0-.096.27v4.12c0 .03.01.06.032.081.021.022.05.032.08.032h.432c.03 0 .06-.01.081-.032a.113.113 0 0 0 .032-.081v-3.86c0-.008.003-.01.003-.01 0-.001.003-.003.01-.003h.634c.21 0 .479.022.692.125a.646.646 0 0 1 .262.219.673.673 0 0 1 .106.385c0 .222-.104.388-.288.512-.187.125-.455.206-.778.25l.485.502zm-.485-.502l-.095.012h-.001a.316.316 0 0 0-.17.072.235.235 0 0 0-.07.18v.07a.388.388 0 0 0 .101.267l.235-.601z' fill='%23fff' stroke='%23fff' stroke-width='.1'/%3E%3C/svg%3E");background-size:contain;background-position:center}.weui-toast{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);background-color:#4c4c4c;border-radius:8px;color:#fff;font-size:14px;line-height:1.4;padding:0 20px}.discounted_price.fade-enter,.discounted_price.fade-leave-to{opacity:0;height:0}.discounted_price.fade-enter-to,.discounted_price.fade-leave{opacity:1;height:15px}.discounted_price.fade-enter-active,.discounted_price.fade-leave-active{transition:opacity .15s,height .15s}.activity_card_wrp{-webkit-user-select:none;-moz-user-select:none;user-select:none;width:-moz-fit-content;width:fit-content}.activity_card_wrp .activity_card_wrp__container{display:flex;flex-direction:column;align-items:center;background-color:#0000001a;-webkit-backdrop-filter:blur(50px);backdrop-filter:blur(50px);border-radius:8px;padding:10px}.activity_card_wrp .activity_card_wrp__container .product_image{width:52px;height:52px;border-radius:2px;margin-bottom:8px}.activity_card_wrp .discounted_price{overflow:hidden;font-weight:500;color:#e0b684;line-height:1;font-family:WeChatSansStd-Medium;line-height:normal;font-size:15px}@font-face{font-family:WeChatSansStd-Medium;src:url(data:application/octet-stream;base64,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AwYAAwABBAkABAAsA1oAAwABBAkABQAYA4YAAwABBAkABgAsA54AAwABBAkABwBMA8oAAwABBAkACAAWBBYAAwABBAkACQBGBCwAAwABBAkACwAwBHIAAwABBAkAEAAeBKIAAwABBAkAEQAMBMAAAwABBAkAEwAiBMwAAwABCAQAAABmBO4AAwABCAQAAQAsBVQAAwABCAQAAgAOBYAAAwABCAQABAAsBY4AAwABCAQABwBMBboAAwABCAQACAAWBgYAAwABCAQACQBGBhwAAwABCAQAEAAeBmIAAwABCAQAEQAMBoBDb3B5cmlnaHQgKGMpIDIwMTcgYnkgVGVuY2VudC4gQWxsIHJpZ2h0cyByZXNlcnZlZC5XZUNoYXQgU2FucyBTdGRNZWRpdW1IYW55aSBXZUNoYXQgU2FucyBTdGQtTWVkaXVtOyBWZXJzaW9uIDEuMDBXZUNoYXQgU2FucyBTdGQtTWVkaXVtVmVyc2lvbiAxLjAwV2VDaGF0LVNhbnMtU3RkLU1lZGl1bVdlQ2hhdCBTYW5zIGlzIGEgdHJhZGVtYXJrIG9mIFRlbmNlbnQuSGFueWkgRm9udHNaSEFORyBYdWFuLCBXQU5HIFRpYW5iaSwgTElVIFhpYW95dWh0dHA6Ly93d3cuaGFueWkuY29tLmNuL1dlQ2hhdCBTYW5zIFN0ZE1lZGl1bVdlQ2hhdCBTYW5zIFN0ZC1NZWRpdW3boiSjX7QKMTIzNDU2Nzg5MENvcHlyaWdodCAoYykgMjAxNyBieSBUZW5jZW50LiBBbGwgcmlnaHRzIHJlc2VydmVkLldlQ2hhdCBTYW5zIFN0ZE1lZGl1bUhhbnlpIFdlQ2hhdCBTYW5zIFN0ZC1NZWRpdW07IFZlcnNpb24gMS4wMFdlQ2hhdCBTYW5zIFN0ZC1NZWRpdW1WZXJzaW9uIDEuMDBXZUNoYXQtU2Fucy1TdGQtTWVkaXVtV2VDaGF0IFNhbnMgaXMgYSB0cmFkZW1hcmsgb2YgVGVuY2VudC5IYW55aSBGb250c1pIQU5HIFh1YW4sIFdBTkcgVGlhbmJpLCBMSVUgWGlhb3l1V2VDaGF0IFNhbnMgU3RkLU1lZGl1bQBDAG8AcAB5AHIAaQBnAGgAdAAgACgAYwApACAAMgAwADEANwAgAGIAeQAgAFQAZQBuAGMAZQBuAHQALgAgAEEAbABsACAAcgBpAGcAaAB0AHMAIAByAGUAcwBlAHIAdgBlAGQALgBXAGUAQwBoAGEAdAAgAFMAYQBuAHMAIABTAHQAZAAgAE0AZQBkAGkAdQBtAFIAZQBnAHUAbABhAHIASABhAG4AeQBpACAAVwBlAEMAaABhAHQAIABTAGEAbgBzACAAUwB0AGQALQBNAGUAZABpAHUAbQA7ACAAVgBlAHIAcwBpAG8AbgAgADEALgAwADAAVwBlAEMAaABhAHQAIABTAGEAbgBzACAAUwB0AGQALQBNAGUAZABpAHUAbQBWAGUAcgBzAGkAbwBuACAAMQAuADAAMABXAGUAQwBoAGEAdAAtAFMAYQBuAHMALQBTAHQAZAAtAE0AZQBkAGkAdQBtAFcAZQBDAGgAYQB0ACAAUwBhAG4AcwAgAGkAcwAgAGEAIAB0AHIAYQBkAGUAbQBhAHIAawAgAG8AZgAgAFQAZQBuAGMAZQBuAHQALgBIAGEAbgB5AGkAIABGAG8AbgB0AHMAWgBIAEEATgBHACAAWAB1AGEAbgAsACAAVwBBAE4ARwAgAFQAaQBhAG4AYgBpACwAIABMAEkAVQAgAFgAaQBhAG8AeQB1AGgAdAB0AHAAOgAvAC8AdwB3AHcALgBoAGEAbgB5AGkALgBjAG8AbQAuAGMAbgAvAFcAZQBDAGgAYQB0ACAAUwBhAG4AcwAgAFMAdABkAE0AZQBkAGkAdQBtIKwAogAkAKMgqQClAAoAMQAyADMANAA1ADYANwA4ADkAMABDAG8AcAB5AHIAaQBnAGgAdAAgACgAYwApACAAMgAwADEANwAgAGIAeQAgAFQAZQBuAGMAZQBuAHQALgAgAEEAbABsACAAcgBpAGcAaAB0AHMAIAByAGUAcwBlAHIAdgBlAGQALgBXAGUAQwBoAGEAdAAgAFMAYQBuAHMAIABTAHQAZAAgAE0AZQBkAGkAdQBtAFIAZQBnAHUAbABhAHIAVwBlAEMAaABhAHQAIABTAGEAbgBzACAAUwB0AGQALQBNAGUAZABpAHUAbQBXAGUAQwBoAGEAdAAgAFMAYQBuAHMAIABpAHMAIABhACAAdAByAGEAZABlAG0AYQByAGsAIABvAGYAIABUAGUAbgBjAGUAbgB0AC4ASABhAG4AeQBpACAARgBvAG4AdABzAFoASABBAE4ARwAgAFgAdQBhAG4ALAAgAFcAQQBOAEcAIABUAGkAYQBuAGIAaQAsACAATABJAFUAIABYAGkAYQBvAHkAdQBXAGUAQwBoAGEAdAAgAFMAYQBuAHMAIABTAHQAZABNAGUAZABpAHUAbQAAAAIAAAAAAAD/tQAyAAAAAAAAAAAAAAAAAAAAAAAAAAAAYwAAAAMAJAAlACYAJwAoACkAKgArACwALQAuAC8AMAAxADIAMwA0ADUANgA3ADgAOQA6ADsAPAA9AEQARQBGAEcASABJAEoASwBMAE0ATgBPAFAAUQBSAFMAVABVAFYAVwBYAFkAWgBbAFwAXQATABQAFQAWABcAGAAZABoAGwAcAA8AEQAQAQIBAwCEAQQAvQAHAQUBBgEHAQgBCQEKAQsBDAENAQ4BDwEQAREBEgCFARMBFAEVAJYBFgEXARgBGQEaAA4A7wd1bmkwRTNGB3VuaTIwQjUNY29sb25tb25ldGFyeQd1bmlGRTY5BGRvbmcERXVybwd1bmkyMEIyB3VuaTIwQjQHdW5pMjBBRAd1bmkyMEJFB3VuaTIwQkEHdW5pMjBCQwd1bmkyMEE2B3VuaTIwQjEHdW5pMjBCRAd1bmkyMEI5B3VuaTIwQUEHdW5pMjBCOAd1bmkyMEFFB3VuaTIwQTkHdW5pRkZFMAd1bmlGRjA0B3VuaUZGRTEHdW5pRkZFNgd1bmlGRkU1) format("truetype")}.activity_card_wrp .origin_price{font-weight:500;color:#fff;line-height:1;transition:font-size .15s,font-weight .15s,color .15s,-webkit-text-decoration .15s;transition:font-size .15s,font-weight .15s,color .15s,text-decoration .15s;transition:font-size .15s,font-weight .15s,color .15s,text-decoration .15s,-webkit-text-decoration .15s;font-family:WeChatSansStd-Medium;line-height:normal;font-size:15px}@font-face{font-family:WeChatSansStd-Medium;src:url(data:application/octet-stream;base64,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AwYAAwABBAkABAAsA1oAAwABBAkABQAYA4YAAwABBAkABgAsA54AAwABBAkABwBMA8oAAwABBAkACAAWBBYAAwABBAkACQBGBCwAAwABBAkACwAwBHIAAwABBAkAEAAeBKIAAwABBAkAEQAMBMAAAwABBAkAEwAiBMwAAwABCAQAAABmBO4AAwABCAQAAQAsBVQAAwABCAQAAgAOBYAAAwABCAQABAAsBY4AAwABCAQABwBMBboAAwABCAQACAAWBgYAAwABCAQACQBGBhwAAwABCAQAEAAeBmIAAwABCAQAEQAMBoBDb3B5cmlnaHQgKGMpIDIwMTcgYnkgVGVuY2VudC4gQWxsIHJpZ2h0cyByZXNlcnZlZC5XZUNoYXQgU2FucyBTdGRNZWRpdW1IYW55aSBXZUNoYXQgU2FucyBTdGQtTWVkaXVtOyBWZXJzaW9uIDEuMDBXZUNoYXQgU2FucyBTdGQtTWVkaXVtVmVyc2lvbiAxLjAwV2VDaGF0LVNhbnMtU3RkLU1lZGl1bVdlQ2hhdCBTYW5zIGlzIGEgdHJhZGVtYXJrIG9mIFRlbmNlbnQuSGFueWkgRm9udHNaSEFORyBYdWFuLCBXQU5HIFRpYW5iaSwgTElVIFhpYW95dWh0dHA6Ly93d3cuaGFueWkuY29tLmNuL1dlQ2hhdCBTYW5zIFN0ZE1lZGl1bVdlQ2hhdCBTYW5zIFN0ZC1NZWRpdW3boiSjX7QKMTIzNDU2Nzg5MENvcHlyaWdodCAoYykgMjAxNyBieSBUZW5jZW50LiBBbGwgcmlnaHRzIHJlc2VydmVkLldlQ2hhdCBTYW5zIFN0ZE1lZGl1bUhhbnlpIFdlQ2hhdCBTYW5zIFN0ZC1NZWRpdW07IFZlcnNpb24gMS4wMFdlQ2hhdCBTYW5zIFN0ZC1NZWRpdW1WZXJzaW9uIDEuMDBXZUNoYXQtU2Fucy1TdGQtTWVkaXVtV2VDaGF0IFNhbnMgaXMgYSB0cmFkZW1hcmsgb2YgVGVuY2VudC5IYW55aSBGb250c1pIQU5HIFh1YW4sIFdBTkcgVGlhbmJpLCBMSVUgWGlhb3l1V2VDaGF0IFNhbnMgU3RkLU1lZGl1bQBDAG8AcAB5AHIAaQBnAGgAdAAgACgAYwApACAAMgAwADEANwAgAGIAeQAgAFQAZQBuAGMAZQBuAHQALgAgAEEAbABsACAAcgBpAGcAaAB0AHMAIAByAGUAcwBlAHIAdgBlAGQALgBXAGUAQwBoAGEAdAAgAFMAYQBuAHMAIABTAHQAZAAgAE0AZQBkAGkAdQBtAFIAZQBnAHUAbABhAHIASABhAG4AeQBpACAAVwBlAEMAaABhAHQAIABTAGEAbgBzACAAUwB0AGQALQBNAGUAZABpAHUAbQA7ACAAVgBlAHIAcwBpAG8AbgAgADEALgAwADAAVwBlAEMAaABhAHQAIABTAGEAbgBzACAAUwB0AGQALQBNAGUAZABpAHUAbQBWAGUAcgBzAGkAbwBuACAAMQAuADAAMABXAGUAQwBoAGEAdAAtAFMAYQBuAHMALQBTAHQAZAAtAE0AZQBkAGkAdQBtAFcAZQBDAGgAYQB0ACAAUwBhAG4AcwAgAGkAcwAgAGEAIAB0AHIAYQBkAGUAbQBhAHIAawAgAG8AZgAgAFQAZQBuAGMAZQBuAHQALgBIAGEAbgB5AGkAIABGAG8AbgB0AHMAWgBIAEEATgBHACAAWAB1AGEAbgAsACAAVwBBAE4ARwAgAFQAaQBhAG4AYgBpACwAIABMAEkAVQAgAFgAaQBhAG8AeQB1AGgAdAB0AHAAOgAvAC8AdwB3AHcALgBoAGEAbgB5AGkALgBjAG8AbQAuAGMAbgAvAFcAZQBDAGgAYQB0ACAAUwBhAG4AcwAgAFMAdABkAE0AZQBkAGkAdQBtIKwAogAkAKMgqQClAAoAMQAyADMANAA1ADYANwA4ADkAMABDAG8AcAB5AHIAaQBnAGgAdAAgACgAYwApACAAMgAwADEANwAgAGIAeQAgAFQAZQBuAGMAZQBuAHQALgAgAEEAbABsACAAcgBpAGcAaAB0AHMAIAByAGUAcwBlAHIAdgBlAGQALgBXAGUAQwBoAGEAdAAgAFMAYQBuAHMAIABTAHQAZAAgAE0AZQBkAGkAdQBtAFIAZQBnAHUAbABhAHIAVwBlAEMAaABhAHQAIABTAGEAbgBzACAAUwB0AGQALQBNAGUAZABpAHUAbQBXAGUAQwBoAGEAdAAgAFMAYQBuAHMAIABpAHMAIABhACAAdAByAGEAZABlAG0AYQByAGsAIABvAGYAIABUAGUAbgBjAGUAbgB0AC4ASABhAG4AeQBpACAARgBvAG4AdABzAFoASABBAE4ARwAgAFgAdQBhAG4ALAAgAFcAQQBOAEcAIABUAGkAYQBuAGIAaQAsACAATABJAFUAIABYAGkAYQBvAHkAdQBXAGUAQwBoAGEAdAAgAFMAYQBuAHMAIABTAHQAZABNAGUAZABpAHUAbQAAAAIAAAAAAAD/tQAyAAAAAAAAAAAAAAAAAAAAAAAAAAAAYwAAAAMAJAAlACYAJwAoACkAKgArACwALQAuAC8AMAAxADIAMwA0ADUANgA3ADgAOQA6ADsAPAA9AEQARQBGAEcASABJAEoASwBMAE0ATgBPAFAAUQBSAFMAVABVAFYAVwBYAFkAWgBbAFwAXQATABQAFQAWABcAGAAZABoAGwAcAA8AEQAQAQIBAwCEAQQAvQAHAQUBBgEHAQgBCQEKAQsBDAENAQ4BDwEQAREBEgCFARMBFAEVAJYBFgEXARgBGQEaAA4A7wd1bmkwRTNGB3VuaTIwQjUNY29sb25tb25ldGFyeQd1bmlGRTY5BGRvbmcERXVybwd1bmkyMEIyB3VuaTIwQjQHdW5pMjBBRAd1bmkyMEJFB3VuaTIwQkEHdW5pMjBCQwd1bmkyMEE2B3VuaTIwQjEHdW5pMjBCRAd1bmkyMEI5B3VuaTIwQUEHdW5pMjBCOAd1bmkyMEFFB3VuaTIwQTkHdW5pRkZFMAd1bmlGRjA0B3VuaUZGRTEHdW5pRkZFNgd1bmlGRkU1) format("truetype")}.activity_card_wrp .origin_price.has_discount{font-weight:400;text-decoration:line-through;-webkit-text-decoration-color:#fff;text-decoration-color:#fff;color:#fff;opacity:.5;font-family:WeChatSansStd-Medium;line-height:normal;font-size:12px}@font-face{font-family:WeChatSansStd-Medium;src:url(data:application/octet-stream;base64,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AwYAAwABBAkABAAsA1oAAwABBAkABQAYA4YAAwABBAkABgAsA54AAwABBAkABwBMA8oAAwABBAkACAAWBBYAAwABBAkACQBGBCwAAwABBAkACwAwBHIAAwABBAkAEAAeBKIAAwABBAkAEQAMBMAAAwABBAkAEwAiBMwAAwABCAQAAABmBO4AAwABCAQAAQAsBVQAAwABCAQAAgAOBYAAAwABCAQABAAsBY4AAwABCAQABwBMBboAAwABCAQACAAWBgYAAwABCAQACQBGBhwAAwABCAQAEAAeBmIAAwABCAQAEQAMBoBDb3B5cmlnaHQgKGMpIDIwMTcgYnkgVGVuY2VudC4gQWxsIHJpZ2h0cyByZXNlcnZlZC5XZUNoYXQgU2FucyBTdGRNZWRpdW1IYW55aSBXZUNoYXQgU2FucyBTdGQtTWVkaXVtOyBWZXJzaW9uIDEuMDBXZUNoYXQgU2FucyBTdGQtTWVkaXVtVmVyc2lvbiAxLjAwV2VDaGF0LVNhbnMtU3RkLU1lZGl1bVdlQ2hhdCBTYW5zIGlzIGEgdHJhZGVtYXJrIG9mIFRlbmNlbnQuSGFueWkgRm9udHNaSEFORyBYdWFuLCBXQU5HIFRpYW5iaSwgTElVIFhpYW95dWh0dHA6Ly93d3cuaGFueWkuY29tLmNuL1dlQ2hhdCBTYW5zIFN0ZE1lZGl1bVdlQ2hhdCBTYW5zIFN0ZC1NZWRpdW3boiSjX7QKMTIzNDU2Nzg5MENvcHlyaWdodCAoYykgMjAxNyBieSBUZW5jZW50LiBBbGwgcmlnaHRzIHJlc2VydmVkLldlQ2hhdCBTYW5zIFN0ZE1lZGl1bUhhbnlpIFdlQ2hhdCBTYW5zIFN0ZC1NZWRpdW07IFZlcnNpb24gMS4wMFdlQ2hhdCBTYW5zIFN0ZC1NZWRpdW1WZXJzaW9uIDEuMDBXZUNoYXQtU2Fucy1TdGQtTWVkaXVtV2VDaGF0IFNhbnMgaXMgYSB0cmFkZW1hcmsgb2YgVGVuY2VudC5IYW55aSBGb250c1pIQU5HIFh1YW4sIFdBTkcgVGlhbmJpLCBMSVUgWGlhb3l1V2VDaGF0IFNhbnMgU3RkLU1lZGl1bQBDAG8AcAB5AHIAaQBnAGgAdAAgACgAYwApACAAMgAwADEANwAgAGIAeQAgAFQAZQBuAGMAZQBuAHQALgAgAEEAbABsACAAcgBpAGcAaAB0AHMAIAByAGUAcwBlAHIAdgBlAGQALgBXAGUAQwBoAGEAdAAgAFMAYQBuAHMAIABTAHQAZAAgAE0AZQBkAGkAdQBtAFIAZQBnAHUAbABhAHIASABhAG4AeQBpACAAVwBlAEMAaABhAHQAIABTAGEAbgBzACAAUwB0AGQALQBNAGUAZABpAHUAbQA7ACAAVgBlAHIAcwBpAG8AbgAgADEALgAwADAAVwBlAEMAaABhAHQAIABTAGEAbgBzACAAUwB0AGQALQBNAGUAZABpAHUAbQBWAGUAcgBzAGkAbwBuACAAMQAuADAAMABXAGUAQwBoAGEAdAAtAFMAYQBuAHMALQBTAHQAZAAtAE0AZQBkAGkAdQBtAFcAZQBDAGgAYQB0ACAAUwBhAG4AcwAgAGkAcwAgAGEAIAB0AHIAYQBkAGUAbQBhAHIAawAgAG8AZgAgAFQAZQBuAGMAZQBuAHQALgBIAGEAbgB5AGkAIABGAG8AbgB0AHMAWgBIAEEATgBHACAAWAB1AGEAbgAsACAAVwBBAE4ARwAgAFQAaQBhAG4AYgBpACwAIABMAEkAVQAgAFgAaQBhAG8AeQB1AGgAdAB0AHAAOgAvAC8AdwB3AHcALgBoAGEAbgB5AGkALgBjAG8AbQAuAGMAbgAvAFcAZQBDAGgAYQB0ACAAUwBhAG4AcwAgAFMAdABkAE0AZQBkAGkAdQBtIKwAogAkAKMgqQClAAoAMQAyADMANAA1ADYANwA4ADkAMABDAG8AcAB5AHIAaQBnAGgAdAAgACgAYwApACAAMgAwADEANwAgAGIAeQAgAFQAZQBuAGMAZQBuAHQALgAgAEEAbABsACAAcgBpAGcAaAB0AHMAIAByAGUAcwBlAHIAdgBlAGQALgBXAGUAQwBoAGEAdAAgAFMAYQBuAHMAIABTAHQAZAAgAE0AZQBkAGkAdQBtAFIAZQBnAHUAbABhAHIAVwBlAEMAaABhAHQAIABTAGEAbgBzACAAUwB0AGQALQBNAGUAZABpAHUAbQBXAGUAQwBoAGEAdAAgAFMAYQBuAHMAIABpAHMAIABhACAAdAByAGEAZABlAG0AYQByAGsAIABvAGYAIABUAGUAbgBjAGUAbgB0AC4ASABhAG4AeQBpACAARgBvAG4AdABzAFoASABBAE4ARwAgAFgAdQBhAG4ALAAgAFcAQQBOAEcAIABUAGkAYQBuAGIAaQAsACAATABJAFUAIABYAGkAYQBvAHkAdQBXAGUAQwBoAGEAdAAgAFMAYQBuAHMAIABTAHQAZABNAGUAZABpAHUAbQAAAAIAAAAAAAD/tQAyAAAAAAAAAAAAAAAAAAAAAAAAAAAAYwAAAAMAJAAlACYAJwAoACkAKgArACwALQAuAC8AMAAxADIAMwA0ADUANgA3ADgAOQA6ADsAPAA9AEQARQBGAEcASABJAEoASwBMAE0ATgBPAFAAUQBSAFMAVABVAFYAVwBYAFkAWgBbAFwAXQATABQAFQAWABcAGAAZABoAGwAcAA8AEQAQAQIBAwCEAQQAvQAHAQUBBgEHAQgBCQEKAQsBDAENAQ4BDwEQAREBEgCFARMBFAEVAJYBFgEXARgBGQEaAA4A7wd1bmkwRTNGB3VuaTIwQjUNY29sb25tb25ldGFyeQd1bmlGRTY5BGRvbmcERXVybwd1bmkyMEIyB3VuaTIwQjQHdW5pMjBBRAd1bmkyMEJFB3VuaTIwQkEHdW5pMjBCQwd1bmkyMEE2B3VuaTIwQjEHdW5pMjBCRAd1bmkyMEI5B3VuaTIwQUEHdW5pMjBCOAd1bmkyMEFFB3VuaTIwQTkHdW5pRkZFMAd1bmlGRjA0B3VuaUZGRTEHdW5pRkZFNgd1bmlGRkU1) format("truetype")}.s1s_card_wrp{font-family:PingFang SC;display:flex;align-items:center}.s1s_card_wrp .product-image{width:64px;height:64px;border-radius:2px;margin-right:12px}.s1s_card_wrp .product-info{flex:1;width:200px;line-height:1}.s1s_card_wrp .product-title{color:var(--weui-FG-0);font-size:15px;width:100%;font-weight:400;margin-bottom:5px;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.s1s_card_wrp .product-price{color:var(--weui-ORANGERED-100);font-family:WeChatSansStd-Medium;line-height:normal;font-size:15px}@font-face{font-family:WeChatSansStd-Medium;src:url(data:application/octet-stream;base64,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AwYAAwABBAkABAAsA1oAAwABBAkABQAYA4YAAwABBAkABgAsA54AAwABBAkABwBMA8oAAwABBAkACAAWBBYAAwABBAkACQBGBCwAAwABBAkACwAwBHIAAwABBAkAEAAeBKIAAwABBAkAEQAMBMAAAwABBAkAEwAiBMwAAwABCAQAAABmBO4AAwABCAQAAQAsBVQAAwABCAQAAgAOBYAAAwABCAQABAAsBY4AAwABCAQABwBMBboAAwABCAQACAAWBgYAAwABCAQACQBGBhwAAwABCAQAEAAeBmIAAwABCAQAEQAMBoBDb3B5cmlnaHQgKGMpIDIwMTcgYnkgVGVuY2VudC4gQWxsIHJpZ2h0cyByZXNlcnZlZC5XZUNoYXQgU2FucyBTdGRNZWRpdW1IYW55aSBXZUNoYXQgU2FucyBTdGQtTWVkaXVtOyBWZXJzaW9uIDEuMDBXZUNoYXQgU2FucyBTdGQtTWVkaXVtVmVyc2lvbiAxLjAwV2VDaGF0LVNhbnMtU3RkLU1lZGl1bVdlQ2hhdCBTYW5zIGlzIGEgdHJhZGVtYXJrIG9mIFRlbmNlbnQuSGFueWkgRm9udHNaSEFORyBYdWFuLCBXQU5HIFRpYW5iaSwgTElVIFhpYW95dWh0dHA6Ly93d3cuaGFueWkuY29tLmNuL1dlQ2hhdCBTYW5zIFN0ZE1lZGl1bVdlQ2hhdCBTYW5zIFN0ZC1NZWRpdW3boiSjX7QKMTIzNDU2Nzg5MENvcHlyaWdodCAoYykgMjAxNyBieSBUZW5jZW50LiBBbGwgcmlnaHRzIHJlc2VydmVkLldlQ2hhdCBTYW5zIFN0ZE1lZGl1bUhhbnlpIFdlQ2hhdCBTYW5zIFN0ZC1NZWRpdW07IFZlcnNpb24gMS4wMFdlQ2hhdCBTYW5zIFN0ZC1NZWRpdW1WZXJzaW9uIDEuMDBXZUNoYXQtU2Fucy1TdGQtTWVkaXVtV2VDaGF0IFNhbnMgaXMgYSB0cmFkZW1hcmsgb2YgVGVuY2VudC5IYW55aSBGb250c1pIQU5HIFh1YW4sIFdBTkcgVGlhbmJpLCBMSVUgWGlhb3l1V2VDaGF0IFNhbnMgU3RkLU1lZGl1bQBDAG8AcAB5AHIAaQBnAGgAdAAgACgAYwApACAAMgAwADEANwAgAGIAeQAgAFQAZQBuAGMAZQBuAHQALgAgAEEAbABsACAAcgBpAGcAaAB0AHMAIAByAGUAcwBlAHIAdgBlAGQALgBXAGUAQwBoAGEAdAAgAFMAYQBuAHMAIABTAHQAZAAgAE0AZQBkAGkAdQBtAFIAZQBnAHUAbABhAHIASABhAG4AeQBpACAAVwBlAEMAaABhAHQAIABTAGEAbgBzACAAUwB0AGQALQBNAGUAZABpAHUAbQA7ACAAVgBlAHIAcwBpAG8AbgAgADEALgAwADAAVwBlAEMAaABhAHQAIABTAGEAbgBzACAAUwB0AGQALQBNAGUAZABpAHUAbQBWAGUAcgBzAGkAbwBuACAAMQAuADAAMABXAGUAQwBoAGEAdAAtAFMAYQBuAHMALQBTAHQAZAAtAE0AZQBkAGkAdQBtAFcAZQBDAGgAYQB0ACAAUwBhAG4AcwAgAGkAcwAgAGEAIAB0AHIAYQBkAGUAbQBhAHIAawAgAG8AZgAgAFQAZQBuAGMAZQBuAHQALgBIAGEAbgB5AGkAIABGAG8AbgB0AHMAWgBIAEEATgBHACAAWAB1AGEAbgAsACAAVwBBAE4ARwAgAFQAaQBhAG4AYgBpACwAIABMAEkAVQAgAFgAaQBhAG8AeQB1AGgAdAB0AHAAOgAvAC8AdwB3AHcALgBoAGEAbgB5AGkALgBjAG8AbQAuAGMAbgAvAFcAZQBDAGgAYQB0ACAAUwBhAG4AcwAgAFMAdABkAE0AZQBkAGkAdQBtIKwAogAkAKMgqQClAAoAMQAyADMANAA1ADYANwA4ADkAMABDAG8AcAB5AHIAaQBnAGgAdAAgACgAYwApACAAMgAwADEANwAgAGIAeQAgAFQAZQBuAGMAZQBuAHQALgAgAEEAbABsACAAcgBpAGcAaAB0AHMAIAByAGUAcwBlAHIAdgBlAGQALgBXAGUAQwBoAGEAdAAgAFMAYQBuAHMAIABTAHQAZAAgAE0AZQBkAGkAdQBtAFIAZQBnAHUAbABhAHIAVwBlAEMAaABhAHQAIABTAGEAbgBzACAAUwB0AGQALQBNAGUAZABpAHUAbQBXAGUAQwBoAGEAdAAgAFMAYQBuAHMAIABpAHMAIABhACAAdAByAGEAZABlAG0AYQByAGsAIABvAGYAIABUAGUAbgBjAGUAbgB0AC4ASABhAG4AeQBpACAARgBvAG4AdABzAFoASABBAE4ARwAgAFgAdQBhAG4ALAAgAFcAQQBOAEcAIABUAGkAYQBuAGIAaQAsACAATABJAFUAIABYAGkAYQBvAHkAdQBXAGUAQwBoAGEAdAAgAFMAYQBuAHMAIABTAHQAZABNAGUAZABpAHUAbQAAAAIAAAAAAAD/tQAyAAAAAAAAAAAAAAAAAAAAAAAAAAAAYwAAAAMAJAAlACYAJwAoACkAKgArACwALQAuAC8AMAAxADIAMwA0ADUANgA3ADgAOQA6ADsAPAA9AEQARQBGAEcASABJAEoASwBMAE0ATgBPAFAAUQBSAFMAVABVAFYAVwBYAFkAWgBbAFwAXQATABQAFQAWABcAGAAZABoAGwAcAA8AEQAQAQIBAwCEAQQAvQAHAQUBBgEHAQgBCQEKAQsBDAENAQ4BDwEQAREBEgCFARMBFAEVAJYBFgEXARgBGQEaAA4A7wd1bmkwRTNGB3VuaTIwQjUNY29sb25tb25ldGFyeQd1bmlGRTY5BGRvbmcERXVybwd1bmkyMEIyB3VuaTIwQjQHdW5pMjBBRAd1bmkyMEJFB3VuaTIwQkEHdW5pMjBCQwd1bmkyMEE2B3VuaTIwQjEHdW5pMjBCRAd1bmkyMEI5B3VuaTIwQUEHdW5pMjBCOAd1bmkyMEFFB3VuaTIwQTkHdW5pRkZFMAd1bmlGRjA0B3VuaUZGRTEHdW5pRkZFNgd1bmlGRkU1) format("truetype")}.s1s_card_wrp .product-brand{color:var(--weui-FG-1);font-size:12px;display:flex;align-items:center}.s1s_card_wrp .product-brand .product-logo{margin-right:2px}.s1s_card_wrp .product-brand .shop-verify-icon{font-size:14px;margin-left:2px;position:relative;top:-.03em}.s1s_card_wrp .product-centercontainer{display:flex;align-items:center;margin-bottom:5px}.s1s_card_wrp .product-gifts{color:var(--weui-FG-2);font-size:12px;margin-left:4px}.s1s_card_wrp .product-gifts .product-gifts__num{margin:0 1px} `, R = { windowproduct: "data-windowproduct", customstyle: "data-customstyle", ecsource: "data-ecsource", exportkey: "data-exportkey", wap_export_token: "data-wap_export_token", loaded: "data-loaded", cardtype: "data-cardtype", is_hover: "data-is-hover", is_selected: "data-is-selected", token: "data-token", title: "data-title", immutable: "data-immutable", req_scene: "data-req-scene", urlParams: "data-url-params", extInfo: "data-ext-info", scrollBlur: "data-scroll-blur", wrpStyle: "data-wrp-style", type: "data-type", productImage: "data-product-image", originPrice: "data-origin-price", discountedPrice: "data-discounted-price", outerclick: "data-outerclick", productInfo: "data-product-info" }; function V(B, A = {}) { let E = {}; return E = o$1.call(this, R), E.loaded = Number(E.loaded || 0), E.cardtype = Number(E.cardtype || 0), E.is_hover = Number(E.is_hover || 0), E.is_selected = Number(E.is_selected || 0), E.immutable = Number(E.immutable || 0), E.req_scene = Number(E.req_scene || 0), E.urlParams = JSON.parse(E.urlParams || "{}"), E.extInfo = JSON.parse(E.extInfo || "{}"), E.productInfo = JSON.parse(E.productInfo || "{}"), E.scrollBlur = Number(E.scrollBlur || 0), E.originPrice = Number(E.originPrice || 0), E.discountedPrice = Number(E.discountedPrice || 0), E.outerclick = Number(E.outerclick || 0), { platform: B, extraInfo: A, ...E }; } function b(B) { k( Object.assign(B, { Component: B.isDev ? B.devComponent : j, styleText: B.isDev ? B.devStyleText : m, customName: B.customName || "mp-common-product", watchAttr: Object.values(R), getProps: V, eventName: ["iframe-message", "document-click", "expose", "element-click"] }) ); } var C = function() { var A = this, E = A._self._c; return E("section", { ref: "js_custom_element", staticClass: "wx-root red_package_cover_wrp", class: [{ disabled: A.disabled, small: A.smallCard }, A.platformClassname], attrs: { role: "option" } }, [E("section", { staticClass: "red_package_cover__inner wx_tap_card wx_card_root", class: [A.is_hover === 1 ? "wx_hover_card" : "", A.is_selected === 1 ? "wx_selected_card" : ""] }, [E("section", { staticClass: "red_package_cover__inner__main" }, [E("section", { staticClass: "red_package_cover__body" }, [A.openImgSrc ? E("span", { staticClass: "red_package_cover_img red_package_open_cover_img", style: { "background-image": `url(${A.openImgSrc})`, width: A.smallCard ? "" : A.openImgWidth, height: A.smallCard ? "" : A.openImgHeight }, attrs: { "data-notusecover": "1" } }) : E("span", { staticClass: "red_package_cover_img", class: { synthetic_cover_img: A.isSynthetic === 1 }, style: "background-image: url(" + A.imgSrc + ")", attrs: { "data-notusecover": "1" } }), A._v(" "), A.smallCard ? E("span", { staticClass: "title-wrp" }, [E("span", { staticClass: "title" }, [A._v(A._s(A.name) + '红包封面')]), A._v(" "), A.isPurchaseOrder === 1 ? E("span", { staticClass: "red_package_cover__purchase" }, [A._v('付费')]) : A._e()]) : A._e()]), A._v(" "), E("section", { staticClass: "red_package_cover__foot" }, [A.smallCard ? [A.status === 0 ? E("span", { staticClass: "weui-btn weui-btn_mini red_package_cover__access-link button" }, [A._v('领取')]) : A.status === 1 ? E("span", { staticClass: "red_package_cover__access-link correct disabled" }, [A._v('已领取')]) : A.status === 2 ? E("span", { staticClass: "red_package_cover__access-link disabled" }, [A._v('已领完')]) : A.status === 3 ? E("span", { staticClass: "red_package_cover__access-link disabled" }, [A._v('不可领取')]) : A._e()] : A.platform !== "wechat" ? [A.disabled ? E("span", { staticClass: "red_package_cover__access-link disabled" }, [A._v('红包封面不可用')]) : E("span", { staticClass: "red_package_cover__access-link" }, [A._v('领取' + A._s(A.name) + '红包封面')])] : [A.status === 0 ? E("span", { staticClass: "red_package_cover__access-link" }, [A._v('领取' + A._s(A.name) + '红包封面')]) : A.status === 1 ? E("span", { staticClass: "red_package_cover__access-link disabled" }, [A._v('已领取红包封面')]) : A.status === 2 ? E("span", { staticClass: "red_package_cover__access-link disabled" }, [A._v('红包封面已领取完')]) : A.status === 3 ? E("span", { staticClass: "red_package_cover__access-link disabled" }, [A._v('红包封面不可领取')]) : A._e()], A._v(" "), A.isPurchaseOrder === 1 && !A.smallCard ? E("section", { staticClass: "red_package_cover__purchase" }, [A._v('付费')]) : A._e()], 2)]), A._v(" "), A._m(0), A._v(" "), A.platform !== "wechat" && A.disabled ? E("section", { staticClass: "red_package_cover_disable_wording" }, [A._v('红包封面不可用')]) : A._e()])]); }, w = [function() { var g = this, A = g._self._c; return A("section", { staticClass: "red_package_cover__extend" }, [A("span", { staticClass: "red_package_cover__extend_icon" }), g._v(" "), A("span", { staticClass: "red_package_cover__extend_info" }, [g._v('微信红包封面')])]); }]; function a(g) { var A = typeof g == "function" ? g.options : g; return C && (A.render = C, A.staticRenderFns = w, A._compiled = !0), { exports: g, options: A }; } const r = { name: "mp-common-redpacket", template: a, mixins: [j$1], props: { errType: { type: String, default: "" }, is_hover: { type: Number, default: 0 }, is_selected: { type: Number, default: 0 }, name: { type: String, default: "" }, isSynthetic: { type: Number, default: 0 }, imgSrc: { type: String, default: "" }, openImgSrc: { type: String, default: "" }, status: { type: Number, default: 3 }, bizuin: { type: String, default: "" }, coveruri: { type: String, default: "" }, orderid: { type: String, default: "" }, isPurchaseOrder: { type: Number, default: 0 }, smallCard: { type: Number, default: 0 } }, data() { return { platformClassname: { web: "common-redpacket-web", app: "common-redpacket-app", wechat: "common-redpacket-webchat" }[this.platform], openImgWidth: "62.33%", openImgHeight: "108%" }; }, methods: { handleClick() { this.$emit("click"); }, calOpenImgWidth() { if (!this.openImgSrc) return; const g = new Image(); g.onload = () => { this.openImgWidth = `${(g.width / g.height * 108).toFixed(2)}%`; }, g.src = decodeURIComponent(this.openImgSrc); } }, computed: { disabled() { return this.errType * 1 > 0; } }, watch: { openImgSrc: function() { this.calOpenImgWidth(); } }, mounted() { this.calOpenImgWidth(); } }, t = `.wx-root,body{--weui-BG-COLOR-ACTIVE: #ececec}.wx-root[data-weui-theme=dark],body[data-weui-theme=dark]{--weui-BG-COLOR-ACTIVE: #373737}@media (prefers-color-scheme: dark){.wx-root:not([data-weui-theme=light]),body:not([data-weui-theme=light]){--weui-BG-COLOR-ACTIVE: #373737}}body,.wx-root,page{--weui-BTN-HEIGHT: 48;--weui-BTN-HEIGHT-MEDIUM: 40;--weui-BTN-HEIGHT-SMALL: 32}.wx-root,body{--weui-BTN-ACTIVE-MASK: rgba(0, 0, 0, .1)}.wx-root[data-weui-theme=dark],body[data-weui-theme=dark]{--weui-BTN-ACTIVE-MASK: rgba(255, 255, 255, .1)}@media (prefers-color-scheme: dark){.wx-root:not([data-weui-theme=light]),body:not([data-weui-theme=light]){--weui-BTN-ACTIVE-MASK: rgba(255, 255, 255, .1)}}.wx-root,body{--weui-BTN-DEFAULT-ACTIVE-BG: #e6e6e6}.wx-root[data-weui-theme=dark],body[data-weui-theme=dark]{--weui-BTN-DEFAULT-ACTIVE-BG: rgba(255, 255, 255, .126)}@media (prefers-color-scheme: dark){.wx-root:not([data-weui-theme=light]),body:not([data-weui-theme=light]){--weui-BTN-DEFAULT-ACTIVE-BG: rgba(255, 255, 255, .126)}}.wx-root,body{--weui-DIALOG-LINE-COLOR: rgba(0, 0, 0, .1)}.wx-root[data-weui-theme=dark],body[data-weui-theme=dark]{--weui-DIALOG-LINE-COLOR: rgba(255, 255, 255, .1)}@media (prefers-color-scheme: dark){.wx-root:not([data-weui-theme=light]),body:not([data-weui-theme=light]){--weui-DIALOG-LINE-COLOR: rgba(255, 255, 255, .1)}}.weui-btn{position:relative;display:block;width:184px;margin-left:auto;margin-right:auto;padding:12px 24px;box-sizing:border-box;font-weight:500;font-size:17px;text-align:center;text-decoration:none;color:#fff;line-height:1.41176471;border-radius:8px;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;-moz-user-select:none;user-select:none}.weui-btn:active:before{content:"";position:absolute;top:0;left:0;width:100%;height:100%;background-color:var(--weui-BTN-ACTIVE-MASK);border-radius:8px}.weui-btn:active.weui-btn_loading:before,.weui-btn:active.weui-btn_disabled:before,.weui-btn:active[disabled]:before{display:none}.weui-btn_block{width:auto}.weui-btn_inline{display:inline-block}.weui-btn_default{color:var(--weui-FG-0);background-color:var(--weui-FG-5)}.weui-btn_default:not(.weui-btn_disabled):visited{color:var(--weui-FG-0)}.weui-btn_primary{background-color:var(--weui-BRAND)}.weui-btn_primary:not(.weui-btn_disabled):visited{color:#fff}.weui-btn_warn{color:var(--weui-RED);background-color:var(--weui-FG-5)}.weui-btn_warn:not(.weui-btn_disabled):visited{color:var(--weui-RED)}.weui-btn_overlay{color:var(--weui-BRAND);background-color:#fff}.weui-btn_overlay:not(.weui-btn_disabled):visited{color:var(--weui-BRAND)}.weui-btn_disabled,.weui-btn[disabled]{color:var(--weui-FG-4);background-color:var(--weui-BG-1)}.weui-btn_loading .weui-loading{margin:-.2em 8px 0 0}.weui-btn_loading .weui-mask-loading{margin:-.2em 8px 0 0;color:currentColor}.weui-btn_loading .weui-primary-loading{margin:-.2em 8px 0 0;vertical-align:middle;color:currentColor}.weui-btn_loading .weui-primary-loading:before{content:""}.weui-btn_loading.weui-btn_primary{color:var(--weui-WHITE)}.weui-btn_cell{position:relative;display:block;margin-left:auto;margin-right:auto;box-sizing:border-box;font-size:17px;text-align:center;text-decoration:none;color:#fff;line-height:1.41176471;padding:16px;-webkit-tap-highlight-color:rgba(0,0,0,0);overflow:hidden;background-color:var(--weui-BG-5)}.weui-btn_cell+.weui-btn_cell{margin-top:16px}.weui-btn_cell:active{background-color:var(--weui-BG-COLOR-ACTIVE)}.weui-btn_cell__icon{display:inline-block;vertical-align:middle;width:24px;height:24px;margin:-.2em .34em 0 0}.weui-btn_cell-default{color:var(--weui-FG-0)}.weui-btn_cell-primary{color:var(--weui-LINK)}.weui-btn_cell-warn{color:var(--weui-RED)}.weui-bottom-fixed-opr-page{height:100%;display:flex;flex-direction:column}.weui-bottom-fixed-opr-page__content{min-height:0;flex:1;padding-bottom:80px;box-sizing:border-box;overflow-y:auto;-webkit-overflow-scrolling:touch}.weui-bottom-fixed-opr-page__tool{padding:16px 32px 24px;padding:16px calc(32px + constant(safe-area-inset-right)) calc(24px + constant(safe-area-inset-bottom)) calc(32px + constant(safe-area-inset-left));padding:16px calc(32px + env(safe-area-inset-right)) calc(24px + env(safe-area-inset-bottom)) calc(32px + env(safe-area-inset-left));background:#ffffff;position:relative;z-index:50}.weui-bottom-fixed-opr-page__tool:before{content:"";height:80px;background:linear-gradient(to top,#ffffff,rgba(255,255,255,0));position:absolute;bottom:calc(100% - 1px);left:0;right:0;transform:translateZ(0);pointer-events:none}.wx-root[data-weui-theme=dark] .weui-bottom-fixed-opr-page__tool,body[data-weui-theme=dark] .weui-bottom-fixed-opr-page__tool{background:#191919}@media (prefers-color-scheme: dark){.wx-root:not([data-weui-theme=light]) .weui-bottom-fixed-opr-page__tool,body:not([data-weui-theme=light]) .weui-bottom-fixed-opr-page__tool{background:#191919}}.wx-root[data-weui-theme=dark] .weui-bottom-fixed-opr-page__tool:before,body[data-weui-theme=dark] .weui-bottom-fixed-opr-page__tool:before{background:linear-gradient(to top,#191919,rgba(25,25,25,0))}@media (prefers-color-scheme: dark){.wx-root:not([data-weui-theme=light]) .weui-bottom-fixed-opr-page__tool:before,body:not([data-weui-theme=light]) .weui-bottom-fixed-opr-page__tool:before{background:linear-gradient(to top,#191919,rgba(25,25,25,0))}}.weui-bottom-fixed-opr-page__tips{margin-bottom:24px;padding:0 32px;text-align:center}.weui-bottom-fixed-opr-page .weui-bottom-fixed-opr{display:flex;align-items:center;justify-content:center}.weui-bottom-fixed-opr-page .weui-bottom-fixed-opr .weui-btn{width:184px;padding-left:16px;padding-right:16px}.weui-bottom-fixed-opr-page .weui-bottom-fixed-opr .weui-btn:nth-last-child(n+2),.weui-bottom-fixed-opr-page .weui-bottom-fixed-opr .weui-btn:nth-last-child(n+2)+.weui-btn{margin:0 8px;width:136px}.weui-bottom-fixed-opr-page .weui-bottom-fixed-opr .weui-btn:nth-last-child(n+2):first-child,.weui-bottom-fixed-opr-page .weui-bottom-fixed-opr .weui-btn:nth-last-child(n+2)+.weui-btn:first-child{margin-left:0}.weui-bottom-fixed-opr-page .weui-bottom-fixed-opr .weui-btn:nth-last-child(n+2):last-child,.weui-bottom-fixed-opr-page .weui-bottom-fixed-opr .weui-btn:nth-last-child(n+2)+.weui-btn:last-child{margin-right:0}.weui-bottom-fixed-opr-page_btn-wrap .weui-bottom-fixed-opr{flex-direction:column}.weui-bottom-fixed-opr-page_btn-wrap .weui-bottom-fixed-opr .weui-btn:nth-last-child(n+2),.weui-bottom-fixed-opr-page_btn-wrap .weui-bottom-fixed-opr .weui-btn:nth-last-child(n+2)+.weui-btn{width:184px;margin:16px 0 0}.weui-bottom-fixed-opr-page_btn-wrap .weui-bottom-fixed-opr .weui-btn:nth-last-child(n+2):first-child,.weui-bottom-fixed-opr-page_btn-wrap .weui-bottom-fixed-opr .weui-btn:nth-last-child(n+2)+.weui-btn:first-child{margin-top:0}.weui-bottom-fixed-opr-page.weui-form{padding-top:0}.weui-bottom-fixed-opr-page.weui-form .weui-form__bd{padding-top:56px;padding-top:calc(56px + constant(safe-area-inset-top));padding-top:calc(56px + env(safe-area-inset-top))}.weui-bottom-fixed-opr-page.weui-form .weui-form__ft{padding-bottom:0}.weui-bottom-fixed-opr-page.weui-form .weui-form__control-area{margin-bottom:0}.weui-bottom-fixed-opr-page.weui-half-screen-dialog{padding:0}.weui-bottom-fixed-opr-page.weui-half-screen-dialog .weui-half-screen-dialog__hd,.weui-bottom-fixed-opr-page.weui-half-screen-dialog .weui-half-screen-dialog__bd,.weui-bottom-fixed-opr-page.weui-half-screen-dialog .weui-half-screen-dialog__ft{padding-left:24px;padding-left:calc(24px + constant(safe-area-inset-left));padding-left:calc(24px + env(safe-area-inset-left));padding-right:24px;padding-right:calc(24px + constant(safe-area-inset-right));padding-right:calc(24px + env(safe-area-inset-right))}.weui-bottom-fixed-opr-page.weui-half-screen-dialog .weui-half-screen-dialog__bd{padding-bottom:80px}.weui-bottom-fixed-opr-page.weui-half-screen-dialog .weui-half-screen-dialog__ft{padding-bottom:64px;padding-bottom:calc(64px + constant(safe-area-inset-bottom));padding-bottom:calc(64px + env(safe-area-inset-bottom))}.weui-half-screen-dialog_bottom-fixed.weui-half-screen-dialog{padding:0}.weui-half-screen-dialog_bottom-fixed.weui-half-screen-dialog .weui-half-screen-dialog__hd{padding:0 24px;padding:0 calc(24px + constant(safe-area-inset-right)) 0 calc(24px + constant(safe-area-inset-left));padding:0 calc(24px + env(safe-area-inset-right)) 0 calc(24px + env(safe-area-inset-left))}.weui-half-screen-dialog_bottom-fixed.weui-half-screen-dialog .weui-half-screen-dialog__bd{padding-bottom:0;display:flex;flex-direction:column}.weui-half-screen-dialog_bottom-fixed.weui-half-screen-dialog .weui-half-screen-dialog__ft{padding:0}.weui-half-screen-dialog_bottom-fixed.weui-half-screen-dialog .weui-bottom-fixed-opr-page{flex:1;min-height:0}.weui-half-screen-dialog_bottom-fixed.weui-half-screen-dialog .weui-bottom-fixed-opr-page__content{padding:0 24px;padding:0 calc(24px + constant(safe-area-inset-right)) 0 calc(24px + constant(safe-area-inset-left));padding:0 calc(24px + env(safe-area-inset-right)) 0 calc(24px + env(safe-area-inset-left))}.weui-half-screen-dialog_bottom-fixed.weui-half-screen-dialog .weui-bottom-fixed-opr{padding:16px 0 64px;padding:16px 0 calc(64px + constant(safe-area-inset-bottom));padding:16px 0 calc(64px + env(safe-area-inset-bottom))}button.weui-btn,input.weui-btn{border-width:0;outline:0;-webkit-appearance:none}button.weui-btn:focus,input.weui-btn:focus{outline:0}button.weui-btn_inline,input.weui-btn_inline,button.weui-btn_mini,input.weui-btn_mini{width:auto}.weui-btn_medium{font-size:14px;padding:10px 24px;line-height:calc((var(--weui-BTN-HEIGHT-MEDIUM) - 20) / 14)}.weui-btn_mini{display:inline-block;width:auto;line-height:calc((32 - 12) / 14);padding:6px 12px;font-size:14px;border-radius:6px}.weui-btn_xmini{display:inline-block;width:auto;padding:4px 12px;line-height:calc((28 - 8) / 14);font-size:14px;font-weight:500;border-radius:4px}.weui-btn+.weui-btn{margin-top:16px}.weui-btn.weui-btn_mini+.weui-btn.weui-btn_mini{margin-top:auto}.weui-btn.weui-btn_xmini+.weui-btn.weui-btn_xmini{margin-top:auto}.weui-btn.weui-btn_inline+.weui-btn.weui-btn_inline{margin-left:16px}.weui-btn-area{margin:48px 16px 8px}.weui-btn-area_inline{display:flex}.weui-btn-area_inline .weui-btn{margin-top:auto;margin-right:16px;width:100%;flex:1}.weui-btn-area_inline .weui-btn:last-child{margin-right:0}.weui-btn_reset{background:transparent;border:0;padding:0;outline:0;font-size:inherit}.weui-btn_icon{background:transparent;border:0;padding:0;outline:0;font-size:0}.weui-btn_icon:active [class*=weui-icon-]{color:var(--weui-FG-1)}body,.wx-root{--weui-BG-0: #ededed;--weui-BG-1: #f7f7f7;--weui-BG-2: #fff;--weui-BG-3: #f7f7f7;--weui-BG-4: #4c4c4c;--weui-BG-5: #fff;--weui-RED: #fa5151;--weui-ORANGERED: #ff6146;--weui-ORANGE: #fa9d3b;--weui-YELLOW: #ffc300;--weui-GREEN: #91d300;--weui-LIGHTGREEN: #95ec69;--weui-BRAND: #07c160;--weui-BLUE: #10aeff;--weui-INDIGO: #1485ee;--weui-PURPLE: #6467f0;--weui-WHITE: #fff;--weui-LINK: #576b95;--weui-TEXTGREEN: #06ae56;--weui-BG: #fff;--weui-TAG-TEXT-ORANGE: #fa9d3b;--weui-TAG-TEXT-GREEN: #06ae56;--weui-TAG-TEXT-BLUE: #10aeff;--weui-REDORANGE: #ff6146;--weui-BG-0: #EDEDED;--weui-BG-1: #F7F7F7;--weui-BG-2: #FFFFFF;--weui-BG-3: #F7F7F7;--weui-BG-4: #4C4C4C;--weui-BG-5: #FFFFFF;--weui-BLUE-100: #10AEFF;--weui-BLUE-120: #3FBEFF;--weui-BLUE-170: #B7E6FF;--weui-BLUE-80: #0C8BCC;--weui-BLUE-90: #0E9CE6;--weui-BLUE-BG-100: #48A6E2;--weui-BLUE-BG-110: #5AAFE4;--weui-BLUE-BG-130: #7FC0EA;--weui-BLUE-BG-90: #4095CB;--weui-BRAND-100: #07C160;--weui-BRAND-120: #38CD7F;--weui-BRAND-170: #B4ECCE;--weui-BRAND-80: #059A4C;--weui-BRAND-90: #06AE56;--weui-BRAND-BG-100: #2AAE67;--weui-BRAND-BG-110: #3EB575;--weui-BRAND-BG-130: #69C694;--weui-BRAND-BG-90: #259C5C;--weui-FG-0: rgba(0, 0, 0, .9);--weui-FG-0_5: rgba(0, 0, 0, .9);--weui-FG-1: rgba(0, 0, 0, .55);--weui-FG-2: rgba(0, 0, 0, .3);--weui-FG-3: rgba(0, 0, 0, .1);--weui-FG-4: rgba(0, 0, 0, .15);--weui-GLYPH-0: rgba(0, 0, 0, .9);--weui-GLYPH-1: rgba(0, 0, 0, .55);--weui-GLYPH-2: rgba(0, 0, 0, .3);--weui-GLYPH-WHITE-0: rgba(255, 255, 255, .8);--weui-GLYPH-WHITE-1: rgba(255, 255, 255, .5);--weui-GLYPH-WHITE-2: rgba(255, 255, 255, .3);--weui-GLYPH-WHITE-3: #FFFFFF;--weui-GREEN-100: #91D300;--weui-GREEN-120: #A7DB33;--weui-GREEN-170: #DEF1B3;--weui-GREEN-80: #74A800;--weui-GREEN-90: #82BD00;--weui-GREEN-BG-100: #96BE40;--weui-GREEN-BG-110: #A0C452;--weui-GREEN-BG-130: #B5D179;--weui-GREEN-BG-90: #86AA39;--weui-INDIGO-100: #1485EE;--weui-INDIGO-120: #439DF1;--weui-INDIGO-170: #B8DAF9;--weui-INDIGO-80: #106ABE;--weui-INDIGO-90: #1277D6;--weui-INDIGO-BG-100: #2B77BF;--weui-INDIGO-BG-110: #3F84C5;--weui-INDIGO-BG-130: #6BA0D2;--weui-INDIGO-BG-90: #266AAB;--weui-LIGHTGREEN-100: #95EC69;--weui-LIGHTGREEN-120: #AAEF87;--weui-LIGHTGREEN-170: #DEF9D1;--weui-LIGHTGREEN-80: #77BC54;--weui-LIGHTGREEN-90: #85D35E;--weui-LIGHTGREEN-BG-100: #72CF60;--weui-LIGHTGREEN-BG-110: #80D370;--weui-LIGHTGREEN-BG-130: #9CDD90;--weui-LIGHTGREEN-BG-90: #66B956;--weui-LINK-100: #576B95;--weui-LINK-120: #7888AA;--weui-LINK-170: #CCD2DE;--weui-LINK-80: #455577;--weui-LINK-90: #4E6085;--weui-LINKFINDER-100: #002666;--weui-MATERIAL-ATTACHMENTCOLUMN: rgba(245, 245, 245, .95);--weui-MATERIAL-NAVIGATIONBAR: rgba(237, 237, 237, .94);--weui-MATERIAL-REGULAR: rgba(247, 247, 247, .3);--weui-MATERIAL-THICK: rgba(247, 247, 247, .8);--weui-MATERIAL-THIN: rgba(255, 255, 255, .2);--weui-MATERIAL-TOOLBAR: rgba(246, 246, 246, .82);--weui-ORANGE-100: #FA9D3B;--weui-ORANGE-120: #FBB062;--weui-ORANGE-170: #FDE1C3;--weui-ORANGE-80: #C87D2F;--weui-ORANGE-90: #E08C34;--weui-ORANGE-BG-100: #EA7800;--weui-ORANGE-BG-110: #EC8519;--weui-ORANGE-BG-130: #F0A04D;--weui-ORANGE-BG-90: #D26B00;--weui-ORANGERED-100: #FF6146;--weui-OVERLAY: rgba(0, 0, 0, .5);--weui-OVERLAY-WHITE: rgba(242, 242, 242, .8);--weui-PURPLE-100: #6467F0;--weui-PURPLE-120: #8385F3;--weui-PURPLE-170: #D0D1FA;--weui-PURPLE-80: #5052C0;--weui-PURPLE-90: #595CD7;--weui-PURPLE-BG-100: #6769BA;--weui-PURPLE-BG-110: #7678C1;--weui-PURPLE-BG-130: #9496CE;--weui-PURPLE-BG-90: #5C5EA7;--weui-RED-100: #FA5151;--weui-RED-120: #FB7373;--weui-RED-170: #FDCACA;--weui-RED-80: #C84040;--weui-RED-90: #E14949;--weui-RED-BG-100: #CF5148;--weui-RED-BG-110: #D3625A;--weui-RED-BG-130: #DD847E;--weui-RED-BG-90: #B94840;--weui-SECONDARY-BG: rgba(0, 0, 0, .05);--weui-SEPARATOR-0: rgba(0, 0, 0, .1);--weui-SEPARATOR-1: rgba(0, 0, 0, .15);--weui-STATELAYER-HOVERED: rgba(0, 0, 0, .02);--weui-STATELAYER-PRESSED: rgba(0, 0, 0, .1);--weui-STATELAYER-PRESSEDSTRENGTHENED: rgba(0, 0, 0, .2);--weui-YELLOW-100: #FFC300;--weui-YELLOW-120: #FFCF33;--weui-YELLOW-170: #FFECB2;--weui-YELLOW-80: #CC9C00;--weui-YELLOW-90: #E6AF00;--weui-YELLOW-BG-100: #EFB600;--weui-YELLOW-BG-110: #F0BD19;--weui-YELLOW-BG-130: #F3CC4D;--weui-YELLOW-BG-90: #D7A400;--weui-FG-HALF: rgba(0, 0, 0, .9);--weui-RED: #FA5151;--weui-ORANGERED: #FF6146;--weui-ORANGE: #FA9D3B;--weui-YELLOW: #FFC300;--weui-GREEN: #91D300;--weui-LIGHTGREEN: #95EC69;--weui-TEXTGREEN: #06AE56;--weui-BRAND: #07C160;--weui-BLUE: #10AEFF;--weui-INDIGO: #1485EE;--weui-PURPLE: #6467F0;--weui-LINK: #576B95;--weui-TAG-TEXT-ORANGE: #FA9D3B;--weui-TAG-TEXT-GREEN: #06AE56;--weui-TAG-TEXT-BLUE: #10AEFF;--weui-REDORANGE: #FF6146;--weui-TAG-TEXT-BLACK: rgba(0, 0, 0, .5);--weui-TAG-BACKGROUND-BLACK: rgba(0, 0, 0, .05);--weui-WHITE: #FFFFFF;--weui-BG: #FFFFFF;--weui-FG: #000;--weui-FG-5: rgba(0, 0, 0, .05);--weui-TAG-BACKGROUND-ORANGE: rgba(250, 157, 59, .1);--weui-TAG-BACKGROUND-GREEN: rgba(6, 174, 86, .1);--weui-TAG-TEXT-RED: rgba(250, 81, 81, .6);--weui-TAG-BACKGROUND-RED: rgba(250, 81, 81, .1);--weui-TAG-BACKGROUND-BLUE: rgba(16, 174, 255, .1)}@media (prefers-color-scheme: dark){.wx-root:not([data-weui-theme=light]),body:not([data-weui-theme=light]){--weui-BG-0: #111;--weui-BG-1: #1e1e1e;--weui-BG-5: #2c2c2c;--weui-RED: #fa5151;--weui-ORANGERED: #ff6146;--weui-ORANGE: #c87d2f;--weui-YELLOW: #cc9c00;--weui-GREEN: #74a800;--weui-LIGHTGREEN: #3eb575;--weui-BRAND: #07c160;--weui-BLUE: #10aeff;--weui-INDIGO: #1196ff;--weui-PURPLE: #8183ff;--weui-LINK: #7d90a9;--weui-TEXTGREEN: #259c5c;--weui-REDORANGE: #ff6146;--weui-BG-0: #111111;--weui-BG-1: #1E1E1E;--weui-BG-2: #191919;--weui-BG-3: #202020;--weui-BG-4: #404040;--weui-BG-5: #2C2C2C;--weui-BLUE-100: #10AEFF;--weui-BLUE-120: #0C8BCC;--weui-BLUE-170: #04344D;--weui-BLUE-80: #3FBEFF;--weui-BLUE-90: #28B6FF;--weui-BLUE-BG-100: #48A6E2;--weui-BLUE-BG-110: #4095CB;--weui-BLUE-BG-130: #32749E;--weui-BLUE-BG-90: #5AAFE4;--weui-BRAND-100: #07C160;--weui-BRAND-120: #059A4C;--weui-BRAND-170: #023A1C;--weui-BRAND-80: #38CD7F;--weui-BRAND-90: #20C770;--weui-BRAND-BG-100: #2AAE67;--weui-BRAND-BG-110: #259C5C;--weui-BRAND-BG-130: #1D7A48;--weui-BRAND-BG-90: #3EB575;--weui-FG-0: rgba(255, 255, 255, .8);--weui-FG-0_5: rgba(255, 255, 255, .6);--weui-FG-1: rgba(255, 255, 255, .5);--weui-FG-2: rgba(255, 255, 255, .3);--weui-FG-3: rgba(255, 255, 255, .1);--weui-FG-4: rgba(255, 255, 255, .15);--weui-GLYPH-0: rgba(255, 255, 255, .8);--weui-GLYPH-1: rgba(255, 255, 255, .5);--weui-GLYPH-2: rgba(255, 255, 255, .3);--weui-GLYPH-WHITE-0: rgba(255, 255, 255, .8);--weui-GLYPH-WHITE-1: rgba(255, 255, 255, .5);--weui-GLYPH-WHITE-2: rgba(255, 255, 255, .3);--weui-GLYPH-WHITE-3: #FFFFFF;--weui-GREEN-100: #74A800;--weui-GREEN-120: #5C8600;--weui-GREEN-170: #233200;--weui-GREEN-80: #8FB933;--weui-GREEN-90: #82B01A;--weui-GREEN-BG-100: #789833;--weui-GREEN-BG-110: #6B882D;--weui-GREEN-BG-130: #65802B;--weui-GREEN-BG-90: #85A247;--weui-INDIGO-100: #1196FF;--weui-INDIGO-120: #0D78CC;--weui-INDIGO-170: #052D4D;--weui-INDIGO-80: #40ABFF;--weui-INDIGO-90: #28A0FF;--weui-INDIGO-BG-100: #0D78CC;--weui-INDIGO-BG-110: #0B6BB7;--weui-INDIGO-BG-130: #09548F;--weui-INDIGO-BG-90: #2585D1;--weui-LIGHTGREEN-100: #3EB575;--weui-LIGHTGREEN-120: #31905D;--weui-LIGHTGREEN-170: #123522;--weui-LIGHTGREEN-80: #64C390;--weui-LIGHTGREEN-90: #51BC83;--weui-LIGHTGREEN-BG-100: #31905D;--weui-LIGHTGREEN-BG-110: #2C8153;--weui-LIGHTGREEN-BG-130: #226541;--weui-LIGHTGREEN-BG-90: #31905D;--weui-LINK-100: #7D90A9;--weui-LINK-120: #647387;--weui-LINK-170: #252A32;--weui-LINK-80: #97A6BA;--weui-LINK-90: #899AB1;--weui-LINKFINDER-100: #DEE9FF;--weui-MATERIAL-ATTACHMENTCOLUMN: rgba(32, 32, 32, .93);--weui-MATERIAL-NAVIGATIONBAR: rgba(18, 18, 18, .9);--weui-MATERIAL-REGULAR: rgba(37, 37, 37, .6);--weui-MATERIAL-THICK: rgba(34, 34, 34, .9);--weui-MATERIAL-THIN: rgba(95, 95, 95, .4);--weui-MATERIAL-TOOLBAR: rgba(35, 35, 35, .93);--weui-ORANGE-100: #C87D2F;--weui-ORANGE-120: #A06425;--weui-ORANGE-170: #3B250E;--weui-ORANGE-80: #D39758;--weui-ORANGE-90: #CD8943;--weui-ORANGE-BG-100: #BB6000;--weui-ORANGE-BG-110: #A85600;--weui-ORANGE-BG-130: #824300;--weui-ORANGE-BG-90: #C1701A;--weui-ORANGERED-100: #FF6146;--weui-OVERLAY: rgba(0, 0, 0, .8);--weui-OVERLAY-WHITE: rgba(242, 242, 242, .8);--weui-PURPLE-100: #8183FF;--weui-PURPLE-120: #6768CC;--weui-PURPLE-170: #26274C;--weui-PURPLE-80: #9A9BFF;--weui-PURPLE-90: #8D8FFF;--weui-PURPLE-BG-100: #6768CC;--weui-PURPLE-BG-110: #5C5DB7;--weui-PURPLE-BG-130: #48498F;--weui-PURPLE-BG-90: #7677D1;--weui-RED-100: #FA5151;--weui-RED-120: #C84040;--weui-RED-170: #4B1818;--weui-RED-80: #FB7373;--weui-RED-90: #FA6262;--weui-RED-BG-100: #CF5148;--weui-RED-BG-110: #BA4940;--weui-RED-BG-130: #913832;--weui-RED-BG-90: #D3625A;--weui-SECONDARY-BG: rgba(255, 255, 255, .1);--weui-SEPARATOR-0: rgba(255, 255, 255, .05);--weui-SEPARATOR-1: rgba(255, 255, 255, .15);--weui-STATELAYER-HOVERED: rgba(0, 0, 0, .02);--weui-STATELAYER-PRESSED: rgba(255, 255, 255, .1);--weui-STATELAYER-PRESSEDSTRENGTHENED: rgba(255, 255, 255, .2);--weui-YELLOW-100: #CC9C00;--weui-YELLOW-120: #A37C00;--weui-YELLOW-170: #3D2F00;--weui-YELLOW-80: #D6AF33;--weui-YELLOW-90: #D1A519;--weui-YELLOW-BG-100: #BF9100;--weui-YELLOW-BG-110: #AB8200;--weui-YELLOW-BG-130: #866500;--weui-YELLOW-BG-90: #C59C1A;--weui-FG-HALF: rgba(255, 255, 255, .6);--weui-RED: #FA5151;--weui-ORANGERED: #FF6146;--weui-ORANGE: #C87D2F;--weui-YELLOW: #CC9C00;--weui-GREEN: #74A800;--weui-LIGHTGREEN: #3EB575;--weui-TEXTGREEN: #259C5C;--weui-BRAND: #07C160;--weui-BLUE: #10AEFF;--weui-INDIGO: #1196FF;--weui-PURPLE: #8183FF;--weui-LINK: #7D90A9;--weui-REDORANGE: #FF6146;--weui-TAG-TEXT-BLACK: rgba(255, 255, 255, .5);--weui-TAG-BACKGROUND-BLACK: rgba(255, 255, 255, .05);--weui-WHITE: rgba(255, 255, 255, .8);--weui-FG: #fff;--weui-BG: #000;--weui-FG-5: rgba(255, 255, 255, .1);--weui-TAG-BACKGROUND-ORANGE: rgba(250, 157, 59, .1);--weui-TAG-BACKGROUND-GREEN: rgba(6, 174, 86, .1);--weui-TAG-TEXT-RED: rgba(250, 81, 81, .6);--weui-TAG-BACKGROUND-RED: rgba(250, 81, 81, .1);--weui-TAG-BACKGROUND-BLUE: rgba(16, 174, 255, .1);--weui-TAG-TEXT-ORANGE: rgba(250, 157, 59, .6);--weui-TAG-TEXT-GREEN: rgba(6, 174, 86, .6);--weui-TAG-TEXT-BLUE: rgba(16, 174, 255, .6)}}.wx-root[data-weui-theme=dark],body[data-weui-theme=dark]{--weui-BG-0: #111;--weui-BG-1: #1e1e1e;--weui-BG-5: #2c2c2c;--weui-RED: #fa5151;--weui-ORANGERED: #ff6146;--weui-ORANGE: #c87d2f;--weui-YELLOW: #cc9c00;--weui-GREEN: #74a800;--weui-LIGHTGREEN: #3eb575;--weui-BRAND: #07c160;--weui-BLUE: #10aeff;--weui-INDIGO: #1196ff;--weui-PURPLE: #8183ff;--weui-LINK: #7d90a9;--weui-TEXTGREEN: #259c5c;--weui-REDORANGE: #ff6146;--weui-BG-0: #111111;--weui-BG-1: #1E1E1E;--weui-BG-2: #191919;--weui-BG-3: #202020;--weui-BG-4: #404040;--weui-BG-5: #2C2C2C;--weui-BLUE-100: #10AEFF;--weui-BLUE-120: #0C8BCC;--weui-BLUE-170: #04344D;--weui-BLUE-80: #3FBEFF;--weui-BLUE-90: #28B6FF;--weui-BLUE-BG-100: #48A6E2;--weui-BLUE-BG-110: #4095CB;--weui-BLUE-BG-130: #32749E;--weui-BLUE-BG-90: #5AAFE4;--weui-BRAND-100: #07C160;--weui-BRAND-120: #059A4C;--weui-BRAND-170: #023A1C;--weui-BRAND-80: #38CD7F;--weui-BRAND-90: #20C770;--weui-BRAND-BG-100: #2AAE67;--weui-BRAND-BG-110: #259C5C;--weui-BRAND-BG-130: #1D7A48;--weui-BRAND-BG-90: #3EB575;--weui-FG-0: rgba(255, 255, 255, .8);--weui-FG-0_5: rgba(255, 255, 255, .6);--weui-FG-1: rgba(255, 255, 255, .5);--weui-FG-2: rgba(255, 255, 255, .3);--weui-FG-3: rgba(255, 255, 255, .1);--weui-FG-4: rgba(255, 255, 255, .15);--weui-GLYPH-0: rgba(255, 255, 255, .8);--weui-GLYPH-1: rgba(255, 255, 255, .5);--weui-GLYPH-2: rgba(255, 255, 255, .3);--weui-GLYPH-WHITE-0: rgba(255, 255, 255, .8);--weui-GLYPH-WHITE-1: rgba(255, 255, 255, .5);--weui-GLYPH-WHITE-2: rgba(255, 255, 255, .3);--weui-GLYPH-WHITE-3: #FFFFFF;--weui-GREEN-100: #74A800;--weui-GREEN-120: #5C8600;--weui-GREEN-170: #233200;--weui-GREEN-80: #8FB933;--weui-GREEN-90: #82B01A;--weui-GREEN-BG-100: #789833;--weui-GREEN-BG-110: #6B882D;--weui-GREEN-BG-130: #65802B;--weui-GREEN-BG-90: #85A247;--weui-INDIGO-100: #1196FF;--weui-INDIGO-120: #0D78CC;--weui-INDIGO-170: #052D4D;--weui-INDIGO-80: #40ABFF;--weui-INDIGO-90: #28A0FF;--weui-INDIGO-BG-100: #0D78CC;--weui-INDIGO-BG-110: #0B6BB7;--weui-INDIGO-BG-130: #09548F;--weui-INDIGO-BG-90: #2585D1;--weui-LIGHTGREEN-100: #3EB575;--weui-LIGHTGREEN-120: #31905D;--weui-LIGHTGREEN-170: #123522;--weui-LIGHTGREEN-80: #64C390;--weui-LIGHTGREEN-90: #51BC83;--weui-LIGHTGREEN-BG-100: #31905D;--weui-LIGHTGREEN-BG-110: #2C8153;--weui-LIGHTGREEN-BG-130: #226541;--weui-LIGHTGREEN-BG-90: #31905D;--weui-LINK-100: #7D90A9;--weui-LINK-120: #647387;--weui-LINK-170: #252A32;--weui-LINK-80: #97A6BA;--weui-LINK-90: #899AB1;--weui-LINKFINDER-100: #DEE9FF;--weui-MATERIAL-ATTACHMENTCOLUMN: rgba(32, 32, 32, .93);--weui-MATERIAL-NAVIGATIONBAR: rgba(18, 18, 18, .9);--weui-MATERIAL-REGULAR: rgba(37, 37, 37, .6);--weui-MATERIAL-THICK: rgba(34, 34, 34, .9);--weui-MATERIAL-THIN: rgba(95, 95, 95, .4);--weui-MATERIAL-TOOLBAR: rgba(35, 35, 35, .93);--weui-ORANGE-100: #C87D2F;--weui-ORANGE-120: #A06425;--weui-ORANGE-170: #3B250E;--weui-ORANGE-80: #D39758;--weui-ORANGE-90: #CD8943;--weui-ORANGE-BG-100: #BB6000;--weui-ORANGE-BG-110: #A85600;--weui-ORANGE-BG-130: #824300;--weui-ORANGE-BG-90: #C1701A;--weui-ORANGERED-100: #FF6146;--weui-OVERLAY: rgba(0, 0, 0, .8);--weui-OVERLAY-WHITE: rgba(242, 242, 242, .8);--weui-PURPLE-100: #8183FF;--weui-PURPLE-120: #6768CC;--weui-PURPLE-170: #26274C;--weui-PURPLE-80: #9A9BFF;--weui-PURPLE-90: #8D8FFF;--weui-PURPLE-BG-100: #6768CC;--weui-PURPLE-BG-110: #5C5DB7;--weui-PURPLE-BG-130: #48498F;--weui-PURPLE-BG-90: #7677D1;--weui-RED-100: #FA5151;--weui-RED-120: #C84040;--weui-RED-170: #4B1818;--weui-RED-80: #FB7373;--weui-RED-90: #FA6262;--weui-RED-BG-100: #CF5148;--weui-RED-BG-110: #BA4940;--weui-RED-BG-130: #913832;--weui-RED-BG-90: #D3625A;--weui-SECONDARY-BG: rgba(255, 255, 255, .1);--weui-SEPARATOR-0: rgba(255, 255, 255, .05);--weui-SEPARATOR-1: rgba(255, 255, 255, .15);--weui-STATELAYER-HOVERED: rgba(0, 0, 0, .02);--weui-STATELAYER-PRESSED: rgba(255, 255, 255, .1);--weui-STATELAYER-PRESSEDSTRENGTHENED: rgba(255, 255, 255, .2);--weui-YELLOW-100: #CC9C00;--weui-YELLOW-120: #A37C00;--weui-YELLOW-170: #3D2F00;--weui-YELLOW-80: #D6AF33;--weui-YELLOW-90: #D1A519;--weui-YELLOW-BG-100: #BF9100;--weui-YELLOW-BG-110: #AB8200;--weui-YELLOW-BG-130: #866500;--weui-YELLOW-BG-90: #C59C1A;--weui-FG-HALF: rgba(255, 255, 255, .6);--weui-RED: #FA5151;--weui-ORANGERED: #FF6146;--weui-ORANGE: #C87D2F;--weui-YELLOW: #CC9C00;--weui-GREEN: #74A800;--weui-LIGHTGREEN: #3EB575;--weui-TEXTGREEN: #259C5C;--weui-BRAND: #07C160;--weui-BLUE: #10AEFF;--weui-INDIGO: #1196FF;--weui-PURPLE: #8183FF;--weui-LINK: #7D90A9;--weui-REDORANGE: #FF6146;--weui-TAG-TEXT-BLACK: rgba(255, 255, 255, .5);--weui-TAG-BACKGROUND-BLACK: rgba(255, 255, 255, .05);--weui-WHITE: rgba(255, 255, 255, .8);--weui-FG: #fff;--weui-BG: #000;--weui-FG-5: rgba(255, 255, 255, .1);--weui-TAG-BACKGROUND-ORANGE: rgba(250, 157, 59, .1);--weui-TAG-BACKGROUND-GREEN: rgba(6, 174, 86, .1);--weui-TAG-TEXT-RED: rgba(250, 81, 81, .6);--weui-TAG-BACKGROUND-RED: rgba(250, 81, 81, .1);--weui-TAG-BACKGROUND-BLUE: rgba(16, 174, 255, .1);--weui-TAG-TEXT-ORANGE: rgba(250, 157, 59, .6);--weui-TAG-TEXT-GREEN: rgba(6, 174, 86, .6);--weui-TAG-TEXT-BLUE: rgba(16, 174, 255, .6)}.wx-root[data-weui-mode=care],body[data-weui-mode=care]{--weui-BG-0: #ededed;--weui-BG-1: #f7f7f7;--weui-BG-2: #fff;--weui-BG-3: #f7f7f7;--weui-BG-4: #4c4c4c;--weui-BG-5: #fff;--weui-RED: #dc3636;--weui-ORANGERED: #d14730;--weui-ORANGE: #e17719;--weui-YELLOW: #bb8e00;--weui-GREEN: #4f8400;--weui-LIGHTGREEN: #2e8800;--weui-BLUE: #007dbb;--weui-INDIGO: #0075e2;--weui-PURPLE: #6265f1;--weui-WHITE: #fff;--weui-LINK: #576b95;--weui-TEXTGREEN: #06ae56;--weui-BG: #fff;--weui-TAG-TEXT-ORANGE: #e17719;--weui-TAG-TEXT-GREEN: #06ae56;--weui-TAG-TEXT-BLUE: #007dbb;--weui-REDORANGE: #d14730;--weui-BG-0: #EDEDED;--weui-BG-1: #F7F7F7;--weui-BG-2: #FFFFFF;--weui-BG-3: #F7F7F7;--weui-BG-4: #4C4C4C;--weui-BG-5: #FFFFFF;--weui-BLUE-100: #007DBB;--weui-BLUE-120: #3FBEFF;--weui-BLUE-170: #B7E6FF;--weui-BLUE-80: #0C8BCC;--weui-BLUE-90: #0E9CE6;--weui-BLUE-BG-100: #48A6E2;--weui-BLUE-BG-110: #5AAFE4;--weui-BLUE-BG-130: #7FC0EA;--weui-BLUE-BG-90: #4095CB;--weui-BRAND-100: #018942;--weui-BRAND-120: #38CD7F;--weui-BRAND-170: #B4ECCE;--weui-BRAND-80: #059A4C;--weui-BRAND-90: #06AE56;--weui-BRAND-BG-100: #2AAE67;--weui-BRAND-BG-110: #3EB575;--weui-BRAND-BG-130: #69C694;--weui-BRAND-BG-90: #259C5C;--weui-FG-0: #000000;--weui-FG-0_5: #000000;--weui-FG-1: rgba(0, 0, 0, .6);--weui-FG-2: rgba(0, 0, 0, .42);--weui-FG-3: rgba(0, 0, 0, .1);--weui-FG-4: rgba(0, 0, 0, .15);--weui-GLYPH-0: #000000;--weui-GLYPH-1: rgba(0, 0, 0, .6);--weui-GLYPH-2: rgba(0, 0, 0, .42);--weui-GLYPH-WHITE-0: rgba(255, 255, 255, .85);--weui-GLYPH-WHITE-1: rgba(255, 255, 255, .55);--weui-GLYPH-WHITE-2: rgba(255, 255, 255, .35);--weui-GLYPH-WHITE-3: #FFFFFF;--weui-GREEN-100: #4F8400;--weui-GREEN-120: #A7DB33;--weui-GREEN-170: #DEF1B3;--weui-GREEN-80: #74A800;--weui-GREEN-90: #82BD00;--weui-GREEN-BG-100: #96BE40;--weui-GREEN-BG-110: #A0C452;--weui-GREEN-BG-130: #B5D179;--weui-GREEN-BG-90: #86AA39;--weui-INDIGO-100: #0075E2;--weui-INDIGO-120: #439DF1;--weui-INDIGO-170: #B8DAF9;--weui-INDIGO-80: #106ABE;--weui-INDIGO-90: #1277D6;--weui-INDIGO-BG-100: #2B77BF;--weui-INDIGO-BG-110: #3F84C5;--weui-INDIGO-BG-130: #6BA0D2;--weui-INDIGO-BG-90: #266AAB;--weui-LIGHTGREEN-100: #2E8800;--weui-LIGHTGREEN-120: #AAEF87;--weui-LIGHTGREEN-170: #DEF9D1;--weui-LIGHTGREEN-80: #77BC54;--weui-LIGHTGREEN-90: #85D35E;--weui-LIGHTGREEN-BG-100: #72CF60;--weui-LIGHTGREEN-BG-110: #80D370;--weui-LIGHTGREEN-BG-130: #9CDD90;--weui-LIGHTGREEN-BG-90: #66B956;--weui-LINK-100: #576B95;--weui-LINK-120: #7888AA;--weui-LINK-170: #CCD2DE;--weui-LINK-80: #455577;--weui-LINK-90: #4E6085;--weui-LINKFINDER-100: #002666;--weui-MATERIAL-ATTACHMENTCOLUMN: rgba(245, 245, 245, .95);--weui-MATERIAL-NAVIGATIONBAR: rgba(237, 237, 237, .94);--weui-MATERIAL-REGULAR: rgba(247, 247, 247, .3);--weui-MATERIAL-THICK: rgba(247, 247, 247, .8);--weui-MATERIAL-THIN: rgba(255, 255, 255, .2);--weui-MATERIAL-TOOLBAR: rgba(246, 246, 246, .82);--weui-ORANGE-100: #E17719;--weui-ORANGE-120: #FBB062;--weui-ORANGE-170: #FDE1C3;--weui-ORANGE-80: #C87D2F;--weui-ORANGE-90: #E08C34;--weui-ORANGE-BG-100: #EA7800;--weui-ORANGE-BG-110: #EC8519;--weui-ORANGE-BG-130: #F0A04D;--weui-ORANGE-BG-90: #D26B00;--weui-ORANGERED-100: #D14730;--weui-OVERLAY: rgba(0, 0, 0, .5);--weui-OVERLAY-WHITE: rgba(242, 242, 242, .8);--weui-PURPLE-100: #6265F1;--weui-PURPLE-120: #8385F3;--weui-PURPLE-170: #D0D1FA;--weui-PURPLE-80: #5052C0;--weui-PURPLE-90: #595CD7;--weui-PURPLE-BG-100: #6769BA;--weui-PURPLE-BG-110: #7678C1;--weui-PURPLE-BG-130: #9496CE;--weui-PURPLE-BG-90: #5C5EA7;--weui-RED-100: #DC3636;--weui-RED-120: #FB7373;--weui-RED-170: #FDCACA;--weui-RED-80: #C84040;--weui-RED-90: #E14949;--weui-RED-BG-100: #CF5148;--weui-RED-BG-110: #D3625A;--weui-RED-BG-130: #DD847E;--weui-RED-BG-90: #B94840;--weui-SECONDARY-BG: rgba(0, 0, 0, .1);--weui-SEPARATOR-0: rgba(0, 0, 0, .1);--weui-SEPARATOR-1: rgba(0, 0, 0, .15);--weui-STATELAYER-HOVERED: rgba(0, 0, 0, .02);--weui-STATELAYER-PRESSED: rgba(0, 0, 0, .1);--weui-STATELAYER-PRESSEDSTRENGTHENED: rgba(0, 0, 0, .2);--weui-YELLOW-100: #BB8E00;--weui-YELLOW-120: #FFCF33;--weui-YELLOW-170: #FFECB2;--weui-YELLOW-80: #CC9C00;--weui-YELLOW-90: #E6AF00;--weui-YELLOW-BG-100: #EFB600;--weui-YELLOW-BG-110: #F0BD19;--weui-YELLOW-BG-130: #F3CC4D;--weui-YELLOW-BG-90: #D7A400;--weui-FG-HALF: #000000;--weui-RED: #DC3636;--weui-ORANGERED: #D14730;--weui-ORANGE: #E17719;--weui-YELLOW: #BB8E00;--weui-GREEN: #4F8400;--weui-LIGHTGREEN: #2E8800;--weui-TEXTGREEN: #06AE56;--weui-BRAND: #018942;--weui-BLUE: #007DBB;--weui-INDIGO: #0075E2;--weui-PURPLE: #6265F1;--weui-LINK: #576B95;--weui-TAG-TEXT-ORANGE: #E17719;--weui-TAG-TEXT-GREEN: #06AE56;--weui-TAG-TEXT-BLUE: #007DBB;--weui-REDORANGE: #D14730;--weui-TAG-TEXT-BLACK: rgba(0, 0, 0, .5);--weui-WHITE: #FFFFFF;--weui-BG: #FFFFFF;--weui-FG: #000;--weui-FG-5: rgba(0, 0, 0, .05);--weui-TAG-BACKGROUND-ORANGE: rgba(225, 119, 25, .1);--weui-TAG-BACKGROUND-GREEN: rgba(6, 174, 86, .1);--weui-TAG-TEXT-RED: rgba(250, 81, 81, .6);--weui-TAG-BACKGROUND-RED: rgba(250, 81, 81, .1);--weui-TAG-BACKGROUND-BLUE: rgba(0, 125, 187, .1);--weui-TAG-BACKGROUND-BLACK: rgba(0, 0, 0, .05)}@media (prefers-color-scheme: dark){.wx-root[data-weui-mode=care]:not([data-weui-theme=light]),body[data-weui-mode=care]:not([data-weui-theme=light]){--weui-BG-0: #111;--weui-BG-1: #1e1e1e;--weui-BG-5: #2c2c2c;--weui-RED: #fa5151;--weui-ORANGERED: #ff6146;--weui-ORANGE: #c87d2f;--weui-YELLOW: #cc9c00;--weui-GREEN: #74a800;--weui-LIGHTGREEN: #3eb575;--weui-BRAND: #07c160;--weui-BLUE: #10aeff;--weui-INDIGO: #1196ff;--weui-PURPLE: #8183ff;--weui-LINK: #7d90a9;--weui-TEXTGREEN: #259c5c;--weui-REDORANGE: #ff6146;--weui-BG-0: #111111;--weui-BG-1: #1E1E1E;--weui-BG-2: #191919;--weui-BG-3: #202020;--weui-BG-4: #404040;--weui-BG-5: #2C2C2C;--weui-BLUE-100: #10AEFF;--weui-BLUE-120: #0C8BCC;--weui-BLUE-170: #04344D;--weui-BLUE-80: #3FBEFF;--weui-BLUE-90: #28B6FF;--weui-BLUE-BG-100: #48A6E2;--weui-BLUE-BG-110: #4095CB;--weui-BLUE-BG-130: #32749E;--weui-BLUE-BG-90: #5AAFE4;--weui-BRAND-100: #07C160;--weui-BRAND-120: #059A4C;--weui-BRAND-170: #023A1C;--weui-BRAND-80: #38CD7F;--weui-BRAND-90: #20C770;--weui-BRAND-BG-100: #2AAE67;--weui-BRAND-BG-110: #259C5C;--weui-BRAND-BG-130: #1D7A48;--weui-BRAND-BG-90: #3EB575;--weui-FG-0: rgba(255, 255, 255, .85);--weui-FG-0_5: rgba(255, 255, 255, .65);--weui-FG-1: rgba(255, 255, 255, .55);--weui-FG-2: rgba(255, 255, 255, .35);--weui-FG-3: rgba(255, 255, 255, .1);--weui-FG-4: rgba(255, 255, 255, .15);--weui-GLYPH-0: rgba(255, 255, 255, .85);--weui-GLYPH-1: rgba(255, 255, 255, .55);--weui-GLYPH-2: rgba(255, 255, 255, .35);--weui-GLYPH-WHITE-0: rgba(255, 255, 255, .85);--weui-GLYPH-WHITE-1: rgba(255, 255, 255, .55);--weui-GLYPH-WHITE-2: rgba(255, 255, 255, .35);--weui-GLYPH-WHITE-3: #FFFFFF;--weui-GREEN-100: #74A800;--weui-GREEN-120: #5C8600;--weui-GREEN-170: #233200;--weui-GREEN-80: #8FB933;--weui-GREEN-90: #82B01A;--weui-GREEN-BG-100: #789833;--weui-GREEN-BG-110: #6B882D;--weui-GREEN-BG-130: #65802B;--weui-GREEN-BG-90: #85A247;--weui-INDIGO-100: #1196FF;--weui-INDIGO-120: #0D78CC;--weui-INDIGO-170: #052D4D;--weui-INDIGO-80: #40ABFF;--weui-INDIGO-90: #28A0FF;--weui-INDIGO-BG-100: #0D78CC;--weui-INDIGO-BG-110: #0B6BB7;--weui-INDIGO-BG-130: #09548F;--weui-INDIGO-BG-90: #2585D1;--weui-LIGHTGREEN-100: #3EB575;--weui-LIGHTGREEN-120: #31905D;--weui-LIGHTGREEN-170: #123522;--weui-LIGHTGREEN-80: #64C390;--weui-LIGHTGREEN-90: #51BC83;--weui-LIGHTGREEN-BG-100: #31905D;--weui-LIGHTGREEN-BG-110: #2C8153;--weui-LIGHTGREEN-BG-130: #226541;--weui-LIGHTGREEN-BG-90: #31905D;--weui-LINK-100: #7D90A9;--weui-LINK-120: #647387;--weui-LINK-170: #252A32;--weui-LINK-80: #97A6BA;--weui-LINK-90: #899AB1;--weui-LINKFINDER-100: #DEE9FF;--weui-MATERIAL-ATTACHMENTCOLUMN: rgba(32, 32, 32, .93);--weui-MATERIAL-NAVIGATIONBAR: rgba(18, 18, 18, .9);--weui-MATERIAL-REGULAR: rgba(37, 37, 37, .6);--weui-MATERIAL-THICK: rgba(34, 34, 34, .9);--weui-MATERIAL-THIN: rgba(245, 245, 245, .4);--weui-MATERIAL-TOOLBAR: rgba(35, 35, 35, .93);--weui-ORANGE-100: #C87D2F;--weui-ORANGE-120: #A06425;--weui-ORANGE-170: #3B250E;--weui-ORANGE-80: #D39758;--weui-ORANGE-90: #CD8943;--weui-ORANGE-BG-100: #BB6000;--weui-ORANGE-BG-110: #A85600;--weui-ORANGE-BG-130: #824300;--weui-ORANGE-BG-90: #C1701A;--weui-ORANGERED-100: #FF6146;--weui-OVERLAY: rgba(0, 0, 0, .8);--weui-OVERLAY-WHITE: rgba(242, 242, 242, .8);--weui-PURPLE-100: #8183FF;--weui-PURPLE-120: #6768CC;--weui-PURPLE-170: #26274C;--weui-PURPLE-80: #9A9BFF;--weui-PURPLE-90: #8D8FFF;--weui-PURPLE-BG-100: #6768CC;--weui-PURPLE-BG-110: #5C5DB7;--weui-PURPLE-BG-130: #48498F;--weui-PURPLE-BG-90: #7677D1;--weui-RED-100: #FA5151;--weui-RED-120: #C84040;--weui-RED-170: #4B1818;--weui-RED-80: #FB7373;--weui-RED-90: #FA6262;--weui-RED-BG-100: #CF5148;--weui-RED-BG-110: #BA4940;--weui-RED-BG-130: #913832;--weui-RED-BG-90: #D3625A;--weui-SECONDARY-BG: rgba(255, 255, 255, .15);--weui-SEPARATOR-0: rgba(255, 255, 255, .05);--weui-SEPARATOR-1: rgba(255, 255, 255, .15);--weui-STATELAYER-HOVERED: rgba(0, 0, 0, .02);--weui-STATELAYER-PRESSED: rgba(255, 255, 255, .1);--weui-STATELAYER-PRESSEDSTRENGTHENED: rgba(255, 255, 255, .2);--weui-YELLOW-100: #CC9C00;--weui-YELLOW-120: #A37C00;--weui-YELLOW-170: #3D2F00;--weui-YELLOW-80: #D6AF33;--weui-YELLOW-90: #D1A519;--weui-YELLOW-BG-100: #BF9100;--weui-YELLOW-BG-110: #AB8200;--weui-YELLOW-BG-130: #866500;--weui-YELLOW-BG-90: #C59C1A;--weui-FG-HALF: rgba(255, 255, 255, .65);--weui-RED: #FA5151;--weui-ORANGERED: #FF6146;--weui-ORANGE: #C87D2F;--weui-YELLOW: #CC9C00;--weui-GREEN: #74A800;--weui-LIGHTGREEN: #3EB575;--weui-TEXTGREEN: #259C5C;--weui-BRAND: #07C160;--weui-BLUE: #10AEFF;--weui-INDIGO: #1196FF;--weui-PURPLE: #8183FF;--weui-LINK: #7D90A9;--weui-REDORANGE: #FF6146;--weui-TAG-BACKGROUND-BLACK: rgba(255, 255, 255, .05);--weui-FG: #fff;--weui-WHITE: rgba(255, 255, 255, .8);--weui-FG-5: rgba(255, 255, 255, .1);--weui-TAG-BACKGROUND-ORANGE: rgba(250, 157, 59, .1);--weui-TAG-BACKGROUND-GREEN: rgba(6, 174, 86, .1);--weui-TAG-TEXT-RED: rgba(250, 81, 81, .6);--weui-TAG-BACKGROUND-RED: rgba(250, 81, 81, .1);--weui-TAG-BACKGROUND-BLUE: rgba(16, 174, 255, .1);--weui-TAG-TEXT-ORANGE: rgba(250, 157, 59, .6);--weui-BG: #000;--weui-TAG-TEXT-GREEN: rgba(6, 174, 86, .6);--weui-TAG-TEXT-BLUE: rgba(16, 174, 255, .6);--weui-TAG-TEXT-BLACK: rgba(255, 255, 255, .5)}}.wx-root[data-weui-mode=care][data-weui-theme=dark],body[data-weui-mode=care][data-weui-theme=dark]{--weui-BG-0: #111;--weui-BG-1: #1e1e1e;--weui-BG-5: #2c2c2c;--weui-RED: #fa5151;--weui-ORANGERED: #ff6146;--weui-ORANGE: #c87d2f;--weui-YELLOW: #cc9c00;--weui-GREEN: #74a800;--weui-LIGHTGREEN: #3eb575;--weui-BRAND: #07c160;--weui-BLUE: #10aeff;--weui-INDIGO: #1196ff;--weui-PURPLE: #8183ff;--weui-LINK: #7d90a9;--weui-TEXTGREEN: #259c5c;--weui-REDORANGE: #ff6146;--weui-BG-0: #111111;--weui-BG-1: #1E1E1E;--weui-BG-2: #191919;--weui-BG-3: #202020;--weui-BG-4: #404040;--weui-BG-5: #2C2C2C;--weui-BLUE-100: #10AEFF;--weui-BLUE-120: #0C8BCC;--weui-BLUE-170: #04344D;--weui-BLUE-80: #3FBEFF;--weui-BLUE-90: #28B6FF;--weui-BLUE-BG-100: #48A6E2;--weui-BLUE-BG-110: #4095CB;--weui-BLUE-BG-130: #32749E;--weui-BLUE-BG-90: #5AAFE4;--weui-BRAND-100: #07C160;--weui-BRAND-120: #059A4C;--weui-BRAND-170: #023A1C;--weui-BRAND-80: #38CD7F;--weui-BRAND-90: #20C770;--weui-BRAND-BG-100: #2AAE67;--weui-BRAND-BG-110: #259C5C;--weui-BRAND-BG-130: #1D7A48;--weui-BRAND-BG-90: #3EB575;--weui-FG-0: rgba(255, 255, 255, .85);--weui-FG-0_5: rgba(255, 255, 255, .65);--weui-FG-1: rgba(255, 255, 255, .55);--weui-FG-2: rgba(255, 255, 255, .35);--weui-FG-3: rgba(255, 255, 255, .1);--weui-FG-4: rgba(255, 255, 255, .15);--weui-GLYPH-0: rgba(255, 255, 255, .85);--weui-GLYPH-1: rgba(255, 255, 255, .55);--weui-GLYPH-2: rgba(255, 255, 255, .35);--weui-GLYPH-WHITE-0: rgba(255, 255, 255, .85);--weui-GLYPH-WHITE-1: rgba(255, 255, 255, .55);--weui-GLYPH-WHITE-2: rgba(255, 255, 255, .35);--weui-GLYPH-WHITE-3: #FFFFFF;--weui-GREEN-100: #74A800;--weui-GREEN-120: #5C8600;--weui-GREEN-170: #233200;--weui-GREEN-80: #8FB933;--weui-GREEN-90: #82B01A;--weui-GREEN-BG-100: #789833;--weui-GREEN-BG-110: #6B882D;--weui-GREEN-BG-130: #65802B;--weui-GREEN-BG-90: #85A247;--weui-INDIGO-100: #1196FF;--weui-INDIGO-120: #0D78CC;--weui-INDIGO-170: #052D4D;--weui-INDIGO-80: #40ABFF;--weui-INDIGO-90: #28A0FF;--weui-INDIGO-BG-100: #0D78CC;--weui-INDIGO-BG-110: #0B6BB7;--weui-INDIGO-BG-130: #09548F;--weui-INDIGO-BG-90: #2585D1;--weui-LIGHTGREEN-100: #3EB575;--weui-LIGHTGREEN-120: #31905D;--weui-LIGHTGREEN-170: #123522;--weui-LIGHTGREEN-80: #64C390;--weui-LIGHTGREEN-90: #51BC83;--weui-LIGHTGREEN-BG-100: #31905D;--weui-LIGHTGREEN-BG-110: #2C8153;--weui-LIGHTGREEN-BG-130: #226541;--weui-LIGHTGREEN-BG-90: #31905D;--weui-LINK-100: #7D90A9;--weui-LINK-120: #647387;--weui-LINK-170: #252A32;--weui-LINK-80: #97A6BA;--weui-LINK-90: #899AB1;--weui-LINKFINDER-100: #DEE9FF;--weui-MATERIAL-ATTACHMENTCOLUMN: rgba(32, 32, 32, .93);--weui-MATERIAL-NAVIGATIONBAR: rgba(18, 18, 18, .9);--weui-MATERIAL-REGULAR: rgba(37, 37, 37, .6);--weui-MATERIAL-THICK: rgba(34, 34, 34, .9);--weui-MATERIAL-THIN: rgba(245, 245, 245, .4);--weui-MATERIAL-TOOLBAR: rgba(35, 35, 35, .93);--weui-ORANGE-100: #C87D2F;--weui-ORANGE-120: #A06425;--weui-ORANGE-170: #3B250E;--weui-ORANGE-80: #D39758;--weui-ORANGE-90: #CD8943;--weui-ORANGE-BG-100: #BB6000;--weui-ORANGE-BG-110: #A85600;--weui-ORANGE-BG-130: #824300;--weui-ORANGE-BG-90: #C1701A;--weui-ORANGERED-100: #FF6146;--weui-OVERLAY: rgba(0, 0, 0, .8);--weui-OVERLAY-WHITE: rgba(242, 242, 242, .8);--weui-PURPLE-100: #8183FF;--weui-PURPLE-120: #6768CC;--weui-PURPLE-170: #26274C;--weui-PURPLE-80: #9A9BFF;--weui-PURPLE-90: #8D8FFF;--weui-PURPLE-BG-100: #6768CC;--weui-PURPLE-BG-110: #5C5DB7;--weui-PURPLE-BG-130: #48498F;--weui-PURPLE-BG-90: #7677D1;--weui-RED-100: #FA5151;--weui-RED-120: #C84040;--weui-RED-170: #4B1818;--weui-RED-80: #FB7373;--weui-RED-90: #FA6262;--weui-RED-BG-100: #CF5148;--weui-RED-BG-110: #BA4940;--weui-RED-BG-130: #913832;--weui-RED-BG-90: #D3625A;--weui-SECONDARY-BG: rgba(255, 255, 255, .15);--weui-SEPARATOR-0: rgba(255, 255, 255, .05);--weui-SEPARATOR-1: rgba(255, 255, 255, .15);--weui-STATELAYER-HOVERED: rgba(0, 0, 0, .02);--weui-STATELAYER-PRESSED: rgba(255, 255, 255, .1);--weui-STATELAYER-PRESSEDSTRENGTHENED: rgba(255, 255, 255, .2);--weui-YELLOW-100: #CC9C00;--weui-YELLOW-120: #A37C00;--weui-YELLOW-170: #3D2F00;--weui-YELLOW-80: #D6AF33;--weui-YELLOW-90: #D1A519;--weui-YELLOW-BG-100: #BF9100;--weui-YELLOW-BG-110: #AB8200;--weui-YELLOW-BG-130: #866500;--weui-YELLOW-BG-90: #C59C1A;--weui-FG-HALF: rgba(255, 255, 255, .65);--weui-RED: #FA5151;--weui-ORANGERED: #FF6146;--weui-ORANGE: #C87D2F;--weui-YELLOW: #CC9C00;--weui-GREEN: #74A800;--weui-LIGHTGREEN: #3EB575;--weui-TEXTGREEN: #259C5C;--weui-BRAND: #07C160;--weui-BLUE: #10AEFF;--weui-INDIGO: #1196FF;--weui-PURPLE: #8183FF;--weui-LINK: #7D90A9;--weui-REDORANGE: #FF6146;--weui-TAG-BACKGROUND-BLACK: rgba(255, 255, 255, .05);--weui-FG: #fff;--weui-WHITE: rgba(255, 255, 255, .8);--weui-FG-5: rgba(255, 255, 255, .1);--weui-TAG-BACKGROUND-ORANGE: rgba(250, 157, 59, .1);--weui-TAG-BACKGROUND-GREEN: rgba(6, 174, 86, .1);--weui-TAG-TEXT-RED: rgba(250, 81, 81, .6);--weui-TAG-BACKGROUND-RED: rgba(250, 81, 81, .1);--weui-TAG-BACKGROUND-BLUE: rgba(16, 174, 255, .1);--weui-TAG-TEXT-ORANGE: rgba(250, 157, 59, .6);--weui-BG: #000;--weui-TAG-TEXT-GREEN: rgba(6, 174, 86, .6);--weui-TAG-TEXT-BLUE: rgba(16, 174, 255, .6);--weui-TAG-TEXT-BLACK: rgba(255, 255, 255, .5)}.wx-root{position:relative;pointer-events:auto;font-family:system-ui,-apple-system,BlinkMacSystemFont,Helvetica Neue,PingFang SC,Hiragino Sans GB,Microsoft YaHei UI,Microsoft YaHei,Arial,sans-serif}.wx_card_root{position:relative}.wxw_hide{display:none!important}.wx_uninteractive{pointer-events:none}:host(.wx_tap_highlight_active) .wx_tap_link{opacity:.5}:host(.wx_tap_highlight_active) .wx_tap_card{background-color:#f3f3f3}:host(.wx_tap_highlight_active) .wx_tap_cell{background-color:#0000000d}@media (prefers-color-scheme: dark){:host(.wx_tap_highlight_active) .wx_tap_card{background-color:#252525}:host(.wx_tap_highlight_active) .wx_tap_cell{background-color:#ffffff1a}}.wx_css_active :active{opacity:.5}.wx_hover_card:before{content:" ";position:absolute;top:0;left:0;right:0;bottom:0;border-radius:8px;box-sizing:border-box;border:1px solid rgba(7,193,96,.3);pointer-events:none;z-index:9}.wx_selected_card:before{content:" ";position:absolute;top:0;left:0;right:0;bottom:0;border-radius:8px;border:1.5px solid #07C160;box-sizing:border-box;background:rgba(7,193,96,.1);pointer-events:none;z-index:9}.wx-root,body{--weui-BG-6: rgba(0, 0, 0, .05)}.wx-root[data-weui-theme=dark],body[data-weui-theme=dark]{--weui-BG-6: rgba(255, 255, 255, .1)}@media (prefers-color-scheme: dark){.wx-root:not([data-weui-theme=light]),body:not([data-weui-theme=light]){--weui-BG-6: rgba(255, 255, 255, .1)}}.point_event_no{pointer-events:none}.red_package_cover_wrp{-webkit-user-select:none;-moz-user-select:none;user-select:none;display:block;font-size:0;text-align:center}.red_package_cover_wrp.disabled .red_package_cover__inner{position:relative;cursor:default}.red_package_cover_wrp.disabled .red_package_cover__inner:after{border-radius:inherit;position:absolute;top:0;bottom:0;left:0;right:0;content:" ";display:block;height:100%;background-color:var(--weui-FG-1)}.red_package_cover_wrp.disabled .red_package_cover_disable_wording{display:block;text-align:center}.red_package_cover_wrp.common-redpacket-web .red_package_cover__inner{max-width:273px}.red_package_cover_wrp .red_package_cover__inner{position:relative;cursor:pointer;display:inline-block;font-size:17px;background:var(--weui-BG-3);border-radius:8px;max-width:300px;width:77%}.red_package_cover_wrp .red_package_cover__inner.red_package_cover__inner__loading{position:relative}.red_package_cover_wrp .red_package_cover__inner.red_package_cover__inner__loading:before{position:absolute;top:50%;left:50%;margin-top:-8px;margin-left:-8px;content:" ";display:block;width:16px;height:16px}.red_package_cover_wrp .red_package_cover__inner.red_package_cover__inner__loading .red_package_cover__inner__main,.red_package_cover_wrp .red_package_cover__inner.red_package_cover__inner__loading .red_package_cover__extend{opacity:0}.red_package_cover_wrp .red_package_cover__inner__main{width:300px;width:100%;padding:13.6% 0 8%}.red_package_cover_wrp .red_package_cover_img{position:relative;display:block;width:196px;height:324px;border-radius:5px;background-size:cover;background-repeat:no-repeat;background-position:center;margin:0 auto;width:65.33%;height:initial;padding-bottom:108%}.red_package_cover_wrp .red_package_cover_img.red_package_cover_img_loading{background-color:#00000008;position:relative}.wx-root[data-weui-theme=dark] .red_package_cover_wrp .red_package_cover_img.red_package_cover_img_loading,body[data-weui-theme=dark] .red_package_cover_wrp .red_package_cover_img.red_package_cover_img_loading{background-color:#ffffff08}@media (prefers-color-scheme: dark){.wx-root:not([data-weui-theme=light]) .red_package_cover_wrp .red_package_cover_img.red_package_cover_img_loading,body:not([data-weui-theme=light]) .red_package_cover_wrp .red_package_cover_img.red_package_cover_img_loading{background-color:#ffffff08}}.red_package_cover_wrp .red_package_cover_img.red_package_cover_img_loading:before{position:absolute;top:50%;left:50%;margin-top:-8px;margin-left:-8px;content:" ";display:block;width:16px;height:16px}.red_package_cover_wrp .red_package_cover_img.red_package_cover_img_loading:after{display:none}.red_package_cover_wrp .red_package_cover_img:after{content:" ";display:block;position:absolute;bottom:0;left:0;right:0;height:100%;background:url(data:image/png;base64,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) no-repeat center bottom;background-size:100% auto}.red_package_cover_wrp .red_package_cover_img.synthetic_cover_img{width:62.33%}.red_package_cover_wrp .red_package_cover_img.synthetic_cover_img:after{content:" ";display:block;position:absolute;bottom:9.3%;left:8px;right:8px;height:100%;background:url(data:image/png;base64,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CCCAAAIIIIDA0ggQAF6at5IbQQABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQACBVRcgALzqvwHcPwIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIILI0AAeCleSu5EQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQWHUBAsCr/hvA/SOAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAwNIIEABemreSG0EAAQQQQAABBBBAAAEE/v/27t9FrvMKA/D97khCO2vFkXCZIjiFAiZJEdQkIYWjiNiFUwQhgwmGOJX/gATyBxh3cZVSjjHG2iwprEBkZEUBg13YlRJcLLhw4VIi2CuthezdL/dbsWK0Wml/arV7zrPNzM7cmbnvc073cmcIECBAgAABAgQIECBAgAABAtkFFMDZN0B+AgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgTCCCiAw4xSEAIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEsgsogLNvgPwECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECIQRUACHGaUgBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAhkF1AAZ98A+QkQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQCCOgAA4zSkEIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEMguoADOvgHyEyBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECAQRkABHGaUghAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgkF1AAZx9A+QnQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQCCMgAI4zCgFIUCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEAgu4ACOPsGyE+AAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQBgBBXCYUQpCgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEB2AQVw9g2QnwABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBMAIK4DCjFIQAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgewCCuDsGyA/AQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQJhBBTAYUYpCAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAEC2QUUwNk3QH4CBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBMIIKIDDjFIQAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSyCyiAs2+A/AQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIhBFQAIcZpSAECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECGQXUABn3wD5CRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAII6AADjNKQQgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQyC6gAM6+AfITIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIBBGQAEcZpSCECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQXUABnH0D5CdAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIIyAAjjMKAUhQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQCC7gAI4+wbIT4AAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAGAEFcJhRCkKAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQHYBBXD2DZCfAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIEwAgrgMKMUhAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACB7AIK4OwbID8BAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAmEEFMBhRikIAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQLZBRTA2TdAfgIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEwggogMOMUhACBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBLILKICzb4D8BAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAiEEVAAhxmlIAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIZBdQAGffAPkJECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEAgjoAAOM0pBCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBDILqAAzr4B8hMgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgEEZAARxmlIIQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIJBdQAGcfQPkJ0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEAgjIACOMwoBSFAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAILuAAjj7BshPgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEAYAQVwmFEKQoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAdgEFcPYNkJ8AAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgTACCuAwoxSEAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIHsAgrg7BsgPwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECYQQUwGFGKQgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAtkFFMDZN0B+AgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgTCCCiAw4xSEAIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEsgsogLNvgPwECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECIQRUACHGaUgBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAhkF1AAZ98A+QkQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQCCOgAA4zSkEIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEMguoADOvgHyEyBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECAQRkABHGaUghAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgkF1AAZx9A+QnQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQCCMgAI4zCgFIUCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEAgu4ACOPsGyE+AAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQBgBBXCYUQpCgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEB2AQVw9g2QnwABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBMAIK4DCjFIQAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgewCCuDsGyA/AQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQJhBBTAYUYpCAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAEC2QUUwNk3QH4CBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBMIIKIDDjFIQAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSyCyiAs2+A/AQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIhBFQAIcZpSAECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECGQXUABn3wD5CRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAII6AADjNKQQgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQyC6gAM6+AfITIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIBBGQAEcZpSCECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQXUABnH0D5CdAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIIyAAjjMKAUhQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQCC7gAI4+wbIT4AAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAGAEFcJhRCkKAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQHYBBXD2DZCfAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIEwAgrgMKMUhAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACB7AIK4OwbID8BAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAmEEFMBhRikIAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQLZBRTA2TdAfgIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEwggogMOMUhACBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBLILKICzb4D8BAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAiEEVAAhxmlIAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIZBdQAGffAPkJECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEAgjoAAOM0pBCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBDILqAAzr4B8hMgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgEEZAARxmlIIQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIJBdQAGcfQPkJ0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEAgjIACOMwoBSFAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAILuAAjj7BshPgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEAYAQVwmFEKQoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAdgEFcPYNkJ8AAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgTACCuAwoxSEAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIHsAgrg7BsgPwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECYQQUwGFGKQgBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAtkFFMDZN0B+AgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgTCCCiAw4xSEAIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEsgsogLNvgPwECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECIQRUACHGaUgBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAhkF1AAZ98A+QkQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQCCOgAA4zSkEIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEMguoADOvgHyEyBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECAQRkABHGaUghAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgkF1AAZx9A+QnQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQCCMgAI4zCgFIUCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEAgu4ACOPsGyE+AAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQBgBBXCYUQpCgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEB2AQVw9g2QnwABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBMAIK4DCjFIQAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgewCCuDsGyA/AQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQJhBBTAYUYpCAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAEC2QUUwNk3QH4CBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBMIIKIDDjFIQAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSyCyiAs2+A/AQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIhBFQAIcZpSAECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECGQXUABn3wD5CRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAII6AADjNKQQgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQyCLmaNcAAA67SURBVC6gAM6+AfITIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIBBGQAEcZpSCECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQXUABnH0D5CdAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIIyAAjjMKAUhQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQCC7gAI4+wbIT4AAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAGAEFcJhRCkKAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQHYBBXD2DZCfAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIEwAgrgMKMUhAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACB7AIK4OwbID8BAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAmEEFMBhRikIAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQLZBRTA2TdAfgIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEwggogMOMUhACBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBLILKICzb4D8BAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAiEEVAAhxmlIAQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIZBdQAGffAPkJECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEAgjoAAOM0pBCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBDILqAAzr4B8hMgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgEEZAARxmlIIQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIJBdQAGcfQPkJ0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEAgjIACOMwoBSFAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAILuAAjj7BshPgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgEAYAQVwmFEKQoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAdgEFcPYNkJ8AAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgTACCuAwoxSEAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIHsAgrg7BsgPwECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECYQT6UsqtMGkEIUCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQFKB1v32tXbzSfOLTYAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgTACrfsdrgCuCuAwIxWEAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIGsAq377WtXFMBZN0BuAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgTCCLTuty/VFcBhJioIAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQJpBVr3264A/jytgOAECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAIItC63750ZS5IHjEIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCQVqB1v33fLSmA066A4AQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIRBFo3W+/dKBXAEeZqBwECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECKQVaN1vPx5PzZWuq2kVBCdAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgMA+F2idb+t++3L2/HxXypV9nsfpEyBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAIK/A0Pm27rdvArV2/84rITkBAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgT2t8BK57tcAJdRvby/4zh7AgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQI5BVY6XyXC+DxgUPvl1IW83JIToAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgf0p0Lre1vm2s799BfBbF76sXf1gf8Zx1gQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEMgr0LreMnS+TWC5AG53Su3fbLf+CBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQGD/CEx2vXcK4HGps6V0N/dPDGdKgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACB3AKt421d74rCnQK4zF76otZyfuUJtwQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECCwtwVax9u63pWzvFMAtwdKX95YecItAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECOxtgdUdb5k83TrUwzdOn/zv8NhTk4+7T4AAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQJ7TuCT6dlLPyil1JUzu/sK4OGJUSmvrDzplgABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgT2pkDrdifL33aWdxXA7YHD3dGZ4aBP231/BAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQILD3BFqn27rd1Wd2TwFcZmcXh1741dUH+p8AAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIE9opA/+rtbvfu87mnAG5Pj7vH/1pKd+XuQ/1HgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAo9aoHW5rdNd6zzWLIBbU1xGo5dL1935seC1XuwxAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIENg9gdbhLne5y9/sfO/nrlkAt8PG5y5+2HXl9Xtf4hECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQeDQC5fXbXe7an37fArgdPj449cehBL629ks9SoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQK7J1Cu3e5w7/+JDyyAy9v/uFpG3Uv3f7lnCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQGA3BFp32zrcB33WAwvg9sLpmUvvdH157UFv4jkCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQeJgC5c/L3e06H7FuAdxeP/3tJ/9QSvfROu/laQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBDYYYHW1U4fe3L4+d71/8r6h9w+4qvnf/XdxcWvP+5q98RGX+M4AgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIENiGQOmujkYHT0yde/ezjbzLhq4Abm/U3rD03bNDu3x9I2/sGAIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBDYukDrZltHu9Hyt33ShgvgdvD0zL8+rn3/m+GDvm7/+yNAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBnRdonWzrZltHu5l331QB3N74sZn3LpbSvzh8d3TdzAc5lgABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgTWF2hdbOtkWze7/tF3H7HpAri9fPy3994uff+CK4HvxvQfAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEtiPQOtjWxbZOdivvM5THW/+7fuaXp8rS0t9r7R7b+rt4JQECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgM5e/19rXPW7nyd0VvWwVwe5MbZ35xoi51/xy+EPqJlTd1S4AAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQKbECjd1dJ3z272N39Xf8KWvgJ68k3aCYxGB08MbfRHk4+7T4AAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQLrC7SutXWu2y1/2ydtuwBubzJ17t3Pxke/97OuL6+1//0RIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAwAYEho61da2tc93A0esesu2vgF79CTfOnPz18JXQZ7taj61+zv8ECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAg0ATKtTLqXpqeufTOTnrsyBXAkyfUTnD6wNTx0pWzQ7tcJ59znwABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABApkFWofautTpg1Pf3+nyt7nu+BXAk8NaeP7UT+ri4l9q7X40+bj7BAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQyCYw/NbvlTIavTw+d/HDh5V9x68AnjzRduLj7tiPSxn9vpTy6eRz7hMgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQCCDQOtKW2fautOHWf42y4d6BfDksOrp06Ob3f/OLNb6p+Hxpyafc58AAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIBBT4ZlfLK4e7oTJmdXdyNfLtWAK+EqbWWhTOnnqlL9cVS6nPD10MfXnnOLQECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBPazwPA1zzeHSvR86csb45mLF4arf+tu5tn1AngyXD198vGFWk7XsvTb4YeOfzqUw6PJ590nQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIDAXhcYSt7F2tUPSu3fHJc6W2YvffGozvmRFsCToesLz3xr4ZtbP6+L5emhBH+6q90Phyp8z5zf5Lm6T4AAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAXoGhxKxDk/mf4Urfy2VUL48PHHq/vHXhy70gsmcL1vq7544sLHx1vP9m6fhS1x8fGvPjpavfqaUcGW6PDJhHhsunh9t6aC9AOgcCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBPa/wHA1763hZ2znh4tW54eWd77U5dvPh280nuu7pbmlA/3ceDw1V86en9+Laf8P5hVEd79xD5kAAAAASUVORK5CYII=) no-repeat center bottom;background-size:100% auto}.red_package_cover_wrp .red_package_cover_img.red_package_open_cover_img:after{display:none}.red_package_cover_wrp .red_package_cover__foot{text-align:center;padding:8% 16px 0}.red_package_cover_wrp .red_package_cover__access-link{font-size:17px;line-height:1.4;font-weight:500;color:var(--weui-RED)}.red_package_cover_wrp .red_package_cover__access-link.disabled{color:var(--weui-FG-2)}.red_package_cover_wrp .red_package_cover__access-link.disabled:after{display:none}.red_package_cover_wrp .red_package_cover__access-link:after{content:"";display:inline-block;font-size:10px;width:1.2em;height:2.4em;margin-left:4px;margin-top:-.3em;vertical-align:middle;background:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMTJweCIgaGVpZ2h0PSIyNHB4IiB2aWV3Qm94PSIwIDAgMTIgMjQiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDYxLjIgKDg5NjUzKSAtIGh0dHBzOi8vc2tldGNoLmNvbSAtLT4KICAgIDx0aXRsZT7liIfniYc8L3RpdGxlPgogICAgPGRlc2M+Q3JlYXRlZCB3aXRoIFNrZXRjaC48L2Rlc2M+CiAgICA8ZGVmcz4KICAgICAgICA8cGF0aCBkPSJNNy41ODc1MDg3MywxMi40Mjk4OTE2IEw2LjUyNjg0ODU2LDEzLjQ5MDU1MTggTDAuNzQ3OTUxNTI2LDcuNzExNjU0NzMgQzAuMzU3ODI2MjI3LDcuMzIxNTI5NDMgMC4zNTQzNjU3ODYsNi42OTI0NzE3OSAwLjc0Nzk1MTUyNiw2LjI5ODg4NjA1IEw2LjUyNjg0ODU2LDAuNTE5OTg5MDE0IEw3LjU4NzUwODczLDEuNTgwNjQ5MTkgTDIuMTYyODg3NTMsNy4wMDUyNzAzOSBMNy41ODc1MDg3MywxMi40Mjk4OTE2IFoiIGlkPSJwYXRoLTEiPjwvcGF0aD4KICAgIDwvZGVmcz4KICAgIDxnIGlkPSJQYWdlLTEiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxnIGlkPSIzLkljb25zL091dGxpbmVkL2Fycm93Ij4KICAgICAgICAgICAgPGcgaWQ9Ikdyb3VwIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyLjAwMDAwMCwgNS4wMDAwMDApIj4KICAgICAgICAgICAgICAgIDxtYXNrIGlkPSJtYXNrLTIiIGZpbGw9IndoaXRlIj4KICAgICAgICAgICAgICAgICAgICA8dXNlIHhsaW5rOmhyZWY9IiNwYXRoLTEiPjwvdXNlPgogICAgICAgICAgICAgICAgPC9tYXNrPgogICAgICAgICAgICAgICAgPHVzZSBpZD0i5Zu+5qCH6aKc6ImyIiBmaWxsPSIjRkE1MTUxIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSg0LjAyMDc4NCwgNy4wMDUyNzApIHJvdGF0ZSgtMTgwLjAwMDAwMCkgdHJhbnNsYXRlKC00LjAyMDc4NCwgLTcuMDA1MjcwKSAiIHhsaW5rOmhyZWY9IiNwYXRoLTEiPjwvdXNlPgogICAgICAgICAgICA8L2c+CiAgICAgICAgPC9nPgogICAgPC9nPgo8L3N2Zz4=) no-repeat center;background-size:cover}.red_package_cover_wrp .red_package_cover__purchase{font-size:14px;font-weight:400;color:var(--weui-FG-2);margin-top:4px}.red_package_cover_wrp .red_package_cover__extend{display:flex;align-items:center;position:relative;line-height:1.4;padding:8px 16px;font-size:14px;color:var(--weui-FG-1);text-align:left}.red_package_cover_wrp .red_package_cover__extend:before{content:" ";position:absolute;top:0;left:16px;right:16px;height:1px;background-color:var(--weui-FG-3);transform:scaleY(.5);transform-origin:0 0;-webkit-transform:scaleY(.5);-webkit-transform-origin:0 0}.red_package_cover_wrp .red_package_cover__extend_icon{display:inline-block;vertical-align:middle;font-size:10px;width:1.6em;height:1.6em;margin-right:4px;background:url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M13.5 8.75149H12.0311C12.1352 8.54415 12.1938 8.30977 12.1938 8.06133C12.1938 7.21422 11.5121 6.52993 10.6741 6.52993C10.259 6.52993 9.86934 6.69916 9.58508 6.99323C8.72588 7.85576 8.3398 8.24353 8.00001 8.58458L6.3806 6.95894C6.09366 6.68304 5.72113 6.52993 5.32607 6.52993C4.48806 6.52993 3.80619 7.21422 3.80619 8.06133C3.80619 8.30977 3.86495 8.54415 3.96891 8.75149H2.50001V2.96628C2.50001 2.57865 2.76965 2.12287 3.11454 1.95118C3.11454 1.95118 3.14324 1.9352 3.23554 1.89586C4.52227 1.34706 6.18193 1 8.00001 1C9.81582 1 11.4782 1.33491 12.7595 1.89368C12.8369 1.92741 12.8815 1.94927 12.8815 1.94927C13.2231 2.12341 13.5 2.57879 13.5 2.96628V8.75149ZM13.5 9.59145V14.3C13.5 14.6875 13.1943 15 12.812 15H3.18804C2.808 15 2.5 14.6873 2.5 14.3V9.59145H5.2614C5.28287 9.59241 5.30446 9.59282 5.32606 9.59282H6.99551C6.41345 10.1719 5.51816 10.9309 4.31259 11.8659L4.81241 12.534C6.06655 11.5614 6.99726 10.7707 7.60789 10.1579L8 9.76423C8.11617 9.88088 8.2467 10.0119 8.4007 10.1663C9.00932 10.7774 9.93721 11.5654 11.1877 12.5342L11.6873 11.8657C10.4797 10.93 9.5844 10.1711 9.00449 9.59282H10.6741C10.6958 9.59282 10.7173 9.59241 10.7387 9.59145H13.5ZM10.7182 8.75143H9.00887L10.1688 7.58691C10.3036 7.44745 10.4821 7.36987 10.6742 7.36987C11.0592 7.36987 11.3688 7.68088 11.3688 8.06127C11.3688 8.42732 11.0825 8.72876 10.7182 8.75143ZM5.28211 8.75143C4.91777 8.72876 4.63136 8.42718 4.63136 8.06127C4.63136 7.68088 4.94111 7.36987 5.32611 7.36987C5.50895 7.36987 5.67945 7.43994 5.80796 7.56341C6.35675 8.11426 6.71506 8.47417 6.99127 8.75143H5.28211Z' fill='%23FA5151'/%3E%3C/svg%3E%0A") no-repeat 50% 50%;background-size:cover}.red_package_cover_wrp .red_package_cover_disable_wording{display:block;text-align:center;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:1;width:100%;color:#fff}.red_package_cover_wrp.small{width:100%}.red_package_cover_wrp.small .red_package_cover__inner{width:100%;max-width:382px}.red_package_cover_wrp.small .red_package_cover__inner__main{display:flex;flex-direction:row;align-items:center;justify-content:space-between;width:100%;padding:16px 16px 16px 24px;box-sizing:border-box}.red_package_cover_wrp.small .red_package_cover__body{flex-shrink:1;display:flex;flex-direction:row;align-items:center;min-width:0}.red_package_cover_wrp.small .red_package_cover__body span.title-wrp{flex-shrink:1;display:block;margin-left:16px;min-width:0;text-align:left;line-height:1.4}.red_package_cover_wrp.small .red_package_cover__body span.title{display:block;word-break:break-all;font-size:15px;font-weight:500;text-align:left;color:var(--weui-FG-0)}.red_package_cover_wrp.small .red_package_cover__body span.red_package_cover__purchase{display:block;margin-top:2px;font-size:12px;font-weight:400;color:var(--weui-FG-1)}.red_package_cover_wrp.small .red_package_cover_img{flex-shrink:0;height:44px;width:26.4px;margin:0;padding-bottom:unset;border-radius:1px}.red_package_cover_wrp.small .red_package_cover__foot{flex-shrink:0;padding:0;margin-left:16px}.red_package_cover_wrp.small .red_package_cover__access-link{font-size:14px;font-weight:500}.red_package_cover_wrp.small .red_package_cover__access-link.button{color:#fff;background-color:var(--weui-ORANGERED-100);border-radius:6px}.red_package_cover_wrp.small .red_package_cover__access-link.correct:before{position:relative;display:inline-block;content:"";margin-right:2px;font-size:16px;width:1em;height:1em;vertical-align:sub;background-color:currentColor;-webkit-mask-image:url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M5.77124 12.29L2 8.51879L2.94281 7.57598L6.24264 10.8758L13.7851 3.33334L14.7279 4.27614L6.71405 12.29C6.4537 12.5504 6.03159 12.5504 5.77124 12.29Z' fill='black' /%3E%3C/svg%3E%0A");mask-image:url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M5.77124 12.29L2 8.51879L2.94281 7.57598L6.24264 10.8758L13.7851 3.33334L14.7279 4.27614L6.71405 12.29C6.4537 12.5504 6.03159 12.5504 5.77124 12.29Z' fill='black' /%3E%3C/svg%3E%0A");-webkit-mask-size:contain;mask-size:contain;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-position:center;mask-position:center}.red_package_cover_wrp.small .red_package_cover__access-link:after{display:none}.red_package_cover_wrp.small .red_package_cover__extend{display:none} `, I = { errType: "data-errortype", name: "data-name", isSynthetic: "data-synthetic", imgSrc: "data-receiveimg", openImgSrc: "data-openimg", orderid: "data-orderid", coveruri: "data-coveruri", bizuin: "data-bizuin", status: "data-status", is_hover: "data-is-hover", is_selected: "data-is-selected", isPurchaseOrder: "data-is-purchase-order", smallCard: "data-small-card" }; function u(g) { let A = {}; return A = o$1.call(this, I), Object.keys(I).forEach((B) => { A[B] = decodeURIComponent(A[B] || ""), ["smallCard", "isSynthetic", "status", "is_hover", "is_selected", "isPurchaseOrder"].indexOf(B) > -1 && (A[B] = A[B] * 1); }), { platform: g, ...A }; } function o(g = {}) { k(Object.assign(g, { Component: g.isDev ? g.devComponent : r, styleText: g.isDev ? g.devStyleText : t, customName: g.customName || "mp-common-redpacket", watchAttr: [ "data-errortype", "data-status", "data-receiveimg", "data-synthetic", "data-openimg", "data-is-hover", "data-is-selected" ], getProps: u })); } var onceListeners = {}; var permanentListeners = {}; function clean(event, all) { delete onceListeners[event]; if (all) { delete permanentListeners[event]; } } function on(event, callback, permanent) { if (typeof callback === 'function') { if (permanent) { if (!permanentListeners[event]) { permanentListeners[event] = []; } permanentListeners[event].push(callback); } else { if (!onceListeners[event]) { onceListeners[event] = []; } onceListeners[event].push(callback); } } } function emit(event) { for (var _len = arguments.length, params = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { params[_key - 1] = arguments[_key]; } if (permanentListeners[event]) { permanentListeners[event].forEach(function (callback) { if (typeof callback === 'function') { callback.apply(void 0, params); } }); } if (onceListeners[event]) { onceListeners[event].forEach(function (callback) { if (typeof callback === 'function') { callback.apply(void 0, params); } }); clean(event); } } function remove(event, callback, permanent) { if (typeof callback === 'function') { if (permanent && permanentListeners[event]) { var idx = permanentListeners[event].indexOf(callback); if (idx !== -1) { permanentListeners[event].splice(idx, 1); } } else if (onceListeners[event]) { var _idx = onceListeners[event].indexOf(callback); if (_idx !== -1) { onceListeners[event].splice(_idx, 1); } } } } var eventBus = { on: on, emit: emit, remove: remove, clean: clean }; window.__page_cls_ctrl__canRenderSilently = '__page_cls_ctrl__canRenderSilently' in window ? window.__page_cls_ctrl__canRenderSilently : true; window.__page_cls_ctrl__forceRenderSilentlyList = '__page_cls_ctrl__forceRenderSilentlyList' in window ? window.__page_cls_ctrl__forceRenderSilentlyList : []; window.__page_cls_ctrl__compRenderInfo = '__page_cls_ctrl__compRenderInfo' in window ? window.__page_cls_ctrl__compRenderInfo : {}; var compRenderInfoInner = {}; var hasReportIdKey = false; function getCompId(renderInfo) { if (renderInfo.subCompType) { return "".concat(renderInfo.compType, "-").concat(renderInfo.compIdx, "-").concat(renderInfo.subCompType); } return "".concat(renderInfo.compType, "-").concat(renderInfo.compIdx); } function setForceRenderSilentlyList(list) { if (Array.isArray(list)) { var _window$__page_cls_ct; (_window$__page_cls_ct = window.__page_cls_ctrl__forceRenderSilentlyList).push.apply(_window$__page_cls_ct, _toConsumableArray(list)); } else if (Object.prototype.toString.call(list).includes('Number')) { window.__page_cls_ctrl__forceRenderSilentlyList.forceRenderSilentScrollTop = list; } } function setRenderSilentlyReadyStatus(status) { window.__page_cls_ctrl__canRenderSilently = status; } function emitRenderNewHeightEvt() { eventBus.emit('cls-render-new-height'); } function setCompRenderInfo(renderInfo, diffHeight) { window.__page_cls_ctrl__compRenderInfo[getCompId(renderInfo)] = { dh: diffHeight, compEle: renderInfo.compEle }; } function renderCompSilentlyPreHandler(renderInfo) { var wrapper = renderInfo.wrapper || renderInfo.compEle.parentNode || { scrollHeight: 0 }; compRenderInfoInner[getCompId(renderInfo)] = { beforeHeight: wrapper.scrollHeight, boundingRectTop: renderInfo.compEle.getBoundingClientRect().top, beforeScrollTop: document.body.scrollTop || document.documentElement.scrollTop, wrapper: wrapper }; } function renderCompSilently(renderInfo) { var compId = getCompId(renderInfo); if (!compRenderInfoInner[compId] || compRenderInfoInner[compId].beforeHeight === compRenderInfoInner[compId].wrapper.scrollHeight || !('compIdx' in renderInfo) || renderInfo.compIdx < 0) { return; } var diffHeight = compRenderInfoInner[compId].wrapper.scrollHeight - compRenderInfoInner[compId].beforeHeight; var autoScrollHeight = (document.body.scrollTop || document.documentElement.scrollTop) - compRenderInfoInner[compId].beforeScrollTop; emitRenderNewHeightEvt(); if ((compRenderInfoInner[compId].boundingRectTop < 0 || window.__page_cls_ctrl__forceRenderSilentlyList.includes(compId) || window.scrollY + compRenderInfoInner[compId].boundingRectTop < window.__page_cls_ctrl__forceRenderSilentlyList.forceRenderSilentScrollTop ) && window.__page_cls_ctrl__canRenderSilently && Math.ceil(autoScrollHeight) !== diffHeight && Math.floor(autoScrollHeight) !== diffHeight) { document.body.scrollTop = document.body.scrollTop + diffHeight; document.documentElement.scrollTop = document.documentElement.scrollTop + diffHeight; window.__addIdKeyReport && window.__addIdKeyReport(330742, 2); !hasReportIdKey && window.__addIdKeyReport && window.__addIdKeyReport(330742, 3); hasReportIdKey = true; } window.__page_cls_ctrl__compRenderInfo[compId] = { dh: diffHeight, compEle: renderInfo.compEle }; var newScrollTop = document.body.scrollTop || document.documentElement.scrollTop; for (var i in compRenderInfoInner) { if (!window.__page_cls_ctrl__compRenderInfo[i]) { compRenderInfoInner[i].beforeScrollTop = newScrollTop; } } } var pageClsCtrl = { compRenderInfo: window.__page_cls_ctrl__compRenderInfo, setForceRenderSilentlyList: setForceRenderSilentlyList, setRenderSilentlyReadyStatus: setRenderSilentlyReadyStatus, renderCompSilentlyPreHandler: renderCompSilentlyPreHandler, renderCompSilently: renderCompSilently, emitRenderNewHeightEvt: emitRenderNewHeightEvt, setCompRenderInfo: setCompRenderInfo }; function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } var ua = navigator.userAgent; var is_ios = /(iPhone|iPad|iPod|iOS)/i.test(ua); var is_wp = /Windows\sPhone/i.test(ua); var is_android = /(Android)/i.test(ua); var is_wechat = /MicroMessenger\/([\d\.]+)/i.test(ua); var is_mac = /mac\sos/i.test(ua) && !is_ios; var is_windows = /windows\snt/i.test(ua) && !is_wp; var is_mpapp = /MPAPP\/([\d\.]+)/i.test(ua); var is_ipad = /iPad/i.test(ua); var is_windows_wechat = /WindowsWechat/i.test(ua); var is_mac_wechat = /MacWechat/i.test(ua) || /wechat.*mac os/i.test(ua); var is_prefetch = is_wechat && window.WeixinPrefecherJSBridge; var is_donut_app = /SAAASDK/i.test(ua); var is_harmony = /OpenHarmony|ArkWeb/i.test(ua); var is_in_miniProgram = is_android && /miniprogram/.test(ua.toLowerCase()) || window.__wxjs_environment == 'miniprogram'; var is_wx_work = /wxwork/i.test(ua); function getUrlParams() { var vars = location.search.substring(1).split('&'); var params = {}; var _iterator = _createForOfIteratorHelper(vars), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var ele = _step.value; var pair = ele.split('='); var key = decodeURIComponent(pair[0]); if (typeof params[key] === 'undefined') { params[key] = decodeURIComponent(pair[1]); } } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } return params; } function get() { var reg = /MicroMessenger\/([\d\.]+)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1]; } return false; } function getMac() { var reg = /MacWechat\/([\d\.]+)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1]; } return false; } function getMacOS() { var reg = /Mac OS X ([\d_]+)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1].replace(/_/g, '.'); } return false; } function getWindows() { var reg = /WindowsWechat\(0x(.+?)\)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1]; } return false; } function getWxWork() { var reg = /wxwork\/([\d\.]+)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1]; } return false; } function getMpApp() { var appVersion = [2, 4, 5]; var match = navigator.userAgent.match(/MPAPP\/(\d+(\.\d+)*)/); if (match) { appVersion = match[1].split('.').map(function (v) { return Number(v); }); } return appVersion.join('.'); } function getUnifiedPcVer() { var versionInfo = navigator.userAgent.match(/UnifiedPC\w+Wechat\(0xf\w{2}(\w+?)\w{2}\)/); if (versionInfo && versionInfo.length === 2) { var version = versionInfo[1]; var mainVersion = getVersionNumber(version.slice(0, 1)); var subVersion = getVersionNumber(version.slice(1, 2)); var subVersion2 = getVersionNumber(version.slice(2, 3)); return [mainVersion, subVersion, subVersion2].join('.'); } } function getVersionNumber(hexStr) { return Number(Number("0x".concat(hexStr)).toString(10)); } function getWindowsVersionFormat() { var versionInfo = navigator.userAgent.match(/WindowsWechat\(0x(\w+?)\)/); if (versionInfo && versionInfo.length === 2) { var version = versionInfo[1]; var mainVersion = getVersionNumber(version.slice(1, 2)); var subVersion = getVersionNumber(version.slice(2, 4)); var subVersion2 = getVersionNumber(version.slice(4, 6)); return [mainVersion, subVersion, subVersion2].join('.'); } return false; } function getInner() { var reg = /MicroMessenger\/[\d\.]+\(0x(.+?)\)/i; var ret = ua.match(reg); if (ret && ret[1] && ret[1] != null) { return ret[1]; } if (!ret && /MicroMessenger\/[\d\.]+/i.test(ua)) { var urlParams = getUrlParams(); if (urlParams.version) { return urlParams.version; } } return false; } var opfunc = { 'cp-1': function cp1(a, b) { return a < b; }, cp0: function cp0(a, b) { return a === b; }, cp1: function cp1(a, b) { return a > b; } }; function cpVersion(ver, op, canEq, type) { var mmver = false; switch (type) { case 'mac': mmver = getMac(); break; case 'windows': mmver = getWindowsVersionFormat(); break; case 'wxwork': mmver = getWxWork(); break; case 'mpapp': mmver = getMpApp(); break; case 'unifiedpc': mmver = getUnifiedPcVer(); break; default: mmver = get(); break; } if (!mmver) { return; } var mmversion = mmver.split('.'); var version = ver.split('.'); if (!/\d+/g.test(mmversion[mmversion.length - 1])) { mmversion.pop(); } for (var i = 0, len = Math.max(mmversion.length, version.length); i < len; ++i) { var mmv = mmversion[i] || ''; var v = version[i] || ''; var mmvn = parseInt(mmv, 10) || 0; var vn = parseInt(v, 10) || 0; var eq = opfunc.cp0(mmvn, vn); if (eq) { continue; } var cp = opfunc["cp".concat(op)]; return cp(mmvn, vn); } return canEq || op === 0; } function eqVersion(version) { return cpVersion(version, 0); } function gtVersion(version, canEq) { return cpVersion(version, 1, canEq); } function ltVersion(version, canEq) { return cpVersion(version, -1, canEq); } function getPlatform() { if (is_ios) { return 'ios'; } if (is_android) { return 'android'; } if (is_mac) { return 'mac_os'; } if (is_windows) { return 'windows'; } return 'unknown'; } var is_google_play = false; var inner_ver_for_google_play_check = getInner(); if (is_android && inner_ver_for_google_play_check) { var v = "0x".concat(inner_ver_for_google_play_check.substr(-2)); if (parseInt(v) >= 64 && parseInt(v) <= 79) { is_google_play = true; } } var MMVersion = { get: get, getMac: getMac, getMacOS: getMacOS, getWindows: getWindows, getInner: getInner, getWxWork: getWxWork, getMpApp: getMpApp, cpVersion: cpVersion, eqVersion: eqVersion, gtVersion: gtVersion, ltVersion: ltVersion, getPlatform: getPlatform, getVersionNumber: getVersionNumber, isWp: is_wp, isIOS: is_ios, isAndroid: is_android, isHarmony: is_harmony, isHarmonyWechat: is_harmony && is_wechat && cpVersion('1.0.0', 1, true), isInMiniProgram: is_in_miniProgram, isWechat: is_wechat, isMac: is_mac, isWindows: is_windows, isMacWechat: is_mac_wechat, isWindowsWechat: is_windows_wechat, isWxWork: is_wx_work, isOnlyWechat: is_wechat && !is_wx_work, isMpapp: is_mpapp, isNewMpApp: false, isIPad: is_ipad, isGooglePlay: is_google_play, isPrefetch: is_prefetch, isDonutAPP: is_donut_app }; var Device = {}; function detect(ua) { var MQQBrowser = ua.match(/MQQBrowser\/(\d+\.\d+)/i); var MQQClient = ua.match(/QQ\/(\d+\.(\d+)\.(\d+)\.(\d+))/i) || ua.match(/V1_AND_SQ_([\d\.]+)/); var WeChat = ua.match(/MicroMessenger\/((\d+)\.(\d+))\.(\d+)/) || ua.match(/MicroMessenger\/((\d+)\.(\d+))/); var MacOS = ua.match(/Mac\sOS\sX\s(\d+[\.|_]\d+)/); var WinOS = ua.match(/Windows(\s+\w+)?\s+?(\d+\.\d+)/); var Linux = ua.match(/Linux\s/); var MiuiBrowser = ua.match(/MiuiBrowser\/(\d+\.\d+)/i); var M1 = ua.match(/MI-ONE/); var MIPAD = ua.match(/MI PAD/); var UC = ua.match(/UCBrowser\/(\d+\.\d+(\.\d+\.\d+)?)/) || ua.match(/\sUC\s/); var IEMobile = ua.match(/IEMobile(\/|\s+)(\d+\.\d+)/) || ua.match(/WPDesktop/); var ipod = ua.match(/(ipod).*\s([\d_]+)/i); var ipad = ua.match(/(ipad).*\s([\d_]+)/i); var iphone = ua.match(/(iphone)\sos\s([\d_]+)/i); var Chrome = ua.match(/Chrome\/(\d+\.\d+)/); var AndriodBrowser = ua.match(/Mozilla.*Linux.*Android.*AppleWebKit.*Mobile Safari/); var android = ua.match(/(android)\s([\d\.]+)/i); var harmony = ua.match(/(OpenHarmony)\s([\d\.]+)/i); Device.browser = Device.browser || {}, Device.os = Device.os || {}; if (window.ActiveXObject) { var vie = 6; (window.XMLHttpRequest || ua.indexOf('MSIE 7.0') > -1) && (vie = 7); (window.XDomainRequest || ua.indexOf('Trident/4.0') > -1) && (vie = 8); ua.indexOf('Trident/5.0') > -1 && (vie = 9); ua.indexOf('Trident/6.0') > -1 && (vie = 10); Device.browser.ie = true, Device.browser.version = vie; } else if (ua.indexOf('Trident/7.0') > -1) { Device.browser.ie = true, Device.browser.version = 11; } if (android) { Device.os.android = true; Device.os.version = android[2]; } if (harmony) { Device.os.harmony = true; Device.os.version = harmony[2]; } if (ipod) { Device.os.ios = Device.os.ipod = true; Device.os.version = ipod[2].replace(/_/g, '.'); } if (ipad) { Device.os.ios = Device.os.ipad = true; Device.os.version = ipad[2].replace(/_/g, '.'); } if (iphone) { Device.os.iphone = Device.os.ios = true; Device.os.version = iphone[2].replace(/_/g, '.'); } if (WinOS) Device.os.windows = true, Device.os.version = WinOS[2]; if (MacOS) Device.os.Mac = true, Device.os.version = MacOS[1]; if (Linux) Device.os.Linux = true; if (ua.indexOf('lepad_hls') > 0) Device.os.LePad = true; if (MIPAD) Device.os.MIPAD = true; if (MQQBrowser) Device.browser.MQQ = true, Device.browser.version = MQQBrowser[1]; if (MQQClient) Device.browser.MQQClient = true, Device.browser.version = MQQClient[1]; if (WeChat) Device.browser.WeChat = true, Device.browser.mmversion = Device.browser.version = WeChat[1]; if (MiuiBrowser) Device.browser.MIUI = true, Device.browser.version = MiuiBrowser[1]; if (UC) Device.browser.UC = true, Device.browser.version = UC[1] || NaN; if (IEMobile) Device.browser.IEMobile = true, Device.browser.version = IEMobile[2]; if (AndriodBrowser) { Device.browser.AndriodBrowser = true; } if (M1) { Device.browser.M1 = true; } if (Chrome) { Device.browser.Chrome = true, Device.browser.version = Chrome[1]; } if (Device.os.windows) { if (typeof navigator.platform !== "undefined" && navigator.platform.toLowerCase() == "win64") { Device.os.win64 = true; } else { Device.os.win64 = false; } } if (Device.os.Mac || Device.os.windows || Device.os.Linux) { Device.os.pc = true; } var osType = { iPad7: 'iPad; CPU OS 7', LePad: 'lepad_hls', XiaoMi: 'MI-ONE', SonyDTV: "SonyDTV", SamSung: 'SAMSUNG', HTC: 'HTC', VIVO: 'vivo' }; for (var os in osType) { Device.os[os] = ua.indexOf(osType[os]) !== -1; } Device.os.phone = Device.os.phone || /windows phone/i.test(ua); Device.os.getNumVersion = function () { return parseFloat(Device.os.version); }; Device.os.hasTouch = 'ontouchstart' in window; if (Device.os.hasTouch && Device.os.ios && Device.os.getNumVersion() < 6) { Device.os.hasTouch = false; } if (Device.browser.WeChat && Device.browser.version < 5.0) { Device.os.hasTouch = false; } Device.browser.getNumVersion = function () { return parseFloat(Device.browser.version); }; Device.browser.isFFCanOcx = function () { return !!Device.browser.firefox && Device.browser.getNumVersion() >= 3.0; }; Device.browser.isCanOcx = function () { return !!Device.os.windows && (!!Device.browser.ie || Device.browser.isFFCanOcx() || !!Device.browser.webkit); }; Device.browser.isNotIESupport = function () { return !!Device.os.windows && (!!Device.browser.webkit || Device.browser.isFFCanOcx()); }; Device.userAgent = {}; Device.userAgent.browserVersion = Device.browser.version; Device.userAgent.osVersion = Device.os.version; Device.os.unifiedPC = ua.match(/UnifiedPC/); delete Device.userAgent.version; } detect(window.navigator.userAgent); function canSupportH5Video() { var ua = window.navigator.userAgent, m = null; if (!!Device.os.android) { if (Device.browser.MQQ && Device.browser.getNumVersion() >= 4.2) { return true; } if (ua.indexOf('MI2') != -1) { return true; } if (Device.os.version >= '4' && (m = ua.match(/MicroMessenger\/((\d+)\.(\d+))\.(\d+)/))) { if (parseFloat(m[1]) >= 4.2) { return true; } } if (Device.os.version >= '4.1') { return true; } } return false; } function canSupportVideoMp4() { var video = document.createElement('video'); if (typeof video.canPlayType === 'function') { if (video.canPlayType('video/mp4; codecs="mp4v.20.8"') === 'probably') { return true; } if (video.canPlayType('video/mp4; codecs="avc1.42E01E"') === 'probably' || video.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"') === 'probably') { return true; } } return false; } function canSupportAutoPlay() { if (Device.os.ios && Device.os.getNumVersion() < 10) { return false; } return true; } function isLockdownMode() { if (!Device.os.ios || Device.os.getNumVersion() < 16) { return false; } if (typeof WebAssembly === 'undefined' && typeof OfflineAudioContext === 'undefined' && typeof WebGLRenderingContext === 'undefined') { return true; } return false; } Device.canSupportVideo = canSupportVideoMp4 || canSupportH5Video; Device.canSupportVideoMp4 = canSupportVideoMp4; Device.canSupportH5Video = canSupportH5Video; Device.canSupportAutoPlay = canSupportAutoPlay; Device.isLockdownMode = isLockdownMode; Device.cpVersion = function (version) { var cp = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; var canEqual = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; var nowVersionStr = Device.os.version; if (!nowVersionStr) return false; var versionArr = version.split('.'); var nowVersionArr = nowVersionStr.split('.'); for (var i = 0; i < Math.max(nowVersionArr.length, versionArr.length); i++) { var vi = +versionArr[i]; var nvi = +nowVersionArr[i]; if (vi === nvi) continue; if (cp > 0) return vi > nvi; if (cp < 0) return vi < nvi; } return canEqual || cp === 0; }; var isWp = MMVersion.isWp, isIOS = MMVersion.isIOS, isAndroid = MMVersion.isAndroid, isInMiniProgram = MMVersion.isInMiniProgram, isWechat = MMVersion.isWechat, isMac = MMVersion.isMac, isWindows = MMVersion.isWindows, isMacWechat = MMVersion.isMacWechat, isWindowsWechat = MMVersion.isWindowsWechat, isWxWork = MMVersion.isWxWork, isMpapp = MMVersion.isMpapp, isIPad = MMVersion.isIPad; var commonCompOpts = { platform: 'wechat', extraInfo: { system: { isWp: isWp, isIOS: isIOS, isAndroid: isAndroid, isInMiniProgram: isInMiniProgram, isWechat: isWechat, isMac: isMac, isWindows: isWindows, isMacWechat: isMacWechat, isWindowsWechat: isWindowsWechat, isWxWork: isWxWork, isMpapp: isMpapp, isIPad: isIPad }, device: Device.os }, beforeRender: function beforeRender(data) { pageClsCtrl.renderCompSilentlyPreHandler(data); }, afterRender: function afterRender(data) { pageClsCtrl.renderCompSilently(data); } }; var allRegisterdTags = []; function initOpts() { var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; if (opts.selector) { var selectors = opts.selector.split(','); allRegisterdTags.push.apply(allRegisterdTags, _toConsumableArray(selectors)); } return Object.assign(opts, commonCompOpts); } if (!customElements.get('mp-common-product')) { b(initOpts({ reflowProps: ['customstyle'] })); } if (!customElements.get('mp-common-redpacket')) { o(initOpts({ selector: 'mp-common-redpacket' })); } if (window.__listenMobileClick__) { window.__listenMobileClick__(allRegisterdTags); } else { window.__listenMobileClick__task__ = window.__listenMobileClick__task__ || []; window.__listenMobileClick__task__.push(allRegisterdTags); } })();</script><script type="text/javascript" nonce="1989770072" reportloaderror>(function () { 'use strict'; function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } var containers = [document.getElementById('page-content')]; var bgPlaceholder = 'url("data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==")'; var isCareMode = window.a_value_which_never_exists || '' * 1 || 0; var isCartoonCopyright = window.a_value_which_never_exists || '0' * 1 || 0; if (!window.__second_open__ && !isCareMode && !isCartoonCopyright) { containers.forEach(function (dom) { var containsBackground = dom.querySelectorAll('[style*="background-image"]'); _toConsumableArray(containsBackground).forEach(function (node) { if (node && node.style && typeof node.getAttribute === 'function' && !node.getAttribute('data-lazy-bgimg') && !window.__lazyload_detected) { var bgImg = node.style.backgroundImage; var bgImgUrl = bgImg && bgImg.match(/url\(['"]?(.*?)['"]?\)/); if (bgImgUrl && bgImgUrl[1]) { node.style.backgroundImage = bgImg.replace(/url\(['"]?.*?['"]?\)/, bgPlaceholder); node.setAttribute('data-lazy-bgimg', bgImgUrl[1]); node.classList.add('wx_imgbc_placeholder'); } } }); }); } })();</script><script type="text/javascript" nonce="1989770072" reportloaderror>var __INLINE_SCRIPT__ = (function () { 'use strict'; var __setTitle = function __setTitle(showTitle, dom) { var title = showTitle; if (showTitle.indexOf('——') > -1) { var replaceHtml = '<span style="letter-spacing:normal">——</span>'; showTitle = showTitle.replace(/——/g, replaceHtml); } if (dom) { dom.innerHTML = dom.innerHTML.replace(title, showTitle); } }; if (!window.__second_open__) { var title = '震惊!用 Redis+AI 模型实现秒级实时风控,这波操作太秀了'; __setTitle(title, document.getElementById('activity-name')); window.__setTitle = __setTitle; } return __setTitle; })();</script><script type="text/javascript" nonce="1989770072" reportloaderror>var __INLINE_SCRIPT__ = (function () { 'use strict'; var __setPubTime = function __setPubTime(svrTime, oriCreateTime, createTime, dom) { var oriTimestamp = oriCreateTime * 1; var dateObj = new Date(oriTimestamp * 1000); var padStart = function padStart(v) { return "0".concat(v).slice(-2); }; var year = dateObj.getFullYear(); var month = padStart(dateObj.getMonth() + 1); var date = padStart(dateObj.getDate()); var hour = padStart(dateObj.getHours()); var minute = padStart(dateObj.getMinutes()); var timeString = "".concat(hour, ":").concat(minute); var dateString = "".concat(year, "年").concat(month, "月").concat(date, "日"); var showDate = "".concat(dateString, " ").concat(timeString); if (dom) { dom.innerText = showDate; } }; if (!window.__second_open__) { var svrDate = '1743644973'; var oriCreateTime = '1743643844'; var createTime = '2025-04-03 09:30'; __setPubTime(svrDate, oriCreateTime, createTime, document.getElementById('publish_time')); window.__setPubTime = __setPubTime; } return __setPubTime; })();</script> <script type="text/javascript" nonce="1989770072" reportloaderror> if (!window.console) window.console = { log: function() {} }; if (typeof getComputedStyle == 'undefined') { if (document.body.currentStyle) { window.getComputedStyle = function(el) { return el.currentStyle; } } else { window.getComputedStyle = {}; } } (function(){ window.__zoom = 1; var ua = navigator.userAgent.toLowerCase(); var re = new RegExp("msie ([0-9]+[\.0-9]*)"); var version; if (re.exec(ua) != null) { version = parseInt(RegExp.$1); } var isIE = false; if (typeof version != 'undefined' && version >= 6 && version <= 9) { isIE = true; } var isAccessibilityKey = 'isMpUserAccessibility'; var isAccessMode = window.localStorage.getItem(isAccessibilityKey); var isCarton = isIE || '0' === '1' || '' === '1' || isAccessMode === '1'; var bodyWidth = '' * 1; if (bodyWidth) { var styles = getComputedStyle(document.getElementById('page-content')); bodyWidth - parseFloat(styles.paddingLeft) - parseFloat(styles.paddingRight); } var getMaxWith = function () { var container = document.getElementById('img-content'); var max_width = container.offsetWidth; !max_width && bodyWidth && (max_width = bodyWidth); var container_padding = 0; var container_style = getComputedStyle(container); container_padding = parseFloat(container_style.paddingLeft) + parseFloat(container_style.paddingRight); max_width -= container_padding; if (!max_width) { max_width = window.innerWidth - 30; } return max_width; }; var getParentWidth = function (dom) { var parent_width = 0; var parent = dom.parentNode; var outerWidth = 0; while (true) { if (!parent || parent.nodeType != 1) break; var parent_style = getComputedStyle(parent); if (!parent_style) break; parent_width = parent.clientWidth - parseFloat(parent_style.paddingLeft) - parseFloat(parent_style.paddingRight) - outerWidth; if (parent_width > 16) break; outerWidth += parseFloat(parent_style.paddingLeft) + parseFloat(parent_style.paddingRight) + parseFloat(parent_style.marginLeft) + parseFloat(parent_style.marginRight) + parseFloat(parent_style.borderLeftWidth) + parseFloat(parent_style.borderRightWidth); parent = parent.parentNode; } return parent_width; } var getOuterW = function (dom) { var style = getComputedStyle(dom), w = 0; if (!!style) { w = parseFloat(style.paddingLeft) + parseFloat(style.paddingRight) + parseFloat(style.borderLeftWidth) + parseFloat(style.borderRightWidth); } return w; }; var getOuterH = function (dom) { var style = getComputedStyle(dom), h = 0; if (!!style) { h = parseFloat(style.paddingTop) + parseFloat(style.paddingBottom) + parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth); } return h; }; var insertAfter = function (dom, afterDom) { var _p = afterDom.parentNode; if (!_p) { return; } if (_p.lastChild === afterDom) { _p.appendChild(dom); } else { _p.insertBefore(dom, afterDom.nextSibling); } }; var getQuery = function (name, url) { var u = arguments[1] || window.location.search, reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"), r = u.substr(u.indexOf("\?") + 1).match(reg); return r != null ? r[2] : ""; }; function setImgSize(item, widthNum, widthUnit, ratio, breakParentWidth) { setTimeout(function () { var img_padding_border = getOuterW(item) || 0; var img_padding_border_top_bottom = getOuterH(item) || 0; if (widthNum > getParentWidth(item) && !breakParentWidth) { widthNum = getParentWidth(item); } var height = (widthNum - img_padding_border) * ratio + img_padding_border_top_bottom; if (isCarton) { var url = item.getAttribute('src'); item.src = url; item.style.height = 'auto'; } else { widthNum !== 'auto' && (item.style.cssText += ";width: " + widthNum + widthUnit + " !important;"); widthNum !== 'auto' && (item.style.cssText += ";height: " + height + widthUnit + " !important;"); } }, 10); } window.__videoDefaultRatio = 16 / 9;//默认值是16/9 window.__getVideoWh = function (dom) { var max_width = getMaxWith(), width = max_width, ratio_ = dom.getAttribute('data-ratio') * 1,//mark16/9 arr = [4 / 3, 16 / 9], ret = arr[0], abs = Math.abs(ret - ratio_); if (!ratio_) { if (dom.getAttribute("data-mpvid")) { ratio_ = 16 / 9; } else { ratio_ = 4 / 3; } } else { for (var j = 1, jl = arr.length; j < jl; j++) { var _abs = Math.abs(arr[j] - ratio_); if (_abs < abs) { abs = _abs; ret = arr[j]; } } ratio_ = ret; } var parent_width = getParentWidth(dom) || max_width, width = width > parent_width ? parent_width : width, outerW = getOuterW(dom) || 0, outerH = getOuterH(dom) || 0, videoW = width - outerW, videoH = videoW / ratio_, speedDotH = 12, height = videoH + outerH + speedDotH; return { w: Math.ceil(width), h: Math.ceil(height), vh: videoH, vw: videoW, ratio: ratio_, sdh: speedDotH }; }; (function () { var iframe = document.getElementsByTagName('iframe'); for (var i = 0, il = iframe.length; i < il; i++) { if (window.__second_open__ && iframe[i].getAttribute('__sec_open_place_holder__')) { continue; } var a = iframe[i]; var src_ = a.getAttribute('src') || a.getAttribute('src') || ""; var vid = getQuery("vid", src_) || a.getAttribute('data-mpvid'); if (!vid) { continue; } vid = vid.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, "");//清除前后空格 a.removeAttribute('src'); a.style.display = "none"; var obj = window.__getVideoWh(a), videoPlaceHolderSpan = document.createElement('span'); videoPlaceHolderSpan.className = "js_img_placeholder wx_widget_placeholder"; videoPlaceHolderSpan.setAttribute("data-vid", vid); videoPlaceHolderSpan.innerHTML = '<span class="weui-primary-loading"><span class="weui-primary-loading__dot"></span></span>'; videoPlaceHolderSpan.style.cssText = "width: " + obj.w + "px !important;"; insertAfter(videoPlaceHolderSpan, a); var mid = "" || "" || "2247616950"; var biz = "" || "MzU0OTk3ODQ3Ng=="; var sessionid = "" || "svr_5fc3db74245"; var idx = "" || "1"; var hitInfos = [ ]; (function setHitStyle(parentNode, copyIframe, index, vid) { var ret = (hitInfos || []).find(function (info) { return info.video_id === vid; } ); if (!ret) return; var ori = ret.ori_status; var hit_biz_headimg = ret.hit_biz_headimg + '/64'; var hit_nickname = ret.hit_nickname; var hit_username = ret.hit_username; var sourceBiz = ret.hit_bizuin; var selfUserName = "gh_6258c101a32a"; if (ori === 2 && selfUserName !== hit_username) { var videoBar = document.createElement('div'); var videoBarHtml = '<div class="wx-edui-video_source_link js_wx_tap_highlight wx_tap_card" id="' + (hit_username + index) + '" data-hit-username="' + hit_username + '" data-hit-biz="' + sourceBiz + '">'; videoBarHtml += '<div class="wx-edui-video_source_word">以下视频来源于</div>'; videoBarHtml += '<div class="wx-edui-video_account_info">'; videoBarHtml += '<div class="wx-edui-video_account_avatar" id="' + (hit_biz_headimg + index) + '" src="' + hit_biz_headimg + '"></div>'; videoBarHtml += '<div class="wx-edui-video_account_name">' + hit_nickname + '</div>'; videoBarHtml += '<i class="wx-edui-video_account_arrow"></i>'; videoBarHtml += '</div>'; videoBarHtml += '<div class="wx-edui-video_source_link__layer_mask"></div>'; videoBarHtml += '</div>'; videoBar.innerHTML = videoBarHtml; var spanContainer = document.getElementById('js_mp_video_container_' + index); if (spanContainer) { spanContainer.parentNode.insertBefore(videoBar, spanContainer); } else if (parentNode.contains && parentNode.contains(copyIframe)) { parentNode.insertBefore(videoBar, copyIframe); } else { parentNode.insertBefore(videoBar, parentNode.firstElementChild); } var avatorEle = document.getElementById(hit_biz_headimg + index); var avatorSrc = avatorEle.dataset.src; console.log('avatorSrc' + avatorSrc); if (ret.hit_biz_headimg) { avatorEle.style.backgroundImage = 'url(' + avatorSrc + ')'; } } })(a.parentNode, a, i, vid); a.style.cssText += ";width: " + obj.w + "px !important;"; a.setAttribute("width", obj.w); if (window.__zoom != 1) { a.style.display = "block"; videoPlaceHolderSpan.style.display = "none"; a.setAttribute("_ratio", obj.ratio); a.setAttribute("_vid", vid); } else { videoPlaceHolderSpan.style.cssText += "height: " + (obj.h - obj.sdh) + "px !important;margin-bottom: " + obj.sdh + "px !important;"; a.style.cssText += "height: " + obj.h + "px !important;"; a.setAttribute("height", obj.h); } a.setAttribute("data-vh", obj.vh); a.setAttribute("data-vw", obj.vw); if (a.getAttribute("data-mpvid")) { a.setAttribute("src", location.protocol + "//mp.weixin.qq.com/mp/readtemplate?t=pages/video_player_tmpl&auto=0&vid=" + vid); } else { a.setAttribute("src", location.protocol + "//v.qq.com/iframe/player.html?vid=" + vid + "&width=" + obj.vw + "&height=" + obj.vh + "&auto=0"); } } })(); (function () { if (window.__zoom != 1) { if (!window.__second_open__) { document.getElementById('page-content').style.zoom = window.__zoom; var a = document.getElementById('activity-name'); var b = document.getElementById('meta_content'); if (!!a) { a.style.zoom = 1 / window.__zoom; } if (!!b) { b.style.zoom = 1 / window.__zoom; } } var images = document.getElementsByTagName('img'); for (var i = 0, il = images.length; i < il; i++) { if (window.__second_open__ && images[i].getAttribute('__sec_open_place_holder__')) { continue; } images[i].style.zoom = 1 / window.__zoom; } var iframe = document.getElementsByTagName('iframe'); for (var i = 0, il = iframe.length; i < il; i++) { if (window.__second_open__ && iframe[i].getAttribute('__sec_open_place_holder__')) { continue; } var a = iframe[i]; a.style.zoom = 1 / window.__zoom; var src_ = a.getAttribute('src') || ""; if (!/^http(s)*\:\/\/v\.qq\.com\/iframe\/(preview|player)\.html\?/.test(src_) && !/^http(s)*\:\/\/mp\.weixin\.qq\.com\/mp\/readtemplate\?t=pages\/video_player_tmpl/.test(src_) ) { continue; } var ratio = a.getAttribute("_ratio"); var vid = a.getAttribute("_vid"); a.removeAttribute("_ratio"); a.removeAttribute("_vid"); var vw = a.offsetWidth - (getOuterW(a) || 0); var vh = vw / ratio; var h = vh + (getOuterH(a) || 0) a.style.cssText += "height: " + h + "px !important;" a.setAttribute("height", h); if (/^http(s)*\:\/\/v\.qq\.com\/iframe\/(preview|player)\.html\?/.test(src_)) { a.setAttribute("src", location.protocol + "//v.qq.com/iframe/player.html?vid=" + vid + "&width=" + vw + "&height=" + vh + "&auto=0"); } a.style.display = "none"; var parent = a.parentNode; if (!parent) { continue; } for (var j = 0, jl = parent.children.length; j < jl; j++) { var child = parent.children[j]; if (child.className.indexOf("js_img_placeholder") >= 0 && child.getAttribute("data-vid") == vid) { child.style.cssText += "height: " + h + "px !important;"; child.style.display = ""; } } } } })(); })(); var anchor_tree_msg = ''; </script> <script type="text/javascript" nonce="1989770072" reportloaderror>(function () { 'use strict'; var _Speed = {}; var _userDefine; var _imgurl = 'https://badjs.weixinbridge.com/frontend/reportspeed?'; function saveSpeeds$1(obj) { if (!obj.pid || !obj.speeds) { return -1; } if (!Array.isArray(obj.speeds)) { obj.speeds = [obj.speeds]; } if (obj.user_define) { _userDefine = obj.user_define; } var pid_uin_rid = _conbinUPRid(obj); for (var i = 0; i < obj.speeds.length; i++) { var os = obj.speeds[i]; os.time = Math.floor(+os.time); if (os.sid > 20 && os.time >= 0) _setSidTime(pid_uin_rid, os.sid, os.time); } } function send$1() { _doFunc(function () { setTimeout(function () { for (var item in _Speed) { _get({ pid_uin_rid: item, speeds: _Speed[item], user_define: _userDefine }, _imgurl); } _Speed = {}; }, 100); }); } function setFirstViewTime(obj) { _doFunc(function () { if (!obj.pid || !obj.time) return -1; var pid_uin_rid = _conbinUPRid(obj); _setSidTime(pid_uin_rid, 9, obj.time); }); } function setBasicTime$1(obj) { _doFunc(function () { var pid_uin_rid = _conbinUPRid(obj); if (!_Speed[pid_uin_rid]) _Speed[pid_uin_rid] = []; var performance = window.performance || window.msPerformance || window.webkitPerformance || {}; if (!!performance && !!performance.timing) { var timing = performance.timing || {}; _setSidTime(pid_uin_rid, 1, timing.domainLookupEnd - timing.domainLookupStart); _setSidTime(pid_uin_rid, 2, location.protocol == "https:" && timing.secureConnectionStart != 0 ? timing.connectEnd - timing.secureConnectionStart : 0); _setSidTime(pid_uin_rid, 3, timing.connectEnd - timing.connectStart); _setSidTime(pid_uin_rid, 4, timing.responseStart - timing.requestStart); _setSidTime(pid_uin_rid, 5, timing.responseEnd - timing.responseStart); _setSidTime(pid_uin_rid, 6, timing.domContentLoadedEventStart - timing.domLoading); _setSidTime(pid_uin_rid, 7, timing.domComplete == 0 ? 0 : timing.domComplete - timing.domLoading); _setSidTime(pid_uin_rid, 8, timing.loadEventEnd == 0 ? 0 : timing.loadEventEnd - timing.loadEventStart); (function (_Speed) { setTimeout(function () { if (timing.loadEventEnd) { _setSidTime(pid_uin_rid, 7, timing.domComplete == 0 ? 0 : timing.domComplete - timing.domLoading); _setSidTime(pid_uin_rid, 8, timing.loadEventEnd == 0 ? 0 : timing.loadEventEnd - timing.loadEventStart); } }, 0); })(); if (!_Speed[pid_uin_rid][9]) _setSidTime(pid_uin_rid, 9, timing.domContentLoadedEventStart - timing.navigationStart); _setSidTime(pid_uin_rid, 10, timing.redirectEnd - timing.redirectStart); _setSidTime(pid_uin_rid, 11, timing.domainLookupStart - timing.fetchStart); _setSidTime(pid_uin_rid, 12, timing.domLoading - timing.responseStart); } }); } function _setSidTime(pid_uin_rid, sid, time) { _Speed[pid_uin_rid] = _Speed[pid_uin_rid] || []; _Speed[pid_uin_rid][sid] = _Speed[pid_uin_rid][sid] || []; if (time < 0) return; if (sid < 21) _Speed[pid_uin_rid][sid][0] = time;else _Speed[pid_uin_rid][sid].push(time); } function _conbinUPRid(obj) { if (!obj || !obj.pid) { console && console.error('Must provide a pid'); return ''; } return "".concat(obj.pid, "_").concat(obj.uin || 0, "_").concat(obj.rid || 0); } function _get(obj, url) { var apur = obj.pid_uin_rid.split('_'); var spur = ''; if (apur.length == 3) { spur = "pid=".concat(apur[0], "&uin=").concat(apur[1], "&rid=").concat(apur[2]); } else { console && console.error('pid,uin,rid, invalid args'); return; } if (obj.user_define) { spur += "&user_define=".concat(obj.user_define); } var url1 = "".concat(url + spur, "&speeds="); var url2 = ''; var urlarr = []; for (var i = 1; i < obj.speeds.length; i++) { if (obj.speeds[i]) { for (var j = 0; j < obj.speeds[i].length; j++) { var s = "".concat(i, "_").concat(obj.speeds[i][j]); if (url1.length + url2.length + s.length < 1024) { url2 = "".concat(url2 + s, ";"); } else { if (url2.length) urlarr.push(url1 + url2.substring(0, url2.length - 1)); url2 = "".concat(s, ";"); } } if (i == obj.speeds.length - 1) { urlarr.push(url1 + url2.substring(0, url2.length - 1)); } } } for (var _i = 0; _i < urlarr.length; _i++) { new Image().src = urlarr[_i]; } } var cblist = []; function _doFunc(fnc) { if (document.readyState == "complete") { fnc(); } else { cblist.push(fnc); } } window.addEventListener('load', onLoad, false); function onLoad() { for (var i = 0; i < cblist.length; i++) { cblist[i](); } cblist = []; } var wxgsdk = { saveSpeeds: saveSpeeds$1, send: send$1, setFirstViewTime: setFirstViewTime, setBasicTime: setBasicTime$1 }; var reportLogs = []; var reportExtraLogs = []; var sendUrl = '/mp/jsmonitor?#wechat_redirect'; var monitor = {}; monitor._reportOptions = { idkey: {} }; function ObjWithoutProperty(source, exclude) { if (source === null) return {}; var target = {}; var sourceKeys = Object.keys(source); for (var i = 0; i < sourceKeys.length; i++) { var key = sourceKeys[i]; if (exclude.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } function formatDataToString(data) { var reportData = []; for (var key in data) { if (Object.prototype.hasOwnProperty.call(data, key)) { reportData.push(key + '=' + encodeURIComponent(data[key])); } } return reportData.join('&'); } monitor.getReportData = function (opt) { opt = opt || {}; var idkey = monitor._reportOptions.idkey || {}; var key = null; var reportData = {}; var nextKey; try { for (key in idkey) { if (Object.prototype.hasOwnProperty.call(idkey, key) && idkey[key]) { reportLogs.push(key + '_' + idkey[key]); } } } catch (e) { return false; } if (reportLogs.length === 0) { return false; } if (reportExtraLogs.length) { reportData.lc = reportExtraLogs.length; reportExtraLogs.forEach(function (extraLog, index) { reportData["log".concat(index)] = extraLog; }); } try { var reportOptions = monitor._reportOptions; if (reportOptions !== null && reportOptions !== undefined) { for (nextKey in reportOptions) { if (Object.prototype.hasOwnProperty.call(reportOptions, nextKey)) { reportData[nextKey] = reportOptions[nextKey]; } } } } catch (e) { reportData = {}; } reportData.idkey = reportLogs.join(';'); reportData.t = Math.random(); if (opt.remove !== false) { reportLogs = []; reportExtraLogs = []; monitor._reportOptions = { idkey: {} }; } return reportData; }; monitor.setLogs = function (opt) { var id = opt.id; var key = opt.key; var value = opt.value; var extraLog = opt.log; var others = ObjWithoutProperty(opt, ['id', 'key', 'value', 'log']); var idkey = monitor._reportOptions.idkey || {}; var param = id + '_' + key; if (idkey[param]) { idkey[param] += value; } else { idkey[param] = value; } monitor._reportOptions.idkey = idkey; if (extraLog) { reportExtraLogs.push(extraLog); } try { if (others !== null && others !== undefined) { for (var otherKey in others) { if (Object.prototype.hasOwnProperty.call(others, otherKey)) { monitor._reportOptions[otherKey] = others[otherKey]; } } } } catch (e) { console.log(e); } return monitor; }; monitor.setAvg = function (id, key, value) { var idkey = monitor._reportOptions.idkey || {}; var param1 = id + '_' + key; var param2 = id + '_' + (key - 1); if (idkey[param1]) { idkey[param1] += value; } else { idkey[param1] = value; } if (idkey[param2]) { idkey[param2] += 1; } else { idkey[param2] = 1; } monitor._reportOptions.idkey = idkey; return monitor; }; monitor.setSum = function (id, key) { var value = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1; var idkey = monitor._reportOptions.idkey; var param = id + '_' + key; if (idkey[param]) { idkey[param] += value; } else { idkey[param] = value; } monitor._reportOptions.idkey = idkey; return monitor; }; monitor.send = function (async, ajax, origin) { if (async !== false) { async = true; } var data = monitor.getReportData(); origin = origin || ''; if (!data) { return; } if (!!ajax && ajax instanceof Function) { ajax({ url: origin + sendUrl, type: 'POST', mayAbort: true, data: data, async: async, timeout: 2000 }); } else { new Image().src = origin + '/mp/jsmonitor?' + formatDataToString(data) + '#wechat_redirect'; } }; if (typeof window !== 'undefined' && window.__monitor) { monitor = window.__monitor; } else { typeof window !== 'undefined' && (window.__monitor = monitor); } var monitor$1 = monitor; function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); } function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); } function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } var logList = []; var log = function log(msg) { logList.push(msg); }; var printLog = function printLog() { for (var i = 0, len = logList.length; i < len; ++i) { console.log("[RespType]".concat(logList[i])); } }; var isArray = function isArray(val) { return Object.prototype.toString.call(val) === '[object Array]'; }; var getValueType = function getValueType(value) { if (isArray(value)) { return 'array'; } return _typeof(value); }; var parseRtDesc = function parseRtDesc(rtDesc, k) { var type = 'mix'; var isRequired = false; var key = k; if (k) { var requireKeyWord = '_R'; var pos = k.indexOf(requireKeyWord); var len = k.length - requireKeyWord.length; isRequired = pos !== -1 && pos === len; key = isRequired ? k.substring(0, len) : k; } if (typeof rtDesc === 'string') { type = rtDesc; } else if (isArray(rtDesc)) { type = 'array'; } else if (_typeof(rtDesc) === 'object') { type = 'object'; } return { key: key, type: type, isRequired: isRequired }; }; var checkForArrayRtDesc = function checkForArrayRtDesc(arr, rtDescs) { if (!isArray(arr)) { return false; } for (var i = 0, len = arr.length; i < len; ++i) { var value = arr[i]; var rtDesc = void 0; var j = 0; var flag = rtDescs.length === 0; while (rtDesc = rtDescs[j++]) { if (checkForRtDesc(value, rtDesc)) { flag = true; break; } } if (!flag) { return false; } } return true; }; var checkForStringRtDesc = function checkForStringRtDesc(value, rtDesc) { var valueType = getValueType(value); var desc = parseRtDesc(rtDesc); var ret = desc.type === valueType; if (!ret) { log("miss match type : ".concat(valueType, " !== ").concat(desc.type)); } return ret; }; var checkForObjectRtDesc = function checkForObjectRtDesc(json, rtDesc) { if (_typeof(json) !== 'object' || isArray(json)) { log('must be object'); return false; } var rootJson = json; var nowCheckValue = json; for (var k in rtDesc) { if (rtDesc.hasOwnProperty(k)) { var nowCheckDesc = rtDesc[k]; var desc = parseRtDesc(nowCheckDesc, k); var key = desc.key; nowCheckValue = rootJson[key]; var valueType = getValueType(nowCheckValue); if (desc.isRequired && nowCheckValue === undefined) { log("is required @key=".concat(key)); return false; } if (nowCheckValue !== undefined) { if (valueType !== desc.type && desc.type !== 'mix') { log("miss match type : ".concat(valueType, " !== ").concat(desc.type, " @key=").concat(key)); return false; } if ((valueType === 'array' || valueType === 'object') && desc.type !== 'mix') { if (!checkForRtDesc(nowCheckValue, nowCheckDesc)) { return false; } } } } } return true; }; var checkForRtDesc = function checkForRtDesc(json, rtDesc) { if (isArray(rtDesc)) { return checkForArrayRtDesc(json, rtDesc); } if (_typeof(rtDesc) === 'object') { return checkForObjectRtDesc(json, rtDesc); } if (typeof rtDesc === 'string') { return checkForStringRtDesc(json, rtDesc); } return false; }; var _check = function check(json, rtDescs) { if (typeof json === 'string') { try { json = eval("(".concat(json, ")")); } catch (e) { log('parse json error'); return false; } } if (_typeof(json) !== 'object') { log('must be object'); return false; } if (!isArray(rtDescs)) { rtDescs = [rtDescs]; } var rtDesc; var i = 0; while (rtDesc = rtDescs[i++]) { if (checkForRtDesc(json, rtDesc)) { return true; } } return false; }; var RespTypes = { check: function check(json, rtDesc) { logList = []; try { var ret = _check(json, rtDesc); if (!ret) { printLog(); } return ret; } catch (e) { logList.push("[rtException]".concat(e.toString())); printLog(); return false; } }, getMsg: function getMsg() { return logList.join(';'); } }; function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray$1(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; } function _unsupportedIterableToArray$1(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray$1(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$1(o, minLen); } function _arrayLikeToArray$1(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } var ua = navigator.userAgent; var is_ios = /(iPhone|iPad|iPod|iOS)/i.test(ua); var is_wp = /Windows\sPhone/i.test(ua); var is_android = /(Android)/i.test(ua); var is_wechat = /MicroMessenger\/([\d\.]+)/i.test(ua); var is_mac = /mac\sos/i.test(ua) && !is_ios; var is_windows = /windows\snt/i.test(ua) && !is_wp; var is_mpapp = /MPAPP\/([\d\.]+)/i.test(ua); var is_ipad = /iPad/i.test(ua); var is_windows_wechat = /WindowsWechat/i.test(ua); var is_mac_wechat = /MacWechat/i.test(ua) || /wechat.*mac os/i.test(ua); var is_prefetch = is_wechat && window.WeixinPrefecherJSBridge; var is_donut_app = /SAAASDK/i.test(ua); var is_harmony = /OpenHarmony|ArkWeb/i.test(ua); var is_in_miniProgram = is_android && /miniprogram/.test(ua.toLowerCase()) || window.__wxjs_environment == 'miniprogram'; var is_wx_work = /wxwork/i.test(ua); function getUrlParams() { var vars = location.search.substring(1).split('&'); var params = {}; var _iterator = _createForOfIteratorHelper(vars), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var ele = _step.value; var pair = ele.split('='); var key = decodeURIComponent(pair[0]); if (typeof params[key] === 'undefined') { params[key] = decodeURIComponent(pair[1]); } } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } return params; } function get() { var reg = /MicroMessenger\/([\d\.]+)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1]; } return false; } function getMac() { var reg = /MacWechat\/([\d\.]+)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1]; } return false; } function getMacOS() { var reg = /Mac OS X ([\d_]+)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1].replace(/_/g, '.'); } return false; } function getWindows() { var reg = /WindowsWechat\(0x(.+?)\)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1]; } return false; } function getWxWork() { var reg = /wxwork\/([\d\.]+)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1]; } return false; } function getMpApp() { var appVersion = [2, 4, 5]; var match = navigator.userAgent.match(/MPAPP\/(\d+(\.\d+)*)/); if (match) { appVersion = match[1].split('.').map(function (v) { return Number(v); }); } return appVersion.join('.'); } function getUnifiedPcVer() { var versionInfo = navigator.userAgent.match(/UnifiedPC\w+Wechat\(0xf\w{2}(\w+?)\w{2}\)/); if (versionInfo && versionInfo.length === 2) { var version = versionInfo[1]; var mainVersion = getVersionNumber(version.slice(0, 1)); var subVersion = getVersionNumber(version.slice(1, 2)); var subVersion2 = getVersionNumber(version.slice(2, 3)); return [mainVersion, subVersion, subVersion2].join('.'); } } function getVersionNumber(hexStr) { return Number(Number("0x".concat(hexStr)).toString(10)); } function getWindowsVersionFormat() { var versionInfo = navigator.userAgent.match(/WindowsWechat\(0x(\w+?)\)/); if (versionInfo && versionInfo.length === 2) { var version = versionInfo[1]; var mainVersion = getVersionNumber(version.slice(1, 2)); var subVersion = getVersionNumber(version.slice(2, 4)); var subVersion2 = getVersionNumber(version.slice(4, 6)); return [mainVersion, subVersion, subVersion2].join('.'); } return false; } function getInner() { var reg = /MicroMessenger\/[\d\.]+\(0x(.+?)\)/i; var ret = ua.match(reg); if (ret && ret[1] && ret[1] != null) { return ret[1]; } if (!ret && /MicroMessenger\/[\d\.]+/i.test(ua)) { var urlParams = getUrlParams(); if (urlParams.version) { return urlParams.version; } } return false; } var opfunc = { 'cp-1': function cp1(a, b) { return a < b; }, cp0: function cp0(a, b) { return a === b; }, cp1: function cp1(a, b) { return a > b; } }; function cpVersion(ver, op, canEq, type) { var mmver = false; switch (type) { case 'mac': mmver = getMac(); break; case 'windows': mmver = getWindowsVersionFormat(); break; case 'wxwork': mmver = getWxWork(); break; case 'mpapp': mmver = getMpApp(); break; case 'unifiedpc': mmver = getUnifiedPcVer(); break; default: mmver = get(); break; } if (!mmver) { return; } var mmversion = mmver.split('.'); var version = ver.split('.'); if (!/\d+/g.test(mmversion[mmversion.length - 1])) { mmversion.pop(); } for (var i = 0, len = Math.max(mmversion.length, version.length); i < len; ++i) { var mmv = mmversion[i] || ''; var v = version[i] || ''; var mmvn = parseInt(mmv, 10) || 0; var vn = parseInt(v, 10) || 0; var eq = opfunc.cp0(mmvn, vn); if (eq) { continue; } var cp = opfunc["cp".concat(op)]; return cp(mmvn, vn); } return canEq || op === 0; } function eqVersion(version) { return cpVersion(version, 0); } function gtVersion(version, canEq) { return cpVersion(version, 1, canEq); } function ltVersion(version, canEq) { return cpVersion(version, -1, canEq); } function getPlatform() { if (is_ios) { return 'ios'; } if (is_android) { return 'android'; } if (is_mac) { return 'mac_os'; } if (is_windows) { return 'windows'; } return 'unknown'; } var is_google_play = false; var inner_ver_for_google_play_check = getInner(); if (is_android && inner_ver_for_google_play_check) { var v = "0x".concat(inner_ver_for_google_play_check.substr(-2)); if (parseInt(v) >= 64 && parseInt(v) <= 79) { is_google_play = true; } } var mmversion = { get: get, getMac: getMac, getMacOS: getMacOS, getWindows: getWindows, getInner: getInner, getWxWork: getWxWork, getMpApp: getMpApp, cpVersion: cpVersion, eqVersion: eqVersion, gtVersion: gtVersion, ltVersion: ltVersion, getPlatform: getPlatform, getVersionNumber: getVersionNumber, isWp: is_wp, isIOS: is_ios, isAndroid: is_android, isHarmony: is_harmony, isHarmonyWechat: is_harmony && is_wechat && cpVersion('1.0.0', 1, true), isInMiniProgram: is_in_miniProgram, isWechat: is_wechat, isMac: is_mac, isWindows: is_windows, isMacWechat: is_mac_wechat, isWindowsWechat: is_windows_wechat, isWxWork: is_wx_work, isOnlyWechat: is_wechat && !is_wx_work, isMpapp: is_mpapp, isNewMpApp: false, isIPad: is_ipad, isGooglePlay: is_google_play, isPrefetch: is_prefetch, isDonutAPP: is_donut_app }; var Device = {}; function detect(ua) { var MQQBrowser = ua.match(/MQQBrowser\/(\d+\.\d+)/i); var MQQClient = ua.match(/QQ\/(\d+\.(\d+)\.(\d+)\.(\d+))/i) || ua.match(/V1_AND_SQ_([\d\.]+)/); var WeChat = ua.match(/MicroMessenger\/((\d+)\.(\d+))\.(\d+)/) || ua.match(/MicroMessenger\/((\d+)\.(\d+))/); var MacOS = ua.match(/Mac\sOS\sX\s(\d+[\.|_]\d+)/); var WinOS = ua.match(/Windows(\s+\w+)?\s+?(\d+\.\d+)/); var Linux = ua.match(/Linux\s/); var MiuiBrowser = ua.match(/MiuiBrowser\/(\d+\.\d+)/i); var M1 = ua.match(/MI-ONE/); var MIPAD = ua.match(/MI PAD/); var UC = ua.match(/UCBrowser\/(\d+\.\d+(\.\d+\.\d+)?)/) || ua.match(/\sUC\s/); var IEMobile = ua.match(/IEMobile(\/|\s+)(\d+\.\d+)/) || ua.match(/WPDesktop/); var ipod = ua.match(/(ipod).*\s([\d_]+)/i); var ipad = ua.match(/(ipad).*\s([\d_]+)/i); var iphone = ua.match(/(iphone)\sos\s([\d_]+)/i); var Chrome = ua.match(/Chrome\/(\d+\.\d+)/); var AndriodBrowser = ua.match(/Mozilla.*Linux.*Android.*AppleWebKit.*Mobile Safari/); var android = ua.match(/(android)\s([\d\.]+)/i); var harmony = ua.match(/(OpenHarmony)\s([\d\.]+)/i); Device.browser = Device.browser || {}, Device.os = Device.os || {}; if (window.ActiveXObject) { var vie = 6; (window.XMLHttpRequest || ua.indexOf('MSIE 7.0') > -1) && (vie = 7); (window.XDomainRequest || ua.indexOf('Trident/4.0') > -1) && (vie = 8); ua.indexOf('Trident/5.0') > -1 && (vie = 9); ua.indexOf('Trident/6.0') > -1 && (vie = 10); Device.browser.ie = true, Device.browser.version = vie; } else if (ua.indexOf('Trident/7.0') > -1) { Device.browser.ie = true, Device.browser.version = 11; } if (android) { Device.os.android = true; Device.os.version = android[2]; } if (harmony) { Device.os.harmony = true; Device.os.version = harmony[2]; } if (ipod) { Device.os.ios = Device.os.ipod = true; Device.os.version = ipod[2].replace(/_/g, '.'); } if (ipad) { Device.os.ios = Device.os.ipad = true; Device.os.version = ipad[2].replace(/_/g, '.'); } if (iphone) { Device.os.iphone = Device.os.ios = true; Device.os.version = iphone[2].replace(/_/g, '.'); } if (WinOS) Device.os.windows = true, Device.os.version = WinOS[2]; if (MacOS) Device.os.Mac = true, Device.os.version = MacOS[1]; if (Linux) Device.os.Linux = true; if (ua.indexOf('lepad_hls') > 0) Device.os.LePad = true; if (MIPAD) Device.os.MIPAD = true; if (MQQBrowser) Device.browser.MQQ = true, Device.browser.version = MQQBrowser[1]; if (MQQClient) Device.browser.MQQClient = true, Device.browser.version = MQQClient[1]; if (WeChat) Device.browser.WeChat = true, Device.browser.mmversion = Device.browser.version = WeChat[1]; if (MiuiBrowser) Device.browser.MIUI = true, Device.browser.version = MiuiBrowser[1]; if (UC) Device.browser.UC = true, Device.browser.version = UC[1] || NaN; if (IEMobile) Device.browser.IEMobile = true, Device.browser.version = IEMobile[2]; if (AndriodBrowser) { Device.browser.AndriodBrowser = true; } if (M1) { Device.browser.M1 = true; } if (Chrome) { Device.browser.Chrome = true, Device.browser.version = Chrome[1]; } if (Device.os.windows) { if (typeof navigator.platform !== "undefined" && navigator.platform.toLowerCase() == "win64") { Device.os.win64 = true; } else { Device.os.win64 = false; } } if (Device.os.Mac || Device.os.windows || Device.os.Linux) { Device.os.pc = true; } var osType = { iPad7: 'iPad; CPU OS 7', LePad: 'lepad_hls', XiaoMi: 'MI-ONE', SonyDTV: "SonyDTV", SamSung: 'SAMSUNG', HTC: 'HTC', VIVO: 'vivo' }; for (var os in osType) { Device.os[os] = ua.indexOf(osType[os]) !== -1; } Device.os.phone = Device.os.phone || /windows phone/i.test(ua); Device.os.getNumVersion = function () { return parseFloat(Device.os.version); }; Device.os.hasTouch = 'ontouchstart' in window; if (Device.os.hasTouch && Device.os.ios && Device.os.getNumVersion() < 6) { Device.os.hasTouch = false; } if (Device.browser.WeChat && Device.browser.version < 5.0) { Device.os.hasTouch = false; } Device.browser.getNumVersion = function () { return parseFloat(Device.browser.version); }; Device.browser.isFFCanOcx = function () { return !!Device.browser.firefox && Device.browser.getNumVersion() >= 3.0; }; Device.browser.isCanOcx = function () { return !!Device.os.windows && (!!Device.browser.ie || Device.browser.isFFCanOcx() || !!Device.browser.webkit); }; Device.browser.isNotIESupport = function () { return !!Device.os.windows && (!!Device.browser.webkit || Device.browser.isFFCanOcx()); }; Device.userAgent = {}; Device.userAgent.browserVersion = Device.browser.version; Device.userAgent.osVersion = Device.os.version; Device.os.unifiedPC = ua.match(/UnifiedPC/); delete Device.userAgent.version; } detect(window.navigator.userAgent); function canSupportH5Video() { var ua = window.navigator.userAgent, m = null; if (!!Device.os.android) { if (Device.browser.MQQ && Device.browser.getNumVersion() >= 4.2) { return true; } if (ua.indexOf('MI2') != -1) { return true; } if (Device.os.version >= '4' && (m = ua.match(/MicroMessenger\/((\d+)\.(\d+))\.(\d+)/))) { if (parseFloat(m[1]) >= 4.2) { return true; } } if (Device.os.version >= '4.1') { return true; } } return false; } function canSupportVideoMp4() { var video = document.createElement('video'); if (typeof video.canPlayType === 'function') { if (video.canPlayType('video/mp4; codecs="mp4v.20.8"') === 'probably') { return true; } if (video.canPlayType('video/mp4; codecs="avc1.42E01E"') === 'probably' || video.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"') === 'probably') { return true; } } return false; } function canSupportAutoPlay() { if (Device.os.ios && Device.os.getNumVersion() < 10) { return false; } return true; } function isLockdownMode() { if (!Device.os.ios || Device.os.getNumVersion() < 16) { return false; } if (typeof WebAssembly === 'undefined' && typeof OfflineAudioContext === 'undefined' && typeof WebGLRenderingContext === 'undefined') { return true; } return false; } Device.canSupportVideo = canSupportVideoMp4 || canSupportH5Video; Device.canSupportVideoMp4 = canSupportVideoMp4; Device.canSupportH5Video = canSupportH5Video; Device.canSupportAutoPlay = canSupportAutoPlay; Device.isLockdownMode = isLockdownMode; Device.cpVersion = function (version) { var cp = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; var canEqual = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; var nowVersionStr = Device.os.version; if (!nowVersionStr) return false; var versionArr = version.split('.'); var nowVersionArr = nowVersionStr.split('.'); for (var i = 0; i < Math.max(nowVersionArr.length, versionArr.length); i++) { var vi = +versionArr[i]; var nvi = +nowVersionArr[i]; if (vi === nvi) continue; if (cp > 0) return vi > nvi; if (cp < 0) return vi < nvi; } return canEqual || cp === 0; }; var initJsBridge = false; if (!window.JSAPIEventCallbackMap) { window.JSAPIEventCallbackMap = {}; } function connectWebViewJavascriptBridge(callback) { if (window.WebViewMPapp || window.WebViewJavascriptBridge) { return callback(window.WebViewMPapp || window.WebViewJavascriptBridge); } if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); } window.WVJBCallbacks = [callback]; if (!initJsBridge) { initJsBridge = true; var WVJBIframe = document.createElement('iframe'); WVJBIframe.style.display = 'none'; WVJBIframe.src = 'https://__bridge_loaded__'; document.body.appendChild(WVJBIframe); setTimeout(function () { initJsBridge = false; document.body.removeChild(WVJBIframe); }, 0); } return false; } function invoke$1(jsapiName, opt, callback) { connectWebViewJavascriptBridge(function (bridge) { try { if (typeof opt === 'function') { callback = opt; } if (_typeof(opt) !== 'object' && typeof opt !== 'string') { opt = {}; } bridge.callHandler(jsapiName, opt, function (res) { try { var ret = _typeof(res) === 'object' ? res : JSON.parse(res); var errMsg = ret.err_msg || ret.errMsg; console.info("[mpapp jsapi] invoke->".concat(jsapiName, " ").concat(opt.action || '', " ").concat(errMsg)); typeof callback === 'function' && callback(ret); } catch (e) { window.WX_BJ_REPORT.BadJs.report('invoke', "callback ".concat(jsapiName, " error:"), { mid: 'mmbizwebapp:js_brridge', _info: e }); console.error("[mpapp jsapi] ".concat(jsapiName, " ").concat(opt.action || ''), e, res); } }); } catch (e) { window.WX_BJ_REPORT.BadJs.report('invoke', 'callback error:', { mid: 'mmbizwebapp:js_brridge', _info: e }); console.error('[mpapp jsapi]', e); } }); } var doc$1 = {}; var isAcrossOrigin$1 = false; var __moon_report$1 = window.__moon_report || function () {}; var MOON_JSAPI_KEY_OFFSET = 8; try { doc$1 = top.window.document; } catch (e) { isAcrossOrigin$1 = true; } if (!window.JSAPIEventCallbackMap) { window.JSAPIEventCallbackMap = {}; } function ready(onBridgeReady) { var bridgeReady = function bridgeReady() { try { if (onBridgeReady) { window.onBridgeReadyTime = window.onBridgeReadyTime || Date.now(); onBridgeReady(); } } catch (e) { __moon_report$1([{ offset: MOON_JSAPI_KEY_OFFSET, log: 'ready', e: e }]); throw e; } window.jsapiReadyTime = Date.now(); }; if (!isAcrossOrigin$1 && (typeof top.window.WeixinJSBridge === 'undefined' || !top.window.WeixinJSBridge.invoke)) { if (doc$1.addEventListener) { doc$1.addEventListener('WeixinJSBridgeReady', bridgeReady, false); } else if (doc$1.attachEvent) { doc$1.attachEvent('WeixinJSBridgeReady', bridgeReady); doc$1.attachEvent('onWeixinJSBridgeReady', bridgeReady); } } else { bridgeReady(); } } function invoke(methodName, args, callback) { if (window.__second_open_wait_a8key__ && window.__second_open_wait_a8key_task__) { window.__second_open_wait_a8key_task__.push(function () { invoke(methodName, args, callback); }); return; } ready(function () { if (isAcrossOrigin$1) return false; if (_typeof(top.window.WeixinJSBridge) !== 'object') { alert('请在微信中打开此链接'); return false; } top.window.WeixinJSBridge.invoke(methodName, args, function () { try { for (var _len = arguments.length, rets = new Array(_len), _key = 0; _key < _len; _key++) { rets[_key] = arguments[_key]; } var ret = rets[0]; var errMsg = ret && ret.err_msg ? ", err_msg-> ".concat(ret.err_msg) : ''; console.info('[system]', "[jsapi] invoke->".concat(methodName).concat(errMsg)); if (callback) { callback.apply(window, rets); } } catch (e) { __moon_report$1([{ offset: MOON_JSAPI_KEY_OFFSET, log: "invoke;methodName:".concat(methodName), e: e }]); throw e; } }); }); } function call(methodName) { if (window.__second_open_wait_a8key__ && window.__second_open_wait_a8key_task__) { window.__second_open_wait_a8key_task__.push(function () { call(methodName); }); return; } ready(function () { if (isAcrossOrigin$1) return false; if (_typeof(top.window.WeixinJSBridge) !== 'object') { return false; } try { top.window.WeixinJSBridge.call(methodName); } catch (e) { __moon_report$1([{ offset: MOON_JSAPI_KEY_OFFSET, log: "call;methodName:".concat(methodName), e: e }]); throw e; } }); } function on(eventName, callback) { if (window.__second_open_wait_a8key__ && window.__second_open_wait_a8key_task__) { window.__second_open_wait_a8key_task__.push(function () { on(eventName, callback); }); return; } ready(function () { if (isAcrossOrigin$1) return false; if (_typeof(top.window.WeixinJSBridge) !== 'object' || !top.window.WeixinJSBridge.on) { return false; } if (!window.JSAPIEventCallbackMap[eventName]) { window.JSAPIEventCallbackMap[eventName] = []; } window.JSAPIEventCallbackMap[eventName].push(callback); if (window.JSAPIEventCallbackMap[eventName].length > 1) { return false; } top.window.WeixinJSBridge.on(eventName, function () { try { for (var _len2 = arguments.length, rets = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { rets[_key2] = arguments[_key2]; } var ret = rets[0]; var errMsg = ret && ret.err_msg ? ", err_msg-> ".concat(ret.err_msg) : ''; console.info('[system]', "[jsapi] event->".concat(eventName).concat(errMsg)); if (window.JSAPIEventCallbackMap[eventName] && window.JSAPIEventCallbackMap[eventName].length) { var result; for (var i = 0; i < window.JSAPIEventCallbackMap[eventName].length; i++) { result = window.JSAPIEventCallbackMap[eventName][i].apply(window, rets); } return result; } } catch (e) { __moon_report$1([{ offset: MOON_JSAPI_KEY_OFFSET, log: "on;eventName:".concat(eventName), e: e }]); throw e; } }); }); } function remove(eventName, callback) { if (window.__second_open_wait_a8key__ && window.__second_open_wait_a8key_task__) { window.__second_open_wait_a8key_task__.push(function () { remove(eventName, callback); }); return; } ready(function () { if (!window.JSAPIEventCallbackMap[eventName]) { return false; } var result = false; for (var i = window.JSAPIEventCallbackMap[eventName].length - 1; i >= 0; i--) { if (window.JSAPIEventCallbackMap[eventName][i] === callback) { window.JSAPIEventCallbackMap[eventName].splice(i, 1); result = true; } } return result; }); } var JSAPI = { ready: ready, invoke: invoke, call: call, on: on, remove: remove }; function parseUrl(url) { var len = url.length; var ques_pos = url.indexOf('?'); var hash_pos = url.indexOf('#'); hash_pos = hash_pos == -1 ? len : hash_pos; ques_pos = ques_pos == -1 ? hash_pos : ques_pos; var host = url.substring(0, ques_pos); var query_str = url.substring(ques_pos + 1, hash_pos); var hash = url.substring(hash_pos + 1); return { host: host, query_str: query_str, hash: hash }; } function join(url, args, noEncode) { var ret = parseUrl(url); var query_str = ret.query_str; var args_arr = []; if (_typeof(args) === 'object') { for (var key in args) { if (args.hasOwnProperty(key)) { args_arr.push("".concat(key, "=").concat(noEncode ? args[key] : encodeURIComponent(args[key]))); } } } else { args_arr.push(noEncode ? args : encodeURIComponent(args)); } if (args_arr.length > 0) { query_str += (query_str !== "" ? "&" : "") + args_arr.join("&"); } return ret.host + (query_str !== "" ? "?".concat(query_str) : "") + (ret.hash !== "" ? "#".concat(ret.hash) : ""); } function addParam(url, param, value, forceReplace) { url = url || location.href; var firstAndPos = url.indexOf("&"); var len = url.length; var reverseUrl = url.replace(/^[\w\d]+:[/\\]+/g, "").split("").reverse(); if (!Array.prototype.indexOf) { Array.prototype.indexOf = function (searchElement, fromIndex) { var k; if (this == null) { throw new TypeError('"this" is null or not defined'); } var O = Object(this); var len = O.length >>> 0; if (len === 0) { return -1; } var n = fromIndex || 0; if (Math.abs(n) === Infinity) { n = 0; } if (n >= len) { return -1; } k = Math.max(n >= 0 ? n : len - Math.abs(n), 0); while (k < len) { if (k in O && O[k] === searchElement) { return k; } k++; } return -1; }; } var lastSlashPos = len - 1 - reverseUrl.indexOf("/"); if (firstAndPos !== -1 && url.indexOf("?") == -1 && firstAndPos > lastSlashPos) { url = url.replace("&", "?"); } var reg = new RegExp("([\\?&]".concat(param, "=)[^&#]*")); if (!url.match(reg)) { var urlInfo = parseUrl(url); var hash = urlInfo.hash ? '#' + urlInfo.hash : ''; url = url.replace(hash, ''); var _pos = url.indexOf("?"); if (_pos == -1) { return "".concat(url, "?").concat(param, "=").concat(value).concat(hash); } if (_pos == url.length - 1) { return "".concat(url + param, "=").concat(value).concat(hash); } return "".concat(url, "&").concat(param, "=").concat(value).concat(hash); } if (forceReplace === true) { return url.replace(reg, "$1".concat(value)); } return url; } function addWxfrom(src, wxfrom) { var offset = window.service_type === 1 ? 10000 : 0; return addParam(src, 'wxfrom', offset + Number(wxfrom), true); } function removeParam(url, param) { var _URL = new URL(url), protocol = _URL.protocol, host = _URL.host, pathname = _URL.pathname, search = _URL.search, hash = _URL.hash; var queryParams = new URLSearchParams(search); queryParams["delete"](param); var newSearch = queryParams.toString(); var newUrl = new URL("".concat(protocol, "//").concat(host).concat(pathname).concat(newSearch ? "?".concat(decodeURIComponent(newSearch)) : "").concat(hash)); return newUrl.toString(); } function getQuery(name, url) { var u = url || window.location.search; var reg = new RegExp("(^|&)".concat(name, "=([^&]*)(&|$)")); var r = u.substring(u.indexOf('?') + 1).match(reg); return r !== null ? r[2] : ''; } function encodeBase64(value) { try { return window.btoa(value); } catch (e) { return ''; } } function decodeBase64(value) { try { return window.atob(value); } catch (e) { return ''; } } function joinUrl(url) { var obj = {}; if (typeof window.uin !== 'undefined') { obj.uin = window.uin; } if (typeof window.key !== 'undefined') { obj.key = window.key; } if (typeof window.pass_ticket !== 'undefined') { obj.pass_ticket = window.pass_ticket; } if (typeof window.wxtoken !== 'undefined') { obj.wxtoken = window.wxtoken; } if (typeof window.devicetype !== 'undefined') { obj.devicetype = window.devicetype; } if (typeof window.clientversion !== 'undefined') { obj.clientversion = window.clientversion || mmversion.getInner(); } obj.version = obj.clientversion; if (window.biz) { obj.__biz = window.biz; } if (getQuery('enterid')) { obj.enterid = getQuery('enterid'); } if (typeof window.appmsg_token !== 'undefined') { obj.appmsg_token = window.appmsg_token; } else if (url.indexOf('advertisement_report') > -1) { new Image().src = "".concat(location.protocol, "//mp.weixin.qq.com/mp/jsmonitor?idkey=68064_13_1&r=").concat(Math.random()); } obj.x5 = navigator.userAgent.indexOf('TBS/') !== -1 ? '1' : '0'; obj.f = 'json'; return join(url, obj); } function getA8keyQuery(name, url) { return new Promise(function (resolve) { if (window.__second_open_wait_a8key__ && window.__second_open_wait_a8key_task__) { window.__second_open_wait_a8key_task__.push(function () { resolve(getQuery(name, url)); }); } else { resolve(getQuery(name, url)); } }); } var Url = { parseUrl: parseUrl, join: join, addParam: addParam, addWxfrom: addWxfrom, getQuery: getQuery, getA8keyQuery: getA8keyQuery, encodeBase64: encodeBase64, decodeBase64: decodeBase64, joinUrl: joinUrl, removeParam: removeParam }; function _log(level, msg) { if (level === 'log') { level = 'info'; msg = "[WechatFe]".concat(msg); } else { var prefix = "__wap__".concat(window.__second_open__ ? ' (sec)' : ''); msg = "".concat(prefix, " ").concat(msg, " location:[").concat(location.href, "]"); } msg += new Error().stack; if (mmversion.isMpapp) { invoke$1('WNNativeCallbackLog', msg); } else if (mmversion.isWechat) { if (mmversion.isAndroid) { console.warn('[system]', "[MicroMsg.JsApiLog][".concat(level, "] jslog : ").concat(msg)); } else if (mmversion.isIOS) { JSAPI.invoke('writeLog', { level: level, msg: msg }); } else { JSAPI.invoke('log', { level: level, msg: msg }); } } } var Log = { info: function info() { for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _log('info', args.join(' ')); }, warn: function warn() { for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } _log('warn', args.join(' ')); }, error: function error() { for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { args[_key3] = arguments[_key3]; } _log('error', args.join(' ')); }, debug: function debug() { for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { args[_key4] = arguments[_key4]; } _log('debug', args.join(' ')); }, log: function log() { for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) { args[_key5] = arguments[_key5]; } _log('info', args.join(' ')); } }; var html = function html(_str, encode) { if (!_str) return ''; var replace = ['`', '`', ''', '\'', '"', '"', ' ', ' ', '>', '>', '<', '<', '¥', '¥', '&', '&', '<', '<', '>', '>']; var replaceReverse = ['&', '&', '¥', '¥', '<', '<', '>', '>', ' ', ' ', '"', '"', '\'', ''', '`', '`']; var str = _str; var target; if (encode) { target = replaceReverse; } else { target = replace; } for (var i = 0; i < target.length; i += 2) { str = str.replace(new RegExp(target[i], 'g'), target[i + 1]); } return str; }; var htmlLite = function htmlLite(_str, encode) { if (!_str) return ''; var replace = ['`', '`', ''', '\'', '"', '"', '>', '>', '<', '<', '&', '&']; var replaceReverse = ['&', '&', '<', '<', '>', '>', '"', '"', '\'', ''', '`', '`']; var str = _str; var target; if (encode) { target = replaceReverse; } else { target = replace; } for (var i = 0; i < target.length; i += 2) { str = str.replace(new RegExp(target[i], 'g'), target[i + 1]); } return str; }; var htmlEncode = function htmlEncode(str) { return html(str, true); }; var htmlDecode = function htmlDecode(str) { return html(str, false); }; var htmlEncodeLite = function htmlEncodeLite(str) { return htmlLite(str, true); }; var htmlDecodeLite = function htmlDecodeLite(str) { return htmlLite(str, false); }; String.prototype.html = function (encode) { return html(this.toString(), encode); }; String.prototype.htmlEncode = function () { return htmlEncode(this.toString()); }; String.prototype.htmlDecode = function () { return htmlDecode(this.toString()); }; String.prototype.htmlLite = function (encode) { return htmlLite(this.toString(), encode); }; String.prototype.htmlEncodeLite = function () { return htmlEncodeLite(this.toString()); }; String.prototype.htmlDecodeLite = function () { return htmlDecodeLite(this.toString()); }; var _a; var METHOD_ENUM = { GET: 0, POST: 1 }; var __moon_report = window.__moon_report || function () {}; var MOON_AJAX_SUCCESS_OFFSET = 3; var MOON_AJAX_NETWORK_OFFSET = 4; var MOON_AJAX_ERROR_OFFSET = 5; var MOON_AJAX_TIMEOUT_OFFSET = 6; var MOON_AJAX_COMPLETE_OFFSET = 7; var LENGTH_LIMIT = 4096; var doc; var isAcrossOrigin = false; try { doc = (_a = window.top) === null || _a === void 0 ? void 0 : _a.window.document; } catch (e) { isAcrossOrigin = true; } function networkStartLog(item) { var _a, _b, _c; console.log('[system]', "< [request ".concat(item.requestType, "]"), item.method, item); if ((_a = window.vConsole) === null || _a === void 0 ? void 0 : _a.network) { try { return (_c = (_b = window.vConsole.network).add) === null || _c === void 0 ? void 0 : _c.call(_b, Object.assign({}, item, { startTime: Date.now(), endTime: Date.now(), status: 0, readyState: 2, response: '' })); } catch (err) {} } return Object.assign({}, item, { id: '__system_log__' }); } function networkEndLog(item) { var _a, _b, _c; console.log('[system]', "> [response ".concat(item.requestType, "]"), item.response, item); if (((_a = window.vConsole) === null || _a === void 0 ? void 0 : _a.network) && item.id !== '__system_log__') { try { return (_c = (_b = window.vConsole.network).update) === null || _c === void 0 ? void 0 : _c.call(_b, item.id, Object.assign({}, item, { readyState: 4 })); } catch (err) {} } } function reqType(obj, path) { return obj.url.indexOf(path) > -1 && obj.url.indexOf('action=') === -1 && (!obj.data || !obj.data.action); } function reportRtError(type, id, key, content) { var log = ''; var prefix = type === 'rt' ? 'rtCheckError' : 'Ajax Length Limit'; if (content === null || content === void 0 ? void 0 : content.length) { var loglen = 1000; var len = content.length; var lc = Math.ceil(len / loglen); log = ["&lc=".concat(lc)]; for (var i = 0; i < lc; ++i) { log.push("&log".concat(i, "=") + "[".concat(prefix, "][").concat(i, "]").concat(encodeURIComponent(content.substring(i * loglen, i * loglen + loglen)))); } log = log.join(''); } var data = "idkey=".concat(id, "_").concat(key, "_1").concat(log, "&r=").concat(Math.random()); var xmlobj = new XMLHttpRequest(); xmlobj.open('POST', "".concat(location.protocol, "//").concat(location.host, "/mp/jsmonitor?"), true); xmlobj.setRequestHeader('cache-control', 'no-cache'); xmlobj.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); xmlobj.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); xmlobj.send(data); if (type === 'ajaxLen') { monitor$1.setLogs({ id: id, key: key, value: 1, log: log }); } } function reportRt(id, key, content) { reportRtError('rt', id, key, content); } function reportAjaxLength(id, key, content) { reportRtError('ajaxLen', id, key, content); } function setCurrentMpInfo(ifShow) { var supportNewTopBar = mmversion.isIOS && mmversion.gtVersion('7.0.10', true) || mmversion.isAndroid && mmversion.gtVersion('7.0.12', true); var supportLiveStatus = mmversion.isIOS && mmversion.gtVersion('8.0.46', true) || mmversion.isAndroid && mmversion.gtVersion('8.0.46', true); JSAPI.invoke('currentMpInfo', { userName: window.user_name, brandName: !!supportNewTopBar && window.nickname === '' ? '未命名账号' : window.title, title: window.msg_title || '', brandIcon: window.hd_head_img.replace(/\/0$/, '/132'), itemShowType: window.item_show_type, isPaySubscribe: window.isPaySubscribe, topBarStyle: supportNewTopBar ? 1 : 0, topBarShowed: ifShow, disableShowFinderLiveTopBar: !ifShow && supportLiveStatus ? 1 : 0 }, function () {}); } function findAjaxScopeByConfig(url, config) { var pathname = new URL(url, location.href).pathname || ''; var scope = config[pathname.slice(1)]; if (scope) { Log.log('ajax transfer config: ', JSON.stringify(config)); return scope; } } function getAjaxScope(ajaxUrl) { if (Url.getQuery('no_transfer', location.href) !== '1' && mmversion.isWechat && !mmversion.isInMiniProgram && !mmversion.isWxWork && !mmversion.isMpapp && !isAcrossOrigin && window.__ajaxTransferConfig && _typeof(window.__ajaxTransferConfig) === 'object' && ( mmversion.isIOS && mmversion.getInner() >= '1800282f' || mmversion.isAndroid && mmversion.getInner() >= '28002234' || mmversion.isWindowsWechat && mmversion.cpVersion('3.9.5', 1, true, 'windows') || mmversion.isMacWechat && mmversion.cpVersion('3.8.4', 1, true, 'mac'))) { try { return findAjaxScopeByConfig(ajaxUrl, window.__ajaxTransferConfig); } catch (err) { } } } function setXhrHeader(xhr, type, opt) { if (opt.contentType) { xhr.setRequestHeader('Content-Type', opt.contentType); } else if (type === 'POST') { xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); } if (!opt.noXRequestedWidthHeader) { xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); } } function Ajax(obj) { if (obj.usePb) { obj.type = 'POST'; obj.data = { data: JSON.stringify(obj.data) }; } var ajaxScope = getAjaxScope(obj.url); var type = (obj.type || 'GET').toUpperCase(); var timer; var url; if (obj.notJoinUrl) { url = obj.url; } else { url = Url.joinUrl(obj.url); } if (obj.f === 'html') { url = url.replace('&f=json', ''); } var data = null; if (_typeof(obj.data) === 'object') { var d = obj.data; var ds = []; for (var k in d) { if (d.hasOwnProperty(k)) { ds.push("".concat(k, "=").concat(encodeURIComponent(d[k]))); } } data = ds.join('&'); } else { data = typeof obj.data === 'string' ? obj.data : null; } var beginTs; var beforeReq = function beforeReq() { if (reqType(obj, '/mp/getappmsgext')) { window.startGetAppmsgExtTime = Date.now(); Log.log('start get appmsgext, url: ', obj.url); } if (reqType(obj, '/mp/getappmsgad')) { window.startGetAppmsgAdTime = Date.now(); Log.log('start get appmsgad, url: ', obj.url); } beginTs = Date.now(); }; var beforeResp = function beforeResp(xhr) { if (reqType(obj, '/mp/getappmsgext')) { window.receiveGetAppmsgExt = "".concat(xhr.status, "|").concat(Date.now()); Log.log("receive appmsgext response, status: ".concat(xhr.status)); } if (reqType(obj, '/mp/getappmsgad')) { window.receiveGetAppmsgAd = "".concat(xhr.status, "|").concat(Date.now()); Log.log("receive appmsgad response, status: ".concat(xhr.status)); } if (Math.random() < 0.01 && window.WX_BJ_REPORT && window.WX_BJ_REPORT.BadJs) { try { var key = ajaxScope ? 'transfer' : 'xhr'; var interval = 250; var time = Date.now() - beginTs; var range = Math.floor(time / interval) * interval; var pathname = new URL(obj.url, location.href).pathname || ''; window.WX_BJ_REPORT.BadJs.report("".concat(key, "_perf:").concat(pathname), JSON.stringify({ status: xhr.status, time: "[".concat(range, "-").concat(range + interval, ")") }), { mid: 'mmbizwap:ajaxtransfer', view: 'wap_business' }); } catch (err) {} } }; var handleRespSucc = function handleRespSucc(xhr) { var _a; try { var responseText = xhr.responseText; var resp = responseText; if (obj.dataType === 'json') { try { if (JSON && JSON.parse) { resp = JSON.parse(resp); } else { resp = eval("(".concat(resp, ")")); monitor$1.setSum(523105, 127, 1).send(); } var rtId = obj.rtId; var rtKey = obj.rtKey || 0; var rtDesc = obj.rtDesc; if (rtId && rtDesc && RespTypes && !RespTypes.check(resp, rtDesc)) { reportRt(+rtId, +rtKey, "".concat(RespTypes.getMsg(), "[detail]").concat(responseText, ";").concat(obj.url)); } if (resp && resp.base_resp && ((_a = resp.base_resp) === null || _a === void 0 ? void 0 : _a.ret) !== 0 && typeof window.WX_BJ_REPORT !== 'undefined' && window.WX_BJ_REPORT.BadJs && Math.random() < 0.001) { var reportUrl = url; if (url.indexOf('?') !== -1) { reportUrl = url.substring(0, url.indexOf('?')); if (Url.getQuery('action', url)) { reportUrl = "".concat(reportUrl, "?action=").concat(Url.getQuery('action', url)); } } if (!((reportUrl === '/mp/getappmsgext' || reportUrl === '/mp/getappmsgad') && typeof resp.base_resp.ret === 'undefined')) { window.WX_BJ_REPORT.BadJs.report(reportUrl, "ret=".concat(resp.base_resp.ret), { mid: window.PAGE_MID, view: 'wap_retcode' }); } } } catch (e) { obj.error && obj.error(xhr, { type: 1, error: e, status: xhr.status }); return; } } obj.success && obj.success(resp); } catch (e) { __moon_report({ offset: MOON_AJAX_SUCCESS_OFFSET, e: e }); throw e; } }; var handleRespErr = function handleRespErr(xhr, error) { try { obj.error && obj.error(xhr, { type: 2, error: error, status: xhr.status }); } catch (e) { __moon_report({ offset: MOON_AJAX_ERROR_OFFSET, e: e }); throw e; } }; var handleRespComplete = function handleRespComplete() { clearTimeout(timer); try { obj.complete && obj.complete(); } catch (e) { __moon_report({ offset: MOON_AJAX_COMPLETE_OFFSET, e: e }); throw e; } obj.complete = null; }; var handleReqTimeout = function handleReqTimeout(xhr) { if (typeof obj.timeout !== 'undefined') { timer = setTimeout(function () { xhr.abort(); try { obj.complete && obj.complete(); } catch (e) { __moon_report({ offset: MOON_AJAX_COMPLETE_OFFSET, e: e }); throw e; } obj.complete = null; __moon_report({ offset: MOON_AJAX_TIMEOUT_OFFSET, log: "ajax_timeout_error: ".concat(url), e: '' }); }, obj.timeout); } }; var retryXhrFn = function retryXhrFn(res, isTimeout, reqLogItem) { var retryXhr = new XMLHttpRequest(); try { retryXhr._noVConsole = true; } catch (err) {} retryXhr.open(type, url); retryXhr.onreadystatechange = function () { if (isTimeout) return; if (retryXhr.readyState === 3) { obj.received && obj.received(retryXhr); } if (retryXhr.readyState === 4) { beforeResp(retryXhr); var retryStatus = retryXhr.status; if (retryStatus >= 200 && retryStatus < 400) { handleRespSucc(retryXhr); } else { handleRespErr(retryXhr, res); window.WX_BJ_REPORT && window.WX_BJ_REPORT.BadJs && window.WX_BJ_REPORT.BadJs.report('req_failure', JSON.stringify({ retryXhrStatus: retryStatus, transferRes: res }), { mid: 'mmbizwap:ajaxtransfer', view: 'wap_business' }); } reqLogItem.status = retryStatus; reqLogItem.endTime = Date.now(); reqLogItem.response = retryXhr.responseText; handleRespComplete(); networkEndLog(reqLogItem); } }; setXhrHeader(retryXhr, type, obj); retryXhr.send(data); }; if (ajaxScope) { var header = { 'User-Agent': navigator.userAgent, 'Cookie': (window.__test_env__ ? 'uniproxy_route=1; ' : '') + document.cookie, 'Referer': location.href }; if (obj.contentType) { header['Content-Type'] = obj.contentType; } else if (type === 'POST') { header['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8'; } if (!obj.noXRequestedWidthHeader) { header['X-Requested-With'] = 'XMLHttpRequest'; } var reqUrl = new URL(url, location.href).href; var method = METHOD_ENUM[type] || 0; var params = Device.os.pc ? { url: reqUrl, req_json: data || '', scope: ajaxScope, webcgi_method: method, webcgi_header: Object.keys(header).map(function (headerItemKey) { return Device.os.Mac ? _defineProperty({}, headerItemKey, header[headerItemKey]) : { key: headerItemKey, value: header[headerItemKey] }; }), cgi_type: 1 } : { reqUrl: reqUrl, reqBody: data, scope: ajaxScope, method: method, header: header }; var reqLogItem = networkStartLog({ method: type, url: url, postData: obj.data || {}, requestHeader: header, requestType: 'transfer' }); var isTimeout = false; handleReqTimeout({ abort: function abort() { isTimeout = true; reqLogItem.endTime = Date.now(); reqLogItem.response = 'timeout'; networkEndLog(reqLogItem); } }); Device.os.pc && monitor$1.setSum(115849, 69, 1); JSAPI.invoke(Device.os.pc ? 'H5ExtTransfer' : 'webTransfer', params, function (res) { var _a, _b, _c, _d, _e, _f; if (isTimeout) return; var status = 400; var result = ''; if (Device.os.pc) { try { var retFlag = res.base_resp.ret === 0 && res.jsapi_resp.ret === 0 && res.err_msg.indexOf(':ok') > -1; var respJsonFlag = res.jsapi_resp.resp_json; status = retFlag && respJsonFlag ? 200 : 400; result = res.jsapi_resp.resp_json; } catch (err) { console.error(err); } } else { status = res && res.errCode * 1 === 0 && typeof res.result === 'string' && res.result ? 200 : 400; result = res.result; } if (status >= 200 && status < 400) { obj.received && obj.received(null); beforeResp({ status: status }); handleRespSucc({ status: status, responseText: result }); reqLogItem.status = status; reqLogItem.endTime = Date.now(); reqLogItem.response = result; handleRespComplete(); networkEndLog(reqLogItem); } else if (window.__second_open__) { JSAPI.invoke('request', { url: reqUrl, method: type, data: data, header: header }, function (retryRes) { if (isTimeout) return; var retryStatus = retryRes.statusCode; obj.received && obj.received(null); beforeResp({ status: retryStatus }); if (retryRes.err_msg.indexOf(':ok') > -1 && retryStatus >= 200 && retryStatus < 400) { handleRespSucc({ status: retryStatus, responseText: retryRes.data }); } else { retryXhrFn(res, isTimeout, reqLogItem); handleRespErr({ status: retryStatus }, res); window.WX_BJ_REPORT && window.WX_BJ_REPORT.BadJs && window.WX_BJ_REPORT.BadJs.report('req_failure_sec_open', JSON.stringify({ retryReqJsapiRes: retryRes, transferRes: res, url: reqUrl }), { mid: 'mmbizwap:ajaxtransfer', view: 'wap_business' }); } reqLogItem.status = retryStatus; reqLogItem.endTime = Date.now(); reqLogItem.response = retryRes.data; handleRespComplete(); networkEndLog(reqLogItem); }); } else { retryXhrFn(res, isTimeout, reqLogItem); } if (Device.os.pc) { if (!res.err_msg.includes(':ok')) { (_b = (_a = window.WX_BJ_REPORT) === null || _a === void 0 ? void 0 : _a.BadJs) === null || _b === void 0 ? void 0 : _b.report("pc transfer res no ok: ".concat(res.err_msg), params.url || '', { mid: window.PAGE_MID, _info: "".concat(JSON.stringify(params), " || ").concat(JSON.stringify(res)) }); } try { if (res.jsapi_resp.resp_json && JSON.parse(res.jsapi_resp.resp_json).base_resp.ret !== 0 && JSON.parse(res.jsapi_resp.resp_json).base_resp.ret !== 190001 || res.base_resp.ret !== 0 || res.jsapi_resp.ret !== 0) { (_d = (_c = window.WX_BJ_REPORT) === null || _c === void 0 ? void 0 : _c.BadJs) === null || _d === void 0 ? void 0 : _d.report("pc transfer res invalid ret", params.url || '', { mid: window.PAGE_MID, _info: "".concat(JSON.stringify(params), " || ").concat(JSON.stringify(res)) }); } } catch (err) {} } else { try { if (res.errCode !== 0) { (_f = (_e = window.WX_BJ_REPORT) === null || _e === void 0 ? void 0 : _e.BadJs) === null || _f === void 0 ? void 0 : _f.report("mobile transfer res invalid ret", params.url || '', { mid: window.PAGE_MID, _info: "".concat(JSON.stringify(params), " || ").concat(JSON.stringify(res)) }); } } catch (err) {} } }); beforeReq(); return; } var xhr = new XMLHttpRequest(); var mayAbort = !!obj.mayAbort; var async = typeof obj.async === 'undefined' ? true : obj.async; var _onreadystatechange = xhr.onreadystatechange; xhr.open(type, url, async); xhr.onreadystatechange = function () { if (typeof _onreadystatechange === 'function') { _onreadystatechange.apply(xhr); } if (xhr.readyState === 3) { obj.received && obj.received(xhr); } if (xhr.readyState === 4) { beforeResp(xhr); xhr.onreadystatechange = null; var status = xhr.status; if (status >= 200 && status < 400) { handleRespSucc(xhr); } else { handleRespErr(xhr, 'status error'); if (!!status || !mayAbort) { var __ajaxtest = window.__ajaxtest || '0'; __moon_report({ offset: MOON_AJAX_NETWORK_OFFSET, log: "ajax_network_error[".concat(status, "][").concat(__ajaxtest, "]: ").concat(url, ";host:").concat(location.host), e: '' }); } } handleRespComplete(); } }; setXhrHeader(xhr, type, obj); handleReqTimeout(xhr); try { xhr.send(data); try { if (url && url.length > LENGTH_LIMIT) { reportAjaxLength(27613, 17, "ajax get limit[length: ".concat(url.length, "]").concat(url.substring(0, 1024))); } if (data && data.length > LENGTH_LIMIT) { reportAjaxLength(27613, 18, "ajax post limit[length: ".concat(data.length, "]").concat(data.substring(0, 1024))); } } catch (e) { } } catch (e) { obj.error && obj.error(xhr, { type: 3, error: e, status: 0 }); } beforeReq(); return xhr; } function AjaxWx(obj) { obj.url += obj.url.indexOf('?') === -1 ? '?fasttmplajax=1' : '&fasttmplajax=1'; if (getAjaxScope(obj.url)) { Ajax(obj); return; } if (obj.usePb) { obj.type = 'POST'; obj.data = { data: JSON.stringify(obj.data) }; } if (!/^(http:\/\/|https:\/\/|\/\/)/.test(obj.url)) { obj.url = "https://mp.weixin.qq.com/".concat(obj.url.replace(/^\//, '')); } else if (/^\/\//.test(obj.url)) { obj.url = "https:".concat(obj.url); } if (obj.f !== 'html' && (obj.url.indexOf('?f=json') === -1 || obj.url.indexOf('&f=json') === -1)) { obj.url += '&f=json'; } if (!obj.notJoinUrl && obj.f !== 'html') { obj.url = Url.joinUrl(obj.url); } var data = null; if (_typeof(obj.data) === 'object') { var d = obj.data; var ds = []; for (var k in d) { if (d.hasOwnProperty(k)) { ds.push("".concat(k, "=").concat(encodeURIComponent(d[k]))); } } data = ds.join('&'); } else { data = typeof obj.data === 'string' ? obj.data : null; } var header = { Cookie: document.cookie, referer: location.href }; var reqLogItem = networkStartLog({ method: obj.type || 'GET', url: obj.url, postData: obj.data || {}, requestHeader: header, requestType: 'jsapi' }); var retryTime = 1; var jsapiRequest = function jsapiRequest(obj, data) { return JSAPI.invoke('request', { url: obj.url, method: obj.type, data: data, header: header }, function (res) { var _a; if (res.err_msg.indexOf(':ok') > -1) { if (reqType(obj, '/mp/getappmsgext')) { window.receiveGetAppmsgExt = "".concat(res.statusCode, "|").concat(Date.now()); } if (reqType(obj, '/mp/getappmsgad')) { window.receiveGetAppmsgAd = "".concat(res.statusCode, "|").concat(Date.now()); } if (retryTime === 1) { obj.received && obj.received(null); } var resData = {}; if (res.data) { try { if (obj.dataType === 'json') { resData = JSON.parse(res.data); } else { resData = res.data; } if (resData && resData.base_resp && ((_a = resData.base_resp) === null || _a === void 0 ? void 0 : _a.ret) !== 0 && typeof window.WX_BJ_REPORT !== 'undefined' && window.WX_BJ_REPORT.BadJs && Math.random() < 0.001) { var reportUrl = obj.url; if (obj.url.indexOf('?') !== -1) { reportUrl = obj.url.substring(0, obj.url.indexOf('?')); if (Url.getQuery('action', obj.url)) { reportUrl = "".concat(reportUrl, "?action=").concat(Url.getQuery('action', obj.url)); } } if (!((reportUrl === '/mp/getappmsgext' || reportUrl === '/mp/getappmsgad') && typeof resData.base_resp.ret === 'undefined')) { window.WX_BJ_REPORT.BadJs.report(reportUrl, "ret=".concat(resData.base_resp.ret), { mid: window.PAGE_MID, view: 'wap_retcode' }); } } } catch (e) { console.error(e); obj.error && obj.error(null, { type: 1, error: e, status: res.statusCode }); obj.complete && obj.complete(); reqLogItem.endTime = Date.now(); reqLogItem.response = res; networkEndLog(reqLogItem); return; } } var tmpResData = {}; try { tmpResData = JSON.parse(res.data); } catch (e) {} if (tmpResData && tmpResData.base_resp && tmpResData.base_resp.ret === -3 && retryTime < 2 && (mmversion.isIOS || mmversion.isAndroid && mmversion.getInner() > '27000600')) { var _retryTime = retryTime++; JSAPI.invoke('updatePageAuth', {}, function (res) { console.log('[skeleton] updatePageAuth', res); monitor$1.setSum(112287, 3, 1); if (res && res.err_msg && res.err_msg.indexOf(':ok') > -1) { window.top.pass_ticket = encodeURIComponent(Url.getQuery('pass_ticket', res.fullUrl).html(false).replace(/\s/g, '+')); if (obj.pass_ticket) { obj.pass_ticket = window.top.pass_ticket; } console.warn('[skeleton] updatePageAuth resetTopbar'); var supportNewTopBar = mmversion.isIOS && mmversion.gtVersion('7.0.10', true); var showBottomBar = !!window.is_login; if (window.top.item_show_type === '0' && supportNewTopBar) { var _top = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop || 0; setCurrentMpInfo(_top > 40 && !showBottomBar); } try { obj.url = Url.addParam(obj.url, 'retry', _retryTime, true); } catch (err) { console.error(err); } jsapiRequest(obj, data); monitor$1.setSum(112287, 4, 1); } else { obj.success && obj.success(resData); obj.complete && obj.complete(); if (mmversion.isIOS) { monitor$1.setSum(112287, 35, 1); } else { monitor$1.setSum(112287, 36, 1); } reqLogItem.status = 200; reqLogItem.endTime = Date.now(); reqLogItem.response = resData; networkEndLog(reqLogItem); } }); } else { obj.success && obj.success(resData); obj.complete && obj.complete(); reqLogItem.status = 200; reqLogItem.endTime = Date.now(); reqLogItem.response = resData; networkEndLog(reqLogItem); } } else if (res.err_msg.indexOf('no permission') > -1 || !mmversion.isOnlyWechat) { Ajax(obj); if (res.err_msg.indexOf('no permission') > -1) { console.warn('[JSAPI Request] No permission'); monitor$1.setSum(112287, 31, 1); } reqLogItem.status = 302; reqLogItem.endTime = Date.now(); reqLogItem.response = res; networkEndLog(reqLogItem); } else { obj.error && obj.error(null, { type: 3, error: res, status: 0 }); obj.complete && obj.complete(); monitor$1.setSum(112287, 32, 1); var sample = 0.001; if (Math.random() < sample) { var msg = "request: ".concat(JSON.stringify(obj.type), " ").concat(JSON.stringify(obj.url), " ;;;; cookie: ").concat(JSON.stringify(document.cookie), " ;;;; data: ").concat(JSON.stringify(data), " ;;;; resp: ").concat(JSON.stringify(res)); if (window.WX_BJ_REPORT && window.WX_BJ_REPORT.BadJs) { window.WX_BJ_REPORT.BadJs.report('ajax_wx_request_error', msg, { mid: 'mmbizwap:Monitor' }); } } reqLogItem.status = 400; reqLogItem.endTime = Date.now(); reqLogItem.response = res; networkEndLog(reqLogItem); } }); }; if (reqType(obj, '/mp/getappmsgext')) { window.startGetAppmsgExtTime = Date.now(); } if (reqType(obj, '/mp/getappmsgad')) { window.startGetAppmsgAdTime = Date.now(); } return jsapiRequest(obj, data); } var ajax = function ajax(obj) { if (window.__second_open_wait_a8key__ && window.__second_open_wait_a8key_task__) { window.__second_open_wait_a8key_task__.push(function () { ajax(obj); }); return; } if (!mmversion.isWxWork && (window.__second_open__ || !isAcrossOrigin && top.window.__second_open__) && window.__is_page_auth_return__) { return AjaxWx(obj); } return Ajax(obj); }; var timer = null; var jsmonitorReport = { setSum: function setSum(id, key, value) { throw new Error('Function not implemented.'); }, setAvg: function setAvg(id, key, value) { throw new Error('Function not implemented.'); }, setLogs: function setLogs(opt) { throw new Error('Function not implemented.'); }, send: function send(async) { throw new Error('Function not implemented.'); } }; window.__monitor_unload_has_done__ = false; jsmonitorReport.setSum = function (id, key, value) { monitor$1.setSum(id, key, value); return jsmonitorReport; }; jsmonitorReport.setAvg = function (id, key, value) { monitor$1.setAvg(id, key, value); return jsmonitorReport; }; jsmonitorReport.setLogs = function (opt) { monitor$1.setLogs(opt); return jsmonitorReport; }; jsmonitorReport.send = function (async) { if (async !== false) { async = true; } monitor$1.send(async, ajax); return jsmonitorReport; }; function reportInterval(fn, delay) { timer = window.setTimeout(function () { fn(); reportInterval(fn, delay); }, delay); } reportInterval(function () { jsmonitorReport.send(); }, 1 * 1000); window.addEventListener('unload', function () { if (window.__monitor_report_has_done__) return; window.__ajaxtest = '2'; if (timer) { window.clearTimeout(timer); timer = null; } jsmonitorReport.send(false); window.__monitor_unload_has_done__ = true; }, false); if (window.__jsmonitorReport) { jsmonitorReport = window.__jsmonitorReport; } else { window.__jsmonitorReport = jsmonitorReport; } var jsmonitorReport$1 = jsmonitorReport; function saveSpeeds(opt) { var sample = 0.001; if (typeof opt.sample === 'number') { sample = opt.sample; } var rand = Math.random(); if (rand < sample) { wxgsdk.saveSpeeds(opt); } } function setBasicTime(opt) { var sample = opt.sample || 0.001; var rand = Math.random(); if (rand < sample) { wxgsdk.setBasicTime(opt); } } function send() { wxgsdk.send(); } function jsmonitor(opt) { opt = opt || []; if (!Array.isArray(opt)) { var item = opt; opt = []; opt.push(item); } for (var i = 0; i < opt.length; i++) { var _item = opt[i]; var id = _item.id; var key = _item.key; var value = _item.value || 1; if (id !== undefined && key !== undefined) { jsmonitorReport$1.setSum(id, key, value); } } } var wxgspeedsdk = { saveSpeeds: saveSpeeds, setBasicTime: setBasicTime, send: send, jsmonitor: jsmonitor }; function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _iterableToArrayLimit(arr, i) { var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; if (null != _i) { var _s, _e, _x, _r, _arr = [], _n = !0, _d = !1; try { if (_x = (_i = _i.call(arr)).next, 0 === i) { if (Object(_i) !== _i) return; _n = !1; } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0); } catch (err) { _d = !0, _e = err; } finally { try { if (!_n && null != _i["return"] && (_r = _i["return"](), Object(_r) !== _r)) return; } finally { if (_d) throw _e; } } return _arr; } } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } var uuid = function uuid() { return ((1 + Math.random()) * 0x10000 | 0).toString(16).substring(1); }; var WRAP_TAG = 'span'; var IMG_TAG = 'IMG'; var NODE_TYPE = { text: 1, img: 2 }; var blockEleTagName = ['P', 'DIV', 'SECTION', 'LI', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'TABLE', 'PRE', 'BLOCKQUOTE']; var exceptEleClassName = ['js_product_container', 'js_blockquote_wrap']; var ignoreTagName = ['IFRAME', 'VIDEO', 'MPVOICE', 'MPGONGYI', 'QQMUSIC', 'MPSHOP', 'MP-WEAPP', 'MP-MINIPROGRAM', 'MPPRODUCT', 'MPCPS']; var ignoreEleId = ['js_mpvideo']; var ignoreEleClassName = ['js_product_container']; var TEMP_NODES = {}; var childNodesHasEle = function childNodesHasEle(element) { var tagNameList = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : blockEleTagName; if (!element || element.nodeType !== 1) { return false; } for (var i = 0; i < element.children.length; i++) { if (tagNameList.indexOf(element.children[i].tagName) !== -1) { return true; } } return false; }; function eleHasAttr(ele) { var attr = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'className'; var AttrList = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : exceptEleClassName; for (var i = 0; i < AttrList.length; i++) { if (ele[attr] && typeof ele[attr] === 'string' && ele[attr].indexOf(AttrList[i]) > -1) { return true; } } return false; } var removeChildMedia = function removeChildMedia(element) { var parentNode = element.parentNode; element.parentNode.removeChild(element); if (parentNode.children && parentNode.children.length) { return false; } return true; }; var getParaList = function getParaList(element, _ref) { var _ref$getNestedStructu = _ref.getNestedStructure, getNestedStructure = _refgetNestedStructu, _ref$removeIgoreEle = _ref.removeIgoreEle, removeIgoreEle = _refremoveIgoreEle; var paraList = function getParaListWithIndex(ele, getNested) { var childNodes = ele.children; if (!childNodes) return []; if (!childNodes.length) { return childNodes; } var child; var paragraphList = []; for (var i = 0; i < childNodes.length; i++) { child = childNodes[i]; if (eleHasAttr(child, 'id', ignoreEleId) || eleHasAttr(child, 'className', ignoreEleClassName)) { if (removeIgoreEle) { child.parentNode.removeChild(child); i -= 1; } continue; } if (childNodesHasEle(child, ignoreTagName)) { if (removeIgoreEle) { removeChildMedia(child); i -= 1; } continue; } if (childNodesHasEle(child, blockEleTagName) && !eleHasAttr(child)) { paragraphList = paragraphList.concat(getParaListWithIndex(child, getNested)); if (getNested) { if (!child.getAttribute('data-index')) { paragraphList.push(child); } } } else { if (!child.getAttribute('data-index')) { paragraphList.push(child); } } } return paragraphList; }(element, getNestedStructure); return [].slice.call(paraList); }; getParaList.paragraphStartIdx = 1000000; var getSplitTextNode = function getSplitTextNode($textNode, startOffset, endOffset, paraIndex) { try { $textNode.splitText(startOffset); } catch (err) { if (typeof WX_BJ_REPORT !== 'undefined' && WX_BJ_REPORT.BadJs) { WX_BJ_REPORT.BadJs.report('ArticleMask:Error', 'splitText Error', { mid: 'mmbizwap:articlemask_Monitor', view: 'wap_business', _info: { type: 'getSplitTextNode textnode', startOffset: startOffset, endOffset: endOffset } }); } } var selectedNode = $textNode.nextSibling; try { selectedNode.splitText(endOffset - startOffset); } catch (e) { if (typeof WX_BJ_REPORT !== 'undefined' && WX_BJ_REPORT.BadJs) { WX_BJ_REPORT.BadJs.report('ArticleMask:Error', 'splitText Error', { mid: 'mmbizwap:articlemask_Monitor', view: 'wap_business', _info: { type: 'getSplitTextNode nextSibling', startOffset: startOffset, endOffset: endOffset } }); } } return [{ $node: selectedNode, type: NODE_TYPE.text, idx: paraIndex }]; }; var getBlockNode = function getBlockNode($node) { if (blockEleTagName.indexOf($node.tagName) !== -1 && typeof $node.dataset.index !== 'undefined') { return $node; } return getBlockNode($node.parentNode); }; var getPureBlockNode = function getPureBlockNode($node) { if (!$node) return $node; if (blockEleTagName.indexOf($node.tagName) !== -1) { return $node; } return getPureBlockNode($node.parentNode); }; var getNodesByDFS = function getNodesByDFS(range) { var start = range.start, end = range.end, container; var node, startOffset = start.offset; var node, endOffset = end.offset; var queue = []; var result = []; var withinSelectRange = false; var achiveSelectRangeEnd = false; var paraIndex = 0; queue.push($container); while (queue.length > 0) { var item = queue.pop(); var nodeType = item.nodeType, tagName = item.tagName; if (item.dataset && item.dataset.index) { paraIndex = +item.dataset.index; } if (withinSelectRange && !achiveSelectRangeEnd) { if (nodeType === 3) { result.push({ $node: item, type: NODE_TYPE.text, idx: paraIndex }); } if (tagName === IMG_TAG) { result.push({ $node: item, type: NODE_TYPE.img, idx: paraIndex }); } } if (item === $startNode) { if (nodeType === 3) { try { item.splitText(startOffset); } catch (e) { WX_BJ_REPORT.BadJs.report('ArticleMask:Error', 'splitText Error', { mid: 'mmbizwap:articlemask_Monitor', view: 'wap_business', _info: { type: 'getNodes startNode', startOffset: startOffset, endOffset: endOffset } }); } var $startTextNode = item.nextSibling; result.push({ startTextNode, type: NODE_TYPE.text, idx: paraIndex }); } else if (tagName === IMG_TAG) { result.push({ $node: item, type: NODE_TYPE.img, idx: paraIndex }); } else { result.push({ $node: item, type: NODE_TYPE.text, idx: paraIndex }); } withinSelectRange = true; } if (item === $endNode || achiveSelectRangeEnd) { if (!achiveSelectRangeEnd) { achiveSelectRangeEnd = true; } if (item === $endNode) result.pop(); if (nodeType === 3) { try { item.splitText(endOffset); } catch (e) { if (typeof WX_BJ_REPORT !== 'undefined' && WX_BJ_REPORT.BadJs) { WX_BJ_REPORT.BadJs.report('ArticleMask:Error', 'splitText Error', { mid: 'mmbizwap:articlemask_Monitor', view: 'wap_business', _info: { type: 'getSplitTextNode endNode', startOffset: startOffset, endOffset: endOffset } }); } } result.push({ $node: item, type: NODE_TYPE.text, idx: paraIndex }); break; } else if (tagName === IMG_TAG) { result.push({ $node: item, type: NODE_TYPE.img, idx: paraIndex }); break; } else { var _children = item.childNodes; for (var i = _children.length - 1; i >= 0; i--) { queue.push(_children[i]); } } } var children = item.childNodes; for (var _i = children.length - 1; _i >= 0; _i--) { queue.push(children[_i]); } } return result; }; var getSelectedNodes = function getSelectedNodes(range) { var start = range.start, end = range.end; var node, startOffset = start.offset; var node, endOffset = end.offset; if (endNode && $startNode instanceof Text) { return getSplitTextNode($startNode, startOffset, endOffset, start.paraIndex); } return getNodesByDFS(range); }; var checkTextNode = function checkTextNode($node) { return $node && (node.innerText); }; var connectSiblingText = function connectSiblingText(prev, next, target) { var $delete = target === prev ? next : prev; if (!checkTextNode(prev) || !checkTextNode(next)) { return $delete; } var text = (prev.nodeValue || prev.innerText) + (next.nodeValue || next.innerText); target.nodeValue = text; target.parentNode.removeChild($delete); return target; }; var getTextNodeByOffset = function getTextNodeByOffset($parentNode, offset) { var queue = []; var curOffset = 0; var startOffset = 0; var $curNode; queue.push($parentNode); while (queue.length > 0) { $curNode = queue.pop(); if ($curNode.nodeType === 3) { startOffset = offset - curOffset; curOffset += $curNode.textContent.length; if (curOffset >= offset) { break; } } var children = $curNode.childNodes; for (var i = children.length - 1; i >= 0; i--) { queue.push(children[i]); } } return { parentNode, curNode, offset: startOffset }; }; function getBlockOffset(_ref2) { var blockNode, node; if ($blockNode === null) { return null; } var queue = []; var offset = 0; queue.push($blockNode); while (queue.length > 0) { var item = queue.pop(); if (item.nodeType === 3 && item.nodeValue !== $node.nodeValue) { offset += item.textContent.length; } else if (item.nodeType === 1) { offset += 1; if (item === $node) break; } else if (item.nodeValue === $node.nodeValue) { offset += item.textContent.length; break; } var children = item.childNodes; for (var i = children.length - 1; i >= 0; i--) { queue.push(children[i]); } } return offset; } var getDomMeta = function getDomMeta(selection) { selection.$node; var parentNode; var parentIndex = Number($parentNode.dataset.index); var offset = getBlockOffset($parentNode); return { parentIndex: parentIndex, fromParentoffset: offset }; }; function nodeToSelection($node) { var $blockNode = getBlockNode($node); var paraIndex = +$blockNode.dataset.index; var offset = 0; var item = { blockNode, node, paraIndex: paraIndex, offset: offset }; var id = uuid(); return { start: item, end: item, id: id }; } var getSelection = function getSelection() { var selection = window.getSelection(); if (selection.anchorNode === null) { return null; } var selectionRange = selection.getRangeAt(0); if (!selectionRange || !selection.toString()) { return null; } var startContainer = selectionRange.startContainer, endContainer = selectionRange.endContainer, commonAncestorContainer = selectionRange.commonAncestorContainer, startOffset = selectionRange.startOffset, endOffset = selectionRange.endOffset; var $startBlockNode = getBlockNode(startContainer); var $endBlockNode = getBlockNode(endContainer); var startIndex = startBlockNode.dataset.index; var endIndex = endBlockNode.dataset.index; var start = { startBlockNode, $node: startContainer, offset: startOffset, paraIndex: Number(startIndex) }; var end = { endBlockNode, $node: endContainer, offset: endOffset, paraIndex: Number(endIndex) }; var $container = typeof commonAncestorContainer === 'string' ? commonAncestorContainer.parentNode : commonAncestorContainer; var id = uuid(); return { start: start, end: end, container, id: id }; }; var transferTextToElement = function transferTextToElement($node, id) { if (!$node) return null; if ($node.nodeType === 3) { var $wrap = document.createElement(WRAP_TAG); $wrap.setAttribute('data-splitid', id); $wrap.appendChild($node.cloneNode(false)); if ($node.parentNode) { $node.parentNode.replaceChild(node); } return $wrap; } return $node; }; var serialize = function serialize(selectionRange) { var start = selectionRange.start, end = selectionRange.end, id = selectionRange.id; var startParaOffset = getBlockOffset(start); var endParaOffset = start.node ? end.offset - start.offset + startParaOffset : getBlockOffset(end); var meta = { id: id, start: { para_offset: startParaOffset, para_index: start.paraIndex }, end: { para_offset: endParaOffset, para_index: end.paraIndex } }; return meta; }; var mapMetaToLocal = function mapMetaToLocal(paraList) { return function (meta) { var paraOffset = meta.para_offset, paraIndex = meta.para_index; var $blockNode = paraList[paraIndex]; var queue = []; var curOffset = 0; var offset = 0; var $curNode; queue.push($blockNode); while (queue.length > 0) { $curNode = queue.pop(); if ($curNode.nodeType === 3) { offset = paraOffset - curOffset; curOffset += $curNode.textContent.length; if (curOffset >= paraOffset) { break; } } if ($curNode.nodeType === 1) { offset = paraOffset - curOffset; curOffset += 1; if (curOffset >= paraOffset) { break; } } var children = $curNode.childNodes; for (var i = children.length - 1; i >= 0; i--) { queue.push(children[i]); } } return { blockNode, curNode, offset: offset, paraIndex: paraIndex }; }; }; var deSerialize = function deSerialize(meta, paraList, $container) { var desparaList = mapMetaToLocal(paraList); return { start: desparaList(meta.start), end: desparaList(meta.end), id: meta.id, container }; }; function getTextNode($node) { if (node.nodeType === 3) { return $node; } return $node.childNodes[0]; } var resetRange = function resetRange(selectionRange) { window.getSelection().removeAllRanges(); var selection = window.getSelection(); var range = document.createRange(); var $startnode = getTextNode(TEMP_NODES.start); var $endnode = getTextNode(TEMP_NODES.end); range.setStart($startnode, selectionRange.start.offset); range.setEnd($endnode, selectionRange.end.offset); selection.addRange(range); }; var getNodeIndex = function getNodeIndex(node) { var queue = []; var index = 0; queue.push($block); while (queue.length > 0) { var $item = queue.pop(); if (node) break; index++; var children = $item.children; for (var i = 0; i < children.length; i++) { queue.push(children[i]); } } return index; }; var getNodeByIndex = function getNodeByIndex($block, index) { var queue = []; var cursor = 0; var $result = null; queue.push($block); while (queue.length > 0) { var $item = queue.pop(); if (cursor === index) { item; break; } cursor++; var children = $item.children; for (var i = 0; i < children.length; i++) { queue.push(children[i]); } } return $result; }; var hasClass = function hasClass(cls, className) { if (cls && typeof cls === 'string' && cls.indexOf(className) !== -1) { return true; } return false; }; var inWhiteList = function inWhiteList(classAttr) { var classWhiteList = 'rich_pages,blockquote_info,blockquote_biz,blockquote_other,blockquote_article,js_jump_icon,h5_image_link,js_banner_container,js_list_container,js_cover,js_tx_video_container,js_product_err_container,js_product_loop_content,js_product_container,img_loading,list-paddingleft-1,list-paddingleft-2,list-paddingleft-3,selectTdClass,noBorderTable,ue-table-interlace-color-single,ue-table-interlace-color-double,__bg_gif,weapp_image_link,js_img_loading,wx_video_context,db,wx_video_thumb_primary,wx_video_play_btn,wx_video_mask,qqmusic_area,tc,tips_global,unsupport_tips,qqmusic_wrp,appmsg_card_context,appmsg_card_active,wx_tap_card,js_wx_tap_highlight,wx_tap_link,qqmusic_bd,play_area,icon_qqmusic_switch,pic_qqmusic_default,qqmusic_thumb,access_area,qqmusic_songname,qqmusic_singername,qqmusic_source,js_audio_frame,share_audio_context,flex_context,pages_reset,share_audio_switch,icon_share_audio_switch,share_audio_info,flex_bd,share_audio_title,share_audio_tips,share_audio_progress_wrp,share_audio_progress,share_audio_progress_inner,share_audio_progress_buffer,share_audio_progress_loading,share_audio_progress_loading_inner,share_audio_progress_handle,share_audio_desc,share_audio_length_current,share_audio_length_total,video_iframe,vote_iframe,js_editor_vote_card,res_iframe,card_iframe,js_editor_card,weapp_display_element,js_weapp_display_element,weapp_card,app_context,weapp_card_bd,weapp_card_profile,radius_avatar,weapp_card_avatar,weapp_card_nickname,weapp_card_info,weapp_card_title,weapp_card_thumb_wrp,weapp_card_ft,weapp_card_logo,js_pay_btn,pay,pay__mask,wx_video_loading,js_redpacketcover,js_uneditable,js_uneditablemouseover,js_editor_qqmusic,js_img_placeholder,js_editor_audio,ct_geography_loc_tip,js_poi_entry,js_mention_entry,product_text_link'.split(','); var qaClassPrefix = 'qa__'; var classWhiteListReg = [new RegExp('^weui'), new RegExp('^appmsg'), new RegExp('^audio'), new RegExp('^music'), new RegExp('^cps_inner'), new RegExp('^bizsvr_'), new RegExp('^code-snippet'), new RegExp('^' + qaClassPrefix), new RegExp('^wx-edui-'), new RegExp('^wx_'), new RegExp('^wx-'), new RegExp('^custom_select_card_') ]; if (!classAttr) return null; var classList = classAttr.split(/\s+/); var newClassList = []; for (var i = 0, len = classList.length; i < len; ++i) { var className = classList[i]; if (className && classWhiteList.indexOf(className) !== -1) { newClassList.push(className); } else { for (var j = 0, jl = classWhiteListReg.length; j < jl; j++) { if (classWhiteListReg[j].test(className)) { newClassList.push(className); break; } } } } var str = newClassList.join('.'); return str && '.' + str; }; var getNodeSelector = function getNodeSelector(node) { var selector = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; var root = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : document.body; if (!node || node === root) return selector; var id = node.getAttribute('id'); var className = node.getAttribute('class'); var tagName = node.tagName.toLowerCase(); var currentSelector = null; if (id && !hasClass(className, 'articlepart-selector-area_choice-button_wrap')) return selector ? "#".concat(id, ">").concat(selector) : "#".concat(id); var whiteClassName = inWhiteList(className); if (whiteClassName) { currentSelector = whiteClassName; } else if (hasClass(className, 'js_choice-img')) { currentSelector = '.js_choice-img'; } else if (hasClass(className, 'articlepart-selector-area_choice')) { currentSelector = node.dataset.splitid ? '' : tagName; } else { currentSelector = tagName; } return getNodeSelector(node.parentNode, [currentSelector, selector].filter(function (item) { return !!item; }).join('>'), root); }; var getNodeSelectorWrap = function getNodeSelectorWrap(node, root) { var selector = getNodeSelector(node, '', root); var collect = []; try { collect = root.querySelectorAll(selector); } catch (error) { console.log('get node selector wrap err', error); } var len = collect.length; var index = null; for (var i = 0; i < len; i++) { if (node === collect[i]) { index = i; break; } } if (index === null) { if (typeof WX_BJ_REPORT !== 'undefined' && WX_BJ_REPORT.BadJs) { WX_BJ_REPORT.BadJs.report('ArticleMask:Error', 'selector:node not find', { mid: 'mmbizwap:articlemask_Monitor', view: 'wap_business', _info: { selector: selector } }); } } var newSelector = (selector || '').replace('>.js_choice-img>', '>') + "|".concat(len, " ").concat(index || 0); return newSelector; }; var serializeToC = function serializeToC(nodes) { return ( nodes.map(function (item) { var node, type = item.type, idx = item.idx; var index = 0; var data = null; var meta = ''; var blockItem = getBlockNode($node); if (type === NODE_TYPE.text) { var nodeIndex = getNodeIndex(blockItem, $node.parentNode); if (node.data) { index = nodeIndex; data = $node.data; meta = node.previousSibling.data; } } else if (type === NODE_TYPE.img) { var imgs = blockItem.getElementsByTagName('img'); data = $node.src; index = Array.prototype.slice.call(imgs).slice(0).indexOf($node); } return { data: data, index: index, idx: idx, type: type, meta: meta }; }).filter(function (item) { return item.index > -1 && !!item.data; }) ); } ; var serializeToC2 = function serializeToC2(nodes, $container) { var root = $container || document.getElementById('js_content'); return nodes.map(function (item) { var node, type = item.type, idx = item.idx; var selector = null; var data = null; var meta = ''; if (type === NODE_TYPE.text) { if (node.data) { selector = getNodeSelectorWrap($node.parentNode, root); data = $node.data; meta = node.previousSibling.data; } } else if (type === NODE_TYPE.img) { selector = getNodeSelectorWrap($node, root); data = $node.src; } return { data: data, idx: idx, type: type, meta: meta, selector: selector }; }).filter(function (item) { return !!item.selector && !!item.data; }); }; function setProperty(el, name, value, priority) { if (!!el.style.setProperty) { priority = priority || null; el.style.setProperty(name, value, priority); } else if (typeof el.style.cssText !== 'undefined') { priority = priority ? '!' + priority : ''; el.style.cssText += ';' + name + ':' + value + priority + ';'; } } function hasImgNode($el) { if (!$el) return false; var nodeType = $el.nodeType, tagName = $el.tagName; if (nodeType === 3) { return false; } if (tagName === IMG_TAG) { return true; } return false; } function getContent(tree) { return tree.reduce(function (acc, cur, idx) { if (idx === 0) { if (cur.type === NODE_TYPE.text) { acc.text.push(cur.data); } else if (cur.type === NODE_TYPE.img) { acc.pic.push(cur.data); } return acc; } if (cur.type === NODE_TYPE.text) { if (tree[idx - 1].type === NODE_TYPE.text) { var text = acc.text.pop(); text += cur.data; acc.text.push(text); } else { acc.text.push(cur.data); } return acc; } if (cur.type === NODE_TYPE.img) { acc.pic.push(cur.data); } return acc; }, { audio: [], pic: [], video: [], text: [] }); } function saveNode($node, key) { TEMP_NODES[key] = $node; } function serializeNode(wrap) { var range = nodeToSelection($node); var anchorTree = serializeToC2([{ node, type: NODE_TYPE.img, idx: range.start.paraIndex }], $wrap); var anchorMeta = serialize(range); var anchorBrief = getContent(anchorTree); return { meta: { anchorTree: anchorTree, anchorMeta: anchorMeta, anchorBrief: anchorBrief }, range: range }; } function findChildIndex(parent, offset) { var childNodes = parent.childNodes; var realOffset = offset; var $node = null; var i = 0; for (i = 0; i < childNodes.length; i++) { $node = childNodes[i]; if ($node.nodeType === 3) { var len = $node.length; if (len > realOffset) { break; } else { realOffset -= len; } } } return { node, cursor: realOffset }; } var qs = function qs(selector, el) { return (el || document).querySelector(selector); }; var qsAll = function qsAll(selector, el) { return (el || document).querySelectorAll(selector); }; var dom = { getDomMeta: getDomMeta, getContent: getContent, getParaList: getParaList, getBlockNode: getBlockNode, getSelectedNodes: getSelectedNodes, connectSiblingText: connectSiblingText, getTextNodeByOffset: getTextNodeByOffset, getBlockOffset: getBlockOffset, getSelection: getSelection, transferTextToElement: transferTextToElement, serialize: serialize, deSerialize: deSerialize, resetRange: resetRange, serializeToC: serializeToC, setProperty: setProperty, hasImgNode: hasImgNode, nodeToSelection: nodeToSelection, saveNode: saveNode, serializeNode: serializeNode, getNodeByIndex: getNodeByIndex, findChildIndex: findChildIndex, serializeToC2: serializeToC2, blockEleTagName: blockEleTagName, getPureBlockNode: getPureBlockNode, qs: qs, qsAll: qsAll, hasClass: hasClass }; function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } var paraList = []; var totalHit = 0; var STATUS = { auditing: 1, ban: 2 }; function keyby(arr, key) { return arr.reduce(function (acc, item) { if (typeof item[key] === 'undefined') return acc; if (!acc[item[key]]) acc[item[key]] = []; acc[item[key]].push(item); return acc; }, {}); } function getBannerWord(anchor) { return '以下内容存在争议 <a style="color: var(--weui-LINK);" target="_blank" href="https://mp.weixin.qq.com/s/_2kC-fXw7UjneZSrsC9CVQ">了解更多</a>'; } function addBanner(node, text) { var paraNode = _typeof(node) === 'object' ? node : paraList[node]; if (paraNode.dataset.hasBanner) return; var divNode = document.createElement('div'); divNode.dataset.hasBanner = 1; divNode.style = 'background-color: var(--weui-BG-1);font-size: 14px;color: var(--weui-FG-2);text-align: left;margin-top: 20px;margin-bottom: 4px;padding: 4px 8px 6px 8px;border-radius:4px;'; var iconNode = document.createElement('span'); iconNode.style = 'color: var(--weui-FG-0);padding: 2px;display: inline-block;vertical-align: middle; width: 20px;height: 20px;margin-right: 4px; background-size: cover;background-position: center center;-webkit-mask: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' width=\'20\' height=\'20\' viewBox=\'0 0 20 20\'%3E %3Cpath fill-opacity=\'.3\' fill-rule=\'evenodd\' d=\'M10 1.667a8.333 8.333 0 1 1 0 16.666 8.333 8.333 0 0 1 0-16.666zm-.004 11.115a.732.732 0 0 0-.746.735c0 .416.33.735.746.735a.73.73 0 0 0 .752-.735.73.73 0 0 0-.752-.735zm.638-7.669h-1.27l.091 6.33h1.088l.091-6.33z\'/%3E%3C/svg%3E") no-repeat 50% 50%;mask: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' width=\'20\' height=\'20\' viewBox=\'0 0 20 20\'%3E %3Cpath fill-opacity=\'.3\' fill-rule=\'evenodd\' d=\'M10 1.667a8.333 8.333 0 1 1 0 16.666 8.333 8.333 0 0 1 0-16.666zm-.004 11.115a.732.732 0 0 0-.746.735c0 .416.33.735.746.735a.73.73 0 0 0 .752-.735.73.73 0 0 0-.752-.735zm.638-7.669h-1.27l.091 6.33h1.088l.091-6.33z\'/%3E%3C/svg%3E") no-repeat 50% 50%;background-color: currentColor;'; var textNode = document.createElement('span'); textNode.style = 'display: inline-block;line-height: 14px;vertical-align: middle;'; textNode.innerHTML = text; divNode.appendChild(iconNode); divNode.appendChild(textNode); paraNode.parentNode.insertBefore(divNode, paraNode, null); paraNode.dataset.hasBanner = 1; } function maskText(data, domNode, cursor) { var len = data.length; var maskMat = _toConsumableArray(Array(len)).map(function () { return '〇'; }).join(''); var childNodes = domNode.childNodes; var newCursor = cursor; for (var i = 0; i < childNodes.length; i++) { var node = childNodes[i]; if (node.nodeType === 3) { if (newCursor > node.data.length) { newCursor -= node.data.length; } else { node.data = node.data.slice(0, newCursor).concat(maskMat).concat(node.data.slice(newCursor + len)); } } else if (node.nodeText === 1) { newCursor -= node.innerText && node.innerText.length || 0; } } } function disputeText(data, domNode, cursor) { var len = data.length; var _dom$findChildIndex = dom.findChildIndex(domNode, cursor), textNode = _domnode, realOffset = _dom$findChildIndex.realOffset; try { textNode.splitText(realOffset); } catch (e) { if (typeof WX_BJ_REPORT !== 'undefined' && WX_BJ_REPORT.BadJs) { WX_BJ_REPORT.BadJs.report('ArticleMask:Error', 'splitText Error', { mid: 'mmbizwap:articlemask_Monitor', view: 'wap_business', _info: { type: 'disputeText textNode', data: data, cursor: cursor } }); } } var repalcedNode = textNode.nextSibling; try { repalcedNode.splitText(len); } catch (e) { if (typeof WX_BJ_REPORT !== 'undefined' && WX_BJ_REPORT.BadJs) { WX_BJ_REPORT.BadJs.report('ArticleMask:Error', 'splitText Error', { mid: 'mmbizwap:articlemask_Monitor', view: 'wap_business', _info: { type: 'disputeText nextSibling', data: data, cursor: cursor } }); } } var spanNode = document.createElement('span'); spanNode.style = 'background-color: rgba(0,0,0,0.10);'; spanNode.appendChild(repalcedNode.cloneNode(true)); repalcedNode.parentNode.replaceChild(spanNode, repalcedNode); } function disputeImage(data, domNode) { var spanNode = document.createElement('span'); spanNode.style = 'position:relative;display: inline-block;'; var iconNode = document.createElement('span'); iconNode.style = "\n position: absolute;\n top: 4px;\n left: 4px;\n display: inline-block;\n vertical-align: middle;\n width: 24px;\n height: 24px;\n background-size: cover;\n background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E %3Cpath fill='%23FFF' fill-rule='evenodd' d='M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2zm-.004 13.339a.878.878 0 0 0-.896.882c0 .499.396.882.896.882.512 0 .902-.383.902-.882 0-.5-.39-.882-.902-.882zm.765-9.203h-1.524l.11 7.596h1.305l.11-7.596z'/%3E%3C/svg%3E\");\n "; var parent = domNode.parentNode; spanNode.appendChild(domNode.cloneNode(false)); parent.replaceChild(spanNode, domNode); spanNode.appendChild(iconNode); } function maskImage(data, domNode) { domNode.style.filter = 'blur(10px)'; domNode.style['-webkit-filter'] = 'blur(10px)'; } function hitMaskText(anchor, domNode) { var data = anchor.data, meta = anchor.meta, index = anchor.index, idx = anchor.idx; var wholeText = domNode.data; var prefixText = (meta || '') + data; if (wholeText.indexOf(prefixText) === -1) { return { hit: false }; } var itemNode = dom.getNodeByIndex(paraList[idx], index); if (itemNode) { totalHit++; } else { if (typeof WX_BJ_REPORT !== 'undefined' && WX_BJ_REPORT.BadJs) { WX_BJ_REPORT.BadJs.report('ArticleMask:Error', 'text node cannot find', { mid: 'mmbizwap:articlemask_Monitor', view: 'wap_business', _info: { anchor: anchor, wholeText: wholeText } }); } } var cursor = itemNode && itemNode.innerText.indexOf(prefixText) + (meta || '').length; return { hit: !!itemNode, $hitDom: itemNode, cursor: cursor }; } function hitMaskImage(anchor, domNode) { var index = anchor.index, idx = anchor.idx, data = anchor.data; var para = paraList[idx]; var allImgNode = para.querySelectorAll('img'); var hitItenNode = allImgNode[index]; var src = hitItenNode && (hitItenNode.getAttribute('src') || hitItenNode.getAttribute('src')); if (src === data) { totalHit++; return { hit: true, $hitDom: domNode, cursor: 0 }; } return { hit: false }; } function createMask(anchor, domNode) { return function (hitFn, maskFn, next) { var _hitFn = hitFn(anchor, domNode), hit = _hitFn.hit, hitDom, cursor = _hitFn.cursor; if (hit) { maskFn(anchor.data, $hitDom, cursor); next(); } }; } function maskAnchors(anchors, paraNode) { var queue = []; var cloneAnchors = _toConsumableArray(anchors); queue.push(paraNode); var anchor = null; var next = function next() { anchor = cloneAnchors.shift(); }; next(); while (queue.length > 0 && cloneAnchors.length >= 0 && anchor) { var itemNode = queue.pop(); if (!itemNode) continue; if (!anchor) continue; var nodeType = itemNode.nodeType, tagName = itemNode.tagName; var createMaskFn = createMask(anchor, itemNode); if (nodeType === 3) { if (anchor.type === NODE_TYPE.text) { createMaskFn(hitMaskText, anchor.status === STATUS.ban ? maskText : disputeText, next); } continue; } if (nodeType === 1 && tagName === IMG_TAG) { if (anchor.type === NODE_TYPE.img) { createMaskFn(hitMaskImage, anchor.status === STATUS.ban ? maskImage : disputeImage, next); } continue; } var children = itemNode.childNodes; for (var i = children.length - 1; i >= 0; i--) { queue.push(children[i]); } } } function parseSelector(selectorStr) { if (!selectorStr) return {}; var _selectorStr$split = selectorStr.split('|'), _selectorStr$split2 = _slicedToArray(_selectorStr$split, 2), selector = _selectorStr$split2[0], other = _selectorStr$split2[1]; var _other$split = other.split(' '), _other$split2 = _slicedToArray(_other$split, 2), total = _other$split2[0], index = _other$split2[1]; return { selector: selector.replace(/>/g, '>'), total: total * 1, index: index * 1 }; } function hitNode(node, anchor) { if (!node) return null; var type = anchor.type, data = anchor.data, meta = anchor.meta; if (type === NODE_TYPE.text) { var nodeText = node.innerText || node.innerHTML || ''; var prefixText = ((meta || '') + data).replace(/&/g, '&'); if (nodeText.indexOf(prefixText) !== -1) { var cursor = nodeText.indexOf(prefixText) + (meta || '').length; return { cursor: cursor, node: node }; } } if (type === NODE_TYPE.img) { var src = node && (node.getAttribute('src') || node.getAttribute('src')); if (src === data.replace(/&/g, '&')) { return { cursor: 0, node: node }; } } return null; } function maskNode(anchor, domNode, cursor) { var type = anchor.type, data = anchor.data, status = anchor.status; if (status !== STATUS.ban) return; if (type === NODE_TYPE.text) maskText(data, domNode, cursor); if (type === NODE_TYPE.img) maskImage(data, domNode); } function initOld(wrapNode, anchors) { paraList = dom.getParaList(wrapNode, { getNestedStructure: true, removeIgoreEle: false }); var formatAnchor = keyby(anchors, 'idx'); if (!paraList) return; (paraList || []).forEach(function (para, index) { var paraAnchors = formatAnchor[index]; if (paraAnchors && paraAnchors.length > 0) { addBanner(index, getBannerWord(paraAnchors[0])); maskAnchors(paraAnchors, para); } }); if (anchors && anchors.length !== totalHit) { if (typeof WX_BJ_REPORT !== 'undefined' && WX_BJ_REPORT.BadJs) { WX_BJ_REPORT.BadJs.report('ArticleMask:Error', 'totalHit', { mid: 'mmbizwap:articlemask_Monitor', view: 'wap_business', _info: { totalHit: totalHit, anchors: anchors } }); } } } function addChildBanner(node, anchor) { var blockNode = dom.getPureBlockNode(node); if (!blockNode) return; addBanner(blockNode, getBannerWord()); } function maskAnchors2(wrapNode, anchors) { var missNodes = []; var countList = []; var maskNodeList = []; var cacheSelector = {}; anchors.forEach(function (anchor, i) { var _parseSelector = parseSelector(anchor.selector), selector = _parseSelector.selector, index = _parseSelector.index, total = _parseSelector.total; var nodes = cacheSelector[selector] || []; if (nodes.length === 0) { try { nodes = wrapNode.querySelectorAll(selector); cacheSelector[selector] = nodes; } catch (e) { if (typeof WX_BJ_REPORT !== 'undefined' && WX_BJ_REPORT.BadJs) { WX_BJ_REPORT.BadJs.report('ArticleMask:Error', 'splitText Error', { mid: 'mmbizwap:articlemask_Monitor', view: 'wap_business', _info: { anchor: anchor } }); } } } var cursorLeft = index; var cursorRight = index; var queue = []; var node = null; var cursor = 0; var count = 0; queue.push(nodes[index]); while (queue.length) { var current = queue.pop(); var hitData = hitNode(current, anchor); count++; if (hitData && hitData.node) { node = hitData.node; cursor = hitData.cursor; break; } if (cursorLeft - 1 >= 0 && nodes[cursorLeft - 1]) { queue.push(nodes[cursorLeft - 1]); cursorLeft -= 1; } if (cursorRight + 1 < nodes.length && nodes[cursorRight + 1]) { queue.push(nodes[cursorRight + 1]); cursorRight += 1; } } if (node) { maskNodeList.push({ anchor: anchor, node: node, cursor: cursor }); addChildBanner(node); } else if (selector && selector.lastIndexOf('>') !== -1) { missNodes.push(_objectSpread(_objectSpread({}, anchor), {}, { selector: selector && selector.slice(0, selector.lastIndexOf('>')) + "|".concat(total, " ").concat(index) })); } countList[i] = count; }); maskNodeList.forEach(function (item) { maskNode(item.anchor, item.node, item.cursor); }); if (missNodes.length) { maskAnchors2(wrapNode, missNodes); if (typeof WX_BJ_REPORT !== 'undefined' && WX_BJ_REPORT.BadJs) { WX_BJ_REPORT.BadJs.report('ArticleMask:Error', 'missNodes', { mid: 'mmbizwap:articlemask_Monitor', view: 'wap_business', _info: { missNodes: missNodes } }); } } if (typeof WX_BJ_REPORT !== 'undefined' && WX_BJ_REPORT.BadJs) { WX_BJ_REPORT.BadJs.report('ArticleMask:Info', 'querycount', { mid: 'mmbizwap:articlemask_Monitor', view: 'wap_business', _info: { countList: countList } }); } } function init2(wrapNode, anchors) { maskAnchors2(wrapNode, anchors); } function init(wrapNode, anchors) { var oldAnchors = []; var newAnchors = []; anchors.forEach(function (anchor) { if (anchor.selector) { newAnchors.push(anchor); } else { oldAnchors.push(anchor); } }); init2(wrapNode, newAnchors); if (oldAnchors.length > 0) { initOld(wrapNode, oldAnchors); } } var complainPainter = { init: init }; try { if (window.anchor_tree_msg) { var start = Date.now(); var $wrap = document.getElementById('js_content'); var anchors = window.anchor_tree_msg ? JSON.parse(window.anchor_tree_msg).anchor_tree : []; var protocol = window.location.protocol; complainPainter.init($wrap, anchors); wxgspeedsdk.saveSpeeds({ sample: 1, uin: window.uin, pid: protocol == 'https:' ? 462 : 417, speeds: { sid: 38, time: Date.now() - start } }); wxgspeedsdk.send(); } } catch (error) { if (typeof WX_BJ_REPORT !== 'undefined' && window.WX_BJ_REPORT.BadJs) { window.WX_BJ_REPORT.BadJs.onError(error, { anchor_tree_msg: window.anchor_tree_msg }); } } })();</script><script type="text/javascript" nonce="1989770072" reportloaderror>(function () { 'use strict'; var AD_TYPE = { ANDROID_APP_PRODUCT_TYPE: 12, IOS_APP_PRODUCT_TYPE: 19, ADD_CONTACT_PRODUCT_TYPE: 23, MINI_GAME_PRODUCT_TYPE: 46, CARD_PRODUCT_TYPE: 36, SHOP_PRODUCT_TYPE: 30, WECHATCARD_PRODUCT_TYPE: 47, BRAND_WECHAT_PRODUCT_TYPE: 29, BRAND_GDT_PRODUCT_TYPE: 31 }; var AD_POS = { POS_BOTTOM: 0, POS_BOTTOM_PC: 38, POS_MID: 4, POS_MID_PC: 39, POS_SPONSOR: 3, POS_AD_BEFORE_VIDEO: 7, POS_AD_AFTER_VIDEO: 9, POS_AD_MID_VIDEO: 16, POS_AD_KEYWORD: 36 }; var AD_DEST_TYPE = { AD_DEST_TYPE: 0, OUTER_DEST_TYPE: 1, APPDETAIL_DEST_TYPE: 2, BIZ_DEST_TYPE: 3, APPINFO_PAGE_DEST_TYPE: 4, WECHAT_SHOP_DEST_TYPE: 5, WECHAT_APPLET_DEST_TYPE: 6, LEAF_DEST_TYPE: 7, CANVAS_AD_DEST_TYPE: 9 }; var AD_CACHE_TIME = 0.5 * 60 * 1000; var AD_JSAPI_WHITE_LIST = ['openUrlWithExtraWebview', 'openADCanvas', 'addContact', 'profile', 'getInstallState', 'installDownloadTask', 'addDownloadTask', 'pauseDownloadTask', 'resumeDownloadTask', 'queryDownloadTask', 'launchApplication', 'writeCommData', 'adDataReport', 'downloadAppInternal', 'wxdownload:progress_change', 'menu:share:appmessage', 'menu:share:timeline', 'menu:share:weibo', 'menu:share:facebook', 'menu:general:share', 'launch3rdApp', 'addDownloadTaskStraight', 'sendAppMessage', 'shareTimeline', 'getNetworkType', 'openBizChat', 'jumpToBizProfile', 'shareWeibo', 'shareFB', 'imagePreview', 'getBackgroundAudioState', 'openWeApp', 'openEmbeddedWeApp', 'preloadMiniProgramContacts', 'preloadMiniProgramEnv', 'calRqt', 'openCardDetail', 'batchAddCard', 'handleMPPageAction', 'makePhoneCall', 'getOAID', 'saveWaid', 'batchPreloadMiniProgram', 'onScreenShot', 'handleAdAction', 'activity:state_change', 'getAdIdInfo', 'onWebPageUrlExposed', 'openFinderView', 'predownloadMiniProgramPackage', 'openCustomerServiceChat', 'showOpenIMContactProfile', 'openWXSearchPage']; var AD_REQ_PATH_WHITE_LIST = [ '/mp/advertisement_report', '/mp/ad_report', '/mp/ad_video_report', '/mp/jsmonitor', '/mp/ad_complaint', '/mp/jsreport', '/tp/datacenter/report', '/mp/getappmsgad', '/mp/ad_biz_info', '/mp/appmsg_video_snap', '/mp/cps_product_info', '/mp/mini_drama_info']; var AD_WEB_COMPT_REQ_PATH_WHITE_LIST = [/(https?:)?\/\/mp\.weixin\.qq\.com\/mp\/advertisement_report/, /(https?:)?\/\/mp\.weixin\.qq\.com\/mp\/ad_report/, /(https?:)?\/\/mp\.weixin\.qq\.com\/mp\/ad_video_report/, /(https?:)?\/\/mp\.weixin\.qq\.com\/mp\/jsmonitor/, /(https?:)?\/\/mp\.weixin\.qq\.com\/mp\/ad_complaint/, /(https?:)?\/\/mp\.weixin\.qq\.com\/mp\/jsreport/, /(https?:)?\/\/mp\.weixin\.qq\.com\/tp\/datacenter\/report/, /(https?:)?\/\/mp\.weixin\.qq\.com\/mp\/getappmsgad/, /(https?:)?\/\/mp\.weixin\.qq\.com\/mp\/ad_biz_info/, /(https?:)?\/\/mp\.weixin\.qq\.com\/tp\/goods_info/, /(https?:)?\/\/mp\.weixin\.qq\.com\/tp\/app_mobile/, /(https?:)?\/\/mp\.weixin\.qq\.com\/tp\/datareport\/report/, /(https?:)?\/\/mp\.weixin\.qq\.com\/promotion\/wxalandpage\/getcanvasinfo/]; var transformText = '转化按钮'; var extraText = '广告文案或辅助信息'; var defaultMidAdData = { hint_txt: '创意-20200827_1', url: 'https://ad.weixin.qq.com/guide/196?weixinadkey=59d5cf0b4fbf7d2f66cd90aaa82a5208057512dd06fcb64d7fd57e71ec15945e1744ac499e05a04999381c3bf30c21ca&gdt_vid=wx0clsqxat6lzly601&weixinadinfo=315019981.wx0clsqxat6lzly601.75.1', type: '0', rl: 'http://ad.wx.com:12638/cgi-bin/click?viewid=AQM1xOr6MFeZmWeZrowCvQcrvQUBUq4o8ER2yFgwF9grPdtUR9bIJQ8laqMAJjGlkGLuVbyABIPX6Eifa2%2FK%2Buq17IIT21tYcUnpeU4VqEEsEQhc5Pa7C7drAvl0Mz30CNepODMXeD%2BEdny8SmmxN7prV78e1L2S6oqhNjrnTqM1t40ZGU84httoAODXEjmE89IX0ncOiP1oTsgm1tYwahSkxN6HLZIb6bhxZrc5ba3mCKMZ5GV4UEyDuQCyySxtA5QTt0eQJJA%2FSgHe79yTxUrzzoGrtlhK0O3HussVeRjKcvLkE6w%2FpQBnropwT%2FmE23RT2bOoyw%2BVCMlWTtk%2Bvxh%2FIOFAmrWHYzDuNkDNRo3um26RD2TFpeyRasbZoFRAV7RA9k4P3REAH4vemxktbNq24rtuF6MFGEcXpcGOD%2FxZJlBmInM7rguFAhRQWvCy3nIpO7knN2rl2DZv%2FcfkuoP4bedzUMcxtrU2Wz%2B82EG9ULHJunGHT%2F%2BcWj%2Bv8n%2Fh9bUtAtk7Fr1HBQdkQ8SbYadhRDWWuSEC2iMfqpMyzNqLltdxhyXxMRpsruPb2p4WoHnSvuGfbnkXIKcDppOTLB38xStPIbbaaR4FC%2B4AOF1UqbtMor9JJQQNz3vspSngY%2F37uYiQXAKNYB2RAB%2BbfoYMSS2VcJvY%2B0lWH3%2BYFTmBs6%2BxixGTJmB4%2FXZZcNs4PgRs6OoIefEnLz%2FvwoAvrs%2FUPotqevoiHfq%2FlLILAzo28D%2FKSU9hOOHXrS4LrUYhK47WKSeoglnagaOZI5kGZa9iBcwj9V6FR4HEml51P9u5xaTOnPZjfEAx5l6BBxTT4379irAZCB2Zfcd6wBU2Eo5p9yXVSH%2FCH8yVAgIEsrJ9oeqpO%2FwozsQ2PkXw%2Bz77B56hYp1zYG7HK%2BCDjx1NSisa6g8PFa72xOb8wpjZ9Lao70oGSWshIjCH4kWfKX0P8uFJc22L%2FZihKj0J%2BqgC1LgiMc6SXmFHdvTSIxTRKm9GImpbVfLTN3xrT%2BGGutwMTfgWta7EDR7d6HXQBA1orNotnnK37GOw1jHud8fzQkfuMN%2F7DO6kW0wAXs4LDMhJpnHi2%2Ba4VjL8Yjh0wmTZkVy4iIPYDmYSAzuJ3aP3cXuGv%2B1JwF%2Fod7hCA6RBYwZN2fXvO5AUo7FdoRr8ssPB7eAiNhcFonMv5%2Bt8L1b7QLoXGlplvxh9Fz669q43xnDsEy8ucOfyush8RiYLPxGj4YFr2gy6%2BAV5u%2FMgZIShq149jRn42%2B%2BnmzPC8JdiiIe4p5Ec7KFFrv%2F302DcKBPI9lQDsC1xWAvIfJcnxC%2FqYgDikLE1SsurxV2PV1icS%2BpU706S2LmnpyAsZw%3D%3D', apurl: 'http://ad.wx.com:12638/cgi-bin/exposure?viewid=AQM1xOr6MFeZmWeZrowCvQcrvQUBUq4o8ER2yFgwF9grPdtUR9bIJQ8laqMAJjGlkGLuVbyABIPX6Eifa2%2FK%2Buq17IIT21tYcUnpeU4VqEEsEQhc5Pa7C7drAvl0Mz30CNepODMXeD%2BEdny8SmmxN7prV78e1L2S6oqhNjrnTqM1t40ZGU84httoAODXEjmE89IX0ncOiP1oTsgm1tYwahSkxN6HLZIb6bhxZrc5ba3mCKMZ5GV4UEyDuQCyySxtA5QTt0eQJJA%2FSgHe79yTxUrzzoGrtlhK0O3HussVeRjKcvLkE6w%2FpQBnropwT%2FmE23RT2bOoyw%2BVCMlWTtk%2Bvxh%2FIOFAmrWHYzDuNkDNRo3um26RD2TFpeyRasbZoFRAV7RA9k4P3REAH4vemxktbNq24rtuF6MFGEcXpcGOD%2FxZJlBmInM7rguFAhRQWvCy3nIpO7knN2rl2DZv%2FcfkuoP4bedzUMcxtrU2Wz%2B82EG9ULHJunGHT%2F%2BcWj%2Bv8n%2Fh9bUtAtk7Fr1HBQdkQ8SbYadhRDWWuSEC2iMfqpMyzNqLltdxhyXxMRpsruPb2p4WoHnSvuGfbnkXIKcDppOTLB38xStPIbbaaR4FC%2B4AOF1UqbtMor9JJQQNz3vspSngY%2F37uYiQXAKNYB2RAB%2BbfoYMSS2VcJvY%2B0lWH3%2BYFTmBs6%2BxixGTJmB4%2FXZZcNs4PgRs6OoIefEnLz%2FvwoAvrs%2FUPotqevoiHfq%2FlLILAzo28D%2FKSU9hOOHXrS4LrUYhK47WKSeoglnagaOZI5kGZa9iBcwj9V6FR4HEml51P9u5xaTOnPZjfEAx5l6BBxTT4379irAZCB2Zfcd6wBU2Eo5p9yXVSH%2FCH8yVAgIEsrJ9oeqpO%2FwozsQ2PkXw%2Bz77B56hYp1zYG7HK%2BCDjx1NSisa6g8PFa72xOb8wpjZ9Lao70oGSWshIjCH4kWfKX0P8uFJc22L%2FZihKj0J%2BqgC1LgiMc6SXmFHdvTSIxTRKm9GImpbVfLTN3xrT%2BGGutwMTfgWta7EDR7d6HXQBA1orNotnnK37GOw1jHud8fzQkfuMN%2F7DO6kW0wAXs4LDMhJpnHi2%2Ba4VjL8Yjh0wmTZkVy4iIPYDmYSAzuJ3aP3cXuGv%2B1JwF%2Fod7hCA6RBYwZN2fXvO5AUo7FdoRr8ssPB7eAiNhcFonMv5%2Bt8L1b7QLoXGlplvxh9Fz669q43xnDsEy8ucOfyush8RiYLPxGj4YFr2gy6%2BAV5u%2FMgZIShq149jRn42%2B%2BnmzPC8JdiiIe4p5Ec7KFFrv%2F302DcKBPI9lQDsC1xWAvIfJcnxC%2FqYgDikLE1SsurxV2PV1icS%2BpU706S2LmnpyAsZw%3D%3D', traceid: 'wx0clsqxat6lzly601', group_id: 'wx0clsqxat6lzly600_wx0clsqxat6lzly601', ticket: '', pt: 2, image_url: 'http://wxsnsdythumb.wxs.qq.com/141/20204/snscosdownload/SH/reserved/5f4604790009bfd700000000b3679d090000008d00004eec?m=1c9e9086c11018ef774e28ee3b744a67&ck=1c9e9086c11018ef774e28ee3b744a67', ad_desc: '', biz_appid: 'wx69618ae091cf2c76', biz_info: { user_name: 'gh_1e80bb81a1d2', nick_name: '微信广告', head_img: 'https://wxa.wxs.qq.com/res/images/bizsdk/preview/wxlogo.png', biz_uin: 3094043316, signature: '微信广告' }, pos_type: 4, watermark_type: 0, logo: '', is_cpm: 0, dest_type: 1, material_width: 960, material_height: 540, ad_width: 0, ad_height: 0, use_new_protocol: 2, product_type: 29, material_type: 0, crt_exp_tid: 0, crt_exp_info: '', flow_exp_info: '[{"exp_para":[{"name":94574,"value":"gb"},{"name":100036,"value":"1"}]}]', watermark_text: '活动推广', crt_size: '484', button_action: "{"button_text":"".concat(transformText, "","jump_type":1,"jump_url":"https:\\/\\/ad.weixin.qq.com\\/guide\\/196?weixinadkey=bd80a7a5a0e57a3b971b1c372bb06a3748f8f01c44f1bfe1a0aa4fe927e21037fc57ddfe77f5e0648611197259574f4b&gdt_vid=wx0clsqxat6lzly601&weixinadinfo=315019981.wx0clsqxat6lzly601.75.1","text_type":0}"), position_index: 21, shop_image: [], material_id_list: [], uxinfo: '315019981|wx0clsqxat6lzly601|289237697|0|1598496949|0|0|9020229299926746||AgI0AyUHOnPeccmEYhaAko8Pr4P95P7Vl6qjqKrxaR/CSGQ3e+STumguP/V43UuYT8o=|315020504', ext_info: '{}', ad_token: 'bf8463b9a4b692768c820c412bb705a73e8a9dd2c769f22549e4bb5aeaaeccc1358b60b6ce7546f95cfdf7f73d187572', crt_info: "[{"width":960,"height":540,"thumb_url":"http://wxsnsdythumb.wxs.qq.com/141/20204/snscosdownload/SH/reserved/5f4604790009bfd700000000b3679d090000008d00004eec?m=1c9e9086c11018ef774e28ee3b744a67&ck=1c9e9086c11018ef774e28ee3b744a67","image_url":"http://wxsnsdythumb.wxs.qq.com/141/20204/snscosdownload/SH/reserved/5f4604790009bfd700000000b3679d090000008d00004eec?m=1c9e9086c11018ef774e28ee3b744a67&ck=1c9e9086c11018ef774e28ee3b744a67","size":18323,"image_md5":"1c9e9086c11018ef774e28ee3b744a67","materialId":"112199640","card_info":{"mp_tag_type":2,"mp_brandeffect_isopen":0,"mp_tags":["".concat(extraText, ""]}}]"), reranking_ext_info: '{"tid":315020504}', ext_back_comm: '{"pctr":0.019999999553}' }; var CPS_GOODS_TYPE = { OLD_GOODS: 'mp', NEW_GOODS: 'cps-to-reader', IMAGE_GOODS: 'cps-to-image-reader', SHORT_PLAY: 'short-play', MINI_GAME: 'mini-game' }; var AD_CONFIG = { defaultMidAdData: defaultMidAdData, AD_TYPE: AD_TYPE, AD_POS: AD_POS, AD_CACHE_TIME: AD_CACHE_TIME, AD_DEST_TYPE: AD_DEST_TYPE, AD_FRAME_DOMAIN: 'https://wxa.wxs.qq.com', CPS_AD_FRAME_DOMAIN: 'https://file.daihuo.qq.com', INVALID_METHOD_NAME_MSG_PREFIX: 'Invalid methodName', INVALID_METHOD_TYPE_MSG_PREFIX: 'Invalid methodType', INVALID_ARGS_MSG_PREFIX: 'Invalid args', INVALID_REQ_PATH_MSG_PREFIX: 'Invalid request path', AD_IFRAME_HIDE_CLASS: 'iframe_ad_dn', AD_JSAPI_WHITE_LIST: AD_JSAPI_WHITE_LIST, AD_REQ_PATH_WHITE_LIST: AD_REQ_PATH_WHITE_LIST, AD_WEB_COMPT_REQ_PATH_WHITE_LIST: AD_WEB_COMPT_REQ_PATH_WHITE_LIST, FRAME_ERROR: 'onError', FRAME_READY: 'onFrameReadyV2', CHANGE_FRAME_STYLE: 'changeFrameStyle', PROXY_CONSOLE: 'consoleOnHostEnv', PROXY_ACTION: 'onProxyV2', PROXY_CALLBACK_ACTION: 'proxyCallbackV2', CLICK_OUTSIDE_ACTION: 'clickOutsideV2', CLICK_AD_ACTION: 'onAdClick', PAGE_SCROLL_ACTION: 'pageScrollV2', ORIGIN_VIDEO_VID_PREFIX: 'wxv', AD_VIDEO_FIN_ACTION: 'adVideoEnd', AD_VIDEO_PLAY_ACTION: 'onVideoPlayV2', AD_VIDEO_END_ACTION: 'onVideoEndV2', AD_PLAY_VIDEO_ACTION: 'playVideoV2', AD_EXPOSE_IMAGE_ACTION: 'exposeImage', AD_HIDE_IMAGE_ACTION: 'hideImage', AD_CHANGE_VIDEO_STATE: 'changeVideoPlayState', AD_VIDEO_SET_SCREEN_STATE_ACTION: 'setScreenState', AD_IMAGE_SET_EXPAND_STATE_ACTION: 'setImageExpandState', GET_APPMSGAD_READY_STATUS_ACTION: 'getAppmsgadReadyStatus', APPMSGAD_READY_ACTION: 'appmsgadReady', HAS_AD_DATA_QUERY_KEY: 'has_ad_data', GET_AD_DATA_AFTER_VIDEO_ACTION_NAME: 'getAdDataAfterVideo', SET_PAGE_DATA_ACTION_NAME: 'setPageDataV2', SET_AD_DATA_ACTION_NAME: 'setAdDataV2', SEND_AD_VID_ACTION: 'sendAdVid', GET_AD_VID_ACTION: 'getAdVid', CPS_GOODS_TYPE: CPS_GOODS_TYPE }; var g = { defaultContentTpl: '<span class="js_img_placeholder wx_widget_placeholder" style="width:#width# !important;height:#height#px !important;text-indent: 0"><span class="weui-primary-loading"><span class="weui-primary-loading__dot"></span></span>', config: [{ querySelector: 'redpacketcover', genId: function genId() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return decodeURIComponent(opt.node.getAttribute('data-coveruri') || ''); }, calW: function calW() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return opt.parentWidth * 0.7854; }, calH: function calH() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return this.calW({ parentWidth: opt.parentWidth }) / 0.73346 + 27 + 37; }, replaceContentCssText: '', outerContainerLeft: '', outerContainerRight: '' }, { querySelector: 'mppoi', genId: function genId() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return opt.node.getAttribute('data-id') || ''; }, calW: function calW() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return opt.parentWidth * 1; }, calH: function calH() { return 219; }, replaceContentCssText: '', appendContentCssText: 'diplay:block;', outerContainerLeft: '', outerContainerRight: '' }, { querySelector: 'mpsearch', genId: function genId() { return decodeURIComponent('mp-common-search'); }, calW: function calW() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return opt.parentWidth * 1; }, calH: function calH() { return 100; }, replaceContentCssText: '', appendContentCssText: 'diplay:block;', outerContainerLeft: '', outerContainerRight: '' }, { querySelector: 'mpvideosnap', genId: function genId() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var type = opt.node.getAttribute('data-type') || 'video'; if (type === 'live') { return decodeURIComponent(opt.node.getAttribute('data-noticeid') || ''); } return decodeURIComponent(opt.node.getAttribute('data-id') || ''); }, calW: function calW() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var type = opt.node.getAttribute('data-type') || 'video'; var width = opt.node.getAttribute('data-width') || ''; var height = opt.node.getAttribute('data-height') || ''; if (type === 'live' || type === 'topic') { return opt.parentWidth; } var ratio = 1; ratio = width / height; var computedHeight = 0; var computedWidth = 0; var isHorizontal = false; if (ratio === 1 || ratio === 3 / 4) ; else if (ratio === 4 / 3 || ratio === 16 / 9) { isHorizontal = true; } else if (ratio < 3 / 4) { ratio = 3 / 4; } else if (ratio > 1 && ratio < 4 / 3) { ratio = 1; } else if (ratio > 4 / 3) { isHorizontal = true; } else if (typeof ratio === 'number' && !Object.is(ratio, NaN)) ; else { ratio = 1; } opt.node.setAttribute('data-ratio', ratio); opt.node.setAttribute('data-isHorizontal', isHorizontal); if (isHorizontal === true) { computedWidth = opt.parentWidth; } else { if (window.innerWidth < 1024) { computedWidth = window.innerWidth * 0.65; } else { computedWidth = opt.parentWidth * 0.65; } } computedHeight = computedWidth / ratio; computedHeight = Math.round(computedHeight); computedWidth = Math.round(computedWidth); opt.node.setAttribute('data-computedWidth', computedWidth); opt.node.setAttribute('data-computedHeight', computedHeight); return computedWidth; }, calH: function calH() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var desc = opt.node.getAttribute('data-desc') || ''; var type = opt.node.getAttribute('data-type') || 'video'; var computedHeight = opt.node.getAttribute('data-computedHeight') || ''; switch (type) { case 'live': return desc ? 152 : 116; case 'topic': return 201; case 'image': case 'video': return parseFloat(computedHeight); } }, getBorderRadius: function getBorderRadius() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var type = opt.node.getAttribute('data-type') || 'video'; if (type === 'video') { return 4; } return 8; }, replaceContentCssText: '', appendContentCssText: 'display:flex;margin:0px auto;', outerContainerLeft: '', outerContainerRight: '' }, { querySelector: 'mp-wxaproduct', genId: function genId() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return decodeURIComponent(opt.node.getAttribute('data-wxaproduct-productid') || ''); }, calW: function calW() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return opt.parentWidth * 1 || '100%'; }, calH: function calH() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var cardtype = opt.node.getAttribute('data-wxaproduct-cardtype') || ''; return cardtype === 'mini' ? 124 : 466; }, replaceContentCssText: '', outerContainerLeft: '', outerContainerRight: '' }, { querySelector: 'mpprofile', genId: function genId(opt) { return opt.node.getAttribute('data-id') || ''; }, calW: function calW() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return opt.parentWidth * 1; }, calH: function calH() { return 143; }, replaceContentCssText: '', appendContentCssText: 'diplay:block;', outerContainerLeft: '', outerContainerRight: '' }, { querySelector: 'mp-common-product:not([data-cardtype="2"])', genId: function genId(opt) { return opt.node.getAttribute('data-windowproduct') || ''; }, calW: function calW() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; if (opt.node.getAttribute('data-cardtype') === "0") { return Math.min(opt.parentWidth, 400) * 1 || '100%'; } return opt.parentWidth * 1 || '100%'; }, calH: function calH(opt) { var customstyle = opt.node.getAttribute('data-customstyle') || '{}'; if (customstyle) { try { var _JSON$parse = JSON.parse(customstyle), display = _JSON$parse.display, height = _JSON$parse.height; if (display !== 'none') { var customHeight = parseInt(height, 10); var ratio; if (opt.node.getAttribute('data-cardtype') === "0") { ratio = Math.min(400, opt.parentWidth) / 350.0 || 1; } else { ratio = opt.parentWidth / 350.0 || 1; } customHeight = Math.round(customHeight * ratio); return customHeight; } return 0; } catch (err) { console.error(err); } } return 0; }, replaceContentCssText: '', appendContentCssText: 'diplay:block;', outerContainerLeft: '<div style="display: flex; margin: 0 auto 24px;justify-content: center;">', outerContainerRight: '</div>' }, { querySelector: 'mpcps:not([data-templateid="video-play"]),mp-common-cpsad:not([data-templateid="video-play"])', genId: function genId(opt) { var node = opt.node; var planId = node.getAttribute('data-planid'); var goodId = node.getAttribute('data-pid'); var traceId = node.getAttribute('data-traceid'); return goodId || planId || traceId || ''; }, calW: function calW() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var node = opt.node; var templateId = node.getAttribute('data-templateid'); var adType = node.getAttribute('data-adtype'); var width = 0; if (templateId === 'list') { width = '100%'; } else if (templateId === 'card') { if (adType === AD_CONFIG.CPS_GOODS_TYPE.SHORT_PLAY || adType === AD_CONFIG.CPS_GOODS_TYPE.MINI_GAME) { width = opt.parentWidth ? opt.parentWidth * 0.65 : '100%'; } else { width = '100%'; } } return width; }, calH: function calH(opt) { var node = opt.node; var templateId = node.getAttribute('data-templateid'); var adType = node.getAttribute('data-adtype'); var height = 0; if (templateId === 'list') { if (adType === AD_CONFIG.CPS_GOODS_TYPE.MINI_GAME) { height = 79; } else { height = 120; } } else if (templateId === 'card') { if (adType === AD_CONFIG.CPS_GOODS_TYPE.SHORT_PLAY) { var width = opt.parentWidth * 0.65; height = Math.ceil(width * (4 / 3)) + 68; } else if (adType === AD_CONFIG.CPS_GOODS_TYPE.MINI_GAME) { var _width = opt.parentWidth * 0.65; height = Math.ceil(_width * (4 / 3)) + 64; } else { height = Math.ceil(opt.parentWidth + 111); } } return height; }, replaceContentCssText: '', appendContentCssText: 'diplay:block;', outerContainerLeft: '<div style="display: flex; justify-content: center">', outerContainerRight: '</div>' } ] }; function preloadingInit() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; if (typeof document.querySelectorAll !== 'function') { return; } var g = { maxWith: document.getElementById('img-content').getBoundingClientRect().width, idAttr: 'data-preloadingid' }; for (var i = 0, il = opt.config.length; i < il; i++) { var a = opt.config[i]; var list = document.querySelectorAll(a.querySelector); for (var j = 0, jl = list.length; j < jl; j++) { var node = list[j]; var parentWidth = node.parentNode.getBoundingClientRect().width; parentWidth = Math.min(parentWidth, g.maxWith); if (node.getAttribute('has-insert-preloading')) { continue; } var nodeW = a.calW({ parentWidth: parentWidth, node: node }); var nodeH = a.calH({ parentWidth: parentWidth, node: node }); var nodeId = a.genId({ index: j, node: node }); var nodeBorderRadius = typeof a.getBorderRadius === 'function' ? a.getBorderRadius({ index: j, node: node }) : 8; if (typeof nodeW === 'number') { nodeW += 'px'; } var imgHtml = opt.defaultContentTpl.replace(/#height#/g, nodeH).replace(/#width#/g, nodeW).replace(/#borderRadius#/g, nodeBorderRadius); var tmpNode = document.createElement('div'); tmpNode.innerHTML = imgHtml; if (a.replaceContentCssText) { var replaceContentCssText = a.replaceContentCssText.replace(/#height#/g, nodeH).replace(/#width#/g, nodeW); tmpNode.firstChild.style.cssText = replaceContentCssText; } else if (a.appendContentCssText) { tmpNode.firstChild.style.cssText += a.appendContentCssText; } var html = (a.outerContainerLeft || '') + tmpNode.innerHTML + (a.outerContainerRight || ''); tmpNode.innerHTML = html; tmpNode.firstChild.setAttribute(g.idAttr, nodeId); node.parentNode.insertBefore(tmpNode.firstChild, node.nextSibling); node.setAttribute('has-insert-preloading', '1'); } } } function init() { preloadingInit(g); } function decode(str) { var replace = ["`", "`", "'", "'", """, '"', " ", " ", ">", ">", "<", "<", "¥", "¥", "&", "&"]; for (var i = 0; i < replace.length; i += 2) { str = str.replace(new RegExp(replace[i], 'g'), replace[i + 1]); } return str; } function getQuery(url) { url = url || 'http://qq.com/s?a=b#rd'; var tmp = url.split('?'), query = (tmp[1] || '').split('#')[0].split('&'), params = {}; for (var i = 0; i < query.length; i++) { var eqIndex = query[i].indexOf('='); if (eqIndex > -1) { var arg = query[i].substring(0, eqIndex); params[arg] = query[i].substring(eqIndex + 1); } } if (params['pass_ticket']) { params['pass_ticket'] = encodeURIComponent(decode(params['pass_ticket']).replace(/\s/g, '+')); } return params; } function insertAfter(dom, afterDom) { var _p = afterDom.parentNode; if (!_p) { return; } if (_p.lastChild === afterDom) { _p.appendChild(dom); } else { _p.insertBefore(dom, afterDom.nextSibling); } } if (typeof getComputedStyle === 'undefined') { if (document.body.currentStyle) { window.getComputedStyle = function (el) { return el.currentStyle; }; } else { window.getComputedStyle = {}; } } function getMaxWith() { var container = document.getElementById('img-content'); var max_width = container.offsetWidth; var container_padding = 0; var container_style = getComputedStyle(container); container_padding = parseFloat(container_style.paddingLeft) + parseFloat(container_style.paddingRight); max_width -= container_padding; if (!max_width) { max_width = window.innerWidth - 32; } return max_width; } function getParentWidth(dom) { var parent_width = 0; var parent = dom.parentNode; var outerWidth = 0; while (true) { if (!parent || parent.nodeType !== 1) break; var parent_style = getComputedStyle(parent); if (!parent_style) break; parent_width = parent.clientWidth - parseFloat(parent_style.paddingLeft) - parseFloat(parent_style.paddingRight) - outerWidth; if (parent_width > 16) break; outerWidth += parseFloat(parent_style.paddingLeft) + parseFloat(parent_style.paddingRight) + parseFloat(parent_style.marginLeft) + parseFloat(parent_style.marginRight) + parseFloat(parent_style.borderLeftWidth) + parseFloat(parent_style.borderRightWidth); parent = parent.parentNode; } if (parent_width < 0) { return 0; } return parent_width; } function getOuterW(dom) { var style = getComputedStyle(dom); var w = 0; if (!!style) { w = parseFloat(style.paddingLeft) + parseFloat(style.paddingRight) + parseFloat(style.borderLeftWidth) + parseFloat(style.borderRightWidth); } return w; } function getOuterH(dom) { var style = getComputedStyle(dom); var h = 0; if (!!style) { h = parseFloat(style.paddingTop) + parseFloat(style.paddingBottom) + parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth); } return h; } function getVideoWh(dom, vid, data) { var max_width = getMaxWith(); var width = max_width; var ratio_ = dom.getAttribute('data-ratio') * 1 || 4 / 3; if (data.video_page_infos && Array.isArray(data.video_page_infos) && data.video_page_infos.some(function (x) { return x.video_id === vid; })) { var videoData = data.video_page_infos.find(function (x) { return x.video_id === vid; }); if (Array.isArray(videoData.mp_video_trans_info) && videoData.mp_video_trans_info.length) { var transInfo = videoData.mp_video_trans_info[0]; if (!!transInfo.width && !!transInfo.height) { ratio_ = transInfo.width / transInfo.height; } } } var arr = [4 / 3, 16 / 9]; var ret = arr[0]; var abs = Math.abs(ret - ratio_); for (var j = 1, jl = arr.length; j < jl; j++) { var _abs = Math.abs(arr[j] - ratio_); if (_abs < abs) { abs = _abs; ret = arr[j]; } } ratio_ = ret; var parent_width = getParentWidth(dom) || max_width; var rwidth = width > parent_width ? parent_width : width; var outerW = getOuterW(dom) || 0; var outerH = getOuterH(dom) || 0; var videoW = rwidth - outerW; var videoH = videoW / ratio_; var speedDotH = 12; var rheight = videoH + outerH + speedDotH; return { w: Math.ceil(rwidth), h: Math.ceil(rheight), vh: videoH, vw: videoW, ratio: ratio_, sdh: speedDotH }; } function setImgSize(item, widthNum, widthUnit, ratio, breakParentWidth) { var imgPaddingBorder = getOuterW(item) || 0; var imgPaddingBorderTopBottom = getOuterH(item) || 0; if (widthNum > getParentWidth(item) && !breakParentWidth) { widthNum = getParentWidth(item); } var heightNum = (widthNum - imgPaddingBorder) * ratio + imgPaddingBorderTopBottom; widthNum !== 'auto' && (item.style.cssText += ";width: ".concat(widthNum).concat(widthUnit, " !important;")); widthNum !== 'auto' && (item.style.cssText += ";height: ".concat(heightNum).concat(widthUnit, " !important;")); } var isAccessibilityKey = 'isMpUserAccessibility'; var imgPlaceholderClass = 'js_img_placeholder'; var isAccessMode = window.localStorage.getItem(isAccessibilityKey); var imgSizeData; var validArr = ',' + [0.875, 1, 1.125, 1.25, 1.375].join(',') + ','; var match = window.location.href.match(/winzoom=(\d+(?:\.\d+)?)/); if (match && match[1]) { var winzoom = parseFloat(match[1]); if (validArr.indexOf(',' + winzoom + ',') >= 0) ; } function getImgSrcMainInfo(src) { var pathName = new URL(src).pathname; var lastIndex = pathName.lastIndexOf('/'); return lastIndex > 0 ? pathName.slice(0, lastIndex) : pathName; } function setSize(images, videos, data) { var bypassPreloading = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; var noWidth = !document.body.clientWidth || !document.getElementById('img-content') || !document.getElementById('img-content').offsetWidth; var _loop = function _loop() { if (noWidth) { return 0; } if (window.__second_open__ && videos[vi].getAttribute('__sec_open_place_holder__')) { return 1; } var a = videos[vi]; var src_ = a.getAttribute('src') || a.getAttribute('src') || ''; var vid = getQuery(src_).vid || a.getAttribute('data-mpvid'); if (!vid) { return 1; } vid = vid.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); a.removeAttribute('src'); a.style.display = 'none'; var obj = getVideoWh(a, vid, data); var videoPlaceHolderSpan = document.createElement('span'); videoPlaceHolderSpan.className = "".concat(imgPlaceholderClass, " wx_widget_placeholder"); videoPlaceHolderSpan.setAttribute('data-vid', vid); videoPlaceHolderSpan.innerHTML = '<span class="weui-primary-loading"><span class="weui-primary-loading__dot"></span></span>'; videoPlaceHolderSpan.style.cssText = "width: " + obj.w + "px !important;"; insertAfter(videoPlaceHolderSpan, a); a.style.cssText += ';width: ' + obj.w + 'px !important;'; a.setAttribute('width', obj.w); { videoPlaceHolderSpan.style.cssText += 'height: ' + (obj.h - obj.sdh) + 'px !important;margin-bottom: ' + obj.sdh + 'px !important;'; a.style.cssText += 'height: ' + obj.h + 'px !important;'; a.setAttribute('height', obj.h); } a.setAttribute('data-vh', obj.vh); a.setAttribute('data-vw', obj.vw); a.setAttribute('src', 'https://v.qq.com/iframe/player.html?vid=' + vid + '&width=' + obj.vw + '&height=' + obj.vh + '&auto=0'); a.setAttribute('__sec_open_place_holder__', true); var index = vi; (function setHitStyle() { var hitInfos = data.video_page_infos; var ret = (hitInfos || []).find(function (info) { return info.video_id === vid; }); if (!ret) return; var ori = ret.ori_status; var hit_biz_headimg = ret.hit_biz_headimg, hit_nickname = ret.hit_nickname, hit_username = ret.hit_username; var sourceBiz = ret.hit_bizuin; var selfUserName = data.user_name; if (ori === 2 && selfUserName !== hit_username) { var videoBar = document.createElement('div'); var videoBarHtml = "\n <div class=\"wx-edui-video_source_link js_wx_tap_highlight wx_tap_card\" id=\"".concat(hit_username).concat(index, "\" data-hit-username=\"").concat(hit_username, "\" data-hit-biz=\"").concat(sourceBiz, "\">\n <div class=\"wx-edui-video_source_word\">_(\"\u4EE5\u4E0B\u89C6\u9891\u6765\u6E90\u4E8E\")</div>\n <div class=\"wx-edui-video_account_info\">\n <div class=\"wx-edui-video_account_avatar\" id=\"").concat(hit_biz_headimg).concat(index, "\" src=\"").concat(hit_biz_headimg, "\"></div>\n <div class=\"wx-edui-video_account_name\">").concat(hit_nickname, "</div>\n <i class=\"wx-edui-video_account_arrow\"></i>\n </div>\n <div class=\"wx-edui-video_source_link__layer_mask\"></div>\n </div>"); videoBar.innerHTML = videoBarHtml; document.querySelectorAll('.video_iframe').forEach(function (item) { if (item.getAttribute('data-mpvid') === vid && item.getAttribute('data-hasSource') !== '1') { item.setAttribute('data-hasSource', 1); item.parentNode.insertBefore(videoBar, item); } }); var avatorEle = document.getElementById(hit_biz_headimg + index); var avatorSrc = avatorEle.dataset.src; if (ret.hit_biz_headimg) avatorEle.style.backgroundImage = "url(".concat(avatorSrc, ")"); } })(); }, _ret; for (var vi = 0, viLen = videos.length; vi < viLen; vi++) { _ret = _loop(); if (_ret === 0) break; if (_ret === 1) continue; } var isCarton = data.copyright_info.is_cartoon_copyright * 1 || data.user_info.is_care_mode * 1 || isAccessMode === '1'; var max_width = getMaxWith(); if (!imgSizeData) { imgSizeData = {}; data.picture_page_info_list = data.picture_page_info_list || []; var noWidthHeightCount = 0; var hasWidthHeightCount = 0; data.picture_page_info_list.forEach(function (imgData) { try { var width = Number(imgData.width); var height = Number(imgData.height); if (width && height) { imgSizeData[getImgSrcMainInfo(imgData.cdn_url)] = { ratio: height / width, width: width }; hasWidthHeightCount++; } else { noWidthHeightCount++; } } catch (err) { console.error(err); } }); if (Math.random() < 0.01 && Number(data.create_timestamp) > 1682352000) { hasWidthHeightCount && (new Image().src = "//mp.weixin.qq.com/mp/jsmonitor?idkey=330742_20_".concat(hasWidthHeightCount, "&r=").concat(Math.random())); noWidthHeightCount && (new Image().src = "//mp.weixin.qq.com/mp/jsmonitor?idkey=330742_21_".concat(noWidthHeightCount, "&r=").concat(Math.random())); if (!data.picture_page_info_list.length) { setTimeout(function () { noWidthHeightCount = document.querySelectorAll('#js_content img').length; noWidthHeightCount && (new Image().src = "//mp.weixin.qq.com/mp/jsmonitor?idkey=330742_21_".concat(noWidthHeightCount, "&r=").concat(Math.random())); }, 300); } } } for (var im = 0, imLen = images.length; im < imLen; im++) { if (window.__second_open__ && images[im].getAttribute('__sec_open_place_holder__')) { continue; } var img = images[im]; var imgDataSrc = img.getAttribute('src'); var realSrc = img.getAttribute('src'); if (!imgDataSrc || realSrc) continue; var imgStyle = img.getAttribute('style'); img.setAttribute('data-original-style', imgStyle); var width_ = img.dataset.w; var imgRatio = 1 * img.dataset.ratio; img.setAttribute('data-index', im); var width_num = 0; var width_unit = 'px'; try { var imgSizeFromBackend = imgSizeData[getImgSrcMainInfo(imgDataSrc)]; if (imgSizeFromBackend) { if (imgSizeFromBackend.ratio) { imgRatio = imgSizeFromBackend.ratio; img.setAttribute('data-ratio', imgSizeFromBackend.ratio); } if (imgSizeFromBackend.width) { width_ = imgSizeFromBackend.width; img.setAttribute('data-w', imgSizeFromBackend.width); } } } catch (err) { console.error(err); } if (imgRatio && imgRatio > 0) { if (!isCarton) { img.src = "data:image/svg+xml,%3C%3Fxml version='1.0' encoding='UTF-8'%3F%3E%3Csvg width='1px' height='1px' viewBox='0 0 1 1' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Ctitle%3E%3C/title%3E%3Cg stroke='none' stroke-width='1' fill='none' fill-rule='evenodd' fill-opacity='0'%3E%3Cg transform='translate(-249.000000, -126.000000)' fill='%23FFFFFF'%3E%3Crect x='249' y='126' width='1' height='1'%3E%3C/rect%3E%3C/g%3E%3C/g%3E%3C/svg%3E"; if (noWidth) { var fallbackWidth = img.style.width || img.getAttribute('width') || width_; var fallbackMaxWidth = 360; fallbackWidth = parseFloat(fallbackWidth, 10) > fallbackMaxWidth ? fallbackMaxWidth : fallbackWidth; if (fallbackWidth === 'inherit') { fallbackWidth = fallbackMaxWidth; } if (fallbackWidth) { img.setAttribute('_width', !isNaN(fallbackWidth * 1) ? fallbackWidth + 'px' : fallbackWidth); } if (typeof fallbackWidth === 'string' && fallbackWidth.indexOf('%') !== -1) { fallbackWidth = parseFloat(fallbackWidth.replace('%', ''), 10) / 100 * fallbackMaxWidth; } if (fallbackWidth === 'auto') { fallbackWidth = width_; if (width_ === 'auto' || !width_) { fallbackWidth = fallbackMaxWidth; } else { fallbackWidth = width_; } } var fallbackRes = /^(\d+(?:\.\d+)?)([a-zA-Z%]+)?$/.exec(fallbackWidth); var fallbackLastWidth = fallbackRes && fallbackRes.length >= 2 ? fallbackRes[1] : 0; var fallbackUnit = fallbackRes && fallbackRes.length >= 3 && fallbackRes[2] ? fallbackRes[2] : 'px'; setImgSize(img, fallbackLastWidth, fallbackUnit, imgRatio, true); img.classList.add(imgPlaceholderClass, "wx_img_placeholder"); continue; } img.classList.add(imgPlaceholderClass, "wx_img_placeholder"); } var parent_width = getParentWidth(img) || max_width; var init_width = img.style.width || img.getAttribute('width') || width_ || parent_width; init_width = parseFloat(init_width, 10) > max_width ? max_width : init_width; if (init_width === 'inherit') { init_width = parent_width; } if (init_width) { img.setAttribute('_width', !isNaN(init_width * 1) ? init_width + 'px' : init_width); } if (typeof init_width === 'string' && init_width.indexOf('%') !== -1) { setImgSize(img, width_, 'px', imgRatio, true); parent_width = getParentWidth(img) || max_width; init_width = parseFloat(init_width.replace('%', ''), 10) / 100 * parent_width; } if (init_width === 'auto') { init_width = width_; if (width_ === 'auto' || !width_) { init_width = parent_width; } else { init_width = width_; } } var res = /^(\d+(?:\.\d+)?)([a-zA-Z%]+)?$/.exec(init_width); width_num = res && res.length >= 2 ? res[1] : 0; width_unit = res && res.length >= 3 && res[2] ? res[2] : 'px'; var imgWidth = width_num; if (isCarton) { img.src = imgDataSrc; img.style.height = 'auto'; } else { setImgSize(img, imgWidth, width_unit, imgRatio, true); setImgSize(img, imgWidth, width_unit, imgRatio, false); } } if (!data.is_h5_render) { img.setAttribute('__sec_open_place_holder__', true); } } if (!bypassPreloading) init(); } var ua = navigator.userAgent; /mac\sos/i.test(ua) && !/(iPhone|iPad|iPod|iOS)/i.test(ua) || /windows\snt/i.test(ua); var images = document.getElementsByTagName('img'); var videos = []; var user_name = "gh_6258c101a32a"; var isCartoonCopyright = '0'; var is_care_mode = ''; var createTimestamp = '1743643844'; var picturePageInfoList = "[]"; picturePageInfoList = picturePageInfoList.includes(',]') ? picturePageInfoList.replace(',]', ']') : picturePageInfoList; try { picturePageInfoList = JSON.parse(picturePageInfoList.replace(/'/g, '"')); } catch (err) { picturePageInfoList = []; console.error(err); } var data = { is_h5_render: true, user_name: user_name, copyright_info: { is_cartoon_copyright: isCartoonCopyright }, picture_page_info_list: picturePageInfoList, create_timestamp: createTimestamp, user_info: { is_care_mode: is_care_mode } }; setSize(images, videos, data); })();</script><script type="text/javascript" nonce="1989770072" reportloaderror>(function () { 'use strict'; var AD_TYPE = { ANDROID_APP_PRODUCT_TYPE: 12, IOS_APP_PRODUCT_TYPE: 19, ADD_CONTACT_PRODUCT_TYPE: 23, MINI_GAME_PRODUCT_TYPE: 46, CARD_PRODUCT_TYPE: 36, SHOP_PRODUCT_TYPE: 30, WECHATCARD_PRODUCT_TYPE: 47, BRAND_WECHAT_PRODUCT_TYPE: 29, BRAND_GDT_PRODUCT_TYPE: 31 }; var AD_POS = { POS_BOTTOM: 0, POS_BOTTOM_PC: 38, POS_MID: 4, POS_MID_PC: 39, POS_SPONSOR: 3, POS_AD_BEFORE_VIDEO: 7, POS_AD_AFTER_VIDEO: 9, POS_AD_MID_VIDEO: 16, POS_AD_KEYWORD: 36 }; var AD_DEST_TYPE = { AD_DEST_TYPE: 0, OUTER_DEST_TYPE: 1, APPDETAIL_DEST_TYPE: 2, BIZ_DEST_TYPE: 3, APPINFO_PAGE_DEST_TYPE: 4, WECHAT_SHOP_DEST_TYPE: 5, WECHAT_APPLET_DEST_TYPE: 6, LEAF_DEST_TYPE: 7, CANVAS_AD_DEST_TYPE: 9 }; var AD_CACHE_TIME = 0.5 * 60 * 1000; var AD_JSAPI_WHITE_LIST = ['openUrlWithExtraWebview', 'openADCanvas', 'addContact', 'profile', 'getInstallState', 'installDownloadTask', 'addDownloadTask', 'pauseDownloadTask', 'resumeDownloadTask', 'queryDownloadTask', 'launchApplication', 'writeCommData', 'adDataReport', 'downloadAppInternal', 'wxdownload:progress_change', 'menu:share:appmessage', 'menu:share:timeline', 'menu:share:weibo', 'menu:share:facebook', 'menu:general:share', 'launch3rdApp', 'addDownloadTaskStraight', 'sendAppMessage', 'shareTimeline', 'getNetworkType', 'openBizChat', 'jumpToBizProfile', 'shareWeibo', 'shareFB', 'imagePreview', 'getBackgroundAudioState', 'openWeApp', 'openEmbeddedWeApp', 'preloadMiniProgramContacts', 'preloadMiniProgramEnv', 'calRqt', 'openCardDetail', 'batchAddCard', 'handleMPPageAction', 'makePhoneCall', 'getOAID', 'saveWaid', 'batchPreloadMiniProgram', 'onScreenShot', 'handleAdAction', 'activity:state_change', 'getAdIdInfo', 'onWebPageUrlExposed', 'openFinderView', 'predownloadMiniProgramPackage', 'openCustomerServiceChat', 'showOpenIMContactProfile', 'openWXSearchPage']; var AD_REQ_PATH_WHITE_LIST = [ '/mp/advertisement_report', '/mp/ad_report', '/mp/ad_video_report', '/mp/jsmonitor', '/mp/ad_complaint', '/mp/jsreport', '/tp/datacenter/report', '/mp/getappmsgad', '/mp/ad_biz_info', '/mp/appmsg_video_snap', '/mp/cps_product_info', '/mp/mini_drama_info']; var AD_WEB_COMPT_REQ_PATH_WHITE_LIST = [/(https?:)?\/\/mp\.weixin\.qq\.com\/mp\/advertisement_report/, /(https?:)?\/\/mp\.weixin\.qq\.com\/mp\/ad_report/, /(https?:)?\/\/mp\.weixin\.qq\.com\/mp\/ad_video_report/, /(https?:)?\/\/mp\.weixin\.qq\.com\/mp\/jsmonitor/, /(https?:)?\/\/mp\.weixin\.qq\.com\/mp\/ad_complaint/, /(https?:)?\/\/mp\.weixin\.qq\.com\/mp\/jsreport/, /(https?:)?\/\/mp\.weixin\.qq\.com\/tp\/datacenter\/report/, /(https?:)?\/\/mp\.weixin\.qq\.com\/mp\/getappmsgad/, /(https?:)?\/\/mp\.weixin\.qq\.com\/mp\/ad_biz_info/, /(https?:)?\/\/mp\.weixin\.qq\.com\/tp\/goods_info/, /(https?:)?\/\/mp\.weixin\.qq\.com\/tp\/app_mobile/, /(https?:)?\/\/mp\.weixin\.qq\.com\/tp\/datareport\/report/, /(https?:)?\/\/mp\.weixin\.qq\.com\/promotion\/wxalandpage\/getcanvasinfo/]; var transformText = '转化按钮'; var extraText = '广告文案或辅助信息'; var defaultMidAdData = { hint_txt: '创意-20200827_1', url: 'https://ad.weixin.qq.com/guide/196?weixinadkey=59d5cf0b4fbf7d2f66cd90aaa82a5208057512dd06fcb64d7fd57e71ec15945e1744ac499e05a04999381c3bf30c21ca&gdt_vid=wx0clsqxat6lzly601&weixinadinfo=315019981.wx0clsqxat6lzly601.75.1', type: '0', rl: 'http://ad.wx.com:12638/cgi-bin/click?viewid=AQM1xOr6MFeZmWeZrowCvQcrvQUBUq4o8ER2yFgwF9grPdtUR9bIJQ8laqMAJjGlkGLuVbyABIPX6Eifa2%2FK%2Buq17IIT21tYcUnpeU4VqEEsEQhc5Pa7C7drAvl0Mz30CNepODMXeD%2BEdny8SmmxN7prV78e1L2S6oqhNjrnTqM1t40ZGU84httoAODXEjmE89IX0ncOiP1oTsgm1tYwahSkxN6HLZIb6bhxZrc5ba3mCKMZ5GV4UEyDuQCyySxtA5QTt0eQJJA%2FSgHe79yTxUrzzoGrtlhK0O3HussVeRjKcvLkE6w%2FpQBnropwT%2FmE23RT2bOoyw%2BVCMlWTtk%2Bvxh%2FIOFAmrWHYzDuNkDNRo3um26RD2TFpeyRasbZoFRAV7RA9k4P3REAH4vemxktbNq24rtuF6MFGEcXpcGOD%2FxZJlBmInM7rguFAhRQWvCy3nIpO7knN2rl2DZv%2FcfkuoP4bedzUMcxtrU2Wz%2B82EG9ULHJunGHT%2F%2BcWj%2Bv8n%2Fh9bUtAtk7Fr1HBQdkQ8SbYadhRDWWuSEC2iMfqpMyzNqLltdxhyXxMRpsruPb2p4WoHnSvuGfbnkXIKcDppOTLB38xStPIbbaaR4FC%2B4AOF1UqbtMor9JJQQNz3vspSngY%2F37uYiQXAKNYB2RAB%2BbfoYMSS2VcJvY%2B0lWH3%2BYFTmBs6%2BxixGTJmB4%2FXZZcNs4PgRs6OoIefEnLz%2FvwoAvrs%2FUPotqevoiHfq%2FlLILAzo28D%2FKSU9hOOHXrS4LrUYhK47WKSeoglnagaOZI5kGZa9iBcwj9V6FR4HEml51P9u5xaTOnPZjfEAx5l6BBxTT4379irAZCB2Zfcd6wBU2Eo5p9yXVSH%2FCH8yVAgIEsrJ9oeqpO%2FwozsQ2PkXw%2Bz77B56hYp1zYG7HK%2BCDjx1NSisa6g8PFa72xOb8wpjZ9Lao70oGSWshIjCH4kWfKX0P8uFJc22L%2FZihKj0J%2BqgC1LgiMc6SXmFHdvTSIxTRKm9GImpbVfLTN3xrT%2BGGutwMTfgWta7EDR7d6HXQBA1orNotnnK37GOw1jHud8fzQkfuMN%2F7DO6kW0wAXs4LDMhJpnHi2%2Ba4VjL8Yjh0wmTZkVy4iIPYDmYSAzuJ3aP3cXuGv%2B1JwF%2Fod7hCA6RBYwZN2fXvO5AUo7FdoRr8ssPB7eAiNhcFonMv5%2Bt8L1b7QLoXGlplvxh9Fz669q43xnDsEy8ucOfyush8RiYLPxGj4YFr2gy6%2BAV5u%2FMgZIShq149jRn42%2B%2BnmzPC8JdiiIe4p5Ec7KFFrv%2F302DcKBPI9lQDsC1xWAvIfJcnxC%2FqYgDikLE1SsurxV2PV1icS%2BpU706S2LmnpyAsZw%3D%3D', apurl: 'http://ad.wx.com:12638/cgi-bin/exposure?viewid=AQM1xOr6MFeZmWeZrowCvQcrvQUBUq4o8ER2yFgwF9grPdtUR9bIJQ8laqMAJjGlkGLuVbyABIPX6Eifa2%2FK%2Buq17IIT21tYcUnpeU4VqEEsEQhc5Pa7C7drAvl0Mz30CNepODMXeD%2BEdny8SmmxN7prV78e1L2S6oqhNjrnTqM1t40ZGU84httoAODXEjmE89IX0ncOiP1oTsgm1tYwahSkxN6HLZIb6bhxZrc5ba3mCKMZ5GV4UEyDuQCyySxtA5QTt0eQJJA%2FSgHe79yTxUrzzoGrtlhK0O3HussVeRjKcvLkE6w%2FpQBnropwT%2FmE23RT2bOoyw%2BVCMlWTtk%2Bvxh%2FIOFAmrWHYzDuNkDNRo3um26RD2TFpeyRasbZoFRAV7RA9k4P3REAH4vemxktbNq24rtuF6MFGEcXpcGOD%2FxZJlBmInM7rguFAhRQWvCy3nIpO7knN2rl2DZv%2FcfkuoP4bedzUMcxtrU2Wz%2B82EG9ULHJunGHT%2F%2BcWj%2Bv8n%2Fh9bUtAtk7Fr1HBQdkQ8SbYadhRDWWuSEC2iMfqpMyzNqLltdxhyXxMRpsruPb2p4WoHnSvuGfbnkXIKcDppOTLB38xStPIbbaaR4FC%2B4AOF1UqbtMor9JJQQNz3vspSngY%2F37uYiQXAKNYB2RAB%2BbfoYMSS2VcJvY%2B0lWH3%2BYFTmBs6%2BxixGTJmB4%2FXZZcNs4PgRs6OoIefEnLz%2FvwoAvrs%2FUPotqevoiHfq%2FlLILAzo28D%2FKSU9hOOHXrS4LrUYhK47WKSeoglnagaOZI5kGZa9iBcwj9V6FR4HEml51P9u5xaTOnPZjfEAx5l6BBxTT4379irAZCB2Zfcd6wBU2Eo5p9yXVSH%2FCH8yVAgIEsrJ9oeqpO%2FwozsQ2PkXw%2Bz77B56hYp1zYG7HK%2BCDjx1NSisa6g8PFa72xOb8wpjZ9Lao70oGSWshIjCH4kWfKX0P8uFJc22L%2FZihKj0J%2BqgC1LgiMc6SXmFHdvTSIxTRKm9GImpbVfLTN3xrT%2BGGutwMTfgWta7EDR7d6HXQBA1orNotnnK37GOw1jHud8fzQkfuMN%2F7DO6kW0wAXs4LDMhJpnHi2%2Ba4VjL8Yjh0wmTZkVy4iIPYDmYSAzuJ3aP3cXuGv%2B1JwF%2Fod7hCA6RBYwZN2fXvO5AUo7FdoRr8ssPB7eAiNhcFonMv5%2Bt8L1b7QLoXGlplvxh9Fz669q43xnDsEy8ucOfyush8RiYLPxGj4YFr2gy6%2BAV5u%2FMgZIShq149jRn42%2B%2BnmzPC8JdiiIe4p5Ec7KFFrv%2F302DcKBPI9lQDsC1xWAvIfJcnxC%2FqYgDikLE1SsurxV2PV1icS%2BpU706S2LmnpyAsZw%3D%3D', traceid: 'wx0clsqxat6lzly601', group_id: 'wx0clsqxat6lzly600_wx0clsqxat6lzly601', ticket: '', pt: 2, image_url: 'http://wxsnsdythumb.wxs.qq.com/141/20204/snscosdownload/SH/reserved/5f4604790009bfd700000000b3679d090000008d00004eec?m=1c9e9086c11018ef774e28ee3b744a67&ck=1c9e9086c11018ef774e28ee3b744a67', ad_desc: '', biz_appid: 'wx69618ae091cf2c76', biz_info: { user_name: 'gh_1e80bb81a1d2', nick_name: '微信广告', head_img: 'https://wxa.wxs.qq.com/res/images/bizsdk/preview/wxlogo.png', biz_uin: 3094043316, signature: '微信广告' }, pos_type: 4, watermark_type: 0, logo: '', is_cpm: 0, dest_type: 1, material_width: 960, material_height: 540, ad_width: 0, ad_height: 0, use_new_protocol: 2, product_type: 29, material_type: 0, crt_exp_tid: 0, crt_exp_info: '', flow_exp_info: '[{"exp_para":[{"name":94574,"value":"gb"},{"name":100036,"value":"1"}]}]', watermark_text: '活动推广', crt_size: '484', button_action: "{"button_text":"".concat(transformText, "","jump_type":1,"jump_url":"https:\\/\\/ad.weixin.qq.com\\/guide\\/196?weixinadkey=bd80a7a5a0e57a3b971b1c372bb06a3748f8f01c44f1bfe1a0aa4fe927e21037fc57ddfe77f5e0648611197259574f4b&gdt_vid=wx0clsqxat6lzly601&weixinadinfo=315019981.wx0clsqxat6lzly601.75.1","text_type":0}"), position_index: 21, shop_image: [], material_id_list: [], uxinfo: '315019981|wx0clsqxat6lzly601|289237697|0|1598496949|0|0|9020229299926746||AgI0AyUHOnPeccmEYhaAko8Pr4P95P7Vl6qjqKrxaR/CSGQ3e+STumguP/V43UuYT8o=|315020504', ext_info: '{}', ad_token: 'bf8463b9a4b692768c820c412bb705a73e8a9dd2c769f22549e4bb5aeaaeccc1358b60b6ce7546f95cfdf7f73d187572', crt_info: "[{"width":960,"height":540,"thumb_url":"http://wxsnsdythumb.wxs.qq.com/141/20204/snscosdownload/SH/reserved/5f4604790009bfd700000000b3679d090000008d00004eec?m=1c9e9086c11018ef774e28ee3b744a67&ck=1c9e9086c11018ef774e28ee3b744a67","image_url":"http://wxsnsdythumb.wxs.qq.com/141/20204/snscosdownload/SH/reserved/5f4604790009bfd700000000b3679d090000008d00004eec?m=1c9e9086c11018ef774e28ee3b744a67&ck=1c9e9086c11018ef774e28ee3b744a67","size":18323,"image_md5":"1c9e9086c11018ef774e28ee3b744a67","materialId":"112199640","card_info":{"mp_tag_type":2,"mp_brandeffect_isopen":0,"mp_tags":["".concat(extraText, ""]}}]"), reranking_ext_info: '{"tid":315020504}', ext_back_comm: '{"pctr":0.019999999553}' }; var CPS_GOODS_TYPE = { OLD_GOODS: 'mp', NEW_GOODS: 'cps-to-reader', IMAGE_GOODS: 'cps-to-image-reader', SHORT_PLAY: 'short-play', MINI_GAME: 'mini-game' }; var AD_CONFIG = { defaultMidAdData: defaultMidAdData, AD_TYPE: AD_TYPE, AD_POS: AD_POS, AD_CACHE_TIME: AD_CACHE_TIME, AD_DEST_TYPE: AD_DEST_TYPE, AD_FRAME_DOMAIN: 'https://wxa.wxs.qq.com', CPS_AD_FRAME_DOMAIN: 'https://file.daihuo.qq.com', INVALID_METHOD_NAME_MSG_PREFIX: 'Invalid methodName', INVALID_METHOD_TYPE_MSG_PREFIX: 'Invalid methodType', INVALID_ARGS_MSG_PREFIX: 'Invalid args', INVALID_REQ_PATH_MSG_PREFIX: 'Invalid request path', AD_IFRAME_HIDE_CLASS: 'iframe_ad_dn', AD_JSAPI_WHITE_LIST: AD_JSAPI_WHITE_LIST, AD_REQ_PATH_WHITE_LIST: AD_REQ_PATH_WHITE_LIST, AD_WEB_COMPT_REQ_PATH_WHITE_LIST: AD_WEB_COMPT_REQ_PATH_WHITE_LIST, FRAME_ERROR: 'onError', FRAME_READY: 'onFrameReadyV2', CHANGE_FRAME_STYLE: 'changeFrameStyle', PROXY_CONSOLE: 'consoleOnHostEnv', PROXY_ACTION: 'onProxyV2', PROXY_CALLBACK_ACTION: 'proxyCallbackV2', CLICK_OUTSIDE_ACTION: 'clickOutsideV2', CLICK_AD_ACTION: 'onAdClick', PAGE_SCROLL_ACTION: 'pageScrollV2', ORIGIN_VIDEO_VID_PREFIX: 'wxv', AD_VIDEO_FIN_ACTION: 'adVideoEnd', AD_VIDEO_PLAY_ACTION: 'onVideoPlayV2', AD_VIDEO_END_ACTION: 'onVideoEndV2', AD_PLAY_VIDEO_ACTION: 'playVideoV2', AD_EXPOSE_IMAGE_ACTION: 'exposeImage', AD_HIDE_IMAGE_ACTION: 'hideImage', AD_CHANGE_VIDEO_STATE: 'changeVideoPlayState', AD_VIDEO_SET_SCREEN_STATE_ACTION: 'setScreenState', AD_IMAGE_SET_EXPAND_STATE_ACTION: 'setImageExpandState', GET_APPMSGAD_READY_STATUS_ACTION: 'getAppmsgadReadyStatus', APPMSGAD_READY_ACTION: 'appmsgadReady', HAS_AD_DATA_QUERY_KEY: 'has_ad_data', GET_AD_DATA_AFTER_VIDEO_ACTION_NAME: 'getAdDataAfterVideo', SET_PAGE_DATA_ACTION_NAME: 'setPageDataV2', SET_AD_DATA_ACTION_NAME: 'setAdDataV2', SEND_AD_VID_ACTION: 'sendAdVid', GET_AD_VID_ACTION: 'getAdVid', CPS_GOODS_TYPE: CPS_GOODS_TYPE }; var g = { defaultContentTpl: '<span class="js_img_placeholder wx_widget_placeholder" style="width:#width# !important;height:#height#px !important;text-indent: 0"><span class="weui-primary-loading"><span class="weui-primary-loading__dot"></span></span>', config: [{ querySelector: 'redpacketcover', genId: function genId() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return decodeURIComponent(opt.node.getAttribute('data-coveruri') || ''); }, calW: function calW() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return opt.parentWidth * 0.7854; }, calH: function calH() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return this.calW({ parentWidth: opt.parentWidth }) / 0.73346 + 27 + 37; }, replaceContentCssText: '', outerContainerLeft: '', outerContainerRight: '' }, { querySelector: 'mppoi', genId: function genId() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return opt.node.getAttribute('data-id') || ''; }, calW: function calW() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return opt.parentWidth * 1; }, calH: function calH() { return 219; }, replaceContentCssText: '', appendContentCssText: 'diplay:block;', outerContainerLeft: '', outerContainerRight: '' }, { querySelector: 'mpsearch', genId: function genId() { return decodeURIComponent('mp-common-search'); }, calW: function calW() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return opt.parentWidth * 1; }, calH: function calH() { return 100; }, replaceContentCssText: '', appendContentCssText: 'diplay:block;', outerContainerLeft: '', outerContainerRight: '' }, { querySelector: 'mpvideosnap', genId: function genId() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var type = opt.node.getAttribute('data-type') || 'video'; if (type === 'live') { return decodeURIComponent(opt.node.getAttribute('data-noticeid') || ''); } return decodeURIComponent(opt.node.getAttribute('data-id') || ''); }, calW: function calW() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var type = opt.node.getAttribute('data-type') || 'video'; var width = opt.node.getAttribute('data-width') || ''; var height = opt.node.getAttribute('data-height') || ''; if (type === 'live' || type === 'topic') { return opt.parentWidth; } var ratio = 1; ratio = width / height; var computedHeight = 0; var computedWidth = 0; var isHorizontal = false; if (ratio === 1 || ratio === 3 / 4) ; else if (ratio === 4 / 3 || ratio === 16 / 9) { isHorizontal = true; } else if (ratio < 3 / 4) { ratio = 3 / 4; } else if (ratio > 1 && ratio < 4 / 3) { ratio = 1; } else if (ratio > 4 / 3) { isHorizontal = true; } else if (typeof ratio === 'number' && !Object.is(ratio, NaN)) ; else { ratio = 1; } opt.node.setAttribute('data-ratio', ratio); opt.node.setAttribute('data-isHorizontal', isHorizontal); if (isHorizontal === true) { computedWidth = opt.parentWidth; } else { if (window.innerWidth < 1024) { computedWidth = window.innerWidth * 0.65; } else { computedWidth = opt.parentWidth * 0.65; } } computedHeight = computedWidth / ratio; computedHeight = Math.round(computedHeight); computedWidth = Math.round(computedWidth); opt.node.setAttribute('data-computedWidth', computedWidth); opt.node.setAttribute('data-computedHeight', computedHeight); return computedWidth; }, calH: function calH() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var desc = opt.node.getAttribute('data-desc') || ''; var type = opt.node.getAttribute('data-type') || 'video'; var computedHeight = opt.node.getAttribute('data-computedHeight') || ''; switch (type) { case 'live': return desc ? 152 : 116; case 'topic': return 201; case 'image': case 'video': return parseFloat(computedHeight); } }, getBorderRadius: function getBorderRadius() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var type = opt.node.getAttribute('data-type') || 'video'; if (type === 'video') { return 4; } return 8; }, replaceContentCssText: '', appendContentCssText: 'display:flex;margin:0px auto;', outerContainerLeft: '', outerContainerRight: '' }, { querySelector: 'mp-wxaproduct', genId: function genId() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return decodeURIComponent(opt.node.getAttribute('data-wxaproduct-productid') || ''); }, calW: function calW() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return opt.parentWidth * 1 || '100%'; }, calH: function calH() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var cardtype = opt.node.getAttribute('data-wxaproduct-cardtype') || ''; return cardtype === 'mini' ? 124 : 466; }, replaceContentCssText: '', outerContainerLeft: '', outerContainerRight: '' }, { querySelector: 'mpprofile', genId: function genId(opt) { return opt.node.getAttribute('data-id') || ''; }, calW: function calW() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return opt.parentWidth * 1; }, calH: function calH() { return 143; }, replaceContentCssText: '', appendContentCssText: 'diplay:block;', outerContainerLeft: '', outerContainerRight: '' }, { querySelector: 'mp-common-product:not([data-cardtype="2"])', genId: function genId(opt) { return opt.node.getAttribute('data-windowproduct') || ''; }, calW: function calW() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; if (opt.node.getAttribute('data-cardtype') === "0") { return Math.min(opt.parentWidth, 400) * 1 || '100%'; } return opt.parentWidth * 1 || '100%'; }, calH: function calH(opt) { var customstyle = opt.node.getAttribute('data-customstyle') || '{}'; if (customstyle) { try { var _JSON$parse = JSON.parse(customstyle), display = _JSON$parse.display, height = _JSON$parse.height; if (display !== 'none') { var customHeight = parseInt(height, 10); var ratio; if (opt.node.getAttribute('data-cardtype') === "0") { ratio = Math.min(400, opt.parentWidth) / 350.0 || 1; } else { ratio = opt.parentWidth / 350.0 || 1; } customHeight = Math.round(customHeight * ratio); return customHeight; } return 0; } catch (err) { console.error(err); } } return 0; }, replaceContentCssText: '', appendContentCssText: 'diplay:block;', outerContainerLeft: '<div style="display: flex; margin: 0 auto 24px;justify-content: center;">', outerContainerRight: '</div>' }, { querySelector: 'mpcps:not([data-templateid="video-play"]),mp-common-cpsad:not([data-templateid="video-play"])', genId: function genId(opt) { var node = opt.node; var planId = node.getAttribute('data-planid'); var goodId = node.getAttribute('data-pid'); var traceId = node.getAttribute('data-traceid'); return goodId || planId || traceId || ''; }, calW: function calW() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var node = opt.node; var templateId = node.getAttribute('data-templateid'); var adType = node.getAttribute('data-adtype'); var width = 0; if (templateId === 'list') { width = '100%'; } else if (templateId === 'card') { if (adType === AD_CONFIG.CPS_GOODS_TYPE.SHORT_PLAY || adType === AD_CONFIG.CPS_GOODS_TYPE.MINI_GAME) { width = opt.parentWidth ? opt.parentWidth * 0.65 : '100%'; } else { width = '100%'; } } return width; }, calH: function calH(opt) { var node = opt.node; var templateId = node.getAttribute('data-templateid'); var adType = node.getAttribute('data-adtype'); var height = 0; if (templateId === 'list') { if (adType === AD_CONFIG.CPS_GOODS_TYPE.MINI_GAME) { height = 79; } else { height = 120; } } else if (templateId === 'card') { if (adType === AD_CONFIG.CPS_GOODS_TYPE.SHORT_PLAY) { var width = opt.parentWidth * 0.65; height = Math.ceil(width * (4 / 3)) + 68; } else if (adType === AD_CONFIG.CPS_GOODS_TYPE.MINI_GAME) { var _width = opt.parentWidth * 0.65; height = Math.ceil(_width * (4 / 3)) + 64; } else { height = Math.ceil(opt.parentWidth + 111); } } return height; }, replaceContentCssText: '', appendContentCssText: 'diplay:block;', outerContainerLeft: '<div style="display: flex; justify-content: center">', outerContainerRight: '</div>' } ] }; function preloadingInit() { var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; if (typeof document.querySelectorAll !== 'function') { return; } var g = { maxWith: document.getElementById('img-content').getBoundingClientRect().width, idAttr: 'data-preloadingid' }; for (var i = 0, il = opt.config.length; i < il; i++) { var a = opt.config[i]; var list = document.querySelectorAll(a.querySelector); for (var j = 0, jl = list.length; j < jl; j++) { var node = list[j]; var parentWidth = node.parentNode.getBoundingClientRect().width; parentWidth = Math.min(parentWidth, g.maxWith); if (node.getAttribute('has-insert-preloading')) { continue; } var nodeW = a.calW({ parentWidth: parentWidth, node: node }); var nodeH = a.calH({ parentWidth: parentWidth, node: node }); var nodeId = a.genId({ index: j, node: node }); var nodeBorderRadius = typeof a.getBorderRadius === 'function' ? a.getBorderRadius({ index: j, node: node }) : 8; if (typeof nodeW === 'number') { nodeW += 'px'; } var imgHtml = opt.defaultContentTpl.replace(/#height#/g, nodeH).replace(/#width#/g, nodeW).replace(/#borderRadius#/g, nodeBorderRadius); var tmpNode = document.createElement('div'); tmpNode.innerHTML = imgHtml; if (a.replaceContentCssText) { var replaceContentCssText = a.replaceContentCssText.replace(/#height#/g, nodeH).replace(/#width#/g, nodeW); tmpNode.firstChild.style.cssText = replaceContentCssText; } else if (a.appendContentCssText) { tmpNode.firstChild.style.cssText += a.appendContentCssText; } var html = (a.outerContainerLeft || '') + tmpNode.innerHTML + (a.outerContainerRight || ''); tmpNode.innerHTML = html; tmpNode.firstChild.setAttribute(g.idAttr, nodeId); node.parentNode.insertBefore(tmpNode.firstChild, node.nextSibling); node.setAttribute('has-insert-preloading', '1'); } } } function init() { preloadingInit(g); } init(); })();</script> <script type="text/javascript" nonce="1989770072" reportloaderror> function htmlDecode(str) { return str .replace(/'/g, '\'') .replace(/<br\s*(\/)?\s*>/g, '\n') .replace(/ /g, ' ') .replace(/</g, '<') .replace(/>/g, '>') .replace(/"/g, '"') .replace(/&/g, '&') .replace(/ /g, ' '); } var uin = ''; var key = ''; var pass_ticket = ''; var new_appmsg = 1; var item_show_type = "0"; var real_item_show_type = "0"; var can_see_complaint = "0"; var tid = ""; var aid = ""; var clientversion = ""; var appuin = "" || "MzU0OTk3ODQ3Ng=="; var voiceid = ""; var create_time = "1743643844" * 1; var source = ""; var ascene = ""; var subscene = ""; var sessionid = "" || "svr_5fc3db74245"; var abtest_cookie = ""; var finder_biz_enter_id = "" * 1; var scene = 75; var itemidx = "" || ""; var appmsg_token = "" || ""; var _copyright_stat = "1"; var _ori_article_type = ""; var is_follow = ""; var nickname = htmlDecode("石杉的架构笔记"); var appmsg_type = "9"; var ct = "1743643844"; var user_name = "gh_6258c101a32a"; var fakeid = ""; var version = ""; var is_limit_user = "0"; var cps_article_data = ""; var round_head_img = "/upload/ac7ecb6e296202cc8a75f7993256decd.png"; var profile_signature = "一线大厂架构经验倾囊相授!"; var profile_signature_new = ""; var hd_head_img = "http://wx.qlogo.cn/mmhead/Q3auHgzwzM579hWFYlRZds9C3OXdbjfQeIxM7Svic6kP7YskDIVGQkg/0" || ""; var ori_head_img_url = "http://wx.qlogo.cn/mmhead/Q3auHgzwzM579hWFYlRZds9C3OXdbjfQeIxM7Svic6kP7YskDIVGQkg/132"; var msg_title = '震惊!用 Redis+AI 模型实现秒级实时风控,这波操作太秀了'.html(false); var msg_desc = htmlDecode(""); var msg_cdn_url = "https://mmbiz.qpic.cn/mmbiz_jpg/1J6IbIcPCLbPOV9sLvC7KdgGic4DpvbVe2Y95aaDWGYhjKA1Dxr7RUT58uEuk1MLGZAJWcwy3g6BZhAwzmBTt4g/0?wx_fmt=jpeg"; var cdn_url_1_1 = "https://mmbiz.qpic.cn/mmbiz_jpg/1J6IbIcPCLbPOV9sLvC7KdgGic4DpvbVexibehpBJel3H1FujV9j9Z1QRCApJb5cV9d0iaZdsX17ib7mtuWMMm9rSQ/0?wx_fmt=jpeg"; var cdn_url_235_1 = "https://mmbiz.qpic.cn/mmbiz_jpg/1J6IbIcPCLbPOV9sLvC7KdgGic4DpvbVe2Y95aaDWGYhjKA1Dxr7RUT58uEuk1MLGZAJWcwy3g6BZhAwzmBTt4g/0?wx_fmt=jpeg"; var msg_link = "https://mp.weixin.qq.com/s/3hbpQRAofG905lAt7Onq5g"; var user_uin = "" * 1; var msg_source_url = ''; var img_format = 'jpeg'; var srcid = ''; var req_id = '0309HjJfojOvcZCbK8cTrrZO'; var networkType; var appmsgid = "2247616950" || '' || ''; var comment_id = '3925979078456426516' || '0'; var mp_comment_id = "" || "" * 1; var comment_enabled = "" * 1; var open_fansmsg = "0" * 1; var is_https_res = ("" * 1) && (location.protocol == "https:"); var msg_daily_idx = "1" || ""; var profileReportInfo = "" || ""; var devicetype = ""; var source_encode_biz = ""; var source_username = ""; var reprint_ticket = ""; var source_mid = ""; var source_idx = ""; var source_biz = ""; var author = "儒猿团队"; var author_id = ""; var author_cancel = "" * 1 || 0; var reward_wording = ""; var extra_comment_id = '3925979090586353664' || '0'; var reward_author_head = ""; var reward_can_whisper = "" * 1 || 0; var reward_total_count = "" * 1 || 0; var optimizing_flag = "" * 1; var show_comment = ""; var __appmsgCgiData = { wxa_product: "" * 1, wxa_cps: "" * 1, show_msg_voice: "0" * 1, can_use_page: "" * 1, is_wxg_stuff_uin: "0" * 1, card_pos: "", copyright_stat: "1", source_biz: "", hd_head_img: "http://wx.qlogo.cn/mmhead/Q3auHgzwzM579hWFYlRZds9C3OXdbjfQeIxM7Svic6kP7YskDIVGQkg/0" || (window.location.protocol + "//" + window.location.host + "//res.wx.qq.com/mmbizappmsg/zh_CN/htmledition/js/images/pic/pic_rumor_link750ed3.jpg"), has_red_packet_cover: "0" * 1 || 0, minishopCardData: "" }; var _empty_v = "//res.wx.qq.com/mmbizappmsg/zh_CN/htmledition/js/audios/empty750ed3.mp3"; var publicTagInfo = [ ]; var appmsg_album_info = (function () { var curAlbumId = ''; for (var i = 0; i < publicTagInfo.length; i++) { if (curAlbumId) { if (curAlbumId === publicTagInfo[i].id) { return publicTagInfo[i]; } } else { if (publicTagInfo[i].continousReadOn) { return publicTagInfo[i]; } } } return {}; })(); var copyright_stat = "1" * 1; var hideSource = "" * 1; var pay_fee = "" * 1; var pay_timestamp = ""; var need_pay = "" * 1; var is_pay_subscribe = "0" * 1; var need_report_cost = "0" * 1; var use_tx_video_player = "0" * 1; var appmsg_fe_filter = "contenteditable"; var friend_read_source = "" || ""; var friend_read_version = "" || ""; var friend_read_class_id = "" || ""; var is_only_read = "1" * 1; var read_num = "" * 1; var read_num_new = '' * 1; var show_read_new = '' * 1; var like_num = "" * 1; var liked = "" == 'true' ? true : false; var is_temp_url = "" ? 1 : 0; var tempkey = ""; var send_time = ""; var icon_emotion_switch = "//res.wx.qq.com/mmbizappmsg/zh_CN/htmledition/js/images/icon/emotion/icon_emotion_switch750ed3.svg"; var icon_emotion_switch_active = "//res.wx.qq.com/mmbizappmsg/zh_CN/htmledition/js/images/icon/emotion/icon_emotion_switch_active750ed3.svg"; var icon_emotion_switch_primary = "//res.wx.qq.com/mmbizappmsg/zh_CN/htmledition/js/images/icon/emotion/icon_emotion_switch_primary750ed3.svg"; var icon_emotion_switch_active_primary = "//res.wx.qq.com/mmbizappmsg/zh_CN/htmledition/js/images/icon/emotion/icon_emotion_switch_active_primary750ed3.svg"; var icon_loading_white = "//res.wx.qq.com/mmbizappmsg/zh_CN/htmledition/js/images/icon/common/icon_loading_white750ed3.gif"; var icon_audio_unread = "//res.wx.qq.com/mmbizappmsg/zh_CN/htmledition/js/images/icon/audio/icon_audio_unread750ed3.png"; var icon_qqmusic_default = "//res.wx.qq.com/mmbizappmsg/zh_CN/htmledition/js/images/icon/audio/icon_qqmusic_default750ed3.png"; var icon_qqmusic_source = "//res.wx.qq.com/mmbizappmsg/zh_CN/htmledition/js/images/icon/audio/icon_qqmusic_source750ed3.svg"; var icon_kugou_source = "//res.wx.qq.com/mmbizappmsg/zh_CN/htmledition/js/images/icon/audio/icon_kugou_source750ed3.png"; var topic_default_img = '//res.wx.qq.com/mmbizappmsg/zh_CN/htmledition/js/images/pic/pic_book_thumb750ed3.png'; var comment_edit_icon = '//res.wx.qq.com/mmbizappmsg/zh_CN/htmledition/js/images/icon/common/icon_edit750ed3.png'; var comment_loading_img = '//res.wx.qq.com/mmbizappmsg/zh_CN/htmledition/js/images/icon/common/icon_loading_white750ed3.gif'; var comment_c2c_not_support_img = '//res.wx.qq.com/mmbizappmsg/zh_CN/htmledition/js/images/pic/pic_discuss_more750ed3.png'; var line_info = { }; var can_feedback = '' * 1; var yqj_info = { }; var frontend_exp_list = [ ]; var tts_is_ban = '' * 1 || 0; var tts_is_show = '' * 1 || 0; var tts_heard_person_cnt = '' * 1 || 0; var can_use_star = '' * 1 || 0;; var star_person_cnt = '' * 1 || 0; var voice_in_appmsg = { }; var voiceList = {}; voiceList={"voice_in_appmsg":[]} var reprint_style = '' * 1; var reprint_type = '' * 1; var wxa_img_alert = "" != 'false'; var weapp_sn_arr_json = "" || ""; var videoPageInfos = [ ]; window.__videoPageInfos = videoPageInfos; if ([1, 2].indexOf('0' * 1) !== -1) { var pageInfoList = []; for(var i = 0; i<videoPageInfos.length; i++){ if (videoPageInfos[i].mp_video_overseas_limit) { videoPageInfos[i].mp_video_trans_info = []; } pageInfoList.push(videoPageInfos[i]); } window.__videoPageInfos = pageInfoList; } var video_snap_json = "" || ""; var mp_profile = [ ]; var ban_scene = "0" * 1; var ban_jump_link = { }; var svr_time = "1743644973" * 1; var is_transfer_msg = "" * 1 || 0; var malicious_title_reason_id = "0" * 1; var malicious_content_type = "0" * 1; var modify_time = "" * 1; var modify_detail = []; var isprofileblock = "0"; var jumpInfo = [ ]; window.service_type = '0' * 1; var hasRelatedArticleInfo = '0' * 1 || 0; var relatedArticleFlag = '' * 1 || 0; var canUseAutoTypeSetting; canUseAutoTypeSetting = '3' * 1 || 0; var styleType = '3'; var originTypeSetting = ''; var originStyleType = ''; var reprintEditable = ''; var currentSvrStyleType, originSvrStyleType; if (!isNaN(parseInt(styleType)) && parseInt(styleType) > 0) { currentSvrStyleType = parseInt(styleType); } else if (!isNaN(parseInt(canUseAutoTypeSetting))) { currentSvrStyleType = parseInt(canUseAutoTypeSetting); } else { currentSvrStyleType = 0; } if (!isNaN(parseInt(originStyleType)) && parseInt(originStyleType) > 0) { originSvrStyleType = parseInt(originStyleType); } else if (!isNaN(parseInt(originTypeSetting))) { originSvrStyleType = parseInt(originTypeSetting); } else { originSvrStyleType = 0; } if (reprint_type > 0 && originSvrStyleType !== currentSvrStyleType && parseInt(reprintEditable) === 0) { var dc = document.getElementById('js_content').classList; dc.remove('autoTypeSetting'); dc.remove('autoTypeSetting24'); dc.remove('autoTypeSetting24psection'); var finalSetting = parseInt(originSvrStyleType); if (finalSetting === 1) { dc.add('autoTypeSetting'); } else if (finalSetting === 2) { dc.add('autoTypeSetting24'); } else if (finalSetting === 3) { dc.add('autoTypeSetting24psection'); } } window.wxtoken = "777"; window.is_login = '' * 1; var title = "石杉的架构笔记"; var is_new_msg = true; var is_wash = '' * 1; var topbarEnable = false; var enterid = "1743644973" * 1 || "1743644973" * 1 || "" * 1 || parseInt(Date.now() / 1000); var reloadid = '' * 1 || parseInt(Date.now() / 1000); var reloadseq = '' * 1 || 1; var miniprogram_appid = ""; var defaultAvatarUrl = '//res.wx.qq.com/mmbizappmsg/zh_CN/htmledition/js/images/icon/common/icon_avatar_default750ed3.svg'; document.addEventListener('DOMContentLoaded', function () { window.domCompleteTime = Date.now(); }); var hasRecommendMsg = 0; ; var isPayTopic = '' * 1; var payTopicPrice = '' * 1; var isRemovedFromPayTopic = '' * 1; var isPaySubscribe = '0' * 1; var isPaid = '0' * 1; var isRefund = '' * 1; var payShowIAPPrice = 1; var payProductId = '' || ''; var previewPercent = '0' || ''; var payGiftsCount = '0' * 1 || 0; var payDesc = htmlDecode(''); var payFreeGift = '' * 1 || 0; var is_finished_preview = 0; var jump2pay = '' * 1; var isFans; var can_reward = '0' * 1 || 0; var is_need_reward = (isPaySubscribe && !isPaid) ? 0 : "0" * 1; var rewardsn = ''; var rewardTimestamp = '' * 1 || 0; var is_teenager = '' * 1 || 0; var is_care_mode = '' * 1 || 0; var zhuge_user_limit = '' * 1 || 0; var segment_comment_id = '3925979091156779012'; var colorScheme = ''; var iapPriceInfo = { }; var productPayPackage = { iap_price_info: iapPriceInfo }; var isCartoonCopyright = '0' * 1; var show_msg_voice = '' * 1; var qnaCardData = ''; var exptype = '' || ''; var expsessionid = '' || ''; var goContentId = ''; var goReplyId = ''; var fromCommentShare = ''; var goAddedInfo = '' * 1; var goAddedInfoContentId = ''; var preload_comment_list = ''; var show_related_article = '' * 1; var wwdistype = ''; var refuteSourceUrl = ''; window.cgiData = { appImg: '//res.wx.qq.com/mmbizappmsg/zh_CN/htmledition/js/images/pic/pic_tencent_video750ed3.png', } window.ip_wording = { countryName: '中国', countryId: '156', provinceName: '江苏', provinceId: '', cityName: '', cityId: '' }; window.show_ip_wording = '1' * 1; window.source_appid = 'wx0f18d4b9ebb547af'; window.is_over_sea = '0' * 1; window.showAdMark = "0" * 1; window.isTitleModified = "" * 1; window.claim_source = { claim_source_type: '', claim_source: '', }; window.hideAdMarkOnCps = ("" || "0" * 1) ? 1 : 0; window.bar_version = '' * 1; window.appmsg_bar_data = { }; window.subcount_version = '' * 1; window.show_comment_bar = '' * 1; window.search_keywords = [ ]; window.s1s_keywords_exp_info = ''; var need_baike_preload = true; ; window.ad_keywords = [ ]; window.show_ad_keyword = 'false'; window.clear_desc_flag = "" * 1; window.mmlisten_playlist_info_buffer = ''; window.key_text = ''; window.merge_playlist_info_base64 = 'CgQxMDQwEBAYAiIM5pKt5pS+5YiX6KGoSAI='; window.star_playlist_info_base64 = 'CgQxMDM3EBAYAiIM5pKt5pS+5YiX6KGoSAI='; window.category_playlist_info_base64 = 'CgQxMDM1EBAYAiIJ56iN5ZCO5ZCsSAI='; if (window.isPaySubscribe) { function onWeixinJsBridgeReady() { window.WeixinJSBridge.invoke('hideMenuItems', { menuList: ['control:showButtonScreenShot'] }, function (res) {}); } if (typeof WeixinJSBridge === 'undefined') { if (document.addEventListener) { document.addEventListener('WeixinJSBridgeReady', onWeixinJsBridgeReady, false); } else if (document.attachEvent) { document.attachEvent('WeixinJSBridgeReady', onWeixinJsBridgeReady); document.attachEvent('onWeixinJSBridgeReady', onWeixinJsBridgeReady); } } else { onWeixinJsBridgeReady(); } } </script> <script type="text/javascript" nonce="1989770072" reportloaderror>var __INLINE_SCRIPT__ = (function () { 'use strict'; function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } var ua = navigator.userAgent; var is_ios = /(iPhone|iPad|iPod|iOS)/i.test(ua); var is_wp = /Windows\sPhone/i.test(ua); var is_android = /(Android)/i.test(ua); var is_wechat = /MicroMessenger\/([\d\.]+)/i.test(ua); var is_mac = /mac\sos/i.test(ua) && !is_ios; var is_windows = /windows\snt/i.test(ua) && !is_wp; var is_mpapp = /MPAPP\/([\d\.]+)/i.test(ua); var is_ipad = /iPad/i.test(ua); var is_windows_wechat = /WindowsWechat/i.test(ua); var is_mac_wechat = /MacWechat/i.test(ua) || /wechat.*mac os/i.test(ua); var is_prefetch = is_wechat && window.WeixinPrefecherJSBridge; var is_donut_app = /SAAASDK/i.test(ua); var is_harmony = /OpenHarmony|ArkWeb/i.test(ua); var is_in_miniProgram = is_android && /miniprogram/.test(ua.toLowerCase()) || window.__wxjs_environment == 'miniprogram'; var is_wx_work = /wxwork/i.test(ua); function getUrlParams() { var vars = location.search.substring(1).split('&'); var params = {}; var _iterator = _createForOfIteratorHelper(vars), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var ele = _step.value; var pair = ele.split('='); var key = decodeURIComponent(pair[0]); if (typeof params[key] === 'undefined') { params[key] = decodeURIComponent(pair[1]); } } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } return params; } function get() { var reg = /MicroMessenger\/([\d\.]+)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1]; } return false; } function getMac() { var reg = /MacWechat\/([\d\.]+)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1]; } return false; } function getMacOS() { var reg = /Mac OS X ([\d_]+)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1].replace(/_/g, '.'); } return false; } function getWindows() { var reg = /WindowsWechat\(0x(.+?)\)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1]; } return false; } function getWxWork() { var reg = /wxwork\/([\d\.]+)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1]; } return false; } function getMpApp() { var appVersion = [2, 4, 5]; var match = navigator.userAgent.match(/MPAPP\/(\d+(\.\d+)*)/); if (match) { appVersion = match[1].split('.').map(function (v) { return Number(v); }); } return appVersion.join('.'); } function getUnifiedPcVer() { var versionInfo = navigator.userAgent.match(/UnifiedPC\w+Wechat\(0xf\w{2}(\w+?)\w{2}\)/); if (versionInfo && versionInfo.length === 2) { var version = versionInfo[1]; var mainVersion = getVersionNumber(version.slice(0, 1)); var subVersion = getVersionNumber(version.slice(1, 2)); var subVersion2 = getVersionNumber(version.slice(2, 3)); return [mainVersion, subVersion, subVersion2].join('.'); } } function getVersionNumber(hexStr) { return Number(Number("0x".concat(hexStr)).toString(10)); } function getWindowsVersionFormat() { var versionInfo = navigator.userAgent.match(/WindowsWechat\(0x(\w+?)\)/); if (versionInfo && versionInfo.length === 2) { var version = versionInfo[1]; var mainVersion = getVersionNumber(version.slice(1, 2)); var subVersion = getVersionNumber(version.slice(2, 4)); var subVersion2 = getVersionNumber(version.slice(4, 6)); return [mainVersion, subVersion, subVersion2].join('.'); } return false; } function getInner() { var reg = /MicroMessenger\/[\d\.]+\(0x(.+?)\)/i; var ret = ua.match(reg); if (ret && ret[1] && ret[1] != null) { return ret[1]; } if (!ret && /MicroMessenger\/[\d\.]+/i.test(ua)) { var urlParams = getUrlParams(); if (urlParams.version) { return urlParams.version; } } return false; } var opfunc = { 'cp-1': function cp1(a, b) { return a < b; }, cp0: function cp0(a, b) { return a === b; }, cp1: function cp1(a, b) { return a > b; } }; function cpVersion(ver, op, canEq, type) { var mmver = false; switch (type) { case 'mac': mmver = getMac(); break; case 'windows': mmver = getWindowsVersionFormat(); break; case 'wxwork': mmver = getWxWork(); break; case 'mpapp': mmver = getMpApp(); break; case 'unifiedpc': mmver = getUnifiedPcVer(); break; default: mmver = get(); break; } if (!mmver) { return; } var mmversion = mmver.split('.'); var version = ver.split('.'); if (!/\d+/g.test(mmversion[mmversion.length - 1])) { mmversion.pop(); } for (var i = 0, len = Math.max(mmversion.length, version.length); i < len; ++i) { var mmv = mmversion[i] || ''; var v = version[i] || ''; var mmvn = parseInt(mmv, 10) || 0; var vn = parseInt(v, 10) || 0; var eq = opfunc.cp0(mmvn, vn); if (eq) { continue; } var cp = opfunc["cp".concat(op)]; return cp(mmvn, vn); } return canEq || op === 0; } function eqVersion(version) { return cpVersion(version, 0); } function gtVersion(version, canEq) { return cpVersion(version, 1, canEq); } function ltVersion(version, canEq) { return cpVersion(version, -1, canEq); } function getPlatform() { if (is_ios) { return 'ios'; } if (is_android) { return 'android'; } if (is_mac) { return 'mac_os'; } if (is_windows) { return 'windows'; } return 'unknown'; } var is_google_play = false; var inner_ver_for_google_play_check = getInner(); if (is_android && inner_ver_for_google_play_check) { var v = "0x".concat(inner_ver_for_google_play_check.substr(-2)); if (parseInt(v) >= 64 && parseInt(v) <= 79) { is_google_play = true; } } ({ get: get, getMac: getMac, getMacOS: getMacOS, getWindows: getWindows, getInner: getInner, getWxWork: getWxWork, getMpApp: getMpApp, cpVersion: cpVersion, eqVersion: eqVersion, gtVersion: gtVersion, ltVersion: ltVersion, getPlatform: getPlatform, getVersionNumber: getVersionNumber, isWp: is_wp, isIOS: is_ios, isAndroid: is_android, isHarmony: is_harmony, isHarmonyWechat: is_harmony && is_wechat && cpVersion('1.0.0', 1, true), isInMiniProgram: is_in_miniProgram, isWechat: is_wechat, isMac: is_mac, isWindows: is_windows, isMacWechat: is_mac_wechat, isWindowsWechat: is_windows_wechat, isWxWork: is_wx_work, isOnlyWechat: is_wechat && !is_wx_work, isMpapp: is_mpapp, isNewMpApp: false, isIPad: is_ipad, isGooglePlay: is_google_play, isPrefetch: is_prefetch, isDonutAPP: is_donut_app }); if (!window.JSAPIEventCallbackMap) { window.JSAPIEventCallbackMap = {}; } var doc = {}; try { doc = top.window.document; } catch (e) { } if (!window.JSAPIEventCallbackMap) { window.JSAPIEventCallbackMap = {}; } var setImmersiveMode = function setImmersiveMode(itemShowType) { var envStr = window.__wxWebEnv && typeof window.__wxWebEnv.getEnv === 'function' && window.__wxWebEnv.getEnv(); if (!envStr) return; var envObj = {}; if (!envStr) return; try { envObj = JSON.parse(envStr); } catch (err) { console.info(err); } var immersiveListMode = envObj.immersiveListMode || 0; window.__immersiveListMode = Number(immersiveListMode) === 1 ? 1 : 0; window.__test_immersive_list = 0; if (window.__test_immersive_list) { window.__immersiveListMode = 1; } var wxExpandArticleEle = document.getElementById('wx_expand_article'); document.getElementById('js_article'); var bottomLoadingTip = document.getElementById('js_network_msg_wrp'); if (!itemShowType && itemShowType !== 0) { itemShowType = window.item_show_type; } itemShowType = Number(itemShowType); if (window.__immersiveListMode) { try { var immersiveSafeBottom = localStorage.getItem('__immersivefeed_safe_bottom__'); if (immersiveSafeBottom) { document.documentElement.style.setProperty('--immersive-safe-bottom', immersiveSafeBottom); } } catch (error) { console.log(error); } if (wxExpandArticleEle) { wxExpandArticleEle.style.display = 'block'; } if (bottomLoadingTip) { bottomLoadingTip.style.display = 'none'; } if (itemShowType === 10 || itemShowType === 7) { document.body.classList.add('ellapse_short_content'); } else { document.body.classList.add('ellapse_stream_article'); } if (itemShowType === 0) { document.body.classList.add('article_extensive_background'); } else { document.body.classList.add('media_content_extensive_background'); } var interactionPlaceholderEle = document.getElementById('js_interaction_placeholder'); if (interactionPlaceholderEle) { interactionPlaceholderEle.style.display = 'block'; } } }; if (!window.__second_open__) { setImmersiveMode(); } return setImmersiveMode; })();</script><script type="text/javascript" nonce="1989770072" reportloaderror>var __INLINE_SCRIPT__ = (function () { 'use strict'; function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); } function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } var ua = navigator.userAgent; var is_ios = /(iPhone|iPad|iPod|iOS)/i.test(ua); var is_wp = /Windows\sPhone/i.test(ua); var is_android = /(Android)/i.test(ua); var is_wechat = /MicroMessenger\/([\d\.]+)/i.test(ua); var is_mac = /mac\sos/i.test(ua) && !is_ios; var is_windows = /windows\snt/i.test(ua) && !is_wp; var is_mpapp = /MPAPP\/([\d\.]+)/i.test(ua); var is_ipad = /iPad/i.test(ua); var is_windows_wechat = /WindowsWechat/i.test(ua); var is_mac_wechat = /MacWechat/i.test(ua) || /wechat.*mac os/i.test(ua); var is_prefetch = is_wechat && window.WeixinPrefecherJSBridge; var is_donut_app = /SAAASDK/i.test(ua); var is_harmony = /OpenHarmony|ArkWeb/i.test(ua); var is_in_miniProgram = is_android && /miniprogram/.test(ua.toLowerCase()) || window.__wxjs_environment == 'miniprogram'; var is_wx_work = /wxwork/i.test(ua); function getUrlParams() { var vars = location.search.substring(1).split('&'); var params = {}; var _iterator = _createForOfIteratorHelper(vars), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var ele = _step.value; var pair = ele.split('='); var key = decodeURIComponent(pair[0]); if (typeof params[key] === 'undefined') { params[key] = decodeURIComponent(pair[1]); } } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } return params; } function get() { var reg = /MicroMessenger\/([\d\.]+)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1]; } return false; } function getMac() { var reg = /MacWechat\/([\d\.]+)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1]; } return false; } function getMacOS() { var reg = /Mac OS X ([\d_]+)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1].replace(/_/g, '.'); } return false; } function getWindows() { var reg = /WindowsWechat\(0x(.+?)\)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1]; } return false; } function getWxWork() { var reg = /wxwork\/([\d\.]+)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1]; } return false; } function getMpApp() { var appVersion = [2, 4, 5]; var match = navigator.userAgent.match(/MPAPP\/(\d+(\.\d+)*)/); if (match) { appVersion = match[1].split('.').map(function (v) { return Number(v); }); } return appVersion.join('.'); } function getUnifiedPcVer() { var versionInfo = navigator.userAgent.match(/UnifiedPC\w+Wechat\(0xf\w{2}(\w+?)\w{2}\)/); if (versionInfo && versionInfo.length === 2) { var version = versionInfo[1]; var mainVersion = getVersionNumber(version.slice(0, 1)); var subVersion = getVersionNumber(version.slice(1, 2)); var subVersion2 = getVersionNumber(version.slice(2, 3)); return [mainVersion, subVersion, subVersion2].join('.'); } } function getVersionNumber(hexStr) { return Number(Number("0x".concat(hexStr)).toString(10)); } function getWindowsVersionFormat() { var versionInfo = navigator.userAgent.match(/WindowsWechat\(0x(\w+?)\)/); if (versionInfo && versionInfo.length === 2) { var version = versionInfo[1]; var mainVersion = getVersionNumber(version.slice(1, 2)); var subVersion = getVersionNumber(version.slice(2, 4)); var subVersion2 = getVersionNumber(version.slice(4, 6)); return [mainVersion, subVersion, subVersion2].join('.'); } return false; } function getInner() { var reg = /MicroMessenger\/[\d\.]+\(0x(.+?)\)/i; var ret = ua.match(reg); if (ret && ret[1] && ret[1] != null) { return ret[1]; } if (!ret && /MicroMessenger\/[\d\.]+/i.test(ua)) { var urlParams = getUrlParams(); if (urlParams.version) { return urlParams.version; } } return false; } var opfunc = { 'cp-1': function cp1(a, b) { return a < b; }, cp0: function cp0(a, b) { return a === b; }, cp1: function cp1(a, b) { return a > b; } }; function cpVersion(ver, op, canEq, type) { var mmver = false; switch (type) { case 'mac': mmver = getMac(); break; case 'windows': mmver = getWindowsVersionFormat(); break; case 'wxwork': mmver = getWxWork(); break; case 'mpapp': mmver = getMpApp(); break; case 'unifiedpc': mmver = getUnifiedPcVer(); break; default: mmver = get(); break; } if (!mmver) { return; } var mmversion = mmver.split('.'); var version = ver.split('.'); if (!/\d+/g.test(mmversion[mmversion.length - 1])) { mmversion.pop(); } for (var i = 0, len = Math.max(mmversion.length, version.length); i < len; ++i) { var mmv = mmversion[i] || ''; var v = version[i] || ''; var mmvn = parseInt(mmv, 10) || 0; var vn = parseInt(v, 10) || 0; var eq = opfunc.cp0(mmvn, vn); if (eq) { continue; } var cp = opfunc["cp".concat(op)]; return cp(mmvn, vn); } return canEq || op === 0; } function eqVersion(version) { return cpVersion(version, 0); } function gtVersion(version, canEq) { return cpVersion(version, 1, canEq); } function ltVersion(version, canEq) { return cpVersion(version, -1, canEq); } function getPlatform() { if (is_ios) { return 'ios'; } if (is_android) { return 'android'; } if (is_mac) { return 'mac_os'; } if (is_windows) { return 'windows'; } return 'unknown'; } var is_google_play = false; var inner_ver_for_google_play_check = getInner(); if (is_android && inner_ver_for_google_play_check) { var v = "0x".concat(inner_ver_for_google_play_check.substr(-2)); if (parseInt(v) >= 64 && parseInt(v) <= 79) { is_google_play = true; } } ({ get: get, getMac: getMac, getMacOS: getMacOS, getWindows: getWindows, getInner: getInner, getWxWork: getWxWork, getMpApp: getMpApp, cpVersion: cpVersion, eqVersion: eqVersion, gtVersion: gtVersion, ltVersion: ltVersion, getPlatform: getPlatform, getVersionNumber: getVersionNumber, isWp: is_wp, isIOS: is_ios, isAndroid: is_android, isHarmony: is_harmony, isHarmonyWechat: is_harmony && is_wechat && cpVersion('1.0.0', 1, true), isInMiniProgram: is_in_miniProgram, isWechat: is_wechat, isMac: is_mac, isWindows: is_windows, isMacWechat: is_mac_wechat, isWindowsWechat: is_windows_wechat, isWxWork: is_wx_work, isOnlyWechat: is_wechat && !is_wx_work, isMpapp: is_mpapp, isNewMpApp: false, isIPad: is_ipad, isGooglePlay: is_google_play, isPrefetch: is_prefetch, isDonutAPP: is_donut_app }); if (!window.JSAPIEventCallbackMap) { window.JSAPIEventCallbackMap = {}; } var doc = {}; var isAcrossOrigin = false; var __moon_report = window.__moon_report || function () {}; var MOON_JSAPI_KEY_OFFSET = 8; try { doc = top.window.document; } catch (e) { isAcrossOrigin = true; } if (!window.JSAPIEventCallbackMap) { window.JSAPIEventCallbackMap = {}; } function ready(onBridgeReady) { var bridgeReady = function bridgeReady() { try { if (onBridgeReady) { window.onBridgeReadyTime = window.onBridgeReadyTime || Date.now(); onBridgeReady(); } } catch (e) { __moon_report([{ offset: MOON_JSAPI_KEY_OFFSET, log: 'ready', e: e }]); throw e; } window.jsapiReadyTime = Date.now(); }; if (!isAcrossOrigin && (typeof top.window.WeixinJSBridge === 'undefined' || !top.window.WeixinJSBridge.invoke)) { if (doc.addEventListener) { doc.addEventListener('WeixinJSBridgeReady', bridgeReady, false); } else if (doc.attachEvent) { doc.attachEvent('WeixinJSBridgeReady', bridgeReady); doc.attachEvent('onWeixinJSBridgeReady', bridgeReady); } } else { bridgeReady(); } } function invoke(methodName, args, callback) { if (window.__second_open_wait_a8key__ && window.__second_open_wait_a8key_task__) { window.__second_open_wait_a8key_task__.push(function () { invoke(methodName, args, callback); }); return; } ready(function () { if (isAcrossOrigin) return false; if (_typeof(top.window.WeixinJSBridge) !== 'object') { alert('请在微信中打开此链接'); return false; } top.window.WeixinJSBridge.invoke(methodName, args, function () { try { for (var _len = arguments.length, rets = new Array(_len), _key = 0; _key < _len; _key++) { rets[_key] = arguments[_key]; } var ret = rets[0]; var errMsg = ret && ret.err_msg ? ", err_msg-> ".concat(ret.err_msg) : ''; console.info('[system]', "[jsapi] invoke->".concat(methodName).concat(errMsg)); if (callback) { callback.apply(window, rets); } } catch (e) { __moon_report([{ offset: MOON_JSAPI_KEY_OFFSET, log: "invoke;methodName:".concat(methodName), e: e }]); throw e; } }); }); } function call(methodName) { if (window.__second_open_wait_a8key__ && window.__second_open_wait_a8key_task__) { window.__second_open_wait_a8key_task__.push(function () { call(methodName); }); return; } ready(function () { if (isAcrossOrigin) return false; if (_typeof(top.window.WeixinJSBridge) !== 'object') { return false; } try { top.window.WeixinJSBridge.call(methodName); } catch (e) { __moon_report([{ offset: MOON_JSAPI_KEY_OFFSET, log: "call;methodName:".concat(methodName), e: e }]); throw e; } }); } function on(eventName, callback) { if (window.__second_open_wait_a8key__ && window.__second_open_wait_a8key_task__) { window.__second_open_wait_a8key_task__.push(function () { on(eventName, callback); }); return; } ready(function () { if (isAcrossOrigin) return false; if (_typeof(top.window.WeixinJSBridge) !== 'object' || !top.window.WeixinJSBridge.on) { return false; } if (!window.JSAPIEventCallbackMap[eventName]) { window.JSAPIEventCallbackMap[eventName] = []; } window.JSAPIEventCallbackMap[eventName].push(callback); if (window.JSAPIEventCallbackMap[eventName].length > 1) { return false; } top.window.WeixinJSBridge.on(eventName, function () { try { for (var _len2 = arguments.length, rets = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { rets[_key2] = arguments[_key2]; } var ret = rets[0]; var errMsg = ret && ret.err_msg ? ", err_msg-> ".concat(ret.err_msg) : ''; console.info('[system]', "[jsapi] event->".concat(eventName).concat(errMsg)); if (window.JSAPIEventCallbackMap[eventName] && window.JSAPIEventCallbackMap[eventName].length) { var result; for (var i = 0; i < window.JSAPIEventCallbackMap[eventName].length; i++) { result = window.JSAPIEventCallbackMap[eventName][i].apply(window, rets); } return result; } } catch (e) { __moon_report([{ offset: MOON_JSAPI_KEY_OFFSET, log: "on;eventName:".concat(eventName), e: e }]); throw e; } }); }); } function remove(eventName, callback) { if (window.__second_open_wait_a8key__ && window.__second_open_wait_a8key_task__) { window.__second_open_wait_a8key_task__.push(function () { remove(eventName, callback); }); return; } ready(function () { if (!window.JSAPIEventCallbackMap[eventName]) { return false; } var result = false; for (var i = window.JSAPIEventCallbackMap[eventName].length - 1; i >= 0; i--) { if (window.JSAPIEventCallbackMap[eventName][i] === callback) { window.JSAPIEventCallbackMap[eventName].splice(i, 1); result = true; } } return result; }); } var JSAPI = { ready: ready, invoke: invoke, call: call, on: on, remove: remove }; function initBodyStyle() { window.scrollTo({ top: 0, behavior: 'smooth' }); setTimeout(function () { document.body.scrollTop = document.documentElement.scrollTop = 0; document.body.style.overflow = 'hidden'; }, 100); } var setRowImmersiveMode = function setRowImmersiveMode(itemShowType) { var envStr = window.__wxWebEnv && typeof window.__wxWebEnv.getEnv === 'function' && window.__wxWebEnv.getEnv(); if (!envStr) return; var envObj = {}; try { envObj = JSON.parse(envStr); } catch (err) { console.info(err); } var immersiveListMode = envObj.immersiveListMode || 0; window.__immersiveListMode = Number(immersiveListMode) === 1 ? 1 : 0; window.__rowImmersiveStream = Number(immersiveListMode) === 2 ? 1 : 0; console.log("iiiiiiimmersiveListMode", immersiveListMode, window.__immersiveListMode, window.__rowImmersiveStream); window.__test_row_immersive_list = 0; if (window.__test_row_immersive_list) { window.__rowImmersiveStream = 1; } if (window.__rowImmersiveStream) { initBodyStyle(); var rowImmersiveStreamWrap = document.getElementById('js_row_immersive_stream_wrap'); if (rowImmersiveStreamWrap) { rowImmersiveStreamWrap.style.display = 'block'; } var bottomBar = document.getElementById('js_article_bottom_bar'); if (bottomBar) { bottomBar.classList.add('row_immersive_bottom_bar'); } var immersiveStreamMask = document.getElementById('js_row_immersive_stream_mask'); var enterBigWebview = function enterBigWebview() { immersiveStreamMask.style.display = 'none'; document.body.style.overflow = 'auto'; if (bottomBar) { bottomBar.classList.add('row_immersive_bigview_bottom_bar'); } }; var exitBigWebview = function exitBigWebview() { initBodyStyle(); immersiveStreamMask.style.display = 'block'; if (bottomBar) { bottomBar.classList.remove('row_immersive_bigview_bottom_bar'); } }; immersiveStreamMask.addEventListener('click', function (e) { e.preventDefault(); e.stopPropagation(); JSAPI.invoke('handleImmersiveStream', { action: 'enterFullArticle', params: { enterTime: Date.now() } }, function (res) { console.log("[immersive] handleImmersiveStream:", res); if (res && res.err_msg && res.err_msg.includes('ok')) { enterBigWebview(); } if (window.__test_row_immersive_list) { setTimeout(function () { console.log("xxxxx ok"); enterBigWebview(); }, 2000); } }); }); JSAPI.on('immersiveStreamExposeArticle', function (res) { console.log("[immersive] immersiveStreamExposeArticle", res); }); JSAPI.on('immersiveStreamExitFullArticle', function (res) { console.log("[immersive] immersiveStreamExitFullArticle", res); exitBigWebview(); }); JSAPI.on('immersiveStreamEnterFullArticle', function (res) { console.log("[immersive] immersiveStreamEnterFullArticle", res); enterBigWebview(); }); JSAPI.on('immersiveStreamSlideOutArticle', function (res) { console.log("[immersive] immersiveStreamSlideOutArticle", res); exitBigWebview(); }); } }; if (!window.__second_open__) { setRowImmersiveMode(); } return setRowImmersiveMode; })();</script><script type="text/javascript" nonce="1989770072" reportloaderror>var __INLINE_SCRIPT__ = (function () { 'use strict'; var getIpWoridng = function getIpWoridng(ipConfig) { var ipWording = ''; if (parseInt(ipConfig.countryId, 10) === 156) { ipWording = ipConfig.provinceName; } else if (ipConfig.countryId) { ipWording = ipConfig.countryName; } return ipWording; }; var __setIpWording = function __setIpWording(ipConfig, userInfo, itemShowType) { var ipWrp = document.getElementById('js_ip_wording_wrp'); var ipWording = document.getElementById('js_ip_wording'); if (ipConfig) { window.ip_wording = { countryName: ipConfig.country_name, countryId: ipConfig.country_id, provinceName: ipConfig.province_name }; } if (userInfo && userInfo.isoversea) { window.is_over_sea = parseInt(userInfo.isoversea, 10); } if (window.ip_wording && ipWrp && ipWording && window.is_over_sea !== 1) { var ipWordingDisplay = getIpWoridng(window.ip_wording); if (ipWordingDisplay !== '') { ipWording.innerHTML = ipWordingDisplay; ipWrp.style.display = 'inline-block'; } } if (+itemShowType === 0) ipWrp && ipWrp.style.display == 'none' && ipWrp.parentNode.removeChild(ipWrp); }; if (!window.__second_open__) { var itemShowType = window.a_value_which_never_exists || '0'; __setIpWording(undefined, undefined, itemShowType); window.__setIpWording = __setIpWording; } return __setIpWording; })();</script><script type="text/javascript" nonce="1989770072" reportloaderror>var __INLINE_SCRIPT__ = (function () { 'use strict'; var __setTitleModify = function __setTitleModify(isTitleModified) { var wrp = document.getElementById('js_title_modify_wrp'); var titleModifyNode = document.getElementById('js_title_modify'); if (!wrp) return; if (isTitleModified || window.isTitleModified) { titleModifyNode.innerHTML = '标题已修改'; wrp.style.display = 'inline-block'; } else { wrp.parentNode.removeChild(wrp); } }; if (!window.__second_open__) { __setTitleModify(); window.__setTitleModify = __setTitleModify; } return __setTitleModify; })();</script><script type="text/javascript" nonce="1989770072" reportloaderror>var __INLINE_SCRIPT__ = (function () { 'use strict'; var dealLikeReadShow_en = function dealLikeReadShow_en(realNum) { if (typeof LANG === 'undefined' || !window.LANG) { return parseInt(realNum) === 0 ? '' : realNum; } if (window.LANG == 'en') { var showHTML = ''; if (parseInt(realNum) > 100000) { showHTML = 100 + 'k+'; } else if (parseInt(realNum) > 10000 && parseInt(realNum) <= 100000) { var num = '' + parseInt(realNum) / 1000; var dotIndex = num.indexOf('.'); if (dotIndex === -1) { showHTML = num + 'k'; } else { showHTML = num.substring(0, dotIndex) + '.' + num.charAt(dotIndex + 1) + 'k'; } } else if (parseInt(realNum) === 0) { showHTML = ''; } else { showHTML = realNum; } return showHTML; } return ''; }; var i18n = { dealLikeReadShow_en: dealLikeReadShow_en }; function getWordCount (dom) { if (!dom) return 0; var textContet = dom.textContent || ''; var fillCharReg = new RegExp("\u200B", 'g'); var bookmarkFillCharReg = new RegExp("\u200D", 'g'); return textContet.replace(fillCharReg, '') .replace(bookmarkFillCharReg, '') .replace(/(\b|^)\w+(\b|$)/g, '#') .replace(/\s/g, '') .length; } function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } var ua = navigator.userAgent; var is_ios = /(iPhone|iPad|iPod|iOS)/i.test(ua); var is_wp = /Windows\sPhone/i.test(ua); var is_android = /(Android)/i.test(ua); var is_wechat = /MicroMessenger\/([\d\.]+)/i.test(ua); var is_mac = /mac\sos/i.test(ua) && !is_ios; var is_windows = /windows\snt/i.test(ua) && !is_wp; var is_mpapp = /MPAPP\/([\d\.]+)/i.test(ua); var is_ipad = /iPad/i.test(ua); var is_windows_wechat = /WindowsWechat/i.test(ua); var is_mac_wechat = /MacWechat/i.test(ua) || /wechat.*mac os/i.test(ua); var is_prefetch = is_wechat && window.WeixinPrefecherJSBridge; var is_donut_app = /SAAASDK/i.test(ua); var is_harmony = /OpenHarmony|ArkWeb/i.test(ua); var is_in_miniProgram = is_android && /miniprogram/.test(ua.toLowerCase()) || window.__wxjs_environment == 'miniprogram'; var is_wx_work = /wxwork/i.test(ua); function getUrlParams() { var vars = location.search.substring(1).split('&'); var params = {}; var _iterator = _createForOfIteratorHelper(vars), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var ele = _step.value; var pair = ele.split('='); var key = decodeURIComponent(pair[0]); if (typeof params[key] === 'undefined') { params[key] = decodeURIComponent(pair[1]); } } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } return params; } function get() { var reg = /MicroMessenger\/([\d\.]+)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1]; } return false; } function getMac() { var reg = /MacWechat\/([\d\.]+)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1]; } return false; } function getMacOS() { var reg = /Mac OS X ([\d_]+)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1].replace(/_/g, '.'); } return false; } function getWindows() { var reg = /WindowsWechat\(0x(.+?)\)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1]; } return false; } function getWxWork() { var reg = /wxwork\/([\d\.]+)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1]; } return false; } function getMpApp() { var appVersion = [2, 4, 5]; var match = navigator.userAgent.match(/MPAPP\/(\d+(\.\d+)*)/); if (match) { appVersion = match[1].split('.').map(function (v) { return Number(v); }); } return appVersion.join('.'); } function getUnifiedPcVer() { var versionInfo = navigator.userAgent.match(/UnifiedPC\w+Wechat\(0xf\w{2}(\w+?)\w{2}\)/); if (versionInfo && versionInfo.length === 2) { var version = versionInfo[1]; var mainVersion = getVersionNumber(version.slice(0, 1)); var subVersion = getVersionNumber(version.slice(1, 2)); var subVersion2 = getVersionNumber(version.slice(2, 3)); return [mainVersion, subVersion, subVersion2].join('.'); } } function getVersionNumber(hexStr) { return Number(Number("0x".concat(hexStr)).toString(10)); } function getWindowsVersionFormat() { var versionInfo = navigator.userAgent.match(/WindowsWechat\(0x(\w+?)\)/); if (versionInfo && versionInfo.length === 2) { var version = versionInfo[1]; var mainVersion = getVersionNumber(version.slice(1, 2)); var subVersion = getVersionNumber(version.slice(2, 4)); var subVersion2 = getVersionNumber(version.slice(4, 6)); return [mainVersion, subVersion, subVersion2].join('.'); } return false; } function getInner$1() { var reg = /MicroMessenger\/[\d\.]+\(0x(.+?)\)/i; var ret = ua.match(reg); if (ret && ret[1] && ret[1] != null) { return ret[1]; } if (!ret && /MicroMessenger\/[\d\.]+/i.test(ua)) { var urlParams = getUrlParams(); if (urlParams.version) { return urlParams.version; } } return false; } var opfunc = { 'cp-1': function cp1(a, b) { return a < b; }, cp0: function cp0(a, b) { return a === b; }, cp1: function cp1(a, b) { return a > b; } }; function cpVersion(ver, op, canEq, type) { var mmver = false; switch (type) { case 'mac': mmver = getMac(); break; case 'windows': mmver = getWindowsVersionFormat(); break; case 'wxwork': mmver = getWxWork(); break; case 'mpapp': mmver = getMpApp(); break; case 'unifiedpc': mmver = getUnifiedPcVer(); break; default: mmver = get(); break; } if (!mmver) { return; } var mmversion = mmver.split('.'); var version = ver.split('.'); if (!/\d+/g.test(mmversion[mmversion.length - 1])) { mmversion.pop(); } for (var i = 0, len = Math.max(mmversion.length, version.length); i < len; ++i) { var mmv = mmversion[i] || ''; var v = version[i] || ''; var mmvn = parseInt(mmv, 10) || 0; var vn = parseInt(v, 10) || 0; var eq = opfunc.cp0(mmvn, vn); if (eq) { continue; } var cp = opfunc["cp".concat(op)]; return cp(mmvn, vn); } return canEq || op === 0; } function eqVersion(version) { return cpVersion(version, 0); } function gtVersion(version, canEq) { return cpVersion(version, 1, canEq); } function ltVersion(version, canEq) { return cpVersion(version, -1, canEq); } function getPlatform() { if (is_ios) { return 'ios'; } if (is_android) { return 'android'; } if (is_mac) { return 'mac_os'; } if (is_windows) { return 'windows'; } return 'unknown'; } var is_google_play = false; var inner_ver_for_google_play_check = getInner$1(); if (is_android && inner_ver_for_google_play_check) { var v = "0x".concat(inner_ver_for_google_play_check.substr(-2)); if (parseInt(v) >= 64 && parseInt(v) <= 79) { is_google_play = true; } } var mmVersion = { get: get, getMac: getMac, getMacOS: getMacOS, getWindows: getWindows, getInner: getInner$1, getWxWork: getWxWork, getMpApp: getMpApp, cpVersion: cpVersion, eqVersion: eqVersion, gtVersion: gtVersion, ltVersion: ltVersion, getPlatform: getPlatform, getVersionNumber: getVersionNumber, isWp: is_wp, isIOS: is_ios, isAndroid: is_android, isHarmony: is_harmony, isHarmonyWechat: is_harmony && is_wechat && cpVersion('1.0.0', 1, true), isInMiniProgram: is_in_miniProgram, isWechat: is_wechat, isMac: is_mac, isWindows: is_windows, isMacWechat: is_mac_wechat, isWindowsWechat: is_windows_wechat, isWxWork: is_wx_work, isOnlyWechat: is_wechat && !is_wx_work, isMpapp: is_mpapp, isNewMpApp: false, isIPad: is_ipad, isGooglePlay: is_google_play, isPrefetch: is_prefetch, isDonutAPP: is_donut_app }; var isIOS = mmVersion.isIOS, getInner = mmVersion.getInner, isAndroid = mmVersion.isAndroid; var formatReadNum = function formatReadNum(value) { if (window.LANG === 'en') { return i18n.dealLikeReadShow_en(value); } var result = ''; if (parseInt(value, 10) > 100000) { result = '10万+'; } else if (parseInt(value, 10) > 10000 && parseInt(value, 10) <= 100000) { var num = '' + parseInt(value, 10) / 10000; var dotIndex = num.indexOf('.'); if (dotIndex === -1) { result = num + '万'; } else { result = num.substr(0, dotIndex) + '.' + num.charAt(dotIndex + 1) + '万'; } } else if (parseInt(value, 10) === 0) { result = ''; } else { result = value || ''; } return result; }; var __setTingHeard = function __setTingHeard(container, dom, cnt, isTempUrl) { var articleWordCnt = getWordCount(container || document.querySelector('#js_content')); window.article_word_cnt = articleWordCnt; if (!dom || articleWordCnt <= 100 || isTempUrl) { dom && dom.parentNode.removeChild(dom); return; } if (isIOS && getInner() >= '18002622' || isAndroid && getInner() >= '2800253A') { if (cnt > 100000) { dom.innerText = "".concat(formatReadNum(cnt), ""); dom.setAttribute('aria-labelledby', 'js_ting_heard js_a11y_op_ting_heard'); } else if (cnt > 0) { dom.innerText = "".concat(formatReadNum(cnt), "人"); dom.setAttribute('aria-labelledby', 'js_ting_heard js_a11y_op_ting_heard'); } else { dom.innerText = "听全文"; dom.setAttribute('aria-labelledby', 'js_ting_heard'); } dom.style.removeProperty('display'); window.__hasClickedAudioPanelHandler = function () { window.__hasClickedAudioPanel = true; }; dom.addEventListener('click', window.__hasClickedAudioPanelHandler); } else { dom.parentNode.removeChild(dom); } }; if (!window.__second_open__) { var tempkey = window.tempkey || ''; var tingHeardDom = document.querySelector('#js_ting_heard'); document.querySelector('#js_a11y_op_ting_heard'); var tingIsShow = window.tts_is_show || ''; var tingHeardCnt = window.tts_heard_person_cnt || ''; console.log('tingIsShow, tingHeardCnt', tingIsShow, tingHeardCnt); !!(tingIsShow * 1) && __setTingHeard(document.querySelector('#js_content'), tingHeardDom, tingHeardCnt * 1, !!tempkey); window.__setTingHeard = __setTingHeard; } return __setTingHeard; })();</script><script type="text/javascript" nonce="1989770072" reportloaderror>var __INLINE_SCRIPT__ = (function (exports) { 'use strict'; function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); } function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray$1(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; } function _unsupportedIterableToArray$1(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray$1(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$1(o, minLen); } function _arrayLikeToArray$1(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } var ua = navigator.userAgent; var is_ios = /(iPhone|iPad|iPod|iOS)/i.test(ua); var is_wp = /Windows\sPhone/i.test(ua); var is_android = /(Android)/i.test(ua); var is_wechat = /MicroMessenger\/([\d\.]+)/i.test(ua); var is_mac = /mac\sos/i.test(ua) && !is_ios; var is_windows = /windows\snt/i.test(ua) && !is_wp; var is_mpapp = /MPAPP\/([\d\.]+)/i.test(ua); var is_ipad = /iPad/i.test(ua); var is_windows_wechat = /WindowsWechat/i.test(ua); var is_mac_wechat = /MacWechat/i.test(ua) || /wechat.*mac os/i.test(ua); var is_prefetch = is_wechat && window.WeixinPrefecherJSBridge; var is_donut_app = /SAAASDK/i.test(ua); var is_harmony = /OpenHarmony|ArkWeb/i.test(ua); var is_in_miniProgram = is_android && /miniprogram/.test(ua.toLowerCase()) || window.__wxjs_environment == 'miniprogram'; var is_wx_work = /wxwork/i.test(ua); function getUrlParams() { var vars = location.search.substring(1).split('&'); var params = {}; var _iterator = _createForOfIteratorHelper(vars), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var ele = _step.value; var pair = ele.split('='); var key = decodeURIComponent(pair[0]); if (typeof params[key] === 'undefined') { params[key] = decodeURIComponent(pair[1]); } } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } return params; } function get() { var reg = /MicroMessenger\/([\d\.]+)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1]; } return false; } function getMac() { var reg = /MacWechat\/([\d\.]+)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1]; } return false; } function getMacOS() { var reg = /Mac OS X ([\d_]+)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1].replace(/_/g, '.'); } return false; } function getWindows() { var reg = /WindowsWechat\(0x(.+?)\)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1]; } return false; } function getWxWork() { var reg = /wxwork\/([\d\.]+)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1]; } return false; } function getMpApp() { var appVersion = [2, 4, 5]; var match = navigator.userAgent.match(/MPAPP\/(\d+(\.\d+)*)/); if (match) { appVersion = match[1].split('.').map(function (v) { return Number(v); }); } return appVersion.join('.'); } function getUnifiedPcVer() { var versionInfo = navigator.userAgent.match(/UnifiedPC\w+Wechat\(0xf\w{2}(\w+?)\w{2}\)/); if (versionInfo && versionInfo.length === 2) { var version = versionInfo[1]; var mainVersion = getVersionNumber(version.slice(0, 1)); var subVersion = getVersionNumber(version.slice(1, 2)); var subVersion2 = getVersionNumber(version.slice(2, 3)); return [mainVersion, subVersion, subVersion2].join('.'); } } function getVersionNumber(hexStr) { return Number(Number("0x".concat(hexStr)).toString(10)); } function getWindowsVersionFormat() { var versionInfo = navigator.userAgent.match(/WindowsWechat\(0x(\w+?)\)/); if (versionInfo && versionInfo.length === 2) { var version = versionInfo[1]; var mainVersion = getVersionNumber(version.slice(1, 2)); var subVersion = getVersionNumber(version.slice(2, 4)); var subVersion2 = getVersionNumber(version.slice(4, 6)); return [mainVersion, subVersion, subVersion2].join('.'); } return false; } function getInner$1() { var reg = /MicroMessenger\/[\d\.]+\(0x(.+?)\)/i; var ret = ua.match(reg); if (ret && ret[1] && ret[1] != null) { return ret[1]; } if (!ret && /MicroMessenger\/[\d\.]+/i.test(ua)) { var urlParams = getUrlParams(); if (urlParams.version) { return urlParams.version; } } return false; } var opfunc = { 'cp-1': function cp1(a, b) { return a < b; }, cp0: function cp0(a, b) { return a === b; }, cp1: function cp1(a, b) { return a > b; } }; function cpVersion(ver, op, canEq, type) { var mmver = false; switch (type) { case 'mac': mmver = getMac(); break; case 'windows': mmver = getWindowsVersionFormat(); break; case 'wxwork': mmver = getWxWork(); break; case 'mpapp': mmver = getMpApp(); break; case 'unifiedpc': mmver = getUnifiedPcVer(); break; default: mmver = get(); break; } if (!mmver) { return; } var mmversion = mmver.split('.'); var version = ver.split('.'); if (!/\d+/g.test(mmversion[mmversion.length - 1])) { mmversion.pop(); } for (var i = 0, len = Math.max(mmversion.length, version.length); i < len; ++i) { var mmv = mmversion[i] || ''; var v = version[i] || ''; var mmvn = parseInt(mmv, 10) || 0; var vn = parseInt(v, 10) || 0; var eq = opfunc.cp0(mmvn, vn); if (eq) { continue; } var cp = opfunc["cp".concat(op)]; return cp(mmvn, vn); } return canEq || op === 0; } function eqVersion(version) { return cpVersion(version, 0); } function gtVersion(version, canEq) { return cpVersion(version, 1, canEq); } function ltVersion(version, canEq) { return cpVersion(version, -1, canEq); } function getPlatform() { if (is_ios) { return 'ios'; } if (is_android) { return 'android'; } if (is_mac) { return 'mac_os'; } if (is_windows) { return 'windows'; } return 'unknown'; } var is_google_play = false; var inner_ver_for_google_play_check = getInner$1(); if (is_android && inner_ver_for_google_play_check) { var v = "0x".concat(inner_ver_for_google_play_check.substr(-2)); if (parseInt(v) >= 64 && parseInt(v) <= 79) { is_google_play = true; } } var mmVersion = { get: get, getMac: getMac, getMacOS: getMacOS, getWindows: getWindows, getInner: getInner$1, getWxWork: getWxWork, getMpApp: getMpApp, cpVersion: cpVersion, eqVersion: eqVersion, gtVersion: gtVersion, ltVersion: ltVersion, getPlatform: getPlatform, getVersionNumber: getVersionNumber, isWp: is_wp, isIOS: is_ios, isAndroid: is_android, isHarmony: is_harmony, isHarmonyWechat: is_harmony && is_wechat && cpVersion('1.0.0', 1, true), isInMiniProgram: is_in_miniProgram, isWechat: is_wechat, isMac: is_mac, isWindows: is_windows, isMacWechat: is_mac_wechat, isWindowsWechat: is_windows_wechat, isWxWork: is_wx_work, isOnlyWechat: is_wechat && !is_wx_work, isMpapp: is_mpapp, isNewMpApp: false, isIPad: is_ipad, isGooglePlay: is_google_play, isPrefetch: is_prefetch, isDonutAPP: is_donut_app }; var initJsBridge = false; if (!window.JSAPIEventCallbackMap) { window.JSAPIEventCallbackMap = {}; } function connectWebViewJavascriptBridge(callback) { if (window.WebViewMPapp || window.WebViewJavascriptBridge) { return callback(window.WebViewMPapp || window.WebViewJavascriptBridge); } if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); } window.WVJBCallbacks = [callback]; if (!initJsBridge) { initJsBridge = true; var WVJBIframe = document.createElement('iframe'); WVJBIframe.style.display = 'none'; WVJBIframe.src = 'https://__bridge_loaded__'; document.body.appendChild(WVJBIframe); setTimeout(function () { initJsBridge = false; document.body.removeChild(WVJBIframe); }, 0); } return false; } function invoke$1(jsapiName, opt, callback) { connectWebViewJavascriptBridge(function (bridge) { try { if (typeof opt === 'function') { callback = opt; } if (_typeof(opt) !== 'object' && typeof opt !== 'string') { opt = {}; } bridge.callHandler(jsapiName, opt, function (res) { try { var ret = _typeof(res) === 'object' ? res : JSON.parse(res); var errMsg = ret.err_msg || ret.errMsg; console.info("[mpapp jsapi] invoke->".concat(jsapiName, " ").concat(opt.action || '', " ").concat(errMsg)); typeof callback === 'function' && callback(ret); } catch (e) { window.WX_BJ_REPORT.BadJs.report('invoke', "callback ".concat(jsapiName, " error:"), { mid: 'mmbizwebapp:js_brridge', _info: e }); console.error("[mpapp jsapi] ".concat(jsapiName, " ").concat(opt.action || ''), e, res); } }); } catch (e) { window.WX_BJ_REPORT.BadJs.report('invoke', 'callback error:', { mid: 'mmbizwebapp:js_brridge', _info: e }); console.error('[mpapp jsapi]', e); } }); } var doc$1 = {}; var isAcrossOrigin$1 = false; var __moon_report$1 = window.__moon_report || function () {}; var MOON_JSAPI_KEY_OFFSET = 8; try { doc$1 = top.window.document; } catch (e) { isAcrossOrigin$1 = true; } if (!window.JSAPIEventCallbackMap) { window.JSAPIEventCallbackMap = {}; } function ready(onBridgeReady) { var bridgeReady = function bridgeReady() { try { if (onBridgeReady) { window.onBridgeReadyTime = window.onBridgeReadyTime || Date.now(); onBridgeReady(); } } catch (e) { __moon_report$1([{ offset: MOON_JSAPI_KEY_OFFSET, log: 'ready', e: e }]); throw e; } window.jsapiReadyTime = Date.now(); }; if (!isAcrossOrigin$1 && (typeof top.window.WeixinJSBridge === 'undefined' || !top.window.WeixinJSBridge.invoke)) { if (doc$1.addEventListener) { doc$1.addEventListener('WeixinJSBridgeReady', bridgeReady, false); } else if (doc$1.attachEvent) { doc$1.attachEvent('WeixinJSBridgeReady', bridgeReady); doc$1.attachEvent('onWeixinJSBridgeReady', bridgeReady); } } else { bridgeReady(); } } function invoke(methodName, args, callback) { if (window.__second_open_wait_a8key__ && window.__second_open_wait_a8key_task__) { window.__second_open_wait_a8key_task__.push(function () { invoke(methodName, args, callback); }); return; } ready(function () { if (isAcrossOrigin$1) return false; if (_typeof(top.window.WeixinJSBridge) !== 'object') { alert('请在微信中打开此链接'); return false; } top.window.WeixinJSBridge.invoke(methodName, args, function () { try { for (var _len = arguments.length, rets = new Array(_len), _key = 0; _key < _len; _key++) { rets[_key] = arguments[_key]; } var ret = rets[0]; var errMsg = ret && ret.err_msg ? ", err_msg-> ".concat(ret.err_msg) : ''; console.info('[system]', "[jsapi] invoke->".concat(methodName).concat(errMsg)); if (callback) { callback.apply(window, rets); } } catch (e) { __moon_report$1([{ offset: MOON_JSAPI_KEY_OFFSET, log: "invoke;methodName:".concat(methodName), e: e }]); throw e; } }); }); } function call(methodName) { if (window.__second_open_wait_a8key__ && window.__second_open_wait_a8key_task__) { window.__second_open_wait_a8key_task__.push(function () { call(methodName); }); return; } ready(function () { if (isAcrossOrigin$1) return false; if (_typeof(top.window.WeixinJSBridge) !== 'object') { return false; } try { top.window.WeixinJSBridge.call(methodName); } catch (e) { __moon_report$1([{ offset: MOON_JSAPI_KEY_OFFSET, log: "call;methodName:".concat(methodName), e: e }]); throw e; } }); } function on(eventName, callback) { if (window.__second_open_wait_a8key__ && window.__second_open_wait_a8key_task__) { window.__second_open_wait_a8key_task__.push(function () { on(eventName, callback); }); return; } ready(function () { if (isAcrossOrigin$1) return false; if (_typeof(top.window.WeixinJSBridge) !== 'object' || !top.window.WeixinJSBridge.on) { return false; } if (!window.JSAPIEventCallbackMap[eventName]) { window.JSAPIEventCallbackMap[eventName] = []; } window.JSAPIEventCallbackMap[eventName].push(callback); if (window.JSAPIEventCallbackMap[eventName].length > 1) { return false; } top.window.WeixinJSBridge.on(eventName, function () { try { for (var _len2 = arguments.length, rets = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { rets[_key2] = arguments[_key2]; } var ret = rets[0]; var errMsg = ret && ret.err_msg ? ", err_msg-> ".concat(ret.err_msg) : ''; console.info('[system]', "[jsapi] event->".concat(eventName).concat(errMsg)); if (window.JSAPIEventCallbackMap[eventName] && window.JSAPIEventCallbackMap[eventName].length) { var result; for (var i = 0; i < window.JSAPIEventCallbackMap[eventName].length; i++) { result = window.JSAPIEventCallbackMap[eventName][i].apply(window, rets); } return result; } } catch (e) { __moon_report$1([{ offset: MOON_JSAPI_KEY_OFFSET, log: "on;eventName:".concat(eventName), e: e }]); throw e; } }); }); } function remove(eventName, callback) { if (window.__second_open_wait_a8key__ && window.__second_open_wait_a8key_task__) { window.__second_open_wait_a8key_task__.push(function () { remove(eventName, callback); }); return; } ready(function () { if (!window.JSAPIEventCallbackMap[eventName]) { return false; } var result = false; for (var i = window.JSAPIEventCallbackMap[eventName].length - 1; i >= 0; i--) { if (window.JSAPIEventCallbackMap[eventName][i] === callback) { window.JSAPIEventCallbackMap[eventName].splice(i, 1); result = true; } } return result; }); } var JSAPI = { ready: ready, invoke: invoke, call: call, on: on, remove: remove }; function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _iterableToArrayLimit(arr, i) { var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; if (null != _i) { var _s, _e, _x, _r, _arr = [], _n = !0, _d = !1; try { if (_x = (_i = _i.call(arr)).next, 0 === i) { if (Object(_i) !== _i) return; _n = !1; } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0); } catch (err) { _d = !0, _e = err; } finally { try { if (!_n && null != _i["return"] && (_r = _i["return"](), Object(_r) !== _r)) return; } finally { if (_d) throw _e; } } return _arr; } } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); } function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } var reportLogs = []; var reportExtraLogs = []; var sendUrl = '/mp/jsmonitor?#wechat_redirect'; var monitor = {}; monitor._reportOptions = { idkey: {} }; function ObjWithoutProperty(source, exclude) { if (source === null) return {}; var target = {}; var sourceKeys = Object.keys(source); for (var i = 0; i < sourceKeys.length; i++) { var key = sourceKeys[i]; if (exclude.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } function formatDataToString(data) { var reportData = []; for (var key in data) { if (Object.prototype.hasOwnProperty.call(data, key)) { reportData.push(key + '=' + encodeURIComponent(data[key])); } } return reportData.join('&'); } monitor.getReportData = function (opt) { opt = opt || {}; var idkey = monitor._reportOptions.idkey || {}; var key = null; var reportData = {}; var nextKey; try { for (key in idkey) { if (Object.prototype.hasOwnProperty.call(idkey, key) && idkey[key]) { reportLogs.push(key + '_' + idkey[key]); } } } catch (e) { return false; } if (reportLogs.length === 0) { return false; } if (reportExtraLogs.length) { reportData.lc = reportExtraLogs.length; reportExtraLogs.forEach(function (extraLog, index) { reportData["log".concat(index)] = extraLog; }); } try { var reportOptions = monitor._reportOptions; if (reportOptions !== null && reportOptions !== undefined) { for (nextKey in reportOptions) { if (Object.prototype.hasOwnProperty.call(reportOptions, nextKey)) { reportData[nextKey] = reportOptions[nextKey]; } } } } catch (e) { reportData = {}; } reportData.idkey = reportLogs.join(';'); reportData.t = Math.random(); if (opt.remove !== false) { reportLogs = []; reportExtraLogs = []; monitor._reportOptions = { idkey: {} }; } return reportData; }; monitor.setLogs = function (opt) { var id = opt.id; var key = opt.key; var value = opt.value; var extraLog = opt.log; var others = ObjWithoutProperty(opt, ['id', 'key', 'value', 'log']); var idkey = monitor._reportOptions.idkey || {}; var param = id + '_' + key; if (idkey[param]) { idkey[param] += value; } else { idkey[param] = value; } monitor._reportOptions.idkey = idkey; if (extraLog) { reportExtraLogs.push(extraLog); } try { if (others !== null && others !== undefined) { for (var otherKey in others) { if (Object.prototype.hasOwnProperty.call(others, otherKey)) { monitor._reportOptions[otherKey] = others[otherKey]; } } } } catch (e) { console.log(e); } return monitor; }; monitor.setAvg = function (id, key, value) { var idkey = monitor._reportOptions.idkey || {}; var param1 = id + '_' + key; var param2 = id + '_' + (key - 1); if (idkey[param1]) { idkey[param1] += value; } else { idkey[param1] = value; } if (idkey[param2]) { idkey[param2] += 1; } else { idkey[param2] = 1; } monitor._reportOptions.idkey = idkey; return monitor; }; monitor.setSum = function (id, key) { var value = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1; var idkey = monitor._reportOptions.idkey; var param = id + '_' + key; if (idkey[param]) { idkey[param] += value; } else { idkey[param] = value; } monitor._reportOptions.idkey = idkey; return monitor; }; monitor.send = function (async, ajax, origin) { if (async !== false) { async = true; } var data = monitor.getReportData(); origin = origin || ''; if (!data) { return; } if (!!ajax && ajax instanceof Function) { ajax({ url: origin + sendUrl, type: 'POST', mayAbort: true, data: data, async: async, timeout: 2000 }); } else { new Image().src = origin + '/mp/jsmonitor?' + formatDataToString(data) + '#wechat_redirect'; } }; if (typeof window !== 'undefined' && window.__monitor) { monitor = window.__monitor; } else { typeof window !== 'undefined' && (window.__monitor = monitor); } var monitor$1 = monitor; var logList = []; var log = function log(msg) { logList.push(msg); }; var printLog = function printLog() { for (var i = 0, len = logList.length; i < len; ++i) { console.log("[RespType]".concat(logList[i])); } }; var isArray = function isArray(val) { return Object.prototype.toString.call(val) === '[object Array]'; }; var getValueType = function getValueType(value) { if (isArray(value)) { return 'array'; } return _typeof(value); }; var parseRtDesc = function parseRtDesc(rtDesc, k) { var type = 'mix'; var isRequired = false; var key = k; if (k) { var requireKeyWord = '_R'; var pos = k.indexOf(requireKeyWord); var len = k.length - requireKeyWord.length; isRequired = pos !== -1 && pos === len; key = isRequired ? k.substring(0, len) : k; } if (typeof rtDesc === 'string') { type = rtDesc; } else if (isArray(rtDesc)) { type = 'array'; } else if (_typeof(rtDesc) === 'object') { type = 'object'; } return { key: key, type: type, isRequired: isRequired }; }; var checkForArrayRtDesc = function checkForArrayRtDesc(arr, rtDescs) { if (!isArray(arr)) { return false; } for (var i = 0, len = arr.length; i < len; ++i) { var value = arr[i]; var rtDesc = void 0; var j = 0; var flag = rtDescs.length === 0; while (rtDesc = rtDescs[j++]) { if (checkForRtDesc(value, rtDesc)) { flag = true; break; } } if (!flag) { return false; } } return true; }; var checkForStringRtDesc = function checkForStringRtDesc(value, rtDesc) { var valueType = getValueType(value); var desc = parseRtDesc(rtDesc); var ret = desc.type === valueType; if (!ret) { log("miss match type : ".concat(valueType, " !== ").concat(desc.type)); } return ret; }; var checkForObjectRtDesc = function checkForObjectRtDesc(json, rtDesc) { if (_typeof(json) !== 'object' || isArray(json)) { log('must be object'); return false; } var rootJson = json; var nowCheckValue = json; for (var k in rtDesc) { if (rtDesc.hasOwnProperty(k)) { var nowCheckDesc = rtDesc[k]; var desc = parseRtDesc(nowCheckDesc, k); var key = desc.key; nowCheckValue = rootJson[key]; var valueType = getValueType(nowCheckValue); if (desc.isRequired && nowCheckValue === undefined) { log("is required @key=".concat(key)); return false; } if (nowCheckValue !== undefined) { if (valueType !== desc.type && desc.type !== 'mix') { log("miss match type : ".concat(valueType, " !== ").concat(desc.type, " @key=").concat(key)); return false; } if ((valueType === 'array' || valueType === 'object') && desc.type !== 'mix') { if (!checkForRtDesc(nowCheckValue, nowCheckDesc)) { return false; } } } } } return true; }; var checkForRtDesc = function checkForRtDesc(json, rtDesc) { if (isArray(rtDesc)) { return checkForArrayRtDesc(json, rtDesc); } if (_typeof(rtDesc) === 'object') { return checkForObjectRtDesc(json, rtDesc); } if (typeof rtDesc === 'string') { return checkForStringRtDesc(json, rtDesc); } return false; }; var _check = function check(json, rtDescs) { if (typeof json === 'string') { try { json = eval("(".concat(json, ")")); } catch (e) { log('parse json error'); return false; } } if (_typeof(json) !== 'object') { log('must be object'); return false; } if (!isArray(rtDescs)) { rtDescs = [rtDescs]; } var rtDesc; var i = 0; while (rtDesc = rtDescs[i++]) { if (checkForRtDesc(json, rtDesc)) { return true; } } return false; }; var RespTypes = { check: function check(json, rtDesc) { logList = []; try { var ret = _check(json, rtDesc); if (!ret) { printLog(); } return ret; } catch (e) { logList.push("[rtException]".concat(e.toString())); printLog(); return false; } }, getMsg: function getMsg() { return logList.join(';'); } }; var Device = {}; function detect(ua) { var MQQBrowser = ua.match(/MQQBrowser\/(\d+\.\d+)/i); var MQQClient = ua.match(/QQ\/(\d+\.(\d+)\.(\d+)\.(\d+))/i) || ua.match(/V1_AND_SQ_([\d\.]+)/); var WeChat = ua.match(/MicroMessenger\/((\d+)\.(\d+))\.(\d+)/) || ua.match(/MicroMessenger\/((\d+)\.(\d+))/); var MacOS = ua.match(/Mac\sOS\sX\s(\d+[\.|_]\d+)/); var WinOS = ua.match(/Windows(\s+\w+)?\s+?(\d+\.\d+)/); var Linux = ua.match(/Linux\s/); var MiuiBrowser = ua.match(/MiuiBrowser\/(\d+\.\d+)/i); var M1 = ua.match(/MI-ONE/); var MIPAD = ua.match(/MI PAD/); var UC = ua.match(/UCBrowser\/(\d+\.\d+(\.\d+\.\d+)?)/) || ua.match(/\sUC\s/); var IEMobile = ua.match(/IEMobile(\/|\s+)(\d+\.\d+)/) || ua.match(/WPDesktop/); var ipod = ua.match(/(ipod).*\s([\d_]+)/i); var ipad = ua.match(/(ipad).*\s([\d_]+)/i); var iphone = ua.match(/(iphone)\sos\s([\d_]+)/i); var Chrome = ua.match(/Chrome\/(\d+\.\d+)/); var AndriodBrowser = ua.match(/Mozilla.*Linux.*Android.*AppleWebKit.*Mobile Safari/); var android = ua.match(/(android)\s([\d\.]+)/i); var harmony = ua.match(/(OpenHarmony)\s([\d\.]+)/i); Device.browser = Device.browser || {}, Device.os = Device.os || {}; if (window.ActiveXObject) { var vie = 6; (window.XMLHttpRequest || ua.indexOf('MSIE 7.0') > -1) && (vie = 7); (window.XDomainRequest || ua.indexOf('Trident/4.0') > -1) && (vie = 8); ua.indexOf('Trident/5.0') > -1 && (vie = 9); ua.indexOf('Trident/6.0') > -1 && (vie = 10); Device.browser.ie = true, Device.browser.version = vie; } else if (ua.indexOf('Trident/7.0') > -1) { Device.browser.ie = true, Device.browser.version = 11; } if (android) { Device.os.android = true; Device.os.version = android[2]; } if (harmony) { Device.os.harmony = true; Device.os.version = harmony[2]; } if (ipod) { Device.os.ios = Device.os.ipod = true; Device.os.version = ipod[2].replace(/_/g, '.'); } if (ipad) { Device.os.ios = Device.os.ipad = true; Device.os.version = ipad[2].replace(/_/g, '.'); } if (iphone) { Device.os.iphone = Device.os.ios = true; Device.os.version = iphone[2].replace(/_/g, '.'); } if (WinOS) Device.os.windows = true, Device.os.version = WinOS[2]; if (MacOS) Device.os.Mac = true, Device.os.version = MacOS[1]; if (Linux) Device.os.Linux = true; if (ua.indexOf('lepad_hls') > 0) Device.os.LePad = true; if (MIPAD) Device.os.MIPAD = true; if (MQQBrowser) Device.browser.MQQ = true, Device.browser.version = MQQBrowser[1]; if (MQQClient) Device.browser.MQQClient = true, Device.browser.version = MQQClient[1]; if (WeChat) Device.browser.WeChat = true, Device.browser.mmversion = Device.browser.version = WeChat[1]; if (MiuiBrowser) Device.browser.MIUI = true, Device.browser.version = MiuiBrowser[1]; if (UC) Device.browser.UC = true, Device.browser.version = UC[1] || NaN; if (IEMobile) Device.browser.IEMobile = true, Device.browser.version = IEMobile[2]; if (AndriodBrowser) { Device.browser.AndriodBrowser = true; } if (M1) { Device.browser.M1 = true; } if (Chrome) { Device.browser.Chrome = true, Device.browser.version = Chrome[1]; } if (Device.os.windows) { if (typeof navigator.platform !== "undefined" && navigator.platform.toLowerCase() == "win64") { Device.os.win64 = true; } else { Device.os.win64 = false; } } if (Device.os.Mac || Device.os.windows || Device.os.Linux) { Device.os.pc = true; } var osType = { iPad7: 'iPad; CPU OS 7', LePad: 'lepad_hls', XiaoMi: 'MI-ONE', SonyDTV: "SonyDTV", SamSung: 'SAMSUNG', HTC: 'HTC', VIVO: 'vivo' }; for (var os in osType) { Device.os[os] = ua.indexOf(osType[os]) !== -1; } Device.os.phone = Device.os.phone || /windows phone/i.test(ua); Device.os.getNumVersion = function () { return parseFloat(Device.os.version); }; Device.os.hasTouch = 'ontouchstart' in window; if (Device.os.hasTouch && Device.os.ios && Device.os.getNumVersion() < 6) { Device.os.hasTouch = false; } if (Device.browser.WeChat && Device.browser.version < 5.0) { Device.os.hasTouch = false; } Device.browser.getNumVersion = function () { return parseFloat(Device.browser.version); }; Device.browser.isFFCanOcx = function () { return !!Device.browser.firefox && Device.browser.getNumVersion() >= 3.0; }; Device.browser.isCanOcx = function () { return !!Device.os.windows && (!!Device.browser.ie || Device.browser.isFFCanOcx() || !!Device.browser.webkit); }; Device.browser.isNotIESupport = function () { return !!Device.os.windows && (!!Device.browser.webkit || Device.browser.isFFCanOcx()); }; Device.userAgent = {}; Device.userAgent.browserVersion = Device.browser.version; Device.userAgent.osVersion = Device.os.version; Device.os.unifiedPC = ua.match(/UnifiedPC/); delete Device.userAgent.version; } detect(window.navigator.userAgent); function canSupportH5Video() { var ua = window.navigator.userAgent, m = null; if (!!Device.os.android) { if (Device.browser.MQQ && Device.browser.getNumVersion() >= 4.2) { return true; } if (ua.indexOf('MI2') != -1) { return true; } if (Device.os.version >= '4' && (m = ua.match(/MicroMessenger\/((\d+)\.(\d+))\.(\d+)/))) { if (parseFloat(m[1]) >= 4.2) { return true; } } if (Device.os.version >= '4.1') { return true; } } return false; } function canSupportVideoMp4() { var video = document.createElement('video'); if (typeof video.canPlayType === 'function') { if (video.canPlayType('video/mp4; codecs="mp4v.20.8"') === 'probably') { return true; } if (video.canPlayType('video/mp4; codecs="avc1.42E01E"') === 'probably' || video.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"') === 'probably') { return true; } } return false; } function canSupportAutoPlay() { if (Device.os.ios && Device.os.getNumVersion() < 10) { return false; } return true; } function isLockdownMode() { if (!Device.os.ios || Device.os.getNumVersion() < 16) { return false; } if (typeof WebAssembly === 'undefined' && typeof OfflineAudioContext === 'undefined' && typeof WebGLRenderingContext === 'undefined') { return true; } return false; } Device.canSupportVideo = canSupportVideoMp4 || canSupportH5Video; Device.canSupportVideoMp4 = canSupportVideoMp4; Device.canSupportH5Video = canSupportH5Video; Device.canSupportAutoPlay = canSupportAutoPlay; Device.isLockdownMode = isLockdownMode; Device.cpVersion = function (version) { var cp = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; var canEqual = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; var nowVersionStr = Device.os.version; if (!nowVersionStr) return false; var versionArr = version.split('.'); var nowVersionArr = nowVersionStr.split('.'); for (var i = 0; i < Math.max(nowVersionArr.length, versionArr.length); i++) { var vi = +versionArr[i]; var nvi = +nowVersionArr[i]; if (vi === nvi) continue; if (cp > 0) return vi > nvi; if (cp < 0) return vi < nvi; } return canEqual || cp === 0; }; function parseUrl(url) { var len = url.length; var ques_pos = url.indexOf('?'); var hash_pos = url.indexOf('#'); hash_pos = hash_pos == -1 ? len : hash_pos; ques_pos = ques_pos == -1 ? hash_pos : ques_pos; var host = url.substring(0, ques_pos); var query_str = url.substring(ques_pos + 1, hash_pos); var hash = url.substring(hash_pos + 1); return { host: host, query_str: query_str, hash: hash }; } function join(url, args, noEncode) { var ret = parseUrl(url); var query_str = ret.query_str; var args_arr = []; if (_typeof(args) === 'object') { for (var key in args) { if (args.hasOwnProperty(key)) { args_arr.push("".concat(key, "=").concat(noEncode ? args[key] : encodeURIComponent(args[key]))); } } } else { args_arr.push(noEncode ? args : encodeURIComponent(args)); } if (args_arr.length > 0) { query_str += (query_str !== "" ? "&" : "") + args_arr.join("&"); } return ret.host + (query_str !== "" ? "?".concat(query_str) : "") + (ret.hash !== "" ? "#".concat(ret.hash) : ""); } function addParam(url, param, value, forceReplace) { url = url || location.href; var firstAndPos = url.indexOf("&"); var len = url.length; var reverseUrl = url.replace(/^[\w\d]+:[/\\]+/g, "").split("").reverse(); if (!Array.prototype.indexOf) { Array.prototype.indexOf = function (searchElement, fromIndex) { var k; if (this == null) { throw new TypeError('"this" is null or not defined'); } var O = Object(this); var len = O.length >>> 0; if (len === 0) { return -1; } var n = fromIndex || 0; if (Math.abs(n) === Infinity) { n = 0; } if (n >= len) { return -1; } k = Math.max(n >= 0 ? n : len - Math.abs(n), 0); while (k < len) { if (k in O && O[k] === searchElement) { return k; } k++; } return -1; }; } var lastSlashPos = len - 1 - reverseUrl.indexOf("/"); if (firstAndPos !== -1 && url.indexOf("?") == -1 && firstAndPos > lastSlashPos) { url = url.replace("&", "?"); } var reg = new RegExp("([\\?&]".concat(param, "=)[^&#]*")); if (!url.match(reg)) { var urlInfo = parseUrl(url); var hash = urlInfo.hash ? '#' + urlInfo.hash : ''; url = url.replace(hash, ''); var _pos = url.indexOf("?"); if (_pos == -1) { return "".concat(url, "?").concat(param, "=").concat(value).concat(hash); } if (_pos == url.length - 1) { return "".concat(url + param, "=").concat(value).concat(hash); } return "".concat(url, "&").concat(param, "=").concat(value).concat(hash); } if (forceReplace === true) { return url.replace(reg, "$1".concat(value)); } return url; } function addWxfrom(src, wxfrom) { var offset = window.service_type === 1 ? 10000 : 0; return addParam(src, 'wxfrom', offset + Number(wxfrom), true); } function removeParam(url, param) { var _URL = new URL(url), protocol = _URL.protocol, host = _URL.host, pathname = _URL.pathname, search = _URL.search, hash = _URL.hash; var queryParams = new URLSearchParams(search); queryParams["delete"](param); var newSearch = queryParams.toString(); var newUrl = new URL("".concat(protocol, "//").concat(host).concat(pathname).concat(newSearch ? "?".concat(decodeURIComponent(newSearch)) : "").concat(hash)); return newUrl.toString(); } function getQuery(name, url) { var u = url || window.location.search; var reg = new RegExp("(^|&)".concat(name, "=([^&]*)(&|$)")); var r = u.substring(u.indexOf('?') + 1).match(reg); return r !== null ? r[2] : ''; } function encodeBase64(value) { try { return window.btoa(value); } catch (e) { return ''; } } function decodeBase64(value) { try { return window.atob(value); } catch (e) { return ''; } } function joinUrl$1(url) { var obj = {}; if (typeof window.uin !== 'undefined') { obj.uin = window.uin; } if (typeof window.key !== 'undefined') { obj.key = window.key; } if (typeof window.pass_ticket !== 'undefined') { obj.pass_ticket = window.pass_ticket; } if (typeof window.wxtoken !== 'undefined') { obj.wxtoken = window.wxtoken; } if (typeof window.devicetype !== 'undefined') { obj.devicetype = window.devicetype; } if (typeof window.clientversion !== 'undefined') { obj.clientversion = window.clientversion || mmVersion.getInner(); } obj.version = obj.clientversion; if (window.biz) { obj.__biz = window.biz; } if (getQuery('enterid')) { obj.enterid = getQuery('enterid'); } if (typeof window.appmsg_token !== 'undefined') { obj.appmsg_token = window.appmsg_token; } else if (url.indexOf('advertisement_report') > -1) { new Image().src = "".concat(location.protocol, "//mp.weixin.qq.com/mp/jsmonitor?idkey=68064_13_1&r=").concat(Math.random()); } obj.x5 = navigator.userAgent.indexOf('TBS/') !== -1 ? '1' : '0'; obj.f = 'json'; return join(url, obj); } function getA8keyQuery(name, url) { return new Promise(function (resolve) { if (window.__second_open_wait_a8key__ && window.__second_open_wait_a8key_task__) { window.__second_open_wait_a8key_task__.push(function () { resolve(getQuery(name, url)); }); } else { resolve(getQuery(name, url)); } }); } var Url = { parseUrl: parseUrl, join: join, addParam: addParam, addWxfrom: addWxfrom, getQuery: getQuery, getA8keyQuery: getA8keyQuery, encodeBase64: encodeBase64, decodeBase64: decodeBase64, joinUrl: joinUrl$1, removeParam: removeParam }; function _log(level, msg) { if (level === 'log') { level = 'info'; msg = "[WechatFe]".concat(msg); } else { var prefix = "__wap__".concat(window.__second_open__ ? ' (sec)' : ''); msg = "".concat(prefix, " ").concat(msg, " location:[").concat(location.href, "]"); } msg += new Error().stack; if (mmVersion.isMpapp) { invoke$1('WNNativeCallbackLog', msg); } else if (mmVersion.isWechat) { if (mmVersion.isAndroid) { console.warn('[system]', "[MicroMsg.JsApiLog][".concat(level, "] jslog : ").concat(msg)); } else if (mmVersion.isIOS) { JSAPI.invoke('writeLog', { level: level, msg: msg }); } else { JSAPI.invoke('log', { level: level, msg: msg }); } } } var Log = { info: function info() { for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _log('info', args.join(' ')); }, warn: function warn() { for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } _log('warn', args.join(' ')); }, error: function error() { for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { args[_key3] = arguments[_key3]; } _log('error', args.join(' ')); }, debug: function debug() { for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { args[_key4] = arguments[_key4]; } _log('debug', args.join(' ')); }, log: function log() { for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) { args[_key5] = arguments[_key5]; } _log('info', args.join(' ')); } }; var html = function html(_str, encode) { if (!_str) return ''; var replace = ['`', '`', ''', '\'', '"', '"', ' ', ' ', '>', '>', '<', '<', '¥', '¥', '&', '&', '<', '<', '>', '>']; var replaceReverse = ['&', '&', '¥', '¥', '<', '<', '>', '>', ' ', ' ', '"', '"', '\'', ''', '`', '`']; var str = _str; var target; if (encode) { target = replaceReverse; } else { target = replace; } for (var i = 0; i < target.length; i += 2) { str = str.replace(new RegExp(target[i], 'g'), target[i + 1]); } return str; }; var htmlLite = function htmlLite(_str, encode) { if (!_str) return ''; var replace = ['`', '`', ''', '\'', '"', '"', '>', '>', '<', '<', '&', '&']; var replaceReverse = ['&', '&', '<', '<', '>', '>', '"', '"', '\'', ''', '`', '`']; var str = _str; var target; if (encode) { target = replaceReverse; } else { target = replace; } for (var i = 0; i < target.length; i += 2) { str = str.replace(new RegExp(target[i], 'g'), target[i + 1]); } return str; }; var htmlEncode = function htmlEncode(str) { return html(str, true); }; var htmlDecode = function htmlDecode(str) { return html(str, false); }; var htmlEncodeLite = function htmlEncodeLite(str) { return htmlLite(str, true); }; var htmlDecodeLite = function htmlDecodeLite(str) { return htmlLite(str, false); }; String.prototype.html = function (encode) { return html(this.toString(), encode); }; String.prototype.htmlEncode = function () { return htmlEncode(this.toString()); }; String.prototype.htmlDecode = function () { return htmlDecode(this.toString()); }; String.prototype.htmlLite = function (encode) { return htmlLite(this.toString(), encode); }; String.prototype.htmlEncodeLite = function () { return htmlEncodeLite(this.toString()); }; String.prototype.htmlDecodeLite = function () { return htmlDecodeLite(this.toString()); }; var _a; var METHOD_ENUM = { GET: 0, POST: 1 }; var __moon_report = window.__moon_report || function () {}; var MOON_AJAX_SUCCESS_OFFSET = 3; var MOON_AJAX_NETWORK_OFFSET = 4; var MOON_AJAX_ERROR_OFFSET = 5; var MOON_AJAX_TIMEOUT_OFFSET = 6; var MOON_AJAX_COMPLETE_OFFSET = 7; var LENGTH_LIMIT = 4096; var doc; var isAcrossOrigin = false; try { doc = (_a = window.top) === null || _a === void 0 ? void 0 : _a.window.document; } catch (e) { isAcrossOrigin = true; } function networkStartLog(item) { var _a, _b, _c; console.log('[system]', "< [request ".concat(item.requestType, "]"), item.method, item); if ((_a = window.vConsole) === null || _a === void 0 ? void 0 : _a.network) { try { return (_c = (_b = window.vConsole.network).add) === null || _c === void 0 ? void 0 : _c.call(_b, Object.assign({}, item, { startTime: Date.now(), endTime: Date.now(), status: 0, readyState: 2, response: '' })); } catch (err) {} } return Object.assign({}, item, { id: '__system_log__' }); } function networkEndLog(item) { var _a, _b, _c; console.log('[system]', "> [response ".concat(item.requestType, "]"), item.response, item); if (((_a = window.vConsole) === null || _a === void 0 ? void 0 : _a.network) && item.id !== '__system_log__') { try { return (_c = (_b = window.vConsole.network).update) === null || _c === void 0 ? void 0 : _c.call(_b, item.id, Object.assign({}, item, { readyState: 4 })); } catch (err) {} } } function reqType(obj, path) { return obj.url.indexOf(path) > -1 && obj.url.indexOf('action=') === -1 && (!obj.data || !obj.data.action); } function reportRtError(type, id, key, content) { var log = ''; var prefix = type === 'rt' ? 'rtCheckError' : 'Ajax Length Limit'; if (content === null || content === void 0 ? void 0 : content.length) { var loglen = 1000; var len = content.length; var lc = Math.ceil(len / loglen); log = ["&lc=".concat(lc)]; for (var i = 0; i < lc; ++i) { log.push("&log".concat(i, "=") + "[".concat(prefix, "][").concat(i, "]").concat(encodeURIComponent(content.substring(i * loglen, i * loglen + loglen)))); } log = log.join(''); } var data = "idkey=".concat(id, "_").concat(key, "_1").concat(log, "&r=").concat(Math.random()); var xmlobj = new XMLHttpRequest(); xmlobj.open('POST', "".concat(location.protocol, "//").concat(location.host, "/mp/jsmonitor?"), true); xmlobj.setRequestHeader('cache-control', 'no-cache'); xmlobj.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); xmlobj.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); xmlobj.send(data); if (type === 'ajaxLen') { monitor$1.setLogs({ id: id, key: key, value: 1, log: log }); } } function reportRt(id, key, content) { reportRtError('rt', id, key, content); } function reportAjaxLength(id, key, content) { reportRtError('ajaxLen', id, key, content); } function setCurrentMpInfo(ifShow) { var supportNewTopBar = mmVersion.isIOS && mmVersion.gtVersion('7.0.10', true) || mmVersion.isAndroid && mmVersion.gtVersion('7.0.12', true); var supportLiveStatus = mmVersion.isIOS && mmVersion.gtVersion('8.0.46', true) || mmVersion.isAndroid && mmVersion.gtVersion('8.0.46', true); JSAPI.invoke('currentMpInfo', { userName: window.user_name, brandName: !!supportNewTopBar && window.nickname === '' ? '未命名账号' : window.title, title: window.msg_title || '', brandIcon: window.hd_head_img.replace(/\/0$/, '/132'), itemShowType: window.item_show_type, isPaySubscribe: window.isPaySubscribe, topBarStyle: supportNewTopBar ? 1 : 0, topBarShowed: ifShow, disableShowFinderLiveTopBar: !ifShow && supportLiveStatus ? 1 : 0 }, function () {}); } function findAjaxScopeByConfig(url, config) { var pathname = new URL(url, location.href).pathname || ''; var scope = config[pathname.slice(1)]; if (scope) { Log.log('ajax transfer config: ', JSON.stringify(config)); return scope; } } function getAjaxScope(ajaxUrl) { if (Url.getQuery('no_transfer', location.href) !== '1' && mmVersion.isWechat && !mmVersion.isInMiniProgram && !mmVersion.isWxWork && !mmVersion.isMpapp && !isAcrossOrigin && window.__ajaxTransferConfig && _typeof(window.__ajaxTransferConfig) === 'object' && ( mmVersion.isIOS && mmVersion.getInner() >= '1800282f' || mmVersion.isAndroid && mmVersion.getInner() >= '28002234' || mmVersion.isWindowsWechat && mmVersion.cpVersion('3.9.5', 1, true, 'windows') || mmVersion.isMacWechat && mmVersion.cpVersion('3.8.4', 1, true, 'mac'))) { try { return findAjaxScopeByConfig(ajaxUrl, window.__ajaxTransferConfig); } catch (err) { } } } function setXhrHeader(xhr, type, opt) { if (opt.contentType) { xhr.setRequestHeader('Content-Type', opt.contentType); } else if (type === 'POST') { xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); } if (!opt.noXRequestedWidthHeader) { xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); } } function Ajax(obj) { if (obj.usePb) { obj.type = 'POST'; obj.data = { data: JSON.stringify(obj.data) }; } var ajaxScope = getAjaxScope(obj.url); var type = (obj.type || 'GET').toUpperCase(); var timer; var url; if (obj.notJoinUrl) { url = obj.url; } else { url = Url.joinUrl(obj.url); } if (obj.f === 'html') { url = url.replace('&f=json', ''); } var data = null; if (_typeof(obj.data) === 'object') { var d = obj.data; var ds = []; for (var k in d) { if (d.hasOwnProperty(k)) { ds.push("".concat(k, "=").concat(encodeURIComponent(d[k]))); } } data = ds.join('&'); } else { data = typeof obj.data === 'string' ? obj.data : null; } var beginTs; var beforeReq = function beforeReq() { if (reqType(obj, '/mp/getappmsgext')) { window.startGetAppmsgExtTime = Date.now(); Log.log('start get appmsgext, url: ', obj.url); } if (reqType(obj, '/mp/getappmsgad')) { window.startGetAppmsgAdTime = Date.now(); Log.log('start get appmsgad, url: ', obj.url); } beginTs = Date.now(); }; var beforeResp = function beforeResp(xhr) { if (reqType(obj, '/mp/getappmsgext')) { window.receiveGetAppmsgExt = "".concat(xhr.status, "|").concat(Date.now()); Log.log("receive appmsgext response, status: ".concat(xhr.status)); } if (reqType(obj, '/mp/getappmsgad')) { window.receiveGetAppmsgAd = "".concat(xhr.status, "|").concat(Date.now()); Log.log("receive appmsgad response, status: ".concat(xhr.status)); } if (Math.random() < 0.01 && window.WX_BJ_REPORT && window.WX_BJ_REPORT.BadJs) { try { var key = ajaxScope ? 'transfer' : 'xhr'; var interval = 250; var time = Date.now() - beginTs; var range = Math.floor(time / interval) * interval; var pathname = new URL(obj.url, location.href).pathname || ''; window.WX_BJ_REPORT.BadJs.report("".concat(key, "_perf:").concat(pathname), JSON.stringify({ status: xhr.status, time: "[".concat(range, "-").concat(range + interval, ")") }), { mid: 'mmbizwap:ajaxtransfer', view: 'wap_business' }); } catch (err) {} } }; var handleRespSucc = function handleRespSucc(xhr) { var _a; try { var responseText = xhr.responseText; var resp = responseText; if (obj.dataType === 'json') { try { if (JSON && JSON.parse) { resp = JSON.parse(resp); } else { resp = eval("(".concat(resp, ")")); monitor$1.setSum(523105, 127, 1).send(); } var rtId = obj.rtId; var rtKey = obj.rtKey || 0; var rtDesc = obj.rtDesc; if (rtId && rtDesc && RespTypes && !RespTypes.check(resp, rtDesc)) { reportRt(+rtId, +rtKey, "".concat(RespTypes.getMsg(), "[detail]").concat(responseText, ";").concat(obj.url)); } if (resp && resp.base_resp && ((_a = resp.base_resp) === null || _a === void 0 ? void 0 : _a.ret) !== 0 && typeof window.WX_BJ_REPORT !== 'undefined' && window.WX_BJ_REPORT.BadJs && Math.random() < 0.001) { var reportUrl = url; if (url.indexOf('?') !== -1) { reportUrl = url.substring(0, url.indexOf('?')); if (Url.getQuery('action', url)) { reportUrl = "".concat(reportUrl, "?action=").concat(Url.getQuery('action', url)); } } if (!((reportUrl === '/mp/getappmsgext' || reportUrl === '/mp/getappmsgad') && typeof resp.base_resp.ret === 'undefined')) { window.WX_BJ_REPORT.BadJs.report(reportUrl, "ret=".concat(resp.base_resp.ret), { mid: window.PAGE_MID, view: 'wap_retcode' }); } } } catch (e) { obj.error && obj.error(xhr, { type: 1, error: e, status: xhr.status }); return; } } obj.success && obj.success(resp); } catch (e) { __moon_report({ offset: MOON_AJAX_SUCCESS_OFFSET, e: e }); throw e; } }; var handleRespErr = function handleRespErr(xhr, error) { try { obj.error && obj.error(xhr, { type: 2, error: error, status: xhr.status }); } catch (e) { __moon_report({ offset: MOON_AJAX_ERROR_OFFSET, e: e }); throw e; } }; var handleRespComplete = function handleRespComplete() { clearTimeout(timer); try { obj.complete && obj.complete(); } catch (e) { __moon_report({ offset: MOON_AJAX_COMPLETE_OFFSET, e: e }); throw e; } obj.complete = null; }; var handleReqTimeout = function handleReqTimeout(xhr) { if (typeof obj.timeout !== 'undefined') { timer = setTimeout(function () { xhr.abort(); try { obj.complete && obj.complete(); } catch (e) { __moon_report({ offset: MOON_AJAX_COMPLETE_OFFSET, e: e }); throw e; } obj.complete = null; __moon_report({ offset: MOON_AJAX_TIMEOUT_OFFSET, log: "ajax_timeout_error: ".concat(url), e: '' }); }, obj.timeout); } }; var retryXhrFn = function retryXhrFn(res, isTimeout, reqLogItem) { var retryXhr = new XMLHttpRequest(); try { retryXhr._noVConsole = true; } catch (err) {} retryXhr.open(type, url); retryXhr.onreadystatechange = function () { if (isTimeout) return; if (retryXhr.readyState === 3) { obj.received && obj.received(retryXhr); } if (retryXhr.readyState === 4) { beforeResp(retryXhr); var retryStatus = retryXhr.status; if (retryStatus >= 200 && retryStatus < 400) { handleRespSucc(retryXhr); } else { handleRespErr(retryXhr, res); window.WX_BJ_REPORT && window.WX_BJ_REPORT.BadJs && window.WX_BJ_REPORT.BadJs.report('req_failure', JSON.stringify({ retryXhrStatus: retryStatus, transferRes: res }), { mid: 'mmbizwap:ajaxtransfer', view: 'wap_business' }); } reqLogItem.status = retryStatus; reqLogItem.endTime = Date.now(); reqLogItem.response = retryXhr.responseText; handleRespComplete(); networkEndLog(reqLogItem); } }; setXhrHeader(retryXhr, type, obj); retryXhr.send(data); }; if (ajaxScope) { var header = { 'User-Agent': navigator.userAgent, 'Cookie': (window.__test_env__ ? 'uniproxy_route=1; ' : '') + document.cookie, 'Referer': location.href }; if (obj.contentType) { header['Content-Type'] = obj.contentType; } else if (type === 'POST') { header['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8'; } if (!obj.noXRequestedWidthHeader) { header['X-Requested-With'] = 'XMLHttpRequest'; } var reqUrl = new URL(url, location.href).href; var method = METHOD_ENUM[type] || 0; var params = Device.os.pc ? { url: reqUrl, req_json: data || '', scope: ajaxScope, webcgi_method: method, webcgi_header: Object.keys(header).map(function (headerItemKey) { return Device.os.Mac ? _defineProperty({}, headerItemKey, header[headerItemKey]) : { key: headerItemKey, value: header[headerItemKey] }; }), cgi_type: 1 } : { reqUrl: reqUrl, reqBody: data, scope: ajaxScope, method: method, header: header }; var reqLogItem = networkStartLog({ method: type, url: url, postData: obj.data || {}, requestHeader: header, requestType: 'transfer' }); var isTimeout = false; handleReqTimeout({ abort: function abort() { isTimeout = true; reqLogItem.endTime = Date.now(); reqLogItem.response = 'timeout'; networkEndLog(reqLogItem); } }); Device.os.pc && monitor$1.setSum(115849, 69, 1); JSAPI.invoke(Device.os.pc ? 'H5ExtTransfer' : 'webTransfer', params, function (res) { var _a, _b, _c, _d, _e, _f; if (isTimeout) return; var status = 400; var result = ''; if (Device.os.pc) { try { var retFlag = res.base_resp.ret === 0 && res.jsapi_resp.ret === 0 && res.err_msg.indexOf(':ok') > -1; var respJsonFlag = res.jsapi_resp.resp_json; status = retFlag && respJsonFlag ? 200 : 400; result = res.jsapi_resp.resp_json; } catch (err) { console.error(err); } } else { status = res && res.errCode * 1 === 0 && typeof res.result === 'string' && res.result ? 200 : 400; result = res.result; } if (status >= 200 && status < 400) { obj.received && obj.received(null); beforeResp({ status: status }); handleRespSucc({ status: status, responseText: result }); reqLogItem.status = status; reqLogItem.endTime = Date.now(); reqLogItem.response = result; handleRespComplete(); networkEndLog(reqLogItem); } else if (window.__second_open__) { JSAPI.invoke('request', { url: reqUrl, method: type, data: data, header: header }, function (retryRes) { if (isTimeout) return; var retryStatus = retryRes.statusCode; obj.received && obj.received(null); beforeResp({ status: retryStatus }); if (retryRes.err_msg.indexOf(':ok') > -1 && retryStatus >= 200 && retryStatus < 400) { handleRespSucc({ status: retryStatus, responseText: retryRes.data }); } else { retryXhrFn(res, isTimeout, reqLogItem); handleRespErr({ status: retryStatus }, res); window.WX_BJ_REPORT && window.WX_BJ_REPORT.BadJs && window.WX_BJ_REPORT.BadJs.report('req_failure_sec_open', JSON.stringify({ retryReqJsapiRes: retryRes, transferRes: res, url: reqUrl }), { mid: 'mmbizwap:ajaxtransfer', view: 'wap_business' }); } reqLogItem.status = retryStatus; reqLogItem.endTime = Date.now(); reqLogItem.response = retryRes.data; handleRespComplete(); networkEndLog(reqLogItem); }); } else { retryXhrFn(res, isTimeout, reqLogItem); } if (Device.os.pc) { if (!res.err_msg.includes(':ok')) { (_b = (_a = window.WX_BJ_REPORT) === null || _a === void 0 ? void 0 : _a.BadJs) === null || _b === void 0 ? void 0 : _b.report("pc transfer res no ok: ".concat(res.err_msg), params.url || '', { mid: window.PAGE_MID, _info: "".concat(JSON.stringify(params), " || ").concat(JSON.stringify(res)) }); } try { if (res.jsapi_resp.resp_json && JSON.parse(res.jsapi_resp.resp_json).base_resp.ret !== 0 && JSON.parse(res.jsapi_resp.resp_json).base_resp.ret !== 190001 || res.base_resp.ret !== 0 || res.jsapi_resp.ret !== 0) { (_d = (_c = window.WX_BJ_REPORT) === null || _c === void 0 ? void 0 : _c.BadJs) === null || _d === void 0 ? void 0 : _d.report("pc transfer res invalid ret", params.url || '', { mid: window.PAGE_MID, _info: "".concat(JSON.stringify(params), " || ").concat(JSON.stringify(res)) }); } } catch (err) {} } else { try { if (res.errCode !== 0) { (_f = (_e = window.WX_BJ_REPORT) === null || _e === void 0 ? void 0 : _e.BadJs) === null || _f === void 0 ? void 0 : _f.report("mobile transfer res invalid ret", params.url || '', { mid: window.PAGE_MID, _info: "".concat(JSON.stringify(params), " || ").concat(JSON.stringify(res)) }); } } catch (err) {} } }); beforeReq(); return; } var xhr = new XMLHttpRequest(); var mayAbort = !!obj.mayAbort; var async = typeof obj.async === 'undefined' ? true : obj.async; var _onreadystatechange = xhr.onreadystatechange; xhr.open(type, url, async); xhr.onreadystatechange = function () { if (typeof _onreadystatechange === 'function') { _onreadystatechange.apply(xhr); } if (xhr.readyState === 3) { obj.received && obj.received(xhr); } if (xhr.readyState === 4) { beforeResp(xhr); xhr.onreadystatechange = null; var status = xhr.status; if (status >= 200 && status < 400) { handleRespSucc(xhr); } else { handleRespErr(xhr, 'status error'); if (!!status || !mayAbort) { var __ajaxtest = window.__ajaxtest || '0'; __moon_report({ offset: MOON_AJAX_NETWORK_OFFSET, log: "ajax_network_error[".concat(status, "][").concat(__ajaxtest, "]: ").concat(url, ";host:").concat(location.host), e: '' }); } } handleRespComplete(); } }; setXhrHeader(xhr, type, obj); handleReqTimeout(xhr); try { xhr.send(data); try { if (url && url.length > LENGTH_LIMIT) { reportAjaxLength(27613, 17, "ajax get limit[length: ".concat(url.length, "]").concat(url.substring(0, 1024))); } if (data && data.length > LENGTH_LIMIT) { reportAjaxLength(27613, 18, "ajax post limit[length: ".concat(data.length, "]").concat(data.substring(0, 1024))); } } catch (e) { } } catch (e) { obj.error && obj.error(xhr, { type: 3, error: e, status: 0 }); } beforeReq(); return xhr; } function AjaxWx(obj) { obj.url += obj.url.indexOf('?') === -1 ? '?fasttmplajax=1' : '&fasttmplajax=1'; if (getAjaxScope(obj.url)) { Ajax(obj); return; } if (obj.usePb) { obj.type = 'POST'; obj.data = { data: JSON.stringify(obj.data) }; } if (!/^(http:\/\/|https:\/\/|\/\/)/.test(obj.url)) { obj.url = "https://mp.weixin.qq.com/".concat(obj.url.replace(/^\//, '')); } else if (/^\/\//.test(obj.url)) { obj.url = "https:".concat(obj.url); } if (obj.f !== 'html' && (obj.url.indexOf('?f=json') === -1 || obj.url.indexOf('&f=json') === -1)) { obj.url += '&f=json'; } if (!obj.notJoinUrl && obj.f !== 'html') { obj.url = Url.joinUrl(obj.url); } var data = null; if (_typeof(obj.data) === 'object') { var d = obj.data; var ds = []; for (var k in d) { if (d.hasOwnProperty(k)) { ds.push("".concat(k, "=").concat(encodeURIComponent(d[k]))); } } data = ds.join('&'); } else { data = typeof obj.data === 'string' ? obj.data : null; } var header = { Cookie: document.cookie, referer: location.href }; var reqLogItem = networkStartLog({ method: obj.type || 'GET', url: obj.url, postData: obj.data || {}, requestHeader: header, requestType: 'jsapi' }); var retryTime = 1; var jsapiRequest = function jsapiRequest(obj, data) { return JSAPI.invoke('request', { url: obj.url, method: obj.type, data: data, header: header }, function (res) { var _a; if (res.err_msg.indexOf(':ok') > -1) { if (reqType(obj, '/mp/getappmsgext')) { window.receiveGetAppmsgExt = "".concat(res.statusCode, "|").concat(Date.now()); } if (reqType(obj, '/mp/getappmsgad')) { window.receiveGetAppmsgAd = "".concat(res.statusCode, "|").concat(Date.now()); } if (retryTime === 1) { obj.received && obj.received(null); } var resData = {}; if (res.data) { try { if (obj.dataType === 'json') { resData = JSON.parse(res.data); } else { resData = res.data; } if (resData && resData.base_resp && ((_a = resData.base_resp) === null || _a === void 0 ? void 0 : _a.ret) !== 0 && typeof window.WX_BJ_REPORT !== 'undefined' && window.WX_BJ_REPORT.BadJs && Math.random() < 0.001) { var reportUrl = obj.url; if (obj.url.indexOf('?') !== -1) { reportUrl = obj.url.substring(0, obj.url.indexOf('?')); if (Url.getQuery('action', obj.url)) { reportUrl = "".concat(reportUrl, "?action=").concat(Url.getQuery('action', obj.url)); } } if (!((reportUrl === '/mp/getappmsgext' || reportUrl === '/mp/getappmsgad') && typeof resData.base_resp.ret === 'undefined')) { window.WX_BJ_REPORT.BadJs.report(reportUrl, "ret=".concat(resData.base_resp.ret), { mid: window.PAGE_MID, view: 'wap_retcode' }); } } } catch (e) { console.error(e); obj.error && obj.error(null, { type: 1, error: e, status: res.statusCode }); obj.complete && obj.complete(); reqLogItem.endTime = Date.now(); reqLogItem.response = res; networkEndLog(reqLogItem); return; } } var tmpResData = {}; try { tmpResData = JSON.parse(res.data); } catch (e) {} if (tmpResData && tmpResData.base_resp && tmpResData.base_resp.ret === -3 && retryTime < 2 && (mmVersion.isIOS || mmVersion.isAndroid && mmVersion.getInner() > '27000600')) { var _retryTime = retryTime++; JSAPI.invoke('updatePageAuth', {}, function (res) { console.log('[skeleton] updatePageAuth', res); monitor$1.setSum(112287, 3, 1); if (res && res.err_msg && res.err_msg.indexOf(':ok') > -1) { window.top.pass_ticket = encodeURIComponent(Url.getQuery('pass_ticket', res.fullUrl).html(false).replace(/\s/g, '+')); if (obj.pass_ticket) { obj.pass_ticket = window.top.pass_ticket; } console.warn('[skeleton] updatePageAuth resetTopbar'); var supportNewTopBar = mmVersion.isIOS && mmVersion.gtVersion('7.0.10', true); var showBottomBar = !!window.is_login; if (window.top.item_show_type === '0' && supportNewTopBar) { var _top = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop || 0; setCurrentMpInfo(_top > 40 && !showBottomBar); } try { obj.url = Url.addParam(obj.url, 'retry', _retryTime, true); } catch (err) { console.error(err); } jsapiRequest(obj, data); monitor$1.setSum(112287, 4, 1); } else { obj.success && obj.success(resData); obj.complete && obj.complete(); if (mmVersion.isIOS) { monitor$1.setSum(112287, 35, 1); } else { monitor$1.setSum(112287, 36, 1); } reqLogItem.status = 200; reqLogItem.endTime = Date.now(); reqLogItem.response = resData; networkEndLog(reqLogItem); } }); } else { obj.success && obj.success(resData); obj.complete && obj.complete(); reqLogItem.status = 200; reqLogItem.endTime = Date.now(); reqLogItem.response = resData; networkEndLog(reqLogItem); } } else if (res.err_msg.indexOf('no permission') > -1 || !mmVersion.isOnlyWechat) { Ajax(obj); if (res.err_msg.indexOf('no permission') > -1) { console.warn('[JSAPI Request] No permission'); monitor$1.setSum(112287, 31, 1); } reqLogItem.status = 302; reqLogItem.endTime = Date.now(); reqLogItem.response = res; networkEndLog(reqLogItem); } else { obj.error && obj.error(null, { type: 3, error: res, status: 0 }); obj.complete && obj.complete(); monitor$1.setSum(112287, 32, 1); var sample = 0.001; if (Math.random() < sample) { var msg = "request: ".concat(JSON.stringify(obj.type), " ").concat(JSON.stringify(obj.url), " ;;;; cookie: ").concat(JSON.stringify(document.cookie), " ;;;; data: ").concat(JSON.stringify(data), " ;;;; resp: ").concat(JSON.stringify(res)); if (window.WX_BJ_REPORT && window.WX_BJ_REPORT.BadJs) { window.WX_BJ_REPORT.BadJs.report('ajax_wx_request_error', msg, { mid: 'mmbizwap:Monitor' }); } } reqLogItem.status = 400; reqLogItem.endTime = Date.now(); reqLogItem.response = res; networkEndLog(reqLogItem); } }); }; if (reqType(obj, '/mp/getappmsgext')) { window.startGetAppmsgExtTime = Date.now(); } if (reqType(obj, '/mp/getappmsgad')) { window.startGetAppmsgAdTime = Date.now(); } return jsapiRequest(obj, data); } var ajax = function ajax(obj) { if (window.__second_open_wait_a8key__ && window.__second_open_wait_a8key_task__) { window.__second_open_wait_a8key_task__.push(function () { ajax(obj); }); return; } if (!mmVersion.isWxWork && (window.__second_open__ || !isAcrossOrigin && top.window.__second_open__) && window.__is_page_auth_return__) { return AjaxWx(obj); } return Ajax(obj); }; var isx5 = navigator.userAgent.indexOf('TBS/') !== -1; var getDataFunc = []; var reportData = []; var specificData = {}; function joinUrl(url) { var obj = {}; if (typeof window.uin !== 'undefined') { obj.uin = window.uin; } if (typeof window.key !== 'undefined') { obj.key = window.key; } if (typeof window.pass_ticket !== 'undefined') { obj.pass_ticket = window.pass_ticket; } if (typeof window.wxtoken !== 'undefined') { obj.wxtoken = window.wxtoken; } if (typeof window.devicetype !== 'undefined') { obj.devicetype = window.devicetype; } if (typeof window.clientversion !== 'undefined') { obj.clientversion = window.clientversion; } if (typeof window.appmsg_token !== 'undefined') { obj.appmsg_token = window.appmsg_token; } else if (url.indexOf('advertisement_report') > -1) { new Image().src = "".concat(location.protocol, "//mp.weixin.qq.com/mp/jsmonitor?idkey=68064_13_1&r=").concat(Math.random()); } obj.x5 = isx5 ? '1' : '0'; obj.f = 'json'; return Url.join(url, obj); } function isObj(obj) { return obj && _typeof(obj) === 'object'; } function assign(target, source) { if (isObj(target) && isObj(source)) { for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } } function assembleReportData(initiative) { var leaveReportLog = []; leaveReportLog.push({ content: "[LeaveReport] specificData keys: ".concat(Object.keys(specificData)), timestamp: Date.now() }); Log.log("[LeaveReport] specificData keys: ".concat(Object.keys(specificData))); console.log("[LeaveReport] specificData keys: ".concat(Object.keys(specificData))); var allReportData = {}; for (var reportField in specificData) { if (!allReportData[reportField]) { allReportData[reportField] = {}; } for (var i = 0; i < specificData[reportField].length; i++) { var param = specificData[reportField][i]; if (typeof param === 'function') { try { assign(allReportData[reportField], param(initiative)); } catch (err) { leaveReportLog.push({ content: "[LeaveReport] specificData exec error: ".concat(param.toString().substring(0, 50)), timestamp: Date.now() }); Log.error("[LeaveReport] specificData exec error: ".concat(param.toString().substring(0, 50))); console.error("[LeaveReport] specificData exec error: ".concat(param.toString().substring(0, 50))); } } else if (isObj(param)) { assign(allReportData[reportField], param); } } } leaveReportLog.push({ content: "[LeaveReport] reportData.length: ".concat(reportData.length), timestamp: Date.now() }); Log.log("[LeaveReport] reportData.length: ".concat(reportData.length)); console.log("[LeaveReport] reportData.length: ".concat(reportData.length)); leaveReportLog.push({ content: "[LeaveReport] getDataFunc.length: ".concat(getDataFunc.length), timestamp: Date.now() }); Log.log("[LeaveReport] getDataFunc.length: ".concat(getDataFunc.length)); console.log("[LeaveReport] getDataFunc.length: ".concat(getDataFunc.length)); for (var _i = 0; _i < getDataFunc.length; _i++) { try { var data = getDataFunc[_i](initiative); if (isObj(data)) { reportData.push(data); } } catch (err) { leaveReportLog.push({ content: "[LeaveReport] getDataFunc exec error: ".concat(getDataFunc[_i].toString().substring(0, 50)), timestamp: Date.now() }); Log.error("[LeaveReport] getDataFunc exec error: ".concat(getDataFunc[_i].toString().substring(0, 50))); console.error("[LeaveReport] getDataFunc exec error: ".concat(getDataFunc[_i].toString().substring(0, 50))); } } for (var _i2 = 0; _i2 < reportData.length; _i2++) { if (reportData[_i2].reportUrl) { reportData[_i2].reportUrl = joinUrl(reportData[_i2].reportUrl); } } allReportData.data = { 'requestList': reportData }; leaveReportLog.push({ content: "[LeaveReport] final reportData.length: ".concat(reportData.length, ", data=").concat(JSON.stringify(reportData)), timestamp: Date.now() }); Log.log("[LeaveReport] final reportData.length: ".concat(reportData.length)); console.log("[LeaveReport] final reportData.length: ".concat(reportData.length)); allReportData.info = leaveReportLog; return allReportData; } function addReport(param) { if (typeof param === 'function') { getDataFunc.push(param); } else if (isObj(param)) { reportData.push(param); } } function addSpecificReport(reportField, param) { if (!specificData[reportField]) { specificData[reportField] = []; } specificData[reportField].push(param); } function reportNow(callback) { var allReportData = assembleReportData(true); JSAPI.invoke('handleMPPageAction', { action: 'reportByLeaveForMPGateway', reportData: allReportData }, function (res) { if (res && res.err_msg && res.err_msg.indexOf(':ok') !== -1) { getDataFunc = []; reportData = []; specificData = {}; typeof callback === 'function' && callback(res); } else { getDataFunc = []; reportData = []; var len = allReportData.data.requestList.length; allReportData.data.requestList.forEach(function (req) { if (req.reportUrl) { ajax({ type: req.method || 'GET', url: req.reportUrl, data: req.reportData, async: false, success: function success(resp) { if (--len < 0) { typeof callback === 'function' && callback({ err_msg: 'handleMPPageAction:ok', fallback: true, resp: resp }); } }, error: function error(xhr, err) { if (--len < 0) { typeof callback === 'function' && callback({ err_msg: 'handleMPPageAction:fail', fallback: true, err: err }); } } }); } }); } }); } var leaveReport = { reportNow: reportNow, addReport: addReport, addSpecificReport: addSpecificReport }; var _leaveReport = (function () { var doc = {}; var isCrossOrigin = false; try { doc = top.window.document; } catch (e) { isCrossOrigin = true; } if (!isCrossOrigin && top.window.__leaveReport) { return top.window.__leaveReport; } if (window.__leaveReport) { return window.__leaveReport; } JSAPI.on('reportOnLeaveForMP', function () { return assembleReportData(false); }); return window.__leaveReport = leaveReport; })(); var getReportJson = function getReportJson(logId, rawData) { var data = JSON.parse(JSON.stringify(rawData)); data.log_id = Number(logId); data.TimeStamp = Math.round(Date.now() / 1000); console.log('[comm_report] reportjson: ', data); return JSON.stringify(data); }; var getSuccessHandler = function getSuccessHandler(logId, data, opt) { return function (res) { if (res && res.err_code !== 0) { console.warn("[comm_report] report ".concat(logId, " fail: "), res.err_msg, data); } if (typeof opt.success === 'function') { opt.success(res); } }; }; var getErrorHandler = function getErrorHandler(logId, data, opt) { return function (xhr, info) { console.error("[comm_report] report ".concat(logId, " error: "), info, data); if (typeof opt.error === 'function') { opt.error(xhr, info); } }; }; var batchReportDataArr = []; var blackLogId = [25587, 18832, 28208, 25574, 29139, 10945]; var BATCH_SIZE = 4; var BATCH_TIME = 1000; var getRepeatedReportJson = function getRepeatedReportJson() { if (!batchReportDataArr || !batchReportDataArr.length) return false; var reportData = { count: 0 }; reportData.count = batchReportDataArr.length; batchReportDataArr.forEach(function (data, index) { reportData["reportjson".concat(index)] = data; }); batchReportDataArr = []; console.log('[reportData]: ', reportData); return reportData; }; var timeOutId; function batchReport() { if (!batchReportDataArr || !batchReportDataArr.length) return; var repeatedReportJson = getRepeatedReportJson(); if (!repeatedReportJson) return; ajax({ type: 'POST', dataType: 'json', url: '/mp/wapcommreport?action=batch_report', data: repeatedReportJson, success: function success(res) { if (res && res.err_code) { console.warn("[comm_report] batch report fail: ", res.err_msg, batchReportDataArr); } }, error: function error(xhr, info) { console.error("[comm_report] batch report error: ", info, batchReportDataArr); } }); } function batchReportThrottle(logId, rawData) { var reportJsonData = getReportJson(logId, rawData); if (!reportJsonData) return; batchReportDataArr.push(reportJsonData); if (batchReportDataArr.length >= BATCH_SIZE) { batchReport(); } else { if (!timeOutId) { timeOutId = setTimeout(function () { batchReport(); clearTimeout(timeOutId); timeOutId = null; }, BATCH_TIME); } } } _leaveReport.addReport(function () { var repeatedReportJson = getRepeatedReportJson(); if (!repeatedReportJson) return false; var reportData = []; for (var _i = 0, _Object$entries = Object.entries(repeatedReportJson); _i < _Object$entries.length; _i++) { var _Object_i = _slicedToArray(_Object$entries[_i], 2), key = _Object_i[0], value = _Object_i[1]; reportData.push("".concat(key, "=").concat(encodeURIComponent(value))); } return { reportUrl: 'https://mp.weixin.qq.com/mp/wapcommreport?action=batch_report', reportData: reportData.join('&'), method: 'POST' }; }); var commReport = { report: function report(logId, rawData, rawOpt) { var opt = rawOpt || {}; if (!opt.realTime && !blackLogId.includes(logId)) { batchReportThrottle(logId, rawData); } else { ajax({ type: 'POST', dataType: 'json', url: '/mp/wapcommreport', data: { reportjson: getReportJson(logId, rawData) }, async: opt.async, success: getSuccessHandler(logId, rawData, opt), error: getErrorHandler(logId, rawData, opt) }); } }, leaveReport: function leaveReport(logId, rawData) { _leaveReport.addReport(function () { var data = typeof rawData === 'function' ? rawData() : rawData; if (!data) { return false; } return { reportUrl: 'https://mp.weixin.qq.com/mp/wapcommreport', reportData: "reportjson=".concat(encodeURIComponent(getReportJson(logId, data))), method: 'POST' }; }); }, reportByBeacon: function reportByBeacon(logId, rawData) { try { if (!Device.os.android && !Device.os.ios) { var data = typeof rawData === 'function' ? rawData() : rawData; if (!data) { return false; } var url = '/mp/wapcommreport'; var reportJsonData = encodeURIComponent(getReportJson(logId, data)); console.log("reportByBeacon", JSON.stringify(reportJsonData)); navigator.sendBeacon(Url.joinUrl(url), "reportjson=".concat(reportJsonData)); } else { _leaveReport.addReport(function () { var data = typeof rawData === 'function' ? rawData() : rawData; if (!data) { return false; } return { reportUrl: 'https://mp.weixin.qq.com/mp/wapcommreport', reportData: "reportjson=".concat(encodeURIComponent(getReportJson(logId, data))), method: 'POST' }; }); } } catch (error) { console.log(error); } } }; var isIOS = mmVersion.isIOS, getInner = mmVersion.getInner, isAndroid = mmVersion.isAndroid; var renderDom = function renderDom(dom, cnt, hasStar) { if (dom) { if (hasStar) { dom.innerText = "已星标"; } else { dom.innerText = "星标"; } if (hasStar) { dom.classList.add('rich_media_meta_star'); dom.classList.remove('rich_media_meta_star_cancel'); } else { dom.classList.add('rich_media_meta_star_cancel'); dom.classList.remove('rich_media_meta_star'); } dom.style.removeProperty('display'); var feedBack = document.querySelector('#js_problem_feedback'); feedBack && feedBack.parentNode.removeChild(feedBack); } }; var __setStar = function __setStar(dom, cnt, statStatus) { var hasReportExpose = false; var hasStar = statStatus; var realCnt = cnt; function addStar() { var dispatchEvent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; localStorage.setItem('star_info', JSON.stringify({ mid: window.mid, has_star: true })); hasStar = 1; realCnt = realCnt + 1; console.log('realCnt' + realCnt); renderDom(dom, realCnt, hasStar); if (dispatchEvent) window.dispatchEvent(new CustomEvent('star')); } function cancelStar() { var dispatchEvent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; console.log('cancelStar'); localStorage.setItem('star_info', JSON.stringify({ mid: window.mid, has_star: false })); hasStar = 0; realCnt = realCnt - 1; console.log('realCnt' + realCnt); renderDom(dom, realCnt, hasStar); if (dispatchEvent) window.dispatchEvent(new CustomEvent('cancel-star')); } if (dom) { renderDom(dom, cnt, statStatus); var clickHander = function clickHander() { if (hasStar === 0) { JSAPI.invoke('operateStar', { opType: 'addStar' }, function (res) { if (res.err_msg && /:ok$/.test(res.err_msg)) addStar(); }); } else { JSAPI.invoke('operateStar', { opType: 'cancelStar' }, function (res) { if (res.err_msg && /:ok$/.test(res.err_msg)) cancelStar(); }); } var data = { BizUin: window.biz, AppMsgID: window.mid * 1, ItemIndex: window.idx * 1, Scene: window.scene, SubScene: window.subscene * 1, EnterId: window.enterid, SessionId: "".concat(window.sessionid), Event: hasStar ? 8 : 7, ItemShowType: window.item_show_type * 1 }; commReport.report(17335, data); }; var exposeHandler = function exposeHandler() { if (hasReportExpose) return; var data = { BizUin: window.biz, AppMsgID: window.mid * 1, ItemIndex: window.idx * 1, Scene: window.scene, SubScene: window.subscene * 1, EnterId: window.enterid, SessionId: "".concat(window.sessionid), Event: 6, ItemShowType: window.item_show_type * 1 }; commReport.report(17335, data); hasReportExpose = true; }; dom.addEventListener('click', clickHander); JSAPI.on('onPageStarStateChanged', function (res) { console.log('onPageStarStateChanged', res); if (res.state) addStar();else cancelStar(); }); var intersectionObserver = new IntersectionObserver(exposeHandler); intersectionObserver.observe(dom); window.addEventListener('star', function (e) { if (e && e.detail && e.detail.from === 'frontend') addStar(false); }); window.addEventListener('cancel-star', function (e) { if (e && e.detail && e.detail.from === 'frontend') cancelStar(false); }); } }; if (!window.__second_open__) { var starDom = document.querySelector('#js_star'); var canUseStar = window.canUseStar || isIOS && getInner() >= '18003623' || isAndroid && getInner() >= '28003630'; var startPersonCnt = window.star_person_cnt || ''; console.log('canUseStar, startPersonCnt', canUseStar, startPersonCnt); if (!!(canUseStar * 1)) { var starSwitch = localStorage.getItem('mp_star_switch'); if (starSwitch === 'true') { var starInfo = localStorage.getItem('star_info'); var hasStar = 0; if (starInfo) { var parseStarInfo = JSON.parse(starInfo); if (Number(parseStarInfo.mid) === Number(window.mid) && parseStarInfo.has_star) { hasStar = 1; } } starDom && renderDom(starDom, startPersonCnt * 1, hasStar); var spanElement = document.getElementById('meta_content_hide_info'); spanElement && spanElement.classList.remove('rich_media_meta_padding'); } else { starDom && starDom.parentNode.removeChild(starDom); } } else { starDom && starDom.parentNode.removeChild(starDom); } window.__setStar = __setStar; } exports.__setStar = __setStar; exports.renderDom = renderDom; Object.defineProperty(exports, '__esModule', { value: true }); return exports; })({});</script><script type="text/javascript" nonce="1989770072" reportloaderror>var __INLINE_SCRIPT__ = (function () { 'use strict'; function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } var ua = navigator.userAgent; var is_ios = /(iPhone|iPad|iPod|iOS)/i.test(ua); var is_wp = /Windows\sPhone/i.test(ua); var is_android = /(Android)/i.test(ua); var is_wechat = /MicroMessenger\/([\d\.]+)/i.test(ua); var is_mac = /mac\sos/i.test(ua) && !is_ios; var is_windows = /windows\snt/i.test(ua) && !is_wp; var is_mpapp = /MPAPP\/([\d\.]+)/i.test(ua); var is_ipad = /iPad/i.test(ua); var is_windows_wechat = /WindowsWechat/i.test(ua); var is_mac_wechat = /MacWechat/i.test(ua) || /wechat.*mac os/i.test(ua); var is_prefetch = is_wechat && window.WeixinPrefecherJSBridge; var is_donut_app = /SAAASDK/i.test(ua); var is_harmony = /OpenHarmony|ArkWeb/i.test(ua); var is_in_miniProgram = is_android && /miniprogram/.test(ua.toLowerCase()) || window.__wxjs_environment == 'miniprogram'; var is_wx_work = /wxwork/i.test(ua); function getUrlParams() { var vars = location.search.substring(1).split('&'); var params = {}; var _iterator = _createForOfIteratorHelper(vars), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var ele = _step.value; var pair = ele.split('='); var key = decodeURIComponent(pair[0]); if (typeof params[key] === 'undefined') { params[key] = decodeURIComponent(pair[1]); } } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } return params; } function get() { var reg = /MicroMessenger\/([\d\.]+)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1]; } return false; } function getMac() { var reg = /MacWechat\/([\d\.]+)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1]; } return false; } function getMacOS() { var reg = /Mac OS X ([\d_]+)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1].replace(/_/g, '.'); } return false; } function getWindows() { var reg = /WindowsWechat\(0x(.+?)\)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1]; } return false; } function getWxWork() { var reg = /wxwork\/([\d\.]+)/i; var ret = ua.match(reg); if (ret && ret[1]) { return ret[1]; } return false; } function getMpApp() { var appVersion = [2, 4, 5]; var match = navigator.userAgent.match(/MPAPP\/(\d+(\.\d+)*)/); if (match) { appVersion = match[1].split('.').map(function (v) { return Number(v); }); } return appVersion.join('.'); } function getUnifiedPcVer() { var versionInfo = navigator.userAgent.match(/UnifiedPC\w+Wechat\(0xf\w{2}(\w+?)\w{2}\)/); if (versionInfo && versionInfo.length === 2) { var version = versionInfo[1]; var mainVersion = getVersionNumber(version.slice(0, 1)); var subVersion = getVersionNumber(version.slice(1, 2)); var subVersion2 = getVersionNumber(version.slice(2, 3)); return [mainVersion, subVersion, subVersion2].join('.'); } } function getVersionNumber(hexStr) { return Number(Number("0x".concat(hexStr)).toString(10)); } function getWindowsVersionFormat() { var versionInfo = navigator.userAgent.match(/WindowsWechat\(0x(\w+?)\)/); if (versionInfo && versionInfo.length === 2) { var version = versionInfo[1]; var mainVersion = getVersionNumber(version.slice(1, 2)); var subVersion = getVersionNumber(version.slice(2, 4)); var subVersion2 = getVersionNumber(version.slice(4, 6)); return [mainVersion, subVersion, subVersion2].join('.'); } return false; } function getInner() { var reg = /MicroMessenger\/[\d\.]+\(0x(.+?)\)/i; var ret = ua.match(reg); if (ret && ret[1] && ret[1] != null) { return ret[1]; } if (!ret && /MicroMessenger\/[\d\.]+/i.test(ua)) { var urlParams = getUrlParams(); if (urlParams.version) { return urlParams.version; } } return false; } var opfunc = { 'cp-1': function cp1(a, b) { return a < b; }, cp0: function cp0(a, b) { return a === b; }, cp1: function cp1(a, b) { return a > b; } }; function cpVersion(ver, op, canEq, type) { var mmver = false; switch (type) { case 'mac': mmver = getMac(); break; case 'windows': mmver = getWindowsVersionFormat(); break; case 'wxwork': mmver = getWxWork(); break; case 'mpapp': mmver = getMpApp(); break; case 'unifiedpc': mmver = getUnifiedPcVer(); break; default: mmver = get(); break; } if (!mmver) { return; } var mmversion = mmver.split('.'); var version = ver.split('.'); if (!/\d+/g.test(mmversion[mmversion.length - 1])) { mmversion.pop(); } for (var i = 0, len = Math.max(mmversion.length, version.length); i < len; ++i) { var mmv = mmversion[i] || ''; var v = version[i] || ''; var mmvn = parseInt(mmv, 10) || 0; var vn = parseInt(v, 10) || 0; var eq = opfunc.cp0(mmvn, vn); if (eq) { continue; } var cp = opfunc["cp".concat(op)]; return cp(mmvn, vn); } return canEq || op === 0; } function eqVersion(version) { return cpVersion(version, 0); } function gtVersion(version, canEq) { return cpVersion(version, 1, canEq); } function ltVersion(version, canEq) { return cpVersion(version, -1, canEq); } function getPlatform() { if (is_ios) { return 'ios'; } if (is_android) { return 'android'; } if (is_mac) { return 'mac_os'; } if (is_windows) { return 'windows'; } return 'unknown'; } var is_google_play = false; var inner_ver_for_google_play_check = getInner(); if (is_android && inner_ver_for_google_play_check) { var v = "0x".concat(inner_ver_for_google_play_check.substr(-2)); if (parseInt(v) >= 64 && parseInt(v) <= 79) { is_google_play = true; } } var mmversion = { get: get, getMac: getMac, getMacOS: getMacOS, getWindows: getWindows, getInner: getInner, getWxWork: getWxWork, getMpApp: getMpApp, cpVersion: cpVersion, eqVersion: eqVersion, gtVersion: gtVersion, ltVersion: ltVersion, getPlatform: getPlatform, getVersionNumber: getVersionNumber, isWp: is_wp, isIOS: is_ios, isAndroid: is_android, isHarmony: is_harmony, isHarmonyWechat: is_harmony && is_wechat && cpVersion('1.0.0', 1, true), isInMiniProgram: is_in_miniProgram, isWechat: is_wechat, isMac: is_mac, isWindows: is_windows, isMacWechat: is_mac_wechat, isWindowsWechat: is_windows_wechat, isWxWork: is_wx_work, isOnlyWechat: is_wechat && !is_wx_work, isMpapp: is_mpapp, isNewMpApp: false, isIPad: is_ipad, isGooglePlay: is_google_play, isPrefetch: is_prefetch, isDonutAPP: is_donut_app }; function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); } function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); } function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } var prefix = '__WXLS__'; var localStorage$1 = window.localStorage || { getItem: function getItem() {}, setItem: function setItem() {}, removeItem: function removeItem() {}, key: function key() {}, clear: function clear() { var _a, _b; (_b = (_a = window.localStorage) === null || _a === void 0 ? void 0 : _a.clear) === null || _b === void 0 ? void 0 : _b.call(_a); }, length: 0 }; var evictionPolicies = { noeviction: function noeviction(data) { return data; }, 'allkeys-random': function allkeysRandom(data, size) { var keys = Object.keys(data); var memCnt = 0; while (memCnt < size) { var len = keys.length; var randomKeyIdx = Math.floor(Math.random() * len); var randomKey = keys[randomKeyIdx]; memCnt += JSON.stringify(data[randomKey]).length; delete data[randomKey]; keys = Object.keys(data); } return data; }, 'volatile-ttl': function volatileTtl(data, size) { var keys = Object.keys(data); keys = keys.sort(function (key1, key2) { var d1 = data[key1]; var d2 = data[key2]; if (d1.exp < d2.exp) return -1; if (d1.exp > d2.exp) return 1; return 0; }); var memCnt = 0; for (var i = 0; i < keys.length; i++) { if (memCnt >= size) break; var key = keys[i]; memCnt += JSON.stringify(data[key]).length; delete data[key]; } return data; }, 'clear-all': function clearAll() { localStorage$1.clear(); return {}; } }; function formatLogMsg(str) { return "[WXLS] ".concat(str); } var LS = function () { function LS(func, evictionPolicy, logger) { _classCallCheck(this, LS); this.logger = function () {}; if (!func) throw 'require function name.'; this.evictionPolicy = 'noeviction'; this.key = func; if (typeof logger === 'function') { this.logger = function (str, type) { return logger(formatLogMsg(str), type); }; } if (evictionPolicy && Object.keys(evictionPolicies).indexOf(evictionPolicy) !== -1) { this.evictionPolicy = evictionPolicy; } this.init(); } _createClass(LS, [{ key: "init", value: function init() { var _a, _b; this.check(); if (Math.random() * 1000 < 1) { (_a = this.logger) === null || _a === void 0 ? void 0 : _a.call(this, "LSlen: ".concat(((_b = window === null || window === void 0 ? void 0 : window.localStorage) === null || _b === void 0 ? void 0 : _b.length) || localStorage$1.length), 'report'); } } }, { key: "getData", value: function getData() { var data = LS.getItem(this.key) || '{}'; try { data = JSON.parse(data); } catch (e) { this.logger("getData error: ".concat(e), 'error'); localStorage$1.removeItem(prefix + this.key); data = {}; } return data; } }, { key: "check", value: function check(isReturn) { var data = this.getData(); var temp = {}; var now = +new Date(); var key; var val; for (key in data) { val = data[key]; if (+val.exp > now) { temp[key] = val; } } this.logger("check info: isReturn:".concat(isReturn, " data:").concat(JSON.stringify(temp)), 'info'); if (isReturn) return temp; LS.setItem(this.key, JSON.stringify(temp), this.logger); } }, { key: "set", value: function set(key, val, exp) { var _a, _b; var data = this.check(true); data[key] = { val: val, exp: exp || +new Date() }; try { if (localStorage$1.getItem(prefix + this.key)) localStorage$1.removeItem(prefix + this.key); localStorage$1.setItem(prefix + this.key, JSON.stringify(data)); this.logger("first set success: LSlen:".concat((_a = window === null || window === void 0 ? void 0 : window.localStorage) === null || _a === void 0 ? void 0 : _a.length, " key:").concat(prefix + this.key, " data:").concat(JSON.stringify(data)), 'success'); } catch (e) { this.logger("first set error: LSlen:".concat((_b = window === null || window === void 0 ? void 0 : window.localStorage) === null || _b === void 0 ? void 0 : _b.length, " error:").concat(e, " key:").concat(prefix + this.key, " data:").concat(JSON.stringify(data), " k:").concat(key, " v:").concat(val, " exp:").concat(exp), 'error'); localStorage$1.clear(); LS.setItem(this.key, JSON.stringify(_defineProperty({}, key, { val: val, exp: exp || +new Date() })), this.logger); } } }, { key: "get", value: function get(key) { var data = this.getData(); data = data[key]; return data ? data.val || null : null; } }, { key: "remove", value: function remove(key) { var data = this.getData(); if (data[key]) delete data[key]; LS.setItem(this.key, JSON.stringify(data), this.logger); } }], [{ key: "getItem", value: function getItem(key) { key = prefix + key; return localStorage$1.getItem(key); } }, { key: "setItem", value: function setItem(key, val, logger) { var _a, _b; key = prefix + key; var n = 3; while (n--) { try { if (localStorage$1.getItem(key)) localStorage$1.removeItem(key); localStorage$1.setItem(key, val); typeof logger === 'function' && logger("setItem success: LSlen:".concat((_a = window === null || window === void 0 ? void 0 : window.localStorage) === null || _a === void 0 ? void 0 : _a.length, " key:").concat(key, " val:").concat(val), 'success'); break; } catch (e) { typeof logger === 'function' && logger("setItem error: LSlen:".concat((_b = window === null || window === void 0 ? void 0 : window.localStorage) === null || _b === void 0 ? void 0 : _b.length, " error:").concat(e, " key:").concat(key, " val:").concat(val), 'error'); LS.clear(); } } } }, { key: "clear", value: function clear() { var i; var k; for (i = localStorage$1.length - 1; i >= 0; i--) { k = localStorage$1.key(i); if (k.indexOf(prefix) == 0) { localStorage$1.removeItem(k); } } } }, { key: "getSupportEvicationPolicy", value: function getSupportEvicationPolicy() { return Object.keys(evictionPolicies); } }]); return LS; }(); var key = 'stream_last_read_pos'; new LS(key); var interactionStatusLS = new LS('bottom_interaction_status'); function getInteractionStatus(opt) { var biz = opt.biz || window.biz; var sn = opt.sn || window.sn; var mid = opt.mid || window.mid; var idx = opt.idx || window.idx; var interactionStatusKey = [biz, sn, mid, idx].join('_'); var interactionStatusInfo = interactionStatusLS.get(interactionStatusKey); if (Object.prototype.toString.call(interactionStatusInfo) !== '[object Object]') { interactionStatusInfo = {}; } return interactionStatusInfo; } var __setBarData = function __setBarData(appmsgBarData, cgiData) { if (!appmsgBarData) { return; } function formatReadNum(value) { var unit = '万'; if (window.LANG === 'en') { unit = 'k'; } var result = ''; if (parseInt(value, 10) > 100000) { result = 10 + unit + '+'; } else if (parseInt(value, 10) > 10000 && parseInt(value, 10) <= 100000) { var num = '' + parseInt(value, 10) / 10000; var dotIndex = num.indexOf('.'); if (dotIndex === -1) { result = num + unit; } else { result = num.substr(0, dotIndex) + '.' + num.charAt(dotIndex + 1) + unit; } } else if (parseInt(value, 10) === 0) { result = ''; } else { result = value || ''; } return result; } try { var bottomBarSafeBottomKey = '__bottom_bar_safe_bottom__'; var bottomBarSafeBottom = localStorage.getItem(bottomBarSafeBottomKey); if (bottomBarSafeBottom) { document.documentElement.style.setProperty('--immersive-safe-bottom', bottomBarSafeBottom); } var barOldlikeBtn = document.getElementById('js_bar_oldlike_btn'); var barShareBtn = document.getElementById('js_bar_share_btn'); var barLikeBtn = document.getElementById('js_bar_like_btn'); var barCommentBtn = document.getElementById('js_bar_comment_btn'); var barCollectBtn = document.getElementById('js_bar_collect_btn'); var barSubscribeBtn = document.getElementById('js_bar_subscribe_btn'); var oldLikeEl = barOldlikeBtn && barOldlikeBtn.parentElement; var likeEl = barLikeBtn && barLikeBtn.parentElement; var interactionStatus = getInteractionStatus({ biz: cgiData.biz, mid: cgiData.mid, sn: cgiData.sn, idx: cgiData.idx }); if (interactionStatus.is_my_old_like) { oldLikeEl && oldLikeEl.classList.add('praised'); } if (interactionStatus.is_my_like) { likeEl && (appmsgBarData.show_friend_seen === 2 ? likeEl.classList.add('love_btn_loved') : likeEl.classList.add('like_btn_liked')); } var old_like_count = interactionStatus.old_like_count * 1 ? Math.max(interactionStatus.old_like_count * 1, appmsgBarData.old_like_count) : appmsgBarData.old_like_count || 0; var share_count = interactionStatus.share_count * 1 ? Math.max(interactionStatus.share_count * 1, appmsgBarData.share_count) : appmsgBarData.share_count || 0; var like_count = interactionStatus.like_count * 1 ? Math.max(interactionStatus.like_count * 1, appmsgBarData.like_count) : appmsgBarData.like_count || 0; var comment_count = appmsgBarData.comment_count || 0; var collect_count = appmsgBarData.collect_count || 0; if (old_like_count && barOldlikeBtn) { barOldlikeBtn.innerText = formatReadNum(old_like_count); } if (share_count && barShareBtn) { barShareBtn.innerText = formatReadNum(share_count); } if (like_count && barLikeBtn) { barLikeBtn.innerText = formatReadNum(like_count); } if (comment_count && barCommentBtn) { barCommentBtn.innerText = formatReadNum(comment_count); } if (collect_count && barCollectBtn) { barCollectBtn.innerText = formatReadNum(collect_count); } if (mmversion.isInMiniProgram) { if (barShareBtn) { barShareBtn.style.display = 'none'; } if (barLikeBtn) { barLikeBtn.style.display = 'none'; } } var tempbarPraiseBtn = document.getElementById('js_temp_sns_sc_praise_btn'); var tempbarShareBtn = document.getElementById('js_temp_sns_sc_share_btn'); var tempbarCollectBtn = document.getElementById('js_temp_sns_sc_collect_btn'); var tempbarLikeBtn = document.getElementById('js_temp_sns_sc_like_btn'); var tempbarCommentBtn = document.getElementById('js_temp_sns_sc_comment_btn'); var handleTempClick = function handleTempClick(_ref) { var type = _ref.type, val = _ref.val, sucCb = _ref.sucCb, failCb = _ref.failCb; if (typeof window.__click_temp_btm_bar_cb__ === 'function') { window.__click_temp_btm_bar_cb__({ type: type, val: val, sucCb: sucCb, failCb: failCb }); } else { if (!window.__wait_click_temp_btm_bar_cb__) window.__wait_click_temp_btm_bar_cb__ = []; window.__wait_click_temp_btm_bar_cb__.push(function () { window.__click_temp_btm_bar_cb__({ type: type, val: val, sucCb: sucCb, failCb: failCb }); }); } }; tempbarPraiseBtn && barOldlikeBtn && oldLikeEl && tempbarPraiseBtn.addEventListener('click', function () { var newPraiseStatus = !oldLikeEl.classList.contains('praised'); handleTempClick({ type: 'praise', val: newPraiseStatus, sucCb: function sucCb() { var readNum = 0; if (newPraiseStatus) { oldLikeEl.classList.add('praised'); readNum = formatReadNum(interactionStatus.is_my_old_like ? old_like_count : old_like_count + 1); } else { oldLikeEl.classList.remove('praised'); readNum = formatReadNum(interactionStatus.is_my_old_like ? Math.max(0, old_like_count - 1) : old_like_count); } barOldlikeBtn.innerText = readNum ? readNum : '赞'; } }); }); tempbarLikeBtn && barLikeBtn && likeEl && tempbarLikeBtn.addEventListener('click', function () { var newRecommendStatus = appmsgBarData.show_friend_seen === 2 ? !likeEl.classList.contains('love_btn_loved') : !likeEl.classList.contains('like_btn_liked'); handleTempClick({ type: 'recommend', val: newRecommendStatus, sucCb: function sucCb() { var recommendNum = 0; if (newRecommendStatus) { appmsgBarData.show_friend_seen === 2 ? likeEl.classList.add('love_btn_loved') : likeEl.classList.add('like_btn_liked'); recommendNum = formatReadNum(interactionStatus.is_my_like ? like_count : like_count + 1); } else { appmsgBarData.show_friend_seen === 2 ? likeEl.classList.remove('love_btn_loved') : likeEl.classList.remove('like_btn_liked'); recommendNum = formatReadNum(interactionStatus.is_my_like ? Math.max(0, like_count - 1) : like_count); } if (recommendNum) { barLikeBtn.innerText = recommendNum; } else { barLikeBtn.innerText = appmsgBarData.show_friend_seen === 2 ? '推荐' : '在看'; } } }); }); tempbarShareBtn && barShareBtn && tempbarShareBtn.addEventListener('click', function () { handleTempClick({ type: 'share' }); }); tempbarCollectBtn && barCollectBtn && tempbarCollectBtn.addEventListener('click', function () { handleTempClick({ type: 'collect' }); }); tempbarCommentBtn && barCommentBtn && tempbarCommentBtn.addEventListener('click', function () { handleTempClick({ type: 'comment' }); }); barSubscribeBtn && barSubscribeBtn.addEventListener('click', function () { handleTempClick({ type: 'subscribe' }); }); } catch (error) { console.log(error); } }; if (!window.__second_open__) { var tmpAppmsgBarData = { show_like: '' * 1, like_count: '' * 1, show_share: '' * 1, share_count: '' * 1, show_old_like: '' * 1, old_like_count: '' * 1, comment_enabled: '' * 1, comment_count: '' * 1, show_collect: '' * 1, collect_count: '' * 1, show_friend_seen: '' * 1, is_subscribed: '' * 1, verify_status: '' * 1, original_content_num: '$user_info.appmsg_bar_data.original_content_num.DATA$' * 1, friend_subscribe_count: '' * 1 }; var cgiData = { idx: '' , biz: '' , mid: '' , sn: '' , subcount_version: '' }; __setBarData(tmpAppmsgBarData, cgiData); window.__setBarData = __setBarData; } return __setBarData; })();</script><script type="text/javascript" nonce="1989770072" reportloaderror>(function () { 'use strict'; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); } function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); } function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); } var classWhiteList = ['rich_pages', 'blockquote_info', 'blockquote_biz', 'blockquote_other', 'blockquote_article', 'h5_image_link', 'img_loading', 'list-paddingleft-1', 'list-paddingleft-2', 'list-paddingleft-3', 'selectTdClass', 'noBorderTable', 'ue-table-interlace-color-single', 'ue-table-interlace-color-double', '__bg_gif', 'weapp_text_link', 'weapp_image_link', 'qqmusic_area', 'tc', 'tips_global', 'unsupport_tips', 'qqmusic_wrp', 'appmsg_card_context', 'appmsg_card_active', 'qqmusic_bd', 'play_area', 'icon_qqmusic_switch', 'pic_qqmusic_default', 'qqmusic_thumb', 'access_area', 'qqmusic_songname', 'qqmusic_singername', 'qqmusic_source', 'share_audio_context', 'flex_context', 'pages_reset', 'share_audio_switch', 'icon_share_audio_switch', 'share_audio_info', 'flex_bd', 'share_audio_title', 'share_audio_tips', 'share_audio_progress_wrp', 'share_audio_progress', 'share_audio_progress_inner', 'share_audio_progress_buffer', 'share_audio_progress_loading', 'share_audio_progress_loading_inner', 'share_audio_progress_handle', 'share_audio_desc', 'share_audio_length_current', 'share_audio_length_total', 'video_iframe', 'vote_iframe', 'res_iframe', 'card_iframe', 'weapp_display_element', 'weapp_card', 'app_context', 'weapp_card_bd', 'weapp_card_profile', 'radius_avatar', 'weapp_card_avatar', 'weapp_card_nickname', 'weapp_card_info', 'weapp_card_title', 'weapp_card_thumb_wrp', 'weapp_card_ft', 'weapp_card_logo', 'pay', 'pay__mask', 'ct_geography_loc_tip', 'subsc_context', 'subsc_btn', 'reset_btn', 'icon_subsc', 'weui-primary-loading', 'weui-primary-loading__dot', 'wxw-img', 'mp-caret', 'appmsg_poi_iframe', 'cpc_iframe', 'channels_iframe_wrp', 'channels_iframe', 'videosnap_video_iframe', 'videosnap_live_iframe', 'videosnap_image_iframe', 'channels_live_iframe', 'minishop_iframe_wrp', 'minishop_iframe', 'mp_profile_iframe', 'mp_profile_iframe_wrp', 'mp_search_iframe_wrp', 'appmsg_search_iframe_wrp', 'appmsg_search_iframe', 'vote_area', 'vote_iframe', 'mp_vote_iframe_wrp', 'mp_vote_iframe', 'qqmusic_iframe', 'blockquote_iframe', 'blockquote_tips_iframe', 'video_iframe', 'shopcard_iframe', 'topic_iframe', 'weapp_app_iframe', 'img_fail_iframe', 'mp_miniprogram_iframe', 'appmsg_cpslink_iframe', 'js_editor_mpcpslink', 'mp-cpslink-iframe-wrp', 'mp_common_sticker_iframe', 'mp_common_sticker_iframe_wrp', 'mp_common_product_iframe', 'mp_common_product_iframe_wrp', 'new_cps_iframe', 'redpackage_iframe', 'mp_redpacket_iframe_wrp', 'product_text_link', 'clmusic_iframe', 'clalbum_iframe', 'mp_common_custom_iframe_wrp', 'mp_common_custom_iframe']; var classWhiteListReg = [new RegExp('^editor__content__'), new RegExp('^wxw'), new RegExp('^js_'), new RegExp('^cps_inner'), new RegExp('^bizsvr_'), new RegExp('^code-snippet'), new RegExp('^wx_(?!text_underline)'), new RegExp('^wx-'), new RegExp('^icon_emoji_'), new RegExp('^custom_select_card') ]; var contentStyle = { classWhiteList: classWhiteList, classWhiteListReg: classWhiteListReg }; function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } function DomFilter (cgiOptData) { return function (Plugin) { var isMMVersionSetted = false; var contentDom = document.getElementById('js_content'); var classWhiteList = contentStyle.classWhiteList, classWhiteListReg = contentStyle.classWhiteListReg; var removeClassByWhiteList = function removeClassByWhiteList(node) { var classAttr = node.getAttribute('class'); if (classAttr) { var classList = classAttr.split(/\s+/); var newClassList = []; for (var i = 0, len = classList.length; i < len; ++i) { var className = classList[i]; if (className && classWhiteList.indexOf(className) != -1) { newClassList.push(className); } else { for (var j = 0, jl = classWhiteListReg.length; j < jl; j++) { if (classWhiteListReg[j].test(className)) { newClassList.push(className); break; } } } } node.setAttribute('class', newClassList.join(' ')); } }; var langBlackList = ['zh-cn', 'en-us']; var removeLangByBlackList = function removeLangByBlackList(node) { var langAttr = node.getAttribute('lang'); if (langAttr) { var lang = langAttr.toLowerCase(); for (var i = 0; i < langBlackList.length; i++) { if (lang === langBlackList[i]) { node.removeAttribute('lang'); return; } } } }; var isAccessMode = window.localStorage.getItem('isMpUserAccessibility'); var isCarton = (cgiOptData === null || cgiOptData === void 0 ? void 0 : cgiOptData.copyright_info.is_cartoon_copyright) || (cgiOptData === null || cgiOptData === void 0 ? void 0 : cgiOptData.user_info.is_care_mode) || isAccessMode === '1'; var bgPlaceholder = 'url("data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==")'; var lazyloadBackgroundImage = function lazyloadBackgroundImage(node) { if (window.__second_open__ && !isCarton && node && node.style && typeof node.getAttribute === 'function' && !node.getAttribute('data-lazy-bgimg')) { var bgImg = node.style.backgroundImage; var bgImgUrl = bgImg && bgImg.match(/url\(['"]?(.*?)['"]?\)/); if (bgImgUrl && bgImgUrl[1]) { node.style.backgroundImage = bgImg.replace(/url\(['"]?.*?['"]?\)/, bgPlaceholder); node.setAttribute('data-lazy-bgimg', bgImgUrl[1]); node.classList.add('wx_imgbc_placeholder'); } } }; return function (_Plugin) { _inherits(_class, _Plugin); function _class() { _classCallCheck(this, _class); return _callSuper(this, _class, arguments); } _createClass(_class, [{ key: "beforeConvertNode", value: function beforeConvertNode(el) { if (el && el.tagName) { var tagName = el.tagName.toLowerCase(); if (tagName !== 'iframe') { removeClassByWhiteList(el); removeLangByBlackList(el); lazyloadBackgroundImage(el); } else { if (el.getAttribute('class') === 'video_ad_iframe') { el.setAttribute('class', ''); } } } } }, { key: "afterConvertNode", value: function afterConvertNode(el) { if (!isMMVersionSetted) { var ua = navigator.userAgent; /(iPhone|iPad|iPod|iOS|mac\sos)/i.test(ua) ? contentDom.classList.add('fix_apple_default_style') : null; isMMVersionSetted = true; } if (el.style && el.style.webkitTextSizeAdjust !== '' && el.style.webkitTextSizeAdjust !== 'none') { el.style.webkitTextSizeAdjust = 'inherit'; } if (el.tagName === 'animate' && el.getAttribute('attributeName') === 'height') { var repeatCountVal = el.getAttribute('repeatCount'); if (repeatCountVal === 'indefinite' || repeatCountVal > '10') { if (el.getAttribute('begin') !== 'click' && el.getAttribute('end') !== 'click') { el.setAttribute('repeatCount', 'undefined'); el.setAttribute('attributeName', 'undefined'); new Image().src = 'https://mp.weixin.qq.com/mp/jsmonitor?idkey=306525_1_1'; } } } if (el.tagName === 'OL') { if ((el.parentNode === document.getElementById('js_content') || el.parentNode.getAttribute('id') === 'js_secopen_content') && el.getAttribute('style') && el.getAttribute('style').indexOf('padding-left') < 0) { if (el.childNodes.length >= 10 && el.childNodes.length < 100) { el.classList.add('extra-list-padding-level1'); el.style.paddingLeft = '2.2em'; } else if (el.childNodes.length > 100) { el.classList.add('extra-list-padding-level2'); el.style.paddingLeft = '3.2em'; } } } if (el.tagName === 'MP-STYLE-TYPE') { var styleType = parseInt(el.getAttribute('data-value'), 10); if (styleType === 3) { if (el.parentNode && el.parentNode.previousSibling) { var realLastP = el.parentNode.previousSibling; if ((realLastP.tagName === 'P' || realLastP.tagName === 'SECTION') && realLastP.style && !realLastP.style.marginBottom) { realLastP.style.marginBottom = '0'; } } } } } }]); return _class; }(Plugin); }; } if (!window.__second_open__ && window.Darkmode) { var cost = 0; window.Darkmode.extend([DomFilter()]); window.Darkmode.run(document.querySelectorAll('#js_content *'), { mode: '', defaultDarkBgColor: '', error: function error() { new Image().src = 'https://mp.weixin.qq.com/mp/jsmonitor?idkey=125617_0_1'; }, begin: function begin(isSwitch) { new Image().src = 'https://mp.weixin.qq.com/mp/jsmonitor?idkey=125617_2_1'; isSwitch && (new Image().src = 'https://mp.weixin.qq.com/mp/jsmonitor?idkey=125617_4_1'); cost = new Date() * 1; }, showFirstPage: function showFirstPage() { document.getElementById('js_content').style.removeProperty('opacity'); cost = new Date() * 1 - cost; var isTop = (document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop) === 0; if (cost <= 10) { new Image().src = 'https://mp.weixin.qq.com/mp/jsmonitor?idkey=125617_6_1'; isTop && (new Image().src = 'https://mp.weixin.qq.com/mp/jsmonitor?idkey=125617_13_1'); } else if (cost > 10 && cost <= 20) { new Image().src = 'https://mp.weixin.qq.com/mp/jsmonitor?idkey=125617_7_1'; isTop && (new Image().src = 'https://mp.weixin.qq.com/mp/jsmonitor?idkey=125617_14_1'); } else if (cost > 20 && cost <= 30) { new Image().src = 'https://mp.weixin.qq.com/mp/jsmonitor?idkey=125617_8_1'; isTop && (new Image().src = 'https://mp.weixin.qq.com/mp/jsmonitor?idkey=125617_15_1'); } else if (cost > 30 && cost <= 40) { new Image().src = 'https://mp.weixin.qq.com/mp/jsmonitor?idkey=125617_9_1'; isTop && (new Image().src = 'https://mp.weixin.qq.com/mp/jsmonitor?idkey=125617_16_1'); } else if (cost > 40 && cost <= 50) { new Image().src = 'https://mp.weixin.qq.com/mp/jsmonitor?idkey=125617_10_1'; isTop && (new Image().src = 'https://mp.weixin.qq.com/mp/jsmonitor?idkey=125617_17_1'); } else if (cost > 50 && cost <= 60) { new Image().src = 'https://mp.weixin.qq.com/mp/jsmonitor?idkey=125617_11_1'; isTop && (new Image().src = 'https://mp.weixin.qq.com/mp/jsmonitor?idkey=125617_18_1'); } else { new Image().src = 'https://mp.weixin.qq.com/mp/jsmonitor?idkey=125617_12_1'; isTop && (new Image().src = 'https://mp.weixin.qq.com/mp/jsmonitor?idkey=125617_19_1'); } } }); document.getElementById('js_content').style.removeProperty('visibility'); } })();</script><script type="text/javascript" nonce="1989770072" reportloaderror>var __INLINE_SCRIPT__ = (function (exports) { 'use strict'; function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); } function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); } function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _arrayLikeToArray$1(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray$1(arr); } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } function _unsupportedIterableToArray$1(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray$1(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$1(o, minLen); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray$1(arr) || _nonIterableSpread(); } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function updateProfileAttr(profiles, infos) { if (!profiles || !Array.isArray(profiles) || !infos || !Array.isArray(infos)) { return; } var _iterator = _createForOfIteratorHelper(profiles), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var profile = _step.value; var profileId = profile.getAttribute('data-id'); var profileInfo = findBizCardInfo(infos, profileId); if (profileInfo) { var is_biz_ban = profileInfo.is_biz_ban, original_num = profileInfo.original_num, biz_account_status = profileInfo.biz_account_status; profile.setAttribute('data-origin_num', original_num * 1); profile.setAttribute('data-is_biz_ban', is_biz_ban * 1); profile.setAttribute('data-isban', is_biz_ban * 1); profile.setAttribute('data-biz_account_status', biz_account_status * 1); } } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } } function findBizCardInfo(infos, id) { return infos.find(function (info) { return info.fakeid === id; }); } function dealWithProfileData(data) { var _data$biz_card; if (!window.__second_open__) { return data; } var profileData = (data === null || data === void 0 ? void 0 : (_data$biz_card = data.biz_card) === null || _databiz_card.list) || []; profileData.map(function (item) { return item['original_num'] = item['orignal_num']; }); return profileData; } function updateCustomElementAttrs(dom, data) { if (!dom || !data) return; var profiles = dom.querySelectorAll('mp-common-profile'); updateProfileAttr(Array.from(profiles), dealWithProfileData(data)); } function preprocessMpAudios(dom, data) { var voiceList = window.__second_open__ ? data === null || data === void 0 ? void 0 : data.voice_in_appmsg_list_json : data.voiceList; if (typeof voiceList === 'string') { try { voiceList = JSON.parse(voiceList); } catch (e) { return; } } if (!dom || !voiceList) return; var albumlist = []; if (voiceList.voice_in_appmsg && voiceList.voice_in_appmsg.length > 0) { albumlist = voiceList.voice_in_appmsg; } var mpvoices = _toConsumableArray(dom.querySelectorAll('mpvoice')); mpvoices.forEach(function (mpvoice) { var mpaudio = document.createElement('mp-common-mpaudio'); var attrs = mpvoice.getAttributeNames().reduce(function (acc, name) { if (name === 'data-trans_state' || name === 'err_tips') return acc; return _objectSpread(_objectSpread({}, acc), {}, _defineProperty({}, name, mpvoice.getAttribute(name))); }, {}); for (var key in attrs) { mpaudio.setAttribute(key, attrs[key]); } mpaudio.setAttribute('data-trans_state', 1); mpvoice.parentNode.replaceChild(mpaudio, mpvoice); }); var mpaudios = _toConsumableArray(dom.querySelectorAll('mp-common-mpaudio')); mpaudios.forEach(function (mpaudio) { mpaudio.style.opacity = 0; mpaudio.setAttribute('author', data.nick_name || ''); var album = albumlist.find(function (a) { var voice_encode_fileid = mpaudio.getAttribute('voice_encode_fileid'); try { voice_encode_fileid = decodeURIComponent(voice_encode_fileid); } catch (e) {} return a.voice_id === voice_encode_fileid && a.appmsgalbuminfo; }); if (album) { mpaudio.setAttribute('data-topic_id', album.appmsgalbuminfo.album_id || 0); mpaudio.setAttribute('data-topic_name', album.appmsgalbuminfo.title || ''); mpaudio.setAttribute('data-topic_link', album.appmsgalbuminfo.link.html(false).replace('#wechat_redirect', '') + '#wechat_redirect'); mpaudio.setAttribute('data-topic_num', album.appmsgalbuminfo.tag_content_num || 0); } }); var claudios = _toConsumableArray(dom.querySelectorAll('mp-common-claudio')); claudios.forEach(function (claudio) { claudio.style.opacity = 0; }); } function handleTagReplacement(ele, newTagName) { var newTag = document.createElement(newTagName); var _iterator2 = _createForOfIteratorHelper(ele.attributes), _step2; try { for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { var attr = _step2.value; newTag.setAttribute(attr.name, attr.value); } } catch (err) { _iterator2.e(err); } finally { _iterator2.f(); } newTag.innerHTML = ele.innerHTML; ele.parentNode.replaceChild(newTag, ele); return newTag; } function preprocessMpMusic(root) { var qqmusicEles = _toConsumableArray(root.querySelectorAll('qqmusic')); qqmusicEles.forEach(function (ele) { return handleTagReplacement(ele, 'mp-common-qqmusic'); }); } if (!window.__second_open__) { updateCustomElementAttrs(window.document, window.mp_profile); preprocessMpAudios(window.document, { voiceList: window.voiceList, nick_name: window.nickname }); preprocessMpMusic(window.document); } exports.preprocessMpAudios = preprocessMpAudios; exports.preprocessMpMusic = preprocessMpMusic; exports.updateCustomElementAttrs = updateCustomElementAttrs; exports.updateProfileAttr = updateProfileAttr; Object.defineProperty(exports, '__esModule', { value: true }); return exports; })({});</script><script type="text/javascript" nonce="1989770072" reportloaderror>var __INLINE_SCRIPT__ = (function (exports) { 'use strict'; function setProfileName() { var ua = window.navigator.userAgent; if (/wxwork/i.test(ua)) { var profileName = document.getElementById('js_name'); var authorName = document.getElementById('js_author_name'); var accountNames = document.getElementsByClassName('account_nickname_inner'); if (profileName) { profileName.classList.add('tips_global_primary'); } if (authorName) { authorName.classList.add('tips_global_primary'); } if (accountNames && accountNames.length) { accountNames[0].classList.add('tips_global_primary'); } } } if (!window.__second_open__) { setProfileName(); } exports.setProfileName = setProfileName; Object.defineProperty(exports, '__esModule', { value: true }); return exports; })({});</script><script type="text/javascript" nonce="1989770072" reportloaderror>var __INLINE_SCRIPT__ = (function () { 'use strict'; function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); } function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); } function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } var prefix = '__WXLS__'; var localStorage = window.localStorage || { getItem: function getItem() {}, setItem: function setItem() {}, removeItem: function removeItem() {}, key: function key() {}, clear: function clear() { var _a, _b; (_b = (_a = window.localStorage) === null || _a === void 0 ? void 0 : _a.clear) === null || _b === void 0 ? void 0 : _b.call(_a); }, length: 0 }; var evictionPolicies = { noeviction: function noeviction(data) { return data; }, 'allkeys-random': function allkeysRandom(data, size) { var keys = Object.keys(data); var memCnt = 0; while (memCnt < size) { var len = keys.length; var randomKeyIdx = Math.floor(Math.random() * len); var randomKey = keys[randomKeyIdx]; memCnt += JSON.stringify(data[randomKey]).length; delete data[randomKey]; keys = Object.keys(data); } return data; }, 'volatile-ttl': function volatileTtl(data, size) { var keys = Object.keys(data); keys = keys.sort(function (key1, key2) { var d1 = data[key1]; var d2 = data[key2]; if (d1.exp < d2.exp) return -1; if (d1.exp > d2.exp) return 1; return 0; }); var memCnt = 0; for (var i = 0; i < keys.length; i++) { if (memCnt >= size) break; var key = keys[i]; memCnt += JSON.stringify(data[key]).length; delete data[key]; } return data; }, 'clear-all': function clearAll() { localStorage.clear(); return {}; } }; function formatLogMsg(str) { return "[WXLS] ".concat(str); } var LS = function () { function LS(func, evictionPolicy, logger) { _classCallCheck(this, LS); this.logger = function () {}; if (!func) throw 'require function name.'; this.evictionPolicy = 'noeviction'; this.key = func; if (typeof logger === 'function') { this.logger = function (str, type) { return logger(formatLogMsg(str), type); }; } if (evictionPolicy && Object.keys(evictionPolicies).indexOf(evictionPolicy) !== -1) { this.evictionPolicy = evictionPolicy; } this.init(); } _createClass(LS, [{ key: "init", value: function init() { var _a, _b; this.check(); if (Math.random() * 1000 < 1) { (_a = this.logger) === null || _a === void 0 ? void 0 : _a.call(this, "LSlen: ".concat(((_b = window === null || window === void 0 ? void 0 : window.localStorage) === null || _b === void 0 ? void 0 : _b.length) || localStorage.length), 'report'); } } }, { key: "getData", value: function getData() { var data = LS.getItem(this.key) || '{}'; try { data = JSON.parse(data); } catch (e) { this.logger("getData error: ".concat(e), 'error'); localStorage.removeItem(prefix + this.key); data = {}; } return data; } }, { key: "check", value: function check(isReturn) { var data = this.getData(); var temp = {}; var now = +new Date(); var key; var val; for (key in data) { val = data[key]; if (+val.exp > now) { temp[key] = val; } } this.logger("check info: isReturn:".concat(isReturn, " data:").concat(JSON.stringify(temp)), 'info'); if (isReturn) return temp; LS.setItem(this.key, JSON.stringify(temp), this.logger); } }, { key: "set", value: function set(key, val, exp) { var _a, _b; var data = this.check(true); data[key] = { val: val, exp: exp || +new Date() }; try { if (localStorage.getItem(prefix + this.key)) localStorage.removeItem(prefix + this.key); localStorage.setItem(prefix + this.key, JSON.stringify(data)); this.logger("first set success: LSlen:".concat((_a = window === null || window === void 0 ? void 0 : window.localStorage) === null || _a === void 0 ? void 0 : _a.length, " key:").concat(prefix + this.key, " data:").concat(JSON.stringify(data)), 'success'); } catch (e) { this.logger("first set error: LSlen:".concat((_b = window === null || window === void 0 ? void 0 : window.localStorage) === null || _b === void 0 ? void 0 : _b.length, " error:").concat(e, " key:").concat(prefix + this.key, " data:").concat(JSON.stringify(data), " k:").concat(key, " v:").concat(val, " exp:").concat(exp), 'error'); localStorage.clear(); LS.setItem(this.key, JSON.stringify(_defineProperty({}, key, { val: val, exp: exp || +new Date() })), this.logger); } } }, { key: "get", value: function get(key) { var data = this.getData(); data = data[key]; return data ? data.val || null : null; } }, { key: "remove", value: function remove(key) { var data = this.getData(); if (data[key]) delete data[key]; LS.setItem(this.key, JSON.stringify(data), this.logger); } }], [{ key: "getItem", value: function getItem(key) { key = prefix + key; return localStorage.getItem(key); } }, { key: "setItem", value: function setItem(key, val, logger) { var _a, _b; key = prefix + key; var n = 3; while (n--) { try { if (localStorage.getItem(key)) localStorage.removeItem(key); localStorage.setItem(key, val); typeof logger === 'function' && logger("setItem success: LSlen:".concat((_a = window === null || window === void 0 ? void 0 : window.localStorage) === null || _a === void 0 ? void 0 : _a.length, " key:").concat(key, " val:").concat(val), 'success'); break; } catch (e) { typeof logger === 'function' && logger("setItem error: LSlen:".concat((_b = window === null || window === void 0 ? void 0 : window.localStorage) === null || _b === void 0 ? void 0 : _b.length, " error:").concat(e, " key:").concat(key, " val:").concat(val), 'error'); LS.clear(); } } } }, { key: "clear", value: function clear() { var i; var k; for (i = localStorage.length - 1; i >= 0; i--) { k = localStorage.key(i); if (k.indexOf(prefix) == 0) { localStorage.removeItem(k); } } } }, { key: "getSupportEvicationPolicy", value: function getSupportEvicationPolicy() { return Object.keys(evictionPolicies); } }]); return LS; }(); var key = 'stream_last_read_pos'; new LS(key); var interactionStatusLS = new LS('bottom_interaction_status'); function getInteractionStatus(opt) { var biz = opt.biz || window.biz; var sn = opt.sn || window.sn; var mid = opt.mid || window.mid; var idx = opt.idx || window.idx; var interactionStatusKey = [biz, sn, mid, idx].join('_'); var interactionStatusInfo = interactionStatusLS.get(interactionStatusKey); if (Object.prototype.toString.call(interactionStatusInfo) !== '[object Object]') { interactionStatusInfo = {}; } return interactionStatusInfo; } var formatReadNum = function formatReadNum(value) { var result = ''; var unit = window.LANG === 'en' ? 'k' : '万'; if (parseInt(value, 10) > 100000) { result = 10 + unit + '+'; } else if (parseInt(value, 10) > 10000 && parseInt(value, 10) <= 100000) { var num = "".concat(parseInt(value, 10) / (unit === 'k' ? 1000 : 10000)); var dotIndex = num.indexOf('.'); if (dotIndex === -1) { result = "".concat(num).concat(unit); } else { result = "".concat(num.substr(0, dotIndex), ".").concat(num.charAt(dotIndex + 1)).concat(unit); } } else if (parseInt(value, 10) === 0) { result = ''; } else { result = value || ''; } return result; }; var formatTime = function formatTime(value) { var time = new Date(value * 1000); var year = time.getFullYear(); var month = time.getMonth() + 1; var day = time.getDate(); return year + '年' + "".concat(month > 9 ? month : '0' + month) + '月' + "".concat(day > 9 ? day : '0' + day) + '日'; }; var __setPageContentBottomData = function __setPageContentBottomData(cgiData) { if (!cgiData) return; try { var tempReadNum = document.getElementById('js_btm_temp_read_num'); var tempModifyTime = document.getElementById('js_btm_temp_modify_time'); var interactionStatus = getInteractionStatus({ biz: cgiData.biz, mid: cgiData.mid, sn: cgiData.sn, idx: cgiData.idx }); var readNum = interactionStatus.read_num * 1 ? Math.max(interactionStatus.read_num * 1, cgiData.read_num) : cgiData.read_num || 0; if (readNum && tempReadNum) { tempReadNum.innerText = formatReadNum(readNum); } if (cgiData.modify_time && tempModifyTime) { tempModifyTime.innerText = formatTime(cgiData.modify_time); } } catch (error) { console.log(error); } }; if (!window.__second_open__) { var cgiData = { modify_time: '' * 1, read_num: '' * 1, idx: '' , biz: '' , mid: '' , sn: '' }; __setPageContentBottomData(cgiData); window.__setPageContentBottomData = __setPageContentBottomData; } return __setPageContentBottomData; })();</script> <script type="text/javascript" nonce="1989770072" reportloaderror> (function(_g){ _g.appmsg_like_type = "2" * 1 ? "2" * 1 : 1; _g.clientversion = ""; _g.passparam = ""; if(!_g.msg_link) { _g.msg_link = "https://mp.weixin.qq.com/s/3hbpQRAofG905lAt7Onq5g"; } _g.appmsg_type = "9"; _g.devicetype = ""; _g.kanyikan_video_educate_pic = "//res.wx.qq.com/mmbizappmsg/zh_CN/htmledition/js/images/pic/pic_like_comment_primary750ed3.png"; _g.kanyikan_educate_pic = "//res.wx.qq.com/mmbizappmsg/zh_CN/htmledition/js/images/pic/pic_like_comment750ed3.png"; })(window); </script> <script type="text/javascript" nonce="1989770072" reportloaderror> (function() { var ua = navigator.userAgent; if (ua.indexOf("MicroMessenger") != -1 && ua.indexOf("Android") != -1){ var script = document.createElement('script'); var head = document.getElementsByTagName('head')[0]; script.type = 'text/javascript'; script.src = "https://midas.gtimg.cn/h5sdk/js/api/h5sdk.js"; head.appendChild(script); } })(); </script> <script type="text/javascript" nonce="1989770072" reportloaderror> var real_show_page_time = +new Date(); if (!!window.addEventListener){ window.addEventListener("load", function(){ window.onload_endtime = +new Date(); }); } </script> <script type="text/javascript" nonce="1989770072" reportloaderror> (function() { const ua = navigator.userAgent; const is_ios = /(iPhone|iPad|iPod|iOS)/i.test(ua); const is_wp = /Windows\sPhone/i.test(ua); const is_mac = /mac\sos/i.test(ua) && !is_ios; const is_windows = /windows\snt/i.test(ua) && !is_wp; if ((is_mac && !is_ios) || (is_windows && !is_wp)) { var script = document.createElement('script'); var head = document.getElementsByTagName('head')[0]; script.type = 'text/javascript'; script.src = "https://res.wx.qq.com/connect/zh_CN/htmledition/js/wxopensdk.js"; head.appendChild(script); } })(); </script> <script nomodule nonce="1989770072" reportloaderror>new Image().src='https://mp.weixin.qq.com/mp/jsmonitor?idkey=66881_111_1&t='+Math.random();</script> <script nomodule nonce="1989770072" reportloaderror>!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script> <script nomodule crossorigin id="vite-legacy-polyfill" src="//res.wx.qq.com/mmbizappmsg/zh_CN/htmledition/js/assets/polyfills-legacy.m8zs8dx7a6217755.js" nonce="1989770072" reportloaderror></script> <script nomodule crossorigin id="vite-legacy-entry" src="//res.wx.qq.com/mmbizappmsg/zh_CN/htmledition/js/assets/appmsg-legacy.m8zs8dx751963a44.js" nonce="1989770072" reportloaderror>System.import(document.getElementById('vite-legacy-entry').getAttribute('src'))</script> </object></span></code></pre> </section>