yankun 1 ماه پیش
کامیت
cd75059f8b
100فایلهای تغییر یافته به همراه28896 افزوده شده و 0 حذف شده
  1. 3 0
      .gitignore
  2. 36 0
      .hbuilderx/launch.json
  3. 243 0
      App.vue
  4. 21 0
      LICENSE
  5. 15 0
      README.md
  6. 78 0
      androidPrivacy.json
  7. 56 0
      api/bank.js
  8. 5 0
      api/index.js
  9. 527 0
      api/shop.js
  10. 167 0
      api/system.js
  11. 368 0
      api/user.js
  12. 58 0
      api/video.js
  13. 8 0
      changelog.md
  14. 122 0
      components/CameraUpload.vue
  15. 533 0
      components/DomVideoPlayer.vue
  16. 141 0
      components/GlobalLoading.vue
  17. 136 0
      components/ImageGrid.vue
  18. 115 0
      components/IosUpdateModal.vue
  19. 388 0
      components/MultiSelectDropdown.vue
  20. 308 0
      components/PinCodeModal.vue
  21. 201 0
      components/ShareDialog.vue
  22. 248 0
      components/UPickerField.vue
  23. 455 0
      components/address.vue
  24. 104 0
      components/area.vue
  25. 493 0
      components/blindModel.vue
  26. 245 0
      components/commentDialog.vue
  27. 127 0
      components/couponModel.vue
  28. 126 0
      components/floatButton.vue
  29. 255 0
      components/footer_input.vue
  30. 137 0
      components/imageUpload.vue
  31. 84 0
      components/imgUp.vue
  32. 158 0
      components/input.vue
  33. 207 0
      components/list copy.vue
  34. 248 0
      components/list.vue
  35. 205 0
      components/message/components/consultCard.vue
  36. 77 0
      components/message/components/purposeCard.vue
  37. 76 0
      components/message/components/questionCard.vue
  38. 76 0
      components/message/components/tipsListCard.vue
  39. 36 0
      components/message/hooks/useTools.js
  40. 216 0
      components/message/index.vue
  41. 256 0
      components/nav_filter.vue
  42. 119 0
      components/nav_menu.vue
  43. 147 0
      components/navbar.vue
  44. 79 0
      components/passwordModal.vue
  45. 110 0
      components/paymentModal/applePay.vue
  46. 190 0
      components/paymentModal/cardPayment_app.vue
  47. 83 0
      components/paymentModal/dropInPay.vue
  48. 107 0
      components/paymentModal/googlePay.vue
  49. 162 0
      components/paymentModal/googlePayment_app.vue
  50. 4 0
      components/paymentModal/hooks/index.js
  51. 63 0
      components/paymentModal/hooks/useAppleInfo.js
  52. 93 0
      components/paymentModal/hooks/useDropInPayInfo.js
  53. 61 0
      components/paymentModal/hooks/useGoogleInfo.js
  54. 99 0
      components/paymentModal/hooks/useSplitCardInfo.js
  55. 166 0
      components/paymentModal/splitCardPay.vue
  56. 183 0
      components/picker.vue
  57. 142 0
      components/placard.vue
  58. 294 0
      components/play.vue
  59. 517 0
      components/popover.vue
  60. 128 0
      components/popup.vue
  61. 222 0
      components/select.vue
  62. 112 0
      components/simpleAgreementModal.vue
  63. 62 0
      components/singleImageUploader.vue
  64. 138 0
      components/swiper.vue
  65. 290 0
      components/tabbar.vue
  66. 132 0
      components/tabs.vue
  67. 74 0
      components/theme.vue
  68. 49 0
      components/tooltip.vue
  69. 16 0
      components/trans.vue
  70. 175 0
      components/videoUpload.vue
  71. 313 0
      components/y-video copy 2.vue
  72. 400 0
      components/y-video.vue
  73. 24 0
      index.html
  74. 591 0
      locale/en.json
  75. 513 0
      locale/es.json
  76. 71 0
      locale/index.js
  77. 599 0
      locale/km.json
  78. 599 0
      locale/zh.json
  79. 29 0
      main.js
  80. 199 0
      manifest.json
  81. 10461 0
      package-lock.json
  82. 103 0
      package.json
  83. 248 0
      pages.json
  84. 26 0
      pages/Commission/index.vue
  85. 349 0
      pages/address/components/addressModel.vue
  86. 269 0
      pages/address/index.vue
  87. 85 0
      pages/bank/account.vue
  88. 236 0
      pages/bank/bank_pay.vue
  89. 200 0
      pages/bank/qrcode.vue
  90. 296 0
      pages/bank/recharge.vue
  91. 120 0
      pages/bank/recharge_list.vue
  92. 192 0
      pages/bank/wallet.vue
  93. 302 0
      pages/bank/withdraw.vue
  94. 132 0
      pages/bank/withdraw_list.vue
  95. 265 0
      pages/channel/index.vue
  96. 52 0
      pages/chat/hooks/useListHeight.js
  97. 142 0
      pages/chat/hooks/useMessageData.js
  98. 36 0
      pages/chat/hooks/useTools.js
  99. 286 0
      pages/chat/index copy.vue
  100. 383 0
      pages/chat/index.vue

+ 3 - 0
.gitignore

@@ -0,0 +1,3 @@
+unpackage/*
+node_modules/*
+*.zip

+ 36 - 0
.hbuilderx/launch.json

@@ -0,0 +1,36 @@
+{
+    // launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
+    // launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数
+    "version" : "0.0",
+    "configurations" : [
+        {
+            "app" : {
+                "launchtype" : "remote"
+            },
+            "app-plus" : {
+                "launchtype" : "local"
+            },
+            "default" : {
+                "launchtype" : "local"
+            },
+            "h5" : {
+                "launchtype" : "local"
+            },
+            "provider" : "aliyun",
+            "type" : "uniCloud"
+        },
+        {
+            "openVueDevtools" : false,
+            "type" : "uni-app:h5"
+        },
+        {
+            "customPlaygroundType" : "local",
+            "playground" : "standard",
+            "type" : "uni-app:app-android"
+        },
+        {
+            "playground" : "standard",
+            "type" : "uni-app:app-ios"
+        }
+    ]
+}

+ 243 - 0
App.vue

@@ -0,0 +1,243 @@
+<script setup>
+import { watch, onBeforeUnmount } from "vue";
+import { onLaunch, onShow, onHide } from "@dcloudio/uni-app";
+import {
+  useSystemStore,
+  useShopStore,
+  useVideoStore,
+  useSocketStore,
+  useMessageStore,
+  useUserStore,
+  useTabbarStore,
+} from "@/store";
+import { storeToRefs } from "pinia";
+import { setLan, findLang } from "@/locale";
+import { parseUrl } from "@/utils";
+import appUpdate from "./utils/appUpdate";
+import { USER_INIT } from "@/api";
+
+const useSystem = useSystemStore();
+const useShop = useShopStore();
+const useVideo = useVideoStore();
+const useScoket = useSocketStore();
+const useMessage = useMessageStore();
+const useUser = useUserStore();
+const useTabbar = useTabbarStore();
+
+const { isFirstConnectNetwork, networkStatus, isHomeFirstConnect } =
+  storeToRefs(useSystem);
+
+function initFunc() {
+  useSystem.setWinnotice();
+  useSystem.setRateList();
+  useShop.setCartList();
+  useShop.setHotLink();
+  useScoket.connect();
+  // useVideo.setVideoList();
+}
+
+onLaunch(async () => {
+  useSystem.checkNetworkStatus();
+  // 监听网络状态
+  listenerNetworkStatus();
+  // initFunc();
+  // #ifdef APP-PLUS
+  appUpdate();
+  initPushService();
+  clearBadge();
+  // #endif
+
+  // #ifdef H5
+  setInit();
+  // #endif
+});
+onShow(() => {
+  clearBadge();
+  // #ifdef H5
+  getLang();
+  // #endif
+});
+onHide(() => {});
+
+onBeforeUnmount(() => {
+  uni.$off("$onMessage");
+  stopWatch();
+});
+
+const stopWatch = watch(
+  [isFirstConnectNetwork, networkStatus], // 监听多个响应式变量
+  ([newIsFirst, newNetStatus], [oldIsFirst, oldNetStatus]) => {
+    // console.log("联动变化:", {
+    //   首次连接标记: `${oldIsFirst}→${newIsFirst}`,
+    //   网络状态: `${oldNetStatus ? "已连接" : "断开"}→${
+    //     newNetStatus ? "已连接" : "断开"
+    //   }`,
+    // });
+    if (newNetStatus) {
+      initFunc();
+      useSystem.setFirstConnectStatus(false);
+    }
+  }
+);
+function listenerNetworkStatus() {
+  uni.onNetworkStatusChange((res) => {
+    const { isConnected, networkType } = res;
+    if (isConnected && networkType != "none") {
+      if (isFirstConnectNetwork.value) {
+        initFunc();
+      }
+      useSystem.setNetworkStatus(true);
+    } else {
+      useSystem.setNetworkStatus(false);
+    }
+  });
+}
+
+const getLang = () => {
+  let urlObj = parseUrl(window.location.href);
+  let lang = urlObj["lang"];
+  let langValue = findLang(lang) && findLang(lang).value;
+  if (langValue) {
+    useSystem.setLan(langValue);
+    setLan(langValue, () => {
+      useShop.setHotLink();
+    });
+  }
+};
+
+function initPushService() {
+  uni.getPushClientId({
+    success: (res) => {
+      setInit({ push_cid: res.cid });
+    },
+    fail: (err) => {
+      setInit();
+      console.error("获取推送ID失败:", err);
+    },
+  });
+}
+const setInit = async (para) => {
+  try {
+    const res = await USER_INIT(para);
+    useUser.setInitId(res.data.auth_id);
+    // #ifdef APP-PLUS
+    useSystem.setAppinfo(res.data.appinfo);
+    // #endif
+    if (res.data.token) {
+      useUser.setUserInfo(res.data);
+    }
+  } catch (error) {}
+};
+
+// 清除角标的方法
+function clearBadge() {
+  // #ifdef APP-PLUS
+  useMessage.getTotalUnreadCount();
+  // #endif
+}
+
+uni.$on("$onMessage", ({ event, channel, data }) => {
+  // console.log('event, channel, data', event, channel, data)
+  useScoket.checkStatus();
+  if (
+    channel &&
+    channel.includes("private-call") &&
+    data.extend.message_event == "new_message"
+  ) {
+    const msgInfo = JSON.parse(data.message);
+    if (msgInfo.send == 1) return;
+    useMessage.updateMessageList(
+      channel,
+      {
+        ...msgInfo,
+        msg: JSON.parse(msgInfo.msg),
+      },
+      "push"
+    );
+    useMessage.updateGlobalMapLasttime(
+      `${msgInfo.type}Channel`,
+      msgInfo.indate
+    );
+    useMessage.updateUnreadCount(channel);
+  } else if (
+    channel &&
+    channel.includes("private-user") &&
+    data.extend.message_event == "new_message"
+  ) {
+    const msgInfo = JSON.parse(data.message);
+    // #ifdef APP-PLUS
+    // const cont = JSON.parse(msgInfo.lastmsg || '{}')
+    // uni.createPushMessage({
+    //   content: cont.text || '测试数据', success: res => {
+    //     console.log('通知栏调用成功', res);
+    //   }, fail: err => {
+    //     console.error('通知栏调用失败', err);
+    //   }
+    // })
+    // #endif
+    useMessage.updateGlobalMapUnreadCount(`${msgInfo.type}Channel`);
+  }
+});
+
+const onPush = () => {
+  uni.onPushMessage((res) => {
+    const data = res.data;
+    console.log(res);
+    if (res.type === "receive") {
+      // 推送到通知栏
+      uni.createPushMessage({
+        title: data?.title,
+        content: data?.content || "收到新消息",
+        payload: data?.payload,
+        success: (r) => {
+          console.log("推送成功", r);
+        },
+        fail: (err) => {
+          console.error("推送失败", err);
+        },
+      });
+    }
+    if (res.type == "click") {
+      console.log("通知栏", data);
+    }
+  });
+};
+
+// #ifdef APP-PLUS
+onPush();
+// #endif
+</script>
+
+<style>
+@import url("./static/fonts.css");
+@import url("static/css/main.css");
+
+/* @font-face {
+  font-family: 'MyCustomFont';
+  src: url('../static/fonts/SourceHanSansCN-VF.otf') format('opentype');
+  font-weight: normal;
+  font-style: normal;
+} */
+
+@font-face {
+  font-family: "HarmonyOS_Sans";
+  src: url("../static/fonts/HarmonyOS_Sans_SC.ttf") format("truetype");
+  font-weight: normal;
+  font-style: normal;
+}
+
+body {
+  /* font-family: 'MyCustomFont'; */
+}
+</style>
+<style lang="scss">
+@import "@/uni_modules/uview-plus/index.scss";
+
+.container {
+  padding: 15px;
+}
+
+button {
+  margin-bottom: 15px;
+}
+</style>

+ 21 - 0
LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2021 DCloud
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 15 - 0
README.md

@@ -0,0 +1,15 @@
+# hello-i18n
+
+# en
+
+A demo project for uni-app globalization
+
+This template include uni-framework, manifest.json, pages.json, tabbar, Page, Component, API
+
+
+# zh-hans
+
+uni-app 国际化演示
+
+包含 uni-framework、manifest.json、pages.json、tabbar、页面、组件、API
+

+ 78 - 0
androidPrivacy.json

@@ -0,0 +1,78 @@
+{
+    "version" : "13",
+    "prompt" : "template",
+    "title" : "User Agreement and Privacy Policy",
+    "titleLocales" : {
+        "en" : "User Agreement and Privacy Policy",
+        "zh-CN" : "用户协议和隐私政策",
+        "es" : "Acuerdo de Usuario y Política de Privacidad"
+    },
+    "message" : "Please carefully read and fully understand all terms of the \"Service Agreement\" and \"Privacy Policy\", including but not limited to: To better provide you with services, we need to collect your device identifiers, operation logs and other information for analyzing and optimizing application performance. <a href=\"https://vavabuy.com/article/article_details?id=20&cateId=36&isTop=true\">Privacy Policy</a> and <a href=\"https://vavabuy.com/article/article_details?id=14&cateId=36&isTop=true\">User Agreement</a> for detailed information. If you agree, please click the button below to start receiving our services.",
+    "messageLocales" : {
+        "en" : "Please carefully read and fully understand all terms of the \"Service Agreement\" and \"Privacy Policy\", including but not limited to: To better provide you with services, we need to collect your device identifiers, operation logs and other information for analyzing and optimizing application performance. <a href=\"https://vavabuy.com/article/article_details?id=20&cateId=36&isTop=true\">Privacy Policy</a> and <a href=\"https://vavabuy.com/article/article_details?id=14&cateId=36&isTop=true\">User Agreement</a> for detailed information. If you agree, please click the button below to start receiving our services.",
+        "zh-CN" : "请您务必审慎阅读、充分理解“服务协议”和“隐私政策”的全部条款,包括但不限于:为了更好地向您提供服务,我们需要收集您的设备标识、操作日志等信息,用于分析和优化应用性能。您可以阅读<a href=\"https://vavabuy.com/article/article_details?id=19&cateId=36&isTop=true\">《隐私政策》</a>和<a href=\"https://vavabuy.com/article/article_details?id=2&cateId=36&isTop=true\">《用户协议》</a>了解详细信息。如果您同意,请点击下方按钮开始接受我们的服务。",
+        "es" : "Por favor, lea detenidamente y comprenda completamente todos los términos del \"Acuerdo de Servicio\" y la \"Política de Privacidad\", incluyendo pero no limitado a: Para brindarle un mejor servicio, necesitamos recopilar sus identificadores de dispositivo, registros de operaciones y otra información para analizar y optimizar el rendimiento de la aplicación. Puede leer <a href=\"https://vavabuy.com/article/article_details?id=20&cateId=36&isTop=true\">Política de Privacidad</a> y <a href=\"https://vavabuy.com/article/article_details?id=14&cateId=36&isTop=true\">Acuerdo de Usuario</a> para obtener información detallada. Si está de acuerdo, haga clic en el botón de abajo para comenzar a recibir nuestros servicios."
+    },
+    "buttonAccept" : "Agree and Accept",
+    "buttonAcceptLocales" : {
+        "en" : "Agree and Accept",
+        "zh-CN" : "同意并接受",
+        "es" : "Aceptar y Confirmar"
+    },
+    "buttonRefuse" : "Do Not Agree Temporarily",
+    "buttonRefuseLocales" : {
+        "en" : "Do Not Agree Temporarily",
+        "zh-CN" : "暂不同意",
+        "es" : "No Aceptar Temporalmente"
+    },
+    "hrefLoader" : "system",
+    "backToExit" : "false",
+    "second" : {
+        "title" : "Confirmation Prompt",
+        "titleLocales" : {
+            "en" : "Confirmation Prompt",
+            "zh-CN" : "确认提示",
+            "es" : "Prompt de Confirmación"
+        },
+        "message" : "Before entering the application, you must agree to the <a href=\"https://vavabuy.com/article/article_details?id=20&cateId=36&isTop=true\">Privacy Policy</a> and <a href=\"https://vavabuy.com/article/article_details?id=14&cateId=36&isTop=true\">User Agreement</a>; otherwise, you will exit the application.",
+        "messageLocales" : {
+            "en" : "Before entering the application, you must agree to the <a href=\"https://vavabuy.com/article/article_details?id=20&cateId=36&isTop=true\">Privacy Policy</a> and <a href=\"https://vavabuy.com/article/article_details?id=14&cateId=36&isTop=true\">User Agreement</a>; otherwise, you will exit the application.",
+            "zh-CN" : "进入应用前,您必须同意<a href=\"https://vavabuy.com/article/article_details?id=19&cateId=36&isTop=true\">《隐私政策》</a>和<a href=\"https://vavabuy.com/article/article_details?id=2&cateId=36&isTop=true\">《用户协议》</a>,否则将退出应用。",
+            "es" : "Antes de entrar en la aplicación, debe aceptar la <a href=\"https://vavabuy.com/article/article_details?id=20&cateId=36&isTop=true\">Política de Privacidad</a> y el <a href=\"https://vavabuy.com/article/article_details?id=14&cateId=36&isTop=true\">Acuerdo de Usuario</a>; de lo contrario, saldrá de la aplicación."
+        },
+        "buttonAccept" : "Agree and Continue",
+        "buttonAcceptLocales" : {
+            "en" : "Agree and Continue",
+            "zh-CN" : "同意并继续",
+            "es" : "Aceptar y Continuar"
+        },
+        "buttonRefuse" : "Exit Application",
+        "buttonRefuseLocales" : {
+            "en" : "Exit Application",
+            "zh-CN" : "退出应用",
+            "es" : "Salir de la Aplicación"
+        }
+    },
+    "disagreeMode" : {
+        "support" : false,
+        "loadNativePlugins" : false,
+        "visitorEntry" : false,
+        "showAlways" : false
+    },
+    "styles" : {
+        "backgroundColor" : "#fff",
+        "borderRadius" : "12px",
+        "title" : {
+            "color" : "#000000"
+        },
+        "buttonAccept" : {
+            "color" : "#1890ff"
+        },
+        "buttonRefuse" : {
+            "color" : "#ff4d4f"
+        },
+        "buttonVisitor" : {
+            "color" : "#ff4d4f"
+        }
+    }
+}

+ 56 - 0
api/bank.js

@@ -0,0 +1,56 @@
+import { $post } from '@/utils'
+
+export const PAY_LISTS = () => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/pay/lists');
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const PAY_SUBMIT = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/pay/submit', params);
+    const { ret } = res
+    if (ret == 1) {
+      resolve(res)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const USER_BANK_ADD = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/users/bank/add', params);
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const USER_BANK = () => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/users/bank');
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const USER_EXTRACT = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/users/extract', params);
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})

+ 5 - 0
api/index.js

@@ -0,0 +1,5 @@
+export * from './user'
+export * from './system'
+export * from './shop'
+export * from './bank'
+export * from './video'

+ 527 - 0
api/shop.js

@@ -0,0 +1,527 @@
+import { $get, $post } from '@/utils'
+
+export const SHOP_ACTION = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/order/actions', params);
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_DETAIL = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/goods/info', params);
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_ADD_CART = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/add/cart', params);
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_CART_LIST = (is_free = 0) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/cart/list', { is_free });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_CART_CONFIRM = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/cart/confirm', params);
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_CART_FCONFIRM = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/cart/fconfirm', params);
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_CART_DEL = (id = '') => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/cart/del', { id });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_ORDER_SUBMIT = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/order/submit', params);
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_ORDER_FSUBMIT = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/order/fsubmit', params);
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+
+export const SHOP_PAY_INFO = (params = {}) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/pay/info', params);
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_SUBMIT_PAY = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/submit/pay', params);
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_ORDER_STATUS = () => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/order/status');
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_ORDER_GETPAY = (orderids = '') => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/order/getpay', { orderids });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_ORDER_DETAIL = (orderid = '') => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/order/detail', { orderid });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const CONTENT_FLOAT = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/content/float', params);
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_SEARCH_SIMILAR = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/search/similar', params);
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_USER_COLLECT = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/user/collect', params);
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_SELLER_INFO = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/seller/info', params);
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+
+export const SHOP_COLLECT_List = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/collect/list', params);
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+
+export const SHOP_PACKAGES_SUBMIT = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/packages/submit', params);
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_ADDRESS_LIST = () => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/address/list');
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_ADDRESS_ADD = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/address/add', params);
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_PACKAGES_CREATED = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/packages/create', params);
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_ADDRESS_DEL = (id = '') => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/address/del', { id });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_PACKAGES_PAY = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/packages/pay', params);
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_PACKAGES_DETAIL = (id = '') => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/packages/detail', { id });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_PACKAGES_CANCEL = (id = '') => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/packages/cancel', { id });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_PACKAGES_FINISH = (id = '') => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/packages/finish', { id });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const VIDEO_LISTS = ({ limit = 10, active_id = 0, isLoading = false }) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/discover/video/lists', { limit, active_id }, { isLoading });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const VIDEO_VIEWS = (id = '') => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/discover/video/views', { id }, { isLoading: true });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_ORDER_EXPRESS = (orderid = '') => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/order/express', { orderid }, { isLoading: true });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_STOCKS_INFO = (id = '') => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/stocks/info', { id });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_GET_CANCOUPON = (money = '') => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/get/cancoupon', { money });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_EXPRESS_TEMPLATE = () => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/express/template');
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+
+export const SHOP_PAY_STATUS = (params = {}) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/pay/status', { ...params });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_ORDER_CANCEL = (params = {}) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/order/cancel', { ...params });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_EDIT_CART = (params = {}) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/edit/cart', { ...params });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+
+export const SHOP_SHOPCOUNPON_LIST = (params = {}) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/shopcoupon/list', { ...params });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_GET_SHOPCOUPON = (money = 0) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/get/shopcoupon', { money });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_INDEX_ORDER = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/index/order', params, { isLoading: true });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_GOODS_CATEGORY = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/goods/category', params, { isLoading: true });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+
+export const SHOP_ADD_COMMENTS = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/add/comments', params, { isLoading: true });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+
+export const SHOP_SHOW_COMMENTS = (orderid = '') => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/show/comments', { orderid });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+
+export const SHOP_BUYBACK_LISTS = () => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/buyback/lists');
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+
+export const SHOP_SUBMIT_BUYBACK = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/submit/buyback', params);
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_BUYBACK_ORDER = (status = 0) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/buyback/order', { status });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_BUYBACK_EXPRESS = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/backbuy/express', params);
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})

+ 167 - 0
api/system.js

@@ -0,0 +1,167 @@
+import { $get, $post } from '@/utils'
+
+export const GTE_BANNER = () => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/content/slide', { position: "home" });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const RATE_LIST = () => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/third/rate/list');
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+
+export const OTHER_CONFIG = (act = '') => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/other/config', { act });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const CONTENT_WINNOTICE = () => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/content/winnotice');
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const CONTENT_TUTORIAL = () => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/content/tutorial');
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const CONTENT_HELP = () => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/content/help');
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const OTHER_ABOUT = (type = '') => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/other/about', { type });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const RONGIMCALL_OPEN = (params = {}) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/rongimcall/open', { ...params });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const RONGIMCALL_CLOSE = (params = {}) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/rongimcall/close', { ...params });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const RONGIMCALL_PAY_RETURN = (params = {}) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/rongimcall/pay/return', { ...params });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const RONGIMCALL_HISTORY = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/rongimcall/history', params, { isLoading: true });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const RONGIMCALL_SEND = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/rongimcall/send', params, { isLoading: true });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const USERS_AUTH = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/users/socket/auth', params, { isLoading: true });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_EXPRESS_CONFIG = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/express/config', params, { isLoading: true });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_POST_CALCULATE = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/post/calculate', params);
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})

+ 368 - 0
api/user.js

@@ -0,0 +1,368 @@
+import { $get, $post, getDeviceInfo, getEnterOptions } from '@/utils'
+import manifest from "@/manifest.json";
+import { version } from 'uuid';
+
+export const LOGIN = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/users/login', {
+      device_id: getDeviceInfo().deviceId,
+      ...params
+    });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+
+export const DEL_ACCOUNT = (params = {}) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/users/delaccount', { ...params });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const GET_USERINFO = (params = {}, other = {}) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/users/info', params, other);
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const USER_STATICS = () => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/users/statics');
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const USER_EDIT_USERPASS = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/users/edit/userpass', params);
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const USER_EDIT_PAYPASS = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/users/edit/paypass', params);
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const USERS_EMAIL_GET = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/users/email/get', params, { isLoading: true });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const USERS_EDIT_AVATAR = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/users/edit/avatar', params);
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const USERS_LEVELAUTH = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/users/levelauth', params);
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+
+export const GET_USERS_LEVELAUTH = () => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $get('/users/levelauth');
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+
+export const USERS_THIRD_LOGIN = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/users/third/login', params);
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const CONTENT_COUPON = (params = {}, other = {}) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/content/coupon', params, other);
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_GET_COUPON = (id = '') => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/get/coupon', { id });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const SHOP_COUPON_LIST = (status = 0) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/coupon/list', { status });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const USER_FORGET = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/users/forget', params, { isLoading: true });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+
+export const USER_INIT = (params = {}) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/users/init', {
+      device: getDeviceInfo(),
+      option: getEnterOptions(),
+      version: manifest.versionCode,
+      ...params
+    }, { isLoading: true });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) {
+    console.error(error);
+
+  }
+})
+
+export const USER_LOGOUT = () => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/users/logout');
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const USER_MESSAGE = (params = {}) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/users/message', { ...params });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) {
+    console.error(error);
+
+  }
+})
+
+export const USER_ORDER_COUNT = () => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/users/order/count');
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const USERS_MESSAGE_READER = (ids = '') => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/users/message/reader', { ids });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const USERS_MESSAGE_UNREAD = () => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/users/message/unread');
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const USERS_MESSAGE_DETAIL = (id = '') => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/users/message/detail', { id });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const USER_SMS = (params = {}) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/users/sms', { ...params });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) {
+    console.error(error);
+
+  }
+})
+
+export const CONTENT_BOXES = (params = {}) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/content/boxes', params, { isLoading: true });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const CONTENT_RECEIVE_BOX = (params = {}) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/content/receive/box', { ...params }, { isLoading: true });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) {
+    console.error(error);
+  }
+})
+
+
+export const CONTENT_BOX_LISTS = (params = {}) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/content/box/lists', { ...params });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) {
+    console.error(error);
+  }
+})
+
+export const SHOP_STORE_LISTS = (params = {}) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/shop/store/lists', { ...params });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) {
+    console.error(error);
+  }
+})
+
+export const USER_CHECK_PAYPASS = (oldpass = '') => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/users/check/paypass', { oldpass });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const RONGIMCALL_NEED_FROMS = (params = {}) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/rongimcall/need/froms', { ...params });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) {
+    console.error(error);
+  }
+})
+
+export const RONGIMCALL_FROMS_LISTS = (params = {}) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/rongimcall/froms/lists', { ...params });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) {
+    console.error(error);
+  }
+})
+
+
+

+ 58 - 0
api/video.js

@@ -0,0 +1,58 @@
+
+import { $get, $post } from '@/utils'
+
+export const VIDEO_GOODS = (id = '') => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/discover/video/goods', { id }, { isLoading: true });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const VIDEO_COLLECTS = (id = '') => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/discover/video/collects', { id }, { isLoading: true });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const DISCOVER_VIDEO_COMMENTS = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/discover/video/comments', params);
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const DISCOVER_VIDEO_SUBCOMMENTS = (params) => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/discover/video/subcomments', params);
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+
+export const DISCOVER_FOLLOW = (userid = "") => new Promise(async (resolve, reject) => {
+  try {
+    const res = await $post('/discover/follow', { userid });
+    const { ret } = res.data
+    if (ret == 1) {
+      resolve(res.data)
+    }
+    reject(res.data)
+  } catch (error) { }
+})
+

+ 8 - 0
changelog.md

@@ -0,0 +1,8 @@
+## 1.0.2(2022-06-30)
+- 新增 支持 ios 安全区
+## 1.0.1(2021-11-26)
+- 新增 schema 国际化 (HBuilderX 3.3+)
+- 修复 非 Android 平台切换语音无法实时变化的问题
+- 修复 设置某些语言下无法生效的问题 (HBuilderX 3.3+)
+## 1.0.0(2021-10-20)
+- 初始化

+ 122 - 0
components/CameraUpload.vue

@@ -0,0 +1,122 @@
+<template>
+  <Popup ref="popRef" mode="center" isClose>
+    <template #content>
+      <view class="content">
+        <view class="modal-header" v-if="isCamera">
+          <view class="title">
+            <trans _t="相机权限说明" />
+          </view>
+          <view class="tip">
+            <trans _t="用于上传用户头像、或依据图片信息搜索内容" />
+          </view>
+        </view>
+        <view class="modal-header">
+          <view class="title">
+            <trans _t="存储权限说明" />
+          </view>
+          <view class="tip">
+            <trans _t="用于选择照片" />
+          </view>
+        </view>
+      </view>
+    </template>
+    <template #footer>
+      <slot name="footer">
+        <view class="footer">
+          <view class="submit_btn" @click="select('camera')" v-if="isCamera">
+            <trans _t="拍照" />
+          </view>
+          <view class="submit_btn" @click="select('album')">
+            <trans _t="相册" />
+          </view>
+        </view>
+      </slot>
+    </template>
+  </Popup>
+</template>
+
+<script setup>
+import { ref, nextTick } from "vue";
+import Popup from "./popup.vue";
+import { uploadChooseImage, $upload, Toast } from "@/utils";
+
+const popRef = ref(null);
+
+const emit = defineEmits(["confirm", "close", "open"]);
+const props = defineProps({
+  isCamera: {
+    type: Boolean,
+    default: true,
+  },
+});
+
+const open = () => {
+  popRef.value && popRef.value.open();
+  emit("open");
+};
+
+const close = () => {
+  emit("close");
+  popRef.value && popRef.value.close();
+};
+
+const select = async (type) => {
+  try {
+    let file = await uploadChooseImage(type);
+    if (file.errMsg == "chooseImage:ok") {
+      const res = await $upload(file.tempFilePath);
+      nextTick(() => {
+        emit("confirm", res.data.url);
+      });
+    }
+  } catch (error) {}
+
+  close();
+};
+
+defineExpose({ open, close });
+</script>
+
+<style lang="less" scoped>
+@import url("@/style.less");
+
+:deep(.conts) {
+  max-width: 75vw;
+}
+
+.content {
+  .modal-header {
+    margin-bottom: 20rpx;
+
+    .title {
+      font-size: 32rpx;
+      font-weight: bold;
+    }
+
+    .tip {
+      font-size: 24rpx;
+    }
+  }
+}
+
+.footer {
+  .hor(space-between);
+  column-gap: 20rpx;
+
+  .submit_btn {
+    height: 76rpx;
+    padding: 16rpx 60rpx;
+    background-color: var(--black);
+    color: var(--light);
+    .flex_center();
+    border-radius: 16rpx;
+    .size(24rpx);
+
+    &.submit_shop {
+      background-color: var(--bg);
+      border: 1rpx solid var(--black);
+      color: var(--black);
+    }
+  }
+}
+</style>

+ 533 - 0
components/DomVideoPlayer.vue

@@ -0,0 +1,533 @@
+<!-- eslint-disable -->
+<template>
+  <view
+    class="player-wrapper"
+    :id="videoWrapperId"
+    :parentId="id"
+    :randomNum="randomNum"
+    :change:randomNum="domVideoPlayer.randomNumChange"
+    :viewportProps="viewportProps"
+    :change:viewportProps="domVideoPlayer.viewportChange"
+    :videoSrc="videoSrc"
+    :change:videoSrc="domVideoPlayer.initVideoPlayer"
+    :command="eventCommand"
+    :change:command="domVideoPlayer.triggerCommand"
+    :func="renderFunc"
+    :change:func="domVideoPlayer.triggerFunc"
+  />
+</template>
+
+<script>
+export default {
+  props: {
+    src: {
+      type: String,
+      default: ''
+    },
+    autoplay: {
+      type: Boolean,
+      default: false
+    },
+    loop: {
+      type: Boolean,
+      default: false
+    },
+    controls: {
+      type: Boolean,
+      default: false
+    },
+    objectFit: {
+      type: String,
+      default: 'contain'
+    },
+    muted: {
+      type: Boolean,
+      default: false
+    },
+    playbackRate: {
+      type: Number,
+      default: 0.5
+    },
+    isLoading: {
+      type: Boolean,
+      default: false
+    },
+    poster: {
+      type: String,
+      default: ''
+    },
+    id: {
+      type: String,
+      default: ''
+    }
+  },
+  data() {
+    return {
+      randomNum: Math.floor(Math.random() * 100000000),
+      videoSrc: '',
+      // 父组件向子组件传递的事件指令(video的原生事件)
+      eventCommand: null,
+      // 父组件传递过来的,对 renderjs 层的函数执行(对视频控制的自定义事件)
+      renderFunc: {
+        name: null,
+        params: null
+      },
+      // 提供给父组件进行获取的视频属性
+      currentTime: 0,
+      duration: 0,
+      playing: false
+    }
+  },
+  watch: {
+    // 监听视频资源地址更新
+    src: {
+      handler(val) {
+        if (!val) return
+        setTimeout(() => {
+          this.videoSrc = val
+        }, 0)
+      },
+      immediate: true
+    }
+  },
+  computed: {
+    videoWrapperId() {
+      return `video-wrapper-${this.randomNum}`
+    },
+    // 聚合视图层的所有数据变化,传给renderjs的渲染层
+    viewportProps() {
+      return {
+        autoplay: this.autoplay,
+        muted: this.muted,
+        controls: this.controls,
+        loop: this.loop,
+        objectFit: this.objectFit,
+        poster: this.poster,
+        isLoading: this.isLoading,
+        playbackRate: this.playbackRate
+      }
+    }
+  },
+  // 方法
+  methods: {
+    // 传递事件指令给父组件
+    eventEmit({ event, data }) {
+      this.$emit(event, data)
+    },
+    // 修改view视图层的data数据
+    setViewData({ key, value }) {
+      key && this.$set(this, key, value)
+    },
+    // 重置事件指令
+    resetEventCommand() {
+      this.eventCommand = null
+    },
+    // 播放指令
+    play() {
+      this.eventCommand = 'play'
+    },
+    // 暂停指令
+    pause() {
+      this.eventCommand = 'pause'
+    },
+    // 重置自定义函数指令
+    resetFunc() {
+      this.renderFunc = {
+        name: null,
+        params: null
+      }
+    },
+    // 自定义函数 - 移除视频
+    remove(params) {
+      this.renderFunc = {
+        name: 'removeHandler',
+        params
+      }
+    },
+    // 自定义函数 - 全屏播放
+    fullScreen(params) {
+      this.renderFunc = {
+        name: 'fullScreenHandler',
+        params
+      }
+    },
+    // 自定义函数 - 跳转到指定时间点
+    toSeek(sec, isDelay = false) {
+      this.renderFunc = {
+        name: 'toSeekHandler',
+        params: { sec, isDelay }
+      }
+    }
+  }
+}
+</script>
+
+
+<script module="domVideoPlayer" lang="renderjs">
+const PLAYER_ID = 'DOM_VIDEO_PLAYER'
+export default {
+  data() {
+    return {
+      num: '',
+      videoEl: null,
+      loadingEl: null,
+      // 延迟生效的函数
+      delayFunc: null,
+      renderProps: {}
+    }
+  },
+  computed: {
+    playerId() {
+      return `${PLAYER_ID}_${this.num}`
+    },
+    wrapperId() {
+      return `video-wrapper-${this.num}`
+    }
+  },
+  methods: {
+    isApple() {
+      const ua = navigator.userAgent.toLowerCase()
+      return ua.indexOf('iphone') !== -1 || ua.indexOf('ipad') !== -1
+    },
+    async initVideoPlayer(src) {
+      this.delayFunc = null
+      await this.$nextTick()
+      if (!src) return
+      if (this.videoEl) {
+        // 切换视频源
+        if (!this.isApple() && this.loadingEl) {
+          this.loadingEl.style.display = 'block'
+        }
+        this.videoEl.src = src
+        return
+      }
+
+      const videoEl = document.createElement('video')
+      this.videoEl = videoEl
+      // 开始监听视频相关事件
+      this.listenVideoEvent()
+
+      const { autoplay, muted, controls, loop, playbackRate, objectFit, poster } = this.renderProps
+      videoEl.src = src
+      videoEl.autoplay = autoplay
+      videoEl.controls = controls
+      videoEl.loop = loop
+      videoEl.muted = muted
+      videoEl.playbackRate = playbackRate
+      videoEl.id = this.playerId
+      // videoEl.setAttribute('x5-video-player-type', 'h5')
+      videoEl.setAttribute('preload', 'auto')
+      videoEl.setAttribute('playsinline', true)
+      videoEl.setAttribute('webkit-playsinline', true)
+      videoEl.setAttribute('crossorigin', 'anonymous')
+      videoEl.setAttribute('controlslist', 'nodownload')
+      videoEl.setAttribute('disablePictureInPicture', true)
+      videoEl.style.objectFit = objectFit
+      poster && (videoEl.poster = poster)
+      videoEl.style.width = '100%'
+      videoEl.style.height = '100%'
+
+      // 插入视频元素
+      // document.getElementById(this.wrapperId).appendChild(videoEl)
+      const playerWrapper = document.getElementById(this.wrapperId)
+      playerWrapper.insertBefore(videoEl, playerWrapper.firstChild)
+
+      // 插入loading 元素(遮挡安卓的默认加载过程中的黑色播放按钮)
+      this.createLoading()
+    },
+    // 创建 loading
+    createLoading() {
+      const { isLoading } = this.renderProps
+      if (!this.isApple() && isLoading) {
+        const loadingEl = document.createElement('div')
+        this.loadingEl = loadingEl
+        loadingEl.className = 'loading-wrapper'
+        loadingEl.style.position = 'absolute'
+        loadingEl.style.top = '0'
+        loadingEl.style.left = '0'
+        loadingEl.style.zIndex = '1'
+        loadingEl.style.width = '100%'
+        loadingEl.style.height = '100%'
+        loadingEl.style.backgroundColor = 'black'
+        document.getElementById(this.wrapperId).appendChild(loadingEl)
+
+        // 创建 loading 动画
+        const animationEl = document.createElement('div')
+        animationEl.className = 'loading'
+        animationEl.style.zIndex = '2'
+        animationEl.style.position = 'absolute'
+        animationEl.style.top = '50%'
+        animationEl.style.left = '50%'
+        animationEl.style.marginTop = '-15px'
+        animationEl.style.marginLeft = '-15px'
+        animationEl.style.width = '30px'
+        animationEl.style.height = '30px'
+        animationEl.style.border = '2px solid #FFF'
+        animationEl.style.borderTopColor = 'rgba(255, 255, 255, 0.2)'
+        animationEl.style.borderRightColor = 'rgba(255, 255, 255, 0.2)'
+        animationEl.style.borderBottomColor = 'rgba(255, 255, 255, 0.2)'
+        animationEl.style.borderRadius = '100%'
+        animationEl.style.animation = 'circle infinite 0.75s linear'
+        loadingEl.appendChild(animationEl)
+
+        // 创建 loading 动画所需的 keyframes
+        const style = document.createElement('style')
+        const keyframes = `
+          @keyframes circle {
+            0% {
+              transform: rotate(0);
+            }
+            100% {
+              transform: rotate(360deg);
+            }
+          }
+        `
+        style.type = 'text/css'
+        if (style.styleSheet) {
+          style.styleSheet.cssText = keyframes
+        } else {
+          style.appendChild(document.createTextNode(keyframes))
+        }
+        document.head.appendChild(style)
+      }
+    },
+    // 监听视频相关事件
+    listenVideoEvent() {
+      // 播放事件监听
+      const playHandler = () => {
+        this.$ownerInstance.callMethod('eventEmit', { event: 'play' })
+        this.$ownerInstance.callMethod('setViewData', {
+          key: 'playing',
+          value: true
+        })
+
+        if (this.loadingEl) {
+          this.loadingEl.style.display = 'none'
+        }
+      }
+      this.videoEl.removeEventListener('play', playHandler)
+      this.videoEl.addEventListener('play', playHandler)
+
+      // 暂停事件监听
+      const pauseHandler = () => {
+        this.$ownerInstance.callMethod('eventEmit', { event: 'pause' })
+        this.$ownerInstance.callMethod('setViewData', {
+          key: 'playing',
+          value: false
+        })
+      }
+      this.videoEl.removeEventListener('pause', pauseHandler)
+      this.videoEl.addEventListener('pause', pauseHandler)
+
+      // 结束事件监听
+      const endedHandler = () => {
+        this.$ownerInstance.callMethod('eventEmit', { event: 'ended' })
+        this.$ownerInstance.callMethod('resetEventCommand')
+      }
+      this.videoEl.removeEventListener('ended', endedHandler)
+      this.videoEl.addEventListener('ended', endedHandler)
+
+      // 加载完成事件监听
+      const canPlayHandler = () => {
+        this.$ownerInstance.callMethod('eventEmit', { event: 'canplay' })
+        this.execDelayFunc()
+      }
+      this.videoEl.removeEventListener('canplay', canPlayHandler)
+      this.videoEl.addEventListener('canplay', canPlayHandler)
+
+      // 加载失败事件监听
+      const errorHandler = (e) => {
+        if (this.loadingEl) {
+          this.loadingEl.style.display = 'block'
+        }
+        this.$ownerInstance.callMethod('eventEmit', { event: 'error' })
+      }
+      this.videoEl.removeEventListener('error', errorHandler)
+      this.videoEl.addEventListener('error', errorHandler)
+
+      // loadedmetadata 事件监听
+      const loadedMetadataHandler = () => {
+        this.$ownerInstance.callMethod('eventEmit', { event: 'loadedmetadata' })
+        // 获取视频的长度
+        const duration = this.videoEl.duration
+        this.$ownerInstance.callMethod('eventEmit', {
+          event: 'durationchange',
+          data: duration
+        })
+
+        this.$ownerInstance.callMethod('setViewData', {
+          key: 'duration',
+          value: duration
+        })
+
+        // 加载首帧视频 模拟出封面图
+        this.loadFirstFrame()
+      }
+      this.videoEl.removeEventListener('loadedmetadata', loadedMetadataHandler)
+      this.videoEl.addEventListener('loadedmetadata', loadedMetadataHandler)
+
+      // 播放进度监听
+      const timeupdateHandler = (e) => {
+        const currentTime = e.target.currentTime
+        this.$ownerInstance.callMethod('eventEmit', {
+          event: 'timeupdate',
+          data: currentTime
+        })
+
+        this.$ownerInstance.callMethod('setViewData', {
+          key: 'currentTime',
+          value: currentTime
+        })
+
+      }
+      this.videoEl.removeEventListener('timeupdate', timeupdateHandler)
+      this.videoEl.addEventListener('timeupdate', timeupdateHandler)
+
+      // 倍速播放监听
+      const ratechangeHandler = (e) => {
+        const playbackRate = e.target.playbackRate
+        this.$ownerInstance.callMethod('eventEmit', {
+          event: 'ratechange',
+          data: playbackRate
+        })
+      }
+      this.videoEl.removeEventListener('ratechange', ratechangeHandler)
+      this.videoEl.addEventListener('ratechange', ratechangeHandler)
+
+      // 全屏事件监听
+      if (this.isApple()) {
+        const webkitbeginfullscreenHandler = () => {
+          const presentationMode = this.videoEl.webkitPresentationMode
+          let isFullScreen = null
+          if (presentationMode === 'fullscreen') {
+            isFullScreen = true
+          } else {
+            isFullScreen = false
+          }
+          this.$ownerInstance.callMethod('eventEmit', {
+            event: 'fullscreenchange',
+            data: isFullScreen
+          })
+        }
+        this.videoEl.removeEventListener('webkitpresentationmodechanged', webkitbeginfullscreenHandler)
+        this.videoEl.addEventListener('webkitpresentationmodechanged', webkitbeginfullscreenHandler)
+      } else {
+        const fullscreenchangeHandler = () => {
+          let isFullScreen = null
+          if (document.fullscreenElement) {
+            isFullScreen = true
+          } else {
+            isFullScreen = false
+          }
+          this.$ownerInstance.callMethod('eventEmit', {
+            event: 'fullscreenchange',
+            data: isFullScreen
+          })
+        }
+        document.removeEventListener('fullscreenchange', fullscreenchangeHandler)
+        document.addEventListener('fullscreenchange', fullscreenchangeHandler)
+      }
+    },
+    // 加载首帧视频,模拟出封面图
+    loadFirstFrame() {
+      let { autoplay, muted } = this.renderProps
+      if (this.isApple()) {
+        this.videoEl.play()
+        if (!autoplay) {
+          this.videoEl.pause()
+        }
+      } else {
+        // optimize: timeout 延迟调用是为了规避控制台的`https://goo.gl/LdLk22`这个报错
+        /**
+         * 原因:chromium 内核中,谷歌协议规定,视频不允许在非静音状态下进行自动播放
+         * 解决:在自动播放时,先将视频静音,然后延迟调用 play 方法,播放视频
+         * 说明:iOS 的 Safari 内核不会有这个,仅在 Android 设备出现,即使有这个报错也不影响的,所以不介意控制台报错的话是可以删掉这个 timeout 的
+         */
+        this.videoEl.muted = true
+        setTimeout(() => {
+          this.videoEl.play()
+          this.videoEl.muted = muted
+          if (!autoplay) {
+            setTimeout(() => {
+              this.videoEl.pause()
+            }, 100)
+          }
+        }, 10)
+      }
+    },
+    triggerCommand(eventType) {
+      if (eventType) {
+        this.$ownerInstance.callMethod('resetEventCommand')
+        this.videoEl && this.videoEl[eventType]()
+      }
+    },
+    triggerFunc(func) {
+      const { name, params } = func || {}
+      if (name) {
+        this[name](params)
+        this.$ownerInstance.callMethod('resetFunc')
+      }
+    },
+    removeHandler() {
+      if (this.videoEl) {
+        this.videoEl.pause()
+        this.videoEl.src = ''
+        this.$ownerInstance.callMethod('setViewData', {
+          key: 'videoSrc',
+          value: ''
+        })
+        this.videoEl.load()
+      }
+    },
+    fullScreenHandler() {
+      if (this.isApple()) {
+        this.videoEl.webkitEnterFullscreen()
+      } else {
+        this.videoEl.requestFullscreen()
+      }
+    },
+    toSeekHandler({ sec, isDelay }) {
+      const func = () => {
+        if (this.videoEl) {
+          this.videoEl.currentTime = sec
+        }
+      }
+
+      // 延迟执行
+      if (isDelay) {
+        this.delayFunc = func
+      } else {
+        func()
+      }
+    },
+    // 执行延迟函数
+    execDelayFunc() {
+      this.delayFunc && this.delayFunc()
+      this.delayFunc = null
+    },
+    viewportChange(props) {
+      this.renderProps = props
+      const { autoplay, muted, controls, loop, playbackRate } = props
+      if (this.videoEl) {
+        this.videoEl.autoplay = autoplay
+        this.videoEl.controls = controls
+        this.videoEl.loop = loop
+        this.videoEl.muted = muted
+        this.videoEl.playbackRate = playbackRate
+      }
+    },
+    randomNumChange(val) {
+      this.num = val
+    }
+  }
+}
+</script>
+
+<style scoped>
+.player-wrapper {
+  overflow: hidden;
+  height: 100%;
+  padding: 0;
+  position: relative;
+}
+</style>

+ 141 - 0
components/GlobalLoading.vue

@@ -0,0 +1,141 @@
+<template>
+  <up-overlay :show="isLoading" :duration="400" :z-index="99999" :opacity="0.1">
+    <view class="loading" @touchmove.stop.prevent>
+      <!-- <up-loading-icon mode="circle" size="46" color="black"></up-loading-icon> -->
+      <!-- <image class="loading-gif" src="/static/loading.gif" mode="aspectFit" /> -->
+      <!-- <view class="loader-inner"></view> -->
+      <view class="load_11">
+        <view class="rect1"></view>
+        <view class="rect2"></view>
+        <view class="rect3"></view>
+        <view class="rect4"></view>
+        <view class="rect5"></view>
+      </view>
+    </view>
+  </up-overlay>
+</template>
+
+<script setup>
+import { watch, computed } from "vue";
+import { useLoadingStore } from "@/store";
+
+const loadingStore = useLoadingStore();
+const props = defineProps({
+  msg: Object,
+});
+
+const isLoading = computed(() => !!(loadingStore?.visible || props.msg?.show));
+
+watch(isLoading, (val) => {
+  // #ifdef H5
+  document.body.style.overflow = val ? "hidden" : "";
+  // #endif
+});
+</script>
+
+<style lang="less" scoped>
+@import url("@/style.less");
+
+.loading {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  padding-bottom: constant(safe-area-inset-bottom); /* iOS < 11.2 */
+  padding-bottom: env(safe-area-inset-bottom); /* iOS >= 11.2 */
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  z-index: 99999;
+  pointer-events: none;
+  cursor: not-allowed;
+  box-sizing: border-box;
+  .loader-inner {
+    width: 60px;
+    height: 60px;
+    border: 6px solid #dfe3eb;
+    border-top: 6px solid @black;
+    border-radius: 50%;
+    animation: spin 1s linear infinite;
+  }
+
+  @keyframes spin {
+    0% {
+      transform: rotate(0deg);
+    }
+
+    100% {
+      transform: rotate(360deg);
+    }
+  }
+
+  .load_11 {
+    width: 100rpx;
+    height: 68rpx;
+    display: inline-block;
+    text-align: center;
+    font-size: 20rpx;
+  }
+
+  .load_11 > view {
+    &:last-child {
+      margin-right: 0;
+    }
+
+    background-color: #000000;
+    height: 100%;
+    width: 10rpx;
+    margin-right: 6rpx;
+    display: inline-block;
+    -webkit-animation: sk-stretchdelay 1.2s infinite ease-in-out;
+    animation: sk-stretchdelay 1.2s infinite ease-in-out;
+  }
+
+  .load_11 .rect2 {
+    -webkit-animation-delay: -1.1s;
+    animation-delay: -1.1s;
+  }
+
+  .load_11 .rect3 {
+    -webkit-animation-delay: -1s;
+    animation-delay: -1s;
+  }
+
+  .load_11 .rect4 {
+    -webkit-animation-delay: -0.9s;
+    animation-delay: -0.9s;
+  }
+
+  .load_11 .rect5 {
+    -webkit-animation-delay: -0.8s;
+    animation-delay: -0.8s;
+  }
+
+  @-webkit-keyframes sk-stretchdelay {
+    0%,
+    40%,
+    100% {
+      -webkit-transform: scaleY(0.4);
+    }
+
+    20% {
+      -webkit-transform: scaleY(1);
+    }
+  }
+
+  @keyframes sk-stretchdelay {
+    0%,
+    40%,
+    100% {
+      transform: scaleY(0.4);
+      -webkit-transform: scaleY(0.4);
+    }
+
+    20% {
+      transform: scaleY(1);
+      -webkit-transform: scaleY(1);
+    }
+  }
+}
+</style>

+ 136 - 0
components/ImageGrid.vue

@@ -0,0 +1,136 @@
+<template>
+  <view class="image-grid-container">
+    <view class="image-grid" :class="`count-${Math.min(images.length, 9)}`">
+      <view
+        v-for="(image, index) in showImages"
+        :key="index"
+        class="image-item"
+        :style="getItemStyle(index)"
+      >
+        <image
+          mode="heightFix"
+          :src="image"
+          class="image-content"
+          lazy-load
+          @click.stop="previewImage(index)"
+        />
+      </view>
+    </view>
+  </view>
+</template>
+
+<script setup>
+import { defineProps, computed } from "vue";
+
+const props = defineProps({
+  images: {
+    type: Array,
+    required: true,
+    default: () => [],
+  },
+  spacing: {
+    type: Number,
+    default: 8,
+  },
+  maxShow: {
+    type: Number,
+    default: 9, // 最多显示几张
+  },
+  isSeeLarge: {
+    type: Boolean,
+    default: false,
+  },
+});
+
+const showImages = computed(() => {
+  return props.images.slice(0, props.maxShow);
+});
+
+const previewImage = (index) => {
+  if (props.isSeeLarge) {
+    uni.previewImage({
+      current: index,
+      urls: props.images,
+      indicator: "number",
+      loop: true,
+    });
+  }
+};
+
+const getItemStyle = (index) => {
+  const count = Math.min(props.images.length, 3);
+  let style = {};
+
+  if (count === 1) {
+    style.width = "100%";
+    style.paddingTop = "56.25%"; // 16:9比例
+  } else {
+    style.width = `calc(${100 / count}% - ${
+      (props.spacing * (count - 1)) / count
+    }px)`;
+    style.paddingTop = style.width;
+  }
+
+  if (index % count !== count - 1) {
+    style.marginRight = `${props.spacing}px`;
+  }
+
+  return style;
+};
+</script>
+
+<style lang="less" scoped>
+.image-grid-container {
+  width: 100%;
+  margin-bottom: 12px;
+
+  .image-grid {
+    display: flex;
+    flex-wrap: wrap;
+    width: 100%;
+
+    .image-item {
+      position: relative;
+      overflow: hidden;
+      border-radius: 16rpx;
+      margin-bottom: v-bind('props.spacing + "px"');
+
+      .image-content {
+        position: absolute;
+        top: 0;
+        left: 0;
+        width: 100%;
+        height: 100%;
+        object-fit: cover;
+        transition: transform 0.2s ease;
+        &:active {
+          transform: scale(0.98);
+        }
+      }
+
+      .image-more {
+        position: absolute;
+        top: 0;
+        left: 0;
+        width: 100%;
+        height: 100%;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        background-color: rgba(0, 0, 0, 0.5);
+        color: white;
+        font-size: 24px;
+        font-weight: bold;
+      }
+    }
+
+    // 特殊处理只有一张图片的情况
+    &.count-1 .image-item {
+      border-radius: 12px;
+    }
+  }
+}
+::v-deep .uni-preview-image {
+  z-index: 999999 !important;
+}
+</style>

+ 115 - 0
components/IosUpdateModal.vue

@@ -0,0 +1,115 @@
+<template>
+  <Popup ref="popRef" mode="center" closeOnClickOverlay zIndex="10077">
+    <template #content>
+      <view class="content">
+        <view class="content_success">
+          <image src="/static/login.png" class="img"></image>
+          <trans _t="新版本"></trans>
+        </view>
+      </view>
+    </template>
+    <template #footer>
+      <view class="footer">
+        <view class="submit_btn submit_shop" @click="close">
+          <trans _t="关闭" />
+        </view>
+        <view class="submit_btn" @click="toUpdate">
+          <trans _t="立即升级" />
+        </view>
+      </view>
+    </template>
+  </Popup>
+</template>
+
+<script setup>
+import { ref, watch, computed, nextTick } from "vue";
+import Popup from "./popup.vue";
+import { t } from "@/locale";
+import { useSystemStore } from "@/store";
+import { openUrl } from "@/utils";
+import { storeToRefs } from "pinia";
+
+const useSystem = useSystemStore();
+const { getAppinfo: appinfo } = storeToRefs(useSystem);
+const popRef = ref(null);
+
+const open = () => {
+  popRef.value && popRef.value.open();
+};
+
+const close = () => {
+  popRef.value && popRef.value.close();
+};
+const toUpdate = () => {
+  openUrl(appinfo.value?.url);
+  close();
+};
+
+watch(
+  appinfo,
+  (newVal) => {
+    if (newVal.update) {
+      // #ifdef APP-PLUS
+      const systemInfo = uni.getSystemInfoSync();
+      if (systemInfo.platform === "ios") {
+        nextTick(() => {
+          open();
+        });
+      }
+      // #endif
+    } else {
+      close();
+    }
+  },
+  {
+    immediate: true, // 初始化时立即执行一次
+    deep: true, // 监听深层属性变化(如 appinfo.value.url 变化)
+  }
+);
+defineExpose({ open, close });
+</script>
+
+<style lang="less" scoped>
+@import url("@/style.less");
+
+:deep(.conts) {
+  min-width: 78vw;
+}
+
+.content {
+  flex: 1;
+  .flex_center();
+
+  &_success {
+    .flex_center();
+    flex-direction: column;
+    gap: 20rpx;
+  }
+
+  .img {
+    width: 120rpx;
+    height: 120rpx;
+  }
+}
+
+.footer {
+  .flex_position(space-between);
+
+  .submit_btn {
+    height: 76rpx;
+    line-height: 76rpx;
+    padding: 0 30rpx;
+    background-color: var(--black);
+    color: var(--light);
+    .flex_center();
+    border-radius: 16rpx;
+    .size(24rpx);
+
+    &.submit_shop {
+      background-color: var(--bg);
+      border: 1rpx solid var(--black);
+      color: var(--black);
+    }
+  }
+}
+</style>

+ 388 - 0
components/MultiSelectDropdown.vue

@@ -0,0 +1,388 @@
+<template>
+  <view class="multi-select-container">
+    <!-- 选中标签展示区 -->
+    <view
+      class="selected-tags"
+      :class="{ 'has-value': selectedItems.length > 0 }"
+      @click="toggleDropdown"
+    >
+      <view class="tag-box" v-if="selectedItems.length > 0">
+        <view
+          class="tag-item"
+          v-for="(item, index) in selectedItems"
+          :key="index"
+          @click.stop.prevent="removeItem(item)"
+        >
+          {{ item.name }}
+          <u-icon name="close" size="20rpx" class="tag-close"></u-icon>
+        </view>
+      </view>
+      <template v-else>
+        <text class="placeholder">{{ placeholder }}</text>
+      </template>
+      <u-icon
+        name="arrow-down"
+        size="24rpx"
+        class="dropdown-icon"
+        :class="{ rotate: isOpen }"
+      ></u-icon>
+    </view>
+
+    <!-- 下拉选项面板 -->
+    <view
+      class="dropdown-panel"
+      v-if="isOpen"
+      :style="{
+        width: panelWidth,
+        maxHeight: panelMaxHeight,
+      }"
+      @tap.stop
+    >
+      <!-- 一级选项 -->
+      <view class="level1-wrapper">
+        <view
+          class="level1-item"
+          v-for="level1 in options"
+          :key="level1.id"
+          :class="{ active: activeLevel1Id === level1.id }"
+          @click="handleLevel1Click(level1.id)"
+        >
+          {{ level1.name }}
+        </view>
+      </view>
+
+      <view class="level2-wrapper">
+        <view
+          class="level2-item"
+          v-for="level2 in filteredLevel2"
+          :key="level2.id"
+          :class="{ checked: isSelected(level2) }"
+          @click="toggleLevel2(level2)"
+        >
+          <text class="item-text">{{ level2.name }}</text>
+        </view>
+        <view class="empty-text" v-if="filteredLevel2.length === 0">
+          <trans _t="暂无选项" />
+        </view>
+      </view>
+    </view>
+    <view v-if="isOpen" class="backdrop" @tap="close"></view>
+  </view>
+</template>
+
+<script setup>
+import { ref, watch, computed, defineProps, defineEmits } from "vue";
+
+// 定义组件属性
+const props = defineProps({
+  // 选项数据
+  options: {
+    type: Array,
+    default: () => [],
+    // 数据格式: [{
+    //   id: 1,
+    //   name: '一级选项1',
+    //   children: [{ id: 11, name: '二级选项1-1' }, ...]
+    // }, ...]
+  },
+  // 占位文本
+  placeholder: {
+    type: String,
+    default: "",
+  },
+  // 面板宽度
+  panelWidth: {
+    type: String,
+    default: "500rpx",
+  },
+  // 面板最大高度
+  panelMaxHeight: {
+    type: String,
+    default: "600rpx",
+  },
+  // 默认选中值
+  modelValue: {
+    type: Array,
+    default: () => [],
+  },
+});
+
+// 定义事件
+const emits = defineEmits(["update:modelValue", "change"]);
+
+// 状态管理
+const isOpen = ref(false); // 下拉面板是否展开
+const activeLevel1Id = ref(""); // 当前激活的一级选项ID
+const selectedItems = ref([]); // 选中的二级选项
+
+// 初始化
+watch(
+  () => props.modelValue,
+  (newVal) => {
+    // 从外部值初始化选中项
+    if (newVal && newVal.length > 0) {
+      const items = [];
+      props.options.forEach((level1) => {
+        level1.children?.forEach((level2) => {
+          if (newVal.includes(level2.id)) {
+            items.push(level2);
+          }
+        });
+      });
+      selectedItems.value = items;
+    }
+  },
+  { immediate: true }
+);
+
+// 初始化默认选中的一级选项
+watch(
+  () => props.options,
+  (newVal) => {
+    if (newVal && newVal.length > 0 && !activeLevel1Id.value) {
+      activeLevel1Id.value = newVal[0].id;
+    }
+  },
+  { immediate: true }
+);
+
+// 过滤当前一级选项对应的二级选项
+const filteredLevel2 = computed(() => {
+  const level1 = props.options.find((item) => item.id === activeLevel1Id.value);
+  return level1?.children || [];
+});
+
+// 切换下拉面板
+const toggleDropdown = () => {
+  isOpen.value = !isOpen.value;
+};
+
+// 点击一级选项
+const handleLevel1Click = (id) => {
+  activeLevel1Id.value = id;
+};
+
+// 切换二级选项选中状态
+const toggleLevel2 = (item) => {
+  const index = selectedItems.value.findIndex((i) => i.id === item.id);
+
+  if (index > -1) {
+    // 取消选中
+    selectedItems.value.splice(index, 1);
+  } else {
+    // 选中
+    selectedItems.value.push(item);
+  }
+
+  // 通知父组件
+  emitChange();
+};
+
+// 判断二级选项是否选中
+const isSelected = (item) => {
+  return selectedItems.value.some((i) => i.id === item.id);
+};
+
+// 移除选中项
+const removeItem = (item) => {
+  const index = selectedItems.value.findIndex((i) => i.id === item.id);
+  if (index > -1) {
+    selectedItems.value.splice(index, 1);
+    // 通知父组件
+    emitChange();
+  }
+};
+
+// 通知父组件变化
+const emitChange = () => {
+  const ids = selectedItems.value.map((item) => item.id);
+  emits("update:modelValue", ids);
+  emits("change", {
+    ids,
+    items: [...selectedItems.value],
+  });
+};
+
+const close = () => (isOpen.value = false);
+
+// 点击外部关闭下拉框
+watch(
+  () => isOpen.value,
+  (newVal) => {
+    const handleClickOutside = (e) => {
+      const dropdown = document.querySelector(".multi-select-container");
+      if (dropdown && !dropdown.contains(e.target)) {
+        isOpen.value = false;
+        document.removeEventListener("click", handleClickOutside);
+      }
+    };
+
+    if (newVal) {
+      setTimeout(() => {
+        document.addEventListener("click", handleClickOutside);
+      }, 0);
+    }
+  }
+);
+</script>
+
+<style lang="less" scoped>
+.multi-select-container {
+  position: relative;
+  display: inline-block;
+
+  // 选中标签区域
+  .selected-tags {
+    display: flex;
+    // flex-wrap: wrap;
+    align-items: center;
+    max-width: 540rpx;
+    min-height: 70rpx;
+    // border: 2rpx solid #ddd;
+    border-radius: 8rpx;
+    // background-color: #fff;
+    cursor: pointer;
+    transition: all 0.2s;
+
+    &.has-value {
+      border-color: #3c9cff;
+    }
+
+    &:focus-within {
+      border-color: #3c9cff;
+      box-shadow: 0 0 0 2rpx rgba(60, 156, 255, 0.2);
+    }
+
+    .placeholder {
+      color: #999;
+      font-weight: 500;
+    }
+    .tag-box {
+      display: flex;
+      flex-wrap: wrap;
+      align-items: center;
+    }
+    .tag-item {
+      display: inline-flex;
+      align-items: center;
+      margin: 5rpx 8rpx 5rpx 0;
+      padding: 5rpx 15rpx;
+      background-color: #f0f7ff;
+      color: #3c9cff;
+      border-radius: 20rpx;
+      font-size: 26rpx;
+
+      .tag-close {
+        margin-left: 8rpx;
+        color: #3c9cff;
+        opacity: 0.8;
+
+        &:hover {
+          opacity: 1;
+        }
+      }
+    }
+
+    .dropdown-icon {
+      margin-left: 10rpx;
+      color: #999;
+      transition: transform 0.2s;
+
+      &.rotate {
+        transform: rotate(180deg);
+      }
+    }
+  }
+
+  // 下拉面板
+  .dropdown-panel {
+    position: absolute;
+    top: 80rpx;
+    right: 0;
+    display: flex;
+    border: 2rpx solid #eee;
+    border-radius: 8rpx;
+    background-color: #fff;
+    box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1);
+    z-index: 999;
+    overflow: hidden;
+
+    // 一级选项
+    .level1-wrapper {
+      width: 35%;
+      border-right: 2rpx solid #eee;
+      background-color: #fafafa;
+      overflow-y: auto;
+
+      .level1-item {
+        padding: 20rpx;
+        font-size: 28rpx;
+        color: #333;
+        transition: all 0.2s;
+
+        &:hover {
+          background-color: #f0f0f0;
+        }
+
+        &.active {
+          background-color: #fff;
+          color: #3c9cff;
+          font-weight: 500;
+        }
+      }
+    }
+
+    // 二级选项
+    .level2-wrapper {
+      width: 65%;
+      padding: 10rpx;
+      overflow-y: auto;
+
+      .level2-item {
+        display: flex;
+        align-items: center;
+        padding: 15rpx 20rpx;
+        font-size: 28rpx;
+        color: #333;
+        border-radius: 6rpx;
+        transition: background-color 0.2s;
+
+        &:hover {
+          background-color: #f5f7fa;
+        }
+
+        &.checked {
+          background-color: #f0f7ff;
+          color: #3c9cff;
+        }
+
+        .check-icon {
+          margin-right: 15rpx;
+        }
+      }
+
+      .empty-text {
+        padding: 40rpx;
+        text-align: center;
+        font-size: 28rpx;
+        color: #999;
+      }
+    }
+  }
+
+  .backdrop {
+    position: fixed;
+    left: 0;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    z-index: 10;
+    background: rgba(0, 0, 0, 0); /* 透明即可捕获点击 */
+  }
+}
+
+// 解决点击事件冒泡问题
+::v-deep .u-icon {
+  pointer-events: none;
+}
+</style>

+ 308 - 0
components/PinCodeModal.vue

@@ -0,0 +1,308 @@
+<template>
+  <!-- 遮罩层 -->
+  <view
+    class="pin-modal-overlay"
+    v-if="visible"
+    :class="{ 'fade-in': visible, 'fade-out': !visible }"
+  >
+    <!-- 弹框内容 -->
+    <view class="pin-modal-container">
+      <!-- 取消按钮 -->
+      <view class="cancel-btn" @click="handleCancel">{{ t("取消") }}</view>
+
+      <!-- 锁图标 -->
+      <view class="lock-icon-wrapper">
+        <view class="lock-icon-bg">
+          <up-icon name="lock" color="#7B61FF" size="36"></up-icon>
+        </view>
+      </view>
+
+      <!-- 标题 -->
+      <view class="title">{{ t(title) }}</view>
+
+      <!-- PIN 码输入指示器 -->
+      <view class="pin-indicators">
+        <view
+          v-for="(dot, index) in 4"
+          :key="index"
+          class="pin-dot"
+          :class="{ filled: pinCode.length > index }"
+        ></view>
+      </view>
+
+      <!-- 数字键盘 -->
+      <view class="number-pad">
+        <view class="number-row" v-for="row in numberRows" :key="row.id">
+          <view
+            class="number-btn"
+            v-for="num in row.numbers"
+            :key="num"
+            @click="handleNumberClick(num)"
+          >
+            <text class="number-text">{{ num }}</text>
+          </view>
+        </view>
+        <view class="last-row">
+          <view class="empty-cell"></view>
+          <view class="number-btn zero-btn" @click="handleNumberClick(0)">
+            <text class="number-text">0</text>
+          </view>
+          <view class="delete-btn" @click="handleDelete">
+            <up-icon name="backspace" color="#FFFFFF" size="24"></up-icon>
+          </view>
+        </view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script setup>
+import { ref, watch } from "vue";
+import { useTabbarStore } from "@/store";
+import { t } from "@/locale";
+
+const props = defineProps({
+  title: {
+    type: String,
+    default: "输入PIN码进行验证",
+  },
+  visible: {
+    type: Boolean,
+    default: false,
+  },
+  isHome: {
+    type: Boolean,
+    default: false,
+  },
+});
+
+const useTabbar = useTabbarStore();
+// 定义组件事件
+const emit = defineEmits(["close", "complete"]);
+
+// PIN 码数据
+const pinCode = ref("");
+
+// 数字键盘布局
+const numberRows = [
+  { id: 1, numbers: [1, 2, 3] },
+  { id: 2, numbers: [4, 5, 6] },
+  { id: 3, numbers: [7, 8, 9] },
+];
+
+watch(
+  () => pinCode.value.length,
+  (length) => {
+    if (length === 4) {
+      emit("complete", pinCode.value);
+      pinCode.value = "";
+    }
+  }
+);
+
+const handleNumberClick = (number) => {
+  if (pinCode.value.length < 4) {
+    pinCode.value += number.toString();
+  }
+};
+
+const handleDelete = () => {
+  pinCode.value = pinCode.value.slice(0, -1);
+};
+
+const handleCancel = () => {
+  pinCode.value = "";
+  if (props.isHome) {
+    uni.switchTab({ url: "/pages/index/index" });
+    useTabbar.getPageCur("index");
+  }
+
+  // 触发关闭事件
+  emit("close");
+};
+
+watch(
+  () => props.visible,
+  (newVal) => {
+    if (!newVal) {
+      pinCode.value = "";
+    }
+  }
+);
+</script>
+
+<style lang="scss" scoped>
+.fade-in {
+  animation: fadeIn 0.3s ease-out forwards;
+}
+
+.fade-out {
+  animation: fadeOut 0.3s ease-in forwards;
+}
+
+@keyframes fadeIn {
+  from {
+    opacity: 0;
+  }
+  to {
+    opacity: 1;
+  }
+}
+
+@keyframes fadeOut {
+  from {
+    opacity: 1;
+  }
+  to {
+    opacity: 0;
+  }
+}
+
+// 遮罩层
+.pin-modal-overlay {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  background-color: #7b61ff;
+  z-index: 9999;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+// 弹框容器
+.pin-modal-container {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+  padding: 60rpx 20rpx 20rpx;
+  box-sizing: border-box;
+}
+
+// 取消按钮
+.cancel-btn {
+  align-self: flex-start;
+  color: #ffffff;
+  font-size: 28rpx;
+  margin: 30rpx 0 60rpx 30rpx;
+}
+
+// 锁图标
+.lock-icon-wrapper {
+  display: flex;
+  justify-content: center;
+  margin-bottom: 60rpx;
+}
+
+.lock-icon-bg {
+  width: 160rpx;
+  height: 160rpx;
+  border-radius: 50%;
+  background-color: #ffffff;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+// 标题
+.title {
+  color: #ffffff;
+  font-size: 36rpx;
+  text-align: center;
+  margin-bottom: 80rpx;
+}
+
+// PIN码指示器
+.pin-indicators {
+  display: flex;
+  justify-content: center;
+  gap: 30rpx;
+  margin-bottom: 120rpx;
+}
+
+.pin-dot {
+  width: 24rpx;
+  height: 24rpx;
+  border-radius: 50%;
+  border: 2rpx solid #ffffff;
+  transition: all 0.2s ease;
+}
+
+.pin-dot.filled {
+  background-color: #ffffff;
+  transform: scale(1.2);
+}
+
+// 数字键盘
+.number-pad {
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  gap: 30rpx;
+  margin-top: auto;
+  padding-bottom: 80rpx;
+}
+
+.number-row {
+  display: flex;
+  gap: 30rpx;
+}
+
+.number-btn {
+  width: 140rpx;
+  height: 140rpx;
+  border-radius: 50%;
+  border: 2rpx solid #ffffff;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  color: #ffffff;
+  font-size: 48rpx;
+  font-weight: 500;
+  transition: all 0.1s ease;
+}
+
+.number-btn:active {
+  background-color: rgba(255, 255, 255, 0.2);
+}
+
+.number-text {
+  user-select: none;
+}
+
+// 最后一行
+.last-row {
+  display: flex;
+  gap: 30rpx;
+  margin-top: 30rpx;
+}
+
+.empty-cell {
+  width: 140rpx;
+}
+
+.zero-btn {
+  width: 140rpx;
+  height: 140rpx;
+}
+
+.delete-btn {
+  width: 140rpx;
+  height: 140rpx;
+  border-radius: 50%;
+  border: 2rpx solid #ffffff;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  transition: all 0.1s ease;
+}
+
+.delete-btn:active {
+  background-color: rgba(255, 255, 255, 0.2);
+}
+</style>

+ 201 - 0
components/ShareDialog.vue

@@ -0,0 +1,201 @@
+<template>
+  <Popup ref="popRef" title="分享到" mode="bottom" isClose>
+    <template #content>
+      <view class="share-options">
+        <!-- 微信 -->
+        <view class="share-option" @click="shareToWechat('friend')">
+          <view class="option-icon">
+            <up-icon name="weixin-fill" color="#07C160" size="48"></up-icon>
+          </view>
+          <trans class="option-text" _t="微信"></trans>
+        </view>
+
+        <!-- 微信朋友圈 -->
+        <view class="share-option" @click="shareToWechat('timeline')">
+          <view class="option-icon">
+            <up-icon
+              name="moments-circel-fill"
+              color="#07C160"
+              size="48"
+            ></up-icon>
+          </view>
+          <trans class="option-text" _t="朋友圈"></trans>
+        </view>
+      </view>
+    </template>
+    <template #footer>
+      <!-- 取消按钮 -->
+      <view class="cancel-btn" @click="close">
+        <trans _t="取消" />
+      </view>
+    </template>
+  </Popup>
+</template>
+
+<script setup>
+import { ref, getCurrentInstance } from "vue";
+import { Toast } from "@/utils";
+import Popup from "./popup.vue";
+
+const popRef = ref(null);
+
+const emit = defineEmits(["open", "close"]);
+
+// 分享内容配置
+const shareConfig = ref({
+  title: "推荐一个好内容",
+  description: "快来看看这个页面吧",
+  imageUrl: "/static/login.png", // 默认分享图片
+});
+
+// 获取当前页面URL
+const getCurrentPageUrl = () => {
+  // 获取当前页面实例
+  const pages = getCurrentPages();
+
+  const currentPage = pages[pages.length - 1];
+  const pagePath = currentPage.route;
+  const query = currentPage.options;
+
+  // 拼接参数
+  let queryStr = "";
+  if (Object.keys(query).length > 0) {
+    queryStr =
+      "?" +
+      Object.entries(query)
+        .map(([k, v]) => `${k}=${v}`)
+        .join("&");
+  }
+  console.log(`https://vavabuy.net/#/${pagePath}${queryStr}`, "pages");
+  // 实际项目中这里应该是你们的H5地址 + 页面路径
+  return `https://vavabuy.net/#/${pagePath}${queryStr}`;
+};
+
+// 打开分享弹框
+const open = () => {
+  uni.getProvider({
+    service: "share",
+    success: (res) => {
+      if (!res.provider.includes("weixin")) {
+        Toast("当前环境不支持微信分享");
+      }
+    },
+  });
+  popRef.value && popRef.value.open();
+};
+// 关闭分享弹框
+const close = () => {
+  popRef.value && popRef.value.close();
+  emit("close");
+};
+
+// 分享到微信
+const shareToWechat = (type) => {
+  close();
+
+  // 获取当前页面URL作为分享链接
+  const shareUrl = getCurrentPageUrl();
+
+  // 配置分享参数
+  const shareParams = {
+    type: "weixin",
+    title: shareConfig.value.title,
+    content: shareConfig.value.description,
+    href: shareUrl,
+    thumbs: shareConfig.value.imageUrl,
+    scene: type === "friend" ? "WXSceneSession" : "WXSceneTimeline",
+  };
+  uni.share({
+    provider: "weixin",
+    scene: shareParams.scene,
+    type: 0, // 0:图文(链接),1:纯文字,2:图片,3:音乐,4:视频
+    title: shareParams.title,
+    summary: shareParams.content,
+    href: shareParams.href,
+    imageUrl: shareParams.thumbs,
+    success: () => {
+      Toast("分享成功!");
+    },
+    fail: (err) => {
+      Toast(`分享失败: ${err.errMsg}`);
+    },
+  });
+};
+
+// 设置分享内容
+const setShareConfig = (config) => {
+  shareConfig.value = { ...shareConfig.value, ...config };
+};
+
+// 暴露方法给父组件
+defineExpose({ setShareConfig, open, close });
+</script>
+
+<style lang="scss" scoped>
+// 分享选项
+.share-options {
+  width: 100%;
+  display: flex;
+  justify-content: center;
+  padding: 20rpx 0;
+}
+
+// 分享选项项
+.share-option {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  margin: 0 60rpx;
+  cursor: pointer;
+}
+
+// 选项图标容器
+.option-icon {
+  width: 120rpx;
+  height: 120rpx;
+  border-radius: 50%;
+  background-color: #f5f5f5;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin-bottom: 15rpx;
+}
+
+// 朋友圈图标特殊样式
+.circle-bg {
+  position: relative;
+
+  &::after {
+    content: "";
+    position: absolute;
+    width: 30rpx;
+    height: 30rpx;
+    border-radius: 50%;
+    background-color: #07c160;
+    bottom: 10rpx;
+    right: 10rpx;
+    border: 4rpx solid #fff;
+  }
+}
+
+// 选项文本
+.option-text {
+  font-size: 28rpx;
+  color: #666;
+}
+
+// 取消按钮
+.cancel-btn {
+  width: 90%;
+  height: 90rpx;
+  line-height: 90rpx;
+  background-color: #f5f5f7;
+  color: #333;
+  text-align: center;
+  font-size: 32rpx;
+  border-radius: 45rpx;
+  margin: 20rpx auto 0;
+  display: block;
+  border: none;
+}
+</style>

+ 248 - 0
components/UPickerField.vue

@@ -0,0 +1,248 @@
+<template>
+  <view class="u-picker-field" @click="openPicker" :class="{ disabled }">
+    <view class="field-left">
+      <text class="field-text" :class="{ placeholder: !selectedText }">
+        {{ selectedText || placeholder }}
+      </text>
+    </view>
+    <view class="field-right">
+      <up-icon
+        name="arrow-down"
+        size="16"
+        color="var(--text-02)"
+        :style="{
+          transform: visible ? 'rotate(180deg)' : 'rotate(0deg)',
+          transition: 'transform .2s ease',
+        }"
+      />
+    </view>
+
+    <!-- up-picker -->
+    <up-picker
+      v-model:show="visible"
+      :columns="normalizedColumns"
+      :loading="loading"
+      :valueName="valueKey"
+      :keyName="labelKey"
+      :item-height="itemHeight"
+      :confirm-text="t(confirmText)"
+      :cancel-text="t(cancelText)"
+      @confirm="onConfirm"
+      @cancel="onCancel"
+      @close="onClose"
+    />
+  </view>
+</template>
+
+<script setup>
+import { computed, ref, watch } from "vue";
+import { t } from "@/locale";
+
+const props = defineProps({
+  // v-model
+  modelValue: {
+    type: [String, Number, Object, Array],
+    default: "",
+  },
+  // up-picker 的 columns(支持一列或多列)
+  columns: {
+    type: Array,
+    default: () => [],
+  },
+  // 当 columns 为对象数组时的显示/取值字段
+  labelKey: {
+    type: String,
+    default: "label",
+  },
+  valueKey: {
+    type: String,
+    default: "value",
+  },
+  placeholder: {
+    type: String,
+    default: "",
+  },
+  disabled: {
+    type: Boolean,
+    default: false,
+  },
+  loading: {
+    type: Boolean,
+    default: false,
+  },
+  itemHeight: {
+    type: Number,
+    default: 44,
+  },
+  confirmText: {
+    type: String,
+    default: "确认",
+  },
+  cancelText: {
+    type: String,
+    default: "取消",
+  },
+  // 是否在值为空时自动选中第一项
+  autoSelectFirst: {
+    type: Boolean,
+    default: true,
+  },
+});
+
+const emit = defineEmits(["update:modelValue", "change", "open", "close"]);
+
+const visible = ref(false);
+
+// 统一成多列结构:[[...]]
+const normalizedColumns = computed(() => {
+  if (props.columns.length === 0) return [];
+  const isMulti = Array.isArray(props.columns[0]);
+  return isMulti ? props.columns : [props.columns];
+});
+
+// 如果 modelValue 为空且有可选项,则默认选中第一项(受 autoSelectFirst 控制)
+watch(
+  () => normalizedColumns.value,
+  (cols) => {
+    if (!props.autoSelectFirst) return;
+    if (!cols || !cols.length) return;
+    const mv = props.modelValue;
+    const isEmpty = mv === undefined || mv === null || mv === "";
+    if (!isEmpty) return;
+    const firstCol = cols[0] || [];
+    const first = firstCol[0];
+    if (first === undefined) return;
+    const value = typeof first === "object" ? first[props.valueKey] : first;
+    const label =
+      typeof first === "object" ? first[props.labelKey] ?? "" : String(first);
+    emit("update:modelValue", value);
+    emit("change", { value, label, raw: { type: "init" } });
+  },
+  { immediate: true, deep: true }
+);
+
+// 选中文本(以第一列为主,常见场景)
+const selectedText = computed(() => {
+  const firstCol = normalizedColumns.value[0] || [];
+  if (!firstCol.length) return "";
+
+  // 根据 modelValue 匹配文本
+  const mv = props.modelValue;
+  if (mv === null || mv === undefined || mv === "") return "";
+
+  // 如果是对象直接取 labelKey
+  if (typeof mv === "object" && !Array.isArray(mv)) {
+    return mv[props.labelKey] ?? "";
+  }
+
+  // 原始值:在第一列匹配
+  const found = firstCol.find((item) => {
+    if (typeof item === "object") return item[props.valueKey] === mv;
+    return item === mv;
+  });
+  if (!found) return "";
+  return typeof found === "object"
+    ? found[props.labelKey] ?? ""
+    : String(found);
+});
+
+const openPicker = () => {
+  if (props.disabled) return;
+  visible.value = true;
+  emit("open");
+};
+
+const onClose = () => {
+  emit("close");
+};
+
+const onCancel = () => {
+  visible.value = false;
+};
+
+// up-picker 的 confirm 事件回调参数在不同版本可能不同,这里做兼容处理
+const onConfirm = (e) => {
+  const firstCol = normalizedColumns.value[0] || [];
+
+  let picked;
+  let pickedDisplay = "";
+
+  // 优先从 e.value 推断
+  if (e && Array.isArray(e.value) && e.value.length) {
+    const v0 = e.value[0];
+    if (typeof v0 === "object") {
+      picked = v0[props.valueKey];
+      pickedDisplay = v0[props.labelKey] ?? "";
+    } else {
+      // v0 是 label,找到对应项拿到 value
+      const found = firstCol.find((item) =>
+        typeof item === "object" ? item[props.labelKey] === v0 : item === v0
+      );
+      if (found) {
+        picked = typeof found === "object" ? found[props.valueKey] : found;
+        pickedDisplay =
+          typeof found === "object"
+            ? found[props.labelKey] ?? ""
+            : String(found);
+      } else {
+        picked = v0;
+        pickedDisplay = String(v0);
+      }
+    }
+  } else if (e && (Array.isArray(e.indexs) || typeof e.index === "number")) {
+    const idx = Array.isArray(e.indexs) ? e.indexs[0] : e.index;
+    const it = firstCol[idx];
+    if (it) {
+      picked = typeof it === "object" ? it[props.valueKey] : it;
+      pickedDisplay =
+        typeof it === "object" ? it[props.labelKey] ?? "" : String(it);
+    }
+  }
+
+  // 回填 & 透传事件
+  if (picked !== undefined) {
+    emit("update:modelValue", picked);
+    emit("change", { value: picked, label: pickedDisplay, raw: e });
+  }
+  visible.value = false;
+};
+</script>
+
+<style lang="less" scoped>
+.u-picker-field {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 16rpx 20rpx;
+  background-color: var(--light);
+  border-radius: 12rpx;
+
+  &.disabled {
+    opacity: 0.6;
+  }
+
+  .field-left {
+    flex: 1;
+    min-width: 0;
+
+    .field-text {
+      color: var(--text);
+      font-size: 28rpx;
+      line-height: 40rpx;
+      overflow: hidden;
+      white-space: nowrap;
+      text-overflow: ellipsis;
+
+      &.placeholder {
+        color: var(--text-02);
+      }
+    }
+  }
+
+  .field-right {
+    margin-left: 12rpx;
+    display: flex;
+    align-items: center;
+  }
+}
+</style>

+ 455 - 0
components/address.vue

@@ -0,0 +1,455 @@
+<template>
+  <popup ref="popRef" :title="title" isClose class="address__popup">
+    <template #content>
+      <scroll-view class="form" scroll-y>
+        <view class="form_item">
+          <view class="item_label">
+            <trans _t="收件人" />
+          </view>
+          <view class="item_value flex">
+            <Input
+              :placeholder="t('名')"
+              border="surround"
+              @focus="inputFocus"
+              v-model="form.lastName"
+            />
+            <Input
+              :placeholder="t('姓')"
+              border="surround"
+              @focus="inputFocus"
+              v-model="form.firstName"
+            />
+          </view>
+        </view>
+        <view class="form_item">
+          <view class="item_label">
+            <trans _t="地区" />
+          </view>
+          <view class="item_value flex">
+            <Select
+              iconColor="#adb8cc"
+              v-model:current="countryCurrent"
+              :options="areaList"
+              keyName="countryName"
+              isTran
+              class="country_select"
+              @select="countryChange"
+              ref="countryRef"
+              @selectClick="() => provinceRef.close()"
+            >
+              <template #text>
+                <view
+                  class="select_label"
+                  style="color: var(--inputText)"
+                  v-if="form.country"
+                >
+                  {{ form.country }}
+                </view>
+                <view class="select_label" v-else>
+                  <trans _t="国家" />
+                </view>
+              </template>
+            </Select>
+            <Select
+              iconColor="#adb8cc"
+              v-model:current="provinceCurrent"
+              :options="provinceList"
+              keyName="name"
+              isTran
+              ref="provinceRef"
+              class="province_select"
+              @select="provinceChange"
+              @selectClick="() => countryRef.close()"
+            >
+              <template #text>
+                <view
+                  class="select_label"
+                  style="color: var(--inputText)"
+                  v-if="form.province"
+                >
+                  {{ form.province }}
+                </view>
+                <view class="select_label" v-else>
+                  <trans _t="选择" />
+                </view>
+              </template>
+            </Select>
+            <Input border="surround" @focus="inputFocus" v-model="form.city" />
+          </view>
+        </view>
+        <view class="form_item">
+          <view class="item_label">
+            <trans _t="详细地址" />
+          </view>
+          <view class="item_value">
+            <Input
+              :placeholder="t('输入公寓号码街道道路地址')"
+              @focus="inputFocus"
+              border="surround"
+              v-model="form.address"
+            />
+          </view>
+        </view>
+        <!-- flex -->
+        <view class="form_item">
+          <view class="item_label">
+            <trans _t="门号" />
+          </view>
+          <view class="item_value">
+            <Input
+              :placeholder="t('如果没有门牌号可以输入')"
+              @focus="inputFocus"
+              border="surround"
+              v-model="form.doorNumber"
+            />
+          </view>
+        </view>
+        <!-- flex -->
+        <view class="form_item">
+          <view class="item_label">
+            <trans _t="邮政编码" />
+          </view>
+          <view class="item_value">
+            <Input
+              :placeholder="t('邮政编码')"
+              border="surround"
+              @focus="inputFocus"
+              v-model="form.zipCode"
+            />
+          </view>
+        </view>
+        <!-- flex -->
+        <view class="form_item">
+          <view class="item_label">
+            <trans _t="电话号码" />
+          </view>
+          <view class="item_value">
+            <Input
+              :placeholder="t('电话号码')"
+              border="surround"
+              @focus="inputFocus"
+              v-model="form.phoneNo"
+            />
+          </view>
+        </view>
+        <!-- flex -->
+        <view class="form_item">
+          <view class="item_label _required">
+            <trans _t="税号" />
+          </view>
+          <view class="item_value">
+            <Input
+              :placeholder="t('税号')"
+              border="surround"
+              @focus="inputFocus"
+              v-model="form.taxId"
+            />
+          </view>
+        </view>
+        <view class="form_item">
+          <view class="item_label _required">
+            <trans _t="地址标签" />
+          </view>
+          <view class="item_value">
+            <Input
+              :placeholder="t('地址标签')"
+              border="surround"
+              @focus="inputFocus"
+              v-model="form.label"
+            />
+          </view>
+          <view class="labels">
+            <view
+              class="labels_item"
+              :class="form.label == label ? 'labels_active' : ''"
+              v-for="(label, num) in labels"
+              :key="num"
+              @click="form.label = label"
+            >
+              <trans :_t="label" />
+            </view>
+          </view>
+        </view>
+        <view class="form_item flex" style="justify-content: space-between">
+          <view class="item_label _required">
+            <trans _t="默认地址" />
+          </view>
+          <view class="item_value" style="flex: none">
+            <up-switch
+              v-model="form.default"
+              activeColor="var(--black)"
+              inactiveColor="#dcdfe6"
+            ></up-switch>
+          </view>
+        </view>
+      </scroll-view>
+    </template>
+    <template #footer>
+      <view class="submit_btn" @click="submit">
+        <trans _t="确认" />
+      </view>
+    </template>
+  </popup>
+</template>
+<script setup>
+import { ref, reactive, nextTick } from "vue";
+import popup from "./popup";
+import Select from "./select";
+import areaList from "@/utils/area";
+import { t } from "@/locale";
+import Input from "./input";
+import { Toast } from "@/utils";
+import { SHOP_ADDRESS_ADD } from "@/api";
+import { useShopStore } from "@/store";
+
+const useShop = useShopStore();
+const props = defineProps({
+  item: {
+    type: Object,
+    default: () => ({}),
+  },
+});
+const countryRef = ref(null);
+const provinceRef = ref(null);
+const countryCurrent = ref(0);
+const provinceCurrent = ref(0);
+const popRef = ref(null);
+const title = ref("新增收货地址");
+const form = reactive({
+  id: "",
+  firstName: "",
+  lastName: "",
+  country: "",
+  province: "",
+  city: "",
+  address: "",
+  doorNumber: "",
+  zipCode: "",
+  phoneNo: "",
+  taxId: "",
+  label: "",
+  default: false,
+});
+const provinceList = ref([]);
+const labels = [t("主页"), t("公司")];
+
+const open = (item = {}) => {
+  popRef.value && popRef.value.open();
+  form.id = item.id;
+  form.firstName = item.firstName || "";
+  form.lastName = item.lastName || "";
+  form.country = item.country || "";
+  form.province = item.province || "";
+  form.city = item.city || "";
+  form.address = item.address || "";
+  form.doorNumber = item.doorNumber || "";
+  form.zipCode = item.zipCode || "";
+  form.phoneNo = item.phoneNo || "";
+  form.taxId = item.taxId || "";
+  form.label = item.label || "";
+  form.default = item.default ? true : false;
+  if (JSON.stringify(item) == "{}") {
+    title.value = "新增收货地址";
+  } else {
+    title.value = "编辑收货地址";
+    const findIndex = areaList.findIndex(
+      (a) => a.countryName === item.countryName
+    );
+    provinceList.value = findIndex == -1 ? [] : areaList[findIndex].regions;
+  }
+};
+const close = () => {
+  popRef.value && popRef.value.close();
+};
+const countryChange = (item) => {
+  form.country = item.countryName;
+  form.province = "";
+  provinceList.value = item.regions;
+  provinceRef.value && provinceRef.value.close();
+};
+const provinceChange = (item) => {
+  form.province = item.name;
+  countryRef.value && countryRef.value.close();
+};
+
+const inputFocus = () => {
+  provinceRef.value && provinceRef.value.close();
+  countryRef.value && countryRef.value.close();
+};
+
+const submit = () => {
+  if (!form.firstName || !form.lastName) return Toast(t("收件人必须填写"));
+  if (!form.country || !form.province || !form.city)
+    return Toast(t("国家和州/省必须填写"));
+  if (!form.address) return Toast(t("详细地址必须填写"));
+  if (!form.doorNumber) return Toast(t("如果没有门牌号可以输入"));
+  if (!form.zipCode) return Toast(t("邮政编码必须填写"));
+  if (!form.phoneNo) return Toast(t("电话号码必须填写"));
+  addressAdd();
+};
+
+const addressAdd = async () => {
+  try {
+    const res = await SHOP_ADDRESS_ADD({
+      ...form,
+      default: form.default === true ? 1 : 0,
+    });
+    nextTick(() => {
+      useShop.setAddressList();
+      close();
+    });
+  } catch (error) {
+    Toast(error.msg);
+    close();
+  }
+};
+
+defineExpose({
+  open,
+  close,
+});
+</script>
+
+
+<style lang="less" scoped>
+@import url("@/style.less");
+
+.form {
+  &_item {
+    margin-top: 24rpx;
+
+    &:first-child {
+      margin-top: 0;
+    }
+
+    .item_label {
+      font-weight: 700;
+      color: var(--text);
+      .size(28rpx);
+      line-height: 60rpx;
+      white-space: nowrap;
+      padding-right: 24rpx;
+      height: 64rpx;
+      width: fit-content;
+      position: relative;
+
+      &::before {
+        content: "*";
+        color: #f56c6c;
+        margin-right: 8rpx;
+      }
+    }
+
+    ._required {
+      &::before {
+        content: "";
+        margin-right: 0rpx;
+      }
+    }
+
+    .item_value {
+      column-gap: 24rpx;
+      flex: 1;
+
+      /deep/ .u-input {
+        border-radius: 16rpx;
+        padding: 0 24rpx !important;
+        background-color: var(--bg);
+
+        .u-input__content {
+          display: unset;
+        }
+      }
+
+      /deep/ .u-select {
+        flex: 1;
+        height: 32px;
+        padding: 0 24rpx;
+        border-radius: 16rpx;
+        background-color: var(--bg);
+        border-color: var(--borderColor) !important;
+        box-shadow: 0 0 0 1px var(--borderColor) inset;
+
+        .u-select__label {
+          margin: 0;
+          line-height: 32px;
+
+          .select_label {
+            flex: 1;
+            color: #adb8cc;
+            .size(28rpx);
+            .ellipsis();
+            width: 100%;
+          }
+
+          .u-select__options {
+            width: 80vw;
+          }
+        }
+      }
+
+      .country_select,
+      .province_select {
+        /deep/ .u-select__options {
+          width: 80vw;
+
+          .u-select__options_item {
+            .size(24rpx);
+            height: 80rpx;
+            line-height: 80rpx;
+            padding: 0 64rpx;
+
+            .u-select__item_text {
+              color: var(--inputText);
+            }
+          }
+
+          .active {
+            .u-select__item_text {
+              font-weight: 700;
+              color: var(--black) !important;
+            }
+          }
+        }
+      }
+
+      .province_select {
+        /deep/ .u-select__options {
+          // width: 300rpx;
+        }
+      }
+    }
+
+    .labels {
+      margin-top: 24rpx;
+      .ver();
+      gap: 24rpx;
+
+      &_item {
+        border: 1px solid #7d8fb3;
+        border-radius: 8rpx;
+        color: #7d8fb3;
+        padding: 0 28rpx;
+        line-height: 64rpx;
+        .size(24rpx);
+      }
+
+      .labels_active {
+        background-color: var(--black);
+        border: 1px solid var(--black);
+        color: var(--light);
+      }
+    }
+  }
+}
+
+.submit_btn {
+  height: 38px;
+  padding: 16rpx 30rpx;
+  background-color: var(--black);
+  color: var(--light);
+  .flex_center();
+  border-radius: 16rpx;
+  .size(24rpx);
+}
+</style>

+ 104 - 0
components/area.vue

@@ -0,0 +1,104 @@
+<template>
+  <view>
+    <view class="area">
+      <view class="img" :style="{ backgroundPosition: items.position }"></view>
+      <view class="area_text">{{ codeNum ? items.code : items?.country }}</view>
+    </view>
+    <Picker
+      :data="arealist"
+      ref="popupRef"
+      v-model="internalCode"
+      labelKey="country"
+      valueKey="code"
+      @confirm="confirm"
+    >
+      <template #pickerItem="{ item }">
+        <view class="picker_item"> {{ item.country }} {{ item.code }} </view>
+      </template>
+    </Picker>
+  </view>
+</template>
+<script setup>
+import Picker from "./picker";
+import { useSystemStore } from "@/store";
+import { ref, computed, watch } from "vue";
+const props = defineProps({
+  modelValue: {
+    type: [String, Number],
+    default: null,
+  },
+  codeNum: Boolean,
+});
+
+const useSystem = useSystemStore();
+const popupRef = ref(null);
+const arealist = computed(() => useSystem.getCountryCodes);
+const internalCode = ref(props.modelValue);
+
+watch(
+  () => props.modelValue,
+  (newVal) => {
+    internalCode.value = newVal;
+  },
+  { immediate: true }
+);
+
+watch(
+  () => internalCode.value,
+  (newVal) => {
+    emit("update:modelValue", newVal);
+  }
+);
+
+const emit = defineEmits(["update:modelValue", "confirm"]);
+
+const confirm = (data) => {
+  emit("confirm", data);
+  emit("update:modelValue", data.code);
+  internalCode.value = data.code;
+};
+
+const open = () => {
+  popupRef.value && popupRef.value.open();
+};
+const items = computed(() => {
+  let areas = JSON.parse(JSON.stringify(arealist.value));
+  if (!areas || !areas.length) {
+    return {};
+  }
+  const list = areas.find((item) => item.code == props.modelValue);
+  if (!props.modelValue) {
+    const defaultItem = areas[0] || {};
+    internalCode.value = defaultItem.code;
+    emit("confirm", defaultItem);
+    return defaultItem;
+  }
+  emit("confirm", list);
+  return list || {};
+});
+defineExpose({
+  open,
+});
+</script>
+<style lang="less" scoped>
+.area {
+  display: flex;
+  align-items: center;
+
+  .img {
+    background: url(@/static/login/country_img.png) no-repeat 0 0;
+    -webkit-background-size: 24px 3876px;
+    background-size: 24px 3876px;
+    width: 24px;
+    height: 16px;
+    overflow: hidden;
+  }
+
+  .area_text {
+    margin-left: 10rpx;
+    color: var(--black);
+    font-size: 28rpx;
+    line-height: 16px;
+  }
+}
+</style>

+ 493 - 0
components/blindModel.vue

@@ -0,0 +1,493 @@
+<template>
+  <Theme>
+    <Popup ref="popRef" mode="center">
+      <template #content>
+        <view class="content">
+          <view class="content_success" v-if="giftStatus == 'await'">
+            <trans _t="恭喜!您有一份盲盒待解锁" class="title"></trans>
+            <view class="gift_container">
+              <image
+                src="/static/user/gift_bg.png"
+                class="gift_box_img"
+              ></image>
+            </view>
+            <view class="gift_bottom"></view>
+          </view>
+          <view class="opening_animation" v-else-if="giftStatus == 'loading'">
+            <view class="gift_container opening">
+              <image
+                src="/static/user/gift_bg.png"
+                class="gift_box_img opening"
+              ></image>
+              <view class="crack_effect">
+                <view
+                  class="crack"
+                  v-for="i in 4"
+                  :key="i"
+                  :style="{ '--delay': i * 0.1 + 's' }"
+                ></view>
+              </view>
+              <view class="explosion_particles">
+                <view
+                  class="explosion"
+                  v-for="i in 12"
+                  :key="i"
+                  :style="{
+                    '--delay': i * 0.05 + 's',
+                    '--angle': i * 30 + 'deg',
+                  }"
+                ></view>
+              </view>
+            </view>
+            <image
+              class="fireworks_img"
+              src="/static/user/fireworks.gif"
+            ></image>
+          </view>
+          <view class="content_success" v-else-if="giftStatus == 'open'">
+            <trans _t="恭喜!您获得" class="title"></trans>
+            <view class="gift_box">
+              <image src="/static/user/get_gift.png" class="img"></image>
+              <view class="cont_box">
+                <view class="title">
+                  <trans _t="盲盒兑换券" />
+                  ×1</view
+                >
+                <view class="time">
+                  <trans _t="有效期限:" />
+                  <view class="days">
+                    180
+                    <trans _t="天" />
+                  </view>
+                </view>
+              </view>
+            </view>
+          </view>
+        </view>
+      </template>
+      <template #footer>
+        <slot name="footer">
+          <view class="footer">
+            <template v-if="giftStatus == 'await'">
+              <view class="submit_btn" @click="openGift">
+                <trans _t="立即打开" />
+              </view>
+              <view class="submit_btn submit_shop" @click="close">
+                <trans _t="一会儿再说" />
+              </view>
+            </template>
+            <view
+              class="submit_btn"
+              @click="gitGift"
+              v-else-if="giftStatus == 'open'"
+            >
+              <trans _t="领取" />
+            </view>
+          </view>
+        </slot>
+      </template>
+    </Popup>
+
+    <floatButton
+      bottom="120px"
+      right="0"
+      image="/static/user/get_gift.png"
+      :unclaimedNum="count"
+      @onConfirm="open"
+      v-if="!giftShow && count"
+    />
+  </Theme>
+</template>
+
+<script setup>
+import { ref, watch, computed, nextTick } from "vue";
+import Popup from "@/components/popup.vue";
+import { t } from "@/locale";
+import { useSystemStore } from "@/store";
+import { CONTENT_RECEIVE_BOX } from "@/api";
+import { Toast, TimeOut } from "@/utils";
+import floatButton from "@/components/floatButton";
+
+const popRef = ref(null);
+const useSystem = useSystemStore();
+const count = computed(() => useSystem.getCount);
+const giftShow = ref(false);
+const giftStatus = ref("await");
+
+const emit = defineEmits(["complete", "close", "open"]);
+
+const open = () => {
+  giftStatus.value = "await";
+  popRef.value && popRef.value.open();
+  giftShow.value = true;
+  emit("open");
+};
+
+const close = () => {
+  emit("close");
+  giftShow.value = false;
+  popRef.value && popRef.value.close();
+};
+const openGift = async () => {
+  giftStatus.value = "loading";
+  try {
+    await CONTENT_RECEIVE_BOX();
+    useSystem.setBoxes();
+    giftStatus.value = "open";
+  } catch (error) {
+    Toast(error.msg);
+    giftStatus.value = "await";
+  }
+  // 添加开启动画的延迟,让用户看到完整的动画效果
+  // setTimeout(async () => {
+
+  // }, 2000);
+};
+const gitGift = () => {
+  uni.navigateTo({ url: "/pages/user/weal_center" });
+  giftStatus.value = "await";
+  close();
+};
+watch(
+  () => count.value,
+  (val) => {
+    if (giftStatus.value == "await") {
+      if (val) {
+        nextTick(() => {
+          open();
+        });
+      } else {
+        close();
+      }
+    }
+  },
+  {
+    immediate: true,
+  }
+);
+
+defineExpose({ open, close });
+</script>
+
+<style lang="less" scoped>
+@import url("@/style.less");
+
+// 关键帧动画定义
+@keyframes giftFloat {
+  0%,
+  100% {
+    transform: translateY(0px) rotate(0deg);
+  }
+  25% {
+    transform: translateY(-10rpx) rotate(1deg);
+  }
+  50% {
+    transform: translateY(-5rpx) rotate(0deg);
+  }
+  75% {
+    transform: translateY(-15rpx) rotate(-1deg);
+  }
+}
+
+@keyframes shine {
+  0% {
+    transform: translateX(-100%) translateY(-100%) rotate(45deg);
+  }
+  50% {
+    transform: translateX(100%) translateY(100%) rotate(45deg);
+  }
+  100% {
+    transform: translateX(100%) translateY(100%) rotate(45deg);
+  }
+}
+
+@keyframes particleFloat {
+  0%,
+  100% {
+    transform: translateY(0px) scale(1);
+    opacity: 0.8;
+  }
+  50% {
+    transform: translateY(-20rpx) scale(1.2);
+    opacity: 1;
+  }
+}
+
+@keyframes giftShake {
+  0%,
+  100% {
+    transform: translateX(0) scale(1);
+  }
+  10% {
+    transform: translateX(-5rpx) scale(1.05);
+  }
+  20% {
+    transform: translateX(5rpx) scale(1.05);
+  }
+  30% {
+    transform: translateX(-5rpx) scale(1.05);
+  }
+  40% {
+    transform: translateX(5rpx) scale(1.05);
+  }
+  50% {
+    transform: translateX(-5rpx) scale(1.05);
+  }
+  60% {
+    transform: translateX(5rpx) scale(1.05);
+  }
+  70% {
+    transform: translateX(-5rpx) scale(1.05);
+  }
+  80% {
+    transform: translateX(5rpx) scale(1.05);
+  }
+  90% {
+    transform: translateX(-5rpx) scale(1.05);
+  }
+}
+
+@keyframes giftExplode {
+  0% {
+    transform: scale(1.1);
+    opacity: 1;
+  }
+  50% {
+    transform: scale(1.3);
+    opacity: 0.8;
+  }
+  100% {
+    transform: scale(0.8);
+    opacity: 0;
+  }
+}
+
+@keyframes crackAppear {
+  0% {
+    width: 0;
+    opacity: 0;
+  }
+  100% {
+    width: var(--width, 80%);
+    opacity: 1;
+  }
+}
+
+@keyframes explosionFly {
+  0% {
+    transform: rotate(var(--angle)) translateX(0) scale(1);
+    opacity: 1;
+  }
+  50% {
+    transform: rotate(var(--angle)) translateX(100rpx) scale(1.5);
+    opacity: 0.8;
+  }
+  100% {
+    transform: rotate(var(--angle)) translateX(200rpx) scale(0.5);
+    opacity: 0;
+  }
+}
+
+:deep(.conts) {
+  min-width: 85vw;
+  max-width: 95vw;
+}
+
+.content {
+  padding: 40rpx 0;
+  flex: 1;
+  .flex_center();
+
+  &_success {
+    position: relative;
+    .flex_center();
+    flex-direction: column;
+    gap: 20rpx;
+    .gift_bottom {
+      position: absolute;
+      left: 50%;
+      bottom: 10rpx;
+      width: 180rpx;
+      height: 40rpx;
+      border-radius: 20rpx;
+      background: #ffdbbb;
+      transform: translateX(-90rpx);
+      filter: blur(40rpx);
+    }
+    .gift_box {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      width: 100%;
+      border-radius: 20rpx;
+      padding: 10rpx 16rpx 0;
+      background: linear-gradient(180deg, #e6734c 0%, #eb3a68 100%);
+      .img {
+        width: 140rpx;
+        height: 140rpx;
+        margin-bottom: 20rpx;
+      }
+      .cont_box {
+        display: flex;
+        flex-direction: column;
+        justify-content: space-between;
+        align-items: center;
+        width: 450rpx;
+        height: 222rpx;
+        background: url("/static/user/gift_box.png");
+        background-size: 100% 100%;
+        padding: 40rpx 0 50rpx;
+
+        .title {
+          .size(32rpx);
+          color: var(--red);
+        }
+        .time {
+          display: flex;
+          .size(28rpx);
+          color: var(--text-02);
+          .days {
+            color: var(--text);
+            font-weight: 700;
+          }
+        }
+      }
+    }
+  }
+  .title {
+    .size(32rpx);
+    color: #3d3d3d;
+    font-weight: 600;
+    margin-bottom: 40rpx;
+  }
+  .img {
+    width: 300rpx;
+    height: 300rpx;
+  }
+
+  // 盲盒容器
+  .gift_container {
+    position: relative;
+    width: 300rpx;
+    height: 300rpx;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+
+    .gift_box_img {
+      width: 300rpx;
+      height: 300rpx;
+      transition: all 0.3s ease;
+      animation: giftFloat 2s ease-in-out infinite;
+
+      &.opening {
+        animation: giftShake 0.5s ease-in-out, giftExplode 0.8s ease-out 0.5s;
+        transform: scale(1.1);
+      }
+    }
+
+    // 拆开时的裂纹效果
+    .crack_effect {
+      position: absolute;
+      top: 0;
+      left: 0;
+      width: 100%;
+      height: 100%;
+
+      .crack {
+        position: absolute;
+        background: linear-gradient(45deg, transparent, #ff6b35, transparent);
+        animation: crackAppear 0.3s ease-out;
+        animation-delay: var(--delay);
+
+        &:nth-child(1) {
+          top: 20%;
+          left: 10%;
+          width: 80%;
+          height: 2rpx;
+          transform: rotate(15deg);
+        }
+        &:nth-child(2) {
+          top: 40%;
+          left: 20%;
+          width: 60%;
+          height: 2rpx;
+          transform: rotate(-25deg);
+        }
+        &:nth-child(3) {
+          top: 60%;
+          left: 15%;
+          width: 70%;
+          height: 2rpx;
+          transform: rotate(35deg);
+        }
+        &:nth-child(4) {
+          top: 80%;
+          left: 25%;
+          width: 50%;
+          height: 2rpx;
+          transform: rotate(-15deg);
+        }
+      }
+    }
+
+    // 爆炸粒子效果
+    .explosion_particles {
+      position: absolute;
+      top: 50%;
+      left: 50%;
+      transform: translate(-50%, -50%);
+
+      .explosion {
+        position: absolute;
+        width: 6rpx;
+        height: 6rpx;
+        background: radial-gradient(circle, #ff6b35, #ffd700);
+        border-radius: 50%;
+        animation: explosionFly 1s ease-out forwards;
+        animation-delay: var(--delay);
+        transform: rotate(var(--angle)) translateX(0);
+      }
+    }
+  }
+
+  // 开启动画容器
+  .opening_animation {
+    position: relative;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    width: 100%;
+    height: 300rpx;
+
+    .fireworks_img {
+      position: absolute;
+      top: 50%;
+      left: 50%;
+      transform: translate(-50%, -50%);
+      width: 400rpx;
+      height: 400rpx;
+      z-index: 10;
+    }
+  }
+}
+
+.footer {
+  .submit_btn {
+    width: 100%;
+    height: 76rpx;
+    padding: 16rpx 30rpx;
+    background-color: var(--black);
+    color: var(--light);
+    .flex_center();
+    border-radius: 16rpx;
+    .size(24rpx);
+    margin-top: 24rpx;
+    &.submit_shop {
+      background-color: var(--bg);
+      border: 1rpx solid var(--black);
+      color: var(--black);
+    }
+  }
+}
+</style>

+ 245 - 0
components/commentDialog.vue

@@ -0,0 +1,245 @@
+<template>
+  <Popup :title="t('评论')" isClose ref="popRef">
+    <template #content>
+      <List url="/discover/video/comments" :defaultParams="{ video_id: video_id }" @datas="getList" ref="listRef">
+        <template #item="{ item }">
+          <view class="comment-item">
+            <image class="avatar" :src="item.avatar || '/static/tx.png'" mode="aspectFill"></image>
+            <view class="content">
+              <view class="username">{{ item.username }}</view>
+              <view class="text">{{ item.content }}</view>
+              <view class="footer">
+                <text class="time">{{ fromTime(item.indate) }}</text>
+                <view class="actions">
+                  <text class="reply" @click="reply(item)">{{ t('回复') }}</text>
+                </view>
+              </view>
+            </view>
+          </view>
+          <view v-if="item.replay && item.replay.length" class="child-comments">
+            <view class="comment-item" v-for="child in item.replay" :key="child.id">
+              <image class="avatar" :src="child.avatar || '/static/tx.png'" mode="aspectFill"></image>
+              <view class="content">
+                <text class="username">{{ child.username }}</text>
+                <view class="text">{{ child.content }}</view>
+                <view class="footer">
+                  <text class="time">{{ fromTime(child.indate) }}</text>
+                </view>
+              </view>
+            </view>
+          </view>
+        </template>
+      </List>
+    </template>
+    <template #footer>
+      <view class="comment-input">
+        <Input class="input" :placeholder="replyTo ? t('回复') + '@' + replyTo.username : t('说点什么...')"
+          @confirm="submitComment" :focus="showReplyInput" border="surround" v-model="commentText" />
+        <view class="submit-btn" @click.stop="submitComment" :style="{ opacity: commentText ? 1 : .5 }">
+          <trans _t="发送" />
+        </view>
+      </view>
+    </template>
+  </Popup>
+</template>
+
+<script setup>
+import { ref, nextTick } from 'vue'
+import Input from "./input";
+import { t } from "@/locale"
+import { DISCOVER_VIDEO_SUBCOMMENTS } from "@/api"
+import List from "@/components/list";
+import { Toast, fromTime } from "@/utils"
+import Popup from './popup.vue';
+
+const props = defineProps({
+  video_id: {
+    required: true
+  }
+})
+const popRef = ref(null);
+
+const defaultParams = ref([])
+// 评论输入
+const commentText = ref('')
+const replyTo = ref(null)
+
+const listRef = ref(null)
+const showReplyInput = ref(false)
+
+const commentList = ref([])
+const getList = (list) => {
+  commentList.value = list
+}
+const open = () => {
+  clearInput()
+  popRef.value && popRef.value.open()
+  defaultParams.video_id = props.video_id
+  nextTick(() => {
+    listRef.value && listRef.value.handleRefresh();
+  })
+}
+
+const close = () => {
+  clearInput()
+  popRef.value && popRef.value.close()
+}
+
+const submitComment = async () => {
+  if (!commentText.value.trim()) return
+
+  try {
+    const result = await DISCOVER_VIDEO_SUBCOMMENTS({
+      video_id: props.video_id,
+      content: commentText.value,
+      pid: replyTo.value ? replyTo.value.id : 0
+    })
+    // 只添加新评论而不刷新整个列表
+    if (replyTo.value) {
+      addReplyToCommentList(commentList.value, replyTo.value.id, result.data)
+    } else {
+      commentList.value.unshift(result.data)
+    }
+    listRef.value && listRef.value.setList(commentList.value);
+    clearInput()
+  } catch (error) {
+    Toast(error.msg)
+  }
+}
+
+// 辅助函数 - 添加回复到评论树
+function addReplyToCommentList(comments, parentId, newComment) {
+  for (const comment of comments) {
+    if (comment.id === parentId) {
+      if (!comment.replay) comment.replay = []
+      comment.replay.unshift(newComment)
+      return true
+    }
+    if (comment.replay && addReplyToCommentList(comment.replay, parentId, newComment)) {
+      return true
+    }
+  }
+  return false
+}
+
+function clearInput() {
+  commentText.value = ''
+  replyTo.value = null
+  showReplyInput.value = false
+}
+
+const reply = (comment) => {
+  replyTo.value = comment
+  showReplyInput.value = true
+}
+
+defineExpose({
+  open,
+  close
+})
+</script>
+
+<style lang="less" scoped>
+@import url('@/style.less');
+
+:deep(.u-list) {
+  height: max-content !important;
+}
+
+.comment-item {
+  display: flex;
+  padding: 20rpx 0;
+
+  // border-bottom: 1rpx solid var(--borderColor);
+  .avatar {
+    width: 80rpx;
+    height: 80rpx;
+    border-radius: 50%;
+    margin-right: 20rpx;
+    flex-shrink: 0;
+  }
+
+  .content {
+    flex: 1;
+    overflow: hidden;
+
+    .username {
+      .size(28rpx);
+      color: var(--text);
+      margin-right: 10rpx;
+    }
+
+    .text {
+      .size(30rpx);
+      margin: 10rpx 0;
+      line-height: 1.5;
+      color: var(--text);
+      word-break: break-all;
+    }
+
+    .footer {
+      display: flex;
+      justify-content: space-between;
+      margin-top: 10rpx;
+
+      .time {
+        font-size: 24rpx;
+        color: var(--text);
+      }
+
+      .actions {
+        display: flex;
+        align-items: center;
+
+        .like,
+        .reply {
+          font-size: 24rpx;
+          color: var(--text);
+          margin-left: 20rpx;
+          display: flex;
+          align-items: center;
+
+          &:active {
+            opacity: 0.7;
+          }
+        }
+      }
+    }
+  }
+}
+
+.child-comments {
+  margin-left: 80rpx;
+}
+
+.comment-input {
+  .flex_center;
+  background-color: var(--bg);
+
+  .input {
+    flex: 1;
+    height: 70rpx;
+    padding: 0 20rpx;
+    background-color: var(--inputBg);
+    border-radius: 35rpx;
+    margin-right: 20rpx;
+    font-size: 28rpx;
+    color: var(--text);
+  }
+
+  .submit-btn {
+    .size(28rpx);
+    height: 70rpx;
+    line-height: 70rpx;
+    padding: 0 30rpx;
+    background-color: var(--black);
+    color: #fff;
+    border-radius: 35rpx;
+    border: none;
+
+    &[disabled] {
+      background-color: var(--text-02);
+    }
+  }
+}
+</style>

+ 127 - 0
components/couponModel.vue

@@ -0,0 +1,127 @@
+<template>
+  <Popup ref="popRef" mode="center" closeOnClickOverlay>
+    <template #content>
+      <view class="content">
+        <image
+          :src="coupon.picture"
+          class="img"
+          mode="widthFix"
+          v-if="coupon.picture"
+          @click="drawCoupon"
+        >
+        </image>
+      </view>
+    </template>
+    <template #footer>
+      <view class="close" @click="close">
+        <image
+          class="icon-font"
+          mode="widthFix"
+          src="/static/home/close.png"
+        ></image>
+      </view>
+    </template>
+  </Popup>
+</template>
+
+<script setup>
+import { ref, watch, computed, nextTick } from "vue";
+import Popup from "@/components/popup.vue";
+import { t } from "@/locale";
+import { useSystemStore } from "@/store";
+import { SHOP_GET_COUPON } from "@/api";
+import { Toast, TimeOut } from "@/utils";
+
+const useSystem = useSystemStore();
+const coupon = computed(() => useSystem.getCoupon);
+const props = defineProps({
+  coponData: {
+    type: Object,
+  },
+});
+const popRef = ref(null);
+
+const emit = defineEmits(["open", "close"]);
+
+const open = () => {
+  popRef.value && popRef.value.open();
+};
+
+const close = () => {
+  popRef.value && popRef.value.close();
+  emit("close");
+};
+
+const drawCoupon = async () => {
+  if (!coupon.value.id) return;
+  try {
+    const res = await SHOP_GET_COUPON(coupon.value.id);
+    Toast(res.msg).then(() => {
+      TimeOut(() => {
+        close();
+        useSystem.setCoupon();
+        uni.navigateTo({ url: "/pages/user/coupon" });
+      });
+    });
+  } catch (error) {
+    Toast(error.msg);
+  }
+};
+
+watch(
+  () => coupon.value?.show,
+  (val) => {
+    if (val) {
+      nextTick(() => {
+        open();
+      });
+    } else {
+      close();
+    }
+  },
+  {
+    immediate: true,
+  }
+);
+
+defineExpose({ open, close });
+</script>
+
+<style lang="less" scoped>
+@import url("@/style.less");
+
+:deep(.conts) {
+  width: 600rpx;
+  padding: 0 !important;
+}
+
+:deep(.u-popup__content) {
+  background-color: transparent !important;
+}
+
+:deep(.footer) {
+  padding: 0 !important;
+}
+
+.content {
+  width: 100%;
+
+  .img {
+    width: 100%;
+    height: auto;
+    display: block;
+  }
+}
+
+.close {
+  .flex_center();
+  height: 76rpx;
+  width: 100%;
+  background-color: transparent;
+
+  .icon-font {
+    width: 46rpx;
+    height: 46rpx;
+  }
+}
+</style>

+ 126 - 0
components/floatButton.vue

@@ -0,0 +1,126 @@
+<template>
+  <up-float-button
+    :isMenu="isMenu"
+    :list="list"
+    :top="top"
+    :buttom="buttom"
+    :right="right"
+    :backgroundColor="backgroundColor"
+    :color="color"
+    :width="width"
+    :height="height"
+    :borderColor="borderColor"
+    @click="btnClick"
+    @item-click="itemClick"
+    style="z-index: 997"
+  >
+    <view class="buttom">
+      <view class="carts">
+        <image :src="image" class="img"></image>
+        <view class="cartNum" v-if="unclaimedNum || cartNum">{{
+          unclaimedNum || cartNum
+        }}</view>
+      </view>
+    </view>
+  </up-float-button>
+</template>
+<script setup>
+import { computed } from "vue";
+import { useShopStore, useTabbarStore } from "@/store";
+
+const useShop = useShopStore();
+const useTabbar = useTabbarStore();
+
+const props = defineProps({
+  isMenu: Boolean,
+  list: {
+    type: Array,
+    default: () => [],
+  },
+  backgroundColor: {
+    type: String,
+    default: "#e1e5ed",
+  },
+  top: String,
+  buttom: String,
+  right: {
+    type: String,
+    default: "30px",
+  },
+  color: {
+    type: String,
+    default: "#fff",
+  },
+  width: {
+    type: String,
+    default: "100rpx",
+  },
+  height: {
+    type: String,
+    default: "100rpx",
+  },
+  borderColor: {
+    type: String,
+    default: "",
+  },
+  image: {
+    type: String,
+    default: "/static/shop/cart.png",
+  },
+  unclaimedNum: {
+    type: Number,
+    default: 0,
+  },
+});
+const emit = defineEmits(["onConfirm", "itemClick"]);
+
+const cartNum = computed(() => useShop.getCartNum);
+
+const btnClick = () => {
+  emit("onConfirm");
+};
+const itemClick = (e) => {
+  emit("itemClick", e);
+};
+</script>
+
+<style lang="less" scoped>
+@import url("@/style.less");
+
+/deep/ .u-float-button__main {
+  .flex();
+}
+
+.buttom {
+  background-color: #1e1e1e;
+  width: 84rpx;
+  height: 84rpx;
+  border-radius: 50%;
+
+  .carts {
+    width: 100%;
+    height: 100%;
+    .flex_center();
+    position: relative;
+
+    .img {
+      width: 40rpx;
+      height: 40rpx;
+    }
+
+    .cartNum {
+      position: absolute;
+      top: 5px;
+      right: 5px;
+      width: 32rpx;
+      height: 32rpx;
+      border-radius: 50%;
+      border: 1px solid var(--light);
+      .flex_center();
+      color: var(--light);
+      background-color: #f56c6c;
+      .size(20rpx);
+    }
+  }
+}
+</style>

+ 255 - 0
components/footer_input.vue

@@ -0,0 +1,255 @@
+<template>
+  <view
+    class="footer_input"
+    :class="[
+      bottomHeight == 0 ? 'iosBottom' : '',
+      isFocused && bottomHeight && systemInfoName.osName == 'ios'
+        ? 'focused'
+        : '',
+    ]"
+    id="chatBottom"
+    :style="{
+      bottom: bottomHeight + 'px',
+      '--bottomHeight': allHeight.keyboardHeight + 'px',
+    }"
+  >
+    <view class="footer_">
+      <view class="inputs">
+        <up-textarea
+          :disabled="disabled"
+          v-model="inputValue"
+          maxlength="-1"
+          :placeholder="$t(placeholder)"
+          :adjustPosition="useGlobal().adjustPosition"
+          confirm-type="send"
+          :showConfirmBar="false"
+          :ignoreCompositionEvent="false"
+          autoHeight
+          @linechange="heightChange"
+          @focus="isFocused = true"
+          @blur="onBlur"
+          @keyboardheightchange="keyboardheightchange"
+          @update:modelValue="input"
+          @confirm="submit"
+          @submit="submit"
+        />
+      </view>
+      <view class="footer_btns">
+        <view class="footer_icon" @click="imageUploader">
+          <image class="img" src="@/static/chat/chat_add-icon.png"></image>
+        </view>
+        <view class="footer_send_btn" @click="submit">
+          <image
+            class="img"
+            src="@/static/chat/arrows_up-icon.png"
+            mode="heightFix"
+          ></image>
+        </view>
+      </view>
+    </view>
+  </view>
+  <CameraUpload ref="cameraUploadRef" @confirm="onCameraConfirm" />
+</template>
+<script setup>
+import {
+  query,
+  useGlobal,
+  uploadChooseImage,
+  $upload,
+  debounce,
+  systemInfo,
+} from "@/utils";
+import { ref, reactive, nextTick, onMounted } from "vue";
+import { onShow } from "@dcloudio/uni-app";
+import CameraUpload from "./CameraUpload.vue";
+const props = defineProps({
+  disabled: {
+    type: Boolean,
+    default: false,
+  },
+  placeholder: {
+    type: String,
+    default: "请输入消息内容",
+  },
+  modelValue: {
+    type: [String, Number],
+    default: "",
+  },
+  bottomHeight: {
+    type: Number,
+    default: 0,
+  },
+});
+const emit = defineEmits([
+  "update:modelValue",
+  "heights",
+  "linechange",
+  "submit",
+  "imageUp",
+]);
+const inputValue = ref(props.modelValue);
+const allHeight = reactive({
+  height: 0,
+  keyboardHeight: 0,
+});
+
+const isFocused = ref(false);
+const systemInfoName = systemInfo();
+
+const clear = () => {
+  inputValue.value = "";
+};
+
+function isIOS() {
+  const userAgent = navigator.userAgent.toLowerCase();
+  return /iphone|ipad|ipod|ios/.test(userAgent);
+}
+
+const emitHeights = debounce((heightData) => {
+  if (!props.disabled) {
+    emit("heights", heightData);
+  }
+}, 100);
+
+const submit = () => {
+  if (!inputValue.value.replace(/\s+/g, "")) return;
+  if (!props.disabled) {
+    emit("submit");
+  }
+};
+const input = (value) => {
+  inputValue.value = value;
+  emit("update:modelValue", value);
+};
+const getHeight = (id = "#chatBottom") => {
+  try {
+    nextTick(async () => {
+      const res = await query(id);
+      allHeight.height = res.height;
+      emitHeights(allHeight);
+    });
+  } catch (error) {}
+};
+
+const keyboardheightchange = (e) => {
+  nextTick(() => {
+    const systemInfo = uni.getSystemInfoSync();
+    const bottomSafeDistance =
+      systemInfo.screenHeight - systemInfo.safeArea.bottom;
+    allHeight.keyboardHeight =
+      e.detail.height -
+      (systemInfo.platform === "ios" && isFocused.value
+        ? bottomSafeDistance
+        : 0);
+    allHeight.bottomSafeDistance = isFocused.value && bottomSafeDistance;
+    emitHeights(allHeight);
+  });
+};
+
+const onBlur = (e) => {
+  isFocused.value = false;
+  keyboardheightchange(e);
+};
+
+const heightChange = (e) => {
+  getHeight();
+  emit("linechange", { detail: e.detail });
+};
+
+const cameraUploadRef = ref(null);
+const imageUploader = () => {
+  if (!props.disabled) {
+    cameraUploadRef.value && cameraUploadRef.value.open();
+  }
+};
+const onCameraConfirm = (url) => {
+  nextTick(() => {
+    emit("imageUp", url);
+  });
+};
+
+onMounted(() => {
+  nextTick(() => {
+    getHeight();
+  });
+});
+
+defineExpose({
+  getHeight,
+  clear,
+});
+</script>
+<style lang="less" scoped>
+@import url("@/style.less");
+
+.footer_input {
+  position: fixed;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  .ver();
+  padding: 0 30rpx;
+  background-color: #fafafa;
+  overflow: hidden;
+  z-index: 9999;
+
+  &.iosBottom {
+    padding-bottom: constant(safe-area-inset-bottom);
+    padding-bottom: env(safe-area-inset-bottom);
+  }
+  &.focused {
+    /*  #ifdef  APP-PLUS  */
+    bottom: calc(var(--bottomHeight) + env(safe-area-inset-bottom)) !important;
+    /*  #endif  */
+  }
+  .footer_ {
+    .ver(flex-end);
+    flex: 1;
+    padding: 20rpx 0;
+
+    .inputs {
+      min-height: 40px;
+      flex: 1;
+
+      /deep/ .u-textarea {
+        padding: 9px;
+
+        .uni-textarea-placeholder {
+          line-height: 1.2;
+        }
+
+        .u-textarea__field {
+          min-height: 0 !important;
+        }
+      }
+    }
+
+    .footer_btns {
+      .ver();
+      height: 40px;
+      margin-left: 20rpx;
+
+      .footer_icon {
+        .img {
+          width: 38rpx;
+          height: 38rpx;
+        }
+      }
+
+      .footer_send_btn {
+        .flex_center();
+        width: 68rpx;
+        height: 68rpx;
+        border-radius: 50%;
+        background-color: var(--black);
+        cursor: pointer;
+        margin-left: 15rpx;
+
+        .img {
+          height: 32rpx;
+        }
+      }
+    }
+  }
+}
+</style>

+ 137 - 0
components/imageUpload.vue

@@ -0,0 +1,137 @@
+<template>
+  <view class="image-uploader">
+    <up-upload
+      :source-type="['camera', 'album']"
+      :fileList="fileList"
+      @afterRead="handleAfterRead"
+      @delete="handleDelete"
+      :maxCount="maxCount"
+      :previewFullImage="true"
+      :multiple="multiple"
+      :disabled="disabled"
+      :deletable="!disabled"
+    >
+      <view class="upload-btn" v-if="fileList.length < maxCount">
+        <u-icon name="plus" size="40" color="#c0c4cc"></u-icon>
+      </view>
+    </up-upload>
+  </view>
+</template>
+
+<script setup>
+import { ref, watch } from "vue";
+import { $upload, Toast } from "@/utils";
+import { t } from "@/locale";
+
+const props = defineProps({
+  // 初始图片列表
+  modelValue: {
+    type: Array,
+    default: () => [],
+  },
+  // 最大上传数量
+  maxCount: {
+    type: Number,
+    default: 1,
+  },
+  // 是否多选
+  multiple: {
+    type: Boolean,
+    default: false,
+  },
+  disabled: {
+    type: Boolean,
+    default: false,
+  },
+  // 上传按钮文字
+  uploadText: {
+    type: String,
+    default: "上传图片",
+  },
+  // 上传接口地址
+  uploadUrl: {
+    type: String,
+    default: "",
+  },
+});
+
+const emit = defineEmits(["update:modelValue", "success", "delete", "error"]);
+
+const uToast = ref(null);
+const fileList = ref([]);
+
+// 监听父组件传入的值
+watch(
+  () => props.modelValue,
+  (newVal) => {
+    fileList.value = newVal.map((item) => {
+      return typeof item === "string" ? { url: item } : item;
+    });
+  },
+  { immediate: true }
+);
+
+// 文件读取完成后处理
+const handleAfterRead = async (event) => {
+  const files = event.file;
+  try {
+    const uploadFiles = Array.isArray(files) ? files : [files];
+    const results = await Promise.all(
+      uploadFiles.map((file) => {
+        return $upload(file.url);
+      })
+    );
+    const newFiles = results.map((res) => ({
+      url: res.data.url,
+      name: res.data.name,
+      status: "success",
+    }));
+    fileList.value = [...fileList.value, ...newFiles];
+    emit("update:modelValue", fileList.value);
+    emit("success", newFiles);
+    Toast(t("成功"));
+  } catch (error) {
+    emit("error", error);
+    Toast(t("失败"));
+  }
+};
+
+const handleDelete = (event) => {
+  const { index } = event;
+  const deletedFile = fileList.value[index];
+  fileList.value.splice(index, 1);
+  emit("update:modelValue", fileList.value);
+  emit("delete", deletedFile);
+};
+
+defineExpose({
+  clearFiles: () => {
+    fileList.value = [];
+    emit("update:modelValue", []);
+  },
+});
+</script>
+
+<style lang="less" scoped>
+.image-uploader {
+  padding: 10rpx;
+
+  .upload-btn {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    width: 150rpx;
+    height: 150rpx;
+    border: 1px dashed #c0c4cc;
+    border-radius: 8rpx;
+    background-color: #f5f7fa;
+
+    .upload-text {
+      margin-top: 10rpx;
+      font-size: 24rpx;
+      color: #909399;
+    }
+  }
+}
+</style>

+ 84 - 0
components/imgUp.vue

@@ -0,0 +1,84 @@
+<template>
+  <view class="my-image-uploader" :class="{ disabled: props.disabled }">
+    <view class="img-list">
+      <image v-for="(item, index) in fileList" :key="index" :src="item" class="img" mode="aspectFill"
+        @click="chooseImage" />
+    </view>
+    <view class="upload-btn" v-if="fileList.length < maxCount" @click="chooseImage">
+      <u-icon name="plus" size="40" color="#c0c4cc"></u-icon>
+    </view>
+
+    <CameraUpload ref="cameraUploadRef" @confirm="onCameraConfirm" />
+  </view>
+</template>
+<script setup>
+import { ref } from 'vue'
+import { $upload, Toast } from '@/utils'
+import { t } from "@/locale"
+import CameraUpload from "./CameraUpload.vue";
+
+const props = defineProps({
+  modelValue: { type: Array, default: () => [] },
+  maxCount: { type: Number, default: 1 },
+  disabled: {
+    type: Boolean,
+    default: false
+  },
+})
+const emit = defineEmits(['update:modelValue', 'success', 'delete', 'error'])
+
+const fileList = ref([...props.modelValue])
+
+const cameraUploadRef = ref(null)
+const chooseImage = () => {
+  if (props.disabled) return;
+  cameraUploadRef.value && cameraUploadRef.value.open()
+}
+
+const onCameraConfirm = async (url) => {
+  try {
+    fileList.value = [];
+    fileList.value.push(url)
+    emit('update:modelValue', fileList.value)
+    emit('success', url)
+  } catch (error) {
+    Toast.error(t('上传失败'))
+    emit('error', error)
+  }
+}
+</script>
+<style lang="less" scoped>
+.my-image-uploader {
+  display: flex;
+  flex-wrap: wrap;
+
+  &.disabled {
+    opacity: 0.5;
+    pointer-events: none;
+  }
+
+  .img-list {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 20rpx;
+
+    .img {
+      width: 150rpx;
+      height: 150rpx;
+      border-radius: 8rpx;
+      background: #f5f7fa;
+    }
+  }
+
+  .upload-btn {
+    width: 150rpx;
+    height: 150rpx;
+    border: 1px dashed #c0c4cc;
+    border-radius: 8rpx;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    background: #f5f7fa;
+  }
+}
+</style>

+ 158 - 0
components/input.vue

@@ -0,0 +1,158 @@
+<template>
+  <up-input :readonly="readonly" :shape="shape" :placeholder="placeholder" :placeholderClass="placeholderClass"
+    :suffixIcon="suffixIcon" :border="border" :adjustPosition="adjustPosition" :suffixIconStyle="suffixIconStyle"
+    :model-value="inputValue" :disabled="disabled" :maxlength="maxlength" :type="type" :clearable="clearable"
+    :placeholderStyle="placeholderStyle" :password="password" :confirm-type="confirmType" :focus="focus"
+    :inputAlign="inputAlign" :fontSize="fontSize" :color="color" :prefixIcon="prefixIcon"
+    :prefixIconStyle="prefixIconStyle" @clear="clear" @change="change" @update:modelValue="input" @confirm="confirm"
+    @keyboardheightchange="keyboardheightchange" @focus="focusChange" @blur="blur"
+    :style="{ '--bordercolor': borderColor, '--bgColor': bgColor }">
+    <template #prefix>
+      <slot name="prefix"></slot>
+    </template>
+    <template #suffix>
+      <slot name="suffix">
+        <view class="search_right" @click.stop="search" v-if="suffixIcon">
+          <u-icon :name="suffixIcon" color="var(--gray1)" size="20"></u-icon>
+        </view>
+      </slot>
+    </template>
+  </up-input>
+</template>
+<script setup>
+import { ref, nextTick, watch } from "vue";
+const props = defineProps({
+  placeholder: {
+    type: String,
+    default: ''
+  },
+  modelValue: {
+    type: [String, Number],
+    default: ''
+  },
+  type: {
+    type: String,
+    default: 'text'
+  },
+  clearable: Boolean,
+  password: Boolean,
+  readonly: Boolean,
+  shape: {
+    type: String,
+    default: 'circle' // circle | square
+  },
+  suffixIcon: {
+    type: String,
+    default: ''
+  },
+  border: {
+    type: String,
+    default: 'surround' // surround | bottom | none
+  },
+  suffixIconStyle: {
+    type: [String, Object],
+    default: ''
+  },
+  placeholderStyle: {
+    type: [String, Object],
+    default: 'color: #adb8cc'
+  },
+  placeholderClass: {
+    type: String,
+    default: ''
+  },
+  adjustPosition: Boolean,
+  disabled: Boolean,
+  maxlength: {
+    type: Number,
+    default: -1
+  },
+  confirmType: {
+    type: String,
+    default: 'done'
+  },
+  focus: Boolean,
+  inputAlign: {
+    type: String,
+    default: 'left'
+  },
+  fontSize: {
+    type: String,
+    default: '14px'
+  },
+  color: {
+    type: String,
+    default: 'var(--inputText)'
+  },
+  prefixIcon: {
+    type: String,
+    default: ''
+  },
+  prefixIconStyle: {
+    type: [String, Object],
+    default: ''
+  },
+  borderColor: {
+    type: String,
+    default: 'var(--inputBorder)'
+  },
+  bgColor: {
+    type: String,
+    default: 'var(--light)'
+  }
+})
+const emit = defineEmits(['update:modelValue', 'search', 'clear', 'change', 'confirm', 'keyboardheightchange', 'focusChange', 'blur'])
+const inputValue = ref(props.modelValue)
+
+const search = () => {
+  emit('search');
+}
+const clear = () => {
+  emit('clear')
+}
+const change = (value) => {
+  emit('change', value)
+}
+const input = (value) => {
+  inputValue.value = value;
+  emit('update:modelValue', value)
+}
+const confirm = (value) => {
+  emit('confirm', value)
+}
+const keyboardheightchange = () => {
+  emit('keyboardheightchange')
+}
+const focusChange = () => {
+  emit('focusChange')
+}
+const blur = (value) => {
+  emit('blur', value)
+}
+
+watch(() => props.modelValue, (newValue) => {
+  inputValue.value = newValue;
+});
+</script>
+<style lang="less" scoped>
+.u-border {
+  border-color: var(--borderColor) !important;
+  box-shadow: 0 0 0 1px var(--borderColor) inset;
+}
+
+.u-input {
+  padding: 0 8px !important;
+  background-color: var(--inputBg);
+
+  /deep/ .u-input__content__prefix-icon {
+    margin-right: 8px;
+  }
+  /deep/ .uni-input-placeholder{
+    color: var(--text-01) !important;
+  }
+
+  /deep/ .u-input__content__field-wrapper__field {
+    height: 32px;
+  }
+}
+</style>

+ 207 - 0
components/list copy.vue

@@ -0,0 +1,207 @@
+<template>
+  <view>
+    <!-- @scrolltolower="scrolltolower" -->
+    <up-list style="height:auto" id="item_height" class="wrap_list">
+      <up-list-item v-for="(item, index) in lists" :key="index">
+        <slot name="item" :item="item" :index="index"></slot>
+      </up-list-item>
+    </up-list>
+    <view class="null_warp" v-if="!!status && !lists.length">
+      <slot name="null">
+        <view class="null_text">{{ t(nullText || '无数据') }}</view>
+      </slot>
+    </view>
+    <template v-if="!!status && lists.length">
+      <view class="load_more">
+        <u-loadmore :status="status" :loading-text="t(loadingText)" :loadmore-text="t(loadmoreText)"
+          :nomore-text="t(nomoreText)" />
+      </view>
+    </template>
+  </view>
+</template>
+
+<script setup>
+import { useCacheStore } from '@/store';
+import { query, $post, systemInfo } from '@/utils';
+import { ref, nextTick } from "vue";
+import { t } from "@/locale";
+
+const useCache = useCacheStore();
+
+const props = defineProps({
+  topHeight: {
+    type: Number,
+    default: 0
+  },
+  url: {
+    type: String,
+    default: ''
+  },
+  pageSize: {
+    type: Number,
+    default: 20
+  },
+  defaultParams: {
+    type: Object,
+    default: () => { }
+  },
+  nullText: String,
+  loadingText: {
+    type: String,
+    default: '正在加载中'
+  },
+  loadmoreText: {
+    type: String,
+    default: '加载更多'
+  },
+  nomoreText: {
+    type: String,
+    default: '没有更多了'
+  },
+  getIndex: {
+    type: Number,
+    default: 0
+  },
+  activeIndex: {
+    type: Number,
+    default: 0
+  },
+  isCache: {
+    type: Boolean,
+    default: false
+  }
+})
+
+const emit = defineEmits(['datas'])
+
+const lists = ref([]);
+const page = ref(1);
+const totals = ref(0);
+const status = ref('nomore');
+const noData = ref(false);
+const height = ref(0);
+
+const scrolltolower = () => {
+  if (!noData.value) {
+    let num = page.value;
+    num += 1;
+    page.value = num;
+    getData();
+  }
+}
+const getListKey = () => `${props.url}_${JSON.stringify(props.defaultParams)}`;
+
+const getData = async (force = false) => {
+  try {
+    if (props.isCache) {
+      const key = getListKey()
+      const list = await useCache.getListPageData({
+        key,
+        page: page.value,
+        pageSize: props.pageSize,
+        apiFn: props.url,
+        params: props.defaultParams,
+        force
+      })
+      if (list) {
+        lists.value = list;
+        emit('datas', lists.value)
+        nextTick(() => {
+          getHeight();
+        })
+        return;
+      }
+    }
+
+    status.value = 'loading';
+    const { data: { data: { item: data, total_results: count } } } = await $post(props.url, { pageSize: props.pageSize, page: page.value, ...props.defaultParams });
+    status.value = 'nomore';
+    if (data.length < props.pageSize) {
+      noData.value = true
+    } else {
+      noData.value = false
+    }
+    totals.value = count - 0;
+    if (page.value > 1) {
+      const arrList = lists.value;
+      lists.value = [...arrList, ...data]
+      emit('datas', lists.value)
+      nextTick(() => {
+        getHeight();
+      })
+      return;
+    }
+    lists.value = data;
+    emit('datas', lists.value)
+    nextTick(() => {
+      getHeight();
+    })
+  } catch (error) {
+    console.error(error, 'getData');
+  }
+}
+const getHeight = async (name = '#item_height') => {
+  const { height: heights } = await query(name, this);
+  nextTick(() => {
+    height.value = heights
+    const { windowHeight, statusBarHeight } = systemInfo();
+    let contHeight = windowHeight - 44 - props.topHeight;
+    if (height < contHeight) {
+      scrolltolower();
+    }
+  })
+  return height
+}
+const handleRefresh = (flag = false) => {
+  page.value = 1;
+  status.value = 'nomore';
+  noData.value = false;
+  if (!flag) {
+    lists.value = []
+  }
+  nextTick(() => {
+    getData();
+  })
+}
+const setList = (_list) => {
+  nextTick(() => {
+    lists.value = _list;
+    emit("datas", lists.value)
+    nextTick(() => {
+      getHeight();
+    })
+  })
+}
+
+defineExpose({
+  handleRefresh,
+  setList,
+  getData,
+  scrolltolower
+})
+</script>
+
+<style lang="less" scoped>
+@import url('@/style.less');
+
+:deep(.u-list) {
+  height: 100% !important;
+}
+
+/deep/ .uni-scroll-view {
+  overflow: unset !important;
+}
+
+.null_warp {
+  .null_text {
+    min-height: 100rpx;
+    .flex_center();
+    font-size: 28rpx;
+    color: #333;
+  }
+}
+
+.load_more {
+  padding: 16rpx 0;
+}
+</style>

+ 248 - 0
components/list.vue

@@ -0,0 +1,248 @@
+<template>
+  <view>
+    <!-- @scrolltolower="scrolltolower" -->
+    <up-list style="height: auto" id="item_height" class="wrap_list">
+      <up-list-item v-for="(item, index) in lists" :key="index">
+        <slot name="item" :item="item" :index="index"></slot>
+      </up-list-item>
+    </up-list>
+    <view class="null_warp" v-if="isLoaded && !lists.length && !isLoading">
+      <slot name="null">
+        <view class="null_text">{{ t(nullText || "无数据") }}</view>
+      </slot>
+    </view>
+    <template v-if="(!!status && lists.length) || isLoading">
+      <view class="load_more">
+        <u-loadmore
+          :status="status"
+          :loading-text="t(loadingText)"
+          :loadmore-text="t(loadmoreText)"
+          :nomore-text="t(nomoreText)"
+        />
+      </view>
+    </template>
+  </view>
+</template>
+
+<script setup>
+import { query, $post, systemInfo } from "@/utils";
+import { ref, nextTick, computed } from "vue";
+import { t } from "@/locale";
+import { useCacheStore } from "@/store";
+
+const useCache = useCacheStore();
+const props = defineProps({
+  topHeight: {
+    type: Number,
+    default: 0,
+  },
+  url: {
+    type: String,
+    default: "",
+  },
+  pageSize: {
+    type: Number,
+    default: 10,
+  },
+  defaultParams: {
+    type: Object,
+    default: () => {},
+  },
+  nullText: String,
+  loadingText: {
+    type: String,
+    default: "正在加载中",
+  },
+  loadmoreText: {
+    type: String,
+    default: "加载更多",
+  },
+  nomoreText: {
+    type: String,
+    default: "没有更多了",
+  },
+  getIndex: {
+    type: Number,
+    default: 0,
+  },
+  activeIndex: {
+    type: Number,
+    default: 0,
+  },
+  isCache: Boolean,
+  isLoading: Boolean,
+});
+
+const emit = defineEmits(["datas"]);
+
+const lists = ref([]);
+const page = ref(1);
+const totals = ref(0);
+const status = ref("nomore");
+const noData = ref(false);
+const height = ref(0);
+const isLoaded = ref(false);
+
+const scrolltolower = () => {
+  if (!noData.value) {
+    let num = page.value;
+    num += 1;
+    page.value = num;
+    nextTick(() => {
+      getData(true);
+    });
+  }
+};
+const deleteSpace = (str) => {
+  return str.replace(/\s+/g, "");
+};
+const getData = async (flag = false) => {
+  let newFlag = flag;
+  const _list = useCache.getShopList(
+    props.defaultParams?.channel,
+    props.defaultParams?.keyWord
+  );
+
+  if (_list && props.isCache && !flag) {
+    let search_text =
+      props.defaultParams.keyWord && deleteSpace(props.defaultParams.keyWord);
+    const searchKey = `search_${search_text}`;
+    const { page: pageNum, children } = _list;
+    page.value = pageNum;
+    if (children[searchKey]) {
+      lists.value = children[searchKey];
+      emit("datas", children[searchKey]);
+      nextTick(() => {
+        getHeight();
+      });
+    } else {
+      newFlag = true;
+    }
+    isLoaded.value = true;
+    if (newFlag) {
+    } else {
+      return;
+    }
+  }
+  try {
+    status.value = "loading";
+    const {
+      data: {
+        data: { item: data, total_results: count },
+      },
+    } = await $post(
+      props.url,
+      {
+        pageSize: props.pageSize,
+        page: page.value,
+        ...props.defaultParams,
+      },
+      { isLoading: props.isLoading }
+    );
+    status.value = "nomore";
+    if (data.length >= count) {
+      noData.value = true;
+    } else {
+      noData.value = false;
+    }
+    totals.value = count - 0;
+    if (page.value > 1) {
+      const arrList = lists.value;
+      lists.value = [...arrList, ...data];
+      !props.defaultParams.img &&
+        useCache.setShopList(
+          props.defaultParams.channel,
+          page.value,
+          data,
+          props.defaultParams.keyWord
+        );
+      emit("datas", lists.value);
+      nextTick(() => {
+        getHeight();
+      });
+      return;
+    }
+    lists.value = data;
+    isLoaded.value = true;
+    !props.defaultParams.img &&
+      useCache.setShopList(
+        props.defaultParams.channel,
+        page.value,
+        data,
+        props.defaultParams.keyWord
+      );
+    emit("datas", lists.value);
+    nextTick(() => {
+      getHeight();
+    });
+  } catch (error) {
+    console.error(error, "getData");
+    isLoaded.value = true;
+  }
+};
+const getHeight = async (name = "#item_height") => {
+  const { height: heights } = await query(name, this);
+  nextTick(() => {
+    height.value = heights || 0;
+    const { windowHeight, statusBarHeight } = systemInfo();
+    let contHeight = windowHeight - 44 - props.topHeight;
+    if (height < contHeight) {
+      scrolltolower();
+    }
+  });
+  return height;
+};
+const handleRefresh = (flag = false) => {
+  page.value = 1;
+  status.value = "nomore";
+  noData.value = false;
+  isLoaded.value = false;
+  if (!flag) {
+    lists.value = [];
+  }
+  nextTick(() => {
+    getData(flag);
+  });
+};
+const setList = (_list) => {
+  nextTick(() => {
+    lists.value = _list;
+    emit("datas", lists.value);
+    nextTick(() => {
+      getHeight();
+    });
+  });
+};
+
+defineExpose({
+  handleRefresh,
+  setList,
+  getData,
+  scrolltolower,
+});
+</script>
+
+<style lang="less" scoped>
+@import url("@/style.less");
+
+:deep(.u-list) {
+  height: 100% !important;
+}
+
+/deep/ .uni-scroll-view {
+  overflow: unset !important;
+}
+
+.null_warp {
+  .null_text {
+    min-height: 100rpx;
+    .flex_center();
+    font-size: 28rpx;
+    color: #333;
+  }
+}
+
+.load_more {
+  padding: 16rpx 0;
+}
+</style>

+ 205 - 0
components/message/components/consultCard.vue

@@ -0,0 +1,205 @@
+<template>
+  <Theme>
+    <view
+      class="consult-card__wrap"
+      :style="{
+        background: props.background,
+        ...props.styles,
+      }"
+    >
+      <view class="consult-card__body">
+        <view class="consult-card__avatar">
+          <image src="@/static/chat/consult_avatar.png" mode="widthFix"></image>
+        </view>
+        <view class="consult-card__title">
+          <text>{{ $t("VAVABUY专属官方客服") }}</text>
+        </view>
+        <!-- <view class="consult-card__label" @click="showModal">
+          <text>{{ $t("付费咨询") }}?</text>
+          <text class="consult-card__label--underline"></text>
+        </view> -->
+      </view>
+      <view class="consult-card__bg">
+        <image src="@/static/chat/consult_bg_2.png" mode="widthFix"></image>
+      </view>
+    </view>
+
+    <Popup
+      ref="tipPopupRef"
+      mode="center"
+      class="consult_pay_tip_popup"
+      title="服务说明"
+    >
+      <template #content>
+        <view class="consult_pay_body">
+          <view
+            class="consult_pay_content"
+            v-html="$t('page.user_chat.tipPopupContentForPay')"
+          ></view>
+        </view>
+      </template>
+      <template #footer>
+        <view class="consult_pay_footer">
+          <view class="consult_pay_footer-btn" @click="onClose">{{
+            $t("取消")
+          }}</view>
+          <view
+            class="consult_pay_footer-btn consult_pay_footer-btn__confirm"
+            @click="onConfirm"
+            >{{ $t("支付") }}</view
+          >
+        </view>
+      </template>
+    </Popup>
+  </Theme>
+</template>
+
+<script setup>
+import { ref, inject } from "vue";
+import { storeToRefs } from "pinia";
+import { Modal } from "@/utils";
+import Popup from "@/components/popup.vue";
+import { useMessageStore } from "@/store";
+
+const props = defineProps({
+  background: {
+    type: String,
+    default: "transparent",
+  },
+  styles: {
+    type: Object,
+    default() {
+      return {};
+    },
+  },
+});
+
+// const channelID = inject("channel");
+const tipPopupRef = ref(null);
+
+function showModal() {
+  tipPopupRef.value && tipPopupRef.value.open();
+}
+
+function onClose() {
+  tipPopupRef.value && tipPopupRef.value.close();
+}
+
+function onConfirm() {
+  uni.navigateTo({
+    url: `/pages/shop/payment?type=service&oid=${channelID.value}`,
+  });
+  tipPopupRef.value && tipPopupRef.value.close();
+}
+</script>
+
+<style lang="less" scoped>
+.consult-card__wrap {
+  --top: 50rpx;
+  --top-up: -80rpx;
+}
+
+.consult-card__wrap {
+  padding-top: var(--top);
+  position: relative;
+  // background-color: transparent;
+}
+
+.consult-card__body {
+  width: 100%;
+  position: absolute;
+  top: 0;
+  left: 50%;
+  transform: translateX(-50%);
+  z-index: 1;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+
+  .consult-card__avatar {
+    overflow: hidden;
+    width: 120rpx;
+    height: 120rpx;
+    border-radius: 50%;
+    image {
+      width: 100%;
+      height: 100%;
+    }
+  }
+
+  .consult-card__title {
+    margin: 16rpx 0 8rpx;
+    // color: #FFE8D5;
+    font-size: 28rpx;
+    font-weight: 500;
+    background: linear-gradient(180deg, #ffe8d5 0%, #d7a16c 100%);
+    -webkit-background-clip: text;
+    background-clip: text;
+    -webkit-text-fill-color: transparent;
+    color: transparent;
+    text-align: center;
+  }
+
+  .consult-card__label {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    background: linear-gradient(180deg, #ffe8d5 0%, #d7a16c 100%);
+    -webkit-background-clip: text;
+    background-clip: text;
+    -webkit-text-fill-color: transparent;
+    color: transparent;
+    text-decoration: underline;
+    font-size: 24rpx;
+    font-weight: 500;
+
+    .consult-card__label--underline {
+      width: 100%;
+      height: 2rpx;
+      background: linear-gradient(180deg, #ffe8d5 0%, #d7a16c 100%);
+    }
+  }
+}
+
+.consult-card__bg {
+  overflow: hidden;
+  width: 100%;
+  height: auto;
+  border-radius: 20rpx;
+  image {
+    width: 100%;
+  }
+}
+
+.consult_pay_content {
+  text-indent: 2em;
+  // text-align: justify;
+  line-height: 1.4;
+}
+
+.consult_pay_footer {
+  display: flex;
+  justify-content: space-around;
+
+  .consult_pay_footer-btn {
+    padding: 12rpx 46rpx;
+    border: 1rpx solid #333;
+    border-radius: 12rpx;
+  }
+
+  .consult_pay_footer-btn__confirm {
+    background-color: var(--black);
+    color: var(--light);
+  }
+}
+</style>
+
+<style lang="less" scoped>
+.consult_pay_tip_popup :deep(.u-popup__content) {
+  width: 85%;
+}
+
+.consult_pay_tip_popup :deep(.pop .top) {
+  justify-content: center;
+}
+</style>

+ 77 - 0
components/message/components/purposeCard.vue

@@ -0,0 +1,77 @@
+<template>
+  <view class="question-card__wrap" @click.stop="toRecord">
+    <view class="question-card__head">
+      <view class="question-card__head-title">{{ datas.goods_name }}</view>
+    </view>
+    <view class="question-card__body">
+      <ImageGrid
+        :images="urlStrToArr(datas.goods_imgs)"
+        isSeeLarge
+        v-if="datas.goods_imgs"
+      />
+    </view>
+  </view>
+</template>
+
+<script setup>
+import ImageGrid from "@/components/ImageGrid";
+import { urlStrToArr } from "@/utils";
+
+const props = defineProps({
+  datas: {
+    type: Object,
+    default() {
+      return null;
+    },
+  },
+});
+
+const toRecord = () => {
+  uni.navigateTo({
+    url: `/pages/purpose/record`,
+  });
+};
+</script>
+
+<style lang="less" scoped>
+.question-card__wrap {
+  width: 100%;
+  height: auto;
+  padding: 16rpx 24rpx;
+  border-radius: 20rpx;
+  background: #fafafa;
+}
+
+.question-card__head {
+  width: 100%;
+  height: 44rpx;
+
+  .question-card__head-title {
+    font-size: 26rpx;
+    font-weight: 500;
+    color: #000;
+  }
+}
+
+.question-card__body {
+  display: flex;
+  flex-wrap: wrap;
+  margin-top: 8px;
+  gap: 20rpx;
+
+  .question-card__item {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    padding: 16rpx;
+    background-color: #fff;
+    border-radius: 12rpx;
+    border: 1rpx solid #999;
+  }
+
+  .question-card__item-content {
+    font-size: 26rpx;
+    color: #000;
+  }
+}
+</style>

+ 76 - 0
components/message/components/questionCard.vue

@@ -0,0 +1,76 @@
+<template>
+	<view class="question-card__wrap">
+		<view class="question-card__head">
+			<view class="question-card__head-title">{{ props.datas ? props.datas.title : '' }}</view>
+		</view>
+		<view class="question-card__body">
+			<template v-if="props.datas">
+				<view class="question-card__item" v-for="(item, index) in props.datas.lists" :key="index" @click="onQuestionSend(item)">
+					<view class="question-card__item-content">
+						{{ item }}
+					</view>
+				</view>
+			</template>
+		</view>
+	</view>
+</template>
+
+<script setup>
+import { inject } from 'vue'
+
+const props = defineProps({
+	datas: {
+		type: Object,
+		default() {
+			return null
+		}
+	}
+})
+
+const onQuestionSend = inject('onQuestionSend');
+
+</script>
+
+<style lang="less" scoped>
+.question-card__wrap {
+	width: 100%;
+	height: auto;
+	padding: 16rpx 24rpx;
+	border-radius: 20rpx;
+	background: #FAFAFA;
+}
+
+.question-card__head {
+	width: 100%;
+	height: 44rpx;
+	
+	.question-card__head-title {
+		font-size: 26rpx;
+		font-weight: 500;
+		color: #000;
+	}
+}
+
+.question-card__body {
+	display: flex;
+	flex-wrap: wrap;
+	margin-top: 8px;
+	gap: 20rpx;
+	
+	.question-card__item {
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		padding: 16rpx;
+		background-color: #fff;
+		border-radius: 12rpx;
+		border: 1rpx solid #999;
+	}
+	
+	
+	.question-card__item-content {
+		font-size: 26rpx;
+		color: #000;
+	}
+}
+</style>

+ 76 - 0
components/message/components/tipsListCard.vue

@@ -0,0 +1,76 @@
+<template>
+	<view class="question-card__wrap">
+		<view class="question-card__head">
+			<view class="question-card__head-title">{{ props.datas ? props.datas.title : '' }}</view>
+		</view>
+		<view class="question-card__body">
+			<view class="question-card__item" v-for="(content, index) in props.datas.lists" :key="index">
+				<view class="question-card__item-left">
+					<text class="question-card__item-content">{{index + 1}}. {{ content }}</text>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script setup>
+
+const props = defineProps({
+	datas: {
+		type: Object,
+		default() {
+			return null
+		}
+	}
+})
+</script>
+
+<style lang="less" scoped>
+.question-card__wrap {
+	width: 100%;
+	height: auto;
+	padding: 16rpx 30rpx;
+	border-radius: 20rpx;
+	background: #FAFAFA;
+}
+
+.question-card__head {
+	width: 100%;
+	height: 44rpx;
+	
+	.question-card__head-title {
+		font-size: 26rpx;
+		font-weight: 500;
+		color: #000;
+	}
+}
+
+.question-card__body {
+	margin-top: 4px;
+	
+	.question-card__item {
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
+		padding: 3px 0;
+	}
+	
+	.question-card__item-left {
+		width: calc(100% - 0rpx);
+		font-size: 28rpx;
+		color: #3D3D3D;
+		// padding-right: 30rpx;
+		white-space: nowrap;
+		overflow: hidden;
+		text-overflow: ellipsis;
+	}
+	
+	.question-card__item-content {
+		width: 100%;
+		text-align: justify;
+		/* white-space: nowrap;
+		overflow: hidden;
+		text-overflow: ellipsis; */
+	}
+}
+</style>

+ 36 - 0
components/message/hooks/useTools.js

@@ -0,0 +1,36 @@
+import { format } from '@/utils';
+
+function useTool() {
+	
+	// 处理消息时间显示
+	function handleTime(index, list) {
+		//第一条消息展示 && 两条消息的间隔时间超过10分钟则显示
+		const { indate } = list[index]
+		
+		if (index >= 1) {					
+			const { indate: old_indate } = list[index - 1]
+			if((Number(indate) - Number(old_indate)) >= 10 * 60){
+				return handleBetterTimeShow(Number(indate * 1000))
+			}
+		}
+		else {
+			return handleBetterTimeShow(Number(indate * 1000))
+		}
+	}
+	// 处理时间显示格式
+	function handleBetterTimeShow(value) {
+		// 今天的消息显示hh:mm 其余的显示yyyy-MM-dd hh:mm
+		if(format(new Date(value), 'yyyy-MM-dd') === format(new Date(), 'yyyy-MM-dd')){
+			return format(new Date(value), 'HH:mm')
+		}
+		return format(new Date(value), 'yyyy-MM-dd HH:mm')
+	}
+	
+	
+	return {
+		handleTime
+	}
+}
+
+
+export default useTool

+ 216 - 0
components/message/index.vue

@@ -0,0 +1,216 @@
+<template>
+  <view class="message_list">
+    <template v-for="(item, i) in newList" :key="i">
+      <!-- 时间 -->
+      <view class="message__item message_item__tips" v-if="handleTime(i, list)">
+        <view class="message__item-time">
+          <text>{{ handleTime(i, list) }}</text>
+        </view>
+      </view>
+      <!-- 系统关闭提示信息 -->
+      <view
+        class="message__item message_item__tips"
+        v-if="item.msg.type == 'service_close'"
+      >
+        <view class="message__item-time">
+          <text>{{ $t("会话已关闭") }}</text>
+        </view>
+      </view>
+      <view
+        class="message__item message_item__tips"
+        v-else-if="item.msg.type == 'service_start'"
+      >
+        <TipsListCard :datas="item.msg.data"></TipsListCard>
+      </view>
+      <view
+        class="message__item message_item__tips"
+        v-else-if="item.msg.type == 'notice_start'"
+      >
+        <QuestionCard :datas="item.msg.data"></QuestionCard>
+      </view>
+      <!-- 意向商品 -->
+      <!-- <view v-else-if="item.msg.type == 'need'">
+        <PurposeCard :datas="item.msg.data"></PurposeCard>
+      </view> -->
+      <view
+        class="message__item"
+        :class="[item.send > 0 ? 'message__item-self' : '']"
+        v-else
+      >
+        <!-- 头像 -->
+        <view class="message__item-left">
+          <image
+            v-if="item.send > 0"
+            class="message__item-avatar"
+            :src="item.uimg || getuserInfo.userimg"
+            mode=""
+          >
+          </image>
+          <image
+            v-else
+            class="message__item-avatar"
+            :src="item.simg"
+            mode=""
+          ></image>
+        </view>
+        <!-- 内容 -->
+        <!-- 意向商品 -->
+        <view v-if="item.msg.type == 'need'" class="purpose__item-right">
+          <PurposeCard :datas="item.msg.data"></PurposeCard>
+        </view>
+        <view class="message__item-right" v-else>
+          <!-- 图片 -->
+          <view v-if="item.msg.type == 'image'">
+            <up-image
+              :show-loading="true"
+              :src="item.msg.url"
+              width="240rpx"
+              height="240rpx"
+              :fade="false"
+              @click="previewImage(1, [item.msg.url])"
+            ></up-image>
+          </view>
+
+          <!-- 欢迎信息 -->
+          <view
+            style="padding: 20rpx 30rpx"
+            v-else-if="item.msg.type == 'service_welcome'"
+          >
+            <text>{{ item.msg.body }}</text>
+          </view>
+          <!-- 文本 -->
+          <view style="padding: 20rpx 30rpx" v-else>
+            <text>{{ item.msg.text || "" }}</text>
+          </view>
+        </view>
+
+        <view class="message__item-status">
+          <up-loading-icon
+            mode="circle"
+            size="40rpx"
+            v-if="item.loading"
+          ></up-loading-icon>
+        </view>
+      </view>
+    </template>
+  </view>
+</template>
+
+<script setup>
+import { computed } from "vue";
+import TipsListCard from "./components/tipsListCard.vue";
+import QuestionCard from "./components/questionCard.vue";
+import PurposeCard from "./components/purposeCard.vue";
+import useTools from "./hooks/useTools";
+import { storeToRefs } from "pinia";
+import { useUserStore } from "@/store";
+const useUser = useUserStore();
+const { getuserInfo } = storeToRefs(useUser);
+
+const { handleTime } = useTools();
+const props = defineProps({
+  list: {
+    type: Array,
+    default: () => [],
+  },
+});
+const newList = computed(() =>
+  parseMessageJSON(props.list).sort((a, b) => a.id - b.id)
+);
+function parseMessageJSON(messages) {
+  return messages.map((message) => {
+    try {
+      const parsedMessage = { ...message };
+      if (typeof parsedMessage.msg === "string") {
+        parsedMessage.msg = JSON.parse(parsedMessage.msg);
+      }
+      return parsedMessage;
+    } catch (error) {
+      return message;
+    }
+  });
+}
+
+function previewImage(index, urls) {
+  uni.previewImage({
+    current: index,
+    urls: urls,
+    success() {},
+  });
+}
+</script>
+
+<style lang="less" scoped>
+@import url("@/style.less");
+
+.message_list {
+  margin-top: 30rpx;
+  padding: 20rpx 30rpx 30rpx;
+
+  .message__item {
+    width: 100%;
+    display: flex;
+    align-items: flex-start;
+    margin-bottom: 30rpx;
+  }
+
+  .message__item-self {
+    display: flex;
+    flex-direction: row-reverse;
+
+    .message__item-right {
+      margin-left: 0;
+      margin-right: 16rpx;
+      background-color: var(--black);
+      color: #fff;
+    }
+
+    .message__item-status {
+      margin-left: 0;
+      margin-right: 12rpx;
+    }
+  }
+
+  .message_item__tips {
+    justify-content: center;
+    margin-bottom: 24rpx;
+    font-size: 24rpx;
+    color: #767676;
+  }
+
+  .message__item-avatar {
+    width: 80rpx;
+    height: 80rpx;
+    border-radius: 50%;
+  }
+
+  .message__item-right {
+    overflow: hidden;
+    max-width: calc(100% - (80rpx * 2) - 16rpx - 20rpx - 40rpx - 12rpx);
+    margin-left: 16rpx;
+    border-radius: 20rpx;
+    background: #fafafa;
+    // text-align: justify;
+    // word-break: break-all;
+    word-wrap: break-word;
+    color: #3d3d3d;
+    font-size: 28rpx;
+  }
+
+  .message__item-status {
+    width: 40rpx;
+    height: 40rpx;
+    margin-left: 12rpx;
+  }
+  .purpose__item-right {
+    overflow: hidden;
+    width: 100%;
+    margin-right: 16rpx;
+    border-radius: 20rpx;
+    background: #fafafa;
+    word-wrap: break-word;
+    color: #3d3d3d;
+    font-size: 28rpx;
+  }
+}
+</style>

+ 256 - 0
components/nav_filter.vue

@@ -0,0 +1,256 @@
+<template>
+  <view class="menu">
+    <view class="menu_item">
+      <i class="icon-font icon-filter_2" @click.stop="open"></i>
+      <popup ref="popupRef" :title="title" isClose>
+        <template #content>
+          <view class="cont">
+            <view class="filter_item">
+              <view class="filter_item_label">
+                <trans _t="创建时间" />
+              </view>
+              <view class="filter_time">
+                <uni-datetime-picker v-model="params.begin" :border="false" :end="params.end" type="date"
+                  @change="beginChange">
+                  <view class="date_time">
+                    <view class="time_left">
+                      <up-icon name="calendar" color="#a8abb2" size="14" />
+                      <trans class="time_text" _t="开始日期" v-if="!params.begin" />
+                      <text class="time_text" v-else>{{ params.begin }}</text>
+                    </view>
+                    <view class="icons" v-if="params.begin" @click.stop="clear('begin')">
+                      <up-icon name="close-circle" color="#a8abb2" />
+                    </view>
+                  </view>
+                </uni-datetime-picker>
+                <view class="time_splice">—</view>
+                <uni-datetime-picker v-model="params.end" type="date" :border="false" @change="endChange"
+                  :start="params.begin">
+                  <view class="date_time">
+                    <view class="time_left">
+                      <up-icon name="calendar" color="#a8abb2" size="14"></up-icon>
+                      <trans class="time_text" _t="结束日期" v-if="!params.end" />
+                      <text class="time_text" v-else>{{ params.end }}</text>
+                    </view>
+                    <view class="icons" v-if="params.end" @click.stop="clear('end')">
+                      <up-icon name="close-circle" color="#a8abb2" />
+                    </view>
+                  </view>
+                </uni-datetime-picker>
+              </view>
+            </view>
+            <template v-if="!isOrderTime">
+              <view class="filter_item">
+                <view class="filter_item_label">
+                  <trans _t="订单时间" />
+                </view>
+              </view>
+              <view class="filter_status">
+                <view class="status_item"
+                  :class="[(index == orderStatus.length - 1) && (orderStatus.length % 2 != 0) ? 'is-block' : '', active == index ? 'active' : '']"
+                  v-for="item, index in orderStatus" :key="index" @click="statusClick(item, index)">
+                  {{ item.value }}
+                </view>
+              </view>
+            </template>
+          </view>
+        </template>
+        <template #footer>
+          <view class="footer_btn">
+            <view class="btn" @click="reset">
+              <trans _t="重置" />
+            </view>
+            <view class="btn btn_search" @click="submit">
+              <trans _t="搜索" />
+            </view>
+          </view>
+        </template>
+      </popup>
+    </view>
+  </view>
+</template>
+<script setup>
+import { ref, reactive, computed } from "vue"
+import popup from "@/components/popup";
+import { useShopStore } from "@/store";
+
+const useShop = useShopStore();
+
+const props = defineProps({
+  title: {
+    type: String,
+    default: '筛选'
+  },
+  isOrderTime: Boolean
+})
+const emit = defineEmits(['submit'])
+
+const popupRef = ref(null);
+const active = ref(-1)
+const orderStatus = computed(() => useShop.getOrderStatus)
+useShop.setOrderStatus();
+
+const params = reactive({
+  begin: '',
+  end: '',
+  status: ''
+})
+
+const open = () => {
+  popupRef.value && popupRef.value.open();
+}
+const close = () => {
+  popupRef.value && popupRef.value.close();
+}
+
+const statusClick = (item, index) => {
+  params.status = item.status;
+  if (active.value == index) return active.value = -1;
+  active.value = index;
+}
+
+const beginChange = (time) => {
+  // console.log(time);
+}
+const endChange = (time) => { }
+
+const clear = (value) => {
+  params[value] = ''
+}
+
+const reset = () => {
+  params.begin = ''
+  params.end = ''
+  params.status = ''
+  active.value = -1;
+  emit('submit', params);
+  close();
+}
+const submit = () => {
+  emit('submit', params);
+  close();
+}
+defineExpose({
+  close
+})
+</script>
+<style lang="less" scoped>
+.menu {
+  &_item {
+    .icon-filter_2 {
+      font-size: 24px;
+      color: var(--text);
+      padding-right: 8px;
+    }
+
+    .cont {
+      width: 100%;
+
+      .filter_item {
+        .filter_item_label {
+          color: var(--text-01);
+          font-size: 28rpx;
+          margin-bottom: 24rpx;
+        }
+
+        .filter_time {
+          display: flex;
+          align-items: center;
+          margin-bottom: 24rpx;
+
+          /deep/ .uni-calendar-item--checked {
+            background-color: var(--black);
+          }
+
+          /deep/ .uni-datetime-picker--btn {
+            background-color: var(--black);
+            border-radius: 16rpx;
+            font-size: 28rpx;
+          }
+
+          .date_time {
+            box-shadow: 0 0 0 1px #dcdfe6 inset;
+            display: flex;
+            height: 42px;
+            align-items: center;
+            background-color: #f5f6f7;
+            padding: 0 11px;
+            border-radius: 8px;
+            justify-content: space-between;
+
+            .time_left {
+              display: flex;
+              align-items: center;
+            }
+
+            .time_text {
+              margin-left: 8px;
+              font-size: 26rpx;
+              color: #aeaeae;
+            }
+          }
+
+          .time_splice {
+            color: var(--text);
+            font-size: 28rpx;
+            padding: 0 24rpx;
+          }
+        }
+      }
+
+      .filter_status {
+        display: flex;
+        gap: 24rpx;
+        flex-wrap: wrap;
+
+        .status_item {
+          width: calc((100% - 24rpx) / 2);
+          font-size: 24rpx;
+          font-weight: 400;
+          height: 72rpx;
+          padding: 16rpx 30rpx;
+          border-radius: 16rpx;
+          border: 1px solid #dcdfe6;
+          background-color: var(--light);
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          color: var(--text-02);
+        }
+
+        .is-block {
+          width: 100%;
+        }
+
+        .active {
+          color: var(--light);
+          background-color: var(--black);
+        }
+      }
+    }
+
+    .footer_btn {
+      display: flex;
+      column-gap: 24rpx;
+
+      .btn {
+        flex: 1;
+        height: 76rpx;
+        padding: 16rpx 30rpx;
+        color: var(--black);
+        border: 1px solid var(--black);
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        border-radius: 16rpx;
+        font-size: 24rpx;
+      }
+
+      .btn_search {
+        background-color: var(--black);
+        color: var(--light);
+      }
+    }
+  }
+}
+</style>

+ 119 - 0
components/nav_menu.vue

@@ -0,0 +1,119 @@
+<template>
+  <view class="menu">
+    <view class="menu_item">
+      <popOver
+        placement="bottom-end"
+        :options="optionsList"
+        key-name="text"
+        ref="popoverRef"
+        @select="selectItem"
+      >
+        <!-- <i class="icon-font icon-menu"></i> -->
+        <view class="icon_menu">
+          <image src="../static/more.png" class="img" v-if="!blacked"></image>
+          <image src="../static/more_light.png" class="img" v-else></image>
+        </view>
+      </popOver>
+    </view>
+  </view>
+</template>
+<script setup>
+import { ref } from "vue";
+import popOver from "@/components/popover";
+import { useTabbarStore, useSystemStore } from "@/store";
+
+const useTabbar = useTabbarStore();
+const useSystem = useSystemStore();
+
+const props = defineProps({
+  options: {
+    type: Object,
+    default: () => ({}),
+  },
+  page: {
+    type: String,
+    default: "",
+  },
+  blacked: Boolean,
+});
+const arr = [
+  {
+    icon: "icon-order",
+    text: "订单",
+  },
+  {
+    icon: "icon-Warehouse",
+    text: "仓库",
+  },
+  {
+    icon: "icon-parcel",
+    text: "包裹",
+  },
+  {
+    icon: "icon-Wallet",
+    text: "钱包",
+  },
+  {
+    icon: "icon-service",
+    text: "在线客服",
+  },
+];
+const optionsList = ref(
+  Object.keys(props.options).length ? [props.options, ...arr] : arr
+);
+
+const selectItem = (item) => {
+  if (item.text == "主页") {
+    uni.switchTab({ url: "/pages/index/index" });
+    useTabbar.getPageCur("index");
+    return;
+  }
+  switch (item.icon) {
+    case "icon-order":
+      if (props.page == "order") {
+      } else {
+        uni.switchTab({ url: "/pages/order/index" });
+        useTabbar.getPageCur("order");
+      }
+      break;
+    case "icon-Wallet":
+      if (props.page == "wallet") {
+      } else {
+        uni.navigateTo({ url: "/pages/bank/wallet" });
+      }
+      break;
+    case "icon-Warehouse":
+      if (props.page == "warehouse") {
+      } else {
+        uni.navigateTo({ url: "/pages/dashboard/warehouse" });
+      }
+      break;
+    case "icon-parcel":
+      if (props.page == "parcel") {
+      } else {
+        uni.navigateTo({ url: "/pages/dashboard/parcel" });
+      }
+      break;
+    case "icon-service":
+      uni.navigateTo({ url: "/pages/setting/system" });
+      break;
+    default:
+      break;
+  }
+};
+</script>
+<style lang="less" scoped>
+.menu {
+  &_item {
+    .icon_menu {
+      width: 50rpx;
+      height: 50rpx;
+
+      .img {
+        width: inherit;
+        height: inherit;
+      }
+    }
+  }
+}
+</style>

+ 147 - 0
components/navbar.vue

@@ -0,0 +1,147 @@
+<template>
+  <view class="navbar__container">
+    <Theme>
+      <up-navbar
+        placeholder
+        :border="border"
+        :fixed="fixed"
+        :bgColor="bgColor"
+        :height="height"
+        :style="{ '--borderColor': borderColor }"
+        @leftClick="handleLeftClick"
+        @rightClick="handleRightClick"
+        v-if="!navShow"
+      >
+        <template #left>
+          <slot name="left">
+            <view class="left">
+              <u-icon
+                :size="iconSize"
+                :color="leftIconColor"
+                :name="!leftShow ? 'arrow-left' : leftIcon"
+              ></u-icon>
+              <view class="left_text" :style="leftStyle" v-if="!!leftText">{{
+                t(leftText)
+              }}</view>
+            </view>
+          </slot>
+        </template>
+        <template #center>
+          <slot name="center">
+            <trans
+              class="nav_title"
+              :style="navStyle"
+              v-if="!!title"
+              :_t="title"
+            />
+          </slot>
+        </template>
+        <template #right>
+          <slot name="right"></slot>
+        </template>
+      </up-navbar>
+    </Theme>
+  </view>
+</template>
+
+<script setup>
+import { t } from "@/locale";
+const props = defineProps({
+  autoBack: Boolean,
+  fixed: Boolean,
+  leftText: {
+    type: [String, Number],
+    default: "",
+  },
+  bgColor: {
+    type: String,
+    default: "var(--light)",
+  },
+  iconSize: {
+    type: Number,
+    default: 20,
+  },
+  leftIconColor: {
+    type: String,
+    default: "var(--text)",
+  },
+  title: {
+    type: String,
+    default: "",
+  },
+  leftIcon: {
+    type: String,
+    default: "",
+  },
+  leftShow: Boolean,
+  border: Boolean,
+  height: {
+    type: String,
+    default: "44px",
+  },
+  leftStyle: {
+    type: Object,
+    default: () => ({}),
+  },
+  navStyle: {
+    type: Object,
+    default: () => ({}),
+  },
+  borderColor: {
+    type: String,
+    default: "var(--bor-color)",
+  },
+  navShow: Boolean,
+});
+const emit = defineEmits(["leftClick", "rightClick"]);
+
+const handleLeftClick = () => {
+  if (props.autoBack) return emit("leftClick");
+  if (props.leftShow) return;
+  uni.navigateBack();
+};
+const handleRightClick = () => {
+  if (props.leftShow) return;
+  emit("rightClick");
+};
+</script>
+
+<style lang="less" scoped>
+@import url("../style.less");
+
+.navbar__container {
+  max-width: 1536rpx;
+}
+
+.left {
+  .flex_position(center, flex-end);
+
+  /deep/ .u-icon--right {
+    .u-icon__icon {
+      font-weight: 700 !important;
+    }
+  }
+
+  .left_text {
+    .size(15px);
+    color: var(--text);
+    margin-left: 3px;
+  }
+}
+
+.nav_title {
+  width: 12.5rem;
+  .size(14px);
+  color: var(--text);
+  text-align: center;
+  font-weight: 700;
+}
+
+/deep/ .u-border-bottom {
+  border-color: var(--bor-color) !important;
+}
+
+/deep/ .u-navbar--fixed {
+  z-index: 1000;
+}
+</style>

+ 79 - 0
components/passwordModal.vue

@@ -0,0 +1,79 @@
+<template>
+  <Popup isClose ref="popRef">
+    <template #content>
+      <Input type="number" :placeholder="t(placeholder)" :maxlength="maxlength" border="surround" @focus="handleInput"
+        v-model="password" />
+    </template>
+    <template #footer>
+      <view class="submit_btn" @click="submit">
+        <trans _t="确认" />
+      </view>
+    </template>
+  </Popup>
+</template>
+
+<script setup>
+import { ref } from 'vue'
+import { useVibrate } from '@/utils'
+import Popup from './popup.vue';
+import Input from "./input";
+
+import { t } from "@/locale"
+
+const popRef = ref(null);
+const { vibrate } = useVibrate()
+
+const props = defineProps({
+  placeholder: { type: String, default: '请输入支付密码' },
+  maxlength: { type: Number, default: 6 },
+  errorMsg: { type: String, default: '密码错误,请重新输入' }
+})
+
+const emit = defineEmits(['complete', 'close'])
+const password = ref('')
+const showError = ref(false)
+
+const open = () => {
+  reset()
+  popRef.value && popRef.value.open()
+}
+
+const close = () => {
+  emit('close')
+  popRef.value && popRef.value.close()
+}
+
+// 处理输入
+const handleInput = (num) => {
+  if (password.value.length >= props.maxlength) return
+  vibrate()
+  password.value += num
+}
+
+const submit = () => {
+  if (password.value.length === props.maxlength) {
+    emit('complete', password.value)
+  }
+}
+
+// 重置输入
+const reset = () => {
+  password.value = ''
+}
+
+defineExpose({ open, close, reset })
+</script>
+
+<style lang="less" scoped>
+@import url('@/style.less');
+
+.submit_btn {
+  height: 38px;
+  padding: 16rpx 30rpx;
+  background-color: var(--black);
+  color: var(--light);
+  .flex_center();
+  border-radius: 16rpx;
+  .size(24rpx);
+}
+</style>

+ 110 - 0
components/paymentModal/applePay.vue

@@ -0,0 +1,110 @@
+<template>
+  <Popup isClose ref="popRef">
+    <template #content>
+      <view class="apple-pay__box">
+        <view id="apple_pay_card"></view>
+      </view>
+    </template>
+  </Popup>
+  <GlobalLoading :msg="loadingStatus" />
+</template>
+
+
+<script setup>
+import { t } from '@/locale';
+import { ref, reactive, nextTick } from "vue";
+import Popup from '@/components/popup.vue';
+import GlobalLoading from '@/components/GlobalLoading'
+import { Toast } from "@/utils"
+import { useAppleInfo } from './hooks'
+
+
+const popRef = ref(null);
+
+// props
+const props = defineProps({
+  paramsObj: { type: Object }
+})
+// emits
+const emit = defineEmits(['on-open', 'on-close', 'on-success', 'on-error']);
+
+const loadingStatus = reactive({ show: false });
+const { appleInstance, init, unmountCard, fetchCardPaymentInfo } = useAppleInfo();
+
+
+// 打开回调
+const open = () => {
+  emit('on-open');
+  popRef.value && popRef.value.open();
+  nextTick(() => {
+    fetchCardPaymentInfo(props.paramsObj, bindEventListener);
+  })
+}
+
+// 关闭回调
+const close = () => {
+  emit('on-close')
+  unmountCard()
+  popRef.value && popRef.value.close()
+}
+
+
+// 事件绑定
+function bindEventListener() {
+  if (!appleInstance.value) return;
+  appleInstance.value.on('success', onPaymentSuccess);
+  appleInstance.value.on('error', onPaymentError);
+  appleInstance.value.on('ready', onPaymentReady);
+}
+
+// 加载完成
+const onPaymentReady = (event) => {
+  console.log('----- apple payment ready -----', event)
+}
+// 成功回调
+const onPaymentSuccess = (event) => {
+  console.log('----- apple payment success -----', event)
+  return
+  emit('on-success');
+}
+// 失败回调
+const onPaymentError = (event) => {
+  console.log('----- apple payment error -----', event)
+  Toast(event.detail.error.message || event.detail.error || t("pay_fail_msg", {}) || "fail!");
+}
+
+defineExpose({
+  open,
+  close
+})
+</script>
+
+
+<style lang="less" scoped>
+@import url('@/style.less');
+
+.apple-pay__box {
+  width: 100%;
+  height: 25vh;
+
+  #apple_pay_card {
+    display: flex;
+    align-items: center;
+    padding: 12rpx;
+    width: 100%;
+    height: 44px;
+    /* border: 1px solid #ccc;
+    border-radius: 14rpx; */
+  }
+}
+
+.submit_btn {
+  height: 38px;
+  padding: 16rpx 30rpx;
+  background-color: var(--black);
+  color: var(--light);
+  .flex_center();
+  border-radius: 16rpx;
+  .size(24rpx);
+}
+</style>

+ 190 - 0
components/paymentModal/cardPayment_app.vue

@@ -0,0 +1,190 @@
+<template>
+  <view class="wallet_app" v-if="show">
+    <view class="wallet_footer" :style="{ 'height': footerHeight + 48 + 'px' }">
+      <view class="close">
+        <view class="close_icon" @click.stop="close">
+          <uni-icons type="closeempty" size="28" color="var(--text-01)"></uni-icons>
+        </view>
+      </view>
+    </view>
+		
+		<!-- <GlobalLoading :msg="loadingStatus"></GlobalLoading> -->
+  </view>
+</template>
+
+<script>
+import GlobalLoading from '@/components/GlobalLoading.vue'
+import { systemInfo, Toast } from "@/utils"
+import { SHOP_SUBMIT_PAY } from '@/api'
+import { getLan } from "@/locale"
+
+
+export default {
+	comments: {
+		GlobalLoading
+	},
+	
+  props: {
+    paramsObj: { type: Object }
+  },
+	emits: ['on-confirm', 'on-open', 'on-close', 'on-success', 'on-error'],
+  data() {
+    return {
+      webview: null,
+      show: false,
+      footerHeight: 0,
+			loadingStatus: { show: false }
+    }
+  },
+  methods: {
+    open(data) {
+      this.show = true;
+      this.fetchPaymentInfo(data);
+      // this.initWebViewBelowElement();
+    },
+    close() {
+      this.webview.close();
+      this.webview = null;
+      this.show = false;
+			uni.hideKeyboard();
+			this.$emit('on-close');
+    },
+		
+    getRequest(url) {
+      let theRequest = new Object();
+      let index = url.indexOf("?");
+      if (index != -1) {
+        let str = url.substring(index + 1);
+        let strs = str.split("&");
+        for (let i = 0; i < strs.length; i++) {
+          theRequest[strs[i].split("=")[0]] = unescape(strs[i].split("=")[1]);
+        }
+      }
+      return theRequest;
+    },
+    
+		async initWebViewBelowElement(eventData) {
+      const res = await systemInfo();
+      try {
+        let wvPath = '/static/hybrid/html/card.html';
+        let wv = plus.webview.create("", wvPath, {
+          'uni-app': 'none',
+          position: 'fixed',
+          background: 'transparent',
+          left: '24px',
+          right: '24px',
+          top: this.footerHeight - 24 + 28 + 'px',
+          overflowY: 'auto',
+        });
+        wv.loadURL(wvPath);
+        wv.overrideUrlLoading({ mode: 'reject' }, (e) => {
+          let { str } = this.getRequest(e.url);
+          str = unescape(str)
+          return this.handleBack(str)
+        });
+				/* wv.evalJS(`
+				window.dispatchEvent(new CustomEvent('appMessage', 
+				{ detail: ${JSON.stringify({ type: 'lan', lan:getLan() })} }))`); */
+        wv.evalJS(`
+        window.dispatchEvent(new CustomEvent('appMessage', 
+        { detail: ${JSON.stringify({ ...eventData, lan: getLan() })} }))`);
+        this.$root.$scope.$getAppWebview().append(wv);
+        this.webview = wv;
+      } catch (error) {
+        console.error(error);
+      }
+    },
+		
+    async fetchPaymentInfo(data) {
+			this.loadingStatus.show = true
+      let obj = data
+      try {
+        const res = await SHOP_SUBMIT_PAY({
+          payType: 'airwallex',
+          ...obj
+        })
+        const { id, client_secret } = res.data;
+        let params = {}
+        params.intent_id = id;
+        params.client_secret = client_secret;
+        this.initWebViewBelowElement({ type: 'pay', ...params })
+      } catch (error) {
+        console.error(error);
+      } finally {
+				this.loadingStatus.show = false
+			}
+    },
+    
+		handleBack(str) {
+			const { status, res } = JSON.parse(str);
+      switch (status) {
+        case 'success':
+          console.log('成功参数', JSON.stringify(res));
+					if (res.status == "SUCCEEDED" || res.status == "succeeded") {
+						this.$emit('on-success', res)
+					}
+					else {
+						Toast(res.status)
+					}
+          break;
+				case 'error':
+					console.log('----- 提交失败 ----- ', JSON.stringify(res))
+					Toast(res.message)
+					break;
+				case 'loading':
+					let s = res.state == true || res.state == 'true' ? true : false
+					this.loadingStatus.show = s
+					if (s) {
+						uni.showLoading({
+							title: '',
+							mask: true
+						})
+					}
+					else {
+						uni.hideLoading();
+					}
+					break;
+        default:
+          break;
+      }
+    }
+  },
+	
+  async mounted() {
+    const res = await systemInfo();
+    this.footerHeight = res.windowHeight / 2;
+    const _this = this;
+    uni.onKeyboardHeightChange(res => {
+      _this.webview.setStyle({
+        top: _this.footerHeight - 24 + 28 - res.height + 'px'
+      })
+    })
+  }
+}
+</script>
+<style lang="less" scoped>
+.wallet_app {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  z-index: 9999999;
+  background-color: rgba(0, 0, 0, .5);
+  display: flex;
+  align-items: flex-end;
+
+  .wallet_footer {
+    width: 100%;
+    background-color: #fff;
+    padding: 24px;
+    border-radius: 10px 10px 0 0;
+
+    .close {
+      height: 28px;
+      display: flex;
+      justify-content: flex-end;
+    }
+  }
+}
+</style>

+ 83 - 0
components/paymentModal/dropInPay.vue

@@ -0,0 +1,83 @@
+<template>
+  <view class="drop-in-payment__container">
+    <view id="dropIn"></view>
+  </view>
+</template>
+
+
+<script setup>
+import { t } from '@/locale';
+import { ref, reactive, nextTick } from "vue";
+import { Toast } from "@/utils"
+import { useDropInPayInfo } from './hooks'
+
+
+// props
+const props = defineProps({
+  oid: { type: String, default: '' }
+})
+// emits
+const emit = defineEmits(['open', 'close', 'success', 'error']);
+
+const {
+		dropInElement,
+		handleInit,
+		handleUnmount,
+		fetchPaymentInitData } = useDropInPayInfo();
+		
+
+const onMount = () => {
+	nextTick(() => {
+		// testDemo()
+	})
+  fetchPaymentInitData({ oid: props.oid }, bindEventListener);
+}
+
+
+const onDestroy = () => {
+  handleUnmount()
+}
+
+
+// 事件绑定
+function bindEventListener() {
+	if (!dropInElement.value) return;
+	dropInElement.value.on('success', onSuccess);
+	dropInElement.value.on('error', onError);
+	dropInElement.value.on('ready', onReady);
+}
+
+
+const onReady = (event) => {
+	console.log('----- drop-in payment ready -----', event)
+}
+
+// 成功回调
+const onSuccess = (event) => {
+	console.log('----- drop-in payment success -----', event)
+}
+
+// 失败回调
+const onError = (event) => {
+	console.log('----- drop-in payment error -----', event)
+	Toast(event.detail.error.message || event.detail.error || t("pay_fail_msg", {}) || "fail!");
+}
+
+
+
+defineExpose({
+  onMount,
+  onDestroy
+})
+
+</script>
+
+
+<style lang="less" scoped>
+@import url('@/style.less');
+
+/* #dropIn {
+  width: 100%,
+  margin: 10rpx auto,
+} */
+</style>

+ 107 - 0
components/paymentModal/googlePay.vue

@@ -0,0 +1,107 @@
+<template>
+  <Popup isClose ref="popRef">
+    <template #content>
+      <view class="payment-card__box">
+        <view id="google_pay_card"></view>
+        <view id="error-info" :style="{ color: 'red' }"></view>
+      </view>
+    </template>
+  </Popup>
+  <GlobalLoading :msg="loadingStatus" />
+</template>
+
+
+<script setup>
+import { t } from '@/locale';
+import { ref, reactive, nextTick } from "vue";
+import Popup from '@/components/popup.vue';
+import GlobalLoading from '@/components/GlobalLoading'
+import { Toast } from "@/utils"
+import { useGoogleInfo } from './hooks'
+
+const popRef = ref(null);
+
+// props
+const props = defineProps({
+  paramsObj: { type: Object }
+})
+// emits
+const emit = defineEmits(['open', 'close', 'success', 'error']);
+
+const loadingStatus = reactive({ show: false });
+const { googleInstance, init, unmountCard, fetchCardPaymentInfo } = useGoogleInfo();
+
+
+// 打开回调
+const open = () => {
+  emit('open');
+  popRef.value && popRef.value.open();
+  nextTick(() => {
+    fetchCardPaymentInfo(props.paramsObj, bindEventListener);
+  })
+}
+
+// 关闭回调
+const close = () => {
+  emit('close')
+  unmountCard()
+  popRef.value && popRef.value.close()
+}
+
+
+// 事件绑定
+function bindEventListener() {
+  if (!googleInstance.value) return;
+  googleInstance.value.on('success', onPaymentSuccess);
+  googleInstance.value.on('error', onPaymentError);
+  // googleInstance.value.on('ready', onPaymentReady);
+}
+
+// 成功回调
+const onPaymentSuccess = (event) => {
+  console.log('----- google payment success -----', event)
+  emit('success');
+}
+
+// 失败回调
+const onPaymentError = (event) => {
+  console.log('----- google payment error -----', event)
+  Toast(event.detail.error.message || event.detail.error || t("pay_fail_msg", {}) || "fail!");
+}
+
+
+
+defineExpose({
+  open,
+  close
+})
+
+</script>
+<style lang="less" scoped>
+@import url('@/style.less');
+
+.payment-card__box {
+  width: 100%;
+  height: 25vh;
+
+  #payment_card {
+    display: flex;
+    align-items: center;
+    padding: 12rpx;
+    width: 100%;
+    height: 44px;
+    border: 1px solid #ccc;
+    border-radius: 14rpx;
+  }
+}
+
+.submit_btn {
+  height: 38px;
+  padding: 16rpx 30rpx;
+  background-color: var(--black);
+  color: var(--light);
+  .flex_center();
+  border-radius: 16rpx;
+  .size(24rpx);
+}
+</style>

+ 162 - 0
components/paymentModal/googlePayment_app.vue

@@ -0,0 +1,162 @@
+<template>
+  <view class="wallet_app" v-if="show">
+    <view class="wallet_footer" :style="{ 'height': footerHeight + 'px' }">
+      <view class="close">
+        <view class="close_icon" @click.stop="close">
+          <uni-icons type="closeempty" size="28" color="var(--text-01)"></uni-icons>
+        </view>
+      </view>
+			<!-- <iframe :src="fullUrl"></iframe> -->
+    </view>
+  </view>
+</template>
+
+
+<script>
+import { systemInfo, Toast, openUrl } from "@/utils"
+import { SHOP_SUBMIT_PAY } from '@/api'
+
+export default {
+  props: {
+    paramsObj: { type: Object }
+  },
+	
+  data() {
+    return {
+      webview: null,
+      show: false,
+      footerHeight: 0,
+      googleParams: {},
+			// srcUrl: 'http://192.168.5.103:4000/static/hybrid/html/google.html',
+			srcUrl: 'https://get.vavabuy.com/google.html',
+    }
+  },
+	
+	
+  methods: {
+    open() {
+      this.show = true;
+      this.$nextTick(() => {
+        this.fetchPaymentInfo()
+      })
+    },
+    close() {
+      this.webview && this.webview.close();
+      this.webview = null;
+      this.show = false
+    },
+		
+    getRequest(url) {
+      let theRequest = new Object();
+      let index = url.indexOf("?");
+      if (index != -1) {
+        let str = url.substring(index + 1);
+        let strs = str.split("&");
+        for (let i = 0; i < strs.length; i++) {
+          theRequest[strs[i].split("=")[0]] = unescape(strs[i].split("=")[1]);
+        }
+      }
+      return theRequest;
+    },
+		
+    async initWebViewBelowElement(eventData) {
+      console.log(21121);
+
+      try {
+        let wvPath = '/static/hybrid/html/google.html';
+        let wv = plus.webview.create("", wvPath, {
+          'uni-app': 'none',
+          position: 'fixed',
+          background: 'transparent',
+          left: '24px',
+          right: '24px',
+          top: this.footerHeight + 48 + 28 + 'px',
+          overflowY: 'auto',
+        });
+        wv.loadURL(wvPath);
+        wv.overrideUrlLoading({ mode: 'reject' }, (e) => {
+					console.log('回调地址',JSON.stringify(e));
+					if (e.url && e.url.includes('pay.google.com')) return openUrl(e.url);
+          let { str } = this.getRequest(e.url);
+          str = unescape(str)
+          return this.handleBack(str)
+        });
+        wv.evalJS(`
+        window.dispatchEvent(new CustomEvent('appMessage', 
+        { detail: ${JSON.stringify(eventData)} }))`);
+        this.$root.$scope.$getAppWebview().append(wv);
+        this.webview = wv;
+      } catch (error) {
+        console.error(error);
+      }
+    },
+		
+    async fetchPaymentInfo() {
+			const params = this.paramsObj ? this.paramsObj : {}
+      try {
+        const res = await SHOP_SUBMIT_PAY({
+          payType: 'airwallex',
+          ...params
+        })
+        const { id, client_secret, amount, currency, countryCode } = res.data;
+				const paramsData = {
+					intent_id: id,
+					client_secret: client_secret,
+					amount: {
+						value: amount,
+						currency,
+					},
+					countryCode: countryCode
+				}
+        this.googleParams = paramsData;
+        this.initWebViewBelowElement({ type: 'pay', ...this.googleParams })
+      }
+			catch (error) {
+				console.log('----- fetch info error ----- ', JSON.stringify(error))
+				Toast(error.msg)
+			}
+    },
+		
+    handleBack(str) {
+      console.log('----- 收到消息 -----', str);
+    }
+  },
+	
+  async mounted() {
+    const res = await systemInfo();
+    this.footerHeight = res.windowHeight / 2;
+		/* this.$nextTick(() => {
+		  this.fetchPaymentInfo()
+		}) */
+  }
+	
+}
+</script>
+
+
+<style lang="less" scoped>
+.wallet_app {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  z-index: 9999999;
+  background-color: rgba(0, 0, 0, .5);
+  display: flex;
+  align-items: flex-end;
+
+  .wallet_footer {
+    width: 100%;
+    background-color: #fff;
+    padding: 24px;
+    border-radius: 10px 10px 0 0;
+
+    .close {
+      height: 28px;
+      display: flex;
+      justify-content: flex-end;
+    }
+  }
+}
+</style>

+ 4 - 0
components/paymentModal/hooks/index.js

@@ -0,0 +1,4 @@
+export * from "./useSplitCardInfo";
+export * from "./useGoogleInfo";
+export * from "./useAppleInfo";
+export * from "./useDropInPayInfo";

+ 63 - 0
components/paymentModal/hooks/useAppleInfo.js

@@ -0,0 +1,63 @@
+import { ref, reactive, nextTick } from 'vue'
+// #ifdef H5
+import { createElement, loadAirwallex, getElement } from 'airwallex-payment-elements'
+// #ifdef H5
+import { SHOP_SUBMIT_PAY } from '@/api'
+import { getLan } from "@/locale"
+import verConfig from '@/ver.config'
+
+
+let appleInstance = ref(null);
+let appleParams = reactive({})
+
+const init = (callback) => {
+  loadAirwallex({
+    env: 'staging',
+    env: 'prod',
+    origin: window.location.origin,
+    // origin: verConfig.origin,
+    locale: getLan(),
+  }).then(() => {
+    appleInstance.value = createElement('applePayButton', {
+      ...appleParams
+    });
+    appleInstance.value.mount('apple_pay_card');
+    callback && callback();
+  })
+}
+
+const unmountCard = () => {
+  let card = getElement('applePayButton');
+  card.destroy();
+  card.unmount();
+  appleInstance.value = null;
+}
+
+
+
+const fetchCardPaymentInfo = (params = {}, callback) => {
+  return new Promise((resolve, reject) => {
+    const query = {
+      payType: 'airwallex',
+      ...params
+    }
+    SHOP_SUBMIT_PAY(query).then(result => {
+      const { id, client_secret, amount, currency, countryCode } = result.data;
+      appleParams.intent_id = id;
+      appleParams.client_secret = client_secret;
+      appleParams.amount = {
+        value: amount,
+        currency,
+      };
+      appleParams.countryCode = countryCode
+      nextTick(() => {
+        init(callback);
+      })
+      resolve(result.data)
+    }).catch(err => { reject(err) })
+  })
+}
+
+export const useAppleInfo = () => {
+  return { appleInstance, init, unmountCard, fetchCardPaymentInfo }
+}

+ 93 - 0
components/paymentModal/hooks/useDropInPayInfo.js

@@ -0,0 +1,93 @@
+import { ref, reactive, nextTick } from 'vue'
+// #ifdef H5
+import { init, createElement } from '@airwallex/components-sdk';
+// #endif
+import { SHOP_SUBMIT_PAY } from '@/api'
+import { getLan } from "@/locale"
+import verConfig from '@/ver.config'
+
+
+export const useDropInPayInfo = () => {
+
+	let dropInElement = ref(null);
+	let createOptions = reactive({});
+
+
+	// 初始化
+	const handleInit = async (callback) => {
+		try {
+			await init({
+				env: 'prod',
+				enabledElements: ['payments'],
+				locale: getLan()
+			});
+			dropInElement.value = await createElement('dropIn', {
+				...createOptions,
+				appearance: {
+					mode: 'light',
+					variables: {
+						colorBrand: '#612FFF',
+					},
+				}
+			});
+			nextTick(() => {
+				dropInElement.value && dropInElement.value.mount('dropIn');
+				callback && callback();
+			})
+		}
+		catch (err) {
+			console.log('--- err ---', err)
+		}
+	}
+
+	// 卸载&销毁
+	const handleUnmount = () => {
+		if (dropInElement.value) {
+			dropInElement.value.unmount();
+			dropInElement.value.destroy();
+			dropInElement.value = null;
+		}
+	}
+
+
+	// 获取初始化配置数据
+	const fetchPaymentInitData = (params = {}, callback) => {
+		return new Promise((resolve, reject) => {
+			SHOP_SUBMIT_PAY({
+				payType: 'airwallex',
+				...params
+			}).then(result => {
+				const {
+					id,
+					client_secret,
+					amount,
+					currency,
+					countryCode
+				} = result.data;
+				createOptions.intent_id = id;
+				createOptions.client_secret = client_secret;
+				/* createOptions.amount = {
+					value: amount,
+					currency,
+				}; */
+				createOptions.currency = currency
+				createOptions.countryCode = countryCode
+				nextTick(() => {
+					console.log('---- createOptions ----', createOptions)
+					handleInit(callback);
+				})
+				resolve(result.data)
+			}).catch(err => {
+				reject(err)
+			})
+		})
+	}
+
+
+	return {
+		dropInElement,
+		handleInit,
+		handleUnmount,
+		fetchPaymentInitData
+	}
+}

+ 61 - 0
components/paymentModal/hooks/useGoogleInfo.js

@@ -0,0 +1,61 @@
+import { ref, reactive, nextTick } from 'vue'
+// #ifdef H5
+import { createElement, loadAirwallex, getElement } from 'airwallex-payment-elements'
+// #endif
+import { SHOP_SUBMIT_PAY } from '@/api'
+import { getLan } from "@/locale"
+import verConfig from '@/ver.config'
+
+let googleInstance = ref(null);
+let googleParams = reactive({})
+
+const init = (callback) => {
+  loadAirwallex({
+    env: 'prod',
+    origin: window.location.origin,
+    locale: getLan()
+  }).then(() => {
+    googleInstance.value = createElement('googlePayButton', {
+      ...googleParams
+    });
+    googleInstance.value.mount('google_pay_card');
+    callback && callback();
+  })
+}
+
+const unmountCard = () => {
+  let card = getElement('googlePayButton');
+  card.destroy();
+  card.unmount();
+  googleInstance.value = null;
+}
+
+
+
+const fetchCardPaymentInfo = (params = {}, callback) => {
+  return new Promise((resolve, reject) => {
+    const query = {
+      payType: 'airwallex',
+      ...params
+    }
+    SHOP_SUBMIT_PAY(query).then(result => {
+      const { id, client_secret, amount, currency, countryCode } = result.data;
+      googleParams.intent_id = id;
+      googleParams.client_secret = client_secret;
+      googleParams.amount = {
+        value: amount,
+        currency,
+      };
+      googleParams.countryCode = countryCode
+      nextTick(() => {
+        console.log('---- googleParams ----', googleParams)
+        init(callback);
+      })
+      resolve(result.data)
+    }).catch(err => { reject(err) })
+  })
+}
+
+export const useGoogleInfo = () => {
+  return { googleInstance, init, unmountCard, fetchCardPaymentInfo }
+}

+ 99 - 0
components/paymentModal/hooks/useSplitCardInfo.js

@@ -0,0 +1,99 @@
+import { reactive, ref } from 'vue'
+// #ifdef H5
+import { createElement, init } from '@airwallex/components-sdk';
+// #endif
+import { SHOP_SUBMIT_PAY } from '@/api'
+import { getLan } from "@/locale"
+import verConfig from '@/ver.config'
+
+
+let cardNumber = '4035501000000008'	// 测试用卡号
+
+
+export const useSplitCardInfo = () => {
+	let paymentInfo = ref(null)
+	let intent_id = ref('')
+	let client_secret = ref('')
+
+	const elementTypeList = reactive({
+		cardNumber: {
+			instance: null,
+			type: "cardNumber",
+			container: "split_card_number",
+			options: {}
+		},
+		expiry: {
+			instance: null,
+			type: "expiry",
+			container: "split_card_expiry",
+			options: {}
+		},
+		cvc: {
+			instance: null,
+			type: "cvc",
+			container: "split_card_cvc",
+			options: {}
+		},
+	})
+
+
+	// 初始化
+	const onInit = () => {
+		const options = {
+			env: 'prod', // 'staging | 'demo' | 'prod'
+			enabledElements: ['payments'],
+			locale: getLan(),
+		}
+		init(options).then(() => {
+			for (let key in elementTypeList) {
+				onMountElement(elementTypeList[key])
+			}
+		});
+	}
+
+	// 挂载元素
+	const onMountElement = async (elementInfo) => {
+		elementInfo.instance = await createElement(elementInfo.type, elementInfo.options);
+		elementInfo.instance && elementInfo.instance.mount(elementInfo.container);
+	}
+
+	// 卸载元素
+	const onUnmountElement = () => {
+		for (let key in elementTypeList) {
+			const info = elementTypeList[key]
+			if (info.instance) {
+				info.instance.destroy();
+				info.instance.unmount();
+				info.instance = null;
+			}
+		}
+	}
+
+	// 支付信息
+	const fetchPaymentInfo = (params = {}) => {
+		return new Promise((resolve, reject) => {
+			const query = {
+				payType: 'airwallex',
+				...params
+			}
+			SHOP_SUBMIT_PAY(query).then((result) => {
+				paymentInfo.value = result.data ? result.data : null
+				intent_id.value = paymentInfo.value ? paymentInfo.value.id : ''
+				client_secret.value = paymentInfo.value ? paymentInfo.value.client_secret : ''
+				resolve(result.data)
+			}).catch(err => {
+				reject(err)
+			})
+		})
+	}
+
+
+	return {
+		elementTypeList,
+		intent_id,
+		client_secret,
+		onInit,
+		onUnmountElement,
+		fetchPaymentInfo
+	}
+}

+ 166 - 0
components/paymentModal/splitCardPay.vue

@@ -0,0 +1,166 @@
+<template>
+	<Popup isClose ref="popRef">
+		<template #content>
+			<view class="split-card__box">
+				<view class="card_item">
+					<view class="card_item_label">
+						<trans _t="银行卡号" />
+					</view>
+					<view class="card_item_input" id="split_card_number"></view>
+				</view>
+				<view class="card_item">
+					<view class="card_item_label">
+						<trans _t="有效期" />
+					</view>
+					<view class="card_item_input" id="split_card_expiry"></view>
+				</view>
+				<view class="card_item">
+					<view class="card_item_label">
+						<trans _t="安全码" />
+					</view>
+					<view class="card_item_input" id="split_card_cvc"></view>
+				</view>
+			</view>
+		</template>
+
+		<!-- footer -->
+		<template #footer>
+			<view class="submit_btn" @click="onConfirm">
+				<trans _t="确认" />
+			</view>
+		</template>
+	</Popup>
+	<GlobalLoading :msg="loadingStatus"></GlobalLoading>
+</template>
+
+<script setup>
+import { reactive, ref, nextTick } from 'vue'
+import Popup from '@/components/popup.vue';
+import GlobalLoading from '@/components/GlobalLoading.vue'
+import { Toast } from "@/utils"
+import { t } from "@/locale"
+import { useSplitCardInfo } from './hooks'
+
+
+const props = defineProps({
+	paramsObj: { type: Object }
+})
+const emit = defineEmits(['on-confirm', 'on-open', 'on-close', 'on-success', 'on-error']);
+
+
+const {
+	elementTypeList,
+	intent_id,
+	client_secret,
+	onInit,
+	onUnmountElement,
+	fetchPaymentInfo } = useSplitCardInfo()
+
+const popRef = ref(null);
+const loadingStatus = reactive({ show: false })
+
+
+// 打开回调
+const open = (data) => {
+	onUnmountElement()
+	emit('on-open')
+	popRef.value && popRef.value.open()
+	nextTick(() => {
+		fetchPaymentInfo(props.paramsObj)
+		onInit()
+	})
+}
+
+// 关闭回调
+const close = () => {
+	emit('on-close')
+	popRef.value && popRef.value.close()
+	onUnmountElement()
+}
+
+// “确认按钮” 回调
+const onConfirm = () => {
+	submitPayment()
+}
+
+
+// 提交支付
+function submitPayment() {
+	const cardNumber = elementTypeList.cardNumber
+	if (!cardNumber.instance) return
+	loadingStatus.show = true
+	const options = {
+		intent_id: intent_id.value,
+		client_secret: client_secret.value,
+		payment_method_options: {
+			card: {
+				auto_capture: true,
+			},
+		},
+	}
+	cardNumber.instance.confirm(options).then((response) => {
+		console.log('--- response ----', response)
+		const { status } = response
+		if (status == "SUCCEEDED" || status == "succeeded") {
+			emit('on-success', response)
+		}
+		else {
+			Toast(status)
+		}
+	}).catch((error) => {
+		console.log('--- error ----', error)
+		Toast(error.message)
+	}).finally(() => {
+		loadingStatus.show = false
+	});
+}
+
+
+defineExpose({
+	open,
+	close
+})
+</script>
+
+
+<style lang="less" scoped>
+@import url('@/style.less');
+
+.split-card__box {
+	width: 100%;
+	height: 40vh;
+
+	.card_item {
+		margin-top: 16px;
+		width: 100%;
+	}
+
+	.card_item:first-child {
+		margin-top: 0;
+	}
+
+	.card_item .card_item_label {
+		font-size: 28rpx;
+		color: #333;
+	}
+
+	.card_item .card_item_input {
+		min-height: 40px;
+		padding: 8rpx 0rpx 8rpx 16rpx;
+		margin-top: 10px;
+		border: 1px solid #ccc;
+		border-radius: 14rpx;
+
+	}
+}
+
+.submit_btn {
+	height: 38px;
+	padding: 16rpx 30rpx;
+	background-color: var(--black);
+	color: var(--light);
+	.flex_center();
+	border-radius: 16rpx;
+	.size(24rpx);
+}
+</style>

+ 183 - 0
components/picker.vue

@@ -0,0 +1,183 @@
+<template>
+  <view class="iosBottom">
+    <uni-popup ref="popupRef" type="bottom">
+      <view class="popup_header">
+        <trans class="cancel_btn" :_t="cancelText" @click="handleClose" />
+        <trans class="confirm_btn" :_t="confirmText" @click="handleConfirm" />
+      </view>
+      <picker-view
+        v-if="true"
+        :indicator-style="indicatorStyle"
+        :value="value"
+        @change="handleChange"
+        class="picker-view"
+        mask-class="mask"
+      >
+        <picker-view-column>
+          <view
+            class="item"
+            v-for="(item, index) in data"
+            :key="`picker_${new Date().getTime}_${index}`"
+          >
+            <slot name="pickerItem" :item="item">
+              {{ item[labelKey] }}
+            </slot>
+          </view>
+        </picker-view-column>
+      </picker-view>
+    </uni-popup>
+  </view>
+</template>
+
+<script setup>
+import { ref, computed } from "vue";
+
+const props = defineProps({
+  data: {
+    type: Array,
+    default: () => [],
+  },
+  labelKey: {
+    type: String,
+    default: "label",
+  },
+  valueKey: {
+    type: String,
+    default: "value",
+  },
+  modelValue: {
+    type: String,
+    default: "",
+  },
+  cancelText: {
+    type: String,
+    default: "取消",
+  },
+  confirmText: {
+    type: String,
+    default: "确认",
+  },
+});
+const emit = defineEmits(["update:modelValue", "confirm"]);
+const popupRef = ref(null);
+const value = ref(null);
+const indicatorStyle = `height: 50px;`;
+let tempObject = {};
+
+// methods
+function handleChange(e) {
+  const index = e.detail.value[0];
+  tempObject = props.data[index];
+}
+
+function handleClose() {
+  tempObject = {};
+  popupRef.value.close();
+}
+
+function setValue(val) {
+  value.value = [val];
+  // _setValue([val]);
+}
+
+function openPopup() {
+  setValue(
+    props.data.findIndex((item) => item[props.valueKey] === props.modelValue)
+  );
+  !!popupRef.value && popupRef.value.open();
+}
+
+function handleConfirm() {
+  const item = props.data.find(
+    (obj) => obj[props.valueKey] == props.modelValue
+  );
+  // if (tempObject[props.valueKey]) {
+  emit("update:modelValue", tempObject[props.valueKey] || item[props.valueKey]);
+  emit("confirm", JSON.stringify(tempObject) != "{}" ? tempObject : item);
+  // }
+  handleClose();
+}
+
+defineExpose({
+  open: openPopup,
+});
+</script>
+
+<style lang="less" scoped>
+@import url("@/style.less");
+
+.picker-view {
+  height: 500rpx;
+  margin-top: 20rpx;
+}
+/deep/ .uni-picker-view-indicator {
+  height: 68rpx !important;
+}
+/deep/ .uni-popup {
+  z-index: 999999;
+}
+
+.item {
+  height: 68rpx !important;
+  line-height: 68rpx;
+  text-align: center;
+  color: var(--black);
+  font-size: 24rpx;
+  background: var(--bg);
+}
+
+.areacode_text {
+  color: var(--light);
+}
+
+.popup_header {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  background-color: var(--light);
+  height: 82rpx;
+  // border-bottom: 1px solid var(--borderColor);
+
+  .btn {
+    line-height: 82rpx;
+    padding: 0 40rpx;
+    font-size: 24rpx;
+  }
+
+  .cancel_btn {
+    .btn();
+    color: var(--black);
+  }
+
+  .confirm_btn {
+    .btn();
+    // color: #2979ff;
+    color: var(--black);
+  }
+}
+
+/deep/ .picker-view {
+  margin-top: 0;
+
+  .uni-picker-view-content {
+    background: var(--light);
+  }
+}
+
+.mask {
+  background: var(--picker-mask);
+  // background: red;
+  background-position: top, bottom;
+  background-repeat: no-repeat;
+  background-size: 100% 100%;
+}
+
+.picker-view {
+  background-color: var(--light);
+}
+
+:deep(.uni-picker-view-indicator) {
+  background-color: var(--light);
+  opacity: 0.3;
+}
+</style>

+ 142 - 0
components/placard.vue

@@ -0,0 +1,142 @@
+<template>
+  <view class="pla_card" @click="open">
+    <view class="card_top">
+      <view class="left">
+        <i class="icon-font icon-announcement"></i>
+        <trans _t="公告" v-if="mode == 'vertical'" />
+        <text v-else class="card_text">{{ winnotcie.title }}</text>
+        <!-- <trans class="card_text" _t="团队服务升级报告" v-else /> -->
+      </view>
+      <i class="icon-font icon-left" v-if="mode == 'horizontal'"></i>
+    </view>
+    <view class="cont" v-if="mode != 'horizontal'">
+      <text>{{ winnotcie.title }}</text>
+      <!-- <trans _t="团队服务升级报告" /> -->
+    </view>
+  </view>
+  <up-popup :show="show" safeAreaInsetTop :round="10" mode="bottom" @close="close">
+    <view class="pop">
+      <view class="top">
+        <view class="top_left">
+          <i class="icon-font icon-announcement"></i>
+          <trans _t="公告" />
+        </view>
+        <view class="close" @click="close">
+          <i class="icon-font icon-close"></i>
+        </view>
+      </view>
+      <view class="conts">
+        <rich-text :nodes="winnotcie.content"></rich-text>
+      </view>
+    </view>
+  </up-popup>
+</template>
+<script setup>
+import { ref, computed } from 'vue';
+import { useSystemStore } from "@/store";
+
+const useSystem = useSystemStore();
+
+const props = defineProps({
+  mode: {
+    type: String,
+    default: 'vertical' // horizontal || vertical
+  }
+})
+const show = ref(false);
+const winnotcie = computed(() => useSystem.getWinnotice)
+
+const open = () => { show.value = true };
+const close = () => { show.value = false };
+</script>
+<style lang="less" scoped>
+.pla_card {
+  background: #f0700c1a;
+  border-radius: 16rpx;
+  font-size: 24rpx;
+  line-height: 40rpx;
+  padding: 16rpx;
+
+  .card_top {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    color: var(--danger);
+    font-weight: 700;
+    margin-bottom: 8rpx;
+
+    .left {
+      display: flex;
+      align-items: center;
+
+      .icon-announcement {
+        font-weight: 400;
+        font-size: 48rpx;
+        margin-right: 16rpx;
+      }
+    }
+
+    .card_text {
+      font-size: 24rpx;
+      font-weight: 400;
+    }
+
+    .icon-left {
+      transform: rotate(180deg);
+      color: var(--danger);
+      font-weight: 400;
+    }
+  }
+
+  .cont {
+    color: #346;
+  }
+}
+
+.pop {
+  max-height: 80vh;
+  display: flex;
+  flex-direction: column;
+
+  .top {
+    padding: 30rpx 30rpx 0;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+
+    &_left {
+      display: flex;
+      align-items: center;
+      color: var(--text);
+      font-size: 32rpx;
+      font-weight: 700;
+
+      .icon-announcement {
+        color: var(--text-01);
+        font-size: 28px;
+        font-weight: 400;
+        margin-right: 16rpx;
+      }
+    }
+
+    .close {
+      .icon-close {
+        color: var(--text-01);
+        cursor: pointer;
+        font-size: 28px;
+        font-weight: 400;
+      }
+    }
+  }
+
+  .conts {
+    flex-grow: 1;
+    padding: 24rpx 30rpx;
+    overflow: hidden scroll;
+    color: var(--text);
+    /deep/ img{
+      width: 100%;
+    }
+  }
+}
+</style>

+ 294 - 0
components/play.vue

@@ -0,0 +1,294 @@
+<template>
+	<view style="overflow: hidden;" :style="{ height: height + 'px' }">
+		<swiper class="swiper" :style="{ height: height + 'px' }" :show-scrollbar="false" vertical :circular="false"
+			:current="current" @change="onSwiperChange">
+			<swiper-item v-for="(item, i) in list" :key="i" :style="{ 'height': height - 1 + 'px' }">
+				<oVideo :ref="el => setItemRef(el, i)" :id="'video' + i" :height="height - 1" :current="current" :item="item"
+					:index="i" @showPinglun="comment(item)" @play="onPlay" @like="like(item, i)" @collect="collect(item, i)"
+					@follow="follow(item, i)" />
+			</swiper-item>
+		</swiper>
+		<!-- 评论弹框 -->
+		<commentDialog ref="dialogRef" :video_id="video_id" />
+	</view>
+</template>
+
+<script setup>
+import { ref, onMounted, computed } from "vue";
+import oVideo from "@/components/y-video";
+import { onShow } from "@dcloudio/uni-app"
+import { useVideoStore, useUserStore } from "@/store"
+import { VIDEO_VIEWS, VIDEO_COLLECTS, VIDEO_GOODS, DISCOVER_FOLLOW } from "@/api"
+import { Toast } from "@/utils"
+import commentDialog from '@/components/commentDialog'
+
+const useUser = useUserStore();
+const userInfo = computed(() => useUser.getuserInfo)
+const dialogRef = ref(null);
+const useVideo = useVideoStore();
+let systemInfo = uni.getSystemInfoSync();
+const top = systemInfo.statusBarHeight + uni.upx2px(30);
+const height = systemInfo.screenHeight;
+const scrollHeight = systemInfo.screenHeight * 0.8 - uni.upx2px(100);
+const current = ref(0);
+const newCurrent = ref(0);
+const info = {
+	name: '测试标题',
+	pic: 'https://img.lzzyimg.com/upload/vod/20240312-1/e3d0aaa1748d757b03fab599abf156d8.jpg'
+}
+const paging = ref(null)
+const video_id = ref(null)
+// const newList = ref([]);
+// const list = ref([{
+// 	title: "第18集",
+// 	src: "http://vjs.zencdn.net/v/oceans.mp4",
+// 	desc: '测试内容'
+// }, {
+// 	title: "第19集",
+// 	src: "https://cloud.video.taobao.com/play/u/3007761989/p/2/e/6/t/1/451969495179.mp4?appKey=38829",
+// 	desc: '测试内容2'
+// }, {
+// 	title: "第20集",
+// 	src: "http://vjs.zencdn.net/v/oceans.mp4",
+// 	desc: '测试内容2'
+// }, {
+// 	title: "第21集",
+// 	src: "http://vjs.zencdn.net/v/oceans.mp4",
+// 	desc: '测试内容'
+// }, {
+// 	title: "第22集",
+// 	src: "https://cloud.video.taobao.com/play/u/3007761989/p/2/e/6/t/1/451969495179.mp4?appKey=38829",
+// 	desc: '测试内容2'
+// }, {
+// 	title: "第23集",
+// 	src: "http://vjs.zencdn.net/v/oceans.mp4",
+// 	desc: '测试内容2'
+// }, {
+// 	title: "第24集",
+// 	src: "https://cloud.video.taobao.com/play/u/3007761989/p/2/e/6/t/1/451969495179.mp4?appKey=38829",
+// 	desc: '测试内容2'
+// }, {
+// 	title: "第25集",
+// 	src: "http://vjs.zencdn.net/v/oceans.mp4",
+// 	desc: '测试内容2'
+// }, {
+// 	title: "第26集",
+// 	src: "https://cloud.video.taobao.com/play/u/3007761989/p/2/e/6/t/1/451969495179.mp4?appKey=38829",
+// 	desc: '测试内容2'
+// }, {
+// 	title: "第27集",
+// 	src: "http://vjs.zencdn.net/v/oceans.mp4",
+// 	desc: '测试内容2'
+// }, {
+// 	title: "第28集",
+// 	src: "https://cloud.video.taobao.com/play/u/3007761989/p/2/e/6/t/1/451969495179.mp4?appKey=38829",
+// 	desc: '测试内容2'
+// }, {
+// 	title: "第29集",
+// 	src: "http://vjs.zencdn.net/v/oceans.mp4",
+// 	desc: '测试内容2'
+// }, {
+// 	title: "第30集",
+// 	src: "https://cloud.video.taobao.com/play/u/3007761989/p/2/e/6/t/1/451969495179.mp4?appKey=38829",
+// 	desc: '测试内容2'
+// }, {
+// 	title: "第31集",
+// 	src: "http://vjs.zencdn.net/v/oceans.mp4",
+// 	desc: '测试内容2'
+// }])
+const list = computed(() => useVideo.getVideoList)
+
+
+let pages = 5;
+const newList = computed(() => {
+	let _list = [];
+	let start = 0;
+	let end = 0
+	let half = Math.floor(newCurrent.value / pages)
+	// console.log(half);
+
+
+	start = half - 1 < 0 ? 0 : start + half;
+	end = half - 1 < 0 ? pages : half * pages + current.value;
+	// if (current.value < 4) {
+	// }
+	// else {
+	// 	start = (newCurrent.value + 1) % pages * pages + current.value
+	// 	end = start + pages;
+	// }
+	_list = list.value.slice(start, end)
+	console.log(start, end);
+
+	return _list
+})
+const videoContexts = ref([]);
+onMounted(() => {
+	if (videoContexts.value[current.value]) {
+		videoContexts.value[current.value].play()
+	}
+
+})
+const setItemRef = (el, index) => {
+	if (el) {
+		videoContexts.value[index] = el
+	}
+}
+const onPlay = async (item) => {
+	try {
+		await VIDEO_VIEWS(item.id)
+	} catch (error) { }
+}
+
+const onSwiperChange = (e) => {
+	const newIndex = e.detail.current;
+	if (videoContexts.value[current.value]) {
+		videoContexts.value[current.value].pause()
+	}
+	if (newIndex == list.value.length - 2) {
+		useVideo.setVideoList(true)
+	}
+
+	current.value = newIndex;
+	if (videoContexts.value[newIndex]) {
+		videoContexts.value[newIndex].play()
+	}
+}
+
+const like = async (item, index) => {
+	let obj = {};
+	try {
+		const res = await VIDEO_GOODS(item.id);
+		obj = { ...item, goods: res.data.goods, is_goods: item.goods == 0 ? 1 : 0 };
+		useVideo.setList(obj, index);
+	} catch (error) {
+		Toast(error.msg)
+	}
+}
+const collect = async (item, index) => {
+	let obj = {};
+	try {
+		const res = await VIDEO_COLLECTS(item.id);
+		obj = { ...item, collects: res.data.collects, is_collect: item.is_collect == 0 ? 1 : 0 };
+		useVideo.setList(obj, index);
+	} catch (error) {
+		Toast(error.msg)
+	}
+}
+
+const follow = async (item, index) => {
+	let obj = {};
+	try {
+		const res = await DISCOVER_FOLLOW(item.userid);
+		obj = { ...item, is_follow: item.is_follow == 0 ? 1 : 0 };
+		useVideo.setList(obj, index);
+	} catch (error) {
+		Toast(error.msg)
+	}
+}
+const comment = (item) => {
+	video_id.value = item.id;
+	dialogRef.value && dialogRef.value.open();
+}
+onShow(() => {
+})
+</script>
+
+<style lang="scss" scoped>
+.pop {
+	position: fixed;
+	width: 750rpx;
+	background-color: #fff;
+	border-radius: 30rpx 30rpx 0 0;
+	left: 0;
+	transition-property: top;
+	transition-duration: 150ms;
+	transition-timing-function: ease-in-out;
+	z-index: 999;
+
+	.title {
+		padding: 30rpx 30rpx 0;
+		align-items: center;
+		justify-content: center;
+		line-height: 40rpx;
+	}
+
+	&--close-btn {
+		height: 40rpx;
+		width: 40rpx;
+		position: absolute;
+		right: 30rpx;
+		top: 30rpx;
+	}
+}
+
+.border-bottom {
+	width: 750rpx;
+	border-bottom: 1rpx solid #e8e8e8;
+	transform: scaleY(.5);
+	margin-top: 30rpx;
+}
+
+.pinglun {
+	flex-direction: row;
+	align-items: flex-start;
+	padding: 30rpx;
+
+	.touxiang {
+		height: 60rpx;
+		width: 60rpx;
+		border-radius: 50%;
+	}
+}
+
+.list_cont {
+	uni-view {
+		position: relative;
+	}
+}
+
+.mulu {
+	padding-left: 30rpx;
+	padding-right: 30rpx;
+
+	.touxiang {
+		height: 114.8rpx;
+		width: 78.4rpx;
+		border-radius: 10rpx;
+	}
+
+	.title {
+		color: rgba(0, 0, 0, .85);
+		padding: 0;
+	}
+
+	.active {
+		.title {
+			color: #f85400;
+		}
+	}
+
+	.tag {
+		background-color: #f85400;
+		padding: 7rpx 12rpx;
+		border-radius: 10rpx;
+
+		.text {
+			color: #fff;
+		}
+	}
+}
+
+.flex-1 {
+	flex: 1;
+}
+
+.lh-40 {
+	line-height: 40rpx;
+}
+
+@for $i from 20 to 40 {
+	.fs-#{$i} {
+		font-size: $i + rpx;
+	}
+}
+</style>

+ 517 - 0
components/popover.vue

@@ -0,0 +1,517 @@
+<template>
+  <view class="zbPopover" :style="{
+    '--theme-bg-color': bgStyleColor
+  }">
+    <view class="mask" @click.stop="close" v-if="show" :style="{ backgroundColor: overlayBg }"></view>
+    <view @click.stop="handleClick" class="zb-button-popover">
+      <slot></slot>
+    </view>
+    <view class="zb-popover" v-show="inited" ref="zb-transition" :class="[classes, `zb-popover-${placement}`]"
+      :style="[mergeStyle, { ...popoverStyle }]" @touchmove="noop">
+      <view class="zb-popover-arrow" :style="[arrowStyle]" :class="[{
+        'zb_popper__up': placement.indexOf('bottom') === 0,
+        'zb_popper__arrow': placement.indexOf('top') === 0,
+        'zb_popper__right': placement.indexOf('right') === 0,
+        'zb_popper__left': placement.indexOf('left') === 0,
+      }]" v-if="isArrow">
+      </view>
+      <slot name="content">
+        <view :class="[{
+          'horizontal__action': actionsDirection === 'horizontal'
+        }]">
+          <view @click.stop="actionAction(item)" v-for="item, index in options" class="zb-popover__action" :class="[{
+            'dark__action': theme === 'dark'
+          }]" :key="index">
+            <slot name="item" :item="item">
+              <i class="icon-font" :class="item.icon" :style="{ fontSize: iconSize }"></i>
+            </slot>
+            <view class="zb-popover__action-text">
+              <trans class="text" :_t="keyName ? item[keyName] : item" />
+            </view>
+          </view>
+        </view>
+      </slot>
+    </view>
+  </view>
+</template>
+
+<script setup>
+import { ref, onMounted, computed, nextTick, watch } from "vue"
+const tranClass = {
+  enter: "zb-fade-zoom-enter zb-fade-zoom-enter-active",
+  'enter-to': "zb-fade-zoom-enter-to zb-fade-zoom-enter-active",
+  leave: "zb-fade-zoom-leave zb-fade-zoom-leave-active",
+  'leave-to': "zb-fade-zoom-leave-to zb-fade-zoom-leave-active",
+}
+const props = defineProps({
+  options: {
+    type: Array,
+    default: () => []
+  },
+  placement: {
+    type: String,
+    default: 'bottom-start'
+  },
+  bgColor: {
+    type: String,
+
+  },
+  theme: {
+    type: String,
+    default: 'light' // light dark
+  },
+  actionsDirection: {
+    type: String,
+    default: 'vertical' // horizontal vertical
+  },
+  keyName: {
+    type: String,
+    default: ''
+  },
+  overlayBg: {
+    type: String,
+    default: 'transparent'
+  },
+  iconSize: {
+    type: String,
+    default: '30px'
+  },
+  isArrow: Boolean
+})
+
+
+const emit = defineEmits(['handleClick', 'select'])
+const show = ref(false);
+const inited = ref(false);
+const classes = ref('');
+const duration = ref(100);
+const popoverStyle = ref({});
+const arrowOldStyle = ref({});
+
+
+
+const bgStyleColor = computed(() => {
+  if (props.bgColor) {
+    return props.bgColor
+  }
+  if (props.theme === 'light') {
+    return 'white'
+  }
+  if (props.theme === 'dark') {
+    return '#4a4a4a'
+  }
+})
+const mergeStyle = computed(() => {
+  return {
+    transitionDuration: `${duration.value}ms`,
+    transitionTimingFunction: `ease-out`,
+    ...popoverStyle.value
+  }
+})
+const arrowStyle = computed(() => {
+  return { ...arrowOldStyle.value }
+})
+onMounted(() => {
+  // // #ifdef H5
+  // window.addEventListener('click', () => {
+  //   show.value = false
+  // })
+  // // #endif  
+
+})
+const handleClick = () => {
+  if (show.value) {
+    show.value = false
+  } else {
+    show.value = true
+  }
+  emit('handleClick', show.value)
+}
+const close = () => {
+  show.value = false
+}
+const actionAction = (item) => {
+  emit('select', item)
+  show.value = false
+}
+const sleep = (value) => {
+  return new Promise((resolve) => {
+    setTimeout(() => {
+      resolve()
+    }, value)
+  })
+}
+const vueEnter = () => {
+  inited.value = true
+  getPosition()
+  classes.value = tranClass.enter
+  nextTick(async () => {
+    await sleep(30)
+    classes.value = tranClass['enter-to']
+
+  })
+}
+const vueLeave = () => {
+  classes.value = tranClass.leave
+  nextTick(async () => {
+    classes.value = tranClass['leave-to']
+    await sleep(120)
+    inited.value = false
+  })
+}
+
+const preventEvent = (e) => {
+  e && typeof (e.stopPropagation) === 'function' && e.stopPropagation()
+}
+
+const getPosition = () => {
+  return new Promise((resolve) => {
+    nextTick(() => {
+      let selectorQuery = uni.createSelectorQuery().in(this).selectAll('.zb-button-popover,.zb-popover')
+      let popoverStyles = {}
+      let arrowOldStyles = {}
+      selectorQuery.boundingClientRect(async (data) => {
+        let { left, bottom, right, top, width, height } = data[0]
+        let popoverClientRect = data[1]
+
+        switch (props.placement) {
+          case 'top':
+            if (popoverClientRect.width > width) {
+              popoverStyles.left = `-${(popoverClientRect.width - width) / 2}px`
+            } else {
+              popoverStyles.left = `${Math.abs(popoverClientRect.width - width) / 2}px`
+            }
+            popoverStyles.bottom = `${height + 8}px`
+            arrowOldStyles.left = (popoverClientRect.width / 2 - 6) + 'px'
+            break;
+          case 'top-start':
+            popoverStyles.left = `0px`
+            popoverStyles.bottom = `${height + 8}px`
+            arrowOldStyles.left = '16px'
+            break;
+          case 'top-end':
+            popoverStyles.right = `0px`
+            popoverStyles.bottom = `${height + 8}px`
+            arrowOldStyles.right = '16px'
+            break;
+          case 'bottom':
+            if (popoverClientRect.width > width) {
+              popoverStyles.left = `-${(popoverClientRect.width - width) / 2}px`
+            } else {
+              popoverStyles.left = `${Math.abs(popoverClientRect.width - width) / 2}px`
+            }
+            popoverStyles.top = `${height + 8}px`
+            arrowOldStyles.left = (popoverClientRect.width / 2 - 6) + 'px'
+            break;
+          case 'bottom-start':
+            popoverStyles.top = `${height + 8}px`
+            popoverStyles.left = `0px`
+            arrowOldStyles.left = '16px'
+            break;
+          case 'bottom-end':
+            popoverStyles.top = `${height + 8}px`
+            popoverStyles.right = `0px`
+            arrowOldStyles.right = '16px'
+            break;
+          case 'right':
+            popoverStyles.left = `${width + 8}px`
+            if (popoverClientRect.height > height) {
+              popoverStyles.top = `-${(popoverClientRect.height - height) / 2}px`
+            } else {
+              popoverStyles.top = `${Math.abs((popoverClientRect.height - height) / 2)}px`
+            }
+            arrowOldStyles.top = `${popoverClientRect.height / 2 - 6}px`
+            break;
+          case 'right-start':
+            popoverStyles.left = `${width + 8}px`
+            popoverStyles.top = `0px`
+            arrowOldStyles.top = `8px`
+            break;
+          case 'right-end':
+            popoverStyles.left = `${width + 8}px`
+            popoverStyles.bottom = `0px`
+            arrowOldStyles.bottom = `8px`
+            break;
+          case 'left':
+            popoverStyles.right = `${width + 8}px`
+            if (popoverClientRect.height > height) {
+              popoverStyles.top = `-${(popoverClientRect.height - height) / 2}px`
+            } else {
+              popoverStyles.top = `${Math.abs((popoverClientRect.height - height) / 2)}px`
+            }
+            arrowOldStyles.top = `${popoverClientRect.height / 2 - 6}px`
+            break;
+          case 'left-start':
+            popoverStyles.right = `${width + 8}px`
+            popoverStyles.top = `0px`
+            arrowOldStyles.top = `8px`
+            break;
+          case 'left-end':
+            popoverStyles.right = `${width + 8}px`
+            popoverStyles.bottom = `0px`
+            arrowOldStyles.bottom = `8px`
+            break;
+        }
+        popoverStyle.value = popoverStyles;
+        arrowOldStyle.value = arrowOldStyles
+        resolve()
+      }).exec()
+    })
+  })
+}
+
+const noop = (e) => {
+  preventEvent(e)
+}
+
+watch(show, (newVal) => {
+  newVal ? vueEnter() : vueLeave()
+}, { immediate: true })
+</script>
+
+<style lang="scss" scoped>
+$theme-bg-color: var(--theme-bg-color);
+
+.mask {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  z-index: 2044;
+}
+
+.zbPopover {
+  position: relative;
+}
+
+.zb-button-popover {
+  display: flex;
+  align-items: center;
+}
+
+.zb-popover {
+  border-radius: 8px;
+  z-index: 2144;
+  position: absolute;
+  background-color: $theme-bg-color;
+  box-shadow: 0 2px 12px #3232331f;
+  overflow: hidden;
+}
+
+.zb-popover-top {
+  transform-origin: 50% bottom;
+}
+
+.zb-popover-top-start {
+  transform-origin: 50% bottom;
+}
+
+.zb-popover-top-end {
+  transform-origin: 0 bottom;
+}
+
+.zb-popover-bottom {
+  transform-origin: 50% 0;
+}
+
+.zb-popover-bottom-end {
+  transform-origin: 100% 0;
+}
+
+.zb-popover-bottom-start {
+  transform-origin: 0 0;
+}
+
+.zb-popover-right {
+  transform-origin: left 50%;
+}
+
+.zb-popover-right-start {
+  transform-origin: left 0;
+}
+
+.zb-popover-right-end {
+  transform-origin: left 100%;
+}
+
+.zb-popover-left {
+  transform-origin: right 50%;
+}
+
+.zb-popover-left-start {
+  transform-origin: right 0;
+}
+
+.zb-popover-left-end {
+  transform-origin: right 100%;
+}
+
+.zb-popover-arrow {
+  position: absolute;
+  width: 0;
+  height: 0;
+  border-color: transparent;
+  border-style: solid;
+  border-width: 6px;
+  color: $theme-bg-color;
+}
+
+.zb_popper__up {
+  border-top-width: 0;
+  border-bottom-color: currentColor;
+  top: -5px;
+}
+
+.zb_popper__right {
+  border-left-width: 0;
+  border-right-color: currentColor;
+  left: -5px;
+}
+
+.zb_popper__left {
+  border-right-width: 0;
+  border-left-color: currentColor;
+  right: -5px;
+}
+
+.zb_popper__arrow {
+  border-bottom-width: 0;
+  border-top-color: currentColor;
+  bottom: -6px;
+}
+
+.zb-popover__action {
+  position: relative;
+  display: flex;
+  align-items: center;
+  box-sizing: border-box;
+  height: 88rpx;
+  padding: 0 24rpx;
+  font-size: 28rpx;
+  cursor: pointer;
+}
+
+.zb-popover__action-text {
+  display: flex;
+  flex: 1;
+  align-items: center;
+  height: 100%;
+  padding: 0 24rpx;
+  // border-bottom: 1rpx solid #ebedf0;
+  word-wrap: break-word;
+  white-space: nowrap;
+  .text{
+    display: inline-block;
+    word-wrap: break-word;
+    white-space: nowrap;
+    color: #62708c;
+  }
+}
+
+.zb-popover__action:last-child {
+  .zb-popover__action-text {
+    border-bottom: none;
+  }
+}
+
+.dark__action {
+  color: white;
+
+  .zb-popover__action-text {
+    // border-bottom: 1rpx solid #ebedf033
+  }
+}
+
+.horizontal__action {
+  display: flex;
+
+  .zb-popover__action {
+    padding: 0 20rpx;
+    border-right: 1rpx solid #ebedf0;
+  }
+
+  .zb-popover__action-text {
+    padding: 0;
+    //border-right:1rpx solid #ebedf0;
+  }
+}
+
+
+$u-zoom-scale: scale(0.95);
+
+.zb-fade-enter-active,
+.zb-fade-leave-active {
+  transition-property: opacity;
+}
+
+.zb-fade-enter,
+.zb-fade-leave-to {
+  opacity: 0
+}
+
+.zb-fade-zoom-enter,
+.zb-fade-zoom-leave-to {
+  transform: $u-zoom-scale;
+  opacity: 0;
+}
+
+.zb-fade-zoom-enter-active,
+.zb-fade-zoom-leave-active {
+  transition-property: transform, opacity;
+}
+
+.zb-fade-down-enter-active,
+.zb-fade-down-leave-active,
+.zb-fade-left-enter-active,
+.zb-fade-left-leave-active,
+.zb-fade-right-enter-active,
+.zb-fade-right-leave-active,
+.zb-fade-up-enter-active,
+.zb-fade-up-leave-active {
+  transition-property: opacity, transform;
+}
+
+.zb-fade-up-enter,
+.zb-fade-up-leave-to {
+  transform: translate3d(0, 100%, 0);
+  opacity: 0
+}
+
+.zb-fade-down-enter,
+.zb-fade-down-leave-to {
+  transform: translate3d(0, -100%, 0);
+  opacity: 0
+}
+
+.zb-fade-left-enter,
+.zb-fade-left-leave-to {
+  transform: translate3d(-100%, 0, 0);
+  opacity: 0
+}
+
+.zb-fade-right-enter,
+.zb-fade-right-leave-to {
+  transform: translate3d(100%, 0, 0);
+  opacity: 0
+}
+
+
+.zb-popover__action {
+  .icon-font {
+    color: #62708c;
+  }
+
+  &:active {
+    background-color: rgba(0, 0, 0, 0.2);
+  }
+
+  &--disabled {
+    color: var(--van-popover-dark-action-disabled-text-color);
+
+    &:active {
+      background-color: transparent;
+    }
+  }
+}
+</style>

+ 128 - 0
components/popup.vue

@@ -0,0 +1,128 @@
+<template>
+  <up-popup
+    :show="show"
+    :overlay="!overlay"
+    :closeOnClickOverlay="!closeOnClickOverlay"
+    :zIndex="zIndex"
+    :safeAreaInsetTop="safeAreaInsetTop"
+    :round="round"
+    :mode="mode"
+    @close="close"
+    :customStyle="{ maxWidth: '1536rpx', margin: '0 auto' }"
+  >
+    <view class="pop">
+      <view class="top" v-if="title || isClose">
+        <view class="top_left">
+          <slot name="title">
+            <trans :_t="title" />
+          </slot>
+        </view>
+        <view class="close" @click="close" v-if="isClose">
+          <i
+            class="icon-font"
+            :class="icon"
+            :style="{ color: iconColor, fontSize: iconSize }"
+          ></i>
+        </view>
+      </view>
+      <view class="conts">
+        <slot name="content"></slot>
+      </view>
+      <view class="footer">
+        <slot name="footer"></slot>
+      </view>
+    </view>
+  </up-popup>
+</template>
+<script setup>
+import { ref } from "vue";
+const props = defineProps({
+  overlay: Boolean,
+  closeOnClickOverlay: Boolean,
+  safeAreaInsetTop: Boolean,
+  title: {
+    type: String,
+    default: "",
+  },
+  round: {
+    type: Number,
+    default: 10,
+  },
+  mode: {
+    type: String,
+    default: "bottom",
+  },
+  isClose: Boolean,
+  icon: {
+    type: String,
+    default: "icon-close",
+  },
+  iconColor: {
+    type: String,
+    default: "var(--text-01)",
+  },
+  iconSize: {
+    type: String,
+    default: "28px",
+  },
+  zIndex: {
+    type: [Number, String],
+    default: 10075,
+  },
+});
+
+const emit = defineEmits(["close"]);
+
+const show = ref(false);
+const open = () => {
+  show.value = true;
+};
+const close = () => {
+  show.value = false;
+};
+defineExpose({
+  open,
+  close,
+});
+</script>
+<style lang="less" scoped>
+.pop {
+  max-height: 80vh;
+  display: flex;
+  flex-direction: column;
+
+  .top {
+    padding: 48rpx 48rpx 0;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+
+    &_left {
+      display: flex;
+      align-items: center;
+      color: var(--text);
+      font-size: 32rpx;
+      font-weight: 700;
+    }
+
+    .close {
+      .icon-close {
+        cursor: pointer;
+        font-weight: 400;
+      }
+    }
+  }
+
+  .conts {
+    display: flex;
+    align-items: stretch;
+    flex-grow: 1;
+    padding: 32rpx 48rpx;
+    overflow: hidden scroll;
+  }
+
+  .footer {
+    padding: 0 48rpx 24rpx;
+  }
+}
+</style>

+ 222 - 0
components/select.vue

@@ -0,0 +1,222 @@
+<template>
+  <view class="u-select" @click="close" :class="{ disabled: disabled }">
+    <view class="u-select__content">
+      <view class="u-select__label" @click.stop="openSelect">
+        <slot name="text">
+          <trans class="u-select__text" :_t="label" />
+        </slot>
+        <slot name="icon" v-if="!icon">
+          <u-icon
+            name="arrow-down"
+            :size="iconSize"
+            :color="iconColor"
+          ></u-icon>
+        </slot>
+      </view>
+      <view class="u-select__options" :style="{ zIndex: zIndex }" v-if="isOpen">
+        <slot name="options">
+          <view class="options" v-if="options.length">
+            <view
+              class="u-select__options_item"
+              :class="current == index ? 'active' : ''"
+              :key="index"
+              v-for="(item, index) in options"
+              @click.stop="selectItem(item, index)"
+            >
+              <slot name="optionItem" :item="item">
+                <trans
+                  class="u-select__item_text"
+                  :style="{ color: itemColor }"
+                  :_t="item[keyName]"
+                  v-if="!isTran"
+                />
+                <text
+                  class="u-select__item_text"
+                  :style="{ color: itemColor }"
+                  v-else
+                >
+                  {{ item[keyName] }}
+                </text>
+              </slot>
+            </view>
+          </view>
+          <view class="_no" v-else>
+            <trans class="no_text" _t="无数据" />
+          </view>
+        </slot>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  name: "up-select",
+  emits: ["update:current", "select", "selectClick"],
+  props: {
+    label: {
+      type: String,
+      default: "选项",
+    },
+    options: {
+      type: Array,
+      default: () => {
+        return [];
+      },
+    },
+    keyName: {
+      type: String,
+      default: "name",
+    },
+    current: {
+      type: [String, Number],
+      default: "",
+    },
+    zIndex: {
+      type: Number,
+      default: 10,
+    },
+    itemColor: {
+      type: String,
+      default: "#333333",
+    },
+    iconColor: {
+      type: String,
+      default: "",
+    },
+    iconSize: {
+      type: [String],
+      default: "13px",
+    },
+    icon: Boolean,
+    isTran: Boolean,
+    disabled: {
+      // 新增的禁用属性
+      type: Boolean,
+      default: false,
+    },
+  },
+  data() {
+    return {
+      isOpen: false,
+    };
+  },
+  methods: {
+    openSelect() {
+      this.isOpen = !this.isOpen;
+      this.$emit("selectClick");
+    },
+    close() {
+      this.isOpen = false;
+    },
+    selectItem(item, index) {
+      this.isOpen = false;
+      this.$emit("update:current", index);
+      this.$emit("select", item);
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.u-select__content {
+  position: relative;
+
+  .u-select__label {
+    display: flex;
+    font-size: 28rpx;
+    font-weight: 500;
+    line-height: 60rpx;
+    margin: 0 8rpx;
+    color: var(--text-02);
+
+    /* #ifdef H5 */
+    &:hover {
+      cursor: pointer;
+    }
+
+    /* #endif */
+  }
+
+  .u-select__text {
+    margin-right: 2px;
+  }
+
+  .u-select__options {
+    min-width: 300rpx;
+    box-sizing: border-box;
+    border-radius: 4px;
+    border: 1px solid #f1f1f1;
+    background-color: #fff;
+    position: absolute;
+    top: auto;
+    left: -10px;
+    padding: 10rpx 0;
+    box-shadow: 0px 0px 12px #0000001f;
+    margin-top: 18rpx;
+    overflow: hidden scroll;
+
+    .options {
+      max-height: 274px;
+      overflow: hidden scroll;
+    }
+
+    .u-select__options_item {
+      box-sizing: border-box;
+      width: 100%;
+      min-width: 300rpx;
+
+      &:hover {
+        background-color: #f7f7f7;
+      }
+
+      /* #ifdef H5 */
+      &:hover {
+        cursor: pointer;
+      }
+
+      .u-select__item_text {
+        white-space: nowrap;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        &:hover {
+          cursor: pointer;
+        }
+      }
+
+      /* #endif */
+    }
+  }
+
+  .u-select__options::after {
+    content: "";
+    position: absolute;
+    left: 60rpx;
+    top: -12rpx;
+    // transform: translateX(-30%);
+    border-left: 14rpx solid transparent;
+    border-right: 14rpx solid transparent;
+    border-bottom: 14rpx solid var(--light);
+    z-index: 10;
+  }
+}
+
+._no {
+  text-align: center;
+
+  .no_text {
+    padding: 20rpx 0;
+    text-align: center;
+    font-size: 24rpx;
+    color: #909399;
+  }
+}
+
+.disabled {
+  pointer-events: none;
+  border: 2rpx solid #dadbde !important;
+  background-color: rgb(245, 247, 250) !important;
+  box-shadow: 0 0 0 1px var(--borderColor) inset;
+  color: #606266;
+}
+</style>

+ 112 - 0
components/simpleAgreementModal.vue

@@ -0,0 +1,112 @@
+<template>
+  <Popup ref="popup" isClose mode="center" class="pop">
+    <template #content>
+      <scroll-view class="content-scroll" scroll-y>
+        <rich-text
+          :nodes="formatContent(content)"
+          class="rich-content"
+        ></rich-text>
+      </scroll-view>
+    </template>
+    <template #footer>
+      <view class="submit_btn" @click="close">
+        <trans _t="我知道了" />
+      </view>
+    </template>
+  </Popup>
+</template>
+
+<script setup>
+import { ref, watch } from "vue";
+import Popup from "./popup.vue";
+import { OTHER_ABOUT } from "@/api";
+
+const props = defineProps({
+  type: {
+    type: String,
+    default: "agree",
+  },
+});
+
+const emit = defineEmits(["close"]);
+
+const popup = ref(null);
+const content = ref("");
+
+const getDetail = async (type) => {
+  try {
+    const res = await OTHER_ABOUT(type);
+    content.value = res.data;
+    popup.value.open();
+  } catch (error) {}
+};
+
+const formatContent = (html) => {
+  if (!html) return "";
+  return html
+    .replace(/<script[^>]*?>.*?<\/script>/gi, "")
+    .replace(/onerror\s*=/gi, "")
+    .replace(/javascript:/gi, "");
+};
+
+// 打开弹窗
+const open = (type) => {
+  getDetail(type);
+};
+
+// 关闭弹窗
+const close = () => {
+  content.value = "";
+  popup.value.close();
+  emit("close");
+};
+
+defineExpose({ open, close });
+</script>
+
+<style lang="less" scoped>
+@import url("@/style.less");
+
+:deep(.u-popup__content) {
+  width: 92%;
+}
+
+.submit_btn {
+  height: 38px;
+  padding: 16rpx 30rpx;
+  background-color: var(--black);
+  color: var(--light);
+  .flex_center();
+  border-radius: 16rpx;
+  .size(24rpx);
+}
+
+.content-scroll {
+  flex: 1;
+  min-width: 80vw;
+  // padding: 16px 20px;
+  min-height: 30vh;
+  max-height: 60vh;
+  box-sizing: border-box;
+
+  .rich-content {
+    font-size: 15px;
+    line-height: 1.6;
+    color: #333;
+
+    :deep(p) {
+      margin-bottom: 12px;
+    }
+
+    :deep(a) {
+      color: #409eff;
+      text-decoration: none;
+    }
+
+    :deep(img) {
+      max-width: 100%;
+      height: auto;
+    }
+  }
+}
+</style>

+ 62 - 0
components/singleImageUploader.vue

@@ -0,0 +1,62 @@
+<template>
+  <view class="single-image-uploader">
+    <popOver placement="bottom-end" :options="optionsList" key-name="text" isArrow ref="popoverRef"
+      @select="selectItem">
+      <i class="icon-font icon-camera"></i>
+    </popOver>
+  </view>
+</template>
+
+<script setup>
+import { ref, nextTick } from 'vue';
+import popOver from './popover.vue'
+import { uploadChooseImage, $upload, Toast } from '@/utils';
+import { t } from "@/locale"
+
+const props = defineProps({
+
+});
+
+const emit = defineEmits(['upload-success', 'change']);
+const optionsList = ref([{
+  type: 'camera',
+  text: '拍照'
+}, {
+  type: 'album',
+  text: '相册'
+}])
+
+const actionSheet = ref(null);
+const imageUrl = ref('');
+
+const selectItem = async (item) => {
+  try {
+    let file = await uploadChooseImage(item.type);
+    file.image = file.tempFile
+    const res = await $upload('image', file);
+    nextTick(() => {
+      imageUrl.value = res.data.url
+      emit('upload-success', imageUrl.value);
+      emit('change', imageUrl.value)
+    })
+  } catch (error) {
+    // Toast(t('上传失败'))
+  }
+}
+
+// 暴露方法给父组件
+defineExpose({
+  getImageUrl: () => imageUrl.value,
+  setImageUrl: (url) => {
+    imageUrl.value = url;
+    emit('change', url);
+  }
+});
+</script>
+
+<style scoped>
+.icon-camera {
+  color: #adb8cc;
+  font-size: 56rpx;
+}
+</style>

+ 138 - 0
components/swiper.vue

@@ -0,0 +1,138 @@
+<template>
+  <swiper
+    :current="current"
+    @change="swiperChange"
+    :indicator-dots="indicatorDots"
+    :indicator-color="indicatorColor"
+    :indicator-active-color="indicatorActiveColor"
+    :autoplay="autoplay"
+    :interval="interval"
+    :duration="duration"
+    :circular="circular"
+    :vertical="vertical"
+    class="swiper_list"
+    :style="{ width: width, height: height, '--borderRadius': borderRadius }"
+  >
+    <template v-if="listArr.length">
+      <swiper-item
+        v-for="(item, index) in listArr"
+        :key="index"
+        style="overflow-y: scroll"
+      >
+        <slot :name="'item_' + index">
+          <image
+            class="img"
+            lazy-load
+            :src="urlName ? item[urlName] : item"
+            alt=""
+            :style="{ width: width, height: height }"
+          >
+          </image>
+        </slot>
+      </swiper-item>
+    </template>
+    <template v-else-if="swiperList.length">
+      <swiper-item
+        v-for="(item, index) in swiperList"
+        :key="index"
+        @click="itemClick(item)"
+      >
+        <slot name="swiper">
+          <image
+            class="img"
+            lazy-load
+            :src="urlName ? item[urlName] : item"
+            alt=""
+            :style="{ width: width, height: height }"
+          >
+          </image>
+        </slot>
+      </swiper-item>
+    </template>
+    <slot name="cont"></slot>
+  </swiper>
+</template>
+
+<script setup>
+import { computed, onMounted } from "vue";
+import { useSystemStore } from "@/store";
+const useSystem = useSystemStore();
+
+const props = defineProps({
+  indicatorDots: Boolean,
+  indicatorColor: {
+    type: String,
+    default: "rgba(0, 0, 0, .3)",
+  },
+  indicatorActiveColor: {
+    type: String,
+    default: "#000000",
+  },
+  autoplay: Boolean,
+  interval: {
+    type: Number,
+    default: 3000,
+  },
+  duration: {
+    type: Number,
+    default: 500,
+  },
+  circular: Boolean,
+  vertical: Boolean,
+  urlName: {
+    type: String,
+    default: "picture",
+  },
+  listArr: {
+    type: Array,
+    default: () => [],
+  },
+  current: {
+    type: Number,
+    default: 0,
+  },
+  width: {
+    type: String,
+    default: "100%",
+  },
+  height: {
+    type: String,
+    default: "175px",
+  },
+  borderRadius: {
+    type: String,
+    default: "8px",
+  },
+});
+
+const emit = defineEmits(["change", "itemClick"]);
+
+const swiperList = computed(() => !props.listArr.length && useSystem.getBanner);
+
+const swiperChange = (e) => {
+  emit("change", e.detail);
+};
+const itemClick = (e) => {
+  emit("itemClick", e);
+};
+
+onMounted(() => {
+  // useSystem.setBanner();
+});
+</script>
+
+<style lang="less" scoped>
+@import url("@/style.less");
+
+.swiper_list {
+  border-radius: var(--borderRadius);
+  overflow: hidden;
+
+  .img {
+    width: 100%;
+    height: 100%;
+    display: block;
+    border-radius: var(--borderRadius);
+  }
+}
+</style>

+ 290 - 0
components/tabbar.vue

@@ -0,0 +1,290 @@
+<template>
+  <Theme>
+    <view class="cu-bar tabbar foot ZIndex tabbars">
+      <view
+        class="action"
+        @click="NavChange(item, index)"
+        v-for="(item, index) in navList"
+        :key="index"
+        :data-cur="item.name"
+      >
+        <!-- 图标和数量显示 -->
+        <view class="cuIcon-cu-image _item">
+          <view>
+            <i
+              class="icon-font"
+              :class="item.icon"
+              :style="
+                pageCur == item.name
+                  ? { color: 'var(--primary)' }
+                  : { color: '#c3cad9' }
+              "
+              v-if="item.icon"
+            ></i>
+            <image
+              class="img"
+              :src="pageCur == item.name ? item.img_active : item.img"
+              mode="heightFix"
+              v-else
+            ></image>
+          </view>
+          <!-- 数量徽章 -->
+          <view class="entry_num" v-if="item.num > 0">{{ item.num }}</view>
+        </view>
+
+        <view :class="pageCur == item.name ? 'tabbar_active' : 'tabbar_item'">
+          {{ t(item.title) }}
+        </view>
+      </view>
+    </view>
+  </Theme>
+</template>
+
+<script setup>
+import { onMounted, computed, watch, ref, nextTick } from "vue";
+import { useTabbarStore, useMessageStore, useShopStore } from "@/store";
+// 导入图片资源(保持不变)
+import channel from "@/static/tabbar/channel.png";
+import home from "@/static/tabbar/home.png";
+import home_active from "@/static/tabbar/home_active.png";
+import cart from "@/static/tabbar/cart.png";
+import cart_active from "@/static/tabbar/cart_active.png";
+import ship from "@/static/tabbar/ship.png";
+import ship_active from "@/static/tabbar/ship_active.png";
+import chat from "@/static/tabbar/chat.png";
+import chat_active from "@/static/tabbar/chat_active.png";
+import user from "@/static/tabbar/user.png";
+import user_active from "@/static/tabbar/user_active.png";
+import { t } from "@/locale";
+import { storeToRefs } from "pinia";
+import { query } from "@/utils";
+import { onShow } from "@dcloudio/uni-app";
+
+const useTabbar = useTabbarStore();
+const useShop = useShopStore();
+const useMessage = useMessageStore();
+const { globalMap } = storeToRefs(useMessage);
+const unreadCount = ref(0);
+
+// 1. 定义购物车数量计算属性(响应式)
+const cartNum = computed(() => useShop.getCartNum);
+
+const props = defineProps({
+  page: {
+    type: String,
+    default: "index",
+  },
+});
+
+const emit = defineEmits(["getTabbarHeight"]);
+
+// 2. 将navList定义为ref响应式数组(关键修改)
+const navList = ref([
+  {
+    name: "index",
+    title: "tabbar.首页",
+    img: home,
+    img_active: home_active,
+    num: 0,
+  },
+  {
+    name: "shop",
+    title: "tabbar.购物车",
+    img: cart,
+    img_active: cart_active,
+    num: cartNum.value, // 初始值
+  },
+  {
+    name: "chat",
+    title: "tabbar.咨询",
+    img: chat,
+    img_active: chat_active,
+    num: unreadCount.value,
+  },
+  {
+    name: "order",
+    title: "tabbar.订单",
+    img: ship,
+    img_active: ship_active,
+    num: 0,
+  },
+  {
+    name: "user",
+    title: "tabbar.我的",
+    img: user,
+    img_active: user_active,
+    num: 0,
+  },
+]);
+
+// 3. 监听cartNum变化,实时更新navList中购物车项的num(关键修改)
+watch(
+  cartNum,
+  (newNum) => {
+    // 找到购物车对应的项并更新数量
+    const cartItem = navList.value.find((item) => item.name === "shop");
+    if (cartItem) {
+      cartItem.num = newNum;
+    }
+  },
+  { immediate: true } // 初始化时立即执行一次
+);
+
+// 监听咨询消息数量(保持不变)
+watch(
+  () => globalMap.value.serviceChannel,
+  (newVal) => {
+    if (newVal) {
+      unreadCount.value = newVal.unreadCount;
+      const chatItem = navList.value.find((item) => item.name === "chat");
+      if (chatItem) {
+        chatItem.num = unreadCount.value;
+      }
+    }
+  },
+  { deep: true, immediate: true }
+);
+
+const pageCur = computed(() => useTabbar.setPageCur);
+
+const NavChange = (item, index) => {
+  if (item.name == pageCur.value) return;
+  if (item.name == "shop") {
+    uni.switchTab({
+      url: `/pages/shop/cart`,
+      success: () => {
+        useTabbar.getPageCur(item.name);
+        useTabbar.getPageIndex(index);
+      },
+    });
+  } else {
+    uni.switchTab({
+      url: `/pages/${item.name}/index`,
+      success: () => {
+        useTabbar.getPageCur(item.name);
+        useTabbar.getPageIndex(index);
+      },
+    });
+  }
+};
+const getHeight = async () => {
+  try {
+    const res = await query(".tabbar");
+    nextTick(() => {
+      emit("getTabbarHeight", res.height);
+    });
+  } catch (error) {}
+};
+
+onMounted(() => {
+  let num = navList.value.findIndex((item) => item.name == props.page);
+  if (num >= 0) {
+    useTabbar.getPageCur(props.page);
+  }
+});
+
+onShow(() => {
+  setTimeout(() => {
+    getHeight();
+  }, 200);
+});
+</script>
+
+<!-- 样式部分保持不变 -->
+<style>
+.ZIndex {
+  z-index: 2000;
+  bottom: 0;
+}
+
+/deep/ .cu-bar .content {
+  cursor: pointer;
+  pointer-events: unset;
+}
+
+.cu-tag.badge:not([class*="bg-"]) {
+  background-color: var(--red) !important;
+  color: var(--black);
+  position: absolute;
+  top: -10rpx;
+  right: 32%;
+}
+</style>
+<style lang="less" scoped>
+@import "@/static/css/theme.less";
+@import url("@/style.less");
+
+.tabbar {
+  background-color: var(--light);
+  bottom: 0;
+}
+
+.action {
+  display: flex !important;
+  justify-content: center;
+  align-items: center;
+  flex-direction: column;
+}
+
+._item {
+  width: max-content !important;
+  position: relative;
+
+  .icon-font {
+    font-size: 24px;
+  }
+
+  ._item {
+    height: 24px;
+    vertical-align: top;
+  }
+  .entry_num {
+    position: absolute;
+    top: -12rpx;
+    right: -14rpx;
+    background-color: var(--danger);
+    border: 1px solid var(--light);
+    color: var(--light);
+    width: 36rpx;
+    height: 36rpx;
+    border-radius: 50%;
+    .size(18rpx);
+    .flex_center();
+  }
+}
+
+.tabbar_item {
+  color: var(--text-01);
+  font-size: 10px;
+  line-height: 12px;
+  margin: 2px auto 0;
+}
+
+.tabbar_active {
+  font-size: 10px;
+  line-height: 12px;
+  margin: 2px auto 0;
+  color: var(--text-02);
+}
+
+.foot {
+  box-shadow: 0 -4px 6px #0000000d;
+}
+
+.cont_num {
+  position: absolute;
+  @width: 32rpx;
+  width: @width;
+  height: @width;
+  border-radius: 50%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  color: var(--light);
+  background-color: var(--red);
+  font-size: 24rpx;
+  z-index: 2;
+  right: -18rpx;
+  top: -6rpx;
+}
+</style>

+ 132 - 0
components/tabs.vue

@@ -0,0 +1,132 @@
+<template>
+  <view class="tab" :class="isRow ? 'tab_row' : ''">
+    <view
+      class="tab_list"
+      :class="[activeNum == index ? 'active' : '', isRow ? 'tab_list_row' : '']"
+      v-for="(item, index) in tabList"
+      :key="index"
+      @click="tabClick(item, index)"
+      :style="{ fontSize: size, height: height }"
+    >
+      <i class="icon-font" :class="item.icon" v-if="item.icon"></i>
+      <image class="img" :src="item.img" v-if="item.img"></image>
+      <trans :_t="keyName ? item[keyName] : item" v-if="!isTran" />
+      <text v-else>{{ keyName ? item[keyName] : item }}</text>
+      <view class="tab-badge" v-if="item.badge > 0">{{ item.badge }}</view>
+    </view>
+  </view>
+</template>
+
+<script setup>
+import { ref, computed, onMounted, watch, nextTick } from "vue";
+import { debounce } from "@/utils";
+
+const props = defineProps({
+  tabList: {
+    type: Object,
+    default: () => [],
+  },
+  keyName: {
+    type: String,
+    default: "",
+  },
+  active: {
+    type: Number,
+    default: 0,
+  },
+  size: {
+    type: String,
+    default: "32rpx",
+  },
+  height: {
+    type: String,
+    default: "110rpx",
+  },
+  isTran: Boolean,
+  isRow: Boolean,
+});
+const emit = defineEmits(["confirm"]);
+const activeNum = computed(() => props.active);
+
+const tabClick = (item, index) => {
+  emit("confirm", item, index);
+};
+</script>
+<style lang="less" scoped>
+@import url("@/style.less");
+
+.tab {
+  .ver();
+  gap: 16rpx;
+  overflow-x: auto;
+  overflow-y: hidden;
+  scrollbar-width: none;
+  -ms-overflow-style: none;
+  padding: 0 16rpx;
+  &.tab_row {
+    gap: 16rpx 44rpx;
+  }
+  &::-webkit-scrollbar {
+    display: none;
+  }
+  .tab_list {
+    flex: 1;
+    padding: 0 24rpx;
+    white-space: nowrap;
+    color: var(--text-01);
+    font-weight: 700;
+    // line-height: 60rpx;
+    position: relative;
+    text-align: center;
+    .flex_center();
+    &.tab_list_row {
+      flex: none;
+      height: auto;
+      min-width: auto;
+    }
+    .icon-font {
+      .size(48rpx);
+      font-weight: 400;
+    }
+    .img {
+      width: 48rpx;
+      height: 48rpx;
+      display: block;
+      margin-right: 6rpx;
+    }
+    .tab-badge {
+      position: absolute;
+      top: 16rpx;
+      right: 30%;
+      min-width: 32rpx;
+      height: 32rpx;
+      padding: 0 8rpx;
+      background-color: #f53f3f;
+      color: #fff;
+      .size(24rpx);
+      border-radius: 16rpx;
+      text-align: center;
+      line-height: 32rpx;
+    }
+
+    &::before {
+      position: absolute;
+      content: "";
+      bottom: 0;
+      left: 0;
+      right: 0;
+      height: 4px;
+      border-radius: 50rpx;
+      background-color: transparent;
+    }
+  }
+
+  .active {
+    color: var(--black);
+
+    &::before {
+      background-color: var(--black);
+    }
+  }
+}
+</style>

+ 74 - 0
components/theme.vue

@@ -0,0 +1,74 @@
+<template>
+  <view :class="`theme_${theme}`">
+    <slot></slot>
+    <GlobalLoading />
+  </view>
+</template>
+<script setup>
+import { computed } from "vue";
+import { useUserStore } from "@/store";
+import GlobalLoading from "./GlobalLoading.vue";
+const useUser = useUserStore();
+
+const theme = computed(() => useUser.getTheme);
+</script>
+<style lang="less">
+@import "@/static/css/theme.less";
+
+:deep(.cu-custom) {
+  .cu-bar {
+    background-color: var(--nav-background) !important;
+    color: var(--theme) !important;
+
+    .action {
+      .cuIcon-back {
+        color: var(--black) !important;
+      }
+    }
+
+    .right {
+      color: var(--black) !important;
+    }
+  }
+}
+
+.uni-picker-custom {
+  .uni-picker-header {
+    background-color: var(--dark);
+  }
+}
+
+:deep(.uni-popup) {
+  .uni-popup-dialog {
+    background-color: var(--bg) !important;
+
+    .uni-dialog-title {
+      .uni-popup__info {
+        color: var(--black);
+      }
+    }
+
+    .uni-dialog-content {
+      color: var(--theme);
+
+      .uni-dialog-input {
+        border-color: var(--border);
+        background-color: var(--dark);
+        color: var(--theme);
+      }
+    }
+
+    .uni-dialog-button {
+      .uni-dialog-button-text {
+        color: var(--gray);
+      }
+    }
+
+    .uni-dialog-button:last-child {
+      .uni-dialog-button-text {
+        color: var(--theme);
+      }
+    }
+  }
+}
+</style>

+ 49 - 0
components/tooltip.vue

@@ -0,0 +1,49 @@
+<template>
+  <view class="tips">
+    <view class="tips_title" v-if="show">{{ t(title) }}</view>
+    <view class="tip_cont">
+      <slot></slot>
+    </view>
+  </view>
+</template>
+<script setup>
+import { t } from "@/locale"
+const props = defineProps({
+  title: {
+    type: String,
+    default: ''
+  },
+  show: Boolean
+})
+</script>
+<style lang="less" scoped>
+.tips {
+  position: relative;
+
+  .tips_title {
+    max-width: 80vw;
+    background-color: #303133;
+    color: var(--light);
+    padding: 10rpx 22rpx;
+    border-radius: 8rpx;
+    font-size: 24rpx;
+    position: absolute;
+    top: -60rpx;
+    left: 50%;
+    transform: translateX(-50%);
+    width: fit-content;
+    text-wrap: nowrap;
+
+    &::before {
+      content: '';
+      position: absolute;
+      left: 50%;
+      bottom: -12rpx;
+      transform: translateX(-50%);
+      border-left: 14rpx solid transparent;
+      border-right: 14rpx solid transparent;
+      border-top: 14rpx solid #303133;
+    }
+  }
+}
+</style>

+ 16 - 0
components/trans.vue

@@ -0,0 +1,16 @@
+<template>
+  <text>{{ !!_t ? t(_t, { ...options }) : '' }}</text>
+</template>
+
+<script setup>
+import { t } from '@/locale';
+
+const props = defineProps({
+  _t: String,
+  options: {
+    type: Object,
+    default: () => ({})
+  }
+})
+// const { t } = useI18n();
+</script>

+ 175 - 0
components/videoUpload.vue

@@ -0,0 +1,175 @@
+<template>
+  <view class="video-uploader">
+    <up-upload
+      :file-list="fileList"
+      :max-count="maxCount"
+      accept="video"
+      :preview-full-image="false"
+      :max-size="maxSize * 1024 * 1024"
+      @after-read="handleAfterRead"
+      @delete="handleDelete"
+    >
+      <view class="upload-btn">
+        <u-icon name="plus" size="32" color="#999"></u-icon>
+        <text class="upload-text">{{
+          fileList.length ? t("重新选择") : t("选择视频")
+        }}</text>
+      </view>
+    </up-upload>
+
+    <!-- 预览 -->
+    <view v-if="fileList.length" class="preview">
+      <video class="preview-video" :src="fileList[0].url" controls></video>
+    </view>
+
+    <!-- 上传进度 -->
+    <u-line-progress
+      v-if="uploading"
+      :percentage="progress"
+      stroke-width="6"
+      active-color="#3c9cff"
+      :show-text="true"
+      class="preview"
+    />
+  </view>
+</template>
+
+<script setup>
+import { ref, watch } from "vue";
+import { $uploadFile, Toast } from "@/utils";
+import { t } from "@/locale";
+
+const props = defineProps({
+  // 初始图片列表
+  modelValue: {
+    type: Array,
+    default: () => [],
+  },
+  // 最大上传数量
+  maxCount: {
+    type: Number,
+    default: 1,
+  },
+  maxSize: {
+    type: Number,
+    default: 50,
+  },
+  // 是否多选
+  multiple: {
+    type: Boolean,
+    default: false,
+  },
+  disabled: {
+    type: Boolean,
+    default: false,
+  },
+  // 上传按钮文字
+  uploadText: {
+    type: String,
+    default: "上传图片",
+  },
+});
+const fileList = ref([]);
+const uploading = ref(false);
+const progress = ref(0);
+
+const emit = defineEmits(["update:modelValue", "success", "delete", "error"]);
+
+watch(
+  () => props.modelValue,
+  (newVal) => {
+    fileList.value = newVal.map((item) => {
+      return typeof item === "string" ? { url: item } : item;
+    });
+  },
+  { immediate: true }
+);
+/**
+ * 文件选择后处理
+ */
+const handleAfterRead = async (event) => {
+  const file = Array.isArray(event.file) ? event.file[0] : event.file;
+  uploading.value = true;
+  progress.value = 0;
+  try {
+    const uploadFiles = Array.isArray(file) ? file : [file];
+    const results = await Promise.all(
+      uploadFiles.map((file) => {
+        return $uploadFile({
+          filePath: file.url,
+          name: "file",
+          onProgress(e) {
+            progress.value = e.progress;
+          },
+        });
+      })
+    );
+    const newFiles = results.map((res) => ({
+      url: res.data.url,
+      name: res.data.name,
+      status: "success",
+    }));
+    fileList.value = [...fileList.value, ...newFiles];
+    emit("update:modelValue", fileList.value);
+    emit("success", newFiles);
+    Toast(t("成功"));
+  } catch (error) {
+    emit("error", error);
+    Toast(t("失败"));
+  } finally {
+    uploading.value = false;
+  }
+};
+
+const handleDelete = (event) => {
+  const { index } = event;
+  const deletedFile = fileList.value[index];
+  fileList.value.splice(index, 1);
+  progress.value = 0;
+  emit("update:modelValue", fileList.value);
+  emit("delete", deletedFile);
+};
+
+defineExpose({
+  clearFiles: () => {
+    fileList.value = [];
+    progress.value = 0;
+    emit("update:modelValue", []);
+  },
+});
+</script>
+
+<style lang="less" scoped>
+.video-uploader {
+  padding: 10rpx;
+
+  .upload-btn {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    width: 150rpx;
+    height: 150rpx;
+    border: 1px dashed #c0c4cc;
+    border-radius: 8rpx;
+    background-color: #f5f7fa;
+
+    .upload-text {
+      margin-top: 10rpx;
+      font-size: 24rpx;
+      color: #909399;
+    }
+  }
+
+  .preview {
+    margin-top: 20rpx;
+
+    .preview-video {
+      width: 100%;
+      max-height: 200rpx;
+      border-radius: 12rpx;
+      background-color: #000;
+    }
+  }
+}
+</style>

+ 313 - 0
components/y-video copy 2.vue

@@ -0,0 +1,313 @@
+<template>
+  <view>
+    <DomVideoPlayer class="video" :style="{ 'height': height + 'px' }" :ref="`domVideoPlayer_${current}`" object-fit='contain'
+      :controls="controls" :autoplay="autoplay" :loop="loop" :src="item.src" :playback-rate="playbackRate"
+      @play="onPlay" @pause="onPause" @ended="onEnded" @timeupdate="onTimeUpdate" @durationchange="onDurationChange"
+      @ratechange="onRateChange" @fullscreenchange="onFullscreenChange" @tap.stop="change" />
+    <view class="play-btn" :style="{ left: `${width / 2}px`, top: `${height / 2}px` }" v-if="showPlayBtn">
+      <up-icon name="play-right-fill" size="16" color="var(--light)"></up-icon>
+    </view>
+    <!-- loading -->
+    <image class="loading" :style="{ left: `${width / 2}px`, top: `${height / 2}px` }" src="@/static/loading.gif"
+      v-if="loading">
+    </image>
+    <view class="info" @click.stop="$emit('showMulu')">
+      <text class="text title">@{{ item.title }}</text>
+      <text class="text" style="margin-top: 25rpx;font-size: 26rpx;line-height: 40rpx;">{{ item.desc ||
+        '讲述温暖出行故事,描绘人间烟火,大锁与陈珂从原来的两条“平行线”,变成了感情不断升温的情侣...'}}</text>
+    </view>
+    <view class="btns" :style="{ height: height + 'px' }" @click.stop>
+      <image class="toux" style="margin-bottom: 40rpx;" src="@/static/tx.png"></image>
+      <image class="btn" :src="isZan ? '/static/dianzan_h.png' : '/static/dianzan.png'" @click="isZan = !isZan">
+      </image>
+      <text class="text">0</text>
+      <image class="btn" src="@/static/pinglun.png" @click.stop="emit('showPinglun')"></image>
+      <text class="text">0</text>
+      <image class="btn" :src="isSc ? '/static/shoucang_h.png' : '/static/shoucang.png'" @click="isSc = !isSc">
+      </image>
+      <text class="text">0</text>
+      <image class="btn" src="@/static/fenxiang.png?v=6"></image>
+    </view>
+    <view class="progress">
+      <view class="line" :style="{ width: lineWidth + 'px' }"></view>
+    </view>
+    <view class="_duration" @click.stop>
+      <view style="flex-direction: row;flex: 1;">
+        <text class="text">{{ currentTime ? currentTime : '00:00' }}</text>
+        <text class="text" style="margin: 0 10rpx;">/</text>
+        <text class="text" style="opacity: .5;">{{ duration ? duration : '00:00' }}</text>
+      </view>
+      <image class="shengyin" :src="muted ? '/static/jingyin.png' : '/static/yinliang.png'" @click="muted = !muted">
+      </image>
+      <image class="shengyin" style="margin-left:20rpx" src="/static/quanping.png" @click="fullScreen">
+      </image>
+    </view>
+  </view>
+</template>
+
+
+<script setup>
+import { ref, computed,onUnmounted } from 'vue'
+import DomVideoPlayer from '@/components/DomVideoPlayer'
+import { onLaunch, onShow, onHide } from "@dcloudio/uni-app";
+
+const systemInfo = uni.getSystemInfoSync();
+const width = systemInfo.screenWidth;
+const height = systemInfo.screenHeight - 50;
+// 将xx秒转为 xx:xx 分秒格式
+const formatSec2Time = (time) => {
+  const min = Math.floor(time / 60)
+  const sec = Math.floor(time % 60)
+  return `${min}:${sec < 10 ? '0' + sec : sec}`
+}
+const props = defineProps({
+  info: {
+    type: Object,
+    default: () => { }
+  },
+  item: {
+    type: Object,
+    default: () => { }
+  },
+  index: {
+    type: Number,
+    default: -1
+  },
+  current: {
+    type: Number,
+    default: 0
+  }
+})
+
+const playing = ref(true)
+const loop = ref(true)
+const controls = ref(false)
+const autoplay = ref(true)
+const playbackRate = ref(1)
+const currentTime = ref(0)
+const duration = ref(0)
+const domVideoPlayer = ref(null);
+const showPlayBtn = ref(false);
+const loading = ref(false);
+const lineWidth = ref(0);
+const muted = ref(false);
+const isZan = ref(false);
+const isSc = ref(false);
+const isFullscreen = ref(false);
+
+const change = () => {
+  if (!isFullscreen.value) {
+    playing.value ? pause() : play()
+  }
+}
+const play = () => {
+  showPlayBtn.value = false
+  playing.value = true
+  domVideoPlayer.value.play()
+}
+const pause = () => {
+  showPlayBtn.value = true
+  playing.value = false
+  domVideoPlayer.value.pause()
+}
+const onPlay = () => {
+  console.log('onPlay')
+  if (props.current != props.index) {
+    domVideoPlayer.value.pause()
+    playing.value = false
+  } else {
+    playing.value = true
+    showPlayBtn.value = false
+    loading.value = false
+  }
+}
+
+const onPause = () => {
+  console.log('onPause')
+  showPlayBtn.value = true
+  playing.value = false
+}
+
+const onEnded = () => {
+  console.log('onEnded')
+  playing.value = false
+}
+
+const fullScreen = () => {
+  console.log('全屏');
+
+  domVideoPlayer.value.fullScreen();
+}
+const onDurationChange = (e) => {
+  console.log(e);
+
+  if (loading.value) loading.value = false;
+  if (!playing.value) playing.value = true;
+  if (!duration.value || duration.value == '00:00') duration.value = secondToTime(e, 1)
+}
+const onTimeUpdate = (e) => {
+  currentTime.value = secondToTime(e)
+  lineWidth.value = e / duration.value * width
+}
+const secondToTime = (s, n) => {
+  const t = parseInt(s)
+  const hours = Math.floor(t / (60 * 60));
+  const seconds = t % (60 * 60)
+  const minutes = Math.floor(seconds / 60);
+  const seconds2 = seconds % 60
+  if (hours > 0) {
+    return `${hours}:${minutes.toString().padStart(2, '0')}:${seconds2.toString().padStart(2, '0')}`;
+  } else {
+    return `${minutes.toString().padStart(2, '0')}:${seconds2.toString().padStart(2, '0')}`;
+  }
+}
+const onRateChange = (e) => {
+  console.log('onRateChange', e)
+  playbackRate.value = e
+}
+
+const onFullscreenChange = (e) => {
+  console.log('onFullScreenChange', e)
+}
+// defineExpose({
+//   play
+// })
+onUnmounted(()=>{
+  console.log('组件卸载');
+  
+})
+onHide(() => {
+  pause()
+})
+</script>
+
+<style scoped lang="less">
+@import url('@/style.less');
+
+.action-box {
+  margin-top: 30rpx;
+  padding: 0 60rpx;
+}
+
+.action-box button {
+  margin-top: 10rpx;
+}
+
+.video {
+  width: 750rpx;
+  background-color: #000000;
+}
+
+.text {
+  color: #fff;
+  font-size: 28rpx;
+}
+
+.info {
+  position: absolute;
+  z-index: 100;
+  left: 0;
+  bottom: 50px;
+  width: 750rpx;
+  padding: 30rpx 140rpx 130rpx 30rpx;
+  .flex();
+  flex-direction: column;
+
+  .title {
+    font-size: 36rpx;
+    max-width: calc(750rpx - 140rpx - 60rpx);
+  }
+
+  .des {
+    background-color: rgba(255, 255, 255, .1);
+    border-radius: 10rpx;
+    padding: 15rpx 20rpx;
+
+    .text {
+      font-size: 24rpx;
+    }
+  }
+}
+
+.btns {
+  position: absolute;
+  z-index: 100;
+  right: 0;
+  bottom: 0;
+  width: 140rpx;
+  .flex_position(flex-end);
+  flex-direction: column;
+  padding-bottom: 340rpx;
+
+  .toux {
+    height: 88rpx;
+    width: 88rpx;
+    border-radius: 50%;
+    object-fit: cover;
+  }
+
+  .btn {
+    height: 66rpx;
+    width: 66rpx;
+  }
+
+  .text {
+    margin-top: 10rpx;
+    margin-bottom: 30rpx;
+    font-size: 26rpx;
+  }
+}
+
+.play-btn {
+  height: 68rpx;
+  width: 68rpx;
+  border-radius: 50%;
+  background-color: rgba(0, 0, 0, .5);
+  position: absolute;
+  margin-left: -34rpx;
+  margin-top: -34rpx;
+  .flex_center();
+}
+
+.loading {
+  position: absolute;
+  height: 60rpx;
+  width: 60rpx;
+  margin-left: -30rpx;
+  margin-top: -30rpx;
+}
+
+.progress {
+  width: 750rpx;
+  height: 90rpx;
+  position: absolute;
+  left: 0;
+  bottom: 50px;
+
+  .line {
+    height: 2rpx;
+    width: 500rpx;
+    background-color: rgba(255, 255, 255, .35);
+    transform: scaleY(.1);
+  }
+
+}
+
+._duration {
+  position: absolute;
+  height: 88rpx;
+  .ver();
+  left: 0;
+  width: 750rpx;
+  bottom: 50px;
+  z-index: 101;
+  padding-left: 30rpx;
+  padding-right: 30rpx;
+  background-color: rgba(255, 255, 255, .05);
+}
+
+.shengyin {
+  height: 38rpx;
+  width: 38rpx;
+}
+</style>

+ 400 - 0
components/y-video.vue

@@ -0,0 +1,400 @@
+<template>
+  <view>
+    <DomVideoPlayer class="video" :style="{ 'height': height + 'px' }" ref="domVideoPlayer" object-fit='contain'
+      :controls="controls" :autoplay="autoplay" :loop="loop" :src="item.video" :key="key" :muted="muted"
+      :playback-rate="playbackRate" @play="onPlay" @pause="onPause" @ended="onEnded" @error="onError"
+      @timeupdate="onTimeUpdate" @durationchange="onDurationChange" @ratechange="onRateChange"
+      @fullscreenchange="onFullscreenChange" @tap.stop="change" />
+    <view class="play-btn" @tap.stop="change" :style="{ left: `${width / 2}px`, top: `${height / 2}px` }"
+      v-if="showPlayBtn">
+      <up-icon name="play-right-fill" size="16" color="var(--light)"></up-icon>
+    </view>
+    <!-- loading -->
+    <image class="loading" :style="{ left: `${width / 2}px`, top: `${height / 2}px` }" src="@/static/loading.gif"
+      v-if="loading">
+    </image>
+    <view class="info" @click.stop="$emit('showMulu')">
+      <text class="text title">@{{ item.user && item.user.realname }}</text>
+      <text class="text" style="margin-top: 25rpx;font-size: 26rpx;line-height: 40rpx;">{{ item.title }}</text>
+      <view class="shop_box" @click.stop="toShopDeatils(item)">
+        <up-image :src="item.extend_data && item.extend_data.pic_url" width="70rpx" height="70rpx" radius="4">
+          <template #error>
+            <image class="toux" src="@/static/tx.png"></image>
+          </template>
+        </up-image>
+        <text class="title">{{ item.extend_data && item.extend_data.title }}</text>
+      </view>
+    </view>
+
+    <view class="btns" :style="{ height: height + 'px' }" @click.stop>
+      <view class="userimg">
+        <up-image :src="item.user && item.user.userimg" shape="circle" width="88rpx" height="88rpx">
+          <template #error>
+            <image class="toux" src="@/static/tx.png"></image>
+          </template>
+
+        </up-image>
+        <view class="user_bottom" @click.stop="$emit('follow')" v-if="!item.is_follow">+</view>
+      </view>
+
+      <image class="btn" :src="item.is_goods ? '/static/dianzan_h.png' : '/static/dianzan.png'"
+        @click.stop="$emit('like')">
+      </image>
+      <text class="text">{{ item.goods }}</text>
+      <image class="btn" src="@/static/pinglun.png" @click.stop="$emit('showPinglun')"></image>
+      <text class="text">{{ item.comments }}</text>
+      <image class="btn" :src="item.is_collect ? '/static/shoucang_h.png' : '/static/shoucang.png'"
+        @click.stop="$emit('collect')">
+      </image>
+      <text class="text">{{ item.collects }}</text>
+      <image class="btn" src="@/static/fenxiang.png"></image>
+    </view>
+    <!-- <view class="progress">
+      <view class="line" :style="{ width: lineWidth + 'px' }"></view>
+    </view> -->
+    <view class="_duration" @click.stop>
+      <view style="flex-direction: row;flex: 1;">
+        <text class="text">{{ currentTime ? currentTime : '00:00' }}</text>
+        <text class="text" style="margin: 0 10rpx;">/</text>
+        <text class="text" style="opacity: .5;">{{ duration ? duration : '00:00' }}</text>
+      </view>
+      <image class="shengyin" :src="muted ? '/static/jingyin.png' : '/static/yinliang.png'" @click="muted = !muted">
+      </image>
+      <image class="shengyin" style="margin-left:20rpx" src="/static/quanping.png" @click="fullScreen">
+      </image>
+    </view>
+  </view>
+</template>
+
+
+<script>
+import DomVideoPlayer from '@/components/DomVideoPlayer'
+const systemInfo = uni.getSystemInfoSync();
+import { t } from "@/locale"
+export default {
+  components: {
+    DomVideoPlayer
+  },
+  props: {
+    info: {
+      type: Object,
+      default: () => { }
+    },
+    item: {
+      type: Object,
+      default: () => { }
+    },
+    index: {
+      type: Number,
+      default: -1
+    },
+    current: {
+      type: Number,
+      default: 0
+    }
+  },
+  data() {
+    return {
+      playing: true,
+      loop: true,
+      controls: false,
+      autoplay: true,
+      playbackRate: 1,
+      currentTime: 0,
+      duration: 0,
+      showPlayBtn: false,
+      loading: false,
+      lineWidth: 0,
+      muted: false,
+      isZan: false,
+      isSc: false,
+      isFullscreen: false,
+      width: systemInfo.screenWidth,
+      height: systemInfo.screenHeight - 1 - 100,
+      key: new Date().getTime(),
+    }
+  },
+  watch: {
+    current: {
+      handler(val) {
+        val == this.index ? this.play() : this.pause()
+      }
+    },
+    playing: {
+      handler(val) {
+        // #ifdef APP-PLUS
+        uni.setKeepScreenOn({
+          keepScreenOn: val
+        });
+        // // #endif
+      }
+    }
+  },
+  methods: {
+    change() {
+      if (!this.isFullscreen) {
+        this.playing ? this.pause() : this.play()
+      }
+    },
+    play() {
+      this.showPlayBtn = false
+      this.playing = true;
+      this.$refs.domVideoPlayer.play();
+      // this.$refs[`domVideoPlayer${this.current}`] && this.$refs[`domVideoPlayer${this.current}`].play();
+    },
+    pause() {
+      this.showPlayBtn = true
+      this.playing = false
+      // this.$refs.domVideoPlayer.pause()
+      this.$refs.domVideoPlayer.pause()
+    },
+    onPlay() {
+      if (this.current != this.index) {
+        this.$refs.domVideoPlayer.pause()
+        this.playing = false
+      } else {
+        this.playing = true
+        this.showPlayBtn = false
+        this.loading = false
+        this.$emit('play', this.item)
+      }
+    },
+    onPause() {
+      this.showPlayBtn = true
+      this.playing = false
+    },
+    onEnded() {
+      this.currentTime = 0
+      this.playing = false;
+      setTimeout(() => {
+        this.key = new Date().getTime()
+      }, 150)
+    },
+    onError() {
+      console.log("onError");
+      if (this.current == this.index) {
+        uni.showToast({
+          title: '播放失败',
+          duration: 1000,
+          icon: 'none'
+        })
+        setTimeout(() => {
+          this.key = new Date().getTime()
+          this.onEnded()
+        }, 1000)
+      }
+    },
+    fullScreen() {
+      this.$refs.domVideoPlayer.fullScreen();
+    },
+    onDurationChange(e) {
+      if (this.loading) this.loading = false;
+      if (!this.playing) this.playing = true;
+      if (!this.duration || this.duration == '00:00') this.duration = this.secondToTime(e, 1)
+    },
+    onTimeUpdate(e) {
+      this.currentTime = this.secondToTime(e)
+      this.lineWidth = e / this.duration * this.width
+    },
+    secondToTime(s, n) {
+      const t = parseInt(s)
+      const hours = Math.floor(t / (60 * 60));
+      const seconds = t % (60 * 60)
+      const minutes = Math.floor(seconds / 60);
+      const seconds2 = seconds % 60
+      if (hours > 0) {
+        return `${hours}:${minutes.toString().padStart(2, '0')}:${seconds2.toString().padStart(2, '0')}`;
+      } else {
+        return `${minutes.toString().padStart(2, '0')}:${seconds2.toString().padStart(2, '0')}`;
+      }
+    },
+    onRateChange(e) {
+      this.playbackRate = e
+    },
+    onFullscreenChange(e) {
+      console.log('onFullScreenChange', e)
+    },
+    toShopDeatils(item) {
+      uni.navigateTo({
+        url: `/pages/shop/productDetail?channel=${item.channel}&goods_id=${item.extend_data.num_iid}`
+      })
+    }
+  },
+
+  onhide() {
+    this.pause()
+  }
+}
+</script>
+
+<style scoped lang="less">
+@import url('@/style.less');
+
+.action-box {
+  margin-top: 30rpx;
+  padding: 0 60rpx;
+}
+
+.action-box button {
+  margin-top: 10rpx;
+}
+
+.video {
+  width: 750rpx;
+  background-color: #000000;
+}
+
+.text {
+  color: #fff;
+  font-size: 28rpx;
+}
+
+.info {
+  position: absolute;
+  z-index: 100;
+  left: 0;
+  bottom: 50px;
+  width: 750rpx;
+  padding: 30rpx 140rpx 130rpx 30rpx;
+  .flex();
+  flex-direction: column;
+
+  .title {
+    font-size: 36rpx;
+    max-width: calc(750rpx - 140rpx - 60rpx);
+  }
+
+  .des {
+    background-color: rgba(255, 255, 255, .1);
+    border-radius: 10rpx;
+    padding: 15rpx 20rpx;
+
+    .text {
+      font-size: 24rpx;
+    }
+  }
+}
+
+.btns {
+  position: absolute;
+  z-index: 100;
+  right: 0;
+  bottom: 0;
+  width: 140rpx;
+  .flex_position(flex-end);
+  flex-direction: column;
+  padding-bottom: 340rpx;
+
+  .userimg {
+    position: relative;
+    margin-bottom: 40rpx;
+
+    .user_bottom {
+      position: absolute;
+      left: 50%;
+      top: 71rpx;
+      margin-left: -17rpx;
+      // margin-top: -14rpx;
+      // margin-bottom: 40rpx;
+      height: 34rpx;
+      width: 34rpx;
+      border-radius: 50%;
+      background: var(--red);
+      color: var(--bg);
+      text-align: center;
+      line-height: 34rpx;
+      z-index: 9;
+    }
+  }
+
+
+
+  .toux {
+    height: 88rpx;
+    width: 88rpx;
+    border-radius: 50%;
+    object-fit: cover;
+  }
+
+  .btn {
+    height: 66rpx;
+    width: 66rpx;
+  }
+
+  .text {
+    margin-top: 10rpx;
+    margin-bottom: 30rpx;
+    font-size: 26rpx;
+  }
+}
+
+.play-btn {
+  height: 68rpx;
+  width: 68rpx;
+  border-radius: 50%;
+  background-color: rgba(0, 0, 0, .5);
+  position: absolute;
+  margin-left: -34rpx;
+  margin-top: -34rpx;
+  .flex_center();
+}
+
+.loading {
+  position: absolute;
+  height: 60rpx;
+  width: 60rpx;
+  margin-left: -30rpx;
+  margin-top: -30rpx;
+}
+
+.progress {
+  width: 750rpx;
+  height: 90rpx;
+  position: absolute;
+  left: 0;
+  bottom: 100rpx;
+
+  .line {
+    height: 2rpx;
+    width: 500rpx;
+    background-color: rgba(255, 255, 255, .35);
+    transform: scaleY(.1);
+  }
+
+}
+
+._duration {
+  position: absolute;
+  height: 88rpx;
+  .ver();
+  left: 0;
+  width: 750rpx;
+  bottom: 50px;
+  z-index: 101;
+  padding-left: 30rpx;
+  padding-right: 30rpx;
+  background-color: rgba(255, 255, 255, .05);
+}
+
+.shengyin {
+  height: 38rpx;
+  width: 38rpx;
+}
+
+.shop_box {
+  .hor;
+  max-width: 400rpx;
+  height: 88rpx;
+  border-radius: 20rpx;
+  background: #3d3d3d;
+  padding: 10rpx;
+  box-sizing: border-box;
+
+  .title {
+    .ellipsis(2);
+    .size(24rpx);
+    margin-left: 4rpx;
+    color: var(--bg);
+  }
+}
+</style>

+ 24 - 0
index.html

@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="UTF-8" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
+  <script>
+    var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
+      CSS.supports('top: constant(a)'))
+    document.write(
+      '<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
+      (coverSupport ? ', viewport-fit=cover' : '') + '" />')
+  </script>
+  <title></title>
+  <!--preload-links-->
+  <!--app-context-->
+</head>
+
+<body>
+  <div id="app"><!--app-html--></div>
+  <script type="module" src="/main.js"></script>
+</body>
+
+</html>

+ 591 - 0
locale/en.json

@@ -0,0 +1,591 @@
+{
+  "tabbar.首页": "Home",
+  "tabbar.购物车": "Cart",
+  "tabbar.社区": "Community",
+  "tabbar.咨询": "Consult",
+  "tabbar.我的": "Me",
+  "公告": "Announcement",
+  "团队服务升级报告": "Hoobuy Service Upgrade Notice",
+  "电子邮件": "Email",
+  "密码": "Password",
+  "电子邮件为必填项": "Email is required",
+  "密码是必需的": "Password is required",
+  "登录": "Login",
+  "忘记密码": "Forgot password?",
+  "注册": "Register",
+  "删除账户": "Delete Account",
+  "账户删除成功": "Account deleted successfully",
+  "cancelRegistrationTips": "Warning: After the account is deleted, all data will be permanently removed and cannot be recovered. Please proceed with caution.",
+  "请输入密码验证身份": "Verify password",
+  "请输入密码": "Please enter password",
+  "验证通过后将执行账户删除操作": "After verification is passed, the account deletion operation will be executed.",
+  "密码不能为空": "Password cannot be empty",
+  "确认密码": "Confirm Password",
+  "已有账户": "Already have an account?",
+  "邀请码": "Invitation Code (Not Required)",
+  "我已阅读并接受": "I have read and accept",
+  "和": "and",
+  "语言/币种": "Language/Currency",
+  "直淘中国无差价": "Direct purchase from China at original price",
+  "主页": "Home",
+  "订单": "Orders",
+  "仓库": "Warehouse",
+  "包裹": "Parcels",
+  "钱包": "Wallet",
+  "在线客服": "Online Support",
+  "拍照": "Take Photo",
+  "相册": "Album",
+  "商品的链接或名称": "Product link or name",
+  "运费估算": "Ship Cost",
+  "新手教程": "Beginner's Guide",
+  "社群": "Community",
+  "装运": "Shipment",
+  "余额": "Balance",
+  "优惠券": "Coupons",
+  "收藏夹": "Favorites",
+  "推荐官": "Referral",
+  "消息": "Messages",
+  "加入社群": "Join Community",
+  "帮助中心": "Help Center",
+  "联系我们": "Contact Us",
+  "设置": "Settings",
+  "好的": "OK",
+  "语言": "Language",
+  "币种": "Currency",
+  "搜索": "Search",
+  "搜索历史": "Search History",
+  "热门搜索": "Popular Searches",
+  "1688": "1688",
+  "淘宝": "Taobao",
+  "JD": "JD",
+  "无数据": "No data",
+  "正在加载中": "Loading",
+  "加载更多": "Load More",
+  "没有更多了": "No more data",
+  "综合": "Comprehensive",
+  "价格": "Price",
+  "搜索条款": "Search Terms",
+  "搜索条款内容": "All products displayed in search results are from third-party platforms. Hoobuy only provides information search, purchasing and shipping services. We do not verify or evaluate product quality or authenticity.",
+  "您已同意搜索条款": "You have agreed to the search terms.",
+  "关闭": "Close",
+  "搜索类似产品": "Search similar products",
+  "产品链接": "Product Link",
+  "分享": "Share",
+  "刷新": "Refresh",
+  "加入": "Join",
+  "立即购买": "Buy Now",
+  "加入购物车": "Add to Cart",
+  "购买记录": "Purchase History",
+  "销售量": "Sales Volume",
+  "平均送达时间": "Average Delivery Time",
+  "重量(克)": "Weight (g)",
+  "尺寸": "Size",
+  "进入商店": "Visit Store",
+  "产品详情": "Product Details",
+  "产品": "Product",
+  "细节": "Details",
+  "更多的": "More",
+  "规格参数": "Specifications",
+  "你可能会喜欢": "You May Also Like",
+  "提交": "Submit",
+  "全部": "All",
+  "删除": "Delete",
+  "不包括运费": "Excluding Shipping",
+  "数量": "Quantity",
+  "最小购买数量": "Minimum Quantity: 1",
+  "库存": "Stock",
+  "确认订单": "Confirm Order",
+  "总计不含国际运费": "Total (Excluding Int'l Shipping)",
+  "违禁物品说明": "《Prohibited Items Notice》",
+  "《服务条款》": "《Terms of Service》",
+  "退货说明": "《Return Policy》",
+  "免责声明": "《Disclaimer》",
+  "我已阅读并同意": "I have read and agree",
+  "订单总价": "Total order price",
+  "总价": "Total Price",
+  "运费到仓库": "Domestic Shipping",
+  "折扣": "Discount",
+  "温馨提示": "Reminder",
+  "提示内容": "After submitting and paying for your order, please wait for the seller to ship. Submit international parcel order after arrival at warehouse.",
+  "请阅读并同意": "Please read and agree",
+  "支付方式": "Payment Method",
+  "请在": "Please complete payment before",
+  "取消付款提示": "or order will be cancelled.",
+  "余额不足需充值": "Insufficient balance, please recharge",
+  "用余额支付": "Pay with Balance",
+  "推荐": "Recommended",
+  "充值": "Recharge",
+  "支付": "Pay",
+  "手续费": "Service Fee",
+  "名称订单号商品名称": "Name/Order No./Product Name",
+  "待付款": "Unpaid",
+  "筛选": "Filter",
+  "创建时间": "Created At",
+  "订单时间": "Order Time",
+  "重置": "Reset",
+  "开始日期": "Start Date",
+  "结束日期": "End Date",
+  "不支退货换货": "No Returns/Exchanges >",
+  "结束时间": "End Time",
+  "取消": "Cancel",
+  "删除订单": "Delete Order",
+  "全选": "Select All",
+  "合并付款": "Combine Payment",
+  "订单详情": "Order Details",
+  "订单流程": "Order Process",
+  "处理中": "Processing",
+  "订单号": "Order Number",
+  "复制": "Copy",
+  "复制成功": "Copied",
+  "小计": "Subtotal",
+  "国内货运": "Domestic Shipping",
+  "订单补充付款": "Additional Payment",
+  "涉及增值服务费": "Including Value-added Service Fee",
+  "店铺": "Store",
+  "提醒": "Reminder",
+  "您确定要从收藏中移除该店铺吗": "Are you sure to remove this store from favorites?",
+  "您确定要从收藏中移除该产品吗": "Are you sure to remove this product from favorites?",
+  "默认": "Default",
+  "收件地址": "Shipping Address",
+  "账户地址": "Account Address",
+  "关于Hoobuy": "About Hoobuy",
+  "隐私政策": "Privacy Policy",
+  "服务条款": "Terms of Service",
+  "ID": "ID",
+  "修改密码tips": "Stronger passwords make your account more secure. We recommend changing it regularly.",
+  "交易密码tips": "Password verification is required when using balance for transactions to enhance account security.",
+  "账户安全": "Account Security",
+  "修改登录密码": "Change Password",
+  "编辑": "Edit",
+  "新交易密码": "New Transaction Password",
+  "登录密码": "Login Password",
+  "新密码": "New Password",
+  "再次输入密码": "Re-enter Password",
+  "交易密码": "Transaction Password",
+  "原交易密码": "Original Transaction Password",
+  "打包": "Pack",
+  "请选择地址": "Please select address",
+  "添加收货地址": "Add Shipping Address",
+  "确认": "Confirm",
+  "添加送货地址": "Add Delivery Address",
+  "收件人": "Recipient",
+  "名": "First Name",
+  "姓": "Last Name",
+  "地区": "Region",
+  "详细地址": "Detailed Address",
+  "输入公寓号码街道道路地址": "Enter apartment number, street/road address, etc.",
+  "如果没有门牌号可以输入": "If no house number, enter 0000",
+  "邮政编码": "Postal Code",
+  "电话号码": "Phone Number",
+  "税号": "Tax ID",
+  "地址标签": "Address Label",
+  "默认地址": "Default Address",
+  "门号": "House Number",
+  "选择": "Select",
+  "国家": "Country",
+  "收件人必须填写": "Recipient is required",
+  "国家和州/省必须填写": "Country and state/province are required",
+  "详细地址必须填写": "Detailed address is required",
+  "邮政编码必须填写": "Postal code is required",
+  "电话号码必须填写": "Phone number is required",
+  "公司": "Company",
+  "请先添加收件地址": "Please add shipping address first",
+  "编辑收货地址": "Edit Shipping Address",
+  "您确认删除吗": "Are you sure to delete?",
+  "所有包裹": "All Parcels",
+  "运费": "Shipping Fee",
+  "确认收货": "Confirm Receipt",
+  "物流信息": "Logistics Info",
+  "账单": "Bills",
+  "提现": "Withdraw",
+  "充值金额": "Recharge Amount",
+  "请输入金额": "Please enter amount",
+  "选择充值方式": "Select Payment Method",
+  "充值步骤": "Recharge Steps",
+  "充值地址": "Recharge Address",
+  "完成付款": "Complete Payment",
+  "记录": "Records",
+  "充值记录": "Recharge History",
+  "银行名称": "Bank Name",
+  "收款人": "Payee",
+  "银行卡": "Bank Card",
+  "待审核": "Pending Review",
+  "已完成": "Completed",
+  "提现记录": "Withdrawal History",
+  "姓名": "Name",
+  "提款": "Withdrawal",
+  "可用余额": "Available Balance",
+  "提款金额": "Withdrawal Amount",
+  "请输入提款金额": "Please enter withdrawal amount",
+  "编辑您的银行卡": "Edit Your Bank Card",
+  "您的银行卡账户": "Your Bank Account",
+  "保存": "Save",
+  "请填写持卡人姓名": "Please enter cardholder name",
+  "请填写银行名称": "Please enter bank name",
+  "请填写银行卡": "Please enter bank card number",
+  "未通过原因": "Rejection Reason",
+  "未通过": "Rejected",
+  "汇款中": "Transferring",
+  "已汇款": "Transferred",
+  "取款金额": "Withdrawal Amount",
+  "步骤": "Steps",
+  "选购商品": "Select Products",
+  "仓储质检": "Whse & QC",
+  "运输到家": "Ship Home",
+  "或者": "or",
+  "tips_text": "If you already have an account, please login and link your Facebook/Google/Apple account in your profile page.",
+  "使用脸书登录": "Login with Facebook",
+  "使用谷歌登录": "Login with Google",
+  "使用苹果登录": "Login with Apple",
+  "没有账号": "No account?",
+  "直播": "Live",
+  "关注": "Follow",
+  "精选": "Featured",
+  "tabbar.商城": "Mall",
+  "tabbar.订单": "Orders",
+  "tabbar.订单详情": "Order Details",
+  "我的订单": "Orders",
+  "我的地址": "My Addresses",
+  "网购专家": "Shopping Expert",
+  "其他功能": "Other Features",
+  "邀请有礼": "Invite Friends",
+  "实名认证": "KYC",
+  "系统设置": "System Settings",
+  "账号管理": "Account Management",
+  "客服中心": "Customer Service",
+  "收货地址": "Shipping Addresses",
+  "新增收货地址": "Add New Address",
+  "购物车": "Shopping Cart",
+  "请输入关键字": "Please enter keywords",
+  "拼多多": "Pinduoduo",
+  "代购订单": "Purchasing Orders",
+  "我的集运包裹": "My Consolidated Parcels",
+  "自助集运包裹": "Self-service Consolidation",
+  "当前状态": "Current Status",
+  "实付": "Actual Payment",
+  "平台订单号": "Platform Order No.",
+  "支付编号": "Payment No.",
+  "订单状态": "Order Status",
+  "查看已完成订单": "View Completed Orders",
+  "五项服务全面呵护你的包裹号": "Five services to protect your parcel",
+  "点击步骤即可查看详情哦~": "Click steps to view details~",
+  "入库中": "In Stocking",
+  "专业质检": "Professional QC",
+  "商品实拍": "Product Photos",
+  "加固/重新包装": "Reinforce/Repack",
+  "已完成,待集运": "Completed, awaiting consolidation",
+  "接受瑕疵": "Accept Flaws",
+  "退款": "Refund",
+  "kf_hint": "This product may have flaws. Accept flawed item or request refund? Contact VAVABUY support if any questions.",
+  "编辑资料": "Edit Profile",
+  "请输入昵称": "Please enter nickname",
+  "昵称": "Nickname",
+  "保存修改": "Save Changes",
+  "请勾选确认接受瑕疵": "Please check to confirm accepting flaws",
+  "返回": "Back",
+  "同意并已阅读免责说明": "Agree and have read disclaimer",
+  "是否专业质检": "Would you like us to conduct a professional quality inspection on this parcel for you?",
+  "商品仓库": "Warehouse",
+  "集运包裹": "Parcels",
+  "物流详细": "Logistics Details",
+  "查看物流": "Track Shipping",
+  "去结算": "Checkout",
+  "确定要退出登录吗": "Are you sure to logout?",
+  "提示": "Notice",
+  "说点什么...": "Say something...",
+  "评论": "Comment",
+  "发送": "Send",
+  "回复": "Reply",
+  "退出登录": "Log out",
+  "个人资料": "Personal Information",
+  "1688工厂直销": "1688 Factory Direct",
+  "工厂直销": "Factory Direct Sales",
+  "服装、美妆、母婴、食品、数码产品、家电、家具": "Clothing, Beauty, Maternal & Child, Food, Digital Products, Home Appliances, Furniture",
+  "全球最大的C2C电商平台之一": "One of the world's largest C2C e-commerce platforms",
+  "主流电子商务应用产品平台": "Mainstream e-commerce application platform",
+  "查看并确认": "Check and confirm",
+  "验证码为必填项": "The verification code is a required field",
+  "请输入电子邮件": "Please enter your email address",
+  "验证码": "Verification code",
+  "我的邀请码": "My Invitation Code",
+  "推广步骤": "Promotion Steps",
+  "证件类型": "ID Type",
+  "证件号码": "ID Number",
+  "上传证件正面照片": "Upload Front Side of ID Card",
+  "上传证件反面照片": "Upload Back Side of ID Card",
+  "请选择证件类型": "Please select ID type",
+  "请填写身份证号码": "Please enter ID number",
+  "请填写姓名": "Please enter name",
+  "成功": "Success",
+  "失败": "Failure",
+  "刚刚": "Just now",
+  "分钟前": "minutes ago",
+  "小时前": "hours ago",
+  "昨天": "Yesterday",
+  "天前": "days ago",
+  "身份证": "ID Card",
+  "护照": "Passport",
+  "驾驶证": "Driver's License",
+  "密码是必需的且为6位": "Password is required and must be 6 digits",
+  "链接已复制": "Link copied",
+  "verification_text": "We don't require mandatory real-name verification for customers. To ensure smooth shopping experience, if your purchase exceeds $1000, according to Australian customs regulations, we'll need your identification documents to expedite the process.",
+  "请输入支付密码": "Please enter the payment password",
+  "qualityInspection": "Professional quality inspection is a value-added service that costs {amount}. We will help you verify the health quality of the goods and take photos for your confirmation before shipping to your country.",
+  "待确认": "Pending",
+  "查看": "Look",
+  "去支付": "To pay",
+  "关于vavabuy": "About VAVABUY",
+  "我知道了": "I understand",
+  "关于我们": "About Us",
+  "用户协议": "User Agreement",
+  "隐私协议": "Privacy Policy",
+  "违规物品说明": "Prohibited Items Description",
+  "上传失败": "fail to upload",
+  "质检费用": "Quality inspection fee",
+  "入库时间": "Warehouse entry time",
+  "支付成功": "The order payment was successful!",
+  "继续购物": "continue shopping",
+  "查看订单": "check an order",
+  "增值服务": "Value-added Services",
+  "易碎品加固": "Fragile Item Reinforcement",
+  "标准质检": "Standard Quality Inspection",
+  "优先采购": "Priority Procurement",
+  "个性化拍照": "Personalized Photography",
+  "服务说明": "Service Instructions",
+  "增值费用": "Value-added Fees",
+  "_gxhpz_desc": "1. Meet your needs for viewing product details. You can make a note when placing an order. One photo can only meet one photography requirement. If you need more details, please note the corresponding shooting requirements while selecting the order quantity.\n2. After you choose to pay successfully and the product is in the 'in stock' status, we will complete the operation for you within 24 hours.",
+  "_yspjg_desc": "1. Use air columns to reinforce the packaging of fragile/vulnerable goods (such as glass products, action figures, etc.).\n2. The weight and volume of the goods will be changed after the operation is completed.\n3. After you choose to pay successfully and the product is in the 'in stock' status, we will complete the operation for you within 24 hours.",
+  "_yxdg_desc": "Orders with the 'Priority Procurement' service checked will be processed within 4 hours during the buyer's working hours; if further confirmation or a balance order is required, the customer needs to cooperate with the processing before procurement. After the order is submitted, the 'Priority Procurement' service fee will not be refunded.",
+  "_bzzj_desc": "1. Provide normal-angle inspection services for the product, including packaging, hang tags, and defects, and take 2-3 clear photos for your review.\n2. After you choose to pay successfully and the product is in the 'in stock' status, we will complete the operation for you within 24 hours.",
+  "Google支付": "Google Pay",
+  "Apple支付": "Apple Pay",
+  "仓储期": "Storage Period",
+  "天": "Day",
+  "续期": "Renewal",
+  "已过期": "Expired",
+  "续存储期": "Renew Storage Period",
+  "续存储期提示": "The renewal of the storage period is at most 100 days",
+  "总计": "Total",
+  "商品数量": "Quantity of Goods",
+  "单价": "Unit Price",
+  "pay_fail_msg": "Payment failed, Please check!",
+  "我的优惠券": "My Coupons",
+  "可使用": "Usable",
+  "已使用": "Used",
+  "立即使用": "Use Immediately",
+  "满": "Minimum",
+  "可用": "applicable",
+  "minimum_amount": "Minimum {amount} applicable",
+  "领取成功": "Received successfully",
+  "运费券": "Shipping coupon",
+  "购物券": "Shopping Voucher",
+  "银行卡号": "Card number",
+  "有效期": "Expiry",
+  "安全码": "CVC",
+  "请输入消息内容": "Please enter the content",
+  "猜你想问": "Guess what you want to ask",
+  "VAVABUY专属官方客服": "VAVABUY Exclusive Official Customer Service",
+  "付费咨询": "Paid consultation",
+  "您已经开通专属客服": "You have activated the exclusive customer service.",
+  "网购助手": "Shopping assistant",
+  "领": "Get",
+  "系统": "system",
+  "重置密码": "Reset Password",
+  "选择物流路线": "Select Shipping Route",
+  "邮寄周期": "Shipping Period",
+  "报价说明": "Quotation Description",
+  "详情": "Details",
+  "请选择物流路线": "Please Select Shipping Route",
+  "正在加载": "Loading...",
+  "条新消息": "new messages",
+  "会话已关闭": "The conversation has been closed.",
+  "结束会话": "End the session",
+  "申请退款": "Refund",
+  "在线": "online",
+  "page.user_chat.tipPopupContentForCloseChat": "Are you sure you want to end the current session?",
+  "page.user_chat.tipPopupContentForRefund": "Are you sure you want to apply for a refund?",
+  "page.user_chat.tipPopupContentForPay": "<view>This service is a fee consultation project, each service charge 1.3 US dollars, we promise to continue to provide services for you, until your problem has been satisfactorily resolved.</view><view class='' style='margin:16rpx 0 0;'>If your problem is not effectively resolved, we promise to refund the payment in full to your account balance.</view>",
+  "你确定要删除此订单吗?": "Are you sure you want to delete this order?",
+  "正在安装文件": "Installing files...",
+  "应用资源更新完成": "Application resource update completed!",
+  "文件下载失败": "File download failed...",
+  "准备下载": "Preparing to download...",
+  "开始下载": "Starting download...",
+  "已下载": "Downloaded",
+  "已取消下载": "Download canceled",
+  "安装文件失败": "File installation failed",
+  "新版本": "New version found",
+  "发现新版本": "New version found:",
+  "立即升级": "Upgrade now",
+  "暂不升级": "Not upgrading now",
+  "正在为您更新请耐心等待": "Updating, please wait patiently",
+  "升级APP": "Upgrade APP",
+  "取消下载": "Cancel download",
+  "后台下载": "Background download",
+  "暂无新版本": "No new version available",
+  "返回首页": "Back to Home",
+  "查看包裹": "View Package",
+  "warehouse_tips": "Your shipping label has been created. Please wait patiently for the specific shipping cost to be generated, which usually takes 1 to 2 hours. You can confirm your international package in the Package Center.",
+  "预付费用明细": "Prepaid Expenses Details",
+  "实际运费明细": "Actual Freight Details",
+  "其他费用明细": "Other Expenses Details",
+  "预估费用": "Estimated Expenses",
+  "预估运费": "Estimated Freight",
+  "预估运费重": "Estimated Freight Weight",
+  "首重": "First Weight",
+  "续重": "Additional Weight",
+  "操作费": "Operation Fee",
+  "报关费": "Customs Clearance Fee",
+  "燃油附加费": "Fuel Surcharge",
+  "偏远地区费用": "Remote Area Fee",
+  "旺季附加费": "Peak Season Surcharge",
+  "运费优惠": "Freight Discount",
+  "实际费用": "Actual Expenses",
+  "实际运费": "Actual Freight",
+  "实际计费重": "Actual Chargeable Weight",
+  "实际体积": "Actual Volume",
+  "其他费用": "Other Expenses",
+  "打包费": "Packaging Fee",
+  "商品已下架": "The product has been removed from the shelves",
+  "相机权限说明": "Camera Permission Description",
+  "用于上传用户头像、或依据图片信息搜索内容": "Used to upload user avatars or search for content based on image information",
+  "存储权限说明": "Storage Permission Description",
+  "用于选择照片": "Used to select photos or upload user avatars",
+  "你想取消付款嘛": "Do you want to cancel the payment?",
+  "订单取消后无法恢复,请选择取消付款的原因": "The order cannot be restored after cancellation. Please select the reason for canceling the payment.",
+  "请输入取消原因": "Please enter the reason for cancellation",
+  "uni.app.quit": "Press again to exit the app",
+  "订单处理中": "Processing order...",
+  "运输中": "In transit",
+  "不想要了": "No longer want it",
+  "买错了": "Bought the wrong item",
+  "价格太贵": "Price is too high",
+  "邀请记录": "Invitation records",
+  "暂无邀请记录": "No invitation records yet",
+  "质检照片": "Quality Inspection Photos",
+  "系统消息": "System Message",
+  "未读": "Unread",
+  "消息详情": "Message Details",
+  "待支付": "To Pay",
+  "待入库": "To Store",
+  "待质检": "To Inspect",
+  "待集运": "To Consolidate",
+  "退款和售后": "Refunds",
+  "体积": "Volume",
+  "重量": "Weight",
+  "您将在安全的环境下付款给": "You will make payment in a secure environment to",
+  "从VAVABUY到": "From VAVABUY to",
+  "请输入重量": "Please enter weight",
+  "商品类别": "Product category",
+  "查询": "Search",
+  "长度": "Length",
+  "宽度": "Width",
+  "高度": "Height",
+  "热门平台": "Popular platforms",
+  "立即进入": "Enter",
+  "网购专家指引": "Online Shopping Expert Guide",
+  "帮你快速上手选择性价比商品": "Choose Cost-Effective Products Quickly",
+  "点击跳转": "Jump",
+  "追踪订单": "Track orders",
+  "价格追踪": "Price tracking",
+  "关注列表": "Watchlist",
+  "请填写必填信息": "Please fill in the required information",
+  "目的地": "Destination",
+  "暂无选项": "No options available",
+  "请选择商品类别": "Please select a product category",
+  "比加入时": "Compared to when added",
+  "降": "Drop",
+  "涨": "Rise",
+  "进行中的订单": "Orders in progress",
+  "手机号": "Phone number",
+  "手机号为必填项": "Phone number is required",
+  "手机登录": "Mobile login",
+  "邮箱登录": "Email login",
+  "手机注册": "Mobile registration",
+  "邮箱注册": "Email registration",
+  "手机重置": "Mobile Reset",
+  "邮箱重置": "Email Reset",
+  "请输入手机号": "Enter phone number",
+  "ABA KHQR": "ABA KHQR",
+  "暂无优惠券": "No coupons available",
+  "免邮专区": "Free Shipping Zone",
+  "实用功能": "Practical Functions",
+  "特色优惠": "Featured Offers",
+  "待评价": "To be evaluated",
+  "查看评论": "See Cmts",
+  "确定收到货了吗": "Are you sure you have received the goods?",
+  "购物车预览": "Shopping Cart Preview",
+  "商品评价": "Product Evaluation",
+  "评价内容": "Evaluation Content",
+  "分享你的使用感受,帮助其他买家选择": "Share your experience to help other buyers choose",
+  "上传图片": "Upload Images",
+  "暂无评论内容": "No comment content available",
+  "用户评论": "User Comments",
+  "总销量": "Total Sales:",
+  "福利中心": "Welfare Center",
+  "VAVA精选": "VAVA Selection",
+  "我要回购": "Repurchase",
+  "敬请期待": "Stay Tuned",
+  "门店": "Store",
+  "恭喜!您有一份盲盒待解锁": "Congratulations! You have a blind box to unlock",
+  "一会儿再说": "Let's Talk Later",
+  "立即打开": "Open Now",
+  "我的盲盒": "My Blind Box",
+  "我的折扣券": "My Discounts",
+  "请注意盲盒有效期": "Note Blind Box Expiry",
+  "有效期限:": "Valid Until:",
+  "恭喜!您获得": "Congratulations! You have received",
+  "领取": "Claim",
+  "盲盒兑换券": "Blind Box Redeem",
+  "兑换码": "Redemption Code",
+  "回购": "Repurchase",
+  "可回购": "Avail.",
+  "已回购": "Done",
+  "回购中": "Pending",
+  "门店列表": "Store List",
+  "选择视频": "Select Video",
+  "上传视频": "Upload Video",
+  "申请回购": "Apply for Repurchase",
+  "请上传视频": "Please Upload Video",
+  "填写物流": "Fill in Logistics",
+  "物流公司": "Logistics",
+  "请填写物流公司": "Please Fill in Logistics Company",
+  "快递单号": "Tracking Number",
+  "请填写快递单号": "Please Enter Tracking Number",
+  "福利规则": "Rules",
+  "回购规则": "Rules",
+  "设置交易密码": "Set Transaction Password",
+  "输入PIN码进行验证": "Enter PIN code for verification",
+  "输入原PIN码进行验证": "Enter original PIN code for verification",
+  "输入新PIN码进行验证": "Enter new PIN code for verification",
+  "199元包邮专区": "199 Yuan Free Postage Zone",
+  "柬埔寨": "Cambodia",
+  "转运服务": "Forwarding Service",
+  "或者选择你的方式": "Or Choose Your Way",
+  "免运费区域": "Free Shipping Zone",
+  "来自卖家": "Direct From Seller",
+  "送货上门": "To Your Door",
+  "新": "New",
+  "代购": "Agent Purchase",
+  "包邮": "Free Shipping",
+  "199包邮": "199 Free Shipping",
+  "优化预算成本": "Optimize Budget Costs",
+  "更新最低报价": "Update Lowest Offer",
+  "关注最新信息": "Follow Latest Information",
+  "意向表单": "Intention Form",
+  "意向记录": "Intention Records",
+  "商品名称": "Product Name",
+  "请输入商品名称": "Please enter the product name",
+  "商品图片": "Product Image",
+  "商品详细描述": "Product Description",
+  "请输入商品详细描述": "Please enter the product description",
+  "价格区间": "Price Range",
+  "购买数量": "Purchase Quantity",
+  "联系人电话": "Contact Phone",
+  "请输入联系人电话": "Please enter the contact phone number",
+  "联系人姓名": "Contact Name",
+  "请输入联系人姓名": "Please enter the contact name",
+  "最低价": "Minimum Price",
+  "最高价": "Maximum Price",
+  "元": "CNY"
+}

+ 513 - 0
locale/es.json

@@ -0,0 +1,513 @@
+{
+  "tabbar.首页": "Inicio",
+  "tabbar.购物车": "Carrito",
+  "tabbar.社区": "Comunidad",
+  "tabbar.咨询": "Consultar",
+  "tabbar.我的": "Mi cuenta",
+  "公告": "Anuncio",
+  "团队服务升级报告": "Anuncio de actualización de servicios del equipo Hoobuy",
+  "电子邮件": "Correo electrónico",
+  "密码": "Contraseña",
+  "电子邮件为必填项": "El correo electrónico es obligatorio",
+  "密码是必需的": "La contraseña es obligatoria",
+  "登录": "Iniciar sesión",
+  "忘记密码": "¿Olvidaste la contraseña?",
+  "注册": "Registrarse",
+  "删除账户": "Eliminar Cuenta",
+  "cancelRegistrationTips": "Advertencia: Una vez que la cuenta sea eliminada, todos los datos serán eliminados permanentemente y no podrán ser recuperados. Por favor, proceda con precaución.",
+  "请输入密码验证身份": "Verificar contraseña",
+  "请输入密码": "Por favor, ingrese contraseña",
+  "验证通过后将执行账户删除操作": "Después de que la verificación sea aprobada, se ejecutará la operación de eliminación de la cuenta.",
+  "密码不能为空": "La contraseña no puede estar vacía",
+  "账户删除成功": "Eliminación de la cuenta exitosa",
+  "确认密码": "Confirmar contraseña",
+  "已有账户": "¿Ya tienes una cuenta?",
+  "邀请码": "Código de invitación (no obligatorio)",
+  "我已阅读并接受": "He leído y acepto",
+  "和": "y",
+  "语言/币种": "Idioma/Moneda",
+  "直淘中国无差价": "Compra directa de China sin margen",
+  "主页": "Página principal",
+  "订单": "Pedidos",
+  "仓库": "Almacén",
+  "包裹": "Paquetes",
+  "钱包": "Monedero",
+  "在线客服": "Servicio al cliente en línea",
+  "拍照": "Tomar foto",
+  "相册": "Álbum de fotos",
+  "商品的链接或名称": "Enlace o nombre del producto",
+  "运费估算": "Estimación de envío",
+  "新手教程": "Tutorial para principiantes",
+  "社群": "Comunidad",
+  "装运": "Envío",
+  "余额": "Saldo",
+  "优惠券": "Cupones",
+  "收藏夹": "Favoritos",
+  "推荐官": "Recomendaciones",
+  "消息": "Mensajes",
+  "加入社群": "Unirse a la comunidad",
+  "帮助中心": "Centro de ayuda",
+  "联系我们": "Contáctenos",
+  "设置": "Configuración",
+  "好的": "De acuerdo",
+  "语言": "Idioma",
+  "币种": "Moneda",
+  "搜索": "Buscar",
+  "搜索历史": "Historial de búsqueda",
+  "热门搜索": "Búsquedas populares",
+  "1688": "1688",
+  "淘宝": "Taobao",
+  "JD": "JD",
+  "无数据": "Sin datos",
+  "正在加载中": "Cargando",
+  "加载更多": "Cargar más",
+  "没有更多了": "No hay más",
+  "综合": "General",
+  "价格": "Precio",
+  "搜索条款": "Términos de búsqueda",
+  "搜索条款内容": "Todos los productos mostrados son de plataformas de terceros. Hoobuy solo proporciona servicios de búsqueda, compra y envío. No verificamos la calidad o autenticidad de los productos.",
+  "您已同意搜索条款": "Has aceptado los términos de búsqueda.",
+  "关闭": "Cerrar",
+  "搜索类似产品": "Buscar productos similares",
+  "产品链接": "Enlace del producto",
+  "分享": "Compartir",
+  "刷新": "Actualizar",
+  "加入": "Unirse",
+  "立即购买": "Comprar ahora",
+  "加入购物车": "Añadir al carrito",
+  "购买记录": "Historial de compras",
+  "销售量": "Ventas",
+  "平均送达时间": "Tiempo promedio de entrega",
+  "重量(克)": "Peso (gramos)",
+  "尺寸": "Tamaño",
+  "进入商店": "Entrar a la tienda",
+  "产品详情": "Detalles del producto",
+  "产品": "Producto",
+  "细节": "Detalles",
+  "更多的": "Más",
+  "规格参数": "Especificaciones",
+  "你可能会喜欢": "Podría gustarte",
+  "提交": "Enviar",
+  "全部": "Todo",
+  "删除": "Eliminar",
+  "不包括运费": "Sin incluir envío",
+  "数量": "Cantidad",
+  "最小购买数量": "Cantidad mínima: 1",
+  "库存": "Inventario",
+  "确认订单": "Confirmar pedido",
+  "总计不含国际运费": "Total (sin envío internacional)",
+  "违禁物品说明": "Descripción de artículos prohibidos",
+  "《服务条款》": "Términos de servicio",
+  "退货说明": "Política de devoluciones",
+  "免责声明": "Descargo de responsabilidad",
+  "我已阅读并同意": "He leído y acepto",
+  "订单总价": "Total del pedido",
+  "总价": "Precio total",
+  "运费到仓库": "Envío al almacén",
+  "折扣": "Descuento",
+  "温馨提示": "Nota",
+  "提示内容": "Después de pagar, espera a que el vendedor envíe los productos al almacén para luego solicitar el envío internacional.",
+  "请阅读并同意": "Por favor lee y acepta",
+  "支付方式": "Método de pago",
+  "请在": "Por favor paga antes de",
+  "取消付款提示": ", de lo contrario se cancelará el pedido.",
+  "余额不足需充值": "Saldo insuficiente, recarga",
+  "用余额支付": "Pagar con saldo",
+  "推荐": "Recomendar",
+  "充值": "Recargar",
+  "支付": "Pagar",
+  "手续费": "Comisión",
+  "名称订单号商品名称": "Nombre/N° de pedido/Producto",
+  "待付款": "Pendiente",
+  "筛选": "Filtrar",
+  "创建时间": "Fecha de creación",
+  "订单时间": "Fecha del pedido",
+  "重置": "Restablecer",
+  "开始日期": "Fecha de inicio",
+  "结束日期": "Fecha de finalización",
+  "不支退货换货": "No aceptamos devoluciones/cambios >",
+  "结束时间": "Hora de finalización",
+  "取消": "Cancelar",
+  "删除订单": "Eliminar pedido",
+  "全选": "Seleccionar todo",
+  "合并付款": "Pago combinado",
+  "订单详情": "Detalles del pedido",
+  "订单流程": "Proceso del pedido",
+  "处理中": "Procesando",
+  "订单号": "N° de pedido",
+  "复制": "Copiar",
+  "复制成功": "Copiado con éxito",
+  "小计": "Subtotal",
+  "国内货运": "Envío nacional",
+  "订单补充付款": "Pago adicional del pedido",
+  "涉及增值服务费": "Incluye tarifas de servicios adicionales",
+  "店铺": "Tienda",
+  "提醒": "Recordatorio",
+  "您确定要从收藏中移除该店铺吗": "¿Seguro que quieres eliminar esta tienda de favoritos?",
+  "您确定要从收藏中移除该产品吗": "¿Seguro que quieres eliminar este producto de favoritos?",
+  "默认": "Predeterminado",
+  "收件地址": "Dirección de entrega",
+  "账户地址": "Dirección de la cuenta",
+  "关于Hoobuy": "Acerca de Hoobuy",
+  "隐私政策": "Política de privacidad",
+  "服务条款": "Términos de servicio",
+  "ID": "ID",
+  "修改密码tips": "Una contraseña más segura protege mejor tu cuenta. Te recomendamos cambiarla regularmente.",
+  "交易密码tips": "Se requiere verificación de contraseña para transacciones con saldo, para mayor seguridad.",
+  "账户安全": "Seguridad de la cuenta",
+  "修改登录密码": "Cambiar contraseña",
+  "编辑": "Editar",
+  "新交易密码": "Nueva contraseña de transacción",
+  "登录密码": "Contraseña",
+  "新密码": "Nueva contraseña",
+  "再次输入密码": "Confirmar contraseña",
+  "交易密码": "Contraseña de transacción",
+  "原交易密码": "Contraseña anterior",
+  "打包": "Empaquetar",
+  "请选择地址": "Selecciona una dirección",
+  "添加收货地址": "Añadir dirección",
+  "确认": "Confirmar",
+  "添加送货地址": "Añadir dirección de envío",
+  "收件人": "Destinatario",
+  "名": "Nombre",
+  "姓": "Apellido",
+  "地区": "Región",
+  "详细地址": "Dirección detallada",
+  "输入公寓号码街道道路地址": "Ingresa apartamento, calle, dirección, etc.",
+  "如果没有门牌号可以输入": "Si no hay número, ingresa 0000",
+  "邮政编码": "Código postal",
+  "电话号码": "Teléfono",
+  "税号": "N° de impuesto",
+  "地址标签": "Etiqueta de dirección",
+  "默认地址": "Dirección predeterminada",
+  "门号": "Número de puerta",
+  "选择": "Seleccionar",
+  "国家": "País",
+  "收件人必须填写": "El destinatario es obligatorio",
+  "国家和州/省必须填写": "País y región son obligatorios",
+  "详细地址必须填写": "La dirección detallada es obligatoria",
+  "邮政编码必须填写": "El código postal es obligatorio",
+  "电话号码必须填写": "El teléfono es obligatorio",
+  "公司": "Empresa",
+  "请先添加收件地址": "Primero añade una dirección",
+  "编辑收货地址": "Editar dirección",
+  "您确认删除吗": "¿Confirmas la eliminación?",
+  "所有包裹": "Todos los paquetes",
+  "运费": "Gastos de envío",
+  "确认收货": "Confirmar recepción",
+  "物流信息": "Información de envío",
+  "账单": "Factura",
+  "提现": "Retirar",
+  "充值金额": "Monto a recargar",
+  "请输入金额": "Ingresa el monto",
+  "选择充值方式": "Seleccionar método de recarga",
+  "充值步骤": "Pasos para recargar",
+  "充值地址": "Dirección de recarga",
+  "完成付款": "Completar pago",
+  "记录": "Registro",
+  "充值记录": "Historial de recargas",
+  "银行名称": "Banco",
+  "收款人": "Beneficiario",
+  "银行卡": "Tarjeta bancaria",
+  "待审核": "Pendiente de revisión",
+  "已完成": "Completado",
+  "提现记录": "Historial de retiros",
+  "姓名": "Nombre",
+  "提款": "Retiro",
+  "可用余额": "Saldo disponible",
+  "提款金额": "Monto a retirar",
+  "请输入提款金额": "Ingresa el monto a retirar",
+  "编辑您的银行卡": "Editar tarjeta bancaria",
+  "您的银行卡账户": "Tu cuenta bancaria",
+  "保存": "Guardar",
+  "请填写持卡人姓名": "Nombre del titular es obligatorio",
+  "请填写银行名称": "Nombre del banco es obligatorio",
+  "请填写银行卡": "Tarjeta bancaria es obligatoria",
+  "未通过原因": "Motivo de rechazo",
+  "未通过": "Rechazado",
+  "汇款中": "Transferencia en proceso",
+  "已汇款": "Transferido",
+  "取款金额": "Monto retirado",
+  "步骤": "Pasos",
+  "选购商品": "Seleccionar productos",
+  "仓储质检": "Almacén e inspección",
+  "运输到家": "Envío a casa",
+  "或者": "o",
+  "tips_text": "Si ya tienes cuenta, inicia sesión y vincula Facebook, Google o Apple en tu perfil.",
+  "使用脸书登录": "Iniciar con Facebook",
+  "使用谷歌登录": "Iniciar con Google",
+  "使用苹果登录": "Iniciar con Apple",
+  "没有账号": "¿No tienes cuenta?",
+  "直播": "En vivo",
+  "关注": "Seguir",
+  "精选": "Seleccionado",
+  "tabbar.商城": "Tienda",
+  "tabbar.订单": "Pedidos",
+  "tabbar.订单详情": "Detalles del pedido",
+  "我的订单": "pedidos",
+  "我的地址": "Mis direcciones",
+  "网购专家": "Experto en compras",
+  "其他功能": "Otras funciones",
+  "邀请有礼": "Invitar amigos",
+  "实名认证": "Verificación de identidad",
+  "系统设置": "Configuración del sistema",
+  "账号管理": "Gestión de cuenta",
+  "客服中心": "Servicio al cliente",
+  "收货地址": "Dirección de entrega",
+  "新增收货地址": "Añadir dirección",
+  "购物车": "Carrito",
+  "请输入关键字": "Ingresa palabras clave",
+  "拼多多": "Pinduoduo",
+  "代购订单": "Pedidos de compra",
+  "我的集运包裹": "Mis paquetes consolidados",
+  "自助集运包裹": "Auto consolidación",
+  "当前状态": "Estado actual",
+  "实付": "Pagado",
+  "平台订单号": "N° de pedido",
+  "支付编号": "N° de pago",
+  "订单状态": "Estado del pedido",
+  "查看已完成订单": "Ver pedidos completados",
+  "五项服务全面呵护你的包裹号": "Cinco servicios para proteger tu paquete",
+  "点击步骤即可查看详情哦~": "Haz clic en los pasos para más detalles~",
+  "入库中": "En almacén",
+  "专业质检": "Inspección profesional",
+  "商品实拍": "Fotos reales",
+  "加固/重新包装": "Refuerzo/Reempaque",
+  "已完成,待集运": "Completado, pendiente de envío",
+  "接受瑕疵": "Aceptar defectos",
+  "退款": "Reembolso",
+  "kf_hint": "Este producto podría tener defectos. ¿Aceptas el producto con defectos o prefieres reembolso? Contacta al servicio al cliente.",
+  "编辑资料": "Editar perfil",
+  "请输入昵称": "Ingresa un apodo",
+  "昵称": "Apodo",
+  "保存修改": "Guardar cambios",
+  "请勾选确认接受瑕疵": "Marca para aceptar defectos",
+  "返回": "Volver",
+  "同意并已阅读免责说明": "Acepto y he leído los términos",
+  "是否专业质检": "¿Inspección profesional?",
+  "商品仓库": "productos",
+  "集运包裹": "consolidados",
+  "物流详细": "Detalles de envío",
+  "查看物流": "Ver envío",
+  "去结算": "Pagar",
+  "确定要退出登录吗": "¿Seguro que quieres cerrar sesión?",
+  "提示": "Aviso",
+  "说点什么...": "Di algo...",
+  "评论": "Comentario",
+  "发送": "Enviar",
+  "回复": "Responder",
+  "退出登录": "Cerrar sesión",
+  "个人资料": "Perfil",
+  "1688工厂直销": "1688 Fábrica directa",
+  "工厂直销": "Venta directa de fábrica",
+  "服装、美妆、母婴、食品、数码产品、家电、家具": "Ropa, belleza, bebés, comida, electrónicos, electrodomésticos, muebles",
+  "全球最大的C2C电商平台之一": "Una de las mayores plataformas C2C del mundo",
+  "主流电子商务应用产品平台": "Plataforma líder de comercio electrónico",
+  "查看并确认": "Revisar y confirmar",
+  "验证码为必填项": "El código de verificación es obligatorio",
+  "请输入电子邮件": "Ingresa tu correo electrónico",
+  "验证码": "Código de verificación",
+  "我的邀请码": "Mi código de invitación",
+  "推广步骤": "Pasos de Promoción",
+  "证件类型": "Tipo de documento",
+  "身份证号码": "Número de identificación",
+  "上传证件正面照片": "Subir foto frontal del documento",
+  "上传证件反面照片": "Subir foto trasera del documento",
+  "请选择证件类型": "Selecciona tipo de documento",
+  "请填写身份证号码": "Ingresa número de identificación",
+  "请填写姓名": "Ingresa tu nombre",
+  "成功": "Éxito",
+  "失败": "Fallo",
+  "刚刚": "Ahora",
+  "分钟前": "minutos atrás",
+  "小时前": "horas atrás",
+  "昨天": "Ayer",
+  "天前": "días atrás",
+  "身份证": "DNI",
+  "护照": "Pasaporte",
+  "驾驶证": "Licencia de conducir",
+  "密码是必需的且为6位": "La contraseña debe tener 6 dígitos",
+  "链接已复制": "Enlace copiado",
+  "verification_text": "No requerimos verificación de identidad obligatoria. Para compras superiores a $1000, según regulaciones aduaneras, necesitamos tu documento para agilizar el proceso.",
+  "请输入支付密码": "Ingresa contraseña de pago",
+  "qualityInspection": "La inspección profesional cuesta {amount} yuan. Verificamos la calidad y te enviamos fotos antes del envío internacional.",
+  "待确认": "Pendiente",
+  "分享给好友": "Compartir con amigos",
+  "分享到朋友圈": "Compartir en redes",
+  "查看": "Ver",
+  "去支付": "Ir a pagar",
+  "关于vavabuy": "Sobre VAVABUY",
+  "我知道了": "Entendido",
+  "关于我们": "Sobre nosotros",
+  "用户协议": "Acuerdo de usuario",
+  "隐私协议": "Política de privacidad",
+  "违规物品说明": "Artículos prohibidos",
+  "上传失败": "Error al subir",
+  "证件号码": "N° de documento",
+  "质检费用": "Costo de inspección",
+  "入库时间": "Fecha de almacenamiento",
+  "支付成功": "Pedido pagado con éxito",
+  "继续购物": "Seguir comprando",
+  "查看订单": "Ver pedido",
+  "增值服务": "Servicios de Valor Añadido",
+  "易碎品加固": "Refuerzo de Productos Frágiles",
+  "标准质检": "Inspección de Calidad Estándar",
+  "优先采购": "Compra Prioritaria",
+  "个性化拍照": "Fotografía Personalizada",
+  "服务说明": "Instrucciones de Servicio",
+  "包含增值费用": "Tarifas de Valor Añadido",
+  "_gxhpz_desc": "1. Satisface su necesidad de visualizar los detalles del producto. Puede hacer un comentario al momento de placing el pedido. Una foto solo puede satisfacer un requisito de fotografía. Si necesita más detalles, por favor especifique los requisitos de fotografía correspondientes al seleccionar la cantidad del pedido.\n2. Después de que elija pagar con éxito y el producto se encuentre en estado 'en stock', completaremos la operación para usted dentro de 24 horas.",
+  "_yspjg_desc": "1. Utilizamos columnas de aire para reforzar el empaque de productos frágiles/vulnerables (como productos de vidrio, figuras coleccionables, etc.).\n2. El peso y el volumen del producto cambiarán después de completar la operación.\n3. Después de que elija pagar con éxito y el producto se encuentre en estado 'en stock', completaremos la operación para usted dentro de 24 horas.",
+  "_yxdg_desc": "Los pedidos con el servicio 'Compra Prioritaria' seleccionado serán procesados dentro de 4 horas durante el horario laboral del comprador; si es necesario una confirmación adicional o un pedido de saldo, el cliente debe colaborar con el procesamiento antes de la compra. Después de la presentación del pedido, la tarifa del servicio 'Compra Prioritaria' no se reembolsará.",
+  "_bzzj_desc": "1. Proporcionamos servicio de inspección de ángulo normal del producto, empaque, etiquetas y defectos, y tomamos 2-3 fotos claras para su revisión.\n2. Después de que elija pagar con éxito y el producto se encuentre en estado 'en stock', completaremos la operación para usted dentro de 24 horas.",
+  "Google支付": "Google Pay",
+  "Apple支付": "Pago de Apple",
+  "仓储期": "Período de Almacenamiento",
+  "天": "Día",
+  "续期": "Renovación",
+  "已过期": "Vencido",
+  "续存储期": "Renovar Período de Almacenamiento",
+  "续存储期提示": "La renovación del período de almacenamiento es de máximo 100 días",
+  "总计": "Total",
+  "商品数量": "Cantidad de Productos",
+  "单价": "Precio Unitario",
+  "pay_fail_msg": "El pago falló, por favor revise!",
+  "我的优惠券": "Mis Cupones",
+  "可使用": "Disponible",
+  "已使用": "Utilizado",
+  "立即使用": "Usar Inmediatamente",
+  "满": "Mínimo",
+  "可用": "aplicable",
+  "minimum_amount": "Mínimo {amount} aplicable",
+  "领取成功": "Recibido con éxito",
+  "运费券": "Cupón de envío",
+  "购物券": "Bono de compra",
+  "银行卡号": "Número de tarjeta",
+  "有效期": "validez",
+  "安全码": "El Código de Seguridad",
+  "请输入消息内容": "Por favor ingrese el contenido",
+  "猜你想问": "Supongo que quieres preguntar",
+  "VAVABUY专属官方客服": "VAVABUY exclusivo servicio oficial de atención al cliente",
+  "付费咨询": "Consulta de pago",
+  "您已经开通专属客服": "Has abierto un servicio de atención al cliente exclusivo",
+  "网购助手": "Asistente de compras",
+  "领": "cuello",
+  "系统": "El sistema",
+  "重置密码": "Restablecer Contraseña",
+  "选择物流路线": "Seleccionar ruta de envío",
+  "邮寄周期": "Período de envío",
+  "报价说明": "Explicación de la cotización",
+  "详情": "Detalles",
+  "请选择物流路线": "Por favor, seleccione una ruta de envío",
+  "正在加载": "Cargando en proceso...",
+  "条新消息": "nuevos mensajes",
+  "会话已关闭": "La sesión ha sido cerrada.",
+  "结束会话": "Cerrar la sesión",
+  "申请退款": "Reembolsos",
+  "在线": "en línea",
+  "page.user_chat.tipPopupContentForCloseChat": "¿Confirma que desea cerrar la sesión actual?",
+  "page.user_chat.tipPopupContentForRefund": "¿Confirma que desea solicitar un reembolso?",
+  "page.user_chat.tipPopupContentForPay": "<view>Este servicio es un programa de consultoría de pago. Cada servicio cuesta $1.3. Nos comprometemos a continuar brindando nuestros servicios hasta que su problema se resuelva satisfactoriamente.</view><view class='' style='margin:16rpx 0 0;'>Si su problema no se resuelve de manera efectiva, nos comprometemos a devolver el importe pagado en su totalidad al saldo de su cuenta.</view>",
+  "你确定要删除此订单吗?": "¿Estás seguro de que quieres eliminar este pedido?",
+  "正在安装文件": "Instalando archivos...",
+  "应用资源更新完成": "¡Actualización de recursos de la aplicación completada!",
+  "文件下载失败": "Error en la descarga del archivo...",
+  "准备下载": "Preparando para descargar...",
+  "开始下载": "Iniciando descarga...",
+  "已下载": "Descargado",
+  "已取消下载": "Descarga cancelada",
+  "安装文件失败": "Error en la instalación del archivo",
+  "新版本": "Nueva versión encontrada",
+  "发现新版本": "Nueva versión encontrada:",
+  "立即升级": "Actualizar ahora",
+  "暂不升级": "No actualizar ahora",
+  "正在为您更新请耐心等待": "Actualizando, por favor, espere pacientemente",
+  "升级APP": "Actualizar APP",
+  "取消下载": "Cancelar descarga",
+  "后台下载": "Descarga en segundo plano",
+  "暂无新版本": "No hay nueva versión disponible",
+  "返回首页": "Volver a la página",
+  "查看包裹": "Ver Paquete",
+  "warehouse_tips": "Tu etiqueta de envío ha sido creada. Por favor, espera pacientemente a que se genere el costo exacto del envío, lo cual generalmente tarda entre 1 y 2 horas. Puedes confirmar tu paquete internacional en el Centro de Paquetes.",
+  "预付费用明细": "Detalles de Gastos Prepagados",
+  "实际运费明细": "Detalles de Flete Real",
+  "其他费用明细": "Detalles de Otros Gastos",
+  "预估费用": "Gastos Estimados",
+  "预估运费": "Flete Estimado",
+  "预估运费重": "Peso Estimado de Flete",
+  "首重": "Peso Inicial",
+  "续重": "Peso Adicional",
+  "操作费": "Tarifa de Operación",
+  "报关费": "Tarifa de Aduana",
+  "燃油附加费": "Recargo de Combustible",
+  "偏远地区费用": "Cargo por Zona Remota",
+  "旺季附加费": "Recargo de Temporada Alta",
+  "运费优惠": "Descuento de Flete",
+  "实际费用": "Gastos Reales",
+  "实际运费": "Flete Real",
+  "实际计费重": "Peso Facturable Real",
+  "实际体积": "Volumen Real",
+  "其他费用": "Otros Gastos",
+  "打包费": "Cargo por Empaque",
+  "商品已下架": "El producto ha sido retirado de la venta",
+  "相机权限说明": "Descripción del permiso de cámara",
+  "用于上传用户头像、或依据图片信息搜索内容": "Se usa para cargar avatares de usuario o buscar contenido según la información de imágenes",
+  "存储权限说明": "Descripción del permiso de almacenamiento",
+  "用于选择照片": "Usado para seleccionar fotos o subir avatares de usuario",
+  "你想取消付款嘛": "¿Quieres cancelar el pago?",
+  "订单取消后无法恢复,请选择取消付款的原因": "Una vez cancelado, el pedido no se puede recuperar. Por favor, selecciona el motivo para cancelar el pago.",
+  "请输入取消原因": "Por favor, ingresa el motivo de la cancelación",
+  "uni.app.quit": "Presiona otra vez para salir de la aplicación",
+  "订单处理中": "Procesando pedido...",
+  "运输中": "En tránsito",
+  "不想要了": "Ya no lo quiero",
+  "买错了": "Compré el producto equivocado",
+  "价格太贵": "El precio es demasiado alto",
+  "邀请记录": "Registros de invitaciones",
+  "暂无邀请记录": "No hay registros de invitaciones",
+  "质检照片": "Fotos de inspección de calidad",
+  "系统消息": "Mensaje del sistema",
+  "未读": "No leído",
+  "消息详情": "Detalles del mensaje",
+  "待支付": "Pago Pend.",
+  "待入库": "Almac. Pend.",
+  "待质检": "Inspec. Pend.",
+  "待集运": "Consol. Pend.",
+  "退款和售后": "Reembolsos",
+  "体积": "Volumen",
+  "重量": "Peso",
+  "您将在安全的环境下付款给": "Realizarás el pago en un entorno seguro a",
+  "从VAVABUY到": "De VAVABUY a",
+  "请输入重量": "Por favor, introduzca el peso",
+  "商品类别": "Categoría de producto",
+  "查询": "Buscar",
+  "长度": "Longitud",
+  "宽度": "Anchura",
+  "高度": "Altura",
+  "热门平台": "Plataformas populares",
+  "立即进入": "Entrar ahora",
+  "网购专家指引": "Guía de expertos en compras en línea",
+  "帮你快速上手选择性价比商品": "Te ayuda a empezar rápido a elegir productos con buena relación calidad-precio",
+  "点击跳转": "Haga clic para ir",
+  "追踪订单": "Rastrear pedido",
+  "价格追踪": "Seguimiento de precios",
+  "关注列表": "Lista de seguimiento",
+  "请填写必填信息": "Por favor, complete la información requerida",
+  "目的地": "Destino",
+  "暂无选项": "Sin opciones disponibles",
+  "请选择商品类别": "Por favor, seleccione una categoría de producto",
+  "比加入时": "En comparación con cuando se añadió",
+  "降": "Bajar",
+  "涨": "Subir",
+  "进行中的订单": "Pedidos en curso",
+  "手机号": "Número de teléfono",
+  "手机号为必填项": "El número de teléfono es obligatorio",
+  "手机登录": "Inicio por teléfono",
+  "邮箱登录": "Inicio por correo",
+  "手机注册": "Registro por teléfono",
+  "邮箱注册": "Registro por correo",
+  "手机重置": "Rest. por teléfono",
+  "邮箱重置": "Rest. por correo",
+  "请输入手机号": "Ingrese número de teléfono",
+  "ABA KHQR": "ABA KHQR"
+}

+ 71 - 0
locale/index.js

@@ -0,0 +1,71 @@
+import { createI18n } from 'vue-i18n';
+import zh from './zh.json';
+import en from './en.json'
+import es from './es.json'
+import km from './km.json'
+import verConfig from '../ver.config';
+import { getStorage, setStorage } from '@/utils';
+
+// setStorage(verConfig.langName, 'zh')
+const lang = getStorage(verConfig.langName);
+const defaultLang = verConfig.lang || "zh"
+if (!lang) {
+	setStorage(verConfig.langName, defaultLang);
+}
+
+export const messages = {
+	zh: { ...zh },
+	en,
+	es,
+	km
+}
+export const setLan = (_lan, callBack = () => { }) => {
+	setStorage(verConfig.langName, _lan);
+	i18n.global.locale = _lan;
+	uni.setLocale(_lan)
+	callBack()
+};
+
+export const getLan = () => {
+	const lan = getStorage(verConfig.langName);
+	if (!lan) {
+		setLan(defaultLang);
+		return defaultLang;
+	}
+	return lan;
+};
+
+export const lans = [
+	{
+		label: '中文简体',
+		value: 'zh'
+	},
+	{
+		label: 'English',
+		value: 'en'
+	},
+	{
+		label: 'Española',
+		value: 'es'
+	}
+	,
+	{
+		label: 'Khmer',
+		value: 'km'
+	}
+]
+
+const locale = getLan();
+export const i18n = createI18n({
+	locale,
+	messages,
+})
+export const findLang = (_lan) => {
+	let find = lans.find(item => _lan === item.value)
+	return find
+}
+
+
+export const t = (key, spareKey = {}) => {
+	return i18n.global.t(key, spareKey)
+}

+ 599 - 0
locale/km.json

@@ -0,0 +1,599 @@
+{
+  "tabbar.首页": "ទំព័រដើម",
+  "tabbar.购物车": "រទេះទំនិញ",
+  "tabbar.社区": "សហគមន៍",
+  "tabbar.咨询": "សួរសំណើ",
+  "tabbar.我的": "ខ្ញុំ",
+  "公告": "សេចក្តីជូនដំណឹង",
+  "团队服务升级报告": "សេចក្តីជូនដំណឹងអំពីការធ្វើឱ្យប្រសើរឡើងសេវាកម្មក្រុម Hoobuy",
+  "电子邮件": "អ៊ីមែល",
+  "密码": "ពាក្យសម្ងាត់",
+  "电子邮件为必填项": "អ៊ីមែលជាតម្រូវការ",
+  "密码是必需的": "ពាក្យសម្ងាត់ជាតម្រូវការ",
+  "登录": "ចូលប្រើ",
+  "忘记密码": "ភ្លេចពាក្យសម្ងាត់?",
+  "注册": "ចុះឈ្មោះ",
+  "删除账户": "លុបគណនី",
+  "cancelRegistrationTips": "ព្រមាន៖ បន្ទាប់ពីលុបគណនីទាំងអស់ទិន្នន័យនឹងត្រូវលុបចោលជារៀងរហូតហើយមិនអាច بازیឡើងវិញបានទេ សូមប្រយ័ត្នចំពោះសកម្មភាពនេះ។",
+  "请输入密码验证身份": "សូមបញ្ចូលពាក្យសម្ងាត់ដើម្បីផ្ទៀងផ្ទាត់អត្តសញ្ញាណ",
+  "请输入密码": "សូមបញ្ចូលពាក្យសម្ងាត់",
+  "验证通过后将执行账户删除操作": "បន្ទាប់ពីផ្ទៀងផ្ទាត់ជោគជ័យនឹងប្រតិបត្តិការលុបគណនី",
+  "密码不能为空": "ពាក្យសម្ងាត់មិនអាចទទេរទេ",
+  "账户删除成功": "លុបគណនីជោគជ័យ",
+  "确认密码": "បញ្ជាក់ពាក្យសម្ងាត់",
+  "已有账户": "មានគណនីរួចហើយ ឥឡូវនេះ",
+  "邀请码": "លេខអញ្ជើញ (មិនចាំបាច់)",
+  "我已阅读并接受": "ខ្ញុំបានអានហើយទទួលយក",
+  "和": "និង",
+  "语言/币种": "ភាសា/រូបិយប័ណ្ណ",
+  "直淘中国无差价": "ទិញដោយផ្ទាល់ពីចិនគ្មានភាពខុសគ្នានៃតម្លៃ",
+  "主页": "ទំព័រដើម",
+  "订单": "ការสั่งซื้อ",
+  "仓库": "ឃ្លាំង",
+  "包裹": "បែបបណ្តុះ",
+  "钱包": "រនាំង",
+  "在线客服": "អ្នកជំនួយអនឡាញ",
+  "拍照": "ថតរូប",
+  "相册": "អាល់ប៊ុមរូប",
+  "商品的链接或名称": "តំណភ្ជាប់ឬឈ្មោះទំនិញ",
+  "运费估算": "ប៉ាន់ស្មានថ្លៃដឹកជញ្ជូន",
+  "新手教程": "រៀនសម្រាប់អ្នកថ្មី",
+  "社群": "ក្រុមសង្គម",
+  "装运": "ការដឹកជញ្ជូន",
+  "余额": "សមតុល្យ",
+  "优惠券": "កាតបញ្ចុះតម្លៃ",
+  "收藏夹": "ការរក្សាទុក",
+  "推荐官": "អ្នកណែនាំ",
+  "消息": "សារ",
+  "加入社群": "ចូលក្រុមសង្គម",
+  "帮助中心": "មជ្ឈមណ្ឌលជំនួយ",
+  "联系我们": "ទំនាក់ទំនងជាមួយយើង",
+  "设置": "ការកំណត់",
+  "好的": "បាទ",
+  "语言": "ភាសា",
+  "币种": "រូបិយប័ណ្ណ",
+  "搜索": "ស្វែងរក",
+  "搜索历史": "ប្រវត្តិស្វែងរក",
+  "热门搜索": "ស្វែងរកពេញនិយម",
+  "1688": "1688",
+  "淘宝": "តូប៉ៅ",
+  "JD": "JD",
+  "无数据": "គ្មានទិន្នន័យ",
+  "正在加载中": "កំពុងផ្ទុក...",
+  "加载更多": "ផ្ទុកបន្ថែម",
+  "没有更多了": "មិនមានបន្ថែមទៀង",
+  "综合": "សរុប",
+  "价格": "តម្លៃ",
+  "搜索条款": "លក្ខខណ្ឌស្វែងរក",
+  "搜索条款内容": "ទាំងអស់ផលិតផលដែលបង្ហាញក្នុងលទ្ធផលស្វែងរកគឺមកពីវេទិកាទីបី។ Hoobuy ផ្តល់តែសេវាកម្មស្វែងរកព័ត៌មាន ការទិញជំនួស និងការដឹកជញ្ជូនប៉ុណ្ណោះ។ យើងមិនផ្ទៀងផ្ទាត់ ឬវាយតម្លៃគុណភាព ឬភាពពិតនៃផលិតផលទេ។",
+  "您已同意搜索条款": "អ្នកបានយល់ព្រមនឹងលក្ខខណ្ឌស្វែងរក។",
+  "关闭": "បិទ",
+  "搜索类似产品": "ស្វែងរកផលិតផលស្រដៀងគ្នា",
+  "产品链接": "តំណភ្ជាប់ផលិតផល",
+  "分享": "ចែករំលែក",
+  "刷新": "ធ្វើឱ្យថ្មី",
+  "加入": "ចូល",
+  "立即购买": "ទិញឥឡូវនេះ",
+  "加入购物车": "បន្ថែមទៅរទេះទំនិញ",
+  "购买记录": "ប្រវត្តិការទិញ",
+  "销售量": "ចំនួនលក់",
+  "平均送达时间": "ពេលវេលាដឹកជញ្ជូនមធ្យម",
+  "重量(克)": "ទម្ងន់ (กรัม)",
+  "尺寸": "ទំហំ",
+  "进入商店": "ចូលហាង",
+  "产品详情": "ព័ត៌មានលម្អិតផលិតផល",
+  "产品": "ផលិតផល",
+  "细节": "លម្អិត",
+  "更多的": "បន្ថែមទៀង",
+  "规格参数": "ប៉ារ៉ាម៉ែត្រសេចក្តីលក្ខខណ្ឌ",
+  "你可能会喜欢": "អ្នកអាចចូលចិត្ត",
+  "提交": "ដាក់ជូន",
+  "全部": "ទាំងអស់",
+  "删除": "លុប",
+  "不包括运费": "មិនរួមបញ្ចូលថ្លៃដឹកជញ្ជូន",
+  "数量": "ចំនួន",
+  "最小购买数量": "ចំនួនអប្បបរមាតម្រូវការទិញ: 1",
+  "库存": "ស្តុក",
+  "确认订单": "បញ្ជាក់ការสั่งซื้อ",
+  "总计不含国际运费": "សរុប (មិនរួមថ្លៃដឹកជញ្ជូនអន្តរជាតិ)",
+  "违禁物品说明": "«ការពិពណ៌នាអំពីទំនិញហាមឃាត់»",
+  "《服务条款》": "«លក្ខខណ្ឌសេវាកម្ម»",
+  "退货说明": "«ការពិពណ៌នាអំពីការប្រគល់វិញ»",
+  "免责声明": "«ប្រកាសដកហ responsabilidad»",
+  "我已阅读并同意": "ខ្ញុំបានអានហើយយល់ព្រម",
+  "订单总价": "តម្លៃសរុបសម្រាប់ការสั่งซื้อ",
+  "总价": "តម្លៃសរុប",
+  "运费到仓库": "ថ្លៃដឹកជញ្ជូនដល់ឃ្លាំង",
+  "折扣": "បញ្ចុះតម្លៃ",
+  "温馨提示": "ការជូនដំណឹងមានអស់កំរិត",
+  "提示内容": "បន្ទាប់ពីដាក់ជូនការสั่งซื้อและបង់ប្រាក់ សូមរង់ចាំអ្នកលក់ផ្ញើទំនិញ ហើយបន្ទាប់ពីមកដល់ឃ្លាំង សូមដាក់ជូនការสั่งបែបបណ្តុះអន្តរជាតិ។",
+  "请阅读并同意": "សូមអានហើយយល់ព្រម",
+  "支付方式": "វិធីបង់ប្រាក់",
+  "请在": "សូមនៅក្នុង",
+  "取消付款提示": "មុនបង់ប្រាក់ ពначеវានឹងត្រូវបានលុបចោល។",
+  "余额不足需充值": "សមតុល្យមិនគ្រប់គ្រាន់ ត្រូវបង់បន្ថែម",
+  "用余额支付": "បង់ប្រាក់ដោយប្រើសមតុល្យ",
+  "推荐": "ណែនាំ",
+  "充值": "បង់បន្ថែម",
+  "支付": "បង់ប្រាក់",
+  "手续费": "កម្រៃសេវាកម្ម",
+  "名称订单号商品名称": "ឈ្មោះ/លេខការสั่งซื้อ/ឈ្មោះទំនិញ",
+  "待付款": "រង់ចាំបង់ប្រាក់",
+  "筛选": "ចម្រាញ់",
+  "创建时间": "ពេលវេលាបង្កើត",
+  "订单时间": "ពេលវេលាការสั่งซื้อ",
+  "重置": "កំណត់ឡើងវិញ",
+  "开始日期": "ថ្ងៃចាប់ផ្តើម",
+  "结束日期": "ថ្ងៃបញ្ចប់",
+  "不支退货换货": "មិនទាញយក/ផ្លាស់ប្តូរទំនិញ >",
+  "结束时间": "ពេលវេលាបញ្ចប់",
+  "取消": "បោះបង់",
+  "删除订单": "លុបការสั่งซื้อ",
+  "全选": "ជ្រើសរើសទាំងអស់",
+  "合并付款": "បង់ប្រាក់រួមគ្នា",
+  "订单详情": "ព័ត៌មានលម្អិតការสั่งซื้อ",
+  "订单流程": "ដំណើរការការสั่งซื้อ",
+  "处理中": "កំពុងដំណើរការ",
+  "订单号": "លេខការสั่งซื้อ",
+  "复制": "ចម្លង",
+  "复制成功": "ចម្លងជោគជ័យ",
+  "小计": "រង់ចាំសរុប",
+  "国内货运": "ដឹកជញ្ជូនក្នុងស្រុក",
+  "订单补充付款": "បង់ប្រាក់បន្ថែមសម្រាប់ការสั่งซื้อ",
+  "涉及增值服务费": "ពាក់ព័ន្ធនឹងកម្រៃសេវាកម្មបន្ថែម",
+  "店铺": "ហាង",
+  "提醒": "រំលឹង",
+  "您确定要从收藏中移除该店铺吗": "តើអ្នកប្រាកដថាចង់ដកហាងនេះចេញពីការរក្សាទុកមែនទេ?",
+  "您确定要从收藏中移除该产品吗": "តើអ្នកប្រាកដថាចង់ដកផលិតផលនេះចេញពីការរក្សាទុកមែនទេ?",
+  "默认": "លំនាំដើម",
+  "收件地址": "អាស័យដ្ឋានទទួល",
+  "账户地址": "អាស័យដ្ឋានគណនី",
+  "关于Hoobuy": "អំពី Hoobuy",
+  "隐私政策": "គោលការណ៍ឯកជនភាព",
+  "服务条款": "លក្ខខណ្ឌសេវាកម្ម",
+  "ID": "លេខសម្គាល់",
+  "修改密码tips": "ពាក្យសម្ងាត់ដែលមានកម្រិតខ្ពស់ធ្វើឱ្យគណនីរបស់អ្នកមានសុវត្ថិភាពកាន់តែច្រើន។ សូមផ្លាស់ប្តូរពាក្យសម្ងាត់ជាទៀងទាត់។",
+  "交易密码tips": "ត្រូវការផ្ទៀងផ្ទាត់ពាក្យសម្ងាត់នៅពេលប្រើសមតុល្យសម្រាប់ប្រតិបត្តិការ ដើម្បីបង្កើនសុវត្ថិភាពគណនី។",
+  "账户安全": "សុវត្ថិភាពគណនី",
+  "修改登录密码": "ផ្លាស់ប្តូរពាក្យសម្ងាត់ចូល",
+  "编辑": "កែសម្រួល",
+  "新交易密码": "ពាក្យសម្ងាត់ប្រតិបត្តិការថ្មី",
+  "登录密码": "ពាក្យសម្ងាត់ចូល",
+  "新密码": "ពាក្យសម្ងាត់ថ្មី",
+  "再次输入密码": "បញ្ចូលពាក្យសម្ងាត់ម្តងទៀង",
+  "交易密码": "ពាក្យសម្ងាត់ប្រតិបត្តិការ",
+  "原交易密码": "ពាក្យសម្ងាត់ប្រតិបត្តិការដើម",
+  "打包": "បែបបណ្តុះ",
+  "请选择地址": "សូមជ្រើសអាស័យដ្ឋាន",
+  "添加收货地址": "បន្ថែមអាស័យដ្ឋានទទួល",
+  "确认": "បញ្ជាក់",
+  "添加送货地址": "បន្ថែមអាស័យដ្ឋានដឹកជញ្ជូន",
+  "收件人": "អ្នកទទួល",
+  "名": "នាមខ្លី",
+  "姓": "នាមត្រកូល",
+  "地区": "តំបន់",
+  "详细地址": "អាស័យដ្ឋានលម្អិត",
+  "输入公寓号码街道道路地址": "បញ្ចូលលេខអಪាតម៉ង់ ផ្លូវ/ផ្លូវអាស័យដ្ឋានជាដើម",
+  "如果没有门牌号可以输入": "ប្រសិនបើគ្មានលេខផ្ទះ អ្នកអាចបញ្ចូល 0000",
+  "邮政编码": "លេខប្រៃសណីយ៍",
+  "电话号码": "លេខទូរស័ព្ទ",
+  "税号": "លេខពន្ធ",
+  "地址标签": "ស្លាកអាស័យដ្ឋាន",
+  "默认地址": "អាស័យដ្ឋានលំនាំដើម",
+  "门号": "លេខផ្ទះ",
+  "选择": "ជ្រើសរើស",
+  "国家": "ប្រទេស",
+  "收件人必须填写": "អ្នកទទួលត្រូវបញ្ចូល",
+  "国家和州/省必须填写": "ប្រទេសនិងរដ្ឋ/ខេត្តត្រូវបញ្ចូល",
+  "详细地址必须填写": "អាស័យដ្ឋានលម្អិតត្រូវបញ្ចូល",
+  "邮政编码必须填写": "លេខប្រៃសណីយ៍ត្រូវបញ្ចូល",
+  "电话号码必须填写": "លេខទូរស័ព្ទត្រូវបញ្ចូល",
+  "公司": "ក្រុមហ៊ុន",
+  "请先添加收件地址": "សូមបន្ថែមអាស័យដ្ឋានទទួលដំបូង",
+  "编辑收货地址": "កែសម្រួលអាស័យដ្ឋានទទួល",
+  "您确认删除吗": "តើអ្នកប្រាកដថាចង់លុបមែនទេ?",
+  "所有包裹": "ទាំងអស់បែបបណ្តុះ",
+  "运费": "ថ្លៃដឹកជញ្ជូន",
+  "确认收货": "បញ្ជាក់ទទួលទំនិញ",
+  "物流信息": "ព័ត៌មានដឹកជញ្ជូន",
+  "账单": "វិក័យប័ត្រ",
+  "提现": "ដកប្រាក់",
+  "充值金额": "ចំនួនបង់បន្ថែម",
+  "请输入金额": "សូមបញ្ចូលចំនួន",
+  "选择充值方式": "ជ្រើសរើសវិធីបង់បន្ថែម",
+  "充值步骤": "ជំហានបង់បន្ថែម",
+  "充值地址": "អាស័យដ្ឋានបង់បន្ថែម",
+  "完成付款": "បញ្ចប់ការបង់ប្រាក់",
+  "记录": "កំណត់ត្រា",
+  "充值记录": "កំណត់ត្រាបង់បន្ថែម",
+  "银行名称": "ឈ្មោះធនាគារ",
+  "收款人": "អ្នកទទួលប្រាក់",
+  "银行卡": "កាតធនាគារ",
+  "待审核": "រង់ចាំពិនិត្យ",
+  "已完成": "បានបញ្ចប់",
+  "提现记录": "កំណត់ត្រាដកប្រាក់",
+  "姓名": "ឈ្មោះ",
+  "提款": "ដកប្រាក់",
+  "可用余额": "សមតុល្យអាចប្រើបាន",
+  "提款金额": "ចំនួនដកប្រាក់",
+  "请输入提款金额": "សូមបញ្ចូលចំនួនដកប្រាក់",
+  "编辑您的银行卡": "កែសម្រួលគណនីធនាគាររបស់អ្នក",
+  "您的银行卡账户": "គណនីធនាគាររបស់អ្នក",
+  "保存": "រក្សាទុក",
+  "请填写持卡人姓名": "សូមបញ្ចូលឈ្មោះម្ចាស់កាត",
+  "请填写银行名称": "សូមបញ្ចូលឈ្មោះធនាគារ",
+  "请填写银行卡": "សូមបញ្ចូលលេខកាតធនាគារ",
+  "未通过原因": "ហេតុផលមិនពេញចិត្ត",
+  "未通过": "មិនពេញចិត្ត",
+  "汇款中": "កំពុងផ្ញើប្រាក់",
+  "已汇款": "បានផ្ញើប្រាក់",
+  "取款金额": "ចំនួនដកប្រាក់",
+  "步骤": "ជំហាន",
+  "选购商品": "ជ្រើសរើសទំនិញ",
+  "仓储质检": "រក្សា & ពិនិត្យ",
+  "运输到家": "ដឹកជញ្ជូនដល់ផ្ទះ",
+  "或者": "ឬ",
+  "tips_text": "ប្រសិនបើអ្នកមានគណនីរួចហើយ សូមប្រើគណនីរបស់អ្នកចូល ហើយបន្ទាប់មកនៅលើទំព័រព័ត៌មានផ្ទាល់ខ្លួនរបស់អ្នកភ្ជាប់ទៅហ្វេសបุក កូហ្គល ឬអេបផល។",
+  "使用脸书登录": "ចូលដោយប្រើហ្វេសបុក",
+  "使用谷歌登录": "ចូលដោយប្រើកូហ្គល",
+  "使用苹果登录": "ចូលដោយប្រើអេបផល",
+  "没有账号": "គ្មានគណនី ឥឡូវនេះ",
+  "直播": "ផ្សាយផ្ទាល់",
+  "关注": "តាមដាន",
+  "精选": "ជ្រើសរើស",
+  "tabbar.商城": "ម៉ាល់",
+  "tabbar.订单": "ការสั่งซื้อ",
+  "tabbar.订单详情": "ព័ត៌មានលម្អិតការสั่งซื้อ",
+  "我的订单": "ការสั่งซื้อរបស់ខ្ញុំ",
+  "我的地址": "អាស័យដ្ឋានរបស់ខ្ញុំ",
+  "网购专家": "អ្នកជំនួយទិញអនឡាញ",
+  "其他功能": "មុខងារផ្សេងទៀង",
+  "邀请有礼": "អញ្ជើញមានរង្វាន់",
+  "实名认证": "ផ្ទៀងផ្ទាត់អត្តសញ្ញាណជាតិ",
+  "系统设置": "ការកំណត់ប្រព័ន្ធ",
+  "账号管理": "គ្រប់គ្រងគណនី",
+  "客服中心": "មជ្ឈមណ្ឌលអ្នកជំនួយ",
+  "收货地址": "អាស័យដ្ឋានទទួល",
+  "新增收货地址": "បន្ថែមអាស័យដ្ឋានទទួលថ្មី",
+  "购物车": "រទេះទំនិញ",
+  "请输入关键字": "សូមបញ្ចូលពាក្យគន្លឹះ",
+  "拼多多": "បីដואដוא",
+  "代购订单": "ការสั่งซื้อជំនួស",
+  "我的集运包裹": "បែបបណ្តុះដឹកជញ្ជូនរបស់ខ្ញុំ",
+  "自助集运包裹": "បែបបណ្តុះដឹកជញ្ជូនដោយខ្លួនឯង",
+  "当前状态": "ស្ថានភាពបច្ចុប្បន្ន",
+  "实付": "បង់ពិតប្រាក់",
+  "平台订单号": "លេខការสั่งซื้อវេទិកា",
+  "支付编号": "លេខកូដបង់ប្រាក់",
+  "订单状态": "ស្ថានភាពការสั่งซื้อ",
+  "查看已完成订单": "មើលការสั่งซื้อដែលបានបញ្ចប់",
+  "五项服务全面呵护你的包裹号": "សេវាកម្មប្រាំប្រភេទការថែរក្សាបែបបណ្តុះរបស់អ្នក",
+  "点击步骤即可查看详情哦~": "ចុចជំហានដើម្បីមើលព័ត៌មានលម្អិត~",
+  "入库中": "កំពុងចូលឃ្លាំង",
+  "专业质检": "ការពិនិត្យគុណភាពជំនាញ",
+  "商品实拍": "ថតរូបទំនិញពិត",
+  "加固/重新包装": "ពង្រឹង/បង្កើតបែបបណ្តុះឡើងវិញ",
+  "已完成,待集运": "បានបញ្ចប់, រង់ចាំដឹកជញ្ជូន",
+  "接受瑕疵": "ទទួលយកខុសត្រូវ",
+  "退款": "សងប្រាក់វិញ",
+  "kf_hint": "បានស្វែងរកឃើញថាផលិតផលអាចមានខុសត្រូវ តើអ្នកទទួលយកខុសត្រូវឬសងប្រាក់វិញ? ប្រសិនបើមានសំណួរអ្នកអាចទំនាក់ទំនងជាមួយសេវាកម្មអតិថិជន VAVABUY",
+  "编辑资料": "កែសម្រួលព័ត៌មាន",
+  "请输入昵称": "សូមបញ្ចូលនាមអនុស្សី",
+  "昵称": "នាមអនុស្សី",
+  "保存修改": "រក្សាទុកការផ្លាស់ប្តូរ",
+  "请勾选确认接受瑕疵": "សូមជ្រើសត្រូវដើម្បីបញ្ជាក់ទទួលយកខុសត្រូវ",
+  "返回": "ត្រឡប់ក្រោយ",
+  "同意并已阅读免责说明": "យល់ព្រមហើយបានអានការពិពណ៌នាដកហឥទ្ធិពល",
+  "是否专业质检": "មានការពិនិត្យគុណភាពជំនាញទេ",
+  "商品仓库": "ឃ្លាំងទំនិញ",
+  "集运包裹": "បែបដឹកជញ្ជូន",
+  "物流详细": "ព័ត៌មានលម្អិតដឹកជញ្ជូន",
+  "查看物流": "មើលដឹកជញ្ជូន",
+  "去结算": "ទៅបង់ប្រាក់",
+  "确定要退出登录吗": "តើអ្នកប្រាកដថាចង់ចាកចេញពីគណនីមែនទេ?",
+  "提示": "ការជូនដំណឹង",
+  "说点什么...": "និយាយអ្វីមួយ...",
+  "评论": "មតិ",
+  "发送": "ផ្ញើ",
+  "回复": "ឆ្លើយតប",
+  "退出登录": "ចាកចេញពីគណនី",
+  "个人资料": "ព័ត៌មានផ្ទាល់ខ្លួន",
+  "1688工厂直销": "1688 ផលិតផលផ្ទាល់",
+  "工厂直销": "ផលិតកម្មផលិតផលដោយផ្ទាល់",
+  "服装、美妆、母婴、食品、数码产品、家电、家具": "សម្លៀកបំពាក់ ផលិតផលសម្អាង កុមារ និងម្តាយ អាហារ ផលិតផលឌីជីថល ឧបករណ៍គ្រួសារ គ្រឿងសង្ហារិម",
+  "全球最大的C2C电商平台之一": "មួយក្នុងចំណោមវេទិកាអេឡិចត្រូនិក C2C ធំជាងគេបណ្តោយពិភពលោក",
+  "主流电子商务应用产品平台": "វេទិកាផលិតផល និងអព្លិកេសិនអេឡិចត្រូនិកពាណិជ្ជកម្មលេចធ្លោ",
+  "查看并确认": "មើលហើយបញ្ជាក់",
+  "验证码为必填项": "កូដផ្ទៀងផ្ទាត់ជាតម្រូវការ",
+  "请输入电子邮件": "សូមបញ្ចូលអ៊ីមែល",
+  "验证码": "កូដផ្ទៀងផ្ទាត់",
+  "我的邀请码": "លេខអញ្ជើញរបស់ខ្ញុំ",
+  "推广步骤": "ជំហានពិពន្ធ",
+  "证件类型": "ប្រភេទឯកសារ",
+  "身份证号码": "លេខអត្តសញ្ញាណបុគ្គល",
+  "上传证件正面照片": "ផ្ទុករូបសមុខឯកសារ",
+  "上传证件反面照片": "ផ្ទុករូបខាងក្រោយឯកសារ",
+  "请选择证件类型": "សូមជ្រើសរើសប្រភេទឯកសារ",
+  "请填写身份证号码": "សូមបញ្ចូលលេខអត្តសញ្ញាណបុគ្គល",
+  "请填写姓名": "សូមបញ្ចូលឈ្មោះ",
+  "成功": "ជោគជ័យ",
+  "失败": "បរាជ័យ",
+  "刚刚": "ទើបតែ",
+  "分钟前": "នាទីមុន",
+  "小时前": "ម៉ោងមុន",
+  "昨天": "ម្សិលមិញ",
+  "天前": "ថ្ងៃមុន",
+  "身份证": "អត្តសញ្ញាណបុគ្គល",
+  "护照": "លិខិតឆ្លងដែន",
+  "驾驶证": "អនុញ្ញាតបើករថយន្ត",
+  "密码是必需的且为6位": "ពាក្យសម្ងាត់ជាតម្រូវការហើយមាន6ខ្ទង់",
+  "链接已复制": "តំណភ្ជាប់ត្រូវបានចម្លង",
+  "verification_text": "យើងនឹងមិនបង្ខំអោយអតិថិជនធ្វើផ្ទៀងផ្ទាត់អត្តសញ្ញាណជាតិទេ ដើម្បីមិនប៉ះពាល់ដល់បទពិសោធន៍ទិញប្រសិនបើផលិតផលដែលអ្នកទិញលើស1000ដុល្លារ។ យោងតាមបទបញ្ញត្តិឆាកអូស្ត្រាលី យើងត្រូវការឯកសាររបស់អ្នកដើម្បីដំណើរការដំណើរការនេះលឿនជាង។",
+  "请输入支付密码": "សូមបញ្ចូលពាក្យសម្ងាត់បង់ប្រាក់",
+  "qualityInspection": "ការពិនិត្យគុណភាពជំនាញគឺជាសេវាកម្មបន្ថែម ដែលសេវាកម្មនេះគ្រប់គ្រាន់{amount}យुआន。 យើងនឹងជួយអ្នកផ្ទៀងផ្ទាត់គុណភាពសុខភាពរបស់ផលិតផល និងថតរូបដើម្បីអ្នកបញ្ជាក់មុនពេលផ្ញើទៅប្រទេសរបស់អ្នក។",
+  "待确认": "រង់ចាំបញ្ជាក់",
+  "分享给好友": "ចែករំលែកទៅមិត្តភក្តិ",
+  "分享到朋友圈": "ចែករំលែកទៅរង្វង់មិត្តភក្តិ",
+  "查看": "មើល",
+  "去支付": "ទៅបង់ប្រាក់",
+  "关于vavabuy": "អំពី VAVABUY",
+  "我知道了": "ខ្ញុំដឹងហើយ",
+  "关于我们": "អំពីយើង",
+  "用户协议": "ព្រមព្រៀងអតិថិជន",
+  "隐私协议": "ព្រមព្រៀងឯកជនភាព",
+  "违规物品说明": "ការពិពណ៌នាអំពីទំនិញប្រហ្មង",
+  "上传失败": "ផ្ទុកបរាជ័យ",
+  "证件号码": "លេខឯកសារ",
+  "质检费用": "កម្រៃការពិនិត្យគុណភាព",
+  "入库时间": "ពេលវេលាចូលឃ្លាំង",
+  "支付成功": "បង់ប្រាក់ជោគជ័យ!",
+  "继续购物": "បន្តទិញ",
+  "查看订单": "មើលការสั่งซื้อ",
+  "增值服务": "សេវាកម្មបន្ថែម",
+  "易碎品加固": "ពង្រឹងទំនិញផុសបែកងាយ",
+  "标准质检": "ការពិនិត្យគុណភាពស្តង់ដារ",
+  "优先采购": "ទិញជាមុន",
+  "个性化拍照": "ថតរូបផ្ទាល់ខ្លួន",
+  "服务说明": "ការពិពណ៌នាសេវាកម្ម",
+  "增值费用": "រួមមានកម្រៃបន្ថែម",
+  "_gxhpz_desc": "1、បំពេញតម្រូវការរបស់អ្នកក្នុងការមើលព័ត៌មានលម្អិតនៃផលិតផល,អ្នកអាចធ្វើចំណាំនៅពេលបញ្ជាទិញ,រូបថតមួយអាចបំពេញតម្រូវការថតរូបមួយប៉ុណ្ណោះ,ប្រសិនបើត្រូវការលម្អិតច្រើនជាងនេះ,សូមធ្វើចំណាំតម្រូវការថតរូបដែលត្រូវនៅពេលជ្រើសរើសចំនួនបញ្ជាទិញ។\n 2、នៅពេលអ្នកជ្រើសរើសបង់ប្រាក់ជោគជ័យហើយផលិតផលមានស្ថានភាព「ក្នុងឃ្លាំង」,យើងនឹងធ្វើបញ្ចប់ប្រតិបត្តិការក្នុងរយៈពេល24ម៉ោង។",
+  "_yspjg_desc": "1、ប្រើជួរពពុះសម្រាប់ស្លាក់បញ្ចូលរឹងមាំសម្រាប់ផលិតផលដែលងាយបែក/ងាយខូច(ដូចជាផលិតផលកែវ、តួចិញ្ចឹមជាដើម)。\n 2、បន្ទាប់ពីបញ្ចប់ប្រតិបត្តិការនឹងផ្លាស់ប្តូរទម្ងន់、បរិមាត្រនៃផលិតផល。\n3、នៅពេលអ្នកជ្រើសរើសបង់ប្រាក់ជោគជ័យហើយផលិតផលមានស្ថានភាព「ក្នុងឃ្លាំង」,យើងនឹងធ្វើបញ្ចប់ប្រតិបត្តិការក្នុងរយៈពេល24ម៉ោង។",
+  "_yxdg_desc": "ការកុម្ម៉ង់ដែលបានគូសធីកសេវាកម្ម «ទិញឥវ៉ាន់អាទិភាព» នឹងត្រូវបានដោះស្រាយក្នុងរយៈពេល 4 ម៉ោងនៃម៉ោងធ្វើការរបស់អ្នកទិញ។ ប្រសិនបើត្រូវការបញ្ជាក់បន្ថែម ឬការកុម្ម៉ង់បន្ថែមប្រាក់ អតិថិជនត្រូវដោះស្រាយជាមួយមុនពេលដែលការទិញត្រូវបានអនុវត្ត។ ក្រោយពីបានដាក់ការកុម្ម៉ង់ ថ្លៃសេវាកម្ម «ទិញឥវ៉ាន់អាទិភាព» នឹងមិនត្រូវបានសងប្រាក់វិញឡើយ។",
+  "_bzzj_desc": "1. ផ្ដល់សេវាកម្មពិនិត្យផលិតផលពីមុំធម្មតា ការវេចខ្ចប់ ស្លាកតម្លៃ និងពិការភាព និងថតរូបច្បាស់លាស់ចំនួន ២-៣ សម្រាប់អ្នកមើល។\n2. បន្ទាប់ពីអ្នកជ្រើសរើសបង់ប្រាក់ដោយជោគជ័យ ហើយផលិតផលស្ថិតក្នុងស្ថានភាព «នៅក្នុងឃ្លាំង» យើងខ្ញុំនឹងធ្វើការក្នុងរយៈពេល ២៤ ម៉ោង។",
+  "Google支付": "បង់ប្រាក់Google",
+  "Apple支付": "បង់ប្រាក់Apple",
+  "仓储期": "រយៈពេលរក្សាទុក",
+  "天": "ថ្ងៃ",
+  "续期": "ពន្យាពេល",
+  "已过期": "ផុតកំណត់",
+  "续存储期": "ពន្យាពេលរក្សាទុក",
+  "续存储期提示": "ពន្យាពេលរក្សាទុកអតិបរមាគឺ100ថ្ងៃ",
+  "总计": "សរុប",
+  "商品数量": "ចំនួនទំនិញ",
+  "单价": "តម្លៃឯកតា",
+  "pay_fail_msg": "បង់ប្រាក់បរាជ័យ សូមពិនិត្យមើល!",
+  "我的优惠券": "កាតបញ្ចុះតម្លៃរបស់ខ្ញុំ",
+  "可使用": "អាចប្រើ",
+  "已使用": "បានប្រើ",
+  "立即使用": "ប្រើឥឡូវនេះ",
+  "满": "ពេញ",
+  "可用": "អាចប្រើបាន",
+  "minimum_amount": "ពេញ{amount}អាចប្រើបាន",
+  "领取成功": "ទទួលជោគជ័យ",
+  "运费券": "កាតថ្លៃដឹកជញ្ជូន",
+  "购物券": "កាតទិញ",
+  "银行卡号": "លេខកាតធនាគារ",
+  "有效期": "អម្ម័នកំណត់",
+  "安全码": "កូដសុវត្ថិភាព",
+  "请输入消息内容": "សូមបញ្ចូលមាតិកាសារ",
+  "猜你想问": "តែងតែសួរ",
+  "VAVABUY专属官方客服": "អ្នកជំនួយផ្លូវការផ្ទាល់VAVABUY",
+  "付费咨询": "សួរសំណើដោយបង់ប្រាក់",
+  "您已经开通专属客服": "អ្នកបានបើកអ្នកជំនួយផ្ទាល់រួចហើយ",
+  "网购助手": "អ្នកជំនួយទិញអនឡាញ",
+  "领": "ទទួល",
+  "系统": "ប្រព័ន្ធ",
+  "重置密码": "កំណត់ពាក្យសម្ងាត់ឡើងវិញ",
+  "选择物流路线": "ជ្រើសរើសផ្លូវដឹកជញ្ជូន",
+  "邮寄周期": "រយៈពេលផ្ញើ",
+  "报价说明": "ការពិពណ៌នាអំពីតម្លៃ",
+  "详情": "លម្អិត",
+  "请选择物流路线": "សូមជ្រើសរើសផ្លូវដឹកជញ្ជូន",
+  "正在加载": "កំពុងផ្ទុក...",
+  "条新消息": "សារថ្មី",
+  "你确定要删除此订单吗?": "តើអ្នកប្រាកដថាចង់លុបការสั่งซื้อนេះមែនទេ?",
+  "会话已关闭": "សន្ទនាត្រូវបានបិទ",
+  "结束会话": "បញ្ចប់សន្ទនា",
+  "申请退款": "ដាក់ស្នើសងប្រាក់វិញ",
+  "在线": "អនឡាញ",
+  "page.user_chat.tipPopupContentForCloseChat": "តើអ្នកប្រាកដថាចង់បញ្ចប់សន្ទនាបច្ចុប្បន្នមែនទេ?",
+  "page.user_chat.tipPopupContentForRefund": "តើអ្នកប្រាកដថាចង់ដាក់ស្នើសងប្រាក់វិញមែនទេ?",
+  "page.user_chat.tipPopupContentForPay": "<view>សេវាកម្មនេះគឺជាកម្មវិធីសួរសំណើដោយបង់ប្រាក់ ដែលសេវាកម្មមួយៗគ្រប់គ្រាន់1.3ដុល្លារ យើងសន្យាកម្មជាលើកនៅតែផ្តល់សេវាកម្មដល់អ្នក ជ JSONSchemaValidatorសំណួររបស់អ្នកទទួលបានការដោះស្រាយដែលពេញចិត្ត។</view><view class='' style='margin:16rpx 0 0;'>ប្រសិនបើសំណួររបស់អ្នកមិនទទួលបានការដោះស្រាយដែលមានប្រសិទ្ធភាព យើងសន្យាអោយសងកម្រៃដែលបានបង់ទាំងអស់ត្រឡប់ទៅសមតុល្យគណនីរបស់អ្នក។</view>",
+  "正在安装文件": "កំពុងដំឡើងឯកសារ...",
+  "应用资源更新完成": "ការធ្វើឱ្យប្រសើរឡើងធនធានអപ്ലიკੇਸិនបានបញ្ចូល!",
+  "文件下载失败": "ការទាញយកឯកសារបរាជ័យ...",
+  "准备下载": "ត្រៀមទាញយក...",
+  "开始下载": "ចាប់ផ្តើមទាញយក...",
+  "已下载": "បានទាញយក",
+  "已取消下载": "បានបោះបង់ការទាញយក",
+  "安装文件失败": "ដំឡើងឯកសារបរាជ័យ",
+  "新版本": "ឃើញកំណែថ្មី",
+  "发现新版本": "បានរកឃើញកំណែថ្មី៖",
+  "立即升级": "ធ្វើឱ្យប្រសើរឡើងឥឡូវនេះ",
+  "暂不升级": "មិនធ្វើឱ្យប្រសើរឡើងឥឡូវនេះ",
+  "正在为您更新请耐心等待": "កំពុងធ្វើឱ្យប្រសើរឡើងសម្រាប់អ្នក សូមរង់ចាំ",
+  "升级APP": "ធ្វើឱ្យប្រសើរឡើងAPP",
+  "取消下载": "បោះបង់ការទាញយក",
+  "后台下载": "ទាញយកនៅខាងក្រោយ",
+  "暂无新版本": "គ្មានកំណែថ្មី",
+  "返回首页": "ត្រឡប់ទៅទំព័រដើម",
+  "查看包裹": "មើលបែបបណ្តុះ",
+  "warehouse_tips": "បែបបញ្ជីដឹកជញ្ជូនរបស់អ្នកត្រូវបានបង្កើត សូមរង់ចាំថ្លៃដឹកជញ្ជូនជាក់លាក់ជាធម្មតាត្រូវការ1ដល់2ម៉ោង។ អ្នកអាចបញ្ជាក់បែបបណ្តុះអន្តរជាតិរបស់អ្នកនៅមជ្ឈមណ្ឌលបែបបណ្តុះ។",
+  "预付费用明细": "ព័ត៌មានលម្អិតកម្រៃប្រាក់ប្រមាណ",
+  "实际运费明细": "ព័ត៌មានលម្អិតថ្លៃដឹកជញ្ជូនពិត",
+  "其他费用明细": "ព័ត៌មានលម្អិតកម្រៃផ្សេងទៀង",
+  "预估费用": "កម្រៃប្រមាណ",
+  "预估运费": "ថ្លៃដឹកជញ្ជូនប្រមាណ",
+  "预估运费重": "ទម្ងន់ថ្លៃដឹកជញ្ជូនប្រមាណ",
+  "首重": "ទម្ងន់ដំបូង",
+  "续重": "ទម្ងន់បន្ថែម",
+  "操作费": "កម្រៃប្រតិបត្តិការ",
+  "报关费": "កម្រៃដាក់ច្បាប់",
+  "燃油附加费": "កម្រៃបន្ថែមប្រេង",
+  "偏远地区费用": "កម្រៃតំបន់ដាច់ស្រយាល",
+  "旺季附加费": "កម្រៃបន្ថែមរដូវកំណើន",
+  "运费优惠": "បញ្ចុះតម្លៃថ្លៃដឹកជញ្ជូន",
+  "实际费用": "កម្រៃពិត",
+  "实际运费": "ថ្លៃដឹកជញ្ជូនពិត",
+  "实际计费重": "ទម្ងន់គណនាពិត",
+  "实际体积": "ទំហំនាពិត",
+  "其他费用": "កម្រៃផ្សេងទៀង",
+  "打包费": "កម្រៃបែបបណ្តុះ",
+  "商品已下架": "ផលិតផលត្រូវបានដកចេញពីលក់",
+  "相机权限说明": "ការពិពណ៌នាសិទ្ធិម៉ាស៊ីនថត",
+  "用于上传用户头像、或依据图片信息搜索内容": "ប្រើសម្រាប់ផ្ទុករូបសម្គាល់អ្នកប្រើ ឬស្វែងរកមាតិកាផ្អែកលើព័ត៌មានរូប",
+  "存储权限说明": "ការពិពណ៌នាសិទ្ធិរក្សាទុក",
+  "用于选择照片": "ប្រើសម្រាប់ជ្រើសរើររូប ឬផ្ទុករូបសម្គាល់អ្នកប្រើ",
+  "你想取消付款嘛": "តើអ្នកចង់បោះបង់ការបង់ប្រាក់មែនទេ?",
+  "订单取消后无法恢复,请选择取消付款的原因": "ការสั่งซื้อត្រូវបានបោះបង់មិនអាច بازیឡើងវិញបានទេ សូមជ្រើសរើរហេតុផលបោះបង់ការបង់ប្រាក់",
+  "请输入取消原因": "សូមបញ្ចូលហេតុផលបោះបង់",
+  "uni.app.quit": "ចុចម្តងទៀងដើម្បីចាកចេញពីអപ്ലიკੇਸិន",
+  "订单处理中": "កំពុងដំណើរការការสั่งซื้อ...",
+  "运输中": "កំពុងដឹកជញ្ជូន",
+  "不想要了": "មិនចង់បានទៀង",
+  "买错了": "ទិញខុស",
+  "价格太贵": "តម្លៃថ្លៃពេក",
+  "邀请记录": "កំណត់ត្រាអញ្ជើញ",
+  "暂无邀请记录": "គ្មានកំណត់ត្រាអញ្ជើញ",
+  "质检照片": "រូបការពិនិត្យគុណភាព",
+  "系统消息": "សារប្រព័ន្ធ",
+  "未读": "មិនបានអាន",
+  "消息详情": "ព័ត៌មានលម្អិតសារ",
+  "待支付": "រង់ចាំបង់",
+  "待入库": "រង់ចាំចូលឃ្លាំង",
+  "待质检": "រង់ចាំពិនិត្យ",
+  "待集运": "រង់ចាំដឹកជញ្ជូន",
+  "退款和售后": "លក់ចុង",
+  "体积": "حجم",
+  "重量": "ទម្ងន់",
+  "明细": "លម្អិត",
+  "总体积": "حجمសរុប",
+  "总重量": "ទម្ងន់សរុប",
+  "续重费用": "កម្រៃទម្ងន់បន្ថែម",
+  "首重费用": "កម្រៃទម្ងន់ដំបូង",
+  "您将在安全的环境下付款给": "អ្នកនឹងបង់ប្រាក់ទៅក្នុងបរិយាកាសសុវត្ថិភាព",
+  "从VAVABUY到": "ពី VAVABUY ទៅ",
+  "请输入重量": "សូមបញ្ចូលទំងន់",
+  "商品类别": "ប្រភេទផលិតផល",
+  "查询": "ស្វែងរក",
+  "长度": "ប្រវែង",
+  "宽度": "ទទឹង",
+  "高度": "កំពស់",
+  "热门平台": "វេទិកាពេញនិយម",
+  "立即进入": "ចូលរហ័ស",
+  "网购专家指引": "ណែនាំអ្នកជំនាញទិញអ៊ីនធឺណិត",
+  "帮你快速上手选择性价比商品": "ជួយរហ័សជ្រើសទំនិញតម្លៃសមរម្យ",
+  "点击跳转": "ចុចទៅ",
+  "追踪订单": "តាមដានការកុម៉ង់",
+  "价格追踪": "តាមដានតម្លៃ",
+  "关注列表": "បញ្ជីតាមដាន",
+  "请填写必填信息": "សូមបំពេញព័ត៌មានចាំបាច់",
+  "目的地": "គោលដៅ",
+  "暂无选项": "មិនមានជម្រើស",
+  "请选择商品类别": "សូមជ្រើសរើសប្រភេទផលិតផល",
+  "比加入时": "បើប្រៀបធៀបនឹងពេលដែលបានបន្ថែម",
+  "降": "ការចុះ",
+  "涨": "ការឡើង",
+  "进行中的订单": "ការបញ្ជាទិញដែលកំពុងដំណើរការ",
+  "手机号": "លេខទូរស័ព្ទ",
+  "手机登录": "ចូលប្រើតាមទូរស័ព្ទ",
+  "手机号为必填项": "លេខទូរស័ព្ទគឺជាលĩnh vựcចាំបាច់",
+  "邮箱登录": "ចូលប្រើតាមអ៊ីម៉ែល",
+  "手机注册": "ចុះឈ្មោះតាមទូរស័ព្ទ",
+  "邮箱注册": "ចុះឈ្មោះតាមអ៊ីម៉ែល",
+  "手机重置": "កំណត់ឡើងវិញទូរស័ព្ទ",
+  "邮箱重置": "កំណត់ឡើងវិញអ៊ីមែល",
+  "请输入手机号": "សូមស្នូលលេខទូរស័ព្ទ",
+  "ABA KHQR": "ABA KHQR",
+  "暂无优惠券": "មិនមានកូដបញ្ចុះតម្លៃទេ",
+  "免邮专区": "តំបន់ដឹកជញ្ជូនឥតគិតថ្លៃ",
+  "实用功能": "មុខងារប្រើប្រាស់",
+  "特色优惠": "ការផ្តល់ពិសេស",
+  "待评价": "ត្រូវប្រเมន",
+  "查看评论": "មើលយោបវន្ត",
+  "确定收到货了吗": "តើអ្នកប្រាកដជាទទួលបានទំនិញហើយឬនៅ?",
+  "购物车预览": "មើលប្រїត្តិភាពរទេះទំនិញ",
+  "商品评价": "ការយោបវន្តទំនិញ",
+  "评价内容": "មាតិកាការយោបវន្ត",
+  "分享你的使用感受,帮助其他买家选择": "ចែករំលែកអារម្មណ៍ការប្រើប្រាស់របស់អ្នក ដើម្បីជួយអ្នកទិញផ្សេងទៀតធ្វើការជ្រើសរើស",
+  "上传图片": "ប្រឡើងបញ្ចូលរូបភាព",
+  "暂无评论内容": "មិនមានមាតិកាការយោបវន្តនៅឡើយ",
+  "用户评论": "ការយោបវន្តរបស់អ្នកប្រើ",
+  "总销量": "ការលក់សរុប៖",
+  "福利中心": "អត្ថប្រយោជន៍",
+  "VAVA精选": "VAVA ជ្រើសរើស",
+  "我要回购": "ខ្ញុំចង់ទិញវិញ",
+  "敬请期待": "សូមរង់ចាំ",
+  "门店": "ហាង",
+  "恭喜!您有一份盲盒待解锁": "អបអរសាទរ! អ្នកមានប្រអប់មួយដែលត្រូវបើក",
+  "一会儿再说": "យើងនឹងនិយាយនៅពេលក្រោយ",
+  "立即打开": "បើកឥឡូវនេះ",
+  "我的盲盒": "ប្រអប់មិនច្បាស់ខ្ញុំ",
+  "我的折扣券": "សំបុត្របញ្ចុះខ្ញុំ",
+  "请注意盲盒有效期": "ចំណាំកាលប្រអប់មិនច្បាស់",
+  "有效期限:": "កាល៖",
+  "恭喜!您获得": "អបអរសាទរ! អ្នកបានទទួល",
+  "领取": "ទទួល",
+  "盲盒兑换券": "ប្រអប់សំបុត្រ",
+  "兑换码": "កូដប្ដូរ",
+  "回购": "ការទិញម្តងទៀត",
+  "可回购": "អាចវិញ",
+  "已回购": "បានវិញ",
+  "回购中": "កំពុងវិញ",
+  "门店列表": "បញ្ជីហាង",
+  "选择视频": "ជ្រើសវីដេអូ",
+  "上传视频": "ផ្ទុកវីដេអូ",
+  "申请回购": "ដាក់ពាក្យទិញវិញ",
+  "请上传视频": "សូមផ្ទុកវីដេអូឡើង",
+  "填写物流": "បំពេញដឹកជញ្ជូន",
+  "物流公司": "ក្រុមហ៊ុនដឹកជញ្ជូន",
+  "请填写物流公司": "សូមបញ្ចូលក្រុមហ៊ុនដឹកជញ្ជូន",
+  "快递单号": "លេខតាមដាន",
+  "请填写快递单号": "សូមបញ្ចូលលេខតាមដាន",
+  "福利规则": "ច្បាប់",
+  "回购规则": "ច្បាប់ទិញ",
+  "设置交易密码": "កំណត់លេខសម្ងាត់",
+  "输入PIN码进行验证": "បញ្ចូលលេខ PIN ដើម្បីផ្ទៀងផ្ទាត់",
+  "输入原PIN码进行验证": "បញ្ចូលលេខ PIN ដើមដើម្បីផ្ទៀងផ្ទាត់",
+  "输入新PIN码进行验证": "បញ្ចូលលេខ PIN ថ្មីដើម្បីផ្ទៀងផ្ទាត់",
+  "199元包邮专区": "តំបន់ផ្តល់ដឹកជញ្ជូនឥតគិតថ្លៃ 199 រៀល",
+  "柬埔寨": "កម្ពុជា",
+  "转运服务": "សេវាកម្មដឹកជញ្ជូន",
+  "或者选择你的方式": "ឬ ជ្រើសរើសវិធីរបស់អ្នក",
+  "免运费区域": "តំបន់ដឹកជញ្ជូនឥតគិតថ្លៃ",
+  "来自卖家": "ពីអ្នកលក់",
+  "送货上门": "ដឹកជញ្ជូនទ្វារ",
+  "新": "ថ្មី",
+  "代购": "ការទិញជំនួយ",
+  "包邮": "ដឹកជញ្ជូនឥតគិតថ្លៃ",
+  "199包邮": "199 ដឹកជញ្ជូនឥតគិតថ្លៃ",
+  "优化预算成本": "បង្កើនកំណត់ថវិកា",
+  "更新最低报价": "អាប់ដេតតម្លៃទាបបំផុត",
+  "关注最新信息": "តាមដានព័ត៌មានថ្មីៗ",
+  "意向表单": "ទម្រង់បំណង",
+  "意向记录": "កំណត់ត្រាបំណង",
+  "商品名称": "ឈ្មោះទំនិញ",
+  "请输入商品名称": "សូមបញ្ចូលឈ្មោះទំនិញ",
+  "商品图片": "រូបភាពទំនិញ",
+  "商品详细描述": "ការពិពណ៌នាលម្អិតអំពីទំនិញ",
+  "请输入商品详细描述": "សូមបញ្ចូលការពិពណ៌នាលម្អិតអំពីទំនិញ",
+  "价格区间": "ជួរតម្លៃ",
+  "购买数量": "បរិមាណទិញ",
+  "联系人电话": "លេខទូរស័ព្ទអ្នកទាក់ទង",
+  "请输入联系人电话": "សូមបញ្ចូលលេខទូរស័ព្ទអ្នកទាក់ទង",
+  "联系人姓名": "ឈ្មោះអ្នកទាក់ទង",
+  "请输入联系人姓名": "សូមបញ្ចូលឈ្មោះអ្នកទាក់ទង",
+  "最低价": "តម្លៃទាបបំផុត",
+  "最高价": "តម្លៃខ្ពស់បំផុត",
+  "元": "យួន"
+}

+ 599 - 0
locale/zh.json

@@ -0,0 +1,599 @@
+{
+  "tabbar.首页": "首页",
+  "tabbar.购物车": "购物车",
+  "tabbar.社区": "社区",
+  "tabbar.咨询": "咨询",
+  "tabbar.我的": "我的",
+  "公告": "公告",
+  "团队服务升级报告": "Hoobuy团队服务升级公告",
+  "电子邮件": "电子邮件",
+  "密码": "密码",
+  "电子邮件为必填项": "电子邮件为必填项",
+  "密码是必需的": "密码是必需的",
+  "登录": "登录",
+  "忘记密码": "忘记密码?",
+  "注册": "注册",
+  "删除账户": "删除账户",
+  "cancelRegistrationTips": "警告:账户删除后,所有数据将永久删除且无法恢复,请谨慎操作。",
+  "请输入密码验证身份": "请输入密码验证身份",
+  "请输入密码": "请输入密码",
+  "验证通过后将执行账户删除操作": "验证通过后将执行账户删除操作",
+  "密码不能为空": "密码不能为空",
+  "账户删除成功": "账户删除成功",
+  "确认密码": "确认密码",
+  "已有账户": "已有账户,立即",
+  "邀请码": "邀请码(非必填)",
+  "我已阅读并接受": "我已阅读并接受",
+  "和": "和",
+  "语言/币种": "语言/币种",
+  "直淘中国无差价": "直淘中国无差价",
+  "主页": "主页",
+  "订单": "订单",
+  "仓库": "仓库",
+  "包裹": "包裹",
+  "钱包": "钱包",
+  "在线客服": "在线客服",
+  "拍照": "拍照",
+  "相册": "相册",
+  "商品的链接或名称": "商品的链接或名称",
+  "运费估算": "运费估算",
+  "新手教程": "新手教程",
+  "社群": "社群",
+  "装运": "装运",
+  "余额": "余额",
+  "优惠券": "优惠券",
+  "收藏夹": "收藏夹",
+  "推荐官": "推荐官",
+  "消息": "消息",
+  "加入社群": "加入社群",
+  "帮助中心": "帮助中心",
+  "联系我们": "联系我们",
+  "设置": "设置",
+  "好的": "好的",
+  "语言": "语言",
+  "币种": "币种",
+  "搜索": "搜索",
+  "搜索历史": "搜索历史",
+  "热门搜索": "热门搜索",
+  "1688": " 1688",
+  "淘宝": " 淘宝",
+  "JD": " JD",
+  "无数据": "无数据",
+  "正在加载中": "正在加载中",
+  "加载更多": "加载更多",
+  "没有更多了": "没有更多了",
+  "综合": "综合",
+  "价格": "价格",
+  "搜索条款": "搜索条款",
+  "搜索条款内容": "搜索结果展示的所有产品均来自第三方平台。 Hoobuy仅提供信息搜索、代购和运输服务。我们不验证或评估产品的质量或真实性。",
+  "您已同意搜索条款": "您已同意搜索条款。",
+  "关闭": "关闭",
+  "搜索类似产品": "搜索类似产品",
+  "产品链接": "产品链接",
+  "分享": "分享",
+  "刷新": "刷新",
+  "加入": "加入",
+  "立即购买": "立即购买",
+  "加入购物车": "加入购物车",
+  "购买记录": "购买记录",
+  "销售量": "销售量",
+  "平均送达时间": "平均送达时间",
+  "重量(克)": "重量(克)",
+  "尺寸": "尺寸",
+  "进入商店": "进入商店",
+  "产品详情": "产品详情",
+  "产品": "产品",
+  "细节": "细节",
+  "更多的": "更多的",
+  "规格参数": "规格参数",
+  "你可能会喜欢": "你可能会喜欢",
+  "提交": "提交",
+  "全部": "全部",
+  "删除": "删除",
+  "不包括运费": "不包括运费",
+  "数量": "数量",
+  "最小购买数量": "最小购买数量: 1",
+  "库存": "库存",
+  "确认订单": "确认订单",
+  "总计不含国际运费": "总计(不含国际运费)",
+  "违禁物品说明": "《违禁物品说明》",
+  "《服务条款》": "《服务条款》",
+  "退货说明": "《退货说明》",
+  "免责声明": "《免责声明》",
+  "我已阅读并同意": "我已阅读并同意",
+  "订单总价": "订单总价",
+  "总价": "总价",
+  "运费到仓库": "运费到仓库",
+  "折扣": "折扣",
+  "温馨提示": "温馨提示",
+  "提示内容": "提交订单并付款后,请等待卖家发货,到库后提交国际包裹订单。",
+  "请阅读并同意": "请阅读并同意",
+  "支付方式": "支付方式",
+  "请在": "请在",
+  "取消付款提示": "之前付款,否则将被取消。",
+  "余额不足需充值": "余额不足,需充值 ",
+  "用余额支付": "用余额支付",
+  "推荐": "推荐",
+  "充值": "充值",
+  "支付": "支付",
+  "手续费": "手续费",
+  "名称订单号商品名称": "名称/订单号/商品名称",
+  "待付款": "待付款",
+  "筛选": "筛选",
+  "创建时间": "创建时间",
+  "订单时间": "订单时间",
+  "重置": "重置",
+  "开始日期": "开始日期",
+  "结束日期": "结束日期",
+  "不支退货换货": "不支退货/换货 >",
+  "结束时间": "结束时间",
+  "取消": "取消",
+  "删除订单": "删除订单",
+  "全选": "全选",
+  "合并付款": "合并付款",
+  "订单详情": "订单详情",
+  "订单流程": "订单流程",
+  "处理中": "处理中",
+  "订单号": "订单号",
+  "复制": "复制",
+  "复制成功": "复制成功",
+  "小计": "小计",
+  "国内货运": "国内货运",
+  "订单补充付款": "订单补充付款",
+  "涉及增值服务费": "涉及增值服务费",
+  "店铺": "店铺",
+  "提醒": "提醒",
+  "您确定要从收藏中移除该店铺吗": "您确定要从收藏中移除该店铺吗?",
+  "您确定要从收藏中移除该产品吗": "您确定要从收藏中移除该产品吗?",
+  "默认": "默认",
+  "收件地址": "收件地址",
+  "账户地址": "账户地址",
+  "关于Hoobuy": "关于 Hoobuy",
+  "隐私政策": "隐私政策",
+  "服务条款": "服务条款",
+  "ID": "ID",
+  "修改密码tips": "更高强度的密码让您的账户更加安全。建议定期更改密码。",
+  "交易密码tips": "使用余额进行交易时需要验证密码,以增强账户的安全性。",
+  "账户安全": "账户安全",
+  "修改登录密码": "修改登录密码",
+  "编辑": "编辑",
+  "新交易密码": "新交易密码",
+  "登录密码": "登录密码",
+  "新密码": "新密码",
+  "再次输入密码": "再次输入密码",
+  "交易密码": "交易密码",
+  "原交易密码": "原交易密码",
+  "打包": "打包",
+  "请选择地址": "请选择地址",
+  "添加收货地址": "添加收货地址",
+  "确认": "确认",
+  "添加送货地址": "添加送货地址",
+  "收件人": "收件人",
+  "名": "名",
+  "姓": "姓",
+  "地区": "地区",
+  "详细地址": "详细地址",
+  "输入公寓号码街道道路地址": "输入公寓号码、街道/道路地址等",
+  "如果没有门牌号可以输入": "如果没有门牌号,可以输入0000",
+  "邮政编码": "邮政编码",
+  "电话号码": "电话号码",
+  "税号": "税号",
+  "地址标签": "地址标签",
+  "默认地址": "默认地址",
+  "门号": "门号",
+  "选择": "选择",
+  "国家": "国家",
+  "收件人必须填写": "收件人必须填写",
+  "国家和州/省必须填写": "国家和州/省必须填写",
+  "详细地址必须填写": "详细地址必须填写",
+  "邮政编码必须填写": "邮政编码必须填写",
+  "电话号码必须填写": "电话号码必须填写",
+  "公司": "公司",
+  "请先添加收件地址": "请先添加收件地址",
+  "编辑收货地址": "编辑收货地址",
+  "您确认删除吗": "您确认删除吗?",
+  "所有包裹": "所有包裹",
+  "运费": "运费",
+  "确认收货": "确认收货",
+  "物流信息": "物流信息",
+  "账单": "账单",
+  "提现": "提现",
+  "充值金额": "充值金额",
+  "请输入金额": "请输入金额",
+  "选择充值方式": "选择充值方式",
+  "充值步骤": "充值步骤",
+  "充值地址": "充值地址",
+  "完成付款": "完成付款",
+  "记录": "记录",
+  "充值记录": "充值记录",
+  "银行名称": "银行名称",
+  "收款人": "收款人",
+  "银行卡": "银行卡",
+  "待审核": "待审核",
+  "已完成": "已完成",
+  "提现记录": "提现记录",
+  "姓名": "姓名",
+  "提款": "提款",
+  "可用余额": "可用余额",
+  "提款金额": "提款金额",
+  "请输入提款金额": "请输入提款金额",
+  "编辑您的银行卡": "编辑您的银行卡",
+  "您的银行卡账户": "您的银行卡账户",
+  "保存": "保存",
+  "请填写持卡人姓名": "请填写持卡人姓名",
+  "请填写银行名称": "请填写银行名称",
+  "请填写银行卡": "请填写银行卡",
+  "未通过原因": "未通过原因",
+  "未通过": "未通过",
+  "汇款中": "汇款中",
+  "已汇款": "已汇款",
+  "取款金额": "取款金额",
+  "步骤": "步骤",
+  "选购商品": "选购商品",
+  "仓储质检": "仓储&质检",
+  "运输到家": "运输到家",
+  "或者": "或者",
+  "tips_text": "如果您已经拥有帐户,请使用您的帐户登录,然后在您的个人信息页面链接到脸书、谷歌或者苹果。",
+  "使用脸书登录": "使用脸书登录",
+  "使用谷歌登录": "使用谷歌登录",
+  "使用苹果登录": "使用苹果登录",
+  "没有账号": "没有账号,立即",
+  "直播": "直播",
+  "关注": "关注",
+  "精选": "精选",
+  "tabbar.商城": "商城",
+  "tabbar.订单": "订单",
+  "tabbar.订单详情": "订单详情",
+  "我的订单": "我的订单",
+  "我的地址": "我的地址",
+  "网购专家": "网购专家",
+  "其他功能": "其他功能",
+  "邀请有礼": "邀请有礼",
+  "实名认证": "实名认证",
+  "系统设置": "系统设置",
+  "账号管理": "账号管理",
+  "客服中心": "客服中心",
+  "收货地址": "收货地址",
+  "新增收货地址": "新增收货地址",
+  "购物车": "购物车",
+  "请输入关键字": "请输入关键字",
+  "拼多多": "拼多多",
+  "代购订单": "代购订单",
+  "我的集运包裹": "我的集运包裹",
+  "自助集运包裹": "自助集运包裹",
+  "当前状态": "当前状态",
+  "实付": "实付",
+  "平台订单号": "平台订单号",
+  "支付编号": "支付编号",
+  "订单状态": "订单状态",
+  "查看已完成订单": "查看已完成订单",
+  "五项服务全面呵护你的包裹号": "五项服务全面呵护你的包裹号",
+  "点击步骤即可查看详情哦~": "点击步骤即可查看详情哦~",
+  "入库中": "入库中",
+  "专业质检": "专业质检",
+  "商品实拍": "商品实拍",
+  "加固/重新包装": "加固/重新包装",
+  "已完成,待集运": "已完成,待集运",
+  "接受瑕疵": "接受瑕疵",
+  "退款": "退款",
+  "kf_hint": "查询到该商品可能有瑕疵,请问是否接受有瑕疵或者退款?有疑问可联系 VAVABUY 客服",
+  "编辑资料": "编辑资料",
+  "请输入昵称": "请输入昵称",
+  "昵称": "昵称",
+  "保存修改": "保存修改",
+  "请勾选确认接受瑕疵": "请勾选确认接受瑕疵",
+  "返回": "返回",
+  "同意并已阅读免责说明": "同意并已阅读免责说明",
+  "是否专业质检": "是否专业质检",
+  "商品仓库": "商品仓库",
+  "集运包裹": "集运包裹",
+  "物流详细": "物流详细",
+  "查看物流": "查看物流",
+  "去结算": "去结算",
+  "确定要退出登录吗": "确定要退出登录吗?",
+  "提示": "提示",
+  "说点什么...": "说点什么...",
+  "评论": "评论",
+  "发送": "发送",
+  "回复": "回复",
+  "退出登录": "退出登录",
+  "个人资料": "个人资料",
+  "1688工厂直销": "1688 工厂直销",
+  "工厂直销": "工厂直销",
+  "服装、美妆、母婴、食品、数码产品、家电、家具": "服装、美妆、母婴、食品、数码产品、家电、家具",
+  "全球最大的C2C电商平台之一": "全球最大的C2C电商平台之一",
+  "主流电子商务应用产品平台": "主流电子商务应用产品平台",
+  "查看并确认": "查看并确认",
+  "验证码为必填项": "验证码为必填项",
+  "请输入电子邮件": "请输入电子邮件",
+  "验证码": "验证码",
+  "我的邀请码": "我的邀请码",
+  "推广步骤": "推广步骤",
+  "证件类型": "证件类型",
+  "身份证号码": "身份证号码",
+  "上传证件正面照片": "上传证件正面照片",
+  "上传证件反面照片": "上传证件反面照片",
+  "请选择证件类型": "请选择证件类型",
+  "请填写身份证号码": "请填写身份证号码",
+  "请填写姓名": "请填写姓名",
+  "成功": "成功",
+  "失败": "失败",
+  "刚刚": "刚刚",
+  "分钟前": "分钟前",
+  "小时前": "小时前",
+  "昨天": "昨天",
+  "天前": "天前",
+  "身份证": "身份证",
+  "护照": "护照",
+  "驾驶证": "驾驶证",
+  "密码是必需的且为6位": "密码是必需的且为6位",
+  "链接已复制": "链接已复制",
+  "verification_text": "我们不会强制要求客户进行实名,为了不影响购物体验如果您购买的商品超过了1000美元。根据澳大利亚海关规定,我们需要您的证件来更快的处理这个过程。",
+  "请输入支付密码": "请输入支付密码",
+  "qualityInspection": "专业质检是一项增值服务,该服务收取{amount}元。我们会在发往您所在国家之前,帮助您验证商品的健康质量并拍摄照片给您确认。",
+  "待确认": "待确认",
+  "分享给好友": "分享给好友",
+  "分享到朋友圈": "分享到朋友圈",
+  "查看": "查看",
+  "去支付": "去支付",
+  "关于vavabuy": "关于 VAVABUY",
+  "我知道了": "我知道了",
+  "关于我们": "关于我们",
+  "用户协议": "用户协议",
+  "隐私协议": "隐私协议",
+  "违规物品说明": "违规物品说明",
+  "上传失败": "上传失败",
+  "证件号码": "证件号码",
+  "质检费用": "质检费用",
+  "入库时间": "入库时间",
+  "支付成功": "支付成功!",
+  "继续购物": "继续购物",
+  "查看订单": "查看订单",
+  "增值服务": "增值服务",
+  "易碎品加固": "易碎品加固",
+  "标准质检": "标准质检",
+  "优先采购": "优先采购",
+  "个性化拍照": "个性化拍照",
+  "服务说明": "服务说明",
+  "增值费用": "包含增值费用",
+  "_gxhpz_desc": "1、满足您对商品细节查看的需求,您可以在下单时进行备注,一张照片只能满足一个要求拍照,如果需要更多细节,请在选择下单数量的同时备注对应的拍摄要求。\n 2、在您选择支付成功后且商品为“在仓”状态,我们将在24小时内为您操作完成。",
+  "_yspjg_desc": "1、使用气泡柱对易碎/易损商品(如玻璃制品、手办等)进行加固包装。\n 2、操作完成后会改变商品的重量、体积。\n3、在您选择支付成功后且商品为“在仓”状态,我们将在24小时内为您操作完成。",
+  "_yxdg_desc": "勾选“优先采购”服务的订单,将在买手工作时间4个小时内处理;如需进一步确认或补款订单需要客户配合处理后再进行采购。订单提交后,“优先采购”服务费用将不退还。",
+  "_bzzj_desc": "1.提供商品正常角度、包装、吊牌、瑕疵的检查服务,并拍摄 2–3 张 清晰照片供您查看。\n2.在您选择支付成功后且商品为“在仓”状态,我们将在 24 小时内为您操作完成。",
+  "Google支付": "Google支付",
+  "Apple支付": "Apple支付",
+  "仓储期": "仓储期",
+  "天": "天",
+  "续期": "续期",
+  "已过期": "已过期",
+  "续存储期": "续存储期",
+  "续存储期提示": "续存储期最多为100天",
+  "总计": "总计",
+  "商品数量": "商品数量",
+  "单价": "单价",
+  "pay_fail_msg": "支付失败, 请检查!",
+  "我的优惠券": "我的优惠券",
+  "可使用": "可使用",
+  "已使用": "已使用",
+  "立即使用": "立即使用",
+  "满": "满",
+  "可用": "可用",
+  "minimum_amount": "满{amount}可用",
+  "领取成功": "领取成功",
+  "运费券": "运费券",
+  "购物券": "购物券",
+  "银行卡号": "银行卡号",
+  "有效期": "有效期",
+  "安全码": "安全码",
+  "请输入消息内容": "请输入消息内容",
+  "猜你想问": "猜你想问",
+  "VAVABUY专属官方客服": "VAVABUY 专属官方客服",
+  "付费咨询": "付费咨询",
+  "您已经开通专属客服": "您已经开通专属客服",
+  "网购助手": "网购助手",
+  "领": "领",
+  "系统": "系统",
+  "重置密码": "重置密码",
+  "选择物流路线": "选择物流路线",
+  "邮寄周期": "邮寄周期",
+  "报价说明": "报价说明",
+  "详情": "详情",
+  "请选择物流路线": "请选择物流路线",
+  "正在加载": "正在加载...",
+  "条新消息": "条新消息",
+  "你确定要删除此订单吗?": "你确定要删除此订单吗?",
+  "会话已关闭": "会话已关闭",
+  "结束会话": "结束会话",
+  "申请退款": "申请退款",
+  "在线": "在线",
+  "page.user_chat.tipPopupContentForCloseChat": "您确认要结束当前会话吗?",
+  "page.user_chat.tipPopupContentForRefund": "您确认要申请退款吗?",
+  "page.user_chat.tipPopupContentForPay": "<view>本服务为收费咨询项目,每次服务收费 1.3 美元,我们承诺持续为您提供服务,直至您的问题获得满意解决为止。</view><view class='' style='margin:16rpx 0 0;'>如果您的问题未得到有效解决,我们承诺将所支付的费用全额退回至您的账户余额。</view>",
+  "正在安装文件": "正在安装文件...",
+  "应用资源更新完成": "应用资源更新完成!",
+  "文件下载失败": "文件下载失败...",
+  "准备下载": "准备下载...",
+  "开始下载": "开始下载...",
+  "已下载": "已下载",
+  "已取消下载": "已取消下载",
+  "安装文件失败": "安装文件失败",
+  "新版本": "发现新版本",
+  "发现新版本": "发现新版本:",
+  "立即升级": "立即升级",
+  "暂不升级": "暂不升级",
+  "正在为您更新请耐心等待": "正在为您更新,请耐心等待",
+  "升级APP": "升级APP",
+  "取消下载": "取消下载",
+  "后台下载": "后台下载",
+  "暂无新版本": "暂无新版本",
+  "返回首页": "返回首页",
+  "查看包裹": "查看包裹",
+  "warehouse_tips": "您的运单已创建,请耐心等待具体运费生成通常需要1到2个小时。您可以在包裹中心确认您的国际包裹。",
+  "预付费用明细": "预付费用明细",
+  "实际运费明细": "实际运费明细",
+  "其他费用明细": "其他费用明细",
+  "预估费用": "预估费用",
+  "预估运费": "预估运费",
+  "预估运费重": "预估运费重",
+  "首重": "首重",
+  "续重": "续重",
+  "操作费": "操作费",
+  "报关费": "报关费",
+  "燃油附加费": "燃油附加费",
+  "偏远地区费用": "偏远地区费用",
+  "旺季附加费": "旺季附加费",
+  "运费优惠": "运费优惠",
+  "实际费用": "实际费用",
+  "实际运费": "实际运费",
+  "实际计费重": "实际计费重",
+  "实际体积": "实际体积",
+  "其他费用": "其他费用",
+  "打包费": "打包费",
+  "商品已下架": "商品已下架",
+  "相机权限说明": "相机权限说明",
+  "用于上传用户头像、或依据图片信息搜索内容": "用于上传用户头像、或依据图片信息搜索内容",
+  "存储权限说明": "存储权限说明",
+  "用于选择照片": "用于选择照片或上传用户头像",
+  "你想取消付款嘛": "你想取消付款吗?",
+  "订单取消后无法恢复,请选择取消付款的原因": "订单取消后无法恢复,请选择取消付款的原因",
+  "请输入取消原因": "请输入取消原因",
+  "uni.app.quit": "再按一次退出应用",
+  "订单处理中": "订单处理中...",
+  "运输中": "运输中",
+  "不想要了": "不想要了",
+  "买错了": "买错了",
+  "价格太贵": "价格太贵",
+  "邀请记录": "邀请记录",
+  "暂无邀请记录": "暂无邀请记录",
+  "质检照片": "质检照片",
+  "系统消息": "系统消息",
+  "未读": "未读",
+  "消息详情": "消息详情",
+  "待支付": "待支付",
+  "待入库": "待入库",
+  "待质检": "待质检",
+  "待集运": "待集运",
+  "退款和售后": "退款和售后",
+  "体积": "体积",
+  "重量": "重量",
+  "明细": "明细",
+  "总体积": "总体积",
+  "总重量": "总重量",
+  "续重费用": "续重费用",
+  "首重费用": "首重费用",
+  "您将在安全的环境下付款给": "您将在安全的环境下付款给",
+  "从VAVABUY到": "从 VAVABUY 到",
+  "请输入重量": "请输入重量",
+  "商品类别": "商品类别",
+  "查询": "查询",
+  "长度": "长度",
+  "宽度": "宽度",
+  "高度": "高度",
+  "热门平台": "热门平台",
+  "立即进入": "立即进入",
+  "网购专家指引": "网购专家指引",
+  "帮你快速上手选择性价比商品": "帮你快速上手选择性价比商品",
+  "点击跳转": "点击跳转",
+  "追踪订单": "追踪订单",
+  "价格追踪": "价格追踪",
+  "关注列表": "关注列表",
+  "请填写必填信息": "请填写必填信息",
+  "目的地": "目的地",
+  "暂无选项": "暂无选项",
+  "请选择商品类别": "请选择商品类别",
+  "比加入时": "比加入时",
+  "降": "降",
+  "涨": "涨",
+  "进行中的订单": "进行中的订单",
+  "手机号": "手机号",
+  "手机登录": "手机登录",
+  "手机号为必填项": "手机号为必填项",
+  "邮箱登录": "邮箱登录",
+  "手机注册": "手机注册",
+  "邮箱注册": "邮箱注册",
+  "手机重置": "手机重置",
+  "邮箱重置": "邮箱重置",
+  "请输入手机号": "请输入手机号",
+  "ABA KHQR": "ABA KHQR",
+  "暂无优惠券": "暂无优惠券",
+  "免邮专区": "免邮专区",
+  "实用功能": "实用功能",
+  "特色优惠": "特色优惠",
+  "待评价": "待评价",
+  "查看评论": "查看评论",
+  "确定收到货了吗": "确定收到货了吗?",
+  "购物车预览": "购物车预览",
+  "商品评价": "商品评价",
+  "评价内容": "评价内容",
+  "分享你的使用感受,帮助其他买家选择": "分享你的使用感受,帮助其他买家选择",
+  "上传图片": "上传图片",
+  "暂无评论内容": "暂无评论内容",
+  "用户评论": "用户评论",
+  "总销量": "总销量:",
+  "福利中心": "福利中心",
+  "VAVA精选": "VAVA精选",
+  "我要回购": "我要回购",
+  "敬请期待": "敬请期待",
+  "门店": "门店",
+  "恭喜!您有一份盲盒待解锁": "恭喜!您有一份盲盒待解锁",
+  "一会儿再说": "一会儿再说",
+  "立即打开": "立即打开",
+  "我的盲盒": "我的盲盒",
+  "我的折扣券": "我的折扣券",
+  "请注意盲盒有效期": "请注意盲盒有效期",
+  "有效期限:": "有效期限:",
+  "恭喜!您获得": "恭喜!您获得",
+  "领取": "领取",
+  "盲盒兑换券": "盲盒兑换券",
+  "兑换码": "兑换码",
+  "回购": "回购",
+  "可回购": "可回购",
+  "已回购": "已回购",
+  "回购中": "回购中",
+  "门店列表": "门店列表",
+  "选择视频": "选择视频",
+  "上传视频": "上传视频",
+  "申请回购": "申请回购",
+  "请上传视频": "请上传视频",
+  "填写物流": "填写物流",
+  "物流公司": "物流公司",
+  "请填写物流公司": "请填写物流公司",
+  "快递单号": "快递单号",
+  "请填写快递单号": "请填写快递单号",
+  "福利规则": "福利规则",
+  "回购规则": "回购规则",
+  "设置交易密码": "设置交易密码",
+  "输入PIN码进行验证": "输入 PIN 码进行验证",
+  "输入原PIN码进行验证": "输入原 PIN 码进行验证",
+  "输入新PIN码进行验证": "输入新 PIN 码进行验证",
+  "199元包邮专区": "199元包邮专区",
+  "柬埔寨": "柬埔寨",
+  "转运服务": "转运服务",
+  "或者选择你的方式": "或者选择你的方式",
+  "免运费区域": "免运费区域",
+  "来自卖家": "来自卖家",
+  "送货上门": "送货上门",
+  "新": "新",
+  "代购": "代购",
+  "包邮": "包邮",
+  "199包邮": "199包邮",
+  "优化预算成本": "优化预算成本",
+  "更新最低报价": "更新最低报价",
+  "关注最新信息": "关注最新信息",
+  "意向表单": "意向表单",
+  "意向记录": "意向记录",
+  "商品名称": "商品名称",
+  "请输入商品名称": "请输入商品名称",
+  "商品图片": "商品图片",
+  "商品详细描述": "商品详细描述",
+  "请输入商品详细描述": "请输入商品详细描述",
+  "价格区间": "价格区间",
+  "购买数量": "购买数量",
+  "联系人电话": "联系人电话",
+  "请输入联系人电话": "请输入联系人电话",
+  "联系人姓名": "联系人姓名",
+  "请输入联系人姓名": "请输入联系人姓名",
+  "最低价": "最低价",
+  "最高价": "最高价",
+  "元": "元"
+}

+ 29 - 0
main.js

@@ -0,0 +1,29 @@
+import { createSSRApp } from 'vue'
+import App from './App'
+import { i18n } from './locale'
+import { createPinia } from 'pinia'
+import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
+import { useImg, systemInfo, format } from './utils';
+import Theme from "@/components/theme"
+import trans from "@/components/trans"
+import uviewPlus from '@/uni_modules/uview-plus'
+
+const systemInfoName = systemInfo();
+const pinia = createPinia();
+pinia.use(piniaPluginPersistedstate);
+
+export function createApp() {
+  const app = createSSRApp(App);
+  app.config.globalProperties.$adjustPosition = systemInfoName.osName == 'ios' ? true : false;
+  app.config.globalProperties.$useImg = useImg;
+  app.config.globalProperties.$format = format;
+
+  app.component('Theme', Theme);
+  app.component('trans', trans)
+  app.use(i18n);
+  app.use(pinia);
+  app.use(uviewPlus);
+  return {
+    app
+  }
+}

+ 199 - 0
manifest.json

@@ -0,0 +1,199 @@
+{
+    "name" : "VAVABUY",
+    "appid" : "__UNI__0358C1D",
+    "description" : "VAVABUY",
+    "versionName" : "1.7.8",
+    "versionCode" : 1708,
+    "transformPx" : false,
+    /* 5+App特有相关 */
+    "app-plus" : {
+        "usingComponents" : true,
+        "nvueStyleCompiler" : "uni-app",
+        "compilerVersion" : 3,
+        "splashscreen" : {
+            "alwaysShowBeforeRender" : true,
+            "waiting" : true,
+            "autoclose" : true,
+            "delay" : 0
+        },
+        /* 模块配置 */
+        "modules" : {
+            "OAuth" : {},
+            "Camera" : {},
+            "Push" : {},
+            "VideoPlayer" : {}
+        },
+        /* 应用发布信息 */
+        "distribute" : {
+            /* android打包配置 */
+            "android" : {
+                "permissions" : [
+                    "<uses-feature android:name=\"android.hardware.camera\"/>",
+                    "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CAMERA\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
+                    "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
+                    "<uses-permission android:name=\"android.permission.INTERNET\"/>",
+                    "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
+                    "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>",
+                    "<uses-permission android:name=\"android.permission.FOREGROUND_SERVICE\"/>",
+                    "<uses-permission android:name=\"android.permission.GET_TASKS\"/>"
+                ],
+                "targetSdkVersion" : 36,
+                "minSdkVersion" : 21,
+                "excludePermissions" : [
+                    "<uses-permission android:name=\"com.google.android.gms.permission.AD_ID\"/>"
+                ],
+                "permissionOptions" : {
+                    "READ_EXTERNAL_STORAGE" : {
+                        "description" : "Used for functions such as uploading avatars and saving chat images."
+                    },
+                    "CAMERA" : {
+                        "description" : "Used for taking chat photos and scanning QR codes."
+                    }
+                }
+            },
+            /* ios打包配置 */
+            "ios" : {
+                "dSYMs" : false,
+                "idfa" : true,
+                "privacyDescription" : {
+                    "NSUserTrackingUsageDescription" : "Please rest assured that enabling this permission will not allow access to your private information on other sites. This permission is only used to identify your device, ensure service security, and enhance your browsing experience.",
+                    "NSPhotoLibraryUsageDescription" : "To upload a user avatar or search for content based on image information, access to the photo album is required.",
+                    "NSCameraUsageDescription" : "To upload a user avatar or search for content based on image information, access to the camera is required."
+                }
+            },
+            /* SDK配置 */
+            "sdkConfigs" : {
+                "oauth" : {
+                    "google" : {
+                        "clientid" : "132211687127-bo929nasc04jk3927j07facbgovfv9vj.apps.googleusercontent.com"
+                    },
+                    "facebook" : {
+                        "appid" : "501088503016892"
+                    }
+                },
+                "share" : {
+                    "weixin" : {
+                        "appid" : "",
+                        "UniversalLinks" : ""
+                    }
+                },
+                "push" : {
+                    "unipush" : {
+                        "version" : "2",
+                        "offline" : true,
+                        "hms" : {},
+                        "icons" : {
+                            "small" : {
+                                "hdpi" : "unpackage/res/icons/36x36.png"
+                            }
+                        }
+                    }
+                },
+                "ad" : {},
+                "payment" : {}
+            },
+            "icons" : {
+                "android" : {
+                    "hdpi" : "unpackage/res/icons/72x72.png",
+                    "xhdpi" : "unpackage/res/icons/96x96.png",
+                    "xxhdpi" : "unpackage/res/icons/144x144.png",
+                    "xxxhdpi" : "unpackage/res/icons/192x192.png"
+                },
+                "ios" : {
+                    "appstore" : "unpackage/res/icons/1024x1024.png",
+                    "ipad" : {
+                        "app" : "unpackage/res/icons/76x76.png",
+                        "app@2x" : "unpackage/res/icons/152x152.png",
+                        "notification" : "unpackage/res/icons/20x20.png",
+                        "notification@2x" : "unpackage/res/icons/40x40.png",
+                        "proapp@2x" : "unpackage/res/icons/167x167.png",
+                        "settings" : "unpackage/res/icons/29x29.png",
+                        "settings@2x" : "unpackage/res/icons/58x58.png",
+                        "spotlight" : "unpackage/res/icons/40x40.png",
+                        "spotlight@2x" : "unpackage/res/icons/80x80.png"
+                    },
+                    "iphone" : {
+                        "app@2x" : "unpackage/res/icons/120x120.png",
+                        "app@3x" : "unpackage/res/icons/180x180.png",
+                        "notification@2x" : "unpackage/res/icons/40x40.png",
+                        "notification@3x" : "unpackage/res/icons/60x60.png",
+                        "settings@2x" : "unpackage/res/icons/58x58.png",
+                        "settings@3x" : "unpackage/res/icons/87x87.png",
+                        "spotlight@2x" : "unpackage/res/icons/80x80.png",
+                        "spotlight@3x" : "unpackage/res/icons/120x120.png"
+                    }
+                }
+            },
+            "splashscreen" : {
+                "androidStyle" : "default",
+                "useOriginalMsgbox" : true,
+                "iosStyle" : "storyboard",
+                "ios" : {
+                    "storyboard" : "C:/Users/PC/Desktop/前端项目/资料/vavabuy_App_资料/CustomStoryboard.zip"
+                }
+            }
+        },
+        "locales" : {
+            "en" : {
+                "ios" : {
+                    "privacyDescription" : {
+                        "NSUserTrackingUsageDescription" : "Rest assured, enabling this permission won't access your private info from other sites. It's only used to identify your device, ensure service security, and improve your browsing experience.",
+                        "NSPhotoLibraryUsageDescription" : "Need access to your photo album to upload a profile picture or search using image info.",
+                        "NSCameraUsageDescription" : "Need access to your photo album to upload a profile picture or search using image info."
+                    }
+                }
+            },
+            "es" : {
+                "ios" : {
+                    "privacyDescription" : {
+                        "NSUserTrackingUsageDescription" : "No te preocupes, activar este permiso no accederá a tu información privada de otros sitios. Solo se usa para identificar el dispositivo, garantizar la seguridad del servicio y mejorar tu experiencia de navegación.",
+                        "NSPhotoLibraryUsageDescription" : "Se necesita acceso a tu álbum de fotos para subir una foto de perfil o buscar usando información de imágenes.",
+                        "NSCameraUsageDescription" : "Se necesita acceso a tu álbum de fotos para subir una foto de perfil o buscar usando información de imágenes."
+                    }
+                }
+            }
+        },
+        "safearea" : {
+            "bottom" : {
+                "offset" : "none"
+            }
+        }
+    },
+    /* 快应用特有相关 */
+    "quickapp" : {},
+    /* 小程序特有相关 */
+    "mp-weixin" : {
+        "appid" : "",
+        "setting" : {
+            "urlCheck" : false
+        },
+        "usingComponents" : true,
+        "mergeVirtualHostAttributes" : true
+    },
+    "mp-alipay" : {
+        "usingComponents" : true
+    },
+    "mp-baidu" : {
+        "usingComponents" : true
+    },
+    "mp-toutiao" : {
+        "usingComponents" : true,
+        "mergeVirtualHostAttributes" : true
+    },
+    "uniStatistics" : {
+        "enable" : false
+    },
+    "vueVersion" : "3"
+}
+/* ios打包配置 *//* SDK配置 */
+

+ 10461 - 0
package-lock.json

@@ -0,0 +1,10461 @@
+{
+  "name": "hello-i18n",
+  "version": "1.0.2",
+  "lockfileVersion": 2,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "hello-i18n",
+      "version": "1.0.2",
+      "license": "ISC",
+      "dependencies": {
+        "@airwallex/components-sdk": "^1.20.0",
+        "@awesome-cordova-plugins/facebook": "^8.0.0",
+        "@capacitor-community/facebook-login": "^7.0.0",
+        "@react-native-google-signin/google-signin": "^14.0.1",
+        "airwallex-payment-elements": "latest",
+        "clipboard": "^2.0.11",
+        "dayjs": "^1.11.13",
+        "fb-sdk": "^1.0.3",
+        "pinia": "^3.0.2",
+        "pinia-plugin-persistedstate": "^4.3.0",
+        "uuid": "^11.1.0",
+        "uview-plus": "^3.5.41",
+        "uview-ui": "^2.0.38"
+      },
+      "devDependencies": {
+        "sass": "^1.85.1",
+        "sass-loader": "10"
+      }
+    },
+    "node_modules/@airwallex/airtracker": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/@airwallex/airtracker/-/airtracker-1.2.0.tgz",
+      "integrity": "sha512-T6u4QnWEhT9jomVwo6FCVK63AOxRVjonUOn1mj16L/xbqhNCnl/kTBP2khFjFJBJ7wKcb7Yb2KrUg803Uu5zcw==",
+      "dependencies": {
+        "web-vitals": "^3.5.1"
+      }
+    },
+    "node_modules/@airwallex/components-sdk": {
+      "version": "1.20.0",
+      "resolved": "https://registry.npmmirror.com/@airwallex/components-sdk/-/components-sdk-1.20.0.tgz",
+      "integrity": "sha512-aDJDYx4/6+bwZOdw2+1ZG4Ti6RfP1Z6rk25NUixUaU264yKMg6bVLNqFxmfllL/qKHHHt0wN/+vtrm7OFRHalQ==",
+      "dependencies": {
+        "@airwallex/airtracker": "1.2.0"
+      }
+    },
+    "node_modules/@ampproject/remapping": {
+      "version": "2.3.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@ampproject/remapping/-/remapping-2.3.0.tgz",
+      "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
+      "peer": true,
+      "dependencies": {
+        "@jridgewell/gen-mapping": "^0.3.5",
+        "@jridgewell/trace-mapping": "^0.3.24"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@awesome-cordova-plugins/core": {
+      "version": "6.16.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@awesome-cordova-plugins/core/-/core-6.16.0.tgz",
+      "integrity": "sha512-ep+nkDY6CyFBfqS/HS03PE+MZWiQoJWb/nLMwfj2ndC14UgZeVO3ecmEFknYjJOBf04emTbs7hbLewFrVkazmg==",
+      "peer": true,
+      "dependencies": {
+        "@types/cordova": "latest"
+      },
+      "peerDependencies": {
+        "rxjs": "^5.5.0 || ^6.5.0 || ^7.3.0"
+      }
+    },
+    "node_modules/@awesome-cordova-plugins/facebook": {
+      "version": "8.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@awesome-cordova-plugins/facebook/-/facebook-8.0.0.tgz",
+      "integrity": "sha512-Jj1Us/HY0WURC1ecCV06oaYHcPZNa7+as+YfRdNQoLbp1UenTaovJmeGvfYsJ3yx07CH4ZaquD06zlI/PTQeAQ==",
+      "dependencies": {
+        "@types/cordova": "latest"
+      },
+      "peerDependencies": {
+        "@awesome-cordova-plugins/core": "^6.0.1",
+        "rxjs": "^5.5.0 || ^6.5.0 || ^7.3.0"
+      }
+    },
+    "node_modules/@babel/code-frame": {
+      "version": "7.27.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/code-frame/-/code-frame-7.27.1.tgz",
+      "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
+      "peer": true,
+      "dependencies": {
+        "@babel/helper-validator-identifier": "^7.27.1",
+        "js-tokens": "^4.0.0",
+        "picocolors": "^1.1.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/code-frame/node_modules/js-tokens": {
+      "version": "4.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/js-tokens/-/js-tokens-4.0.0.tgz",
+      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+      "peer": true
+    },
+    "node_modules/@babel/compat-data": {
+      "version": "7.27.5",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/compat-data/-/compat-data-7.27.5.tgz",
+      "integrity": "sha512-KiRAp/VoJaWkkte84TvUd9qjdbZAdiqyvMxrGl1N6vzFogKmaLgoM3L1kgtLicp2HP5fBJS8JrZKLVIZGVJAVg==",
+      "peer": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/core": {
+      "version": "7.27.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/core/-/core-7.27.4.tgz",
+      "integrity": "sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==",
+      "peer": true,
+      "dependencies": {
+        "@ampproject/remapping": "^2.2.0",
+        "@babel/code-frame": "^7.27.1",
+        "@babel/generator": "^7.27.3",
+        "@babel/helper-compilation-targets": "^7.27.2",
+        "@babel/helper-module-transforms": "^7.27.3",
+        "@babel/helpers": "^7.27.4",
+        "@babel/parser": "^7.27.4",
+        "@babel/template": "^7.27.2",
+        "@babel/traverse": "^7.27.4",
+        "@babel/types": "^7.27.3",
+        "convert-source-map": "^2.0.0",
+        "debug": "^4.1.0",
+        "gensync": "^1.0.0-beta.2",
+        "json5": "^2.2.3",
+        "semver": "^6.3.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/babel"
+      }
+    },
+    "node_modules/@babel/core/node_modules/semver": {
+      "version": "6.3.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-6.3.1.tgz",
+      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+      "peer": true,
+      "bin": {
+        "semver": "bin/semver.js"
+      }
+    },
+    "node_modules/@babel/generator": {
+      "version": "7.27.5",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/generator/-/generator-7.27.5.tgz",
+      "integrity": "sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==",
+      "peer": true,
+      "dependencies": {
+        "@babel/parser": "^7.27.5",
+        "@babel/types": "^7.27.3",
+        "@jridgewell/gen-mapping": "^0.3.5",
+        "@jridgewell/trace-mapping": "^0.3.25",
+        "jsesc": "^3.0.2"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-compilation-targets": {
+      "version": "7.27.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz",
+      "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==",
+      "peer": true,
+      "dependencies": {
+        "@babel/compat-data": "^7.27.2",
+        "@babel/helper-validator-option": "^7.27.1",
+        "browserslist": "^4.24.0",
+        "lru-cache": "^5.1.1",
+        "semver": "^6.3.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-compilation-targets/node_modules/semver": {
+      "version": "6.3.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-6.3.1.tgz",
+      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+      "peer": true,
+      "bin": {
+        "semver": "bin/semver.js"
+      }
+    },
+    "node_modules/@babel/helper-module-imports": {
+      "version": "7.27.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz",
+      "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==",
+      "peer": true,
+      "dependencies": {
+        "@babel/traverse": "^7.27.1",
+        "@babel/types": "^7.27.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-module-transforms": {
+      "version": "7.27.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz",
+      "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==",
+      "peer": true,
+      "dependencies": {
+        "@babel/helper-module-imports": "^7.27.1",
+        "@babel/helper-validator-identifier": "^7.27.1",
+        "@babel/traverse": "^7.27.3"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/@babel/helper-plugin-utils": {
+      "version": "7.27.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz",
+      "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==",
+      "peer": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-string-parser": {
+      "version": "7.27.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+      "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
+      "peer": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-validator-identifier": {
+      "version": "7.27.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
+      "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
+      "peer": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-validator-option": {
+      "version": "7.27.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
+      "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
+      "peer": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helpers": {
+      "version": "7.27.6",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helpers/-/helpers-7.27.6.tgz",
+      "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==",
+      "peer": true,
+      "dependencies": {
+        "@babel/template": "^7.27.2",
+        "@babel/types": "^7.27.6"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/parser": {
+      "version": "7.27.5",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/parser/-/parser-7.27.5.tgz",
+      "integrity": "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==",
+      "peer": true,
+      "dependencies": {
+        "@babel/types": "^7.27.3"
+      },
+      "bin": {
+        "parser": "bin/babel-parser.js"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-async-generators": {
+      "version": "7.8.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
+      "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
+      "peer": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-bigint": {
+      "version": "7.8.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz",
+      "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==",
+      "peer": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-class-properties": {
+      "version": "7.12.13",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
+      "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
+      "peer": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.12.13"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-class-static-block": {
+      "version": "7.14.5",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz",
+      "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==",
+      "peer": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.14.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-import-attributes": {
+      "version": "7.27.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz",
+      "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==",
+      "peer": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.27.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-import-meta": {
+      "version": "7.10.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
+      "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
+      "peer": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-json-strings": {
+      "version": "7.8.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
+      "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
+      "peer": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
+      "version": "7.10.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
+      "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+      "peer": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
+      "version": "7.8.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
+      "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
+      "peer": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-numeric-separator": {
+      "version": "7.10.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
+      "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
+      "peer": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-object-rest-spread": {
+      "version": "7.8.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
+      "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+      "peer": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-optional-catch-binding": {
+      "version": "7.8.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
+      "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
+      "peer": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-optional-chaining": {
+      "version": "7.8.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
+      "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+      "peer": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-private-property-in-object": {
+      "version": "7.14.5",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz",
+      "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==",
+      "peer": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.14.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-top-level-await": {
+      "version": "7.14.5",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
+      "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
+      "peer": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.14.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/runtime": {
+      "version": "7.27.6",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/runtime/-/runtime-7.27.6.tgz",
+      "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==",
+      "peer": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/template": {
+      "version": "7.27.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/template/-/template-7.27.2.tgz",
+      "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==",
+      "peer": true,
+      "dependencies": {
+        "@babel/code-frame": "^7.27.1",
+        "@babel/parser": "^7.27.2",
+        "@babel/types": "^7.27.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/traverse": {
+      "version": "7.27.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/traverse/-/traverse-7.27.4.tgz",
+      "integrity": "sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==",
+      "peer": true,
+      "dependencies": {
+        "@babel/code-frame": "^7.27.1",
+        "@babel/generator": "^7.27.3",
+        "@babel/parser": "^7.27.4",
+        "@babel/template": "^7.27.2",
+        "@babel/types": "^7.27.3",
+        "debug": "^4.3.1",
+        "globals": "^11.1.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/traverse--for-generate-function-map": {
+      "name": "@babel/traverse",
+      "version": "7.27.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/traverse/-/traverse-7.27.4.tgz",
+      "integrity": "sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==",
+      "peer": true,
+      "dependencies": {
+        "@babel/code-frame": "^7.27.1",
+        "@babel/generator": "^7.27.3",
+        "@babel/parser": "^7.27.4",
+        "@babel/template": "^7.27.2",
+        "@babel/types": "^7.27.3",
+        "debug": "^4.3.1",
+        "globals": "^11.1.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/types": {
+      "version": "7.27.6",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/types/-/types-7.27.6.tgz",
+      "integrity": "sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==",
+      "peer": true,
+      "dependencies": {
+        "@babel/helper-string-parser": "^7.27.1",
+        "@babel/helper-validator-identifier": "^7.27.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@capacitor-community/facebook-login": {
+      "version": "7.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@capacitor-community/facebook-login/-/facebook-login-7.0.0.tgz",
+      "integrity": "sha512-zwCBaqHysWpjFfb4F/Ax2oJjt1vQVkp+SAdjCOaPtloiak+AceXW9U0mtYVxfk0aOO9gKALbkKnivcfviIDN0A==",
+      "dependencies": {
+        "@capacitor/core": "^7.0.0"
+      },
+      "engines": {
+        "node": ">=20.0.0"
+      }
+    },
+    "node_modules/@capacitor/core": {
+      "version": "7.3.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@capacitor/core/-/core-7.3.0.tgz",
+      "integrity": "sha512-t/DdTyBchQ2eAZuCmAARlqQsrEm0WyeNwh5zeRuv+cR6gnAsw+86/EWvJ/em5dTnZyaqEy8vlmOMdWarrUbnuQ==",
+      "dependencies": {
+        "tslib": "^2.1.0"
+      }
+    },
+    "node_modules/@isaacs/ttlcache": {
+      "version": "1.4.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz",
+      "integrity": "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==",
+      "peer": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@istanbuljs/load-nyc-config": {
+      "version": "1.1.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
+      "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
+      "peer": true,
+      "dependencies": {
+        "camelcase": "^5.3.1",
+        "find-up": "^4.1.0",
+        "get-package-type": "^0.1.0",
+        "js-yaml": "^3.13.1",
+        "resolve-from": "^5.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/@istanbuljs/schema": {
+      "version": "0.1.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@istanbuljs/schema/-/schema-0.1.3.tgz",
+      "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
+      "peer": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/@jest/create-cache-key-function": {
+      "version": "29.7.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz",
+      "integrity": "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==",
+      "peer": true,
+      "dependencies": {
+        "@jest/types": "^29.6.3"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/@jest/environment": {
+      "version": "29.7.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@jest/environment/-/environment-29.7.0.tgz",
+      "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==",
+      "peer": true,
+      "dependencies": {
+        "@jest/fake-timers": "^29.7.0",
+        "@jest/types": "^29.6.3",
+        "@types/node": "*",
+        "jest-mock": "^29.7.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/@jest/fake-timers": {
+      "version": "29.7.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@jest/fake-timers/-/fake-timers-29.7.0.tgz",
+      "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==",
+      "peer": true,
+      "dependencies": {
+        "@jest/types": "^29.6.3",
+        "@sinonjs/fake-timers": "^10.0.2",
+        "@types/node": "*",
+        "jest-message-util": "^29.7.0",
+        "jest-mock": "^29.7.0",
+        "jest-util": "^29.7.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/@jest/schemas": {
+      "version": "29.6.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@jest/schemas/-/schemas-29.6.3.tgz",
+      "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
+      "peer": true,
+      "dependencies": {
+        "@sinclair/typebox": "^0.27.8"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/@jest/transform": {
+      "version": "29.7.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@jest/transform/-/transform-29.7.0.tgz",
+      "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==",
+      "peer": true,
+      "dependencies": {
+        "@babel/core": "^7.11.6",
+        "@jest/types": "^29.6.3",
+        "@jridgewell/trace-mapping": "^0.3.18",
+        "babel-plugin-istanbul": "^6.1.1",
+        "chalk": "^4.0.0",
+        "convert-source-map": "^2.0.0",
+        "fast-json-stable-stringify": "^2.1.0",
+        "graceful-fs": "^4.2.9",
+        "jest-haste-map": "^29.7.0",
+        "jest-regex-util": "^29.6.3",
+        "jest-util": "^29.7.0",
+        "micromatch": "^4.0.4",
+        "pirates": "^4.0.4",
+        "slash": "^3.0.0",
+        "write-file-atomic": "^4.0.2"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/@jest/types": {
+      "version": "29.6.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@jest/types/-/types-29.6.3.tgz",
+      "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+      "peer": true,
+      "dependencies": {
+        "@jest/schemas": "^29.6.3",
+        "@types/istanbul-lib-coverage": "^2.0.0",
+        "@types/istanbul-reports": "^3.0.0",
+        "@types/node": "*",
+        "@types/yargs": "^17.0.8",
+        "chalk": "^4.0.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/@jridgewell/gen-mapping": {
+      "version": "0.3.8",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
+      "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==",
+      "peer": true,
+      "dependencies": {
+        "@jridgewell/set-array": "^1.2.1",
+        "@jridgewell/sourcemap-codec": "^1.4.10",
+        "@jridgewell/trace-mapping": "^0.3.24"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/resolve-uri": {
+      "version": "3.1.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+      "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+      "peer": true,
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/set-array": {
+      "version": "1.2.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@jridgewell/set-array/-/set-array-1.2.1.tgz",
+      "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
+      "peer": true,
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/source-map": {
+      "version": "0.3.6",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@jridgewell/source-map/-/source-map-0.3.6.tgz",
+      "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
+      "peer": true,
+      "dependencies": {
+        "@jridgewell/gen-mapping": "^0.3.5",
+        "@jridgewell/trace-mapping": "^0.3.25"
+      }
+    },
+    "node_modules/@jridgewell/sourcemap-codec": {
+      "version": "1.5.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
+      "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="
+    },
+    "node_modules/@jridgewell/trace-mapping": {
+      "version": "0.3.25",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
+      "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
+      "peer": true,
+      "dependencies": {
+        "@jridgewell/resolve-uri": "^3.1.0",
+        "@jridgewell/sourcemap-codec": "^1.4.14"
+      }
+    },
+    "node_modules/@microsoft/tsdoc": {
+      "version": "0.15.1",
+      "resolved": "https://registry.npmmirror.com/@microsoft/tsdoc/-/tsdoc-0.15.1.tgz",
+      "integrity": "sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw=="
+    },
+    "node_modules/@microsoft/tsdoc-config": {
+      "version": "0.17.1",
+      "resolved": "https://registry.npmmirror.com/@microsoft/tsdoc-config/-/tsdoc-config-0.17.1.tgz",
+      "integrity": "sha512-UtjIFe0C6oYgTnad4q1QP4qXwLhe6tIpNTRStJ2RZEPIkqQPREAwE5spzVxsdn9UaEMUqhh0AqSx3X4nWAKXWw==",
+      "dependencies": {
+        "@microsoft/tsdoc": "0.15.1",
+        "ajv": "~8.12.0",
+        "jju": "~1.4.0",
+        "resolve": "~1.22.2"
+      }
+    },
+    "node_modules/@microsoft/tsdoc-config/node_modules/ajv": {
+      "version": "8.12.0",
+      "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.12.0.tgz",
+      "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
+      "dependencies": {
+        "fast-deep-equal": "^3.1.1",
+        "json-schema-traverse": "^1.0.0",
+        "require-from-string": "^2.0.2",
+        "uri-js": "^4.2.2"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/epoberezkin"
+      }
+    },
+    "node_modules/@microsoft/tsdoc-config/node_modules/json-schema-traverse": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+      "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
+    },
+    "node_modules/@nuxt/kit": {
+      "version": "3.17.5",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@nuxt/kit/-/kit-3.17.5.tgz",
+      "integrity": "sha512-NdCepmA+S/SzgcaL3oYUeSlXGYO6BXGr9K/m1D0t0O9rApF8CSq/QQ+ja5KYaYMO1kZAEWH4s2XVcE3uPrrAVg==",
+      "dependencies": {
+        "c12": "^3.0.4",
+        "consola": "^3.4.2",
+        "defu": "^6.1.4",
+        "destr": "^2.0.5",
+        "errx": "^0.1.0",
+        "exsolve": "^1.0.5",
+        "ignore": "^7.0.5",
+        "jiti": "^2.4.2",
+        "klona": "^2.0.6",
+        "knitwork": "^1.2.0",
+        "mlly": "^1.7.4",
+        "ohash": "^2.0.11",
+        "pathe": "^2.0.3",
+        "pkg-types": "^2.1.0",
+        "scule": "^1.3.0",
+        "semver": "^7.7.2",
+        "std-env": "^3.9.0",
+        "tinyglobby": "^0.2.14",
+        "ufo": "^1.6.1",
+        "unctx": "^2.4.1",
+        "unimport": "^5.0.1",
+        "untyped": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=18.12.0"
+      }
+    },
+    "node_modules/@parcel/watcher": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher/-/watcher-2.5.1.tgz",
+      "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==",
+      "dev": true,
+      "hasInstallScript": true,
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "detect-libc": "^1.0.3",
+        "is-glob": "^4.0.3",
+        "micromatch": "^4.0.5",
+        "node-addon-api": "^7.0.0"
+      },
+      "engines": {
+        "node": ">= 10.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      },
+      "optionalDependencies": {
+        "@parcel/watcher-android-arm64": "2.5.1",
+        "@parcel/watcher-darwin-arm64": "2.5.1",
+        "@parcel/watcher-darwin-x64": "2.5.1",
+        "@parcel/watcher-freebsd-x64": "2.5.1",
+        "@parcel/watcher-linux-arm-glibc": "2.5.1",
+        "@parcel/watcher-linux-arm-musl": "2.5.1",
+        "@parcel/watcher-linux-arm64-glibc": "2.5.1",
+        "@parcel/watcher-linux-arm64-musl": "2.5.1",
+        "@parcel/watcher-linux-x64-glibc": "2.5.1",
+        "@parcel/watcher-linux-x64-musl": "2.5.1",
+        "@parcel/watcher-win32-arm64": "2.5.1",
+        "@parcel/watcher-win32-ia32": "2.5.1",
+        "@parcel/watcher-win32-x64": "2.5.1"
+      }
+    },
+    "node_modules/@parcel/watcher-win32-x64": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz",
+      "integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">= 10.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/@react-native-google-signin/google-signin": {
+      "version": "14.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@react-native-google-signin/google-signin/-/google-signin-14.0.1.tgz",
+      "integrity": "sha512-2f903eaHiv/Ob96vsWZitz+Z0k2J2W0/C7Ygrr6ejAT2JVzJCatmjF/eq62MWhuTNdU2WDX/oePxMbpQW6k2UA==",
+      "peerDependencies": {
+        "expo": ">=52.0.40",
+        "react": "*",
+        "react-dom": "*",
+        "react-native": "*"
+      },
+      "peerDependenciesMeta": {
+        "expo": {
+          "optional": true
+        },
+        "react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@react-native/assets-registry": {
+      "version": "0.79.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@react-native/assets-registry/-/assets-registry-0.79.3.tgz",
+      "integrity": "sha512-Vy8DQXCJ21YSAiHxrNBz35VqVlZPpRYm50xRTWRf660JwHuJkFQG8cUkrLzm7AUriqUXxwpkQHcY+b0ibw9ejQ==",
+      "peer": true,
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@react-native/codegen": {
+      "version": "0.79.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@react-native/codegen/-/codegen-0.79.3.tgz",
+      "integrity": "sha512-CZejXqKch/a5/s/MO5T8mkAgvzCXgsTkQtpCF15kWR9HN8T+16k0CsN7TXAxXycltoxiE3XRglOrZNEa/TiZUQ==",
+      "peer": true,
+      "dependencies": {
+        "glob": "^7.1.1",
+        "hermes-parser": "0.25.1",
+        "invariant": "^2.2.4",
+        "nullthrows": "^1.1.1",
+        "yargs": "^17.6.2"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "peerDependencies": {
+        "@babel/core": "*"
+      }
+    },
+    "node_modules/@react-native/community-cli-plugin": {
+      "version": "0.79.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@react-native/community-cli-plugin/-/community-cli-plugin-0.79.3.tgz",
+      "integrity": "sha512-N/+p4HQqN4yK6IRzn7OgMvUIcrmEWkecglk1q5nj+AzNpfIOzB+mqR20SYmnPfeXF+mZzYCzRANb3KiM+WsSDA==",
+      "peer": true,
+      "dependencies": {
+        "@react-native/dev-middleware": "0.79.3",
+        "chalk": "^4.0.0",
+        "debug": "^2.2.0",
+        "invariant": "^2.2.4",
+        "metro": "^0.82.0",
+        "metro-config": "^0.82.0",
+        "metro-core": "^0.82.0",
+        "semver": "^7.1.3"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "peerDependencies": {
+        "@react-native-community/cli": "*"
+      },
+      "peerDependenciesMeta": {
+        "@react-native-community/cli": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@react-native/community-cli-plugin/node_modules/debug": {
+      "version": "2.6.9",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-2.6.9.tgz",
+      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "peer": true,
+      "dependencies": {
+        "ms": "2.0.0"
+      }
+    },
+    "node_modules/@react-native/community-cli-plugin/node_modules/ms": {
+      "version": "2.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+      "peer": true
+    },
+    "node_modules/@react-native/debugger-frontend": {
+      "version": "0.79.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@react-native/debugger-frontend/-/debugger-frontend-0.79.3.tgz",
+      "integrity": "sha512-ImNDuEeKH6lEsLXms3ZsgIrNF94jymfuhPcVY5L0trzaYNo9ZFE9Ni2/18E1IbfXxdeIHrCSBJlWD6CTm7wu5A==",
+      "peer": true,
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@react-native/dev-middleware": {
+      "version": "0.79.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@react-native/dev-middleware/-/dev-middleware-0.79.3.tgz",
+      "integrity": "sha512-x88+RGOyG71+idQefnQg7wLhzjn/Scs+re1O5vqCkTVzRAc/f7SdHMlbmECUxJPd08FqMcOJr7/X3nsJBrNuuw==",
+      "peer": true,
+      "dependencies": {
+        "@isaacs/ttlcache": "^1.4.1",
+        "@react-native/debugger-frontend": "0.79.3",
+        "chrome-launcher": "^0.15.2",
+        "chromium-edge-launcher": "^0.2.0",
+        "connect": "^3.6.5",
+        "debug": "^2.2.0",
+        "invariant": "^2.2.4",
+        "nullthrows": "^1.1.1",
+        "open": "^7.0.3",
+        "serve-static": "^1.16.2",
+        "ws": "^6.2.3"
+      },
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@react-native/dev-middleware/node_modules/debug": {
+      "version": "2.6.9",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-2.6.9.tgz",
+      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "peer": true,
+      "dependencies": {
+        "ms": "2.0.0"
+      }
+    },
+    "node_modules/@react-native/dev-middleware/node_modules/ms": {
+      "version": "2.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+      "peer": true
+    },
+    "node_modules/@react-native/gradle-plugin": {
+      "version": "0.79.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@react-native/gradle-plugin/-/gradle-plugin-0.79.3.tgz",
+      "integrity": "sha512-imfpZLhNBc9UFSzb/MOy2tNcIBHqVmexh/qdzw83F75BmUtLb/Gs1L2V5gw+WI1r7RqDILbWk7gXB8zUllwd+g==",
+      "peer": true,
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@react-native/js-polyfills": {
+      "version": "0.79.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@react-native/js-polyfills/-/js-polyfills-0.79.3.tgz",
+      "integrity": "sha512-PEBtg6Kox6KahjCAch0UrqCAmHiNLEbp2SblUEoFAQnov4DSxBN9safh+QSVaCiMAwLjvNfXrJyygZz60Dqz3Q==",
+      "peer": true,
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@react-native/normalize-colors": {
+      "version": "0.79.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@react-native/normalize-colors/-/normalize-colors-0.79.3.tgz",
+      "integrity": "sha512-T75NIQPRFCj6DFMxtcVMJTZR+3vHXaUMSd15t+CkJpc5LnyX91GVaPxpRSAdjFh7m3Yppl5MpdjV/fntImheYQ==",
+      "peer": true
+    },
+    "node_modules/@react-native/virtualized-lists": {
+      "version": "0.79.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@react-native/virtualized-lists/-/virtualized-lists-0.79.3.tgz",
+      "integrity": "sha512-/0rRozkn+iIHya2vnnvprDgT7QkfI54FLrACAN3BLP7MRlfOIGOrZsXpRLndnLBVnjNzkcre84i1RecjoXnwIA==",
+      "peer": true,
+      "dependencies": {
+        "invariant": "^2.2.4",
+        "nullthrows": "^1.1.1"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "peerDependencies": {
+        "@types/react": "^19.0.0",
+        "react": "*",
+        "react-native": "*"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@sinclair/typebox": {
+      "version": "0.27.8",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@sinclair/typebox/-/typebox-0.27.8.tgz",
+      "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==",
+      "peer": true
+    },
+    "node_modules/@sinonjs/commons": {
+      "version": "3.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@sinonjs/commons/-/commons-3.0.1.tgz",
+      "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==",
+      "peer": true,
+      "dependencies": {
+        "type-detect": "4.0.8"
+      }
+    },
+    "node_modules/@sinonjs/fake-timers": {
+      "version": "10.3.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz",
+      "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==",
+      "peer": true,
+      "dependencies": {
+        "@sinonjs/commons": "^3.0.0"
+      }
+    },
+    "node_modules/@types/applepayjs": {
+      "version": "14.0.9",
+      "resolved": "https://registry.npmmirror.com/@types/applepayjs/-/applepayjs-14.0.9.tgz",
+      "integrity": "sha512-xEprYbb0TEP/XIiDPbVnTYpDai8fTFpsQfVSfTd81Is2GOMUy7ie019eyX6Mz2ECxfjoUVKaiGSL577roIeHCg=="
+    },
+    "node_modules/@types/babel__core": {
+      "version": "7.20.5",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@types/babel__core/-/babel__core-7.20.5.tgz",
+      "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+      "peer": true,
+      "dependencies": {
+        "@babel/parser": "^7.20.7",
+        "@babel/types": "^7.20.7",
+        "@types/babel__generator": "*",
+        "@types/babel__template": "*",
+        "@types/babel__traverse": "*"
+      }
+    },
+    "node_modules/@types/babel__generator": {
+      "version": "7.27.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@types/babel__generator/-/babel__generator-7.27.0.tgz",
+      "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
+      "peer": true,
+      "dependencies": {
+        "@babel/types": "^7.0.0"
+      }
+    },
+    "node_modules/@types/babel__template": {
+      "version": "7.4.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@types/babel__template/-/babel__template-7.4.4.tgz",
+      "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+      "peer": true,
+      "dependencies": {
+        "@babel/parser": "^7.1.0",
+        "@babel/types": "^7.0.0"
+      }
+    },
+    "node_modules/@types/babel__traverse": {
+      "version": "7.20.7",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@types/babel__traverse/-/babel__traverse-7.20.7.tgz",
+      "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==",
+      "peer": true,
+      "dependencies": {
+        "@babel/types": "^7.20.7"
+      }
+    },
+    "node_modules/@types/cordova": {
+      "version": "11.0.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@types/cordova/-/cordova-11.0.3.tgz",
+      "integrity": "sha512-kyuRQ40/NWQVhqGIHq78Ehu2Bf9Mlg0LhmSmis6ZFJK7z933FRfYi8tHe/k/0fB+PGfCf95rJC6TO7dopaFvAg=="
+    },
+    "node_modules/@types/eslint": {
+      "version": "9.6.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@types/eslint/-/eslint-9.6.1.tgz",
+      "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "@types/estree": "*",
+        "@types/json-schema": "*"
+      }
+    },
+    "node_modules/@types/eslint-scope": {
+      "version": "3.7.7",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@types/eslint-scope/-/eslint-scope-3.7.7.tgz",
+      "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "@types/eslint": "*",
+        "@types/estree": "*"
+      }
+    },
+    "node_modules/@types/estree": {
+      "version": "1.0.7",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@types/estree/-/estree-1.0.7.tgz",
+      "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ=="
+    },
+    "node_modules/@types/googlepay": {
+      "version": "0.7.6",
+      "resolved": "https://registry.npmmirror.com/@types/googlepay/-/googlepay-0.7.6.tgz",
+      "integrity": "sha512-5003wG+qvf4Ktf1hC9IJuRakNzQov00+Xf09pAWGJLpdOjUrq0SSLCpXX7pwSeTG9r5hrdzq1iFyZcW7WVyr4g=="
+    },
+    "node_modules/@types/graceful-fs": {
+      "version": "4.1.9",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@types/graceful-fs/-/graceful-fs-4.1.9.tgz",
+      "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==",
+      "peer": true,
+      "dependencies": {
+        "@types/node": "*"
+      }
+    },
+    "node_modules/@types/istanbul-lib-coverage": {
+      "version": "2.0.6",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
+      "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==",
+      "peer": true
+    },
+    "node_modules/@types/istanbul-lib-report": {
+      "version": "3.0.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz",
+      "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==",
+      "peer": true,
+      "dependencies": {
+        "@types/istanbul-lib-coverage": "*"
+      }
+    },
+    "node_modules/@types/istanbul-reports": {
+      "version": "3.0.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz",
+      "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==",
+      "peer": true,
+      "dependencies": {
+        "@types/istanbul-lib-report": "*"
+      }
+    },
+    "node_modules/@types/json-schema": {
+      "version": "7.0.15",
+      "resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.15.tgz",
+      "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@types/node": {
+      "version": "22.15.29",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@types/node/-/node-22.15.29.tgz",
+      "integrity": "sha512-LNdjOkUDlU1RZb8e1kOIUpN1qQUlzGkEtbVNo53vbrwDg5om6oduhm4SiUaPW5ASTXhAiP0jInWG8Qx9fVlOeQ==",
+      "peer": true,
+      "dependencies": {
+        "undici-types": "~6.21.0"
+      }
+    },
+    "node_modules/@types/stack-utils": {
+      "version": "2.0.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@types/stack-utils/-/stack-utils-2.0.3.tgz",
+      "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==",
+      "peer": true
+    },
+    "node_modules/@types/yargs": {
+      "version": "17.0.33",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@types/yargs/-/yargs-17.0.33.tgz",
+      "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==",
+      "peer": true,
+      "dependencies": {
+        "@types/yargs-parser": "*"
+      }
+    },
+    "node_modules/@types/yargs-parser": {
+      "version": "21.0.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@types/yargs-parser/-/yargs-parser-21.0.3.tgz",
+      "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==",
+      "peer": true
+    },
+    "node_modules/@vue/compiler-core": {
+      "version": "3.5.16",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/compiler-core/-/compiler-core-3.5.16.tgz",
+      "integrity": "sha512-AOQS2eaQOaaZQoL1u+2rCJIKDruNXVBZSiUD3chnUrsoX5ZTQMaCvXlWNIfxBJuU15r1o7+mpo5223KVtIhAgQ==",
+      "peer": true,
+      "dependencies": {
+        "@babel/parser": "^7.27.2",
+        "@vue/shared": "3.5.16",
+        "entities": "^4.5.0",
+        "estree-walker": "^2.0.2",
+        "source-map-js": "^1.2.1"
+      }
+    },
+    "node_modules/@vue/compiler-core/node_modules/estree-walker": {
+      "version": "2.0.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/estree-walker/-/estree-walker-2.0.2.tgz",
+      "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
+      "peer": true
+    },
+    "node_modules/@vue/compiler-dom": {
+      "version": "3.5.16",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/compiler-dom/-/compiler-dom-3.5.16.tgz",
+      "integrity": "sha512-SSJIhBr/teipXiXjmWOVWLnxjNGo65Oj/8wTEQz0nqwQeP75jWZ0n4sF24Zxoht1cuJoWopwj0J0exYwCJ0dCQ==",
+      "peer": true,
+      "dependencies": {
+        "@vue/compiler-core": "3.5.16",
+        "@vue/shared": "3.5.16"
+      }
+    },
+    "node_modules/@vue/compiler-sfc": {
+      "version": "3.5.16",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/compiler-sfc/-/compiler-sfc-3.5.16.tgz",
+      "integrity": "sha512-rQR6VSFNpiinDy/DVUE0vHoIDUF++6p910cgcZoaAUm3POxgNOOdS/xgoll3rNdKYTYPnnbARDCZOyZ+QSe6Pw==",
+      "peer": true,
+      "dependencies": {
+        "@babel/parser": "^7.27.2",
+        "@vue/compiler-core": "3.5.16",
+        "@vue/compiler-dom": "3.5.16",
+        "@vue/compiler-ssr": "3.5.16",
+        "@vue/shared": "3.5.16",
+        "estree-walker": "^2.0.2",
+        "magic-string": "^0.30.17",
+        "postcss": "^8.5.3",
+        "source-map-js": "^1.2.1"
+      }
+    },
+    "node_modules/@vue/compiler-sfc/node_modules/estree-walker": {
+      "version": "2.0.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/estree-walker/-/estree-walker-2.0.2.tgz",
+      "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
+      "peer": true
+    },
+    "node_modules/@vue/compiler-ssr": {
+      "version": "3.5.16",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/compiler-ssr/-/compiler-ssr-3.5.16.tgz",
+      "integrity": "sha512-d2V7kfxbdsjrDSGlJE7my1ZzCXViEcqN6w14DOsDrUCHEA6vbnVCpRFfrc4ryCP/lCKzX2eS1YtnLE/BuC9f/A==",
+      "peer": true,
+      "dependencies": {
+        "@vue/compiler-dom": "3.5.16",
+        "@vue/shared": "3.5.16"
+      }
+    },
+    "node_modules/@vue/devtools-api": {
+      "version": "7.7.2",
+      "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-7.7.2.tgz",
+      "integrity": "sha512-1syn558KhyN+chO5SjlZIwJ8bV/bQ1nOVTG66t2RbG66ZGekyiYNmRO7X9BJCXQqPsFHlnksqvPhce2qpzxFnA==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/devtools-kit": "^7.7.2"
+      }
+    },
+    "node_modules/@vue/devtools-kit": {
+      "version": "7.7.2",
+      "resolved": "https://registry.npmmirror.com/@vue/devtools-kit/-/devtools-kit-7.7.2.tgz",
+      "integrity": "sha512-CY0I1JH3Z8PECbn6k3TqM1Bk9ASWxeMtTCvZr7vb+CHi+X/QwQm5F1/fPagraamKMAHVfuuCbdcnNg1A4CYVWQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/devtools-shared": "^7.7.2",
+        "birpc": "^0.2.19",
+        "hookable": "^5.5.3",
+        "mitt": "^3.0.1",
+        "perfect-debounce": "^1.0.0",
+        "speakingurl": "^14.0.1",
+        "superjson": "^2.2.1"
+      }
+    },
+    "node_modules/@vue/devtools-shared": {
+      "version": "7.7.2",
+      "resolved": "https://registry.npmmirror.com/@vue/devtools-shared/-/devtools-shared-7.7.2.tgz",
+      "integrity": "sha512-uBFxnp8gwW2vD6FrJB8JZLUzVb6PNRG0B0jBnHsOH8uKyva2qINY8PTF5Te4QlTbMDqU5K6qtJDr6cNsKWhbOA==",
+      "license": "MIT",
+      "dependencies": {
+        "rfdc": "^1.4.1"
+      }
+    },
+    "node_modules/@vue/reactivity": {
+      "version": "3.5.16",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/reactivity/-/reactivity-3.5.16.tgz",
+      "integrity": "sha512-FG5Q5ee/kxhIm1p2bykPpPwqiUBV3kFySsHEQha5BJvjXdZTUfmya7wP7zC39dFuZAcf/PD5S4Lni55vGLMhvA==",
+      "peer": true,
+      "dependencies": {
+        "@vue/shared": "3.5.16"
+      }
+    },
+    "node_modules/@vue/runtime-core": {
+      "version": "3.5.16",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/runtime-core/-/runtime-core-3.5.16.tgz",
+      "integrity": "sha512-bw5Ykq6+JFHYxrQa7Tjr+VSzw7Dj4ldR/udyBZbq73fCdJmyy5MPIFR9IX/M5Qs+TtTjuyUTCnmK3lWWwpAcFQ==",
+      "peer": true,
+      "dependencies": {
+        "@vue/reactivity": "3.5.16",
+        "@vue/shared": "3.5.16"
+      }
+    },
+    "node_modules/@vue/runtime-dom": {
+      "version": "3.5.16",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/runtime-dom/-/runtime-dom-3.5.16.tgz",
+      "integrity": "sha512-T1qqYJsG2xMGhImRUV9y/RseB9d0eCYZQ4CWca9ztCuiPj/XWNNN+lkNBuzVbia5z4/cgxdL28NoQCvC0Xcfww==",
+      "peer": true,
+      "dependencies": {
+        "@vue/reactivity": "3.5.16",
+        "@vue/runtime-core": "3.5.16",
+        "@vue/shared": "3.5.16",
+        "csstype": "^3.1.3"
+      }
+    },
+    "node_modules/@vue/server-renderer": {
+      "version": "3.5.16",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/server-renderer/-/server-renderer-3.5.16.tgz",
+      "integrity": "sha512-BrX0qLiv/WugguGsnQUJiYOE0Fe5mZTwi6b7X/ybGB0vfrPH9z0gD/Y6WOR1sGCgX4gc25L1RYS5eYQKDMoNIg==",
+      "peer": true,
+      "dependencies": {
+        "@vue/compiler-ssr": "3.5.16",
+        "@vue/shared": "3.5.16"
+      },
+      "peerDependencies": {
+        "vue": "3.5.16"
+      }
+    },
+    "node_modules/@vue/shared": {
+      "version": "3.5.16",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/shared/-/shared-3.5.16.tgz",
+      "integrity": "sha512-c/0fWy3Jw6Z8L9FmTyYfkpM5zklnqqa9+a6dz3DvONRKW2NEbh46BP0FHuLFSWi2TnQEtp91Z6zOWNrU6QiyPg==",
+      "peer": true
+    },
+    "node_modules/@webassemblyjs/ast": {
+      "version": "1.14.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@webassemblyjs/ast/-/ast-1.14.1.tgz",
+      "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "@webassemblyjs/helper-numbers": "1.13.2",
+        "@webassemblyjs/helper-wasm-bytecode": "1.13.2"
+      }
+    },
+    "node_modules/@webassemblyjs/floating-point-hex-parser": {
+      "version": "1.13.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz",
+      "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==",
+      "dev": true,
+      "peer": true
+    },
+    "node_modules/@webassemblyjs/helper-api-error": {
+      "version": "1.13.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz",
+      "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==",
+      "dev": true,
+      "peer": true
+    },
+    "node_modules/@webassemblyjs/helper-buffer": {
+      "version": "1.14.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz",
+      "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==",
+      "dev": true,
+      "peer": true
+    },
+    "node_modules/@webassemblyjs/helper-numbers": {
+      "version": "1.13.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz",
+      "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "@webassemblyjs/floating-point-hex-parser": "1.13.2",
+        "@webassemblyjs/helper-api-error": "1.13.2",
+        "@xtuc/long": "4.2.2"
+      }
+    },
+    "node_modules/@webassemblyjs/helper-wasm-bytecode": {
+      "version": "1.13.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz",
+      "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==",
+      "dev": true,
+      "peer": true
+    },
+    "node_modules/@webassemblyjs/helper-wasm-section": {
+      "version": "1.14.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz",
+      "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "@webassemblyjs/ast": "1.14.1",
+        "@webassemblyjs/helper-buffer": "1.14.1",
+        "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+        "@webassemblyjs/wasm-gen": "1.14.1"
+      }
+    },
+    "node_modules/@webassemblyjs/ieee754": {
+      "version": "1.13.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz",
+      "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "@xtuc/ieee754": "^1.2.0"
+      }
+    },
+    "node_modules/@webassemblyjs/leb128": {
+      "version": "1.13.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@webassemblyjs/leb128/-/leb128-1.13.2.tgz",
+      "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "@xtuc/long": "4.2.2"
+      }
+    },
+    "node_modules/@webassemblyjs/utf8": {
+      "version": "1.13.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@webassemblyjs/utf8/-/utf8-1.13.2.tgz",
+      "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==",
+      "dev": true,
+      "peer": true
+    },
+    "node_modules/@webassemblyjs/wasm-edit": {
+      "version": "1.14.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz",
+      "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "@webassemblyjs/ast": "1.14.1",
+        "@webassemblyjs/helper-buffer": "1.14.1",
+        "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+        "@webassemblyjs/helper-wasm-section": "1.14.1",
+        "@webassemblyjs/wasm-gen": "1.14.1",
+        "@webassemblyjs/wasm-opt": "1.14.1",
+        "@webassemblyjs/wasm-parser": "1.14.1",
+        "@webassemblyjs/wast-printer": "1.14.1"
+      }
+    },
+    "node_modules/@webassemblyjs/wasm-gen": {
+      "version": "1.14.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz",
+      "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "@webassemblyjs/ast": "1.14.1",
+        "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+        "@webassemblyjs/ieee754": "1.13.2",
+        "@webassemblyjs/leb128": "1.13.2",
+        "@webassemblyjs/utf8": "1.13.2"
+      }
+    },
+    "node_modules/@webassemblyjs/wasm-opt": {
+      "version": "1.14.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz",
+      "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "@webassemblyjs/ast": "1.14.1",
+        "@webassemblyjs/helper-buffer": "1.14.1",
+        "@webassemblyjs/wasm-gen": "1.14.1",
+        "@webassemblyjs/wasm-parser": "1.14.1"
+      }
+    },
+    "node_modules/@webassemblyjs/wasm-parser": {
+      "version": "1.14.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz",
+      "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "@webassemblyjs/ast": "1.14.1",
+        "@webassemblyjs/helper-api-error": "1.13.2",
+        "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+        "@webassemblyjs/ieee754": "1.13.2",
+        "@webassemblyjs/leb128": "1.13.2",
+        "@webassemblyjs/utf8": "1.13.2"
+      }
+    },
+    "node_modules/@webassemblyjs/wast-printer": {
+      "version": "1.14.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz",
+      "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "@webassemblyjs/ast": "1.14.1",
+        "@xtuc/long": "4.2.2"
+      }
+    },
+    "node_modules/@xtuc/ieee754": {
+      "version": "1.2.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
+      "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
+      "dev": true,
+      "peer": true
+    },
+    "node_modules/@xtuc/long": {
+      "version": "4.2.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@xtuc/long/-/long-4.2.2.tgz",
+      "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
+      "dev": true,
+      "peer": true
+    },
+    "node_modules/abort-controller": {
+      "version": "3.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/abort-controller/-/abort-controller-3.0.0.tgz",
+      "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
+      "peer": true,
+      "dependencies": {
+        "event-target-shim": "^5.0.0"
+      },
+      "engines": {
+        "node": ">=6.5"
+      }
+    },
+    "node_modules/accepts": {
+      "version": "1.3.8",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/accepts/-/accepts-1.3.8.tgz",
+      "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
+      "peer": true,
+      "dependencies": {
+        "mime-types": "~2.1.34",
+        "negotiator": "0.6.3"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/acorn": {
+      "version": "8.14.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/acorn/-/acorn-8.14.1.tgz",
+      "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
+      "bin": {
+        "acorn": "bin/acorn"
+      },
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/agent-base": {
+      "version": "7.1.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/agent-base/-/agent-base-7.1.3.tgz",
+      "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==",
+      "peer": true,
+      "engines": {
+        "node": ">= 14"
+      }
+    },
+    "node_modules/airwallex-payment-elements": {
+      "version": "1.122.0",
+      "resolved": "https://registry.npmmirror.com/airwallex-payment-elements/-/airwallex-payment-elements-1.122.0.tgz",
+      "integrity": "sha512-DbIu3NtonRrJk8yHQHR+Wx3tcUFVscfRYuNPLd4ylxxLw2KqvIeDHdRybOk1u5qihaAZVIJa9erwYuMO8qjp8Q==",
+      "dependencies": {
+        "@types/applepayjs": "^14.0.9",
+        "@types/googlepay": "^0.7.6",
+        "csstype": "^3.0.6",
+        "eslint-plugin-tsdoc": "^0.4.0"
+      },
+      "bin": {
+        "airwallex-payment-elements": "lib/bin/airwallex.cjs.js"
+      }
+    },
+    "node_modules/ajv": {
+      "version": "6.12.6",
+      "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz",
+      "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "fast-deep-equal": "^3.1.1",
+        "fast-json-stable-stringify": "^2.0.0",
+        "json-schema-traverse": "^0.4.1",
+        "uri-js": "^4.2.2"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/epoberezkin"
+      }
+    },
+    "node_modules/ajv-formats": {
+      "version": "2.1.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ajv-formats/-/ajv-formats-2.1.1.tgz",
+      "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "ajv": "^8.0.0"
+      },
+      "peerDependencies": {
+        "ajv": "^8.0.0"
+      },
+      "peerDependenciesMeta": {
+        "ajv": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/ajv-formats/node_modules/ajv": {
+      "version": "8.17.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ajv/-/ajv-8.17.1.tgz",
+      "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "fast-deep-equal": "^3.1.3",
+        "fast-uri": "^3.0.1",
+        "json-schema-traverse": "^1.0.0",
+        "require-from-string": "^2.0.2"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/epoberezkin"
+      }
+    },
+    "node_modules/ajv-formats/node_modules/json-schema-traverse": {
+      "version": "1.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+      "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+      "dev": true,
+      "peer": true
+    },
+    "node_modules/ajv-keywords": {
+      "version": "3.5.2",
+      "resolved": "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
+      "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
+      "dev": true,
+      "license": "MIT",
+      "peerDependencies": {
+        "ajv": "^6.9.1"
+      }
+    },
+    "node_modules/anser": {
+      "version": "1.4.10",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/anser/-/anser-1.4.10.tgz",
+      "integrity": "sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==",
+      "peer": true
+    },
+    "node_modules/ansi-regex": {
+      "version": "5.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-regex/-/ansi-regex-5.0.1.tgz",
+      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+      "peer": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/ansi-styles": {
+      "version": "4.3.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-styles/-/ansi-styles-4.3.0.tgz",
+      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+      "peer": true,
+      "dependencies": {
+        "color-convert": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+      }
+    },
+    "node_modules/anymatch": {
+      "version": "3.1.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/anymatch/-/anymatch-3.1.3.tgz",
+      "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+      "peer": true,
+      "dependencies": {
+        "normalize-path": "^3.0.0",
+        "picomatch": "^2.0.4"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/argparse": {
+      "version": "1.0.10",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/argparse/-/argparse-1.0.10.tgz",
+      "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+      "peer": true,
+      "dependencies": {
+        "sprintf-js": "~1.0.2"
+      }
+    },
+    "node_modules/asap": {
+      "version": "2.0.6",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/asap/-/asap-2.0.6.tgz",
+      "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==",
+      "peer": true
+    },
+    "node_modules/async-limiter": {
+      "version": "1.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/async-limiter/-/async-limiter-1.0.1.tgz",
+      "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==",
+      "peer": true
+    },
+    "node_modules/babel-jest": {
+      "version": "29.7.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/babel-jest/-/babel-jest-29.7.0.tgz",
+      "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==",
+      "peer": true,
+      "dependencies": {
+        "@jest/transform": "^29.7.0",
+        "@types/babel__core": "^7.1.14",
+        "babel-plugin-istanbul": "^6.1.1",
+        "babel-preset-jest": "^29.6.3",
+        "chalk": "^4.0.0",
+        "graceful-fs": "^4.2.9",
+        "slash": "^3.0.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.8.0"
+      }
+    },
+    "node_modules/babel-plugin-istanbul": {
+      "version": "6.1.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz",
+      "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==",
+      "peer": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.0.0",
+        "@istanbuljs/load-nyc-config": "^1.0.0",
+        "@istanbuljs/schema": "^0.1.2",
+        "istanbul-lib-instrument": "^5.0.4",
+        "test-exclude": "^6.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/babel-plugin-jest-hoist": {
+      "version": "29.6.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz",
+      "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==",
+      "peer": true,
+      "dependencies": {
+        "@babel/template": "^7.3.3",
+        "@babel/types": "^7.3.3",
+        "@types/babel__core": "^7.1.14",
+        "@types/babel__traverse": "^7.0.6"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/babel-plugin-syntax-hermes-parser": {
+      "version": "0.25.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.25.1.tgz",
+      "integrity": "sha512-IVNpGzboFLfXZUAwkLFcI/bnqVbwky0jP3eBno4HKtqvQJAHBLdgxiG6lQ4to0+Q/YCN3PO0od5NZwIKyY4REQ==",
+      "peer": true,
+      "dependencies": {
+        "hermes-parser": "0.25.1"
+      }
+    },
+    "node_modules/babel-preset-current-node-syntax": {
+      "version": "1.1.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz",
+      "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==",
+      "peer": true,
+      "dependencies": {
+        "@babel/plugin-syntax-async-generators": "^7.8.4",
+        "@babel/plugin-syntax-bigint": "^7.8.3",
+        "@babel/plugin-syntax-class-properties": "^7.12.13",
+        "@babel/plugin-syntax-class-static-block": "^7.14.5",
+        "@babel/plugin-syntax-import-attributes": "^7.24.7",
+        "@babel/plugin-syntax-import-meta": "^7.10.4",
+        "@babel/plugin-syntax-json-strings": "^7.8.3",
+        "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
+        "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
+        "@babel/plugin-syntax-numeric-separator": "^7.10.4",
+        "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+        "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
+        "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+        "@babel/plugin-syntax-private-property-in-object": "^7.14.5",
+        "@babel/plugin-syntax-top-level-await": "^7.14.5"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/babel-preset-jest": {
+      "version": "29.6.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz",
+      "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==",
+      "peer": true,
+      "dependencies": {
+        "babel-plugin-jest-hoist": "^29.6.3",
+        "babel-preset-current-node-syntax": "^1.0.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/balanced-match": {
+      "version": "1.0.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/balanced-match/-/balanced-match-1.0.2.tgz",
+      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+      "peer": true
+    },
+    "node_modules/base64-js": {
+      "version": "1.5.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/base64-js/-/base64-js-1.5.1.tgz",
+      "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ],
+      "peer": true
+    },
+    "node_modules/big.js": {
+      "version": "5.2.2",
+      "resolved": "https://registry.npmmirror.com/big.js/-/big.js-5.2.2.tgz",
+      "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/birpc": {
+      "version": "0.2.19",
+      "resolved": "https://registry.npmmirror.com/birpc/-/birpc-0.2.19.tgz",
+      "integrity": "sha512-5WeXXAvTmitV1RqJFppT5QtUiz2p1mRSYU000Jkft5ZUCLJIk4uQriYNO50HknxKwM6jd8utNc66K1qGIwwWBQ==",
+      "license": "MIT",
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      }
+    },
+    "node_modules/brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "peer": true,
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "node_modules/braces": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.3.tgz",
+      "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+      "license": "MIT",
+      "dependencies": {
+        "fill-range": "^7.1.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/browserslist": {
+      "version": "4.25.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/browserslist/-/browserslist-4.25.0.tgz",
+      "integrity": "sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA==",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/browserslist"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/browserslist"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "peer": true,
+      "dependencies": {
+        "caniuse-lite": "^1.0.30001718",
+        "electron-to-chromium": "^1.5.160",
+        "node-releases": "^2.0.19",
+        "update-browserslist-db": "^1.1.3"
+      },
+      "bin": {
+        "browserslist": "cli.js"
+      },
+      "engines": {
+        "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+      }
+    },
+    "node_modules/bser": {
+      "version": "2.1.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/bser/-/bser-2.1.1.tgz",
+      "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==",
+      "peer": true,
+      "dependencies": {
+        "node-int64": "^0.4.0"
+      }
+    },
+    "node_modules/buffer-from": {
+      "version": "1.1.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/buffer-from/-/buffer-from-1.1.2.tgz",
+      "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+      "peer": true
+    },
+    "node_modules/c12": {
+      "version": "3.0.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/c12/-/c12-3.0.4.tgz",
+      "integrity": "sha512-t5FaZTYbbCtvxuZq9xxIruYydrAGsJ+8UdP0pZzMiK2xl/gNiSOy0OxhLzHUEEb0m1QXYqfzfvyIFEmz/g9lqg==",
+      "dependencies": {
+        "chokidar": "^4.0.3",
+        "confbox": "^0.2.2",
+        "defu": "^6.1.4",
+        "dotenv": "^16.5.0",
+        "exsolve": "^1.0.5",
+        "giget": "^2.0.0",
+        "jiti": "^2.4.2",
+        "ohash": "^2.0.11",
+        "pathe": "^2.0.3",
+        "perfect-debounce": "^1.0.0",
+        "pkg-types": "^2.1.0",
+        "rc9": "^2.1.2"
+      },
+      "peerDependencies": {
+        "magicast": "^0.3.5"
+      },
+      "peerDependenciesMeta": {
+        "magicast": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/caller-callsite": {
+      "version": "2.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/caller-callsite/-/caller-callsite-2.0.0.tgz",
+      "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=",
+      "peer": true,
+      "dependencies": {
+        "callsites": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/caller-path": {
+      "version": "2.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/caller-path/-/caller-path-2.0.0.tgz",
+      "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=",
+      "peer": true,
+      "dependencies": {
+        "caller-callsite": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/callsites": {
+      "version": "2.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/callsites/-/callsites-2.0.0.tgz",
+      "integrity": "sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==",
+      "peer": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/camelcase": {
+      "version": "5.3.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/camelcase/-/camelcase-5.3.1.tgz",
+      "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+      "peer": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/caniuse-lite": {
+      "version": "1.0.30001721",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/caniuse-lite/-/caniuse-lite-1.0.30001721.tgz",
+      "integrity": "sha512-cOuvmUVtKrtEaoKiO0rSc29jcjwMwX5tOHDy4MgVFEWiUXj4uBMJkwI8MDySkgXidpMiHUcviogAvFi4pA2hDQ==",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/browserslist"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "peer": true
+    },
+    "node_modules/chalk": {
+      "version": "4.1.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/chalk/-/chalk-4.1.2.tgz",
+      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+      "peer": true,
+      "dependencies": {
+        "ansi-styles": "^4.1.0",
+        "supports-color": "^7.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/chalk?sponsor=1"
+      }
+    },
+    "node_modules/chalk/node_modules/supports-color": {
+      "version": "7.2.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/supports-color/-/supports-color-7.2.0.tgz",
+      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+      "peer": true,
+      "dependencies": {
+        "has-flag": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/chokidar": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-4.0.3.tgz",
+      "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
+      "license": "MIT",
+      "dependencies": {
+        "readdirp": "^4.0.1"
+      },
+      "engines": {
+        "node": ">= 14.16.0"
+      },
+      "funding": {
+        "url": "https://paulmillr.com/funding/"
+      }
+    },
+    "node_modules/chrome-launcher": {
+      "version": "0.15.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/chrome-launcher/-/chrome-launcher-0.15.2.tgz",
+      "integrity": "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==",
+      "peer": true,
+      "dependencies": {
+        "@types/node": "*",
+        "escape-string-regexp": "^4.0.0",
+        "is-wsl": "^2.2.0",
+        "lighthouse-logger": "^1.0.0"
+      },
+      "bin": {
+        "print-chrome-path": "bin/print-chrome-path.js"
+      },
+      "engines": {
+        "node": ">=12.13.0"
+      }
+    },
+    "node_modules/chrome-launcher/node_modules/escape-string-regexp": {
+      "version": "4.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+      "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+      "peer": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/chrome-trace-event": {
+      "version": "1.0.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz",
+      "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==",
+      "dev": true,
+      "peer": true,
+      "engines": {
+        "node": ">=6.0"
+      }
+    },
+    "node_modules/chromium-edge-launcher": {
+      "version": "0.2.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/chromium-edge-launcher/-/chromium-edge-launcher-0.2.0.tgz",
+      "integrity": "sha512-JfJjUnq25y9yg4FABRRVPmBGWPZZi+AQXT4mxupb67766/0UlhG8PAZCz6xzEMXTbW3CsSoE8PcCWA49n35mKg==",
+      "peer": true,
+      "dependencies": {
+        "@types/node": "*",
+        "escape-string-regexp": "^4.0.0",
+        "is-wsl": "^2.2.0",
+        "lighthouse-logger": "^1.0.0",
+        "mkdirp": "^1.0.4",
+        "rimraf": "^3.0.2"
+      }
+    },
+    "node_modules/chromium-edge-launcher/node_modules/escape-string-regexp": {
+      "version": "4.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+      "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+      "peer": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/ci-info": {
+      "version": "3.9.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ci-info/-/ci-info-3.9.0.tgz",
+      "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/sibiraj-s"
+        }
+      ],
+      "peer": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/citty": {
+      "version": "0.1.6",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/citty/-/citty-0.1.6.tgz",
+      "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==",
+      "dependencies": {
+        "consola": "^3.2.3"
+      }
+    },
+    "node_modules/clipboard": {
+      "version": "2.0.11",
+      "resolved": "https://registry.npmmirror.com/clipboard/-/clipboard-2.0.11.tgz",
+      "integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==",
+      "license": "MIT",
+      "dependencies": {
+        "good-listener": "^1.2.2",
+        "select": "^1.1.2",
+        "tiny-emitter": "^2.0.0"
+      }
+    },
+    "node_modules/cliui": {
+      "version": "8.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/cliui/-/cliui-8.0.1.tgz",
+      "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+      "peer": true,
+      "dependencies": {
+        "string-width": "^4.2.0",
+        "strip-ansi": "^6.0.1",
+        "wrap-ansi": "^7.0.0"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/color-convert": {
+      "version": "2.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/color-convert/-/color-convert-2.0.1.tgz",
+      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+      "peer": true,
+      "dependencies": {
+        "color-name": "~1.1.4"
+      },
+      "engines": {
+        "node": ">=7.0.0"
+      }
+    },
+    "node_modules/color-name": {
+      "version": "1.1.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/color-name/-/color-name-1.1.4.tgz",
+      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+      "peer": true
+    },
+    "node_modules/commander": {
+      "version": "2.20.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/commander/-/commander-2.20.3.tgz",
+      "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+      "peer": true
+    },
+    "node_modules/concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+      "peer": true
+    },
+    "node_modules/confbox": {
+      "version": "0.2.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/confbox/-/confbox-0.2.2.tgz",
+      "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ=="
+    },
+    "node_modules/connect": {
+      "version": "3.7.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/connect/-/connect-3.7.0.tgz",
+      "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==",
+      "peer": true,
+      "dependencies": {
+        "debug": "2.6.9",
+        "finalhandler": "1.1.2",
+        "parseurl": "~1.3.3",
+        "utils-merge": "1.0.1"
+      },
+      "engines": {
+        "node": ">= 0.10.0"
+      }
+    },
+    "node_modules/connect/node_modules/debug": {
+      "version": "2.6.9",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-2.6.9.tgz",
+      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "peer": true,
+      "dependencies": {
+        "ms": "2.0.0"
+      }
+    },
+    "node_modules/connect/node_modules/ms": {
+      "version": "2.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+      "peer": true
+    },
+    "node_modules/consola": {
+      "version": "3.4.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/consola/-/consola-3.4.2.tgz",
+      "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==",
+      "engines": {
+        "node": "^14.18.0 || >=16.10.0"
+      }
+    },
+    "node_modules/convert-source-map": {
+      "version": "2.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/convert-source-map/-/convert-source-map-2.0.0.tgz",
+      "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+      "peer": true
+    },
+    "node_modules/copy-anything": {
+      "version": "3.0.5",
+      "resolved": "https://registry.npmmirror.com/copy-anything/-/copy-anything-3.0.5.tgz",
+      "integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==",
+      "license": "MIT",
+      "dependencies": {
+        "is-what": "^4.1.8"
+      },
+      "engines": {
+        "node": ">=12.13"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/mesqueeb"
+      }
+    },
+    "node_modules/cosmiconfig": {
+      "version": "5.2.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/cosmiconfig/-/cosmiconfig-5.2.1.tgz",
+      "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==",
+      "peer": true,
+      "dependencies": {
+        "import-fresh": "^2.0.0",
+        "is-directory": "^0.3.1",
+        "js-yaml": "^3.13.1",
+        "parse-json": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/csstype": {
+      "version": "3.1.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/csstype/-/csstype-3.1.3.tgz",
+      "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
+    },
+    "node_modules/dayjs": {
+      "version": "1.11.13",
+      "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.13.tgz",
+      "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==",
+      "license": "MIT"
+    },
+    "node_modules/debug": {
+      "version": "4.4.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-4.4.1.tgz",
+      "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+      "peer": true,
+      "dependencies": {
+        "ms": "^2.1.3"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/deep-pick-omit": {
+      "version": "1.2.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/deep-pick-omit/-/deep-pick-omit-1.2.1.tgz",
+      "integrity": "sha512-2J6Kc/m3irCeqVG42T+SaUMesaK7oGWaedGnQQK/+O0gYc+2SP5bKh/KKTE7d7SJ+GCA9UUE1GRzh6oDe0EnGw=="
+    },
+    "node_modules/defu": {
+      "version": "6.1.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/defu/-/defu-6.1.4.tgz",
+      "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg=="
+    },
+    "node_modules/delegate": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmmirror.com/delegate/-/delegate-3.2.0.tgz",
+      "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==",
+      "license": "MIT"
+    },
+    "node_modules/depd": {
+      "version": "2.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/depd/-/depd-2.0.0.tgz",
+      "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+      "peer": true,
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/destr": {
+      "version": "2.0.5",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/destr/-/destr-2.0.5.tgz",
+      "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA=="
+    },
+    "node_modules/destroy": {
+      "version": "1.2.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/destroy/-/destroy-1.2.0.tgz",
+      "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
+      "peer": true,
+      "engines": {
+        "node": ">= 0.8",
+        "npm": "1.2.8000 || >= 1.4.16"
+      }
+    },
+    "node_modules/detect-libc": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-1.0.3.tgz",
+      "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "optional": true,
+      "bin": {
+        "detect-libc": "bin/detect-libc.js"
+      },
+      "engines": {
+        "node": ">=0.10"
+      }
+    },
+    "node_modules/dotenv": {
+      "version": "16.5.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/dotenv/-/dotenv-16.5.0.tgz",
+      "integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==",
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://dotenvx.com"
+      }
+    },
+    "node_modules/ee-first": {
+      "version": "1.1.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ee-first/-/ee-first-1.1.1.tgz",
+      "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
+      "peer": true
+    },
+    "node_modules/electron-to-chromium": {
+      "version": "1.5.163",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/electron-to-chromium/-/electron-to-chromium-1.5.163.tgz",
+      "integrity": "sha512-y6WESxcFekrMfiz9+pTLNacCTsOyeha5JkleNgE12k+7M8P8gaA09h6r/Kc5m2iQ87V9taexvLjAl2ILdJ+xmw==",
+      "peer": true
+    },
+    "node_modules/emoji-regex": {
+      "version": "8.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/emoji-regex/-/emoji-regex-8.0.0.tgz",
+      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+      "peer": true
+    },
+    "node_modules/emojis-list": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmmirror.com/emojis-list/-/emojis-list-3.0.0.tgz",
+      "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 4"
+      }
+    },
+    "node_modules/encodeurl": {
+      "version": "1.0.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/encodeurl/-/encodeurl-1.0.2.tgz",
+      "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
+      "peer": true,
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/enhanced-resolve": {
+      "version": "5.18.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz",
+      "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "graceful-fs": "^4.2.4",
+        "tapable": "^2.2.0"
+      },
+      "engines": {
+        "node": ">=10.13.0"
+      }
+    },
+    "node_modules/entities": {
+      "version": "4.5.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/entities/-/entities-4.5.0.tgz",
+      "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+      "peer": true,
+      "engines": {
+        "node": ">=0.12"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/entities?sponsor=1"
+      }
+    },
+    "node_modules/error-ex": {
+      "version": "1.3.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/error-ex/-/error-ex-1.3.2.tgz",
+      "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+      "peer": true,
+      "dependencies": {
+        "is-arrayish": "^0.2.1"
+      }
+    },
+    "node_modules/error-stack-parser": {
+      "version": "2.1.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/error-stack-parser/-/error-stack-parser-2.1.4.tgz",
+      "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==",
+      "peer": true,
+      "dependencies": {
+        "stackframe": "^1.3.4"
+      }
+    },
+    "node_modules/errx": {
+      "version": "0.1.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/errx/-/errx-0.1.0.tgz",
+      "integrity": "sha512-fZmsRiDNv07K6s2KkKFTiD2aIvECa7++PKyD5NC32tpRw46qZA3sOz+aM+/V9V0GDHxVTKLziveV4JhzBHDp9Q=="
+    },
+    "node_modules/es-module-lexer": {
+      "version": "1.7.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
+      "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==",
+      "dev": true,
+      "peer": true
+    },
+    "node_modules/escalade": {
+      "version": "3.2.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/escalade/-/escalade-3.2.0.tgz",
+      "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+      "peer": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/escape-html": {
+      "version": "1.0.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/escape-html/-/escape-html-1.0.3.tgz",
+      "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
+      "peer": true
+    },
+    "node_modules/escape-string-regexp": {
+      "version": "5.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
+      "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/eslint-plugin-tsdoc": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmmirror.com/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.4.0.tgz",
+      "integrity": "sha512-MT/8b4aKLdDClnS8mP3R/JNjg29i0Oyqd/0ym6NnQf+gfKbJJ4ZcSh2Bs1H0YiUMTBwww5JwXGTWot/RwyJ7aQ==",
+      "dependencies": {
+        "@microsoft/tsdoc": "0.15.1",
+        "@microsoft/tsdoc-config": "0.17.1"
+      }
+    },
+    "node_modules/eslint-scope": {
+      "version": "5.1.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/eslint-scope/-/eslint-scope-5.1.1.tgz",
+      "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "esrecurse": "^4.3.0",
+        "estraverse": "^4.1.1"
+      },
+      "engines": {
+        "node": ">=8.0.0"
+      }
+    },
+    "node_modules/esprima": {
+      "version": "4.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/esprima/-/esprima-4.0.1.tgz",
+      "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+      "peer": true,
+      "bin": {
+        "esparse": "bin/esparse.js",
+        "esvalidate": "bin/esvalidate.js"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/esrecurse": {
+      "version": "4.3.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/esrecurse/-/esrecurse-4.3.0.tgz",
+      "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "estraverse": "^5.2.0"
+      },
+      "engines": {
+        "node": ">=4.0"
+      }
+    },
+    "node_modules/esrecurse/node_modules/estraverse": {
+      "version": "5.3.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/estraverse/-/estraverse-5.3.0.tgz",
+      "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+      "dev": true,
+      "peer": true,
+      "engines": {
+        "node": ">=4.0"
+      }
+    },
+    "node_modules/estraverse": {
+      "version": "4.3.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/estraverse/-/estraverse-4.3.0.tgz",
+      "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+      "dev": true,
+      "peer": true,
+      "engines": {
+        "node": ">=4.0"
+      }
+    },
+    "node_modules/estree-walker": {
+      "version": "3.0.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/estree-walker/-/estree-walker-3.0.3.tgz",
+      "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
+      "dependencies": {
+        "@types/estree": "^1.0.0"
+      }
+    },
+    "node_modules/etag": {
+      "version": "1.8.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/etag/-/etag-1.8.1.tgz",
+      "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+      "peer": true,
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/event-target-shim": {
+      "version": "5.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/event-target-shim/-/event-target-shim-5.0.1.tgz",
+      "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
+      "peer": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/events": {
+      "version": "3.3.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/events/-/events-3.3.0.tgz",
+      "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+      "dev": true,
+      "peer": true,
+      "engines": {
+        "node": ">=0.8.x"
+      }
+    },
+    "node_modules/exponential-backoff": {
+      "version": "3.1.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/exponential-backoff/-/exponential-backoff-3.1.2.tgz",
+      "integrity": "sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==",
+      "peer": true
+    },
+    "node_modules/exsolve": {
+      "version": "1.0.5",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/exsolve/-/exsolve-1.0.5.tgz",
+      "integrity": "sha512-pz5dvkYYKQ1AHVrgOzBKWeP4u4FRb3a6DNK2ucr0OoNwYIU4QWsJ+NM36LLzORT+z845MzKHHhpXiUF5nvQoJg=="
+    },
+    "node_modules/fast-deep-equal": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+      "license": "MIT"
+    },
+    "node_modules/fast-json-stable-stringify": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+      "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+      "license": "MIT"
+    },
+    "node_modules/fast-uri": {
+      "version": "3.0.6",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/fast-uri/-/fast-uri-3.0.6.tgz",
+      "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/fastify"
+        },
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/fastify"
+        }
+      ],
+      "peer": true
+    },
+    "node_modules/fb-sdk": {
+      "version": "1.0.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/fb-sdk/-/fb-sdk-1.0.3.tgz",
+      "integrity": "sha512-i1n/72J9u2pS6tLlIydilRlu8GrcsgPqs+0JOW6dH2CB5Pu4CjfCbpPqjlw+pbA02ViHg2J2O1mm7TDLbgiDUg==",
+      "dependencies": {
+        "load-script": "^1.0.0"
+      }
+    },
+    "node_modules/fb-watchman": {
+      "version": "2.0.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/fb-watchman/-/fb-watchman-2.0.2.tgz",
+      "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==",
+      "peer": true,
+      "dependencies": {
+        "bser": "2.1.1"
+      }
+    },
+    "node_modules/fill-range": {
+      "version": "7.1.1",
+      "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.1.1.tgz",
+      "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+      "license": "MIT",
+      "dependencies": {
+        "to-regex-range": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/finalhandler": {
+      "version": "1.1.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/finalhandler/-/finalhandler-1.1.2.tgz",
+      "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
+      "peer": true,
+      "dependencies": {
+        "debug": "2.6.9",
+        "encodeurl": "~1.0.2",
+        "escape-html": "~1.0.3",
+        "on-finished": "~2.3.0",
+        "parseurl": "~1.3.3",
+        "statuses": "~1.5.0",
+        "unpipe": "~1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/finalhandler/node_modules/debug": {
+      "version": "2.6.9",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-2.6.9.tgz",
+      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "peer": true,
+      "dependencies": {
+        "ms": "2.0.0"
+      }
+    },
+    "node_modules/finalhandler/node_modules/ms": {
+      "version": "2.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+      "peer": true
+    },
+    "node_modules/find-up": {
+      "version": "4.1.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/find-up/-/find-up-4.1.0.tgz",
+      "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+      "peer": true,
+      "dependencies": {
+        "locate-path": "^5.0.0",
+        "path-exists": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/flow-enums-runtime": {
+      "version": "0.0.6",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz",
+      "integrity": "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==",
+      "peer": true
+    },
+    "node_modules/fresh": {
+      "version": "0.5.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/fresh/-/fresh-0.5.2.tgz",
+      "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
+      "peer": true,
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/fs.realpath": {
+      "version": "1.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/fs.realpath/-/fs.realpath-1.0.0.tgz",
+      "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+      "peer": true
+    },
+    "node_modules/fsevents": {
+      "version": "2.3.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/fsevents/-/fsevents-2.3.3.tgz",
+      "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+      "hasInstallScript": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "peer": true,
+      "engines": {
+        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+      }
+    },
+    "node_modules/function-bind": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz",
+      "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/gensync": {
+      "version": "1.0.0-beta.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/gensync/-/gensync-1.0.0-beta.2.tgz",
+      "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+      "peer": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/get-caller-file": {
+      "version": "2.0.5",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/get-caller-file/-/get-caller-file-2.0.5.tgz",
+      "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+      "peer": true,
+      "engines": {
+        "node": "6.* || 8.* || >= 10.*"
+      }
+    },
+    "node_modules/get-package-type": {
+      "version": "0.1.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/get-package-type/-/get-package-type-0.1.0.tgz",
+      "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
+      "peer": true,
+      "engines": {
+        "node": ">=8.0.0"
+      }
+    },
+    "node_modules/giget": {
+      "version": "2.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/giget/-/giget-2.0.0.tgz",
+      "integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==",
+      "dependencies": {
+        "citty": "^0.1.6",
+        "consola": "^3.4.0",
+        "defu": "^6.1.4",
+        "node-fetch-native": "^1.6.6",
+        "nypm": "^0.6.0",
+        "pathe": "^2.0.3"
+      },
+      "bin": {
+        "giget": "dist/cli.mjs"
+      }
+    },
+    "node_modules/glob": {
+      "version": "7.2.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/glob/-/glob-7.2.3.tgz",
+      "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+      "deprecated": "Glob versions prior to v9 are no longer supported",
+      "peer": true,
+      "dependencies": {
+        "fs.realpath": "^1.0.0",
+        "inflight": "^1.0.4",
+        "inherits": "2",
+        "minimatch": "^3.1.1",
+        "once": "^1.3.0",
+        "path-is-absolute": "^1.0.0"
+      },
+      "engines": {
+        "node": "*"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/glob-to-regexp": {
+      "version": "0.4.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
+      "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
+      "dev": true,
+      "peer": true
+    },
+    "node_modules/globals": {
+      "version": "11.12.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/globals/-/globals-11.12.0.tgz",
+      "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+      "peer": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/good-listener": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmmirror.com/good-listener/-/good-listener-1.2.2.tgz",
+      "integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==",
+      "license": "MIT",
+      "dependencies": {
+        "delegate": "^3.1.2"
+      }
+    },
+    "node_modules/graceful-fs": {
+      "version": "4.2.11",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/graceful-fs/-/graceful-fs-4.2.11.tgz",
+      "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+      "peer": true
+    },
+    "node_modules/has-flag": {
+      "version": "4.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/has-flag/-/has-flag-4.0.0.tgz",
+      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+      "peer": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/hasown": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz",
+      "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+      "dependencies": {
+        "function-bind": "^1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/hermes-estree": {
+      "version": "0.25.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/hermes-estree/-/hermes-estree-0.25.1.tgz",
+      "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==",
+      "peer": true
+    },
+    "node_modules/hermes-parser": {
+      "version": "0.25.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/hermes-parser/-/hermes-parser-0.25.1.tgz",
+      "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==",
+      "peer": true,
+      "dependencies": {
+        "hermes-estree": "0.25.1"
+      }
+    },
+    "node_modules/hookable": {
+      "version": "5.5.3",
+      "resolved": "https://registry.npmmirror.com/hookable/-/hookable-5.5.3.tgz",
+      "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==",
+      "license": "MIT"
+    },
+    "node_modules/http-errors": {
+      "version": "2.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/http-errors/-/http-errors-2.0.0.tgz",
+      "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
+      "peer": true,
+      "dependencies": {
+        "depd": "2.0.0",
+        "inherits": "2.0.4",
+        "setprototypeof": "1.2.0",
+        "statuses": "2.0.1",
+        "toidentifier": "1.0.1"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/http-errors/node_modules/statuses": {
+      "version": "2.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/statuses/-/statuses-2.0.1.tgz",
+      "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
+      "peer": true,
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/https-proxy-agent": {
+      "version": "7.0.6",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
+      "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
+      "peer": true,
+      "dependencies": {
+        "agent-base": "^7.1.2",
+        "debug": "4"
+      },
+      "engines": {
+        "node": ">= 14"
+      }
+    },
+    "node_modules/ignore": {
+      "version": "7.0.5",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ignore/-/ignore-7.0.5.tgz",
+      "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
+      "engines": {
+        "node": ">= 4"
+      }
+    },
+    "node_modules/image-size": {
+      "version": "1.2.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/image-size/-/image-size-1.2.1.tgz",
+      "integrity": "sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw==",
+      "peer": true,
+      "dependencies": {
+        "queue": "6.0.2"
+      },
+      "bin": {
+        "image-size": "bin/image-size.js"
+      },
+      "engines": {
+        "node": ">=16.x"
+      }
+    },
+    "node_modules/immutable": {
+      "version": "5.0.3",
+      "resolved": "https://registry.npmmirror.com/immutable/-/immutable-5.0.3.tgz",
+      "integrity": "sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/import-fresh": {
+      "version": "2.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/import-fresh/-/import-fresh-2.0.0.tgz",
+      "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==",
+      "peer": true,
+      "dependencies": {
+        "caller-path": "^2.0.0",
+        "resolve-from": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/import-fresh/node_modules/resolve-from": {
+      "version": "3.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/resolve-from/-/resolve-from-3.0.0.tgz",
+      "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=",
+      "peer": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/imurmurhash": {
+      "version": "0.1.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/imurmurhash/-/imurmurhash-0.1.4.tgz",
+      "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+      "peer": true,
+      "engines": {
+        "node": ">=0.8.19"
+      }
+    },
+    "node_modules/inflight": {
+      "version": "1.0.6",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/inflight/-/inflight-1.0.6.tgz",
+      "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+      "peer": true,
+      "dependencies": {
+        "once": "^1.3.0",
+        "wrappy": "1"
+      }
+    },
+    "node_modules/inherits": {
+      "version": "2.0.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+      "peer": true
+    },
+    "node_modules/invariant": {
+      "version": "2.2.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/invariant/-/invariant-2.2.4.tgz",
+      "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
+      "peer": true,
+      "dependencies": {
+        "loose-envify": "^1.0.0"
+      }
+    },
+    "node_modules/is-arrayish": {
+      "version": "0.2.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/is-arrayish/-/is-arrayish-0.2.1.tgz",
+      "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+      "peer": true
+    },
+    "node_modules/is-core-module": {
+      "version": "2.16.1",
+      "resolved": "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.16.1.tgz",
+      "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
+      "dependencies": {
+        "hasown": "^2.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-directory": {
+      "version": "0.3.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/is-directory/-/is-directory-0.3.1.tgz",
+      "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=",
+      "peer": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-docker": {
+      "version": "2.2.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/is-docker/-/is-docker-2.2.1.tgz",
+      "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
+      "peer": true,
+      "bin": {
+        "is-docker": "cli.js"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/is-extglob": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz",
+      "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-fullwidth-code-point": {
+      "version": "3.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+      "peer": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/is-glob": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz",
+      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "is-extglob": "^2.1.1"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-number": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz",
+      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.12.0"
+      }
+    },
+    "node_modules/is-what": {
+      "version": "4.1.16",
+      "resolved": "https://registry.npmmirror.com/is-what/-/is-what-4.1.16.tgz",
+      "integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=12.13"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/mesqueeb"
+      }
+    },
+    "node_modules/is-wsl": {
+      "version": "2.2.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/is-wsl/-/is-wsl-2.2.0.tgz",
+      "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+      "peer": true,
+      "dependencies": {
+        "is-docker": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/istanbul-lib-coverage": {
+      "version": "3.2.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
+      "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==",
+      "peer": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/istanbul-lib-instrument": {
+      "version": "5.2.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz",
+      "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==",
+      "peer": true,
+      "dependencies": {
+        "@babel/core": "^7.12.3",
+        "@babel/parser": "^7.14.7",
+        "@istanbuljs/schema": "^0.1.2",
+        "istanbul-lib-coverage": "^3.2.0",
+        "semver": "^6.3.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/istanbul-lib-instrument/node_modules/semver": {
+      "version": "6.3.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-6.3.1.tgz",
+      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+      "peer": true,
+      "bin": {
+        "semver": "bin/semver.js"
+      }
+    },
+    "node_modules/jest-environment-node": {
+      "version": "29.7.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/jest-environment-node/-/jest-environment-node-29.7.0.tgz",
+      "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==",
+      "peer": true,
+      "dependencies": {
+        "@jest/environment": "^29.7.0",
+        "@jest/fake-timers": "^29.7.0",
+        "@jest/types": "^29.6.3",
+        "@types/node": "*",
+        "jest-mock": "^29.7.0",
+        "jest-util": "^29.7.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/jest-get-type": {
+      "version": "29.6.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/jest-get-type/-/jest-get-type-29.6.3.tgz",
+      "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==",
+      "peer": true,
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/jest-haste-map": {
+      "version": "29.7.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/jest-haste-map/-/jest-haste-map-29.7.0.tgz",
+      "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==",
+      "peer": true,
+      "dependencies": {
+        "@jest/types": "^29.6.3",
+        "@types/graceful-fs": "^4.1.3",
+        "@types/node": "*",
+        "anymatch": "^3.0.3",
+        "fb-watchman": "^2.0.0",
+        "graceful-fs": "^4.2.9",
+        "jest-regex-util": "^29.6.3",
+        "jest-util": "^29.7.0",
+        "jest-worker": "^29.7.0",
+        "micromatch": "^4.0.4",
+        "walker": "^1.0.8"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      },
+      "optionalDependencies": {
+        "fsevents": "^2.3.2"
+      }
+    },
+    "node_modules/jest-haste-map/node_modules/jest-worker": {
+      "version": "29.7.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/jest-worker/-/jest-worker-29.7.0.tgz",
+      "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==",
+      "peer": true,
+      "dependencies": {
+        "@types/node": "*",
+        "jest-util": "^29.7.0",
+        "merge-stream": "^2.0.0",
+        "supports-color": "^8.0.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/jest-message-util": {
+      "version": "29.7.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/jest-message-util/-/jest-message-util-29.7.0.tgz",
+      "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==",
+      "peer": true,
+      "dependencies": {
+        "@babel/code-frame": "^7.12.13",
+        "@jest/types": "^29.6.3",
+        "@types/stack-utils": "^2.0.0",
+        "chalk": "^4.0.0",
+        "graceful-fs": "^4.2.9",
+        "micromatch": "^4.0.4",
+        "pretty-format": "^29.7.0",
+        "slash": "^3.0.0",
+        "stack-utils": "^2.0.3"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/jest-mock": {
+      "version": "29.7.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/jest-mock/-/jest-mock-29.7.0.tgz",
+      "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==",
+      "peer": true,
+      "dependencies": {
+        "@jest/types": "^29.6.3",
+        "@types/node": "*",
+        "jest-util": "^29.7.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/jest-regex-util": {
+      "version": "29.6.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/jest-regex-util/-/jest-regex-util-29.6.3.tgz",
+      "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==",
+      "peer": true,
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/jest-util": {
+      "version": "29.7.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/jest-util/-/jest-util-29.7.0.tgz",
+      "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
+      "peer": true,
+      "dependencies": {
+        "@jest/types": "^29.6.3",
+        "@types/node": "*",
+        "chalk": "^4.0.0",
+        "ci-info": "^3.2.0",
+        "graceful-fs": "^4.2.9",
+        "picomatch": "^2.2.3"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/jest-validate": {
+      "version": "29.7.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/jest-validate/-/jest-validate-29.7.0.tgz",
+      "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==",
+      "peer": true,
+      "dependencies": {
+        "@jest/types": "^29.6.3",
+        "camelcase": "^6.2.0",
+        "chalk": "^4.0.0",
+        "jest-get-type": "^29.6.3",
+        "leven": "^3.1.0",
+        "pretty-format": "^29.7.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/jest-validate/node_modules/camelcase": {
+      "version": "6.3.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/camelcase/-/camelcase-6.3.0.tgz",
+      "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+      "peer": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/jest-worker": {
+      "version": "27.5.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/jest-worker/-/jest-worker-27.5.1.tgz",
+      "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "@types/node": "*",
+        "merge-stream": "^2.0.0",
+        "supports-color": "^8.0.0"
+      },
+      "engines": {
+        "node": ">= 10.13.0"
+      }
+    },
+    "node_modules/jiti": {
+      "version": "2.4.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/jiti/-/jiti-2.4.2.tgz",
+      "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==",
+      "bin": {
+        "jiti": "lib/jiti-cli.mjs"
+      }
+    },
+    "node_modules/jju": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmmirror.com/jju/-/jju-1.4.0.tgz",
+      "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA=="
+    },
+    "node_modules/js-tokens": {
+      "version": "9.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/js-tokens/-/js-tokens-9.0.1.tgz",
+      "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ=="
+    },
+    "node_modules/js-yaml": {
+      "version": "3.14.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/js-yaml/-/js-yaml-3.14.1.tgz",
+      "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+      "peer": true,
+      "dependencies": {
+        "argparse": "^1.0.7",
+        "esprima": "^4.0.0"
+      },
+      "bin": {
+        "js-yaml": "bin/js-yaml.js"
+      }
+    },
+    "node_modules/jsc-safe-url": {
+      "version": "0.2.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/jsc-safe-url/-/jsc-safe-url-0.2.4.tgz",
+      "integrity": "sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q==",
+      "peer": true
+    },
+    "node_modules/jsesc": {
+      "version": "3.1.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/jsesc/-/jsesc-3.1.0.tgz",
+      "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+      "peer": true,
+      "bin": {
+        "jsesc": "bin/jsesc"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/json-parse-better-errors": {
+      "version": "1.0.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+      "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
+      "peer": true
+    },
+    "node_modules/json-parse-even-better-errors": {
+      "version": "2.3.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+      "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+      "dev": true,
+      "peer": true
+    },
+    "node_modules/json-schema-traverse": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+      "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/json5": {
+      "version": "2.2.3",
+      "resolved": "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz",
+      "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+      "license": "MIT",
+      "bin": {
+        "json5": "lib/cli.js"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/klona": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmmirror.com/klona/-/klona-2.0.6.tgz",
+      "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/knitwork": {
+      "version": "1.2.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/knitwork/-/knitwork-1.2.0.tgz",
+      "integrity": "sha512-xYSH7AvuQ6nXkq42x0v5S8/Iry+cfulBz/DJQzhIyESdLD7425jXsPy4vn5cCXU+HhRN2kVw51Vd1K6/By4BQg=="
+    },
+    "node_modules/leven": {
+      "version": "3.1.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/leven/-/leven-3.1.0.tgz",
+      "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
+      "peer": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/lighthouse-logger": {
+      "version": "1.4.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz",
+      "integrity": "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==",
+      "peer": true,
+      "dependencies": {
+        "debug": "^2.6.9",
+        "marky": "^1.2.2"
+      }
+    },
+    "node_modules/lighthouse-logger/node_modules/debug": {
+      "version": "2.6.9",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-2.6.9.tgz",
+      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "peer": true,
+      "dependencies": {
+        "ms": "2.0.0"
+      }
+    },
+    "node_modules/lighthouse-logger/node_modules/ms": {
+      "version": "2.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+      "peer": true
+    },
+    "node_modules/load-script": {
+      "version": "1.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/load-script/-/load-script-1.0.0.tgz",
+      "integrity": "sha1-BJGTngvuVkPuSUp+PaPSuscMbKQ="
+    },
+    "node_modules/loader-runner": {
+      "version": "4.3.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/loader-runner/-/loader-runner-4.3.0.tgz",
+      "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==",
+      "dev": true,
+      "peer": true,
+      "engines": {
+        "node": ">=6.11.5"
+      }
+    },
+    "node_modules/loader-utils": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-2.0.4.tgz",
+      "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "big.js": "^5.2.2",
+        "emojis-list": "^3.0.0",
+        "json5": "^2.1.2"
+      },
+      "engines": {
+        "node": ">=8.9.0"
+      }
+    },
+    "node_modules/local-pkg": {
+      "version": "1.1.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/local-pkg/-/local-pkg-1.1.1.tgz",
+      "integrity": "sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg==",
+      "dependencies": {
+        "mlly": "^1.7.4",
+        "pkg-types": "^2.0.1",
+        "quansync": "^0.2.8"
+      },
+      "engines": {
+        "node": ">=14"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      }
+    },
+    "node_modules/locate-path": {
+      "version": "5.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/locate-path/-/locate-path-5.0.0.tgz",
+      "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+      "peer": true,
+      "dependencies": {
+        "p-locate": "^4.1.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/lodash.throttle": {
+      "version": "4.1.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
+      "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==",
+      "peer": true
+    },
+    "node_modules/loose-envify": {
+      "version": "1.4.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/loose-envify/-/loose-envify-1.4.0.tgz",
+      "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+      "peer": true,
+      "dependencies": {
+        "js-tokens": "^3.0.0 || ^4.0.0"
+      },
+      "bin": {
+        "loose-envify": "cli.js"
+      }
+    },
+    "node_modules/loose-envify/node_modules/js-tokens": {
+      "version": "4.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/js-tokens/-/js-tokens-4.0.0.tgz",
+      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+      "peer": true
+    },
+    "node_modules/lru-cache": {
+      "version": "5.1.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/lru-cache/-/lru-cache-5.1.1.tgz",
+      "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+      "peer": true,
+      "dependencies": {
+        "yallist": "^3.0.2"
+      }
+    },
+    "node_modules/magic-string": {
+      "version": "0.30.17",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/magic-string/-/magic-string-0.30.17.tgz",
+      "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
+      "dependencies": {
+        "@jridgewell/sourcemap-codec": "^1.5.0"
+      }
+    },
+    "node_modules/makeerror": {
+      "version": "1.0.12",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/makeerror/-/makeerror-1.0.12.tgz",
+      "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==",
+      "peer": true,
+      "dependencies": {
+        "tmpl": "1.0.5"
+      }
+    },
+    "node_modules/marky": {
+      "version": "1.3.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/marky/-/marky-1.3.0.tgz",
+      "integrity": "sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ==",
+      "peer": true
+    },
+    "node_modules/memoize-one": {
+      "version": "5.2.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/memoize-one/-/memoize-one-5.2.1.tgz",
+      "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==",
+      "peer": true
+    },
+    "node_modules/merge-stream": {
+      "version": "2.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/merge-stream/-/merge-stream-2.0.0.tgz",
+      "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+      "peer": true
+    },
+    "node_modules/metro": {
+      "version": "0.82.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/metro/-/metro-0.82.4.tgz",
+      "integrity": "sha512-/gFmw3ux9CPG5WUmygY35hpyno28zi/7OUn6+OFfbweA8l0B+PPqXXLr0/T6cf5nclCcH0d22o+02fICaShVxw==",
+      "peer": true,
+      "dependencies": {
+        "@babel/code-frame": "^7.24.7",
+        "@babel/core": "^7.25.2",
+        "@babel/generator": "^7.25.0",
+        "@babel/parser": "^7.25.3",
+        "@babel/template": "^7.25.0",
+        "@babel/traverse": "^7.25.3",
+        "@babel/types": "^7.25.2",
+        "accepts": "^1.3.7",
+        "chalk": "^4.0.0",
+        "ci-info": "^2.0.0",
+        "connect": "^3.6.5",
+        "debug": "^4.4.0",
+        "error-stack-parser": "^2.0.6",
+        "flow-enums-runtime": "^0.0.6",
+        "graceful-fs": "^4.2.4",
+        "hermes-parser": "0.28.1",
+        "image-size": "^1.0.2",
+        "invariant": "^2.2.4",
+        "jest-worker": "^29.7.0",
+        "jsc-safe-url": "^0.2.2",
+        "lodash.throttle": "^4.1.1",
+        "metro-babel-transformer": "0.82.4",
+        "metro-cache": "0.82.4",
+        "metro-cache-key": "0.82.4",
+        "metro-config": "0.82.4",
+        "metro-core": "0.82.4",
+        "metro-file-map": "0.82.4",
+        "metro-resolver": "0.82.4",
+        "metro-runtime": "0.82.4",
+        "metro-source-map": "0.82.4",
+        "metro-symbolicate": "0.82.4",
+        "metro-transform-plugins": "0.82.4",
+        "metro-transform-worker": "0.82.4",
+        "mime-types": "^2.1.27",
+        "nullthrows": "^1.1.1",
+        "serialize-error": "^2.1.0",
+        "source-map": "^0.5.6",
+        "throat": "^5.0.0",
+        "ws": "^7.5.10",
+        "yargs": "^17.6.2"
+      },
+      "bin": {
+        "metro": "src/cli.js"
+      },
+      "engines": {
+        "node": ">=18.18"
+      }
+    },
+    "node_modules/metro-babel-transformer": {
+      "version": "0.82.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/metro-babel-transformer/-/metro-babel-transformer-0.82.4.tgz",
+      "integrity": "sha512-4juJahGRb1gmNbQq48lNinB6WFNfb6m0BQqi/RQibEltNiqTCxew/dBspI2EWA4xVCd3mQWGfw0TML4KurQZnQ==",
+      "peer": true,
+      "dependencies": {
+        "@babel/core": "^7.25.2",
+        "flow-enums-runtime": "^0.0.6",
+        "hermes-parser": "0.28.1",
+        "nullthrows": "^1.1.1"
+      },
+      "engines": {
+        "node": ">=18.18"
+      }
+    },
+    "node_modules/metro-babel-transformer/node_modules/hermes-estree": {
+      "version": "0.28.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/hermes-estree/-/hermes-estree-0.28.1.tgz",
+      "integrity": "sha512-w3nxl/RGM7LBae0v8LH2o36+8VqwOZGv9rX1wyoWT6YaKZLqpJZ0YQ5P0LVr3tuRpf7vCx0iIG4i/VmBJejxTQ==",
+      "peer": true
+    },
+    "node_modules/metro-babel-transformer/node_modules/hermes-parser": {
+      "version": "0.28.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/hermes-parser/-/hermes-parser-0.28.1.tgz",
+      "integrity": "sha512-nf8o+hE8g7UJWParnccljHumE9Vlq8F7MqIdeahl+4x0tvCUJYRrT0L7h0MMg/X9YJmkNwsfbaNNrzPtFXOscg==",
+      "peer": true,
+      "dependencies": {
+        "hermes-estree": "0.28.1"
+      }
+    },
+    "node_modules/metro-cache": {
+      "version": "0.82.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/metro-cache/-/metro-cache-0.82.4.tgz",
+      "integrity": "sha512-vX0ylSMGtORKiZ4G8uP6fgfPdDiCWvLZUGZ5zIblSGylOX6JYhvExl0Zg4UA9pix/SSQu5Pnp9vdODMFsNIxhw==",
+      "peer": true,
+      "dependencies": {
+        "exponential-backoff": "^3.1.1",
+        "flow-enums-runtime": "^0.0.6",
+        "https-proxy-agent": "^7.0.5",
+        "metro-core": "0.82.4"
+      },
+      "engines": {
+        "node": ">=18.18"
+      }
+    },
+    "node_modules/metro-cache-key": {
+      "version": "0.82.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/metro-cache-key/-/metro-cache-key-0.82.4.tgz",
+      "integrity": "sha512-2JCTqcpF+f2OghOpe/+x+JywfzDkrHdAqinPFWmK2ezNAU/qX0jBFaTETogPibFivxZJil37w9Yp6syX8rFUng==",
+      "peer": true,
+      "dependencies": {
+        "flow-enums-runtime": "^0.0.6"
+      },
+      "engines": {
+        "node": ">=18.18"
+      }
+    },
+    "node_modules/metro-config": {
+      "version": "0.82.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/metro-config/-/metro-config-0.82.4.tgz",
+      "integrity": "sha512-Ki3Wumr3hKHGDS7RrHsygmmRNc/PCJrvkLn0+BWWxmbOmOcMMJDSmSI+WRlT8jd5VPZFxIi4wg+sAt5yBXAK0g==",
+      "peer": true,
+      "dependencies": {
+        "connect": "^3.6.5",
+        "cosmiconfig": "^5.0.5",
+        "flow-enums-runtime": "^0.0.6",
+        "jest-validate": "^29.7.0",
+        "metro": "0.82.4",
+        "metro-cache": "0.82.4",
+        "metro-core": "0.82.4",
+        "metro-runtime": "0.82.4"
+      },
+      "engines": {
+        "node": ">=18.18"
+      }
+    },
+    "node_modules/metro-core": {
+      "version": "0.82.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/metro-core/-/metro-core-0.82.4.tgz",
+      "integrity": "sha512-Xo4ozbxPg2vfgJGCgXZ8sVhC2M0lhTqD+tsKO2q9aelq/dCjnnSb26xZKcQO80CQOQUL7e3QWB7pLFGPjZm31A==",
+      "peer": true,
+      "dependencies": {
+        "flow-enums-runtime": "^0.0.6",
+        "lodash.throttle": "^4.1.1",
+        "metro-resolver": "0.82.4"
+      },
+      "engines": {
+        "node": ">=18.18"
+      }
+    },
+    "node_modules/metro-file-map": {
+      "version": "0.82.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/metro-file-map/-/metro-file-map-0.82.4.tgz",
+      "integrity": "sha512-eO7HD1O3aeNsbEe6NBZvx1lLJUrxgyATjnDmb7bm4eyF6yWOQot9XVtxTDLNifECuvsZ4jzRiTInrbmIHkTdGA==",
+      "peer": true,
+      "dependencies": {
+        "debug": "^4.4.0",
+        "fb-watchman": "^2.0.0",
+        "flow-enums-runtime": "^0.0.6",
+        "graceful-fs": "^4.2.4",
+        "invariant": "^2.2.4",
+        "jest-worker": "^29.7.0",
+        "micromatch": "^4.0.4",
+        "nullthrows": "^1.1.1",
+        "walker": "^1.0.7"
+      },
+      "engines": {
+        "node": ">=18.18"
+      }
+    },
+    "node_modules/metro-file-map/node_modules/jest-worker": {
+      "version": "29.7.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/jest-worker/-/jest-worker-29.7.0.tgz",
+      "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==",
+      "peer": true,
+      "dependencies": {
+        "@types/node": "*",
+        "jest-util": "^29.7.0",
+        "merge-stream": "^2.0.0",
+        "supports-color": "^8.0.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/metro-minify-terser": {
+      "version": "0.82.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/metro-minify-terser/-/metro-minify-terser-0.82.4.tgz",
+      "integrity": "sha512-W79Mi6BUwWVaM8Mc5XepcqkG+TSsCyyo//dmTsgYfJcsmReQorRFodil3bbJInETvjzdnS1mCsUo9pllNjT1Hg==",
+      "peer": true,
+      "dependencies": {
+        "flow-enums-runtime": "^0.0.6",
+        "terser": "^5.15.0"
+      },
+      "engines": {
+        "node": ">=18.18"
+      }
+    },
+    "node_modules/metro-resolver": {
+      "version": "0.82.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/metro-resolver/-/metro-resolver-0.82.4.tgz",
+      "integrity": "sha512-uWoHzOBGQTPT5PjippB8rRT3iI9CTgFA9tRiLMzrseA5o7YAlgvfTdY9vFk2qyk3lW3aQfFKWkmqENryPRpu+Q==",
+      "peer": true,
+      "dependencies": {
+        "flow-enums-runtime": "^0.0.6"
+      },
+      "engines": {
+        "node": ">=18.18"
+      }
+    },
+    "node_modules/metro-runtime": {
+      "version": "0.82.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/metro-runtime/-/metro-runtime-0.82.4.tgz",
+      "integrity": "sha512-vVyFO7H+eLXRV2E7YAUYA7aMGBECGagqxmFvC2hmErS7oq90BbPVENfAHbUWq1vWH+MRiivoRxdxlN8gBoF/dw==",
+      "peer": true,
+      "dependencies": {
+        "@babel/runtime": "^7.25.0",
+        "flow-enums-runtime": "^0.0.6"
+      },
+      "engines": {
+        "node": ">=18.18"
+      }
+    },
+    "node_modules/metro-source-map": {
+      "version": "0.82.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/metro-source-map/-/metro-source-map-0.82.4.tgz",
+      "integrity": "sha512-9jzDQJ0FPas1FuQFtwmBHsez2BfhFNufMowbOMeG3ZaFvzeziE8A0aJwILDS3U+V5039ssCQFiQeqDgENWvquA==",
+      "peer": true,
+      "dependencies": {
+        "@babel/traverse": "^7.25.3",
+        "@babel/traverse--for-generate-function-map": "npm:@babel/traverse@^7.25.3",
+        "@babel/types": "^7.25.2",
+        "flow-enums-runtime": "^0.0.6",
+        "invariant": "^2.2.4",
+        "metro-symbolicate": "0.82.4",
+        "nullthrows": "^1.1.1",
+        "ob1": "0.82.4",
+        "source-map": "^0.5.6",
+        "vlq": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=18.18"
+      }
+    },
+    "node_modules/metro-source-map/node_modules/source-map": {
+      "version": "0.5.7",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/source-map/-/source-map-0.5.7.tgz",
+      "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
+      "peer": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/metro-symbolicate": {
+      "version": "0.82.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/metro-symbolicate/-/metro-symbolicate-0.82.4.tgz",
+      "integrity": "sha512-LwEwAtdsx7z8rYjxjpLWxuFa2U0J6TS6ljlQM4WAATKa4uzV8unmnRuN2iNBWTmRqgNR77mzmI2vhwD4QSCo+w==",
+      "peer": true,
+      "dependencies": {
+        "flow-enums-runtime": "^0.0.6",
+        "invariant": "^2.2.4",
+        "metro-source-map": "0.82.4",
+        "nullthrows": "^1.1.1",
+        "source-map": "^0.5.6",
+        "vlq": "^1.0.0"
+      },
+      "bin": {
+        "metro-symbolicate": "src/index.js"
+      },
+      "engines": {
+        "node": ">=18.18"
+      }
+    },
+    "node_modules/metro-symbolicate/node_modules/source-map": {
+      "version": "0.5.7",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/source-map/-/source-map-0.5.7.tgz",
+      "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
+      "peer": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/metro-transform-plugins": {
+      "version": "0.82.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/metro-transform-plugins/-/metro-transform-plugins-0.82.4.tgz",
+      "integrity": "sha512-NoWQRPHupVpnDgYguiEcm7YwDhnqW02iWWQjO2O8NsNP09rEMSq99nPjARWfukN7+KDh6YjLvTIN20mj3dk9kw==",
+      "peer": true,
+      "dependencies": {
+        "@babel/core": "^7.25.2",
+        "@babel/generator": "^7.25.0",
+        "@babel/template": "^7.25.0",
+        "@babel/traverse": "^7.25.3",
+        "flow-enums-runtime": "^0.0.6",
+        "nullthrows": "^1.1.1"
+      },
+      "engines": {
+        "node": ">=18.18"
+      }
+    },
+    "node_modules/metro-transform-worker": {
+      "version": "0.82.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/metro-transform-worker/-/metro-transform-worker-0.82.4.tgz",
+      "integrity": "sha512-kPI7Ad/tdAnI9PY4T+2H0cdgGeSWWdiPRKuytI806UcN4VhFL6OmYa19/4abYVYF+Cd2jo57CDuwbaxRfmXDhw==",
+      "peer": true,
+      "dependencies": {
+        "@babel/core": "^7.25.2",
+        "@babel/generator": "^7.25.0",
+        "@babel/parser": "^7.25.3",
+        "@babel/types": "^7.25.2",
+        "flow-enums-runtime": "^0.0.6",
+        "metro": "0.82.4",
+        "metro-babel-transformer": "0.82.4",
+        "metro-cache": "0.82.4",
+        "metro-cache-key": "0.82.4",
+        "metro-minify-terser": "0.82.4",
+        "metro-source-map": "0.82.4",
+        "metro-transform-plugins": "0.82.4",
+        "nullthrows": "^1.1.1"
+      },
+      "engines": {
+        "node": ">=18.18"
+      }
+    },
+    "node_modules/metro/node_modules/ci-info": {
+      "version": "2.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ci-info/-/ci-info-2.0.0.tgz",
+      "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
+      "peer": true
+    },
+    "node_modules/metro/node_modules/hermes-estree": {
+      "version": "0.28.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/hermes-estree/-/hermes-estree-0.28.1.tgz",
+      "integrity": "sha512-w3nxl/RGM7LBae0v8LH2o36+8VqwOZGv9rX1wyoWT6YaKZLqpJZ0YQ5P0LVr3tuRpf7vCx0iIG4i/VmBJejxTQ==",
+      "peer": true
+    },
+    "node_modules/metro/node_modules/hermes-parser": {
+      "version": "0.28.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/hermes-parser/-/hermes-parser-0.28.1.tgz",
+      "integrity": "sha512-nf8o+hE8g7UJWParnccljHumE9Vlq8F7MqIdeahl+4x0tvCUJYRrT0L7h0MMg/X9YJmkNwsfbaNNrzPtFXOscg==",
+      "peer": true,
+      "dependencies": {
+        "hermes-estree": "0.28.1"
+      }
+    },
+    "node_modules/metro/node_modules/jest-worker": {
+      "version": "29.7.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/jest-worker/-/jest-worker-29.7.0.tgz",
+      "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==",
+      "peer": true,
+      "dependencies": {
+        "@types/node": "*",
+        "jest-util": "^29.7.0",
+        "merge-stream": "^2.0.0",
+        "supports-color": "^8.0.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/metro/node_modules/source-map": {
+      "version": "0.5.7",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/source-map/-/source-map-0.5.7.tgz",
+      "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
+      "peer": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/metro/node_modules/ws": {
+      "version": "7.5.10",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ws/-/ws-7.5.10.tgz",
+      "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
+      "peer": true,
+      "engines": {
+        "node": ">=8.3.0"
+      },
+      "peerDependencies": {
+        "bufferutil": "^4.0.1",
+        "utf-8-validate": "^5.0.2"
+      },
+      "peerDependenciesMeta": {
+        "bufferutil": {
+          "optional": true
+        },
+        "utf-8-validate": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/micromatch": {
+      "version": "4.0.8",
+      "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.8.tgz",
+      "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+      "license": "MIT",
+      "dependencies": {
+        "braces": "^3.0.3",
+        "picomatch": "^2.3.1"
+      },
+      "engines": {
+        "node": ">=8.6"
+      }
+    },
+    "node_modules/mime": {
+      "version": "1.6.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/mime/-/mime-1.6.0.tgz",
+      "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+      "peer": true,
+      "bin": {
+        "mime": "cli.js"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/mime-db": {
+      "version": "1.52.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/mime-db/-/mime-db-1.52.0.tgz",
+      "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+      "peer": true,
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/mime-types": {
+      "version": "2.1.35",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/mime-types/-/mime-types-2.1.35.tgz",
+      "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+      "peer": true,
+      "dependencies": {
+        "mime-db": "1.52.0"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/minimatch": {
+      "version": "3.1.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/minimatch/-/minimatch-3.1.2.tgz",
+      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+      "peer": true,
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/mitt": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmmirror.com/mitt/-/mitt-3.0.1.tgz",
+      "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==",
+      "license": "MIT"
+    },
+    "node_modules/mkdirp": {
+      "version": "1.0.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/mkdirp/-/mkdirp-1.0.4.tgz",
+      "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+      "peer": true,
+      "bin": {
+        "mkdirp": "bin/cmd.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/mlly": {
+      "version": "1.7.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/mlly/-/mlly-1.7.4.tgz",
+      "integrity": "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==",
+      "dependencies": {
+        "acorn": "^8.14.0",
+        "pathe": "^2.0.1",
+        "pkg-types": "^1.3.0",
+        "ufo": "^1.5.4"
+      }
+    },
+    "node_modules/mlly/node_modules/confbox": {
+      "version": "0.1.8",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/confbox/-/confbox-0.1.8.tgz",
+      "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="
+    },
+    "node_modules/mlly/node_modules/pkg-types": {
+      "version": "1.3.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/pkg-types/-/pkg-types-1.3.1.tgz",
+      "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==",
+      "dependencies": {
+        "confbox": "^0.1.8",
+        "mlly": "^1.7.4",
+        "pathe": "^2.0.1"
+      }
+    },
+    "node_modules/ms": {
+      "version": "2.1.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.1.3.tgz",
+      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+      "peer": true
+    },
+    "node_modules/nanoid": {
+      "version": "3.3.11",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/nanoid/-/nanoid-3.3.11.tgz",
+      "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "peer": true,
+      "bin": {
+        "nanoid": "bin/nanoid.cjs"
+      },
+      "engines": {
+        "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+      }
+    },
+    "node_modules/negotiator": {
+      "version": "0.6.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/negotiator/-/negotiator-0.6.3.tgz",
+      "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+      "peer": true,
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/neo-async": {
+      "version": "2.6.2",
+      "resolved": "https://registry.npmmirror.com/neo-async/-/neo-async-2.6.2.tgz",
+      "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/node-addon-api": {
+      "version": "7.1.1",
+      "resolved": "https://registry.npmmirror.com/node-addon-api/-/node-addon-api-7.1.1.tgz",
+      "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
+      "dev": true,
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/node-fetch-native": {
+      "version": "1.6.6",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/node-fetch-native/-/node-fetch-native-1.6.6.tgz",
+      "integrity": "sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ=="
+    },
+    "node_modules/node-int64": {
+      "version": "0.4.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/node-int64/-/node-int64-0.4.0.tgz",
+      "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=",
+      "peer": true
+    },
+    "node_modules/node-releases": {
+      "version": "2.0.19",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/node-releases/-/node-releases-2.0.19.tgz",
+      "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==",
+      "peer": true
+    },
+    "node_modules/normalize-path": {
+      "version": "3.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/normalize-path/-/normalize-path-3.0.0.tgz",
+      "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+      "peer": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/nullthrows": {
+      "version": "1.1.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/nullthrows/-/nullthrows-1.1.1.tgz",
+      "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==",
+      "peer": true
+    },
+    "node_modules/nypm": {
+      "version": "0.6.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/nypm/-/nypm-0.6.0.tgz",
+      "integrity": "sha512-mn8wBFV9G9+UFHIrq+pZ2r2zL4aPau/by3kJb3cM7+5tQHMt6HGQB8FDIeKFYp8o0D2pnH6nVsO88N4AmUxIWg==",
+      "dependencies": {
+        "citty": "^0.1.6",
+        "consola": "^3.4.0",
+        "pathe": "^2.0.3",
+        "pkg-types": "^2.0.0",
+        "tinyexec": "^0.3.2"
+      },
+      "bin": {
+        "nypm": "dist/cli.mjs"
+      },
+      "engines": {
+        "node": "^14.16.0 || >=16.10.0"
+      }
+    },
+    "node_modules/ob1": {
+      "version": "0.82.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ob1/-/ob1-0.82.4.tgz",
+      "integrity": "sha512-n9S8e4l5TvkrequEAMDidl4yXesruWTNTzVkeaHSGywoTOIwTzZzKw7Z670H3eaXDZui5MJXjWGNzYowVZIxCA==",
+      "peer": true,
+      "dependencies": {
+        "flow-enums-runtime": "^0.0.6"
+      },
+      "engines": {
+        "node": ">=18.18"
+      }
+    },
+    "node_modules/ohash": {
+      "version": "2.0.11",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ohash/-/ohash-2.0.11.tgz",
+      "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ=="
+    },
+    "node_modules/on-finished": {
+      "version": "2.3.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/on-finished/-/on-finished-2.3.0.tgz",
+      "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==",
+      "peer": true,
+      "dependencies": {
+        "ee-first": "1.1.1"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/once": {
+      "version": "1.4.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/once/-/once-1.4.0.tgz",
+      "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+      "peer": true,
+      "dependencies": {
+        "wrappy": "1"
+      }
+    },
+    "node_modules/open": {
+      "version": "7.4.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/open/-/open-7.4.2.tgz",
+      "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==",
+      "peer": true,
+      "dependencies": {
+        "is-docker": "^2.0.0",
+        "is-wsl": "^2.1.1"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/p-limit": {
+      "version": "2.3.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/p-limit/-/p-limit-2.3.0.tgz",
+      "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+      "peer": true,
+      "dependencies": {
+        "p-try": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/p-locate": {
+      "version": "4.1.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/p-locate/-/p-locate-4.1.0.tgz",
+      "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+      "peer": true,
+      "dependencies": {
+        "p-limit": "^2.2.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/p-try": {
+      "version": "2.2.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/p-try/-/p-try-2.2.0.tgz",
+      "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+      "peer": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/parse-json": {
+      "version": "4.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/parse-json/-/parse-json-4.0.0.tgz",
+      "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==",
+      "peer": true,
+      "dependencies": {
+        "error-ex": "^1.3.1",
+        "json-parse-better-errors": "^1.0.1"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/parseurl": {
+      "version": "1.3.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/parseurl/-/parseurl-1.3.3.tgz",
+      "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+      "peer": true,
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/path-exists": {
+      "version": "4.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/path-exists/-/path-exists-4.0.0.tgz",
+      "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+      "peer": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/path-is-absolute": {
+      "version": "1.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+      "peer": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/path-parse": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz",
+      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
+    },
+    "node_modules/pathe": {
+      "version": "2.0.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/pathe/-/pathe-2.0.3.tgz",
+      "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="
+    },
+    "node_modules/perfect-debounce": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/perfect-debounce/-/perfect-debounce-1.0.0.tgz",
+      "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==",
+      "license": "MIT"
+    },
+    "node_modules/picocolors": {
+      "version": "1.1.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/picocolors/-/picocolors-1.1.1.tgz",
+      "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+      "peer": true
+    },
+    "node_modules/picomatch": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz",
+      "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=8.6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert"
+      }
+    },
+    "node_modules/pinia": {
+      "version": "3.0.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/pinia/-/pinia-3.0.2.tgz",
+      "integrity": "sha512-sH2JK3wNY809JOeiiURUR0wehJ9/gd9qFN2Y828jCbxEzKEmEt0pzCXwqiSTfuRsK9vQsOflSdnbdBOGrhtn+g==",
+      "dependencies": {
+        "@vue/devtools-api": "^7.7.2"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/posva"
+      },
+      "peerDependencies": {
+        "typescript": ">=4.4.4",
+        "vue": "^2.7.0 || ^3.5.11"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/pinia-plugin-persistedstate": {
+      "version": "4.3.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/pinia-plugin-persistedstate/-/pinia-plugin-persistedstate-4.3.0.tgz",
+      "integrity": "sha512-x9wxpHj6iFDj5ITQJ3rj6+KesEqyRk/vqcE3WE+VGfetleV9Zufqwa9qJ6AkA5wmRSQEp7BTA1us/MDVTRHFFw==",
+      "dependencies": {
+        "@nuxt/kit": "^3.17.2",
+        "deep-pick-omit": "^1.2.1",
+        "defu": "^6.1.4",
+        "destr": "^2.0.5"
+      },
+      "peerDependencies": {
+        "@pinia/nuxt": ">=0.10.0",
+        "pinia": ">=3.0.0"
+      },
+      "peerDependenciesMeta": {
+        "@pinia/nuxt": {
+          "optional": true
+        },
+        "pinia": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/pirates": {
+      "version": "4.0.7",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/pirates/-/pirates-4.0.7.tgz",
+      "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==",
+      "peer": true,
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/pkg-types": {
+      "version": "2.1.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/pkg-types/-/pkg-types-2.1.0.tgz",
+      "integrity": "sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A==",
+      "dependencies": {
+        "confbox": "^0.2.1",
+        "exsolve": "^1.0.1",
+        "pathe": "^2.0.3"
+      }
+    },
+    "node_modules/postcss": {
+      "version": "8.5.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/postcss/-/postcss-8.5.4.tgz",
+      "integrity": "sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w==",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/postcss/"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/postcss"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "peer": true,
+      "dependencies": {
+        "nanoid": "^3.3.11",
+        "picocolors": "^1.1.1",
+        "source-map-js": "^1.2.1"
+      },
+      "engines": {
+        "node": "^10 || ^12 || >=14"
+      }
+    },
+    "node_modules/pretty-format": {
+      "version": "29.7.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/pretty-format/-/pretty-format-29.7.0.tgz",
+      "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+      "peer": true,
+      "dependencies": {
+        "@jest/schemas": "^29.6.3",
+        "ansi-styles": "^5.0.0",
+        "react-is": "^18.0.0"
+      },
+      "engines": {
+        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+      }
+    },
+    "node_modules/pretty-format/node_modules/ansi-styles": {
+      "version": "5.2.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-styles/-/ansi-styles-5.2.0.tgz",
+      "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+      "peer": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+      }
+    },
+    "node_modules/promise": {
+      "version": "8.3.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/promise/-/promise-8.3.0.tgz",
+      "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==",
+      "peer": true,
+      "dependencies": {
+        "asap": "~2.0.6"
+      }
+    },
+    "node_modules/punycode": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz",
+      "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/quansync": {
+      "version": "0.2.10",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/quansync/-/quansync-0.2.10.tgz",
+      "integrity": "sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A==",
+      "funding": [
+        {
+          "type": "individual",
+          "url": "https://github.com/sponsors/antfu"
+        },
+        {
+          "type": "individual",
+          "url": "https://github.com/sponsors/sxzz"
+        }
+      ]
+    },
+    "node_modules/queue": {
+      "version": "6.0.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/queue/-/queue-6.0.2.tgz",
+      "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==",
+      "peer": true,
+      "dependencies": {
+        "inherits": "~2.0.3"
+      }
+    },
+    "node_modules/randombytes": {
+      "version": "2.1.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/randombytes/-/randombytes-2.1.0.tgz",
+      "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "safe-buffer": "^5.1.0"
+      }
+    },
+    "node_modules/range-parser": {
+      "version": "1.2.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/range-parser/-/range-parser-1.2.1.tgz",
+      "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+      "peer": true,
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/rc9": {
+      "version": "2.1.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/rc9/-/rc9-2.1.2.tgz",
+      "integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==",
+      "dependencies": {
+        "defu": "^6.1.4",
+        "destr": "^2.0.3"
+      }
+    },
+    "node_modules/react": {
+      "version": "19.1.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/react/-/react-19.1.0.tgz",
+      "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
+      "peer": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/react-devtools-core": {
+      "version": "6.1.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/react-devtools-core/-/react-devtools-core-6.1.2.tgz",
+      "integrity": "sha512-ldFwzufLletzCikNJVYaxlxMLu7swJ3T2VrGfzXlMsVhZhPDKXA38DEROidaYZVgMAmQnIjymrmqto5pyfrwPA==",
+      "peer": true,
+      "dependencies": {
+        "shell-quote": "^1.6.1",
+        "ws": "^7"
+      }
+    },
+    "node_modules/react-devtools-core/node_modules/ws": {
+      "version": "7.5.10",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ws/-/ws-7.5.10.tgz",
+      "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
+      "peer": true,
+      "engines": {
+        "node": ">=8.3.0"
+      },
+      "peerDependencies": {
+        "bufferutil": "^4.0.1",
+        "utf-8-validate": "^5.0.2"
+      },
+      "peerDependenciesMeta": {
+        "bufferutil": {
+          "optional": true
+        },
+        "utf-8-validate": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/react-is": {
+      "version": "18.3.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/react-is/-/react-is-18.3.1.tgz",
+      "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
+      "peer": true
+    },
+    "node_modules/react-native": {
+      "version": "0.79.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/react-native/-/react-native-0.79.3.tgz",
+      "integrity": "sha512-EzH1+9gzdyEo9zdP6u7Sh3Jtf5EOMwzy+TK65JysdlgAzfEVfq4mNeXcAZ6SmD+CW6M7ARJbvXLyTD0l2S5rpg==",
+      "peer": true,
+      "dependencies": {
+        "@jest/create-cache-key-function": "^29.7.0",
+        "@react-native/assets-registry": "0.79.3",
+        "@react-native/codegen": "0.79.3",
+        "@react-native/community-cli-plugin": "0.79.3",
+        "@react-native/gradle-plugin": "0.79.3",
+        "@react-native/js-polyfills": "0.79.3",
+        "@react-native/normalize-colors": "0.79.3",
+        "@react-native/virtualized-lists": "0.79.3",
+        "abort-controller": "^3.0.0",
+        "anser": "^1.4.9",
+        "ansi-regex": "^5.0.0",
+        "babel-jest": "^29.7.0",
+        "babel-plugin-syntax-hermes-parser": "0.25.1",
+        "base64-js": "^1.5.1",
+        "chalk": "^4.0.0",
+        "commander": "^12.0.0",
+        "event-target-shim": "^5.0.1",
+        "flow-enums-runtime": "^0.0.6",
+        "glob": "^7.1.1",
+        "invariant": "^2.2.4",
+        "jest-environment-node": "^29.7.0",
+        "memoize-one": "^5.0.0",
+        "metro-runtime": "^0.82.0",
+        "metro-source-map": "^0.82.0",
+        "nullthrows": "^1.1.1",
+        "pretty-format": "^29.7.0",
+        "promise": "^8.3.0",
+        "react-devtools-core": "^6.1.1",
+        "react-refresh": "^0.14.0",
+        "regenerator-runtime": "^0.13.2",
+        "scheduler": "0.25.0",
+        "semver": "^7.1.3",
+        "stacktrace-parser": "^0.1.10",
+        "whatwg-fetch": "^3.0.0",
+        "ws": "^6.2.3",
+        "yargs": "^17.6.2"
+      },
+      "bin": {
+        "react-native": "cli.js"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "peerDependencies": {
+        "@types/react": "^19.0.0",
+        "react": "^19.0.0"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/react-native/node_modules/commander": {
+      "version": "12.1.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/commander/-/commander-12.1.0.tgz",
+      "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
+      "peer": true,
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/react-refresh": {
+      "version": "0.14.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/react-refresh/-/react-refresh-0.14.2.tgz",
+      "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==",
+      "peer": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/readdirp": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-4.1.2.tgz",
+      "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 14.18.0"
+      },
+      "funding": {
+        "type": "individual",
+        "url": "https://paulmillr.com/funding/"
+      }
+    },
+    "node_modules/regenerator-runtime": {
+      "version": "0.13.11",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
+      "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==",
+      "peer": true
+    },
+    "node_modules/require-directory": {
+      "version": "2.1.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/require-directory/-/require-directory-2.1.1.tgz",
+      "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
+      "peer": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/require-from-string": {
+      "version": "2.0.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/require-from-string/-/require-from-string-2.0.2.tgz",
+      "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/resolve": {
+      "version": "1.22.10",
+      "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.10.tgz",
+      "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==",
+      "dependencies": {
+        "is-core-module": "^2.16.0",
+        "path-parse": "^1.0.7",
+        "supports-preserve-symlinks-flag": "^1.0.0"
+      },
+      "bin": {
+        "resolve": "bin/resolve"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/resolve-from": {
+      "version": "5.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/resolve-from/-/resolve-from-5.0.0.tgz",
+      "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+      "peer": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/rfdc": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.4.1.tgz",
+      "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==",
+      "license": "MIT"
+    },
+    "node_modules/rimraf": {
+      "version": "3.0.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/rimraf/-/rimraf-3.0.2.tgz",
+      "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+      "peer": true,
+      "dependencies": {
+        "glob": "^7.1.3"
+      },
+      "bin": {
+        "rimraf": "bin.js"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/rxjs": {
+      "version": "7.8.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/rxjs/-/rxjs-7.8.2.tgz",
+      "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==",
+      "peer": true,
+      "dependencies": {
+        "tslib": "^2.1.0"
+      }
+    },
+    "node_modules/safe-buffer": {
+      "version": "5.2.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/safe-buffer/-/safe-buffer-5.2.1.tgz",
+      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ],
+      "peer": true
+    },
+    "node_modules/sass": {
+      "version": "1.85.1",
+      "resolved": "https://registry.npmmirror.com/sass/-/sass-1.85.1.tgz",
+      "integrity": "sha512-Uk8WpxM5v+0cMR0XjX9KfRIacmSG86RH4DCCZjLU2rFh5tyutt9siAXJ7G+YfxQ99Q6wrRMbMlVl6KqUms71ag==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "chokidar": "^4.0.0",
+        "immutable": "^5.0.2",
+        "source-map-js": ">=0.6.2 <2.0.0"
+      },
+      "bin": {
+        "sass": "sass.js"
+      },
+      "engines": {
+        "node": ">=14.0.0"
+      },
+      "optionalDependencies": {
+        "@parcel/watcher": "^2.4.1"
+      }
+    },
+    "node_modules/sass-loader": {
+      "version": "10.5.2",
+      "resolved": "https://registry.npmmirror.com/sass-loader/-/sass-loader-10.5.2.tgz",
+      "integrity": "sha512-vMUoSNOUKJILHpcNCCyD23X34gve1TS7Rjd9uXHeKqhvBG39x6XbswFDtpbTElj6XdMFezoWhkh5vtKudf2cgQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "klona": "^2.0.4",
+        "loader-utils": "^2.0.0",
+        "neo-async": "^2.6.2",
+        "schema-utils": "^3.0.0",
+        "semver": "^7.3.2"
+      },
+      "engines": {
+        "node": ">= 10.13.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      },
+      "peerDependencies": {
+        "fibers": ">= 3.1.0",
+        "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0",
+        "sass": "^1.3.0",
+        "webpack": "^4.36.0 || ^5.0.0"
+      },
+      "peerDependenciesMeta": {
+        "fibers": {
+          "optional": true
+        },
+        "node-sass": {
+          "optional": true
+        },
+        "sass": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/scheduler": {
+      "version": "0.25.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/scheduler/-/scheduler-0.25.0.tgz",
+      "integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==",
+      "peer": true
+    },
+    "node_modules/schema-utils": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-3.3.0.tgz",
+      "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@types/json-schema": "^7.0.8",
+        "ajv": "^6.12.5",
+        "ajv-keywords": "^3.5.2"
+      },
+      "engines": {
+        "node": ">= 10.13.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      }
+    },
+    "node_modules/scule": {
+      "version": "1.3.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/scule/-/scule-1.3.0.tgz",
+      "integrity": "sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g=="
+    },
+    "node_modules/select": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/select/-/select-1.1.2.tgz",
+      "integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==",
+      "license": "MIT"
+    },
+    "node_modules/semver": {
+      "version": "7.7.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-7.7.2.tgz",
+      "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
+      "bin": {
+        "semver": "bin/semver.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/send": {
+      "version": "0.19.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/send/-/send-0.19.0.tgz",
+      "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
+      "peer": true,
+      "dependencies": {
+        "debug": "2.6.9",
+        "depd": "2.0.0",
+        "destroy": "1.2.0",
+        "encodeurl": "~1.0.2",
+        "escape-html": "~1.0.3",
+        "etag": "~1.8.1",
+        "fresh": "0.5.2",
+        "http-errors": "2.0.0",
+        "mime": "1.6.0",
+        "ms": "2.1.3",
+        "on-finished": "2.4.1",
+        "range-parser": "~1.2.1",
+        "statuses": "2.0.1"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/send/node_modules/debug": {
+      "version": "2.6.9",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-2.6.9.tgz",
+      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "peer": true,
+      "dependencies": {
+        "ms": "2.0.0"
+      }
+    },
+    "node_modules/send/node_modules/debug/node_modules/ms": {
+      "version": "2.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+      "peer": true
+    },
+    "node_modules/send/node_modules/on-finished": {
+      "version": "2.4.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/on-finished/-/on-finished-2.4.1.tgz",
+      "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
+      "peer": true,
+      "dependencies": {
+        "ee-first": "1.1.1"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/send/node_modules/statuses": {
+      "version": "2.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/statuses/-/statuses-2.0.1.tgz",
+      "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
+      "peer": true,
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/serialize-error": {
+      "version": "2.1.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/serialize-error/-/serialize-error-2.1.0.tgz",
+      "integrity": "sha1-ULZ51WNc34Rme9yOWa9OW4HV9go=",
+      "peer": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/serialize-javascript": {
+      "version": "6.0.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
+      "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "randombytes": "^2.1.0"
+      }
+    },
+    "node_modules/serve-static": {
+      "version": "1.16.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/serve-static/-/serve-static-1.16.2.tgz",
+      "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
+      "peer": true,
+      "dependencies": {
+        "encodeurl": "~2.0.0",
+        "escape-html": "~1.0.3",
+        "parseurl": "~1.3.3",
+        "send": "0.19.0"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/serve-static/node_modules/encodeurl": {
+      "version": "2.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/encodeurl/-/encodeurl-2.0.0.tgz",
+      "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
+      "peer": true,
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/setprototypeof": {
+      "version": "1.2.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/setprototypeof/-/setprototypeof-1.2.0.tgz",
+      "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
+      "peer": true
+    },
+    "node_modules/shell-quote": {
+      "version": "1.8.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/shell-quote/-/shell-quote-1.8.3.tgz",
+      "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==",
+      "peer": true,
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/signal-exit": {
+      "version": "3.0.7",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/signal-exit/-/signal-exit-3.0.7.tgz",
+      "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+      "peer": true
+    },
+    "node_modules/slash": {
+      "version": "3.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/slash/-/slash-3.0.0.tgz",
+      "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+      "peer": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/source-map": {
+      "version": "0.6.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/source-map/-/source-map-0.6.1.tgz",
+      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+      "peer": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/source-map-js": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz",
+      "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+      "license": "BSD-3-Clause",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/source-map-support": {
+      "version": "0.5.21",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/source-map-support/-/source-map-support-0.5.21.tgz",
+      "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+      "peer": true,
+      "dependencies": {
+        "buffer-from": "^1.0.0",
+        "source-map": "^0.6.0"
+      }
+    },
+    "node_modules/speakingurl": {
+      "version": "14.0.1",
+      "resolved": "https://registry.npmmirror.com/speakingurl/-/speakingurl-14.0.1.tgz",
+      "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==",
+      "license": "BSD-3-Clause",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/sprintf-js": {
+      "version": "1.0.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/sprintf-js/-/sprintf-js-1.0.3.tgz",
+      "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
+      "peer": true
+    },
+    "node_modules/stack-utils": {
+      "version": "2.0.6",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/stack-utils/-/stack-utils-2.0.6.tgz",
+      "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==",
+      "peer": true,
+      "dependencies": {
+        "escape-string-regexp": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/stack-utils/node_modules/escape-string-regexp": {
+      "version": "2.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
+      "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
+      "peer": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/stackframe": {
+      "version": "1.3.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/stackframe/-/stackframe-1.3.4.tgz",
+      "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==",
+      "peer": true
+    },
+    "node_modules/stacktrace-parser": {
+      "version": "0.1.11",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/stacktrace-parser/-/stacktrace-parser-0.1.11.tgz",
+      "integrity": "sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==",
+      "peer": true,
+      "dependencies": {
+        "type-fest": "^0.7.1"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/statuses": {
+      "version": "1.5.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/statuses/-/statuses-1.5.0.tgz",
+      "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
+      "peer": true,
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/std-env": {
+      "version": "3.9.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/std-env/-/std-env-3.9.0.tgz",
+      "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw=="
+    },
+    "node_modules/string-width": {
+      "version": "4.2.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/string-width/-/string-width-4.2.3.tgz",
+      "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+      "peer": true,
+      "dependencies": {
+        "emoji-regex": "^8.0.0",
+        "is-fullwidth-code-point": "^3.0.0",
+        "strip-ansi": "^6.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/strip-ansi": {
+      "version": "6.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/strip-ansi/-/strip-ansi-6.0.1.tgz",
+      "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+      "peer": true,
+      "dependencies": {
+        "ansi-regex": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/strip-literal": {
+      "version": "3.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/strip-literal/-/strip-literal-3.0.0.tgz",
+      "integrity": "sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==",
+      "dependencies": {
+        "js-tokens": "^9.0.1"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      }
+    },
+    "node_modules/superjson": {
+      "version": "2.2.2",
+      "resolved": "https://registry.npmmirror.com/superjson/-/superjson-2.2.2.tgz",
+      "integrity": "sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==",
+      "license": "MIT",
+      "dependencies": {
+        "copy-anything": "^3.0.2"
+      },
+      "engines": {
+        "node": ">=16"
+      }
+    },
+    "node_modules/supports-color": {
+      "version": "8.1.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/supports-color/-/supports-color-8.1.1.tgz",
+      "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+      "peer": true,
+      "dependencies": {
+        "has-flag": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/supports-color?sponsor=1"
+      }
+    },
+    "node_modules/supports-preserve-symlinks-flag": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+      "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/tapable": {
+      "version": "2.2.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/tapable/-/tapable-2.2.2.tgz",
+      "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==",
+      "dev": true,
+      "peer": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/terser": {
+      "version": "5.40.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/terser/-/terser-5.40.0.tgz",
+      "integrity": "sha512-cfeKl/jjwSR5ar7d0FGmave9hFGJT8obyo0z+CrQOylLDbk7X81nPU6vq9VORa5jU30SkDnT2FXjLbR8HLP+xA==",
+      "peer": true,
+      "dependencies": {
+        "@jridgewell/source-map": "^0.3.3",
+        "acorn": "^8.14.0",
+        "commander": "^2.20.0",
+        "source-map-support": "~0.5.20"
+      },
+      "bin": {
+        "terser": "bin/terser"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/terser-webpack-plugin": {
+      "version": "5.3.14",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz",
+      "integrity": "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "@jridgewell/trace-mapping": "^0.3.25",
+        "jest-worker": "^27.4.5",
+        "schema-utils": "^4.3.0",
+        "serialize-javascript": "^6.0.2",
+        "terser": "^5.31.1"
+      },
+      "engines": {
+        "node": ">= 10.13.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      },
+      "peerDependencies": {
+        "webpack": "^5.1.0"
+      },
+      "peerDependenciesMeta": {
+        "@swc/core": {
+          "optional": true
+        },
+        "esbuild": {
+          "optional": true
+        },
+        "uglify-js": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/terser-webpack-plugin/node_modules/ajv": {
+      "version": "8.17.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ajv/-/ajv-8.17.1.tgz",
+      "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "fast-deep-equal": "^3.1.3",
+        "fast-uri": "^3.0.1",
+        "json-schema-traverse": "^1.0.0",
+        "require-from-string": "^2.0.2"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/epoberezkin"
+      }
+    },
+    "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": {
+      "version": "5.1.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
+      "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "fast-deep-equal": "^3.1.3"
+      },
+      "peerDependencies": {
+        "ajv": "^8.8.2"
+      }
+    },
+    "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": {
+      "version": "1.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+      "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+      "dev": true,
+      "peer": true
+    },
+    "node_modules/terser-webpack-plugin/node_modules/schema-utils": {
+      "version": "4.3.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/schema-utils/-/schema-utils-4.3.2.tgz",
+      "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "@types/json-schema": "^7.0.9",
+        "ajv": "^8.9.0",
+        "ajv-formats": "^2.1.1",
+        "ajv-keywords": "^5.1.0"
+      },
+      "engines": {
+        "node": ">= 10.13.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      }
+    },
+    "node_modules/test-exclude": {
+      "version": "6.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/test-exclude/-/test-exclude-6.0.0.tgz",
+      "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
+      "peer": true,
+      "dependencies": {
+        "@istanbuljs/schema": "^0.1.2",
+        "glob": "^7.1.4",
+        "minimatch": "^3.0.4"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/throat": {
+      "version": "5.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/throat/-/throat-5.0.0.tgz",
+      "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==",
+      "peer": true
+    },
+    "node_modules/tiny-emitter": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
+      "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==",
+      "license": "MIT"
+    },
+    "node_modules/tinyexec": {
+      "version": "0.3.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/tinyexec/-/tinyexec-0.3.2.tgz",
+      "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="
+    },
+    "node_modules/tinyglobby": {
+      "version": "0.2.14",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/tinyglobby/-/tinyglobby-0.2.14.tgz",
+      "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==",
+      "dependencies": {
+        "fdir": "^6.4.4",
+        "picomatch": "^4.0.2"
+      },
+      "engines": {
+        "node": ">=12.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/SuperchupuDev"
+      }
+    },
+    "node_modules/tinyglobby/node_modules/fdir": {
+      "version": "6.4.5",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/fdir/-/fdir-6.4.5.tgz",
+      "integrity": "sha512-4BG7puHpVsIYxZUbiUE3RqGloLaSSwzYie5jvasC4LWuBWzZawynvYouhjbQKw2JuIGYdm0DzIxl8iVidKlUEw==",
+      "peerDependencies": {
+        "picomatch": "^3 || ^4"
+      },
+      "peerDependenciesMeta": {
+        "picomatch": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/tinyglobby/node_modules/picomatch": {
+      "version": "4.0.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/picomatch/-/picomatch-4.0.2.tgz",
+      "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert"
+      }
+    },
+    "node_modules/tmpl": {
+      "version": "1.0.5",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/tmpl/-/tmpl-1.0.5.tgz",
+      "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
+      "peer": true
+    },
+    "node_modules/to-regex-range": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz",
+      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+      "license": "MIT",
+      "dependencies": {
+        "is-number": "^7.0.0"
+      },
+      "engines": {
+        "node": ">=8.0"
+      }
+    },
+    "node_modules/toidentifier": {
+      "version": "1.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/toidentifier/-/toidentifier-1.0.1.tgz",
+      "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+      "peer": true,
+      "engines": {
+        "node": ">=0.6"
+      }
+    },
+    "node_modules/tslib": {
+      "version": "2.8.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/tslib/-/tslib-2.8.1.tgz",
+      "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+    },
+    "node_modules/type-detect": {
+      "version": "4.0.8",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/type-detect/-/type-detect-4.0.8.tgz",
+      "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
+      "peer": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/type-fest": {
+      "version": "0.7.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/type-fest/-/type-fest-0.7.1.tgz",
+      "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==",
+      "peer": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/ufo": {
+      "version": "1.6.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ufo/-/ufo-1.6.1.tgz",
+      "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA=="
+    },
+    "node_modules/unctx": {
+      "version": "2.4.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/unctx/-/unctx-2.4.1.tgz",
+      "integrity": "sha512-AbaYw0Nm4mK4qjhns67C+kgxR2YWiwlDBPzxrN8h8C6VtAdCgditAY5Dezu3IJy4XVqAnbrXt9oQJvsn3fyozg==",
+      "dependencies": {
+        "acorn": "^8.14.0",
+        "estree-walker": "^3.0.3",
+        "magic-string": "^0.30.17",
+        "unplugin": "^2.1.0"
+      }
+    },
+    "node_modules/undici-types": {
+      "version": "6.21.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/undici-types/-/undici-types-6.21.0.tgz",
+      "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
+      "peer": true
+    },
+    "node_modules/unimport": {
+      "version": "5.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/unimport/-/unimport-5.0.1.tgz",
+      "integrity": "sha512-1YWzPj6wYhtwHE+9LxRlyqP4DiRrhGfJxdtH475im8ktyZXO3jHj/3PZ97zDdvkYoovFdi0K4SKl3a7l92v3sQ==",
+      "dependencies": {
+        "acorn": "^8.14.1",
+        "escape-string-regexp": "^5.0.0",
+        "estree-walker": "^3.0.3",
+        "local-pkg": "^1.1.1",
+        "magic-string": "^0.30.17",
+        "mlly": "^1.7.4",
+        "pathe": "^2.0.3",
+        "picomatch": "^4.0.2",
+        "pkg-types": "^2.1.0",
+        "scule": "^1.3.0",
+        "strip-literal": "^3.0.0",
+        "tinyglobby": "^0.2.13",
+        "unplugin": "^2.3.2",
+        "unplugin-utils": "^0.2.4"
+      },
+      "engines": {
+        "node": ">=18.12.0"
+      }
+    },
+    "node_modules/unimport/node_modules/picomatch": {
+      "version": "4.0.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/picomatch/-/picomatch-4.0.2.tgz",
+      "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert"
+      }
+    },
+    "node_modules/unpipe": {
+      "version": "1.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/unpipe/-/unpipe-1.0.0.tgz",
+      "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
+      "peer": true,
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/unplugin": {
+      "version": "2.3.5",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/unplugin/-/unplugin-2.3.5.tgz",
+      "integrity": "sha512-RyWSb5AHmGtjjNQ6gIlA67sHOsWpsbWpwDokLwTcejVdOjEkJZh7QKu14J00gDDVSh8kGH4KYC/TNBceXFZhtw==",
+      "dependencies": {
+        "acorn": "^8.14.1",
+        "picomatch": "^4.0.2",
+        "webpack-virtual-modules": "^0.6.2"
+      },
+      "engines": {
+        "node": ">=18.12.0"
+      }
+    },
+    "node_modules/unplugin-utils": {
+      "version": "0.2.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/unplugin-utils/-/unplugin-utils-0.2.4.tgz",
+      "integrity": "sha512-8U/MtpkPkkk3Atewj1+RcKIjb5WBimZ/WSLhhR3w6SsIj8XJuKTacSP8g+2JhfSGw0Cb125Y+2zA/IzJZDVbhA==",
+      "dependencies": {
+        "pathe": "^2.0.2",
+        "picomatch": "^4.0.2"
+      },
+      "engines": {
+        "node": ">=18.12.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sxzz"
+      }
+    },
+    "node_modules/unplugin-utils/node_modules/picomatch": {
+      "version": "4.0.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/picomatch/-/picomatch-4.0.2.tgz",
+      "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert"
+      }
+    },
+    "node_modules/unplugin/node_modules/picomatch": {
+      "version": "4.0.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/picomatch/-/picomatch-4.0.2.tgz",
+      "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert"
+      }
+    },
+    "node_modules/untyped": {
+      "version": "2.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/untyped/-/untyped-2.0.0.tgz",
+      "integrity": "sha512-nwNCjxJTjNuLCgFr42fEak5OcLuB3ecca+9ksPFNvtfYSLpjf+iJqSIaSnIile6ZPbKYxI5k2AfXqeopGudK/g==",
+      "dependencies": {
+        "citty": "^0.1.6",
+        "defu": "^6.1.4",
+        "jiti": "^2.4.2",
+        "knitwork": "^1.2.0",
+        "scule": "^1.3.0"
+      },
+      "bin": {
+        "untyped": "dist/cli.mjs"
+      }
+    },
+    "node_modules/update-browserslist-db": {
+      "version": "1.1.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
+      "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/browserslist"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/browserslist"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "peer": true,
+      "dependencies": {
+        "escalade": "^3.2.0",
+        "picocolors": "^1.1.1"
+      },
+      "bin": {
+        "update-browserslist-db": "cli.js"
+      },
+      "peerDependencies": {
+        "browserslist": ">= 4.21.0"
+      }
+    },
+    "node_modules/uri-js": {
+      "version": "4.4.1",
+      "resolved": "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz",
+      "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "punycode": "^2.1.0"
+      }
+    },
+    "node_modules/utils-merge": {
+      "version": "1.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/utils-merge/-/utils-merge-1.0.1.tgz",
+      "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
+      "peer": true,
+      "engines": {
+        "node": ">= 0.4.0"
+      }
+    },
+    "node_modules/uuid": {
+      "version": "11.1.0",
+      "resolved": "https://registry.npmmirror.com/uuid/-/uuid-11.1.0.tgz",
+      "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==",
+      "funding": [
+        "https://github.com/sponsors/broofa",
+        "https://github.com/sponsors/ctavan"
+      ],
+      "license": "MIT",
+      "bin": {
+        "uuid": "dist/esm/bin/uuid"
+      }
+    },
+    "node_modules/uview-plus": {
+      "version": "3.5.41",
+      "resolved": "https://registry.npmmirror.com/uview-plus/-/uview-plus-3.5.41.tgz",
+      "integrity": "sha512-X+oCPvTngZaqbzMlTZepPxEHk750br2UnywnIShXWHm3uiV3WzrFh5TQzK9f8JveX6FS/dVUgcVk89BJPMC6mw==",
+      "dependencies": {
+        "clipboard": "^2.0.11",
+        "dayjs": "^1.11.3"
+      },
+      "engines": {
+        "HBuilderX": "^3.1.0",
+        "uni-app": "^4.66",
+        "uni-app-x": ""
+      }
+    },
+    "node_modules/uview-ui": {
+      "version": "2.0.38",
+      "resolved": "https://registry.npmmirror.com/uview-ui/-/uview-ui-2.0.38.tgz",
+      "integrity": "sha512-6egHDf9lXHKpG3hEjRE0vMx4+VWwKk/ReTf5x18KrIKqdvdPRqO3+B8Unh7vYYwrIxzAWIlmhZ9RJpKI/4UqPQ==",
+      "engines": {
+        "HBuilderX": "^3.1.0"
+      }
+    },
+    "node_modules/vlq": {
+      "version": "1.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/vlq/-/vlq-1.0.1.tgz",
+      "integrity": "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==",
+      "peer": true
+    },
+    "node_modules/vue": {
+      "version": "3.5.16",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/vue/-/vue-3.5.16.tgz",
+      "integrity": "sha512-rjOV2ecxMd5SiAmof2xzh2WxntRcigkX/He4YFJ6WdRvVUrbt6DxC1Iujh10XLl8xCDRDtGKMeO3D+pRQ1PP9w==",
+      "peer": true,
+      "dependencies": {
+        "@vue/compiler-dom": "3.5.16",
+        "@vue/compiler-sfc": "3.5.16",
+        "@vue/runtime-dom": "3.5.16",
+        "@vue/server-renderer": "3.5.16",
+        "@vue/shared": "3.5.16"
+      },
+      "peerDependencies": {
+        "typescript": "*"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/walker": {
+      "version": "1.0.8",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/walker/-/walker-1.0.8.tgz",
+      "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==",
+      "peer": true,
+      "dependencies": {
+        "makeerror": "1.0.12"
+      }
+    },
+    "node_modules/watchpack": {
+      "version": "2.4.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/watchpack/-/watchpack-2.4.4.tgz",
+      "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "glob-to-regexp": "^0.4.1",
+        "graceful-fs": "^4.1.2"
+      },
+      "engines": {
+        "node": ">=10.13.0"
+      }
+    },
+    "node_modules/web-vitals": {
+      "version": "3.5.2",
+      "resolved": "https://registry.npmmirror.com/web-vitals/-/web-vitals-3.5.2.tgz",
+      "integrity": "sha512-c0rhqNcHXRkY/ogGDJQxZ9Im9D19hDihbzSQJrsioex+KnFgmMzBiy57Z1EjkhX/+OjyBpclDCzz2ITtjokFmg=="
+    },
+    "node_modules/webpack": {
+      "version": "5.99.9",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/webpack/-/webpack-5.99.9.tgz",
+      "integrity": "sha512-brOPwM3JnmOa+7kd3NsmOUOwbDAj8FT9xDsG3IW0MgbN9yZV7Oi/s/+MNQ/EcSMqw7qfoRyXPoeEWT8zLVdVGg==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "@types/eslint-scope": "^3.7.7",
+        "@types/estree": "^1.0.6",
+        "@types/json-schema": "^7.0.15",
+        "@webassemblyjs/ast": "^1.14.1",
+        "@webassemblyjs/wasm-edit": "^1.14.1",
+        "@webassemblyjs/wasm-parser": "^1.14.1",
+        "acorn": "^8.14.0",
+        "browserslist": "^4.24.0",
+        "chrome-trace-event": "^1.0.2",
+        "enhanced-resolve": "^5.17.1",
+        "es-module-lexer": "^1.2.1",
+        "eslint-scope": "5.1.1",
+        "events": "^3.2.0",
+        "glob-to-regexp": "^0.4.1",
+        "graceful-fs": "^4.2.11",
+        "json-parse-even-better-errors": "^2.3.1",
+        "loader-runner": "^4.2.0",
+        "mime-types": "^2.1.27",
+        "neo-async": "^2.6.2",
+        "schema-utils": "^4.3.2",
+        "tapable": "^2.1.1",
+        "terser-webpack-plugin": "^5.3.11",
+        "watchpack": "^2.4.1",
+        "webpack-sources": "^3.2.3"
+      },
+      "bin": {
+        "webpack": "bin/webpack.js"
+      },
+      "engines": {
+        "node": ">=10.13.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      },
+      "peerDependenciesMeta": {
+        "webpack-cli": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/webpack-sources": {
+      "version": "3.3.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/webpack-sources/-/webpack-sources-3.3.2.tgz",
+      "integrity": "sha512-ykKKus8lqlgXX/1WjudpIEjqsafjOTcOJqxnAbMLAu/KCsDCJ6GBtvscewvTkrn24HsnvFwrSCbenFrhtcCsAA==",
+      "dev": true,
+      "peer": true,
+      "engines": {
+        "node": ">=10.13.0"
+      }
+    },
+    "node_modules/webpack-virtual-modules": {
+      "version": "0.6.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz",
+      "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ=="
+    },
+    "node_modules/webpack/node_modules/ajv": {
+      "version": "8.17.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ajv/-/ajv-8.17.1.tgz",
+      "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "fast-deep-equal": "^3.1.3",
+        "fast-uri": "^3.0.1",
+        "json-schema-traverse": "^1.0.0",
+        "require-from-string": "^2.0.2"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/epoberezkin"
+      }
+    },
+    "node_modules/webpack/node_modules/ajv-keywords": {
+      "version": "5.1.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
+      "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "fast-deep-equal": "^3.1.3"
+      },
+      "peerDependencies": {
+        "ajv": "^8.8.2"
+      }
+    },
+    "node_modules/webpack/node_modules/json-schema-traverse": {
+      "version": "1.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+      "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+      "dev": true,
+      "peer": true
+    },
+    "node_modules/webpack/node_modules/schema-utils": {
+      "version": "4.3.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/schema-utils/-/schema-utils-4.3.2.tgz",
+      "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==",
+      "dev": true,
+      "peer": true,
+      "dependencies": {
+        "@types/json-schema": "^7.0.9",
+        "ajv": "^8.9.0",
+        "ajv-formats": "^2.1.1",
+        "ajv-keywords": "^5.1.0"
+      },
+      "engines": {
+        "node": ">= 10.13.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      }
+    },
+    "node_modules/whatwg-fetch": {
+      "version": "3.6.20",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz",
+      "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==",
+      "peer": true
+    },
+    "node_modules/wrap-ansi": {
+      "version": "7.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+      "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+      "peer": true,
+      "dependencies": {
+        "ansi-styles": "^4.0.0",
+        "string-width": "^4.1.0",
+        "strip-ansi": "^6.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+      }
+    },
+    "node_modules/wrappy": {
+      "version": "1.0.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/wrappy/-/wrappy-1.0.2.tgz",
+      "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+      "peer": true
+    },
+    "node_modules/write-file-atomic": {
+      "version": "4.0.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/write-file-atomic/-/write-file-atomic-4.0.2.tgz",
+      "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==",
+      "peer": true,
+      "dependencies": {
+        "imurmurhash": "^0.1.4",
+        "signal-exit": "^3.0.7"
+      },
+      "engines": {
+        "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+      }
+    },
+    "node_modules/ws": {
+      "version": "6.2.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ws/-/ws-6.2.3.tgz",
+      "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==",
+      "peer": true,
+      "dependencies": {
+        "async-limiter": "~1.0.0"
+      }
+    },
+    "node_modules/y18n": {
+      "version": "5.0.8",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/y18n/-/y18n-5.0.8.tgz",
+      "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+      "peer": true,
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/yallist": {
+      "version": "3.1.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/yallist/-/yallist-3.1.1.tgz",
+      "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+      "peer": true
+    },
+    "node_modules/yargs": {
+      "version": "17.7.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/yargs/-/yargs-17.7.2.tgz",
+      "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+      "peer": true,
+      "dependencies": {
+        "cliui": "^8.0.1",
+        "escalade": "^3.1.1",
+        "get-caller-file": "^2.0.5",
+        "require-directory": "^2.1.1",
+        "string-width": "^4.2.3",
+        "y18n": "^5.0.5",
+        "yargs-parser": "^21.1.1"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/yargs-parser": {
+      "version": "21.1.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/yargs-parser/-/yargs-parser-21.1.1.tgz",
+      "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+      "peer": true,
+      "engines": {
+        "node": ">=12"
+      }
+    }
+  },
+  "dependencies": {
+    "@airwallex/airtracker": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/@airwallex/airtracker/-/airtracker-1.2.0.tgz",
+      "integrity": "sha512-T6u4QnWEhT9jomVwo6FCVK63AOxRVjonUOn1mj16L/xbqhNCnl/kTBP2khFjFJBJ7wKcb7Yb2KrUg803Uu5zcw==",
+      "requires": {
+        "web-vitals": "^3.5.1"
+      }
+    },
+    "@airwallex/components-sdk": {
+      "version": "1.20.0",
+      "resolved": "https://registry.npmmirror.com/@airwallex/components-sdk/-/components-sdk-1.20.0.tgz",
+      "integrity": "sha512-aDJDYx4/6+bwZOdw2+1ZG4Ti6RfP1Z6rk25NUixUaU264yKMg6bVLNqFxmfllL/qKHHHt0wN/+vtrm7OFRHalQ==",
+      "requires": {
+        "@airwallex/airtracker": "1.2.0"
+      }
+    },
+    "@ampproject/remapping": {
+      "version": "2.3.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@ampproject/remapping/-/remapping-2.3.0.tgz",
+      "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
+      "peer": true,
+      "requires": {
+        "@jridgewell/gen-mapping": "^0.3.5",
+        "@jridgewell/trace-mapping": "^0.3.24"
+      }
+    },
+    "@awesome-cordova-plugins/core": {
+      "version": "6.16.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@awesome-cordova-plugins/core/-/core-6.16.0.tgz",
+      "integrity": "sha512-ep+nkDY6CyFBfqS/HS03PE+MZWiQoJWb/nLMwfj2ndC14UgZeVO3ecmEFknYjJOBf04emTbs7hbLewFrVkazmg==",
+      "peer": true,
+      "requires": {
+        "@types/cordova": "latest"
+      }
+    },
+    "@awesome-cordova-plugins/facebook": {
+      "version": "8.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@awesome-cordova-plugins/facebook/-/facebook-8.0.0.tgz",
+      "integrity": "sha512-Jj1Us/HY0WURC1ecCV06oaYHcPZNa7+as+YfRdNQoLbp1UenTaovJmeGvfYsJ3yx07CH4ZaquD06zlI/PTQeAQ==",
+      "requires": {
+        "@types/cordova": "latest"
+      }
+    },
+    "@babel/code-frame": {
+      "version": "7.27.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/code-frame/-/code-frame-7.27.1.tgz",
+      "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
+      "peer": true,
+      "requires": {
+        "@babel/helper-validator-identifier": "^7.27.1",
+        "js-tokens": "^4.0.0",
+        "picocolors": "^1.1.1"
+      },
+      "dependencies": {
+        "js-tokens": {
+          "version": "4.0.0",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/js-tokens/-/js-tokens-4.0.0.tgz",
+          "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+          "peer": true
+        }
+      }
+    },
+    "@babel/compat-data": {
+      "version": "7.27.5",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/compat-data/-/compat-data-7.27.5.tgz",
+      "integrity": "sha512-KiRAp/VoJaWkkte84TvUd9qjdbZAdiqyvMxrGl1N6vzFogKmaLgoM3L1kgtLicp2HP5fBJS8JrZKLVIZGVJAVg==",
+      "peer": true
+    },
+    "@babel/core": {
+      "version": "7.27.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/core/-/core-7.27.4.tgz",
+      "integrity": "sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==",
+      "peer": true,
+      "requires": {
+        "@ampproject/remapping": "^2.2.0",
+        "@babel/code-frame": "^7.27.1",
+        "@babel/generator": "^7.27.3",
+        "@babel/helper-compilation-targets": "^7.27.2",
+        "@babel/helper-module-transforms": "^7.27.3",
+        "@babel/helpers": "^7.27.4",
+        "@babel/parser": "^7.27.4",
+        "@babel/template": "^7.27.2",
+        "@babel/traverse": "^7.27.4",
+        "@babel/types": "^7.27.3",
+        "convert-source-map": "^2.0.0",
+        "debug": "^4.1.0",
+        "gensync": "^1.0.0-beta.2",
+        "json5": "^2.2.3",
+        "semver": "^6.3.1"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "6.3.1",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-6.3.1.tgz",
+          "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+          "peer": true
+        }
+      }
+    },
+    "@babel/generator": {
+      "version": "7.27.5",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/generator/-/generator-7.27.5.tgz",
+      "integrity": "sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==",
+      "peer": true,
+      "requires": {
+        "@babel/parser": "^7.27.5",
+        "@babel/types": "^7.27.3",
+        "@jridgewell/gen-mapping": "^0.3.5",
+        "@jridgewell/trace-mapping": "^0.3.25",
+        "jsesc": "^3.0.2"
+      }
+    },
+    "@babel/helper-compilation-targets": {
+      "version": "7.27.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz",
+      "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==",
+      "peer": true,
+      "requires": {
+        "@babel/compat-data": "^7.27.2",
+        "@babel/helper-validator-option": "^7.27.1",
+        "browserslist": "^4.24.0",
+        "lru-cache": "^5.1.1",
+        "semver": "^6.3.1"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "6.3.1",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-6.3.1.tgz",
+          "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+          "peer": true
+        }
+      }
+    },
+    "@babel/helper-module-imports": {
+      "version": "7.27.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz",
+      "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==",
+      "peer": true,
+      "requires": {
+        "@babel/traverse": "^7.27.1",
+        "@babel/types": "^7.27.1"
+      }
+    },
+    "@babel/helper-module-transforms": {
+      "version": "7.27.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz",
+      "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==",
+      "peer": true,
+      "requires": {
+        "@babel/helper-module-imports": "^7.27.1",
+        "@babel/helper-validator-identifier": "^7.27.1",
+        "@babel/traverse": "^7.27.3"
+      }
+    },
+    "@babel/helper-plugin-utils": {
+      "version": "7.27.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz",
+      "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==",
+      "peer": true
+    },
+    "@babel/helper-string-parser": {
+      "version": "7.27.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+      "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
+      "peer": true
+    },
+    "@babel/helper-validator-identifier": {
+      "version": "7.27.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
+      "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
+      "peer": true
+    },
+    "@babel/helper-validator-option": {
+      "version": "7.27.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
+      "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
+      "peer": true
+    },
+    "@babel/helpers": {
+      "version": "7.27.6",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/helpers/-/helpers-7.27.6.tgz",
+      "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==",
+      "peer": true,
+      "requires": {
+        "@babel/template": "^7.27.2",
+        "@babel/types": "^7.27.6"
+      }
+    },
+    "@babel/parser": {
+      "version": "7.27.5",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/parser/-/parser-7.27.5.tgz",
+      "integrity": "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==",
+      "peer": true,
+      "requires": {
+        "@babel/types": "^7.27.3"
+      }
+    },
+    "@babel/plugin-syntax-async-generators": {
+      "version": "7.8.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
+      "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
+      "peer": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      }
+    },
+    "@babel/plugin-syntax-bigint": {
+      "version": "7.8.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz",
+      "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==",
+      "peer": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      }
+    },
+    "@babel/plugin-syntax-class-properties": {
+      "version": "7.12.13",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
+      "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
+      "peer": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.12.13"
+      }
+    },
+    "@babel/plugin-syntax-class-static-block": {
+      "version": "7.14.5",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz",
+      "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==",
+      "peer": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.14.5"
+      }
+    },
+    "@babel/plugin-syntax-import-attributes": {
+      "version": "7.27.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz",
+      "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==",
+      "peer": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.27.1"
+      }
+    },
+    "@babel/plugin-syntax-import-meta": {
+      "version": "7.10.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
+      "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
+      "peer": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      }
+    },
+    "@babel/plugin-syntax-json-strings": {
+      "version": "7.8.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
+      "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
+      "peer": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      }
+    },
+    "@babel/plugin-syntax-logical-assignment-operators": {
+      "version": "7.10.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
+      "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+      "peer": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      }
+    },
+    "@babel/plugin-syntax-nullish-coalescing-operator": {
+      "version": "7.8.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
+      "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
+      "peer": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      }
+    },
+    "@babel/plugin-syntax-numeric-separator": {
+      "version": "7.10.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
+      "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
+      "peer": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      }
+    },
+    "@babel/plugin-syntax-object-rest-spread": {
+      "version": "7.8.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
+      "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+      "peer": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      }
+    },
+    "@babel/plugin-syntax-optional-catch-binding": {
+      "version": "7.8.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
+      "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
+      "peer": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      }
+    },
+    "@babel/plugin-syntax-optional-chaining": {
+      "version": "7.8.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
+      "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+      "peer": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      }
+    },
+    "@babel/plugin-syntax-private-property-in-object": {
+      "version": "7.14.5",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz",
+      "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==",
+      "peer": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.14.5"
+      }
+    },
+    "@babel/plugin-syntax-top-level-await": {
+      "version": "7.14.5",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
+      "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
+      "peer": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.14.5"
+      }
+    },
+    "@babel/runtime": {
+      "version": "7.27.6",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/runtime/-/runtime-7.27.6.tgz",
+      "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==",
+      "peer": true
+    },
+    "@babel/template": {
+      "version": "7.27.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/template/-/template-7.27.2.tgz",
+      "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==",
+      "peer": true,
+      "requires": {
+        "@babel/code-frame": "^7.27.1",
+        "@babel/parser": "^7.27.2",
+        "@babel/types": "^7.27.1"
+      }
+    },
+    "@babel/traverse": {
+      "version": "7.27.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/traverse/-/traverse-7.27.4.tgz",
+      "integrity": "sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==",
+      "peer": true,
+      "requires": {
+        "@babel/code-frame": "^7.27.1",
+        "@babel/generator": "^7.27.3",
+        "@babel/parser": "^7.27.4",
+        "@babel/template": "^7.27.2",
+        "@babel/types": "^7.27.3",
+        "debug": "^4.3.1",
+        "globals": "^11.1.0"
+      }
+    },
+    "@babel/traverse--for-generate-function-map": {
+      "version": "npm:@babel/traverse@7.27.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/traverse/-/traverse-7.27.4.tgz",
+      "integrity": "sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==",
+      "peer": true,
+      "requires": {
+        "@babel/code-frame": "^7.27.1",
+        "@babel/generator": "^7.27.3",
+        "@babel/parser": "^7.27.4",
+        "@babel/template": "^7.27.2",
+        "@babel/types": "^7.27.3",
+        "debug": "^4.3.1",
+        "globals": "^11.1.0"
+      }
+    },
+    "@babel/types": {
+      "version": "7.27.6",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@babel/types/-/types-7.27.6.tgz",
+      "integrity": "sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==",
+      "peer": true,
+      "requires": {
+        "@babel/helper-string-parser": "^7.27.1",
+        "@babel/helper-validator-identifier": "^7.27.1"
+      }
+    },
+    "@capacitor-community/facebook-login": {
+      "version": "7.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@capacitor-community/facebook-login/-/facebook-login-7.0.0.tgz",
+      "integrity": "sha512-zwCBaqHysWpjFfb4F/Ax2oJjt1vQVkp+SAdjCOaPtloiak+AceXW9U0mtYVxfk0aOO9gKALbkKnivcfviIDN0A==",
+      "requires": {
+        "@capacitor/core": "^7.0.0"
+      }
+    },
+    "@capacitor/core": {
+      "version": "7.3.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@capacitor/core/-/core-7.3.0.tgz",
+      "integrity": "sha512-t/DdTyBchQ2eAZuCmAARlqQsrEm0WyeNwh5zeRuv+cR6gnAsw+86/EWvJ/em5dTnZyaqEy8vlmOMdWarrUbnuQ==",
+      "requires": {
+        "tslib": "^2.1.0"
+      }
+    },
+    "@isaacs/ttlcache": {
+      "version": "1.4.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz",
+      "integrity": "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==",
+      "peer": true
+    },
+    "@istanbuljs/load-nyc-config": {
+      "version": "1.1.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
+      "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
+      "peer": true,
+      "requires": {
+        "camelcase": "^5.3.1",
+        "find-up": "^4.1.0",
+        "get-package-type": "^0.1.0",
+        "js-yaml": "^3.13.1",
+        "resolve-from": "^5.0.0"
+      }
+    },
+    "@istanbuljs/schema": {
+      "version": "0.1.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@istanbuljs/schema/-/schema-0.1.3.tgz",
+      "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
+      "peer": true
+    },
+    "@jest/create-cache-key-function": {
+      "version": "29.7.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz",
+      "integrity": "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==",
+      "peer": true,
+      "requires": {
+        "@jest/types": "^29.6.3"
+      }
+    },
+    "@jest/environment": {
+      "version": "29.7.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@jest/environment/-/environment-29.7.0.tgz",
+      "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==",
+      "peer": true,
+      "requires": {
+        "@jest/fake-timers": "^29.7.0",
+        "@jest/types": "^29.6.3",
+        "@types/node": "*",
+        "jest-mock": "^29.7.0"
+      }
+    },
+    "@jest/fake-timers": {
+      "version": "29.7.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@jest/fake-timers/-/fake-timers-29.7.0.tgz",
+      "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==",
+      "peer": true,
+      "requires": {
+        "@jest/types": "^29.6.3",
+        "@sinonjs/fake-timers": "^10.0.2",
+        "@types/node": "*",
+        "jest-message-util": "^29.7.0",
+        "jest-mock": "^29.7.0",
+        "jest-util": "^29.7.0"
+      }
+    },
+    "@jest/schemas": {
+      "version": "29.6.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@jest/schemas/-/schemas-29.6.3.tgz",
+      "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
+      "peer": true,
+      "requires": {
+        "@sinclair/typebox": "^0.27.8"
+      }
+    },
+    "@jest/transform": {
+      "version": "29.7.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@jest/transform/-/transform-29.7.0.tgz",
+      "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==",
+      "peer": true,
+      "requires": {
+        "@babel/core": "^7.11.6",
+        "@jest/types": "^29.6.3",
+        "@jridgewell/trace-mapping": "^0.3.18",
+        "babel-plugin-istanbul": "^6.1.1",
+        "chalk": "^4.0.0",
+        "convert-source-map": "^2.0.0",
+        "fast-json-stable-stringify": "^2.1.0",
+        "graceful-fs": "^4.2.9",
+        "jest-haste-map": "^29.7.0",
+        "jest-regex-util": "^29.6.3",
+        "jest-util": "^29.7.0",
+        "micromatch": "^4.0.4",
+        "pirates": "^4.0.4",
+        "slash": "^3.0.0",
+        "write-file-atomic": "^4.0.2"
+      }
+    },
+    "@jest/types": {
+      "version": "29.6.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@jest/types/-/types-29.6.3.tgz",
+      "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+      "peer": true,
+      "requires": {
+        "@jest/schemas": "^29.6.3",
+        "@types/istanbul-lib-coverage": "^2.0.0",
+        "@types/istanbul-reports": "^3.0.0",
+        "@types/node": "*",
+        "@types/yargs": "^17.0.8",
+        "chalk": "^4.0.0"
+      }
+    },
+    "@jridgewell/gen-mapping": {
+      "version": "0.3.8",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
+      "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==",
+      "peer": true,
+      "requires": {
+        "@jridgewell/set-array": "^1.2.1",
+        "@jridgewell/sourcemap-codec": "^1.4.10",
+        "@jridgewell/trace-mapping": "^0.3.24"
+      }
+    },
+    "@jridgewell/resolve-uri": {
+      "version": "3.1.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+      "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+      "peer": true
+    },
+    "@jridgewell/set-array": {
+      "version": "1.2.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@jridgewell/set-array/-/set-array-1.2.1.tgz",
+      "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
+      "peer": true
+    },
+    "@jridgewell/source-map": {
+      "version": "0.3.6",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@jridgewell/source-map/-/source-map-0.3.6.tgz",
+      "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
+      "peer": true,
+      "requires": {
+        "@jridgewell/gen-mapping": "^0.3.5",
+        "@jridgewell/trace-mapping": "^0.3.25"
+      }
+    },
+    "@jridgewell/sourcemap-codec": {
+      "version": "1.5.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
+      "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="
+    },
+    "@jridgewell/trace-mapping": {
+      "version": "0.3.25",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
+      "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
+      "peer": true,
+      "requires": {
+        "@jridgewell/resolve-uri": "^3.1.0",
+        "@jridgewell/sourcemap-codec": "^1.4.14"
+      }
+    },
+    "@microsoft/tsdoc": {
+      "version": "0.15.1",
+      "resolved": "https://registry.npmmirror.com/@microsoft/tsdoc/-/tsdoc-0.15.1.tgz",
+      "integrity": "sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw=="
+    },
+    "@microsoft/tsdoc-config": {
+      "version": "0.17.1",
+      "resolved": "https://registry.npmmirror.com/@microsoft/tsdoc-config/-/tsdoc-config-0.17.1.tgz",
+      "integrity": "sha512-UtjIFe0C6oYgTnad4q1QP4qXwLhe6tIpNTRStJ2RZEPIkqQPREAwE5spzVxsdn9UaEMUqhh0AqSx3X4nWAKXWw==",
+      "requires": {
+        "@microsoft/tsdoc": "0.15.1",
+        "ajv": "~8.12.0",
+        "jju": "~1.4.0",
+        "resolve": "~1.22.2"
+      },
+      "dependencies": {
+        "ajv": {
+          "version": "8.12.0",
+          "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.12.0.tgz",
+          "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
+          "requires": {
+            "fast-deep-equal": "^3.1.1",
+            "json-schema-traverse": "^1.0.0",
+            "require-from-string": "^2.0.2",
+            "uri-js": "^4.2.2"
+          }
+        },
+        "json-schema-traverse": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+          "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
+        }
+      }
+    },
+    "@nuxt/kit": {
+      "version": "3.17.5",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@nuxt/kit/-/kit-3.17.5.tgz",
+      "integrity": "sha512-NdCepmA+S/SzgcaL3oYUeSlXGYO6BXGr9K/m1D0t0O9rApF8CSq/QQ+ja5KYaYMO1kZAEWH4s2XVcE3uPrrAVg==",
+      "requires": {
+        "c12": "^3.0.4",
+        "consola": "^3.4.2",
+        "defu": "^6.1.4",
+        "destr": "^2.0.5",
+        "errx": "^0.1.0",
+        "exsolve": "^1.0.5",
+        "ignore": "^7.0.5",
+        "jiti": "^2.4.2",
+        "klona": "^2.0.6",
+        "knitwork": "^1.2.0",
+        "mlly": "^1.7.4",
+        "ohash": "^2.0.11",
+        "pathe": "^2.0.3",
+        "pkg-types": "^2.1.0",
+        "scule": "^1.3.0",
+        "semver": "^7.7.2",
+        "std-env": "^3.9.0",
+        "tinyglobby": "^0.2.14",
+        "ufo": "^1.6.1",
+        "unctx": "^2.4.1",
+        "unimport": "^5.0.1",
+        "untyped": "^2.0.0"
+      }
+    },
+    "@parcel/watcher": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher/-/watcher-2.5.1.tgz",
+      "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "@parcel/watcher-android-arm64": "2.5.1",
+        "@parcel/watcher-darwin-arm64": "2.5.1",
+        "@parcel/watcher-darwin-x64": "2.5.1",
+        "@parcel/watcher-freebsd-x64": "2.5.1",
+        "@parcel/watcher-linux-arm-glibc": "2.5.1",
+        "@parcel/watcher-linux-arm-musl": "2.5.1",
+        "@parcel/watcher-linux-arm64-glibc": "2.5.1",
+        "@parcel/watcher-linux-arm64-musl": "2.5.1",
+        "@parcel/watcher-linux-x64-glibc": "2.5.1",
+        "@parcel/watcher-linux-x64-musl": "2.5.1",
+        "@parcel/watcher-win32-arm64": "2.5.1",
+        "@parcel/watcher-win32-ia32": "2.5.1",
+        "@parcel/watcher-win32-x64": "2.5.1",
+        "detect-libc": "^1.0.3",
+        "is-glob": "^4.0.3",
+        "micromatch": "^4.0.5",
+        "node-addon-api": "^7.0.0"
+      }
+    },
+    "@parcel/watcher-win32-x64": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz",
+      "integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==",
+      "dev": true,
+      "optional": true
+    },
+    "@react-native-google-signin/google-signin": {
+      "version": "14.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@react-native-google-signin/google-signin/-/google-signin-14.0.1.tgz",
+      "integrity": "sha512-2f903eaHiv/Ob96vsWZitz+Z0k2J2W0/C7Ygrr6ejAT2JVzJCatmjF/eq62MWhuTNdU2WDX/oePxMbpQW6k2UA==",
+      "requires": {}
+    },
+    "@react-native/assets-registry": {
+      "version": "0.79.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@react-native/assets-registry/-/assets-registry-0.79.3.tgz",
+      "integrity": "sha512-Vy8DQXCJ21YSAiHxrNBz35VqVlZPpRYm50xRTWRf660JwHuJkFQG8cUkrLzm7AUriqUXxwpkQHcY+b0ibw9ejQ==",
+      "peer": true
+    },
+    "@react-native/codegen": {
+      "version": "0.79.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@react-native/codegen/-/codegen-0.79.3.tgz",
+      "integrity": "sha512-CZejXqKch/a5/s/MO5T8mkAgvzCXgsTkQtpCF15kWR9HN8T+16k0CsN7TXAxXycltoxiE3XRglOrZNEa/TiZUQ==",
+      "peer": true,
+      "requires": {
+        "glob": "^7.1.1",
+        "hermes-parser": "0.25.1",
+        "invariant": "^2.2.4",
+        "nullthrows": "^1.1.1",
+        "yargs": "^17.6.2"
+      }
+    },
+    "@react-native/community-cli-plugin": {
+      "version": "0.79.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@react-native/community-cli-plugin/-/community-cli-plugin-0.79.3.tgz",
+      "integrity": "sha512-N/+p4HQqN4yK6IRzn7OgMvUIcrmEWkecglk1q5nj+AzNpfIOzB+mqR20SYmnPfeXF+mZzYCzRANb3KiM+WsSDA==",
+      "peer": true,
+      "requires": {
+        "@react-native/dev-middleware": "0.79.3",
+        "chalk": "^4.0.0",
+        "debug": "^2.2.0",
+        "invariant": "^2.2.4",
+        "metro": "^0.82.0",
+        "metro-config": "^0.82.0",
+        "metro-core": "^0.82.0",
+        "semver": "^7.1.3"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "peer": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "ms": {
+          "version": "2.0.0",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz",
+          "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+          "peer": true
+        }
+      }
+    },
+    "@react-native/debugger-frontend": {
+      "version": "0.79.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@react-native/debugger-frontend/-/debugger-frontend-0.79.3.tgz",
+      "integrity": "sha512-ImNDuEeKH6lEsLXms3ZsgIrNF94jymfuhPcVY5L0trzaYNo9ZFE9Ni2/18E1IbfXxdeIHrCSBJlWD6CTm7wu5A==",
+      "peer": true
+    },
+    "@react-native/dev-middleware": {
+      "version": "0.79.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@react-native/dev-middleware/-/dev-middleware-0.79.3.tgz",
+      "integrity": "sha512-x88+RGOyG71+idQefnQg7wLhzjn/Scs+re1O5vqCkTVzRAc/f7SdHMlbmECUxJPd08FqMcOJr7/X3nsJBrNuuw==",
+      "peer": true,
+      "requires": {
+        "@isaacs/ttlcache": "^1.4.1",
+        "@react-native/debugger-frontend": "0.79.3",
+        "chrome-launcher": "^0.15.2",
+        "chromium-edge-launcher": "^0.2.0",
+        "connect": "^3.6.5",
+        "debug": "^2.2.0",
+        "invariant": "^2.2.4",
+        "nullthrows": "^1.1.1",
+        "open": "^7.0.3",
+        "serve-static": "^1.16.2",
+        "ws": "^6.2.3"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "peer": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "ms": {
+          "version": "2.0.0",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz",
+          "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+          "peer": true
+        }
+      }
+    },
+    "@react-native/gradle-plugin": {
+      "version": "0.79.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@react-native/gradle-plugin/-/gradle-plugin-0.79.3.tgz",
+      "integrity": "sha512-imfpZLhNBc9UFSzb/MOy2tNcIBHqVmexh/qdzw83F75BmUtLb/Gs1L2V5gw+WI1r7RqDILbWk7gXB8zUllwd+g==",
+      "peer": true
+    },
+    "@react-native/js-polyfills": {
+      "version": "0.79.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@react-native/js-polyfills/-/js-polyfills-0.79.3.tgz",
+      "integrity": "sha512-PEBtg6Kox6KahjCAch0UrqCAmHiNLEbp2SblUEoFAQnov4DSxBN9safh+QSVaCiMAwLjvNfXrJyygZz60Dqz3Q==",
+      "peer": true
+    },
+    "@react-native/normalize-colors": {
+      "version": "0.79.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@react-native/normalize-colors/-/normalize-colors-0.79.3.tgz",
+      "integrity": "sha512-T75NIQPRFCj6DFMxtcVMJTZR+3vHXaUMSd15t+CkJpc5LnyX91GVaPxpRSAdjFh7m3Yppl5MpdjV/fntImheYQ==",
+      "peer": true
+    },
+    "@react-native/virtualized-lists": {
+      "version": "0.79.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@react-native/virtualized-lists/-/virtualized-lists-0.79.3.tgz",
+      "integrity": "sha512-/0rRozkn+iIHya2vnnvprDgT7QkfI54FLrACAN3BLP7MRlfOIGOrZsXpRLndnLBVnjNzkcre84i1RecjoXnwIA==",
+      "peer": true,
+      "requires": {
+        "invariant": "^2.2.4",
+        "nullthrows": "^1.1.1"
+      }
+    },
+    "@sinclair/typebox": {
+      "version": "0.27.8",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@sinclair/typebox/-/typebox-0.27.8.tgz",
+      "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==",
+      "peer": true
+    },
+    "@sinonjs/commons": {
+      "version": "3.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@sinonjs/commons/-/commons-3.0.1.tgz",
+      "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==",
+      "peer": true,
+      "requires": {
+        "type-detect": "4.0.8"
+      }
+    },
+    "@sinonjs/fake-timers": {
+      "version": "10.3.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz",
+      "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==",
+      "peer": true,
+      "requires": {
+        "@sinonjs/commons": "^3.0.0"
+      }
+    },
+    "@types/applepayjs": {
+      "version": "14.0.9",
+      "resolved": "https://registry.npmmirror.com/@types/applepayjs/-/applepayjs-14.0.9.tgz",
+      "integrity": "sha512-xEprYbb0TEP/XIiDPbVnTYpDai8fTFpsQfVSfTd81Is2GOMUy7ie019eyX6Mz2ECxfjoUVKaiGSL577roIeHCg=="
+    },
+    "@types/babel__core": {
+      "version": "7.20.5",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@types/babel__core/-/babel__core-7.20.5.tgz",
+      "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+      "peer": true,
+      "requires": {
+        "@babel/parser": "^7.20.7",
+        "@babel/types": "^7.20.7",
+        "@types/babel__generator": "*",
+        "@types/babel__template": "*",
+        "@types/babel__traverse": "*"
+      }
+    },
+    "@types/babel__generator": {
+      "version": "7.27.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@types/babel__generator/-/babel__generator-7.27.0.tgz",
+      "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
+      "peer": true,
+      "requires": {
+        "@babel/types": "^7.0.0"
+      }
+    },
+    "@types/babel__template": {
+      "version": "7.4.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@types/babel__template/-/babel__template-7.4.4.tgz",
+      "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+      "peer": true,
+      "requires": {
+        "@babel/parser": "^7.1.0",
+        "@babel/types": "^7.0.0"
+      }
+    },
+    "@types/babel__traverse": {
+      "version": "7.20.7",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@types/babel__traverse/-/babel__traverse-7.20.7.tgz",
+      "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==",
+      "peer": true,
+      "requires": {
+        "@babel/types": "^7.20.7"
+      }
+    },
+    "@types/cordova": {
+      "version": "11.0.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@types/cordova/-/cordova-11.0.3.tgz",
+      "integrity": "sha512-kyuRQ40/NWQVhqGIHq78Ehu2Bf9Mlg0LhmSmis6ZFJK7z933FRfYi8tHe/k/0fB+PGfCf95rJC6TO7dopaFvAg=="
+    },
+    "@types/eslint": {
+      "version": "9.6.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@types/eslint/-/eslint-9.6.1.tgz",
+      "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==",
+      "dev": true,
+      "peer": true,
+      "requires": {
+        "@types/estree": "*",
+        "@types/json-schema": "*"
+      }
+    },
+    "@types/eslint-scope": {
+      "version": "3.7.7",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@types/eslint-scope/-/eslint-scope-3.7.7.tgz",
+      "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==",
+      "dev": true,
+      "peer": true,
+      "requires": {
+        "@types/eslint": "*",
+        "@types/estree": "*"
+      }
+    },
+    "@types/estree": {
+      "version": "1.0.7",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@types/estree/-/estree-1.0.7.tgz",
+      "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ=="
+    },
+    "@types/googlepay": {
+      "version": "0.7.6",
+      "resolved": "https://registry.npmmirror.com/@types/googlepay/-/googlepay-0.7.6.tgz",
+      "integrity": "sha512-5003wG+qvf4Ktf1hC9IJuRakNzQov00+Xf09pAWGJLpdOjUrq0SSLCpXX7pwSeTG9r5hrdzq1iFyZcW7WVyr4g=="
+    },
+    "@types/graceful-fs": {
+      "version": "4.1.9",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@types/graceful-fs/-/graceful-fs-4.1.9.tgz",
+      "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==",
+      "peer": true,
+      "requires": {
+        "@types/node": "*"
+      }
+    },
+    "@types/istanbul-lib-coverage": {
+      "version": "2.0.6",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
+      "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==",
+      "peer": true
+    },
+    "@types/istanbul-lib-report": {
+      "version": "3.0.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz",
+      "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==",
+      "peer": true,
+      "requires": {
+        "@types/istanbul-lib-coverage": "*"
+      }
+    },
+    "@types/istanbul-reports": {
+      "version": "3.0.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz",
+      "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==",
+      "peer": true,
+      "requires": {
+        "@types/istanbul-lib-report": "*"
+      }
+    },
+    "@types/json-schema": {
+      "version": "7.0.15",
+      "resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.15.tgz",
+      "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+      "dev": true
+    },
+    "@types/node": {
+      "version": "22.15.29",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@types/node/-/node-22.15.29.tgz",
+      "integrity": "sha512-LNdjOkUDlU1RZb8e1kOIUpN1qQUlzGkEtbVNo53vbrwDg5om6oduhm4SiUaPW5ASTXhAiP0jInWG8Qx9fVlOeQ==",
+      "peer": true,
+      "requires": {
+        "undici-types": "~6.21.0"
+      }
+    },
+    "@types/stack-utils": {
+      "version": "2.0.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@types/stack-utils/-/stack-utils-2.0.3.tgz",
+      "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==",
+      "peer": true
+    },
+    "@types/yargs": {
+      "version": "17.0.33",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@types/yargs/-/yargs-17.0.33.tgz",
+      "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==",
+      "peer": true,
+      "requires": {
+        "@types/yargs-parser": "*"
+      }
+    },
+    "@types/yargs-parser": {
+      "version": "21.0.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@types/yargs-parser/-/yargs-parser-21.0.3.tgz",
+      "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==",
+      "peer": true
+    },
+    "@vue/compiler-core": {
+      "version": "3.5.16",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/compiler-core/-/compiler-core-3.5.16.tgz",
+      "integrity": "sha512-AOQS2eaQOaaZQoL1u+2rCJIKDruNXVBZSiUD3chnUrsoX5ZTQMaCvXlWNIfxBJuU15r1o7+mpo5223KVtIhAgQ==",
+      "peer": true,
+      "requires": {
+        "@babel/parser": "^7.27.2",
+        "@vue/shared": "3.5.16",
+        "entities": "^4.5.0",
+        "estree-walker": "^2.0.2",
+        "source-map-js": "^1.2.1"
+      },
+      "dependencies": {
+        "estree-walker": {
+          "version": "2.0.2",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/estree-walker/-/estree-walker-2.0.2.tgz",
+          "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
+          "peer": true
+        }
+      }
+    },
+    "@vue/compiler-dom": {
+      "version": "3.5.16",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/compiler-dom/-/compiler-dom-3.5.16.tgz",
+      "integrity": "sha512-SSJIhBr/teipXiXjmWOVWLnxjNGo65Oj/8wTEQz0nqwQeP75jWZ0n4sF24Zxoht1cuJoWopwj0J0exYwCJ0dCQ==",
+      "peer": true,
+      "requires": {
+        "@vue/compiler-core": "3.5.16",
+        "@vue/shared": "3.5.16"
+      }
+    },
+    "@vue/compiler-sfc": {
+      "version": "3.5.16",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/compiler-sfc/-/compiler-sfc-3.5.16.tgz",
+      "integrity": "sha512-rQR6VSFNpiinDy/DVUE0vHoIDUF++6p910cgcZoaAUm3POxgNOOdS/xgoll3rNdKYTYPnnbARDCZOyZ+QSe6Pw==",
+      "peer": true,
+      "requires": {
+        "@babel/parser": "^7.27.2",
+        "@vue/compiler-core": "3.5.16",
+        "@vue/compiler-dom": "3.5.16",
+        "@vue/compiler-ssr": "3.5.16",
+        "@vue/shared": "3.5.16",
+        "estree-walker": "^2.0.2",
+        "magic-string": "^0.30.17",
+        "postcss": "^8.5.3",
+        "source-map-js": "^1.2.1"
+      },
+      "dependencies": {
+        "estree-walker": {
+          "version": "2.0.2",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/estree-walker/-/estree-walker-2.0.2.tgz",
+          "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
+          "peer": true
+        }
+      }
+    },
+    "@vue/compiler-ssr": {
+      "version": "3.5.16",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/compiler-ssr/-/compiler-ssr-3.5.16.tgz",
+      "integrity": "sha512-d2V7kfxbdsjrDSGlJE7my1ZzCXViEcqN6w14DOsDrUCHEA6vbnVCpRFfrc4ryCP/lCKzX2eS1YtnLE/BuC9f/A==",
+      "peer": true,
+      "requires": {
+        "@vue/compiler-dom": "3.5.16",
+        "@vue/shared": "3.5.16"
+      }
+    },
+    "@vue/devtools-api": {
+      "version": "7.7.2",
+      "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-7.7.2.tgz",
+      "integrity": "sha512-1syn558KhyN+chO5SjlZIwJ8bV/bQ1nOVTG66t2RbG66ZGekyiYNmRO7X9BJCXQqPsFHlnksqvPhce2qpzxFnA==",
+      "requires": {
+        "@vue/devtools-kit": "^7.7.2"
+      }
+    },
+    "@vue/devtools-kit": {
+      "version": "7.7.2",
+      "resolved": "https://registry.npmmirror.com/@vue/devtools-kit/-/devtools-kit-7.7.2.tgz",
+      "integrity": "sha512-CY0I1JH3Z8PECbn6k3TqM1Bk9ASWxeMtTCvZr7vb+CHi+X/QwQm5F1/fPagraamKMAHVfuuCbdcnNg1A4CYVWQ==",
+      "requires": {
+        "@vue/devtools-shared": "^7.7.2",
+        "birpc": "^0.2.19",
+        "hookable": "^5.5.3",
+        "mitt": "^3.0.1",
+        "perfect-debounce": "^1.0.0",
+        "speakingurl": "^14.0.1",
+        "superjson": "^2.2.1"
+      }
+    },
+    "@vue/devtools-shared": {
+      "version": "7.7.2",
+      "resolved": "https://registry.npmmirror.com/@vue/devtools-shared/-/devtools-shared-7.7.2.tgz",
+      "integrity": "sha512-uBFxnp8gwW2vD6FrJB8JZLUzVb6PNRG0B0jBnHsOH8uKyva2qINY8PTF5Te4QlTbMDqU5K6qtJDr6cNsKWhbOA==",
+      "requires": {
+        "rfdc": "^1.4.1"
+      }
+    },
+    "@vue/reactivity": {
+      "version": "3.5.16",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/reactivity/-/reactivity-3.5.16.tgz",
+      "integrity": "sha512-FG5Q5ee/kxhIm1p2bykPpPwqiUBV3kFySsHEQha5BJvjXdZTUfmya7wP7zC39dFuZAcf/PD5S4Lni55vGLMhvA==",
+      "peer": true,
+      "requires": {
+        "@vue/shared": "3.5.16"
+      }
+    },
+    "@vue/runtime-core": {
+      "version": "3.5.16",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/runtime-core/-/runtime-core-3.5.16.tgz",
+      "integrity": "sha512-bw5Ykq6+JFHYxrQa7Tjr+VSzw7Dj4ldR/udyBZbq73fCdJmyy5MPIFR9IX/M5Qs+TtTjuyUTCnmK3lWWwpAcFQ==",
+      "peer": true,
+      "requires": {
+        "@vue/reactivity": "3.5.16",
+        "@vue/shared": "3.5.16"
+      }
+    },
+    "@vue/runtime-dom": {
+      "version": "3.5.16",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/runtime-dom/-/runtime-dom-3.5.16.tgz",
+      "integrity": "sha512-T1qqYJsG2xMGhImRUV9y/RseB9d0eCYZQ4CWca9ztCuiPj/XWNNN+lkNBuzVbia5z4/cgxdL28NoQCvC0Xcfww==",
+      "peer": true,
+      "requires": {
+        "@vue/reactivity": "3.5.16",
+        "@vue/runtime-core": "3.5.16",
+        "@vue/shared": "3.5.16",
+        "csstype": "^3.1.3"
+      }
+    },
+    "@vue/server-renderer": {
+      "version": "3.5.16",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/server-renderer/-/server-renderer-3.5.16.tgz",
+      "integrity": "sha512-BrX0qLiv/WugguGsnQUJiYOE0Fe5mZTwi6b7X/ybGB0vfrPH9z0gD/Y6WOR1sGCgX4gc25L1RYS5eYQKDMoNIg==",
+      "peer": true,
+      "requires": {
+        "@vue/compiler-ssr": "3.5.16",
+        "@vue/shared": "3.5.16"
+      }
+    },
+    "@vue/shared": {
+      "version": "3.5.16",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@vue/shared/-/shared-3.5.16.tgz",
+      "integrity": "sha512-c/0fWy3Jw6Z8L9FmTyYfkpM5zklnqqa9+a6dz3DvONRKW2NEbh46BP0FHuLFSWi2TnQEtp91Z6zOWNrU6QiyPg==",
+      "peer": true
+    },
+    "@webassemblyjs/ast": {
+      "version": "1.14.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@webassemblyjs/ast/-/ast-1.14.1.tgz",
+      "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==",
+      "dev": true,
+      "peer": true,
+      "requires": {
+        "@webassemblyjs/helper-numbers": "1.13.2",
+        "@webassemblyjs/helper-wasm-bytecode": "1.13.2"
+      }
+    },
+    "@webassemblyjs/floating-point-hex-parser": {
+      "version": "1.13.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz",
+      "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==",
+      "dev": true,
+      "peer": true
+    },
+    "@webassemblyjs/helper-api-error": {
+      "version": "1.13.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz",
+      "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==",
+      "dev": true,
+      "peer": true
+    },
+    "@webassemblyjs/helper-buffer": {
+      "version": "1.14.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz",
+      "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==",
+      "dev": true,
+      "peer": true
+    },
+    "@webassemblyjs/helper-numbers": {
+      "version": "1.13.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz",
+      "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==",
+      "dev": true,
+      "peer": true,
+      "requires": {
+        "@webassemblyjs/floating-point-hex-parser": "1.13.2",
+        "@webassemblyjs/helper-api-error": "1.13.2",
+        "@xtuc/long": "4.2.2"
+      }
+    },
+    "@webassemblyjs/helper-wasm-bytecode": {
+      "version": "1.13.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz",
+      "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==",
+      "dev": true,
+      "peer": true
+    },
+    "@webassemblyjs/helper-wasm-section": {
+      "version": "1.14.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz",
+      "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==",
+      "dev": true,
+      "peer": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.14.1",
+        "@webassemblyjs/helper-buffer": "1.14.1",
+        "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+        "@webassemblyjs/wasm-gen": "1.14.1"
+      }
+    },
+    "@webassemblyjs/ieee754": {
+      "version": "1.13.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz",
+      "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==",
+      "dev": true,
+      "peer": true,
+      "requires": {
+        "@xtuc/ieee754": "^1.2.0"
+      }
+    },
+    "@webassemblyjs/leb128": {
+      "version": "1.13.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@webassemblyjs/leb128/-/leb128-1.13.2.tgz",
+      "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==",
+      "dev": true,
+      "peer": true,
+      "requires": {
+        "@xtuc/long": "4.2.2"
+      }
+    },
+    "@webassemblyjs/utf8": {
+      "version": "1.13.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@webassemblyjs/utf8/-/utf8-1.13.2.tgz",
+      "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==",
+      "dev": true,
+      "peer": true
+    },
+    "@webassemblyjs/wasm-edit": {
+      "version": "1.14.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz",
+      "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==",
+      "dev": true,
+      "peer": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.14.1",
+        "@webassemblyjs/helper-buffer": "1.14.1",
+        "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+        "@webassemblyjs/helper-wasm-section": "1.14.1",
+        "@webassemblyjs/wasm-gen": "1.14.1",
+        "@webassemblyjs/wasm-opt": "1.14.1",
+        "@webassemblyjs/wasm-parser": "1.14.1",
+        "@webassemblyjs/wast-printer": "1.14.1"
+      }
+    },
+    "@webassemblyjs/wasm-gen": {
+      "version": "1.14.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz",
+      "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==",
+      "dev": true,
+      "peer": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.14.1",
+        "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+        "@webassemblyjs/ieee754": "1.13.2",
+        "@webassemblyjs/leb128": "1.13.2",
+        "@webassemblyjs/utf8": "1.13.2"
+      }
+    },
+    "@webassemblyjs/wasm-opt": {
+      "version": "1.14.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz",
+      "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==",
+      "dev": true,
+      "peer": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.14.1",
+        "@webassemblyjs/helper-buffer": "1.14.1",
+        "@webassemblyjs/wasm-gen": "1.14.1",
+        "@webassemblyjs/wasm-parser": "1.14.1"
+      }
+    },
+    "@webassemblyjs/wasm-parser": {
+      "version": "1.14.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz",
+      "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==",
+      "dev": true,
+      "peer": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.14.1",
+        "@webassemblyjs/helper-api-error": "1.13.2",
+        "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+        "@webassemblyjs/ieee754": "1.13.2",
+        "@webassemblyjs/leb128": "1.13.2",
+        "@webassemblyjs/utf8": "1.13.2"
+      }
+    },
+    "@webassemblyjs/wast-printer": {
+      "version": "1.14.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz",
+      "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==",
+      "dev": true,
+      "peer": true,
+      "requires": {
+        "@webassemblyjs/ast": "1.14.1",
+        "@xtuc/long": "4.2.2"
+      }
+    },
+    "@xtuc/ieee754": {
+      "version": "1.2.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
+      "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
+      "dev": true,
+      "peer": true
+    },
+    "@xtuc/long": {
+      "version": "4.2.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/@xtuc/long/-/long-4.2.2.tgz",
+      "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
+      "dev": true,
+      "peer": true
+    },
+    "abort-controller": {
+      "version": "3.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/abort-controller/-/abort-controller-3.0.0.tgz",
+      "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
+      "peer": true,
+      "requires": {
+        "event-target-shim": "^5.0.0"
+      }
+    },
+    "accepts": {
+      "version": "1.3.8",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/accepts/-/accepts-1.3.8.tgz",
+      "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
+      "peer": true,
+      "requires": {
+        "mime-types": "~2.1.34",
+        "negotiator": "0.6.3"
+      }
+    },
+    "acorn": {
+      "version": "8.14.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/acorn/-/acorn-8.14.1.tgz",
+      "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg=="
+    },
+    "agent-base": {
+      "version": "7.1.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/agent-base/-/agent-base-7.1.3.tgz",
+      "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==",
+      "peer": true
+    },
+    "airwallex-payment-elements": {
+      "version": "1.122.0",
+      "resolved": "https://registry.npmmirror.com/airwallex-payment-elements/-/airwallex-payment-elements-1.122.0.tgz",
+      "integrity": "sha512-DbIu3NtonRrJk8yHQHR+Wx3tcUFVscfRYuNPLd4ylxxLw2KqvIeDHdRybOk1u5qihaAZVIJa9erwYuMO8qjp8Q==",
+      "requires": {
+        "@types/applepayjs": "^14.0.9",
+        "@types/googlepay": "^0.7.6",
+        "csstype": "^3.0.6",
+        "eslint-plugin-tsdoc": "^0.4.0"
+      }
+    },
+    "ajv": {
+      "version": "6.12.6",
+      "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz",
+      "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+      "dev": true,
+      "requires": {
+        "fast-deep-equal": "^3.1.1",
+        "fast-json-stable-stringify": "^2.0.0",
+        "json-schema-traverse": "^0.4.1",
+        "uri-js": "^4.2.2"
+      }
+    },
+    "ajv-formats": {
+      "version": "2.1.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ajv-formats/-/ajv-formats-2.1.1.tgz",
+      "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
+      "dev": true,
+      "peer": true,
+      "requires": {
+        "ajv": "^8.0.0"
+      },
+      "dependencies": {
+        "ajv": {
+          "version": "8.17.1",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/ajv/-/ajv-8.17.1.tgz",
+          "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
+          "dev": true,
+          "peer": true,
+          "requires": {
+            "fast-deep-equal": "^3.1.3",
+            "fast-uri": "^3.0.1",
+            "json-schema-traverse": "^1.0.0",
+            "require-from-string": "^2.0.2"
+          }
+        },
+        "json-schema-traverse": {
+          "version": "1.0.0",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+          "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+          "dev": true,
+          "peer": true
+        }
+      }
+    },
+    "ajv-keywords": {
+      "version": "3.5.2",
+      "resolved": "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
+      "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
+      "dev": true,
+      "requires": {}
+    },
+    "anser": {
+      "version": "1.4.10",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/anser/-/anser-1.4.10.tgz",
+      "integrity": "sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==",
+      "peer": true
+    },
+    "ansi-regex": {
+      "version": "5.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-regex/-/ansi-regex-5.0.1.tgz",
+      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+      "peer": true
+    },
+    "ansi-styles": {
+      "version": "4.3.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-styles/-/ansi-styles-4.3.0.tgz",
+      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+      "peer": true,
+      "requires": {
+        "color-convert": "^2.0.1"
+      }
+    },
+    "anymatch": {
+      "version": "3.1.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/anymatch/-/anymatch-3.1.3.tgz",
+      "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+      "peer": true,
+      "requires": {
+        "normalize-path": "^3.0.0",
+        "picomatch": "^2.0.4"
+      }
+    },
+    "argparse": {
+      "version": "1.0.10",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/argparse/-/argparse-1.0.10.tgz",
+      "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+      "peer": true,
+      "requires": {
+        "sprintf-js": "~1.0.2"
+      }
+    },
+    "asap": {
+      "version": "2.0.6",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/asap/-/asap-2.0.6.tgz",
+      "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==",
+      "peer": true
+    },
+    "async-limiter": {
+      "version": "1.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/async-limiter/-/async-limiter-1.0.1.tgz",
+      "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==",
+      "peer": true
+    },
+    "babel-jest": {
+      "version": "29.7.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/babel-jest/-/babel-jest-29.7.0.tgz",
+      "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==",
+      "peer": true,
+      "requires": {
+        "@jest/transform": "^29.7.0",
+        "@types/babel__core": "^7.1.14",
+        "babel-plugin-istanbul": "^6.1.1",
+        "babel-preset-jest": "^29.6.3",
+        "chalk": "^4.0.0",
+        "graceful-fs": "^4.2.9",
+        "slash": "^3.0.0"
+      }
+    },
+    "babel-plugin-istanbul": {
+      "version": "6.1.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz",
+      "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==",
+      "peer": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.0.0",
+        "@istanbuljs/load-nyc-config": "^1.0.0",
+        "@istanbuljs/schema": "^0.1.2",
+        "istanbul-lib-instrument": "^5.0.4",
+        "test-exclude": "^6.0.0"
+      }
+    },
+    "babel-plugin-jest-hoist": {
+      "version": "29.6.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz",
+      "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==",
+      "peer": true,
+      "requires": {
+        "@babel/template": "^7.3.3",
+        "@babel/types": "^7.3.3",
+        "@types/babel__core": "^7.1.14",
+        "@types/babel__traverse": "^7.0.6"
+      }
+    },
+    "babel-plugin-syntax-hermes-parser": {
+      "version": "0.25.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.25.1.tgz",
+      "integrity": "sha512-IVNpGzboFLfXZUAwkLFcI/bnqVbwky0jP3eBno4HKtqvQJAHBLdgxiG6lQ4to0+Q/YCN3PO0od5NZwIKyY4REQ==",
+      "peer": true,
+      "requires": {
+        "hermes-parser": "0.25.1"
+      }
+    },
+    "babel-preset-current-node-syntax": {
+      "version": "1.1.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz",
+      "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==",
+      "peer": true,
+      "requires": {
+        "@babel/plugin-syntax-async-generators": "^7.8.4",
+        "@babel/plugin-syntax-bigint": "^7.8.3",
+        "@babel/plugin-syntax-class-properties": "^7.12.13",
+        "@babel/plugin-syntax-class-static-block": "^7.14.5",
+        "@babel/plugin-syntax-import-attributes": "^7.24.7",
+        "@babel/plugin-syntax-import-meta": "^7.10.4",
+        "@babel/plugin-syntax-json-strings": "^7.8.3",
+        "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
+        "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
+        "@babel/plugin-syntax-numeric-separator": "^7.10.4",
+        "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+        "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
+        "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+        "@babel/plugin-syntax-private-property-in-object": "^7.14.5",
+        "@babel/plugin-syntax-top-level-await": "^7.14.5"
+      }
+    },
+    "babel-preset-jest": {
+      "version": "29.6.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz",
+      "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==",
+      "peer": true,
+      "requires": {
+        "babel-plugin-jest-hoist": "^29.6.3",
+        "babel-preset-current-node-syntax": "^1.0.0"
+      }
+    },
+    "balanced-match": {
+      "version": "1.0.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/balanced-match/-/balanced-match-1.0.2.tgz",
+      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+      "peer": true
+    },
+    "base64-js": {
+      "version": "1.5.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/base64-js/-/base64-js-1.5.1.tgz",
+      "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+      "peer": true
+    },
+    "big.js": {
+      "version": "5.2.2",
+      "resolved": "https://registry.npmmirror.com/big.js/-/big.js-5.2.2.tgz",
+      "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==",
+      "dev": true
+    },
+    "birpc": {
+      "version": "0.2.19",
+      "resolved": "https://registry.npmmirror.com/birpc/-/birpc-0.2.19.tgz",
+      "integrity": "sha512-5WeXXAvTmitV1RqJFppT5QtUiz2p1mRSYU000Jkft5ZUCLJIk4uQriYNO50HknxKwM6jd8utNc66K1qGIwwWBQ=="
+    },
+    "brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "peer": true,
+      "requires": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "braces": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.3.tgz",
+      "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+      "requires": {
+        "fill-range": "^7.1.1"
+      }
+    },
+    "browserslist": {
+      "version": "4.25.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/browserslist/-/browserslist-4.25.0.tgz",
+      "integrity": "sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA==",
+      "peer": true,
+      "requires": {
+        "caniuse-lite": "^1.0.30001718",
+        "electron-to-chromium": "^1.5.160",
+        "node-releases": "^2.0.19",
+        "update-browserslist-db": "^1.1.3"
+      }
+    },
+    "bser": {
+      "version": "2.1.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/bser/-/bser-2.1.1.tgz",
+      "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==",
+      "peer": true,
+      "requires": {
+        "node-int64": "^0.4.0"
+      }
+    },
+    "buffer-from": {
+      "version": "1.1.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/buffer-from/-/buffer-from-1.1.2.tgz",
+      "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+      "peer": true
+    },
+    "c12": {
+      "version": "3.0.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/c12/-/c12-3.0.4.tgz",
+      "integrity": "sha512-t5FaZTYbbCtvxuZq9xxIruYydrAGsJ+8UdP0pZzMiK2xl/gNiSOy0OxhLzHUEEb0m1QXYqfzfvyIFEmz/g9lqg==",
+      "requires": {
+        "chokidar": "^4.0.3",
+        "confbox": "^0.2.2",
+        "defu": "^6.1.4",
+        "dotenv": "^16.5.0",
+        "exsolve": "^1.0.5",
+        "giget": "^2.0.0",
+        "jiti": "^2.4.2",
+        "ohash": "^2.0.11",
+        "pathe": "^2.0.3",
+        "perfect-debounce": "^1.0.0",
+        "pkg-types": "^2.1.0",
+        "rc9": "^2.1.2"
+      }
+    },
+    "caller-callsite": {
+      "version": "2.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/caller-callsite/-/caller-callsite-2.0.0.tgz",
+      "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=",
+      "peer": true,
+      "requires": {
+        "callsites": "^2.0.0"
+      }
+    },
+    "caller-path": {
+      "version": "2.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/caller-path/-/caller-path-2.0.0.tgz",
+      "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=",
+      "peer": true,
+      "requires": {
+        "caller-callsite": "^2.0.0"
+      }
+    },
+    "callsites": {
+      "version": "2.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/callsites/-/callsites-2.0.0.tgz",
+      "integrity": "sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==",
+      "peer": true
+    },
+    "camelcase": {
+      "version": "5.3.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/camelcase/-/camelcase-5.3.1.tgz",
+      "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+      "peer": true
+    },
+    "caniuse-lite": {
+      "version": "1.0.30001721",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/caniuse-lite/-/caniuse-lite-1.0.30001721.tgz",
+      "integrity": "sha512-cOuvmUVtKrtEaoKiO0rSc29jcjwMwX5tOHDy4MgVFEWiUXj4uBMJkwI8MDySkgXidpMiHUcviogAvFi4pA2hDQ==",
+      "peer": true
+    },
+    "chalk": {
+      "version": "4.1.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/chalk/-/chalk-4.1.2.tgz",
+      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+      "peer": true,
+      "requires": {
+        "ansi-styles": "^4.1.0",
+        "supports-color": "^7.1.0"
+      },
+      "dependencies": {
+        "supports-color": {
+          "version": "7.2.0",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/supports-color/-/supports-color-7.2.0.tgz",
+          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+          "peer": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
+      }
+    },
+    "chokidar": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-4.0.3.tgz",
+      "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
+      "requires": {
+        "readdirp": "^4.0.1"
+      }
+    },
+    "chrome-launcher": {
+      "version": "0.15.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/chrome-launcher/-/chrome-launcher-0.15.2.tgz",
+      "integrity": "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==",
+      "peer": true,
+      "requires": {
+        "@types/node": "*",
+        "escape-string-regexp": "^4.0.0",
+        "is-wsl": "^2.2.0",
+        "lighthouse-logger": "^1.0.0"
+      },
+      "dependencies": {
+        "escape-string-regexp": {
+          "version": "4.0.0",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+          "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+          "peer": true
+        }
+      }
+    },
+    "chrome-trace-event": {
+      "version": "1.0.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz",
+      "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==",
+      "dev": true,
+      "peer": true
+    },
+    "chromium-edge-launcher": {
+      "version": "0.2.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/chromium-edge-launcher/-/chromium-edge-launcher-0.2.0.tgz",
+      "integrity": "sha512-JfJjUnq25y9yg4FABRRVPmBGWPZZi+AQXT4mxupb67766/0UlhG8PAZCz6xzEMXTbW3CsSoE8PcCWA49n35mKg==",
+      "peer": true,
+      "requires": {
+        "@types/node": "*",
+        "escape-string-regexp": "^4.0.0",
+        "is-wsl": "^2.2.0",
+        "lighthouse-logger": "^1.0.0",
+        "mkdirp": "^1.0.4",
+        "rimraf": "^3.0.2"
+      },
+      "dependencies": {
+        "escape-string-regexp": {
+          "version": "4.0.0",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+          "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+          "peer": true
+        }
+      }
+    },
+    "ci-info": {
+      "version": "3.9.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ci-info/-/ci-info-3.9.0.tgz",
+      "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+      "peer": true
+    },
+    "citty": {
+      "version": "0.1.6",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/citty/-/citty-0.1.6.tgz",
+      "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==",
+      "requires": {
+        "consola": "^3.2.3"
+      }
+    },
+    "clipboard": {
+      "version": "2.0.11",
+      "resolved": "https://registry.npmmirror.com/clipboard/-/clipboard-2.0.11.tgz",
+      "integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==",
+      "requires": {
+        "good-listener": "^1.2.2",
+        "select": "^1.1.2",
+        "tiny-emitter": "^2.0.0"
+      }
+    },
+    "cliui": {
+      "version": "8.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/cliui/-/cliui-8.0.1.tgz",
+      "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+      "peer": true,
+      "requires": {
+        "string-width": "^4.2.0",
+        "strip-ansi": "^6.0.1",
+        "wrap-ansi": "^7.0.0"
+      }
+    },
+    "color-convert": {
+      "version": "2.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/color-convert/-/color-convert-2.0.1.tgz",
+      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+      "peer": true,
+      "requires": {
+        "color-name": "~1.1.4"
+      }
+    },
+    "color-name": {
+      "version": "1.1.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/color-name/-/color-name-1.1.4.tgz",
+      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+      "peer": true
+    },
+    "commander": {
+      "version": "2.20.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/commander/-/commander-2.20.3.tgz",
+      "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+      "peer": true
+    },
+    "concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+      "peer": true
+    },
+    "confbox": {
+      "version": "0.2.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/confbox/-/confbox-0.2.2.tgz",
+      "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ=="
+    },
+    "connect": {
+      "version": "3.7.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/connect/-/connect-3.7.0.tgz",
+      "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==",
+      "peer": true,
+      "requires": {
+        "debug": "2.6.9",
+        "finalhandler": "1.1.2",
+        "parseurl": "~1.3.3",
+        "utils-merge": "1.0.1"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "peer": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "ms": {
+          "version": "2.0.0",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz",
+          "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+          "peer": true
+        }
+      }
+    },
+    "consola": {
+      "version": "3.4.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/consola/-/consola-3.4.2.tgz",
+      "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA=="
+    },
+    "convert-source-map": {
+      "version": "2.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/convert-source-map/-/convert-source-map-2.0.0.tgz",
+      "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+      "peer": true
+    },
+    "copy-anything": {
+      "version": "3.0.5",
+      "resolved": "https://registry.npmmirror.com/copy-anything/-/copy-anything-3.0.5.tgz",
+      "integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==",
+      "requires": {
+        "is-what": "^4.1.8"
+      }
+    },
+    "cosmiconfig": {
+      "version": "5.2.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/cosmiconfig/-/cosmiconfig-5.2.1.tgz",
+      "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==",
+      "peer": true,
+      "requires": {
+        "import-fresh": "^2.0.0",
+        "is-directory": "^0.3.1",
+        "js-yaml": "^3.13.1",
+        "parse-json": "^4.0.0"
+      }
+    },
+    "csstype": {
+      "version": "3.1.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/csstype/-/csstype-3.1.3.tgz",
+      "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
+    },
+    "dayjs": {
+      "version": "1.11.13",
+      "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.13.tgz",
+      "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg=="
+    },
+    "debug": {
+      "version": "4.4.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-4.4.1.tgz",
+      "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+      "peer": true,
+      "requires": {
+        "ms": "^2.1.3"
+      }
+    },
+    "deep-pick-omit": {
+      "version": "1.2.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/deep-pick-omit/-/deep-pick-omit-1.2.1.tgz",
+      "integrity": "sha512-2J6Kc/m3irCeqVG42T+SaUMesaK7oGWaedGnQQK/+O0gYc+2SP5bKh/KKTE7d7SJ+GCA9UUE1GRzh6oDe0EnGw=="
+    },
+    "defu": {
+      "version": "6.1.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/defu/-/defu-6.1.4.tgz",
+      "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg=="
+    },
+    "delegate": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmmirror.com/delegate/-/delegate-3.2.0.tgz",
+      "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw=="
+    },
+    "depd": {
+      "version": "2.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/depd/-/depd-2.0.0.tgz",
+      "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+      "peer": true
+    },
+    "destr": {
+      "version": "2.0.5",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/destr/-/destr-2.0.5.tgz",
+      "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA=="
+    },
+    "destroy": {
+      "version": "1.2.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/destroy/-/destroy-1.2.0.tgz",
+      "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
+      "peer": true
+    },
+    "detect-libc": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-1.0.3.tgz",
+      "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==",
+      "dev": true,
+      "optional": true
+    },
+    "dotenv": {
+      "version": "16.5.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/dotenv/-/dotenv-16.5.0.tgz",
+      "integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg=="
+    },
+    "ee-first": {
+      "version": "1.1.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ee-first/-/ee-first-1.1.1.tgz",
+      "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
+      "peer": true
+    },
+    "electron-to-chromium": {
+      "version": "1.5.163",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/electron-to-chromium/-/electron-to-chromium-1.5.163.tgz",
+      "integrity": "sha512-y6WESxcFekrMfiz9+pTLNacCTsOyeha5JkleNgE12k+7M8P8gaA09h6r/Kc5m2iQ87V9taexvLjAl2ILdJ+xmw==",
+      "peer": true
+    },
+    "emoji-regex": {
+      "version": "8.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/emoji-regex/-/emoji-regex-8.0.0.tgz",
+      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+      "peer": true
+    },
+    "emojis-list": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmmirror.com/emojis-list/-/emojis-list-3.0.0.tgz",
+      "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
+      "dev": true
+    },
+    "encodeurl": {
+      "version": "1.0.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/encodeurl/-/encodeurl-1.0.2.tgz",
+      "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
+      "peer": true
+    },
+    "enhanced-resolve": {
+      "version": "5.18.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz",
+      "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==",
+      "dev": true,
+      "peer": true,
+      "requires": {
+        "graceful-fs": "^4.2.4",
+        "tapable": "^2.2.0"
+      }
+    },
+    "entities": {
+      "version": "4.5.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/entities/-/entities-4.5.0.tgz",
+      "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+      "peer": true
+    },
+    "error-ex": {
+      "version": "1.3.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/error-ex/-/error-ex-1.3.2.tgz",
+      "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+      "peer": true,
+      "requires": {
+        "is-arrayish": "^0.2.1"
+      }
+    },
+    "error-stack-parser": {
+      "version": "2.1.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/error-stack-parser/-/error-stack-parser-2.1.4.tgz",
+      "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==",
+      "peer": true,
+      "requires": {
+        "stackframe": "^1.3.4"
+      }
+    },
+    "errx": {
+      "version": "0.1.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/errx/-/errx-0.1.0.tgz",
+      "integrity": "sha512-fZmsRiDNv07K6s2KkKFTiD2aIvECa7++PKyD5NC32tpRw46qZA3sOz+aM+/V9V0GDHxVTKLziveV4JhzBHDp9Q=="
+    },
+    "es-module-lexer": {
+      "version": "1.7.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
+      "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==",
+      "dev": true,
+      "peer": true
+    },
+    "escalade": {
+      "version": "3.2.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/escalade/-/escalade-3.2.0.tgz",
+      "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+      "peer": true
+    },
+    "escape-html": {
+      "version": "1.0.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/escape-html/-/escape-html-1.0.3.tgz",
+      "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
+      "peer": true
+    },
+    "escape-string-regexp": {
+      "version": "5.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
+      "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="
+    },
+    "eslint-plugin-tsdoc": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmmirror.com/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.4.0.tgz",
+      "integrity": "sha512-MT/8b4aKLdDClnS8mP3R/JNjg29i0Oyqd/0ym6NnQf+gfKbJJ4ZcSh2Bs1H0YiUMTBwww5JwXGTWot/RwyJ7aQ==",
+      "requires": {
+        "@microsoft/tsdoc": "0.15.1",
+        "@microsoft/tsdoc-config": "0.17.1"
+      }
+    },
+    "eslint-scope": {
+      "version": "5.1.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/eslint-scope/-/eslint-scope-5.1.1.tgz",
+      "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+      "dev": true,
+      "peer": true,
+      "requires": {
+        "esrecurse": "^4.3.0",
+        "estraverse": "^4.1.1"
+      }
+    },
+    "esprima": {
+      "version": "4.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/esprima/-/esprima-4.0.1.tgz",
+      "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+      "peer": true
+    },
+    "esrecurse": {
+      "version": "4.3.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/esrecurse/-/esrecurse-4.3.0.tgz",
+      "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+      "dev": true,
+      "peer": true,
+      "requires": {
+        "estraverse": "^5.2.0"
+      },
+      "dependencies": {
+        "estraverse": {
+          "version": "5.3.0",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/estraverse/-/estraverse-5.3.0.tgz",
+          "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+          "dev": true,
+          "peer": true
+        }
+      }
+    },
+    "estraverse": {
+      "version": "4.3.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/estraverse/-/estraverse-4.3.0.tgz",
+      "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+      "dev": true,
+      "peer": true
+    },
+    "estree-walker": {
+      "version": "3.0.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/estree-walker/-/estree-walker-3.0.3.tgz",
+      "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
+      "requires": {
+        "@types/estree": "^1.0.0"
+      }
+    },
+    "etag": {
+      "version": "1.8.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/etag/-/etag-1.8.1.tgz",
+      "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+      "peer": true
+    },
+    "event-target-shim": {
+      "version": "5.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/event-target-shim/-/event-target-shim-5.0.1.tgz",
+      "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
+      "peer": true
+    },
+    "events": {
+      "version": "3.3.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/events/-/events-3.3.0.tgz",
+      "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+      "dev": true,
+      "peer": true
+    },
+    "exponential-backoff": {
+      "version": "3.1.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/exponential-backoff/-/exponential-backoff-3.1.2.tgz",
+      "integrity": "sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==",
+      "peer": true
+    },
+    "exsolve": {
+      "version": "1.0.5",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/exsolve/-/exsolve-1.0.5.tgz",
+      "integrity": "sha512-pz5dvkYYKQ1AHVrgOzBKWeP4u4FRb3a6DNK2ucr0OoNwYIU4QWsJ+NM36LLzORT+z845MzKHHhpXiUF5nvQoJg=="
+    },
+    "fast-deep-equal": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
+    },
+    "fast-json-stable-stringify": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+      "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
+    },
+    "fast-uri": {
+      "version": "3.0.6",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/fast-uri/-/fast-uri-3.0.6.tgz",
+      "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==",
+      "dev": true,
+      "peer": true
+    },
+    "fb-sdk": {
+      "version": "1.0.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/fb-sdk/-/fb-sdk-1.0.3.tgz",
+      "integrity": "sha512-i1n/72J9u2pS6tLlIydilRlu8GrcsgPqs+0JOW6dH2CB5Pu4CjfCbpPqjlw+pbA02ViHg2J2O1mm7TDLbgiDUg==",
+      "requires": {
+        "load-script": "^1.0.0"
+      }
+    },
+    "fb-watchman": {
+      "version": "2.0.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/fb-watchman/-/fb-watchman-2.0.2.tgz",
+      "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==",
+      "peer": true,
+      "requires": {
+        "bser": "2.1.1"
+      }
+    },
+    "fill-range": {
+      "version": "7.1.1",
+      "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.1.1.tgz",
+      "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+      "requires": {
+        "to-regex-range": "^5.0.1"
+      }
+    },
+    "finalhandler": {
+      "version": "1.1.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/finalhandler/-/finalhandler-1.1.2.tgz",
+      "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
+      "peer": true,
+      "requires": {
+        "debug": "2.6.9",
+        "encodeurl": "~1.0.2",
+        "escape-html": "~1.0.3",
+        "on-finished": "~2.3.0",
+        "parseurl": "~1.3.3",
+        "statuses": "~1.5.0",
+        "unpipe": "~1.0.0"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "peer": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "ms": {
+          "version": "2.0.0",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz",
+          "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+          "peer": true
+        }
+      }
+    },
+    "find-up": {
+      "version": "4.1.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/find-up/-/find-up-4.1.0.tgz",
+      "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+      "peer": true,
+      "requires": {
+        "locate-path": "^5.0.0",
+        "path-exists": "^4.0.0"
+      }
+    },
+    "flow-enums-runtime": {
+      "version": "0.0.6",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz",
+      "integrity": "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==",
+      "peer": true
+    },
+    "fresh": {
+      "version": "0.5.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/fresh/-/fresh-0.5.2.tgz",
+      "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
+      "peer": true
+    },
+    "fs.realpath": {
+      "version": "1.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/fs.realpath/-/fs.realpath-1.0.0.tgz",
+      "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+      "peer": true
+    },
+    "fsevents": {
+      "version": "2.3.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/fsevents/-/fsevents-2.3.3.tgz",
+      "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+      "optional": true,
+      "peer": true
+    },
+    "function-bind": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz",
+      "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="
+    },
+    "gensync": {
+      "version": "1.0.0-beta.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/gensync/-/gensync-1.0.0-beta.2.tgz",
+      "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+      "peer": true
+    },
+    "get-caller-file": {
+      "version": "2.0.5",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/get-caller-file/-/get-caller-file-2.0.5.tgz",
+      "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+      "peer": true
+    },
+    "get-package-type": {
+      "version": "0.1.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/get-package-type/-/get-package-type-0.1.0.tgz",
+      "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
+      "peer": true
+    },
+    "giget": {
+      "version": "2.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/giget/-/giget-2.0.0.tgz",
+      "integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==",
+      "requires": {
+        "citty": "^0.1.6",
+        "consola": "^3.4.0",
+        "defu": "^6.1.4",
+        "node-fetch-native": "^1.6.6",
+        "nypm": "^0.6.0",
+        "pathe": "^2.0.3"
+      }
+    },
+    "glob": {
+      "version": "7.2.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/glob/-/glob-7.2.3.tgz",
+      "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+      "peer": true,
+      "requires": {
+        "fs.realpath": "^1.0.0",
+        "inflight": "^1.0.4",
+        "inherits": "2",
+        "minimatch": "^3.1.1",
+        "once": "^1.3.0",
+        "path-is-absolute": "^1.0.0"
+      }
+    },
+    "glob-to-regexp": {
+      "version": "0.4.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
+      "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
+      "dev": true,
+      "peer": true
+    },
+    "globals": {
+      "version": "11.12.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/globals/-/globals-11.12.0.tgz",
+      "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+      "peer": true
+    },
+    "good-listener": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmmirror.com/good-listener/-/good-listener-1.2.2.tgz",
+      "integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==",
+      "requires": {
+        "delegate": "^3.1.2"
+      }
+    },
+    "graceful-fs": {
+      "version": "4.2.11",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/graceful-fs/-/graceful-fs-4.2.11.tgz",
+      "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+      "peer": true
+    },
+    "has-flag": {
+      "version": "4.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/has-flag/-/has-flag-4.0.0.tgz",
+      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+      "peer": true
+    },
+    "hasown": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz",
+      "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+      "requires": {
+        "function-bind": "^1.1.2"
+      }
+    },
+    "hermes-estree": {
+      "version": "0.25.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/hermes-estree/-/hermes-estree-0.25.1.tgz",
+      "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==",
+      "peer": true
+    },
+    "hermes-parser": {
+      "version": "0.25.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/hermes-parser/-/hermes-parser-0.25.1.tgz",
+      "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==",
+      "peer": true,
+      "requires": {
+        "hermes-estree": "0.25.1"
+      }
+    },
+    "hookable": {
+      "version": "5.5.3",
+      "resolved": "https://registry.npmmirror.com/hookable/-/hookable-5.5.3.tgz",
+      "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="
+    },
+    "http-errors": {
+      "version": "2.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/http-errors/-/http-errors-2.0.0.tgz",
+      "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
+      "peer": true,
+      "requires": {
+        "depd": "2.0.0",
+        "inherits": "2.0.4",
+        "setprototypeof": "1.2.0",
+        "statuses": "2.0.1",
+        "toidentifier": "1.0.1"
+      },
+      "dependencies": {
+        "statuses": {
+          "version": "2.0.1",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/statuses/-/statuses-2.0.1.tgz",
+          "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
+          "peer": true
+        }
+      }
+    },
+    "https-proxy-agent": {
+      "version": "7.0.6",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
+      "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
+      "peer": true,
+      "requires": {
+        "agent-base": "^7.1.2",
+        "debug": "4"
+      }
+    },
+    "ignore": {
+      "version": "7.0.5",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ignore/-/ignore-7.0.5.tgz",
+      "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="
+    },
+    "image-size": {
+      "version": "1.2.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/image-size/-/image-size-1.2.1.tgz",
+      "integrity": "sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw==",
+      "peer": true,
+      "requires": {
+        "queue": "6.0.2"
+      }
+    },
+    "immutable": {
+      "version": "5.0.3",
+      "resolved": "https://registry.npmmirror.com/immutable/-/immutable-5.0.3.tgz",
+      "integrity": "sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==",
+      "dev": true
+    },
+    "import-fresh": {
+      "version": "2.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/import-fresh/-/import-fresh-2.0.0.tgz",
+      "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==",
+      "peer": true,
+      "requires": {
+        "caller-path": "^2.0.0",
+        "resolve-from": "^3.0.0"
+      },
+      "dependencies": {
+        "resolve-from": {
+          "version": "3.0.0",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/resolve-from/-/resolve-from-3.0.0.tgz",
+          "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=",
+          "peer": true
+        }
+      }
+    },
+    "imurmurhash": {
+      "version": "0.1.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/imurmurhash/-/imurmurhash-0.1.4.tgz",
+      "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+      "peer": true
+    },
+    "inflight": {
+      "version": "1.0.6",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/inflight/-/inflight-1.0.6.tgz",
+      "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+      "peer": true,
+      "requires": {
+        "once": "^1.3.0",
+        "wrappy": "1"
+      }
+    },
+    "inherits": {
+      "version": "2.0.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+      "peer": true
+    },
+    "invariant": {
+      "version": "2.2.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/invariant/-/invariant-2.2.4.tgz",
+      "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
+      "peer": true,
+      "requires": {
+        "loose-envify": "^1.0.0"
+      }
+    },
+    "is-arrayish": {
+      "version": "0.2.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/is-arrayish/-/is-arrayish-0.2.1.tgz",
+      "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+      "peer": true
+    },
+    "is-core-module": {
+      "version": "2.16.1",
+      "resolved": "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.16.1.tgz",
+      "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
+      "requires": {
+        "hasown": "^2.0.2"
+      }
+    },
+    "is-directory": {
+      "version": "0.3.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/is-directory/-/is-directory-0.3.1.tgz",
+      "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=",
+      "peer": true
+    },
+    "is-docker": {
+      "version": "2.2.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/is-docker/-/is-docker-2.2.1.tgz",
+      "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
+      "peer": true
+    },
+    "is-extglob": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz",
+      "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+      "dev": true,
+      "optional": true
+    },
+    "is-fullwidth-code-point": {
+      "version": "3.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+      "peer": true
+    },
+    "is-glob": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz",
+      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "is-extglob": "^2.1.1"
+      }
+    },
+    "is-number": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz",
+      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
+    },
+    "is-what": {
+      "version": "4.1.16",
+      "resolved": "https://registry.npmmirror.com/is-what/-/is-what-4.1.16.tgz",
+      "integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A=="
+    },
+    "is-wsl": {
+      "version": "2.2.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/is-wsl/-/is-wsl-2.2.0.tgz",
+      "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+      "peer": true,
+      "requires": {
+        "is-docker": "^2.0.0"
+      }
+    },
+    "istanbul-lib-coverage": {
+      "version": "3.2.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
+      "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==",
+      "peer": true
+    },
+    "istanbul-lib-instrument": {
+      "version": "5.2.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz",
+      "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==",
+      "peer": true,
+      "requires": {
+        "@babel/core": "^7.12.3",
+        "@babel/parser": "^7.14.7",
+        "@istanbuljs/schema": "^0.1.2",
+        "istanbul-lib-coverage": "^3.2.0",
+        "semver": "^6.3.0"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "6.3.1",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-6.3.1.tgz",
+          "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+          "peer": true
+        }
+      }
+    },
+    "jest-environment-node": {
+      "version": "29.7.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/jest-environment-node/-/jest-environment-node-29.7.0.tgz",
+      "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==",
+      "peer": true,
+      "requires": {
+        "@jest/environment": "^29.7.0",
+        "@jest/fake-timers": "^29.7.0",
+        "@jest/types": "^29.6.3",
+        "@types/node": "*",
+        "jest-mock": "^29.7.0",
+        "jest-util": "^29.7.0"
+      }
+    },
+    "jest-get-type": {
+      "version": "29.6.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/jest-get-type/-/jest-get-type-29.6.3.tgz",
+      "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==",
+      "peer": true
+    },
+    "jest-haste-map": {
+      "version": "29.7.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/jest-haste-map/-/jest-haste-map-29.7.0.tgz",
+      "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==",
+      "peer": true,
+      "requires": {
+        "@jest/types": "^29.6.3",
+        "@types/graceful-fs": "^4.1.3",
+        "@types/node": "*",
+        "anymatch": "^3.0.3",
+        "fb-watchman": "^2.0.0",
+        "fsevents": "^2.3.2",
+        "graceful-fs": "^4.2.9",
+        "jest-regex-util": "^29.6.3",
+        "jest-util": "^29.7.0",
+        "jest-worker": "^29.7.0",
+        "micromatch": "^4.0.4",
+        "walker": "^1.0.8"
+      },
+      "dependencies": {
+        "jest-worker": {
+          "version": "29.7.0",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/jest-worker/-/jest-worker-29.7.0.tgz",
+          "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==",
+          "peer": true,
+          "requires": {
+            "@types/node": "*",
+            "jest-util": "^29.7.0",
+            "merge-stream": "^2.0.0",
+            "supports-color": "^8.0.0"
+          }
+        }
+      }
+    },
+    "jest-message-util": {
+      "version": "29.7.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/jest-message-util/-/jest-message-util-29.7.0.tgz",
+      "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==",
+      "peer": true,
+      "requires": {
+        "@babel/code-frame": "^7.12.13",
+        "@jest/types": "^29.6.3",
+        "@types/stack-utils": "^2.0.0",
+        "chalk": "^4.0.0",
+        "graceful-fs": "^4.2.9",
+        "micromatch": "^4.0.4",
+        "pretty-format": "^29.7.0",
+        "slash": "^3.0.0",
+        "stack-utils": "^2.0.3"
+      }
+    },
+    "jest-mock": {
+      "version": "29.7.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/jest-mock/-/jest-mock-29.7.0.tgz",
+      "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==",
+      "peer": true,
+      "requires": {
+        "@jest/types": "^29.6.3",
+        "@types/node": "*",
+        "jest-util": "^29.7.0"
+      }
+    },
+    "jest-regex-util": {
+      "version": "29.6.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/jest-regex-util/-/jest-regex-util-29.6.3.tgz",
+      "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==",
+      "peer": true
+    },
+    "jest-util": {
+      "version": "29.7.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/jest-util/-/jest-util-29.7.0.tgz",
+      "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
+      "peer": true,
+      "requires": {
+        "@jest/types": "^29.6.3",
+        "@types/node": "*",
+        "chalk": "^4.0.0",
+        "ci-info": "^3.2.0",
+        "graceful-fs": "^4.2.9",
+        "picomatch": "^2.2.3"
+      }
+    },
+    "jest-validate": {
+      "version": "29.7.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/jest-validate/-/jest-validate-29.7.0.tgz",
+      "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==",
+      "peer": true,
+      "requires": {
+        "@jest/types": "^29.6.3",
+        "camelcase": "^6.2.0",
+        "chalk": "^4.0.0",
+        "jest-get-type": "^29.6.3",
+        "leven": "^3.1.0",
+        "pretty-format": "^29.7.0"
+      },
+      "dependencies": {
+        "camelcase": {
+          "version": "6.3.0",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/camelcase/-/camelcase-6.3.0.tgz",
+          "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+          "peer": true
+        }
+      }
+    },
+    "jest-worker": {
+      "version": "27.5.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/jest-worker/-/jest-worker-27.5.1.tgz",
+      "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==",
+      "dev": true,
+      "peer": true,
+      "requires": {
+        "@types/node": "*",
+        "merge-stream": "^2.0.0",
+        "supports-color": "^8.0.0"
+      }
+    },
+    "jiti": {
+      "version": "2.4.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/jiti/-/jiti-2.4.2.tgz",
+      "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A=="
+    },
+    "jju": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmmirror.com/jju/-/jju-1.4.0.tgz",
+      "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA=="
+    },
+    "js-tokens": {
+      "version": "9.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/js-tokens/-/js-tokens-9.0.1.tgz",
+      "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ=="
+    },
+    "js-yaml": {
+      "version": "3.14.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/js-yaml/-/js-yaml-3.14.1.tgz",
+      "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+      "peer": true,
+      "requires": {
+        "argparse": "^1.0.7",
+        "esprima": "^4.0.0"
+      }
+    },
+    "jsc-safe-url": {
+      "version": "0.2.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/jsc-safe-url/-/jsc-safe-url-0.2.4.tgz",
+      "integrity": "sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q==",
+      "peer": true
+    },
+    "jsesc": {
+      "version": "3.1.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/jsesc/-/jsesc-3.1.0.tgz",
+      "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+      "peer": true
+    },
+    "json-parse-better-errors": {
+      "version": "1.0.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+      "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
+      "peer": true
+    },
+    "json-parse-even-better-errors": {
+      "version": "2.3.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+      "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+      "dev": true,
+      "peer": true
+    },
+    "json-schema-traverse": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+      "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+      "dev": true
+    },
+    "json5": {
+      "version": "2.2.3",
+      "resolved": "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz",
+      "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="
+    },
+    "klona": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmmirror.com/klona/-/klona-2.0.6.tgz",
+      "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA=="
+    },
+    "knitwork": {
+      "version": "1.2.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/knitwork/-/knitwork-1.2.0.tgz",
+      "integrity": "sha512-xYSH7AvuQ6nXkq42x0v5S8/Iry+cfulBz/DJQzhIyESdLD7425jXsPy4vn5cCXU+HhRN2kVw51Vd1K6/By4BQg=="
+    },
+    "leven": {
+      "version": "3.1.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/leven/-/leven-3.1.0.tgz",
+      "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
+      "peer": true
+    },
+    "lighthouse-logger": {
+      "version": "1.4.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz",
+      "integrity": "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==",
+      "peer": true,
+      "requires": {
+        "debug": "^2.6.9",
+        "marky": "^1.2.2"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "peer": true,
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
+        "ms": {
+          "version": "2.0.0",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz",
+          "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+          "peer": true
+        }
+      }
+    },
+    "load-script": {
+      "version": "1.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/load-script/-/load-script-1.0.0.tgz",
+      "integrity": "sha1-BJGTngvuVkPuSUp+PaPSuscMbKQ="
+    },
+    "loader-runner": {
+      "version": "4.3.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/loader-runner/-/loader-runner-4.3.0.tgz",
+      "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==",
+      "dev": true,
+      "peer": true
+    },
+    "loader-utils": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-2.0.4.tgz",
+      "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
+      "dev": true,
+      "requires": {
+        "big.js": "^5.2.2",
+        "emojis-list": "^3.0.0",
+        "json5": "^2.1.2"
+      }
+    },
+    "local-pkg": {
+      "version": "1.1.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/local-pkg/-/local-pkg-1.1.1.tgz",
+      "integrity": "sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg==",
+      "requires": {
+        "mlly": "^1.7.4",
+        "pkg-types": "^2.0.1",
+        "quansync": "^0.2.8"
+      }
+    },
+    "locate-path": {
+      "version": "5.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/locate-path/-/locate-path-5.0.0.tgz",
+      "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+      "peer": true,
+      "requires": {
+        "p-locate": "^4.1.0"
+      }
+    },
+    "lodash.throttle": {
+      "version": "4.1.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
+      "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==",
+      "peer": true
+    },
+    "loose-envify": {
+      "version": "1.4.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/loose-envify/-/loose-envify-1.4.0.tgz",
+      "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+      "peer": true,
+      "requires": {
+        "js-tokens": "^3.0.0 || ^4.0.0"
+      },
+      "dependencies": {
+        "js-tokens": {
+          "version": "4.0.0",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/js-tokens/-/js-tokens-4.0.0.tgz",
+          "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+          "peer": true
+        }
+      }
+    },
+    "lru-cache": {
+      "version": "5.1.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/lru-cache/-/lru-cache-5.1.1.tgz",
+      "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+      "peer": true,
+      "requires": {
+        "yallist": "^3.0.2"
+      }
+    },
+    "magic-string": {
+      "version": "0.30.17",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/magic-string/-/magic-string-0.30.17.tgz",
+      "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
+      "requires": {
+        "@jridgewell/sourcemap-codec": "^1.5.0"
+      }
+    },
+    "makeerror": {
+      "version": "1.0.12",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/makeerror/-/makeerror-1.0.12.tgz",
+      "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==",
+      "peer": true,
+      "requires": {
+        "tmpl": "1.0.5"
+      }
+    },
+    "marky": {
+      "version": "1.3.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/marky/-/marky-1.3.0.tgz",
+      "integrity": "sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ==",
+      "peer": true
+    },
+    "memoize-one": {
+      "version": "5.2.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/memoize-one/-/memoize-one-5.2.1.tgz",
+      "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==",
+      "peer": true
+    },
+    "merge-stream": {
+      "version": "2.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/merge-stream/-/merge-stream-2.0.0.tgz",
+      "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+      "peer": true
+    },
+    "metro": {
+      "version": "0.82.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/metro/-/metro-0.82.4.tgz",
+      "integrity": "sha512-/gFmw3ux9CPG5WUmygY35hpyno28zi/7OUn6+OFfbweA8l0B+PPqXXLr0/T6cf5nclCcH0d22o+02fICaShVxw==",
+      "peer": true,
+      "requires": {
+        "@babel/code-frame": "^7.24.7",
+        "@babel/core": "^7.25.2",
+        "@babel/generator": "^7.25.0",
+        "@babel/parser": "^7.25.3",
+        "@babel/template": "^7.25.0",
+        "@babel/traverse": "^7.25.3",
+        "@babel/types": "^7.25.2",
+        "accepts": "^1.3.7",
+        "chalk": "^4.0.0",
+        "ci-info": "^2.0.0",
+        "connect": "^3.6.5",
+        "debug": "^4.4.0",
+        "error-stack-parser": "^2.0.6",
+        "flow-enums-runtime": "^0.0.6",
+        "graceful-fs": "^4.2.4",
+        "hermes-parser": "0.28.1",
+        "image-size": "^1.0.2",
+        "invariant": "^2.2.4",
+        "jest-worker": "^29.7.0",
+        "jsc-safe-url": "^0.2.2",
+        "lodash.throttle": "^4.1.1",
+        "metro-babel-transformer": "0.82.4",
+        "metro-cache": "0.82.4",
+        "metro-cache-key": "0.82.4",
+        "metro-config": "0.82.4",
+        "metro-core": "0.82.4",
+        "metro-file-map": "0.82.4",
+        "metro-resolver": "0.82.4",
+        "metro-runtime": "0.82.4",
+        "metro-source-map": "0.82.4",
+        "metro-symbolicate": "0.82.4",
+        "metro-transform-plugins": "0.82.4",
+        "metro-transform-worker": "0.82.4",
+        "mime-types": "^2.1.27",
+        "nullthrows": "^1.1.1",
+        "serialize-error": "^2.1.0",
+        "source-map": "^0.5.6",
+        "throat": "^5.0.0",
+        "ws": "^7.5.10",
+        "yargs": "^17.6.2"
+      },
+      "dependencies": {
+        "ci-info": {
+          "version": "2.0.0",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/ci-info/-/ci-info-2.0.0.tgz",
+          "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
+          "peer": true
+        },
+        "hermes-estree": {
+          "version": "0.28.1",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/hermes-estree/-/hermes-estree-0.28.1.tgz",
+          "integrity": "sha512-w3nxl/RGM7LBae0v8LH2o36+8VqwOZGv9rX1wyoWT6YaKZLqpJZ0YQ5P0LVr3tuRpf7vCx0iIG4i/VmBJejxTQ==",
+          "peer": true
+        },
+        "hermes-parser": {
+          "version": "0.28.1",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/hermes-parser/-/hermes-parser-0.28.1.tgz",
+          "integrity": "sha512-nf8o+hE8g7UJWParnccljHumE9Vlq8F7MqIdeahl+4x0tvCUJYRrT0L7h0MMg/X9YJmkNwsfbaNNrzPtFXOscg==",
+          "peer": true,
+          "requires": {
+            "hermes-estree": "0.28.1"
+          }
+        },
+        "jest-worker": {
+          "version": "29.7.0",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/jest-worker/-/jest-worker-29.7.0.tgz",
+          "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==",
+          "peer": true,
+          "requires": {
+            "@types/node": "*",
+            "jest-util": "^29.7.0",
+            "merge-stream": "^2.0.0",
+            "supports-color": "^8.0.0"
+          }
+        },
+        "source-map": {
+          "version": "0.5.7",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/source-map/-/source-map-0.5.7.tgz",
+          "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
+          "peer": true
+        },
+        "ws": {
+          "version": "7.5.10",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/ws/-/ws-7.5.10.tgz",
+          "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
+          "peer": true,
+          "requires": {}
+        }
+      }
+    },
+    "metro-babel-transformer": {
+      "version": "0.82.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/metro-babel-transformer/-/metro-babel-transformer-0.82.4.tgz",
+      "integrity": "sha512-4juJahGRb1gmNbQq48lNinB6WFNfb6m0BQqi/RQibEltNiqTCxew/dBspI2EWA4xVCd3mQWGfw0TML4KurQZnQ==",
+      "peer": true,
+      "requires": {
+        "@babel/core": "^7.25.2",
+        "flow-enums-runtime": "^0.0.6",
+        "hermes-parser": "0.28.1",
+        "nullthrows": "^1.1.1"
+      },
+      "dependencies": {
+        "hermes-estree": {
+          "version": "0.28.1",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/hermes-estree/-/hermes-estree-0.28.1.tgz",
+          "integrity": "sha512-w3nxl/RGM7LBae0v8LH2o36+8VqwOZGv9rX1wyoWT6YaKZLqpJZ0YQ5P0LVr3tuRpf7vCx0iIG4i/VmBJejxTQ==",
+          "peer": true
+        },
+        "hermes-parser": {
+          "version": "0.28.1",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/hermes-parser/-/hermes-parser-0.28.1.tgz",
+          "integrity": "sha512-nf8o+hE8g7UJWParnccljHumE9Vlq8F7MqIdeahl+4x0tvCUJYRrT0L7h0MMg/X9YJmkNwsfbaNNrzPtFXOscg==",
+          "peer": true,
+          "requires": {
+            "hermes-estree": "0.28.1"
+          }
+        }
+      }
+    },
+    "metro-cache": {
+      "version": "0.82.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/metro-cache/-/metro-cache-0.82.4.tgz",
+      "integrity": "sha512-vX0ylSMGtORKiZ4G8uP6fgfPdDiCWvLZUGZ5zIblSGylOX6JYhvExl0Zg4UA9pix/SSQu5Pnp9vdODMFsNIxhw==",
+      "peer": true,
+      "requires": {
+        "exponential-backoff": "^3.1.1",
+        "flow-enums-runtime": "^0.0.6",
+        "https-proxy-agent": "^7.0.5",
+        "metro-core": "0.82.4"
+      }
+    },
+    "metro-cache-key": {
+      "version": "0.82.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/metro-cache-key/-/metro-cache-key-0.82.4.tgz",
+      "integrity": "sha512-2JCTqcpF+f2OghOpe/+x+JywfzDkrHdAqinPFWmK2ezNAU/qX0jBFaTETogPibFivxZJil37w9Yp6syX8rFUng==",
+      "peer": true,
+      "requires": {
+        "flow-enums-runtime": "^0.0.6"
+      }
+    },
+    "metro-config": {
+      "version": "0.82.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/metro-config/-/metro-config-0.82.4.tgz",
+      "integrity": "sha512-Ki3Wumr3hKHGDS7RrHsygmmRNc/PCJrvkLn0+BWWxmbOmOcMMJDSmSI+WRlT8jd5VPZFxIi4wg+sAt5yBXAK0g==",
+      "peer": true,
+      "requires": {
+        "connect": "^3.6.5",
+        "cosmiconfig": "^5.0.5",
+        "flow-enums-runtime": "^0.0.6",
+        "jest-validate": "^29.7.0",
+        "metro": "0.82.4",
+        "metro-cache": "0.82.4",
+        "metro-core": "0.82.4",
+        "metro-runtime": "0.82.4"
+      }
+    },
+    "metro-core": {
+      "version": "0.82.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/metro-core/-/metro-core-0.82.4.tgz",
+      "integrity": "sha512-Xo4ozbxPg2vfgJGCgXZ8sVhC2M0lhTqD+tsKO2q9aelq/dCjnnSb26xZKcQO80CQOQUL7e3QWB7pLFGPjZm31A==",
+      "peer": true,
+      "requires": {
+        "flow-enums-runtime": "^0.0.6",
+        "lodash.throttle": "^4.1.1",
+        "metro-resolver": "0.82.4"
+      }
+    },
+    "metro-file-map": {
+      "version": "0.82.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/metro-file-map/-/metro-file-map-0.82.4.tgz",
+      "integrity": "sha512-eO7HD1O3aeNsbEe6NBZvx1lLJUrxgyATjnDmb7bm4eyF6yWOQot9XVtxTDLNifECuvsZ4jzRiTInrbmIHkTdGA==",
+      "peer": true,
+      "requires": {
+        "debug": "^4.4.0",
+        "fb-watchman": "^2.0.0",
+        "flow-enums-runtime": "^0.0.6",
+        "graceful-fs": "^4.2.4",
+        "invariant": "^2.2.4",
+        "jest-worker": "^29.7.0",
+        "micromatch": "^4.0.4",
+        "nullthrows": "^1.1.1",
+        "walker": "^1.0.7"
+      },
+      "dependencies": {
+        "jest-worker": {
+          "version": "29.7.0",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/jest-worker/-/jest-worker-29.7.0.tgz",
+          "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==",
+          "peer": true,
+          "requires": {
+            "@types/node": "*",
+            "jest-util": "^29.7.0",
+            "merge-stream": "^2.0.0",
+            "supports-color": "^8.0.0"
+          }
+        }
+      }
+    },
+    "metro-minify-terser": {
+      "version": "0.82.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/metro-minify-terser/-/metro-minify-terser-0.82.4.tgz",
+      "integrity": "sha512-W79Mi6BUwWVaM8Mc5XepcqkG+TSsCyyo//dmTsgYfJcsmReQorRFodil3bbJInETvjzdnS1mCsUo9pllNjT1Hg==",
+      "peer": true,
+      "requires": {
+        "flow-enums-runtime": "^0.0.6",
+        "terser": "^5.15.0"
+      }
+    },
+    "metro-resolver": {
+      "version": "0.82.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/metro-resolver/-/metro-resolver-0.82.4.tgz",
+      "integrity": "sha512-uWoHzOBGQTPT5PjippB8rRT3iI9CTgFA9tRiLMzrseA5o7YAlgvfTdY9vFk2qyk3lW3aQfFKWkmqENryPRpu+Q==",
+      "peer": true,
+      "requires": {
+        "flow-enums-runtime": "^0.0.6"
+      }
+    },
+    "metro-runtime": {
+      "version": "0.82.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/metro-runtime/-/metro-runtime-0.82.4.tgz",
+      "integrity": "sha512-vVyFO7H+eLXRV2E7YAUYA7aMGBECGagqxmFvC2hmErS7oq90BbPVENfAHbUWq1vWH+MRiivoRxdxlN8gBoF/dw==",
+      "peer": true,
+      "requires": {
+        "@babel/runtime": "^7.25.0",
+        "flow-enums-runtime": "^0.0.6"
+      }
+    },
+    "metro-source-map": {
+      "version": "0.82.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/metro-source-map/-/metro-source-map-0.82.4.tgz",
+      "integrity": "sha512-9jzDQJ0FPas1FuQFtwmBHsez2BfhFNufMowbOMeG3ZaFvzeziE8A0aJwILDS3U+V5039ssCQFiQeqDgENWvquA==",
+      "peer": true,
+      "requires": {
+        "@babel/traverse": "^7.25.3",
+        "@babel/traverse--for-generate-function-map": "npm:@babel/traverse@^7.25.3",
+        "@babel/types": "^7.25.2",
+        "flow-enums-runtime": "^0.0.6",
+        "invariant": "^2.2.4",
+        "metro-symbolicate": "0.82.4",
+        "nullthrows": "^1.1.1",
+        "ob1": "0.82.4",
+        "source-map": "^0.5.6",
+        "vlq": "^1.0.0"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.5.7",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/source-map/-/source-map-0.5.7.tgz",
+          "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
+          "peer": true
+        }
+      }
+    },
+    "metro-symbolicate": {
+      "version": "0.82.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/metro-symbolicate/-/metro-symbolicate-0.82.4.tgz",
+      "integrity": "sha512-LwEwAtdsx7z8rYjxjpLWxuFa2U0J6TS6ljlQM4WAATKa4uzV8unmnRuN2iNBWTmRqgNR77mzmI2vhwD4QSCo+w==",
+      "peer": true,
+      "requires": {
+        "flow-enums-runtime": "^0.0.6",
+        "invariant": "^2.2.4",
+        "metro-source-map": "0.82.4",
+        "nullthrows": "^1.1.1",
+        "source-map": "^0.5.6",
+        "vlq": "^1.0.0"
+      },
+      "dependencies": {
+        "source-map": {
+          "version": "0.5.7",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/source-map/-/source-map-0.5.7.tgz",
+          "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
+          "peer": true
+        }
+      }
+    },
+    "metro-transform-plugins": {
+      "version": "0.82.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/metro-transform-plugins/-/metro-transform-plugins-0.82.4.tgz",
+      "integrity": "sha512-NoWQRPHupVpnDgYguiEcm7YwDhnqW02iWWQjO2O8NsNP09rEMSq99nPjARWfukN7+KDh6YjLvTIN20mj3dk9kw==",
+      "peer": true,
+      "requires": {
+        "@babel/core": "^7.25.2",
+        "@babel/generator": "^7.25.0",
+        "@babel/template": "^7.25.0",
+        "@babel/traverse": "^7.25.3",
+        "flow-enums-runtime": "^0.0.6",
+        "nullthrows": "^1.1.1"
+      }
+    },
+    "metro-transform-worker": {
+      "version": "0.82.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/metro-transform-worker/-/metro-transform-worker-0.82.4.tgz",
+      "integrity": "sha512-kPI7Ad/tdAnI9PY4T+2H0cdgGeSWWdiPRKuytI806UcN4VhFL6OmYa19/4abYVYF+Cd2jo57CDuwbaxRfmXDhw==",
+      "peer": true,
+      "requires": {
+        "@babel/core": "^7.25.2",
+        "@babel/generator": "^7.25.0",
+        "@babel/parser": "^7.25.3",
+        "@babel/types": "^7.25.2",
+        "flow-enums-runtime": "^0.0.6",
+        "metro": "0.82.4",
+        "metro-babel-transformer": "0.82.4",
+        "metro-cache": "0.82.4",
+        "metro-cache-key": "0.82.4",
+        "metro-minify-terser": "0.82.4",
+        "metro-source-map": "0.82.4",
+        "metro-transform-plugins": "0.82.4",
+        "nullthrows": "^1.1.1"
+      }
+    },
+    "micromatch": {
+      "version": "4.0.8",
+      "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.8.tgz",
+      "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+      "requires": {
+        "braces": "^3.0.3",
+        "picomatch": "^2.3.1"
+      }
+    },
+    "mime": {
+      "version": "1.6.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/mime/-/mime-1.6.0.tgz",
+      "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+      "peer": true
+    },
+    "mime-db": {
+      "version": "1.52.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/mime-db/-/mime-db-1.52.0.tgz",
+      "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+      "peer": true
+    },
+    "mime-types": {
+      "version": "2.1.35",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/mime-types/-/mime-types-2.1.35.tgz",
+      "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+      "peer": true,
+      "requires": {
+        "mime-db": "1.52.0"
+      }
+    },
+    "minimatch": {
+      "version": "3.1.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/minimatch/-/minimatch-3.1.2.tgz",
+      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+      "peer": true,
+      "requires": {
+        "brace-expansion": "^1.1.7"
+      }
+    },
+    "mitt": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmmirror.com/mitt/-/mitt-3.0.1.tgz",
+      "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="
+    },
+    "mkdirp": {
+      "version": "1.0.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/mkdirp/-/mkdirp-1.0.4.tgz",
+      "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+      "peer": true
+    },
+    "mlly": {
+      "version": "1.7.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/mlly/-/mlly-1.7.4.tgz",
+      "integrity": "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==",
+      "requires": {
+        "acorn": "^8.14.0",
+        "pathe": "^2.0.1",
+        "pkg-types": "^1.3.0",
+        "ufo": "^1.5.4"
+      },
+      "dependencies": {
+        "confbox": {
+          "version": "0.1.8",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/confbox/-/confbox-0.1.8.tgz",
+          "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="
+        },
+        "pkg-types": {
+          "version": "1.3.1",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/pkg-types/-/pkg-types-1.3.1.tgz",
+          "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==",
+          "requires": {
+            "confbox": "^0.1.8",
+            "mlly": "^1.7.4",
+            "pathe": "^2.0.1"
+          }
+        }
+      }
+    },
+    "ms": {
+      "version": "2.1.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.1.3.tgz",
+      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+      "peer": true
+    },
+    "nanoid": {
+      "version": "3.3.11",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/nanoid/-/nanoid-3.3.11.tgz",
+      "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+      "peer": true
+    },
+    "negotiator": {
+      "version": "0.6.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/negotiator/-/negotiator-0.6.3.tgz",
+      "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+      "peer": true
+    },
+    "neo-async": {
+      "version": "2.6.2",
+      "resolved": "https://registry.npmmirror.com/neo-async/-/neo-async-2.6.2.tgz",
+      "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
+      "dev": true
+    },
+    "node-addon-api": {
+      "version": "7.1.1",
+      "resolved": "https://registry.npmmirror.com/node-addon-api/-/node-addon-api-7.1.1.tgz",
+      "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
+      "dev": true,
+      "optional": true
+    },
+    "node-fetch-native": {
+      "version": "1.6.6",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/node-fetch-native/-/node-fetch-native-1.6.6.tgz",
+      "integrity": "sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ=="
+    },
+    "node-int64": {
+      "version": "0.4.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/node-int64/-/node-int64-0.4.0.tgz",
+      "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=",
+      "peer": true
+    },
+    "node-releases": {
+      "version": "2.0.19",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/node-releases/-/node-releases-2.0.19.tgz",
+      "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==",
+      "peer": true
+    },
+    "normalize-path": {
+      "version": "3.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/normalize-path/-/normalize-path-3.0.0.tgz",
+      "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+      "peer": true
+    },
+    "nullthrows": {
+      "version": "1.1.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/nullthrows/-/nullthrows-1.1.1.tgz",
+      "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==",
+      "peer": true
+    },
+    "nypm": {
+      "version": "0.6.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/nypm/-/nypm-0.6.0.tgz",
+      "integrity": "sha512-mn8wBFV9G9+UFHIrq+pZ2r2zL4aPau/by3kJb3cM7+5tQHMt6HGQB8FDIeKFYp8o0D2pnH6nVsO88N4AmUxIWg==",
+      "requires": {
+        "citty": "^0.1.6",
+        "consola": "^3.4.0",
+        "pathe": "^2.0.3",
+        "pkg-types": "^2.0.0",
+        "tinyexec": "^0.3.2"
+      }
+    },
+    "ob1": {
+      "version": "0.82.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ob1/-/ob1-0.82.4.tgz",
+      "integrity": "sha512-n9S8e4l5TvkrequEAMDidl4yXesruWTNTzVkeaHSGywoTOIwTzZzKw7Z670H3eaXDZui5MJXjWGNzYowVZIxCA==",
+      "peer": true,
+      "requires": {
+        "flow-enums-runtime": "^0.0.6"
+      }
+    },
+    "ohash": {
+      "version": "2.0.11",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ohash/-/ohash-2.0.11.tgz",
+      "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ=="
+    },
+    "on-finished": {
+      "version": "2.3.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/on-finished/-/on-finished-2.3.0.tgz",
+      "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==",
+      "peer": true,
+      "requires": {
+        "ee-first": "1.1.1"
+      }
+    },
+    "once": {
+      "version": "1.4.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/once/-/once-1.4.0.tgz",
+      "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+      "peer": true,
+      "requires": {
+        "wrappy": "1"
+      }
+    },
+    "open": {
+      "version": "7.4.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/open/-/open-7.4.2.tgz",
+      "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==",
+      "peer": true,
+      "requires": {
+        "is-docker": "^2.0.0",
+        "is-wsl": "^2.1.1"
+      }
+    },
+    "p-limit": {
+      "version": "2.3.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/p-limit/-/p-limit-2.3.0.tgz",
+      "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+      "peer": true,
+      "requires": {
+        "p-try": "^2.0.0"
+      }
+    },
+    "p-locate": {
+      "version": "4.1.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/p-locate/-/p-locate-4.1.0.tgz",
+      "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+      "peer": true,
+      "requires": {
+        "p-limit": "^2.2.0"
+      }
+    },
+    "p-try": {
+      "version": "2.2.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/p-try/-/p-try-2.2.0.tgz",
+      "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+      "peer": true
+    },
+    "parse-json": {
+      "version": "4.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/parse-json/-/parse-json-4.0.0.tgz",
+      "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==",
+      "peer": true,
+      "requires": {
+        "error-ex": "^1.3.1",
+        "json-parse-better-errors": "^1.0.1"
+      }
+    },
+    "parseurl": {
+      "version": "1.3.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/parseurl/-/parseurl-1.3.3.tgz",
+      "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+      "peer": true
+    },
+    "path-exists": {
+      "version": "4.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/path-exists/-/path-exists-4.0.0.tgz",
+      "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+      "peer": true
+    },
+    "path-is-absolute": {
+      "version": "1.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+      "peer": true
+    },
+    "path-parse": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz",
+      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
+    },
+    "pathe": {
+      "version": "2.0.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/pathe/-/pathe-2.0.3.tgz",
+      "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="
+    },
+    "perfect-debounce": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/perfect-debounce/-/perfect-debounce-1.0.0.tgz",
+      "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA=="
+    },
+    "picocolors": {
+      "version": "1.1.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/picocolors/-/picocolors-1.1.1.tgz",
+      "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+      "peer": true
+    },
+    "picomatch": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz",
+      "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="
+    },
+    "pinia": {
+      "version": "3.0.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/pinia/-/pinia-3.0.2.tgz",
+      "integrity": "sha512-sH2JK3wNY809JOeiiURUR0wehJ9/gd9qFN2Y828jCbxEzKEmEt0pzCXwqiSTfuRsK9vQsOflSdnbdBOGrhtn+g==",
+      "requires": {
+        "@vue/devtools-api": "^7.7.2"
+      }
+    },
+    "pinia-plugin-persistedstate": {
+      "version": "4.3.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/pinia-plugin-persistedstate/-/pinia-plugin-persistedstate-4.3.0.tgz",
+      "integrity": "sha512-x9wxpHj6iFDj5ITQJ3rj6+KesEqyRk/vqcE3WE+VGfetleV9Zufqwa9qJ6AkA5wmRSQEp7BTA1us/MDVTRHFFw==",
+      "requires": {
+        "@nuxt/kit": "^3.17.2",
+        "deep-pick-omit": "^1.2.1",
+        "defu": "^6.1.4",
+        "destr": "^2.0.5"
+      }
+    },
+    "pirates": {
+      "version": "4.0.7",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/pirates/-/pirates-4.0.7.tgz",
+      "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==",
+      "peer": true
+    },
+    "pkg-types": {
+      "version": "2.1.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/pkg-types/-/pkg-types-2.1.0.tgz",
+      "integrity": "sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A==",
+      "requires": {
+        "confbox": "^0.2.1",
+        "exsolve": "^1.0.1",
+        "pathe": "^2.0.3"
+      }
+    },
+    "postcss": {
+      "version": "8.5.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/postcss/-/postcss-8.5.4.tgz",
+      "integrity": "sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w==",
+      "peer": true,
+      "requires": {
+        "nanoid": "^3.3.11",
+        "picocolors": "^1.1.1",
+        "source-map-js": "^1.2.1"
+      }
+    },
+    "pretty-format": {
+      "version": "29.7.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/pretty-format/-/pretty-format-29.7.0.tgz",
+      "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+      "peer": true,
+      "requires": {
+        "@jest/schemas": "^29.6.3",
+        "ansi-styles": "^5.0.0",
+        "react-is": "^18.0.0"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "5.2.0",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/ansi-styles/-/ansi-styles-5.2.0.tgz",
+          "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+          "peer": true
+        }
+      }
+    },
+    "promise": {
+      "version": "8.3.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/promise/-/promise-8.3.0.tgz",
+      "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==",
+      "peer": true,
+      "requires": {
+        "asap": "~2.0.6"
+      }
+    },
+    "punycode": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz",
+      "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="
+    },
+    "quansync": {
+      "version": "0.2.10",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/quansync/-/quansync-0.2.10.tgz",
+      "integrity": "sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A=="
+    },
+    "queue": {
+      "version": "6.0.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/queue/-/queue-6.0.2.tgz",
+      "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==",
+      "peer": true,
+      "requires": {
+        "inherits": "~2.0.3"
+      }
+    },
+    "randombytes": {
+      "version": "2.1.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/randombytes/-/randombytes-2.1.0.tgz",
+      "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+      "dev": true,
+      "peer": true,
+      "requires": {
+        "safe-buffer": "^5.1.0"
+      }
+    },
+    "range-parser": {
+      "version": "1.2.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/range-parser/-/range-parser-1.2.1.tgz",
+      "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+      "peer": true
+    },
+    "rc9": {
+      "version": "2.1.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/rc9/-/rc9-2.1.2.tgz",
+      "integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==",
+      "requires": {
+        "defu": "^6.1.4",
+        "destr": "^2.0.3"
+      }
+    },
+    "react": {
+      "version": "19.1.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/react/-/react-19.1.0.tgz",
+      "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
+      "peer": true
+    },
+    "react-devtools-core": {
+      "version": "6.1.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/react-devtools-core/-/react-devtools-core-6.1.2.tgz",
+      "integrity": "sha512-ldFwzufLletzCikNJVYaxlxMLu7swJ3T2VrGfzXlMsVhZhPDKXA38DEROidaYZVgMAmQnIjymrmqto5pyfrwPA==",
+      "peer": true,
+      "requires": {
+        "shell-quote": "^1.6.1",
+        "ws": "^7"
+      },
+      "dependencies": {
+        "ws": {
+          "version": "7.5.10",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/ws/-/ws-7.5.10.tgz",
+          "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
+          "peer": true,
+          "requires": {}
+        }
+      }
+    },
+    "react-is": {
+      "version": "18.3.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/react-is/-/react-is-18.3.1.tgz",
+      "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
+      "peer": true
+    },
+    "react-native": {
+      "version": "0.79.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/react-native/-/react-native-0.79.3.tgz",
+      "integrity": "sha512-EzH1+9gzdyEo9zdP6u7Sh3Jtf5EOMwzy+TK65JysdlgAzfEVfq4mNeXcAZ6SmD+CW6M7ARJbvXLyTD0l2S5rpg==",
+      "peer": true,
+      "requires": {
+        "@jest/create-cache-key-function": "^29.7.0",
+        "@react-native/assets-registry": "0.79.3",
+        "@react-native/codegen": "0.79.3",
+        "@react-native/community-cli-plugin": "0.79.3",
+        "@react-native/gradle-plugin": "0.79.3",
+        "@react-native/js-polyfills": "0.79.3",
+        "@react-native/normalize-colors": "0.79.3",
+        "@react-native/virtualized-lists": "0.79.3",
+        "abort-controller": "^3.0.0",
+        "anser": "^1.4.9",
+        "ansi-regex": "^5.0.0",
+        "babel-jest": "^29.7.0",
+        "babel-plugin-syntax-hermes-parser": "0.25.1",
+        "base64-js": "^1.5.1",
+        "chalk": "^4.0.0",
+        "commander": "^12.0.0",
+        "event-target-shim": "^5.0.1",
+        "flow-enums-runtime": "^0.0.6",
+        "glob": "^7.1.1",
+        "invariant": "^2.2.4",
+        "jest-environment-node": "^29.7.0",
+        "memoize-one": "^5.0.0",
+        "metro-runtime": "^0.82.0",
+        "metro-source-map": "^0.82.0",
+        "nullthrows": "^1.1.1",
+        "pretty-format": "^29.7.0",
+        "promise": "^8.3.0",
+        "react-devtools-core": "^6.1.1",
+        "react-refresh": "^0.14.0",
+        "regenerator-runtime": "^0.13.2",
+        "scheduler": "0.25.0",
+        "semver": "^7.1.3",
+        "stacktrace-parser": "^0.1.10",
+        "whatwg-fetch": "^3.0.0",
+        "ws": "^6.2.3",
+        "yargs": "^17.6.2"
+      },
+      "dependencies": {
+        "commander": {
+          "version": "12.1.0",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/commander/-/commander-12.1.0.tgz",
+          "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
+          "peer": true
+        }
+      }
+    },
+    "react-refresh": {
+      "version": "0.14.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/react-refresh/-/react-refresh-0.14.2.tgz",
+      "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==",
+      "peer": true
+    },
+    "readdirp": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-4.1.2.tgz",
+      "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="
+    },
+    "regenerator-runtime": {
+      "version": "0.13.11",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
+      "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==",
+      "peer": true
+    },
+    "require-directory": {
+      "version": "2.1.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/require-directory/-/require-directory-2.1.1.tgz",
+      "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
+      "peer": true
+    },
+    "require-from-string": {
+      "version": "2.0.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/require-from-string/-/require-from-string-2.0.2.tgz",
+      "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="
+    },
+    "resolve": {
+      "version": "1.22.10",
+      "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.10.tgz",
+      "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==",
+      "requires": {
+        "is-core-module": "^2.16.0",
+        "path-parse": "^1.0.7",
+        "supports-preserve-symlinks-flag": "^1.0.0"
+      }
+    },
+    "resolve-from": {
+      "version": "5.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/resolve-from/-/resolve-from-5.0.0.tgz",
+      "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+      "peer": true
+    },
+    "rfdc": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.4.1.tgz",
+      "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="
+    },
+    "rimraf": {
+      "version": "3.0.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/rimraf/-/rimraf-3.0.2.tgz",
+      "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+      "peer": true,
+      "requires": {
+        "glob": "^7.1.3"
+      }
+    },
+    "rxjs": {
+      "version": "7.8.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/rxjs/-/rxjs-7.8.2.tgz",
+      "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==",
+      "peer": true,
+      "requires": {
+        "tslib": "^2.1.0"
+      }
+    },
+    "safe-buffer": {
+      "version": "5.2.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/safe-buffer/-/safe-buffer-5.2.1.tgz",
+      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+      "dev": true,
+      "peer": true
+    },
+    "sass": {
+      "version": "1.85.1",
+      "resolved": "https://registry.npmmirror.com/sass/-/sass-1.85.1.tgz",
+      "integrity": "sha512-Uk8WpxM5v+0cMR0XjX9KfRIacmSG86RH4DCCZjLU2rFh5tyutt9siAXJ7G+YfxQ99Q6wrRMbMlVl6KqUms71ag==",
+      "dev": true,
+      "requires": {
+        "@parcel/watcher": "^2.4.1",
+        "chokidar": "^4.0.0",
+        "immutable": "^5.0.2",
+        "source-map-js": ">=0.6.2 <2.0.0"
+      }
+    },
+    "sass-loader": {
+      "version": "10.5.2",
+      "resolved": "https://registry.npmmirror.com/sass-loader/-/sass-loader-10.5.2.tgz",
+      "integrity": "sha512-vMUoSNOUKJILHpcNCCyD23X34gve1TS7Rjd9uXHeKqhvBG39x6XbswFDtpbTElj6XdMFezoWhkh5vtKudf2cgQ==",
+      "dev": true,
+      "requires": {
+        "klona": "^2.0.4",
+        "loader-utils": "^2.0.0",
+        "neo-async": "^2.6.2",
+        "schema-utils": "^3.0.0",
+        "semver": "^7.3.2"
+      }
+    },
+    "scheduler": {
+      "version": "0.25.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/scheduler/-/scheduler-0.25.0.tgz",
+      "integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==",
+      "peer": true
+    },
+    "schema-utils": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-3.3.0.tgz",
+      "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
+      "dev": true,
+      "requires": {
+        "@types/json-schema": "^7.0.8",
+        "ajv": "^6.12.5",
+        "ajv-keywords": "^3.5.2"
+      }
+    },
+    "scule": {
+      "version": "1.3.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/scule/-/scule-1.3.0.tgz",
+      "integrity": "sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g=="
+    },
+    "select": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/select/-/select-1.1.2.tgz",
+      "integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA=="
+    },
+    "semver": {
+      "version": "7.7.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/semver/-/semver-7.7.2.tgz",
+      "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="
+    },
+    "send": {
+      "version": "0.19.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/send/-/send-0.19.0.tgz",
+      "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
+      "peer": true,
+      "requires": {
+        "debug": "2.6.9",
+        "depd": "2.0.0",
+        "destroy": "1.2.0",
+        "encodeurl": "~1.0.2",
+        "escape-html": "~1.0.3",
+        "etag": "~1.8.1",
+        "fresh": "0.5.2",
+        "http-errors": "2.0.0",
+        "mime": "1.6.0",
+        "ms": "2.1.3",
+        "on-finished": "2.4.1",
+        "range-parser": "~1.2.1",
+        "statuses": "2.0.1"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "peer": true,
+          "requires": {
+            "ms": "2.0.0"
+          },
+          "dependencies": {
+            "ms": {
+              "version": "2.0.0",
+              "resolved": "https://mirrors.cloud.tencent.com/npm/ms/-/ms-2.0.0.tgz",
+              "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+              "peer": true
+            }
+          }
+        },
+        "on-finished": {
+          "version": "2.4.1",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/on-finished/-/on-finished-2.4.1.tgz",
+          "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
+          "peer": true,
+          "requires": {
+            "ee-first": "1.1.1"
+          }
+        },
+        "statuses": {
+          "version": "2.0.1",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/statuses/-/statuses-2.0.1.tgz",
+          "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
+          "peer": true
+        }
+      }
+    },
+    "serialize-error": {
+      "version": "2.1.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/serialize-error/-/serialize-error-2.1.0.tgz",
+      "integrity": "sha1-ULZ51WNc34Rme9yOWa9OW4HV9go=",
+      "peer": true
+    },
+    "serialize-javascript": {
+      "version": "6.0.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
+      "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
+      "dev": true,
+      "peer": true,
+      "requires": {
+        "randombytes": "^2.1.0"
+      }
+    },
+    "serve-static": {
+      "version": "1.16.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/serve-static/-/serve-static-1.16.2.tgz",
+      "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
+      "peer": true,
+      "requires": {
+        "encodeurl": "~2.0.0",
+        "escape-html": "~1.0.3",
+        "parseurl": "~1.3.3",
+        "send": "0.19.0"
+      },
+      "dependencies": {
+        "encodeurl": {
+          "version": "2.0.0",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/encodeurl/-/encodeurl-2.0.0.tgz",
+          "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
+          "peer": true
+        }
+      }
+    },
+    "setprototypeof": {
+      "version": "1.2.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/setprototypeof/-/setprototypeof-1.2.0.tgz",
+      "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
+      "peer": true
+    },
+    "shell-quote": {
+      "version": "1.8.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/shell-quote/-/shell-quote-1.8.3.tgz",
+      "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==",
+      "peer": true
+    },
+    "signal-exit": {
+      "version": "3.0.7",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/signal-exit/-/signal-exit-3.0.7.tgz",
+      "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+      "peer": true
+    },
+    "slash": {
+      "version": "3.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/slash/-/slash-3.0.0.tgz",
+      "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+      "peer": true
+    },
+    "source-map": {
+      "version": "0.6.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/source-map/-/source-map-0.6.1.tgz",
+      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+      "peer": true
+    },
+    "source-map-js": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz",
+      "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="
+    },
+    "source-map-support": {
+      "version": "0.5.21",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/source-map-support/-/source-map-support-0.5.21.tgz",
+      "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+      "peer": true,
+      "requires": {
+        "buffer-from": "^1.0.0",
+        "source-map": "^0.6.0"
+      }
+    },
+    "speakingurl": {
+      "version": "14.0.1",
+      "resolved": "https://registry.npmmirror.com/speakingurl/-/speakingurl-14.0.1.tgz",
+      "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ=="
+    },
+    "sprintf-js": {
+      "version": "1.0.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/sprintf-js/-/sprintf-js-1.0.3.tgz",
+      "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
+      "peer": true
+    },
+    "stack-utils": {
+      "version": "2.0.6",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/stack-utils/-/stack-utils-2.0.6.tgz",
+      "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==",
+      "peer": true,
+      "requires": {
+        "escape-string-regexp": "^2.0.0"
+      },
+      "dependencies": {
+        "escape-string-regexp": {
+          "version": "2.0.0",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
+          "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
+          "peer": true
+        }
+      }
+    },
+    "stackframe": {
+      "version": "1.3.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/stackframe/-/stackframe-1.3.4.tgz",
+      "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==",
+      "peer": true
+    },
+    "stacktrace-parser": {
+      "version": "0.1.11",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/stacktrace-parser/-/stacktrace-parser-0.1.11.tgz",
+      "integrity": "sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==",
+      "peer": true,
+      "requires": {
+        "type-fest": "^0.7.1"
+      }
+    },
+    "statuses": {
+      "version": "1.5.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/statuses/-/statuses-1.5.0.tgz",
+      "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
+      "peer": true
+    },
+    "std-env": {
+      "version": "3.9.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/std-env/-/std-env-3.9.0.tgz",
+      "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw=="
+    },
+    "string-width": {
+      "version": "4.2.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/string-width/-/string-width-4.2.3.tgz",
+      "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+      "peer": true,
+      "requires": {
+        "emoji-regex": "^8.0.0",
+        "is-fullwidth-code-point": "^3.0.0",
+        "strip-ansi": "^6.0.1"
+      }
+    },
+    "strip-ansi": {
+      "version": "6.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/strip-ansi/-/strip-ansi-6.0.1.tgz",
+      "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+      "peer": true,
+      "requires": {
+        "ansi-regex": "^5.0.1"
+      }
+    },
+    "strip-literal": {
+      "version": "3.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/strip-literal/-/strip-literal-3.0.0.tgz",
+      "integrity": "sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==",
+      "requires": {
+        "js-tokens": "^9.0.1"
+      }
+    },
+    "superjson": {
+      "version": "2.2.2",
+      "resolved": "https://registry.npmmirror.com/superjson/-/superjson-2.2.2.tgz",
+      "integrity": "sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==",
+      "requires": {
+        "copy-anything": "^3.0.2"
+      }
+    },
+    "supports-color": {
+      "version": "8.1.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/supports-color/-/supports-color-8.1.1.tgz",
+      "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+      "peer": true,
+      "requires": {
+        "has-flag": "^4.0.0"
+      }
+    },
+    "supports-preserve-symlinks-flag": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+      "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="
+    },
+    "tapable": {
+      "version": "2.2.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/tapable/-/tapable-2.2.2.tgz",
+      "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==",
+      "dev": true,
+      "peer": true
+    },
+    "terser": {
+      "version": "5.40.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/terser/-/terser-5.40.0.tgz",
+      "integrity": "sha512-cfeKl/jjwSR5ar7d0FGmave9hFGJT8obyo0z+CrQOylLDbk7X81nPU6vq9VORa5jU30SkDnT2FXjLbR8HLP+xA==",
+      "peer": true,
+      "requires": {
+        "@jridgewell/source-map": "^0.3.3",
+        "acorn": "^8.14.0",
+        "commander": "^2.20.0",
+        "source-map-support": "~0.5.20"
+      }
+    },
+    "terser-webpack-plugin": {
+      "version": "5.3.14",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz",
+      "integrity": "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==",
+      "dev": true,
+      "peer": true,
+      "requires": {
+        "@jridgewell/trace-mapping": "^0.3.25",
+        "jest-worker": "^27.4.5",
+        "schema-utils": "^4.3.0",
+        "serialize-javascript": "^6.0.2",
+        "terser": "^5.31.1"
+      },
+      "dependencies": {
+        "ajv": {
+          "version": "8.17.1",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/ajv/-/ajv-8.17.1.tgz",
+          "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
+          "dev": true,
+          "peer": true,
+          "requires": {
+            "fast-deep-equal": "^3.1.3",
+            "fast-uri": "^3.0.1",
+            "json-schema-traverse": "^1.0.0",
+            "require-from-string": "^2.0.2"
+          }
+        },
+        "ajv-keywords": {
+          "version": "5.1.0",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
+          "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
+          "dev": true,
+          "peer": true,
+          "requires": {
+            "fast-deep-equal": "^3.1.3"
+          }
+        },
+        "json-schema-traverse": {
+          "version": "1.0.0",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+          "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+          "dev": true,
+          "peer": true
+        },
+        "schema-utils": {
+          "version": "4.3.2",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/schema-utils/-/schema-utils-4.3.2.tgz",
+          "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==",
+          "dev": true,
+          "peer": true,
+          "requires": {
+            "@types/json-schema": "^7.0.9",
+            "ajv": "^8.9.0",
+            "ajv-formats": "^2.1.1",
+            "ajv-keywords": "^5.1.0"
+          }
+        }
+      }
+    },
+    "test-exclude": {
+      "version": "6.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/test-exclude/-/test-exclude-6.0.0.tgz",
+      "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
+      "peer": true,
+      "requires": {
+        "@istanbuljs/schema": "^0.1.2",
+        "glob": "^7.1.4",
+        "minimatch": "^3.0.4"
+      }
+    },
+    "throat": {
+      "version": "5.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/throat/-/throat-5.0.0.tgz",
+      "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==",
+      "peer": true
+    },
+    "tiny-emitter": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
+      "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
+    },
+    "tinyexec": {
+      "version": "0.3.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/tinyexec/-/tinyexec-0.3.2.tgz",
+      "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="
+    },
+    "tinyglobby": {
+      "version": "0.2.14",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/tinyglobby/-/tinyglobby-0.2.14.tgz",
+      "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==",
+      "requires": {
+        "fdir": "^6.4.4",
+        "picomatch": "^4.0.2"
+      },
+      "dependencies": {
+        "fdir": {
+          "version": "6.4.5",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/fdir/-/fdir-6.4.5.tgz",
+          "integrity": "sha512-4BG7puHpVsIYxZUbiUE3RqGloLaSSwzYie5jvasC4LWuBWzZawynvYouhjbQKw2JuIGYdm0DzIxl8iVidKlUEw==",
+          "requires": {}
+        },
+        "picomatch": {
+          "version": "4.0.2",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/picomatch/-/picomatch-4.0.2.tgz",
+          "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="
+        }
+      }
+    },
+    "tmpl": {
+      "version": "1.0.5",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/tmpl/-/tmpl-1.0.5.tgz",
+      "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
+      "peer": true
+    },
+    "to-regex-range": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz",
+      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+      "requires": {
+        "is-number": "^7.0.0"
+      }
+    },
+    "toidentifier": {
+      "version": "1.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/toidentifier/-/toidentifier-1.0.1.tgz",
+      "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+      "peer": true
+    },
+    "tslib": {
+      "version": "2.8.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/tslib/-/tslib-2.8.1.tgz",
+      "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+    },
+    "type-detect": {
+      "version": "4.0.8",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/type-detect/-/type-detect-4.0.8.tgz",
+      "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
+      "peer": true
+    },
+    "type-fest": {
+      "version": "0.7.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/type-fest/-/type-fest-0.7.1.tgz",
+      "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==",
+      "peer": true
+    },
+    "ufo": {
+      "version": "1.6.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ufo/-/ufo-1.6.1.tgz",
+      "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA=="
+    },
+    "unctx": {
+      "version": "2.4.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/unctx/-/unctx-2.4.1.tgz",
+      "integrity": "sha512-AbaYw0Nm4mK4qjhns67C+kgxR2YWiwlDBPzxrN8h8C6VtAdCgditAY5Dezu3IJy4XVqAnbrXt9oQJvsn3fyozg==",
+      "requires": {
+        "acorn": "^8.14.0",
+        "estree-walker": "^3.0.3",
+        "magic-string": "^0.30.17",
+        "unplugin": "^2.1.0"
+      }
+    },
+    "undici-types": {
+      "version": "6.21.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/undici-types/-/undici-types-6.21.0.tgz",
+      "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
+      "peer": true
+    },
+    "unimport": {
+      "version": "5.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/unimport/-/unimport-5.0.1.tgz",
+      "integrity": "sha512-1YWzPj6wYhtwHE+9LxRlyqP4DiRrhGfJxdtH475im8ktyZXO3jHj/3PZ97zDdvkYoovFdi0K4SKl3a7l92v3sQ==",
+      "requires": {
+        "acorn": "^8.14.1",
+        "escape-string-regexp": "^5.0.0",
+        "estree-walker": "^3.0.3",
+        "local-pkg": "^1.1.1",
+        "magic-string": "^0.30.17",
+        "mlly": "^1.7.4",
+        "pathe": "^2.0.3",
+        "picomatch": "^4.0.2",
+        "pkg-types": "^2.1.0",
+        "scule": "^1.3.0",
+        "strip-literal": "^3.0.0",
+        "tinyglobby": "^0.2.13",
+        "unplugin": "^2.3.2",
+        "unplugin-utils": "^0.2.4"
+      },
+      "dependencies": {
+        "picomatch": {
+          "version": "4.0.2",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/picomatch/-/picomatch-4.0.2.tgz",
+          "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="
+        }
+      }
+    },
+    "unpipe": {
+      "version": "1.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/unpipe/-/unpipe-1.0.0.tgz",
+      "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
+      "peer": true
+    },
+    "unplugin": {
+      "version": "2.3.5",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/unplugin/-/unplugin-2.3.5.tgz",
+      "integrity": "sha512-RyWSb5AHmGtjjNQ6gIlA67sHOsWpsbWpwDokLwTcejVdOjEkJZh7QKu14J00gDDVSh8kGH4KYC/TNBceXFZhtw==",
+      "requires": {
+        "acorn": "^8.14.1",
+        "picomatch": "^4.0.2",
+        "webpack-virtual-modules": "^0.6.2"
+      },
+      "dependencies": {
+        "picomatch": {
+          "version": "4.0.2",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/picomatch/-/picomatch-4.0.2.tgz",
+          "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="
+        }
+      }
+    },
+    "unplugin-utils": {
+      "version": "0.2.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/unplugin-utils/-/unplugin-utils-0.2.4.tgz",
+      "integrity": "sha512-8U/MtpkPkkk3Atewj1+RcKIjb5WBimZ/WSLhhR3w6SsIj8XJuKTacSP8g+2JhfSGw0Cb125Y+2zA/IzJZDVbhA==",
+      "requires": {
+        "pathe": "^2.0.2",
+        "picomatch": "^4.0.2"
+      },
+      "dependencies": {
+        "picomatch": {
+          "version": "4.0.2",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/picomatch/-/picomatch-4.0.2.tgz",
+          "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="
+        }
+      }
+    },
+    "untyped": {
+      "version": "2.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/untyped/-/untyped-2.0.0.tgz",
+      "integrity": "sha512-nwNCjxJTjNuLCgFr42fEak5OcLuB3ecca+9ksPFNvtfYSLpjf+iJqSIaSnIile6ZPbKYxI5k2AfXqeopGudK/g==",
+      "requires": {
+        "citty": "^0.1.6",
+        "defu": "^6.1.4",
+        "jiti": "^2.4.2",
+        "knitwork": "^1.2.0",
+        "scule": "^1.3.0"
+      }
+    },
+    "update-browserslist-db": {
+      "version": "1.1.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
+      "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==",
+      "peer": true,
+      "requires": {
+        "escalade": "^3.2.0",
+        "picocolors": "^1.1.1"
+      }
+    },
+    "uri-js": {
+      "version": "4.4.1",
+      "resolved": "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz",
+      "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+      "requires": {
+        "punycode": "^2.1.0"
+      }
+    },
+    "utils-merge": {
+      "version": "1.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/utils-merge/-/utils-merge-1.0.1.tgz",
+      "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
+      "peer": true
+    },
+    "uuid": {
+      "version": "11.1.0",
+      "resolved": "https://registry.npmmirror.com/uuid/-/uuid-11.1.0.tgz",
+      "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="
+    },
+    "uview-plus": {
+      "version": "3.5.41",
+      "resolved": "https://registry.npmmirror.com/uview-plus/-/uview-plus-3.5.41.tgz",
+      "integrity": "sha512-X+oCPvTngZaqbzMlTZepPxEHk750br2UnywnIShXWHm3uiV3WzrFh5TQzK9f8JveX6FS/dVUgcVk89BJPMC6mw==",
+      "requires": {
+        "clipboard": "^2.0.11",
+        "dayjs": "^1.11.3"
+      }
+    },
+    "uview-ui": {
+      "version": "2.0.38",
+      "resolved": "https://registry.npmmirror.com/uview-ui/-/uview-ui-2.0.38.tgz",
+      "integrity": "sha512-6egHDf9lXHKpG3hEjRE0vMx4+VWwKk/ReTf5x18KrIKqdvdPRqO3+B8Unh7vYYwrIxzAWIlmhZ9RJpKI/4UqPQ=="
+    },
+    "vlq": {
+      "version": "1.0.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/vlq/-/vlq-1.0.1.tgz",
+      "integrity": "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==",
+      "peer": true
+    },
+    "vue": {
+      "version": "3.5.16",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/vue/-/vue-3.5.16.tgz",
+      "integrity": "sha512-rjOV2ecxMd5SiAmof2xzh2WxntRcigkX/He4YFJ6WdRvVUrbt6DxC1Iujh10XLl8xCDRDtGKMeO3D+pRQ1PP9w==",
+      "peer": true,
+      "requires": {
+        "@vue/compiler-dom": "3.5.16",
+        "@vue/compiler-sfc": "3.5.16",
+        "@vue/runtime-dom": "3.5.16",
+        "@vue/server-renderer": "3.5.16",
+        "@vue/shared": "3.5.16"
+      }
+    },
+    "walker": {
+      "version": "1.0.8",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/walker/-/walker-1.0.8.tgz",
+      "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==",
+      "peer": true,
+      "requires": {
+        "makeerror": "1.0.12"
+      }
+    },
+    "watchpack": {
+      "version": "2.4.4",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/watchpack/-/watchpack-2.4.4.tgz",
+      "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==",
+      "dev": true,
+      "peer": true,
+      "requires": {
+        "glob-to-regexp": "^0.4.1",
+        "graceful-fs": "^4.1.2"
+      }
+    },
+    "web-vitals": {
+      "version": "3.5.2",
+      "resolved": "https://registry.npmmirror.com/web-vitals/-/web-vitals-3.5.2.tgz",
+      "integrity": "sha512-c0rhqNcHXRkY/ogGDJQxZ9Im9D19hDihbzSQJrsioex+KnFgmMzBiy57Z1EjkhX/+OjyBpclDCzz2ITtjokFmg=="
+    },
+    "webpack": {
+      "version": "5.99.9",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/webpack/-/webpack-5.99.9.tgz",
+      "integrity": "sha512-brOPwM3JnmOa+7kd3NsmOUOwbDAj8FT9xDsG3IW0MgbN9yZV7Oi/s/+MNQ/EcSMqw7qfoRyXPoeEWT8zLVdVGg==",
+      "dev": true,
+      "peer": true,
+      "requires": {
+        "@types/eslint-scope": "^3.7.7",
+        "@types/estree": "^1.0.6",
+        "@types/json-schema": "^7.0.15",
+        "@webassemblyjs/ast": "^1.14.1",
+        "@webassemblyjs/wasm-edit": "^1.14.1",
+        "@webassemblyjs/wasm-parser": "^1.14.1",
+        "acorn": "^8.14.0",
+        "browserslist": "^4.24.0",
+        "chrome-trace-event": "^1.0.2",
+        "enhanced-resolve": "^5.17.1",
+        "es-module-lexer": "^1.2.1",
+        "eslint-scope": "5.1.1",
+        "events": "^3.2.0",
+        "glob-to-regexp": "^0.4.1",
+        "graceful-fs": "^4.2.11",
+        "json-parse-even-better-errors": "^2.3.1",
+        "loader-runner": "^4.2.0",
+        "mime-types": "^2.1.27",
+        "neo-async": "^2.6.2",
+        "schema-utils": "^4.3.2",
+        "tapable": "^2.1.1",
+        "terser-webpack-plugin": "^5.3.11",
+        "watchpack": "^2.4.1",
+        "webpack-sources": "^3.2.3"
+      },
+      "dependencies": {
+        "ajv": {
+          "version": "8.17.1",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/ajv/-/ajv-8.17.1.tgz",
+          "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
+          "dev": true,
+          "peer": true,
+          "requires": {
+            "fast-deep-equal": "^3.1.3",
+            "fast-uri": "^3.0.1",
+            "json-schema-traverse": "^1.0.0",
+            "require-from-string": "^2.0.2"
+          }
+        },
+        "ajv-keywords": {
+          "version": "5.1.0",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
+          "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
+          "dev": true,
+          "peer": true,
+          "requires": {
+            "fast-deep-equal": "^3.1.3"
+          }
+        },
+        "json-schema-traverse": {
+          "version": "1.0.0",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+          "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+          "dev": true,
+          "peer": true
+        },
+        "schema-utils": {
+          "version": "4.3.2",
+          "resolved": "https://mirrors.cloud.tencent.com/npm/schema-utils/-/schema-utils-4.3.2.tgz",
+          "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==",
+          "dev": true,
+          "peer": true,
+          "requires": {
+            "@types/json-schema": "^7.0.9",
+            "ajv": "^8.9.0",
+            "ajv-formats": "^2.1.1",
+            "ajv-keywords": "^5.1.0"
+          }
+        }
+      }
+    },
+    "webpack-sources": {
+      "version": "3.3.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/webpack-sources/-/webpack-sources-3.3.2.tgz",
+      "integrity": "sha512-ykKKus8lqlgXX/1WjudpIEjqsafjOTcOJqxnAbMLAu/KCsDCJ6GBtvscewvTkrn24HsnvFwrSCbenFrhtcCsAA==",
+      "dev": true,
+      "peer": true
+    },
+    "webpack-virtual-modules": {
+      "version": "0.6.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz",
+      "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ=="
+    },
+    "whatwg-fetch": {
+      "version": "3.6.20",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz",
+      "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==",
+      "peer": true
+    },
+    "wrap-ansi": {
+      "version": "7.0.0",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+      "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+      "peer": true,
+      "requires": {
+        "ansi-styles": "^4.0.0",
+        "string-width": "^4.1.0",
+        "strip-ansi": "^6.0.0"
+      }
+    },
+    "wrappy": {
+      "version": "1.0.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/wrappy/-/wrappy-1.0.2.tgz",
+      "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+      "peer": true
+    },
+    "write-file-atomic": {
+      "version": "4.0.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/write-file-atomic/-/write-file-atomic-4.0.2.tgz",
+      "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==",
+      "peer": true,
+      "requires": {
+        "imurmurhash": "^0.1.4",
+        "signal-exit": "^3.0.7"
+      }
+    },
+    "ws": {
+      "version": "6.2.3",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/ws/-/ws-6.2.3.tgz",
+      "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==",
+      "peer": true,
+      "requires": {
+        "async-limiter": "~1.0.0"
+      }
+    },
+    "y18n": {
+      "version": "5.0.8",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/y18n/-/y18n-5.0.8.tgz",
+      "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+      "peer": true
+    },
+    "yallist": {
+      "version": "3.1.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/yallist/-/yallist-3.1.1.tgz",
+      "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+      "peer": true
+    },
+    "yargs": {
+      "version": "17.7.2",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/yargs/-/yargs-17.7.2.tgz",
+      "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+      "peer": true,
+      "requires": {
+        "cliui": "^8.0.1",
+        "escalade": "^3.1.1",
+        "get-caller-file": "^2.0.5",
+        "require-directory": "^2.1.1",
+        "string-width": "^4.2.3",
+        "y18n": "^5.0.5",
+        "yargs-parser": "^21.1.1"
+      }
+    },
+    "yargs-parser": {
+      "version": "21.1.1",
+      "resolved": "https://mirrors.cloud.tencent.com/npm/yargs-parser/-/yargs-parser-21.1.1.tgz",
+      "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+      "peer": true
+    }
+  }
+}

+ 103 - 0
package.json

@@ -0,0 +1,103 @@
+{
+  "id": "uni-hello-i18n",
+  "name": "hello-i18n",
+  "displayName": "hello-i18n 示例工程",
+  "version": "1.0.2",
+  "description": "uni-app 国际化演示",
+  "keywords": [
+    "i18n",
+    "hello-i18n",
+    "多语言"
+  ],
+  "dcloudext": {
+    "category": [
+      "前端页面模板",
+      "uni-app前端项目模板"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": ""
+  },
+  "uni_modules": {
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "u",
+          "app-nvue": "u"
+        },
+        "H5-mobile": {
+          "Safari": "u",
+          "Android Browser": "u",
+          "微信浏览器(Android)": "u",
+          "QQ浏览器(Android)": "u"
+        },
+        "H5-pc": {
+          "Chrome": "u",
+          "IE": "u",
+          "Edge": "u",
+          "Firefox": "u",
+          "Safari": "u"
+        },
+        "小程序": {
+          "微信": "u",
+          "阿里": "u",
+          "百度": "u",
+          "字节跳动": "u",
+          "QQ": "u",
+          "京东": "u"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+          "vue2": "u",
+          "vue3": "u"
+        }
+      }
+    }
+  },
+  "devDependencies": {
+    "sass": "^1.85.1",
+    "sass-loader": "10"
+  },
+  "dependencies": {
+    "@airwallex/components-sdk": "^1.20.0",
+    "@awesome-cordova-plugins/facebook": "^8.0.0",
+    "@capacitor-community/facebook-login": "^7.0.0",
+    "@react-native-google-signin/google-signin": "^14.0.1",
+    "airwallex-payment-elements": "latest",
+    "clipboard": "^2.0.11",
+    "dayjs": "^1.11.13",
+    "fb-sdk": "^1.0.3",
+    "pinia": "^3.0.2",
+    "pinia-plugin-persistedstate": "^4.3.0",
+    "uuid": "^11.1.0",
+    "uview-plus": "^3.5.41",
+    "uview-ui": "^2.0.38"
+  },
+  "main": "main.js",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "author": "",
+  "license": "ISC"
+}

+ 248 - 0
pages.json

@@ -0,0 +1,248 @@
+{
+  "easycom": {
+    "autoscan": true,
+    // 注意一定要放在custom里,否则无效,https://ask.dcloud.net.cn/question/131175
+    "custom": {
+      "^u--(.*)": "@/uni_modules/uview-plus/components/u-$1/u-$1.vue",
+      "^up-(.*)": "@/uni_modules/uview-plus/components/u-$1/u-$1.vue",
+      "^u-([^-].*)": "@/uni_modules/uview-plus/components/u-$1/u-$1.vue"
+    }
+  },
+  "pages": [
+    //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
+    {
+      "path": "pages/index/index"
+    },
+    {
+      "path": "pages/login/login"
+    },
+    {
+      "path": "pages/login/register"
+    },
+    {
+      "path": "pages/shop/index"
+    },
+    {
+      "path": "pages/channel/index"
+    },
+    {
+      "path": "pages/Commission/index"
+    },
+    {
+      "path": "pages/user/index"
+    },
+    {
+      "path": "pages/setting/language_currency"
+    },
+    {
+      "path": "pages/index/products"
+    },
+    {
+      "path": "pages/index/search"
+    },
+    {
+      "path": "pages/shop/productDetail"
+    },
+    {
+      "path": "pages/shop/shopConfirm"
+    },
+    {
+      "path": "pages/shop/payment"
+    },
+    {
+      "path": "pages/dashboard/order"
+    },
+    {
+      "path": "pages/dashboard/order_detail"
+    },
+    {
+      "path": "pages/dashboard/favorites"
+    },
+    {
+      "path": "pages/shop/merchants"
+    },
+    {
+      "path": "pages/dashboard/warehouse"
+    },
+    {
+      "path": "pages/dashboard/warehouse_detail"
+    },
+    {
+      "path": "pages/setting/index"
+    },
+    {
+      "path": "pages/setting/profile"
+    },
+    {
+      "path": "pages/setting/account-safety"
+    },
+    {
+      "path": "pages/dashboard/pack"
+    },
+    {
+      "path": "pages/dashboard/parcel"
+    },
+    {
+      "path": "pages/dashboard/parcel_detail"
+    },
+    {
+      "path": "pages/dashboard/payment"
+    },
+    {
+      "path": "pages/bank/wallet"
+    },
+    {
+      "path": "pages/bank/account"
+    },
+    {
+      "path": "pages/bank/recharge"
+    },
+    {
+      "path": "pages/bank/withdraw"
+    },
+    {
+      "path": "pages/bank/qrcode"
+    },
+    {
+      "path": "pages/bank/bank_pay"
+    },
+    {
+      "path": "pages/bank/recharge_list"
+    },
+    {
+      "path": "pages/bank/withdraw_list"
+    },
+    {
+      "path": "pages/user/beginner_guide"
+    },
+    {
+      "path": "pages/user/help_center"
+    },
+    {
+      "path": "pages/index/estimation"
+    },
+    {
+      "path": "pages/community/index"
+    },
+    {
+      "path": "pages/order/index"
+    },
+    {
+      "path": "pages/order/details"
+    },
+    {
+      "path": "pages/address/index"
+    },
+    {
+      "path": "pages/shop/cart"
+    },
+    {
+      "path": "pages/user/edit_user"
+    },
+    {
+      "path": "pages/user/invite"
+    },
+    {
+      "path": "pages/user/verification"
+    },
+    {
+      "path": "pages/user/coupon"
+    },
+    {
+      "path": "pages/setting/system",
+      "style": {
+        "app-plus": {
+          "softinputMode": "adjustResize"
+        }
+      }
+    },
+    {
+      "path": "pages/chat/index",
+      "style": {
+        "app-plus": {
+          "softinputMode": "adjustResize"
+        }
+      }
+    },
+    {
+      "path": "pages/login/forget"
+    },
+    {
+      "path": "pages/dashboard/logistics"
+    },
+    {
+      "path": "pages/user/message/list"
+    },
+    {
+      "path": "pages/user/message/detail"
+    },
+    {
+      "path": "pages/index/activityList"
+    },
+    {
+      "path": "pages/user/weal_center"
+    },
+    {
+      "path": "pages/repo/index"
+    },
+    {
+      "path": "pages/user/mystore"
+    },
+    {
+      "path": "pages/purpose/index"
+    },
+    {
+      "path": "pages/purpose/record"
+    }
+  ],
+  "tabBar": {
+    "custom": true,
+    "color": "#7A7E83",
+    "selectedColor": "#007AFF",
+    "borderStyle": "black",
+    "backgroundColor": "#F8F8F8",
+    "navigationStyle": "custom",
+    "list": [
+      {
+        "pagePath": "pages/index/index",
+        "text": "%tabbar.首页%",
+        "visible": false
+      },
+      {
+        "pagePath": "pages/shop/cart",
+        "text": "%tabbar.购物车%",
+        "visible": false
+      },
+      {
+        "pagePath": "pages/chat/index",
+        "text": "%tabbar.咨询%",
+        "visible": false
+      },
+      // {
+      //   "pagePath": "pages/community/index",
+      //   "text": "%tabbar.社区%",
+      //   "visible": false
+      // },
+      {
+        "pagePath": "pages/order/index",
+        "text": "%tabbar.订单%",
+        "visible": false
+      },
+      {
+        "pagePath": "pages/user/index",
+        "text": "%tabbar.我的%",
+        "visible": false
+      }
+    ]
+  },
+  "globalStyle": {
+    "navigationBarTextStyle": "black",
+    "navigationBarTitleText": "VAVABUY",
+    "navigationBarBackgroundColor": "#000",
+    "backgroundColor": "#F8F8F8",
+    "navigationStyle": "custom",
+    "app-plus": {
+      "bounce": "none"
+    }
+  }
+}

+ 26 - 0
pages/Commission/index.vue

@@ -0,0 +1,26 @@
+<template>
+  <Theme>
+    <view class="wrap">
+      运输
+    </view>
+    <Tabbar page="Commission" />
+  </Theme>
+</template>
+
+<script setup>
+import Tabbar from '@/components/tabbar';
+import { computed } from 'vue'
+import { useUserStore } from "@/store"
+const useUser = useUserStore();
+const userInfo = computed(() => useUser.getuserInfo)
+
+uni.hideTabBar();
+</script>
+
+<style lang="less" scoped>
+.wrap {
+  background: var(--bg);
+  min-height: calc(100vh - 50px);
+  padding-bottom: 50px;
+}
+</style>

+ 349 - 0
pages/address/components/addressModel.vue

@@ -0,0 +1,349 @@
+<template>
+  <view>
+    <view class="address">
+      <view
+        class="address_item"
+        :class="addressList.length ? '' : 'flex'"
+        @click="addressClick"
+      >
+        <template v-if="addressList.length">
+          <view class="_item">
+            <view class="_item_top">
+              <view class="_top_left">
+                <view class="name"
+                  >{{ selectItem.firstName }}&nbsp;{{
+                    selectItem.lastName
+                  }}</view
+                >
+                <view class="phone">{{ selectItem.phoneNo }}</view>
+                <view class="code">{{ selectItem.zipCode }}</view>
+              </view>
+              <i class="icon-font icon-left"></i>
+            </view>
+            <view class="_item_middle">
+              {{ selectItem.country }}&nbsp;{{ selectItem.province }},{{
+                selectItem.city
+              }},{{ selectItem.address }}
+            </view>
+            <view class="_item_bottom">
+              <view class="default_btn" v-if="selectItem.default == 1">
+                <trans _t="默认" />
+              </view>
+              <view class="label_btn" v-if="selectItem.label">{{
+                selectItem.label
+              }}</view>
+            </view>
+          </view>
+        </template>
+        <template v-else>
+          <view class="address_empty">
+            <trans _t="请选择地址" />
+
+            <up-icon name="arrow-right"></up-icon>
+          </view>
+        </template>
+      </view>
+    </view>
+    <popup title="请选择地址" isClose ref="popRef">
+      <template #content>
+        <view class="pop_cont">
+          <view
+            class="cont_list"
+            v-for="(item, index) in addressList"
+            :key="index"
+            @click="listClick(item)"
+          >
+            <view class="_list_item">
+              <view class="_item_top">
+                <view class="_top_left">
+                  <view class="name"
+                    >{{ item.firstName }}&nbsp;{{ item.lastName }}</view
+                  >
+                  <view class="phone">{{ item.phoneNo }}</view>
+                </view>
+              </view>
+              <view class="_item_middle">
+                {{ item.country }}&nbsp;{{ item.province }},{{ item.city }},{{
+                  item.address
+                }}
+              </view>
+              <view class="_item_bottom">
+                <view class="default_btn" v-if="item.default == 1">
+                  <trans _t="默认" />
+                </view>
+                <view class="label_btn" v-if="item.label">{{
+                  item.label
+                }}</view>
+              </view>
+            </view>
+            <view @click.stop="editAddress(item)">
+              <i class="icon-font icon-edit"></i>
+            </view>
+          </view>
+        </view>
+      </template>
+      <template #footer>
+        <view class="footer_btn" @click="addressOpen">
+          <trans _t="添加送货地址" />
+        </view>
+      </template>
+    </popup>
+    <Address ref="addressRef" />
+  </view>
+</template>
+
+<script setup>
+import { computed, ref, reactive, nextTick } from "vue";
+import Popup from "@/components/popup.vue";
+import { t } from "@/locale";
+import { useShopStore } from "@/store";
+import Address from "@/components/address";
+import { onShow } from "@dcloudio/uni-app";
+
+const emit = defineEmits(["confirm", "open", "close"]);
+
+const popRef = ref(null);
+const addressRef = ref(null);
+
+const useShop = useShopStore();
+const ids = ref([]);
+const addressList = computed(() => {
+  const list = useShop.getAddressList;
+  const items = list.length && (list.find((item) => item.default == 1) || {});
+  let obj = list.length && (JSON.stringify(items) === "{}" ? list[0] : items);
+  ids.value = [obj.id || ""];
+  return list;
+});
+const selectItem = computed(() => {
+  let item = {};
+  if (addressList.value.length) {
+    item = addressList.value.find((item) => item.id == ids.value[0]) || {};
+    getCheck(item);
+    return item;
+  }
+  return item;
+});
+
+const getCheck = (item) => {
+  emit("confirm", item || selectItem.value);
+};
+const form = reactive({
+  id: "",
+  express_name: "",
+  express_no: "",
+});
+const open = () => {
+  emit("open");
+  popRef.value && popRef.value.open();
+};
+
+const close = () => {
+  emit("close");
+  popRef.value && popRef.value.close();
+};
+const addressClick = () => {
+  popRef.value && popRef.value.open();
+};
+const listClick = (item) => {
+  ids.value = [item.id];
+  nextTick(() => {
+    getCheck();
+    popRef.value && popRef.value.close();
+  });
+};
+const editAddress = (item) => {
+  popRef.value && popRef.value.close();
+  addressRef.value && addressRef.value.open(item);
+};
+const addressOpen = () => {
+  popRef.value && popRef.value.close();
+  addressRef.value && addressRef.value.open();
+};
+
+onShow(() => {
+  nextTick(() => {
+    useShop.setAddressList();
+  });
+});
+defineExpose({ open, close });
+</script>
+
+
+<style lang="less" scoped>
+@import url("@/style.less");
+
+.address {
+  margin-top: 24rpx;
+  background: url("@/static/address_bg.png") no-repeat 50%;
+  background-size: cover;
+  padding: 2px;
+  border-radius: 16rpx;
+
+  &_item {
+    padding: 24rpx 20rpx;
+    background-color: var(--light);
+    border-radius: 16rpx;
+    min-height: 160rpx;
+
+    .address_empty {
+      height: inherit;
+      flex: 1;
+      .flex_position(space-between);
+      color: var(--text-01);
+      line-height: 60rpx;
+      .size(28rpx);
+
+      .icon-left {
+        .size(36rpx);
+        transform: rotate(180deg);
+      }
+    }
+
+    ._item {
+      overflow: hidden;
+
+      &_top {
+        .flex_position(space-between);
+        padding-right: 30rpx;
+        line-height: 60rpx;
+
+        ._top_left {
+          .ver();
+
+          .name {
+            .size(36rpx);
+            font-weight: 700;
+            color: var(--text);
+          }
+
+          .phone,
+          .code {
+            color: var(--text-01);
+            margin-left: 30rpx;
+            .size(28rpx);
+            font-weight: 700;
+          }
+        }
+
+        .icon-left {
+          color: var(--text-01);
+          transform: rotate(180deg);
+          .size();
+        }
+      }
+
+      &_middle {
+        text-wrap: wrap;
+        white-space: pre-wrap;
+        word-wrap: break-word;
+        .size(28rpx);
+        color: var(--text-01);
+        margin-top: 8rpx;
+        line-height: 48rpx;
+        margin-bottom: 12rpx;
+      }
+
+      &_bottom {
+        .flex();
+        flex-wrap: wrap;
+        gap: 24rpx;
+
+        .default_btn,
+        .label_btn {
+          padding: 8rpx 16rpx;
+          .size(24rpx);
+          border-radius: 8rpx;
+        }
+
+        .default_btn {
+          color: var(--danger);
+          background-color: #e62e2e1a;
+        }
+
+        .label_btn {
+          background-color: #ff66331a;
+          color: var(--primary);
+        }
+      }
+    }
+  }
+}
+.pop_cont {
+  .cont_list {
+    .ver();
+
+    ._list_item {
+      flex: 1;
+      margin-left: 12rpx;
+
+      ._item_top {
+        line-height: 48rpx;
+
+        ._top_left {
+          .ver();
+          color: var(--text);
+
+          .name,
+          .phone {
+            .size(28rpx);
+            font-weight: 700;
+          }
+
+          .phone {
+            margin-left: 16rpx;
+          }
+        }
+      }
+
+      ._item_middle {
+        color: var(--text-02);
+        .size(24rpx);
+        line-height: 40rpx;
+        text-wrap: wrap;
+        white-space: pre-wrap;
+        word-wrap: break-word;
+        margin-bottom: 12rpx;
+        word-break: break-all;
+      }
+
+      ._item_bottom {
+        .flex();
+        flex-wrap: wrap;
+        gap: 24rpx;
+
+        .default_btn,
+        .label_btn {
+          padding: 8rpx 16rpx;
+          .size(24rpx);
+          border-radius: 8rpx;
+        }
+
+        .default_btn {
+          color: var(--danger);
+          background-color: #e62e2e1a;
+        }
+
+        .label_btn {
+          background-color: #ff66331a;
+          color: var(--primary);
+        }
+      }
+    }
+
+    .icon-edit {
+      .size(36rpx);
+      color: var(--primary);
+    }
+  }
+}
+
+.footer_btn {
+  height: 38px;
+  padding: 16rpx 30rpx;
+  background-color: var(--black);
+  color: var(--light);
+  .flex_center();
+  border-radius: 16rpx;
+  .size(24rpx);
+}
+</style>

+ 269 - 0
pages/address/index.vue

@@ -0,0 +1,269 @@
+<template>
+  <Theme>
+    <view class="wrap">
+      <Navbar title="收货地址" fixed />
+      <view class="content">
+        <view class="address">
+          <view class="address_list" v-for="item, index in addressList" :key="index">
+            <view class="top">
+              <view class="top_title">
+                <view class="name">{{ item.firstName }} {{ item.lastName }}</view>
+                <view class="phone">{{ item.phoneNo }}</view>
+              </view>
+              <view class="top_address">
+                {{ item.country }}&nbsp;{{ item.province }}&nbsp;{{ item.city }}&nbsp;{{ item.address
+                }}
+              </view>
+            </view>
+            <view class="bottom">
+              <up-radio-group v-model="radioModel" placement="column" @change="groupChange(item)"
+                activeColor="var(--black)" inactiveColor="var(--text-01)" size="16">
+                <up-radio :name="item.id">
+                  <template #label>
+                    <trans class="radio_text" _t="默认" />
+                  </template>
+                </up-radio>
+              </up-radio-group>
+              <view class="btns">
+                <view class="del" @click="deleteClick(item.id)">
+                  <view class="_icon">
+                    <image src="../../static/shop/del.png" class="img"></image>
+                  </view>
+                  <trans class="label" _t="删除" />
+                </view>
+                <view class="del" @click="editAddress(item)">
+                  <view class="_icon">
+                    <image src="../../static/shop/edit.png" class="img"></image>
+                  </view>
+                  <trans class="label" _t="编辑" />
+                </view>
+              </view>
+            </view>
+          </view>
+        </view>
+      </view>
+      <view class="btn" @click="addressOpen">
+        <trans _t="新增收货地址" />
+      </view>
+    </view>
+    <Address ref="addressRef" />
+    <popup title="提醒" isClose ref="popRef">
+      <template #content>
+        <trans class="pop_cont" _t="您确认删除吗" />
+      </template>
+      <template #footer>
+        <view class="footer_btn">
+          <view class="btn" @click="() => popRef.close()">
+            <trans _t="取消" />
+          </view>
+          <view class="btn submit_btn" @click="submitClick">
+            <trans _t="确认" />
+          </view>
+        </view>
+      </template>
+    </popup>
+  </Theme>
+</template>
+
+<script setup>
+import Navbar from '@/components/navbar';
+import { computed, onMounted, nextTick, ref } from 'vue'
+import { useShopStore } from "@/store"
+import Address from "@/components/address";
+import { SHOP_ADDRESS_ADD, SHOP_ADDRESS_DEL } from "@/api"
+import { Toast } from "@/utils";
+import popup from '@/components/popup';
+
+const useShop = useShopStore();
+const addressRef = ref(null);
+const popRef = ref(null);
+const radioModel = ref('');
+const selectId = ref('');
+
+const addressList = computed(() => {
+  let list = useShop.getAddressList;
+  let obj = list.find(item => item.default == 1);
+  radioModel.value = obj && obj.id
+  return list
+});
+
+const groupChange = (item) => {
+  addressAdd({ ...item, default: item.default === 1 ? 0 : 1 })
+}
+
+const editAddress = (item) => {
+  addressRef.value && addressRef.value.open(item);
+}
+const addressOpen = () => {
+  addressRef.value && addressRef.value.open();
+}
+
+const addressAdd = async (params) => {
+  try {
+    await SHOP_ADDRESS_ADD(params);
+    nextTick(() => {
+      useShop.setAddressList();
+    })
+  } catch (error) {
+    Toast(error.msg);
+  }
+}
+const deleteClick = (id) => {
+  popRef.value && popRef.value.open();
+  selectId.value = id;
+}
+const submitClick = async () => {
+  try {
+    await SHOP_ADDRESS_DEL(selectId.value);
+    popRef.value && popRef.value.close();
+    nextTick(() => {
+      useShop.setAddressList();
+    })
+  } catch (error) {
+    popRef.value && popRef.value.close();
+    Toast(error.msg);
+  }
+}
+
+
+onMounted(() => {
+  nextTick(() => {
+    useShop.setAddressList();
+  })
+})
+</script>
+
+<style lang="less" scoped>
+@import url('@/style.less');
+
+.wrap {
+  background: var(--bg);
+  min-height: 100vh;
+
+  .content {
+    padding: 0 28rpx;
+    padding-bottom: 128rpx;
+
+    .address {
+      .address_list {
+        background-color: var(--inputBg);
+        border-radius: 10px;
+        margin-top: 28rpx;
+
+        .top {
+          border-bottom: 1px solid #F3F3F3;
+          padding: 24rpx 20rpx;
+
+          &_title {
+            .flex_position(space-between);
+
+            .name,
+            .phone {
+              .size();
+              line-height: 44rpx;
+              color: var(--black);
+            }
+          }
+
+          &_address {
+            word-wrap: break-word;
+            overflow-wrap: break-word;
+            white-space: pre-wrap;
+            padding-top: 16rpx;
+            color: var(--text-02);
+            line-height: 44rpx;
+            .size(28rpx);
+          }
+        }
+
+        .bottom {
+          padding: 20rpx;
+          .flex_position(space-between);
+
+          :deep(.u-radio) {
+            margin: 0;
+            align-items: baseline;
+
+            .u-radio__label-wrap {
+              .flex();
+            }
+          }
+
+          .radio_text {
+            .size(24rpx);
+            line-height: 24rpx;
+          }
+
+          .btns {
+            .ver();
+
+            .del {
+              .ver(flex-start);
+              margin-left: 24rpx;
+
+              ._icon {
+                width: 32rpx;
+                height: 32rpx;
+
+                .img {
+                  width: inherit;
+                  height: inherit;
+                }
+              }
+
+              .label {
+                color: var(--text-02);
+                .size(20rpx);
+                line-height: 44rpx;
+                margin-left: 6rpx;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+  .btn {
+    height: 100rpx;
+    position: fixed;
+    left: 28rpx;
+    right: 28rpx;
+    bottom: 28rpx;
+    background-color: var(--black);
+    padding: 28rpx;
+    .size();
+    color: var(--light);
+    font-weight: bold;
+    text-align: center;
+    border-radius: 20rpx;
+  }
+}
+
+.pop_cont {
+  color: var(--text-01);
+  .size(28rpx);
+  line-height: 60rpx;
+}
+
+.footer_btn {
+  .ver();
+  column-gap: 24rpx;
+
+  .btn {
+    flex: 1;
+    height: 38px;
+    padding: 16rpx 30rpx;
+    border: 1px solid var(--black);
+    border-radius: 16rpx;
+    .size(24rpx);
+    color: var(--black);
+    text-align: center;
+  }
+
+  .submit_btn {
+    background-color: var(--black);
+    color: var(--light);
+  }
+}
+</style>

+ 85 - 0
pages/bank/account.vue

@@ -0,0 +1,85 @@
+<template>
+  <Theme>
+    <view class="wrap">
+      <Navbar title="账单" border fixed />
+      <view class="content">
+        <List url="/users/account/lists" ref="listRef">
+          <template #item="{ item }">
+            <view class="list">
+              <view class="list_top">
+                <view class="title">{{ item.title }}</view>
+                <view class="money"
+                  >{{ symbol.symbol }}&nbsp;{{ Moneyhtml(item.setup) }}</view
+                >
+              </view>
+              <view class="date">{{ useGlobal().$format(item.indate) }}</view>
+            </view>
+          </template>
+        </List>
+      </view>
+    </view>
+  </Theme>
+</template>
+<script setup>
+import Navbar from "@/components/navbar";
+import List from "@/components/list";
+import { ref, computed, onMounted, nextTick } from "vue";
+import { useGlobal, Moneyhtml } from "@/utils";
+import { onReachBottom } from "@dcloudio/uni-app";
+import { useSystemStore } from "@/store";
+
+const useSystem = useSystemStore();
+const listRef = ref(null);
+const symbol = computed(() => useSystem.getSymbol);
+
+onMounted(() => {
+  nextTick(() => {
+    listRef.value && listRef.value.getData();
+  });
+});
+onReachBottom(() => {
+  nextTick(() => {
+    listRef.value && listRef.value.scrolltolower();
+  });
+});
+</script>
+<style lang="less" scoped>
+@import url("@/style.less");
+
+.wrap {
+  min-height: 100vh;
+  background-color: var(--bg);
+
+  .content {
+    padding: 0 24rpx;
+
+    .list {
+      padding: 24rpx;
+      background-color: var(--light);
+      margin-top: 24rpx;
+      border-radius: 12rpx;
+      border-bottom: var(--bor);
+      &_top {
+        .flex_position(space-between);
+        .size(28rpx);
+
+        .title {
+          color: var(--text);
+        }
+
+        .money {
+          font-weight: 700;
+          color: var(--danger);
+        }
+      }
+
+      .date {
+        color: var(--text-02);
+        .size(24rpx);
+        text-align: right;
+        margin-top: 8rpx;
+      }
+    }
+  }
+}
+</style>

+ 236 - 0
pages/bank/bank_pay.vue

@@ -0,0 +1,236 @@
+<template>
+  <Theme>
+    <view class="wrap">
+      <Navbar title="充值" fixed border>
+        <template #right>
+          <navMenu :options="{ icon: 'icon-home', text: '主页' }" />
+        </template>
+      </Navbar>
+      <view class="content">
+        <view class="cont">
+          <view class="item">
+            <view class="label">
+              <trans _t="充值金额" />:
+            </view>
+            <view class="value">{{ currency }}<text>{{ obj.money }}</text></view>
+          </view>
+          <view class="item">
+            <view class="item_left">
+              <view class="label">
+                <trans _t="银行名称" />:
+              </view>
+              <view class="value">{{ obj.setting.open }}</view>
+            </view>
+            <up-copy :content="obj.setting.open" :notice="t('复制成功')">
+              <trans class="copy" _t="复制" />
+            </up-copy>
+          </view>
+          <view class="item">
+            <view class="item_left">
+              <view class="label">
+                <trans _t="收款人" />:
+              </view>
+              <view class="value">{{ obj.setting.name }}</view>
+            </view>
+            <up-copy :content="obj.setting.name" :notice="t('复制成功')">
+              <trans class="copy" _t="复制" />
+            </up-copy>
+          </view>
+          <view class="item">
+            <view class="item_left">
+              <view class="label">
+                <trans _t="银行卡" />:
+              </view>
+              <view class="value">{{ obj.setting.card }}</view>
+            </view>
+            <up-copy :content="obj.setting.card" :notice="t('复制成功')">
+              <trans class="copy" _t="复制" />
+            </up-copy>
+          </view>
+        </view>
+        <view class="desc">
+          <view class="desc_title">
+            <trans _t="充值步骤" />:
+          </view>
+          <view class="desc_cont">
+            <view class="cont_list" v-for="item, index in obj.steps" :key="index">
+              {{ index + 1 }}.{{ item }}
+            </view>
+          </view>
+        </view>
+      </view>
+      <view class="btn" @click="paySubmit">
+        <trans _t="完成付款" />
+      </view>
+    </view>
+  </Theme>
+</template>
+<script setup>
+import { ref, computed } from "vue";
+import Navbar from "@/components/navbar";
+import navMenu from "@/components/nav_menu";
+import { useSystemStore, useUserStore } from "@/store";
+import { Toast } from "@/utils"
+import { PAY_SUBMIT } from "@/api"
+import { onLoad } from "@dcloudio/uni-app";
+import { t } from "@/locale"
+
+const useSystem = useSystemStore();
+const obj = ref({});
+
+const currency = computed(() => useSystem.getCurrency);
+
+const paySubmit = async () => {
+  try {
+    const res = await PAY_SUBMIT({
+      id: obj.value.id,
+      money: obj.value.money,
+      account: obj.value.account,
+      isbefore: 1
+    })
+    Toast(res.msg)
+  } catch (error) {
+    if (error.ret == 3) {
+      Toast(res.msg).then(res => {
+        setTimeout(() => {
+          uni.navigateBack();
+        }, 1000);
+      })
+    } else {
+      Toast(error.msg)
+    }
+  }
+}
+
+onLoad((options) => {
+  obj.value = JSON.parse(options.obj || '{}')
+})
+
+</script>
+<style lang="less" scoped>
+@import url('@/style.less');
+
+.wrap {
+  min-height: 100vh;
+  background-color: var(--bg);
+  .flex();
+  flex-direction: column;
+
+  .content {
+    padding: 24rpx;
+    flex-grow: 1;
+
+    .cont {
+      background-color: var(--light);
+      padding: 24rpx;
+      border-radius: 16rpx;
+
+      .item {
+        .flex_position(space-between);
+        color: var(--text);
+        column-gap: 24rpx;
+        line-height: 50rpx;
+
+        .label {
+          .size(28rpx);
+        }
+
+        .value {
+          .size(28rpx);
+
+          text {
+            .size(40rpx);
+            margin-left: 12rpx;
+          }
+        }
+
+        &_left {
+          .ver();
+          column-gap: 24rpx;
+        }
+
+        &:first-child {
+          justify-content: unset;
+        }
+
+        .copy {
+          color: var(--text);
+          .size(28rpx);
+        }
+      }
+
+      .item_address {
+        margin-top: 16rpx;
+
+        .label {
+          color: var(--text);
+          .size(28rpx);
+        }
+
+        .value {
+          border: 1px solid var(--borderColor);
+          margin-top: 16rpx;
+          .flex_position(space-between);
+          padding: 12rpx;
+          column-gap: 16rpx;
+          .size(28rpx);
+          color: var(--text);
+
+          .copy {
+            border: 1px solid var(--primary);
+            color: var(--primary);
+            .size(24rpx);
+            padding: 6rpx 18rpx;
+            border-radius: 50rpx;
+
+            text {
+              white-space: nowrap;
+            }
+          }
+        }
+      }
+
+      .item_qrimg {
+        margin-top: 16rpx;
+        aspect-ratio: 1 / 1;
+        width: 100%;
+        height: 100%;
+
+        .img {
+          width: inherit;
+          height: inherit;
+          display: block;
+        }
+      }
+    }
+
+    .desc {
+      margin-top: 16rpx;
+
+      &_title {
+        color: var(--text);
+        .size(28rpx);
+        line-height: 60rpx;
+      }
+
+      &_cont {
+        .cont_list {
+          color: var(--text);
+          .size(24rpx);
+          line-height: 40rpx;
+        }
+      }
+    }
+  }
+
+  .btn {
+    background-color: var(--black);
+    height: 52px;
+    padding: 16rpx 30rpx;
+    color: var(--light);
+    font-weight: 700;
+    .size(28rpx);
+    .flex_center();
+  }
+}
+</style>

+ 200 - 0
pages/bank/qrcode.vue

@@ -0,0 +1,200 @@
+<template>
+  <Theme>
+    <view class="wrap">
+      <Navbar title="充值" fixed border>
+        <template #right>
+          <navMenu :options="{ icon: 'icon-home', text: '主页' }" />
+        </template>
+      </Navbar>
+      <view class="content">
+        <view class="cont">
+          <view class="item">
+            <view class="label">
+              <trans _t="充值金额" />
+            </view>
+            <view class="value">{{ currency }}<text>{{ obj.money }}</text></view>
+          </view>
+          <view class="item_address">
+            <view class="label">
+              <trans _t="充值地址" />
+            </view>
+            <view class="value">
+              <view class="_url">
+                {{ obj.url }}
+              </view>
+              <up-copy :content="obj.url" :notice="t('复制成功')">
+                <trans _t="复制" />
+              </up-copy>
+            </view>
+          </view>
+          <view class="item_qrimg" v-if="!!obj.qrimg">
+            <image :src="obj.qrimg" class="img"></image>
+          </view>
+        </view>
+        <view class="desc">
+          <view class="desc_title">
+            <trans _t="充值步骤" />:
+          </view>
+          <view class="desc_cont">
+            <view class="cont_list" v-for="item, index in obj.steps" :key="index">
+              {{ index + 1 }}.{{ item }}
+            </view>
+          </view>
+        </view>
+      </view>
+      <view class="btn" @click="paySubmit">
+        <trans _t="完成付款" />
+      </view>
+    </view>
+  </Theme>
+</template>
+<script setup>
+import { ref, computed } from "vue";
+import Navbar from "@/components/navbar";
+import navMenu from "@/components/nav_menu";
+import { useSystemStore, useUserStore } from "@/store";
+import { Toast } from "@/utils"
+import { PAY_SUBMIT } from "@/api"
+import { onLoad } from "@dcloudio/uni-app";
+import { t } from "@/locale"
+
+const useSystem = useSystemStore();
+const obj = ref({});
+
+const currency = computed(() => useSystem.getCurrency);
+
+const paySubmit = async () => {
+  try {
+    const res = await PAY_SUBMIT({
+      id: obj.value.id,
+      money: obj.value.money,
+      account: obj.value.account,
+      isbefore: 1
+    })
+    Toast(res.msg).then(res => {
+      setTimeout(() => {
+        uni.navigateBack();
+      }, 1000);
+    })
+  } catch (error) {
+    Toast(error.msg)
+  }
+}
+
+onLoad((options) => {
+  obj.value = JSON.parse(options.obj || '{}')
+})
+
+</script>
+<style lang="less" scoped>
+@import url('@/style.less');
+
+.wrap {
+  min-height: 100vh;
+  background-color: var(--bg);
+  .flex();
+  flex-direction: column;
+
+  .content {
+    padding: 24rpx;
+    flex-grow: 1;
+
+    .cont {
+      background-color: var(--light);
+      padding: 24rpx;
+      border-radius: 16rpx;
+
+      .item {
+        .flex_position(space-between);
+        color: var(--text);
+
+        .label {
+          margin-right: 24rpx;
+          .size(28rpx);
+        }
+
+        .value {
+          .size(28rpx);
+
+          text {
+            .size(40rpx);
+            margin-left: 12rpx;
+          }
+        }
+      }
+
+      .item_address {
+        margin-top: 16rpx;
+
+        .label {
+          color: var(--text);
+          .size(28rpx);
+        }
+
+        .value {
+          border: 1px solid var(--borderColor);
+          margin-top: 16rpx;
+          .flex_position(space-between);
+          padding: 12rpx;
+          column-gap: 16rpx;
+          .size(28rpx);
+          color: var(--text);
+
+          .copy {
+            border: 1px solid var(--primary);
+            color: var(--primary);
+            .size(24rpx);
+            padding: 6rpx 18rpx;
+            border-radius: 50rpx;
+
+            text {
+              white-space: nowrap;
+            }
+          }
+        }
+      }
+
+      .item_qrimg {
+        margin-top: 16rpx;
+        aspect-ratio: 1 / 1;
+        width: 100%;
+        height: 100%;
+
+        .img {
+          width: inherit;
+          height: inherit;
+          display: block;
+        }
+      }
+    }
+
+    .desc {
+      margin-top: 16rpx;
+
+      &_title {
+        color: var(--text);
+        .size(28rpx);
+        line-height: 60rpx;
+      }
+
+      &_cont {
+        .cont_list {
+          color: var(--text);
+          .size(24rpx);
+          line-height: 40rpx;
+        }
+      }
+    }
+  }
+
+  .btn {
+    background-color: var(--primary);
+    height: 52px;
+    padding: 16rpx 30rpx;
+    color: var(--light);
+    font-weight: 700;
+    .size(28rpx);
+    .flex_center();
+  }
+}
+</style>

+ 296 - 0
pages/bank/recharge.vue

@@ -0,0 +1,296 @@
+<template>
+  <Theme>
+    <view class="wrap">
+      <Navbar fixed border title="充值">
+        <template #right>
+          <navMenu :options="{ icon: 'icon-home', text: '主页' }" />
+          <view class="nav_right" @click.stop="handleTo">
+            <trans _t="记录" />
+          </view>
+        </template>
+      </Navbar>
+      <view class="content">
+        <view>
+          <view class="recharge_top">
+            <view class="label">
+              <trans _t="余额" />
+            </view>
+            <view class="value"
+              >{{ symbol.symbol }} <text>{{ Moneyhtml(userInfo.money) }}</text>
+            </view>
+          </view>
+          <view class="recharge_money">
+            <view class="money">
+              <view class="label">
+                <trans _t="充值金额" />
+              </view>
+              <view class="value">
+                <text class="currency">{{ symbol.symbol }}</text>
+                <Input
+                  shape="square"
+                  v-model="money"
+                  :placeholder="t('请输入金额')"
+                />
+              </view>
+            </view>
+            <view class="money_list">
+              <view
+                class="_list"
+                :class="money == item ? 'active' : ''"
+                v-for="(item, index) in moneyList"
+                :key="index"
+                @click="listActive(item)"
+              >
+                <text>{{ symbol.symbol }} </text>{{ item }}
+              </view>
+            </view>
+          </view>
+        </view>
+        <!-- <view class="bank_list">
+          <view class="label">
+            <trans _t="选择充值方式" />
+          </view>
+          <view class="value">
+            <view
+              class="_list_"
+              v-for="(item, index) in bankList"
+              :key="index"
+              @click="paySubmit(item)"
+            >
+              <view class="_list_left">
+                <view class="bank_title">{{ item.title }}</view>
+                <view class="desc">{{ item.desc }}</view>
+              </view>
+              <i class="icon-font icon-left"></i>
+            </view>
+          </view>
+        </view> -->
+        <view class="footer" @click="paySubmit">
+          <trans _t="充值" />
+        </view>
+      </view>
+    </view>
+  </Theme>
+</template>
+<script setup>
+import { computed, ref, onMounted } from "vue";
+import Navbar from "@/components/navbar";
+import navMenu from "@/components/nav_menu";
+import { useSystemStore, useUserStore } from "@/store";
+import Input from "@/components/input";
+import { t } from "@/locale";
+import { PAY_LISTS, PAY_SUBMIT } from "@/api";
+import { openUrl, Toast, Moneyhtml } from "@/utils";
+
+const useUser = useUserStore();
+const useSystem = useSystemStore();
+const money = ref("");
+const moneyList = [500, 1000, 2000, 3000];
+const bankList = ref([]);
+
+const currency = computed(() => useSystem.getCurrency);
+const symbol = computed(() => useSystem.getSymbol);
+const userInfo = computed(() => useUser.getuserInfo);
+
+const listActive = (item) => {
+  if (money.value == item) return (money.value = "");
+  money.value = item;
+};
+
+const handleTo = () => {
+  uni.navigateTo({ url: "/pages/bank/recharge_list" });
+};
+
+const getPayList = async () => {
+  try {
+    const res = await PAY_LISTS();
+    const bankData = res.data;
+    let arr = [];
+    bankData.forEach((item) => {
+      if (item.lists.length) {
+        arr = [...arr, ...item.lists];
+      }
+    });
+    bankList.value = arr;
+  } catch (error) {}
+};
+
+const paySubmit = async () => {
+  if (!money.value) return Toast(t("请输入金额"));
+  let recharge_money = money.value;
+  if (symbol.value.code != "CNY") {
+    recharge_money = (Number(money.value) * Number(symbol.value.rate)).toFixed(
+      2
+    );
+  }
+  try {
+    const res = await PAY_SUBMIT({
+      money: recharge_money,
+    });
+    uni.navigateTo({
+      url: `/pages/shop/payment?oid=${res.data.orderid}&type=recharge`,
+    });
+  } catch (error) {
+    if (error.ret) {
+      uni.navigateTo({
+        url: `/pages/shop/payment?oid=${error.data.orderid}&type=recharge`,
+      });
+    } else {
+      Toast(error.msg);
+    }
+  }
+};
+
+onMounted(() => {
+  useUser.getUserInfo();
+  getPayList();
+});
+</script>
+<style lang="less" scoped>
+@import url("@/style.less");
+
+.wrap {
+  min-height: 100vh;
+  display: flex;
+  flex-direction: column;
+  background-color: var(--bg);
+
+  .nav_right {
+    color: var(--text);
+    .size(28rpx);
+    margin-left: 16rpx;
+  }
+
+  .content {
+    flex-grow: 1;
+    display: flex;
+    flex-direction: column;
+    justify-content: space-between;
+    padding: 24rpx;
+    padding-bottom: calc(24rpx + env(safe-area-inset-bottom));
+    box-sizing: border-box;
+    .recharge_top {
+      background-color: var(--light);
+      border-radius: 16rpx;
+      padding: 24rpx;
+      .size(28rpx);
+      .flex_position(space-between);
+      column-gap: 24rpx;
+
+      .value {
+        .size(40rpx);
+
+        text {
+          margin-left: 6rpx;
+        }
+      }
+    }
+
+    .recharge_money {
+      margin-top: 24rpx;
+      background-color: var(--light);
+      padding: 24rpx;
+      border-radius: 16rpx;
+
+      .money {
+        .label {
+          color: var(--text);
+          .size(28rpx);
+          font-weight: 700;
+        }
+
+        .value {
+          margin-top: 24rpx;
+          .ver();
+
+          .currency {
+            // .size();
+            // color: var(--text-02);
+            margin-right: 18rpx;
+          }
+        }
+      }
+
+      .money_list {
+        margin-top: 24rpx;
+        .flex();
+        gap: 24rpx;
+        background-color: var(--light);
+
+        ._list {
+          height: 76rpx;
+          padding: 8rpx;
+          background-color: var(--light);
+          color: var(--text);
+          border: 1px solid var(--black);
+          border-radius: 8rpx;
+          .flex_center();
+          flex: 1;
+          .size(28rpx);
+        }
+
+        .active {
+          background-color: var(--black);
+          color: var(--light);
+        }
+      }
+    }
+
+    .bank_list {
+      margin-top: 24rpx;
+      background-color: var(--light);
+      padding: 24rpx;
+      border-radius: 16rpx;
+
+      .label {
+        color: var(--text);
+        .size(28rpx);
+        font-weight: 700;
+      }
+
+      .value {
+        ._list_ {
+          .flex_position(space-between);
+          padding: 20rpx 0;
+          border-bottom: 1px solid var(--borderColor);
+
+          ._list_left {
+            .bank_title {
+              .size(28rpx);
+              color: var(--text);
+            }
+
+            .desc {
+              color: var(--text-01);
+              margin-top: 16rpx;
+              .size(24rpx);
+            }
+          }
+
+          .icon-left {
+            color: var(--text-01);
+            .size();
+            transform: rotate(180deg);
+          }
+
+          &:last-child {
+            border-bottom: none;
+          }
+        }
+      }
+    }
+
+    .footer {
+      padding: 0 24rpx 24rpx;
+      background-color: var(--black);
+      color: var(--light);
+      padding: 16rpx 30rpx;
+      height: 96rpx;
+      .flex_center();
+      border-radius: 16rpx;
+      font-weight: 700;
+      .size(28rpx);
+    }
+  }
+}
+</style>

+ 120 - 0
pages/bank/recharge_list.vue

@@ -0,0 +1,120 @@
+<template>
+  <Theme>
+    <view class="wrap">
+      <Navbar title="充值记录" fixed border>
+        <template #right>
+          <navMenu :options="{ icon: 'icon-home', text: '主页' }" />
+        </template>
+      </Navbar>
+      <view class="content">
+        <List url="/pay/record" ref="listRef">
+          <template #item="{ item }">
+            <view class="_list">
+              <view class="status">{{ statusText(item.status) }}</view>
+              <view class="_list_item">
+                <view class="label">
+                  <trans _t="订单号" />
+                </view>
+                <view class="value">{{ item.payid }}</view>
+              </view>
+              <view class="_list_item">
+                <view class="label">
+                  <trans _t="充值金额" />
+                </view>
+                <view class="money">{{ symbol.symbol }}<text>{{ Moneyhtml(item.money) }}</text></view>
+              </view>
+              <view class="indate">{{ useGlobal().$format(item.indate) }}</view>
+            </view>
+          </template>
+        </List>
+      </view>
+    </view>
+  </Theme>
+</template>
+<script setup>
+import Navbar from "@/components/navbar";
+import navMenu from "@/components/nav_menu";
+import List from "@/components/list";
+import { onMounted, ref, nextTick, computed } from "vue";
+import { useSystemStore } from "@/store";
+import { onReachBottom } from "@dcloudio/uni-app";
+import { t } from "@/locale"
+import { useGlobal, Moneyhtml } from "@/utils"
+
+
+const useSystem = useSystemStore();
+const symbol = computed(() => useSystem.getSymbol);
+const listRef = ref(null);
+
+const currency = computed(() => useSystem.getCurrency);
+
+const statusText = (status) => {
+  switch (status) {
+    case '待审核':
+      return t('待审核')
+      break;
+    case '已完成':
+      return t('已完成')
+      break;
+    default:
+      return status
+      break;
+  }
+}
+
+onMounted(() => {
+  nextTick(() => {
+    listRef.value && listRef.value.getData();
+  })
+})
+onReachBottom(() => {
+  nextTick(() => {
+    listRef.value && listRef.value.scrolltolower();
+  })
+})
+</script>
+<style lang="less" scoped>
+@import url('@/style.less');
+
+.wrap {
+  min-height: 100vh;
+  background-color: var(--bg);
+
+  .content {
+    padding: 0 24rpx;
+
+    ._list {
+      margin-top: 16rpx;
+      border-radius: 16rpx;
+      background-color: var(--light);
+      padding: 16rpx;
+      .size(28rpx);
+
+      .status {
+        .flex_position(flex-end);
+        line-height: 50rpx;
+      }
+
+      &_item {
+        .flex_position(space-between);
+        line-height: 50rpx;
+
+        .money {
+          .size(32rpx);
+
+          text {
+
+            margin-left: 8rpx;
+          }
+        }
+      }
+
+      .indate {
+        .flex_position(flex-end);
+        color: var(--text-01);
+        .size(24rpx);
+      }
+    }
+  }
+}
+</style>

+ 192 - 0
pages/bank/wallet.vue

@@ -0,0 +1,192 @@
+<template>
+  <Theme>
+    <view class="wrap">
+      <Navbar fixed border title="钱包" page="wallet">
+        <template #right>
+          <view class="nav_right" @click.stop="rightClick">
+            <trans _t="账单" />
+          </view>
+        </template>
+      </Navbar>
+      <view class="wallet_top" id="tops">
+        <view class="wallet_header">
+          <view class="wallet_header_content">
+            <trans class="cont_title" _t="余额" />
+            <view class="wallet_money">
+              <text class="currency">{{ symbol.symbol }}</text>
+              <text>{{ Moneyhtml(userInfo.money) }}</text>
+            </view>
+            <view class="wallet_btn">
+              <view
+                class="btn recharge"
+                @click="handleTo('/pages/bank/recharge')"
+              >
+                <trans _t="充值" />
+              </view>
+              <view
+                class="btn withdrawal"
+                @click="handleTo('/pages/bank/withdraw')"
+              >
+                <trans _t="提现" />
+              </view>
+            </view>
+          </view>
+        </view>
+      </view>
+      <view class="content">
+        <view class="cont">
+          <List url="/users/account/lists" ref="listRef">
+            <template #item="{ item }">
+              <view class="list">
+                <view class="list_top">
+                  <view class="title">{{ item.title }}</view>
+                  <view class="money"
+                    >{{ symbol.symbol }}&nbsp;{{ Moneyhtml(item.setup) }}</view
+                  >
+                </view>
+                <view class="date">{{ useGlobal().$format(item.indate) }}</view>
+              </view>
+            </template>
+          </List>
+        </view>
+      </view>
+    </view>
+  </Theme>
+</template>
+<script setup>
+import Navbar from "@/components/navbar";
+import { computed, ref, onMounted, nextTick } from "vue";
+import { useSystemStore, useUserStore } from "@/store";
+import List from "@/components/list";
+import { useGlobal, Toast, Moneyhtml } from "@/utils";
+import { onReachBottom } from "@dcloudio/uni-app";
+
+const useSystem = useSystemStore();
+const useUser = useUserStore();
+const listRef = ref(null);
+
+const currency = computed(() => useSystem.getCurrency);
+const userInfo = computed(() => useUser.getuserInfo);
+const symbol = computed(() => useSystem.getSymbol);
+
+const rightClick = () => {
+  uni.navigateTo({ url: "/pages/bank/account" });
+};
+
+const handleTo = (url) => {
+  uni.navigateTo({ url });
+};
+
+onMounted(() => {
+  nextTick(() => {
+    listRef.value && listRef.value.getData();
+  });
+});
+onReachBottom(() => {
+  nextTick(() => {
+    listRef.value && listRef.value.scrolltolower();
+  });
+});
+</script>
+<style lang="less" scoped>
+@import url("@/style.less");
+
+.wrap {
+  min-height: 100vh;
+  background-color: var(--bg);
+
+  .nav_right {
+    color: var(--text);
+    .size(24rpx);
+  }
+
+  .wallet_top {
+    .wallet_header {
+      background-color: var(--black);
+      padding: 24rpx;
+
+      &_content {
+        background-color: var(--light);
+        border-radius: 16rpx;
+        padding: 24rpx;
+        .ver();
+        flex-direction: column;
+
+        .cont_title {
+          color: var(--text-01);
+          .size(28rpx);
+          text-align: center;
+          font-weight: 700;
+          line-height: 60rpx;
+        }
+
+        .wallet_money {
+          line-height: 100rpx;
+          .size(48rpx);
+          color: var(--text);
+          font-weight: 700;
+
+          .currency {
+            // .size(28rpx);
+            margin-right: 8rpx;
+          }
+        }
+
+        .wallet_btn {
+          .flex();
+          column-gap: 24rpx;
+
+          .btn {
+            width: 240rpx;
+            height: 38px;
+            padding: 16rpx 30rpx;
+            border: 1px solid var(--black);
+            background-color: var(--black);
+            border-radius: 16rpx;
+            .size(24rpx);
+            color: var(--light);
+            text-align: center;
+          }
+
+          .withdrawal {
+            color: var(--black);
+            background-color: var(--light);
+          }
+        }
+      }
+    }
+  }
+
+  .content {
+    padding: 0 24rpx;
+
+    .list {
+      padding: 24rpx;
+      background-color: var(--light);
+      margin-top: 24rpx;
+      border-radius: 12rpx;
+      border-bottom: var(--bor);
+      &_top {
+        .flex_position(space-between);
+        .size(28rpx);
+
+        .title {
+          color: var(--text);
+        }
+
+        .money {
+          font-weight: 700;
+          color: var(--danger);
+        }
+      }
+
+      .date {
+        color: var(--text-02);
+        .size(24rpx);
+        text-align: right;
+        margin-top: 8rpx;
+      }
+    }
+  }
+}
+</style>

+ 302 - 0
pages/bank/withdraw.vue

@@ -0,0 +1,302 @@
+<template>
+  <Theme>
+    <view class="wrap">
+      <Navbar fixed border title="提现">
+        <template #right>
+          <navMenu :options="{ icon: 'icon-home', text: '主页' }" />
+          <view class="nav_right" @click.stop="handleTo">
+            <trans _t="记录" />
+          </view>
+        </template>
+      </Navbar>
+      <view class="content">
+        <view class="bank">
+          <view class="bank_item">
+            <view class="label">
+              <trans _t="可用余额" />({{ symbol.symbol }})
+            </view>
+            <view class="value">{{ symbol.symbol }}{{ Moneyhtml(userInfo.money) }}
+            </view>
+          </view>
+        </view>
+        <view class="bank">
+          <view class="bank_item">
+            <view class="label">
+              <trans _t="提款金额" />({{ symbol.symbol }})
+            </view>
+            <view class="money_value">
+              <Input v-model="money" shape="square" type="number" :placeholder="t('请输入提款金额')" />
+              <view class="all" @click="all">
+                <trans _t="全部" />
+              </view>
+            </view>
+          </view>
+        </view>
+        <view class="edit_bank" @click="() => popupRef.open()">
+          <view class="edit_label">
+            <trans _t="编辑您的银行卡" />
+          </view>
+          <i class="icon-font icon-back"></i>
+        </view>
+        <view class="btn" @click="submit">
+          <trans _t="提款" />
+        </view>
+      </view>
+      <popup title="您的银行卡账户" isClose ref="popupRef">
+        <template #content>
+          <view class="bank_info">
+            <view class="info_name">
+              <view class="label">
+                <trans _t="姓名" />
+              </view>
+              <view class="value">
+                <Input v-model="bank.name" shape="square" :placeholder="t('请填写持卡人姓名')" />
+              </view>
+            </view>
+            <view class="info_bank">
+              <view class="label">
+                <trans _t="银行名称" />
+              </view>
+              <view class="value">
+                <Input v-model="bank.bank" shape="square" :placeholder="t('请填写银行名称')" />
+              </view>
+            </view>
+            <view class="info_card">
+              <view class="label">
+                <trans _t="银行卡" />
+              </view>
+              <view class="value">
+                <Input v-model="bank.card" shape="square" :placeholder="t('请填写银行卡')" />
+              </view>
+            </view>
+          </view>
+        </template>
+        <template #footer>
+          <view class="footer_btn" :style="{ opacity: (bank.name && bank.card && bank.card) ? 1 : .5 }"
+            @click="AddBank">
+            <trans _t="保存" />
+          </view>
+        </template>
+      </popup>
+    </view>
+  </Theme>
+</template>
+<script setup>
+import Navbar from "@/components/navbar";
+import navMenu from "@/components/nav_menu";
+import popup from "@/components/popup"
+import { ref, onMounted, computed, nextTick } from "vue";
+import { useUserStore, useSystemStore } from "@/store"
+import Input from "@/components/input"
+import { t } from "@/locale"
+import { USER_BANK_ADD, USER_BANK, USER_EXTRACT } from "@/api"
+import { Toast, Moneyhtml } from "@/utils";
+import { onShow } from "@dcloudio/uni-app"
+
+const useUser = useUserStore();
+const useSystem = useSystemStore();
+const popupRef = ref(null);
+const money = ref('');
+const userInfo = computed(() => useUser.getuserInfo);
+const currency = computed(() => useSystem.getCurrency);
+const symbol = computed(() => useSystem.getSymbol);
+const bank = ref({
+  name: '',
+  bank: '',
+  card: ''
+})
+
+const handleTo = () => {
+  uni.navigateTo({ url: '/pages/bank/withdraw_list' })
+}
+const all = () => {
+  if (userInfo.value.money && Number(userInfo.value.money)) {
+    money.value = userInfo.value.money
+  }
+}
+
+const AddBank = async () => {
+  if (!bank.value.name && !bank.value.card && !bank.value.bank) return;
+  try {
+    const res = await USER_BANK_ADD(bank.value);
+    bank.value = res.data
+    nextTick(() => {
+      popupRef.value && popupRef.value.close();
+    })
+  } catch (error) {
+    Toast(error.msg)
+  }
+}
+
+const submit = async () => {
+  if (!money.value) return Toast(t('请输入提款金额'));
+  if (!bank.value.id) return popupRef.value && popupRef.value.open();
+  try {
+    const res = await USER_EXTRACT({
+      money: money.value,
+      bankid: bank.value.id
+    });
+    Toast(res.msg, 1000).then(() => {
+      setTimeout(() => {
+        uni.navigateTo({ url: '/pages/bank/withdraw_list' })
+      }, 1000)
+    })
+  } catch (error) {
+    Toast(error.msg
+    )
+  }
+}
+
+const getBankInfo = async () => {
+  try {
+    const res = await USER_BANK();
+    if (!res.data) return;
+    bank.value = res.data[0];
+  } catch (error) { }
+}
+
+onShow(() => {
+  useUser.getUserInfo();
+  getBankInfo();
+})
+</script>
+<style lang="less" scoped>
+@import url('@/style.less');
+
+.wrap {
+  min-height: 100vh;
+  background-color: var(--bg);
+
+  .nav_right {
+    color: var(--text);
+    .size(28rpx);
+    margin-left: 16rpx;
+  }
+
+  .content {
+    padding: 24rpx;
+
+    .bank {
+      padding: 16rpx 24rpx;
+      border-radius: 16rpx;
+      background-color: var(--light);
+      margin-bottom: 24rpx;
+
+      .bank_item {
+        .label {
+          color: var(--text);
+          .size(28rpx);
+          line-height: 50rpx;
+          font-weight: 700;
+        }
+
+        .value {
+          color: var(--black);
+          font-weight: 700;
+          .size(48rpx);
+          line-height: 92rpx;
+
+          text {
+            .size(28rpx);
+            margin-right: 12rpx;
+          }
+        }
+
+        .money_value {
+          .ver();
+          margin-top: 16rpx;
+          column-gap: 16rpx;
+
+          /deep/ .u-input {
+            border-radius: 16rpx;
+
+            .u-input__content__field-wrapper__field {
+              height: 38px;
+            }
+          }
+
+          .all {
+            color: var(--text);
+            .size(28rpx);
+            padding: 0 12rpx;
+          }
+        }
+      }
+    }
+
+    .edit_bank {
+      padding: 16rpx 24rpx;
+      border-radius: 16rpx;
+      background-color: var(--light);
+      .flex_position(space-between);
+
+      .edit_label {
+        .size(28rpx);
+        color: var(--text);
+        line-height: 60rpx;
+      }
+
+      .icon-back {
+        color: #7d8fb3;
+        transform: rotateY(180deg);
+        .size();
+      }
+    }
+
+    .btn {
+      height: 90rpx;
+      padding: 16rpx 30rpx;
+      .size(28rpx);
+      border-radius: 16rpx;
+      background-color: var(--black);
+      color: var(--light);
+      font-weight: 700;
+      .flex_center();
+      margin-top: 50rpx;
+    }
+  }
+
+  .bank_info {
+    width:100%;
+    .flex();
+    flex-direction: column;
+    row-gap: 24rpx;
+
+    .info_name,
+    .info_bank,
+    .info_card {
+      .ver();
+
+      .label {
+        color: var(--text);
+        .size(28rpx);
+        width: 160rpx;
+      }
+
+      .value {
+        flex: 1;
+
+        /deep/ .u-input {
+          border-radius: 16rpx;
+
+          .u-input__content__field-wrapper__field {
+            height: 38px;
+          }
+        }
+      }
+    }
+  }
+
+  .footer_btn {
+    height: 76rpx;
+    padding: 16rpx 30rpx;
+    .size(28rpx);
+    border-radius: 16rpx;
+    background-color: var(--black);
+    color: var(--light);
+    font-weight: 700;
+    .flex_center();
+    margin-top: 50rpx;
+  }
+}
+</style>

+ 132 - 0
pages/bank/withdraw_list.vue

@@ -0,0 +1,132 @@
+<template>
+  <Theme>
+    <view class="wrap">
+      <Navbar title="提现记录" fixed border>
+        <template #right>
+          <navMenu :options="{ icon: 'icon-home', text: '主页' }" />
+        </template>
+      </Navbar>
+      <view class="content">
+        <List url="/users/extract/record" ref="listRef">
+          <template #item="{ item }">
+            <view class="_list">
+              <view class="status">{{ statusText(item.status) }}</view>
+              <view class="_list_item">
+                <view class="label">
+                  <trans _t="订单号" />
+                </view>
+                <view class="value">{{ item.order_no }}</view>
+              </view>
+              <view class="_list_item">
+                <view class="label">
+                  <trans _t="取款金额" />
+                </view>
+                <view class="money"
+                  ><text
+                    >{{ symbol.symbol }}{{ Moneyhtml(item.money) }}</text
+                  ></view
+                >
+              </view>
+              <view class="_list_item" v-if="item.status == '未通过'">
+                <view class="label">
+                  <trans _t="未通过原因" />
+                </view>
+                <view class="money">{{ item.reason }}</view>
+              </view>
+              <view class="indate">{{ useGlobal().$format(item.indate) }}</view>
+            </view>
+          </template>
+        </List>
+      </view>
+    </view>
+  </Theme>
+</template>
+<script setup>
+import Navbar from "@/components/navbar";
+import navMenu from "@/components/nav_menu";
+import List from "@/components/list";
+import { onMounted, ref, nextTick, computed } from "vue";
+import { useSystemStore } from "@/store";
+import { onReachBottom } from "@dcloudio/uni-app";
+import { t } from "@/locale";
+import { useGlobal, Moneyhtml } from "@/utils";
+
+const useSystem = useSystemStore();
+const listRef = ref(null);
+
+const currency = computed(() => useSystem.getCurrency);
+
+const statusText = (status) => {
+  switch (status) {
+    case "汇款中":
+      return t("汇款中");
+      break;
+    case "已汇款":
+      return t("已汇款");
+      break;
+    case "未通过":
+      return t("未通过");
+      break;
+    default:
+      return status;
+      break;
+  }
+};
+
+onMounted(() => {
+  nextTick(() => {
+    listRef.value && listRef.value.getData();
+  });
+});
+onReachBottom(() => {
+  nextTick(() => {
+    listRef.value && listRef.value.scrolltolower();
+  });
+});
+</script>
+<style lang="less" scoped>
+@import url("@/style.less");
+
+.wrap {
+  min-height: 100vh;
+  background-color: var(--bg);
+
+  .content {
+    padding: 0 24rpx;
+
+    ._list {
+      margin-top: 16rpx;
+      border-radius: 16rpx;
+      background-color: var(--light);
+      padding: 16rpx;
+      border-bottom: var(--bor);
+      .size(28rpx);
+
+      .status {
+        .flex_position(flex-end);
+        line-height: 50rpx;
+      }
+
+      &_item {
+        .flex_position(space-between);
+        line-height: 50rpx;
+
+        .money {
+          .size(24rpx);
+
+          text {
+            .size(32rpx);
+            margin-left: 8rpx;
+          }
+        }
+      }
+
+      .indate {
+        .flex_position(flex-end);
+        color: var(--text-01);
+        .size(24rpx);
+      }
+    }
+  }
+}
+</style>

+ 265 - 0
pages/channel/index.vue

@@ -0,0 +1,265 @@
+<template>
+  <Theme>
+    <view class="wrap">
+      <Navbar title="tabbar.订单" leftShow border fixed>
+        <template #right>
+          <navMenu :options="{ icon: 'icon-home', text: '主页' }" />
+        </template>
+      </Navbar>
+      <!-- <view class="tops" id="tabs" :style="{ top: tabTop + 'px' }">
+        <view class="tab">
+          <Tab :active="actvieNum" keyName="text" :tabList="tabList" @confirm="tabClick" />
+        </view>
+        <view class="product_sort">
+          <view class="sort_list" :class="sortActive == index ? 'sort_active' : ''" v-for="item, index in sortList"
+            :key="index" @click="item.callback(item, index)">
+            <trans :_t="item.text" />
+            <template v-if="item.isTrue == 1">
+              <view class="sort_arrow">
+                <view class="sort_arrow_top"
+                  :style="defaultParams.sort == 'moneyAsc' ? { borderBottom: '4px solid #f0700c' } : {}"></view>
+                <view class="sort_arrow_bottom"
+                  :style="defaultParams.sort == 'moneyDesc' ? { borderTop: '4px solid #f0700c' } : {}"></view>
+              </view>
+            </template>
+          </view>
+        </view>
+      </view> -->
+      <view class="content">
+        <List
+          url="/shop/search/recommend"
+          :topHeight="tabHeight"
+          :defaultParams="defaultParams"
+          ref="listRef"
+        >
+          <template #item="{ item }">
+            <shopList :channel="actvieNum" :item="item" />
+          </template>
+        </List>
+      </view>
+    </view>
+    <Tabbar page="channel" />
+  </Theme>
+</template>
+<script setup>
+import { ref, reactive, computed, onMounted, nextTick } from "vue";
+import Tabbar from "@/components/tabbar";
+import navMenu from "@/components/nav_menu";
+import Navbar from "@/components/navbar";
+import { onReachBottom } from "@dcloudio/uni-app";
+import List from "@/components/list";
+import { query, systemInfo } from "@/utils";
+import shopList from "../index/components/shop_list";
+import popup from "@/components/popup";
+import Tab from "@/components/tabs";
+
+const searchValue = ref("");
+const listRef = ref(null);
+const popupRef = ref(null);
+const actvieNum = ref(1);
+const tabHeight = ref(0);
+const tabTop = ref(44);
+const sortActive = ref(0);
+const tabList = ref([
+  {
+    icon: "icon-ds-1688",
+    text: "1688",
+    channel: 0,
+  },
+  {
+    icon: "icon-ds-taobao",
+    text: "淘宝",
+    channel: 1,
+  },
+  {
+    icon: "icon-ds-jd",
+    text: "JD",
+    channel: 3,
+  },
+]);
+const defaultParams = reactive({});
+const sortList = reactive([
+  {
+    text: "综合",
+    sort: "",
+    callback: (index) => {
+      actvieNum.value = index;
+      defaultParams.sort = "";
+      nextTick(() => {
+        listRef.value && listRef.value.handleRefresh();
+      });
+    },
+  },
+  {
+    text: "价格",
+    isTrue: 1,
+    sort: "moneyDesc", // moneyAsc 升序
+    callback: (item, index) => {
+      priceClick(item, index);
+    },
+  },
+]);
+
+const priceClick = (item, index) => {
+  if (sortActive.value == index) {
+    if (defaultParams.sort == "moneyAsc") {
+      defaultParams.sort = "";
+      sortActive.value = 0;
+    } else {
+      defaultParams.sort = "moneyAsc";
+    }
+  } else {
+    sortActive.value = index;
+    defaultParams.sort = item.sort;
+  }
+  nextTick(() => {
+    listRef.value && listRef.value.handleRefresh();
+  });
+};
+
+const tabClick = (item, index) => {
+  defaultParams.channel = item.channel;
+  if (actvieNum.value == index) return;
+  actvieNum.value = index;
+  nextTick(() => {
+    listRef.value && listRef.value.handleRefresh();
+  });
+};
+
+onMounted(() => {
+  nextTick(async () => {
+    tabTop.value = systemInfo().statusBarHeight;
+    nextTick(() => {
+      listRef.value && listRef.value.getData();
+    });
+  });
+});
+
+onReachBottom(() => {
+  nextTick(() => {
+    listRef.value && listRef.value.scrolltolower();
+  });
+});
+uni.hideTabBar();
+</script>
+<style lang="less" scoped>
+@import url("@/style.less");
+
+.wrap {
+  min-height: calc(100vh - 50px);
+  background-color: var(--bg);
+
+  .nav_center {
+    width: calc(100% - 46px - 50px);
+
+    .icon-camera {
+      color: #adb8cc;
+      font-size: 56rpx;
+    }
+  }
+
+  .nav_right {
+    .icon-font {
+      .size(28px);
+      color: var(--text);
+    }
+  }
+
+  .tops {
+    // position: fixed;
+    // top: 44px;
+    // left: 0;
+    // right: 0;
+    // background-color: var(--bg);
+    // z-index: 1;
+    .tab {
+      padding: 0 24rpx;
+    }
+
+    .product_sort {
+      .flex();
+      padding: 24rpx 32rpx;
+
+      .sort_list {
+        color: var(--text);
+        .size(24rpx);
+        line-height: 40rpx;
+        margin-right: 72rpx;
+        padding: 16rpx 0;
+        .ver();
+
+        .sort_arrow {
+          margin-left: 20rpx;
+
+          &_top {
+            border-bottom: 4px solid #adb8cc;
+            border-left: 4px solid transparent;
+            border-right: 4px solid transparent;
+            font-size: 0;
+            height: 0;
+            line-height: 0;
+            margin-bottom: 1px;
+            width: 0;
+          }
+
+          &_bottom {
+            border-left: 4px solid transparent;
+            border-right: 4px solid transparent;
+            border-top: 4px solid #adb8cc;
+            font-size: 0;
+            height: 0;
+            line-height: 0;
+            margin-top: 1px;
+            width: 0;
+          }
+        }
+      }
+
+      .sort_active {
+        color: var(--primary);
+      }
+    }
+  }
+
+  .content {
+    padding: 16rpx 32rpx;
+
+    /deep/ .wrap_list {
+      .uni-scroll-view-content {
+        > uni-view {
+          .flex();
+          flex-wrap: wrap;
+          gap: 16rpx;
+
+          .u-list-item {
+            width: calc((100% - 16rpx) / 2);
+          }
+        }
+      }
+    }
+  }
+}
+
+.pop_cont {
+  color: var(--text);
+  .size(28rpx);
+  line-height: 60rpx;
+}
+
+.pop_tip {
+  color: var(--text-01);
+  .size(28rpx);
+  line-height: 60rpx;
+}
+
+.pop_btn {
+  margin-top: 32rpx;
+  height: 76rpx;
+  padding: 16rpx 30rpx;
+  color: var(--primary);
+  border: 1px solid var(--primary);
+  border-radius: 16rpx;
+  .size(24rpx);
+  .flex_center();
+}
+</style>

+ 52 - 0
pages/chat/hooks/useListHeight.js

@@ -0,0 +1,52 @@
+import { ref, nextTick, computed } from 'vue'
+import { onReady } from "@dcloudio/uni-app"
+import { query, systemInfo } from "@/utils"
+
+
+function useListHeight() {
+	const navbarNodeInfo = ref(null)
+	const footerHeightInfo = ref({
+		height: 0,
+		keyboardHeight: 0,
+		bottomSafeDistance: 0
+	})
+	const sysInfo = ref(systemInfo())
+
+
+	// 计算列表高度
+	const listHeight = computed(() => {
+		const { windowHeight } = sysInfo.value
+		const navbarHeight = navbarNodeInfo.value ? navbarNodeInfo.value.height : 0
+		let footerHeight = 0
+		if (footerHeightInfo.value) {
+			const { height = 0, keyboardHeight = 0, bottomSafeDistance = 0 } = footerHeightInfo.value
+			footerHeight = height + keyboardHeight
+			const isIOS = uni.getSystemInfoSync().platform === 'ios';
+			if (isIOS) {
+				footerHeight += bottomSafeDistance;
+			}
+		}
+
+		return windowHeight - navbarHeight - footerHeight
+	})
+
+
+	onReady(() => {
+		nextTick(() => {
+			query(".user-chat__navbar")
+				.then(result => {
+					navbarNodeInfo.value = result
+				})
+		})
+	})
+
+	return {
+		navbarNodeInfo,
+		footerHeightInfo,
+		sysInfo,
+		listHeight
+	}
+}
+
+
+export default useListHeight

+ 142 - 0
pages/chat/hooks/useMessageData.js

@@ -0,0 +1,142 @@
+import { reactive, ref, computed, watch } from 'vue';
+import { storeToRefs } from 'pinia';
+import { useSocketStore, useMessageStore } from "@/store";
+import { RONGIMCALL_OPEN, RONGIMCALL_HISTORY, RONGIMCALL_SEND } from '@/api';
+import { Toast, format } from '@/utils';
+
+
+function useMessageData() {
+
+	const useScoket = useSocketStore();
+	const useMessage = useMessageStore();
+	const { messageMap } = storeToRefs(useMessage);
+
+	const lowerThreshold = ref(80)
+	const distanceFromBottom = ref(0)
+
+	const newMessageCount = ref(0)
+	const dataList = ref([]);
+	const loadedAll = ref(false);
+	const isLoading = ref(false);
+	const historyMessageQuery = reactive({
+		page: 1,
+		pagesize: 20,
+		type: 'service'
+	})
+
+	const isOpenning = ref(false)
+
+	const channel = ref('')
+	const channelData = ref(null)
+
+	watch(
+		() => (messageMap.value),
+		(newVal, oldVal) => {
+			if (channel.value) {
+				const info = newVal[channel.value]
+				channelData.value = info
+				console.log("messageMap.value[channel.value]", info)
+				dataList.value = info.messageList
+				newMessageCount.value =
+					distanceFromBottom.value > lowerThreshold.value ?
+						info.unreadCount : 0;
+				console.log('newMessageCount.value', newMessageCount.value)
+			}
+		},
+		{
+			deep: true
+		}
+	)
+
+
+	function resetHistoryQuery() {
+		historyMessageQuery.page = 1
+		historyMessageQuery.pagesize = 20
+		historyMessageQuery.type = 'service'
+		loadedAll.value = false
+		isLoading.value = false
+	}
+
+	// 获取历史消息列表
+	function fetchHistoryMessageList() {
+		return new Promise(async (resolve, reject) => {
+			if (loadedAll.value) return;
+			if (isLoading.value) return;
+			isLoading.value = true;
+
+			try {
+				const result = await RONGIMCALL_HISTORY(historyMessageQuery, { isLoading: true });
+				const { lists, total } = result.data;
+				for (let i = 0; i < lists.length; i++) {
+					const msgInfo = {
+						...lists[i],
+						msg: JSON.parse(lists[i].msg)
+					}
+					useMessage.updateMessageList(channel.value, msgInfo, 'unshift')
+				}
+				loadedAll.value = lists.length < historyMessageQuery.pagesize;
+				historyMessageQuery.page = historyMessageQuery.page + 1;
+				isLoading.value = false;
+				resolve(result.data);
+			}
+			catch (err) {
+				isLoading.value = false;
+				reject(err);
+			}
+		})
+	}
+
+
+	function openService() {
+		if (isOpenning.value) return;
+		isOpenning.value = true;
+		resetHistoryQuery();
+		useMessage.openChannel({
+			type: 'service',
+			socket_id: useScoket.socketId
+		}).then(async (res) => {
+			channel.value = res.data.auth.channel
+			try {
+				const data = await fetchHistoryMessageList();
+				if (data.total < 1) {
+					const val = { ...res.data }
+					delete val.auth
+					dataList.push(val)
+					useMessage.updateMessageList(channel.value, val, 'unshift')
+				}
+				if (data.lists.length > 0) {
+					let result = data.lists[0]
+					let lastTime = result ? result.indate : (Date.now() / 1000).toFixed(0) - 0
+					useMessage.updateGlobalMapLasttime(`serviceChannel`, lastTime)
+				}
+			}
+			catch (err) { }
+			finally {
+				isOpenning.value = false;
+			}
+		})
+			.catch(() => {
+				isOpenning.value = false;
+			})
+	}
+	openService()
+
+
+
+	return {
+		useMessage,
+		channel,
+		channelData,
+		dataList,
+		newMessageCount,
+		lowerThreshold,
+		distanceFromBottom,
+		isLoading,
+		fetchHistoryMessageList,
+		openService
+	}
+}
+
+
+
+export default useMessageData

+ 36 - 0
pages/chat/hooks/useTools.js

@@ -0,0 +1,36 @@
+import { format } from '@/utils';
+
+function useTool() {
+	
+	// 处理消息时间显示
+	function handleTime(index, list) {
+		//第一条消息展示 && 两条消息的间隔时间超过10分钟则显示
+		const { indate } = list[index]
+		
+		if (index >= 1) {					
+			const { indate: old_indate } = list[index - 1]
+			if((Number(indate) - Number(old_indate)) >= 10 * 60){
+				return handleBetterTimeShow(Number(indate * 1000))
+			}
+		}
+		else {
+			return handleBetterTimeShow(Number(indate * 1000))
+		}
+	}
+	// 处理时间显示格式
+	function handleBetterTimeShow(value) {
+		// 今天的消息显示hh:mm 其余的显示yyyy-MM-dd hh:mm
+		if(format(new Date(value), 'yyyy-MM-dd') === format(new Date(), 'yyyy-MM-dd')){
+			return format(new Date(value), 'HH:mm')
+		}
+		return format(new Date(value), 'yyyy-MM-dd HH:mm')
+	}
+	
+	
+	return {
+		handleTime
+	}
+}
+
+
+export default useTool

+ 286 - 0
pages/chat/index copy.vue

@@ -0,0 +1,286 @@
+<template>
+  <Theme>
+    <view class="user-chat__wrap">
+      <!-- navbar -->
+      <view class="user-chat__navbar">
+        <Navbar fixed leftIconColor="var(--black)" id="chat_nav" leftShow>
+          <template #center>
+            <view class="nav_title">
+              <trans _t="网购助手" />
+            </view>
+          </template>
+        </Navbar>
+      </view>
+
+      <!-- list box -->
+      <view class="message_body">
+        <MessageList
+          ref="messageListRef"
+          :lower-threshold="lowerThreshold"
+          :height="listHeight ? `${listHeight - tabbarHeight}px` : ''"
+          :listHeight="listHeight ? listHeight : 0"
+          :tabbarHeight="tabbarHeight"
+          :data-list="dataList"
+          :loading="isLoading"
+          @on-scroll="handleScroll"
+          @on-scroll-top="handleScrollTop"
+          @on-scroll-bottom="handleScrollBottom"
+        ></MessageList>
+      </view>
+
+      <view
+        class="new_count"
+        :style="{ bottom: footerHeightInfo.height + tabbarHeight + 5 + 'px' }"
+        v-show="newMessageCount > 0"
+        @click="messageListRef && messageListRef.computeScrollHeight()"
+      >
+        <text>{{ newMessageCount }} {{ $t("条新消息") }}</text>
+      </view>
+      <footer-input
+        ref="footerInputRef"
+        v-model="message"
+        :bottomHeight="tabbarHeight"
+        @heights="getFooterHeight"
+        @submit="onMessageSend"
+        @imageUp="imageUp"
+        @linechange="inputHeightChange"
+      />
+
+      <Tabbar page="chat" @getTabbarHeight="getTabbarHeight" />
+    </view>
+  </Theme>
+</template>
+
+<script setup>
+import { onUnload, onLoad } from "@dcloudio/uni-app";
+import {
+  ref,
+  reactive,
+  getCurrentInstance,
+  nextTick,
+  computed,
+  provide,
+} from "vue";
+import { storeToRefs } from "pinia";
+import { t } from "@/locale";
+import { getUuid } from "@/utils";
+import Navbar from "@/components/navbar";
+import Tabbar from "@/components/tabbar";
+import MessageList from "./modules/messageList.vue";
+import footerInput from "@/components/footer_input";
+import { useSocketStore, useUserStore, useTabbarStore } from "@/store";
+import useListHeight from "./hooks/useListHeight";
+import useMessageData from "./hooks/useMessageData";
+
+const useScoket = useSocketStore();
+const useUser = useUserStore();
+const useTabbar = useTabbarStore();
+const { getuserInfo } = storeToRefs(useUser);
+const { navbarNodeInfo, footerHeightInfo, listHeight } = useListHeight();
+const {
+  useMessage,
+  channel,
+  channelData,
+  dataList,
+  newMessageCount,
+  lowerThreshold,
+  distanceFromBottom,
+  isLoading,
+  isOpenning,
+  fetchHistoryMessageList,
+  openService,
+} = useMessageData();
+
+uni.$on("on-service-open", () => {
+  messageListRef.value && messageListRef.value.updateInitState();
+  openService();
+});
+
+uni.hideTabBar();
+
+provide("channel", channel);
+provide("channelData", channelData);
+
+const messageListRef = ref(null);
+const footerInputRef = ref(null);
+const footerInputLineCount = ref(1);
+const message = ref("");
+const tabbarHeight = ref(0);
+
+onLoad(() => {
+  useMessage.updateUnreadCount(channel.value, -1);
+  useMessage.updateGlobalMapUnreadCount("serviceChannel", -1);
+});
+onUnload(() => {
+  useScoket.send({
+    event: "pusher:unsubscribe",
+    data: { channel: channel.value },
+  });
+  useMessage.updateUnreadCount(channel.value, -1);
+  useMessage.updateGlobalMapUnreadCount("serviceChannel", -1);
+});
+
+function handleScroll(e) {
+  const { detail } = e;
+  const distanceForBottom =
+    detail.scrollHeight - detail.scrollTop - listHeight.value;
+  distanceFromBottom.value = distanceForBottom > 0 ? distanceForBottom : 0;
+  if (distanceFromBottom.value <= lowerThreshold.value) {
+    useMessage.updateUnreadCount(channel.value, -1);
+  }
+}
+// 滚动顶部回调
+function handleScrollTop() {
+  fetchHistoryMessageList();
+}
+function handleScrollBottom() {
+  useMessage.updateUnreadCount(channel.value, -1);
+}
+
+// 图片
+const imageUp = (url) => {
+  const msg = {
+    type: "image",
+    url: url,
+  };
+  sendMessage(msg, () => {
+    nextTick(() => {
+      messageListRef.value && messageListRef.value.computeScrollHeight();
+    });
+  });
+};
+// 消息发送:发送按钮回调(手机键盘右下角确认按钮回调&电脑键盘回车)
+function onMessageSend() {
+  if (!message.value) return;
+  const msg = {
+    type: "text",
+    text: message.value,
+  };
+  sendMessage(msg);
+}
+// 消息发送: 快捷问题
+function onQuestionSend(messageText) {
+  if (!(channelData.value && channelData.value.openInfo.status == 1)) return;
+  if (!messageText) return;
+  const msg = {
+    type: "text",
+    text: messageText,
+  };
+  sendMessage(msg, () => {
+    messageListRef.value && messageListRef.value.computeScrollHeight();
+  });
+}
+provide("onQuestionSend", onQuestionSend);
+
+function sendMessage(msg, callback) {
+  const messageData = reactive({
+    loading: true,
+    status: -1,
+    send: 1,
+    msg: msg,
+  });
+  useMessage.updateMessageList(channel.value, messageData, "push");
+  useMessage
+    .sendMessage(msg)
+    .then((data) => {
+      messageData.loading = false;
+      messageData.status = 1;
+      for (let key in data) {
+        if (key != "msg") {
+          messageData[key] = data[key];
+        }
+      }
+      useMessage.updateGlobalMapLasttime(`serviceChannel`, data.indate);
+    })
+    .catch(() => {
+      messageData.loading = false;
+      messageData.status = 0;
+    });
+  callback && callback();
+  /* if (footerInputLineCount.value == 1) {
+		messageListRef.value && messageListRef.value.computeScrollHeight();
+	} */
+  footerInputRef.value && footerInputRef.value.clear();
+}
+
+// 底部高度
+const getFooterHeight = (res) => {
+  footerHeightInfo.value = {
+    ...res,
+  };
+};
+const getTabbarHeight = (height) => {
+  tabbarHeight.value = height;
+};
+
+// 输入框高度发送变化
+const inputHeightChange = (res) => {
+  footerInputLineCount.value = res.detail.lineCount;
+};
+
+const leftClick = () => {
+  uni.switchTab({ url: "/pages/index/index" });
+  useTabbar.getPageCur("index");
+};
+</script>
+
+<style scoped lang="less">
+.user-chat__wrap {
+  display: flex;
+  flex-direction: column;
+  height: 100vh;
+  background-color: #fff;
+  padding-bottom: constant(safe-area-inset-bottom);
+  padding-bottom: env(safe-area-inset-bottom);
+}
+
+.nav_title {
+  color: var(--black);
+  font-size: 32rpx;
+  font-weight: 500;
+}
+
+.bg_logo {
+  position: absolute;
+  // .size(128rpx);
+  color: var(--inputBg);
+  opacity: 0.06;
+  top: 0;
+  left: 50%;
+  font-weight: bold;
+  transform: translateX(-50%);
+  line-height: 88rpx;
+  text-transform: uppercase;
+  font-family: "HarmonyOS_Sans";
+  text-wrap: nowrap;
+}
+
+.message_body {
+  width: 100%;
+  height: auto;
+}
+
+.new_count {
+  position: fixed;
+  bottom: 0;
+  right: 16rpx;
+  z-index: 20;
+  height: 52rpx;
+  padding: 0 20rpx;
+  border-radius: 26rpx;
+  background-color: rgba(0, 0, 0, 1);
+  color: #fff;
+  font-size: 24rpx;
+  line-height: 52rpx;
+}
+</style>
+
+<style lang="less">
+.message__input :deep(.uni-textarea-wrapper .uni-textarea-placeholder),
+.message__input :deep(.uni-textarea-wrapper .uni-textarea-line),
+.message__input :deep(.uni-textarea-wrapper .uni-textarea-compute),
+.message__input :deep(.uni-textarea-wrapper .uni-textarea-textarea) {
+  top: 50%;
+  transform: translateY(-50%);
+}
+</style>

+ 383 - 0
pages/chat/index.vue

@@ -0,0 +1,383 @@
+<template>
+  <Theme>
+    <view class="wrap">
+      <Navbar title="网购助手" fixed border leftShow id="navbar" />
+      <ConsultCard
+        class="topcard"
+        id="top_card"
+        :style="{ '--navbarHeight': navbarHeight + 'px' }"
+      ></ConsultCard>
+      <view
+        class="content"
+        :style="{
+          '--topHeight': topHeight + 'px',
+          '--height': bottomHeight + 'px',
+          '--keyboardHeight': keyboardHeight + 'px',
+          '--contHeight': contHeight + 'px',
+          '--navbarHeight': navbarHeight + 'px',
+          '--tabbarHeight': tabbarHeight + 'px',
+        }"
+      >
+        <scroll-view
+          class="chat_content"
+          scroll-anchoring
+          :scroll-y="true"
+          :scroll-top="scrollTop"
+          :lower-threshold="lowerThreshold"
+          :refresher-triggered="refresherTriggered"
+          :refresher-enabled="refresherEnabled"
+          @refresherrefresh="refresherrefresh"
+          refresher-default-style="none"
+          refresher-background="var(--bg)"
+          @scroll="onScroll"
+          @scrolltolower="onScrollLower"
+        >
+          <view class="refresher" v-if="refresherTriggered">
+            <up-loadmore :status="'loading'" :loadingText="$t('正在加载')" />
+          </view>
+          <view class="scroll" id="scroll_items">
+            <Message :list="msgList" />
+          </view>
+        </scroll-view>
+      </view>
+      <view
+        class="new_count"
+        :style="{ bottom: bottomHeight + tabbarHeight + 5 + 'px' }"
+        v-show="newMessageCount > 0"
+        @click="getContHeight"
+      >
+        <text>{{ newMessageCount }} {{ $t("条新消息") }}</text>
+      </view>
+      <footer-input
+        v-model="message"
+        :bottomHeight="tabbarHeight"
+        @heights="getFooterHeight"
+        @submit="send"
+        @linechange="inputHeightChange"
+        @imageUp="imageUp"
+        ref="footerInputRef"
+      />
+
+      <Tabbar page="chat" @getTabbarHeight="getTabbarHeight" />
+    </view>
+  </Theme>
+</template>
+<script setup>
+import { onUnload, onLoad, onShow } from "@dcloudio/uni-app";
+import { ref, nextTick, onMounted, reactive, watch, provide } from "vue";
+import Navbar from "@/components/navbar";
+import footerInput from "@/components/footer_input";
+import Message from "@/components/message";
+import Tabbar from "@/components/tabbar";
+import ConsultCard from "@/components/message/components/consultCard.vue";
+import { query, systemInfo, useGlobal } from "@/utils";
+import { RONGIMCALL_HISTORY } from "@/api";
+import { useSocketStore, useMessageStore } from "@/store";
+import { storeToRefs } from "pinia";
+
+const useSocket = useSocketStore();
+const useMessage = useMessageStore();
+const { messageMap } = storeToRefs(useMessage);
+const bottomHeight = ref(0);
+const scrollTop = ref(0);
+const keyboardHeight = ref(0);
+const contHeight = ref(0);
+const newHeight = ref(0);
+const message = ref("");
+const footerInputRef = ref(null);
+
+const refresherTriggered = ref(false);
+const refresherEnabled = ref(true);
+const msgList = ref([]);
+const page = ref(1);
+const pagesize = ref(10);
+const total = ref(0);
+
+const channel = ref("");
+const firstMsg = ref({});
+const lowerThreshold = ref(0);
+const distanceFromBottom = ref(0);
+const newMessageCount = ref(0);
+const bottomSafeDistanceHeight = ref(0);
+const tabbarHeight = ref(0);
+const topHeight = ref(0);
+const navbarHeight = ref(0);
+
+watch(
+  () => messageMap.value,
+  (newVal, oldVal) => {
+    const info = newVal[channel.value];
+    if (channel.value && info) {
+      msgList.value = info.messageList;
+      newMessageCount.value =
+        distanceFromBottom.value > lowerThreshold.value ? info.unreadCount : 0;
+    }
+  },
+  { deep: true, immediate: true }
+);
+
+provide("onQuestionSend", send);
+
+function onScroll(e) {
+  const { detail } = e;
+  const distanceForBottom =
+    detail.scrollHeight - detail.scrollTop - contHeight.value;
+  distanceFromBottom.value = distanceForBottom > 0 ? distanceForBottom : 0;
+  if (distanceFromBottom.value <= lowerThreshold.value) {
+    useMessage.updateUnreadCount(channel.value, -1);
+  }
+}
+function onScrollLower() {
+  useMessage.updateUnreadCount(channel.value, -1);
+}
+const refresherrefresh = () => {
+  refresherTriggered.value = true;
+  if (total.value <= page.value * pagesize.value) {
+    nextTick(() => {
+      refresherTriggered.value = false;
+    });
+    return;
+  }
+  page.value += 1;
+  nextTick(() => {
+    getHistory(true);
+  });
+};
+
+const getCont = () => {
+  nextTick(() => {
+    const { windowHeight, statusBarHeight } = systemInfo();
+    contHeight.value = windowHeight - statusBarHeight - navbarHeight.value;
+  });
+};
+
+const getContHeight = (isLoading) => {
+  try {
+    nextTick(async () => {
+      const res = await query("#scroll_items");
+      let info = uni.getSystemInfoSync();
+      if (isLoading) {
+        scrollTop.value = res.height - newHeight.value - navbarHeight.value;
+      } else {
+        if (info.platform === "ios") {
+          scrollTop.value =
+            res.height +
+            bottomHeight.value -
+            keyboardHeight.value +
+            tabbarHeight.value;
+        } else {
+          scrollTop.value =
+            res.height -
+            bottomHeight.value -
+            keyboardHeight.value -
+            tabbarHeight.value;
+        }
+      }
+      newHeight.value = res.height;
+    });
+  } catch (error) {}
+};
+const getFooterHeight = (res) => {
+  nextTick(() => {
+    bottomHeight.value = res.height || 0;
+    keyboardHeight.value = res.keyboardHeight || 0;
+    bottomSafeDistanceHeight.value = res.bottomSafeDistance || 0;
+    getContHeight();
+  });
+};
+
+function send(text) {
+  sendMessage({ type: "text", text: text || message.value });
+}
+
+const imageUp = (url) => {
+  sendMessage({ type: "image", url: url });
+};
+
+const sendMessage = (msgObject) => {
+  let messageData = reactive({
+    type: "service",
+    msg: JSON.stringify(msgObject),
+    send: 1,
+    loading: true,
+    status: -1,
+  });
+  useMessage.updateMessageList(channel.value, messageData, "push");
+  getContHeight();
+  useMessage
+    .sendMessage(msgObject, "service")
+    .then((data) => {
+      messageData.loading = false;
+      messageData.status = 1;
+      for (let key in data) {
+        if (key != "msg") {
+          messageData[key] = data[key];
+        }
+      }
+      useMessage.updateGlobalMapLasttime(`serviceChannel`, data.indate);
+    })
+    .catch(() => {
+      messageData.loading = false;
+      messageData.status = 0;
+    });
+  nextTick(() => {
+    footerInputRef.value && footerInputRef.value.clear();
+  });
+};
+
+const getTabbarHeight = (height) => {
+  tabbarHeight.value = height;
+};
+
+const inputHeightChange = () => {
+  // console.log("输入框高度发送变化");
+};
+const open = () => {
+  useMessage
+    .openChannel({
+      type: "service",
+      socket_id: useSocket.socketId,
+    })
+    .then(async (res) => {
+      firstMsg.value = res.data;
+      channel.value = res.data.auth.channel;
+      await getHistory();
+      await clearCount();
+    });
+};
+
+const getHistory = async (isLoading = false) => {
+  try {
+    let para = {
+      page: page.value,
+      pagesize: pagesize.value,
+      type: "service",
+    };
+    const res = await RONGIMCALL_HISTORY(para);
+    const lists = res.data.lists;
+    for (let i = 0; i < lists.length; i++) {
+      const msgInfo = {
+        ...lists[i],
+        msg: JSON.parse(lists[i].msg),
+      };
+      useMessage.updateMessageList(channel.value, msgInfo, "unshift");
+    }
+    if (lists.length > 0 && page.value == 1) {
+      let result = lists[0];
+      let lastTime = result
+        ? result.indate
+        : (Date.now() / 1000).toFixed(0) - 0;
+      useMessage.updateGlobalMapLasttime(`serviceChannel`, lastTime);
+    }
+    total.value = res.data.total;
+    !total.value &&
+      useMessage.updateMessageList(channel.value, firstMsg.value, "unshift");
+    if (total.value <= page.value * pagesize.value) {
+      nextTick(() => {
+        refresherEnabled.value = false;
+      });
+    }
+    nextTick(() => {
+      getContHeight(isLoading);
+      refresherTriggered.value = false;
+    });
+  } catch (error) {}
+};
+
+const clearCount = () => {
+  useMessage.updateUnreadCount(channel.value, -1);
+  useMessage.updateGlobalMapUnreadCount("serviceChannel", -1);
+};
+
+const getHeight = async () => {
+  try {
+    const res = await query("#top_card");
+    topHeight.value = res.height;
+    const resNav = await query("#navbar");
+    navbarHeight.value = resNav.height;
+  } catch (error) {}
+};
+
+const openAndGetHistory = async () => {
+  try {
+    await getHeight();
+    await open();
+    await getCont();
+    await getContHeight();
+  } catch (error) {
+    console.error(error);
+  }
+};
+onMounted(() => {
+  nextTick(() => {
+    openAndGetHistory();
+  });
+});
+uni.hideTabBar();
+onUnload(() => {
+  useSocket.send({
+    event: "pusher:unsubscribe",
+    data: { channel: channel.value },
+  });
+  clearCount();
+});
+</script>
+<style lang="less" scoped>
+@import url("@/style.less");
+
+.wrap {
+  background: var(--bg);
+  height: 100vh;
+  padding-bottom: constant(safe-area-inset-bottom);
+  padding-bottom: env(safe-area-inset-bottom);
+  .topcard {
+    position: sticky;
+    top: var(--navbarHeight);
+    padding: 0 30rpx;
+    background: var(--bg);
+    z-index: 10;
+  }
+  .content {
+    width: 100%;
+    // padding: 0 30rpx;
+
+    .chat_content {
+      height: calc(
+        var(--contHeight) - var(--keyboardHeight) - var(--height) -
+          var(--tabbarHeight)
+      );
+      /*  #ifdef  APP-PLUS  */
+      padding-bottom: constant(safe-area-inset-bottom);
+      padding-bottom: env(safe-area-inset-bottom);
+      /*  #endif  */
+      /*  #ifdef  H5  */
+      padding-bottom: calc(
+        var(--tabbarHeight) + var(--height) + constant(safe-area-inset-bottom)
+      );
+      padding-bottom: calc(
+        var(--tabbarHeight) + var(--height) + env(safe-area-inset-bottom)
+      );
+      // padding-bottom: calc(var(--tabbarHeight) + var(--height));
+      /*  #endif  */
+
+      .scroll {
+        overflow: hidden;
+      }
+    }
+  }
+
+  .new_count {
+    position: fixed;
+    bottom: 0;
+    right: 16rpx;
+    z-index: 20;
+    height: 52rpx;
+    padding: 0 20rpx;
+    border-radius: 26rpx;
+    background-color: rgba(0, 0, 0, 1);
+    color: #fff;
+    font-size: 24rpx;
+    line-height: 52rpx;
+  }
+}
+</style>

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است