[
  {
    "path": ".github/workflows/deploy-demo.yml",
    "content": "name: Deploy Pages Demo\n\non:\n  push:\n    branches: ['master']\n\n  workflow_dispatch:\n\npermissions:\n  contents: read\n  pages: write\n  id-token: write\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      # 设置服务器时区为东八区\n      - name: Set time zone\n        run: sudo timedatectl set-timezone 'Asia/Shanghai'\n      - uses: actions/checkout@v4\n      - uses: pnpm/action-setup@v2\n        with:\n          version: 8\n      - uses: actions/setup-node@v4\n        with:\n          node-version: '20'\n          cache: 'pnpm'\n      - name: Install dependencies\n        run: pnpm i --no-frozen-lockfile\n      - name: Build\n        run: pnpm build:h5\n      - name: Upload artifact\n        uses: actions/upload-pages-artifact@v3\n        with:\n          path: ./dist/build/h5\n\n  deploy:\n    environment:\n      name: github-pages\n      url: ${{ steps.deployment.outputs.page_url }}\n    runs-on: ubuntu-latest\n    needs: build\n    steps:\n      - name: Deploy to GitHub Pages\n        id: deployment\n        uses: actions/deploy-pages@v4"
  },
  {
    "path": ".gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n**/.eslintrc*\n**/.eslintcache*\n\nnode_modules\n.DS_Store\ndist\n*.local\n\n# Editor directories and files\n.idea\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?"
  },
  {
    "path": ".hbuilderx/launch.json",
    "content": "{\n  // launch.json 配置了启动调试时相关设置，configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/\n  // launchtype项可配置值为local或remote, local代表前端连本地云函数，remote代表前端连云端云函数\n  \"version\": \"0.0\",\n  \"configurations\": [\n    {\n      \"app-plus\": {\n        \"launchtype\": \"local\"\n      },\n      \"default\": {\n        \"launchtype\": \"local\"\n      },\n      \"mp-weixin\": {\n        \"launchtype\": \"local\"\n      },\n      \"type\": \"uniCloud\"\n    },\n    {\n      \"playground\": \"custom\",\n      \"type\": \"uni-app:app-android\"\n    }\n  ]\n}\n"
  },
  {
    "path": ".husky/pre-commit",
    "content": "#!/usr/bin/env sh\n. \"$(dirname -- \"$0\")/_/husky.sh\"\n\n# Run the pre-commit hook\nnpx --no-install -- lint-staged\n"
  },
  {
    "path": ".npmrc",
    "content": "# registry = https://registry.npmjs.org\nregistry = https://registry.npmmirror.com\n\nstrict-peer-dependencies=false\nauto-install-peers=true\nshamefully-hoist=true\n"
  },
  {
    "path": ".prettierignore",
    "content": "# Logs\nlogs\n*.log\n\n# Editor directories and files\n.vscode\n.idea\n**/*.svg\n\n# projects\n.husky\nnode_modules\nsrc/uni_modules/\nsrc/static/\ndist/\n\n# uniapp 插件生成的文件\nsrc/pages.json\nsrc/manifest.json\n"
  },
  {
    "path": ".release-it.json",
    "content": "{\n  \"plugins\": {\n    \"@release-it/conventional-changelog\": {\n      \"emoji\": true,\n      \"emojiPosition\": \"before\",\n      \"infile\": \"CHANGELOG.md\",\n      \"ignoreRecommendedBump\": true,\n      \"strictSemVer\": true\n    }\n  },\n  \"npm\": {\n    \"publish\": false\n  },\n  \"git\": {\n    \"commitMessage\": \"🐳 chore: release v${version}\"\n  },\n  \"github\": {\n    \"release\": false,\n    \"draft\": false\n  }\n}\n"
  },
  {
    "path": ".stylelintignore",
    "content": "node_modules\nsrc/uni_modules/\nsrc/static/\ndist/\n\n**/*.svg\n\n"
  },
  {
    "path": ".vscode/settings.json",
    "content": "{\n  // 默认格式化工具选择prettier\n  \"editor.defaultFormatter\": \"esbenp.prettier-vscode\",\n  \"files.encoding\": \"utf8\",\n  \"cSpell.words\": [\n    \"Attributify\",\n    \"autofocus\",\n    \"autoscan\",\n    \"bianjiliebiao\",\n    \"commitlint\",\n    \"conventionalcommits\",\n    \"darkmode\",\n    \"easycom\",\n    \"echart\",\n    \"Fbase\",\n    \"Fdemo\",\n    \"FILESYSTEMS\",\n    \"Fpages\",\n    \"Froute\",\n    \"infile\",\n    \"itemclick\",\n    \"Logined\",\n    \"miniprogram\",\n    \"mjsx\",\n    \"mtsx\",\n    \"nvue\",\n    \"plusplus\",\n    \"Prefixs\",\n    \"splashscreen\",\n    \"timedatectl\",\n    \"tseslint\",\n    \"unplugin\",\n    \"VITE\"\n  ],\n  \"GitCommitPlugin.ShowEmoji\": true, // 提交是否显示 emoji 符号\n  \"GitCommitPlugin.MaxSubjectCharacters\": 20, // 提交 Subject 最大字符数\n  // 增加自定义类型，可以配置多个\n  \"GitCommitPlugin.CustomCommitType\": [ // 自定义提交类型\n    // {\n    //   \"key\": \"wip\", \n    //   \"label\": \"wip\",\n    //   \"detail\": \"正在开发中\",\n    //   \"icon\":\"🔓️ \",\n    // },\n    // {\n    //   \"key\": \"workflow\", \n    //   \"label\": \"workflow\",\n    //   \"detail\": \"工作流程改进\",\n    //   \"icon\":\"⏳️ \",\n    // },\n    // {\n    //   \"key\": \"types\", \n    //   \"label\": \"types\",\n    //   \"detail\": \"类型定义文件修改\",\n    //   \"icon\":\"🚙 \",\n    // },\n  ],\n  \"GitCommitPlugin.Templates\": [ // 自定义提交模板\n    // {\n    //   \"templateName\": \"git-uni-plus\",\n    //   \"templateContent\": \"<icon><scope><type>(<scope>):<subject>\",\n    //   \"default\":true // 是否覆盖默认模板\n    // }\n  ],\n  // 配置stylelint检查的文件类型范围\n  \"stylelint.validate\": [\"css\", \"scss\", \"vue\", \"html\"], // 与package.json的scripts对应\n  \"stylelint.enable\": true, // 开启stylelint\n  \"css.validate\": false, // 关闭 vsocode 的 css校验\n  \"less.validate\": false, // 关闭 vsocode 的 less校验\n  \"scss.validate\": false, // 关闭 vsocode 的 scss校验\n  \"[shellscript]\": {\n    \"editor.defaultFormatter\": \"foxundermoon.shell-format\"\n  },\n  \"[dotenv]\": {\n    \"editor.defaultFormatter\": \"foxundermoon.shell-format\"\n  },\n  \"[vue]\": {\n    \"editor.defaultFormatter\": \"esbenp.prettier-vscode\"\n  },\n  \"[typescript]\": {\n    \"editor.defaultFormatter\": \"esbenp.prettier-vscode\"\n  },\n  \"[jsonc]\": {\n    \"editor.defaultFormatter\": \"esbenp.prettier-vscode\"\n  },\n  // 配置语言的文件关联\n  \"files.associations\": {\n    \"pages.json\": \"jsonc\", // pages.json 可以写注释\n    \"manifest.json\": \"jsonc\" // manifest.json 可以写注释\n  },\n  \"explorer.fileNesting.enabled\": true, // 开启文件嵌套\n  \"explorer.fileNesting.expand\": false, // 默认折叠\n  \"explorer.fileNesting.patterns\": {\n    \"*.ts\": \"$(capture).test.ts, $(capture).test.tsx\",\n    \"*.tsx\": \"$(capture).test.ts, $(capture).test.tsx\",\n    // \"*.env\": \"$(capture).env.*\",\n    \"README.md\": \"*.md\",\n    \"package.json\": \"pnpm-lock.yaml,pnpm-workspace.yaml,LICENSE,.gitattributes,.gitignore,.gitpod.yml,CNAME,.npmrc,.browserslistrc\",\n    \"eslint.config.mjs\": \".eslintignore,.prettierignore,.stylelintignore,commitlint.*,prettier.*,stylelint.*,.eslintrc-auto-import.*,.release*\",\n    \".env\": \".env.*\",\n  },\n  \"i18n-ally.localesPaths\": [\n    \"src/i18n\"\n  ]\n}"
  },
  {
    "path": ".vscode/vue3.code-snippets",
    "content": "{\n  \"Uni-Plus Vue3 SFC\": {\n    \"scope\": \"vue\",\n    \"prefix\": \"v3\",\n    \"description\": \"vue3 的 uni-plus sfc 文件模板\",\n    \"body\": [\n      \"<!--\",\n      \"@description: $1\",\n      \"@creationTime: ${CURRENT_YEAR}-${CURRENT_MONTH}-${CURRENT_DATE}\",\n      \"-->\\n\",\n      \"<route type=\\\"page\\\" lang=\\\"json5\\\" >\",\n      \"{\",\n      \"  layout: 'default',\",\n      \"  style: {\",\n      \"    navigationBarTitleText: '$2',\",\n      \"  },\",\n      \"}\",\n      \"</route>\\n\",\n      \"<template>\",\n      \"  <view>$3</view>\",\n      \"</template>\\n\",\n      \"<script lang=\\\"ts\\\" setup>\",\n      \"/* ------------------------ 导入 与 引用 ----------------------------------- */\",\n      \"/* ------------------------ 函数 与 方法 ----------------------------------- */\",\n      \"/* ------------------------- 生命周期 -------------------------------------- */\",\n      \"</script>\\n\",\n      \"<style lang=\\\"scss\\\" scoped></style>\\n\",\n    ],\n  }\n}\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Changelog\r\n\r\n## 1.0.0 (2025-02-11)\r\n\r\n- ✨ feat: 适配 H5 与 微信小程序端 ([c438d98](https://github.com/DaMaiCoding/uni-plus/commit/c438d98))\r\n- ✨ feat: 完善 首页基本功能 ([27773cd](https://github.com/DaMaiCoding/uni-plus/commit/27773cd))\r\n- ✨ feat: 优化 暗黑模式 与 增加各个案例的链接 ([2a9a70b](https://github.com/DaMaiCoding/uni-plus/commit/2a9a70b))\r\n- ✨ feat: 增加 demo 导航页 ([e107631](https://github.com/DaMaiCoding/uni-plus/commit/e107631))\r\n- ✨ feat: 增加 README.md 与 LICENSE 开源协议 ([582cd6d](https://github.com/DaMaiCoding/uni-plus/commit/582cd6d))\r\n- 🎈 perf: 去掉 vue-i18n，使用自定义代替 ([6833bd9](https://github.com/DaMaiCoding/uni-plus/commit/6833bd9))\r\n- 🎉 init: 项目初始化 ([baf10db](https://github.com/DaMaiCoding/uni-plus/commit/baf10db))\r\n- 🐎 ci: 修复 CI build 报错 ([b5fed26](https://github.com/DaMaiCoding/uni-plus/commit/b5fed26))\r\n- 🐎 ci: 修复 CI build 报错 ([23c00d0](https://github.com/DaMaiCoding/uni-plus/commit/23c00d0))\r\n- 🐎 ci: 增加 在线 DEMO ([65c571b](https://github.com/DaMaiCoding/uni-plus/commit/65c571b))\r\n- 🐞 fix: 修复 全局 CSS 变量不生效问题 ([0d35ac9](https://github.com/DaMaiCoding/uni-plus/commit/0d35ac9))\r\n- 🐞 fix: 修复 uni-plus DEMO 不显示问题 ([d4f3a86](https://github.com/DaMaiCoding/uni-plus/commit/d4f3a86))\r\n- 📃 docs: 优化 README.md ([f1a1b59](https://github.com/DaMaiCoding/uni-plus/commit/f1a1b59))\r\n- 📃 docs: 增加 README 兼容性 环境配置 ([22787a1](https://github.com/DaMaiCoding/uni-plus/commit/22787a1))\r\n\r\n## <small>0.0.12 (2025-01-02)</small>\r\n\r\n- ✨ feat: git 提交规范化 ([cc31756](https://gitee.com/FOM/uni-plus/commits/cc31756))\r\n- 🎈 perf: 去掉没必要的 eslint 缓存 ([d70797e](https://gitee.com/FOM/uni-plus/commits/d70797e))\r\n- 🎈 perf: 优化 git 提交 ([208478d](https://gitee.com/FOM/uni-plus/commits/208478d))\r\n\r\n## <small>0.0.1 (2024-12-31)</small>\r\n\r\n- ✨ feat: 新增 emoji ([7865661](https://gitee.com/FOM/uni-plus/commits/7865661))\r\n- uni-plus 项目初始化 ([be9e6fa](https://gitee.com/FOM/uni-plus/commits/be9e6fa))\r\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2024-present, 大麦大麦\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
  },
  {
    "path": "README.md",
    "content": "<p align=\"center\">\n  <a href=\"https://github.com/DaMaiCoding/uni-plus\">\n    <img width=\"160\" src=\"./src/static/local/logo.png\">\n  </a>\n</p>\n\n<h1 align=\"center\">\n  <b>一个 “超超超” 好用的 uniapp 开发模板</b>\n</h1>\n\n`uni-plus` 提供了 `layout布局`、`请求封装`、`请求拦截`、`权限控制`、`原子CSS`、`路由拦截`、`路由自动导入` 等基础功能，并且配备了 `代码提示`、`代码高亮`、`代码格式化`、`commit 优化` 等开发环境配置，让您的开发更加高效、便捷。\n\n<p align=\"center\">\n  <a href=\"https://damaicoding.github.io/uni-plus-doc/\" target=\"_blank\">📓 文档地址</a>\n  <span style=\"margin:0 10px;\">|</span>\n  <a href=\"https://damaicoding.github.io/uni-plus/\" target=\"_blank\">🌰 预览地址</a>\n</p>\n\n| H5  | IOS | 安卓 | 微信小程序 | 字节小程序 | 快手小程序 | 支付宝小程序 | 钉钉小程序 | 百度小程序 |\n| --- | --- | ---- | ---------- | ---------- | ---------- | ------------ | ---------- | ---------- |\n| ✔️  | ✔️  | ✔️   | ✔️         | ✔️         | ✔️         | ✔️           | ✔️         | ✔️         |\n\n## ☘️ 环境配置\n\n- Node.js 20+\n- Pnpm 9+\n- Vue3 3.4+\n- TypeScript 4.9+\n\n## 🦈 mock 配置\n\n这个 `mock` 项目主要为 `demo` 分支的案例，提供 `mock` 数据\n\n如果你不下载这个 `mock` 项目来提供数据的话，里面请求部分的案例，将无法正常显示数据\n\n- [`mock` 项目地址（`github`）](https://github.com/DaMaiCoding/uni-plus-mock)\n\n- [`mock` 项目地址（`gitee`）](https://gitee.com/DaMaiCoding/uni-plus-mock)\n\n```shell\n# mock 项目下载下来后，执行下面命令运行即可\npnpm i\npnpm start:dev\n```\n\n## 🎯 快速开始\n\n```bash\npnpm create uni-plus my-project # my-project 为项目名称\npnpm i # 安装依赖\npnpm dev:h5 # 启动 h5 开发环境\n```\n\n## 📦 运行方式\n\n- 推荐使用 `VScode` 进行开发，因为本模板已经配置好了 `VScode` 的开发环境，包括代码格式化、代码提示、代码高亮、插件等\n- `Vscode` 开发的话，非 `h5` 的情况下，执行 `pnpm dev:mp-weixin` 然后打开微信开发者工具，导入 `dist/dev/mp-weixin` 文件，其他平台类似\n- 如果你使用 `HBuilderX` 开发，直接打开项目，鼠标选中项目文件文件，然后点击 运行 -> 允许到小程序模拟器，然后选择对应的平台即可\n\n## 😄 维护者\n\n[大麦大麦（DaMaiCoding）](https://github.com/DaMaiCoding)\n\n## 📄 许可证\n\n完全免费开源\n\n[MIT © 2024-present, 大麦大麦（DaMaiCoding）](./LICENSE)\n\n## 🤔 如何贡献\n\n非常欢迎您的加入！[提一个 Issue](https://github.com/DaMaiCoding/uni-plus/issues) 或者提交一个 `Pull Request`\n\n**Pull Request:**\n\n1. `Fork` 代码到自己的项目下，不要直接在仓库下建分支\n2. 请选择 `dev` 分支，进行 `PR`\n3. 提交 `PR` 前请 `rebase`，确保 `commit` 记录的整洁\n4. 注意 `commit` 信息规范，要以 `emoji type: 描述信息` 的形式填写，注意 `type` 得是下面规范之中的一个\n5. 示例 `commit` 信息：`🐞 fix: 修复 无感刷新 重试失败问题`\n6. 可以使用项目中的 `pnpm cz` 进行 `commit` 提交，这样就会默认为 `type` 前面添加 `emoji`\n7. 等待作者 `review` 通过后，即可合并\n\n## ⌛ Git 贡献提交规范\n\n参考 [历史提交记录](https://github.com/DaMaiCoding/uni-plus/commits/dev)\n\n- `✨ feat` 新增功能\n- `🐞 fix` 修复 bug\n- `📃 docs` 文档变更\n- `🌈 style` 代码格式（仅仅修改了空格、缩进、逗号等等，不改变代码逻辑）\n- `🦄 refactor` 代码重构，没有加新功能或修复 bug\n- `🎈 perf` 代码优化，比如提升性能、体验\n- `🔧 build` 构建流程、外部依赖变更 (如升级 npm 包、修改打包配置等)\n- `🐳 chore` 对构建过程或辅助工具和库的更改 (不影响源文件、测试用例)\n- `⏳️ workflow` 工作流程改进\n\n## ⭐ Star\n\n非常感谢留下星星的 `小哥哥 、小姐姐`，感谢您的支持 ❤\n\n[![Stargazers repo roster for @DaMaiCoding/uni-plus](https://bytecrank.com/nastyox/reporoster/php/stargazersSVG.php?user=DaMaiCoding&repo=uni-plus)](https://github.com/DaMaiCoding/uni-plus/stargazers)\n"
  },
  {
    "path": "commitlint.config.cjs",
    "content": "// const fs = require('fs')\n// const path = require('path')\n// const { execSync } = require('child_process')\n\n// const scopes = fs\n//   .readdirSync(path.resolve(__dirname, 'src'), { withFileTypes: true })\n//   .filter(dirent => dirent.isDirectory())\n//   .map(dirent => dirent.name.replace(/s$/, ''))\n\n// // precomputed scope\n// const scopeComplete = execSync('git status --porcelain || true')\n//   .toString()\n//   .trim()\n//   .split('\\n')\n//   .find(r => ~r.indexOf('M  src'))\n//   ?.replace(/(\\/)/g, '%%')\n//   ?.match(/src%%((\\w|-)*)/)?.[1]\n//   ?.replace(/s$/, '')\n\nmodule.exports = {\n  userEmoji: true,\n  // ignores: [commit => commit.includes('init')],\n  extends: ['git-commit-emoji'],\n  rules: {\n    // 'header-max-length': [2, 'always', 108],\n  },\n  prompt: {\n    /** @use `pnpm commit :f` */\n    // customScopesAlign: !scopeComplete ? 'top' : 'bottom', //  如果 scope 不完整，则将 customScopesAlign 设置为 top，否则设置为 bottom\n    // defaultScope: scopeComplete, //  如果 scope 完整，则将 defaultScope 设置为 true，否则设置为 false\n    // scopes: [...scopes, 'mock'],\n    allowEmptyIssuePrefixs: false, //  不允许空 issue 前缀\n    allowCustomIssuePrefixs: false, //  不允许自定义 issue 前缀\n    // emptyScopesAlias: 'empty: 不填写',\n    // customScopesAlias: 'custom: 自定义',\n    skipQuestions: ['scope', 'body', 'breaking', 'footer'], // 跳过 body、breaking、footer 三个问题\n    userEmoji: true,\n    emojiAlign: 'left',\n\n    messages: {\n      type: '选择你要提交的类型 :',\n      // scope: '选择一个提交范围 (可选):',\n      // customScope: '请输入自定义的提交范围 :',\n      subject: '填写简短精炼的变更描述 :\\n',\n      // body: '填写更加详细的变更描述 (可选)。使用 \"|\" 换行 :\\n',\n      // breaking: '列举非兼容性重大的变更 (可选)。使用 \"|\" 换行 :\\n',\n      // footerPrefixsSelect: '选择关联issue前缀 (可选):',\n      // customFooterPrefixs: '输入自定义issue前缀 :',\n      // footer: '列举关联issue (可选) 例如: #31, #I3244 :\\n',\n      confirmCommit: '是否提交或修改commit ?'\n    },\n\n    typeEnum: [\n      'init',\n      'feat',\n      'fix',\n      'docs',\n      'style',\n      'refactor',\n      'perf',\n      'test',\n      'build',\n      'ci',\n      'chore',\n      'wip',\n      'workflow',\n      'types',\n      'versions',\n      'revert'\n    ],\n\n    types: [\n      { value: 'init', name: '🎉 init: 初始化项目', emoji: '🎉' },\n      { value: 'feat', name: '✨ feat: 新增功能', emoji: '✨' },\n      { value: 'fix', name: '🐞 fix: 修复bug', emoji: '🐞' },\n      { value: 'docs', name: '📃 docs: 文档变更', emoji: '📃' },\n      { value: 'style', name: '🌈 style: 代码格式（仅仅修改了空格、缩进、逗号等等，不改变代码逻辑）', emoji: '🌈' },\n      { value: 'refactor', name: '🦄 refactor: 代码重构，没有加新功能或修复bug', emoji: '🦄' },\n      { value: 'perf', name: '🎈 perf: 代码优化，比如提升性能、体验', emoji: '🎈' },\n      { value: 'test', name: '🧪 test: 添加疏漏测试或已有测试改动', emoji: '🧪' },\n      { value: 'build', name: '🔧 build: 构建流程、外部依赖变更 (如升级 npm 包、修改打包配置等)', emoji: '🔧' },\n      { value: 'ci', name: '🐎 ci: 修改 CI 配置，例如对k8s、docker的配置文件的修改', emoji: '🐎' },\n      { value: 'chore', name: '🐳 chore: 对构建过程或辅助工具和库的更改 (不影响源文件、测试用例)', emoji: '🐳' },\n      { value: 'wip', name: '🔓️ wip: 正在开发中', emoji: '🔓️' },\n      { value: 'workflow', name: '⏳️ workflow: 工作流程改进', emoji: '⏳️' },\n      { value: 'types', name: '🚙 types: 类型定义文件修改', emoji: '🚙' },\n      { value: 'versions', name: '🔖 versions: 类型定义文件修改', emoji: '🔖' },\n      { value: 'revert', name: '↩ revert: 回滚 commit', emoji: '↩' }\n    ]\n  }\n}\n"
  },
  {
    "path": "components.d.ts",
    "content": "/* eslint-disable */\n/* prettier-ignore */\n// @ts-nocheck\n// Generated by vite-plugin-uni-components\n// Read more: https://github.com/vuejs/core/pull/3399\nexport {}\n\ndeclare module 'vue' {\n  export interface GlobalComponents {\n    WdBadge: (typeof import('wot-design-uni/components/wd-badge/wd-badge.vue'))['default']\n    WdButton: (typeof import('wot-design-uni/components/wd-button/wd-button.vue'))['default']\n    WdCalendar: (typeof import('wot-design-uni/components/wd-calendar/wd-calendar.vue'))['default']\n    WdCheckbox: (typeof import('wot-design-uni/components/wd-checkbox/wd-checkbox.vue'))['default']\n    WdConfigProvider: (typeof import('wot-design-uni/components/wd-config-provider/wd-config-provider.vue'))['default']\n    WdDivider: (typeof import('wot-design-uni/components/wd-divider/wd-divider.vue'))['default']\n    WdGrid: (typeof import('wot-design-uni/components/wd-grid/wd-grid.vue'))['default']\n    WdGridItem: (typeof import('wot-design-uni/components/wd-grid-item/wd-grid-item.vue'))['default']\n    WdIcon: (typeof import('wot-design-uni/components/wd-icon/wd-icon.vue'))['default']\n    WdSlider: (typeof import('wot-design-uni/components/wd-slider/wd-slider.vue'))['default']\n    WdSwitch: (typeof import('wot-design-uni/components/wd-switch/wd-switch.vue'))['default']\n    WdTab: (typeof import('wot-design-uni/components/wd-tab/wd-tab.vue'))['default']\n    WdTabs: (typeof import('wot-design-uni/components/wd-tabs/wd-tabs.vue'))['default']\n    WdTag: (typeof import('wot-design-uni/components/wd-tag/wd-tag.vue'))['default']\n  }\n}\n"
  },
  {
    "path": "eslint.config.mjs",
    "content": "// eslint.config.mjs\n\nimport globals from 'globals'\nimport pluginJs from '@eslint/js'\nimport { configs, parser } from 'typescript-eslint'\nimport pluginVue from 'eslint-plugin-vue'\nimport eslintPluginImportX from 'eslint-plugin-import-x'\n// import tsParser from '@typescript-eslint/parser'\nimport eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'\n\nimport { readFile } from 'node:fs/promises'\n\nconst autoImportFile = new URL('./.eslintrc-auto-import.json', import.meta.url)\nconst autoImportGlobals = JSON.parse(await readFile(autoImportFile, 'utf8'))\n\n/** @type {import('eslint').Linter.Config[]} */\nconst config = [\n  // 全局 files 指定 ESlint 匹配的文件\n  {\n    files: ['**/*.{js,mjs,jsx,mjsx,ts,tsx,mtsx,vue}']\n  },\n  // 基础配置\n  {\n    languageOptions: {\n      // 指定全局变量\n      globals: {\n        ...globals.browser, // 浏览器环境\n        ...globals.node, // node 环境\n        ...autoImportGlobals.globals, // 自动导入配置\n        $t: true,\n        uni: true,\n        wx: true,\n        assets: true,\n        UniApp: true,\n        WechatMiniprogram: true,\n        getCurrentPages: true,\n        UniHelper: true,\n        Page: true,\n        App: true,\n        NodeJS: true\n      },\n      // parser: tsParser,\n      ecmaVersion: 'latest',\n      sourceType: 'module'\n    }\n  },\n  pluginJs.configs.recommended,\n  ...configs.recommended,\n  ...pluginVue.configs['flat/essential'],\n  // eslint-plugin-import-x 扩展插件\n  eslintPluginImportX.flatConfigs.recommended,\n  eslintPluginImportX.flatConfigs.typescript,\n  // prettier 扩展插件\n  eslintPluginPrettierRecommended,\n  // 仅对所有 vue 文件的自定义配置\n  {\n    files: ['**/*.vue'],\n    languageOptions: { parserOptions: { parser: parser } }\n  },\n  // 自定义 rules\n  {\n    rules: {\n      // 不允许存在未使用的变量\n      '@typescript-eslint/no-unused-vars': 'warn',\n      // vue 组件必须多单词驼峰命名，关闭它\n      'vue/multi-word-component-names': 'off',\n      // 禁止变量重新声明\n      '@typescript-eslint/no-redeclare': 'error',\n      // 禁止变量重新声明，与 @typescript-eslint 重复提示了，关闭它\n      'no-redeclare': 'off',\n      // 关闭 import-x 的 no-unresolved\n      'import-x/no-unresolved': 'off',\n      '@typescript-eslint/no-explicit-any': 'off',\n      '@typescript-eslint/no-require-imports': 'off',\n      '@typescript-eslint/no-unused-expressions': 'off'\n    }\n  },\n  // ignores 提升为全局忽略项\n  {\n    ignores: ['src/uni_modules/', 'src/static/', '.vscode', '.husky']\n  }\n]\n\nexport default config\n"
  },
  {
    "path": "index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\" />\n    <script>\n      var coverSupport =\n        'CSS' in window &&\n        typeof CSS.supports === 'function' &&\n        (CSS.supports('top: env(a)') || CSS.supports('top: constant(a)'))\n      document.write(\n        '<meta name=\"viewport\" content=\"width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +\n          (coverSupport ? ', viewport-fit=cover' : '') +\n          '\" />'\n      )\n    </script>\n    <title></title>\n    <!--preload-links-->\n    <!--app-context-->\n  </head>\n  <body>\n    <div id=\"app\"><!--app-html--></div>\n    <script type=\"module\" src=\"/src/main.ts\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"uni-plus\",\n  \"version\": \"1.0.0\",\n  \"type\": \"commonjs\",\n  \"author\": {\n    \"name\": \"DaMaiCoding\",\n    \"zhName\": \"大麦大麦\",\n    \"email\": \"1351123861@qq.com\",\n    \"github\": \"https://github.com/DaMaiCoding\",\n    \"gitee\": \"https://gitee.com/DaMaiCoding\"\n  },\n  \"license\": \"MIT\",\n  \"repository\": \"https://github.com/DaMaiCoding/uni-plus\",\n  \"repository-gitee\": \"https://gitee.com/DaMaiCoding/uni-plus\",\n  \"bugs\": {\n    \"url\": \"https://github.com/DaMaiCoding/uni-plus/issues\"\n  },\n  \"homepage\": \"https://damaicoding.github.io/uni-plus/\",\n  \"engines\": {\n    \"node\": \">=18\",\n    \"pnpm\": \">=7.30\"\n  },\n  \"scripts\": {\n    \"dev:custom\": \"uni -p\",\n    \"dev:h5\": \"uni\",\n    \"dev:h5:ssr\": \"uni --ssr\",\n    \"dev:mp-alipay\": \"uni -p mp-alipay\",\n    \"dev:mp-baidu\": \"uni -p mp-baidu\",\n    \"dev:mp-jd\": \"uni -p mp-jd\",\n    \"dev:mp-kuaishou\": \"uni -p mp-kuaishou\",\n    \"dev:mp-lark\": \"uni -p mp-lark\",\n    \"dev:mp-qq\": \"uni -p mp-qq\",\n    \"dev:mp-toutiao\": \"uni -p mp-toutiao\",\n    \"dev:mp-weixin\": \"uni -p mp-weixin\",\n    \"dev:mp-xhs\": \"uni -p mp-xhs\",\n    \"dev:quickapp-webview\": \"uni -p quickapp-webview\",\n    \"dev:quickapp-webview-huawei\": \"uni -p quickapp-webview-huawei\",\n    \"dev:quickapp-webview-union\": \"uni -p quickapp-webview-union\",\n    \"build:custom\": \"uni build -p\",\n    \"build:h5\": \"uni build\",\n    \"build:h5:ssr\": \"uni build --ssr\",\n    \"build:mp-alipay\": \"uni build -p mp-alipay\",\n    \"build:mp-baidu\": \"uni build -p mp-baidu\",\n    \"build:mp-jd\": \"uni build -p mp-jd\",\n    \"build:mp-kuaishou\": \"uni build -p mp-kuaishou\",\n    \"build:mp-lark\": \"uni build -p mp-lark\",\n    \"build:mp-qq\": \"uni build -p mp-qq\",\n    \"build:mp-toutiao\": \"uni build -p mp-toutiao\",\n    \"build:mp-weixin\": \"uni build -p mp-weixin\",\n    \"build:mp-xhs\": \"uni build -p mp-xhs\",\n    \"build:quickapp-webview\": \"uni build -p quickapp-webview\",\n    \"build:quickapp-webview-huawei\": \"uni build -p quickapp-webview-huawei\",\n    \"build:quickapp-webview-union\": \"uni build -p quickapp-webview-union\",\n    \"prepare\": \"husky\",\n    \"release\": \"release-it\",\n    \"type-check\": \"vue-tsc --noEmit\",\n    \"cz\": \"czg emoji\"\n  },\n  \"lint-staged\": {\n    \"**/*.{vue,js,ts,jsx,tsx,mjs,cjs,html,json,md}\": [\n      \"prettier --write\"\n    ],\n    \"**/*.{vue,js,ts,jsx,tsx,mjs,cjs}\": [\n      \"eslint --fix\"\n    ],\n    \"**/*.{vue,css,scss,html}\": [\n      \"stylelint --fix\"\n    ]\n  },\n  \"dependencies\": {\n    \"@dcloudio/uni-app\": \"3.0.0-4040520250104002\",\n    \"@dcloudio/uni-app-harmony\": \"3.0.0-4040520250104002\",\n    \"@dcloudio/uni-app-plus\": \"3.0.0-4040520250104002\",\n    \"@dcloudio/uni-components\": \"3.0.0-4040520250104002\",\n    \"@dcloudio/uni-h5\": \"3.0.0-4040520250104002\",\n    \"@dcloudio/uni-mp-alipay\": \"3.0.0-4040520250104002\",\n    \"@dcloudio/uni-mp-baidu\": \"3.0.0-4040520250104002\",\n    \"@dcloudio/uni-mp-jd\": \"3.0.0-4040520250104002\",\n    \"@dcloudio/uni-mp-kuaishou\": \"3.0.0-4040520250104002\",\n    \"@dcloudio/uni-mp-lark\": \"3.0.0-4040520250104002\",\n    \"@dcloudio/uni-mp-qq\": \"3.0.0-4040520250104002\",\n    \"@dcloudio/uni-mp-toutiao\": \"3.0.0-4040520250104002\",\n    \"@dcloudio/uni-mp-weixin\": \"3.0.0-4040520250104002\",\n    \"@dcloudio/uni-mp-xhs\": \"3.0.0-4040520250104002\",\n    \"@dcloudio/uni-quickapp-webview\": \"3.0.0-4040520250104002\",\n    \"czg\": \"^1.11.0\",\n    \"echarts\": \"^5.6.0\",\n    \"husky\": \"^9.1.7\",\n    \"lodash-es\": \"^4.17.21\",\n    \"pinia\": \"^2.3.0\",\n    \"pinia-plugin-persistedstate\": \"^3.2.3\",\n    \"vue\": \"^3.4.21\",\n    \"wot-design-uni\": \"^1.6.1\",\n    \"z-paging\": \"^2.8.4\"\n  },\n  \"devDependencies\": {\n    \"@commitlint/cli\": \"^19.6.1\",\n    \"@dcloudio/types\": \"^3.4.8\",\n    \"@dcloudio/uni-automator\": \"3.0.0-4040520250104002\",\n    \"@dcloudio/uni-cli-shared\": \"3.0.0-4040520250104002\",\n    \"@dcloudio/uni-stacktracey\": \"3.0.0-4040520250104002\",\n    \"@dcloudio/vite-plugin-uni\": \"3.0.0-4040520250104002\",\n    \"@eslint/js\": \"^9.17.0\",\n    \"@iconify-json/uiw\": \"^1.2.1\",\n    \"@release-it/conventional-changelog\": \"^9.0.4\",\n    \"@types/wechat-miniprogram\": \"^3.4.8\",\n    \"@typescript-eslint/parser\": \"^8.18.2\",\n    \"@uni-helper/uni-types\": \"1.0.0-alpha.6\",\n    \"@uni-helper/vite-plugin-uni-components\": \"^0.2.0\",\n    \"@uni-helper/vite-plugin-uni-layouts\": \"^0.1.10\",\n    \"@uni-helper/vite-plugin-uni-pages\": \"^0.2.28\",\n    \"@unocss/preset-legacy-compat\": \"^65.4.2\",\n    \"@vue/runtime-core\": \"^3.4.21\",\n    \"@vue/tsconfig\": \"^0.1.3\",\n    \"commitlint-config-git-commit-emoji\": \"^1.0.0\",\n    \"eslint\": \"^9.17.0\",\n    \"eslint-config-prettier\": \"^9.1.0\",\n    \"eslint-import-resolver-typescript\": \"^3.7.0\",\n    \"eslint-plugin-import-x\": \"^4.6.1\",\n    \"eslint-plugin-prettier\": \"^5.2.1\",\n    \"eslint-plugin-vue\": \"^9.32.0\",\n    \"globals\": \"^15.14.0\",\n    \"lint-staged\": \"^15.4.1\",\n    \"prettier\": \"3.4.2\",\n    \"release-it\": \"^17.11.0\",\n    \"sass\": \"^1.78.0\",\n    \"sass-embedded\": \"^1.83.0\",\n    \"stylelint\": \"^16.12.0\",\n    \"stylelint-config-recess-order\": \"^5.1.1\",\n    \"stylelint-config-recommended\": \"^14.0.1\",\n    \"stylelint-config-recommended-scss\": \"^14.1.0\",\n    \"stylelint-config-recommended-vue\": \"^1.5.0\",\n    \"stylelint-config-standard\": \"^36.0.1\",\n    \"typescript\": \"^4.9.4\",\n    \"typescript-eslint\": \"^8.18.2\",\n    \"unocss\": \"0.65.2\",\n    \"unocss-applet\": \"~0.7.8\",\n    \"unplugin-auto-import\": \"^19.0.0\",\n    \"vite\": \"5.2.8\",\n    \"vite-plugin-restart\": \"^0.4.2\",\n    \"vue-tsc\": \"^1.0.24\"\n  }\n}\n"
  },
  {
    "path": "pages.config.ts",
    "content": "import { defineUniPages } from '@uni-helper/vite-plugin-uni-pages'\n\nexport default defineUniPages({\n  // 你也可以定义 pages 字段，它具有最高的优先级。\n  pages: [],\n  globalStyle: {\n    // 导航栏字体颜色\n    navigationBarTextStyle: '@navTxtStyle',\n    // 导航栏背景色\n    navigationBarBackgroundColor: '@navBgColor',\n    // 导航栏背景底色\n    backgroundColor: '@bgColor'\n  },\n  easycom: {\n    autoscan: true,\n    custom: {\n      '^wd-(.*)': 'wot-design-uni/components/wd-$1/wd-$1.vue',\n      '^(?!z-paging-refresh|z-paging-load-more)z-paging(.*)': 'z-paging/components/z-paging$1/z-paging$1.vue'\n    }\n  }\n})\n"
  },
  {
    "path": "prettier.config.mjs",
    "content": "// prettier.config.mjs\n\n/**\n * @see https://prettier.io/docs/en/configuration.html\n * @type {import(\"prettier\").Config}\n */\nconst config = {\n  // 不尾随分号\n  semi: false,\n  // 使用单引号\n  singleQuote: true,\n  // 多行逗号分割的语法中，最后一行不加逗号\n  trailingComma: 'none',\n  // 行尾风格，设置为auto\n  endOfLine: 'auto',\n  // 一行最多 100 字符\n  printWidth: 120,\n  // 使用 2 个空格缩进\n  tabWidth: 2,\n  // 不使用缩进符，而使用空格\n  useTabs: false,\n  // 单个参数的箭头函数不加括号 x => x\n  arrowParens: 'avoid',\n  // 对象大括号内两边是否加空格 { a:0 }\n  bracketSpacing: true,\n  // 忽略html中的空格\n  htmlWhitespaceSensitivity: 'ignore'\n}\n\nexport default config\n"
  },
  {
    "path": "src/App.vue",
    "content": "<script setup lang=\"ts\">\r\nimport { onLaunch, onShow, onHide } from '@dcloudio/uni-app'\r\nimport { logPromotional } from '@/utils/log'\r\nonLaunch(() => {\r\n  // 控制台打印项目宣传信息\r\n  logPromotional()\r\n  // #ifdef MP-WEIXIN\r\n  // 更新版本提示\r\n  if (wx.canIUse('getUpdateManager')) {\r\n    const updateManager = wx.getUpdateManager()\r\n    updateManager.onCheckForUpdate(function (res) {\r\n      if (res.hasUpdate) {\r\n        updateManager.onUpdateReady(function () {\r\n          wx.showModal({\r\n            title: '更新提示',\r\n            content: '新版本已经准备好，是否重启应用？',\r\n            success: function (res) {\r\n              if (res.confirm) {\r\n                updateManager.applyUpdate()\r\n              }\r\n            }\r\n          })\r\n        })\r\n        updateManager.onUpdateFailed(function () {\r\n          wx.showModal({\r\n            title: '已经有新版本了哟~',\r\n            content: '新版本已经上线啦~，请您删除当前小程序，重新搜索打开哟~'\r\n          })\r\n        })\r\n      }\r\n    })\r\n  } else {\r\n    wx.showModal({\r\n      title: '提示',\r\n      content: '当前微信版本过低，无法使用该功能，请升级到最新微信版本后重试。'\r\n    })\r\n  }\r\n  // #endif\r\n})\r\nonShow(() => {\r\n  // console.log('App Show')\r\n})\r\nonHide(() => {\r\n  // console.log('App Hide')\r\n})\r\n</script>\r\n\r\n<style>\r\n/* 默认主题 */\r\n:root page {\r\n  color: #000000;\r\n  background: #f5f5f5;\r\n  --theme-bg-color: #ffffff;\r\n}\r\n</style>\r\n"
  },
  {
    "path": "src/api/loginApi.ts",
    "content": "import http from '@/http/httpClient'\nimport { useUserStore } from '@/store'\n\n/* 登录 获取 accessToken */\nexport const loginApi: any = async data => {\n  const res: any = await http.post('/login', {\n    data\n  })\n  const store = useUserStore()\n  store.setUserInfo({\n    refreshToken: res.data.refreshToken,\n    accessToken: res.data.accessToken\n  })\n}\n\n/* 拿 refreshToken 换取 accessToken 与 新 refreshToken */\n/* 即刷新 accessToken */\nexport const refreshTokenApi: any = () => {\n  const store = useUserStore()\n  const { refreshToken } = store.userInfo || {}\n  return http\n    .get('/refresh', {\n      data: {\n        refreshToken: refreshToken\n      }\n    })\n    .then(\n      res => {\n        store.setUserInfo({\n          refreshToken: res.data.refreshToken,\n          accessToken: res.data.accessToken\n        })\n        return [res, null]\n      },\n      e => [null, e]\n    )\n}\n\n/* 获取用户信息 */\nexport const getListApi: any = async () => {\n  return http.get('/userInfo')\n}\n"
  },
  {
    "path": "src/api/testApi.ts",
    "content": "import http from '@/http/httpClient'\n\n/** GET 请求测试 */\nexport const getTestApi: any = query => {\n  return http.get('/getTest', { query })\n}\n\n/** POST 请求测试 */\nexport const postTestApi: any = (data, query) => {\n  return http.post('/postTest', { data, query })\n}\n\n/* await-to-js 简洁用法 */\nexport const awaitToJsTestApi: any = query => {\n  return (\n    http\n      .post('/postTest', { query }) // 返回正常\n      // .post('/error', { query }) // 返回错误\n      .then(\n        data => [data, null],\n        e => [null, e]\n      )\n  )\n}\n\n/** 分页 请求测试 */\nexport const getUserListApi: any = query => {\n  return http.get('/testList', { query })\n}\n\n/** 长时间请求 请求测试 */\nexport const getLongRequestApi: any = () => {\n  return http.get('/longRequest')\n}\n"
  },
  {
    "path": "src/hooks/useEcharts.ts",
    "content": "// 小程序中引入 echarts\n// #ifndef APP-PLUS || H5\nconst echarts = require('../uni_modules/lime-echart/static/echarts.min')\n// #endif\n\n// APP 与 H5 引入 echarts\n// #ifdef APP-PLUS || H5\nimport * as echartsAppOrH5 from 'echarts'\n// #endif\n\nimport { ref } from 'vue'\n\n// echarts 图表 Hooks\nexport const useEcharts = (options): any => {\n  // echarts 图实例\n  const chartRef = ref(null)\n  // echarts 图绘制函数\n  const draw = () => {\n    setTimeout(async () => {\n      if (!chartRef.value) return\n      // #ifndef APP-PLUS || H5\n      const chart = await chartRef.value.init(echarts)\n      chart.setOption(options.value)\n      // #endif\n      // #ifdef APP-PLUS || H5\n      const chartAPP = await chartRef.value.init(echartsAppOrH5)\n      chartAPP.setOption(options.value)\n      // #endif\n    }, 300)\n  }\n  // 这里就封装巧妙之处，如果是对象，那么需要重命名，而是是数组，无需重命名\n  return [chartRef, options, draw]\n}\n"
  },
  {
    "path": "src/hooks/useI18n.ts",
    "content": "import { useUserStore } from '@/store'\nimport { Locale, useCurrentLang } from 'wot-design-uni'\nimport enUS from 'wot-design-uni/locale/lang/en-US'\nimport zhCN from 'wot-design-uni/locale/lang/zh-CN'\n\nimport en from '@/locale/en.json'\nimport zh from '@/locale/zh-Hans.json'\n\nexport const useI18n = () => {\n  const store = useUserStore()\n  const pagePath = getCurrentPages()\n  const pagePathKey = pagePath[pagePath.length - 1].route.replace(/\\//g, '.')\n\n  const t = (key, type?: string) => {\n    /* 如果国际化是元素，直接返回，如果是 ref 中的数据就需要加 computed 不然不会动态变化 */\n    if (type === 'text') {\n      return computed(() => {\n        return (store.getLocale === 'zh-CN' ? zh[pagePathKey][key] : en[pagePathKey][key]) ?? ''\n      })\n    }\n    return (store.getLocale === 'zh-CN' ? zh[pagePathKey][key] : en[pagePathKey][key]) ?? ''\n  }\n\n  /* 切换 原生元素 语言 */\n  const changeNativeLang = () => {\n    // 切换 顶部导航栏 语言\n    uni.setNavigationBarTitle({\n      title: (store.getLocale === 'zh-CN' ? zh[pagePathKey]?.title : en[pagePathKey]?.title) ?? ''\n    })\n    // 切换 tabBar 语言\n    // ...\n  }\n\n  /* 切换 UI 库 语言 */\n  const changeUiLang = () => {\n    /* 设置 WotUI 组件语言 */\n    const wotUiCurrentLang = useCurrentLang().value\n    if (wotUiCurrentLang != store.getLocale) {\n      Locale.use(store.getLocale, store.getLocale === 'zh-CN' ? zhCN : enUS)\n    }\n  }\n\n  const setLocale = () => {\n    /* 切换 语言 */\n    store.setLocale()\n    changeNativeLang()\n    changeUiLang()\n  }\n\n  /* 页面初始化渲染一次 */\n  changeNativeLang()\n  changeUiLang()\n\n  return {\n    t,\n    setLocale\n  }\n}\n"
  },
  {
    "path": "src/hooks/useRequest.ts",
    "content": "import { UnwrapRef, Ref } from 'vue'\n\ntype RequestOptions = {\n  /** 是否立即执行 */\n  immediate?: boolean\n}\n\n/**\n * useRequest 是请求的再次封装，类似于 react-query 中的 userQuery\n * 核心使用场景，就前端而言，分页查询用的比较多，其他嘛用得还是比较少\n * @param queryFn 一个执行异步请求的函数，返回一个包含响应数据的 Promise\n * @param queryKey 请求的唯一标识，用于监听参数变化，重新发起请求\n * @param options 包含请求选项的对象 {immediate}。\n * @param options.immediate 是否立即执行请求，默认为false。\n * @returns 返回一个对象{loading, error, data, run}，包含请求的加载状态、错误信息、响应数据和手动触发请求的函数。\n */\nexport default function useRequest<T>({\n  queryKey,\n  options = { immediate: false },\n  queryFn\n}: {\n  queryKey: Ref<T>[]\n  options: RequestOptions\n  queryFn: () => Promise<ResData<T>>\n}) {\n  const loading = ref(false)\n  const error = ref(false)\n  const data = ref() // 不做类型定义，让 ts 默认推导\n  const run = async () => {\n    loading.value = true\n    return queryFn()\n      .then(res => {\n        data.value = res.data as UnwrapRef<T>\n        error.value = false\n        return data.value\n      })\n      .catch(err => {\n        error.value = err\n        throw err\n      })\n      .finally(() => {\n        loading.value = false\n      })\n  }\n  // 监听 queryKey 变化，重新发起请求\n  watch([...queryKey], () => {\n    run()\n  })\n  options.immediate && run()\n  return { loading, error, data, run }\n}\n"
  },
  {
    "path": "src/hooks/useTheme.ts",
    "content": "import type { ConfigProviderThemeVars } from 'wot-design-uni'\nimport { ref } from 'vue'\nimport { useUserStore } from '@/store'\nimport { storeToRefs } from 'pinia'\n\nconst theme = ref<'light' | 'dark'>('light')\nconst themeVars = ref<ConfigProviderThemeVars>()\n\nexport function useTheme(vars?: ConfigProviderThemeVars) {\n  const store = useUserStore()\n  const { userInfo } = storeToRefs(store)\n\n  /* 替换 Wot 组件的样式 */\n  vars && (themeVars.value = vars)\n\n  const setTheme = () => {\n    nextTick(() => {\n      if (userInfo.value.followSystem) {\n        // #ifdef APP-PLUS\n        plus.nativeUI.setUIStyle('auto') // 设置应用主题为跟随系统（android下能够切换，IOS 未测试）\n        theme.value = 'light'\n        // #endif\n        // #ifndef APP-PLUS\n        uni.getSystemInfo({\n          success: (res: any) => {\n            const osThemeInfo = res.hostTheme ? res.hostTheme : res.osTheme\n            store.setUserInfo({ theme: osThemeInfo })\n            theme.value = osThemeInfo\n            uni.setNavigationBarColor({\n              frontColor: theme.value === 'light' ? '#000000' : '#ffffff',\n              backgroundColor: theme.value === 'light' ? '#ffffff' : '#000000',\n              animation: {\n                duration: 400,\n                timingFunc: 'easeIn'\n              }\n            })\n          }\n        })\n        // #endif\n      } else {\n        // #ifdef APP-PLUS\n        plus.nativeUI.setUIStyle('light') // 设置应用主题为跟随系统（android下能够切换，IOS 未测试）\n        // #endif\n        uni.setNavigationBarColor({\n          frontColor: theme.value === 'light' ? '#000000' : '#ffffff',\n          backgroundColor: theme.value === 'light' ? '#ffffff' : '#000000',\n          animation: {\n            duration: 400,\n            timingFunc: 'easeIn'\n          }\n        })\n      }\n    })\n  }\n\n  watch(theme, () => {\n    store.setUserInfo({ theme: theme.value })\n    setTheme()\n  })\n\n  onShow(() => {\n    setTheme()\n  })\n\n  return {\n    theme,\n    themeVars,\n    setTheme\n  }\n}\n"
  },
  {
    "path": "src/http/httpClient.ts",
    "content": "import { refreshTokenApi } from '@/api/loginApi'\nimport { CustomRequestOptions } from '@/interceptors/request'\nimport { useUserStore } from '@/store'\n\ntype CustomRequestOptionsOmit = Omit<CustomRequestOptions, 'url' | 'method'>\n\nlet refreshing = false // 防止重复刷新 token 标示\nlet taskQueue = [] // 刷新 token 请求队列\n\nexport default class ApiClient {\n  private static http<T>(options: Omit<CustomRequestOptions, 'isBaseUrl'>) {\n    let requestTask\n    const promise = new Promise<ResData<T>>((resolve, reject) => {\n      requestTask = uni.request({\n        ...options,\n        success: async (res: any) => {\n          /* -------- 请求成功 ----------- */\n          if ((res.statusCode >= 200 && res.statusCode < 300) || res.data.code === 0) {\n            return resolve(res.data as ResData<T>)\n          }\n\n          /* -------- 无感刷新 token ----------- */\n          const store = useUserStore()\n          const { refreshToken } = store.userInfo || {}\n          // token 失效的，且有刷新 token 的，才放到请求队列里\n          if ((res.data.code == 401 || res.statusCode == 401) && refreshToken != '') {\n            taskQueue.push(() => {\n              resolve(this.http<T>(options))\n            })\n          }\n\n          if ((res.data.code == 401 || res.statusCode == 401) && refreshToken != '' && !refreshing) {\n            refreshing = true\n            // 发起刷新 token 请求\n            const [refreshTokenRes, refreshTokenErr] = await refreshTokenApi()\n            refreshing = false\n            // 刷新 token 成功，将任务队列的所有任务重新请求\n            if (refreshTokenRes?.data.code == 200) {\n              nextTick(() => {\n                // 关闭其他弹窗\n                uni.hideToast()\n                // 刷新 token 失败，跳转到登录页\n                uni.showToast({\n                  title: 'token 刷新成功，重载中',\n                  icon: 'none'\n                })\n              })\n              taskQueue.forEach(event => {\n                event()\n              })\n            }\n            if (refreshTokenErr) {\n              // 刷新 token 失败，跳转到登录页\n              nextTick(() => {\n                // 关闭其他弹窗\n                uni.hideToast()\n                // 刷新 token 失败，跳转到登录页\n                uni.showToast({\n                  title: '登录已过期，请重新登录',\n                  icon: 'none'\n                })\n              })\n              // setTimeout(() => {\n              //   // 清除 用户信息（包括 token）\n              //   store.clearUserInfo()\n              //   // 跳转到登录页\n              //   uni.navigateTo({ url: '/pages/login/login' })\n              // }, 2500)\n            }\n            // 不管刷新 token 成功与否，都清空任务队列\n            taskQueue = []\n          }\n\n          /* -------- 剩余情况都默认请求异常 ----------- */\n          uni.showToast({\n            title: res.data.msg || res.data.message || '请求异常',\n            icon: 'none'\n          })\n          reject(res)\n        },\n        fail: err => {\n          if (err.errMsg === 'request:fail abort') {\n            console.log(`请求 ${options.url} 被取消`)\n          } else {\n            reject(err)\n          }\n        }\n      })\n    })\n    return {\n      ...promise, // 补全 Promise 的类型\n      then: promise.then.bind(promise),\n      catch: promise.catch.bind(promise),\n      finally: promise.finally.bind(promise),\n      [Symbol.iterator]: promise[Symbol.iterator],\n      abort: () => {\n        // 取消请求\n        requestTask.abort()\n      }\n    }\n  }\n  // GET\n  public static get<T>(url: string, options?: CustomRequestOptionsOmit) {\n    return this.http<T>({\n      url,\n      method: 'GET',\n      ...options\n    })\n  }\n  // POST\n  public static post<T>(url: string, options?: CustomRequestOptionsOmit) {\n    return this.http<T>({\n      url,\n      method: 'POST',\n      ...options\n    })\n  }\n  // PUT\n  public static put<T>(url: string, options?: CustomRequestOptionsOmit) {\n    return this.http<T>({\n      url,\n      method: 'PUT',\n      ...options\n    })\n  }\n  // DELETE\n  public static delete<T>(url: string, options?: CustomRequestOptionsOmit) {\n    return this.http<T>({\n      url,\n      method: 'DELETE',\n      ...options\n    })\n  }\n}\n"
  },
  {
    "path": "src/interceptors/index.ts",
    "content": "export { requestInterceptor } from './request'\nexport { routerInterceptor } from './router'\n"
  },
  {
    "path": "src/interceptors/request.ts",
    "content": "import { qs } from '@/utils'\nimport { useUserStore } from '@/store'\n\nexport type CustomRequestOptions = UniApp.RequestOptions & {\n  query?: Record<string, any>\n  /** 出错时是否隐藏错误提示 */\n  hideErrorToast?: boolean\n}\n\nconst timeout = 30000 // 请求超时时间\nconst baseUrl = (import.meta as any).env.VITE_SERVER_BASEURL // 请求基础路径\n\n// 拦截器配置\nconst httpInterceptor = {\n  // 请求前的拦截\n  invoke(options: CustomRequestOptions) {\n    // 1. 设置请求路径\n    if (!options.url.includes('//')) {\n      // 非完整路径，补全基础路径\n      // 完整路径：http://localhost:8080/api/user/login\n      // 非完整路径：api/user/loginApi\n      options.url = baseUrl + options.url\n    }\n    // 2. query 参数处理\n    if (options.query) {\n      // qs.stringify() 方法将一个 JavaScript 对象或数组转换为一个查询字符串\n      // 比如： { name: 'tom', age: 18 } 转换成 name=tom&age=18\n      const query = qs.stringify(options.query)\n      options.url += options.url.includes('?') ? '&' : '?' + query\n    }\n    // 3. 请求超时时间设置\n    options.timeout = timeout\n    // 4. 定义请求返回数据的格式（设为 json，会尝试对返回的数据做一次 JSON.parse）\n    options.dataType = 'json'\n    // #ifndef MP-WEIXIN\n    options.responseType = 'json'\n    // #endif\n    // 5. 添加请求头标识，可以告诉后台是小程序端发起的请求\n    options.header = {\n      ...options.header,\n      'Content-Type': 'application/json; charset=utf-8'\n      // platform: 'mini-program', 比如 platform 字段可以告诉后台是小程序端发起的请求\n    }\n    // 6. 添加 token 请求头标识\n    const store = useUserStore()\n    const { accessToken } = store.userInfo || {}\n    if (accessToken) {\n      options.header.Authorization = `Bearer ${accessToken}`\n    }\n    return options\n  }\n}\n\nexport const requestInterceptor = {\n  install() {\n    // 拦截 request 请求\n    uni.addInterceptor('request', httpInterceptor)\n  }\n}\n"
  },
  {
    "path": "src/interceptors/router.ts",
    "content": "/**\n * 权限拦截\n * 主要分两个：路由权限、按钮权限\n * 1. 路由权限\n * 这里主要实现路由权限，实现了黑名单拦截，权限不够就拦截\n * 比如现在用户权限是 ['logined', 'vip'] 那么他能进入就只能是 permissionKeys 在 ['logined', 'vip'] 范围里面的路由\n * 如果页面 permissionKeys 是 ['logined', 'vip', 'admin']，那么这个页面就无法被当前用户访问\n * 如果页面 permissionKeys 是 ['logined']、['logined', 'vip']，或者没有 permissionKeys 那么这个页面可以被当前用户访问\n *\n * 2. 按钮权限在 utils/router.ts\n */\nimport { useUserStore } from '@/store'\nimport { getPermissionKeysByPath } from '@/utils'\n\nconst loginRoute = '/pages/routerDemo/login'\n\n// 获取用户权限标识\nconst getUserPermissionKeys = () => {\n  const userStore = useUserStore()\n  return userStore.getUserPermissionKeys\n}\n\n/**\n * 实现原理：\n * 1. 或者所有需要登录的路由，存到黑名单，需要在 route-block 配置标识 key，根据 isNeedLogin 判断是否需要登录\n * 2. 在路由跳转前，判断是否需要登录，如果需要登录，判断是否已经登录，如果没有登录，跳转到登录页\n **/\nconst navigateToInterceptor = {\n  invoke({ url }: { url: string }) {\n    // 'pages.json' 里面的 path 是 'pages/index/index'\n    // url 如果带参数则是 /pages/route-interceptor/index?name=uni-plus，所以需要去掉带的参数、去掉前面的 /\n    const path = url.split('?')[0].slice(1) // pages/index/index\n    // 用户已有权限\n    const userPermissionKeys = getUserPermissionKeys() // ['logined', 'vip']\n    // 页面所需权限\n    const pageRoutePaths = getPermissionKeysByPath(path) // ['vip']\n    // 两个权限取交集，然后交集再与用户权限取补集\n    const LackPermissionKeys = pageRoutePaths.filter(item => !userPermissionKeys.includes(item))\n\n    // 如果有权限就放行\n    if (LackPermissionKeys.length === 0) {\n      return true\n    }\n\n    /* ---------- 无权限，对缺少各种权限做处理 --------- */\n    // 如果缺少登录权限，跳转到登录页\n    if (LackPermissionKeys.includes('logined')) {\n      const redirectRoute = `${loginRoute}?redirect=${encodeURIComponent(url)}`\n      uni.navigateTo({ url: redirectRoute })\n    }\n    // 如果缺少其他权限，提示无权限，需要其他权限特殊判定可以继续添加\n    else {\n      uni.showToast({\n        title: '无权限访问',\n        icon: 'none'\n      })\n    }\n    return false\n  }\n}\n\nexport const routerInterceptor = {\n  install() {\n    uni.addInterceptor('navigateTo', navigateToInterceptor)\n    uni.addInterceptor('reLaunch', navigateToInterceptor)\n    uni.addInterceptor('redirectTo', navigateToInterceptor)\n    uni.addInterceptor('switchTab', navigateToInterceptor)\n  }\n}\n"
  },
  {
    "path": "src/layouts/default.vue",
    "content": "<!-- default.vue -->\n<template>\n  <slot></slot>\n</template>\n"
  },
  {
    "path": "src/layouts/fullPage.vue",
    "content": "<!-- fullPage.vue -->\n<template>\n  <WdConfigProvider :theme=\"theme\" :theme-vars=\"themeVars\">\n    <div class=\"flex-col-center min-h-100vh\">\n      <div class=\"w-100vw h-30vh bg-#f1bbba flex justify-center items-center\">我是页头</div>\n      <slot></slot>\n      <div class=\"w-100vw h-30vh bg-#f8ecc9 flex justify-center items-center\">我是页尾</div>\n    </div>\n  </WdConfigProvider>\n</template>\n\n<script setup lang=\"ts\">\nimport { useTheme } from '@/hooks/useTheme'\nconst { theme, themeVars } = useTheme()\n</script>\n\n<style>\n/* 默认主题 */\n:root page {\n  color: #000000;\n  background: #f5f5f5;\n  --theme-bg-color: #ffffff;\n}\n</style>\n"
  },
  {
    "path": "src/layouts/theme.vue",
    "content": "<!-- theme.vue -->\n<template>\n  <WdConfigProvider :theme=\"theme\" :theme-vars=\"themeVars\">\n    <div class=\"min-h-100vh\">\n      <slot></slot>\n    </div>\n  </WdConfigProvider>\n</template>\n\n<script setup lang=\"ts\">\nimport { useTheme } from '@/hooks/useTheme'\nconst { theme, themeVars } = useTheme()\n</script>\n"
  },
  {
    "path": "src/locale/en.json",
    "content": "{\n  \"pages.index.index\": {\n    \"layersTitle\": \"Layout SFC\",\n    \"attachTitle\": \"Pinia use\",\n    \"attachText\": \"State management\",\n    \"linkUnlinkTitle\": \"Single request\",\n    \"linkUnlinkText\": \"Separation\",\n    \"linkTitle\": \"Request+Status\",\n    \"linkText\": \"Combined\",\n    \"userTitle\": \"Login example\",\n    \"userText\": \"Noninductive refresh\",\n    \"lockOffTitle\": \"Right control\",\n    \"lockOffText\": \"Routes and buttons\",\n    \"chartTitle\": \"Chart module\",\n    \"transferTitle\": \"WotUI module\",\n    \"transferText\": \"High-frequency\",\n    \"viewModuleTitle\": \"Paging case\",\n    \"viewListTitle\": \"Multilingual\",\n    \"menuFoldTitle\": \"Customize bar\",\n    \"menuFoldText\": \"Custom component\",\n    \"chartBubbleTitle\": \"Atomic CSS\",\n    \"nowLocale\": \"English-US\",\n    \"nowLocaleText\": \"Language setting (i18n)\",\n    \"darkMode\": \"Dark Mode: \",\n    \"darkModeFollowText\": \"Dark mode follow system\",\n    \"about\": \"A 'super super super' easy to use uniapp template\",\n    \"bgColor1\": \"Yellow\",\n    \"bgColor2\": \"Orange\",\n    \"bgColor3\": \"Default\",\n    \"authorText\": \"Author: DaMaiCoding\"\n  },\n  \"pages.i18nDemo.index\": {\n    \"title\": \"i18n Multilingual Demo\",\n    \"authorText\": \"Author: DaMaiCoding\",\n    \"about\": \"A 'super super super' easy to use uniapp template\",\n    \"nowLocale\": \"Click to switch language(English-US)\",\n    \"calendarLabel\": \"Calendar\"\n  }\n}\n"
  },
  {
    "path": "src/locale/zh-Hans.json",
    "content": "{\n  \"pages.index.index\": {\n    \"layersTitle\": \"Layout布局\",\n    \"attachTitle\": \"Pinia使用\",\n    \"attachText\": \"状态管理\",\n    \"linkUnlinkTitle\": \"单一请求\",\n    \"linkUnlinkText\": \"请求(与状态分离)\",\n    \"linkTitle\": \"请求+状态\",\n    \"linkText\": \"请求(与状态结合)\",\n    \"userTitle\": \"登录示例\",\n    \"userText\": \"无感刷新\",\n    \"lockOffTitle\": \"权限控制\",\n    \"lockOffText\": \"路由与按钮\",\n    \"chartTitle\": \"图表组件\",\n    \"transferTitle\": \"WotUI组件\",\n    \"transferText\": \"高频组件\",\n    \"viewModuleTitle\": \"分页案例\",\n    \"viewListTitle\": \"国际化\",\n    \"menuFoldTitle\": \"自定义导航栏\",\n    \"menuFoldText\": \"自定义组件实现\",\n    \"chartBubbleTitle\": \"原子CSS\",\n    \"nowLocale\": \"简体中文\",\n    \"nowLocaleText\": \"设置语言（国际化）\",\n    \"darkMode\": \"暗黑模式：\",\n    \"darkModeFollowText\": \"暗黑模式跟随系统\",\n    \"about\": \"一个 “超超超” 好用的 uniapp 模板\",\n    \"bgColor1\": \"小黄\",\n    \"bgColor2\": \"橙色\",\n    \"bgColor3\": \"默认\",\n    \"authorText\": \"作者：大麦大麦\"\n  },\n  \"pages.i18nDemo.index\": {\n    \"title\": \"i18n 多语言 Demo\",\n    \"authorText\": \"作者：大麦大麦\",\n    \"about\": \"一个 “超超超” 好用的 uniapp 模板\",\n    \"nowLocale\": \"点击切换语言（简体中文）\",\n    \"calendarLabel\": \"日历\"\n  }\n}\n"
  },
  {
    "path": "src/main.ts",
    "content": "import { createSSRApp } from 'vue'\r\nimport { requestInterceptor, routerInterceptor } from './interceptors'\r\nimport { checkBtnPermission, useAssets } from './utils'\r\nimport App from './App.vue'\r\nimport store from './store'\r\nimport 'uno.css'\r\n\r\nexport function createApp() {\r\n  const app = createSSRApp(App)\r\n  app.use(store)\r\n  app.config.globalProperties.$perms = checkBtnPermission\r\n  app.config.globalProperties.$assets = useAssets\r\n  app.use(requestInterceptor)\r\n  app.use(routerInterceptor)\r\n  return {\r\n    app\r\n  }\r\n}\r\n"
  },
  {
    "path": "src/manifest.json",
    "content": "{\n    \"name\" : \"uni-plus\",\n    \"appid\" : \"__UNI__42E0EC3\",\n    \"description\" : \"uni-plus app 打包\",\n    \"versionName\" : \"1.0.1\",\n    \"versionCode\" : 101,\n    /* 5+App特有相关 */\n    \"app-plus\" : {\n        \"usingComponents\" : true,\n        \"nvueStyleCompiler\" : \"uni-app\",\n        \"compilerVersion\" : 3,\n        \"splashscreen\" : {\n            \"alwaysShowBeforeRender\" : true,\n            \"waiting\" : true,\n            \"autoclose\" : true\n        },\n        /* 模块配置 */\n        \"modules\" : {},\n        \"darkmode\" : true, // 开启支持深色模式\n        \"themeLocation\" : \"theme.json\", // 深色模式JSON文件，如果 theme.json 在根目录可省略\n        /* 应用发布信息 */\n        \"distribute\" : {\n            /* android打包配置 */\n            \"android\" : {\n                \"permissions\" : [\n                    \"<uses-permission android:name=\\\"android.permission.CHANGE_NETWORK_STATE\\\"/>\",\n                    \"<uses-permission android:name=\\\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\\\"/>\",\n                    \"<uses-permission android:name=\\\"android.permission.VIBRATE\\\"/>\",\n                    \"<uses-permission android:name=\\\"android.permission.READ_LOGS\\\"/>\",\n                    \"<uses-permission android:name=\\\"android.permission.ACCESS_WIFI_STATE\\\"/>\",\n                    \"<uses-feature android:name=\\\"android.hardware.camera.autofocus\\\"/>\",\n                    \"<uses-permission android:name=\\\"android.permission.ACCESS_NETWORK_STATE\\\"/>\",\n                    \"<uses-permission android:name=\\\"android.permission.CAMERA\\\"/>\",\n                    \"<uses-permission android:name=\\\"android.permission.GET_ACCOUNTS\\\"/>\",\n                    \"<uses-permission android:name=\\\"android.permission.READ_PHONE_STATE\\\"/>\",\n                    \"<uses-permission android:name=\\\"android.permission.CHANGE_WIFI_STATE\\\"/>\",\n                    \"<uses-permission android:name=\\\"android.permission.WAKE_LOCK\\\"/>\",\n                    \"<uses-permission android:name=\\\"android.permission.FLASHLIGHT\\\"/>\",\n                    \"<uses-feature android:name=\\\"android.hardware.camera\\\"/>\",\n                    \"<uses-permission android:name=\\\"android.permission.WRITE_SETTINGS\\\"/>\"\n                ]\n            },\n            /* ios打包配置 */\n            \"ios\" : {\n                \"dSYMs\" : false\n            },\n            /* SDK配置 */\n            \"sdkConfigs\" : {\n                \"ad\" : {}\n            }\n        }\n    },\n    /* 快应用特有相关 */\n    \"quickapp\" : {},\n    /* 小程序特有相关 */\n    \"mp-weixin\" : {\n        \"appid\" : \"\",\n        \"setting\" : {\n            \"urlCheck\" : false,\n            \"es6\" : true,\n            \"postcss\" : true,\n            \"minified\" : true,\n            \"uglifyFileName\" : true,\n            \"swc\" : true\n        },\n        \"usingComponents\" : true,\n        \"darkmode\" : true, // 开启支持深色模式\n        \"themeLocation\" : \"theme.json\", // 深色模式JSON文件，如果 theme.json 在根目录可省略\n        \"libVersion\" : \"latest\", // 处理微信开发者工具报错\n\n        /* 该配置，上传时会忽略已配置的静态资源文件 */\n        \"packOptions\" : {\n            \"ignore\" : [\n                {\n                    \"type\" : \"folder\",\n                    \"value\" : \"static/onLine\"\n                }\n            ]\n        }\n    },\n    \"mp-alipay\" : {\n        \"usingComponents\" : true\n    },\n    \"mp-baidu\" : {\n        \"usingComponents\" : true\n    },\n    \"mp-toutiao\" : {\n        \"usingComponents\" : true\n    },\n    \"uniStatistics\" : {\n        \"enable\" : false\n    },\n    \"vueVersion\" : \"3\",\n    \"locale\" : \"zh-Hans\",\n    \"h5\" : {\n        \"router\" : {\n            \"base\" : \"/uni-plus/\"\n        }\n    }\n}\n"
  },
  {
    "path": "src/pages/customDemo/index.vue",
    "content": "<!--\n@description: 自定义导航栏 demo\n-->\n\n<route lang=\"json5\" type=\"page\">\n{\n  layout: 'theme', // 使用主题\n  style: {\n    navigationStyle: 'custom'\n  }\n}\n</route>\n\n<template>\n  <div :style=\"{ height: `${statusBarHeight}px` }\" class=\"bg-[var(--theme-bg-color)]\"></div>\n  <div\n    class=\"w-[calc(100vw-24px)] flex justify-between items-center bg-[var(--theme-bg-color)] font-size-16px p-x-12px\"\n    :style=\"{ height: `${barHeight}px` }\"\n  >\n    <div class=\"flex items-center w-80rpx h-100%\" @click=\"goBack\">\n      <wd-icon name=\"thin-arrow-left\" size=\"18px\"></wd-icon>\n    </div>\n    <div class=\"w-[calc(100%-160rpx)] pr-80rpx text-center\">自定义导航栏 demo</div>\n  </div>\n</template>\n\n<script setup lang=\"ts\">\n/* 返回上一页 */\nconst goBack = () => {\n  uni.redirectTo({ url: '/pages/index/index' })\n}\n\nconst statusBarHeight = ref(20)\nconst barHeight = ref(38)\n\nonLoad(() => {\n  // 状态栏高度\n  statusBarHeight.value = (uni.getSystemInfoSync().statusBarHeight as number) || 0\n  // #ifdef MP-WEIXIN\n  // 胶囊数据\n  const { top, height } = uni.getMenuButtonBoundingClientRect()\n  // 自定义导航栏高度 = 胶囊高度 + 胶囊的 padding * 2, 如果获取不到设置为 38\n  barHeight.value = height ? height + (top - statusBarHeight.value) * 2 : 38\n  // #endif\n})\n</script>\n\n<style>\n/* 暗黑模式 start */\n.wot-theme-dark {\n  color: #f5f5f5;\n  background: black;\n  --theme-bg-color: #1b1b1b;\n}\n</style>\n"
  },
  {
    "path": "src/pages/echartsDemo/echartsData.ts",
    "content": "import { useEcharts } from '@/hooks/useEcharts'\nimport { ref } from 'vue'\n\n// 折线图\nexport const useLineEcharts = (): any => {\n  // 折线图配置项数据\n  // 每次编写新类型的图表时，只需要复制一份修改这里的配置即可\n  // 应用 这个类型的图表时，只需在 .vue 文件中通过 set 修复数据即可，或者简单的样式修改，如果样式过于复杂，可以重新建立一个 linkHookB 等等\n  const option = ref({\n    xAxis: {\n      data: [12, 13, 10, 13, 9, 23, 21, 32, 12, 15, 13, 10],\n      boundaryGap: false,\n      axisTick: {\n        show: false\n      },\n      axisLine: {\n        show: true,\n        lineStyle: {\n          color: '#0C4787'\n        }\n      },\n      axisLabel: {\n        show: true,\n        color: '#000000'\n      }\n    },\n    grid: {\n      left: 5,\n      right: 16,\n      bottom: 5,\n      top: 20,\n      containLabel: true\n    },\n    tooltip: {\n      trigger: 'axis',\n      axisPointer: {\n        type: 'cross'\n      },\n      padding: [5, 10]\n    },\n    yAxis: {\n      axisTick: {\n        show: false\n      },\n      splitLine: {\n        show: false\n      },\n      axisLine: {\n        show: true,\n        lineStyle: {\n          color: '#0C4787'\n        }\n      },\n      axisLabel: {\n        show: true,\n        color: '#000000'\n      }\n    },\n    series: {\n      smooth: true,\n      type: 'line',\n      data: [12, 13, 10, 13, 9, 23, 21, 32, 12, 15, 13, 10],\n      animationDuration: 2800,\n      animationEasing: 'cubicInOut',\n      symbol: 'circle',\n      color: '#fed42b',\n      symbolSize: 8,\n      lineStyle: {\n        color: '#fed42b' //改变折线颜色\n      },\n      areaStyle: {\n        color: {\n          type: 'linear',\n          x: 0,\n          y: 0,\n          x2: 0,\n          y2: 1,\n          colorStops: [\n            {\n              offset: 0,\n              color: '#fed42b' // 0% 处的颜色\n            },\n            {\n              offset: 1,\n              color: 'rgba(254, 212, 43, 0.1)' // 100% 处的颜色\n            }\n          ],\n          global: false // 缺省为 false\n        }\n      }\n    }\n  })\n  return useEcharts(option)\n}\n\n// 柱状图\nexport const useBarEcharts = (): any => {\n  const option = ref({\n    xAxis: {\n      data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],\n      axisTick: {\n        show: false\n      },\n      axisLine: {\n        show: true,\n        lineStyle: {\n          color: '#0C4787'\n        }\n      },\n      axisLabel: {\n        show: true,\n        color: '#000000'\n      }\n    },\n    grid: {\n      left: 5,\n      right: 16,\n      bottom: 5,\n      top: 20,\n      containLabel: true\n    },\n    tooltip: {\n      trigger: 'axis',\n      axisPointer: {\n        type: 'cross'\n      },\n      padding: [5, 10]\n    },\n    yAxis: {\n      axisTick: {\n        show: false\n      },\n      splitLine: {\n        show: false\n      },\n      axisLine: {\n        show: true,\n        lineStyle: {\n          color: '#0C4787'\n        }\n      },\n      axisLabel: {\n        show: true,\n        color: '#000000'\n      }\n    },\n    series: {\n      type: 'bar',\n      data: [120, 200, 150, 80, 70, 110, 130],\n      animationDuration: 2800,\n      animationEasing: 'cubicInOut',\n      color: '#fed42b',\n      barWidth: 10,\n      itemStyle: {\n        barBorderRadius: [3, 3, 0, 0]\n      }\n    }\n  })\n  return useEcharts(option)\n}\n"
  },
  {
    "path": "src/pages/echartsDemo/index.vue",
    "content": "<!--\n@description: Echarts 图表 dome\n-->\n<route type=\"page\" lang=\"json5\">\n{\n  layout: 'theme', // 使用主题\n  style: {\n    navigationBarTitleText: '图表 dome'\n  }\n}\n</route>\n\n<template>\n  <view>折线图1</view>\n  <view style=\"width: 300rpx; height: 300rpx\">\n    <l-echart ref=\"lineChartRef\" />\n  </view>\n  <view>折线图2</view>\n  <view style=\"width: 300rpx; height: 300rpx\">\n    <l-echart ref=\"lineChartRef2\" />\n  </view>\n  <view>柱状图</view>\n  <view style=\"width: 300rpx; height: 300rpx\">\n    <l-echart ref=\"barChartRef\" />\n  </view>\n  <button @click=\"changeLineChartData\">切换折线图1数据</button>\n  <button @click=\"changeBarChartData\">改变柱状图样式</button>\n</template>\n\n<script setup lang=\"ts\">\nimport { onMounted } from 'vue'\nimport { useBarEcharts, useLineEcharts } from './echartsData'\nimport { set } from 'lodash-es'\nconst [lineChartRef, lineOption, lineDraw] = useLineEcharts()\nconst [lineChartRef2, lineOption2, lineDraw2] = useLineEcharts()\nconst [barChartRef, barOption, barDraw] = useBarEcharts()\n\n// 初始化 折线图表1\nconst initLineChart = () => {\n  set(lineOption.value, 'series.data', [120, 132, 101, 134, 90, 230, 210, 220, 182, 191, 234, 290])\n  lineDraw()\n}\n\n// 初始化 折线图表2\nconst initLineChart2 = () => {\n  set(lineOption2.value, 'series.data', [220, 182, 191, 234, 290, 330, 310, 320, 302, 301, 334, 390])\n  lineDraw2()\n}\n\n// 初始化 柱状图表\nconst initBarChart = () => {\n  set(barOption.value, 'series.data', [120, 200, 150, 80, 70, 110, 130])\n  barDraw()\n}\n\n// 切换折线图数据\nconst changeLineChartData = () => {\n  set(lineOption.value, 'series.data', [324, 332, 301, 334, 390, 330, 320, 302, 301, 334, 390, 330])\n  lineDraw()\n}\n\n// 改变柱状图样式\nconst changeBarChartData = () => {\n  set(barOption.value, 'series.color', '#5677fc')\n  barDraw()\n}\n\nonMounted(() => {\n  initLineChart()\n  initLineChart2()\n  initBarChart()\n})\n</script>\n\n<style>\n/* 暗黑模式 start */\n.wot-theme-dark {\n  color: #f5f5f5;\n  background: #222222;\n  --theme-bg-color: #222222;\n}\n</style>\n"
  },
  {
    "path": "src/pages/i18nDemo/index.vue",
    "content": "<route type=\"page\" lang=\"json5\">\n{\n  layout: 'theme', // 使用主题\n  style: {\n    navigationBarTitleText: '%pages.index.index.title%'\n  }\n}\n</route>\n\n<template>\n  <button @click=\"setLocale\">{{ t('nowLocale') }}</button>\n  <!-- 底部作者信息 -->\n  <div class=\"w-60% mt-10rpx opacity-60 m-auto\">\n    <wd-divider>{{ t('authorText') }}</wd-divider>\n  </div>\n  <div class=\"w-100vw mt-10rpx opacity-60 flex justify-center font-size-28rpx\" v-for=\"item in list\" :key=\"item.about\">\n    {{ item.about }}\n  </div>\n  <div class=\"w-100vw mt-40rpx\">\n    <wd-calendar v-model=\"calendarData\" :label=\"t('calendarLabel')\" />\n  </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { useI18n } from '@/hooks/useI18n'\nconst { t, setLocale } = useI18n()\nconst calendarData = ref<number>(Date.now())\n\nconst list = ref([\n  {\n    about: t('about', 'text')\n  }\n])\n</script>\n\n<style>\n/* 暗黑模式 start */\n.wot-theme-dark {\n  color: #f5f5f5;\n  background: #222222;\n  --theme-bg-color: #222222;\n}\n</style>\n"
  },
  {
    "path": "src/pages/index/index.vue",
    "content": "<!--\r\n@description: DEMO 案例主导航页\r\n-->\r\n\r\n<route lang=\"json5\" type=\"home\">\r\n{\r\n  layout: 'theme', // 使用主题\r\n  style: {\r\n    navigationStyle: 'custom'\r\n  }\r\n}\r\n</route>\r\n\r\n<template>\r\n  <div class=\"min-h-100vh\">\r\n    <!-- 顶部自定义导航栏 -->\r\n    <div class=\"w-[calc(100vw-60rpx)] p-x-30rpx bg-[var(--wot-color-theme)]\">\r\n      <!-- 状态栏高度 -->\r\n      <div :style=\"{ height: `${statusBarHeight}px` }\"></div>\r\n      <div class=\"flex p-b-20rpx\">\r\n        <div class=\"w-160rpx h-100% flex\">\r\n          <img class=\"w-160rpx h-160rpx\" :src=\"$assets('@/static/local/logo.png')\" />\r\n          <!-- <img class=\"w-160rpx h-160rpx\" :src=\"'@/static/local/logo.png'\" /> -->\r\n        </div>\r\n        <div class=\"ml-30rpx w-[calc(100%-160rpx)] flex flex-col\">\r\n          <div class=\"font-size-44rpx font-bold flex items-center\" :style=\"{ height: `${barHeight}px` }\">uni-plus</div>\r\n          <div class=\"font-size-26rpx opacity-60 flex-1 flex flex-col justify-center\">{{ t('about') }}</div>\r\n        </div>\r\n      </div>\r\n    </div>\r\n    <div class=\"p-x-30rpx flex flex-col items-center mt-30rpx\">\r\n      <!-- 切换主题色 -->\r\n      <div\r\n        class=\"bg-[var(--theme-bg-color)] rounded-20rpx overflow-hidden flex justify-evenly items-center w-100% h-120rpx font-size-20rpx line-height-28rpx shadow-sm\"\r\n      >\r\n        <div\r\n          class=\"w-94rpx h-50rpx rounded-25rpx bg-#ffc400 flex justify-center items-center\"\r\n          @click=\"changeTheme('#ffc400')\"\r\n        >\r\n          {{ t('bgColor1') }}\r\n        </div>\r\n        <div\r\n          class=\"w-94rpx h-50rpx rounded-25rpx bg-#ff5f2e color-#ffffff flex justify-center items-center\"\r\n          @click=\"changeTheme('#ff5f2e', '#ffffff')\"\r\n        >\r\n          {{ t('bgColor2') }}\r\n        </div>\r\n        <div\r\n          class=\"w-94rpx h-50rpx rounded-25rpx bg-#795548 color-#ffffff flex justify-center items-center\"\r\n          @click=\"changeTheme()\"\r\n        >\r\n          {{ t('bgColor3') }}\r\n        </div>\r\n        <div class=\"flex justify-center items-center w-260rpx\">\r\n          <div class=\"font-size-28rpx mr-10rpx color-#9e9e9e flex-1 text-right\">{{ t('darkMode') }}</div>\r\n          <wd-switch\r\n            v-model=\"theme\"\r\n            size=\"23px\"\r\n            active-value=\"dark\"\r\n            inactive-value=\"light\"\r\n            active-color=\"#272a2f\"\r\n            :disabled=\"userInfo.followSystem\"\r\n          />\r\n        </div>\r\n      </div>\r\n      <!-- 功能列表 -->\r\n      <div class=\"bg-[var(--theme-bg-color)] w-100% shadow-md rounded-20rpx overflow-hidden mt-40rpx\">\r\n        <wd-grid border :column=\"3\" clickable>\r\n          <wd-grid-item use-slot v-for=\"item in gridList\" :key=\"item.iconName\" link-type=\"navigateTo\" :url=\"item.url\">\r\n            <wd-icon :name=\"item.iconName\" size=\"36px\" :color=\"item.color\"></wd-icon>\r\n            <div class=\"font-size-28rpx font-bold\">{{ item.title }}</div>\r\n            <div class=\"color-#9e9e9e font-size-22rpx\">{{ item.text }}</div>\r\n          </wd-grid-item>\r\n        </wd-grid>\r\n      </div>\r\n      <!-- 多语言 -->\r\n      <div\r\n        class=\"bg-[var(--theme-bg-color)] rounded-20rpx overflow-hidden flex justify-between items-center w-[calc(100%-60rpx)] h-120rpx mt-40rpx p-x-30rpx shadow-sm\"\r\n        @click=\"setLocale\"\r\n      >\r\n        <div class=\"flex items-center\">\r\n          <wd-icon name=\"setting\" size=\"22px\" color=\"#0163ff\"></wd-icon>\r\n          <div class=\"font-size-30rpx ml-30rpx\">{{ t('nowLocaleText') }}</div>\r\n        </div>\r\n        <div class=\"flex items-center\">\r\n          <div class=\"font-size-28rpx color-#9e9e9e mr-5rpx h-22px line-height-22px\">{{ t('nowLocale') }}</div>\r\n          <wd-icon name=\"chevron-right\" size=\"22px\" color=\"#9e9e9e\"></wd-icon>\r\n        </div>\r\n      </div>\r\n      <!-- 暗黑模式 -->\r\n      <div\r\n        class=\"bg-[var(--theme-bg-color)] rounded-20rpx overflow-hidden flex justify-between items-center w-[calc(100%-60rpx)] h-120rpx mt-40rpx p-x-30rpx shadow-sm\"\r\n      >\r\n        <div class=\"flex items-center\">\r\n          <wd-icon name=\"windows-filled\" size=\"26px\" color=\"#cf3d35\"></wd-icon>\r\n          <div class=\"font-size-30rpx ml-30rpx\">{{ t('darkModeFollowText') }}</div>\r\n        </div>\r\n        <wd-checkbox\r\n          custom-shape-class=\"w-[var(--wot-checkbox-size,22px)!important] h-[var(--wot-checkbox-size,22px)!important]\"\r\n          v-model=\"userInfo.followSystem\"\r\n          checked-color=\"#cf3d35\"\r\n          custom-style=\"margin:0\"\r\n          @change=\"setTheme\"\r\n        />\r\n      </div>\r\n      <!-- 底部作者信息 -->\r\n      <div class=\"w-60% mt-10rpx opacity-60\">\r\n        <wd-divider>{{ t('authorText') }}</wd-divider>\r\n      </div>\r\n    </div>\r\n  </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref } from 'vue'\r\nimport { useTheme } from '@/hooks/useTheme'\r\nimport { storeToRefs } from 'pinia'\r\nimport { useUserStore } from '@/store'\r\nimport { useI18n } from '@/hooks/useI18n'\r\nconst store = useUserStore()\r\nconst { theme, themeVars, setTheme } = useTheme()\r\nconst { t, setLocale } = useI18n()\r\nconst { userInfo } = storeToRefs(store)\r\nconst statusBarHeight = ref(20)\r\nconst barHeight = ref(38)\r\n\r\n/* 宫格列表 */\r\nconst gridList = ref([\r\n  {\r\n    iconName: 'layers',\r\n    title: t('layersTitle', 'text'),\r\n    text: 'SFC',\r\n    color: '#0163ff',\r\n    url: '/pages/layoutDemo/index'\r\n  },\r\n  {\r\n    iconName: 'attach',\r\n    title: t('attachTitle', 'text'),\r\n    text: t('attachText', 'text'),\r\n    color: '#ffc400',\r\n    url: '/pages/piniaDemo/index'\r\n  },\r\n  {\r\n    iconName: 'link-unlink',\r\n    title: t('linkUnlinkTitle', 'text'),\r\n    text: t('linkUnlinkText', 'text'),\r\n    color: '#ca145d',\r\n    url: '/pages/queryDemo/queryTestDemo'\r\n  },\r\n  {\r\n    iconName: 'link',\r\n    title: t('linkTitle', 'text'),\r\n    text: t('linkText', 'text'),\r\n    color: '#11cde8',\r\n    url: '/pages/queryDemo/useRequestDemo'\r\n  },\r\n  {\r\n    iconName: 'user',\r\n    title: t('userTitle', 'text'),\r\n    text: t('userText', 'text'),\r\n    color: '#fe1c00',\r\n    url: '/pages/queryDemo/loginDemo'\r\n  },\r\n  {\r\n    iconName: 'lock-off',\r\n    title: t('lockOffTitle', 'text'),\r\n    text: t('lockOffText', 'text'),\r\n    color: '#607d8b',\r\n    url: '/pages/routerDemo/index'\r\n  },\r\n  {\r\n    iconName: 'chart',\r\n    title: t('chartTitle', 'text'),\r\n    text: 'Echarts 5.14',\r\n    color: '#795548',\r\n    url: '/pages/echartsDemo/index'\r\n  },\r\n  {\r\n    iconName: 'transfer',\r\n    title: t('transferTitle', 'text'),\r\n    text: t('transferText', 'text'),\r\n    color: '#a61bc3',\r\n    url: '/pages/wotUiDemo/index'\r\n  },\r\n  {\r\n    iconName: 'view-module',\r\n    title: t('viewModuleTitle', 'text'),\r\n    text: 'z-padding',\r\n    color: '#d4ed00',\r\n    url: '/pages/queryDemo/zPagingDemo'\r\n  },\r\n  {\r\n    iconName: 'bianjiliebiao',\r\n    title: t('viewListTitle', 'text'),\r\n    text: 'i18n',\r\n    color: '#fea600',\r\n    url: '/pages/i18nDemo/index'\r\n  },\r\n  {\r\n    iconName: 'menu-fold',\r\n    title: t('menuFoldTitle', 'text'),\r\n    text: t('menuFoldText', 'text'),\r\n    color: '#652df4',\r\n    url: '/pages/customDemo/index'\r\n  },\r\n  {\r\n    iconName: 'chart-bubble',\r\n    title: 'Unocss',\r\n    text: t('chartBubbleTitle', 'text'),\r\n    color: '#ca145d',\r\n    url: '/pages/unocssDemo/index'\r\n  }\r\n])\r\n\r\n/* 切换主题色 */\r\nconst changeTheme = (bgColor?: string, fontColor?: string) => {\r\n  themeVars.value = {\r\n    colorTheme: bgColor ?? 'transparency',\r\n    darkColor3: (fontColor ?? theme.value === 'dark') ? '#f5f5f5' : '#272a2f'\r\n  }\r\n}\r\n\r\nonLoad(() => {\r\n  // 状态栏高度\r\n  statusBarHeight.value = (uni.getSystemInfoSync().statusBarHeight as number) || 20\r\n  // #ifdef MP-WEIXIN\r\n  // 胶囊数据\r\n  const { top, height } = uni.getMenuButtonBoundingClientRect()\r\n  // 自定义导航栏高度 = 胶囊高度 + 胶囊的 padding * 2, 如果获取不到设置为 38\r\n  barHeight.value = height ? height + (top - statusBarHeight.value) * 2 : 38\r\n  // #endif\r\n})\r\n</script>\r\n\r\n<style>\r\n/* 暗黑模式 start */\r\n.wot-theme-dark {\r\n  color: #f5f5f5;\r\n  background: black;\r\n  --theme-bg-color: #1b1b1b;\r\n}\r\n</style>\r\n"
  },
  {
    "path": "src/pages/layoutDemo/index.vue",
    "content": "<route type=\"page\" lang=\"json5\">\n{\n  layout: 'fullPage', // 使用默认布局，替换成 foot 试试\n  style: {\n    navigationBarTitleText: '布局 Demo'\n  }\n}\n</route>\n<template>\n  <div class=\"flex w-100vw h-40vh justify-center items-center bg-#f9cdad\">我是布局 Demo 页面的内容</div>\n</template>\n\n<style>\n/* 暗黑模式 start */\n.wot-theme-dark {\n  color: #f5f5f5;\n  background: #222222;\n  --theme-bg-color: #222222;\n}\n</style>\n"
  },
  {
    "path": "src/pages/piniaDemo/index.vue",
    "content": "<!--\n@description: pinia 使用 dome\n-->\n\n<route type=\"page\" lang=\"json5\">\n{\n  layout: 'theme', // 使用主题\n  style: {\n    navigationBarTitleText: 'pinia 使用 dome'\n  }\n}\n</route>\n\n<template>\n  <div>用户名：{{ userInfo.userName }}</div>\n  <button @click=\"changeUserName\">改变用户名</button>\n</template>\n\n<script setup lang=\"ts\">\n/* ------------------------ 导入 与 引用 ----------------------------------- */\nimport { useUserStore } from '@/store'\nimport { storeToRefs } from 'pinia'\nconst store = useUserStore()\nconst { userInfo } = storeToRefs(store)\n\n// 改变用户名\nconst changeUserName = () => {\n  store.setUserInfo({ userName: 'uni-plus-pro' })\n}\n\nonMounted(() => {\n  console.log('userInfo', userInfo.value)\n})\n</script>\n\n<style>\n/* 暗黑模式 start */\n.wot-theme-dark {\n  color: #f5f5f5;\n  background: #222222;\n  --theme-bg-color: #222222;\n}\n</style>\n"
  },
  {
    "path": "src/pages/queryDemo/loginDemo.vue",
    "content": "<route type=\"page\" lang=\"json5\">\n{\n  layout: 'theme', // 使用主题\n  style: {\n    navigationBarTitleText: '登录请求示例'\n  }\n}\n</route>\n\n<template>\n  <button @click=\"login\">登录请求</button>\n  <div class=\"flex w-100vw justify-center items-center h-80rpx font-size-26rpx\">\n    【 accessToken 失效,有 refreshToken 获取列表会无感刷新】\n  </div>\n  <button @click=\"getList\">获取列表</button>\n  <button @click=\"accessTokenInvalid\">accessToken 失效</button>\n  <button @click=\"refreshTokenInvalid\">refreshToken 失效</button>\n  <div class=\"flex flex-col justify-center items-center mt-40rpx\">\n    <div>----- accessToken -----</div>\n    <div class=\"w-80vw break-words mt-20rpx\">{{ userInfo.accessToken }}</div>\n    <div class=\"mt-40rpx\">----- refreshToken -----</div>\n    <div class=\"w-80vw break-words mt-20rpx\">{{ userInfo.refreshToken }}</div>\n    <div class=\"m-y-20rpx\">----- list 数据 -----</div>\n    <div>{{ list }}</div>\n  </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { loginApi, getListApi } from '@/api/loginApi'\nimport { useUserStore } from '@/store'\nimport { storeToRefs } from 'pinia'\nconst store = useUserStore()\nconst { userInfo } = storeToRefs(store)\n\n// 登录请求\nconst login = () => {\n  loginApi({\n    username: 'uniLin',\n    password: '111111'\n  })\n}\n\n// 获取 列表数据\nconst list = ref()\nconst getList = async () => {\n  list.value = []\n  list.value = await getListApi()\n}\n\n// token 失效\nconst accessTokenInvalid = () => {\n  const str = userInfo.value.accessToken.split('')\n  store.setUserInfo({\n    accessToken: [...str].sort(() => Math.random() - 0.5).join('')\n  })\n}\n\n// refreshToken 失效\nconst refreshTokenInvalid = () => {\n  const str = userInfo.value.refreshToken.split('')\n  store.setUserInfo({\n    refreshToken: [...str].sort(() => Math.random() - 0.5).join('')\n  })\n}\n</script>\n\n<style>\n/* 暗黑模式 start */\n.wot-theme-dark {\n  color: #f5f5f5;\n  background: black;\n  --theme-bg-color: #1b1b1b;\n}\n</style>\n"
  },
  {
    "path": "src/pages/queryDemo/queryTestDemo.vue",
    "content": "<route type=\"page\" lang=\"json5\">\n{\n  layout: 'theme', // 使用主题\n  style: {\n    navigationBarTitleText: '请求测试页面'\n  }\n}\n</route>\n\n<template>\n  <div>\n    <button @click=\"getTest\">GET 请求</button>\n    <button @click=\"postTest\">POST 请求</button>\n    <button @click=\"delayRequest\">3S后返回数据, 可点击下面取消请求取消</button>\n    <button @click=\"cancelRequest\">取消 请求</button>\n    <button @click=\"awaitToJs\">awaitToJs</button>\n    <div class=\"mt-40rpx\">\n      {{ pageData }}\n    </div>\n  </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { awaitToJsTestApi, getTestApi, postTestApi, getLongRequestApi } from '@/api/testApi'\nconst pageData = ref()\n\n// GET 请求\nconst getTest = async () => {\n  pageData.value = await getTestApi({ name: 'uni-plus' })\n}\n\n// POST 请求\nconst postTest = async () => {\n  pageData.value = await postTestApi({ name: 'uni-plus' }, { id: '123456' })\n}\n\n// 长时间请求（测试取消请求）\nlet requestTask = null\nconst delayRequest = () => {\n  requestTask = getLongRequestApi({ name: 'uni-plus' }, { id: '123456' })\n  requestTask\n    .then(res => {\n      pageData.value = res\n    })\n    .catch(err => {\n      pageData.value = err\n    })\n}\n\n// 取消 请求\nconst cancelRequest = () => {\n  // 取消请求\n  requestTask.abort()\n  pageData.value = { msg: '取消请求' }\n}\n\n/* await-to-js 代替 try catch 用法，根据实际需求进行使用 */\nconst awaitToJs = async () => {\n  const [data, err] = await awaitToJsTestApi({ name: 'uni-plus' })\n  if (data) {\n    pageData.value = data\n  }\n  if (err) {\n    pageData.value = err\n  }\n}\n</script>\n\n<style>\n/* 暗黑模式 start */\n.wot-theme-dark {\n  color: #f5f5f5;\n  background: black;\n  --theme-bg-color: #1b1b1b;\n}\n</style>\n"
  },
  {
    "path": "src/pages/queryDemo/useRequestDemo.vue",
    "content": "<route type=\"page\" lang=\"json5\">\n{\n  layout: 'theme', // 使用主题\n  style: {\n    navigationBarTitleText: 'useRequest使用示例'\n  }\n}\n</route>\n\n<template>\n  <button @click=\"prevPage\">上一页</button>\n  <button @click=\"nextPage\">下一页</button>\n  <button @click=\"getList\">重新获取列表</button>\n  <div v-if=\"loading\">加载中...</div>\n  <div v-else>\n    <div class=\"w-100vw font-size-36rpx m-y-20rpx\">当前页码：{{ page }}</div>\n    <ul>\n      <li v-for=\"item in filterData\" :key=\"item.id\" class=\"mb-10rpx\">\n        {{ item.title }}\n      </li>\n    </ul>\n  </div>\n  <div v-if=\"error\">请求失败: {{ error }}</div>\n</template>\n\n<script setup lang=\"ts\">\nimport { getUserListApi } from '@/api/testApi'\nimport useRequest from '@/hooks/useRequest'\n\n// data 数据处理\nconst filterData = computed(() => {\n  return data.value?.map((item: any) => {\n    return {\n      ...item,\n      title: item.title + '（这是额外添加的内容~）'\n    }\n  })\n})\n\n// useRequest 的使用\nconst page = ref(1)\nconst { loading, error, data, run } = useRequest({\n  queryKey: [page],\n  queryFn: () => getUserListApi({ page: page.value, limit: 10 }),\n  options: { immediate: true }\n})\n\n// 上一页\nconst prevPage = () => {\n  page.value = Math.max(page.value - 1, 1)\n}\n\n// 下一页\nconst nextPage = () => {\n  page.value = page.value + 1\n}\n\n// 重新获取列表数据\nconst getList = () => {\n  run()\n}\n</script>\n\n<style>\n/* 暗黑模式 start */\n.wot-theme-dark {\n  color: #f5f5f5;\n  background: black;\n  --theme-bg-color: #1b1b1b;\n}\n</style>\n"
  },
  {
    "path": "src/pages/queryDemo/zPagingDemo.vue",
    "content": "<route type=\"page\" lang=\"json5\">\n{\n  layout: 'theme', // 使用主题\n  style: {\n    navigationBarTitleText: 'z-paging 使用示例'\n  }\n}\n</route>\n\n<template>\n  <z-paging ref=\"paging\" v-model=\"dataList\" @query=\"queryList\">\n    <div>\n      <ul>\n        <li v-for=\"item in dataList\" :key=\"item.id\">\n          {{ item.title }}\n        </li>\n      </ul>\n    </div>\n    <!-- 页面内容 -->\n  </z-paging>\n</template>\n\n<script setup lang=\"ts\">\nimport { getUserListApi } from '@/api/testApi'\n\nconst paging = ref(null)\nconst dataList = ref([])\n\nconst queryList = (pageNo, pageSize) => {\n  // 这里的pageNo和pageSize会自动计算好，直接传给服务器即可\n  // 这里的请求只是演示，请替换成自己的项目的网络请求，并在网络请求回调中通过paging.value.complete(请求回来的数组)将请求结果传给z-paging\n  getUserListApi({ page: pageNo, limit: pageSize })\n    .then(res => {\n      // 请勿在网络请求回调中给dataList赋值！！只需要调用complete就可以了\n      // 如果你需要处理 res.data 的数据，请在 complete 之前处理\n      paging.value.complete(res.data)\n    })\n    .catch(res => {\n      console.log(res)\n      // 如果请求失败写paging.value.complete(false)，会自动展示错误页面\n      // 注意，每次都需要在catch中写这句话很麻烦，z-paging提供了方案可以全局统一处理\n      // 在底层的网络请求抛出异常时，写uni.$emit('z-paging-error-emit');即可\n      paging.value.complete(false)\n    })\n}\n\nonMounted(() => {\n  queryList(1, 10)\n})\n</script>\n\n<style>\n/* 暗黑模式 start */\n.wot-theme-dark {\n  color: #f5f5f5;\n  background: black;\n  --theme-bg-color: #1b1b1b;\n}\n</style>\n"
  },
  {
    "path": "src/pages/routerDemo/index.vue",
    "content": "<route lang=\"json5\" type=\"page\">\n{\n  layout: 'theme', // 使用主题\n  style: {\n    navigationBarTitleText: '页面路由权限控制'\n  }\n}\n</route>\n\n<template>\n  <div class=\"w-100vw flex justify-center items-center p-y-20rpx\">--------用户权限----------</div>\n  <div class=\"w-100vw flex justify-center items-center p-y-20rpx\">{{ getUserPermissionKeys() }}</div>\n  <div class=\"w-100vw flex justify-center items-center p-y-20rpx\">--------页面权限----------</div>\n  <button @click=\"goToPage1\">['vip']</button>\n  <button @click=\"goToPage2\">['vip', 'admin']</button>\n  <button @click=\"goToPage3\">['logined']</button>\n  <div class=\"w-100vw flex justify-center items-center p-y-20rpx\">--------按钮权限----------</div>\n  <button v-perms=\"['operation:user:create']\">有按钮权限: operation:user:create</button>\n  <button v-perms=\"['operation:user:delete']\">无按钮权限: operation:user:delete</button>\n</template>\n\n<script setup lang=\"ts\">\nimport { useUserStore } from '@/store'\n\nconst getUserPermissionKeys = () => {\n  const userStore = useUserStore()\n  return userStore.getUserPermissionKeys\n}\n\n// 跳转到页面1\nconst goToPage1 = () => {\n  uni.navigateTo({\n    url: '/pages/routerDemo/page1'\n  })\n}\n\n// 跳转到页面2\nconst goToPage2 = () => {\n  uni.navigateTo({\n    url: '/pages/routerDemo/page2'\n  })\n}\n\n// 跳转到页面3\nconst goToPage3 = () => {\n  uni.navigateTo({\n    url: '/pages/routerDemo/page3'\n  })\n}\n</script>\n\n<style>\n/* 暗黑模式 start */\n.wot-theme-dark {\n  color: #f5f5f5;\n  background: black;\n  --theme-bg-color: #1b1b1b;\n}\n</style>\n"
  },
  {
    "path": "src/pages/routerDemo/login.vue",
    "content": "<route lang=\"json5\" type=\"page\">\n{\n  layout: 'theme', // 使用主题\n  style: {\n    navigationBarTitleText: '登录页'\n  }\n}\n</route>\n\n<template>\n  <button @click=\"login\">使用假数据模拟登录</button>\n</template>\n\n<script setup lang=\"ts\">\nimport { useUserStore } from '@/store'\nimport { redirectRouteTo } from '@/utils'\nconst userStore = useUserStore()\n\n/* 假登录 */\nconst login = () => {\n  userStore.setUserInfo({\n    accessToken: 'fakeAccessToken',\n    refreshToken: 'fakeRefreshToken'\n  })\n  // 如果有重定向路径，跳转才有效\n  redirectRouteTo()\n}\n</script>\n\n<style>\n/* 暗黑模式 start */\n.wot-theme-dark {\n  color: #f5f5f5;\n  background: black;\n  --theme-bg-color: #1b1b1b;\n}\n</style>\n"
  },
  {
    "path": "src/pages/routerDemo/page1.vue",
    "content": "<route lang=\"json5\" type=\"page\">\n{\n  layout: 'theme', // 使用主题\n  style: {\n    navigationBarTitleText: '页面1'\n  },\n  permissionKeys: ['vip']\n}\n</route>\n\n<template>\n  <h1>页面1</h1>\n</template>\n\n<style>\n/* 暗黑模式 start */\n.wot-theme-dark {\n  color: #f5f5f5;\n  background: black;\n  --theme-bg-color: #1b1b1b;\n}\n</style>\n"
  },
  {
    "path": "src/pages/routerDemo/page2.vue",
    "content": "<route lang=\"json5\" type=\"page\">\n{\n  layout: 'theme', // 使用主题\n  style: {\n    navigationBarTitleText: '页面2'\n  },\n  permissionKeys: ['vip', 'admin']\n}\n</route>\n\n<template>\n  <h1>页面2</h1>\n</template>\n\n<style>\n/* 暗黑模式 start */\n.wot-theme-dark {\n  color: #f5f5f5;\n  background: black;\n  --theme-bg-color: #1b1b1b;\n}\n</style>\n"
  },
  {
    "path": "src/pages/routerDemo/page3.vue",
    "content": "<route lang=\"json5\" type=\"page\">\n{\n  layout: 'theme', // 使用主题\n  style: {\n    navigationBarTitleText: '页面3'\n  },\n  permissionKeys: ['logined']\n}\n</route>\n\n<template>\n  <h1>页面3</h1>\n</template>\n\n<style>\n/* 暗黑模式 start */\n.wot-theme-dark {\n  color: #f5f5f5;\n  background: black;\n  --theme-bg-color: #1b1b1b;\n}\n</style>\n"
  },
  {
    "path": "src/pages/unocssDemo/index.vue",
    "content": "<!--\n@description: Unocss 使用 dome\n-->\n\n<route type=\"page\" lang=\"json5\">\n{\n  layout: 'theme', // 使用主题\n  style: {\n    navigationBarTitleText: 'Unocss 使用 dome'\n  }\n}\n</route>\n\n<template>\n  <div class=\"w-100vw flex justify-center items-center p-y-20rpx\">--------unocss 图标----------</div>\n  <div class=\"flex justify-center gap-3 text-5xl text-blue-300\">\n    <!-- 类目最前面加 i-  -->\n    <!-- 写法一：图标库名称 + : + 图标名称 -->\n    <i class=\"i-uiw-alipay\" />\n    <!-- 写法二：图标库名称 + - + 图标名称 -->\n    <i class=\"i-uiw:apple\" />\n  </div>\n  <div class=\"w-100vw flex justify-center items-center p-y-20rpx\">--------传统图标----------</div>\n  <div class=\"flex justify-center items-center gap-3\">\n    <img class=\"w-100rpx h-100rpx\" src=\"https://api.iconify.design/uiw:github.svg?color=%23faa5a2\" />\n    <img class=\"w-100rpx h-100rpx\" src=\"https://api.iconify.design/uiw:html5.svg?color=%23faa5a2\" />\n  </div>\n</template>\n\n<style>\n/* 暗黑模式 start */\n.wot-theme-dark {\n  color: #f5f5f5;\n  background: black;\n  --theme-bg-color: #1b1b1b;\n}\n</style>\n"
  },
  {
    "path": "src/pages/wotUiDemo/index.vue",
    "content": "<route type=\"page\" lang=\"json5\">\n{\n  layout: 'theme', // 使用主题\n  style: {\n    navigationBarTitleText: 'Wot UI Demo'\n  }\n}\n</route>\n<template>\n  <div class=\"flex-col-center font-size-14\">\n    <div class=\"flex flex-col\">\n      <text class=\"title\">{{ title }}</text>\n      <wd-button type=\"success\">成功按钮</wd-button>\n      <wd-button type=\"info\">默认按钮</wd-button>\n      <wd-slider v-model=\"value\" />\n    </div>\n  </div>\n</template>\n\n<script setup lang=\"ts\">\nconst title = ref<string>('Hello')\nconst value = ref<number>(30)\n</script>\n\n<style>\n/* 暗黑模式 start */\n.wot-theme-dark {\n  color: #f5f5f5;\n  background: black;\n  --theme-bg-color: #1b1b1b;\n}\n</style>\n"
  },
  {
    "path": "src/pages-sub/subDemo/index.vue",
    "content": "<route lang=\"json5\" type=\"page\">\n{\n  style: { navigationBarTitleText: 'subDemo 分包页面' }\n}\n</route>\n\n<template>\n  <view class=\"text-center\">\n    <view class=\"text-green-500\">subDemo 分包页面</view>\n  </view>\n</template>\n"
  },
  {
    "path": "src/pages-sub/testDemo/index.vue",
    "content": "<!--\n@description: 测试页面\n@creationTime: 2025-01-23\n-->\n\n<route type=\"page\" lang=\"json5\">\n{\n  layout: 'default',\n  style: {\n    navigationBarTitleText: '测试页面'\n  }\n}\n</route>\n\n<template>\n  <view>测试页面</view>\n</template>\n\n<script lang=\"ts\" setup>\n/* ------------------------ 导入 与 引用 ----------------------------------- */\n/* ------------------------ 函数 与 方法 ----------------------------------- */\n/* ------------------------- 生命周期 -------------------------------------- */\n</script>\n\n<style lang=\"scss\" scoped></style>\n"
  },
  {
    "path": "src/pages.json",
    "content": "{\n\t\"pages\": [\n\t\t{\n\t\t\t\"path\": \"pages/index/index\",\n\t\t\t\"type\": \"home\",\n\t\t\t\"layout\": \"theme\",\n\t\t\t\"style\": {\n\t\t\t\t\"navigationStyle\": \"custom\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"path\": \"pages/customDemo/index\",\n\t\t\t\"type\": \"page\",\n\t\t\t\"layout\": \"theme\",\n\t\t\t\"style\": {\n\t\t\t\t\"navigationStyle\": \"custom\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"path\": \"pages/echartsDemo/index\",\n\t\t\t\"type\": \"page\",\n\t\t\t\"layout\": \"theme\",\n\t\t\t\"style\": {\n\t\t\t\t\"navigationBarTitleText\": \"图表 dome\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"path\": \"pages/i18nDemo/index\",\n\t\t\t\"type\": \"page\",\n\t\t\t\"layout\": \"theme\",\n\t\t\t\"style\": {\n\t\t\t\t\"navigationBarTitleText\": \"%pages.index.index.title%\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"path\": \"pages/layoutDemo/index\",\n\t\t\t\"type\": \"page\",\n\t\t\t\"layout\": \"fullPage\",\n\t\t\t\"style\": {\n\t\t\t\t\"navigationBarTitleText\": \"布局 Demo\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"path\": \"pages/piniaDemo/index\",\n\t\t\t\"type\": \"page\",\n\t\t\t\"layout\": \"theme\",\n\t\t\t\"style\": {\n\t\t\t\t\"navigationBarTitleText\": \"pinia 使用 dome\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"path\": \"pages/queryDemo/loginDemo\",\n\t\t\t\"type\": \"page\",\n\t\t\t\"layout\": \"theme\",\n\t\t\t\"style\": {\n\t\t\t\t\"navigationBarTitleText\": \"登录请求示例\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"path\": \"pages/queryDemo/queryTestDemo\",\n\t\t\t\"type\": \"page\",\n\t\t\t\"layout\": \"theme\",\n\t\t\t\"style\": {\n\t\t\t\t\"navigationBarTitleText\": \"请求测试页面\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"path\": \"pages/queryDemo/useRequestDemo\",\n\t\t\t\"type\": \"page\",\n\t\t\t\"layout\": \"theme\",\n\t\t\t\"style\": {\n\t\t\t\t\"navigationBarTitleText\": \"useRequest使用示例\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"path\": \"pages/queryDemo/zPagingDemo\",\n\t\t\t\"type\": \"page\",\n\t\t\t\"layout\": \"theme\",\n\t\t\t\"style\": {\n\t\t\t\t\"navigationBarTitleText\": \"z-paging 使用示例\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"path\": \"pages/routerDemo/index\",\n\t\t\t\"type\": \"page\",\n\t\t\t\"layout\": \"theme\",\n\t\t\t\"style\": {\n\t\t\t\t\"navigationBarTitleText\": \"页面路由权限控制\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"path\": \"pages/routerDemo/login\",\n\t\t\t\"type\": \"page\",\n\t\t\t\"layout\": \"theme\",\n\t\t\t\"style\": {\n\t\t\t\t\"navigationBarTitleText\": \"登录页\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"path\": \"pages/routerDemo/page1\",\n\t\t\t\"type\": \"page\",\n\t\t\t\"layout\": \"theme\",\n\t\t\t\"style\": {\n\t\t\t\t\"navigationBarTitleText\": \"页面1\"\n\t\t\t},\n\t\t\t\"permissionKeys\": [\n\t\t\t\t\"vip\"\n\t\t\t]\n\t\t},\n\t\t{\n\t\t\t\"path\": \"pages/routerDemo/page2\",\n\t\t\t\"type\": \"page\",\n\t\t\t\"layout\": \"theme\",\n\t\t\t\"style\": {\n\t\t\t\t\"navigationBarTitleText\": \"页面2\"\n\t\t\t},\n\t\t\t\"permissionKeys\": [\n\t\t\t\t\"vip\",\n\t\t\t\t\"admin\"\n\t\t\t]\n\t\t},\n\t\t{\n\t\t\t\"path\": \"pages/routerDemo/page3\",\n\t\t\t\"type\": \"page\",\n\t\t\t\"layout\": \"theme\",\n\t\t\t\"style\": {\n\t\t\t\t\"navigationBarTitleText\": \"页面3\"\n\t\t\t},\n\t\t\t\"permissionKeys\": [\n\t\t\t\t\"logined\"\n\t\t\t]\n\t\t},\n\t\t{\n\t\t\t\"path\": \"pages/unocssDemo/index\",\n\t\t\t\"type\": \"page\",\n\t\t\t\"layout\": \"theme\",\n\t\t\t\"style\": {\n\t\t\t\t\"navigationBarTitleText\": \"Unocss 使用 dome\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"path\": \"pages/wotUiDemo/index\",\n\t\t\t\"type\": \"page\",\n\t\t\t\"layout\": \"theme\",\n\t\t\t\"style\": {\n\t\t\t\t\"navigationBarTitleText\": \"Wot UI Demo\"\n\t\t\t}\n\t\t}\n\t],\n\t\"globalStyle\": {\n\t\t\"navigationBarTextStyle\": \"@navTxtStyle\",\n\t\t\"navigationBarBackgroundColor\": \"@navBgColor\",\n\t\t\"backgroundColor\": \"@bgColor\"\n\t},\n\t\"easycom\": {\n\t\t\"autoscan\": true,\n\t\t\"custom\": {\n\t\t\t\"^wd-(.*)\": \"wot-design-uni/components/wd-$1/wd-$1.vue\",\n\t\t\t\"^(?!z-paging-refresh|z-paging-load-more)z-paging(.*)\": \"z-paging/components/z-paging$1/z-paging$1.vue\"\n\t\t}\n\t},\n\t\"subPackages\": [\n\t\t{\n\t\t\t\"root\": \"pages-sub\",\n\t\t\t\"pages\": [\n\t\t\t\t{\n\t\t\t\t\t\"path\": \"subDemo/index\",\n\t\t\t\t\t\"type\": \"page\",\n\t\t\t\t\t\"style\": {\n\t\t\t\t\t\t\"navigationBarTitleText\": \"subDemo 分包页面\"\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"path\": \"testDemo/index\",\n\t\t\t\t\t\"type\": \"page\",\n\t\t\t\t\t\"layout\": \"default\",\n\t\t\t\t\t\"style\": {\n\t\t\t\t\t\t\"navigationBarTitleText\": \"测试页面\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t]\n}"
  },
  {
    "path": "src/store/index.ts",
    "content": "import { createPinia } from 'pinia'\nimport { createPersistedState } from 'pinia-plugin-persistedstate' // 数据持久化\n\n// 持久化把数据放在本地存储中\nconst store = createPinia()\nstore.use(\n  createPersistedState({\n    storage: {\n      getItem: uni.getStorageSync,\n      setItem: uni.setStorageSync\n    }\n  })\n)\n\nexport default store\n\n// 模块统一导出\nexport * from './user'\n"
  },
  {
    "path": "src/store/user.ts",
    "content": "import { defineStore } from 'pinia'\nimport { ref } from 'vue'\n\ntype UserInfo = {\n  userName?: string\n  userId?: string\n  avatar?: string\n  accessToken?: string\n  refreshToken?: string\n  isVip?: boolean\n  theme?: 'light' | 'dark'\n  locale?: string\n  followSystem?: boolean\n  userBtnPermission?: string[]\n}\n\n// 初始用户数据，可用户初始化\nconst initState = {\n  userName: 'uni-plus',\n  userId: '',\n  avatar: '',\n  accessToken: '',\n  refreshToken: '',\n  theme: <'light' | 'dark'>'light',\n  followSystem: false,\n  locale: 'zh-CN',\n  isVip: true,\n  userBtnPermission: ['operation:user:create', 'operation:user:update']\n  // ...\n}\n\nexport const useUserStore = defineStore(\n  'user',\n  // Setup Store 写法，Vue3 推荐用这个种方法写\n  () => {\n    const userInfo = ref<UserInfo>({ ...initState })\n\n    // 设置用户信息 可设置部分信息（比如更新 token）\n    const setUserInfo = (val: UserInfo): void => {\n      userInfo.value = { ...userInfo.value, ...val }\n    }\n\n    // 清除用户信息\n    const clearUserInfo = (): void => {\n      userInfo.value = { ...initState }\n    }\n\n    // 获取页面权限信息\n    const getUserPermissionKeys = computed(() => {\n      const permissionKeys: string[] = []\n      // 是登录\n      if (!!userInfo.value.accessToken && !!userInfo.value.refreshToken) {\n        permissionKeys.push('logined')\n      }\n      // 是否为 vip\n      if (userInfo.value.isVip) {\n        permissionKeys.push('vip')\n      }\n      // 可以继续加你需要的权限判定 ...\n      return permissionKeys\n    })\n\n    // 获取用户按钮权限\n    const getUserBtnPermission = computed(() => {\n      return userInfo.value.userBtnPermission\n    })\n\n    // 获取主题状态\n    const getTheme = computed(() => {\n      return userInfo.value.theme\n    })\n\n    // 获取 locale\n    const getLocale = computed(() => {\n      return userInfo.value.locale\n    })\n\n    // 设置 locale\n    const setLocale = () => {\n      userInfo.value.locale = userInfo.value.locale === 'zh-CN' ? 'en-US' : 'zh-CN'\n    }\n\n    return {\n      userInfo,\n      getLocale,\n      getTheme,\n      getUserPermissionKeys,\n      getUserBtnPermission,\n      setUserInfo,\n      clearUserInfo,\n      setLocale\n    }\n  },\n  {\n    persist: true // 是否持久化\n  }\n)\n"
  },
  {
    "path": "src/theme.json",
    "content": "{\n  // 浅色模式\n  \"light\": {\n    \"navBgColor\": \"#fff\", // 导航栏背景色\n    \"navTxtStyle\": \"black\", // 导航栏文字颜色\n    \"bgColor\": \"#f5f5f5\", // 页面背景色\n    \"bgTxtStyle\": \"light\", // 下拉 loading 的样式，仅支持 dark/light\n    \"bgColorTop\": \"#eeeeee\", // 顶部窗口的背景色（bounce回弹区域）\n    \"bgColorBottom\": \"#efefef\", // 底部窗口的背景色（bounce回弹区域）\n    \"tabFontColor\": \"#666666\", // tabBar 上的文字默认颜色\n    \"tabSelectedColor\": \"#8fc97f\", // tabBar 上的文字选中颜色\n    \"tabBgColor\": \"#ffffff\", // tabBar 背景色\n    \"tabBorderStyle\": \"white\" // tabBar 上边框的颜色，可选值 black/white，也支持其他颜色值\n  },\n  // 深色模式\n  \"dark\": {\n    \"navBgColor\": \"#1d1d1d\", // 导航栏背景色\n    \"navTxtStyle\": \"white\", // 导航栏文字颜色\n    \"bgColor\": \"#222222\", // 页面背景色\n    \"bgTxtStyle\": \"dark\", // 下拉 loading 的样式，仅支持 dark/light\n    \"bgColorTop\": \"#1e1e1e\", // 顶部窗口的背景色（bounce回弹区域）\n    \"bgColorBottom\": \"#1e1e1e\", // 底部窗口的背景色（bounce回弹区域）\n    \"tabFontColor\": \"#bbb\", // tabBar 上的文字默认颜色\n    \"tabSelectedColor\": \"#8fc97f\", // tabBar 上的文字选中颜色\n    \"tabBgColor\": \"#212121\", // tabBar 背景色\n    \"tabBorderStyle\": \"black\" // tabBar 上边框的颜色，可选值 black/white，也支持其他颜色值\n  }\n}\n"
  },
  {
    "path": "src/types/auto-import.d.ts",
    "content": "/* eslint-disable */\n/* prettier-ignore */\n// @ts-nocheck\n// noinspection JSUnusedGlobalSymbols\n// Generated by unplugin-auto-import\n// biome-ignore lint: disable\nexport {}\ndeclare global {\n  const EffectScope: (typeof import('vue'))['EffectScope']\n  const computed: (typeof import('vue'))['computed']\n  const createApp: (typeof import('vue'))['createApp']\n  const customRef: (typeof import('vue'))['customRef']\n  const defineAsyncComponent: (typeof import('vue'))['defineAsyncComponent']\n  const defineComponent: (typeof import('vue'))['defineComponent']\n  const effectScope: (typeof import('vue'))['effectScope']\n  const getCurrentInstance: (typeof import('vue'))['getCurrentInstance']\n  const getCurrentScope: (typeof import('vue'))['getCurrentScope']\n  const h: (typeof import('vue'))['h']\n  const inject: (typeof import('vue'))['inject']\n  const isProxy: (typeof import('vue'))['isProxy']\n  const isReactive: (typeof import('vue'))['isReactive']\n  const isReadonly: (typeof import('vue'))['isReadonly']\n  const isRef: (typeof import('vue'))['isRef']\n  const markRaw: (typeof import('vue'))['markRaw']\n  const nextTick: (typeof import('vue'))['nextTick']\n  const onActivated: (typeof import('vue'))['onActivated']\n  const onAddToFavorites: (typeof import('@dcloudio/uni-app'))['onAddToFavorites']\n  const onBackPress: (typeof import('@dcloudio/uni-app'))['onBackPress']\n  const onBeforeMount: (typeof import('vue'))['onBeforeMount']\n  const onBeforeUnmount: (typeof import('vue'))['onBeforeUnmount']\n  const onBeforeUpdate: (typeof import('vue'))['onBeforeUpdate']\n  const onDeactivated: (typeof import('vue'))['onDeactivated']\n  const onError: (typeof import('@dcloudio/uni-app'))['onError']\n  const onErrorCaptured: (typeof import('vue'))['onErrorCaptured']\n  const onHide: (typeof import('@dcloudio/uni-app'))['onHide']\n  const onLaunch: (typeof import('@dcloudio/uni-app'))['onLaunch']\n  const onLoad: (typeof import('@dcloudio/uni-app'))['onLoad']\n  const onMounted: (typeof import('vue'))['onMounted']\n  const onNavigationBarButtonTap: (typeof import('@dcloudio/uni-app'))['onNavigationBarButtonTap']\n  const onNavigationBarSearchInputChanged: (typeof import('@dcloudio/uni-app'))['onNavigationBarSearchInputChanged']\n  const onNavigationBarSearchInputClicked: (typeof import('@dcloudio/uni-app'))['onNavigationBarSearchInputClicked']\n  const onNavigationBarSearchInputConfirmed: (typeof import('@dcloudio/uni-app'))['onNavigationBarSearchInputConfirmed']\n  const onNavigationBarSearchInputFocusChanged: (typeof import('@dcloudio/uni-app'))['onNavigationBarSearchInputFocusChanged']\n  const onPageNotFound: (typeof import('@dcloudio/uni-app'))['onPageNotFound']\n  const onPageScroll: (typeof import('@dcloudio/uni-app'))['onPageScroll']\n  const onPullDownRefresh: (typeof import('@dcloudio/uni-app'))['onPullDownRefresh']\n  const onReachBottom: (typeof import('@dcloudio/uni-app'))['onReachBottom']\n  const onReady: (typeof import('@dcloudio/uni-app'))['onReady']\n  const onRenderTracked: (typeof import('vue'))['onRenderTracked']\n  const onRenderTriggered: (typeof import('vue'))['onRenderTriggered']\n  const onResize: (typeof import('@dcloudio/uni-app'))['onResize']\n  const onScopeDispose: (typeof import('vue'))['onScopeDispose']\n  const onServerPrefetch: (typeof import('vue'))['onServerPrefetch']\n  const onShareAppMessage: (typeof import('@dcloudio/uni-app'))['onShareAppMessage']\n  const onShareTimeline: (typeof import('@dcloudio/uni-app'))['onShareTimeline']\n  const onShow: (typeof import('@dcloudio/uni-app'))['onShow']\n  const onTabItemTap: (typeof import('@dcloudio/uni-app'))['onTabItemTap']\n  const onThemeChange: (typeof import('@dcloudio/uni-app'))['onThemeChange']\n  const onUnhandledRejection: (typeof import('@dcloudio/uni-app'))['onUnhandledRejection']\n  const onUnload: (typeof import('@dcloudio/uni-app'))['onUnload']\n  const onUnmounted: (typeof import('vue'))['onUnmounted']\n  const onUpdated: (typeof import('vue'))['onUpdated']\n  const onWatcherCleanup: (typeof import('vue'))['onWatcherCleanup']\n  const provide: (typeof import('vue'))['provide']\n  const reactive: (typeof import('vue'))['reactive']\n  const readonly: (typeof import('vue'))['readonly']\n  const ref: (typeof import('vue'))['ref']\n  const resolveComponent: (typeof import('vue'))['resolveComponent']\n  const shallowReactive: (typeof import('vue'))['shallowReactive']\n  const shallowReadonly: (typeof import('vue'))['shallowReadonly']\n  const shallowRef: (typeof import('vue'))['shallowRef']\n  const toRaw: (typeof import('vue'))['toRaw']\n  const toRef: (typeof import('vue'))['toRef']\n  const toRefs: (typeof import('vue'))['toRefs']\n  const toValue: (typeof import('vue'))['toValue']\n  const triggerRef: (typeof import('vue'))['triggerRef']\n  const unref: (typeof import('vue'))['unref']\n  const useAttrs: (typeof import('vue'))['useAttrs']\n  const useCssModule: (typeof import('vue'))['useCssModule']\n  const useCssVars: (typeof import('vue'))['useCssVars']\n  const useEcharts: (typeof import('../hooks/useEcharts'))['useEcharts']\n  const useI18n: (typeof import('../hooks/useI18n'))['useI18n']\n  const useId: (typeof import('vue'))['useId']\n  const useModel: (typeof import('vue'))['useModel']\n  const useRequest: (typeof import('../hooks/useRequest'))['default']\n  const useSlots: (typeof import('vue'))['useSlots']\n  const useTemplateRef: (typeof import('vue'))['useTemplateRef']\n  const useTheme: (typeof import('../hooks/useTheme'))['useTheme']\n  const watch: (typeof import('vue'))['watch']\n  const watchEffect: (typeof import('vue'))['watchEffect']\n  const watchPostEffect: (typeof import('vue'))['watchPostEffect']\n  const watchSyncEffect: (typeof import('vue'))['watchSyncEffect']\n}\n// for type re-export\ndeclare global {\n  // @ts-ignore\n  export type {\n    Component,\n    ComponentPublicInstance,\n    ComputedRef,\n    DirectiveBinding,\n    ExtractDefaultPropTypes,\n    ExtractPropTypes,\n    ExtractPublicPropTypes,\n    InjectionKey,\n    PropType,\n    Ref,\n    MaybeRef,\n    MaybeRefOrGetter,\n    VNode,\n    WritableComputedRef\n  } from 'vue'\n  import('vue')\n}\n\n// for vue template auto import\nimport { UnwrapRef } from 'vue'\ndeclare module 'vue' {\n  interface GlobalComponents {}\n  interface ComponentCustomProperties {\n    readonly EffectScope: UnwrapRef<(typeof import('vue'))['EffectScope']>\n    readonly computed: UnwrapRef<(typeof import('vue'))['computed']>\n    readonly createApp: UnwrapRef<(typeof import('vue'))['createApp']>\n    readonly customRef: UnwrapRef<(typeof import('vue'))['customRef']>\n    readonly defineAsyncComponent: UnwrapRef<(typeof import('vue'))['defineAsyncComponent']>\n    readonly defineComponent: UnwrapRef<(typeof import('vue'))['defineComponent']>\n    readonly effectScope: UnwrapRef<(typeof import('vue'))['effectScope']>\n    readonly getCurrentInstance: UnwrapRef<(typeof import('vue'))['getCurrentInstance']>\n    readonly getCurrentScope: UnwrapRef<(typeof import('vue'))['getCurrentScope']>\n    readonly h: UnwrapRef<(typeof import('vue'))['h']>\n    readonly inject: UnwrapRef<(typeof import('vue'))['inject']>\n    readonly isProxy: UnwrapRef<(typeof import('vue'))['isProxy']>\n    readonly isReactive: UnwrapRef<(typeof import('vue'))['isReactive']>\n    readonly isReadonly: UnwrapRef<(typeof import('vue'))['isReadonly']>\n    readonly isRef: UnwrapRef<(typeof import('vue'))['isRef']>\n    readonly markRaw: UnwrapRef<(typeof import('vue'))['markRaw']>\n    readonly nextTick: UnwrapRef<(typeof import('vue'))['nextTick']>\n    readonly onActivated: UnwrapRef<(typeof import('vue'))['onActivated']>\n    readonly onAddToFavorites: UnwrapRef<(typeof import('@dcloudio/uni-app'))['onAddToFavorites']>\n    readonly onBackPress: UnwrapRef<(typeof import('@dcloudio/uni-app'))['onBackPress']>\n    readonly onBeforeMount: UnwrapRef<(typeof import('vue'))['onBeforeMount']>\n    readonly onBeforeUnmount: UnwrapRef<(typeof import('vue'))['onBeforeUnmount']>\n    readonly onBeforeUpdate: UnwrapRef<(typeof import('vue'))['onBeforeUpdate']>\n    readonly onDeactivated: UnwrapRef<(typeof import('vue'))['onDeactivated']>\n    readonly onError: UnwrapRef<(typeof import('@dcloudio/uni-app'))['onError']>\n    readonly onErrorCaptured: UnwrapRef<(typeof import('vue'))['onErrorCaptured']>\n    readonly onHide: UnwrapRef<(typeof import('@dcloudio/uni-app'))['onHide']>\n    readonly onLaunch: UnwrapRef<(typeof import('@dcloudio/uni-app'))['onLaunch']>\n    readonly onLoad: UnwrapRef<(typeof import('@dcloudio/uni-app'))['onLoad']>\n    readonly onMounted: UnwrapRef<(typeof import('vue'))['onMounted']>\n    readonly onNavigationBarButtonTap: UnwrapRef<(typeof import('@dcloudio/uni-app'))['onNavigationBarButtonTap']>\n    readonly onNavigationBarSearchInputChanged: UnwrapRef<\n      (typeof import('@dcloudio/uni-app'))['onNavigationBarSearchInputChanged']\n    >\n    readonly onNavigationBarSearchInputClicked: UnwrapRef<\n      (typeof import('@dcloudio/uni-app'))['onNavigationBarSearchInputClicked']\n    >\n    readonly onNavigationBarSearchInputConfirmed: UnwrapRef<\n      (typeof import('@dcloudio/uni-app'))['onNavigationBarSearchInputConfirmed']\n    >\n    readonly onNavigationBarSearchInputFocusChanged: UnwrapRef<\n      (typeof import('@dcloudio/uni-app'))['onNavigationBarSearchInputFocusChanged']\n    >\n    readonly onPageNotFound: UnwrapRef<(typeof import('@dcloudio/uni-app'))['onPageNotFound']>\n    readonly onPageScroll: UnwrapRef<(typeof import('@dcloudio/uni-app'))['onPageScroll']>\n    readonly onPullDownRefresh: UnwrapRef<(typeof import('@dcloudio/uni-app'))['onPullDownRefresh']>\n    readonly onReachBottom: UnwrapRef<(typeof import('@dcloudio/uni-app'))['onReachBottom']>\n    readonly onReady: UnwrapRef<(typeof import('@dcloudio/uni-app'))['onReady']>\n    readonly onRenderTracked: UnwrapRef<(typeof import('vue'))['onRenderTracked']>\n    readonly onRenderTriggered: UnwrapRef<(typeof import('vue'))['onRenderTriggered']>\n    readonly onResize: UnwrapRef<(typeof import('@dcloudio/uni-app'))['onResize']>\n    readonly onScopeDispose: UnwrapRef<(typeof import('vue'))['onScopeDispose']>\n    readonly onServerPrefetch: UnwrapRef<(typeof import('vue'))['onServerPrefetch']>\n    readonly onShareAppMessage: UnwrapRef<(typeof import('@dcloudio/uni-app'))['onShareAppMessage']>\n    readonly onShareTimeline: UnwrapRef<(typeof import('@dcloudio/uni-app'))['onShareTimeline']>\n    readonly onShow: UnwrapRef<(typeof import('@dcloudio/uni-app'))['onShow']>\n    readonly onTabItemTap: UnwrapRef<(typeof import('@dcloudio/uni-app'))['onTabItemTap']>\n    readonly onThemeChange: UnwrapRef<(typeof import('@dcloudio/uni-app'))['onThemeChange']>\n    readonly onUnhandledRejection: UnwrapRef<(typeof import('@dcloudio/uni-app'))['onUnhandledRejection']>\n    readonly onUnload: UnwrapRef<(typeof import('@dcloudio/uni-app'))['onUnload']>\n    readonly onUnmounted: UnwrapRef<(typeof import('vue'))['onUnmounted']>\n    readonly onUpdated: UnwrapRef<(typeof import('vue'))['onUpdated']>\n    readonly onWatcherCleanup: UnwrapRef<(typeof import('vue'))['onWatcherCleanup']>\n    readonly provide: UnwrapRef<(typeof import('vue'))['provide']>\n    readonly reactive: UnwrapRef<(typeof import('vue'))['reactive']>\n    readonly readonly: UnwrapRef<(typeof import('vue'))['readonly']>\n    readonly ref: UnwrapRef<(typeof import('vue'))['ref']>\n    readonly resolveComponent: UnwrapRef<(typeof import('vue'))['resolveComponent']>\n    readonly shallowReactive: UnwrapRef<(typeof import('vue'))['shallowReactive']>\n    readonly shallowReadonly: UnwrapRef<(typeof import('vue'))['shallowReadonly']>\n    readonly shallowRef: UnwrapRef<(typeof import('vue'))['shallowRef']>\n    readonly toRaw: UnwrapRef<(typeof import('vue'))['toRaw']>\n    readonly toRef: UnwrapRef<(typeof import('vue'))['toRef']>\n    readonly toRefs: UnwrapRef<(typeof import('vue'))['toRefs']>\n    readonly toValue: UnwrapRef<(typeof import('vue'))['toValue']>\n    readonly triggerRef: UnwrapRef<(typeof import('vue'))['triggerRef']>\n    readonly unref: UnwrapRef<(typeof import('vue'))['unref']>\n    readonly useAttrs: UnwrapRef<(typeof import('vue'))['useAttrs']>\n    readonly useCssModule: UnwrapRef<(typeof import('vue'))['useCssModule']>\n    readonly useCssVars: UnwrapRef<(typeof import('vue'))['useCssVars']>\n    readonly useEcharts: UnwrapRef<(typeof import('../hooks/useEcharts'))['useEcharts']>\n    readonly useI18n: UnwrapRef<(typeof import('../hooks/useI18n'))['useI18n']>\n    readonly useId: UnwrapRef<(typeof import('vue'))['useId']>\n    readonly useModel: UnwrapRef<(typeof import('vue'))['useModel']>\n    readonly useRequest: UnwrapRef<(typeof import('../hooks/useRequest'))['default']>\n    readonly useSlots: UnwrapRef<(typeof import('vue'))['useSlots']>\n    readonly useTemplateRef: UnwrapRef<(typeof import('vue'))['useTemplateRef']>\n    readonly useTheme: UnwrapRef<(typeof import('../hooks/useTheme'))['useTheme']>\n    readonly watch: UnwrapRef<(typeof import('vue'))['watch']>\n    readonly watchEffect: UnwrapRef<(typeof import('vue'))['watchEffect']>\n    readonly watchPostEffect: UnwrapRef<(typeof import('vue'))['watchPostEffect']>\n    readonly watchSyncEffect: UnwrapRef<(typeof import('vue'))['watchSyncEffect']>\n  }\n}\n"
  },
  {
    "path": "src/types/gloal.d.ts",
    "content": "import { ComponentCustomProperties } from 'vue'\n\ndeclare module 'vue' {\n  interface ComponentCustomProperties {\n    $assets: any\n  }\n}\n"
  },
  {
    "path": "src/types/uni-pages.d.ts",
    "content": "/* eslint-disable */\n/* prettier-ignore */\n// @ts-nocheck\n// Generated by vite-plugin-uni-pages\n\ninterface NavigateToOptions {\n  url: \"/pages/index/index\" |\n       \"/pages/customDemo/index\" |\n       \"/pages/echartsDemo/index\" |\n       \"/pages/i18nDemo/index\" |\n       \"/pages/layoutDemo/index\" |\n       \"/pages/piniaDemo/index\" |\n       \"/pages/queryDemo/loginDemo\" |\n       \"/pages/queryDemo/queryTestDemo\" |\n       \"/pages/queryDemo/useRequestDemo\" |\n       \"/pages/queryDemo/zPagingDemo\" |\n       \"/pages/routerDemo/index\" |\n       \"/pages/routerDemo/login\" |\n       \"/pages/routerDemo/page1\" |\n       \"/pages/routerDemo/page2\" |\n       \"/pages/routerDemo/page3\" |\n       \"/pages/unocssDemo/index\" |\n       \"/pages/wotUiDemo/index\" |\n       \"/pages-sub/subDemo/index\" |\n       \"/pages-sub/testDemo/index\";\n}\ninterface RedirectToOptions extends NavigateToOptions {}\n\ninterface SwitchTabOptions {}\n\ntype ReLaunchOptions = NavigateToOptions | SwitchTabOptions\n\ndeclare interface Uni {\n  navigateTo(options: UniNamespace.NavigateToOptions & NavigateToOptions): void\n  redirectTo(options: UniNamespace.RedirectToOptions & RedirectToOptions): void\n  switchTab(options: UniNamespace.SwitchTabOptions & SwitchTabOptions): void\n  reLaunch(options: UniNamespace.ReLaunchOptions & ReLaunchOptions): void\n}\n"
  },
  {
    "path": "src/typings.ts",
    "content": "type ResData<T> = {\n  data: T\n  code: number\n  message: string\n}\n"
  },
  {
    "path": "src/uni.scss",
    "content": "/**\r\n * 这里是uni-app内置的常用样式变量\r\n *\r\n * uni-app 官方扩展插件及插件市场（https://ext.dcloud.net.cn）上很多三方插件均使用了这些样式变量\r\n * 如果你是插件开发者，建议你使用scss预处理，并在插件代码中直接使用这些变量（无需 import 这个文件），方便用户通过搭积木的方式开发整体风格一致的App\r\n *\r\n */\r\n\r\n/**\r\n * 如果你是App开发者（插件使用者），你可以通过修改这些变量来定制自己的插件主题，实现自定义主题功能\r\n *\r\n * 如果你的项目同样使用了scss预处理，你也可以直接在你的 scss 代码中使用如下变量，同时无需 import 这个文件\r\n */\r\n\r\n/* 颜色变量 */\r\n\r\n/* 行为相关颜色 */\r\n$uni-color-primary: #007aff;\r\n$uni-color-success: #4cd964;\r\n$uni-color-warning: #f0ad4e;\r\n$uni-color-error: #dd524d;\r\n\r\n/* 文字基本颜色 */\r\n$uni-text-color: #333; // 基本色\r\n$uni-text-color-inverse: #fff; // 反色\r\n$uni-text-color-grey: #999; // 辅助灰色，如加载更多的提示信息\r\n$uni-text-color-placeholder: #808080;\r\n$uni-text-color-disable: #c0c0c0;\r\n\r\n/* 背景颜色 */\r\n$uni-bg-color: #fff;\r\n$uni-bg-color-grey: #f8f8f8;\r\n$uni-bg-color-hover: #f1f1f1; // 点击状态颜色\r\n$uni-bg-color-mask: rgba(0, 0, 0, 0.4); // 遮罩颜色\r\n\r\n/* 边框颜色 */\r\n$uni-border-color: #c8c7cc;\r\n\r\n/* 尺寸变量 */\r\n\r\n/* 文字尺寸 */\r\n$uni-font-size-sm: 12px;\r\n$uni-font-size-base: 14px;\r\n$uni-font-size-lg: 16;\r\n\r\n/* 图片尺寸 */\r\n$uni-img-size-sm: 20px;\r\n$uni-img-size-base: 26px;\r\n$uni-img-size-lg: 40px;\r\n\r\n/* Border Radius */\r\n$uni-border-radius-sm: 2px;\r\n$uni-border-radius-base: 3px;\r\n$uni-border-radius-lg: 6px;\r\n$uni-border-radius-circle: 50%;\r\n\r\n/* 水平间距 */\r\n$uni-spacing-row-sm: 5px;\r\n$uni-spacing-row-base: 10px;\r\n$uni-spacing-row-lg: 15px;\r\n\r\n/* 垂直间距 */\r\n$uni-spacing-col-sm: 4px;\r\n$uni-spacing-col-base: 8px;\r\n$uni-spacing-col-lg: 12px;\r\n\r\n/* 透明度 */\r\n$uni-opacity-disabled: 0.3; // 组件禁用态的透明度\r\n\r\n/* 文章场景相关 */\r\n$uni-color-title: #2c405a; // 文章标题颜色\r\n$uni-font-size-title: 20px;\r\n$uni-color-subtitle: #555; // 二级标题颜色\r\n$uni-font-size-subtitle: 18px;\r\n$uni-color-paragraph: #3f536e; // 文章段落颜色\r\n$uni-font-size-paragraph: 15px;"
  },
  {
    "path": "src/uni_modules/lime-echart/changelog.md",
    "content": "## 0.9.8（2024-12-20）\n- fix: 修复 APP 无法放大问题\n## 0.9.7（2024-12-02）\n- feat: uniapp 增加`landscape`，当`landscape`为`true`时旋转90deg达到横屏效果。\n- feat: 支持uniapp x 微信小程序\n## 0.9.6（2024-07-23）\n- fix: 修复 uni is not defined\n## 0.9.5（2024-07-19）\n- chore: 鸿蒙`measureText`为异步，异步字体不正常，使用模拟方式。\n## 0.9.4（2024-07-18）\n- chore: 更新文档\r\n## 0.9.3（2024-07-16）\n- feat: 鸿蒙 canvas 事件缺失，待官方修复，如何在鸿蒙使用请看文档`常见问题 vue3` \r\n## 0.9.2（2024-07-12）\n- chore: 删除多余文件\n## 0.9.1（2024-07-12）\n- fix: 修复 安卓5不显示图表问题\n## 0.9.0（2024-06-13）\n- chore: 合并nvue和uvue\n## 0.8.9（2024-05-19）\n- chore: 更新文档\n## 0.8.8（2024-05-13）\n- chore: 更新文档和uvue示例\n## 0.8.7（2024-04-26）\n- fix: uniapp x需要HBX 4.13以上\n## 0.8.6（2024-04-10）\n- feat: 支持 uniapp x ios\n## 0.8.5（2024-04-03）\n- fix: 修复 nvue `reset`传值不生效问题\n- feat: 支持 uniapp x web\n## 0.8.4（2024-01-27）\n- chore: 更新文档\n## 0.8.3（2024-01-21）\n- chore: 更新文档\n## 0.8.2（2024-01-21）\n- feat: 支持 `uvue`\n## 0.8.1（2023-08-24）\n- fix: app 的`touch`事件为`object` 导致无法显示 `tooltip`\n## 0.8.0（2023-08-22）\n- fix: 离屏 报错问题\n- fix: 微信小程序PC无法使用事件\n- chore: 更新文档\n## 0.7.9（2023-07-29）\n- chore: 更新文档\n## 0.7.8（2023-07-29）\n- fix: 离屏 报错问题\n## 0.7.7（2023-07-27）\n- chore: 更新文档\n- chore: lime-echart 里的示例使用自定tooltips\n- feat: 对支持离屏的使用离屏创建(微信、字节、支付宝)\n## 0.7.6（2023-06-30）\n- fix: vue3 报`width`的错\n## 0.7.5（2023-05-25）\n- chore: 更新文档 和 demo, 使用`lime-echart`这个标签即可查看示例\n## 0.7.4（2023-05-22）\n- chore: 增加关于钉钉小程序上传时提示安全问题的说明及修改建议\n## 0.7.3（2023-05-16）\n- chore: 更新 vue3 非微信小程序平台可能缺少`wx`的说明\n## 0.7.2（2023-05-16）\n- chore: 更新 vue3 非微信小程序平台的可以缺少`wx`的说明\n## 0.7.1（2023-04-26）\n- chore: 更新demo，使用`lime-echart`这个标签即可查看示例\n- chore：微信小程序的`tooltip`文字有阴影，怀疑是微信的锅，临时解决方法是`tooltip.shadowBlur = 0`\n## 0.7.0（2023-04-24）\n- fix: 修复`setAttribute is not a function`\n## 0.6.9（2023-04-15）\n- chore: 更新文档，vue3请使用echarts esm的包\n## 0.6.8（2023-03-22）\n- feat: mac pc无法使用canvas 2d\n## 0.6.7（2023-03-17）\n- feat: 更新文档\n## 0.6.6（2023-03-17）\n- feat: 微信小程序PC已经支持canvas 2d，故去掉判断PC\n## 0.6.5（2022-11-03）\n- fix: 某些手机touches为对象，导致无法交互。\n## 0.6.4（2022-10-28）\n- fix: 优化点击事件的触发条件\n## 0.6.3（2022-10-26）\n- fix: 修复 dataZoom 拖动问题\n## 0.6.2（2022-10-23）\n- fix: 修复 飞书小程序 尺寸问题\n## 0.6.1（2022-10-19）\n- fix: 修复 PC mousewheel 事件 鼠标位置不准确的BUG，不兼容火狐！\n- feat: showLoading 增加传参\n## 0.6.0（2022-09-16）\n- feat: 增加PC的mousewheel事件\n## 0.5.4（2022-09-16）\n- fix: 修复 nvue 动态数据不显示问题\n## 0.5.3（2022-09-16）\n- feat: 增加enableHover属性， 在PC端时当鼠标进入显示tooltip，不必按下。\n- chore: 更新文档\n## 0.5.2（2022-09-16）\n- feat: 增加enableHover属性， 在PC端时当鼠标进入显示tooltip，不必按下。\n## 0.5.1（2022-09-16）\n- fix: 修复nvue报错\n## 0.5.0（2022-09-15）\n- feat: init(echarts, theme?:string, opts?:{}, callback: function(chart))\n## 0.4.8（2022-09-11）\n- feat: 增加 @finished\n## 0.4.7（2022-08-24）\n- chore: 去掉 stylus\n## 0.4.6（2022-08-24）\n- feat: 增加 beforeDelay\n## 0.4.5（2022-08-12）\n- chore: 更新文档\n## 0.4.4（2022-08-12）\n- fix: 修复 resize 无参数时报错\n## 0.4.3（2022-08-07）\n# 评论有说本插件对新手不友好，让我做不好就不要发出来。 还有的说跟官网一样，发出来做什么，给我整无语了。\n# 所以在此提醒一下准备要下载的你，如果你从未使用过 echarts 请不要下载 或 谨慎下载。\n# 如果你确认要下载，麻烦看完文档。还有请注意插件是让echarts在uniapp能运行，API 配置请自行去官网查阅!\n# 如果你不会echarts 但又需要图表，市场上有个很优秀的图表插件 uchart 你可以去使用这款插件，uchart的作者人很好，也热情。\n# 每个人都有自己的本职工作，如果你能力强可以自行兼容，如果使用了他人的插件也麻烦尊重他人的成果和劳动时间。谢谢。\n# 为了心情愉悦，本人已经使用插件屏蔽差评。\n- chore: 更新文档\n## 0.4.2（2022-07-20）\n- feat: 增加 resize\n## 0.4.1（2022-06-07）\n- fix: 修复 canvasToTempFilePath 不生效问题\n## 0.4.0（2022-06-04）\n- chore 为了词云 增加一个canvas 标签\n- 词云下载地址[echart-wordcloud](https://ext.dcloud.net.cn/plugin?id=8430)\n## 0.3.9（2022-06-02）\n- chore: 更新文档\n- tips: lines 不支持 `trailLength`\r\n## 0.3.8（2022-05-31）\n- fix: 修复 因mouse事件冲突tooltip跳动问题\n## 0.3.7（2022-05-26）\r\n- chore: 更新文档\r\n- chore: 设置默认宽高300px\r\n- fix: 修复 vue3 微信小程序 拖影BUG\r\n- chore: 支持PC\r\n## 0.3.5（2022-04-28）\r\n- chore: 更新使用方式\r\n- 🔔 必须使用hbuilderx 3.4.8-alpha以上\r\n## 0.3.4（2021-08-03）\r\n- chore: 增加 setOption的参数值\r\n## 0.3.3（2021-07-22）\r\n- fix: 修复 径向渐变报错的问题\r\n## 0.3.2（2021-07-09）\r\n- chore: 统一命名规范，无须主动引入组件\r\n## [代码示例站点1](https://limeui.qcoon.cn/#/echart-example)\r\n## [代码示例站点2](http://liangei.gitee.io/limeui/#/echart-example)\r\n## 0.3.1（2021-06-21）\r\n- fix: 修复 app-nvue ios is-enable 无效的问题\r\n## [代码示例站点1](https://limeui.qcoon.cn/#/echart-example)\r\n## [代码示例站点2](http://liangei.gitee.io/limeui/#/echart-example)\r\n## 0.3.0（2021-06-14）\r\n- fix: 修复 头条系小程序 2d 报 JSON.stringify 的问题\r\n- 目前 头条系小程序 2d 无法在开发工具上预览，划动图表页面无法滚动，axisLabel 字体颜色无法更改，建议使用非2d。\r\n## 0.2.9（2021-06-06）\r\n- fix: 修复 头条系小程序 2d 放大的BUG \r\n- 头条系小程序 2d 无法在开发工具上预览，也存在划动图表页面无法滚动的问题。\r\n## [代码示例：http://liangei.gitee.io/limeui/#/echart-example](http://liangei.gitee.io/limeui/#/echart-example)\r\n## 0.2.8（2021-05-19）\r\n- fix: 修复 微信小程序 PC 显示过大的问题\r\n## 0.2.7（2021-05-19）\r\n- fix: 修复 微信小程序 PC 不显示问题\r\n## [代码示例：http://liangei.gitee.io/limeui/#/echart-example](http://liangei.gitee.io/limeui/#/echart-example)\r\n## 0.2.6（2021-05-14）\r\n- feat: 支持 `image`\r\n- feat: props 增加 `ec.clear`，更新时是否先删除图表样式 \r\n- feat: props 增加 `isDisableScroll` ，触摸图表时是否禁止页面滚动\r\n- feat: props 增加 `webviewStyles` ，webview 的样式, 仅nvue有效\r\n## 0.2.5（2021-05-13）\r\n- docs: 插件用到了css 预编译器 [stylus](https://ext.dcloud.net.cn/plugin?name=compile-stylus) 请安装它\r\n## 0.2.4（2021-05-12）\r\n- fix: 修复 百度平台 多个图表ctx 和 渐变色 bug\r\n- ## [代码示例：http://liangei.gitee.io/limeui/#/echart-example](http://liangei.gitee.io/limeui/#/echart-example)\r\n## 0.2.3（2021-05-10）\r\n- feat: 增加 `canvasToTempFilePath` 方法，用于生成图片\r\n```js\r\nthis.$refs.chart.canvasToTempFilePath({success: (res) => {\r\n\tconsole.log('tempFilePath:', res.tempFilePath)\r\n}})\r\n```\r\n## 0.2.2（2021-05-10）\r\n- feat: 增加 `dispose` 方法，用于销毁实例\r\n- feat: 增加 `isClickable` 是否派发点击\r\n- feat: 实验性的支持 `nvue` 使用要慎重考虑\r\n- ## [代码示例：http://liangei.gitee.io/limeui/#/echart-example](http://liangei.gitee.io/limeui/#/echart-example)\r\n## 0.2.1（2021-05-06）\r\n- fix：修复 微信小程序 json 报错\r\n- chore: `reset` 更改为 `setChart`\r\n- feat: 增加 `isEnable` 开启初始化 启用这个后 无须再使用`init`方法\r\n```html\r\n<l-echart ref=\"chart\" is-enable />\r\n```\r\n```js\r\n// 显示加载\r\nthis.$refs.chart.showLoading()\r\n// 使用实例回调\r\nthis.$refs.chart.setChart(chart => ...code)\r\n// 直接设置图表配置\r\nthis.$refs.chart.setOption(data)\r\n```\r\n## 0.2.0（2021-05-05）\r\n- fix：修复 头条 百度 偏移的问题\r\n- docs: 更新文档\r\n## [代码示例：http://liangei.gitee.io/limeui/#/echart-example](http://liangei.gitee.io/limeui/#/echart-example)\r\n## 0.1.0（2021-05-02）\r\n- chore:  第一次上传，基本全端兼容，使用方法与官网一致。\r\n- 已知BUG：非2d 无法使用背景色，已反馈官方\r\n- 已知BUG：头条 百度 有许些偏移\r\n- 后期计划：兼容nvue\r\n"
  },
  {
    "path": "src/uni_modules/lime-echart/components/l-echart/canvas.js",
    "content": "import {getDeviceInfo} from './utils';\r\n\r\nconst cacheChart = {}\r\nconst fontSizeReg = /([\\d\\.]+)px/;\r\nclass EventEmit {\n\tconstructor() {\n\t\tthis.__events = {};\n\t}\n\ton(type, listener) {\n\t\tif (!type || !listener) {\n\t\t\treturn;\n\t\t}\n\t\tconst events = this.__events[type] || [];\n\t\tevents.push(listener);\n\t\tthis.__events[type] = events;\n\t}\n\temit(type, e) {\n\t\tif (type.constructor === Object) {\n\t\t\te = type;\n\t\t\ttype = e && e.type;\n\t\t}\n\t\tif (!type) {\n\t\t\treturn;\n\t\t}\n\t\tconst events = this.__events[type];\n\t\tif (!events || !events.length) {\n\t\t\treturn;\n\t\t}\n\t\tevents.forEach((listener) => {\n\t\t\tlistener.call(this, e);\n\t\t});\n\t}\n\toff(type, listener) {\n\t\tconst __events = this.__events;\n\t\tconst events = __events[type];\n\t\tif (!events || !events.length) {\n\t\t\treturn;\n\t\t}\n\t\tif (!listener) {\n\t\t\tdelete __events[type];\n\t\t\treturn;\n\t\t}\n\t\tfor (let i = 0, len = events.length; i < len; i++) {\n\t\t\tif (events[i] === listener) {\n\t\t\t\tevents.splice(i, 1);\n\t\t\t\ti--;\n\t\t\t}\n\t\t}\n\t}\n}\r\nclass Image {\r\n\tconstructor() {\r\n\t\tthis.currentSrc = null\r\n\t\tthis.naturalHeight = 0\r\n\t\tthis.naturalWidth = 0\r\n\t\tthis.width = 0\r\n\t\tthis.height = 0\r\n\t\tthis.tagName = 'IMG'\r\n\t}\r\n\tset src(src) {\r\n\t\tthis.currentSrc = src\r\n\t\tuni.getImageInfo({\r\n\t\t\tsrc,\r\n\t\t\tsuccess: (res) => {\r\n\t\t\t\tthis.naturalWidth = this.width = res.width\r\n\t\t\t\tthis.naturalHeight = this.height = res.height\r\n\t\t\t\tthis.onload()\r\n\t\t\t},\r\n\t\t\tfail: () => {\r\n\t\t\t\tthis.onerror()\r\n\t\t\t}\r\n\t\t})\r\n\t}\r\n\tget src() {\r\n\t\treturn this.currentSrc\r\n\t}\r\n}\r\nclass OffscreenCanvas {\r\n\tconstructor(ctx, com, canvasId) {\r\n\t\tthis.tagName = 'canvas'\r\n\t\tthis.com = com\r\n\t\tthis.canvasId = canvasId\r\n\t\tthis.ctx = ctx\r\n\t}\r\n\tset width(w) {\r\n\t\tthis.com.offscreenWidth = w\r\n\t}\r\n\tset height(h) {\r\n\t\tthis.com.offscreenHeight = h\r\n\t}\r\n\tget width() {\r\n\t\treturn this.com.offscreenWidth || 0\r\n\t}\r\n\tget height() {\r\n\t\treturn this.com.offscreenHeight || 0\r\n\t}\r\n\tgetContext(type) {\r\n\t\treturn this.ctx\r\n\t}\r\n\tgetImageData() {\r\n\t\treturn new Promise((resolve, reject) => {\r\n\t\t\tthis.com.$nextTick(() => {\r\n\t\t\t\tuni.canvasGetImageData({\r\n\t\t\t\t\tx:0,\r\n\t\t\t\t\ty:0,\r\n\t\t\t\t\twidth: this.com.offscreenWidth,\r\n\t\t\t\t\theight: this.com.offscreenHeight,\r\n\t\t\t\t\tcanvasId: this.canvasId,\r\n\t\t\t\t\tsuccess: (res) => {\r\n\t\t\t\t\t\tresolve(res)\r\n\t\t\t\t\t},\r\n\t\t\t\t\tfail: (err) => {\r\n\t\t\t\t\t\treject(err)\r\n\t\t\t\t\t},\r\n\t\t\t\t}, this.com)\r\n\t\t\t})\r\n\t\t})\r\n\t}\r\n}\r\nexport class Canvas {\r\n\tconstructor(ctx, com, isNew, canvasNode={}) {\r\n\t\tcacheChart[com.canvasId] = {ctx}\r\n\t\tthis.canvasId = com.canvasId;\r\n\t\tthis.chart = null;\r\n\t\tthis.isNew = isNew\r\n\t\tthis.tagName = 'canvas'\r\n\t\tthis.canvasNode = canvasNode;\r\n\t\tthis.com = com;\r\n\t\tif (!isNew) {\r\n\t\t\tthis._initStyle(ctx)\r\n\t\t}\r\n\t\tthis._initEvent();\r\n\t\tthis._ee = new EventEmit()\r\n\t}\r\n\tgetContext(type) {\r\n\t\tif (type === '2d') {\r\n\t\t\treturn this.ctx;\r\n\t\t}\r\n\t}\r\n\tsetAttribute(key, value) {\r\n\t\tif(key === 'aria-label') {\r\n\t\t\tthis.com['ariaLabel'] = value\r\n\t\t}\r\n\t}\r\n\tsetChart(chart) {\r\n\t\tthis.chart = chart;\r\n\t}\r\n\tcreateOffscreenCanvas(param){\r\n\t\tif(!this.children) {\r\n\t\t\tthis.com.isOffscreenCanvas = true\r\n\t\t\tthis.com.offscreenWidth = param.width||300\r\n\t\t\tthis.com.offscreenHeight = param.height||300\r\n\t\t\tconst com = this.com\r\n\t\t\tconst canvasId = this.com.offscreenCanvasId\r\n\t\t\tconst context = uni.createCanvasContext(canvasId, this.com)\r\n\t\t\tthis._initStyle(context)\r\n\t\t\tthis.children = new OffscreenCanvas(context, com, canvasId)\r\n\t\t} \r\n\t\treturn this.children\r\n\t}\r\n\tappendChild(child) {\r\n\t\tconsole.log('child', child)\r\n\t}\r\n\tdispatchEvent(type, e) {\r\n\t\tif(typeof type == 'object') {\r\n\t\t\tthis._ee.emit(type.type, type);\r\n\t\t} else {\r\n\t\t\tthis._ee.emit(type, e);\r\n\t\t}\r\n\t\treturn true\r\n\t}\r\n\tattachEvent() {\r\n\t}\r\n\tdetachEvent() {\r\n\t}\r\n\taddEventListener(type, listener) {\r\n\t\tthis._ee.on(type, listener)\r\n\t}\r\n\tremoveEventListener(type, listener) {\r\n\t\tthis._ee.off(type, listener)\r\n\t}\r\n\t_initCanvas(zrender, ctx) {\r\n\t\t// zrender.util.getContext = function() {\r\n\t\t// \treturn ctx;\r\n\t\t// };\r\n\t\t// zrender.util.$override('measureText', function(text, font) {\r\n\t\t// \tctx.font = font || '12px sans-serif';\r\n\t\t// \treturn ctx.measureText(text, font);\r\n\t\t// });\r\n\t}\r\n\t_initStyle(ctx, child) {\r\n\t\tconst styles = [\r\n\t\t\t'fillStyle',\r\n\t\t\t'strokeStyle',\r\n\t\t\t'fontSize',\r\n\t\t\t'globalAlpha',\r\n\t\t\t'opacity',\r\n\t\t\t'textAlign',\r\n\t\t\t'textBaseline',\r\n\t\t\t'shadow',\r\n\t\t\t'lineWidth',\r\n\t\t\t'lineCap',\r\n\t\t\t'lineJoin',\r\n\t\t\t'lineDash',\r\n\t\t\t'miterLimit',\r\n\t\t\t// #ifdef H5\r\n\t\t\t'font',\r\n\t\t\t// #endif\r\n\t\t];\r\n\t\tconst colorReg = /#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])\\b/g;\r\n\t\tstyles.forEach(style => {\r\n\t\t\tObject.defineProperty(ctx, style, {\r\n\t\t\t\tset: value => {\r\n\t\t\t\t\t// #ifdef H5\r\n\t\t\t\t\tif (style === 'font' && fontSizeReg.test(value)) {\r\n\t\t\t\t\t\tconst match = fontSizeReg.exec(value);\r\n\t\t\t\t\t\tctx.setFontSize(match[1]);\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t// #endif\r\n\t\t\t\t\t\r\n\t\t\t\t\tif (style === 'opacity') {\r\n\t\t\t\t\t\tctx.setGlobalAlpha(value)\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (style !== 'fillStyle' && style !== 'strokeStyle' || value !== 'none' && value !== null) {\r\n\t\t\t\t\t\t// #ifdef H5 || APP-PLUS || MP-BAIDU\r\n\t\t\t\t\t\tif(typeof value == 'object') {\r\n\t\t\t\t\t\t\tif (value.hasOwnProperty('colorStop') || value.hasOwnProperty('colors')) {\r\n\t\t\t\t\t\t\t\tctx['set' + style.charAt(0).toUpperCase() + style.slice(1)](value);\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\treturn\r\n\t\t\t\t\t\t} \r\n\t\t\t\t\t\t// #endif\r\n\t\t\t\t\t\t// #ifdef MP-TOUTIAO\r\n\t\t\t\t\t\tif(colorReg.test(value)) {\r\n\t\t\t\t\t\t\tvalue = value.replace(colorReg, '#$1$1$2$2$3$3')\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\t// #endif\r\n\t\t\t\t\t\tctx['set' + style.charAt(0).toUpperCase() + style.slice(1)](value);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t});\r\n\t\tif(!this.isNew && !child) {\r\n\t\t\tctx.uniDrawImage = ctx.drawImage\r\n\t\t\tctx.drawImage = (...a) => {\r\n\t\t\t\ta[0] = a[0].src\r\n\t\t\t\tctx.uniDrawImage(...a)\r\n\t\t\t}\r\n\t\t}\r\n\t\tif(!ctx.createRadialGradient) {\r\n\t\t\tctx.createRadialGradient = function() {\r\n\t\t\t\treturn ctx.createCircularGradient(...[...arguments].slice(-3))\r\n\t\t\t};\r\n\t\t}\r\n\t\t// 字节不支持\r\n\t\tif (!ctx.strokeText) {\r\n\t\t\tctx.strokeText = (...a) => {\r\n\t\t\t\tctx.fillText(...a)\r\n\t\t\t}\r\n\t\t}\r\n\t\t\r\n\t\t// 钉钉不支持 , 鸿蒙是异步\r\n\t\tif (!ctx.measureText || getDeviceInfo().osName == 'harmonyos') {\r\n\t\t\tctx._measureText = ctx.measureText\r\n\t\t\tconst strLen = (str) => {\r\n\t\t\t\tlet len = 0;\r\n\t\t\t\tfor (let i = 0; i < str.length; i++) {\r\n\t\t\t\t\tif (str.charCodeAt(i) > 0 && str.charCodeAt(i) < 128) {\r\n\t\t\t\t\t\tlen++;\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tlen += 2;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\treturn len;\r\n\t\t\t}\r\n\t\t\tctx.measureText = (text, font) => {\r\n\t\t\t\tlet fontSize = ctx?.state?.fontSize || 12;\r\n\t\t\t\tif (font) {\r\n\t\t\t\t\tfontSize = parseInt(font.match(/([\\d\\.]+)px/)[1])\r\n\t\t\t\t}\r\n\t\t\t\tfontSize /= 2;\r\n\t\t\t\tlet isBold = fontSize >= 16;\r\n\t\t\t\tconst widthFactor = isBold ? 1.3 : 1;\r\n\t\t\t\t// ctx._measureText(text, (res) => {})\r\n\t\t\t\treturn {\r\n\t\t\t\t\twidth: strLen(text) * fontSize * widthFactor\r\n\t\t\t\t};\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t_initEvent(e) {\r\n\t\tthis.event = {};\r\n\t\tconst eventNames = [{\r\n\t\t\twxName: 'touchStart',\r\n\t\t\tecName: 'mousedown'\r\n\t\t}, {\r\n\t\t\twxName: 'touchMove',\r\n\t\t\tecName: 'mousemove'\r\n\t\t}, {\r\n\t\t\twxName: 'touchEnd',\r\n\t\t\tecName: 'mouseup'\r\n\t\t}, {\r\n\t\t\twxName: 'touchEnd',\r\n\t\t\tecName: 'click'\r\n\t\t}];\r\n\r\n\t\teventNames.forEach(name => {\r\n\t\t\tthis.event[name.wxName] = e => {\r\n\t\t\t\tconst touch = e.touches[0];\r\n\t\t\t\tthis.chart.getZr().handler.dispatch(name.ecName, {\r\n\t\t\t\t\tzrX: name.wxName === 'tap' ? touch.clientX : touch.x,\r\n\t\t\t\t\tzrY: name.wxName === 'tap' ? touch.clientY : touch.y\r\n\t\t\t\t});\r\n\t\t\t};\r\n\t\t});\r\n\t}\r\n\r\n\tset width(w) {\r\n\t\tthis.canvasNode.width = w\r\n\t}\r\n\tset height(h) {\r\n\t\tthis.canvasNode.height = h\r\n\t}\r\n\r\n\tget width() {\r\n\t\treturn this.canvasNode.width || 0\r\n\t}\r\n\tget height() {\r\n\t\treturn this.canvasNode.height || 0\r\n\t}\r\n\tget ctx() {\r\n\t\treturn cacheChart[this.canvasId]['ctx'] || null\r\n\t}\r\n\tset chart(chart) {\r\n\t\tcacheChart[this.canvasId]['chart'] = chart\r\n\t}\r\n\tget chart() {\r\n\t\treturn cacheChart[this.canvasId]['chart'] || null\r\n\t}\r\n}\r\n\r\nexport function dispatch(name, {x,y, wheelDelta}) {\r\n\tthis.dispatch(name, {\r\n\t\tzrX: x,\r\n\t\tzrY: y,\r\n\t\tzrDelta: wheelDelta,\r\n\t\tpreventDefault: () => {},\r\n\t\tstopPropagation: () =>{}\r\n\t});\r\n}\r\nexport function setCanvasCreator(echarts, {canvas, node}) {\r\n\t// echarts.setCanvasCreator(() => canvas);\r\n\tif(echarts && !echarts.registerPreprocessor) {\r\n\t\treturn console.warn('echarts 版本不对或未传入echarts，vue3请使用esm格式')\r\n\t}\r\n\techarts.registerPreprocessor(option => {\r\n\t\tif (option && option.series) {\r\n\t\t\tif (option.series.length > 0) {\r\n\t\t\t\toption.series.forEach(series => {\r\n\t\t\t\t\tseries.progressive = 0;\r\n\t\t\t\t});\r\n\t\t\t} else if (typeof option.series === 'object') {\r\n\t\t\t\toption.series.progressive = 0;\r\n\t\t\t}\r\n\t\t}\r\n\t});\r\n\tfunction loadImage(src, onload, onerror) {\r\n\t\tlet img = null\r\n\t\tif(node && node.createImage) {\r\n\t\t\timg = node.createImage()\r\n\t\t\timg.onload = onload.bind(img);\r\n\t\t\timg.onerror = onerror.bind(img);\r\n\t\t\timg.src = src;\r\n\t\t\treturn img\r\n\t\t} else {\r\n\t\t\timg = new Image()\r\n\t\t\timg.onload = onload.bind(img)\r\n\t\t\timg.onerror = onerror.bind(img);\r\n\t\t\timg.src = src\r\n\t\t\treturn img\r\n\t\t}\r\n\t}\r\n\tif(echarts.setPlatformAPI) {\r\n\t\techarts.setPlatformAPI({\r\n\t\t\tloadImage: canvas.setChart ? loadImage : null,\r\n\t\t\tcreateCanvas(){\r\n\t\t\t\tconst key = 'createOffscreenCanvas'\r\n\t\t\t\treturn uni.canIUse(key) && uni[key] ? uni[key]({type: '2d'}) : canvas\r\n\t\t\t}\r\n\t\t})\r\n\t}\r\n}"
  },
  {
    "path": "src/uni_modules/lime-echart/components/l-echart/l-echart.uvue",
    "content": "<template>\r\n\t<!-- #ifdef APP -->\r\n\t<web-view class=\"lime-echart\" ref=\"chartRef\" @load=\"loaded\" :style=\"[customStyle]\" \r\n\t\t:webview-styles=\"[webviewStyles]\" src=\"/uni_modules/lime-echart/static/uvue.html?v=10112\">\r\n\t</web-view>\r\n\t<!-- #endif -->\r\n\t<!-- #ifdef H5 -->\r\n\t<div class=\"lime-echart\" ref=\"chartRef\"></div>\r\n\t<!-- #endif -->\r\n\t<!-- #ifndef H5 || APP-->\r\n\t<canvas class=\"lime-echart\" :id=\"canvasid\" :canvas-id=\"canvasid\" \r\n\t\t@touchstart=\"touchstart\"\r\n\t\t@touchmove=\"touchmove\"\r\n\t\t@touchend=\"touchend\">\r\n\t</canvas>\r\n\t<!-- #endif -->\r\n</template>\r\n\r\n<script lang=\"uts\" setup>\r\n\t// @ts-nocheck\r\n\timport { getCurrentInstance, nextTick } from \"vue\";\n\timport { Echarts } from './uvue';\r\n\t// #ifdef WEB\r\n\timport { dispatch } from './canvas';\r\n\t// #endif\r\n\t// #ifndef APP || WEB\r\n\timport {Canvas, setCanvasCreator, dispatch} from './canvas';\r\n\timport {wrapTouch, convertTouchesToArray, devicePixelRatio ,sleep, canIUseCanvas2d, getRect} from './utils';\r\n\t// #endif\r\n\ttype EchartsResolve = (value : Echarts) => void\r\n\tdefineOptions({\r\n\t\tname: 'l-echart'\r\n\t})\r\n\tconst emits = defineEmits(['finished'])\r\n\tconst props = defineProps({\r\n\t\t// #ifdef APP\r\n\t\twebviewStyles: {\r\n\t\t\ttype: Object\r\n\t\t},\r\n\t\tcustomStyle: {\r\n\t\t\ttype: Object\r\n\t\t},\r\n\t\t// #endif\r\n\t\t// #ifndef APP\r\n\t\twebviewStyles: {\r\n\t\t\ttype: Object\r\n\t\t},\r\n\t\tcustomStyle: {\r\n\t\t\ttype: [String, Object]\r\n\t\t},\r\n\t\t// #endif\r\n\t\tisDisableScroll: {\r\n\t\t\ttype: Boolean,\r\n\t\t\tdefault: false\r\n\t\t},\r\n\t\tisClickable: {\r\n\t\t\ttype: Boolean,\r\n\t\t\tdefault: true\r\n\t\t},\r\n\t\tenableHover: {\r\n\t\t\ttype: Boolean,\r\n\t\t\tdefault: false\r\n\t\t},\r\n\t\tbeforeDelay: {\r\n\t\t\ttype: Number,\r\n\t\t\tdefault: 30\r\n\t\t}\r\n\t})\r\n\tconst instance = getCurrentInstance()!;\r\n\tconst canvasid = `lime-echart-${instance.uid}`\r\n\tconst finished = ref(false)\r\n\tconst map = [] as EchartsResolve[]\r\n\tconst callbackMap = [] as EchartsResolve[]\r\n\t// let context = null as UniWebViewElement | null\r\n\tlet chart = null as Echarts | null\r\n\tlet chartRef = ref<UniWebViewElement | null>(null)\r\n\t\r\n\tconst trigger = () => {\r\n\t\t// #ifdef APP\r\n\t\tif (finished.value) {\r\n\t\t\tif (chart == null) {\r\n\t\t\t\tchart = new Echarts(chartRef.value!)\r\n\t\t\t}\r\n\t\t\twhile (map.length > 0) {\r\n\t\t\t\tconst resolve = map.pop() as EchartsResolve\r\n\t\t\t\tresolve(chart!)\r\n\t\t\t}\r\n\t\t}\r\n\t\t// #endif\r\n\t\t// #ifndef APP\r\n\t\twhile (map.length > 0) {\r\n\t\t\tif(chart != null){\r\n\t\t\t\tconst resolve = map.pop() as EchartsResolve\r\n\t\t\t\tresolve(chart!)\r\n\t\t\t}\r\n\t\t}\r\n\t\t// #endif\r\n\t\t\r\n\t\tif(chart != null){\r\n\t\t\twhile(callbackMap.length > 0){\r\n\t\t\t\tconst callback = callbackMap.pop() as EchartsResolve\r\n\t\t\t\tcallback(chart!)\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\t// #ifdef APP\r\n\tconst loaded = (event : UniWebViewLoadEvent) => {\r\n\t\tevent.stopPropagation()\r\n\t\tevent.preventDefault()\r\n\t\tfinished.value = true\r\n\t\ttrigger()\r\n\t\temits('finished')\r\n\t}\r\n\t// #endif\r\n\t\r\n\t\r\n\tconst _next = () : boolean => {\r\n\t\tif (chart == null) {\r\n\t\t\tconsole.warn(`组件还未初始化，请先使用 init`)\r\n\t\t\treturn true\r\n\t\t}\r\n\t\treturn false\r\n\t}\r\n\tconst setOption = (option : UTSJSONObject) => {\r\n\t\tif (_next()) return\r\n\t\tchart!.setOption(option);\r\n\t}\r\n\tconst showLoading = () => {\r\n\t\tif (_next()) return\r\n\t\tchart!.showLoading();\r\n\t}\r\n\tconst hideLoading = () => {\r\n\t\tif (_next()) return\r\n\t\tchart!.hideLoading();\r\n\t}\r\n\tconst clear = () => {\r\n\t\tif (_next()) return\r\n\t\tchart!.clear();\r\n\t}\r\n\tconst dispose = () => {\r\n\t\tif (_next()) return\r\n\t\tchart!.dispose();\r\n\t}\r\n\tconst resize = (size : UTSJSONObject) => {\r\n\t\tif (_next()) return\r\n\t\tchart!.resize(size);\r\n\t}\r\n\tconst canvasToTempFilePath = (opt : UTSJSONObject) => {\r\n\t\tif (_next()) return\r\n\t\tchart!.canvasToTempFilePath(opt);\r\n\t}\r\n\t\r\n\t// #ifdef APP\r\n\tfunction init(callback : ((chart : Echarts) => void) | null) : Promise<Echarts> {\r\n\r\n\t\tif(callback!=null){\r\n\t\t\tcallbackMap.push(callback)\r\n\t\t}\r\n\t\treturn new Promise<Echarts>((resolve) => {\r\n\t\t\tmap.push(resolve)\r\n\t\t\ttrigger()\r\n\t\t})\r\n\t}\r\n\t// #endif\r\n\t// #ifndef APP \r\n\t// #ifndef WEB \r\n\tlet use2dCanvas = canIUseCanvas2d()\r\n\tconst getContext = async () =>{\r\n\t\treturn getRect(`#${canvasid}`, {context: instance.proxy!, type: use2dCanvas ? 'fields': 'boundingClientRect'}).then(res => {\r\n\t\t\tif(res) {\r\n\t\t\t\tlet dpr = uni.getWindowInfo().pixelRatio\r\n\t\t\t\tlet {width, height, node} = res\r\n\t\t\t\tlet canvas;\r\n\t\t\t\tif(node) {\r\n\t\t\t\t\tconst ctx = node.getContext('2d');\r\n\t\t\t\t\tcanvas = new Canvas(ctx, instance.proxy, true, node);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tconst ctx = uni.createCanvasContext(canvasid, instance.proxy);\r\n\t\t\t\t\tcanvas =  new Canvas(ctx, instance.proxy, false);\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t\treturn { canvas, width, height, devicePixelRatio: dpr, node };\r\n\t\t\t} else {\r\n\t\t\t\treturn {}\r\n\t\t\t}\r\n\t\t})\r\n\t}\r\n\t// #endif\r\n\tconst getTouch = (e) => {\r\n\t\tconst touches = e.touches[0]\r\n\t\t// #ifdef WEB\r\n\t\tconst rect = chart!.getZr().dom.getBoundingClientRect();\r\n\t\tconst touch = {\r\n\t\t\tx: touches.clientX - rect.left,\r\n\t\t\ty: touches.clientY - rect.top\r\n\t\t}\r\n\t\t// #endif\r\n\t\t// #ifndef WEB\r\n\t\tconst touch = {\r\n\t\t\tx: touches.x,\r\n\t\t\ty: touches.y\r\n\t\t}\r\n\t\t// #endif\r\n\t\treturn touch\r\n\t}\r\n\tconst touchstart = (e) => {\r\n\t\tif(chart == null) return\r\n\t\tconst handler = chart.getZr().handler;\r\n\t\tconst touch = getTouch(e)\r\n\t\tdispatch.call(handler, 'mousedown', touch)\r\n\t\tdispatch.call(handler, 'click', touch)\r\n\t}\r\n\tconst touchmove = (e) => {\r\n\t\tif(chart == null) return\r\n\t\tconst handler = chart.getZr().handler;\r\n\t\tconst touch = getTouch(e)\r\n\t\tdispatch.call(handler, 'mousemove', touch)\r\n\t\t// const rect = chart.getZr().dom.getBoundingClientRect()\r\n\t\t// handler.dispatch('mousemove', {\r\n\t\t// \tzrX: e.touches[0].clientX - rect.left,\r\n\t\t// \tzrY: e.touches[0].clientY - rect.top\r\n\t\t// })\r\n\t}\r\n\tconst touchend = (e) => {\r\n\t\tif(chart == null) return\r\n\t\tconst handler = chart.getZr().handler;\r\n\t\t\r\n\t\tconst touch = {\r\n\t\t\tx: 999999999,\r\n\t\t\ty: 999999999\r\n\t\t}\r\n\t\t\r\n\t\tdispatch.call(handler, 'mousemove', touch)\r\n\t\tdispatch.call(handler, 'touchend', touch)\r\n\t\t\r\n\t}\r\n\tasync function init(echarts: any, ...args: any[]): Promise<Echarts>{\r\n\t\tif(echarts == null){\r\n\t\t\tconsole.error('请确保已经引入了 ECharts 库');\r\n\t\t\treturn Promise.reject('请确保已经引入了 ECharts 库');\r\n\t\t}\r\n\t\tlet theme:string|null=null\r\n\t\tlet opts={}\r\n\t\tlet callback:Function|null=null;\r\n\t\t\r\n\t\targs.forEach(item =>{\r\n\t\t\tif(typeof item === 'function') {\r\n\t\t\t\tcallback = item\r\n\t\t\t} else if(['string'].includes(typeof item)){\r\n\t\t\t\ttheme = item\r\n\t\t\t} else if(typeof item === 'object'){\r\n\t\t\t\topts = item\r\n\t\t\t}\r\n\t\t})\r\n\t\t\r\n\t\t// #ifdef WEB\r\n\t\tchart = echarts.init(chartRef.value, theme, opts)\r\n\t\twindow.addEventListener('touchstart', touchstart)\r\n\t\twindow.addEventListener('touchmove', touchmove)\r\n\t\twindow.addEventListener('touchend', touchend)\r\n\t\t// #endif\r\n\t\t\r\n\t\t// #ifndef WEB\r\n\t\tlet config = await getContext();\r\n\t\tsetCanvasCreator(echarts, config)\r\n\t\tchart = echarts.init(config.canvas, theme, Object.assign({}, config, opts))\r\n\t\t// #endif\r\n\t\tconsole.log('chart', chart)\r\n\t\tif(callback!=null && typeof callback == 'function'){\r\n\t\t\tcallbackMap.push(callback)\r\n\t\t}\r\n\t\treturn new Promise<Echarts>((resolve) => {\r\n\t\t\tmap.push(resolve)\r\n\t\t\ttrigger()\r\n\t\t})\r\n\t}\r\n\tonMounted(()=>{\r\n\t\tnextTick(()=>{\r\n\t\t\tfinished.value = true\r\n\t\t\ttrigger()\r\n\t\t\temits('finished')\r\n\t\t})\r\n\t})\r\n\tonUnmounted(()=>{\r\n\t\t// #ifdef WEB\r\n\t\twindow.removeEventListener('touchstart', touchstart)\r\n\t\twindow.removeEventListener('touchmove', touchmove)\r\n\t\twindow.removeEventListener('touchend', touchend)\r\n\t\t// #endif\r\n\t})\r\n\t// #endif\r\n\t\r\n\tdefineExpose({\r\n\t\tinit,\r\n\t\tsetOption,\r\n\t\tshowLoading,\r\n\t\thideLoading,\r\n\t\tclear,\r\n\t\tdispose,\r\n\t\tresize,\r\n\t\tcanvasToTempFilePath\r\n\t})\r\n</script>\r\n<style lang=\"scss\">\r\n\t.lime-echart {\r\n\t\tflex: 1;\r\n\t\twidth: 100%;\r\n\t}\r\n</style>"
  },
  {
    "path": "src/uni_modules/lime-echart/components/l-echart/l-echart.vue",
    "content": "<template>\r\n\t<view class=\"lime-echart\" :style=\"[customStyle]\" v-if=\"canvasId\" ref=\"limeEchart\" :aria-label=\"ariaLabel\">\r\n\t\t<!-- #ifndef APP-NVUE -->\r\n\t\t<canvas\r\n\t\t\tclass=\"lime-echart__canvas\"\r\n\t\t\tv-if=\"use2dCanvas\"\r\n\t\t\ttype=\"2d\"\r\n\t\t\t:id=\"canvasId\"\r\n\t\t\t:style=\"canvasStyle\"\r\n\t\t\t:disable-scroll=\"isDisableScroll\"\r\n\t\t\t@touchstart=\"touchStart\"\r\n\t\t\t@touchmove=\"touchMove\"\r\n\t\t\t@touchend=\"touchEnd\"\r\n\t\t/>\r\n\t\t<canvas\r\n\t\t\tclass=\"lime-echart__canvas\"\r\n\t\t\tv-else\r\n\t\t\t:width=\"nodeWidth\"\r\n\t\t\t:height=\"nodeHeight\"\r\n\t\t\t:style=\"canvasStyle\"\r\n\t\t\t:canvas-id=\"canvasId\"\r\n\t\t\t:id=\"canvasId\"\r\n\t\t\t:disable-scroll=\"isDisableScroll\"\r\n\t\t\t@touchstart=\"touchStart\"\r\n\t\t\t@touchmove=\"touchMove\"\r\n\t\t\t@touchend=\"touchEnd\"\r\n\t\t/>\r\n\t\t<view class=\"lime-echart__mask\"\r\n\t\t\tv-if=\"isPC\"\r\n\t\t\t@mousedown=\"touchStart\"\r\n\t\t\t@mousemove=\"touchMove\"\r\n\t\t\t@mouseup=\"touchEnd\"\r\n\t\t\t@touchstart=\"touchStart\"\r\n\t\t\t@touchmove=\"touchMove\"\r\n\t\t\t@touchend=\"touchEnd\">\r\n\t\t</view>\r\n\t\t<canvas v-if=\"isOffscreenCanvas\" :style=\"offscreenStyle\" :canvas-id=\"offscreenCanvasId\"></canvas>\r\n\t\t<!-- #endif -->\r\n\t\t<!-- #ifdef APP-NVUE -->\r\n\t\t<web-view\r\n\t\t\tclass=\"lime-echart__canvas\"\r\n\t\t\t:id=\"canvasId\"\r\n\t\t\t:style=\"canvasStyle\"\r\n\t\t\t:webview-styles=\"webviewStyles\"\r\n\t\t\tref=\"webview\"\r\n\t\t\tsrc=\"/uni_modules/lime-echart/static/uvue.html?v=1\"\r\n\t\t\t@pagefinish=\"finished = true\"\r\n\t\t\t@onPostMessage=\"onMessage\"\r\n\t\t></web-view>\r\n\t\t<!-- #endif -->\r\n\t</view>\r\n</template>\r\n\r\n<script>\r\n// @ts-nocheck\r\n// #ifndef APP-NVUE\r\nimport {Canvas, setCanvasCreator, dispatch} from './canvas';\r\nimport {wrapTouch, convertTouchesToArray, devicePixelRatio ,sleep, canIUseCanvas2d, getRect, getDeviceInfo} from './utils';\r\n// #endif\r\n// #ifdef APP-NVUE\r\nimport { base64ToPath, sleep } from './utils';\r\nimport {Echarts} from './nvue'\r\n// #endif\r\nconst charts = {}\r\nconst echartsObj = {}\r\n\r\n\r\n/**\r\n * LimeChart 图表\r\n * @description 全端兼容的eCharts\r\n * @tutorial https://ext.dcloud.net.cn/plugin?id=4899\r\n\r\n * @property {String} customStyle 自定义样式\r\n * @property {String} type 指定 canvas 类型\r\n * @value 2d 使用canvas 2d，部分小程序支持\r\n * @value '' 使用原生canvas，会有层级问题\r\n * @value bottom right\t不缩放图片，只显示图片的右下边区域\r\n * @property {Boolean} isDisableScroll\t \r\n * @property {number} beforeDelay = [30]  延迟初始化 (毫秒)\r\n * @property {Boolean} enableHover PC端使用鼠标悬浮\r\n\r\n * @event {Function} finished 加载完成触发\r\n */\r\nexport default {\r\n\tname: 'lime-echart',\r\n\tprops: {\r\n\t\t// #ifdef MP-WEIXIN || MP-TOUTIAO\r\n\t\ttype: {\r\n\t\t\ttype: String,\r\n\t\t\tdefault: '2d'\r\n\t\t},\r\n\t\t// #endif\r\n\t\t// #ifdef APP-NVUE\r\n\t\twebviewStyles: Object,\r\n\t\t// hybrid: Boolean,\r\n\t\t// #endif\r\n\t\tcustomStyle: String,\r\n\t\tisDisableScroll: Boolean,\r\n\t\tisClickable: {\r\n\t\t\ttype: Boolean,\r\n\t\t\tdefault: true\r\n\t\t},\r\n\t\tenableHover: Boolean,\r\n\t\tbeforeDelay: {\r\n\t\t\ttype: Number,\r\n\t\t\tdefault: 30\r\n\t\t},\r\n\t\tlandscape: Boolean\r\n\t},\r\n\tdata() {\r\n\t\treturn {\r\n\t\t\t// #ifdef MP-WEIXIN || MP-TOUTIAO || MP-ALIPAY\r\n\t\t\tuse2dCanvas: true,\r\n\t\t\t// #endif\r\n\t\t\t// #ifndef MP-WEIXIN || MP-TOUTIAO || MP-ALIPAY\r\n\t\t\tuse2dCanvas: false,\r\n\t\t\t// #endif\r\n\t\t\tariaLabel: '图表',\r\n\t\t\twidth: null,\r\n\t\t\theight: null,\r\n\t\t\tnodeWidth: null,\r\n\t\t\tnodeHeight: null,\r\n\t\t\t// canvasNode: null,\r\n\t\t\tconfig: {},\r\n\t\t\tinited: false,\r\n\t\t\tfinished: false,\r\n\t\t\tfile: '',\r\n\t\t\tplatform: '',\r\n\t\t\tisPC: false,\r\n\t\t\tisDown: false,\r\n\t\t\tisOffscreenCanvas: false,\r\n\t\t\toffscreenWidth: 0,\r\n\t\t\toffscreenHeight: 0,\r\n\t\t};\r\n\t},\r\n\tcomputed: {\r\n\t\trootStyle() {\r\n\t\t\tif(this.landscape) {\r\n\t\t\t\treturn `transform: translate(-50%,-50%) rotate(90deg); top:50%; left:50%;`\r\n\t\t\t}\r\n\t\t},\r\n\t\tcanvasId() {\r\n\t\t\treturn `lime-echart${this._ && this._.uid || this._uid}`\r\n\t\t},\r\n\t\toffscreenCanvasId() {\r\n\t\t\treturn `${this.canvasId}_offscreen`\r\n\t\t},\r\n\t\toffscreenStyle() {\r\n\t\t\treturn `width:${this.offscreenWidth}px;height: ${this.offscreenHeight}px; position: fixed; left: 99999px; background: red`\r\n\t\t},\r\n\t\tcanvasStyle() {\r\n\t\t\treturn this.rootStyle + (this.width && this.height ? ('width:' + this.width + 'px;height:' + this.height + 'px') : '')\r\n\t\t}\r\n\t},\r\n\t// #ifndef VUE3\r\n\tbeforeDestroy() {\r\n\t\tthis.clear()\r\n\t\tthis.dispose()\r\n\t\t// #ifdef H5\r\n\t\tif(this.isPC) {\r\n\t\t\tdocument.removeEventListener('mousewheel', this.mousewheel)\r\n\t\t}\r\n\t\t// #endif\r\n\t},\r\n\t// #endif\r\n\t// #ifdef VUE3\r\n\tbeforeUnmount() {\r\n\t\tthis.clear()\r\n\t\tthis.dispose()\r\n\t\t// #ifdef H5\r\n\t\tif(this.isPC) {\r\n\t\t\tdocument.removeEventListener('mousewheel', this.mousewheel)\r\n\t\t}\r\n\t\t// #endif\r\n\t},\r\n\t// #endif\r\n\tcreated() {\r\n\t\t// #ifdef H5\r\n\t\tif(!('ontouchstart' in window)) {\r\n\t\t\tthis.isPC = true\r\n\t\t\tdocument.addEventListener('mousewheel', this.mousewheel)\r\n\t\t}\r\n\t\t// #endif\r\n\t\t// #ifdef MP-WEIXIN || MP-TOUTIAO || MP-ALIPAY\r\n\t\t// const { platform } = uni.getSystemInfoSync();\r\n\t\tconst { platform } = getDeviceInfo();\r\n\t\tthis.isPC = /windows/i.test(platform)\r\n\t\t// #endif\r\n\t\tthis.use2dCanvas = this.type === '2d' && canIUseCanvas2d()\r\n\t},\r\n\tmounted() {\r\n\t\tthis.$nextTick(() => {\r\n\t\t\tthis.$emit('finished')\r\n\t\t})\r\n\t},\r\n\tmethods: {\r\n\t\t// #ifdef APP-NVUE\r\n\t\tonMessage(e) {\r\n\t\t\tconst detail = e?.detail?.data[0] || null;\r\n\t\t\tconst data = detail?.data\r\n\t\t\tconst key = detail?.event\r\n\t\t\tconst options = data?.options\r\n\t\t\tconst event = data?.event\r\n\t\t\tconst file = detail?.file\r\n\t\t\tif (key == 'log' && data) {\r\n\t\t\t\tconsole.log(data)\r\n\t\t\t}\r\n\t\t\tif(event) {\r\n\t\t\t\tthis.chart.dispatchAction(event.replace(/\"/g,''), options)\r\n\t\t\t}\r\n\t\t\tif(file) {\r\n\t\t\t\tthie.file = file\r\n\t\t\t}\r\n\t\t},\r\n\t\t// #endif\r\n\t\tsetChart(callback) {\r\n\t\t\tif(!this.chart) {\r\n\t\t\t\tconsole.warn(`组件还未初始化，请先使用 init`)\r\n\t\t\t\treturn\r\n\t\t\t}\r\n\t\t\tif(typeof callback === 'function' && this.chart) {\r\n\t\t\t\tcallback(this.chart);\r\n\t\t\t}\r\n\t\t\t// #ifdef APP-NVUE\r\n\t\t\tif(typeof callback === 'function') {\r\n\t\t\t\tthis.$refs.webview.evalJs(`setChart(${JSON.stringify(callback.toString())}, ${JSON.stringify(this.chart.options)})`);\r\n\t\t\t}\r\n\t\t\t// #endif\r\n\t\t},\r\n\t\tsetOption() {\r\n\t\t\tif (!this.chart || !this.chart.setOption) {\r\n\t\t\t\tconsole.warn(`组件还未初始化，请先使用 init`)\r\n\t\t\t\treturn\r\n\t\t\t}\r\n\t\t\tthis.chart.setOption(...arguments);\r\n\t\t},\r\n\t\tshowLoading() {\r\n\t\t\tif(this.chart) {\r\n\t\t\t\tthis.chart.showLoading(...arguments)\r\n\t\t\t}\r\n\t\t},\r\n\t\thideLoading() {\r\n\t\t\tif(this.chart) {\r\n\t\t\t\tthis.chart.hideLoading()\r\n\t\t\t}\r\n\t\t},\r\n\t\tclear() {\r\n\t\t\tif(this.chart) {\r\n\t\t\t\tthis.chart.clear()\r\n\t\t\t}\r\n\t\t},\r\n\t\tdispose() {\r\n\t\t\tif(this.chart) {\r\n\t\t\t\tthis.chart.dispose()\r\n\t\t\t}\r\n\t\t},\r\n\t\tresize(size) {\r\n\t\t\tif(size && size.width && size.height) {\r\n\t\t\t\tthis.height = size.height\r\n\t\t\t\tthis.width = size.width\r\n\t\t\t\tif(this.chart) {this.chart.resize(size)}\r\n\t\t\t} else {\r\n\t\t\t\tthis.$nextTick(() => {\r\n\t\t\t\t\tuni.createSelectorQuery()\r\n\t\t\t\t\t\t.in(this)\r\n\t\t\t\t\t\t.select(`.lime-echart`)\r\n\t\t\t\t\t\t.boundingClientRect()\r\n\t\t\t\t\t\t.exec(res => {\r\n\t\t\t\t\t\t\tif (res) {\r\n\t\t\t\t\t\t\t\tlet { width, height } = res[0];\r\n\t\t\t\t\t\t\t\tthis.width = width = width || 300;\r\n\t\t\t\t\t\t\t\tthis.height = height = height || 300;\r\n\t\t\t\t\t\t\t\tthis.chart.resize({width, height})\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t});\r\n\t\t\t\t})\r\n\t\t\t\t\r\n\t\t\t}\r\n\t\t\t\r\n\t\t},\r\n\t\tcanvasToTempFilePath(args = {}) {\r\n\t\t\t// #ifndef APP-NVUE\r\n\t\t\tconst { use2dCanvas, canvasId } = this;\r\n\t\t\treturn new Promise((resolve, reject) => {\r\n\t\t\t\tconst copyArgs = Object.assign({\r\n\t\t\t\t\tcanvasId,\r\n\t\t\t\t\tsuccess: resolve,\r\n\t\t\t\t\tfail: reject\r\n\t\t\t\t}, args);\r\n\t\t\t\tif (use2dCanvas) {\r\n\t\t\t\t\tdelete copyArgs.canvasId;\r\n\t\t\t\t\tcopyArgs.canvas = this.canvasNode;\r\n\t\t\t\t}\r\n\t\t\t\tuni.canvasToTempFilePath(copyArgs, this);\r\n\t\t\t});\r\n\t\t\t// #endif\r\n\t\t\t// #ifdef APP-NVUE\r\n\t\t\tthis.file = ''\r\n\t\t\tthis.$refs.webview.evalJs(`canvasToTempFilePath()`);\r\n\t\t\treturn new Promise((resolve, reject) => {\r\n\t\t\t\tthis.$watch('file', async (file) => {\r\n\t\t\t\t\tif(file) {\r\n\t\t\t\t\t\tconst tempFilePath = await base64ToPath(file)\r\n\t\t\t\t\t\tresolve(args.success({tempFilePath}))\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\treject(args.fail({error: ``}))\r\n\t\t\t\t\t}\r\n\t\t\t\t})\r\n\t\t\t})\r\n\t\t\t// #endif\r\n\t\t},\r\n\t\tasync init(echarts, ...args) {\r\n\t\t\t// #ifndef APP-NVUE\r\n\t\t\tif(args && args.length == 0 && !echarts) {\r\n\t\t\t\tconsole.error('缺少参数：init(echarts, theme?:string, opts?: object, callback?: function)')\r\n\t\t\t\treturn\r\n\t\t\t}\r\n\t\t\t// #endif\r\n\t\t\tlet theme=null,opts={},callback;\r\n\t\t\t\r\n\t\t\tArray.from(arguments).forEach(item => {\r\n\t\t\t\tif(typeof item === 'function') {\r\n\t\t\t\t\tcallback = item\r\n\t\t\t\t}\r\n\t\t\t\tif(['string'].includes(typeof item)) {\r\n\t\t\t\t\ttheme = item\r\n\t\t\t\t}\r\n\t\t\t\tif(typeof item === 'object') {\r\n\t\t\t\t\topts = item\r\n\t\t\t\t}\r\n\t\t\t})\r\n\t\t\t\r\n\t\t\tif(this.beforeDelay) {\r\n\t\t\t\tawait sleep(this.beforeDelay)\r\n\t\t\t}\r\n\t\t\tlet config = await this.getContext();\r\n\t\t\t// #ifndef APP-NVUE\r\n\t\t\tsetCanvasCreator(echarts, config)\r\n\t\t\ttry {\r\n\t\t\t\tthis.chart = echarts.init(config.canvas, theme, Object.assign({}, config, opts))\r\n\t\t\t\tif(typeof callback === 'function') {\r\n\t\t\t\t\tcallback(this.chart)\r\n\t\t\t\t} else {\r\n\t\t\t\t\treturn this.chart\r\n\t\t\t\t}\r\n\t\t\t} catch(e) {\r\n\t\t\t\tconsole.error(e.messges)\r\n\t\t\t\treturn null\r\n\t\t\t}\r\n\t\t\t// #endif\r\n\t\t\t// #ifdef APP-NVUE\r\n\t\t\tthis.chart = new Echarts(this.$refs.webview)\r\n\t\t\tthis.$refs.webview.evalJs(`init(null, null, ${JSON.stringify(opts)}, ${theme})`)\r\n\t\t\tif(callback) {\r\n\t\t\t\tcallback(this.chart)\r\n\t\t\t} else {\r\n\t\t\t\treturn this.chart\r\n\t\t\t}\r\n\t\t\t// #endif\r\n\t\t},\r\n\t\tgetContext() {\r\n\t\t\t// #ifdef APP-NVUE\r\n\t\t\tif(this.finished) {\r\n\t\t\t\treturn Promise.resolve(this.finished)\r\n\t\t\t}\r\n\t\t\treturn new Promise(resolve => {\r\n\t\t\t\tthis.$watch('finished', (val) => {\r\n\t\t\t\t\tif(val) {\r\n\t\t\t\t\t\tresolve(this.finished)\r\n\t\t\t\t\t}\r\n\t\t\t\t})\r\n\t\t\t})\r\n\t\t\t// #endif\r\n\t\t\t// #ifndef APP-NVUE\r\n\t\t\treturn getRect(`#${this.canvasId}`, {context: this, type: this.use2dCanvas ? 'fields': 'boundingClientRect'}).then(res => {\r\n\t\t\t\tif(res) {\r\n\t\t\t\t\tlet dpr = devicePixelRatio\r\n\t\t\t\t\tlet {width, height, node} = res\r\n\t\t\t\t\tlet canvas;\r\n\t\t\t\t\tthis.width = width = width || 300;\r\n\t\t\t\t\tthis.height = height = height || 300;\r\n\t\t\t\t\tif(node) {\r\n\t\t\t\t\t\tconst ctx = node.getContext('2d');\r\n\t\t\t\t\t\tcanvas = new Canvas(ctx, this, true, node);\r\n\t\t\t\t\t\tthis.canvasNode = node\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\t// #ifdef MP-TOUTIAO\r\n\t\t\t\t\t\tdpr = !this.isPC ? devicePixelRatio : 1// 1.25\r\n\t\t\t\t\t\t// #endif\r\n\t\t\t\t\t\t// #ifndef MP-ALIPAY || MP-TOUTIAO\r\n\t\t\t\t\t\tdpr = this.isPC ? devicePixelRatio : 1\r\n\t\t\t\t\t\t// #endif\r\n\t\t\t\t\t\t// #ifdef MP-ALIPAY || MP-LARK\r\n\t\t\t\t\t\tdpr = devicePixelRatio\r\n\t\t\t\t\t\t// #endif\r\n\t\t\t\t\t\t// #ifdef WEB\r\n\t\t\t\t\t\tdpr = 1\r\n\t\t\t\t\t\t// #endif\r\n\t\t\t\t\t\tthis.rect = res\r\n\t\t\t\t\t\tthis.nodeWidth = width * dpr;\r\n\t\t\t\t\t\tthis.nodeHeight = height * dpr;\r\n\t\t\t\t\t\tconst ctx = uni.createCanvasContext(this.canvasId, this);\r\n\t\t\t\t\t\tcanvas =  new Canvas(ctx, this, false);\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\treturn { canvas, width, height, devicePixelRatio: dpr, node };\r\n\t\t\t\t} else {\r\n\t\t\t\t\treturn {}\r\n\t\t\t\t}\r\n\t\t\t})\r\n\t\t\t// #endif\r\n\t\t},\r\n\t\t// #ifndef APP-NVUE\r\n\t\tgetRelative(e, touches) {\r\n\t\t\tlet { clientX, clientY } = e\r\n\t\t\tif(!(clientX && clientY) && touches && touches[0]) {\r\n\t\t\t\tclientX = touches[0].clientX\r\n\t\t\t\tclientY = touches[0].clientY\r\n\t\t\t}\r\n\t\t\treturn {x: clientX - this.rect.left, y: clientY - this.rect.top, wheelDelta: e.wheelDelta || 0}\r\n\t\t},\r\n\t\tgetTouch(e, touches) {\r\n\t\t\tconst {x} = touches && touches[0] || {}\r\n\t\t\tconst touch = x ? touches[0] : this.getRelative(e, touches);\r\n\t\t\tif(this.landscape) {\r\n\t\t\t\t[touch.x, touch.y] = [touch.y, this.height - touch.x]\r\n\t\t\t}\r\n\t\t\treturn touch;\r\n\t\t},\r\n\t\ttouchStart(e) {\r\n\t\t\tthis.isDown = true\r\n\t\t\tconst next = () => {\r\n\t\t\t\tconst touches = convertTouchesToArray(e.touches)\r\n\t\t\t\tif(this.chart) {\r\n\t\t\t\t\tconst touch = this.getTouch(e, touches)\r\n\t\t\t\t\tthis.startX = touch.x\r\n\t\t\t\t\tthis.startY = touch.y\r\n\t\t\t\t\tthis.startT = new Date()\r\n\t\t\t\t\tconst handler = this.chart.getZr().handler;\r\n\t\t\t\t\tdispatch.call(handler, 'mousedown', touch)\r\n\t\t\t\t\tdispatch.call(handler, 'mousemove', touch)\r\n\t\t\t\t\thandler.processGesture(wrapTouch(e), 'start');\r\n\t\t\t\t\tclearTimeout(this.endTimer);\r\n\t\t\t\t}\r\n\t\t\t\t\r\n\t\t\t}\r\n\t\t\tif(this.isPC) {\r\n\t\t\t\tgetRect(`#${this.canvasId}`, {context: this}).then(res => {\r\n\t\t\t\t\tthis.rect = res\r\n\t\t\t\t\tnext()\r\n\t\t\t\t})\r\n\t\t\t\treturn\r\n\t\t\t}\r\n\t\t\tnext()\r\n\t\t},\r\n\t\ttouchMove(e) {\r\n\t\t\tif(this.isPC && this.enableHover && !this.isDown) {this.isDown = true}\r\n\t\t\tconst touches = convertTouchesToArray(e.touches)\r\n\t\t\tif (this.chart && this.isDown) {\r\n\t\t\t\tconst handler = this.chart.getZr().handler;\r\n\t\t\t\tdispatch.call(handler, 'mousemove', this.getTouch(e, touches))\r\n\t\t\t\thandler.processGesture(wrapTouch(e), 'change');\r\n\t\t\t}\r\n\t\t\t\r\n\t\t},\r\n\t\ttouchEnd(e) {\r\n\t\t\tthis.isDown = false\r\n\t\t\tif (this.chart) {\r\n\t\t\t\tconst touches = convertTouchesToArray(e.changedTouches)\r\n\t\t\t\tconst {x} = touches && touches[0] || {}\r\n\t\t\t\tconst touch = (x ? touches[0] : this.getRelative(e, touches)) || {};\r\n\t\t\t\tif(this.landscape) {\r\n\t\t\t\t\t[touch.x, touch.y] = [touch.y,  this.height - touch.x]\r\n\t\t\t\t}\r\n\t\t\t\tconst handler = this.chart.getZr().handler;\r\n\t\t\t\tconst isClick = Math.abs(touch.x - this.startX) < 10 && new Date() - this.startT < 200;\r\n\t\t\t\tdispatch.call(handler, 'mouseup', touch)\r\n\t\t\t\thandler.processGesture(wrapTouch(e), 'end');\r\n\t\t\t\tif(isClick) {\r\n\t\t\t\t\tdispatch.call(handler, 'click', touch)\r\n\t\t\t\t} else {\r\n\t\t\t\t\tthis.endTimer = setTimeout(() => {\r\n\t\t\t\t\t\tdispatch.call(handler, 'mousemove', {x: 999999999,y: 999999999});\r\n\t\t\t\t\t\tdispatch.call(handler, 'mouseup', {x: 999999999,y: 999999999});\r\n\t\t\t\t\t},50)\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t},\r\n\t\t// #endif\r\n\t\t// #ifdef H5\r\n\t\tmousewheel(e){\r\n\t\t\tif(this.chart) {\r\n\t\t\t\t// dispatch.call(this.chart.getZr().handler, 'mousewheel', this.getTouch(e))\r\n\t\t\t}\r\n\t\t}\r\n\t\t// #endif\r\n\t}\r\n};\r\n</script>\r\n<style>\t\r\n.lime-echart {\r\n\tposition: relative;\r\n\t/* #ifndef APP-NVUE */\r\n\twidth: 100%;\r\n\theight: 100%;\r\n\t/* #endif */\r\n\t/* #ifdef APP-NVUE */\r\n\tflex: 1;\r\n\t/* #endif */\r\n}\r\n.lime-echart__canvas {\r\n\t/* #ifndef APP-NVUE */\r\n\twidth: 100%;\r\n\theight: 100%;\r\n\t/* #endif */\r\n\t/* #ifdef APP-NVUE */\r\n\tflex: 1;\r\n\t/* #endif */\r\n}\r\n/* #ifndef APP-NVUE */\r\n.lime-echart__mask {\r\n\tposition: absolute;\r\n\twidth: 100%;\r\n\theight: 100%;\r\n\tleft: 0;\r\n\ttop: 0;\r\n\tz-index: 1;\r\n}\r\n/* #endif */\r\n</style>\r\n"
  },
  {
    "path": "src/uni_modules/lime-echart/components/l-echart/nvue.js",
    "content": "export class Echarts {\r\n\teventMap = new Map()\r\n\tconstructor(webview) {\r\n\t\tthis.webview = webview\r\n\t\tthis.options = null\r\n\t}\r\n\tsetOption() {\r\n\t\tthis.options = arguments\r\n\t\tthis.webview.evalJs(`setOption(${JSON.stringify(arguments)})`);\r\n\t}\r\n\tgetOption() {\r\n\t\treturn this.options\r\n\t}\r\n\tshowLoading() {\r\n\t\tthis.webview.evalJs(`showLoading(${JSON.stringify(arguments)})`);\r\n\t}\r\n\thideLoading() {\r\n\t\tthis.webview.evalJs(`hideLoading()`);\r\n\t}\r\n\tclear() {\r\n\t\tthis.webview.evalJs(`clear()`);\r\n\t}\r\n\tdispose() {\r\n\t\tthis.webview.evalJs(`dispose()`);\r\n\t}\r\n\tresize(size) {\r\n\t\tif(size) {\r\n\t\t\tthis.webview.evalJs(`resize(${JSON.stringify(size)})`);\r\n\t\t} else {\r\n\t\t\tthis.webview.evalJs(`resize()`);\r\n\t\t}\r\n\t}\r\n\ton(type, ...args) {\r\n\t\tconst query = args[0]\r\n\t\tconst useQuery = query && typeof query != 'function'\r\n\t\tconst param = useQuery ? [type, query] : [type]\r\n\t\tconst key = `${type}${useQuery ? JSON.stringify(query): '' }`\r\n\t\tconst callback = useQuery ? args[1]: args[0]\r\n\t\tif(typeof callback == 'function'){\r\n\t\t\tthis.eventMap.set(key, callback)\r\n\t\t}\r\n\t\tthis.webview.evalJs(`on(${JSON.stringify(param)})`);\r\n\t\tconsole.warn('nvue 暂不支持事件')\r\n\t}\r\n\tdispatchAction(type, options){\r\n\t\tconst handler = this.eventMap.get(type)\r\n\t\tif(handler){\r\n\t\t\thandler(options)\r\n\t\t}\r\n\t}\r\n}"
  },
  {
    "path": "src/uni_modules/lime-echart/components/l-echart/utils.js",
    "content": "// @ts-nocheck\r\n/**\n * 获取设备基础信息\n *\n * @see [uni.getDeviceInfo](https://uniapp.dcloud.net.cn/api/system/getDeviceInfo.html)\n */\nexport function getDeviceInfo() {\n\tif (uni.getDeviceInfo && uni.canIUse('getDeviceInfo')) {\n\t\treturn uni.getDeviceInfo();\n\t} else {\n\t\treturn uni.getSystemInfoSync();\n\t}\n}\n\n/**\n * 获取窗口信息\n *\n * @see [uni.getWindowInfo](https://uniapp.dcloud.net.cn/api/system/getWindowInfo.html)\n */\nexport function getWindowInfo() {\n\tif (uni.getWindowInfo && uni.canIUse('getWindowInfo')) {\n\t\treturn uni.getWindowInfo();\n\t} else {\n\t\treturn uni.getSystemInfoSync();\n\t}\n}\n\n/**\n * 获取APP基础信息\n *\n * @see [uni.getAppBaseInfo](https://uniapp.dcloud.net.cn/api/system/getAppBaseInfo.html)\n */\nexport function getAppBaseInfo() {\n\tif (uni.getAppBaseInfo && uni.canIUse('getAppBaseInfo')) {\n\t\treturn uni.getAppBaseInfo();\n\t} else {\n\t\treturn uni.getSystemInfoSync();\n\t}\n}\r\n\r\n\r\n// #ifndef APP-NVUE\r\n// 计算版本\r\nexport function compareVersion(v1, v2) {\r\n\tv1 = v1.split('.')\r\n\tv2 = v2.split('.')\r\n\tconst len = Math.max(v1.length, v2.length)\r\n\twhile (v1.length < len) {\r\n\t\tv1.push('0')\r\n\t}\r\n\twhile (v2.length < len) {\r\n\t\tv2.push('0')\r\n\t}\r\n\tfor (let i = 0; i < len; i++) {\r\n\t\tconst num1 = parseInt(v1[i], 10)\r\n\t\tconst num2 = parseInt(v2[i], 10)\r\n\r\n\t\tif (num1 > num2) {\r\n\t\t\treturn 1\r\n\t\t} else if (num1 < num2) {\r\n\t\t\treturn -1\r\n\t\t}\r\n\t}\r\n\treturn 0\r\n}\r\n// const systemInfo = uni.getSystemInfoSync();\r\n\r\nfunction gte(version) {\r\n\t// 截止 2023-03-22 mac pc小程序不支持 canvas 2d\r\n\t// let {\r\n\t// \tSDKVersion,\r\n\t// \tplatform\r\n\t// } = systemInfo;\r\n\tconst { platform } = getDeviceInfo();\r\n\tlet { SDKVersion } = getAppBaseInfo();\r\n\t// #ifdef MP-ALIPAY\r\n\tSDKVersion = my.SDKVersion\r\n\t// #endif\r\n\t// #ifdef MP-WEIXIN\r\n\treturn platform !== 'mac' && compareVersion(SDKVersion, version) >= 0;\r\n\t// #endif\r\n\treturn compareVersion(SDKVersion, version) >= 0;\r\n}\r\n\r\n\r\nexport function canIUseCanvas2d() {\r\n\t// #ifdef MP-WEIXIN\r\n\treturn gte('2.9.0');\r\n\t// #endif\r\n\t// #ifdef MP-ALIPAY\r\n\treturn gte('2.7.0');\r\n\t// #endif\r\n\t// #ifdef MP-TOUTIAO\r\n\treturn gte('1.78.0');\r\n\t// #endif\r\n\treturn false\r\n}\r\n\r\nexport function convertTouchesToArray(touches) {\r\n\t// 如果 touches 是一个数组，则直接返回它\r\n\tif (Array.isArray(touches)) {\r\n\t\treturn touches;\r\n\t}\r\n\t// 如果touches是一个对象，则转换为数组\r\n\tif (typeof touches === 'object' && touches !== null) {\r\n\t\treturn Object.values(touches);\r\n\t}\r\n\t// 对于其他类型，直接返回它\r\n\treturn touches;\r\n}\r\n\r\nexport function wrapTouch(event) {\r\n\tevent.touches = convertTouchesToArray(event.touches)\r\n\tfor (let i = 0; i < event.touches.length; ++i) {\r\n\t\tconst touch = event.touches[i];\r\n\t\ttouch.offsetX = touch.x;\r\n\t\ttouch.offsetY = touch.y;\r\n\t}\r\n\treturn event;\r\n}\r\n// export const devicePixelRatio = uni.getSystemInfoSync().pixelRatio\r\nexport const devicePixelRatio = getWindowInfo().pixelRatio;\r\n// #endif\r\n// #ifdef APP-NVUE\r\nexport function base64ToPath(base64) {\r\n\treturn new Promise((resolve, reject) => {\r\n\t\tconst [, format, bodyData] = /data:image\\/(\\w+);base64,(.*)/.exec(base64) || [];\r\n\t\tconst bitmap = new plus.nativeObj.Bitmap('bitmap' + Date.now())\r\n\t\tbitmap.loadBase64Data(base64, () => {\r\n\t\t\tif (!format) {\r\n\t\t\t\treject(new Error('ERROR_BASE64SRC_PARSE'))\r\n\t\t\t}\r\n\t\t\tconst time = new Date().getTime();\r\n\t\t\tconst filePath = `_doc/uniapp_temp/${time}.${format}`\r\n\r\n\t\t\tbitmap.save(filePath, {},\r\n\t\t\t\t() => {\r\n\t\t\t\t\tbitmap.clear()\r\n\t\t\t\t\tresolve(filePath)\r\n\t\t\t\t},\r\n\t\t\t\t(error) => {\r\n\t\t\t\t\tbitmap.clear()\r\n\t\t\t\t\tconsole.error(`${JSON.stringify(error)}`)\r\n\t\t\t\t\treject(error)\r\n\t\t\t\t})\r\n\t\t}, (error) => {\r\n\t\t\tbitmap.clear()\r\n\t\t\tconsole.error(`${JSON.stringify(error)}`)\r\n\t\t\treject(error)\r\n\t\t})\r\n\t})\r\n}\r\n// #endif\r\n\r\n\r\nexport function sleep(time) {\r\n\treturn new Promise((resolve) => {\r\n\t\tsetTimeout(() => {\r\n\t\t\tresolve(true)\r\n\t\t}, time)\r\n\t})\r\n}\r\n\r\n\r\nexport function getRect(selector, options = {}) {\r\n\tconst typeDefault = 'boundingClientRect'\r\n\tconst {\r\n\t\tcontext,\r\n\t\ttype = typeDefault\r\n\t} = options\r\n\treturn new Promise((resolve, reject) => {\r\n\t\tconst dom = uni.createSelectorQuery().in(context).select(selector);\r\n\t\tconst result = (rect) => {\r\n\t\t\tif (rect) {\r\n\t\t\t\tresolve(rect)\r\n\t\t\t} else {\r\n\t\t\t\treject()\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (type == typeDefault) {\r\n\t\t\tdom[type](result).exec()\r\n\t\t} else {\r\n\t\t\tdom[type]({\r\n\t\t\t\tnode: true,\r\n\t\t\t\tsize: true,\r\n\t\t\t\trect: true\r\n\t\t\t}, result).exec()\r\n\t\t}\r\n\t});\r\n};"
  },
  {
    "path": "src/uni_modules/lime-echart/components/l-echart/uvue.uts",
    "content": "// @ts-nocheck\r\n// #ifdef APP\r\ntype EchartsEventHandler = (event: UTSJSONObject)=>void\r\n// type EchartsTempResolve = (obj : UTSJSONObject) => void\r\n// type EchartsTempOptions = UTSJSONObject\r\nexport class Echarts {\r\n\toptions: UTSJSONObject = {} as UTSJSONObject\r\n\tcontext: UniWebViewElement\r\n\teventMap: Map<string, EchartsEventHandler> = new Map()\r\n\tprivate temp: UTSJSONObject[] = []\r\n\tconstructor(context: UniWebViewElement){\r\n\t\tthis.context = context\r\n\t\tthis.init()\r\n\t}\r\n\tinit(){\r\n\t\tthis.context.evalJS(`init(null, null, ${JSON.stringify({})})`)\r\n\t\t\r\n\t\tthis.context.addEventListener('message', (e : UniWebViewMessageEvent) => {\r\n\t\t\t// event.stopPropagation()\r\n\t\t\t// event.preventDefault()\r\n\t\t\t\r\n\t\t\tconst detail = e.detail.data[0]\r\n\t\t\tconst file = detail.getString('file')\r\n\t\t\tconst data = detail.get('data')\r\n\t\t\tconst key = detail.getString('event')\r\n\t\t\tconst options = typeof data == 'object' ? (data as UTSJSONObject).getJSON('options'): null\r\n\t\t\tconst event = typeof data == 'object' ? (data as UTSJSONObject).getString('event'): null\r\n\t\t\tif (key == 'log' && data != null) {\r\n\t\t\t\tconsole.log(data)\r\n\t\t\t}\r\n\t\t\tif (event != null && options != null) {\r\n\t\t\t\tthis.dispatchAction(event.replace(/\"/g,''), options)\r\n\t\t\t}\r\n\t\t\tif(file != null){\r\n\t\t\t\twhile (this.temp.length > 0) {\r\n\t\t\t\t\tconst opt = this.temp.pop()\r\n\t\t\t\t\tconst success = opt?.get('success')\r\n\t\t\t\t\tif(typeof success == 'function'){\r\n\t\t\t\t\t\tsuccess as (res: UTSJSONObject) => void\r\n\t\t\t\t\t\tsuccess({tempFilePath: file})\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t})\r\n\t}\r\n\tsetOption(option: UTSJSONObject){\r\n\t\tthis.options = option;\r\n\t\tthis.context.evalJS(`setOption(${JSON.stringify([option])})`)\r\n\t}\r\n\tsetOption(option: UTSJSONObject, notMerge: boolean = false, lazyUpdate: boolean = false){\r\n\t\tthis.options = option;\r\n\t\tthis.context.evalJS(`setOption(${JSON.stringify([option, notMerge, lazyUpdate])})`)\r\n\t}\r\n\tsetOption(option: UTSJSONObject, notMerge: UTSJSONObject){\r\n\t\tthis.options = option;\r\n\t\tthis.context.evalJS(`setOption(${JSON.stringify([option, notMerge])})`)\r\n\t}\r\n\tgetOption(): UTSJSONObject {\r\n\t\treturn this.options\r\n\t}\r\n\tshowLoading(){\r\n\t\tthis.context.evalJS(`showLoading(${JSON.stringify([] as any[])})`);\r\n\t}\r\n\tshowLoading(type: string, opts: UTSJSONObject){\r\n\t\tthis.context.evalJS(`showLoading(${JSON.stringify([type, opts])})`);\r\n\t}\r\n\thideLoading(){\r\n\t\tthis.context.evalJS(`hideLoading()`);\r\n\t}\r\n\tclear(){\r\n\t\tthis.context.evalJS(`clear()`);\r\n\t}\r\n\tdispose(){\r\n\t\tthis.context.evalJS(`dispose()`);\r\n\t}\r\n\tresize(size:UTSJSONObject){\n\t\tsetTimeout(()=>{\n\t\t\tthis.context.evalJS(`resize(${JSON.stringify(size)})`);\n\t\t},0)\r\n\t}\r\n\tresize(){\n\t\tsetTimeout(()=>{\n\t\t\tthis.context.evalJS(`resize()`);\n\t\t},10)\r\n\t\t\r\n\t}\r\n\ton(type:string, query: any, callback: EchartsEventHandler) {\r\n\t\tconst key = `${type}${JSON.stringify(query)}`\r\n\t\tif(typeof callback == 'function'){\r\n\t\t\tthis.eventMap.set(key, callback)\r\n\t\t}\r\n\t\tthis.context.evalJS(`on(${JSON.stringify([type, query])})`);\r\n\t\tconsole.warn('uvue 暂不支持事件')\r\n\t}\r\n\ton(type:string, callback: EchartsEventHandler) {\r\n\t\tconst key = `${type}`\r\n\t\tif(typeof callback == 'function'){\r\n\t\t\tthis.eventMap.set(key, callback)\r\n\t\t}\r\n\t\tthis.context.evalJS(`on(${JSON.stringify([type])})`);\r\n\t\tconsole.warn('uvue 暂不支持事件')\r\n\t}\r\n\tdispatchAction(type:string, options: UTSJSONObject){\r\n\t\tconst handler = this.eventMap.get(type)\r\n\t\tif(handler!=null){\r\n\t\t\thandler(options)\r\n\t\t}\r\n\t}\r\n\tcanvasToTempFilePath(opt: UTSJSONObject){\r\n\t\t// this.context.evalJS(`on(${JSON.stringify(opt)})`);\r\n\t\tthis.context.evalJS(`canvasToTempFilePath(${JSON.stringify(opt)})`);\r\n\t\tthis.temp.push(opt)\r\n\t}\r\n}\r\n\r\n// #endif\r\n// #ifndef APP\r\nexport class Echarts {\r\n\tconstructor() {}\r\n\tsetOption(option: UTSJSONObject): void\r\n\tisDisposed(): boolean;\r\n\tclear(): void;\r\n\tresize(size:UTSJSONObject): void;\r\n\tresize(): void;\r\n\tcanvasToTempFilePath(opt : UTSJSONObject): void;\r\n\tdispose(): void;\r\n\tshowLoading(cfg?: UTSJSONObject): void;\r\n\tshowLoading(name?: string, cfg?: UTSJSONObject): void;\r\n\thideLoading(): void;\r\n\tgetZr(): any\r\n}\r\n// #endif"
  },
  {
    "path": "src/uni_modules/lime-echart/components/lime-echart/lime-echart.nvue",
    "content": "<template>\r\n\t<view style=\"width: 100%; height: 408px;\">\r\n\t\t<l-echart ref=\"chartRef\" @finished=\"init\"></l-echart>\r\n\t</view>\r\n</template>\r\n\r\n<script>\r\n\texport default {\r\n\t\tdata() {\r\n\t\t\treturn {\r\n\t\t\t\tshowTip: false,\r\n\t\t\t\toption: {\r\n\t\t\t\t\ttooltip: {\r\n\t\t\t\t\t\ttrigger: 'axis',\r\n\t\t\t\t\t\t// shadowBlur: 0,\r\n\t\t\t\t\t\ttextStyle: {\r\n\t\t\t\t\t\t\ttextShadowBlur: 0\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t\trenderMode: 'richText',\r\n\t\t\t\t\t},\r\n\t\t\t\t\tlegend: {\r\n\t\t\t\t\t\tdata: ['邮件营销', '联盟广告', '视频广告', '直接访问', '搜索引擎']\r\n\t\t\t\t\t},\r\n\t\t\t\t\tgrid: {\r\n\t\t\t\t\t\tleft: '3%',\r\n\t\t\t\t\t\tright: '4%',\r\n\t\t\t\t\t\tbottom: '3%',\r\n\t\t\t\t\t\tcontainLabel: true\r\n\t\t\t\t\t},\r\n\t\t\t\t\txAxis: {\r\n\t\t\t\t\t\ttype: 'category',\r\n\t\t\t\t\t\tboundaryGap: false,\r\n\t\t\t\t\t\tdata: ['周一', '周二', '周三', '周四', '周五', '周六', '周日']\r\n\t\t\t\t\t},\r\n\t\t\t\t\tyAxis: {\r\n\t\t\t\t\t\ttype: 'value'\r\n\t\t\t\t\t},\r\n\t\t\t\t\tseries: [\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tname: '邮件营销',\r\n\t\t\t\t\t\t\ttype: 'line',\r\n\t\t\t\t\t\t\tstack: '总量',\r\n\t\t\t\t\t\t\tdata: [120, 132, 101, 134, 90, 230, 210]\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tname: '联盟广告',\r\n\t\t\t\t\t\t\ttype: 'line',\r\n\t\t\t\t\t\t\tstack: '总量',\r\n\t\t\t\t\t\t\tdata: [220, 182, 191, 234, 290, 330, 310]\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tname: '视频广告',\r\n\t\t\t\t\t\t\ttype: 'line',\r\n\t\t\t\t\t\t\tstack: '总量',\r\n\t\t\t\t\t\t\tdata: [150, 232, 201, 154, 190, 330, 410]\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tname: '直接访问',\r\n\t\t\t\t\t\t\ttype: 'line',\r\n\t\t\t\t\t\t\tstack: '总量',\r\n\t\t\t\t\t\t\tdata: [320, 332, 301, 334, 390, 330, 320]\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\tname: '搜索引擎',\r\n\t\t\t\t\t\t\ttype: 'line',\r\n\t\t\t\t\t\t\tstack: '总量',\r\n\t\t\t\t\t\t\tdata: [820, 932, 901, 934, 1290, 1330, 1320]\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t]\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t},\r\n\t\tmounted() {\r\n\t\t\tconsole.log('lime echarts nvue')\r\n\t\t},\r\n\t\tmethods: {\r\n\t\t\tinit() {\r\n\t\t\t\tconst chartRef = this.$refs['chartRef']\r\n\t\t\t\tchartRef.init(chart => {\r\n\t\t\t\t\tchart.setOption(this.option);\r\n\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\tsetTimeout(()=>{\r\n\t\t\t\t\t\tconst option = {\r\n\t\t\t\t\t\t\ttooltip: {\r\n\t\t\t\t\t\t\t\ttrigger: 'axis',\r\n\t\t\t\t\t\t\t\t// shadowBlur: 0,\r\n\t\t\t\t\t\t\t\ttextStyle: {\r\n\t\t\t\t\t\t\t\t\ttextShadowBlur: 0\r\n\t\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\t\trenderMode: 'richText',\r\n\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\tlegend: {\r\n\t\t\t\t\t\t\t\tdata: ['邮件营销', '联盟广告', '视频广告', '直接访问', '搜索引擎']\r\n\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\tgrid: {\r\n\t\t\t\t\t\t\t\tleft: '3%',\r\n\t\t\t\t\t\t\t\tright: '4%',\r\n\t\t\t\t\t\t\t\tbottom: '3%',\r\n\t\t\t\t\t\t\t\tcontainLabel: true\r\n\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\txAxis: {\r\n\t\t\t\t\t\t\t\ttype: 'category',\r\n\t\t\t\t\t\t\t\tboundaryGap: false,\r\n\t\t\t\t\t\t\t\tdata: ['周一', '周二', '周三', '周四', '周五', '周六', '周日']\r\n\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\tyAxis: {\r\n\t\t\t\t\t\t\t\ttype: 'value'\r\n\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\tseries: [\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tname: '邮件营销',\r\n\t\t\t\t\t\t\t\t\ttype: 'line',\r\n\t\t\t\t\t\t\t\t\tstack: '总量',\r\n\t\t\t\t\t\t\t\t\tdata: [120, 132, 101, 134, 90, 230, 210]\r\n\t\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tname: '联盟广告',\r\n\t\t\t\t\t\t\t\t\ttype: 'line',\r\n\t\t\t\t\t\t\t\t\tstack: '总量',\r\n\t\t\t\t\t\t\t\t\tdata: [220, 182, 191, 234, 290, 330, 310]\r\n\t\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tname: '视频广告',\r\n\t\t\t\t\t\t\t\t\ttype: 'line',\r\n\t\t\t\t\t\t\t\t\tstack: '总量',\r\n\t\t\t\t\t\t\t\t\tdata: [150, 232, 201, 154, 190, 330, 410]\r\n\t\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tname: '直接访问',\r\n\t\t\t\t\t\t\t\t\ttype: 'line',\r\n\t\t\t\t\t\t\t\t\tstack: '总量',\r\n\t\t\t\t\t\t\t\t\tdata: [320, 332, 301, 334, 390, 330, 320]\r\n\t\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\t\t\tname: '搜索引擎',\r\n\t\t\t\t\t\t\t\t\ttype: 'line',\r\n\t\t\t\t\t\t\t\t\tstack: '总量',\r\n\t\t\t\t\t\t\t\t\tdata: [820, 932, 901, 934, 1290, 1330, 1320]\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t]\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tchart.setOption(option);\r\n\t\t\t\t\t},1000)\r\n\t\t\t\t})\r\n\t\t\t},\r\n\t\t\tsave() {\r\n\t\t\t\t// this.$refs.chart.canvasToTempFilePath({\r\n\t\t\t\t// \tsuccess(res) {\r\n\t\t\t\t// \t\tconsole.log('res::::', res)\r\n\t\t\t\t// \t}\r\n\t\t\t\t// })\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n</script>\r\n<style>\r\n\r\n</style>"
  },
  {
    "path": "src/uni_modules/lime-echart/components/lime-echart/lime-echart.uvue",
    "content": "<template>\r\n\t<view style=\"width: 100%; height: 408px;\">\r\n\t\t<l-echart ref=\"chartRef\" @finished=\"init\"></l-echart>\r\n\t</view>\r\n</template>\r\n\r\n<script lang=\"uts\" setup>\r\n\t// @ts-nocheck\r\n\t// #ifndef APP\r\n\timport * as echarts from 'echarts/dist/echarts.esm.js'\r\n\t// #endif\r\n\tconst chartRef = ref<LEchartComponentPublicInstance|null>(null)\r\n\tconst option = {\r\n\t\ttooltip: {\r\n\t\t\ttrigger: 'axis',\r\n\t\t\t// shadowBlur: 0,\r\n\t\t\ttextStyle: {\r\n\t\t\t\ttextShadowBlur: 0\r\n\t\t\t},\r\n\t\t\trenderMode: 'richText',\r\n\t\t},\r\n\t\t// formatter: async (params: any) => {\r\n\t\t// \tconsole.log('params', params)\r\n\t\t// \treturn 1\r\n\t\t// },\r\n\t\tlegend: {\r\n\t\t\tdata: ['邮件营销', '联盟广告', '视频广告', '直接访问', '搜索引擎']\r\n\t\t},\r\n\t\tgrid: {\r\n\t\t\tleft: '3%',\r\n\t\t\tright: '4%',\r\n\t\t\tbottom: '3%',\r\n\t\t\tcontainLabel: true\r\n\t\t},\r\n\t\txAxis: {\r\n\t\t\ttype: 'category',\r\n\t\t\tboundaryGap: false,\r\n\t\t\tdata: ['周一', '周二', '周三', '周四', '周五', '周六', '周日']\r\n\t\t},\r\n\t\tyAxis: {\r\n\t\t\ttype: 'value'\r\n\t\t},\r\n\t\tseries: [\r\n\t\t\t{\r\n\t\t\t\tname: '邮件营销',\r\n\t\t\t\ttype: 'line',\r\n\t\t\t\tstack: '总量',\r\n\t\t\t\tdata: [120, 132, 101, 134, 90, 230, 210]\r\n\t\t\t},\r\n\t\t\t{\r\n\t\t\t\tname: '联盟广告',\r\n\t\t\t\ttype: 'line',\r\n\t\t\t\tstack: '总量',\r\n\t\t\t\tdata: [220, 182, 191, 234, 290, 330, 310]\r\n\t\t\t},\r\n\t\t\t{\r\n\t\t\t\tname: '视频广告',\r\n\t\t\t\ttype: 'line',\r\n\t\t\t\tstack: '总量',\r\n\t\t\t\tdata: [150, 232, 201, 154, 190, 330, 410]\r\n\t\t\t},\r\n\t\t\t{\r\n\t\t\t\tname: '直接访问',\r\n\t\t\t\ttype: 'line',\r\n\t\t\t\tstack: '总量',\r\n\t\t\t\tdata: [320, 332, 301, 334, 390, 330, 320]\r\n\t\t\t},\r\n\t\t\t{\r\n\t\t\t\tname: '搜索引擎',\r\n\t\t\t\ttype: 'line',\r\n\t\t\t\tstack: '总量',\r\n\t\t\t\tdata: [820, 932, 901, 934, 1290, 1330, 1320]\r\n\t\t\t}\r\n\t\t]\r\n\t}\r\n\r\n\tconst init = async () =>{\r\n\t\tif(chartRef.value== null) return\r\n\t\t// #ifdef APP\r\n\t\tconst chart = await chartRef.value!.init(null)\r\n\t\t// #endif\r\n\t\t// #ifndef APP\r\n\t\tconst chart = await chartRef.value!.init(echarts, null)\r\n\t\t// #endif\r\n\t\tchart.setOption(option)\r\n\t\tchart.on('mouseover', function (params) {\r\n\t\t    console.log('params', params);\r\n\t\t});\r\n\t\t\r\n\t\t\r\n\t\t// setTimeout(()=> {\r\n\t\t// \tconst option1 = {\r\n\t\t// \t\ttooltip: {\r\n\t\t// \t\t\ttrigger: 'axis',\r\n\t\t// \t\t\t// shadowBlur: 0,\r\n\t\t// \t\t\ttextStyle: {\r\n\t\t// \t\t\t\ttextShadowBlur: 0\r\n\t\t// \t\t\t},\r\n\t\t// \t\t\trenderMode: 'richText',\r\n\t\t// \t\t},\r\n\t\t// \t\tlegend: {\r\n\t\t// \t\t\tdata: ['邮件营销', '联盟广告', '视频广告', '直接访问', '搜索引擎']\r\n\t\t// \t\t},\r\n\t\t// \t\tgrid: {\r\n\t\t// \t\t\tleft: '3%',\r\n\t\t// \t\t\tright: '4%',\r\n\t\t// \t\t\tbottom: '3%',\r\n\t\t// \t\t\tcontainLabel: true\r\n\t\t// \t\t},\r\n\t\t// \t\txAxis: {\r\n\t\t// \t\t\ttype: 'category',\r\n\t\t// \t\t\tboundaryGap: false,\r\n\t\t// \t\t\tdata: ['周一', '周二', '周三', '周四', '周五', '周六', '周日']\r\n\t\t// \t\t},\r\n\t\t// \t\tyAxis: {\r\n\t\t// \t\t\ttype: 'value'\r\n\t\t// \t\t},\r\n\t\t// \t\tseries: [\r\n\t\t// \t\t\t{\r\n\t\t// \t\t\t\tname: '邮件营销',\r\n\t\t// \t\t\t\ttype: 'line',\r\n\t\t// \t\t\t\tstack: '总量',\r\n\t\t// \t\t\t\tdata: [820, 132, 101, 134, 90, 230, 210]\r\n\t\t// \t\t\t},\r\n\t\t// \t\t\t{\r\n\t\t// \t\t\t\tname: '联盟广告',\r\n\t\t// \t\t\t\ttype: 'line',\r\n\t\t// \t\t\t\tstack: '总量',\r\n\t\t// \t\t\t\tdata: [220, 182, 191, 234, 290, 330, 310]\r\n\t\t// \t\t\t},\r\n\t\t// \t\t\t{\r\n\t\t// \t\t\t\tname: '视频广告',\r\n\t\t// \t\t\t\ttype: 'line',\r\n\t\t// \t\t\t\tstack: '总量',\r\n\t\t// \t\t\t\tdata: [950, 232, 201, 154, 190, 330, 410]\r\n\t\t// \t\t\t},\r\n\t\t// \t\t\t{\r\n\t\t// \t\t\t\tname: '直接访问',\r\n\t\t// \t\t\t\ttype: 'line',\r\n\t\t// \t\t\t\tstack: '总量',\r\n\t\t// \t\t\t\tdata: [320, 332, 301, 334, 390, 330, 320]\r\n\t\t// \t\t\t},\r\n\t\t// \t\t\t{\r\n\t\t// \t\t\t\tname: '搜索引擎',\r\n\t\t// \t\t\t\ttype: 'line',\r\n\t\t// \t\t\t\tstack: '总量',\r\n\t\t// \t\t\t\tdata: [820, 932, 901, 934, 1290, 1330, 1320]\r\n\t\t// \t\t\t}\r\n\t\t// \t\t]\r\n\t\t// \t}\r\n\t\t// \tchart.setOption(option1)\r\n\t\t// },1000)\r\n\t}\r\n\t\r\n\t\r\n\t\r\n</script>\r\n<style>\r\n\r\n</style>"
  },
  {
    "path": "src/uni_modules/lime-echart/components/lime-echart/lime-echart.vue",
    "content": "<template>\n  <view>\n    <view style=\"height: 750rpx; position: relative\">\n      <l-echart ref=\"chart\" @finished=\"init\"></l-echart>\n      <view\n        class=\"customTooltips\"\n        :style=\"{ left: position[0] + 'px', top: position[1] + 'px' }\"\n        v-if=\"params.length && position.length && showTip\"\n      >\n        <view>这是个自定的tooltips</view>\n        <view>{{ params[0]['axisValue'] }}</view>\n        <view v-for=\"item in params\">\n          <view>\n            <text>{{ item.seriesName }}</text>\n            <text>{{ item.value }}</text>\n          </view>\n        </view>\n      </view>\n    </view>\n  </view>\n</template>\n\n<script>\n// nvue 不需要引入\n// #ifdef VUE2\nimport * as echarts from '@/uni_modules/lime-echart/static/echarts.min'\n// #endif\n// #ifdef VUE3\n// #ifdef MP\n// 由于vue3 使用vite 不支持umd格式的包，小程序依然可以使用，但需要使用require\nconst echarts = require('../../static/echarts.min')\n// #endif\n// #ifndef MP\n// 由于 vue3 使用vite 不支持umd格式的包，故引入npm的包\nimport * as echarts from 'echarts/dist/echarts.esm'\n// #endif\n// #endif\nexport default {\n  data() {\n    return {\n      showTip: false,\n      position: [],\n      params: [],\n      option: {\n        tooltip: {\n          trigger: 'axis',\n          // shadowBlur: 0,\n          textStyle: {\n            textShadowBlur: 0,\n          },\n          renderMode: 'richText',\n          position: (point, params, dom, rect, size) => {\n            // 假设自定义的tooltips尺寸\n            const box = [170, 170]\n            // 偏移\n            const offsetX = point[0] < size.viewSize[0] / 2 ? 20 : -box[0] - 20\n            const offsetY = point[1] < size.viewSize[1] / 2 ? 20 : -box[1] - 20\n            const x = point[0] + offsetX\n            const y = point[1] + offsetY\n\n            this.position = [x, y]\n            this.params = params\n          },\n          formatter: (params, ticket, callback) => {},\n        },\n        legend: {\n          data: ['邮件营销', '联盟广告', '视频广告', '直接访问', '搜索引擎'],\n        },\n        grid: {\n          left: '3%',\n          right: '4%',\n          bottom: '3%',\n          containLabel: true,\n        },\n        xAxis: {\n          type: 'category',\n          boundaryGap: false,\n          data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],\n        },\n        yAxis: {\n          type: 'value',\n        },\n        series: [\n          {\n            name: '邮件营销',\n            type: 'line',\n            stack: '总量',\n            data: [120, 132, 101, 134, 90, 230, 210],\n          },\n          {\n            name: '联盟广告',\n            type: 'line',\n            stack: '总量',\n            data: [220, 182, 191, 234, 290, 330, 310],\n          },\n          {\n            name: '视频广告',\n            type: 'line',\n            stack: '总量',\n            data: [150, 232, 201, 154, 190, 330, 410],\n          },\n          {\n            name: '直接访问',\n            type: 'line',\n            stack: '总量',\n            data: [320, 332, 301, 334, 390, 330, 320],\n          },\n          {\n            name: '搜索引擎',\n            type: 'line',\n            stack: '总量',\n            data: [820, 932, 901, 934, 1290, 1330, 1320],\n          },\n        ],\n      },\n    }\n  },\n\n  methods: {\n    init() {\n      // init(echarts, theme?:string, opts?:{}, chart => {})\n      // echarts 必填， 非nvue必填，nvue不用填\n      // theme 可选，应用的主题，目前只支持名称，如：'dark'\n      // opts = { // 可选\n      //\tlocale?: string  // 从 `5.0.0` 开始支持\n      // }\n      // chart => {} ， callback 返回图表实例\n      // setTimeout(()=>{\n      // \tthis.$refs.chart.init(echarts, chart => {\n      // \t\tchart.setOption(this.option);\n      // \t});\n      // },300)\n      this.$refs.chart.init(echarts, (chart) => {\n        chart.setOption(this.option)\n\n        // 监听tooltip显示事件\n        chart.on('showTip', (params) => {\n          this.showTip = true\n          console.log('showTip::')\n        })\n        chart.on('hideTip', (params) => {\n          setTimeout(() => {\n            this.showTip = false\n          }, 300)\n        })\n\n        setTimeout(() => {\n          const option = {\n            tooltip: {\n              trigger: 'axis',\n              // shadowBlur: 0,\n              textStyle: {\n                textShadowBlur: 0,\n              },\n              renderMode: 'richText',\n            },\n            legend: {\n              data: ['邮件营销', '联盟广告', '视频广告', '直接访问', '搜索引擎'],\n            },\n            grid: {\n              left: '3%',\n              right: '4%',\n              bottom: '3%',\n              containLabel: true,\n            },\n            xAxis: {\n              type: 'category',\n              boundaryGap: false,\n              data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],\n            },\n            yAxis: {\n              type: 'value',\n            },\n            series: [\n              {\n                name: '邮件营销',\n                type: 'line',\n                stack: '总量',\n                data: [1120, 132, 101, 134, 90, 230, 210],\n              },\n              {\n                name: '联盟广告',\n                type: 'line',\n                stack: '总量',\n                data: [220, 182, 191, 234, 290, 330, 310],\n              },\n              {\n                name: '视频广告',\n                type: 'line',\n                stack: '总量',\n                data: [150, 632, 201, 154, 190, 330, 410],\n              },\n              {\n                name: '直接访问',\n                type: 'line',\n                stack: '总量',\n                data: [820, 332, 301, 334, 390, 330, 320],\n              },\n              {\n                name: '搜索引擎',\n                type: 'line',\n                stack: '总量',\n                data: [820, 932, 901, 934, 1290, 1330, 1320],\n              },\n            ],\n          }\n          chart.setOption(option)\n        }, 1000)\n      })\n    },\n    save() {\n      this.$refs.chart.canvasToTempFilePath({\n        success(res) {\n          console.log('res::::', res)\n        },\n      })\n    },\n  },\n}\n</script>\n<style>\n.customTooltips {\n  position: absolute;\n  background-color: rgba(255, 255, 255, 0.8);\n  padding: 20rpx;\n}\n</style>\n"
  },
  {
    "path": "src/uni_modules/lime-echart/package.json",
    "content": "{\n  \"id\": \"lime-echart\",\n  \"displayName\": \"echarts\",\n  \"version\": \"0.9.8\",\n  \"description\": \"echarts 全端兼容，一款使echarts图表能跑在uniapp各端中的插件, 支持uniapp/uniappx(web,ios,安卓)\",\n  \"keywords\": [\n    \"echarts\",\n    \"canvas\",\n    \"图表\",\n    \"可视化\"\n],\n  \"repository\": \"https://gitee.com/liangei/lime-echart\",\n  \"engines\": {\n    \"HBuilderX\": \"^3.6.4\"\n  },\n  \"dcloudext\": {\n    \"sale\": {\n      \"regular\": {\n        \"price\": \"0.00\"\n      },\n      \"sourcecode\": {\n        \"price\": \"0.00\"\n      }\n    },\n    \"contact\": {\n      \"qq\": \"\"\n    },\n    \"declaration\": {\n      \"ads\": \"无\",\n      \"data\": \"无\",\n      \"permissions\": \"无\"\n    },\n    \"npmurl\": \"\",\n    \"type\": \"component-vue\"\n  },\n  \"uni_modules\": {\n    \"dependencies\": [],\n    \"encrypt\": [],\n    \"platforms\": {\n      \"cloud\": {\n        \"tcb\": \"y\",\n        \"aliyun\": \"y\",\n        \"alipay\": \"n\"\n      },\n      \"client\": {\n        \"App\": {\n            \"app-vue\": \"y\",\n            \"app-nvue\": \"y\",\n            \"app-uvue\": \"y\",\n            \"app-harmony\": \"u\"\n        },\n        \"H5-mobile\": {\n          \"Safari\": \"y\",\n          \"Android Browser\": \"y\",\n          \"微信浏览器(Android)\": \"y\",\n          \"QQ浏览器(Android)\": \"y\"\n        },\n        \"H5-pc\": {\n          \"Chrome\": \"u\",\n          \"IE\": \"u\",\n          \"Edge\": \"u\",\n          \"Firefox\": \"u\",\n          \"Safari\": \"u\"\n        },\n        \"小程序\": {\n          \"微信\": \"y\",\n          \"阿里\": \"y\",\n          \"百度\": \"y\",\n          \"字节跳动\": \"y\",\n          \"QQ\": \"y\",\n          \"钉钉\": \"u\",\n          \"快手\": \"u\",\n          \"飞书\": \"u\",\n          \"京东\": \"u\"\n        },\n        \"快应用\": {\n          \"华为\": \"u\",\n          \"联盟\": \"u\"\n        },\n        \"Vue\": {\n          \"vue2\": \"y\",\n          \"vue3\": \"y\"\n        }\n      }\n    }\n  },\n  \"dependencies\": {\n    \"echarts\": \"^5.4.1\",\n    \"zrender\": \"^5.4.3\"\n  }\n}"
  },
  {
    "path": "src/uni_modules/lime-echart/readme.md",
    "content": "# echarts 图表 <span style=\"font-size:16px;\">👑👑👑👑👑 <span style=\"background:#ff9d00;padding:2px 4px;color:#fff;font-size:10px;border-radius: 3px;\">全端</span></span>\r\n> 一个基于 JavaScript 的开源可视化图表库   [查看更多](https://limeui.qcoon.cn/#/echart) <br>\r\n> 基于 echarts 做了兼容处理，更多示例请访问  [uni示例](https://limeui.qcoon.cn/#/echart-example) | [官方示例](https://echarts.apache.org/examples/zh/index.html)  <br>\r\n\r\n\r\n## 平台兼容\r\n\r\n| H5  | 微信小程序 | 支付宝小程序 | 百度小程序 | 头条小程序 | QQ 小程序 | App  |\r\n| --- | ---------- | ------------ | ---------- | ---------- | --------- | ---- |\r\n| √   | √          | √         | √      | √       | √      | √ |\r\n\r\n\r\n## 安装\r\n- 第一步：在市场导入 [百度图表](https://ext.dcloud.net.cn/plugin?id=4899) \r\n- 第二步：选择插件依赖：<br>\r\n  1、可以选插件内的`echarts`包或自定义包，自定义包[下载地址](https://echarts.apache.org/zh/builder.html)<br>\r\n  2、或者使用`npm`安装`echarts`\t\r\n\r\n**注意** \r\n* 🔔 echarts 5.3.0及以上\r\n* 🔔 如果是 `cli` 项目请下载插件到`src`目录下的`uni_modules`,没有这个目录就创建一个\r\n\r\n\r\n## 代码演示\r\n\r\n### Vue2\r\n- 引入依赖，可以是插件内提供或自己下载的[自定义包](https://echarts.apache.org/zh/builder.html)，也可以是`npm`包\r\n\r\n```html\r\n<view style=\"width:750rpx; height:750rpx\"><l-echart ref=\"chartRef\" @finished=\"init\"></l-echart></view>\r\n```\r\n\r\n```js\r\n// 插件内的 三选一\r\nimport * as echarts from '@/uni_modules/lime-echart/static/echarts.min'\r\n// 自定义的 三选一 下载后放入项目的路径\r\nimport * as echarts from 'xxx/echarts.min'\r\n// npm包 三选一 需要在控制台 输入命令：npm install echarts\r\nimport * as echarts from 'echarts'\r\n```\r\n\r\n```js\r\nexport default {\r\n\tdata() {\r\n\t\treturn {\r\n\t\t\toption: {\r\n\t\t\t\ttooltip: {\r\n\t\t\t\t\ttrigger: 'axis',\r\n\t\t\t\t\taxisPointer: {\r\n\t\t\t\t\t\ttype: 'shadow' \r\n\t\t\t\t\t},\r\n\t\t\t\t\tconfine: true\r\n\t\t\t\t},\r\n\t\t\t\tlegend: {\r\n\t\t\t\t\tdata: ['热度', '正面', '负面']\r\n\t\t\t\t},\r\n\t\t\t\tgrid: {\r\n\t\t\t\t\tleft: 20,\r\n\t\t\t\t\tright: 20,\r\n\t\t\t\t\tbottom: 15,\r\n\t\t\t\t\ttop: 40,\r\n\t\t\t\t\tcontainLabel: true\r\n\t\t\t\t},\r\n\t\t\t\txAxis: [\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttype: 'value',\r\n\t\t\t\t\t\taxisLine: {\r\n\t\t\t\t\t\t\tlineStyle: {\r\n\t\t\t\t\t\t\t\tcolor: '#999999'\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t\taxisLabel: {\r\n\t\t\t\t\t\t\tcolor: '#666666'\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t],\r\n\t\t\t\tyAxis: [\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttype: 'category',\r\n\t\t\t\t\t\taxisTick: { show: false },\r\n\t\t\t\t\t\tdata: ['汽车之家', '今日头条', '百度贴吧', '一点资讯', '微信', '微博', '知乎'],\r\n\t\t\t\t\t\taxisLine: {\r\n\t\t\t\t\t\t\tlineStyle: {\r\n\t\t\t\t\t\t\t\tcolor: '#999999'\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t\taxisLabel: {\r\n\t\t\t\t\t\t\tcolor: '#666666'\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t],\r\n\t\t\t\tseries: [\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tname: '热度',\r\n\t\t\t\t\t\ttype: 'bar',\r\n\t\t\t\t\t\tlabel: {\r\n\t\t\t\t\t\t\tnormal: {\r\n\t\t\t\t\t\t\t\tshow: true,\r\n\t\t\t\t\t\t\t\tposition: 'inside'\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t\tdata: [300, 270, 340, 344, 300, 320, 310],\r\n\t\t\t\t\t},\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tname: '正面',\r\n\t\t\t\t\t\ttype: 'bar',\r\n\t\t\t\t\t\tstack: '总量',\r\n\t\t\t\t\t\tlabel: {\r\n\t\t\t\t\t\t\tnormal: {\r\n\t\t\t\t\t\t\t\tshow: true\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t\tdata: [120, 102, 141, 174, 190, 250, 220]\r\n\t\t\t\t\t},\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tname: '负面',\r\n\t\t\t\t\t\ttype: 'bar',\r\n\t\t\t\t\t\tstack: '总量',\r\n\t\t\t\t\t\tlabel: {\r\n\t\t\t\t\t\t\tnormal: {\r\n\t\t\t\t\t\t\t\tshow: true,\r\n\t\t\t\t\t\t\t\tposition: 'left'\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t\tdata: [-20, -32, -21, -34, -90, -130, -110]\r\n\t\t\t\t\t}\r\n\t\t\t\t]\r\n\t\t\t},\r\n\t\t};\r\n\t},\r\n\t// 组件能被调用必须是组件的节点已经被渲染到页面上\r\n\tmethods: {\r\n\t\tasync init() {\r\n\t\t\t// chart 图表实例不能存在data里\r\n\t\t\tconst chart = await this.$refs.chartRef.init(echarts);\r\n\t\t\tchart.setOption(this.option)\r\n\t\t}\r\n\t}\r\n}\r\n```\r\n\r\n### Vue3\r\n- 小程序可以使用`require`引入插件内提供或自己下载的[自定义包](https://echarts.apache.org/zh/builder.html)\r\n- `require`仅支持相对路径,不支持路径别名\r\n- 非小程序使用 `npm` 包\r\n\r\n\r\n```html\r\n<view style=\"width:750rpx; height:750rpx\"><l-echart ref=\"chartRef\"></l-echart></view>\r\n```\r\n\r\n```js\r\n// 小程序 二选一 \r\n// 插件内的 二选一 \r\nconst echarts = require('../../uni_modules/lime-echart/static/echarts.min');\r\n// 自定义的 二选一 下载后放入项目的路径\r\nconst echarts = require('xxx/xxx/echarts');\r\n\r\n//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n// 非小程序 \r\n// 需要在控制台 输入命令：npm install echarts\r\nimport * as echarts from 'echarts'\r\n```\r\n\r\n```js\r\n\r\nconst chartRef = ref(null)\r\nconst option = {\r\n\ttooltip: {\r\n\t\ttrigger: 'axis',\r\n\t\taxisPointer: {\r\n\t\t\ttype: 'shadow' \r\n\t\t},\r\n\t\tconfine: true\r\n\t},\r\n\tlegend: {\r\n\t\tdata: ['热度', '正面', '负面']\r\n\t},\r\n\tgrid: {\r\n\t\tleft: 20,\r\n\t\tright: 20,\r\n\t\tbottom: 15,\r\n\t\ttop: 40,\r\n\t\tcontainLabel: true\r\n\t},\r\n\txAxis: [\r\n\t\t{\r\n\t\t\ttype: 'value',\r\n\t\t\taxisLine: {\r\n\t\t\t\tlineStyle: {\r\n\t\t\t\t\tcolor: '#999999'\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t\taxisLabel: {\r\n\t\t\t\tcolor: '#666666'\r\n\t\t\t}\r\n\t\t}\r\n\t],\r\n\tyAxis: [\r\n\t\t{\r\n\t\t\ttype: 'category',\r\n\t\t\taxisTick: { show: false },\r\n\t\t\tdata: ['汽车之家', '今日头条', '百度贴吧', '一点资讯', '微信', '微博', '知乎'],\r\n\t\t\taxisLine: {\r\n\t\t\t\tlineStyle: {\r\n\t\t\t\t\tcolor: '#999999'\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t\taxisLabel: {\r\n\t\t\t\tcolor: '#666666'\r\n\t\t\t}\r\n\t\t}\r\n\t],\r\n\tseries: [\r\n\t\t{\r\n\t\t\tname: '热度',\r\n\t\t\ttype: 'bar',\r\n\t\t\tlabel: {\r\n\t\t\t\tnormal: {\r\n\t\t\t\t\tshow: true,\r\n\t\t\t\t\tposition: 'inside'\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t\tdata: [300, 270, 340, 344, 300, 320, 310],\r\n\t\t},\r\n\t\t{\r\n\t\t\tname: '正面',\r\n\t\t\ttype: 'bar',\r\n\t\t\tstack: '总量',\r\n\t\t\tlabel: {\r\n\t\t\t\tnormal: {\r\n\t\t\t\t\tshow: true\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t\tdata: [120, 102, 141, 174, 190, 250, 220]\r\n\t\t},\r\n\t\t{\r\n\t\t\tname: '负面',\r\n\t\t\ttype: 'bar',\r\n\t\t\tstack: '总量',\r\n\t\t\tlabel: {\r\n\t\t\t\tnormal: {\r\n\t\t\t\t\tshow: true,\r\n\t\t\t\t\tposition: 'left'\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t\tdata: [-20, -32, -21, -34, -90, -130, -110]\r\n\t\t}\r\n\t]\r\n};\r\n\r\n\r\nonMounted( ()=>{\r\n\t// 组件能被调用必须是组件的节点已经被渲染到页面上\r\n\tsetTimeout(async()=>{\r\n\t\tif(!chartRef.value) return\r\n\t\tconst myChart = await chartRef.value.init(echarts)\r\n\t\tmyChart.setOption(option)\r\n\t},300)\r\n})\r\n\r\n```\r\n\r\n\r\n### Uvue\r\n- Uvue和Nvue不需要引入`echarts`，因为它们的实现方式是`webview`\r\n- uniapp x需要HBX 4.13以上\r\n\r\n```html\r\n<view style=\"width: 100%; height: 408px;\">\r\n\t<l-echart ref=\"chartRef\" @finished=\"init\"></l-echart>\r\n</view>\r\n```\r\n\r\n```js\r\n// @ts-nocheck\r\n// #ifdef H5\r\nimport * as echarts from 'echarts/dist/echarts.esm.js'\r\n// #endif\r\nconst chartRef = ref<LEchartComponentPublicInstance|null>(null);\r\nconst init = async () => {\r\n\tif(chartRef.value== null) return\r\n\t// #ifdef APP\r\n\tconst chart = await chartRef.value!.init(null)\r\n\t// #endif\r\n\t// #ifdef H5\r\n\tconst chart = await chartRef.value!.init(echarts, null)\r\n\t// #endif\r\n\tchart.setOption(option)\r\n}\r\n```\r\n\r\n\r\n## 数据更新\r\n- 1、使用 `ref` 可获取`setOption`设置更新\r\n- 2、也可以拿到图表实例`chart`设置`myChart.setOption(data)`\r\n\r\n```js\r\n// ref\r\nthis.$refs.chart.setOption(data)\r\n\r\n// 图表实例\r\nmyChart.setOption(data)\r\n```\r\n\r\n## 图表大小\r\n- 在有些场景下，我们希望当容器大小改变时，图表的大小也相应地改变。\r\n\r\n```js\r\n// 默认获取容器尺寸\r\nthis.$refs.chart.resize()\r\n// 指定尺寸\r\nthis.$refs.chart.resize({width: 375, height: 375})\r\n```\r\n\r\n## 自定义Tooltips\r\n- uvue\\nvue 不支持\r\n由于除H5之外都不存在dom，但又有tooltips个性化的需求，代码就不贴了，看示例吧\r\n```\r\n代码位于/uni_modules/lime-echart/component/lime-echart\r\n```\r\n\r\n\r\n## 插件标签\r\n- 默认 l-echart 为 component\r\n- 默认 lime-echart 为 demo\r\n```html\r\n // 在任意地方使用可查看domo, 代码位于/uni_modules/lime-echart/component/lime-echart\r\n<lime-echart></lime-echart>\r\n```\r\n\r\n\r\n## 常见问题\r\n- 钉钉小程序 由于没有`measureText`,模拟的`measureText`又无法得到当前字体的`fontWeight`,故可能存在估计不精细的问题\r\n- 微信小程序 `2d` 只支持 真机调试2.0\r\n- 微信开发工具会出现 `canvas` 不跟随页面的情况，真机不影响\r\n- 微信开发工具会出现 `canvas` 层级过高的问题，真机一般不受影响，可以先测只有两个元素的页面看是否会有层级问题。\r\n- toolbox 不支持 `saveImage`\r\n- echarts 5.3.0 的 lines 不支持 trailLength，故需设置为 `0`\r\n- dataZoom H5不要设置 `showDetail` \r\n- 如果微信小程序的`tooltip`文字有阴影，可能是微信的锅，临时解决方法是`tooltip.shadowBlur = 0`\r\n- 如果钉钉小程序上传时报安全问题`Uint8Clamped`,可以向钉钉反馈是安全代码扫描把Uint8Clamped数组错误识别了，也可以在 echarts 文件修改`Uint8Clamped`\r\n```js\r\n// 找到这段代码把代码中`Uint8Clamped`改成`Uint8_Clamped`，再把下划线去掉，不过直接去掉`Uint8Clamped`也是可行的\r\n// [\"Int8\",\"Uint8\",\"Uint8Clamped\",\"Int16\",\"Uint16\",\"Int32\",\"Uint32\",\"Float32\",\"Float64\"],(function(t,e){return t[\"[object \"+e+\"Array]\"]\r\n// 改成如下\r\n[\"Int8\",\"Uint8\",\"Uint8_Clamped\",\"Int16\",\"Uint16\",\"Int32\",\"Uint32\",\"Float32\",\"Float64\"],(function(t,e){return t[\"[object \"+e.replace('_','')+\"Array]\"]\r\n```\r\n\r\n### vue3\r\n如果您是使用 **vite + vue3** 非微信小程序可能会遇到`echarts`文件缺少`wx`判断导致无法使用或缺少`tooltip`<br>\r\n\r\n方式一：可以在`echarts.min.js`文件开头增加以下内容，参考插件内的echart.min.js的做法\r\n\r\n```js\r\nlet global = null\r\nlet wx = uni\r\n```\r\n\r\n方式二：在`vite.config.js`的`define`设置环境\r\n\r\n```js\r\n//  或者在`vite.config.js`的`define`设置环境\r\nimport { defineConfig } from 'vite';\nimport uni from '@dcloudio/vite-plugin-uni';\r\n\r\nconst define = {}\r\nif(![\"mp-weixin\", \"h5\", \"web\"].includes(process.env.UNI_PLATFORM)) {\r\n\tdefine['global'] =  null\r\n\tdefine['wx'] =  'uni'\r\n}\nexport default defineConfig({\n\tplugins: [uni()],\r\n\tdefine\n});\r\n```\r\n\r\n\r\n## Props\r\n\r\n| 参数             | 说明                                                            | 类型             | 默认值        | 版本 \t|\r\n| ---------------  | --------                                                        | -------         | ------------ | ----- \t|\r\n| custom-style     | 自定义样式                                                      |   `string`       | -            | -     \t|\r\n| type             | 指定 canvas 类型                                \t\t\t\t |    `string`      | `2d`         |   \t    |\r\n| is-disable-scroll | 触摸图表时是否禁止页面滚动                                       |    `boolean`     | `false`     |   \t    |\r\n| beforeDelay       |  延迟初始化 (毫秒)                       \t\t\t\t\t\t|    `number`     | `30`     |   \t    |\r\n| enableHover       |  PC端使用鼠标悬浮                       \t\t\t\t\t\t|    `boolean`     | `false`     |   \t    |\r\n| landscape       |  是否旋转90deg,模拟横屏效果                       \t\t\t\t\t\t|    `boolean`     | `false`     |   \t    |\r\n\r\n## 事件\r\n\r\n| 参数                    | 说明                                                                                                             |\r\n| ---------------        | ---------------                                                                                                  |\r\n| init(echarts, chart => {})  | 初始化调用函数,第一个参数是传入`echarts`,第二个参数是回调函数，回调函数的参数是 `chart` 实例                                           |  \r\n| setChart(chart => {})        | 已经初始化后，请使用这个方法，是个回调函数，参数是 `chart` 实例                  |  \r\n| setOption(data)        | [图表配置项](https://echarts.apache.org/zh/option.html#title)，用于更新 ，传递是数据 `option`  |  \r\n| clear()                | 清空当前实例，会移除实例中所有的组件和图表。  |  \r\n| dispose()              | 销毁实例  |  \r\n| showLoading()          | 显示加载  |  \r\n| hideLoading()          | 隐藏加载  |  \r\n| [canvasToTempFilePath](https://uniapp.dcloud.io/api/canvas/canvasToTempFilePath.html#canvastotempfilepath)(opt)  | 用于生成图片,与官方使用方法一致，但不需要传`canvasId`  |  \r\n\r\n\r\n## 打赏\r\n如果你觉得本插件，解决了你的问题，赠人玫瑰，手留余香。  \r\n![](https://testingcf.jsdelivr.net/gh/liangei/image@1.9/alipay.png)\r\n![](https://testingcf.jsdelivr.net/gh/liangei/image@1.9/wpay.png)"
  },
  {
    "path": "src/uni_modules/lime-echart/static/uni.webview.1.5.5.js",
    "content": "!function(e,n){\"object\"==typeof exports&&\"undefined\"!=typeof module?module.exports=n():\"function\"==typeof define&&define.amd?define(n):(e=e||self).uni=n()}(this,(function(){\"use strict\";try{var e={};Object.defineProperty(e,\"passive\",{get:function(){!0}}),window.addEventListener(\"test-passive\",null,e)}catch(e){}var n=Object.prototype.hasOwnProperty;function i(e,i){return n.call(e,i)}var t=[];function o(){return window.__dcloud_weex_postMessage||window.__dcloud_weex_}function a(){return window.__uniapp_x_postMessage||window.__uniapp_x_}var r=function(e,n){var i={options:{timestamp:+new Date},name:e,arg:n};if(a()){if(\"postMessage\"===e){var r={data:n};return window.__uniapp_x_postMessage?window.__uniapp_x_postMessage(r):window.__uniapp_x_.postMessage(JSON.stringify(r))}var d={type:\"WEB_INVOKE_APPSERVICE\",args:{data:i,webviewIds:t}};window.__uniapp_x_postMessage?window.__uniapp_x_postMessageToService(d):window.__uniapp_x_.postMessageToService(JSON.stringify(d))}else if(o()){if(\"postMessage\"===e){var s={data:[n]};return window.__dcloud_weex_postMessage?window.__dcloud_weex_postMessage(s):window.__dcloud_weex_.postMessage(JSON.stringify(s))}var w={type:\"WEB_INVOKE_APPSERVICE\",args:{data:i,webviewIds:t}};window.__dcloud_weex_postMessage?window.__dcloud_weex_postMessageToService(w):window.__dcloud_weex_.postMessageToService(JSON.stringify(w))}else{if(!window.plus)return window.parent.postMessage({type:\"WEB_INVOKE_APPSERVICE\",data:i,pageId:\"\"},\"*\");if(0===t.length){var u=plus.webview.currentWebview();if(!u)throw new Error(\"plus.webview.currentWebview() is undefined\");var g=u.parent(),v=\"\";v=g?g.id:u.id,t.push(v)}if(plus.webview.getWebviewById(\"__uniapp__service\"))plus.webview.postMessageToUniNView({type:\"WEB_INVOKE_APPSERVICE\",args:{data:i,webviewIds:t}},\"__uniapp__service\");else{var c=JSON.stringify(i);plus.webview.getLaunchWebview().evalJS('UniPlusBridge.subscribeHandler(\"'.concat(\"WEB_INVOKE_APPSERVICE\",'\",').concat(c,\",\").concat(JSON.stringify(t),\");\"))}}},d={navigateTo:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;r(\"navigateTo\",{url:encodeURI(n)})},navigateBack:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.delta;r(\"navigateBack\",{delta:parseInt(n)||1})},switchTab:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;r(\"switchTab\",{url:encodeURI(n)})},reLaunch:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;r(\"reLaunch\",{url:encodeURI(n)})},redirectTo:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;r(\"redirectTo\",{url:encodeURI(n)})},getEnv:function(e){a()?e({uvue:!0}):o()?e({nvue:!0}):window.plus?e({plus:!0}):e({h5:!0})},postMessage:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};r(\"postMessage\",e.data||{})}},s=/uni-app/i.test(navigator.userAgent),w=/Html5Plus/i.test(navigator.userAgent),u=/complete|loaded|interactive/;var g=window.my&&navigator.userAgent.indexOf([\"t\",\"n\",\"e\",\"i\",\"l\",\"C\",\"y\",\"a\",\"p\",\"i\",\"l\",\"A\"].reverse().join(\"\"))>-1;var v=window.swan&&window.swan.webView&&/swan/i.test(navigator.userAgent);var c=window.qq&&window.qq.miniProgram&&/QQ/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var p=window.tt&&window.tt.miniProgram&&/toutiaomicroapp/i.test(navigator.userAgent);var _=window.wx&&window.wx.miniProgram&&/micromessenger/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var m=window.qa&&/quickapp/i.test(navigator.userAgent);var f=window.ks&&window.ks.miniProgram&&/micromessenger/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var l=window.tt&&window.tt.miniProgram&&/Lark|Feishu/i.test(navigator.userAgent);var E=window.jd&&window.jd.miniProgram&&/micromessenger/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var x=window.xhs&&window.xhs.miniProgram&&/xhsminiapp/i.test(navigator.userAgent);for(var S,h=function(){window.UniAppJSBridge=!0,document.dispatchEvent(new CustomEvent(\"UniAppJSBridgeReady\",{bubbles:!0,cancelable:!0}))},y=[function(e){if(s||w)return window.__uniapp_x_postMessage||window.__uniapp_x_||window.__dcloud_weex_postMessage||window.__dcloud_weex_?document.addEventListener(\"DOMContentLoaded\",e):window.plus&&u.test(document.readyState)?setTimeout(e,0):document.addEventListener(\"plusready\",e),d},function(e){if(_)return window.WeixinJSBridge&&window.WeixinJSBridge.invoke?setTimeout(e,0):document.addEventListener(\"WeixinJSBridgeReady\",e),window.wx.miniProgram},function(e){if(c)return window.QQJSBridge&&window.QQJSBridge.invoke?setTimeout(e,0):document.addEventListener(\"QQJSBridgeReady\",e),window.qq.miniProgram},function(e){if(g){document.addEventListener(\"DOMContentLoaded\",e);var n=window.my;return{navigateTo:n.navigateTo,navigateBack:n.navigateBack,switchTab:n.switchTab,reLaunch:n.reLaunch,redirectTo:n.redirectTo,postMessage:n.postMessage,getEnv:n.getEnv}}},function(e){if(v)return document.addEventListener(\"DOMContentLoaded\",e),window.swan.webView},function(e){if(p)return document.addEventListener(\"DOMContentLoaded\",e),window.tt.miniProgram},function(e){if(m){window.QaJSBridge&&window.QaJSBridge.invoke?setTimeout(e,0):document.addEventListener(\"QaJSBridgeReady\",e);var n=window.qa;return{navigateTo:n.navigateTo,navigateBack:n.navigateBack,switchTab:n.switchTab,reLaunch:n.reLaunch,redirectTo:n.redirectTo,postMessage:n.postMessage,getEnv:n.getEnv}}},function(e){if(f)return window.WeixinJSBridge&&window.WeixinJSBridge.invoke?setTimeout(e,0):document.addEventListener(\"WeixinJSBridgeReady\",e),window.ks.miniProgram},function(e){if(l)return document.addEventListener(\"DOMContentLoaded\",e),window.tt.miniProgram},function(e){if(E)return window.JDJSBridgeReady&&window.JDJSBridgeReady.invoke?setTimeout(e,0):document.addEventListener(\"JDJSBridgeReady\",e),window.jd.miniProgram},function(e){if(x)return window.xhs.miniProgram},function(e){return document.addEventListener(\"DOMContentLoaded\",e),d}],M=0;M<y.length&&!(S=y[M](h));M++);S||(S={});var P=\"undefined\"!=typeof uni?uni:{};if(!P.navigateTo)for(var b in S)i(S,b)&&(P[b]=S[b]);return P.webView=S,P}));\r\n"
  },
  {
    "path": "src/uni_modules/lime-echart/static/uvue.html",
    "content": "<!DOCTYPE html>\r\n<html lang=\"zh\">\r\n\t<head>\r\n\t\t<meta charset=\"UTF-8\">\r\n\t\t<meta name=\"viewport\"\r\n\t\t\tcontent=\"width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no\">\r\n\t\t<meta http-equiv=\"X-UA-Compatible\" content=\"ie=edge\">\r\n\t\t<title></title>\r\n\t\t<style type=\"text/css\">\r\n\t\t\thtml,\r\n\t\t\tbody,\r\n\t\t\t.canvas {\r\n\t\t\t\tpadding: 0;\r\n\t\t\t\tmargin: 0;\r\n\t\t\t\toverflow-y: hidden;\r\n\t\t\t\tbackground-color: transparent;\r\n\t\t\t\twidth: 100%;\r\n\t\t\t\theight: 100%;\r\n\t\t\t}\r\n\t\t</style>\r\n\t</head>\r\n\t<body>\r\n\t\t<div class=\"canvas\" id=\"limeChart\"></div>\r\n\t\t<script type=\"text/javascript\" src=\"./uni.webview.1.5.5.js\"></script>\r\n\t\t<script type=\"text/javascript\" src=\"./echarts.min.js\"></script>\r\n\t\t<script type=\"text/javascript\" src=\"./ecStat.min.js\"></script>\r\n\t\t<!-- <script type=\"text/javascript\" src=\"https://cdn.jsdelivr.net/npm/echarts-liquidfill@latest/dist/echarts-liquidfill.min.js\"></script> -->\r\n\t\t<script>\r\n\t\t\tlet chart = null;\r\n\t\t\tlet cache = [];\r\n\t\t\tconsole.log = function() {\r\n\t\t\t\temit('log', {\r\n\t\t\t\t\tlog: arguments,\r\n\t\t\t\t})\r\n\t\t\t}\r\n\r\n\t\t\tfunction emit(event, data) {\r\n\t\t\t\tpostMessage({\r\n\t\t\t\t\tevent,\r\n\t\t\t\t\tdata\r\n\t\t\t\t})\r\n\t\t\t\tcache = []\r\n\t\t\t}\r\n\r\n\t\t\tfunction postMessage(data) {\r\n\t\t\t\tuni.webView.postMessage({\r\n\t\t\t\t\tdata\r\n\t\t\t\t})\r\n\t\t\t\t// window.__uniapp_x_.postMessage(JSON.stringify(data))\r\n\t\t\t};\r\n\r\n\t\t\tfunction stringify(key, value) {\r\n\t\t\t\tif (typeof value === 'object' && value !== null) {\r\n\t\t\t\t\tif (cache.indexOf(value) !== -1) {\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcache.push(value);\r\n\t\t\t\t}\r\n\t\t\t\treturn value;\r\n\t\t\t}\r\n\r\n\t\t\tfunction parse(name, callback, options) {\r\n\t\t\t\tconst optionNameReg = /[\\w]+\\.setOption\\(([\\w]+\\.)?([\\w]+)\\)/\r\n\t\t\t\tif (optionNameReg.test(callback)) {\r\n\t\t\t\t\tconst optionNames = callback.match(optionNameReg)\r\n\t\t\t\t\tif (optionNames[1]) {\r\n\t\t\t\t\t\tconst _this = optionNames[1].split('.')[0]\r\n\t\t\t\t\t\twindow[_this] = {}\r\n\t\t\t\t\t\twindow[_this][optionNames[2]] = options\r\n\t\t\t\t\t\treturn optionNames[2]\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\treturn null\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\treturn null\r\n\t\t\t}\r\n\r\n\t\t\tfunction init(callback, options, opts, theme) {\r\n\t\t\t\tif (!chart) {\r\n\t\t\t\t\tchart = echarts.init(document.getElementById('limeChart'), theme, opts)\r\n\r\n\t\t\t\t\tif (options) {\r\n\t\t\t\t\t\tchart.setOption(options)\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tfunction on(data) {\r\n\t\t\t\tif (chart && data.length > 0) {\r\n\t\t\t\t\tconst [type, query] = data\r\n\t\t\t\t\tconst key = `${type}${JSON.stringify(query||'')}`\r\n\t\t\t\t\tif (query) {\r\n\t\t\t\t\t\tchart.on(type, query, function(options) {\r\n\t\t\t\t\t\t\tvar obj = {};\r\n\t\t\t\t\t\t\tObject.keys(options).forEach(function(key) {\r\n\t\t\t\t\t\t\t\tif (key != 'event') {\r\n\t\t\t\t\t\t\t\t\tobj[key] = options[key];\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t});\r\n\t\t\t\t\t\t\temit(key, {\r\n\t\t\t\t\t\t\t\tevent: key,\r\n\t\t\t\t\t\t\t\toptions: obj,\r\n\t\t\t\t\t\t\t});\r\n\t\t\t\t\t\t});\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tchart.on(type, function(options) {\r\n\t\t\t\t\t\t\tvar obj = {};\r\n\t\t\t\t\t\t\tObject.keys(options).forEach(function(key) {\r\n\t\t\t\t\t\t\t\tif (key != 'event') {\r\n\t\t\t\t\t\t\t\t\tobj[key] = options[key];\r\n\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t});\r\n\t\t\t\t\t\t\temit(key, {\r\n\t\t\t\t\t\t\t\tevent: key,\r\n\t\t\t\t\t\t\t\toptions: obj,\r\n\t\t\t\t\t\t\t});\r\n\t\t\t\t\t\t});\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfunction setChart(callback, options) {\r\n\t\t\t\tif (!callback) return\r\n\t\t\t\tif (chart && callback && options) {\r\n\t\t\t\t\tvar r = null\r\n\t\t\t\t\tconst name = parse('r', callback, options)\r\n\t\t\t\t\tif (name) this[name] = options\r\n\t\t\t\t\teval(`r = ${callback};`)\r\n\t\t\t\t\tif (r) {\r\n\t\t\t\t\t\tr(chart)\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tfunction setOption(data) {\r\n\t\t\t\tif (chart) chart.setOption(data[0], data[1])\r\n\t\t\t}\r\n\r\n\t\t\tfunction showLoading(data) {\r\n\t\t\t\tif (chart) chart.showLoading(data[0], data[1])\r\n\t\t\t}\r\n\r\n\t\t\tfunction hideLoading() {\r\n\t\t\t\tif (chart) chart.hideLoading()\r\n\t\t\t}\r\n\r\n\t\t\tfunction clear() {\r\n\t\t\t\tif (chart) chart.clear()\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfunction dispose() {\r\n\t\t\t\tif (chart) chart.dispose()\r\n\t\t\t}\r\n\r\n\t\t\tfunction resize(size) {\r\n\t\t\t\tif (chart) chart.resize(size)\r\n\t\t\t}\r\n\r\n\t\t\tfunction canvasToTempFilePath(opt) {\r\n\t\t\t\tif (chart) {\r\n\t\t\t\t\tdelete opt.success\r\n\t\t\t\t\tconst src = chart.getDataURL(opt)\r\n\t\t\t\t\tpostMessage({\r\n\t\t\t\t\t\t// event: 'file',\r\n\t\t\t\t\t\tfile: src\r\n\t\t\t\t\t})\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\tdocument.addEventListener('touchmove', () => {\r\n\t\t\t\t\r\n\t\t\t})\r\n\t\t</script>\r\n\t</body>\r\n</html>"
  },
  {
    "path": "src/utils/assets.ts",
    "content": "const imgBaseUrl = (import.meta as any).env.VITE_IMG_BASEURL // 图片请求路径\n\nfunction useImgAssets(filePath: string, { noCache = false } = {}) {\n  // 去掉 filePath 前面的 @ 符号\n  if (filePath.startsWith('@')) {\n    filePath = 'src' + filePath.slice(1)\n  }\n\n  const fileUrl = `${imgBaseUrl}${filePath}`\n\n  if (noCache) {\n    return fileUrl + '?t=' + Date.now()\n  } else {\n    return fileUrl\n  }\n}\n\nexport const useAssets = useImgAssets\n\nexport default useImgAssets\n"
  },
  {
    "path": "src/utils/index.ts",
    "content": "// 模块统一导出\nexport * from './qs'\nexport * from './router'\nexport * from './log'\nexport * from './assets'\n"
  },
  {
    "path": "src/utils/log.ts",
    "content": "/* 打印 控制台宣传信息 */\nexport const logPromotional = () => {\n  console.log(\n    `%c uni-plus %c 一个超超超好用的 uniapp 开发框架 作者：大麦大麦 %c`,\n    `background:#2d8cf0;border:1px solid #2d8cf0;\n      padding: 1px; border-radius: 4px 0 0 4px; color: #fff;`,\n    `border:1px solid #2d8cf0;\n      padding: 1px; border-radius: 0 4px 4px 0; color: #2d8cf0;`,\n    'background:transparent'\n  )\n  console.log('github：https://github.com/damai-dm/uni-plus')\n  console.log('掘金：https://juejin.cn/user/2368772393149325')\n}\n"
  },
  {
    "path": "src/utils/qs.ts",
    "content": "// 没必要为了 qs 一个简单的功能引入 qs，手写一个\nexport const qs = {\n  stringify: function (obj) {\n    return Object.keys(obj)\n      .map(key => encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]))\n      .join('&')\n  }\n}\n"
  },
  {
    "path": "src/utils/router.ts",
    "content": "import { pages, subPackages } from '@/pages.json'\nimport { useUserStore } from '@/store'\n\n/**\n * 根据路由路径，获取页面权限 permissionKeys: ['isNeedLogin', 'isVip', 'admin']\n **/\nexport const getPermissionKeysByPath = (path: string): string[] => {\n  let navigateToPage\n  if (path.split('/')[0] === 'pages') {\n    navigateToPage = pages.find(page => page.path === path)\n  } else {\n    navigateToPage = subPackages.find((page: Record<string, any>) => page.path === path)\n  }\n  return navigateToPage ? navigateToPage.permissionKeys || [] : []\n}\n\n/**\n * 获取上一页路由路径\n **/\nconst getLastPage = () => {\n  // getCurrentPages() 至少有1个元素，所以不再额外判断\n  // const lastPage = getCurrentPages().at(-1)\n  // 上面那个在低版本安卓中打包回报错，所以改用下面这个【虽然我加了src/interceptions/prototype.ts，但依然报错】\n  const pages = getCurrentPages()\n  return pages[pages.length - 1]\n}\n\n// 确保 decodeURIComponent 递归调用\nconst ensureDecodeURIComponent = (url: string) => {\n  if (url.startsWith('%')) {\n    return ensureDecodeURIComponent(decodeURIComponent(url))\n  }\n  return url\n}\n\n/**\n * 解析 url 得到 path 和 query\n * 比如输入url: /pages/login/index?redirect=%2Fpages%2Fdemo%2Fbase%2Froute-interceptor\n * 输出: {path: /pages/login/index, query: {redirect: /pages/demo/base/route-interceptor}}\n */\nconst getUrlObj = (url: string) => {\n  const [path, queryStr] = url.split('?')\n\n  if (!queryStr) {\n    return {\n      path,\n      query: {}\n    }\n  }\n  const query: Record<string, string> = {}\n  queryStr.split('&').forEach(item => {\n    const [key, value] = item.split('=')\n    query[key] = ensureDecodeURIComponent(value) // 这里需要统一 decodeURIComponent 一下，可以兼容h5和微信y\n  })\n  return { path, query }\n}\n\n/**\n * 根据当前路由路径，判定是否有 redirectPath 路由，如果有则跳转，没有则返回 false\n **/\nexport const redirectRouteTo = () => {\n  // 获取上一页路由路径\n  const lastPage = getLastPage()\n  const currRoute = (lastPage as any).$page\n  const { fullPath } = currRoute as { fullPath: string }\n  // 获取上一页路由路径的 query 参数\n  const { query } = getUrlObj(fullPath)\n  //\n  const { redirect } = query\n  if (redirect) {\n    uni.redirectTo({\n      url: redirect\n    })\n    return true\n  } else {\n    return false\n  }\n}\n\n/* 自定义指令 按钮权限控制 */\nexport const checkBtnPermission = (btnPermissions: string[]) => {\n  const store = useUserStore() // 放函数内是为了保证，每次调用都获取最新的用户权限\n  const userBtnPermissions = store.getUserBtnPermission // 用户已有按钮权限\n  const intersectionPermissions = btnPermissions.filter(item => userBtnPermissions.includes(item)) // 用户已有按钮权限与当前按钮权限的交集\n  return !!(intersectionPermissions.length === btnPermissions.length)\n}\n"
  },
  {
    "path": "stylelint.config.mjs",
    "content": "// prettier.config.mjs\n\n/** @type {import('stylelint').Config} */\nconst config = {\n  extends: [\n    'stylelint-config-recommended',\n    'stylelint-config-recommended-scss',\n    'stylelint-config-recommended-vue',\n    'stylelint-config-recess-order'\n  ],\n  overrides: [\n    // 扫描 .vue/html 文件中的<style>标签内的样式\n    {\n      files: ['**/*.{vue,html}'],\n      customSyntax: 'postcss-html'\n    },\n    {\n      files: ['**/*.{css,scss}'],\n      customSyntax: 'postcss-scss'\n    }\n  ],\n  rules: {\n    'no-empty-source': null,\n    // 处理不认识 rpx 问题\n    'unit-no-unknown': [\n      true,\n      {\n        ignoreUnits: ['rpx']\n      }\n    ],\n    // 处理小程序page标签不认识的问题\n    'selector-type-no-unknown': [\n      true,\n      {\n        ignoreTypes: ['page']\n      }\n    ]\n  }\n}\n\nexport default config\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"composite\": true,\n    \"skipLibCheck\": true,\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"Node\",\n    \"resolveJsonModule\": true,\n    \"noImplicitThis\": true,\n    \"allowSyntheticDefaultImports\": true,\n    \"allowJs\": true,\n    \"sourceMap\": true,\n    \"baseUrl\": \".\",\n    \"paths\": {\n      \"@/*\": [\"./src/*\"]\n    },\n    \"outDir\": \"dist\",\n    \"lib\": [\"esnext\", \"dom\"],\n    \"types\": [\"@dcloudio/types\", \"@uni-helper/uni-types\", \"@types/wechat-miniprogram\", \"wot-design-uni/global\"]\n  },\n  \"vueCompilerOptions\": {\n    \"plugins\": [\"@uni-helper/uni-types/volar-plugin\"]\n  },\n  \"exclude\": [\"node_modules\"],\n  \"include\": [\n    \"src/**/*.ts\",\n    \"src/**/*.js\",\n    \"src/**/*.d.ts\",\n    \"src/**/*.tsx\",\n    \"src/**/*.jsx\",\n    \"src/**/*.vue\",\n    \"src/**/*.json\"\n  ]\n}\n"
  },
  {
    "path": "unocss.config.ts",
    "content": "import {\n  type Preset,\n  defineConfig,\n  presetUno,\n  presetAttributify,\n  presetIcons,\n  transformerDirectives,\n  transformerVariantGroup,\n  SourceCodeTransformer\n} from 'unocss'\n\nimport { presetApplet, presetRemRpx, transformerApplet, transformerAttributify } from 'unocss-applet'\n\n// 判断是否是小程序\nconst isApplet = process.env?.UNI_PLATFORM?.startsWith('mp-') ?? false\n\nconst presets: Preset[] = []\nconst transformers: SourceCodeTransformer[] = []\n\n// 先判断是不是小程序，如果是小程序，则使用小程序的预设和转换器\nif (isApplet) {\n  // 使用小程序预设\n  presets.push(\n    // 小程序用官方预设\n    presetApplet(),\n    // 小程序用 rpx 预设\n    presetRemRpx()\n  )\n  transformers.push(\n    // 小程序用 @apply 功能\n    transformerApplet(),\n    // 小程序，解决与第三方框架样式冲突问题\n    transformerAttributify({\n      prefixedOnly: true, // 只支持以 `ul-` 开头的类名\n      prefix: 'ul'\n    })\n  )\n} else {\n  presets.push(\n    // 非小程序用官方预设\n    presetUno(),\n    // 解决与第三方框架样式冲突问题\n    presetAttributify({\n      prefixedOnly: true, // 只支持以 `ul-` 开头的类名\n      prefix: 'ul'\n    })\n  )\n  transformers.push(\n    // 启用 @apply 功能，比如：\n    // .custom - div { @apply text-center my-0 font-medium } =>\n    // .custom - div { margin-top: 0rem; margin-bottom: 0rem; text-align: center; font-weight: 500;}\n    transformerDirectives(),\n    // 启用 () 分组功能，比如：\n    // <div class=\"hover:(bg-gray-400 font-medium) font-(light mono)\"/> =>\n    // <div class=\"hover:bg-gray-400 hover:font-medium font-light font-mono\"/>\n    transformerVariantGroup()\n  )\n}\n\n/* 公共部分 */\npresets.push(\n  // 支持图标，需要搭配图标库，eg: @iconify-json/uiw, 使用 <i class=\"i-uiw-alipay\" />\n  presetIcons({\n    scale: 1.2, // 图标大小\n    warn: true, // 警告\n    prefix: ['i-'], // 图标前缀\n    // 额外的 CSS 属性来控制图标的默认行为，默认内联图标\n    extraProperties: {\n      display: 'inline-block',\n      'vertical-align': 'middle'\n    }\n  })\n)\n\nexport default defineConfig({\n  // presets 是预设\n  presets: [...presets],\n  // transformers 是转换器\n  transformers: [...transformers],\n  // shortcuts 自定义样式快捷方式\n  // 具体使用方法，在需要使用到 flex justify-center items-center 这个几个类名时，只需要写一个 flex-center 即可\n  shortcuts: [\n    { 'flex-center': 'flex justify-center items-center' },\n    { 'flex-col-center': 'flex justify-center items-center flex-col' }\n  ],\n  // rules 的作用是：在全局范围内添加自定义规则\n  // 下面的配置适用于有安全区域的设备（如 iPhone X 上的刘海屏）\n  // 具体使用也很简单，在需要使用安全区域的元素上添加 p-safe 类名即可\n  rules: [\n    [\n      'p-safe',\n      {\n        padding:\n          'env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left)'\n      }\n    ],\n    ['pt-safe', { 'padding-top': 'env(safe-area-inset-top)' }],\n    ['pb-safe', { 'padding-bottom': 'env(safe-area-inset-bottom)' }],\n    [\n      'ptb-safe',\n      {\n        'padding-top': 'env(safe-area-inset-top)',\n        'padding-bottom': 'env(safe-area-inset-bottom)'\n      }\n    ]\n  ]\n})\n\n/**\n * 最终这一套组合下来会得到：\n * mp 里面：mt-4 => margin-top: 32rpx  == 16px\n * h5 里面：mt-4 => margin-top: 1rem == 16px\n *\n * 如果是传统方式写样式，则推荐设计稿设置为 750，这样设计稿1px，代码写1rpx。\n * rpx是响应式的，可以让不同设备的屏幕显示效果保持一致。\n */\n"
  },
  {
    "path": "vite-plugin/vite-plugin-directives.ts",
    "content": "import { Plugin } from 'vite'\nimport { parse } from 'vue/compiler-sfc'\n\nconst vitePluginDirectives = ({ directives = 'v-perms' }): Plugin => {\n  return {\n    name: 'vite-plugin-directives',\n    // code 是源码，path 是文件路径\n    transform(code, path) {\n      try {\n        if (!/.vue$/.test(path)) return null //  如果不是vue文件，则返回null\n        const parseCode = parse(code) // parse 的作用是将源码解析成 ast\n        if (!parseCode) return null //  如果解析失败，则返回null\n        if (!parseCode.descriptor?.template?.content) return null // 如果没有模板内容，则返回null\n\n        // 正则匹配 (根据传入的指令名称) /v-perms=\"([^\"]+)\"/g\n        const reg = new RegExp(`${directives}=\"([^\"]+)\"`, 'g') // 匹配指令\n        const checkPermsName = directives.slice(2) // 检查函数名称 与 指令名称一致\n        const $code = parseCode.descriptor.template.content.replace(reg, `v-if=\"$${checkPermsName}($1)\"`) // 模板内容\n        return {\n          code: code.replace(parseCode.descriptor.template.content, $code)\n        }\n      } catch (error) {\n        return null\n      }\n    }\n  }\n}\n\nexport default vitePluginDirectives\n"
  },
  {
    "path": "vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport path from 'node:path'\nimport uni from '@dcloudio/vite-plugin-uni'\nimport UniPages from '@uni-helper/vite-plugin-uni-pages'\nimport UniLayouts from '@uni-helper/vite-plugin-uni-layouts'\nimport AutoImport from 'unplugin-auto-import/vite'\nimport vitePluginDirectives from './vite-plugin/vite-plugin-directives'\nimport { WotResolver } from '@uni-helper/vite-plugin-uni-components/resolvers'\nimport ViteRestart from 'vite-plugin-restart'\nimport Components from '@uni-helper/vite-plugin-uni-components'\n\nexport default defineConfig(async () => {\n  const UnoCSS = (await import('unocss/vite')).default\n  return {\n    plugins: [\n      vitePluginDirectives({\n        directives: 'v-perms' // 自定义指令名称（默认：v-perms）\n      }),\n      UniPages({\n        exclude: ['**/components/**/**.*'], // 排除的文件\n        routeBlockLang: 'json5', // 虽然设了默认值，但是vue文件还是要加上 lang=\"json5\", 这样才能很好地格式化\n        // homePage 通过 vue 文件的 route-block 的type=\"home\"来设定\n        // pages 目录为 src/pages，分包目录不能配置在pages目录下\n        subPackages: ['src/pages-sub'], // 是个数组，可以配置多个，但是不能为pages里面的目录\n        dts: 'src/types/uni-pages.d.ts' // 生成的类型文件，默认是 src/types/uni-pages.d.ts\n      }),\n      UniLayouts(),\n      Components({\n        resolvers: [WotResolver()]\n      }),\n      AutoImport({\n        imports: ['vue', 'uni-app'],\n        dts: 'src/types/auto-import.d.ts',\n        dirs: ['src/hooks'], // 自动导入 hooks\n        eslintrc: { enabled: true },\n        vueTemplate: true // default false\n      }),\n      UnoCSS(),\n      uni(),\n      ViteRestart({\n        // 通过这个插件，在修改vite.config.js文件则不需要重新运行也生效配置\n        restart: ['vite.config.js']\n      })\n    ],\n    resolve: {\n      alias: {\n        '@': path.join(process.cwd(), './src'),\n        '@img': path.join(process.cwd(), './src/static')\n      }\n    },\n    // 防止在 dev 阶段就会出现页面使用预构建产物中的国际化数据，而组件库使用组件库内部的国际化数据\n    optimizeDeps: {\n      exclude: process.env.UNI_PLATFORM === 'h5' && process.env.NODE_ENV === 'development' ? ['wot-design-uni'] : []\n    }\n  }\n})\n"
  }
]