shareAiConsult.html 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345
  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="utf-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
  6. <meta name="format-detection" content="telephone=no">
  7. <title>与U宝对话</title>
  8. <meta property="og:title" content="和U宝的对话">
  9. <meta property="og:description" content="点击查看对话内容">
  10. <meta property="og:site_name" content="U店在哪">
  11. <meta name="application-name" content="U店在哪">
  12. <link rel="icon" type="image/png" href="https://alien-volume.oss-cn-beijing.aliyuncs.com/icon/ubao.png">
  13. <link rel="apple-touch-icon" href="https://alien-volume.oss-cn-beijing.aliyuncs.com/icon/ubao.png">
  14. <style>
  15. :root {
  16. --bg: #f4f6fb;
  17. --text: #151515;
  18. --muted: #aaaaaa;
  19. --orange: #f47d1f;
  20. --safe-bottom: env(safe-area-inset-bottom, 0px);
  21. }
  22. * {
  23. margin: 0;
  24. padding: 0;
  25. box-sizing: border-box;
  26. }
  27. html {
  28. height: 100%;
  29. -webkit-tap-highlight-color: transparent;
  30. overflow: hidden;
  31. }
  32. body {
  33. font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", sans-serif;
  34. background: var(--bg);
  35. color: var(--text);
  36. height: 100vh;
  37. display: flex;
  38. flex-direction: column;
  39. overflow: hidden;
  40. }
  41. #main {
  42. flex: 1;
  43. min-height: 0;
  44. overflow-x: hidden;
  45. overflow-y: auto;
  46. -webkit-overflow-scrolling: touch;
  47. padding-bottom: calc(100px + var(--safe-bottom));
  48. }
  49. .hero {
  50. padding: 16px 15px 0;
  51. }
  52. .hero__title {
  53. font-size: 20px;
  54. font-weight: 700;
  55. line-height: 1.4;
  56. word-break: break-word;
  57. }
  58. .hero__meta {
  59. margin-top: 8px;
  60. font-size: 12px;
  61. color: var(--muted);
  62. line-height: 1.4;
  63. }
  64. .hero__divider {
  65. margin-top: 14px;
  66. height: 1px;
  67. background: rgba(170, 170, 170, 0.25);
  68. }
  69. .conversation {
  70. padding: 14px 15px 8px;
  71. }
  72. .scroll-spacer {
  73. height: calc(72px + var(--safe-bottom));
  74. flex-shrink: 0;
  75. }
  76. .conversation .row:last-child {
  77. margin-bottom: 0;
  78. }
  79. .row {
  80. display: flex;
  81. margin-bottom: 12px;
  82. }
  83. .row--user {
  84. justify-content: flex-end;
  85. }
  86. .row--ai {
  87. justify-content: flex-start;
  88. }
  89. .user-bubble {
  90. position: relative;
  91. max-width: 78%;
  92. padding: 10px 14px;
  93. background: var(--orange);
  94. border-radius: 8px 8px 2px 8px;
  95. color: #fff;
  96. font-size: 15px;
  97. font-weight: 500;
  98. line-height: 1.5;
  99. white-space: pre-wrap;
  100. word-break: break-word;
  101. }
  102. .user-bubble::after {
  103. content: "";
  104. position: absolute;
  105. right: -6px;
  106. bottom: 8px;
  107. width: 0;
  108. height: 0;
  109. border-style: solid;
  110. border-width: 6px 0 6px 7px;
  111. border-color: transparent transparent transparent var(--orange);
  112. }
  113. .ai-card {
  114. width: 100%;
  115. padding: 14px 13px;
  116. background: #fff;
  117. border-radius: 12px;
  118. box-shadow: 0 1px 6px rgba(0, 0, 0, 0.04);
  119. }
  120. .ai-card__text {
  121. font-size: 14px;
  122. line-height: 1.65;
  123. white-space: pre-wrap;
  124. word-break: break-word;
  125. text-align: left;
  126. }
  127. .ai-card__image {
  128. display: block;
  129. max-width: 100%;
  130. height: auto;
  131. margin: 8px 0;
  132. border-radius: 6px;
  133. }
  134. .user-bubble__image {
  135. display: block;
  136. max-width: 180px;
  137. border-radius: 4px;
  138. }
  139. .fallback-card {
  140. margin: 14px 15px 0;
  141. padding: 14px 13px;
  142. background: #fff;
  143. border-radius: 8px;
  144. box-shadow: 0 1px 6px rgba(0, 0, 0, 0.04);
  145. }
  146. .fallback-card .ai-card__text {
  147. font-size: 14px;
  148. line-height: 1.65;
  149. white-space: pre-wrap;
  150. word-break: break-word;
  151. text-align: left;
  152. }
  153. .empty {
  154. padding: 48px 20px;
  155. text-align: center;
  156. color: var(--muted);
  157. font-size: 14px;
  158. }
  159. .fab-wrap {
  160. position: fixed;
  161. left: 0;
  162. right: 0;
  163. bottom: 0;
  164. z-index: 200;
  165. padding: 12px 24px calc(12px + var(--safe-bottom));
  166. background: linear-gradient(to top, rgba(255, 255, 255, 0.98) 70%, transparent);
  167. pointer-events: none;
  168. }
  169. .fab-dock__slot {
  170. position: relative;
  171. width: 100%;
  172. max-width: 198px;
  173. height: 48px;
  174. margin: 0 auto;
  175. pointer-events: auto;
  176. }
  177. #openApp.fab {
  178. padding: 0 10px;
  179. -webkit-font-smoothing: antialiased;
  180. text-rendering: optimizeLegibility;
  181. }
  182. .fab__brand-clip {
  183. display: block;
  184. flex-shrink: 0;
  185. line-height: 0;
  186. }
  187. .fab__brand-img {
  188. display: block;
  189. height: 26px;
  190. width: auto;
  191. max-width: none;
  192. pointer-events: none;
  193. -webkit-user-drag: none;
  194. }
  195. .fab__label {
  196. font-size: 15px;
  197. line-height: 1;
  198. letter-spacing: 0.04em;
  199. white-space: nowrap;
  200. }
  201. #launch-btn {
  202. display: none;
  203. position: absolute;
  204. left: 0;
  205. top: 0;
  206. z-index: 2;
  207. width: 100%;
  208. height: 48px;
  209. min-height: 48px;
  210. border-radius: 24px;
  211. overflow: hidden;
  212. opacity: 1;
  213. }
  214. /* 开放标签叠在 openApp 上;保留 openApp 作视觉兜底,避免标签未渲染时按钮消失 */
  215. body.is-wechat.wx-jssdk-ready #launch-btn {
  216. display: block;
  217. pointer-events: auto;
  218. }
  219. body.is-wechat.wx-jssdk-ready #openApp {
  220. pointer-events: none;
  221. }
  222. .fab-wrap .fab {
  223. pointer-events: auto;
  224. }
  225. #openApp {
  226. touch-action: manipulation;
  227. }
  228. .fab {
  229. display: flex;
  230. align-items: center;
  231. justify-content: center;
  232. gap: 4px;
  233. width: 100%;
  234. max-width: 198px;
  235. margin: 0 auto;
  236. height: 48px;
  237. border: none;
  238. border-radius: 24px;
  239. background: #F47D1F;
  240. color: #fff;
  241. font-size: 16px;
  242. font-weight: 600;
  243. box-shadow: 0 4px 16px rgba(245, 130, 32, 0.45);
  244. cursor: pointer;
  245. }
  246. .home-indicator {
  247. height: 5px;
  248. background: #000;
  249. border-radius: 3px;
  250. width: 134px;
  251. margin: 8px auto 4px;
  252. opacity: 0.2;
  253. }
  254. #openAppToast {
  255. display: none;
  256. position: fixed;
  257. left: 16px;
  258. right: 16px;
  259. bottom: calc(72px + var(--safe-bottom));
  260. z-index: 10001;
  261. padding: 10px 14px;
  262. font-size: 13px;
  263. line-height: 1.45;
  264. color: #fff;
  265. text-align: center;
  266. background: rgba(0, 0, 0, 0.78);
  267. border-radius: 8px;
  268. pointer-events: none;
  269. word-break: break-all;
  270. }
  271. </style>
  272. </head>
  273. <body>
  274. <main id="main">
  275. <div class="empty">对话内容加载中…</div>
  276. </main>
  277. <div id="openAppToast" role="status" aria-live="polite"></div>
  278. <div class="fab-wrap">
  279. <div class="fab-dock__slot">
  280. <button type="button" class="fab" id="openApp" aria-label="APP内打开">
  281. <span class="fab__brand-clip" aria-hidden="true">
  282. <img class="fab__brand-img" src="images/uCharts.png" alt="" decoding="async">
  283. </span>
  284. </button>
  285. <wx-open-launch-app id="launch-btn" appid="wxf5f1efe3a9f5012e" extinfo="">
  286. <script type="text/wxtag-template">
  287. <style>
  288. .wx-open-app-btn {
  289. display: flex;
  290. align-items: center;
  291. justify-content: center;
  292. gap: 4px;
  293. width: 100%;
  294. height: 48px;
  295. margin: 0;
  296. padding: 0 10px;
  297. border: none;
  298. border-radius: 24px;
  299. background: #F47D1F;
  300. box-shadow: 0 4px 16px rgba(245, 130, 32, 0.45);
  301. color: #fff;
  302. font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Helvetica Neue", sans-serif;
  303. -webkit-font-smoothing: antialiased;
  304. cursor: pointer;
  305. overflow: hidden;
  306. -webkit-tap-highlight-color: transparent;
  307. box-sizing: border-box;
  308. }
  309. .wx-open-app-btn .fab__brand-clip {
  310. display: block;
  311. flex-shrink: 0;
  312. line-height: 0;
  313. }
  314. .wx-open-app-btn .fab__brand-img {
  315. display: block;
  316. height: 26px;
  317. width: auto;
  318. max-width: none;
  319. pointer-events: none;
  320. -webkit-user-drag: none;
  321. }
  322. .wx-open-app-btn .fab__label {
  323. font-size: 15px;
  324. line-height: 1;
  325. letter-spacing: 0.04em;
  326. white-space: nowrap;
  327. }
  328. </style>
  329. <button class="wx-open-app-btn" aria-label="APP内打开">
  330. <span class="fab__brand-clip" aria-hidden="true">
  331. <img class="fab__brand-img" src="https://prod.ailien.shop/h5/HBuilderProjects/images/uCharts.png" alt="" decoding="async">
  332. </span>
  333. </button>
  334. </script>
  335. </wx-open-launch-app>
  336. </div>
  337. <div class="home-indicator" aria-hidden="true"></div>
  338. </div>
  339. <script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
  340. <script>
  341. (function () {
  342. "use strict";
  343. var API_BASE = "https://prod.ailien.shop/alienStore";
  344. var WECHAT_MP_APP_ID = "wx412792c77f47babd";
  345. var WECHAT_OPEN_APP_ID = "wxf5f1efe3a9f5012e";
  346. var WECHAT_GET_WX_CONFIG_PATH = "/wx/getWxConfig";
  347. var H5_PAGE_BASE_FALLBACK = "https://prod.ailien.shop/h5/HBuilderProjects/";
  348. var WX_GET_CONFIG_SIGN_URL = H5_PAGE_BASE_FALLBACK + "shareAiConsult.html";
  349. var WECHAT_JS_SAFE_HOSTS = ["uat.ailien.shop", "prod.ailien.shop"];
  350. var APP_ANDROID_PACKAGE = "com.alien.Udianzaizhe";
  351. var APP_IOS_URL_SCHEME = "shopro://";
  352. var APP_UNI_AI_PATH = "pages/aiSearchResult/index";
  353. var sharePayloadCache = null;
  354. var weChatJssdkConfigured = false;
  355. var wxConfigSignRetriedBaseUrl = false;
  356. var wxInitLastError = "";
  357. var wxJssdkInitPromise = null;
  358. function escHtml(s) {
  359. return String(s || "")
  360. .replace(/&/g, "&amp;")
  361. .replace(/</g, "&lt;")
  362. .replace(/>/g, "&gt;")
  363. .replace(/"/g, "&quot;");
  364. }
  365. var IMAGE_EXT = "(?:jpe?g|png|gif|webp|bmp|avif)";
  366. var IMAGE_URL_PATTERN =
  367. "https?:\\/\\/[^\\s))\\]]+\\." + IMAGE_EXT + "(?:\\?[^\\s))\\]]*)?";
  368. function isInsideImageUrlSyntax(full, offset) {
  369. if (offset >= 2 && full.slice(offset - 2, offset) === "](") return true;
  370. if (offset >= 1 && full[offset - 1] === "(") return true;
  371. if (offset >= 6 && full.slice(offset - 6, offset) === "{{IMG|") return true;
  372. return false;
  373. }
  374. /** AI 回复常见:店名(https://...jpg) — 转为可渲染的图片占位 */
  375. function embedInlineImageUrls(text) {
  376. if (text == null) return "";
  377. var t = String(text);
  378. t = t.replace(
  379. new RegExp("([^\\n((]+?)\\((" + IMAGE_URL_PATTERN + ")\\)", "gi"),
  380. function (_, label, url) {
  381. var name = String(label).trim();
  382. if (!name) return "\n\n{{IMG|" + url + "|}}\n\n";
  383. var alt = name.length > 24 ? "图片" : name.replace(/[\[\]]/g, "");
  384. return name + "\n\n{{IMG|" + url + "|" + alt + "}}\n\n";
  385. }
  386. );
  387. t = t.replace(
  388. new RegExp("\\((" + IMAGE_URL_PATTERN + ")\\)", "gi"),
  389. function (_, url) {
  390. return "\n\n{{IMG|" + url + "|}}\n\n";
  391. }
  392. );
  393. t = t.replace(new RegExp(IMAGE_URL_PATTERN, "gi"), function (url, offset, full) {
  394. if (isInsideImageUrlSyntax(full, offset)) return url;
  395. return "\n\n{{IMG|" + url + "|}}\n\n";
  396. });
  397. return t.replace(/\n{3,}/g, "\n\n");
  398. }
  399. function formatTextBlockHtml(text) {
  400. return escHtml(text).replace(/\n/g, "<br>");
  401. }
  402. function buildAiImageTag(url, alt) {
  403. var safeUrl = escHtml(url);
  404. var safeAlt = escHtml(alt || "图片");
  405. return (
  406. '<img class="ai-card__image" src="' +
  407. safeUrl +
  408. '" alt="' +
  409. safeAlt +
  410. '" loading="lazy" decoding="async" />'
  411. );
  412. }
  413. function renderAiContentHtml(text) {
  414. var t = embedInlineImageUrls(text);
  415. var html = "";
  416. var tokenRe = /\{\{IMG\|([^|]+)\|([^}]*)\}\}/g;
  417. var lastIndex = 0;
  418. var match;
  419. while ((match = tokenRe.exec(t)) !== null) {
  420. if (match.index > lastIndex) {
  421. html += formatTextBlockHtml(t.slice(lastIndex, match.index));
  422. }
  423. html += buildAiImageTag(match[1], match[2]);
  424. lastIndex = tokenRe.lastIndex;
  425. }
  426. if (lastIndex < t.length) {
  427. html += formatTextBlockHtml(t.slice(lastIndex));
  428. }
  429. return html;
  430. }
  431. function q(name) {
  432. try {
  433. var v = new URLSearchParams(location.search || "").get(name);
  434. return v == null ? "" : String(v);
  435. } catch (e) {
  436. return "";
  437. }
  438. }
  439. function getQueryParam(name) {
  440. var m = new RegExp("[?&]" + name + "=([^&]*)").exec(window.location.search);
  441. if (!m) return "";
  442. try {
  443. return decodeURIComponent(m[1].replace(/\+/g, " "));
  444. } catch (e) {
  445. return "";
  446. }
  447. }
  448. function parsePayload() {
  449. var raw = getQueryParam("payload");
  450. if (!raw) return null;
  451. try {
  452. return JSON.parse(raw);
  453. } catch (e) {
  454. return null;
  455. }
  456. }
  457. function getFirstUserQuestion(messages) {
  458. var list = Array.isArray(messages) ? messages : [];
  459. for (var i = 0; i < list.length; i++) {
  460. var m = list[i];
  461. if (!m || m.role !== "user") continue;
  462. if (m.isImage) return "[图片]";
  463. var t = String(m.content || "").trim();
  464. if (t) return t;
  465. }
  466. return "";
  467. }
  468. function formatDiscussionTitle(question) {
  469. var qText = String(question || "").trim();
  470. if (!qText) return "与AI助手对话";
  471. if (qText.slice(-3) === "的讨论") return qText;
  472. return qText + "的讨论";
  473. }
  474. function formatDate(ts) {
  475. var d = ts ? new Date(Number(ts)) : new Date();
  476. if (isNaN(d.getTime())) d = new Date();
  477. return d.getFullYear() + "年" + (d.getMonth() + 1) + "月" + d.getDate() + "日";
  478. }
  479. function renderMessages(messages) {
  480. var html = "";
  481. var list = Array.isArray(messages) ? messages : [];
  482. for (var i = 0; i < list.length; i++) {
  483. var msg = list[i];
  484. if (!msg) continue;
  485. if (msg.role === "user") {
  486. if (msg.isImage && msg.imageUrl) {
  487. html +=
  488. '<div class="row row--user"><div class="user-bubble"><img class="user-bubble__image" src="' +
  489. escHtml(msg.imageUrl) +
  490. '" alt="图片" loading="lazy" decoding="async" /></div></div>';
  491. continue;
  492. }
  493. var userText = String(msg.content || "").trim();
  494. if (!userText) continue;
  495. html +=
  496. '<div class="row row--user"><div class="user-bubble">' +
  497. escHtml(userText) +
  498. "</div></div>";
  499. continue;
  500. }
  501. if (msg.role === "ai" || msg.role === "assistant") {
  502. var aiText = String(msg.content || "").trim();
  503. if (!aiText) continue;
  504. html +=
  505. '<div class="row row--ai"><div class="ai-card"><div class="ai-card__text">' +
  506. renderAiContentHtml(aiText) +
  507. "</div></div></div>";
  508. }
  509. }
  510. return html;
  511. }
  512. function applyWeixinShareMeta() {
  513. var siteName = "U店在哪";
  514. var iconUrl =
  515. "https://alien-volume.oss-cn-beijing.aliyuncs.com/icon/ubao.png";
  516. var setMeta = function (key, content) {
  517. var el =
  518. document.querySelector('meta[property="' + key + '"]') ||
  519. document.querySelector('meta[name="' + key + '"]');
  520. if (!el) {
  521. el = document.createElement("meta");
  522. if (key.indexOf("og:") === 0) {
  523. el.setAttribute("property", key);
  524. } else {
  525. el.setAttribute("name", key);
  526. }
  527. document.head.appendChild(el);
  528. }
  529. el.setAttribute("content", content);
  530. };
  531. setMeta("og:site_name", siteName);
  532. setMeta("application-name", siteName);
  533. setMeta("og:title", "和U宝的对话");
  534. setMeta("og:description", "点击查看对话内容");
  535. var links = document.querySelectorAll('link[rel="icon"], link[rel="apple-touch-icon"]');
  536. for (var i = 0; i < links.length; i++) {
  537. links[i].setAttribute("href", iconUrl);
  538. }
  539. }
  540. function countDisplayableMessages(messages) {
  541. var list = Array.isArray(messages) ? messages : [];
  542. var count = 0;
  543. for (var i = 0; i < list.length; i++) {
  544. var msg = list[i];
  545. if (!msg) continue;
  546. if (msg.role === "user") {
  547. if (msg.isImage && msg.imageUrl) {
  548. count += 1;
  549. continue;
  550. }
  551. if (String(msg.content || "").trim()) count += 1;
  552. continue;
  553. }
  554. if (msg.role === "ai" || msg.role === "assistant") {
  555. if (String(msg.content || "").trim()) count += 1;
  556. }
  557. }
  558. return count;
  559. }
  560. function parseMessagesFromContent(text) {
  561. var raw = String(text || "").trim();
  562. if (!raw) return [];
  563. var list = [];
  564. var blocks = raw.split(/\n\n+/);
  565. for (var i = 0; i < blocks.length; i++) {
  566. var block = String(blocks[i] || "").trim();
  567. if (!block) continue;
  568. var userMatch = block.match(/^我[::]\s*([\s\S]*)$/);
  569. if (userMatch) {
  570. var userText = String(userMatch[1] || "").trim();
  571. if (userText) list.push({ role: "user", content: userText });
  572. continue;
  573. }
  574. var aiMatch = block.match(/^UBAO[::]\s*([\s\S]*)$/i);
  575. if (aiMatch) {
  576. var aiText = String(aiMatch[1] || "").trim();
  577. if (aiText) list.push({ role: "ai", content: aiText });
  578. }
  579. }
  580. if (list.length) return list;
  581. var current = null;
  582. var lines = raw.split(/\n/);
  583. for (var j = 0; j < lines.length; j++) {
  584. var line = String(lines[j] || "");
  585. var userLine = line.match(/^我[::]\s*(.*)$/);
  586. var aiLine = line.match(/^UBAO[::]\s*(.*)$/i);
  587. if (userLine) {
  588. if (current) list.push(current);
  589. current = { role: "user", content: String(userLine[1] || "").trim() };
  590. continue;
  591. }
  592. if (aiLine) {
  593. if (current) list.push(current);
  594. current = { role: "ai", content: String(aiLine[1] || "").trim() };
  595. continue;
  596. }
  597. if (current && line.trim()) {
  598. current.content = (current.content ? current.content + "\n" : "") + line.trim();
  599. }
  600. }
  601. if (current && String(current.content || "").trim()) list.push(current);
  602. return list;
  603. }
  604. function resolveShareMessagesForDisplay(data) {
  605. var fromArray = Array.isArray(data && data.messages) ? data.messages : [];
  606. var fromContent = parseMessagesFromContent((data && data.content) || "");
  607. var arrayCount = countDisplayableMessages(fromArray);
  608. var contentCount = countDisplayableMessages(fromContent);
  609. // 分享链接超长时 messages 会被截断,但 content 仍保留完整对话文本
  610. if (contentCount > arrayCount) return fromContent;
  611. if (arrayCount) return fromArray;
  612. return fromContent;
  613. }
  614. function render(data) {
  615. applyWeixinShareMeta();
  616. sharePayloadCache = data || null;
  617. var main = document.getElementById("main");
  618. if (!data) {
  619. main.innerHTML = '<div class="empty">对话内容不存在或链接已失效</div>';
  620. refreshWxLaunchTagAttrs();
  621. return;
  622. }
  623. var messages = resolveShareMessagesForDisplay(data);
  624. var firstQuestion =
  625. String(data.firstQuestion || "").trim() ||
  626. getFirstUserQuestion(messages) ||
  627. (function () {
  628. var text = String(data.content || "").trim();
  629. var m = text.match(/^我[::]([\s\S]+?)(?:\n\n|$)/);
  630. return m ? String(m[1] || "").trim() : "";
  631. })();
  632. var pageTitle = formatDiscussionTitle(firstQuestion);
  633. var dateText = formatDate(data.shareTime);
  634. document.title = pageTitle;
  635. var bodyHtml =
  636. '<section class="hero">' +
  637. '<h1 class="hero__title">' +
  638. escHtml(pageTitle) +
  639. "</h1>" +
  640. '<p class="hero__meta">' +
  641. escHtml(dateText) +
  642. " · 内容由AI生成,不能完全保障真实</p>" +
  643. '<div class="hero__divider"></div>' +
  644. "</section>";
  645. var convHtml = renderMessages(messages);
  646. if (convHtml) {
  647. bodyHtml +=
  648. '<section class="conversation">' +
  649. convHtml +
  650. '</section><div class="scroll-spacer" aria-hidden="true"></div>';
  651. } else {
  652. bodyHtml += '<div class="empty">暂无对话内容</div>';
  653. }
  654. main.innerHTML = bodyHtml;
  655. refreshWxLaunchTagAttrs();
  656. if (weChatJssdkConfigured && isWeChatInAppBrowser()) {
  657. activateWxLaunchTagUi();
  658. }
  659. }
  660. function buildAiConsultOpenParams() {
  661. var params = new URLSearchParams();
  662. params.set("pageType", "home");
  663. params.set("fromShareAiConsult", "1");
  664. return params;
  665. }
  666. function buildAppDeepLink() {
  667. var path = APP_UNI_AI_PATH;
  668. var qs = buildAiConsultOpenParams().toString();
  669. var root = APP_IOS_URL_SCHEME.replace(/\/$/, "");
  670. return root + "/" + path + (qs ? "?" + qs : "");
  671. }
  672. function buildWeChatLaunchExtinfo(useBarePathOnly) {
  673. var path = APP_UNI_AI_PATH.replace(/^\//, "");
  674. if (useBarePathOnly) return path;
  675. var qs = buildAiConsultOpenParams().toString();
  676. var uniPage = qs ? path + "?" + qs : path;
  677. if (uniPage.length <= 1024) return uniPage;
  678. return path + "?pageType=home&fromShareAiConsult=1";
  679. }
  680. function isWeChatInAppBrowser() {
  681. return /MicroMessenger/i.test(navigator.userAgent || "");
  682. }
  683. function getWxShareEntryFrom() {
  684. var from = q("from");
  685. if (from) return String(from).trim().toLowerCase();
  686. try {
  687. var h = location.hash || "";
  688. var qi = h.indexOf("?");
  689. if (qi >= 0) {
  690. var hf = new URLSearchParams(h.slice(qi + 1)).get("from");
  691. if (hf) return String(hf).trim().toLowerCase();
  692. }
  693. } catch (eH) {}
  694. return "";
  695. }
  696. function logWxEntryDiagnostics() {
  697. if (!isWeChatInAppBrowser()) return;
  698. console.log("[wx-entry]", {
  699. entryFrom: getWxShareEntryFrom() || "(无)",
  700. wxJssdkReady: weChatJssdkConfigured,
  701. signUrl: getWxConfigSignUrl(),
  702. });
  703. }
  704. function isIOSWeChatBrowser() {
  705. var ua = navigator.userAgent || "";
  706. return /MicroMessenger/i.test(ua) && /iPhone|iPad|iPod/i.test(ua);
  707. }
  708. function isWxDebugOn() {
  709. return q("wxDebug") === "1";
  710. }
  711. function isWxForceDebug() {
  712. return q("wxForce") === "1";
  713. }
  714. function isWxPcAutoDebugHost() {
  715. var h = (location.hostname || "").toLowerCase();
  716. if (h === "localhost" || h === "127.0.0.1") return true;
  717. for (var i = 0; i < WECHAT_JS_SAFE_HOSTS.length; i++) {
  718. if (WECHAT_JS_SAFE_HOSTS[i] === h) return true;
  719. }
  720. return false;
  721. }
  722. function isWxPcBrowser() {
  723. return !isWeChatInAppBrowser();
  724. }
  725. function shouldInitWeChatJssdkOnLoad() {
  726. if (isWeChatInAppBrowser()) return true;
  727. return isWxForceDebug() || isWxPcAutoDebugHost();
  728. }
  729. function shouldFetchWxConfig(fromUserClick) {
  730. if (isWeChatInAppBrowser()) return true;
  731. if (fromUserClick) return true;
  732. return isWxForceDebug() || isWxPcAutoDebugHost();
  733. }
  734. function getWxHtmlUrl() {
  735. var forced = String(q("wxSignUrl") || "").trim();
  736. if (forced) return forced.split("#")[0];
  737. return String(location.href || "").split("#")[0];
  738. }
  739. function getWxSignPageUrlForApi() {
  740. var htmlUrl = getWxHtmlUrl();
  741. if (htmlUrl && /^https?:\/\//i.test(htmlUrl)) return htmlUrl;
  742. return WX_GET_CONFIG_SIGN_URL;
  743. }
  744. function getWxHtmlUrlBase() {
  745. var htmlUrl = getWxSignPageUrlForApi();
  746. try {
  747. var u = new URL(htmlUrl);
  748. return u.origin + u.pathname;
  749. } catch (eU) {
  750. return WX_GET_CONFIG_SIGN_URL;
  751. }
  752. }
  753. /** 默认 pathname 验签:AI 分享链常带超长 payload,与后端无参签名一致,避免开放标签 fail_check */
  754. function getWxConfigSignUrl() {
  755. if (String(q("wxSignFullUrl") || "") === "1") return getWxSignPageUrlForApi();
  756. if (String(q("wxSignBaseOnly") || "") === "1") return getWxHtmlUrlBase();
  757. if (isWeChatInAppBrowser()) return getWxHtmlUrlBase();
  758. return getWxSignPageUrlForApi();
  759. }
  760. function getWxGetConfigApiUrl() {
  761. return API_BASE.replace(/\/$/, "") + WECHAT_GET_WX_CONFIG_PATH;
  762. }
  763. function buildWxGetConfigRequestBody(htmlUrl) {
  764. return {
  765. url: String(htmlUrl || "").split("#")[0].trim(),
  766. };
  767. }
  768. function resolveWxConfigAppIdFromSignData(d) {
  769. if (!d || typeof d !== "object") return "";
  770. var mp =
  771. d.mpAppId ||
  772. d.mpAppid ||
  773. d.officialAppId ||
  774. d.gzhAppId ||
  775. d.serviceAppId;
  776. if (mp != null && String(mp).trim() !== "") return String(mp).trim();
  777. var fromQuery = String(q("wxMpAppId") || WECHAT_MP_APP_ID || "").trim();
  778. if (fromQuery) return fromQuery;
  779. var raw = d.appId || d.appid || d.wxAppId;
  780. return raw != null && String(raw).trim() !== "" ? String(raw).trim() : "";
  781. }
  782. function normalizeWxJssdkSignPayload(res, signUrlUsed) {
  783. if (!res || typeof res !== "object") return null;
  784. var d = res.data != null && typeof res.data === "object" ? res.data : res;
  785. if (!d || typeof d !== "object") return null;
  786. var appId = resolveWxConfigAppIdFromSignData(d);
  787. var timestamp = d.timestamp != null ? d.timestamp : d.timeStamp;
  788. var nonceStr =
  789. d.nonceStr != null && String(d.nonceStr) !== ""
  790. ? d.nonceStr
  791. : d.noncestr != null && String(d.noncestr) !== ""
  792. ? d.noncestr
  793. : d.nonce;
  794. var signature = d.signature || d.sign;
  795. if (!appId || timestamp == null || nonceStr == null || nonceStr === "" || !signature) {
  796. return null;
  797. }
  798. return {
  799. appId: String(appId),
  800. timestamp: Number(timestamp),
  801. nonceStr: String(nonceStr),
  802. signature: String(signature),
  803. signUrl: String(signUrlUsed || "")
  804. .split("#")[0]
  805. .trim(),
  806. };
  807. }
  808. function getWxErrMsg(err) {
  809. if (!err) return "";
  810. if (err.errMsg) return String(err.errMsg);
  811. if (typeof err === "string") return err;
  812. try {
  813. return JSON.stringify(err);
  814. } catch (e) {
  815. return String(err);
  816. }
  817. }
  818. function formatWxConfigErrorTip(err, signPageUrl) {
  819. var errMsg = getWxErrMsg(err);
  820. var tip = "微信 JSSDK 配置失败";
  821. if (/invalid signature/i.test(errMsg)) {
  822. return (
  823. tip +
  824. ":签名无效。请核对:①后端用与前端相同的 url 签名;②url=" +
  825. (signPageUrl || getWxHtmlUrl()) +
  826. ";③nonceStr/timestamp 与接口返回一致;④appId=" +
  827. WECHAT_MP_APP_ID
  828. );
  829. }
  830. if (/require\s*subscribe/i.test(errMsg)) {
  831. return tip + ":" + errMsg + "(服务号需用户已关注)";
  832. }
  833. return errMsg ? tip + ":" + errMsg : tip;
  834. }
  835. function setWxInitError(msg) {
  836. wxInitLastError = String(msg || "").trim();
  837. if (wxInitLastError) console.warn("[wx]", wxInitLastError);
  838. }
  839. function requestWeChatJssdkSignAndConfig(htmlUrlOptional) {
  840. var htmlUrl = String(htmlUrlOptional != null ? htmlUrlOptional : getWxConfigSignUrl())
  841. .split("#")[0]
  842. .trim();
  843. if (!htmlUrl || !/^https?:\/\//i.test(htmlUrl)) {
  844. htmlUrl = WX_GET_CONFIG_SIGN_URL;
  845. }
  846. if (isWxDebugOn()) {
  847. try {
  848. window.alert("htmlUrl(签名用,应与地址栏一致):\n" + htmlUrl);
  849. } catch (eDbg) {}
  850. }
  851. var requestUrl = getWxGetConfigApiUrl();
  852. var requestBody = buildWxGetConfigRequestBody(htmlUrl);
  853. return fetch(requestUrl, {
  854. method: "POST",
  855. mode: "cors",
  856. credentials: "omit",
  857. headers: {
  858. Accept: "application/json",
  859. "Content-Type": "application/json;charset=UTF-8",
  860. },
  861. body: JSON.stringify(requestBody),
  862. })
  863. .then(function (r) {
  864. if (r.ok) return r.json();
  865. return r
  866. .text()
  867. .catch(function () {
  868. return "";
  869. })
  870. .then(function (text) {
  871. var hint = "";
  872. try {
  873. var j = JSON.parse(text);
  874. hint = j.msg || j.message || "";
  875. } catch (eP) {
  876. if (text) hint = text.slice(0, 120);
  877. }
  878. throw new Error("getWxConfig HTTP " + r.status + (hint ? ":" + hint : ""));
  879. });
  880. })
  881. .then(function (res) {
  882. if (res && res.code != null) {
  883. var c = Number(res.code);
  884. if (c !== 200 && c !== 0 && res.success !== true) {
  885. throw new Error(res.msg || res.message || "getWxConfig code " + c);
  886. }
  887. }
  888. var sign = normalizeWxJssdkSignPayload(res, htmlUrl);
  889. if (!sign) {
  890. throw new Error("getWxConfig 缺少 appId/timestamp/nonceStr/signature(见控制台)");
  891. }
  892. if (typeof wx === "undefined") {
  893. if (isWxPcBrowser()) {
  894. console.log("[wx] PC getWxConfig 成功(无 jweixin)", sign);
  895. return true;
  896. }
  897. setWxInitError("jweixin.js 未加载");
  898. return false;
  899. }
  900. return applyWxConfigFromSign(sign, htmlUrl);
  901. });
  902. }
  903. function isWxLaunchTagRendered() {
  904. var tag = document.getElementById("launch-btn");
  905. if (!tag) return false;
  906. try {
  907. if (tag.shadowRoot) {
  908. var innerBtn = tag.shadowRoot.querySelector("button, .wx-open-app-btn");
  909. if (innerBtn) return true;
  910. }
  911. } catch (eShadow) {}
  912. var rect = tag.getBoundingClientRect();
  913. return rect.height >= 40 && rect.width >= 40;
  914. }
  915. function activateWxLaunchTagUi() {
  916. document.body.classList.add("wx-jssdk-ready");
  917. if (!isWeChatInAppBrowser()) return;
  918. window.setTimeout(function () {
  919. if (isWxLaunchTagRendered()) return;
  920. document.body.classList.remove("wx-jssdk-ready");
  921. console.warn("[wx] launch tag not rendered, fallback to #openApp");
  922. }, 500);
  923. }
  924. function applyWxConfigFromSign(sign, htmlUrl) {
  925. var wxConfigParams = {
  926. debug: isWxDebugOn(),
  927. appId: String(sign.appId),
  928. timestamp: sign.timestamp,
  929. nonceStr: String(sign.nonceStr),
  930. signature: String(sign.signature),
  931. jsApiList: [],
  932. openTagList: ["wx-open-launch-app"],
  933. };
  934. return new Promise(function (resolve) {
  935. wx.config(wxConfigParams);
  936. wx.ready(function () {
  937. weChatJssdkConfigured = true;
  938. refreshWxLaunchTagAttrs();
  939. activateWxLaunchTagUi();
  940. console.log("[wx.config] ready, htmlUrl=", htmlUrl);
  941. resolve(true);
  942. });
  943. wx.error(function (err) {
  944. weChatJssdkConfigured = false;
  945. document.body.classList.remove("wx-jssdk-ready");
  946. wxJssdkInitPromise = null;
  947. var errMsg = getWxErrMsg(err);
  948. setWxInitError(formatWxConfigErrorTip(err, htmlUrl));
  949. if (isWxDebugOn()) window.alert(wxInitLastError);
  950. console.warn("[wx.config]", errMsg, "htmlUrl=", htmlUrl);
  951. var baseUrl = getWxHtmlUrlBase();
  952. var fullUrl = getWxSignPageUrlForApi();
  953. if (
  954. !/invalid signature/i.test(errMsg) ||
  955. wxConfigSignRetriedBaseUrl ||
  956. baseUrl === fullUrl ||
  957. htmlUrl === baseUrl
  958. ) {
  959. resolve(false);
  960. return;
  961. }
  962. wxConfigSignRetriedBaseUrl = true;
  963. requestWeChatJssdkSignAndConfig(baseUrl).then(resolve);
  964. });
  965. });
  966. }
  967. function refreshWxLaunchTagAttrs(useBarePathOnly) {
  968. var tag = document.getElementById("launch-btn");
  969. if (!tag) return;
  970. try {
  971. tag.setAttribute("appid", WECHAT_OPEN_APP_ID);
  972. tag.setAttribute("extinfo", buildWeChatLaunchExtinfo(!!useBarePathOnly));
  973. } catch (eA) {}
  974. }
  975. function bindWeChatLaunchTagEvents() {
  976. var tag = document.getElementById("launch-btn");
  977. if (!tag || tag._wxLaunchBound) return;
  978. tag._wxLaunchBound = true;
  979. refreshWxLaunchTagAttrs();
  980. tag.addEventListener("launch", function () {
  981. console.log("[wx-open-launch-app] launch ok");
  982. });
  983. tag.addEventListener("error", function (e) {
  984. var detail = e && e.detail;
  985. var errMsg =
  986. detail && detail.errMsg
  987. ? String(detail.errMsg)
  988. : detail && detail.errmsg
  989. ? String(detail.errmsg)
  990. : "";
  991. console.warn(
  992. "[wx-open-launch-app]",
  993. detail,
  994. "extinfo=",
  995. tag.getAttribute("extinfo")
  996. );
  997. if (/launch:fail_check/i.test(errMsg)) {
  998. showAppOpenFailTip(
  999. "请用微信分享卡片进入,或确认已安装最新版「U店在哪」"
  1000. );
  1001. return;
  1002. }
  1003. if (
  1004. /launch:fail/i.test(errMsg) &&
  1005. !tag._wxLaunchBareRetried &&
  1006. tag.getAttribute("extinfo") !== buildWeChatLaunchExtinfo(true)
  1007. ) {
  1008. tag._wxLaunchBareRetried = true;
  1009. refreshWxLaunchTagAttrs(true);
  1010. showFabToast("请再点一次「和U宝继续聊」");
  1011. return;
  1012. }
  1013. if (/launch:fail/i.test(errMsg) && !getWxShareEntryFrom()) {
  1014. showAppOpenFailTip(
  1015. "当前环境无法直接打开 App,请使用 App「分享到微信」后点分享卡片进入"
  1016. );
  1017. return;
  1018. }
  1019. showAppOpenFailTip(
  1020. errMsg
  1021. ? "未能打开 App:" + errMsg
  1022. : "未能打开 App,请确认已安装最新版「U店在哪」"
  1023. );
  1024. });
  1025. }
  1026. function initWeChatOpenLaunchApp(fromUserClick) {
  1027. if (!shouldFetchWxConfig(!!fromUserClick)) {
  1028. return Promise.resolve(false);
  1029. }
  1030. if (wxJssdkInitPromise && !fromUserClick) return wxJssdkInitPromise;
  1031. wxConfigSignRetriedBaseUrl = false;
  1032. wxInitLastError = "";
  1033. var htmlUrl = getWxConfigSignUrl();
  1034. bindWeChatLaunchTagEvents();
  1035. wxJssdkInitPromise = requestWeChatJssdkSignAndConfig(htmlUrl)
  1036. .then(function (ok) {
  1037. if (ok === true) return true;
  1038. if (!wxInitLastError) {
  1039. setWxInitError("wx.config 失败,可加 ?wxDebug=1 查看 htmlUrl");
  1040. }
  1041. return false;
  1042. })
  1043. .catch(function (e) {
  1044. var msg = e && e.message ? e.message : "getWxConfig 请求失败";
  1045. setWxInitError(msg);
  1046. console.warn("[wx] requestWeChatJssdkSignAndConfig failed", msg, "htmlUrl=", htmlUrl);
  1047. if (isWeChatInAppBrowser() && isWxDebugOn()) window.alert(msg);
  1048. return false;
  1049. })
  1050. .finally(function () {
  1051. if (!weChatJssdkConfigured) wxJssdkInitPromise = null;
  1052. });
  1053. return wxJssdkInitPromise;
  1054. }
  1055. function scheduleWeChatJssdkBootstrap() {
  1056. if (!shouldInitWeChatJssdkOnLoad()) return;
  1057. var attempts = 0;
  1058. function tick() {
  1059. attempts += 1;
  1060. if (weChatJssdkConfigured) return;
  1061. initWeChatOpenLaunchApp();
  1062. if (!weChatJssdkConfigured && attempts < 8 && typeof wx === "undefined") {
  1063. setTimeout(tick, 400);
  1064. }
  1065. }
  1066. if (isIOSWeChatBrowser()) {
  1067. setTimeout(tick, 350);
  1068. } else {
  1069. tick();
  1070. }
  1071. }
  1072. function showFabToast(msg, ms) {
  1073. var tip = String(msg || "").trim();
  1074. if (!tip) return;
  1075. var el = document.getElementById("openAppToast");
  1076. if (el) {
  1077. el.textContent = tip;
  1078. el.style.display = "block";
  1079. if (showFabToast._t) clearTimeout(showFabToast._t);
  1080. showFabToast._t = setTimeout(function () {
  1081. el.style.display = "none";
  1082. }, ms || 2800);
  1083. }
  1084. console.log("[openApp]", tip);
  1085. }
  1086. function showDownloadTip() {
  1087. var msg = "请到应用商店下载「U店在哪」";
  1088. if (typeof uni !== "undefined" && typeof uni.showToast === "function") {
  1089. uni.showToast({ title: msg, icon: "none", duration: 2500 });
  1090. } else {
  1091. window.alert(msg);
  1092. }
  1093. }
  1094. function showAppOpenFailTip(msg) {
  1095. var tip = msg || "未能打开 App,请确认已安装最新版「U店在哪」。";
  1096. if (typeof uni !== "undefined" && typeof uni.showToast === "function") {
  1097. uni.showToast({ title: msg, icon: "none", duration: 2800 });
  1098. } else if (isWeChatInAppBrowser()) {
  1099. window.alert(tip);
  1100. } else {
  1101. showFabToast(tip);
  1102. }
  1103. }
  1104. function launchAppDeepLink(deepLink) {
  1105. try {
  1106. var a = document.createElement("a");
  1107. a.href = deepLink;
  1108. a.setAttribute("target", "_self");
  1109. document.body.appendChild(a);
  1110. a.click();
  1111. document.body.removeChild(a);
  1112. } catch (e1) {}
  1113. try {
  1114. window.location.href = deepLink;
  1115. } catch (e2) {}
  1116. }
  1117. function tryOpenHBuilderAppViaScheme() {
  1118. var deepLink = buildAppDeepLink();
  1119. if (typeof plus !== "undefined" && plus.runtime) {
  1120. var installed = null;
  1121. try {
  1122. if (typeof plus.runtime.isApplicationExist === "function") {
  1123. installed = plus.runtime.isApplicationExist({
  1124. pname: APP_ANDROID_PACKAGE,
  1125. action: APP_IOS_URL_SCHEME,
  1126. });
  1127. }
  1128. } catch (e) {
  1129. console.warn(e);
  1130. }
  1131. try {
  1132. plus.runtime.openURL(deepLink);
  1133. } catch (e2) {
  1134. console.warn(e2);
  1135. if (installed === false) {
  1136. showDownloadTip();
  1137. }
  1138. }
  1139. return;
  1140. }
  1141. var done = false;
  1142. function finish() {
  1143. if (done) return;
  1144. done = true;
  1145. document.removeEventListener("visibilitychange", onVis);
  1146. window.removeEventListener("pagehide", onHide);
  1147. }
  1148. function onVis() {
  1149. if (document.visibilityState === "hidden") finish();
  1150. }
  1151. function onHide() {
  1152. finish();
  1153. }
  1154. document.addEventListener("visibilitychange", onVis);
  1155. window.addEventListener("pagehide", onHide);
  1156. try {
  1157. launchAppDeepLink(deepLink);
  1158. } catch (e3) {
  1159. finish();
  1160. showDownloadTip();
  1161. return;
  1162. }
  1163. window.setTimeout(function () {
  1164. finish();
  1165. }, 3200);
  1166. }
  1167. function tryOpenApp() {
  1168. if (isWeChatInAppBrowser()) return;
  1169. tryOpenHBuilderAppViaScheme();
  1170. }
  1171. function boot() {
  1172. var launchTag = document.getElementById("launch-btn");
  1173. if (launchTag) launchTag.setAttribute("appid", WECHAT_OPEN_APP_ID);
  1174. bindWeChatLaunchTagEvents();
  1175. if (isWeChatInAppBrowser()) {
  1176. document.body.classList.add("is-wechat");
  1177. logWxEntryDiagnostics();
  1178. }
  1179. if (shouldInitWeChatJssdkOnLoad()) {
  1180. if (isWxPcBrowser() && (isWxForceDebug() || isWxPcAutoDebugHost())) {
  1181. document.body.classList.add("wx-pc-debug");
  1182. }
  1183. scheduleWeChatJssdkBootstrap();
  1184. }
  1185. document.addEventListener("WeixinOpenTagsError", function (e) {
  1186. document.body.classList.remove("wx-jssdk-ready");
  1187. weChatJssdkConfigured = false;
  1188. wxJssdkInitPromise = null;
  1189. console.warn("[WeixinOpenTagsError]", e && e.detail);
  1190. });
  1191. var openBtnWx = document.getElementById("openApp");
  1192. if (openBtnWx) {
  1193. if (isWeChatInAppBrowser()) {
  1194. openBtnWx.addEventListener("click", function () {
  1195. if (!weChatJssdkConfigured) {
  1196. showFabToast(
  1197. wxInitLastError || "微信 SDK 初始化中,请稍候再点底部按钮"
  1198. );
  1199. initWeChatOpenLaunchApp(true);
  1200. }
  1201. });
  1202. } else {
  1203. openBtnWx.addEventListener("click", tryOpenApp);
  1204. }
  1205. }
  1206. render(parsePayload());
  1207. }
  1208. if (document.readyState === "complete") {
  1209. boot();
  1210. } else {
  1211. window.addEventListener("load", boot);
  1212. }
  1213. })();
  1214. </script>
  1215. </body>
  1216. </html>