[
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\ngithub: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]\npatreon: # Replace with a single Patreon username\nopen_collective: # Replace with a single Open Collective username\nko_fi: # Replace with a single Ko-fi username\ntidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel\ncommunity_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry\nliberapay: # Replace with a single Liberapay username\nissuehunt: # Replace with a single IssueHunt username\notechie: # Replace with a single Otechie username\ncustom: https://lin-xin.github.io/images/weixin.jpg\n"
  },
  {
    "path": ".gitignore",
    "content": ".DS_Store\r\nnode_modules\r\n/dist\r\n\r\n\r\n# local env files\r\n.env.local\r\n.env.*.local\r\n\r\n# Log files\r\nnpm-debug.log*\r\nyarn-debug.log*\r\nyarn-error.log*\r\npnpm-debug.log*\r\n\r\n# Editor directories and files\r\n.idea\r\n.vscode\r\n*.suo\r\n*.ntvs*\r\n*.njsproj\r\n*.sln\r\n*.sw?\r\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2016-2023 vue-manage-system\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": "# vue-manage-system\r\n\r\n  <a href=\"https://github.com/lin-xin/vue-manage-system/releases\">\r\n    <img src=\"https://img.shields.io/github/release/lin-xin/vue-manage-system.svg\" alt=\"GitHub release\">\r\n  </a>\r\n   <a href=\"https://github.com/lin-xin/vue-manage-system/blob/master/LICENSE\">\r\n    <img src=\"https://img.shields.io/github/license/mashape/apistatus.svg\" alt=\"license\">\r\n  </a>\r\n\r\n基于 Vue3 + pinia + Element Plus 的后台管理系统解决方案。[线上演示](https://lin-xin.github.io/example/vue-manage-system/)\r\n\r\n> Vue2 版本请看 [tag-V4.2.0](https://github.com/lin-xin/vue-manage-system/tree/V4.2.0)，带后台功能请看 [tsrpc-manage-system](https://github.com/lin-xin/tsrpc-manage-system)\r\n\r\n[文档地址](https://lin-xin.github.io/example/vuems-doc/)\r\n[English document](https://github.com/lin-xin/manage-system/blob/master/README_EN.md)\r\n\r\n## 赞助商\r\n\r\n### 好问\r\n\r\n[<img src=\"https://static.bestqa.net/logo/bestqa_haowen.png\" width=\"220\" height=\"100\">](https://www.bestqa.net/home/index.html)\r\n\r\n专业问卷服务，一对一客服，按需定制\r\n\r\n## 支持作者\r\n\r\n请作者喝杯咖啡吧！(微信号：linxin_20)\r\n\r\n![微信扫一扫](https://lin-xin.github.io/images/weixin.jpg)\r\n\r\n## 前言\r\n\r\n该方案作为一套多功能的后台框架模板，适用于绝大部分的后台管理系统开发。基于 Vue3 + pinia + typescript，引用 Element Plus 组件库，方便开发。实现逻辑简单，适合外包项目，快速交付。\r\n\r\n## 功能\r\n\r\n-   [x] Element Plus\r\n-   [x] vite 3\r\n-   [x] pinia\r\n-   [x] typescript\r\n-   [x] 登录/注册\r\n-   [x] Dashboard\r\n-   [x] 表格/表单\r\n-   [x] 图表 :bar_chart:\r\n-   [x] 富文本/markdown 编辑器\r\n-   [x] 图片拖拽/裁剪上传\r\n-   [x] 权限管理\r\n-   [x] 三级菜单\r\n-   [x] 自定义图标\r\n-   [x] 主题切换\r\n\r\n## 安装步骤\r\n\r\n> 因为使用 vite3，node 版本需要 14.18+\r\n\r\n```\r\ngit clone https://github.com/lin-xin/vue-manage-system.git      // 把模板下载到本地\r\ncd vue-manage-system    // 进入模板目录\r\nnpm install         // 安装项目依赖，等待安装完成之后，安装失败可用 cnpm 或 yarn\r\n\r\n// 运行\r\nnpm run dev\r\n\r\n// 执行构建命令，生成的dist文件夹放在服务器下即可访问\r\nnpm run build\r\n```\r\n\r\n## 项目截图\r\n\r\n### 首页\r\n\r\n![Image text](https://github.com/lin-xin/manage-system/raw/master/screenshots/wms1.png)\r\n\r\n### 登录\r\n\r\n![Image text](https://github.com/lin-xin/manage-system/raw/master/screenshots/wms3.png)\r\n\r\n## License\r\n\r\n[MIT](https://github.com/lin-xin/vue-manage-system/blob/master/LICENSE)\r\n"
  },
  {
    "path": "README_EN.md",
    "content": "# vue-manage-system\r\n\r\n<a href=\"https://github.com/vuejs/vue\">\r\n    <img src=\"https://img.shields.io/badge/vue-2.6.10-brightgreen.svg\" alt=\"vue\">\r\n  </a>\r\n  <a href=\"https://github.com/ElemeFE/element\">\r\n    <img src=\"https://img.shields.io/badge/element--ui-2.8.2-brightgreen.svg\" alt=\"element-ui\">\r\n  </a>\r\n  <a href=\"https://github.com/lin-xin/vue-manage-system/blob/master/LICENSE\">\r\n    <img src=\"https://img.shields.io/github/license/mashape/apistatus.svg\" alt=\"license\">\r\n  </a>\r\n  <a href=\"https://github.com/lin-xin/vue-manage-system/releases\">\r\n    <img src=\"https://img.shields.io/github/release/lin-xin/vue-manage-system.svg\" alt=\"GitHub release\">\r\n  </a>\r\n  <a href=\"https://lin-xin.gitee.io/example/work/#/donate\">\r\n    <img src=\"https://img.shields.io/badge/%24-donate-ff69b4.svg\" alt=\"donate\">\r\n  </a>\r\n\r\nThe web management system solution based on Vue3 and ElementPlus。[live demo](https://lin-xin.gitee.io/example/work/)\r\n\r\nPlease check the version of vue2 in [tag V4.2.0](https://github.com/lin-xin/vue-manage-system/tree/V4.2.0)\r\n\r\n## Donation\r\n\r\n![WeChat](https://lin-xin.gitee.io/images/weixin.jpg)\r\n\r\n## Preface\r\n\r\nThe scheme as a set of multi-function background frame templates, suitable for most of the WEB management system development. Convenient development fast simple good components based on Vue3 and ElementPlus. Color separation of color style, support manual switch themes, and it is convenient to use a custom theme color.\r\n\r\n## Function\r\n\r\n-   [x] Element-UI\r\n-   [x] Login/Logout\r\n-   [x] Dashboard\r\n-   [x] Table\r\n-   [x] Tabs\r\n-   [x] From\r\n-   [x] Chart :bar_chart:\r\n-   [x] Editor\r\n-   [x] Markdown\r\n-   [x] Upload pictures by clipping or dragging\r\n-   [x] Permission\r\n-   [x] Three level menu\r\n-   [x] Custom icon\r\n\r\n## Installation steps\r\n\r\n    git clone https://github.com/lin-xin/vue-manage-system.git\t\t// Clone templates\r\n    cd vue-manage-system\t\t\t\t\t\t\t\t\t\t\t// Enter template directory\r\n    npm install\t\t\t\t\t\t\t\t\t\t\t\t\t// Installation dependency\r\n\r\n## Local development\r\n\r\n    npm run dev\r\n\r\n## Constructing production\r\n\r\n    // Constructing project\r\n    npm run build\r\n\r\n## Component description and presentation\r\n\r\n### vue-schart\r\n\r\nVue.js wrapper for sChart.js. Github : [vue-schart](https://github.com/lin-xin/vue-schart#/)\r\n\r\n```html\r\n<template>\r\n    <div>\r\n        <schart class=\"wrapper\" canvasId=\"myCanvas\" :options=\"options\"></schart>\r\n    </div>\r\n</template>\r\n<script setup>\r\nimport { ref } from 'vue';\r\nimport Schart from \"vue-schart\"; // 导入Schart组件\r\nconst options = ref({\r\n    type: \"bar\",\r\n    title: {\r\n        text: \"最近一周各品类销售图\",\r\n    },\r\n    labels: [\"周一\", \"周二\", \"周三\", \"周四\", \"周五\"],\r\n    datasets: [\r\n        {\r\n            label: \"家电\",\r\n            data: [234, 278, 270, 190, 230],\r\n        },\r\n        {\r\n            label: \"百货\",\r\n            data: [164, 178, 190, 135, 160],\r\n        },\r\n        {\r\n            label: \"食品\",\r\n            data: [144, 198, 150, 235, 120],\r\n        },\r\n    ],\r\n})\r\n</script>\r\n<style>\r\n    .wrapper {\r\n        width: 7rem;\r\n        height: 5rem;\r\n    }\r\n</style>\r\n```\r\n\r\n## Screenshot\r\n\r\n### Default theme\r\n\r\n![Image text](https://github.com/lin-xin/manage-system/raw/master/screenshots/wms1.png)\r\n\r\n### Login\r\n\r\n![Image text](https://github.com/lin-xin/manage-system/raw/master/screenshots/wms3.png)\r\n\r\n## License\r\n\r\n[MIT](https://github.com/lin-xin/vue-manage-system/blob/master/LICENSE)\r\n"
  },
  {
    "path": "auto-imports.d.ts",
    "content": "// Generated by 'unplugin-auto-import'\nexport {}\ndeclare global {\n\n}\n"
  },
  {
    "path": "components.d.ts",
    "content": "// generated by unplugin-vue-components\n// We suggest you to commit this file into source control\n// Read more: https://github.com/vuejs/core/pull/3399\nimport '@vue/runtime-core'\n\nexport {}\n\ndeclare module '@vue/runtime-core' {\n  export interface GlobalComponents {\n    Countup: typeof import('./src/components/countup.vue')['default']\n    ElAvatar: typeof import('element-plus/es')['ElAvatar']\n    ElButton: typeof import('element-plus/es')['ElButton']\n    ElCalendar: typeof import('element-plus/es')['ElCalendar']\n    ElCard: typeof import('element-plus/es')['ElCard']\n    ElCarousel: typeof import('element-plus/es')['ElCarousel']\n    ElCarouselItem: typeof import('element-plus/es')['ElCarouselItem']\n    ElCascader: typeof import('element-plus/es')['ElCascader']\n    ElCheckbox: typeof import('element-plus/es')['ElCheckbox']\n    ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']\n    ElCol: typeof import('element-plus/es')['ElCol']\n    ElColorPicker: typeof import('element-plus/es')['ElColorPicker']\n    ElCountdown: typeof import('element-plus/es')['ElCountdown']\n    ElDatePicker: typeof import('element-plus/es')['ElDatePicker']\n    ElDescriptions: typeof import('element-plus/es')['ElDescriptions']\n    ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem']\n    ElDialog: typeof import('element-plus/es')['ElDialog']\n    ElDivider: typeof import('element-plus/es')['ElDivider']\n    ElDropdown: typeof import('element-plus/es')['ElDropdown']\n    ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']\n    ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']\n    ElForm: typeof import('element-plus/es')['ElForm']\n    ElFormItem: typeof import('element-plus/es')['ElFormItem']\n    ElIcon: typeof import('element-plus/es')['ElIcon']\n    ElImage: typeof import('element-plus/es')['ElImage']\n    ElInput: typeof import('element-plus/es')['ElInput']\n    ElInputNumber: typeof import('element-plus/es')['ElInputNumber']\n    ElLink: typeof import('element-plus/es')['ElLink']\n    ElMenu: typeof import('element-plus/es')['ElMenu']\n    ElMenuItem: typeof import('element-plus/es')['ElMenuItem']\n    ElOption: typeof import('element-plus/es')['ElOption']\n    ElPagination: typeof import('element-plus/es')['ElPagination']\n    ElProgress: typeof import('element-plus/es')['ElProgress']\n    ElRadio: typeof import('element-plus/es')['ElRadio']\n    ElRadioButton: typeof import('element-plus/es')['ElRadioButton']\n    ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']\n    ElRate: typeof import('element-plus/es')['ElRate']\n    ElResult: typeof import('element-plus/es')['ElResult']\n    ElRow: typeof import('element-plus/es')['ElRow']\n    ElSelect: typeof import('element-plus/es')['ElSelect']\n    ElSlider: typeof import('element-plus/es')['ElSlider']\n    ElSpace: typeof import('element-plus/es')['ElSpace']\n    ElStatistic: typeof import('element-plus/es')['ElStatistic']\n    ElStep: typeof import('element-plus/es')['ElStep']\n    ElSteps: typeof import('element-plus/es')['ElSteps']\n    ElSubMenu: typeof import('element-plus/es')['ElSubMenu']\n    ElSwitch: typeof import('element-plus/es')['ElSwitch']\n    ElTable: typeof import('element-plus/es')['ElTable']\n    ElTableColumn: typeof import('element-plus/es')['ElTableColumn']\n    ElTabPane: typeof import('element-plus/es')['ElTabPane']\n    ElTabs: typeof import('element-plus/es')['ElTabs']\n    ElTag: typeof import('element-plus/es')['ElTag']\n    ElTimeline: typeof import('element-plus/es')['ElTimeline']\n    ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem']\n    ElTimePicker: typeof import('element-plus/es')['ElTimePicker']\n    ElTooltip: typeof import('element-plus/es')['ElTooltip']\n    ElTour: typeof import('element-plus/es')['ElTour']\n    ElTourStep: typeof import('element-plus/es')['ElTourStep']\n    ElTransfer: typeof import('element-plus/es')['ElTransfer']\n    ElUpload: typeof import('element-plus/es')['ElUpload']\n    ElWatermark: typeof import('element-plus/es')['ElWatermark']\n    Header: typeof import('./src/components/header.vue')['default']\n    RouterLink: typeof import('vue-router')['RouterLink']\n    RouterView: typeof import('vue-router')['RouterView']\n    Sidebar: typeof import('./src/components/sidebar.vue')['default']\n    TableCustom: typeof import('./src/components/table-custom.vue')['default']\n    TableDetail: typeof import('./src/components/table-detail.vue')['default']\n    TableEdit: typeof import('./src/components/table-edit.vue')['default']\n    TableSearch: typeof import('./src/components/table-search.vue')['default']\n    Tabs: typeof import('./src/components/tabs.vue')['default']\n  }\n}\n"
  },
  {
    "path": "index.html",
    "content": "<!DOCTYPE html>\r\n<html lang=\"\">\r\n\r\n<head>\r\n  <meta charset=\"utf-8\">\r\n  <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\r\n  <meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\">\r\n  <title>vue-manage-system后台管理系统</title>\r\n  <link rel=\"stylesheet\" href=\"//at.alicdn.com/t/c/font_830376_92o68tc95je.css\">\r\n</head>\r\n\r\n<body>\r\n  <noscript>\r\n    <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.\r\n        Please enable it to continue.</strong>\r\n  </noscript>\r\n  <div id=\"app\"></div>\r\n  <script type=\"module\" src=\"/src/main.ts\"></script>\r\n  <!-- built files will be auto injected -->\r\n</body>\r\n\r\n</html>"
  },
  {
    "path": "package.json",
    "content": "{\r\n\t\"name\": \"vue-manage-system\",\r\n\t\"version\": \"5.5.0\",\r\n\t\"private\": true,\r\n\t\"scripts\": {\r\n\t\t\"dev\": \"vite\",\r\n\t\t\"build\": \"vue-tsc --noEmit && vite build\",\r\n\t\t\"serve\": \"vite preview\"\r\n\t},\r\n\t\"dependencies\": {\r\n\t\t\"@element-plus/icons-vue\": \"*\",\r\n\t\t\"@wangeditor/editor\": \"^5.1.23\",\r\n\t\t\"@wangeditor/editor-for-vue\": \"^5.1.12\",\r\n\t\t\"axios\": \"^1.6.3\",\r\n\t\t\"countup.js\": \"^2.8.0\",\r\n\t\t\"echarts\": \"^5.5.0\",\r\n\t\t\"echarts-wordcloud\": \"^2.1.0\",\r\n\t\t\"element-plus\": \"^2.6.3\",\r\n\t\t\"md-editor-v3\": \"^2.11.2\",\r\n\t\t\"nprogress\": \"^0.2.0\",\r\n\t\t\"pinia\": \"^2.1.7\",\r\n\t\t\"vue\": \"^3.4.5\",\r\n\t\t\"vue-cropper\": \"1.1.1\",\r\n\t\t\"vue-echarts\": \"^6.6.9\",\r\n\t\t\"vue-router\": \"^4.2.5\",\r\n\t\t\"vue-schart\": \"^2.0.0\",\r\n\t\t\"xlsx\": \"^0.18.5\"\r\n\t},\r\n\t\"devDependencies\": {\r\n\t\t\"@vitejs/plugin-vue\": \"^3.0.0\",\r\n\t\t\"@vue/compiler-sfc\": \"^3.1.2\",\r\n\t\t\"typescript\": \"^4.6.4\",\r\n\t\t\"unplugin-auto-import\": \"^0.11.2\",\r\n\t\t\"unplugin-vue-components\": \"^0.22.4\",\r\n\t\t\"vite\": \"^3.0.0\",\r\n\t\t\"vite-plugin-vue-setup-extend\": \"^0.4.0\",\r\n\t\t\"vue-tsc\": \"^0.38.4\"\r\n\t},\r\n\t\"browserslist\": [\r\n\t\t\"> 1%\",\r\n\t\t\"last 2 versions\",\r\n\t\t\"not dead\"\r\n\t]\r\n}\r\n"
  },
  {
    "path": "public/mock/role.json",
    "content": "{\r\n    \"list\": [\r\n        {\r\n            \"id\": 1,\r\n            \"name\": \"管理员\",\r\n            \"key\": \"admin\",\r\n            \"status\": true,\r\n            \"permiss\": [\r\n                \"0\",\r\n                \"1\",\r\n                \"11\",\r\n                \"12\",\r\n                \"13\",\r\n                \"2\",\r\n                \"21\",\r\n                \"22\",\r\n                \"23\",\r\n                \"24\",\r\n                \"3\",\r\n                \"31\",\r\n                \"32\",\r\n                \"33\",\r\n                \"331\",\r\n                \"332\",\r\n                \"4\",\r\n                \"41\",\r\n                \"42\",\r\n                \"5\"\r\n            ]\r\n        },\r\n        {\r\n            \"id\": 2,\r\n            \"name\": \"普通用户\",\r\n            \"key\": \"user\",\r\n            \"status\": true,\r\n            \"permiss\": [\r\n                \"0\",\r\n                \"1\",\r\n                \"11\",\r\n                \"12\",\r\n                \"13\"\r\n            ]\r\n        }\r\n    ],\r\n    \"pageTotal\": 2\r\n}"
  },
  {
    "path": "public/mock/table.json",
    "content": "{\r\n    \"list\": [\r\n        {\r\n            \"id\": 1,\r\n            \"name\": \"张三\",\r\n            \"money\": 123,\r\n            \"address\": \"广东省东莞市长安镇\",\r\n            \"state\": true,\r\n            \"date\": \"2019-11-1\",\r\n            \"thumb\": \"https://lin-xin.gitee.io/images/post/wms.png\"\r\n        },\r\n        {\r\n            \"id\": 2,\r\n            \"name\": \"李四\",\r\n            \"money\": 456,\r\n            \"address\": \"广东省广州市白云区\",\r\n            \"state\": true,\r\n            \"date\": \"2019-10-11\",\r\n            \"thumb\": \"https://lin-xin.gitee.io/images/post/node3.png\"\r\n        },\r\n        {\r\n            \"id\": 3,\r\n            \"name\": \"王五\",\r\n            \"money\": 789,\r\n            \"address\": \"湖南省长沙市\",\r\n            \"state\": false,\r\n            \"date\": \"2019-11-11\",\r\n            \"thumb\": \"https://lin-xin.gitee.io/images/post/parcel.png\"\r\n        },\r\n        {\r\n            \"id\": 4,\r\n            \"name\": \"赵六\",\r\n            \"money\": 1011,\r\n            \"address\": \"福建省厦门市鼓浪屿\",\r\n            \"state\": true,\r\n            \"date\": \"2019-10-20\",\r\n            \"thumb\": \"https://lin-xin.gitee.io/images/post/notice.png\"\r\n        }\r\n    ],\r\n    \"pageTotal\": 4\r\n}"
  },
  {
    "path": "public/mock/user.json",
    "content": "{\r\n    \"list\": [\r\n        {\r\n            \"id\": 1,\r\n            \"name\": \"张三\",\r\n            \"password\": \"123\",\r\n            \"email\": \"123@qq.com\",\r\n            \"phone\": \"12345678944\",\r\n            \"date\": \"2024-01-01\",\r\n            \"role\": \"管理员\"\r\n        },\r\n        {\r\n            \"id\": 2,\r\n            \"name\": \"李四\",\r\n            \"password\": \"123\",\r\n            \"email\": \"1234@qq.com\",\r\n            \"phone\": \"12345678945\",\r\n            \"date\": \"2024-01-01\",\r\n            \"role\": \"普通用户\"\r\n        }\r\n    ],\r\n    \"pageTotal\": 2\r\n}"
  },
  {
    "path": "src/App.vue",
    "content": "<template>\r\n\t<el-config-provider :locale=\"zhCn\">\r\n\t\t<router-view />\r\n\t</el-config-provider>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ElConfigProvider } from 'element-plus';\r\nimport zhCn from 'element-plus/es/locale/lang/zh-cn';\r\nimport { useThemeStore } from './store/theme';\r\n\r\nconst theme = useThemeStore();\r\ntheme.initTheme();\r\n</script>\r\n<style>\r\n@import './assets/css/main.css';\r\n</style>\r\n"
  },
  {
    "path": "src/api/index.ts",
    "content": "import request from '../utils/request';\r\n\r\nexport const fetchData = () => {\r\n    return request({\r\n        url: './mock/table.json',\r\n        method: 'get'\r\n    });\r\n};\r\n\r\nexport const fetchUserData = () => {\r\n    return request({\r\n        url: './mock/user.json',\r\n        method: 'get'\r\n    });\r\n};\r\n\r\nexport const fetchRoleData = () => {\r\n    return request({\r\n        url: './mock/role.json',\r\n        method: 'get'\r\n    });\r\n};\r\n"
  },
  {
    "path": "src/assets/css/icon.css",
    "content": "[class*=\" el-icon-lx\"],\r\n[class^=el-icon-lx] {\r\n    font-family: lx-iconfont !important;\r\n}"
  },
  {
    "path": "src/assets/css/main.css",
    "content": "* {\r\n\tmargin: 0;\r\n\tpadding: 0;\r\n\toutline: 0 !important;\r\n}\r\n\r\n\r\nbody {\r\n\tfont-family: 'PingFang SC', 'Helvetica Neue', Helvetica, 'microsoft yahei', arial, STHeiTi, sans-serif;\r\n}\r\n\r\na {\r\n\ttext-decoration: none;\r\n}\r\ni {\r\n\tfont-style: normal;\r\n}\r\n\r\n.container {\r\n\tpadding: 30px;\r\n\tbackground: #fff;\r\n\tborder: 1px solid #ddd;\r\n\tborder-radius: 5px;\r\n}\r\n\r\n.el-table th {\r\n\tbackground-color: #f5f7fa !important;\r\n}\r\n\r\n.plugins-tips {\r\n\tpadding: 20px 10px;\r\n\tmargin-bottom: 20px;\r\n\tbackground: #eef1f6;\r\n}\r\n\r\n.plugins-tips a {\r\n\tcolor: var(--el-color-primary);\r\n}\r\n\r\n.el-button + .el-tooltip {\r\n\tmargin-left: 10px;\r\n}\r\n\r\n.mgb20 {\r\n\tmargin-bottom: 20px;\r\n}\r\n.mgb10 {\r\n\tmargin-bottom: 10px;\r\n}\r\n.mr10 {\r\n\tmargin-right: 10px;\r\n}\r\n\r\n.move-enter-active,\r\n.move-leave-active {\r\n\ttransition: opacity 0.1s ease;\r\n}\r\n\r\n.move-enter-from,\r\n.move-leave-to {\r\n\topacity: 0;\r\n}\r\n\r\n.el-time-panel__content::after,\r\n.el-time-panel__content::before {\r\n\tmargin-top: -7px;\r\n}\r\n\r\n.el-time-spinner__wrapper .el-scrollbar__wrap:not(.el-scrollbar__wrap--hidden-default) {\r\n\tpadding-bottom: 0;\r\n}\r\n\r\n[hidden] {\r\n\tdisplay: none !important;\r\n}\r\n\r\n.flex-center {\r\n\tdisplay: flex;\r\n\tjustify-content: center;\r\n\talign-items: center;\r\n}\r\n\r\n:root {\r\n\t--header-bg-color: #242f42;\r\n\t--header-text-color: #fff;\r\n\t--active-color: var(--el-color-primary);\r\n}\r\n"
  },
  {
    "path": "src/components/countup.vue",
    "content": "<template>\r\n    <span ref=\"countRef\"></span>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { onMounted, ref, watch } from 'vue';\r\nimport { CountUp } from 'countup.js';\r\n\r\nconst props = defineProps({\r\n    end: {\r\n        type: Number,\r\n        required: true,\r\n    },\r\n    options: {\r\n        type: Object,\r\n        default: () => ({}),\r\n        required: false,\r\n    },\r\n});\r\n\r\nconst countRef = ref<any>(null);\r\nlet countUp: any;\r\nonMounted(() => {\r\n    countUp = new CountUp(countRef.value, props.end, props.options);\r\n    if (countUp.error) {\r\n        console.error(countUp.error);\r\n        return;\r\n    }\r\n    countUp.start();\r\n});\r\n\r\nwatch(() => props.end, (newVal) => {\r\n    if (countUp) {\r\n        countUp.update(newVal);\r\n    }\r\n});\r\n\r\n\r\n</script>"
  },
  {
    "path": "src/components/header.vue",
    "content": "<template>\r\n    <div class=\"header\">\r\n        <!-- 折叠按钮 -->\r\n        <div class=\"header-left\">\r\n            <img class=\"logo\" src=\"../assets/img/logo.svg\" alt=\"\" />\r\n            <div class=\"web-title\">后台管理系统</div>\r\n            <div class=\"collapse-btn\" @click=\"collapseChage\">\r\n                <el-icon v-if=\"sidebar.collapse\">\r\n                    <Expand />\r\n                </el-icon>\r\n                <el-icon v-else>\r\n                    <Fold />\r\n                </el-icon>\r\n            </div>\r\n        </div>\r\n        <div class=\"header-right\">\r\n            <div class=\"header-user-con\">\r\n                <div class=\"btn-icon\" @click=\"router.push('/theme')\">\r\n                    <el-tooltip effect=\"dark\" content=\"设置主题\" placement=\"bottom\">\r\n                        <i class=\"el-icon-lx-skin\"></i>\r\n                    </el-tooltip>\r\n                </div>\r\n                <div class=\"btn-icon\" @click=\"router.push('/ucenter')\">\r\n                    <el-tooltip\r\n                        effect=\"dark\"\r\n                        :content=\"message ? `有${message}条未读消息` : `消息中心`\"\r\n                        placement=\"bottom\"\r\n                    >\r\n                        <i class=\"el-icon-lx-notice\"></i>\r\n                    </el-tooltip>\r\n                    <span class=\"btn-bell-badge\" v-if=\"message\"></span>\r\n                </div>\r\n                <div class=\"btn-icon\" @click=\"setFullScreen\">\r\n                    <el-tooltip effect=\"dark\" content=\"全屏\" placement=\"bottom\">\r\n                        <i class=\"el-icon-lx-full\"></i>\r\n                    </el-tooltip>\r\n                </div>\r\n                <!-- 用户头像 -->\r\n                <el-avatar class=\"user-avator\" :size=\"30\" :src=\"imgurl\" />\r\n                <!-- 用户名下拉菜单 -->\r\n                <el-dropdown class=\"user-name\" trigger=\"click\" @command=\"handleCommand\">\r\n                    <span class=\"el-dropdown-link\">\r\n                        {{ username }}\r\n                        <el-icon class=\"el-icon--right\">\r\n                            <arrow-down />\r\n                        </el-icon>\r\n                    </span>\r\n                    <template #dropdown>\r\n                        <el-dropdown-menu>\r\n                            <a href=\"https://github.com/lin-xin/vue-manage-system\" target=\"_blank\">\r\n                                <el-dropdown-item>项目仓库</el-dropdown-item>\r\n                            </a>\r\n                            <a href=\"https://lin-xin.gitee.io/example/vuems-doc/\" target=\"_blank\">\r\n                                <el-dropdown-item>官方文档</el-dropdown-item>\r\n                            </a>\r\n                            <el-dropdown-item command=\"user\">个人中心</el-dropdown-item>\r\n                            <el-dropdown-item divided command=\"loginout\">退出登录</el-dropdown-item>\r\n                        </el-dropdown-menu>\r\n                    </template>\r\n                </el-dropdown>\r\n            </div>\r\n        </div>\r\n    </div>\r\n</template>\r\n<script setup lang=\"ts\">\r\nimport { onMounted } from 'vue';\r\nimport { useSidebarStore } from '../store/sidebar';\r\nimport { useRouter } from 'vue-router';\r\nimport imgurl from '../assets/img/img.jpg';\r\n\r\nconst username: string | null = localStorage.getItem('vuems_name');\r\nconst message: number = 2;\r\n\r\nconst sidebar = useSidebarStore();\r\n// 侧边栏折叠\r\nconst collapseChage = () => {\r\n    sidebar.handleCollapse();\r\n};\r\n\r\nonMounted(() => {\r\n    if (document.body.clientWidth < 1500) {\r\n        collapseChage();\r\n    }\r\n});\r\n\r\n// 用户名下拉菜单选择事件\r\nconst router = useRouter();\r\nconst handleCommand = (command: string) => {\r\n    if (command == 'loginout') {\r\n        localStorage.removeItem('vuems_name');\r\n        router.push('/login');\r\n    } else if (command == 'user') {\r\n        router.push('/ucenter');\r\n    }\r\n};\r\n\r\nconst setFullScreen = () => {\r\n    if (document.fullscreenElement) {\r\n        document.exitFullscreen();\r\n    } else {\r\n        document.body.requestFullscreen.call(document.body);\r\n    }\r\n};\r\n</script>\r\n<style scoped>\r\n.header {\r\n    display: flex;\r\n    justify-content: space-between;\r\n    align-items: center;\r\n    box-sizing: border-box;\r\n    width: 100%;\r\n    height: 70px;\r\n    color: var(--header-text-color);\r\n    background-color: var(--header-bg-color);\r\n    border-bottom: 1px solid #ddd;\r\n}\r\n\r\n.header-left {\r\n    display: flex;\r\n    align-items: center;\r\n    padding-left: 20px;\r\n    height: 100%;\r\n}\r\n\r\n.logo {\r\n    width: 35px;\r\n}\r\n\r\n.web-title {\r\n    margin: 0 40px 0 10px;\r\n    font-size: 22px;\r\n}\r\n\r\n.collapse-btn {\r\n    display: flex;\r\n    justify-content: center;\r\n    align-items: center;\r\n    height: 100%;\r\n    padding: 0 10px;\r\n    cursor: pointer;\r\n    opacity: 0.8;\r\n    font-size: 22px;\r\n}\r\n\r\n.collapse-btn:hover {\r\n    opacity: 1;\r\n}\r\n\r\n.header-right {\r\n    float: right;\r\n    padding-right: 50px;\r\n}\r\n\r\n.header-user-con {\r\n    display: flex;\r\n    height: 70px;\r\n    align-items: center;\r\n}\r\n\r\n.btn-fullscreen {\r\n    transform: rotate(45deg);\r\n    margin-right: 5px;\r\n    font-size: 24px;\r\n}\r\n\r\n.btn-icon {\r\n    position: relative;\r\n    width: 30px;\r\n    height: 30px;\r\n    text-align: center;\r\n    cursor: pointer;\r\n    display: flex;\r\n    align-items: center;\r\n    color: var(--header-text-color);\r\n    margin: 0 5px;\r\n    font-size: 20px;\r\n}\r\n\r\n.btn-bell-badge {\r\n    position: absolute;\r\n    right: 4px;\r\n    top: 0px;\r\n    width: 8px;\r\n    height: 8px;\r\n    border-radius: 4px;\r\n    background: #f56c6c;\r\n    color: var(--header-text-color);\r\n}\r\n\r\n.user-avator {\r\n    margin: 0 10px 0 20px;\r\n}\r\n\r\n.el-dropdown-link {\r\n    color: var(--header-text-color);\r\n    cursor: pointer;\r\n    display: flex;\r\n    align-items: center;\r\n}\r\n\r\n.el-dropdown-menu__item {\r\n    text-align: center;\r\n}\r\n</style>\r\n"
  },
  {
    "path": "src/components/menu.ts",
    "content": "import { Menus } from '@/types/menu';\r\n\r\nexport const menuData: Menus[] = [\r\n    {\r\n        id: '0',\r\n        title: '系统首页',\r\n        index: '/dashboard',\r\n        icon: 'Odometer',\r\n    },\r\n    {\r\n        id: '1',\r\n        title: '系统管理',\r\n        index: '1',\r\n        icon: 'HomeFilled',\r\n        children: [\r\n            {\r\n                id: '11',\r\n                pid: '1',\r\n                index: '/system-user',\r\n                title: '用户管理',\r\n            },\r\n            {\r\n                id: '12',\r\n                pid: '1',\r\n                index: '/system-role',\r\n                title: '角色管理',\r\n            },\r\n            {\r\n                id: '13',\r\n                pid: '1',\r\n                index: '/system-menu',\r\n                title: '菜单管理',\r\n            },\r\n        ],\r\n    },\r\n    {\r\n        id: '2',\r\n        title: '组件',\r\n        index: '2-1',\r\n        icon: 'Calendar',\r\n        children: [\r\n            {\r\n                id: '21',\r\n                pid: '3',\r\n                index: '/form',\r\n                title: '表单',\r\n            },\r\n            {\r\n                id: '22',\r\n                pid: '3',\r\n                index: '/upload',\r\n                title: '上传',\r\n            },\r\n            {\r\n                id: '23',\r\n                pid: '2',\r\n                index: '/carousel',\r\n                title: '走马灯',\r\n            },\r\n            {\r\n                id: '24',\r\n                pid: '2',\r\n                index: '/calendar',\r\n                title: '日历',\r\n            },\r\n            {\r\n                id: '25',\r\n                pid: '2',\r\n                index: '/watermark',\r\n                title: '水印',\r\n            },\r\n            {\r\n                id: '26',\r\n                pid: '2',\r\n                index: '/tour',\r\n                title: '分布引导',\r\n            },\r\n            {\r\n                id: '27',\r\n                pid: '2',\r\n                index: '/steps',\r\n                title: '步骤条',\r\n            },\r\n            {\r\n                id: '28',\r\n                pid: '2',\r\n                index: '/statistic',\r\n                title: '统计',\r\n            },\r\n            {\r\n                id: '29',\r\n                pid: '3',\r\n                index: '29',\r\n                title: '三级菜单',\r\n                children: [\r\n                    {\r\n                        id: '291',\r\n                        pid: '29',\r\n                        index: '/editor',\r\n                        title: '富文本编辑器',\r\n                    },\r\n                    {\r\n                        id: '292',\r\n                        pid: '29',\r\n                        index: '/markdown',\r\n                        title: 'markdown编辑器',\r\n                    },\r\n                ],\r\n            },\r\n        ],\r\n    },\r\n    {\r\n        id: '3',\r\n        title: '表格',\r\n        index: '3',\r\n        icon: 'Calendar',\r\n        children: [\r\n            {\r\n                id: '31',\r\n                pid: '3',\r\n                index: '/table',\r\n                title: '基础表格',\r\n            },\r\n            {\r\n                id: '32',\r\n                pid: '3',\r\n                index: '/table-editor',\r\n                title: '可编辑表格',\r\n            },\r\n            {\r\n                id: '33',\r\n                pid: '3',\r\n                index: '/import',\r\n                title: '导入Excel',\r\n            },\r\n            {\r\n                id: '34',\r\n                pid: '3',\r\n                index: '/export',\r\n                title: '导出Excel',\r\n            },\r\n        ],\r\n    },\r\n    {\r\n        id: '4',\r\n        icon: 'PieChart',\r\n        index: '4',\r\n        title: '图表',\r\n        children: [\r\n            {\r\n                id: '41',\r\n                pid: '4',\r\n                index: '/schart',\r\n                title: 'schart图表',\r\n            },\r\n            {\r\n                id: '42',\r\n                pid: '4',\r\n                index: '/echarts',\r\n                title: 'echarts图表',\r\n            },\r\n        ],\r\n    },\r\n    {\r\n        id: '5',\r\n        icon: 'Guide',\r\n        index: '/icon',\r\n        title: '图标',\r\n        permiss: '5',\r\n    },\r\n    {\r\n        id: '7',\r\n        icon: 'Brush',\r\n        index: '/theme',\r\n        title: '主题',\r\n    },\r\n    {\r\n        id: '6',\r\n        icon: 'DocumentAdd',\r\n        index: '6',\r\n        title: '附加页面',\r\n        children: [\r\n            {\r\n                id: '61',\r\n                pid: '6',\r\n                index: '/ucenter',\r\n                title: '个人中心',\r\n            },\r\n            {\r\n                id: '62',\r\n                pid: '6',\r\n                index: '/login',\r\n                title: '登录',\r\n            },\r\n            {\r\n                id: '63',\r\n                pid: '6',\r\n                index: '/register',\r\n                title: '注册',\r\n            },\r\n            {\r\n                id: '64',\r\n                pid: '6',\r\n                index: '/reset-pwd',\r\n                title: '重设密码',\r\n            },\r\n            {\r\n                id: '65',\r\n                pid: '6',\r\n                index: '/403',\r\n                title: '403',\r\n            },\r\n            {\r\n                id: '66',\r\n                pid: '6',\r\n                index: '/404',\r\n                title: '404',\r\n            },\r\n        ],\r\n    },\r\n];\r\n"
  },
  {
    "path": "src/components/sidebar.vue",
    "content": "<template>\r\n    <div class=\"sidebar\">\r\n        <el-menu\r\n            class=\"sidebar-el-menu\"\r\n            :default-active=\"onRoutes\"\r\n            :collapse=\"sidebar.collapse\"\r\n            :background-color=\"sidebar.bgColor\"\r\n            :text-color=\"sidebar.textColor\"\r\n            router\r\n        >\r\n            <template v-for=\"item in menuData\">\r\n                <template v-if=\"item.children\">\r\n                    <el-sub-menu :index=\"item.index\" :key=\"item.index\" v-permiss=\"item.id\">\r\n                        <template #title>\r\n                            <el-icon>\r\n                                <component :is=\"item.icon\"></component>\r\n                            </el-icon>\r\n                            <span>{{ item.title }}</span>\r\n                        </template>\r\n                        <template v-for=\"subItem in item.children\">\r\n                            <el-sub-menu\r\n                                v-if=\"subItem.children\"\r\n                                :index=\"subItem.index\"\r\n                                :key=\"subItem.index\"\r\n                                v-permiss=\"item.id\"\r\n                            >\r\n                                <template #title>{{ subItem.title }}</template>\r\n                                <el-menu-item\r\n                                    v-for=\"(threeItem, i) in subItem.children\"\r\n                                    :key=\"i\"\r\n                                    :index=\"threeItem.index\"\r\n                                >\r\n                                    {{ threeItem.title }}\r\n                                </el-menu-item>\r\n                            </el-sub-menu>\r\n                            <el-menu-item v-else :index=\"subItem.index\" v-permiss=\"item.id\">\r\n                                {{ subItem.title }}\r\n                            </el-menu-item>\r\n                        </template>\r\n                    </el-sub-menu>\r\n                </template>\r\n                <template v-else>\r\n                    <el-menu-item :index=\"item.index\" :key=\"item.index\" v-permiss=\"item.id\">\r\n                        <el-icon>\r\n                            <component :is=\"item.icon\"></component>\r\n                        </el-icon>\r\n                        <template #title>{{ item.title }}</template>\r\n                    </el-menu-item>\r\n                </template>\r\n            </template>\r\n        </el-menu>\r\n    </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { computed } from 'vue';\r\nimport { useSidebarStore } from '../store/sidebar';\r\nimport { useRoute } from 'vue-router';\r\nimport { menuData } from '@/components/menu';\r\n\r\nconst route = useRoute();\r\nconst onRoutes = computed(() => {\r\n    return route.path;\r\n});\r\n\r\nconst sidebar = useSidebarStore();\r\n</script>\r\n\r\n<style scoped>\r\n.sidebar {\r\n    display: block;\r\n    position: absolute;\r\n    left: 0;\r\n    top: 70px;\r\n    bottom: 0;\r\n    overflow-y: scroll;\r\n}\r\n\r\n.sidebar::-webkit-scrollbar {\r\n    width: 0;\r\n}\r\n\r\n.sidebar-el-menu:not(.el-menu--collapse) {\r\n    width: 250px;\r\n}\r\n\r\n.sidebar-el-menu {\r\n    min-height: 100%;\r\n}\r\n</style>\r\n"
  },
  {
    "path": "src/components/table-custom.vue",
    "content": "<template>\r\n    <div>\r\n        <div class=\"table-toolbar\" v-if=\"hasToolbar\">\r\n            <div class=\"table-toolbar-left\">\r\n                <slot name=\"toolbarBtn\"></slot>\r\n            </div>\r\n            <div class=\"table-toolbar-right flex-center\">\r\n                <template v-if=\"multipleSelection.length > 0\">\r\n                    <el-tooltip effect=\"dark\" content=\"删除选中\" placement=\"top\">\r\n                        <el-icon class=\"columns-setting-icon\" @click=\"delSelection(multipleSelection)\">\r\n                            <Delete />\r\n                        </el-icon>\r\n                    </el-tooltip>\r\n                    <el-divider direction=\"vertical\" />\r\n                </template>\r\n                <el-tooltip effect=\"dark\" content=\"刷新\" placement=\"top\">\r\n                    <el-icon class=\"columns-setting-icon\" @click=\"refresh\">\r\n                        <Refresh />\r\n                    </el-icon>\r\n                </el-tooltip>\r\n                <el-divider direction=\"vertical\" />\r\n                <el-tooltip effect=\"dark\" content=\"列设置\" placement=\"top\">\r\n                    <el-dropdown :hide-on-click=\"false\" size=\"small\" trigger=\"click\">\r\n                        <el-icon class=\"columns-setting-icon\">\r\n                            <Setting />\r\n                        </el-icon>\r\n                        <template #dropdown>\r\n                            <el-dropdown-menu>\r\n                                <el-dropdown-item v-for=\"c in columns\">\r\n                                    <el-checkbox v-model=\"c.visible\" :label=\"c.label\" />\r\n                                </el-dropdown-item>\r\n                            </el-dropdown-menu>\r\n                        </template>\r\n                    </el-dropdown>\r\n                </el-tooltip>\r\n            </div>\r\n        </div>\r\n        <el-table class=\"mgb20\" :style=\"{ width: '100%' }\" border :data=\"tableData\" :row-key=\"rowKey\"\r\n            @selection-change=\"handleSelectionChange\" table-layout=\"auto\">\r\n            <template v-for=\"item in columns\" :key=\"item.prop\">\r\n                <el-table-column v-if=\"item.visible\" :prop=\"item.prop\" :label=\"item.label\" :width=\"item.width\"\r\n                    :type=\"item.type\" :align=\"item.align || 'center'\">\r\n\r\n                    <template #default=\"{ row, column, $index }\" v-if=\"item.type === 'index'\">\r\n                        {{ getIndex($index) }}\r\n                    </template>\r\n                    <template #default=\"{ row, column, $index }\" v-if=\"!item.type\">\r\n                        <slot :name=\"item.prop\" :rows=\"row\" :index=\"$index\">\r\n                            <template v-if=\"item.prop == 'operator'\">\r\n                                <el-button type=\"warning\" size=\"small\" :icon=\"View\" @click=\"viewFunc(row)\">\r\n                                    查看\r\n                                </el-button>\r\n                                <el-button type=\"primary\" size=\"small\" :icon=\"Edit\" @click=\"editFunc(row)\">\r\n                                    编辑\r\n                                </el-button>\r\n                                <el-button type=\"danger\" size=\"small\" :icon=\"Delete\" @click=\"handleDelete(row)\">\r\n                                    删除\r\n                                </el-button>\r\n                            </template>\r\n                            <span v-else-if=\"item.formatter\">\r\n                                {{ item.formatter(row[item.prop]) }}\r\n                            </span>\r\n                            <span v-else>\r\n                                {{ row[item.prop] }}\r\n                            </span>\r\n                        </slot>\r\n                    </template>\r\n                </el-table-column>\r\n            </template>\r\n        </el-table>\r\n        <el-pagination v-if=\"hasPagination\" :current-page=\"currentPage\" :page-size=\"pageSize\" :background=\"true\"\r\n            :layout=\"layout\" :total=\"total\" @current-change=\"handleCurrentChange\" />\r\n    </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { toRefs, PropType, ref } from 'vue'\r\nimport { Delete, Edit, View, Refresh } from '@element-plus/icons-vue';\r\nimport { ElMessageBox } from 'element-plus';\r\n\r\nconst props = defineProps({\r\n    // 表格相关\r\n    tableData: {\r\n        type: Array,\r\n        default: []\r\n    },\r\n    columns: {\r\n        type: Array as PropType<any[]>,\r\n        default: []\r\n    },\r\n    rowKey: {\r\n        type: String,\r\n        default: 'id'\r\n    },\r\n    hasToolbar: {\r\n        type: Boolean,\r\n        default: true\r\n    },\r\n    //  分页相关\r\n    hasPagination: {\r\n        type: Boolean,\r\n        default: true\r\n    },\r\n    total: {\r\n        type: Number,\r\n        default: 0\r\n    },\r\n    currentPage: {\r\n        type: Number,\r\n        default: 1\r\n    },\r\n    pageSize: {\r\n        type: Number,\r\n        default: 10\r\n    },\r\n\r\n    layout: {\r\n        type: String,\r\n        default: 'total, prev, pager, next'\r\n    },\r\n    delFunc: {\r\n        type: Function,\r\n        default: () => { }\r\n    },\r\n    viewFunc: {\r\n        type: Function,\r\n        default: () => { }\r\n    },\r\n    editFunc: {\r\n        type: Function,\r\n        default: () => { }\r\n    },\r\n    delSelection: {\r\n        type: Function,\r\n        default: () => { }\r\n    },\r\n    refresh: {\r\n        type: Function,\r\n        default: () => { }\r\n    },\r\n    changePage: {\r\n        type: Function,\r\n        default: () => { }\r\n    }\r\n})\r\n\r\nlet {\r\n    tableData,\r\n    columns,\r\n    rowKey,\r\n    hasToolbar,\r\n    hasPagination,\r\n    total,\r\n    currentPage,\r\n    pageSize,\r\n    layout,\r\n} = toRefs(props)\r\n\r\ncolumns.value.forEach((item) => {\r\n    if (item.visible === undefined) {\r\n        item.visible = true\r\n    }\r\n})\r\n\r\n// 当选择项发生变化时会触发该事件\r\nconst multipleSelection = ref([])\r\nconst handleSelectionChange = (selection: any[]) => {\r\n    multipleSelection.value = selection\r\n}\r\n\r\n// 当前页码变化的事件\r\nconst handleCurrentChange = (val: number) => {\r\n    props.changePage(val)\r\n}\r\n\r\nconst handleDelete = (row) => {\r\n    ElMessageBox.confirm('确定要删除吗？', '提示', {\r\n        type: 'warning'\r\n    })\r\n        .then(async () => {\r\n            props.delFunc(row);\r\n        })\r\n        .catch(() => { });\r\n};\r\n\r\nconst getIndex = (index: number) => {\r\n    return index + 1 + (currentPage.value - 1) * pageSize.value\r\n}\r\n\r\n</script>\r\n\r\n<style scoped>\r\n.table-toolbar {\r\n    display: flex;\r\n    justify-content: space-between;\r\n    align-items: flex-end;\r\n    margin-bottom: 10px;\r\n}\r\n\r\n.columns-setting-icon {\r\n    display: block;\r\n    font-size: 18px;\r\n    cursor: pointer;\r\n    color: #676767;\r\n}\r\n</style>\r\n<style>\r\n.table-header .cell {\r\n    color: #333;\r\n}\r\n</style>"
  },
  {
    "path": "src/components/table-detail.vue",
    "content": "<template>\r\n\t<el-descriptions :title=\"title\" :column=\"column\" border>\r\n\t\t<el-descriptions-item v-for=\"item in list\" :span=\"item.span\">\r\n\t\t\t<template #label> {{ item.label }} </template>\r\n\t\t\t<slot :name=\"item.prop\" :rows=\"row\">\r\n\t\t\t\t{{ item.value || row[item.prop] }}\r\n\t\t\t</slot>\r\n\t\t</el-descriptions-item>\r\n\t</el-descriptions>\r\n</template>\r\n\r\n<script lang=\"ts\" setup>\r\nconst props = defineProps({\r\n\tdata: {\r\n\t\ttype: Object,\r\n\t\trequired: true,\r\n\t}\r\n});\r\nconst { row, title, column = 2, list } = props.data;\r\n\r\n</script>\r\n"
  },
  {
    "path": "src/components/table-edit.vue",
    "content": "<template>\r\n\t<el-form ref=\"formRef\" :model=\"form\" :rules=\"rules\" :label-width=\"options.labelWidth\">\r\n\t\t<el-row>\r\n\t\t\t<el-col :span=\"options.span\" v-for=\"item in options.list\">\r\n\t\t\t\t<el-form-item :label=\"item.label\" :prop=\"item.prop\">\r\n\t\t\t\t\t<!-- 文本框、数字框、下拉框、日期框、开关、上传 -->\r\n\t\t\t\t\t<el-input v-if=\"item.type === 'input'\" v-model=\"form[item.prop]\" :disabled=\"item.disabled\"\r\n\t\t\t\t\t\t:placeholder=\"item.placeholder\" clearable></el-input>\r\n\t\t\t\t\t<el-input-number v-else-if=\"item.type === 'number'\" v-model=\"form[item.prop]\"\r\n\t\t\t\t\t\t:disabled=\"item.disabled\" controls-position=\"right\"></el-input-number>\r\n\t\t\t\t\t<el-select v-else-if=\"item.type === 'select'\" v-model=\"form[item.prop]\" :disabled=\"item.disabled\"\r\n\t\t\t\t\t\t:placeholder=\"item.placeholder\" clearable>\r\n\t\t\t\t\t\t<el-option v-for=\"opt in item.opts\" :label=\"opt.label\" :value=\"opt.value\"></el-option>\r\n\t\t\t\t\t</el-select>\r\n\t\t\t\t\t<el-date-picker v-else-if=\"item.type === 'date'\" type=\"date\" v-model=\"form[item.prop]\"\r\n\t\t\t\t\t\t:value-format=\"item.format\"></el-date-picker>\r\n\t\t\t\t\t<el-switch v-else-if=\"item.type === 'switch'\" v-model=\"form[item.prop]\"\r\n\t\t\t\t\t\t:active-value=\"item.activeValue\" :inactive-value=\"item.inactiveValue\"\r\n\t\t\t\t\t\t:active-text=\"item.activeText\" :inactive-text=\"item.inactiveText\"></el-switch>\r\n\t\t\t\t\t<el-upload v-else-if=\"item.type === 'upload'\" class=\"avatar-uploader\" action=\"#\"\r\n\t\t\t\t\t\t:show-file-list=\"false\" :on-success=\"handleAvatarSuccess\">\r\n\t\t\t\t\t\t<img v-if=\"form[item.prop]\" :src=\"form[item.prop]\" class=\"avatar\" />\r\n\t\t\t\t\t\t<el-icon v-else class=\"avatar-uploader-icon\">\r\n\t\t\t\t\t\t\t<Plus />\r\n\t\t\t\t\t\t</el-icon>\r\n\t\t\t\t\t</el-upload>\r\n\t\t\t\t\t<slot :name=\"item.prop\" v-else>\r\n\r\n\t\t\t\t\t</slot>\r\n\t\t\t\t</el-form-item>\r\n\t\t\t</el-col>\r\n\t\t</el-row>\r\n\r\n\t\t<el-form-item>\r\n\t\t\t<el-button type=\"primary\" @click=\"saveEdit(formRef)\">保 存</el-button>\r\n\t\t</el-form-item>\r\n\t</el-form>\r\n</template>\r\n\r\n<script lang=\"ts\" setup>\r\nimport { FormOption } from '@/types/form-option';\r\nimport { FormInstance, FormRules, UploadProps } from 'element-plus';\r\nimport { PropType, ref } from 'vue';\r\n\r\nconst { options, formData, edit, update } = defineProps({\r\n\toptions: {\r\n\t\ttype: Object as PropType<FormOption>,\r\n\t\trequired: true\r\n\t},\r\n\tformData: {\r\n\t\ttype: Object,\r\n\t\trequired: true\r\n\t},\r\n\tedit: {\r\n\t\ttype: Boolean,\r\n\t\trequired: false\r\n\t},\r\n\tupdate: {\r\n\t\ttype: Function,\r\n\t\trequired: true\r\n\t}\r\n});\r\n\r\n\r\nconst form = ref({ ...(edit ? formData : {}) });\r\n\r\nconst rules: FormRules = options.list.map(item => {\r\n\tif (item.required) {\r\n\t\treturn { [item.prop]: [{ required: true, message: `${item.label}不能为空`, trigger: 'blur' }] };\r\n\t}\r\n\treturn {};\r\n}).reduce((acc, cur) => ({ ...acc, ...cur }), {});\r\n\r\n\r\nconst formRef = ref<FormInstance>();\r\nconst saveEdit = (formEl: FormInstance | undefined) => {\r\n\tif (!formEl) return;\r\n\tformEl.validate(valid => {\r\n\t\tif (!valid) return false;\r\n\t\tupdate(form.value);\r\n\t});\r\n};\r\n\r\nconst handleAvatarSuccess: UploadProps['onSuccess'] = (response, uploadFile) => {\r\n\tform.value.thumb = URL.createObjectURL(uploadFile.raw!);\r\n};\r\n\r\n</script>\r\n\r\n<style>\r\n.avatar-uploader .el-upload {\r\n\tborder: 1px dashed var(--el-border-color);\r\n\tborder-radius: 6px;\r\n\tcursor: pointer;\r\n\tposition: relative;\r\n\toverflow: hidden;\r\n\ttransition: var(--el-transition-duration-fast);\r\n}\r\n\r\n.avatar-uploader .el-upload:hover {\r\n\tborder-color: var(--el-color-primary);\r\n}\r\n\r\n.el-icon.avatar-uploader-icon {\r\n\tfont-size: 28px;\r\n\tcolor: #8c939d;\r\n\twidth: 178px;\r\n\theight: 178px;\r\n\ttext-align: center;\r\n}\r\n</style>\r\n"
  },
  {
    "path": "src/components/table-search.vue",
    "content": "<template>\r\n\t<div class=\"search-container\">\r\n\t\t<el-form ref=\"searchRef\" :model=\"query\" :inline=\"true\">\r\n\t\t\t<el-form-item :label=\"item.label\" :prop=\"item.prop\" v-for=\"item in options\">\r\n\t\t\t\t<!-- 文本框、下拉框、日期框 -->\r\n\t\t\t\t<el-input v-if=\"item.type === 'input'\" v-model=\"query[item.prop]\" :disabled=\"item.disabled\"\r\n\t\t\t\t\t:placeholder=\"item.placeholder\" clearable></el-input>\r\n\t\t\t\t<el-select v-else-if=\"item.type === 'select'\" v-model=\"query[item.prop]\" :disabled=\"item.disabled\"\r\n\t\t\t\t\t:placeholder=\"item.placeholder\" clearable>\r\n\t\t\t\t\t<el-option v-for=\"opt in item.opts\" :label=\"opt.label\" :value=\"opt.value\"></el-option>\r\n\t\t\t\t</el-select>\r\n\t\t\t\t<el-date-picker v-else-if=\"item.type === 'date'\" type=\"date\" v-model=\"query[item.prop]\"\r\n\t\t\t\t\t:value-format=\"item.format\"></el-date-picker>\r\n\t\t\t</el-form-item>\r\n\t\t\t<el-form-item>\r\n\t\t\t\t<el-button type=\"primary\" :icon=\"Search\" @click=\"search\">搜索</el-button>\r\n\t\t\t\t<el-button :icon=\"Refresh\" @click=\"resetForm(searchRef)\">重置</el-button>\r\n\t\t\t</el-form-item>\r\n\t\t</el-form>\r\n\t</div>\r\n</template>\r\n\r\n<script lang=\"ts\" setup>\r\nimport { FormInstance } from 'element-plus';\r\nimport { Search, Refresh } from '@element-plus/icons-vue';\r\nimport { PropType, ref } from 'vue';\r\nimport { FormOptionList } from '@/types/form-option';\r\n\r\nconst props = defineProps({\r\n\tquery: {\r\n\t\ttype: Object,\r\n\t\trequired: true\r\n\t},\r\n\toptions: {\r\n\t\ttype: Array as PropType<Array<FormOptionList>>,\r\n\t\trequired: true\r\n\t},\r\n\tsearch: {\r\n\t\ttype: Function,\r\n\t\tdefault: () => { }\r\n\t}\r\n});\r\n\r\nconst searchRef = ref<FormInstance>();\r\nconst resetForm = (formEl: FormInstance | undefined) => {\r\n\tif (!formEl) return\r\n\tformEl.resetFields()\r\n\tprops.search();\r\n}\r\n</script>\r\n\r\n<style scoped>\r\n.search-container {\r\n\tpadding: 20px 30px 0;\r\n\tbackground-color: #fff;\r\n\tmargin-bottom: 10px;\r\n\tborder: 1px solid #ddd;\r\n\tborder-radius: 5px\r\n}\r\n</style>\r\n"
  },
  {
    "path": "src/components/tabs.vue",
    "content": "<template>\r\n    <div class=\"tabs-container\">\r\n        <el-tabs v-model=\"activePath\" class=\"tabs\" type=\"card\" closable @tab-click=\"clickTabls\" @tab-remove=\"closeTabs\">\r\n            <el-tab-pane\r\n                v-for=\"item in tabs.list\"\r\n                :key=\"item.path\"\r\n                :label=\"item.title\"\r\n                :name=\"item.path\"\r\n                @click=\"setTags(item)\"\r\n            ></el-tab-pane>\r\n        </el-tabs>\r\n        <div class=\"Tabs-close-box\">\r\n            <el-dropdown @command=\"handleTags\">\r\n                <el-button size=\"small\" type=\"primary\" plain>\r\n                    标签选项\r\n                    <el-icon class=\"el-icon--right\">\r\n                        <arrow-down />\r\n                    </el-icon>\r\n                </el-button>\r\n                <template #dropdown>\r\n                    <el-dropdown-menu size=\"small\">\r\n                        <el-dropdown-item command=\"other\">关闭其他</el-dropdown-item>\r\n                        <el-dropdown-item command=\"current\">关闭当前</el-dropdown-item>\r\n                        <el-dropdown-item command=\"all\">关闭所有</el-dropdown-item>\r\n                    </el-dropdown-menu>\r\n                </template>\r\n            </el-dropdown>\r\n        </div>\r\n    </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, watch } from 'vue';\r\nimport { useTabsStore } from '../store/tabs';\r\nimport { onBeforeRouteUpdate, useRoute, useRouter } from 'vue-router';\r\n\r\nconst route = useRoute();\r\nconst router = useRouter();\r\nconst activePath = ref(route.fullPath);\r\nconst tabs = useTabsStore();\r\n// 设置标签\r\nconst setTags = (route: any) => {\r\n    const isExist = tabs.list.some((item) => {\r\n        return item.path === route.fullPath;\r\n    });\r\n    if (!isExist) {\r\n        tabs.setTabsItem({\r\n            name: route.name,\r\n            title: route.meta.title,\r\n            path: route.fullPath,\r\n        });\r\n    }\r\n};\r\nsetTags(route);\r\nonBeforeRouteUpdate((to) => {\r\n    setTags(to);\r\n});\r\n\r\n// 关闭全部标签\r\nconst closeAll = () => {\r\n    tabs.clearTabs();\r\n    router.push('/');\r\n};\r\n// 关闭其他标签\r\nconst closeOther = () => {\r\n    const curItem = tabs.list.filter((item) => {\r\n        return item.path === route.fullPath;\r\n    });\r\n    tabs.closeTabsOther(curItem);\r\n};\r\nconst handleTags = (command: string) => {\r\n    switch (command) {\r\n        case 'current':\r\n            // 关闭当前页面的标签页\r\n            tabs.closeCurrentTag({\r\n                $router: router,\r\n                $route: route,\r\n            });\r\n            break;\r\n        case 'all':\r\n            closeAll();\r\n            break;\r\n\r\n        case 'other':\r\n            closeOther();\r\n            break;\r\n    }\r\n};\r\n\r\nconst clickTabls = (item: any) => {\r\n    router.push(item.props.name);\r\n};\r\nconst closeTabs = (path: string) => {\r\n    const index = tabs.list.findIndex((item) => item.path === path);\r\n    tabs.delTabsItem(index);\r\n    const item = tabs.list[index] || tabs.list[index - 1];\r\n    router.push(item ? item.path : '/');\r\n};\r\n\r\nwatch(\r\n    () => route.fullPath,\r\n    (newVal, oldVal) => {\r\n        activePath.value = newVal;\r\n    }\r\n);\r\n</script>\r\n\r\n<style scss>\r\n.tabs-container {\r\n    position: relative;\r\n    overflow: hidden;\r\n    background: #fff;\r\n    padding: 2px 120px 0 0;\r\n}\r\n\r\n.tabs {\r\n    .el-tabs__header {\r\n        margin-bottom: 0;\r\n    }\r\n\r\n    .el-tabs__nav {\r\n        height: 28px;\r\n    }\r\n\r\n    .el-tabs__nav-next,\r\n    .el-tabs__nav-prev {\r\n        line-height: 32px;\r\n    }\r\n\r\n    &.el-tabs {\r\n        --el-tabs-header-height: 28px;\r\n    }\r\n}\r\n\r\n.Tabs-close-box {\r\n    position: absolute;\r\n    right: 0;\r\n    top: 0;\r\n    box-sizing: border-box;\r\n    padding-top: 1px;\r\n    text-align: center;\r\n    width: 110px;\r\n    height: 30px;\r\n    background: #fff;\r\n    box-shadow: -3px 0 15px 3px rgba(0, 0, 0, 0.1);\r\n    z-index: 10;\r\n}\r\n</style>\r\n"
  },
  {
    "path": "src/main.ts",
    "content": "import { createApp } from 'vue';\r\nimport { createPinia } from 'pinia';\r\nimport * as ElementPlusIconsVue from '@element-plus/icons-vue';\r\nimport App from './App.vue';\r\nimport router from './router';\r\nimport { usePermissStore } from './store/permiss';\r\nimport 'element-plus/dist/index.css';\r\nimport './assets/css/icon.css';\r\n\r\nconst app = createApp(App);\r\napp.use(createPinia());\r\napp.use(router);\r\n\r\n// 注册elementplus图标\r\nfor (const [key, component] of Object.entries(ElementPlusIconsVue)) {\r\n    app.component(key, component);\r\n}\r\n// 自定义权限指令\r\nconst permiss = usePermissStore();\r\napp.directive('permiss', {\r\n    mounted(el, binding) {\r\n        if (binding.value && !permiss.key.includes(String(binding.value))) {\r\n            el['hidden'] = true;\r\n        }\r\n    },\r\n});\r\n\r\napp.mount('#app');\r\n"
  },
  {
    "path": "src/router/index.ts",
    "content": "import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router';\r\nimport { usePermissStore } from '../store/permiss';\r\nimport Home from '../views/home.vue';\r\nimport NProgress from 'nprogress';\r\nimport 'nprogress/nprogress.css';\r\n\r\nconst routes: RouteRecordRaw[] = [\r\n    {\r\n        path: '/',\r\n        redirect: '/dashboard',\r\n    },\r\n    {\r\n        path: '/',\r\n        name: 'Home',\r\n        component: Home,\r\n        children: [\r\n            {\r\n                path: '/dashboard',\r\n                name: 'dashboard',\r\n                meta: {\r\n                    title: '系统首页',\r\n                    noAuth: true,\r\n                },\r\n                component: () => import(/* webpackChunkName: \"dashboard\" */ '../views/dashboard.vue'),\r\n            },\r\n            {\r\n                path: '/system-user',\r\n                name: 'system-user',\r\n                meta: {\r\n                    title: '用户管理',\r\n                    permiss: '11',\r\n                },\r\n                component: () => import(/* webpackChunkName: \"system-user\" */ '../views/system/user.vue'),\r\n            },\r\n            {\r\n                path: '/system-role',\r\n                name: 'system-role',\r\n                meta: {\r\n                    title: '角色管理',\r\n                    permiss: '12',\r\n                },\r\n                component: () => import(/* webpackChunkName: \"system-role\" */ '../views/system/role.vue'),\r\n            },\r\n            {\r\n                path: '/system-menu',\r\n                name: 'system-menu',\r\n                meta: {\r\n                    title: '菜单管理',\r\n                    permiss: '13',\r\n                },\r\n                component: () => import(/* webpackChunkName: \"system-menu\" */ '../views/system/menu.vue'),\r\n            },\r\n            {\r\n                path: '/table',\r\n                name: 'basetable',\r\n                meta: {\r\n                    title: '基础表格',\r\n                    permiss: '31',\r\n                },\r\n                component: () => import(/* webpackChunkName: \"table\" */ '../views/table/basetable.vue'),\r\n            },\r\n            {\r\n                path: '/table-editor',\r\n                name: 'table-editor',\r\n                meta: {\r\n                    title: '可编辑表格',\r\n                    permiss: '32',\r\n                },\r\n                component: () => import(/* webpackChunkName: \"table-editor\" */ '../views/table/table-editor.vue'),\r\n            },\r\n            {\r\n                path: '/schart',\r\n                name: 'schart',\r\n                meta: {\r\n                    title: 'schart图表',\r\n                    permiss: '41',\r\n                },\r\n                component: () => import(/* webpackChunkName: \"schart\" */ '../views/chart/schart.vue'),\r\n            },\r\n            {\r\n                path: '/echarts',\r\n                name: 'echarts',\r\n                meta: {\r\n                    title: 'echarts图表',\r\n                    permiss: '42',\r\n                },\r\n                component: () => import(/* webpackChunkName: \"echarts\" */ '../views/chart/echarts.vue'),\r\n            },\r\n\r\n            {\r\n                path: '/icon',\r\n                name: 'icon',\r\n                meta: {\r\n                    title: '图标',\r\n                    permiss: '5',\r\n                },\r\n                component: () => import(/* webpackChunkName: \"icon\" */ '../views/pages/icon.vue'),\r\n            },\r\n            {\r\n                path: '/ucenter',\r\n                name: 'ucenter',\r\n                meta: {\r\n                    title: '个人中心',\r\n                },\r\n                component: () => import(/* webpackChunkName: \"ucenter\" */ '../views/pages/ucenter.vue'),\r\n            },\r\n            {\r\n                path: '/editor',\r\n                name: 'editor',\r\n                meta: {\r\n                    title: '富文本编辑器',\r\n                    permiss: '291',\r\n                },\r\n                component: () => import(/* webpackChunkName: \"editor\" */ '../views/pages/editor.vue'),\r\n            },\r\n            {\r\n                path: '/markdown',\r\n                name: 'markdown',\r\n                meta: {\r\n                    title: 'markdown编辑器',\r\n                    permiss: '292',\r\n                },\r\n                component: () => import(/* webpackChunkName: \"markdown\" */ '../views/pages/markdown.vue'),\r\n            },\r\n            {\r\n                path: '/export',\r\n                name: 'export',\r\n                meta: {\r\n                    title: '导出Excel',\r\n                    permiss: '34',\r\n                },\r\n                component: () => import(/* webpackChunkName: \"export\" */ '../views/table/export.vue'),\r\n            },\r\n            {\r\n                path: '/import',\r\n                name: 'import',\r\n                meta: {\r\n                    title: '导入Excel',\r\n                    permiss: '33',\r\n                },\r\n                component: () => import(/* webpackChunkName: \"import\" */ '../views/table/import.vue'),\r\n            },\r\n            {\r\n                path: '/theme',\r\n                name: 'theme',\r\n                meta: {\r\n                    title: '主题设置',\r\n                    permiss: '7',\r\n                },\r\n                component: () => import(/* webpackChunkName: \"theme\" */ '../views/pages/theme.vue'),\r\n            },\r\n            {\r\n                path: '/calendar',\r\n                name: 'calendar',\r\n                meta: {\r\n                    title: '日历',\r\n                    permiss: '24',\r\n                },\r\n                component: () => import(/* webpackChunkName: \"calendar\" */ '../views/element/calendar.vue'),\r\n            },\r\n            {\r\n                path: '/watermark',\r\n                name: 'watermark',\r\n                meta: {\r\n                    title: '水印',\r\n                    permiss: '25',\r\n                },\r\n                component: () => import(/* webpackChunkName: \"watermark\" */ '../views/element/watermark.vue'),\r\n            },\r\n            {\r\n                path: '/carousel',\r\n                name: 'carousel',\r\n                meta: {\r\n                    title: '走马灯',\r\n                    permiss: '23',\r\n                },\r\n                component: () => import(/* webpackChunkName: \"carousel\" */ '../views/element/carousel.vue'),\r\n            },\r\n            {\r\n                path: '/tour',\r\n                name: 'tour',\r\n                meta: {\r\n                    title: '分步引导',\r\n                    permiss: '26',\r\n                },\r\n                component: () => import(/* webpackChunkName: \"tour\" */ '../views/element/tour.vue'),\r\n            },\r\n            {\r\n                path: '/steps',\r\n                name: 'steps',\r\n                meta: {\r\n                    title: '步骤条',\r\n                    permiss: '27',\r\n                },\r\n                component: () => import(/* webpackChunkName: \"steps\" */ '../views/element/steps.vue'),\r\n            },\r\n            {\r\n                path: '/form',\r\n                name: 'forms',\r\n                meta: {\r\n                    title: '表单',\r\n                    permiss: '21',\r\n                },\r\n                component: () => import(/* webpackChunkName: \"form\" */ '../views/element/form.vue'),\r\n            },\r\n            {\r\n                path: '/upload',\r\n                name: 'upload',\r\n                meta: {\r\n                    title: '上传',\r\n                    permiss: '22',\r\n                },\r\n                component: () => import(/* webpackChunkName: \"upload\" */ '../views/element/upload.vue'),\r\n            },\r\n            {\r\n                path: '/statistic',\r\n                name: 'statistic',\r\n                meta: {\r\n                    title: '统计',\r\n                    permiss: '28',\r\n                },\r\n                component: () => import(/* webpackChunkName: \"statistic\" */ '../views/element/statistic.vue'),\r\n            },\r\n        ],\r\n    },\r\n    {\r\n        path: '/login',\r\n        meta: {\r\n            title: '登录',\r\n            noAuth: true,\r\n        },\r\n        component: () => import(/* webpackChunkName: \"login\" */ '../views/pages/login.vue'),\r\n    },\r\n    {\r\n        path: '/register',\r\n        meta: {\r\n            title: '注册',\r\n            noAuth: true,\r\n        },\r\n        component: () => import(/* webpackChunkName: \"register\" */ '../views/pages/register.vue'),\r\n    },\r\n    {\r\n        path: '/reset-pwd',\r\n        meta: {\r\n            title: '重置密码',\r\n            noAuth: true,\r\n        },\r\n        component: () => import(/* webpackChunkName: \"reset-pwd\" */ '../views/pages/reset-pwd.vue'),\r\n    },\r\n    {\r\n        path: '/403',\r\n        meta: {\r\n            title: '没有权限',\r\n            noAuth: true,\r\n        },\r\n        component: () => import(/* webpackChunkName: \"403\" */ '../views/pages/403.vue'),\r\n    },\r\n    {\r\n        path: '/404',\r\n        meta: {\r\n            title: '找不到页面',\r\n            noAuth: true,\r\n        },\r\n        component: () => import(/* webpackChunkName: \"404\" */ '../views/pages/404.vue'),\r\n    },\r\n    { path: '/:path(.*)', redirect: '/404' },\r\n];\r\n\r\nconst router = createRouter({\r\n    history: createWebHashHistory(),\r\n    routes,\r\n});\r\n\r\nrouter.beforeEach((to, from, next) => {\r\n    NProgress.start();\r\n    const role = localStorage.getItem('vuems_name');\r\n    const permiss = usePermissStore();\r\n\r\n    if (!role && to.meta.noAuth !== true) {\r\n        next('/login');\r\n    } else if (typeof to.meta.permiss == 'string' && !permiss.key.includes(to.meta.permiss)) {\r\n        // 如果没有权限，则进入403\r\n        next('/403');\r\n    } else {\r\n        next();\r\n    }\r\n});\r\n\r\nrouter.afterEach(() => {\r\n    NProgress.done();\r\n});\r\n\r\nexport default router;\r\n"
  },
  {
    "path": "src/store/permiss.ts",
    "content": "import { defineStore } from 'pinia';\r\n\r\ninterface ObjectList {\r\n    [key: string]: string[];\r\n}\r\n\r\nexport const usePermissStore = defineStore('permiss', {\r\n    state: () => {\r\n        const defaultList: ObjectList = {\r\n            admin: [\r\n                '0',\r\n                '1',\r\n                '11',\r\n                '12',\r\n                '13',\r\n                '2',\r\n                '21',\r\n                '22',\r\n                '23',\r\n                '24',\r\n                '25',\r\n                '26',\r\n                '27',\r\n                '28',\r\n                '29',\r\n                '291',\r\n                '292',\r\n                '3',\r\n                '31',\r\n                '32',\r\n                '33',\r\n                '34',\r\n                '4',\r\n                '41',\r\n                '42',\r\n                '5',\r\n                '7',\r\n                '6',\r\n                '61',\r\n                '62',\r\n                '63',\r\n                '64',\r\n                '65',\r\n                '66',\r\n            ],\r\n            user: ['0', '1', '11', '12', '13'],\r\n        };\r\n        const username = localStorage.getItem('vuems_name');\r\n        console.log(username);\r\n        return {\r\n            key: (username == 'admin' ? defaultList.admin : defaultList.user) as string[],\r\n            defaultList,\r\n        };\r\n    },\r\n    actions: {\r\n        handleSet(val: string[]) {\r\n            this.key = val;\r\n        },\r\n    },\r\n});\r\n"
  },
  {
    "path": "src/store/sidebar.ts",
    "content": "import { defineStore } from 'pinia';\r\n\r\nexport const useSidebarStore = defineStore('sidebar', {\r\n\tstate: () => {\r\n\t\treturn {\r\n\t\t\tcollapse: false,\r\n\t\t\tbgColor: localStorage.getItem('sidebar-bg-color') || '#324157',\r\n\t\t\ttextColor: localStorage.getItem('sidebar-text-color') || '#bfcbd9'\r\n\t\t};\r\n\t},\r\n\tgetters: {},\r\n\tactions: {\r\n\t\thandleCollapse() {\r\n\t\t\tthis.collapse = !this.collapse;\r\n\t\t},\r\n\t\tsetBgColor(color: string) {\r\n\t\t\tthis.bgColor = color;\r\n\t\t\tlocalStorage.setItem('sidebar-bg-color', color);\r\n\t\t},\r\n\t\tsetTextColor(color: string) {\r\n\t\t\tthis.textColor = color;\r\n\t\t\tlocalStorage.setItem('sidebar-text-color', color);\r\n\t\t}\r\n\t}\r\n});\r\n"
  },
  {
    "path": "src/store/tabs.ts",
    "content": "import { defineStore } from 'pinia';\r\n\r\ninterface ListItem {\r\n\tname: string;\r\n\tpath: string;\r\n\ttitle: string;\r\n}\r\n\r\nexport const useTabsStore = defineStore('tabs', {\r\n\tstate: () => {\r\n\t\treturn {\r\n\t\t\tlist: <ListItem[]>[]\r\n\t\t};\r\n\t},\r\n\tgetters: {\r\n\t\tshow: state => {\r\n\t\t\treturn state.list.length > 0;\r\n\t\t},\r\n\t\tnameList: state => {\r\n\t\t\treturn state.list.map(item => item.name);\r\n\t\t}\r\n\t},\r\n\tactions: {\r\n\t\tdelTabsItem(index: number) {\r\n\t\t\tthis.list.splice(index, 1);\r\n\t\t},\r\n\t\tsetTabsItem(data: ListItem) {\r\n\t\t\tthis.list.push(data);\r\n\t\t},\r\n\t\tclearTabs() {\r\n\t\t\tthis.list = [];\r\n\t\t},\r\n\t\tcloseTabsOther(data: ListItem[]) {\r\n\t\t\tthis.list = data;\r\n\t\t},\r\n\t\tcloseCurrentTag(data: any) {\r\n\t\t\tfor (let i = 0, len = this.list.length; i < len; i++) {\r\n\t\t\t\tconst item = this.list[i];\r\n\t\t\t\tif (item.path === data.$route.fullPath) {\r\n\t\t\t\t\tif (i < len - 1) {\r\n\t\t\t\t\t\tdata.$router.push(this.list[i + 1].path);\r\n\t\t\t\t\t} else if (i > 0) {\r\n\t\t\t\t\t\tdata.$router.push(this.list[i - 1].path);\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tdata.$router.push('/');\r\n\t\t\t\t\t}\r\n\t\t\t\t\tthis.list.splice(i, 1);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n});\r\n"
  },
  {
    "path": "src/store/theme.ts",
    "content": "import { mix, setProperty } from '@/utils';\r\nimport { defineStore } from 'pinia';\r\n\r\nexport const useThemeStore = defineStore('theme', {\r\n    state: () => {\r\n        return {\r\n            primary: '',\r\n            success: '',\r\n            warning: '',\r\n            danger: '',\r\n            info: '',\r\n            headerBgColor: '#242f42',\r\n            headerTextColor: '#fff',\r\n        };\r\n    },\r\n    getters: {},\r\n    actions: {\r\n        initTheme() {\r\n            ['primary', 'success', 'warning', 'danger', 'info'].forEach((type) => {\r\n                const color = localStorage.getItem(`theme-${type}`) || '';\r\n                if (color) {\r\n                    this.setPropertyColor(color, type); // 设置主题色\r\n                }\r\n            });\r\n            const headerBgColor = localStorage.getItem('header-bg-color');\r\n            headerBgColor && this.setHeaderBgColor(headerBgColor);\r\n            const headerTextColor = localStorage.getItem('header-text-color');\r\n            headerTextColor && this.setHeaderTextColor(headerTextColor);\r\n        },\r\n        resetTheme() {\r\n            ['primary', 'success', 'warning', 'danger', 'info'].forEach((type) => {\r\n                this.setPropertyColor('', type); // 重置主题色\r\n            });\r\n        },\r\n        setPropertyColor(color: string, type: string = 'primary') {\r\n            this[type] = color;\r\n            setProperty(`--el-color-${type}`, color);\r\n            localStorage.setItem(`theme-${type}`, color);\r\n            this.setThemeLight(type);\r\n        },\r\n        setThemeLight(type: string = 'primary') {\r\n            [3, 5, 7, 8, 9].forEach((v) => {\r\n                setProperty(`--el-color-${type}-light-${v}`, mix('#ffffff', this[type], v / 10));\r\n            });\r\n            setProperty(`--el-color-${type}-dark-2`, mix('#ffffff', this[type], 0.2));\r\n        },\r\n        setHeaderBgColor(color: string) {\r\n            this.headerBgColor = color;\r\n            setProperty('--header-bg-color', color);\r\n            localStorage.setItem(`header-bg-color`, color);\r\n        },\r\n        setHeaderTextColor(color: string) {\r\n            this.headerTextColor = color;\r\n            setProperty('--header-text-color', color);\r\n            localStorage.setItem(`header-text-color`, color);\r\n        }\r\n    }\r\n});"
  },
  {
    "path": "src/types/form-option.ts",
    "content": "export interface FormOption {\r\n    list: FormOptionList[];\r\n    labelWidth?: number | string;\r\n    span?: number;\r\n\r\n}\r\n\r\nexport interface FormOptionList {\r\n    prop: string;\r\n    label: string;\r\n    type: string;\r\n    placeholder?: string;\r\n    disabled?: boolean;\r\n    opts?: any[];\r\n    format?: string;\r\n    activeValue?: any;\r\n    inactiveValue?: any;\r\n    activeText?: string;\r\n    inactiveText?: string;\r\n    required?: boolean;\r\n}"
  },
  {
    "path": "src/types/menu.ts",
    "content": "export interface Menus {\r\n    id: string;\r\n    pid?: string;\r\n    icon?: string;\r\n    index: string;\r\n    title: string;\r\n    permiss?: string;\r\n    children?: Menus[];\r\n}"
  },
  {
    "path": "src/types/role.ts",
    "content": "\r\nexport interface Role {\r\n    id: number;\r\n    name: string;\r\n    key: string;\r\n    status: boolean;\r\n    permiss: string[]\r\n}"
  },
  {
    "path": "src/types/table.ts",
    "content": "export interface TableItem {\r\n    id: number;\r\n    name: string;\r\n    thumb: string;\r\n    money: number;\r\n    state: string;\r\n    date: string;\r\n    address: string;\r\n}"
  },
  {
    "path": "src/types/user.ts",
    "content": "\r\nexport interface User {\r\n    id: number;\r\n    name: string;\r\n    password: string;\r\n    email: string;\r\n    phone: string;\r\n    role: string;\r\n    date: string;\r\n}\r\n\r\nexport interface Register {\r\n    username: string;\r\n    password: string;\r\n    email: string;\r\n}"
  },
  {
    "path": "src/utils/china.ts",
    "content": "let chinaMap:any = {\"type\":\"FeatureCollection\",\"features\":[{\"id\":\"710000\",\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[\"@@°Ü¯Û\",\"@@ƛĴÕƊÉɼģºðʀ\\\\ƎsÆNŌÔĚänÜƤɊĂǀĆĴĤǊŨxĚĮǂƺòƌâÔ®ĮXŦţƸZûÐƕƑGđ¨ĭMó·ęcëƝɉlÝƯֹÅŃ^Ó·śŃǋƏďíåɛGɉ¿IċããF¥ĘWǬÏĶñÄ\",\"@@\\\\p|WoYG¿¥Ij@\",\"@@¡@V^RqBbAnTXeQr©C\",\"@@ÆEEkWqë I\"]],\"encodeOffsets\":[[[122886,24033],[123335,22980],[122375,24193],[122518,24117],[124427,22618]]]},\"properties\":{\"cp\":[121.509062,25.044332],\"name\":\"台湾\",\"childNum\":5}},{\"id\":\"130000\",\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[\"@@\\\\aM`Ç½ÓnUKĜēs¤­©yrý§uģcJ»eIP]ªrºc_ħ²G¼s`jÎŸnüsÂľP\",\"@@U`Ts¿mÄ\",\"@@FOhđ©OiÃ`ww^ÌkÑH«ƇǤŗĺtFu{Z}Ö@U´ʚLg®¯Oı°Ãw ^VbÉsmAê]]w§RRl£ŭuwNÁ`ÇFēÝčȻuT¡Ĺ¯Õ¯sŗő£YªhVƍ£ƅnëYNgq¼ś¿µı²UºÝUąąŖóxV@tƯJ]eR¾fe|rHA|h~Ėƍl§ÏjVë` ØoÅbbx³^zÃĶ¶Sj®AyÂhðk`«PËµEFÛ¬Y¨Ļrõqi¼Wi°§Ð±²°`[À|ĠO@ÆxO\\\\ta\\\\p_Zõ^û{ġȧXýĪÓjùÎRb^Î»j{íděYfíÙTymńŵōHim½éŅ­aVcř§ax¹XŻácWU£ôãºQ¨÷Ñws¥qEHÙ|šYQoŕÇyáĂ£MÃ°oťÊP¡mWO¡v{ôvîēÜISpÌhp¨ jdeŔQÖjX³àĈ[n`Yp@UcM`RKhEbpŞlNut®EtqnsÁgAiúoHqCXhfgu~ÏWP½¢G^}¯ÅīGCÑ^ãziMáļMTÃƘrMc|O_¯Ŏ´|morDkO\\\\mĆJfl@cĢ¬¢aĦtRıÒXòë¬WP{ŵǫƝīÛ÷ąV×qƥV¿aȉd³BqPBmaËđŻģmÅ®V¹d^KKonYg¯XhqaLdu¥Ípǅ¡KąÅkĝęěhq}HyÃ]¹ǧ£Í÷¿qágPmoei¤o^á¾ZEY^Ný{nOl±Í@Mċèk§daNaÇį¿]øRiiñEūiǱàUtėGyl}ÓM}jpEC~¡FtoQiHkk{ILgĽxqÈƋÄdeVDJj£J|ÅdzÂFt~KŨ¸IÆv|¢r}èonb}`RÎÄn°ÒdÞ²^®lnÐèĄlðÓ×]ªÆ}LiĂ±Ö`^°Ç¶p®đDcŋ`ZÔ¶êqvFÆN®ĆTH®¦O¾IbÐã´BĐɢŴÆíȦpĐÞXR·nndO¤OÀĈƒ­QgµFo|gȒęSWb©osx|hYhgŃfmÖĩnºTÌSp¢dYĤ¶UĈjlǐpäðëx³kÛfw²Xjz~ÂqbTÑěŨ@|oMzv¢ZrÃVw¬ŧĖ¸f°ÐTªqs{S¯r æÝl¼ÖĞ ǆiGĘJ¼lr}~K¨ŸƐÌWö¼Þ°nÞoĦL|C~D©|q]SvKÑcwpÏÏĿćènĪWlĄkT}¬Tp~®Hgd˒ĺBVtEÀ¢ôPĎƗè@~kü\\\\rÊĔÖæW_§¼F´©òDòjYÈrbĞāøŀG{ƀ|¦ðrb|ÀH`pʞkvGpuARhÞÆǶgĘTǼƹS£¨¡ù³ŘÍ]¿ÂyôEP xX¶¹ÜO¡gÚ¡IwÃé¦ÅBÏ|Ç°N«úmH¯âbęU~xĈbȒ{^xÖlD¸dɂ~\"]],\"encodeOffsets\":[[[120023,41045],[121616,39981],[122102,42307]]]},\"properties\":{\"cp\":[114.502461,38.045474],\"name\":\"河北\",\"childNum\":3}},{\"id\":\"140000\",\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[\"@@ħÜ_ªlìwGkÛÃǏokćiµVZģ¡coTSË¹ĪmnÕńehZg{gtwªpXaĚThȑp{¶Eh®RćƑP¿£PmcªaJyý{ýȥoÅîɡųAďä³aÏJ½¥PG­ąSM­sWz½µÛYÓŖgxoOkĒCo­Èµ]¯_²ÕjāK~©ÅØ^ÔkïçămÏk]­±cÝ¯ÑÃmQÍ~_apm~ç¡qu{JÅŧ·Ls}EyÁÆcI{¤IiCfUcƌÃp§]ě«vD@¡SÀµMÅwuYY¡DbÑc¡h×]nkoQdaMç~eDÛtT©±@¥ù@É¡ZcW|WqOJmĩl«ħşvOÓ«IqăV¥D[mI~Ó¢cehiÍ]Ɠ~ĥqX·eƷn±}v[ěďŕ]_œ`¹§ÕōIo©b­s^}Ét±ū«³p£ÿ¥WÑxçÁ«h×u×¥ř¾dÒ{ºvĴÎêÌɊ²¶ü¨|ÞƸµȲLLúÉƎ¤ϊęĔV`_bªS^|dzY|dz¥pZbÆ£¶ÒK}tĦÔņƠPYznÍvX¶Ěn ĠÔzý¦ª÷ÑĸÙUȌ¸dòÜJð´ìúNM¬XZ´¤ŊǸ_tldI{¦ƀðĠȤ¥NehXnYGR° ƬDj¬¸|CĞKqºfƐiĺ©ª~ĆOQª ¤@ìǦɌ²æBÊTĞHƘÁĪËĖĴŞȀÆÿȄlŤĒötÎ½î¼ĨXh|ªM¤ÐzÞĩÒSrao³\"],\"encodeOffsets\":[[117016,41452]]},\"properties\":{\"cp\":[112.549248,37.857014],\"name\":\"山西\",\"childNum\":1}},{\"id\":\"150000\",\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[\"@@ǪƫÌÛMĂ[`ÕCn}¶Vcês¯PqFB|S³C|kñHdiÄ¥sŉÅPóÑÑE^ÅPpy_YtShQ·aHwsOnŉÃs©iqjUSiº]ïW«gW¡ARëśĳĘů`çõh]y»ǃǛҤxÒm~zf}pf|ÜroÈzrKÈĵSƧż؜Ġu~è¬vîS¼ĂhĖMÈÄw\\\\fŦ°W ¢¾luŸDw\\\\Ŗĝ\",\"@@GVu»Aylßí¹ãe]Eāò³C¹ð¾²iÒAdkò^P²CǜңǄ z¼g^èöŰ_Ĳĕê}gÁnUI«m]jvV¼euhwqAaW_µj»çjioQR¹ēÃßt@r³[ÛlćË^ÍÉáGOUÛOB±XkÅ¹£k|e]olkVÍ¼ÕqtaÏõjgÁ£§U^RLËnX°ÇBz^~wfvypV ¯ƫĉ˭ȫƗŷɿÿĿƑ˃ĝÿÃǃßËőó©ǐȍŒĖM×ÍEyxþp]ÉvïèvƀnÂĴÖ@V~Ĉ³MEĸÅĖtējyÄDXÄxGQuv_i¦aBçw˛wD©{tāmQ{EJ§KPśƘƿ¥@sCTÉ}ɃwƇy±gÑ}T[÷kÐç¦«SÒ¥¸ëBX½HáÅµÀğtSÝÂa[ƣ°¯¦Pï¡]£ġÒk®G²èQ°óMq}EóƐÇ\\\\@áügQÍu¥FTÕ¿Jû]|mvāÎYua^WoÀa·­ząÒot×¶CLƗi¯¤mƎHǊ¤îìɾŊìTdåwsRÖgĒųúÍġäÕ}Q¶¿A[¡{d×uQAMxVvMOmăl«ct[wº_ÇÊjbÂ£ĦS_éQZ_lwgOiýe`YYJq¥IÁǳ£ÙË[ÕªuƏ³ÍTs·bÁĽäė[b[ŗfãcn¥îC¿÷µ[ŏÀQ­ōĉm¿Á^£mJVmL[{Ï_£F¥Ö{ŹA}×Wu©ÅaųĳƳhB{·TQqÙIķËZđ©Yc|M¡LeVUóK_QWk_ĥ¿ãZ»X\\\\ĴuUèlG®ěłTĠğDŃGÆÍz]±ŭ©Å]ÅÐ}UË¥©TċïxgckfWgi\\\\ÏĒ¥HkµEë{»ÏetcG±ahUiñiWsɁ·cCÕk]wȑ|ća}wVaĚá G°ùnM¬¯{ÈÐÆA¥ÄêJxÙ¢hP¢ÛºµwWOóFÁz^ÀŗÎú´§¢T¤ǻƺSėǵhÝÅQgvBHouʝl_o¿Ga{ïq{¥|ſĿHĂ÷aĝÇqZñiñC³ª»E`¨åXēÕqÉû[l}ç@čƘóO¿¡FUsAʽīccocÇS}£IS~ălkĩXçmĈŀÐoÐdxÒuL^T{r@¢ÍĝKén£kQyÅõËXŷƏL§~}kq»IHėǅjĝ»ÑÞoå°qTt|r©ÏS¯·eŨĕx«È[eM¿yupN~¹ÏyN£{©għWí»Í¾səšǅ_ÃĀɗ±ąĳĉʍŌŷSÉA±åǥɋ@ë£R©ąP©}ĹªƏj¹erLDĝ·{i«ƫC½ÉshVzGS|úþXgp{ÁX¿ć{ƱȏñZáĔyoÁhA}ŅĆfdŉ_¹Y°ėǩÑ¡H¯¶oMQqð¡Ë|Ñ`ƭŁX½·óÛxğįÅcQs«tȋǅFù^it«Č¯[hAi©á¥ÇĚ×l|¹y¯Kȝqgů{ñǙµïċĹzŚȭ¶¡oŽäÕG\\\\ÄT¿Òõr¯LguÏYęRƩɷŌO\\\\İÐ¢æ^Ŋ ĲȶȆbÜGĝ¬¿ĚVĎgª^íu½jÿĕęjık@Ľ]ėl¥ËĭûÁėéV©±ćn©­ȇÍq¯½YÃÔŉÉNÑÅÝy¹NqáʅDǡËñ­ƁYÅy̱os§ȋµʽǘǏƬɱàưN¢ƔÊuľýľώȪƺɂļxZĈ}ÌŉŪĺœĭFЛĽ̅ȣͽÒŵìƩÇϋÿȮǡŏçƑůĕ~Ç¼ȳÐUfdIxÿ\\\\G zâɏÙOº·pqy£@qþ@Ǟ˽IBäƣzsÂZÁàĻdñ°ŕzéØűzșCìDȐĴĺf®Àľưø@ɜÖÞKĊŇƄ§͑těï͡VAġÑÑ»d³öǍÝXĉĕÖ{þĉu¸ËʅğU̎éhɹƆ̗̮ȘǊ֥ड़ࡰţાíϲäʮW¬®ҌeרūȠkɬɻ̼ãüfƠSצɩςåȈHϚÎKǳͲOðÏȆƘ¼CϚǚ࢚˼ФÔ¤ƌĞ̪Qʤ´¼mȠJˀƲÀɠmɆǄĜƠ´ǠN~ʢĜ¶ƌĆĘźʆȬ˪ĚĒ¸ĞGȖƴƀj`ĢçĶāàŃºēĢĖćYÀŎüôQÐÂŎŞǆŞêƖoˆDĤÕºÑǘÛˤ³̀gńƘĔÀ^ªƂ`ªt¾äƚêĦĀ¼ÐĔǎ¨Ȕ»͠^ˮÊȦƤøxRrŜH¤¸ÂxDÄ|ø˂˜ƮÐ¬ɚwɲFjĔ²Äw°ǆdÀÉ_ĸdîàŎjÊêTĞªŌŜWÈ|tqĢUB~´°ÎFCU¼pĀēƄN¦¾O¶łKĊOjĚj´ĜYp{¦SĚÍ\\\\T×ªV÷Ší¨ÅDK°ßtŇĔK¨ǵÂcḷ̌ĚǣȄĽFlġUĵŇȣFʉɁMğįʏƶɷØŭOǽ«ƽū¹Ʊő̝Ȩ§ȞʘĖiɜɶʦ}¨֪ࠜ̀ƇǬ¹ǨE˦ĥªÔêFxúQEr´Wrh¤Ɛ \\\\talĈDJÜ|[Pll̚¸ƎGú´P¬W¦^¦H]prRn|or¾wLVnÇIujkmon£cX^Bh`¥V¦U¤¸}xRj[^xN[~ªxQ[`ªHÆÂExx^wN¶Ê|¨ìMrdYpoRzNyÀDs~bcfÌ`L¾n|¾T°c¨È¢ar¤`[|òDŞĔöxElÖdHÀI`Ď\\\\Àì~ÆR¼tf¦^¢ķ¶eÐÚMptgjɡČÅyġLûŇV®ÄÈƀĎ°P|ªVVªj¬ĚÒêp¬E|ŬÂ_~¼rƐK f{ĘFĒƌXưăkÃĄ}nµo×q£ç­kX{uĩ«āíÓUŅÝVUŌ]Ť¥lyň[oi{¦LĸĦ^ôâJ¨^UZðÚĒL¿Ìf£K£ʺoqNwğc`uetOj×°KJ±qÆġmĚŗos¬qehqsuH{¸kH¡ÊRǪÇƌbȆ¢´äÜ¢NìÉʖ¦â©Ɨؗ\"]],\"encodeOffsets\":[[[128500,52752],[127089,51784]]]},\"properties\":{\"cp\":[111.670801,40.818311],\"name\":\"内蒙古\",\"childNum\":2}},{\"id\":\"210000\",\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[\"@@L@@s]\",\"@@MnNm\",\"@@dc\",\"@@eÀC@b\",\"@@fXwkbrÄ`qg\",\"@@^jtWQ\",\"@@~ Y[c\",\"@@I`ĖN^_¿ZÁM\",\"@@Ïxǌ{q_×^Gigp\",\"@@iX¶BY\",\"@@YZ\",\"@@L_yG`b\",\"@@^WqCTZ\",\"@@\\\\[§t|]\",\"@@m`p[\",\"@@@é^BntaÊU]x ¯ÄPĲ­°hʙK³VÕ@Y~|EvĹsÇ¦­L^pÃ²ŸÒG Ël]xxÄ_fT¤Ď¤cPC¨¸TVjbgH²sdÎdHt`B²¬GJję¶[ÐhjeXdlwhðSČ¦ªVÊÏÆZÆŶ®²^ÎyÅHńĚDMħĜŁH­kçvV[ĳ¼WYÀäĦ`XlR`ôLUVfK¢{NZdĒªYĸÌÚJRr¸SA|ƴgŴĴÆbvªØX~źB|¦ÕE¤Ð`\\\\|KUnnI]¤ÀÂĊnŎR®Ő¿¶\\\\ÀøíDm¦ÎbŨabaĘ\\\\ľãÂ¸atÎSƐ´©v\\\\ÖÚÌǴ¤Â¨JKrZ_ZfjþhPkx`YRIjJcVf~sCN¤ EhæmsHy¨SðÑÌ\\\\\\\\ĐRÊwS¥fqŒßýáĞÙÉÖ[^¯ǤŲê´\\\\¦¬ĆPM¯£»uïpùzExanµyoluqe¦W^£ÊL}ñrkqWňûPUP¡ôJoo·U}£[·¨@XĸDXm­ÛÝºGUCÁª½{íĂ^cjk¶Ã[q¤LÉö³cux«|Zd²BWÇ®Yß½ve±ÃCý£W{Ú^q^sÑ·¨ËMr¹·C¥GDrí@wÕKţÃ«V·i}xËÍ÷i©ĝɝǡ]{c±OW³Ya±_ç©HĕoƫŇqr³Lys[ñ³¯OSďOMisZ±ÅFC¥Pq{Ã[Pg}\\\\¿ghćOk^ĩÃXaĕËĥM­oEqqZûěŉ³F¦oĵhÕP{¯~TÍlªNßYÐ{Ps{ÃVUeĎwk±ŉVÓ½ŽJãÇÇ»Jm°dhcÀffdF~ĀeĖd`sx² ®EĦ¦dQÂd^~ăÔH¦\\\\LKpĄVez¤NP ǹÓRÆąJSh­a[¦´ÂghwmBÐ¨źhI|VV|p] Â¼èNä¶ÜBÖ¼L`¼bØæKVpoúNZÞÒKxpw|ÊEMnzEQIZZNBčÚFÜçmĩWĪñtÞĵÇñZ«uD±|ƏlǗw·±PmÍada CLǑkùó¡³Ï«QaċÏOÃ¥ÕđQȥċƭy³ÁA\"]],\"encodeOffsets\":[[[123686,41445],[126019,40435],[124393,40128],[126117,39963],[125322,40140],[126686,40700],[126041,40374],[125584,40168],[125509,40217],[125453,40165],[125362,40214],[125280,40291],[125774,39997],[125976,40496],[125822,39993],[122731,40949]]]},\"properties\":{\"cp\":[123.429096,41.796767],\"name\":\"辽宁\",\"childNum\":16}},{\"id\":\"220000\",\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[\"@@ñr½ÉKāGÁ¤ia ÉÈ¹`\\\\xs¬dĆkNnuNUwNx¶c¸|\\\\¢GªóĄ~RãÖÎĢùđŴÕhQxtcæëSɽŉíëǉ£ƍG£nj°KƘµDsØÑpyĆ¸®¿bXp]vbÍZuĂ{n^IüÀSÖ¦EvRÎûh@â[ƏÈô~FNr¯ôçR±­HÑlĢ^¤¢OðætxsŒ]ÞÁTĠs¶¿âÆGW¾ìA¦·TÑ¬è¥ÏÐJ¨¼ÒÖ¼ƦɄxÊ~StD@Ă¼Ŵ¡jlºWvÐzƦZÐ²CH AxiukdGgetqmcÛ£Ozy¥cE}|¾cZk¿uŐã[oxGikfeäT@SUwpiÚFM©£è^Ú`@v¶eňf heP¶täOlÃUgÞzŸU`l}ÔÆUvØ_Ō¬Öi^ĉi§²ÃB~¡ĈÚEgc|DC_Ȧm²rBx¼MÔ¦ŮdĨÃâYxƘDVÇĺĿg¿cwÅ\\\\¹¥Yĭl¤OvLjM_a W`zļMž·\\\\swqÝSAqŚĳ¯°kRē°wx^ĐkǂÒ\\\\]nrĂ}²ĊŲÒøãh·M{yMzysěnĒġV·°G³¼XÀ¤¹i´o¤ŃÈ`ÌǲÄUĞd\\\\iÖmÈBĤÜɲDEh LG¾ƀÄ¾{WaYÍÈĢĘÔRîĐj}ÇccjoUb½{h§Ǿ{KƖµÎ÷GĄØŜçưÌs«lyiē«`å§H¥Ae^§GK}iã\\\\c]v©ģZmÃ|[M}ģTɟĵÂÂ`ÀçmFK¥ÚíÁbX³ÌQÒHof{]ept·GŋĜYünĎųVY^ydõkÅZW«WUa~U·SbwGçǑiW^qFuNĝ·EwUtW·Ýďæ©PuqEzwAVXRãQ`­©GYYhcUGorBd}ģÉb¡·µMicF«Yƅ»é\\\\ɹ~ǙG³mØ©BšuT§Ĥ½¢Ã_Ã½L¡ûsT\\\\rke\\\\PnwAKy}ywdSefµ]UhĿD@mÿvaÙNSkCuncÿ`lWėVâ¦÷~^fÏ~vwHCį`xqT­­lW«ï¸skmßEGqd¯R©Ý¯¯S\\\\cZ¹iűƏCuƍÓXoR}M^o£R}oªU­FuuXHlEÅÏ©¤ßgXþ¤D²ÄufàÀ­XXÈ±Ac{Yw¬dvõ´KÊ£\\\\rµÄlidā]|î©¾DÂVH¹Þ®ÜWnCķ W§@\\\\¸~¤Vp¸póIO¢VOŇürXql~òÉK]¤¥Xrfkvzpm¶bwyFoúvð¼¤ N°ąO¥«³[éǣű]°Õ\\\\ÚÊĝôîŇÔaâBYlďQ[ Ë[ïÒ¥RI|`j]P\"],\"encodeOffsets\":[[126831,44503]]},\"properties\":{\"cp\":[125.3245,43.886841],\"name\":\"吉林\",\"childNum\":1}},{\"id\":\"230000\",\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[\"@@UµNÿ¥īèçHÍøƕ¶Lǽ|g¨|a¾pVidd~ÈiíďÓQġėÇZÎXb½|ſÃH½KFgɱCģÛÇAnjÕc[VĝǱÃËÇ_ £ń³pj£º¿»WH´¯U¸đĢmtĜyzzNN|g¸÷äűÑ±ĉā~mq^[ǁÑďlw]¯xQĔ¯l°řĴrBÞTxr[tŽ¸ĻN_yX`biNKuP£kZĮ¦[ºxÆÀdhĹŀUÈƗCwáZħÄŭcÓ¥»NAw±qȥnD`{ChdÙFć}¢A±Äj¨]ĊÕjŋ«×`VuÓÅ~_kŷVÝyhVkÄãPsOµfgeŇµf@u_Ù ÙcªNªÙEojVxT@ãSefjlwH\\\\pŏäÀvlY½d{F~¦dyz¤PÜndsrhfHcvlwjF£G±DÏƥYyÏu¹XikĿ¦ÏqƗǀOŜ¨LI|FRĂn sª|C˜zxAè¥bfudTrFWÁ¹Am|ĔĕsķÆF´N}ćUÕ@Áĳſmuçuð^ÊýowFzØÎĕNőǏȎôªÌŒǄàĀÄ˄ĞŀƒʀĀƘŸˮȬƬĊ°Uzouxe]}AyÈW¯ÌmKQ]Īºif¸ÄX|sZt|½ÚUÎ lk^p{f¤lºlÆW A²PVÜPHÊâ]ÎĈÌÜk´\\\\@qàsĔÄQºpRij¼èi`¶bXrBgxfv»uUi^v~J¬mVp´£´VWrnP½ì¢BX¬hðX¹^TjVriªjtŊÄmtPGx¸bgRsT`ZozÆO]ÒFôÒOÆŊvÅpcGêsx´DR{AEOr°x|íb³Wm~DVjºéNNËÜ˛ɶ­GxŷCSt}]ûōSmtuÇÃĕNāg»íT«u}ç½BĵÞʣ¥ëÊ¡MÛ³ãȅ¡ƋaǩÈÉQG¢·lG|tvgrrf«ptęŘnÅĢrI²¯LiØsPf_vĠdxM prʹL¤¤eËÀđKïÙVY§]Ióáĥ]ķK¥j|pŇ\\\\kzţ¦šnņäÔVĂîĪ¬|vW®l¤èØrxm¶ă~lÄƯĄ̈́öȄEÔ¤ØQĄĄ»ƢjȦOǺ¨ìSŖÆƬyQv`cwZSÌ®ü±Ǆ]ŀç¬B¬©ńzƺŷɄeeOĨSfm ĊƀP̎ēz©ĊÄÕÊmgÇsJ¥ƔŊśæÎÑqv¿íUOµªÂnĦÁ_½ä@êí£P}Ġ[@gġ}gɊ×ûÏWXá¢užƻÌsNÍ½ƎÁ§čŐAēeL³àydl¦ĘVçŁpśǆĽĺſÊQíÜçÛġÔsĕ¬Ǹ¯YßċġHµ ¡eå`ļrĉŘóƢFìĎWøxÊkƈdƬv|I|·©NqńRŀ¤éeŊŀàŀU²ŕƀBQ£Ď}L¹Îk@©ĈuǰųǨÚ§ƈnTËÇéƟÊcfčŤ^XmHĊĕË«W·ċëx³ǔķÐċJāwİ_ĸȀ^ôWr­°oú¬ĦŨK~ȰCĐ´Ƕ£fNÎèâw¢XnŮeÂÆĶ¾¾xäLĴĘlļO¤ÒĨA¢Êɚ¨®ØCÔ ŬGƠƦYĜĘÜƬDJg_ͥœ@čŅĻA¶¯@wÎqC½Ĉ»NăëKďÍQÙƫ[«ÃígßÔÇOÝáWñuZ¯ĥŕā¡ÑķJu¤E å¯°WKÉ±_d_}}vyõu¬ï¹ÓU±½@gÏ¿rÃ½DgCdµ°MFYxw¿CG£Rƛ½Õ{]L§{qqą¿BÇƻğëܭǊË|c²}Fµ}ÙRsÓpg±QNqǫŋRwŕnéÑÉK«SeYRŋ@{¤SJ}D Ûǖ֍]gr¡µŷjqWÛham³~S«Ü[\",\"@@ƨĶTLÇyqpÇÛqe{~oyen}s`qiXGù]Ëp½©lÉÁp]Þñ´FĂ^fäîºkàz¼BUv¬D\"]],\"encodeOffsets\":[[[134456,44547],[127123,51780]]]},\"properties\":{\"cp\":[126.642464,45.756967],\"name\":\"黑龙江\",\"childNum\":2}},{\"id\":\"320000\",\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[\"@@Õg^vÁbnÀ`Jnĝ¬òM¶ĘTÖŒbe¦¦{¸ZâćNp©Hp|`mjhSEb\\\\afv`sz^lkljÄtg¤D­¾X¿À|ĐiZȀåB·î}GL¢õcßjayBFµÏC^ĭcÙt¿sğH]j{s©HM¢QnDÀ©DaÜÞ·jgàiDbPufjDk`dPOîhw¡ĥ¥GP²ĐobºrYî¶aHŢ´ ]´rılw³r_{£DB_Ûdåuk|Ũ¯F Cºyr{XFye³Þċ¿ÂkĭB¿MvÛpm`rÚã@Ę¹hågËÖƿxnlč¶Åì½Ot¾dJlVJĂǀŞqvnO^JZż·Q}êÍÅmµÒ]ƍ¦Dq}¬R^èĂ´ŀĻĊIÔtĲyQŐĠMNtR®òLhĚs©»}OÓGZz¶A\\\\jĨFäOĤHYJvÞHNiÜaĎÉnFQlNM¤B´ĄNöɂtpŬdZÅglmuÇUšŞÚb¤uŃJŴu»¹ĄlȖħŴw̌ŵ²ǹǠ͛hĭłƕrçü±Yrřl¥i`ã__¢ćSÅr[Çq^ùzWmOĈaŐÝɞï²ʯʊáĘĳĒǭPħ͍ôƋÄÄÍīçÛɈǥ£­ÛmY`ó£Z«§°Ó³QafusNıǅ_k}¢m[ÝóDµ¡RLčiXyÅNïă¡¸iĔÏNÌķoıdōîåŤûHcs}~Ûwbù¹£¦ÓCtOPrE^ÒogĉIµÛÅʹK¤½phMú`mR¸¦PƚgÉLRs`£¯ãhD¨|³¤C\"],\"encodeOffsets\":[[121451,32518]]},\"properties\":{\"cp\":[118.767413,32.041544],\"name\":\"江苏\",\"childNum\":1}},{\"id\":\"330000\",\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[\"@@jX^n\",\"@@sfdM\",\"@@qP\\\\xz[_i\",\"@@o\\\\VzRZ}mECy\",\"@@R¢FX}°[m]\",\"@@Cb\\\\}\",\"@@e|v\\\\laus\",\"@@v~s{\",\"@@QxÂF©}\",\"@@¹nvÞs©m\",\"@@rQgYIh\",\"@@bi«ZX\",\"@@p[}ILd\",\"@@À¿|\",\"@@¹dnb\",\"@@rS}[Kl\",\"@@g~h}\",\"@@FlCk\",\"@@ůTG°ĄLHm°UF\",\"@@OdRe\",\"@@v[u\\\\\",\"@@FjâL~wyoo~sµLZ\",\"@@¬e¹aH\",\"@@\\\\nÔ¡q]L³ë\\\\ÿ®QÌ\",\"@@ÊA­©]ª\",\"@@Kxv{­\",\"@@@hlIk_\",\"@@pWcrxp\",\"@@Md|_iA\",\"@@¢X£½z\\\\ðpN\",\"@@hlÜ[LykAvyfw^E \",\"@@fp¤MusH\",\"@@®_ma~LÁ¬`\",\"@@@°¡mÛGĕ¨§Ianá[ýƤjfæÐNäGp\",\"@@iMt\\\\\",\"@@Zc[b\",\"@@X®±GrÆ°Zæĉm\",\"@@Z~dOSo|A¿qZv\",\"@@@`EN£p\",\"@@|s\",\"@@@nDi\",\"@@na£¾uYL¯QªmĉÅdMgÇjcº«ę¬­K­´B«Âącoċ\\\\xK`cįŧ«®á[~ıxu·ÅKsËÉc¢Ù\\\\ĭƛëbf¹­ģSĜkáƉÔ­ĈZB{aMµfzŉfÓÔŹŁƋǝÊĉ{ğč±g³ne{ç­ií´S¬\\\\ßðK¦w\\\\iqªĭiAuA­µ_W¥ƣO\\\\lċĢttC¨£t`PZäuXßBsĻyekOđġĵHuXBµ]×­­\\\\°®¬F¢¾pµ¼kŘó¬Wät¸|@L¨¸µrºù³Ù~§WIZW®±Ð¨ÒÉx`²pĜrOògtÁZ{üÙ[|ûKwsPlU[}¦Rvn`hsª^nQ´ĘRWb_ rtČFIÖkĦPJ¶ÖÀÖJĈĄTĚòC ²@PúØz©Pî¢£CÈÚĒ±hŖl¬â~nm¨f©iļ«mntqÒTÜÄjL®EÌFª²iÊxØ¨IÈhhst[Ôx}dtüGæţŔïĬaĸpMËÐjē¢·ðĄÆMzjWKĎ¢Q¶À_ê_@ıi«pZgf¤Nrq]§ĂN®«H±yƳí¾×ŊďŀĐÏŴǝĂíÀBŖÕªÁŐTFqĉ¯³ËCĕģi¨hÜ·ñt»¯Ï\",\"@@ºwZRkĕWK \"]],\"encodeOffsets\":[[[125785,31436],[125729,31431],[125513,31380],[125329,30690],[125223,30438],[125115,30114],[124815,29155],[124419,28746],[124095,28635],[124005,28609],[125000,30713],[125111,30698],[125078,30682],[125150,30684],[124014,28103],[125008,31331],[125411,31468],[125329,31479],[125369,31139],[125626,30916],[125417,30956],[125254,30976],[125199,30997],[125095,31058],[125083,30915],[124885,31015],[125218,30798],[124867,30838],[124755,30788],[124802,30809],[125267,30657],[125218,30578],[125200,30562],[125192,30787],[124968,30474],[125167,30396],[125115,30363],[124955,29879],[124714,29781],[124762,29462],[124325,28754],[124863,30077],[125366,31477]]]},\"properties\":{\"cp\":[120.153576,30.287459],\"name\":\"浙江\",\"childNum\":43}},{\"id\":\"340000\",\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[\"@@^iuLV\\\\\",\"@@e©Edh\",\"@@´CE¶zAXêeödK¡~H¸íæAȽd{ďÅÀ½W®£ChÃsikkly]_teu[bFaTign{]GqªoĈMYá|·¥f¥őaSÕėNµñĞ«Im_m¿Âa]uĜp Z_§{Cäg¤°r[_YjÆOdý[I[á·¥Q_nùgL¾mzˆDÜÆ¶ĊJhpc¹O]iŠ]¥ jtsggDÑ¡w×jÉ©±EFË­KiÛÃÕYvsm¬njĻª§emná}k«ŕgđ²ÙDÇ¤í¡ªOy×Où±@DñSęćăÕIÕ¿IµĥOlJÕÍRÍ|JìĻÒåyķrĕq§ÄĩsWÆßF¶X®¿mwRIÞfßoG³¾©uyHį{Ɓħ¯AFnuPÍÔzVdàôº^Ðæd´oG¤{S¬ćxã}ŧ×Kǥĩ«ÕOEÐ·ÖdÖsƘÑ¨[Û^Xr¢¼§xvÄÆµ`K§ tÒ´Cvlo¸fzŨð¾NY´ı~ÉĔēßúLÃÃ_ÈÏ|]ÂÏHlg`ben¾¢pUh~ƴĖ¶_r sĄ~cƈ]|r c~`¼{À{ȒiJjz`îÀT¥Û³]u}fïQl{skloNdjäËzDvčoQďHI¦rbrHĖ~BmlNRaĥTX\\\\{fÁKÁ®TLÂÄMtÊgĀDĄXƔvDcÎJbt[¤D@®hh~kt°ǾzÖ@¾ªdbYhüóV´ŮŒ¨Üc±r@J|àuYÇÔG·ĚąĐlŪÚpSJ¨ĸLvÞcPæķŨ®mÐálsgd×mQ¨ųÆ©Þ¤IÎs°KZpĄ|XwWdĎµmkǀwÌÕæhºgBĝâqÙĊzÖgņtÀÁĂÆáhEz|WzqD¹°Eŧl{ævÜcA`¤C`|´qxĲkq^³³GšµbíZ¹qpa±ď OH¦Ħx¢gPícOl_iCveaOjChß¸iÝbÛªCC¿mRV§¢A|tbkĜEÀtîm^g´fÄ\"]],\"encodeOffsets\":[[[121722,32278],[119475,30423],[121606,33646]]]},\"properties\":{\"cp\":[117.283042,31.86119],\"name\":\"安徽\",\"childNum\":3}},{\"id\":\"350000\",\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[\"@@zht´}[\",\"@@aj^~ĆGå\",\"@@edHse\",\"@@@vPGsyQ\",\"@@sBzddW[O\",\"@@S¨Qy\",\"@@NVucW\",\"@@qptB@q\",\"@@¸[iu\",\"@@Q\\\\pD[_\",\"@@jSwUappI\",\"@@eXª~\",\"@@AjvFoo\",\"@@fT_Çí\\\\v|ba¦jZÆy|®\",\"@@IjLg\",\"@@wJIx«¼AoNe{M¥\",\"@@K±¡ÓČ~N¾\",\"@@k¡¹Eh~c®uDqZì¡I~Māe£bN¨gZý¡a±Öcp©PhI¢QqÇGj|¥U g[Ky¬ŏv@OptÉEF\\\\@ åA¬V{XģĐBycpě¼³Ăp·¤¥ohqqÚ¡ŅLs^Ã¡§qlÀhH¨MCe»åÇGD¥zPO£čÙkJA¼ßėuĕeûÒiÁŧS[¡Uûŗ½ùěcÝ§SùĩąSWó«íęACµeRåǃRCÒÇZÍ¢ź±^dlstjD¸ZpuÔâÃH¾oLUêÃÔjjēò´ĄWƛ^Ñ¥Ħ@ÇòmOw¡õyJyD}¢ďÑÈġfZda©º²z£NjD°Ötj¶¬ZSÎ~¾c°¶ÐmxO¸¢Pl´SL|¥AȪĖMņĲg®áIJČĒü` QF¬h|ĂJ@zµ |ê³È ¸UÖŬŬÀCtrĸr]ðM¤ĶĲHtÏ AĬkvsq^aÎbvdfÊòSD´Z^xPsĂrvƞŀjJd×ŘÉ ®AÎ¦ĤdxĆqAZRÀMźnĊ»İÐZ YXæJyĊ²·¶q§·K@·{sXãô«lŗ¶»o½E¡­«¢±¨Y®Ø¶^AvWĶGĒĢPlzfļtàAvWYãO_¤sD§ssČġ[kƤPX¦`¶®BBvĪjv©jx[L¥àï[F¼ÍË»ğV`«Ip}ccÅĥZEãoP´B@D¸m±z«Ƴ¿å³BRØ¶Wlâþäą`]Z£Tc ĹGµ¶Hm@_©k¾xĨôȉðX«½đCIbćqK³ÁÄš¬OAwã»aLŉËĥW[ÂGIÂNxĳ¤D¢îĎÎB§°_JGs¥E@¤ućPåcuMuw¢BI¿]zG¹guĮI\"]],\"encodeOffsets\":[[[123250,27563],[122541,27268],[123020,27189],[122916,27125],[122887,26845],[122808,26762],[122568,25912],[122778,26197],[122515,26757],[122816,26587],[123388,27005],[122450,26243],[122578,25962],[121255,25103],[120987,24903],[122339,25802],[121042,25093],[122439,26024]]]},\"properties\":{\"cp\":[119.306239,26.075302],\"name\":\"福建\",\"childNum\":18}},{\"id\":\"360000\",\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[\"@@ÖP¬ǦĪØLŨä~Ĉw«|TH£pc³Ïå¹]ĉđxe{ÎÓvOEm°BƂĨİ|Gvz½ª´HàpeJÝQxnÀW­EµàXÅĪt¨ÃĖrÄwÀFÎ|Ă¡WÕ¸cf¥XaęST±m[r«_gmQu~¥V\\\\OkxtL E¢Ú^~ýØkbēqoě±_Êw§Ñ²ÏƟė¼mĉŹ¿NQYBąrwģcÍ¥B­ŗÊcØiIƝĿuqtāwO]³YCñTeÉcaubÍ]trluīBÐGsĵıN£ï^ķqsq¿DūūVÕ·´Ç{éĈýÿOER_đûIċâJh­ŅıNȩĕB¦K{Tk³¡OP·wnµÏd¯}½TÍ«YiµÕsC¯iM¤­¦¯P|ÿUHvhe¥oFTuõ\\\\OSsMòđƇiaºćXĊĵà·çhƃ÷Ç{ígu^đgm[ÙxiIN¶Õ»lđÕwZSÆv©_ÈëJbVkĔVÀ¤P¾ºÈMÖxlò~ªÚàGĂ¢B±ÌKyñ`w²¹·`gsÙfIěxŕeykpudjuTfb·hh¿Jd[\\\\LáƔĨƐAĈepÀÂMD~ņªe^\\\\^§ý©j×cZØ¨zdÒa¶lÒJìõ`oz÷@¤uŞ¸´ôęöY¼HČƶajlÞƩ¥éZ[|h}^U  ¥pĄžƦO lt¸Æ Q\\\\aÆ|CnÂOjt­ĚĤdÈF`¶@Ðë ¦ōÒ¨SêvHĢÛ@[ÆQoxHW[ŰîÀt¦Ǆ~NĠ¢lĄtZoCƞÔºCxrpČNpj¢{f_Y`_eq®Aot`@oDXfkp¨|s¬\\\\DÄSfè©Hn¬^DhÆyøJhØxĢĀLÊƠPżċĄwĮ¶\"],\"encodeOffsets\":[[118923,30536]]},\"properties\":{\"cp\":[115.892151,28.676493],\"name\":\"江西\",\"childNum\":1}},{\"id\":\"370000\",\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[\"@@Xjd]mE\",\"@@itnq\",\"@@Dl@k\",\"@@TGw\",\"@@K¬U\",\"@@Wd`c\",\"@@PtMs\",\"@@LnXlc\",\"@@ppVu]Qn\",\"@@cdzAU_\",\"@@udRhnCE\",\"@@oIpP\",\"@@M{ĿčwbxƨîKÎMĮ]ZF½Y]â£ph¶¨râøÀÎǨ¤^ºÄGz~grĚĜlĞÆLĆǆ¢Îo¦cvKbgr°WhmZp L]LºcUÆ­nżĤÌĒbAnrOA´ȊcÀbƦUØrĆUÜøĬƞŶǬĴóò_A̈«ªdÎÉnb²ĦhņBĖįĦåXćì@L¯´ywƕCéÃµė ƿ¸lµZæyj|BíÂKNNnoƈfÈMZwnŐNàúÄsTJULîVjǎ¾ĒØDz²XPn±ŴPè¸ŔLƔÜƺ_TüÃĤBBċÈöA´faM¨{«M`¶d¡ôÖ°mȰBÔjj´PM|c^d¤u¤Û´ä«ƢfPk¶Môl]Lb}su^ke{lCMrDÇ­]NÑFsmoõľHyGă{{çrnÓEƕZGª¹Fj¢ÿ©}ÌCǷë¡ąuhÛ¡^KxC`C\\\\bÅxì²ĝÝ¿_NīCȽĿåB¥¢·IŖÕy\\\\¹kxÃ£ČáKµË¤ÁçFQ¡KtŵƋ]CgÏAùSedcÚźuYfyMmhUWpSyGwMPqŀÁ¼zK¶G­Y§Ë@´śÇµƕBm@IogZ¯uTMx}CVKï{éƵP_K«pÛÙqċtkkù]gTğwoɁsMõ³ăAN£MRkmEÊčÛbMjÝGuIZGPģãħE[iµBEuDPÔ~ª¼ęt]ûG§¡QMsğNPŏįzs£Ug{đJĿļā³]ç«Qr~¥CƎÑ^n¶ÆéÎR~Ż¸YI] PumŝrƿIā[xeÇ³L¯v¯s¬ÁY~}ťuŁgƋpÝĄ_ņī¶ÏSR´ÁP~¿Cyċßdwk´SsX|t`Ä ÈðAªìÎT°¦Dda^lĎDĶÚY°`ĪŴǒàŠv\\\\ebZHŖR¬ŢƱùęOÑM­³FÛaj\"]],\"encodeOffsets\":[[[123806,39303],[123821,39266],[123742,39256],[123702,39203],[123649,39066],[123847,38933],[123580,38839],[123894,37288],[123043,36624],[123344,38676],[123522,38857],[123628,38858],[118267,36772]]]},\"properties\":{\"cp\":[117.000923,36.675807],\"name\":\"山东\",\"childNum\":13}},{\"id\":\"410000\",\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[\"@@dXD}~Hgq~ÔN~zkĘHVsǲßjŬŢ`Pûàl¢\\\\ÀEhİgÞē X¼`khÍLùµP³swIÓzeŠĠð´E®ÚPtºIŊÊºL«šŕQGYfa[şußǑĩų_Z¯ĵÙčC]kbc¥CS¯ëÍB©ïÇÃ_{sWTt³xlàcČzÀD}ÂOQ³ÐTĬµƑÐ¿ŸghłŦv~}ÂZ«¤lPÇ£ªÝŴÅR§ØnhctâknÏ­ľŹUÓÝdKuķI§oTũÙďkęĆH¸Ó\\\\Ä¿PcnS{wBIvÉĽ[GqµuŇôYgûZca©@½Õǽys¯}lgg@­C\\\\£asIdÍuCQñ[L±ęk·ţb¨©kK»KC²òGKmĨS`UQnk}AGēsqaJ¥ĐGRĎpCuÌy ã iMcplk|tRkðev~^´¦ÜSí¿_iyjI|ȑ|¿_»d}q^{Ƈdă}tqµ`ŷé£©V¡om½ZÙÏÁRD|JOÈpÀRsI{ùÓjuµ{t}uËRivGçJFjµåkWê´MÂHewixGw½Yŷpµú³XU½ġyłåkÚwZX·l¢Á¢KzOÎÎjc¼htoDHr|­J½}JZ_¯iPq{tę½ĕ¦Zpĵø«kQĹ¤]MÛfaQpě±ǽ¾]u­Fu÷nčÄ¯ADp}AjmcEÇaª³o³ÆÍSƇĈÙDIzçñİ^KNiÞñ[aA²zzÌ÷D|[íÄ³gfÕÞd®|`Ć~oĠƑô³ŊD×°¯CsøÂ«ìUMhTº¨¸ǝêWÔDruÂÇZ£ĆPZW~ØØv¬gèÂÒw¦X¤Ā´oŬ¬²Ês~]®tªapŎJ¨Öº_ŔfŐ\\\\Đ\\\\Ĝu~m²Ƹ¸fWĦrƔ}Î^gjdfÔ¡J}\\\\n C¦þWxªJRÔŠu¬ĨĨmFdM{\\\\d\\\\YÊ¢ú@@¦ª²SÜsC}fNècbpRmlØ^gd¢aÒ¢CZZxvÆ¶N¿¢T@uC¬^ĊðÄn|lIlXhun[\",\"@@hzUq\"]],\"encodeOffsets\":[[[116744,37216],[116480,33048]]]},\"properties\":{\"cp\":[113.665412,34.757975],\"name\":\"河南\",\"childNum\":2}},{\"id\":\"420000\",\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[\"@@ASd\",\"@@ls{d\",\"@@¾«}{ra®pîÃ\\\\{øCËyyB±b\\\\òÝjKL ]ĎĽÌJyÚCƈćÎT´Å´pb©ÈdFin~BCo°BĎÃømv®E^vǾ½Ĝ²RobÜeN^ĺ£R¬lĶ÷YoĖ¥Ě¾|sOr°jY`~I¾®I{GqpCgyl{£ÍÍyPLÂ¡¡¸kWxYlÙæŁĢz¾V´W¶ùŸo¾ZHxjwfxGNÁ³Xéæl¶EièIH ujÌQ~v|sv¶Ôi|ú¢FhQsğ¦SiŠBgÐE^ÁÐ{čnOÂÈUÎóĔÊēĲ}Z³½Mŧïeyp·uk³DsÑ¨L¶_ÅuÃ¨w»¡WqÜ]\\\\Ò§tƗcÕ¸ÕFÏǝĉăxŻČƟOKÉġÿ×wg÷IÅzCg]m«ªGeçÃTC«[t§{loWeC@ps_Bp­rf_``Z|ei¡oċMqow¹DƝÓDYpûsYkıǃ}s¥ç³[§cY§HK«Qy]¢wwö¸ïx¼ņ¾Xv®ÇÀµRĠÐHM±cÏdƒǍũȅȷ±DSyúĝ£ŤĀàtÖÿï[îb\\\\}pĭÉI±Ñy¿³x¯No|¹HÏÛmjúË~TuęjCöAwě¬Rđl¯ Ñb­ŇTĿ_[IčĄʿnM¦ğ\\\\É[T·k¹©oĕ@A¾wya¥Y\\\\¥Âaz¯ãÁ¡k¥ne£ÛwE©Êō¶˓uoj_U¡cF¹­[WvP©whuÕyBF`RqJUw\\\\i¡{jEPïÿ½fćQÑÀQ{°fLÔ~wXgītêÝ¾ĺHd³fJd]HJ²EoU¥HhwQsƐ»Xmg±çve]DmÍPoCc¾_hhøYrŊU¶eD°Č_N~øĹĚ·`z]Äþp¼äÌQv\\\\rCé¾TnkžŐÚÜa¼ÝƆĢ¶ÛodĔňÐ¢JqPb ¾|J¾fXƐîĨ_Z¯À}úƲN_ĒÄ^ĈaŐyp»CÇÄKñL³ġM²wrIÒŭxjb[n«øæà ^²­h¯ÚŐªÞ¸Y²ĒVø}Ā^İ´LÚm¥ÀJÞ{JVųÞŃx×sxxƈē ģMřÚðòIfĊŒ\\\\Ʈ±ŒdÊ§ĘDvČ_Àæ~Dċ´A®µ¨ØLV¦êHÒ¤\"]],\"encodeOffsets\":[[[113712,34000],[115612,30507],[113649,34054]]]},\"properties\":{\"cp\":[114.298572,30.584355],\"name\":\"湖北\",\"childNum\":3}},{\"id\":\"430000\",\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[\"@@nFZw\",\"@@ãÆá½ÔXrCOËRïÿĩ­TooQyÓ[ŅBE¬ÎÓXaį§Ã¸G °ITxpúxÚĳ¥ÏĢ¾edÄ©ĸGàGhM¤Â_U}Ċ}¢pczfþg¤ÇôAV\",\"@@ȴÚĖÁĐiOĜ«BxDõĚivSÌ}iùÜnÐºG{p°M°yÂÒzJ²Ì ÂcXëöüiáÿñőĞ¤ùTz²CȆȸǎŪƑÐc°dPÎğË¶[È½u¯½WM¡­ÉB·rínZÒ `¨GA¾\\\\pēXhÃRC­üWGġuTé§ŎÑ©êLM³}_EÇģc®ęisÁPDmÅ{b[RÅs·kPŽƥóRoOV~]{g\\\\êYƪ¦kÝbiċƵGZ»Ěõó·³vŝ£ø@pyö_ëIkÑµbcÑ§y×dYØªiþUjŅ³C}ÁN»hĻħƏâƓKA·³CQ±µ§¿AUƑ¹AtćOwD]JUÖgk¯b£ylZFËÑ±H­}EbóľA¡»Ku¦·³åş¥ùBD^{ÌC´­¦ŷJ£^[ª¿ğ|ƅN skóā¹¿ï]ă~÷O§­@Vm¡Qđ¦¢Ĥ{ºjÔª¥nf´~Õo×ÛąGû¥cÑ[Z¶ŨĪ²SÊǔƐƀAÚŌ¦QØ¼rŭ­«}NÏürÊ¬mjr@ĘrTW ­SsdHzƓ^ÇÂyUi¯DÅYlŹu{hT}mĉ¹¥ěDÿë©ıÓ[Oº£¥ótł¹MÕƪ`PDiÛU¾ÅâìUñBÈ£ýhedy¡oċ`pfmjP~kZaZsÐd°wj§@Ĵ®w~^kÀÅKvNmX\\\\¨aŃqvíó¿F¤¡@ũÑVw}S@j}¾«pĂrªg àÀ²NJ¶¶DôK|^ª°LX¾ŴäPĪ±£EXd^¶ĲÞÜ~u¸ǔMRhsRe`ÄofIÔ\\\\Ø  ićymnú¨cj ¢»GČìƊÿÐ¨XeĈĀ¾Oð Fi ¢|[jVxrIQ_EzAN¦zLU`cªxOTu RLÄªpUĪȴ^ŎµªÉFxÜf¤ºgĲèy°Áb[¦Zb¦z½xBĖ@ªpºjS´rVźOd©ʪiĎăJP`\"]],\"encodeOffsets\":[[[115640,30489],[112577,27316],[114113,30649]]]},\"properties\":{\"cp\":[112.982279,28.19409],\"name\":\"湖南\",\"childNum\":3}},{\"id\":\"440000\",\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[\"@@QdAsa\",\"@@lxDRm\",\"@@sbhNLo\",\"@@Ă ý\",\"@@WltOY[\",\"@@Kr]S\",\"@@e~AS}\",\"@@I|Mym\",\"@@Û³LS²Q\",\"@@nvºBë¥cÕº\",\"@@zdÛJm\",\"@@°³\",\"@@a yAª¸ËJIxØ@ĀHÉÕZofoo\",\"@@sŗÃÔėAƁZÄ ~°ČPºb\",\"@@¶ÝÌvmĞh¹Ĺ\",\"@@HdSjĒ¢D}waru«ZqadY{K\",\"@@el\\\\LqqO\",\"@@~rMmX\",\"@@f^E\",\"@@øPªoj÷ÍÝħXČx°Q¨ıXJp\",\"@@gÇƳmxatfu\",\"@@EÆC½\",\"@@¸B_¶ekWvSivc}p}Ăº¾NĎyj¦Èm th_®Ä}»âUzLË²Aā¡ßH©Ùñ}wkNÕ¹ÇO½¿£ēUlaUìIÇª`uTÅxYĒÖ¼kÖµMjJÚwn\\\\hĒv]îh|ÈƄøèg¸Ķß ĉĈWb¹ƀdéĘNTtP[öSvrCZaGubo´ŖÒÇĐ~¡zCIözx¢PnÈñ @ĥÒ¦]ƜX³ăĔñiiÄÓVépKG½ÄÓávYoC·sitiaÀyŧÎ¡ÈYDÑům}ý|m[węõĉZÅxUO}÷N¹³ĉo_qtăqwµŁYÙǝŕ¹tïÛUÃ¯mRCºĭ|µÕÊK½Rē ó]GªęAxNqSF|ām¡diď×YïYWªŉOeÚtĐ«zđ¹TāúEáÎÁWwíHcòßÎſ¿Çdğ·ùT×Çūʄ¡XgWÀǇğ·¿ÃOj YÇ÷Sğ³kzőõmĝ[³¡VÙæÅöMÌ³¹pÁaËýý©D©ÜJŹƕģGą¤{ÙūÇO²«BƱéAÒĥ¡«BhlmtÃPµyU¯ucd·w_bŝcīímGOGBȅŹãĻFŷŽŕ@Óoo¿ē±ß}}ÓF÷tĲWÈCőâUâǙIğŉ©IĳE×Á³AĥDĈ±ÌÜÓĨ£L]ĈÙƺZǾĆĖMĸĤfÎĵlŨnÈĐtFFĤêk¶^k°f¶g}®Faf`vXŲxl¦ÔÁ²¬Ð¦pqÊÌ²iXØRDÎ}Ä@ZĠsx®AR~®ETtĄZƈfŠŠHâÒÐAµ\\\\S¸^wĖkRzalŜ|E¨ÈNĀňZTpBh£\\\\ĎƀuXĖtKL¶G|»ĺEļĞ~ÜĢÛĊrOÙîvd]n¬VÊĜ°RÖpMƀ¬HbwEÀ©\\\\¤]ŸI®¥D³|Ë]CúAŠ¦æ´¥¸Lv¼¢ĽBaôF~®²GÌÒEYzk¤°ahlVÕI^CxĈPsBƒºVÀB¶¨R²´D\",\"@@OR\"]],\"encodeOffsets\":[[[117381,22988],[116552,22934],[116790,22617],[116973,22545],[116444,22536],[116931,22515],[116496,22490],[116453,22449],[113301,21439],[118726,21604],[118709,21486],[113210,20816],[115482,22082],[113171,21585],[113199,21590],[115232,22102],[115739,22373],[115134,22184],[113056,21175],[119573,21271],[119957,24020],[115859,22356],[116680,26053],[116561,22649]]]},\"properties\":{\"cp\":[113.280637,23.125178],\"name\":\"广东\",\"childNum\":24}},{\"id\":\"450000\",\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[\"@@H TI¡U\",\"@@Ɣ_LÊFZgčP­kini«qÇczÍY®¬Ů»qR×ō©DÕ§ƙǃŵTÉĩ±ıdÑnYYĲvNĆĆØÜ Öp}e³¦m©iÓ|¹ħņ|ª¦QF¢Â¬ʖovg¿em^ucäāmÇÖåB¡Õçĝ}FĻ¼Ĺ{µHKsLSđƃrč¤[AgoSŇYMÿ§Ç{FśbkylQxĕ]T·¶[BÑÏGáşşƇeăYSs­FQ}­BwtYğÃ@~CÍQ ×WjË±rÉ¥oÏ ±«ÓÂ¥kwWűue_b­E~µh¯ecl¯Ïr¯EģJğ}w³Ƈē`ãògK_ÛsUʝćğ¶höO¤Ǜn³c`¡yię[ďĵűMę§]XÎ_íÛ]éÛUćİÕBƣ±dy¹T^dûÅÑŦ·PĻþÙ`K¦¢ÍeĥR¿³£[~äu¼dltW¸oRM¢ď\\\\z}Æzdvň{ÎXF¶°Â_ÒÂÏL©ÖTmu¼ãlīkiqéfA·Êµ\\\\őDc¥ÝFyÔćcűH_hLÜêĺĐ¨c}rn`½Ì@¸¶ªVLhŒ\\\\Ţĺk~Ġið°|gtTĭĸ^xvKVGréAébUuMJVÃO¡qĂXËSģãlýà_juYÛÒBG^éÖ¶§EGÅzěƯ¤EkN[kdåucé¬dnYpAyČ{`]þ±X\\\\ÞÈk¡ĬjàhÂƄ¢Hè ŔâªLĒ^Öm¶ħĊAǦė¸zÚGn£¾rªŀÜt¬@ÖÚSx~øOŒŶÐÂæȠ\\\\ÈÜObĖw^oÞLf¬°bI lTØBÌF£Ć¹gñĤaYt¿¤VSñK¸¤nM¼JE±½¸ñoÜCƆæĪ^ĚQÖ¦^f´QüÜÊz¯lzUĺš@ìp¶n]sxtx¶@~ÒĂJb©gk{°~c°`Ô¬rV\\\\la¼¤ôá`¯¹LCÆbxEræOv[H­[~|aB£ÖsºdAĐzNÂðsÞÆĤªbab`ho¡³F«èVZs\\\\\\\\ÔRzpp®SĪº¨ÖºNĳd`a¦¤F³¢@`¢ĨĀìhYvlĆº¦Ċ~nS|gźv^kGÆÀè·\"]],\"encodeOffsets\":[[[111707,21520],[113706,26955]]]},\"properties\":{\"cp\":[108.320004,22.82402],\"name\":\"广西\",\"childNum\":2}},{\"id\":\"460000\",\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[\"@@¦Ŝil¢XƦƞòïè§ŞCêɕrŧůÇąĻõ·ĉ³œ̅kÇm@ċȧŧĥĽʉ­ƅſȓÒË¦ŝE}ºƑ[ÍĜȋ gÎfǐÏĤ¨êƺ\\\\Ɔ¸ĠĎvʄȀÐ¾jNðĀÒRZǆzÐĊ¢DÀɘZ\"],\"encodeOffsets\":[[112750,20508]]},\"properties\":{\"cp\":[110.33119,20.031971],\"name\":\"海南\",\"childNum\":1}},{\"id\":\"510000\",\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[\"@@LqSn\",\"@@ĆOìÛÐ@ĞǔNY{¤Á§di´ezÝúØãwIþËQÇ¦ÃqÉSJ»ĂéʔõÔƁİlƞ¹§ĬqtÀƄmÀêErĒtD®ċæcQE®³^ĭ¥©l}äQtoŖÜqÆkµªÔĻĴ¡@Ċ°B²Èw^^RsºTĀ£ŚæQPJvÄz^Đ¹Æ¯fLà´GC²dt­ĀRt¼¤ĦOðğfÔðDŨŁĞƘïPÈ®âbMüÀXZ ¸£@Å»»QÉ­]dsÖ×_Í_ÌêŮPrĔĐÕGĂeZÜîĘqBhtO ¤tE[h|YÔZśÎs´xº±Uñt|OĩĠºNbgþJy^dÂY Į]Řz¦gC³R`Āz¢Aj¸CL¤RÆ»@­Ŏk\\\\Ç´£YW}z@Z}Ã¶oû¶]´^NÒ}èNªPÍy¹`S°´ATeVamdUĐwʄvĮÕ\\\\uÆŗ¨Yp¹àZÂmWh{á}WØǍÉüwga§ßAYrÅÂQĀÕ¬LŐý®Xøxª½Ű¦¦[þ`ÜUÖ´òrÙŠ°²ÄkĳnDX{U~ET{ļº¦PZcjF²Ė@pg¨B{u¨ŦyhoÚD®¯¢ WòàFÎ¤¨GDäz¦kŮPġqË¥À]eâÚ´ªKxīPÖ|æ[xÃ¤JÞĥsNÖ½I¬nĨY´®ÐƐmDŝuäđđEbee_v¡}ìęǊē}qÉåT¯µRs¡M@}ůaa­¯wvƉåZw\\\\Z{åû`[±oiJDÅ¦]ĕãïrG réÏ·~ąSfy×Í·ºſƽĵȁŗūmHQ¡Y¡®ÁÃ×t«­T¤JJJyJÈ`Ohß¦¡uËhIyCjmÿwZGTiSsOB²fNmsPa{M{õE^Hj}gYpaeu¯oáwHjÁ½M¡pMuåmni{fk\\\\oÎqCwEZ¼KĝAy{m÷LwO×SimRI¯rKõBS«sFe]fµ¢óY_ÆPRcue°Cbo×bd£ŌIHgtrnyPt¦foaXďxlBowz_{ÊéWiêEGhÜ¸ºuFĈIxf®Y½ĀǙ]¤EyF²ċw¸¿@g¢§RGv»áW`ÃĵJwi]t¥wO­½a[×]`Ãi­üL¦LabbTÀåc}ÍhÆh®BHî|îºÉk­¤Sy£ia©taį·Ɖ`ō¥UhOĝLk}©Fos´JmµlŁuønÑJWÎªYÀïAetTŅÓGË«bo{ıwodƟ½OġÜÂµxàNÖ¾P²§HKv¾]|BÆåoZ`¡Ø`ÀmºĠ~ÌÐ§nÇ¿¤]wğ@srğu~Io[é±¹ ¿ſđÓ@qg¹zƱřaí°KtÇ¤V»Ã[ĩǭƑ^ÇÓ@áťsZÏÅĭƋěpwDóÖáŻneQËq·GCœýS]x·ýq³OÕ¶Qzßti{řáÍÇWŝŭñzÇWpç¿JXĩè½cFÂLiVjx}\\\\NŇĖ¥GeJA¼ÄHfÈu~¸Æ«dE³ÉMA|bÒćhG¬CMõƤąAvüVéŀ_VÌ³ĐwQj´·ZeÈÁ¨X´Æ¡Qu·»ÕZ³ġqDoy`L¬gdp°şp¦ėìÅĮZ°Iähzĵf²å ĚÑKpIN|Ñz]ń·FU×é»R³MÉ»GM«kiér}Ã`¹ăÞmÈnÁîRǀ³ĜoİzŔwǶVÚ£À]ɜ»ĆlƂ²ĠþTº·àUȞÏʦ¶I«dĽĢdĬ¿»Ĕ×h\\\\c¬ä²GêëĤł¥ÀǿżÃÆMº}BÕĢyFVvwxBèĻĒ©Ĉt@Ğû¸£B¯¨ˋäßkķ½ªôNÔ~t¼Ŵu^s¼{TA¼ø°¢İªDè¾Ň¶ÝJ®Z´ğ~Sn|ªWÚ©òzPOȸbð¢|øĞA\"]],\"encodeOffsets\":[[[108815,30935],[100197,35028]]]},\"properties\":{\"cp\":[104.065735,30.659462],\"name\":\"四川\",\"childNum\":2}},{\"id\":\"520000\",\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[\"@@G\\\\lY£cj\",\"@@q|mc¯vÏV\",\"@@hÑ£IsNgßHHªķÃh_¹¡ĝÄ§ń¦uÙùgS¯JH|sÝÅtÁïyMDč»eÕtA¤{b\\\\}G®u\\\\åPFqwÅaDK°ºâ_£ùbµmÁÛĹM[q|hlaªāI}Ñµ@swtwm^oµDéĽŠyVky°ÉûÛR³e¥]RÕěħ[ƅåÛDpJiVÂF²I»mN·£LbÒYbWsÀbpkiTZĄă¶Hq`ĥ_J¯ae«KpÝx]aĕÛPÇȟ[ÁåŵÏő÷Pw}TÙ@Õs«ĿÛq©½m¤ÙH·yǥĘĉBµĨÕnđ]K©œáGçş§ÕßgǗĦTèƤƺ{¶ÉHÎd¾ŚÊ·OÐjXWrãLyzÉAL¾ę¢bĶėy_qMĔąro¼hĊw¶øV¤w²Ĉ]ÊKx|`ź¦ÂÈdrcÈbe¸`I¼čTF´¼Óýȃr¹ÍJ©k_șl³´_pĐ`oÒh¶pa^ÓĔ}D»^Xy`d[KvJPhèhCrĂĚÂ^Êƌ wZL­Ġ£ÁbrzOIlMMĪŐžËr×ÎeŦtw|¢mKjSǘňĂStÎŦEtqFT¾Eì¬¬ôxÌO¢ K³ŀºäYPVgŎ¦ŊmŞ¼VZwVlz¤£Tl®ctĽÚó{G­AÇge~Îd¿æaSba¥KKûj®_Ä^\\\\Ø¾bP®¦x^sxjĶI_Ä Xâ¼Hu¨Qh¡À@Ëô}±GNìĎlT¸`V~R°tbÕĊ`¸úÛtÏFDu[MfqGH·¥yAztMFe|R_GkChZeÚ°tov`xbDnÐ{E}ZèxNEÞREn[Pv@{~rĆAB§EO¿|UZ~ìUf¨J²ĂÝÆsªB`s¶fvö¦Õ~dÔq¨¸º»uù[[§´sb¤¢zþF¢ÆÀhÂW\\\\ıËIÝo±ĭŠ£þÊs}¡R]ěDg´VG¢j±®èºÃmpU[Áëº°rÜbNu¸}º¼`niºÔXĄ¤¼ÔdaµÁ_ÃftQQgR·Ǔv}Ý×ĵ]µWc¤F²OĩųãW½¯K©]{LóµCIµ±Mß¿h©āq¬o½~@i~TUxð´Đhw­ÀEîôuĶb[§nWuMÆJl½]vuıµb\"]],\"encodeOffsets\":[[[112158,27383],[112105,27474],[112095,27476]]]},\"properties\":{\"cp\":[106.713478,26.578343],\"name\":\"贵州\",\"childNum\":3}},{\"id\":\"530000\",\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[\"@@[ùx½}ÑRHYīĺûsÍniEoã½Ya²ė{c¬ĝgĂsAØÅwďõzFjw}«Dx¿}Uũlê@HÅ­F¨ÇoJ´Ónũuą¡Ã¢pÒÅØ TF²xa²ËXcÊlHîAßËŁkŻƑŷÉ©hW­æßUËs¡¦}teèÆ¶StÇÇ}Fd£jĈZĆÆ¤Tč\\\\D}O÷£U§~ŃGåŃDĝ¸Tsd¶¶Bª¤u¢ŌĎo~t¾ÍŶÒtD¦ÚiôözØX²ghįh½Û±¯ÿm·zR¦Ɵ`ªŊÃh¢rOÔ´£Ym¼èêf¯ŪĽncÚbw\\\\zlvWªâ ¦gmĿBĹ£¢ƹřbĥkǫßeeZkÙIKueT»sVesbaĕ  ¶®dNĄÄpªy¼³BE®lGŭCǶwêżĔÂepÍÀQƞpC¼ŲÈ­AÎô¶RäQ^Øu¬°_Èôc´¹ò¨PÎ¢hlĎ¦´ĦÆ´sâÇŲPnÊD^¯°Upv}®BPÌªjǬxSöwlfòªvqĸ|`H­viļndĜ­Ćhňem·FyÞqóSį¯³X_ĞçêtryvL¤§z¦c¦¥jnŞklD¤øz½ĜàĂŧMÅ|áƆàÊcðÂFÜáŢ¥\\\\\\\\ºİøÒÐJĴîD¦zK²ǏÎEh~CD­hMn^ÌöÄ©ČZÀaüfɭyœpį´ěFűk]Ôě¢qlÅĆÙa¶~ÄqêljN¬¼HÊNQ´ê¼VØ¸E^ŃÒyM{JLoÒęæe±Ķygã¯JYÆĭĘëo¥Šo¯hcK«z_prC´ĢÖY¼ v¸¢RÅW³Â§fÇ¸Yi³xR´ďUË`êĿUûuĆBƣöNDH«ĈgÑaB{ÊNF´¬c·Åv}eÇÃGB»If¦HňĕM~[iwjUÁKE¾dĪçWIèÀoÈXòyŞŮÈXâÎŚj|àsRyµÖPr´þ ¸^wþTDŔHr¸RÌmfżÕâCôoxĜƌÆĮÐYtâŦÔ@]ÈǮƒ\\\\Ī¼Ä£UsÈ¯LbîƲŚºyhr@ĒÔƀÀ²º\\\\êpJ}ĠvqtĠ@^xÀ£È¨mËÏğ}n¹_¿¢×Y_æpÅA^{½Lu¨GO±Õ½ßM¶wÁĢÛPƢ¼pcĲx|apÌ¬HÐŊSfsðBZ¿©XÏÒKk÷Eû¿SrEFsÕūkóVǥŉiTL¡n{uxţÏhôŝ¬ğōNNJkyPaqÂğ¤K®YxÉƋÁ]āęDqçgOgILu\\\\_gz]W¼~CÔē]bµogpÑ_oď`´³Țkl`IªºÎȄqÔþ»E³ĎSJ»_f·adÇqÇc¥Á_Źw{L^É±ćxU£µ÷xgĉp»ĆqNē`rĘzaĵĚ¡K½ÊBzyäKXqiWPÏÉ¸½řÍcÊG|µƕƣGË÷k°_^ý|_zċBZocmø¯hhcæ\\\\lMFlư£ĜÆyHF¨µêÕ]HAàÓ^it `þßäkĤÎT~Wlÿ¨ÔPzUCNVv [jâôDôď[}z¿msSh¯{jïğl}šĹ[őgK©U·µË@¾m_~q¡f¹ÅË^»f³ø}Q¡ÖË³gÍ±^Ç\\\\ëÃA_¿bWÏ[¶ƛé£F{īZgm@|kHǭƁć¦UĔť×ëǟeċ¼ȡȘÏíBÉ£āĘPªĳ¶ŉÿy©nď£G¹¡I±LÉĺÑdĉÜW¥}gÁ{aqÃ¥aıęÏZÁ`\"],\"encodeOffsets\":[[104636,22969]]},\"properties\":{\"cp\":[102.712251,25.040609],\"name\":\"云南\",\"childNum\":1}},{\"id\":\"540000\",\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[\"@@ÂhľxŖxÒVºÅâAĪÝȆµę¯Ňa±r_w~uSÕňqOj]ɄQ£ZUDûoY»©M[L¼qãË{VÍçWVi]ë©Ä÷àyƛhÚU°adcQ~Mx¥caÛcSyFÖk­uRýq¿ÔµQĽ³aG{¿FµëªéĜÿª@¬·K·àariĕĀ«V»ŶĴūgèLǴŇƶaftèBŚ£^âǐÝ®M¦ÁǞÿ¬LhJ¾óƾÆºcxwf]Y´¦|QLn°adĊ\\\\¨oǀÍŎ´ĩĀd`tÊQŞŕ|¨C^©Ĉ¦¦ÎJĊ{ëĎjª²rÐl`¼Ą[t|¦Stè¾PÜK¸dƄı]s¤î_v¹ÎVòŦj£Əsc¬_Ğ´|Ł¦Av¦w`ăaÝaa­¢e¤ı²©ªSªÈMĄwÉØŔì@T¤Ę\\\\õª@þo´­xA sÂtŎKzó²ÇČµ¢r^nĊ­Æ¬×üG¢³ {âĊ]G~bÀgVjzlhǶfOfdªB]pjTOtĊn¤}®¦Č¥d¢¼»ddY¼t¢eȤJ¤}Ǿ¡°§¤AÐlc@ĝsªćļđAçwxUuzEÖġ~AN¹ÄÅȀŻ¦¿ģŁéì±Hãd«g[Ø¼ēÀcīľġ¬cJµÐʥVȝ¸ßS¹ý±ğkƁ¼ą^ɛ¤Ûÿb[}¬ōõÃ]ËNm®g@Bg}ÍF±ǐyL¥íCIĳÏ÷Ñį[¹¦[âšEÛïÁÉdƅß{âNÆāŨß¾ě÷yC£k­´ÓH@Â¹TZ¥¢į·ÌAÐ§®Zcv½Z­¹|ÅWZqgW|ieZÅYVÓqdqbc²R@c¥Rã»GeeƃīQ}J[ÒK¬Ə|oėjġĠÑN¡ð¯EBčnwôɍėª²CλŹġǝʅįĭạ̃ūȹ]ΓͧgšsgȽóϧµǛęgſ¶ҍć`ĘąŌJÞä¤rÅň¥ÖÁUětęuůÞiĊÄÀ\\\\Æs¦ÓRb|Â^řÌkÄŷ¶½÷f±iMÝ@ĥ°G¬ÃM¥n£Øąğ¯ß§aëbéüÑOčk£{\\\\eµª×MÉfm«Ƒ{Å×Gŏǩãy³©WÑăû··Qòı}¯ãIéÕÂZ¨īès¶ZÈsæĔTŘvgÌsN@îá¾ó@ÙwU±ÉTå»£TđWxq¹Zobs[×¯cĩvėŧ³BM|¹kªħ¥TzNYnÝßpęrñĠĉRS~½ěVVµõ«M££µBĉ¥áºae~³AuĐh`Ü³ç@BÛïĿa©|z²Ý¼D£àč²ŸIûI āóK¥}rÝ_Á´éMaň¨~ªSĈ½½KÙóĿeƃÆB·¬ën×W|Uº}LJrƳlŒµ`bÔ`QÐÓ@s¬ñIÍ@ûws¡åQÑßÁ`ŋĴ{ĪTÚÅTSÄ³Yo|Ç[Ç¾µMW¢ĭiÕØ¿@MhpÕ]jéò¿OƇĆƇpêĉâlØwěsǩĵ¸cbU¹ř¨WavquSMzeo_^gsÏ·¥Ó@~¯¿RiīB\\\\qTGªÇĜçPoÿfñòą¦óQīÈáPābß{ZŗĸIæÅhnszÁCËìñÏ·ąĚÝUm®ó­L·ăUÈíoù´Êj°ŁŤ_uµ^°ìÇ@tĶĒ¡ÆM³Ģ«İĨÅ®ğRāðggheÆ¢zÊ©Ô\\\\°ÝĎz~ź¤PnMĪÖB£kné§żćĆKĒ°¼L¶èâz¨u¦¥LDĘz¬ýÎmĘd¾ßFzhg²Fy¦ĝ¤ċņbÎ@yĄæm°NĮZRÖíJ²öLĸÒ¨Y®ƌÐVàtt_ÚÂyĠz]ŢhzĎ{ÂĢXc|ÐqfO¢¤ögÌHNPKŖUú´xx[xvĐCûĀìÖT¬¸^}Ìsòd´_KgžLĴÀBon|H@Êx¦BpŰŌ¿fµƌA¾zǈRx¶FkĄźRzŀ~¶[´HnªVƞuĒ­È¨ƎcƽÌm¸ÁÈM¦x͊ëÀxǆBú^´W£dkɾĬpw˂ØɦļĬIŚÊnŔa¸~J°îlɌxĤÊÈðhÌ®gT´øàCÀ^ªerrƘd¢İP|Ė ŸWªĦ^¶´ÂLaT±üWƜǀRÂŶUńĖ[QhlLüAÜ\\\\qRĄ©\"],\"encodeOffsets\":[[90849,37210]]},\"properties\":{\"cp\":[91.132212,29.660361],\"name\":\"西藏\",\"childNum\":1}},{\"id\":\"610000\",\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[\"@@¸ÂW¢xR­Fq§uF@N¢XLRMº[ğȣſï|¥Jkc`sŉǷ£Y³WN«ùMëï³ÛIg÷±mTșÚÒķø©þ¥yÓğęmWµÎumZyOŅƟĥÓ~sÑL¤µaÅY¦ocyZ{y c]{Ta©`U_Ěē£ωÊƍKùK¶ȱÝƷ§{û»ÅÁȹÍéuĳ|¹cÑdìUYOuFÕÈYvÁCqÓTǢí§·S¹NgV¬ë÷Át°DØ¯C´ŉƒópģ}ąiEËFéGU¥×K§­¶³BČ}C¿åċ`wġB·¤őcƭ²ő[Å^axwQOñJÙïŚĤNĔwƇÄńwĪ­o[_KÓª³ÙnKÇěÿ]ďă_d©·©Ýŏ°Ù®g]±ß×¥¬÷m\\\\iaǑkěX{¢|ZKlçhLtŇîŵœè[É@ƉĄEtƇÏ³­ħZ«mJ×¾MtÝĦ£IwÄå\\\\Õ{OwĬ©LÙ³ÙTª¿^¦rÌĢŭO¥lãyC§HÍ£ßEñX¡­°ÙCgpťzb`wIvA|¥hoĕ@E±iYd¥OÿµÇvPW|mCĴŜǂÒW¶¸AĜh^Wx{@¬­F¸¡ķn£P|ªĴ@^ĠĈæbÔc¶lYi^MicĎ°Â[ävï¶gv@ÀĬ·lJ¸sn|¼u~a]ÆÈtŌºJpþ£KKf~¦UbyäIĺãnÔ¿^­ŵMThĠÜ¤ko¼Ŏìąǜh`[tRd²Ĳ_XPrɲlXiL§à¹H°Ȧqº®QCbAŌJ¸ĕÚ³ĺ§ `d¨YjiZvRĺ±öVKkjGȊÄePĞZmļKÀ[`ösìhïÎoĬdtKÞ{¬èÒÒBÔpĲÇĬJŊ¦±J«[©ārHµàåVKe§|P²ÇÓ·vUzgnN¾yI@oHĆÛķhxen¡QQ±ƝJǖRbzy¸ËÐl¼EºpĤ¼x¼½~Ğà@ÚüdK^mÌSjp²ȮµûGĦ}Ħðǚ¶òƄjɂz°{ºØkÈęâ¦jªBg\\\\ċ°s¬]jú EȌǆ¬stRÆdĠİwÜ¸ôW¾ƮłÒ_{Ìû¼jº¹¢GǪÒ¯ĘZ`ºŊecņą~BÂgzpâēòYƲȐĎ\"],\"encodeOffsets\":[[113634,40474]]},\"properties\":{\"cp\":[108.948024,34.263161],\"name\":\"陕西\",\"childNum\":1}},{\"id\":\"620000\",\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[\"@@Vu_^\",\"@@ųEĠtt~nkh`Q¦ÅÄÜdwAb×ĠąJ¤DüègĺqBqj°lI¡Ĩ¶ĖIHdjÎB°aZ¢KJO[|A£Dx}NĂ¬HUnrk kp¼Y kMJn[aGáÚÏ[½rc}aQxOgsPMnUsncZsKúvAtÞġ£®ĀYKdnFw¢JE°Latf`¼h¬we|Æbj}GA·~W`¢MC¤tL©Ĳ°qdfObÞĬ¹ttu`^ZúE`[@Æsîz®¡CƳƜG²R¢RmfwĸgÜą G@pzJM½mhVy¸uÈÔO±¨{LfæU¶ßGĂq\\\\ª¬²I¥IŉÈīoıÓÑAçÑ|«LÝcspīðÍgtë_õ\\\\ĉñLYnĝgRǡÁiHLlõUĹ²uQjYi§Z_c¨´ĹĖÙ·ŋIaBD­R¹ȥr¯GºßK¨jWkɱOqWĳ\\\\a­Q\\\\sg_ĆǛōëp»£lğÛgSŶN®À]ÓämĹãJaz¥V}Le¤Lýo¹IsŋÅÇ^bz³tmEÁ´a¹cčecÇNĊãÁ\\\\č¯dNj]jZµkÓdaćå]ğĳ@ ©O{¤ĸm¢E·®«|@Xwg]Aģ±¯XǁÑǳªcwQÚŝñsÕ³ÛV_ý¥\\\\ů¥©¾÷w©WÕÊĩhÿÖÁRo¸V¬âDb¨hûxÊ×ǌ~Zâg|XÁnßYoº§ZÅŘv[ĭÖʃuďxcVbnUSfB¯³_TzºÎO©çMÑ~M³]µ^püµÄY~y@X~¤Z³[Èōl@®Å¼£QK·Di¡ByÿQ_´D¥hŗy^ĭÁZ]cIzýah¹MĪğPs{ò²Vw¹t³ŜË[Ñ}X\\\\gsF£sPAgěp×ëfYHāďÖqēŭOÏëdLü\\\\it^c®RÊº¶¢H°mrY£B¹čIoľu¶uI]vģSQ{UŻÅ}QÂ|Ì°ƅ¤ĩŪU ęĄÌZÒ\\\\v²PĔ»ƢNHĂyAmƂwVm`]ÈbH`Ì¢²ILvĜH®¤Dlt_¢JJÄämèÔDëþgºƫaʎÌrêYi~ Îİ¤NpÀA¾Ĕ¼bð÷®üszMzÖĖQdȨýv§Tè|ªHÃ¾a¸|Ð ƒwKĢx¦ivr^ÿ ¸l öæfƟĴ·PJv}n\\\\h¹¶v·À|\\\\ƁĚN´ĜçèÁz]ġ¤²¨QÒŨTIlªťØ}¼˗ƦvÄùØEÂ«FïËIqōTvāÜŏíÛßÛVj³âwGăÂíNOPìyV³ŉĖýZso§HÑiYw[ß\\\\X¦¥c]ÔƩÜ·«jÐqvÁ¦m^ċ±R¦΋ƈťĚgÀ»IïĨʗƮ°ƝĻþÍAƉſ±tÍEÕÞāNUÍ¡\\\\ſčåÒʻĘm ƭÌŹöʥëQ¤µ­ÇcƕªoIýIÉ_mkl³ăƓ¦j¡YzŇi}Msßõīʋ }ÁVm_[n}eı­Uĥ¼ªI{Î§DÓƻėojqYhĹT©oūĶ£]ďxĩǑMĝq`B´ƃ˺Чç~²ņj@¥@đ´ί}ĥtPńÇ¾V¬ufÓÉCtÓ̻¹£G³]ƖƾŎĪŪĘ̖¨ʈĢƂlɘ۪üºňUðǜȢƢż̌ȦǼĤŊɲĖÂ­KqĘŉ¼ĔǲņɾªǀÞĈĂD½ĄĎÌŗĞrôñnN¼â¾ʄľԆ|Ǆ֦ज़ȗǉ̘̭ɺƅêgV̍ʆĠ·ÌĊv|ýĖÕWĊǎÞ´õ¼cÒÒBĢ͢UĜð͒s¨ňƃLĉÕÝ@ɛƯ÷¿Ľ­ĹeȏĳëCȚDŲyê×Ŗyò¯ļcÂßYtÁƤyAã˾J@ǝrý@¤rz¸oP¹ɐÚyáHĀ[JwcVeȴÏ»ÈĖ}ƒŰŐèȭǢόĀƪÈŶë;Ñ̆ȤМľĮEŔĹŊũ~ËUă{ĻƹɁύȩþĽvĽƓÉ@ēĽɲßǐƫʾǗĒpäWÐxnsÀ^ƆwW©¦cÅ¡Ji§vúF¶¨c~c¼īeXǚ\\\\đ¾JwÀďksãAfÕ¦L}waoZD½Ml«]eÒÅaÉ²áo½FõÛ]ĻÒ¡wYR£¢rvÓ®y®LFLzĈôe]gx}|KK}xklL]c¦£fRtív¦PŨ£\",\"@@M T¥\"]],\"encodeOffsets\":[[[108619,36299],[108594,36341],[108600,36306]]]},\"properties\":{\"cp\":[103.823557,36.058039],\"name\":\"甘肃\",\"childNum\":3}},{\"id\":\"630000\",\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[\"@@InJo\",\"@@CÆ½OŃĦsΰ~Ē³¦@@Ņi±è}ШƄ˹A³r_ĞǒNĪĐw¤^ŬĵªpĺSZgrpiƼĘÔ¨C|ÍJ©Ħ»®VĲ~f\\\\m `UnÂ~ʌĬàöNt~ňjy¢ZiƔ¥Ąk´nl`JÊJþ©pdƖ®È£¶ìRʦźõƮËnʼėæÑƀĎ[¢VÎĂMÖÝÎF²sƊƀÎBļýƞ¯ʘƭðħ¼Jh¿ŦęΌƇ¥²Q]Č¥nuÂÏri¸¬ƪÛ^Ó¦d¥[Wàx\\\\ZjÒ¨GtpþYŊĕ´zUOëPîMĄÁxH´áiÜUàîÜŐĂÛSuŎrJðÌ¬EFÁú×uÃÎkrĒ{V}İ«O_ÌËĬ©ÓŧSRÑ±§Ģ£^ÂyèçěM³Ƃę{[¸¿uºµ[gt£¸OƤĿéYõ·kĀq]juw¥DĩƍõÇPéÄ½G©ã¤GuȧþRcÕĕNyyût­øï»a½ē¿BMoį£Íj}éZËqbʍƬh¹ìÿÓAçãnIÃ¡I`ks£CG­ěUy×Cy@¶ʡÊBnāzGơMē¼±O÷õJËĚăVĪũƆ£¯{ËL½ÌzżVR|ĠTbuvJvµhĻĖHAëáa­OÇðñęNwœľ·LmI±íĠĩPÉ×®ÿscB³±JKßĊ«`ađ»·QAmOVţéÿ¤¹SQt]]Çx±¯A@ĉĳ¢Óļ©l¶ÅÛrŕspãRk~¦ª]Į­´FRåd­ČsCqđéFn¿ÅƃmÉx{W©ºƝºįkÕƂƑ¸wWūÐ©ÈF£\\\\tÈ¥ÄRÈýÌJ lGr^×äùyÞ³fjc¨£ÂZ|ǓMĝÏ@ëÜőRĝ÷¡{aïȷPu°ËXÙ{©TmĠ}Y³­ÞIňµç½©C¡į÷¯B»|St»]vųs»}MÓ ÿʪƟǭA¡fs»PY¼c¡»¦cċ­¥£~msĉPSi^o©AecPeǵkgyUi¿h}aHĉ^|á´¡HØûÅ«ĉ®]m¡qċ¶±ÈyôōLÁstB®wn±ă¥HSòė£Së@×œÊăxÇN©©T±ª£Ĳ¡fb®Þbb_Ą¥xu¥B{łĝ³«`dƐt¤ťiñÍUuºí`£^tƃĲc·ÛLO½sç¥Ts{ă\\\\_»kÏ±q©čiìĉ|ÍI¥ć¥]ª§D{ŝŖÉR_sÿc³ĪōƿÎ§p[ĉc¯bKmR¥{³Ze^wx¹dƽÅ½ôIg §Mĕ ƹĴ¿ǣÜÍ]Ý]snåA{eƭ`ǻŊĿ\\\\ĳŬűYÂÿ¬jĖqßb¸L«¸©@ěĀ©ê¶ìÀEH|´bRľÓ¶rÀQþvl®ÕETzÜdb hw¤{LRdcb¯ÙVgƜßzÃôì®^jUèXÎ|UäÌ»rK\\\\ªN¼pZCüVY¤ɃRi^rPŇTÖ}|br°qňbĚ°ªiƶGQ¾²x¦PmlŜ[Ĥ¡ΞsĦÔÏâ\\\\ªÚŒU\\\\f¢N²§x|¤§xĔsZPòʛ²SÐqF`ªVÞŜĶƨVZÌL`¢dŐIqr\\\\oäõFÎ·¤»Ŷ×h¹]ClÙ\\\\¦ďÌį¬řtTӺƙgQÇÓHţĒ´ÃbEÄlbʔC|CŮkƮ[ʼ¬ň´KŮÈΰÌĪ¶ƶlðļATUvdTGº̼ÔsÊDÔveMg\"]],\"encodeOffsets\":[[[105308,37219],[95370,40081]]]},\"properties\":{\"cp\":[101.778916,36.623178],\"name\":\"青海\",\"childNum\":2}},{\"id\":\"640000\",\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[\"@@KëÀęĞ«Oęȿȕı]ŉ¡åįÕÔ«ǴõƪĚQÐZhv K°öqÀÑS[ÃÖHƖčËnL]ûcÙß@ĝ¾}w»»oģF¹»kÌÏ·{zP§B­¢íyÅt@@á]Yv_ssģ¼ißĻL¾ġsKD£¡N_X¸}B~HaiÅf{«x»ge_bsKF¯¡IxmELcÿZ¤­ĢÝsuBLùtYdmVtNmtOPhRw~bd¾qÐ\\\\âÙH\\\\bImlNZ»loqlVmGā§~QCw¤{A\\\\PKNY¯bFkC¥sks_Ã\\\\ă«¢ħkJi¯rrAhĹûç£CUĕĊ_ÔBixÅÙĄnªÑaM~ħpOu¥sîeQ¥¤^dkKwlL~{L~hw^ófćKyE­K­zuÔ¡qQ¤xZÑ¢^ļöÜ¾Ep±âbÊÑÆ^fk¬NC¾YpxbK~¥eÖäBlt¿Đx½I[ĒǙWf»Ĭ}d§dµùEuj¨IÆ¢¥dXªƅx¿]mtÏwßRĶX¢͎vÆzƂZò®ǢÌʆCrâºMÞzÆMÒÊÓŊZÄ¾r°Î®Ȉmª²ĈUªĚîøºĮ¦ÌĘk^FłĬhĚiĀĖ¾iİbjË\"],\"encodeOffsets\":[[109366,40242]]},\"properties\":{\"cp\":[106.278179,38.46637],\"name\":\"宁夏\",\"childNum\":1}},{\"id\":\"650000\",\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[\"@@QØĔ²X¨~ǘBºjʐßØvKƔX¨vĊOÃ·¢i@~cĝe_«E}QxgɪëÏÃ@sÅyXoŖ{ô«ŸuXêÎf`C¹ÂÿÐGĮÕĞXŪōŸMźÈƺQèĽôe|¿ƸJR¤ĘEjcUóº¯Ĩ_ŘÁMª÷Ð¥OéÈ¿ÖğǤǷÂFÒzÉx[]­Ĥĝœ¦EP}ûƥé¿İƷTėƫœŕƅƱB»Đ±ēO¦E}`cȺrĦáŖuÒª«ĲπdƺÏØZƴwʄ¤ĖGĐǂZĶèH¶}ÚZצʥĪï|ÇĦMŔ»İĝǈì¥Βba­¯¥ǕǚkĆŵĦɑĺƯxūД̵nơʃĽá½M»òmqóŘĝčË¾ăCćāƿÝɽ©ǱŅ»ēėŊLrÁ®ɱĕģŉǻ̋ȥơŻǛȡVï¹Ň۩ûkɗġƁ§ʇė̕ĩũƽō^ƕUv£ƁQïƵkŏ½ΉÃŭÇ³LŇʻ«ƭ\\\\lŭD{ʓDkaFÃÄa³ŤđÔGRÈƚhSӹŚsİ«ĐË[¥ÚDkº^Øg¼ŵ¸£EÍöůŉT¡c_ËKYƧUśĵÝU_©rETÏʜ±OñtYwē¨{£¨uM³x½şL©Ùá[ÓÐĥ Νtģ¢\\\\śnkOw¥±T»ƷFɯàĩÞáB¹ÆÑUwŕĽw]kE½Èå~Æ÷QyěCFmĭZīŵVÁƿQƛûXS²b½KÏ½ĉS©ŷXĕ{ĕK·¥Ɨcqq©f¿]ßDõU³h­gËÇïģÉɋwk¯í}I·œbmÉřīJɥĻˁ×xoɹīlc¤³Xù]ǅA¿w͉ì¥wÇN·ÂËnƾƍdÇ§đ®ƝvUm©³G\\\\}µĿQyŹlăµEwǇQ½yƋBe¶ŋÀůo¥AÉw@{Gpm¿AĳŽKLh³`ñcËtW±»ÕSëüÿďDu\\\\wwwù³VLŕOMËGh£õP¡erÏd{ġWÁč|yšg^ğyÁzÙs`s|ÉåªÇ}m¢Ń¨`x¥ù^}Ì¥H«YªƅAÐ¹n~ź¯f¤áÀzgÇDIÔ´AňĀÒ¶ûEYospõD[{ù°]uJqU|Soċxţ[õÔĥkŋÞŭZËºóYËüċrw ÞkrťË¿XGÉbřaDü·Ē÷AÃª[ÄäIÂ®BÕĐÞ_¢āĠpÛÄȉĖġDKwbmÄNôfƫVÉviǳHQµâFù­Âœ³¦{YGd¢ĚÜO {Ö¦ÞÍÀP^bƾl[vt×ĈÍEË¨¡Đ~´î¸ùÎhuè`¸HÕŔVºwĠââWò@{ÙNÝ´ə²ȕn{¿¥{l÷eé^eďXj©î\\\\ªÑòÜìc\\\\üqÕ[Č¡xoÂċªbØ­ø|¶ȴZdÆÂońéG\\\\¼C°ÌÆn´nxÊOĨŪƴĸ¢¸òTxÊǪMīĞÖŲÃɎOvʦƢ~FRěò¿ġ~åŊúN¸qĘ[Ĕ¶ÂćnÒPĒÜvúĀÊbÖ{Äî¸~Ŕünp¤ÂH¾ĄYÒ©ÊfºmÔĘcDoĬMŬS¤s²ʘÚžȂVŦ èW°ªB|ĲXŔþÈJĦÆæFĚêYĂªĂ]øªŖNÞüAfɨJ¯ÎrDDĤ`mz\\\\§~D¬{vJÂ«lµĂb¤pŌŰNĄ¨ĊXW|ų ¿¾ɄĦƐMTòP÷fØĶK¢ȝ˔Sô¹òEð­`Ɩ½ǒÂň×äı§ĤƝ§C~¡hlåǺŦŞkâ~}FøàĲaĞfƠ¥Ŕd®U¸źXv¢aƆúŪtŠųƠjdƺƺÅìnrh\\\\ĺ¯äɝĦ]èpĄ¦´LƞĬ´ƤǬ˼Ēɸ¤rºǼ²¨zÌPðŀbþ¹ļD¢¹\\\\ĜÑŚ¶ZƄ³âjĦoâȴLÊȮĐ­ĚăÀêZǚŐ¤qȂ\\\\L¢ŌİfÆs|zºeªÙæ§΢{Ā´ƐÚ¬¨Ĵà²łhʺKÞºÖTiƢ¾ªì°`öøu®Ê¾ãÖ\"],\"encodeOffsets\":[[88824,50096]]},\"properties\":{\"cp\":[87.617733,43.792818],\"name\":\"新疆\",\"childNum\":1}},{\"id\":\"110000\",\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[\"@@RºaYÕQaúÍÔiþĩȨWĢü|Ėu[qb[swP@ÅğP¿{\\\\¯Y²·Ñ¨j¯X\\\\¯MSvU¯YIŕY{[fk­VÁûtŷmiÍt_H»Ĩ±d`¹­{bwYr³S]§§o¹qGtm_SŧoaFLgQN_dV@Zom_ć\\\\ßW´ÕiœRcfio§ËgToÛJíĔóu|wP¤XnO¢ÉŦ¯pNÄā¤zâŖÈRpŢZÚ{GrFt¦Òx§ø¹RóäV¤XdżâºWbwŚ¨Ud®bêņ¾jnŎGŃŶnzÚScîĚZen¬\"],\"encodeOffsets\":[[119421,42013]]},\"properties\":{\"cp\":[116.405285,39.904989],\"name\":\"北京\",\"childNum\":1}},{\"id\":\"120000\",\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[\"@@ŬgX§Ü«E¶FÌ¬O_ïlÁgz±AXeµÄĵ{¶]gitgIj·¥ì_iU¨ÐƎk}ĕ{gBqGf{¿aU^fIư³õ{YıëNĿk©ïËZukāAīlĕĥs¡bġ«@dekąI[nlPqCnp{ō³°`{PNdƗqSÄĻNNâyj]äÒD ĬH°Æ]~¡HO¾X}ÐxgpgWrDGpù^LrzWxZ^¨´T\\\\|~@IzbĤjeĊªz£®ĔvěLmV¾Ô_ÈNW~zbĬvG²ZmDM~~\"],\"encodeOffsets\":[[120237,41215]]},\"properties\":{\"cp\":[117.190182,39.125596],\"name\":\"天津\",\"childNum\":1}},{\"id\":\"310000\",\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[\"@@ɧư¬EpƸÁx]\",\"@@©²\",\"@@MA\",\"@@QpªKWT§¨\",\"@@bŝÕÕEȣÚƥêImɇǦèÜĠÚÄÓŴ·ʌÇ\",\"@@Sô¤r]ìƬįǜûȬɋŭ×^sYɍDŋŽąñCG²«ªč@h_p¯A{oloY¬j@Ĳ`gQÚpptǀ^MĲvtbe´Rh@oj¨\",\"@@ÆLH{a}Eo¦\"]],\"encodeOffsets\":[[[124702,32062],[124547,32200],[124808,31991],[124726,32110],[124903,32376],[124065,32166],[124870,31965]]]},\"properties\":{\"cp\":[121.472644,31.231706],\"name\":\"上海\",\"childNum\":7}},{\"id\":\"500000\",\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[\"@@TÂÛ`Ùƅően½SêqDu[RåÍ¹÷eXÍy¸_ĺę}÷`M¯ċfCVµqŉ÷Zgg^d½pDOÎCn^uf²ènh¼WtƏxRGg¦pVFI±G^Ic´ecGĹÞ½sëÆNäÌ¤KÓe¯|R¸§LÜkPoïƭNï¶}Gywdiù©nkĈzj@Óc£»Wă¹Óf§c[µo·Ó|MvÛaq½«è\\\\ÂoVnÓØÍ²«bq¿ehCĜ^Q~ Évýş¤²ĮpEĶyhsŊwH½¿gÅ¡ýE¡ya£³t\\\\¨\\\\vú¹¼©·Ñr_oÒý¥et³]Et©uÖ¥±ă©KVeë]}wVPÀFA¨ąB}qTjgRemfFmQFÝMyùnÑAmÑCawu_p¯sfÛ_gI_pNysB¦zG¸rHeN\\\\CvEsÐñÚkcDÖĉsaQ¯}_UzÁē}^R Äd^ÍĸZ¾·¶`wećJE¹vÛ·HgéFXjÉê`|ypxkAwWĐpb¥eOsmzwqChóUQl¥F^lafanòsrEvfQdÁUVfÎvÜ^eftET¬ôA\\\\¢sJnQTjPØxøK|nBzĞ»LYFDxÓvr[ehľvN¢o¾NiÂxGpâ¬zbfZo~hGi]öF||NbtOMn eA±tPTLjpYQ|SHYĀxinzDJÌg¢và¥Pg_ÇzIIII£®S¬ØsÎ¼¥¨^LnGĲļĲƤjÎƀƾ¹¸ØÎezĆT¸}êÐqHðqĖä¥^CÆIj²p\\\\_ æüY|[YxƊæu°xb®Űb@~¢NQt°¶Sæ Ê~rǉĔëĚ¢~uf`faĔJåĊnÔ]jƎćÊ@£¾a®£Ű{ŶĕFègLk{Y|¡ĜWƔtƬJÑxq±ĢN´òKLÈÃ¼D|s`ŋć]Ã`đMùƱ¿~Y°ħ`ƏíW½eI½{aOIrÏ¡ĕŇapµÜƃġ²\"],\"encodeOffsets\":[[111728,31311]]},\"properties\":{\"cp\":[106.504962,29.533155],\"name\":\"重庆\",\"childNum\":1}},{\"id\":\"810000\",\"geometry\":{\"type\":\"MultiPolygon\",\"coordinates\":[[\"@@AlFi\",\"@@mp\",\"@@EpHo\",\"@@rMUwAS¬]\",\"@@ea¢pl¸Eõ¹hj[]ÔCÎ@lj¡uBX´AI¹[yDU]W`çwZkmcMpÅv}IoJlcafŃK°ä¬XJmÐ đhI®æÔtSHnEÒrÄc\"]],\"encodeOffsets\":[[[117111,23002],[117072,22876],[117045,22887],[116882,22747],[116975,23082]]]},\"properties\":{\"cp\":[114.173355,22.320048],\"name\":\"香港\",\"childNum\":5}},{\"id\":\"820000\",\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[\"@@áw{Îr\"],\"encodeOffsets\":[[116285,22746]]},\"properties\":{\"cp\":[113.54909,22.198951],\"name\":\"澳门\",\"childNum\":1}}],\"UTF8Encoding\":true}\r\n\r\nexport default chinaMap;"
  },
  {
    "path": "src/utils/index.ts",
    "content": "export const setProperty = (prop: string, val: any, dom = document.documentElement) => {\r\n    dom.style.setProperty(prop, val);\r\n};\r\n\r\nexport const mix = (color1: string, color2: string, weight: number = 0.5): string => {\r\n    let color = '#';\r\n    for (let i = 0; i <= 2; i++) {\r\n        const c1 = parseInt(color1.substring(1 + i * 2, 3 + i * 2), 16);\r\n        const c2 = parseInt(color2.substring(1 + i * 2, 3 + i * 2), 16);\r\n        const c = Math.round(c1 * weight + c2 * (1 - weight));\r\n        color += c.toString(16).padStart(2, '0');\r\n    }\r\n    return color;\r\n};\r\n"
  },
  {
    "path": "src/utils/request.ts",
    "content": "import axios, { AxiosInstance, AxiosError, AxiosResponse, InternalAxiosRequestConfig } from 'axios';\r\n\r\nconst service: AxiosInstance = axios.create({\r\n    timeout: 5000\r\n});\r\n\r\nservice.interceptors.request.use(\r\n    (config: InternalAxiosRequestConfig) => {\r\n        return config;\r\n    },\r\n    (error: AxiosError) => {\r\n        console.log(error);\r\n        return Promise.reject();\r\n    }\r\n);\r\n\r\nservice.interceptors.response.use(\r\n    (response: AxiosResponse) => {\r\n        if (response.status === 200) {\r\n            return response;\r\n        } else {\r\n            Promise.reject();\r\n        }\r\n    },\r\n    (error: AxiosError) => {\r\n        console.log(error);\r\n        return Promise.reject();\r\n    }\r\n);\r\n\r\nexport default service;\r\n"
  },
  {
    "path": "src/views/chart/echarts.vue",
    "content": "<template>\r\n    <div class=\"container\">\r\n        <div class=\"plugins-tips\">\r\n            vue-echarts：Apache ECharts™ 的 Vue.js 组件。 访问地址：\r\n            <a href=\"https://github.com/ecomfe/vue-echarts\" target=\"_blank\">vue-echarts</a>\r\n        </div>\r\n        <el-card class=\"mgb20\" shadow=\"hover\">\r\n            <template #header>\r\n                <div class=\"content-title\">柱状图</div>\r\n            </template>\r\n            <v-chart class=\"schart\" :option=\"barOptions\" />\r\n        </el-card>\r\n        <el-card class=\"mgb20\" shadow=\"hover\">\r\n            <template #header>\r\n                <div class=\"content-title\">折线图</div>\r\n            </template>\r\n            <v-chart class=\"schart\" :option=\"lineOptions\" />\r\n        </el-card>\r\n        <el-card class=\"mgb20\" shadow=\"hover\">\r\n            <template #header>\r\n                <div class=\"content-title\">饼状图</div>\r\n            </template>\r\n            <v-chart class=\"schart\" :option=\"pieOptions\" />\r\n        </el-card>\r\n        <el-card class=\"mgb20\" shadow=\"hover\">\r\n            <template #header>\r\n                <div class=\"content-title\">环形图</div>\r\n            </template>\r\n            <v-chart class=\"schart\" :option=\"ringOptions\" />\r\n        </el-card>\r\n        <el-card class=\"mgb20\" shadow=\"hover\">\r\n            <template #header>\r\n                <div class=\"content-title\">词云图</div>\r\n            </template>\r\n            <v-chart class=\"schart\" :option=\"wordOptions\" />\r\n        </el-card>\r\n        <el-card class=\"mgb20\" shadow=\"hover\">\r\n            <template #header>\r\n                <div class=\"content-title\">地图</div>\r\n            </template>\r\n            <v-chart class=\"schart\" :option=\"mapOptions\" />\r\n        </el-card>\r\n    </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\" name=\"echarts\">\r\nimport { registerMap, use } from 'echarts/core';\r\nimport { BarChart, LineChart, PieChart, MapChart } from 'echarts/charts';\r\nimport {\r\n    GridComponent,\r\n    TooltipComponent,\r\n    LegendComponent,\r\n    TitleComponent,\r\n    VisualMapComponent,\r\n} from 'echarts/components';\r\nimport { CanvasRenderer } from 'echarts/renderers';\r\nimport VChart from 'vue-echarts';\r\nimport 'echarts-wordcloud';\r\nimport { barOptions, lineOptions, pieOptions, ringOptions, wordOptions, mapOptions } from './options';\r\nimport chinaMap from '@/utils/china';\r\nuse([\r\n    CanvasRenderer,\r\n    BarChart,\r\n    GridComponent,\r\n    LineChart,\r\n    PieChart,\r\n    MapChart,\r\n    TooltipComponent,\r\n    LegendComponent,\r\n    TitleComponent,\r\n    VisualMapComponent,\r\n]);\r\nregisterMap('china', chinaMap);\r\n</script>\r\n\r\n<style scoped>\r\n.schart {\r\n    width: 100%;\r\n    height: 400px;\r\n}\r\n\r\n.content-title {\r\n    font-weight: 400;\r\n    font-size: 22px;\r\n    color: #1f2f3d;\r\n}\r\n</style>\r\n"
  },
  {
    "path": "src/views/chart/options.ts",
    "content": "import { graphic } from 'echarts/core';\r\nexport const barOptions = {\r\n    xAxis: {\r\n        type: 'category',\r\n        data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],\r\n    },\r\n    yAxis: {\r\n        type: 'value',\r\n    },\r\n    tooltip: {\r\n        trigger: 'axis',\r\n        axisPointer: {\r\n            type: 'shadow',\r\n        },\r\n    },\r\n    color: ['#009688', '#f44336'],\r\n    series: [\r\n        {\r\n            data: [120, 200, 150, 80, 70, 110, 130],\r\n            type: 'bar',\r\n        },\r\n        {\r\n            data: [180, 230, 190, 120, 110, 230, 235],\r\n            type: 'bar',\r\n        },\r\n    ],\r\n};\r\n\r\nexport const lineOptions = {\r\n    tooltip: {\r\n        trigger: 'axis',\r\n    },\r\n    grid: {\r\n        left: '3%',\r\n        right: '4%',\r\n        bottom: '3%',\r\n        containLabel: true,\r\n    },\r\n    xAxis: {\r\n        type: 'category',\r\n        boundaryGap: false,\r\n        data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],\r\n    },\r\n    yAxis: {\r\n        type: 'value',\r\n    },\r\n    color: ['#009688', '#f44336'],\r\n    series: [\r\n        {\r\n            name: 'Email',\r\n            type: 'line',\r\n            stack: 'Total',\r\n            areaStyle: {},\r\n            smooth: true,\r\n            data: [120, 132, 101, 134, 90, 230, 210],\r\n        },\r\n        {\r\n            name: 'Union Ads',\r\n            type: 'line',\r\n            stack: 'Total',\r\n            areaStyle: {},\r\n            smooth: true,\r\n            data: [220, 182, 191, 234, 290, 330, 310],\r\n        },\r\n    ],\r\n};\r\n\r\nexport const pieOptions = {\r\n    title: {\r\n        text: 'Referer of a Website',\r\n        subtext: 'Fake Data',\r\n        left: 'center',\r\n    },\r\n    tooltip: {\r\n        trigger: 'item',\r\n    },\r\n    legend: {\r\n        orient: 'vertical',\r\n        left: 'left',\r\n    },\r\n    series: [\r\n        {\r\n            name: 'Access From',\r\n            type: 'pie',\r\n            radius: '50%',\r\n            data: [\r\n                { value: 1048, name: 'Search Engine' },\r\n                { value: 735, name: 'Direct' },\r\n                { value: 580, name: 'Email' },\r\n                { value: 484, name: 'Union Ads' },\r\n                { value: 300, name: 'Video Ads' },\r\n            ],\r\n            emphasis: {\r\n                itemStyle: {\r\n                    shadowBlur: 10,\r\n                    shadowOffsetX: 0,\r\n                    shadowColor: 'rgba(0, 0, 0, 0.5)',\r\n                },\r\n            },\r\n        },\r\n    ],\r\n};\r\n\r\nexport const wordOptions = {\r\n    series: [\r\n        {\r\n            type: 'wordCloud',\r\n            rotationRange: [0, 0],\r\n            autoSize: {\r\n                enable: true,\r\n                minSize: 14,\r\n            },\r\n            textStyle: {\r\n                fontFamily: '微软雅黑,sans-serif',\r\n                color: function () {\r\n                    return (\r\n                        'rgb(' +\r\n                        [\r\n                            Math.round(Math.random() * 160),\r\n                            Math.round(Math.random() * 160),\r\n                            Math.round(Math.random() * 160),\r\n                        ].join(',') +\r\n                        ')'\r\n                    );\r\n                },\r\n            },\r\n            data: [\r\n                {\r\n                    name: 'Vue',\r\n                    value: 10000,\r\n                },\r\n                {\r\n                    name: 'React',\r\n                    value: 9000,\r\n                },\r\n                {\r\n                    name: '图表',\r\n                    value: 4000,\r\n                },\r\n                {\r\n                    name: '产品',\r\n                    value: 7000,\r\n                },\r\n                {\r\n                    name: 'vue-manage-system',\r\n                    value: 2000,\r\n                },\r\n                {\r\n                    name: 'element-plus',\r\n                    value: 6000,\r\n                },\r\n                {\r\n                    name: '管理系统',\r\n                    value: 5000,\r\n                },\r\n                {\r\n                    name: '前端',\r\n                    value: 4000,\r\n                },\r\n                {\r\n                    name: '测试',\r\n                    value: 3000,\r\n                },\r\n                {\r\n                    name: '后端',\r\n                    value: 8000,\r\n                },\r\n                {\r\n                    name: '软件开发',\r\n                    value: 6000,\r\n                },\r\n                {\r\n                    name: '程序员',\r\n                    value: 4000,\r\n                },\r\n            ],\r\n        },\r\n    ],\r\n};\r\n\r\nexport const ringOptions = {\r\n    tooltip: {\r\n        trigger: 'item',\r\n    },\r\n    legend: {\r\n        top: '5%',\r\n        left: 'center',\r\n    },\r\n\r\n    series: [\r\n        {\r\n            name: 'Access From',\r\n            type: 'pie',\r\n            radius: ['40%', '70%'],\r\n            avoidLabelOverlap: false,\r\n            itemStyle: {\r\n                borderRadius: 10,\r\n                borderColor: '#fff',\r\n                borderWidth: 2,\r\n            },\r\n            label: {\r\n                show: false,\r\n                position: 'center',\r\n            },\r\n            emphasis: {\r\n                label: {\r\n                    show: true,\r\n                    fontSize: 40,\r\n                    fontWeight: 'bold',\r\n                },\r\n            },\r\n            labelLine: {\r\n                show: false,\r\n            },\r\n            data: [\r\n                { value: 1048, name: 'Search Engine' },\r\n                { value: 735, name: 'Direct' },\r\n                { value: 580, name: 'Email' },\r\n                { value: 484, name: 'Union Ads' },\r\n                { value: 300, name: 'Video Ads' },\r\n            ],\r\n        },\r\n    ],\r\n};\r\n\r\nexport const dashOpt1 = {\r\n    xAxis: {\r\n        type: 'category',\r\n        boundaryGap: false,\r\n        data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],\r\n    },\r\n    yAxis: {\r\n        type: 'value',\r\n    },\r\n    grid: {\r\n        top: '2%',\r\n        left: '2%',\r\n        right: '3%',\r\n        bottom: '2%',\r\n        containLabel: true,\r\n    },\r\n    color: ['#009688', '#f44336'],\r\n    series: [\r\n        {\r\n            type: 'line',\r\n            areaStyle: {\r\n                color: new graphic.LinearGradient(0, 0, 0, 1, [\r\n                    {\r\n                        offset: 0,\r\n                        color: 'rgba(0, 150, 136,0.8)',\r\n                    },\r\n                    {\r\n                        offset: 1,\r\n                        color: 'rgba(0, 150, 136,0.2)',\r\n                    },\r\n                ]),\r\n            },\r\n            smooth: true,\r\n            data: [120, 132, 301, 134, 90, 230, 210],\r\n        },\r\n        {\r\n            type: 'line',\r\n            smooth: true,\r\n            data: [220, 122, 191, 234, 190, 130, 310],\r\n        },\r\n    ],\r\n};\r\n\r\nexport const dashOpt2 = {\r\n    legend: {\r\n        bottom: '1%',\r\n        left: 'center',\r\n    },\r\n    color: ['#3f51b5', '#009688', '#f44336', '#00bcd4', '#1ABC9C'],\r\n    series: [\r\n        {\r\n            type: 'pie',\r\n            radius: ['40%', '70%'],\r\n            avoidLabelOverlap: false,\r\n            itemStyle: {\r\n                borderRadius: 10,\r\n                borderColor: '#fff',\r\n                borderWidth: 2,\r\n            },\r\n            data: [\r\n                { value: 1048, name: '数码' },\r\n                { value: 735, name: '食品' },\r\n                { value: 580, name: '母婴' },\r\n                { value: 484, name: '家电' },\r\n                { value: 300, name: '运动' },\r\n            ],\r\n        },\r\n    ],\r\n};\r\n\r\nexport const mapOptions = {\r\n    tooltip: {\r\n        trigger: 'item',\r\n    },\r\n    geo: {\r\n        map: 'china',\r\n        roam: false,\r\n        emphasis: {\r\n            label: {\r\n                show: false,\r\n            },\r\n        },\r\n    },\r\n    visualMap: {\r\n        show: false,\r\n        min: 0,\r\n        max: 100,\r\n        realtime: false,\r\n        calculable: false,\r\n        inRange: {\r\n            color: ['#d2e0f5', '#71A9FF'],\r\n        },\r\n    },\r\n    series: [\r\n        {\r\n            geoIndex: 0,\r\n            name: '地域分布',\r\n            type: 'map',\r\n            coordinateSystem: 'geo',\r\n            map: 'china',\r\n            data: [\r\n                { name: '北京', value: 100 },\r\n                { name: '上海', value: 100 },\r\n                { name: '广东', value: 100 },\r\n                { name: '浙江', value: 90 },\r\n                { name: '江西', value: 80 },\r\n                { name: '山东', value: 70 },\r\n                { name: '广西', value: 60 },\r\n                { name: '河南', value: 50 },\r\n                { name: '河南', value: 40 },\r\n                { name: '青海', value: 70 },\r\n                { name: '河南', value: 30 },\r\n                { name: '黑龙江', value: 20 },\r\n                { name: '新疆', value: 20 },\r\n                { name: '云南', value: 20 },\r\n                { name: '甘肃', value: 20 },\r\n            ],\r\n        },\r\n    ],\r\n};\r\n"
  },
  {
    "path": "src/views/chart/schart.vue",
    "content": "<template>\r\n\t<div class=\"container\">\r\n\t\t<div class=\"plugins-tips\">\r\n\t\t\tvue-schart：vue.js封装sChart.js的图表组件。 访问地址：\r\n\t\t\t<a href=\"https://github.com/lin-xin/vue-schart\" target=\"_blank\">vue-schart</a>\r\n\t\t</div>\r\n\t\t<el-card class=\"mgb20\" shadow=\"hover\">\r\n\t\t\t<template #header>\r\n\t\t\t\t<div class=\"content-title\">柱状图</div>\r\n\t\t\t</template>\r\n\t\t\t<schart class=\"schart\" canvasId=\"bar\" :options=\"options1\"></schart>\r\n\t\t</el-card>\r\n\t\t<el-card class=\"mgb20\" shadow=\"hover\">\r\n\t\t\t<template #header>\r\n\t\t\t\t<div class=\"content-title\">折线图</div>\r\n\t\t\t</template>\r\n\t\t\t<schart class=\"schart\" canvasId=\"line\" :options=\"options2\"></schart>\r\n\t\t</el-card>\r\n\t\t<el-card class=\"mgb20\" shadow=\"hover\">\r\n\t\t\t<template #header>\r\n\t\t\t\t<div class=\"content-title\">饼状图</div>\r\n\t\t\t</template>\r\n\t\t\t<schart class=\"schart\" canvasId=\"pie\" :options=\"options3\"></schart>\r\n\t\t</el-card>\r\n\t\t<el-card class=\"mgb20\" shadow=\"hover\">\r\n\t\t\t<template #header>\r\n\t\t\t\t<div class=\"content-title\">环形图</div>\r\n\t\t\t</template>\r\n\t\t\t<schart class=\"schart\" canvasId=\"ring\" :options=\"options4\"></schart>\r\n\t\t</el-card>\r\n\t</div>\r\n</template>\r\n\r\n<script setup lang=\"ts\" name=\"schart\">\r\nimport Schart from 'vue-schart';\r\n\r\nconst options1 = {\r\n\ttype: 'bar',\r\n\ttitle: {\r\n\t\ttext: '最近一周各品类销售图'\r\n\t},\r\n\tcolorList: [\"#3f51b5\", \"#009688\", \"#f44336\", \"#00bcd4\", \"#1ABC9C\"],\r\n\tlabels: ['周一', '周二', '周三', '周四', '周五'],\r\n\tdatasets: [\r\n\t\t{\r\n\t\t\tlabel: '家电',\r\n\t\t\t// fillColor: 'rgba(241, 49, 74, 0.5)',\r\n\t\t\tdata: [234, 278, 270, 190, 230]\r\n\t\t},\r\n\t\t{\r\n\t\t\tlabel: '百货',\r\n\t\t\tdata: [164, 178, 190, 135, 160]\r\n\t\t},\r\n\t\t{\r\n\t\t\tlabel: '食品',\r\n\t\t\tdata: [144, 198, 150, 235, 120]\r\n\t\t}\r\n\t]\r\n};\r\nconst options2 = {\r\n\ttype: 'line',\r\n\ttitle: {\r\n\t\ttext: '最近几个月各品类销售趋势图'\r\n\t},\r\n\tcolorList: [\"#3f51b5\", \"#009688\", \"#f44336\", \"#00bcd4\", \"#1ABC9C\"],\r\n\tlabels: ['6月', '7月', '8月', '9月', '10月'],\r\n\tdatasets: [\r\n\t\t{\r\n\t\t\tlabel: '家电',\r\n\t\t\tdata: [234, 278, 270, 190, 230]\r\n\t\t},\r\n\t\t{\r\n\t\t\tlabel: '百货',\r\n\t\t\tdata: [164, 178, 150, 135, 160]\r\n\t\t},\r\n\t\t{\r\n\t\t\tlabel: '食品',\r\n\t\t\tdata: [114, 138, 200, 235, 190]\r\n\t\t}\r\n\t]\r\n};\r\nconst options3 = {\r\n\ttype: 'pie',\r\n\ttitle: {\r\n\t\ttext: '服装品类销售饼状图'\r\n\t},\r\n\tlegend: {\r\n\t\tposition: 'left'\r\n\t},\r\n\tcolorList: [\"#2196f3\", '#673ab7', \"#009688\", \"#1ABC9C\", \"#3f51b5\", \"#f44336\", \"#00bcd4\"],\r\n\tlabels: ['T恤', '牛仔裤', '连衣裙', '毛衣', '七分裤', '短裙', '羽绒服'],\r\n\tdatasets: [\r\n\t\t{\r\n\t\t\tdata: [334, 278, 190, 235, 260, 200, 141]\r\n\t\t}\r\n\t]\r\n};\r\nconst options4 = {\r\n\ttype: 'ring',\r\n\ttitle: {\r\n\t\ttext: '环形三等分'\r\n\t},\r\n\tshowValue: false,\r\n\tlegend: {\r\n\t\tposition: 'bottom',\r\n\t\tbottom: 40\r\n\t},\r\n\tcolorList: [\"#3f51b5\", \"#009688\", \"#f44336\", \"#00bcd4\", \"#1ABC9C\"],\r\n\tlabels: ['vue', 'react', 'angular'],\r\n\tdatasets: [\r\n\t\t{\r\n\t\t\tdata: [500, 500, 500]\r\n\t\t}\r\n\t]\r\n};\r\n</script>\r\n\r\n<style scoped>\r\n.schart {\r\n\twidth: 100%;\r\n\theight: 400px;\r\n}\r\n\r\n.content-title {\r\n\tfont-weight: 400;\r\n\tfont-size: 22px;\r\n\tcolor: #1f2f3d;\r\n}\r\n</style>\r\n"
  },
  {
    "path": "src/views/dashboard.vue",
    "content": "<template>\r\n    <div>\r\n        <el-row :gutter=\"20\" class=\"mgb20\">\r\n            <el-col :span=\"6\">\r\n                <el-card shadow=\"hover\" body-class=\"card-body\">\r\n                    <el-icon class=\"card-icon bg1\">\r\n                        <User />\r\n                    </el-icon>\r\n                    <div class=\"card-content\">\r\n                        <countup class=\"card-num color1\" :end=\"6666\" />\r\n                        <div>用户访问量</div>\r\n                    </div>\r\n                </el-card>\r\n            </el-col>\r\n            <el-col :span=\"6\">\r\n                <el-card shadow=\"hover\" body-class=\"card-body\">\r\n                    <el-icon class=\"card-icon bg2\">\r\n                        <ChatDotRound />\r\n                    </el-icon>\r\n                    <div class=\"card-content\">\r\n                        <countup class=\"card-num color2\" :end=\"168\" />\r\n                        <div>系统消息</div>\r\n                    </div>\r\n                </el-card>\r\n            </el-col>\r\n            <el-col :span=\"6\">\r\n                <el-card shadow=\"hover\" body-class=\"card-body\">\r\n                    <el-icon class=\"card-icon bg3\">\r\n                        <Goods />\r\n                    </el-icon>\r\n                    <div class=\"card-content\">\r\n                        <countup class=\"card-num color3\" :end=\"8888\" />\r\n                        <div>商品数量</div>\r\n                    </div>\r\n                </el-card>\r\n            </el-col>\r\n            <el-col :span=\"6\">\r\n                <el-card shadow=\"hover\" body-class=\"card-body\">\r\n                    <el-icon class=\"card-icon bg4\">\r\n                        <ShoppingCartFull />\r\n                    </el-icon>\r\n                    <div class=\"card-content\">\r\n                        <countup class=\"card-num color4\" :end=\"568\" />\r\n                        <div>今日订单量</div>\r\n                    </div>\r\n                </el-card>\r\n            </el-col>\r\n        </el-row>\r\n\r\n        <el-row :gutter=\"20\" class=\"mgb20\">\r\n            <el-col :span=\"18\">\r\n                <el-card shadow=\"hover\">\r\n                    <div class=\"card-header\">\r\n                        <p class=\"card-header-title\">订单动态</p>\r\n                        <p class=\"card-header-desc\">最近一周订单状态，包括订单成交量和订单退货量</p>\r\n                    </div>\r\n                    <v-chart class=\"chart\" :option=\"dashOpt1\" />\r\n                </el-card>\r\n            </el-col>\r\n            <el-col :span=\"6\">\r\n                <el-card shadow=\"hover\">\r\n                    <div class=\"card-header\">\r\n                        <p class=\"card-header-title\">品类分布</p>\r\n                        <p class=\"card-header-desc\">最近一个月销售商品的品类情况</p>\r\n                    </div>\r\n                    <v-chart class=\"chart\" :option=\"dashOpt2\" />\r\n                </el-card>\r\n            </el-col>\r\n        </el-row>\r\n        <el-row :gutter=\"20\">\r\n            <el-col :span=\"7\">\r\n                <el-card shadow=\"hover\" :body-style=\"{ height: '400px' }\">\r\n                    <div class=\"card-header\">\r\n                        <p class=\"card-header-title\">时间线</p>\r\n                        <p class=\"card-header-desc\">最新的销售动态和活动信息</p>\r\n                    </div>\r\n                    <el-timeline>\r\n                        <el-timeline-item v-for=\"(activity, index) in activities\" :key=\"index\" :color=\"activity.color\">\r\n                            <div class=\"timeline-item\">\r\n                                <div>\r\n                                    <p>{{ activity.content }}</p>\r\n                                    <p class=\"timeline-desc\">{{ activity.description }}</p>\r\n                                </div>\r\n                                <div class=\"timeline-time\">{{ activity.timestamp }}</div>\r\n                            </div>\r\n                        </el-timeline-item>\r\n                    </el-timeline>\r\n                </el-card>\r\n            </el-col>\r\n            <el-col :span=\"10\">\r\n                <el-card shadow=\"hover\" :body-style=\"{ height: '400px' }\">\r\n                    <div class=\"card-header\">\r\n                        <p class=\"card-header-title\">渠道统计</p>\r\n                        <p class=\"card-header-desc\">最近一个月的订单来源统计</p>\r\n                    </div>\r\n                    <v-chart class=\"map-chart\" :option=\"mapOptions\" />\r\n                </el-card>\r\n            </el-col>\r\n            <el-col :span=\"7\">\r\n                <el-card shadow=\"hover\" :body-style=\"{ height: '400px' }\">\r\n                    <div class=\"card-header\">\r\n                        <p class=\"card-header-title\">排行榜</p>\r\n                        <p class=\"card-header-desc\">销售商品的热门榜单Top5</p>\r\n                    </div>\r\n                    <div>\r\n                        <div class=\"rank-item\" v-for=\"(rank, index) in ranks\">\r\n                            <div class=\"rank-item-avatar\">{{ index + 1 }}</div>\r\n                            <div class=\"rank-item-content\">\r\n                                <div class=\"rank-item-top\">\r\n                                    <div class=\"rank-item-title\">{{ rank.title }}</div>\r\n                                    <div class=\"rank-item-desc\">销量：{{ rank.value }}</div>\r\n                                </div>\r\n                                <el-progress\r\n                                    :show-text=\"false\"\r\n                                    striped\r\n                                    :stroke-width=\"10\"\r\n                                    :percentage=\"rank.percent\"\r\n                                    :color=\"rank.color\"\r\n                                />\r\n                            </div>\r\n                        </div>\r\n                    </div>\r\n                </el-card>\r\n            </el-col>\r\n        </el-row>\r\n    </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\" name=\"dashboard\">\r\nimport countup from '@/components/countup.vue';\r\nimport { use, registerMap } from 'echarts/core';\r\nimport { BarChart, LineChart, PieChart, MapChart } from 'echarts/charts';\r\nimport {\r\n    GridComponent,\r\n    TooltipComponent,\r\n    LegendComponent,\r\n    TitleComponent,\r\n    VisualMapComponent,\r\n} from 'echarts/components';\r\nimport { CanvasRenderer } from 'echarts/renderers';\r\nimport VChart from 'vue-echarts';\r\nimport { dashOpt1, dashOpt2, mapOptions } from './chart/options';\r\nimport chinaMap from '@/utils/china';\r\nuse([\r\n    CanvasRenderer,\r\n    BarChart,\r\n    GridComponent,\r\n    LineChart,\r\n    PieChart,\r\n    TooltipComponent,\r\n    LegendComponent,\r\n    TitleComponent,\r\n    VisualMapComponent,\r\n    MapChart,\r\n]);\r\nregisterMap('china', chinaMap);\r\nconst activities = [\r\n    {\r\n        content: '收藏商品',\r\n        description: 'xxx收藏了你的商品，就是不买',\r\n        timestamp: '30分钟前',\r\n        color: '#00bcd4',\r\n    },\r\n    {\r\n        content: '用户评价',\r\n        description: 'xxx给了某某商品一个差评，吐血啊',\r\n        timestamp: '55分钟前',\r\n        color: '#1ABC9C',\r\n    },\r\n    {\r\n        content: '订单提交',\r\n        description: 'xxx提交了订单，快去收钱吧',\r\n        timestamp: '1小时前',\r\n        color: '#3f51b5',\r\n    },\r\n    {\r\n        content: '退款申请',\r\n        description: 'xxx申请了仅退款，又要亏钱了',\r\n        timestamp: '15小时前',\r\n        color: '#f44336',\r\n    },\r\n    {\r\n        content: '商品上架',\r\n        description: '运营专员瞒着你上架了一辆飞机',\r\n        timestamp: '1天前',\r\n        color: '#009688',\r\n    },\r\n];\r\n\r\nconst ranks = [\r\n    {\r\n        title: '手机',\r\n        value: 10000,\r\n        percent: 80,\r\n        color: '#f25e43',\r\n    },\r\n    {\r\n        title: '电脑',\r\n        value: 8000,\r\n        percent: 70,\r\n        color: '#00bcd4',\r\n    },\r\n    {\r\n        title: '相机',\r\n        value: 6000,\r\n        percent: 60,\r\n        color: '#64d572',\r\n    },\r\n    {\r\n        title: '衣服',\r\n        value: 5000,\r\n        percent: 55,\r\n        color: '#e9a745',\r\n    },\r\n    {\r\n        title: '书籍',\r\n        value: 4000,\r\n        percent: 50,\r\n        color: '#009688',\r\n    },\r\n];\r\n</script>\r\n\r\n<style>\r\n.card-body {\r\n    display: flex;\r\n    align-items: center;\r\n    height: 100px;\r\n    padding: 0;\r\n}\r\n</style>\r\n<style scoped>\r\n.card-content {\r\n    flex: 1;\r\n    text-align: center;\r\n    font-size: 14px;\r\n    color: #999;\r\n    padding: 0 20px;\r\n}\r\n\r\n.card-num {\r\n    font-size: 30px;\r\n}\r\n\r\n.card-icon {\r\n    font-size: 50px;\r\n    width: 100px;\r\n    height: 100px;\r\n    text-align: center;\r\n    line-height: 100px;\r\n    color: #fff;\r\n}\r\n\r\n.bg1 {\r\n    background: #2d8cf0;\r\n}\r\n\r\n.bg2 {\r\n    background: #64d572;\r\n}\r\n\r\n.bg3 {\r\n    background: #f25e43;\r\n}\r\n\r\n.bg4 {\r\n    background: #e9a745;\r\n}\r\n\r\n.color1 {\r\n    color: #2d8cf0;\r\n}\r\n\r\n.color2 {\r\n    color: #64d572;\r\n}\r\n\r\n.color3 {\r\n    color: #f25e43;\r\n}\r\n\r\n.color4 {\r\n    color: #e9a745;\r\n}\r\n\r\n.chart {\r\n    width: 100%;\r\n    height: 400px;\r\n}\r\n\r\n.card-header {\r\n    padding-left: 10px;\r\n    margin-bottom: 20px;\r\n}\r\n\r\n.card-header-title {\r\n    font-size: 18px;\r\n    font-weight: bold;\r\n    margin-bottom: 5px;\r\n}\r\n\r\n.card-header-desc {\r\n    font-size: 14px;\r\n    color: #999;\r\n}\r\n\r\n.timeline-item {\r\n    display: flex;\r\n    justify-content: space-between;\r\n    align-items: center;\r\n    font-size: 16px;\r\n    color: #000;\r\n}\r\n\r\n.timeline-time,\r\n.timeline-desc {\r\n    font-size: 12px;\r\n    color: #787878;\r\n}\r\n\r\n.rank-item {\r\n    display: flex;\r\n    align-items: center;\r\n    margin-bottom: 20px;\r\n}\r\n\r\n.rank-item-avatar {\r\n    width: 40px;\r\n    height: 40px;\r\n    border-radius: 50%;\r\n    background: #f2f2f2;\r\n    text-align: center;\r\n    line-height: 40px;\r\n    margin-right: 10px;\r\n}\r\n\r\n.rank-item-content {\r\n    flex: 1;\r\n}\r\n\r\n.rank-item-top {\r\n    display: flex;\r\n    justify-content: space-between;\r\n    align-items: center;\r\n    color: #343434;\r\n    margin-bottom: 10px;\r\n}\r\n\r\n.rank-item-desc {\r\n    font-size: 14px;\r\n    color: #999;\r\n}\r\n.map-chart {\r\n    width: 100%;\r\n    height: 350px;\r\n}\r\n</style>\r\n"
  },
  {
    "path": "src/views/element/calendar.vue",
    "content": "<template>\r\n    <div class=\"container\">\r\n        <el-calendar v-model=\"value\">\r\n            <template #date-cell=\"{ data }\">\r\n                <div>{{ data.date.getDate() }}</div>\r\n                <div class=\"notes-container\" v-if=\"notes[data.day.toString()]\">\r\n                    <div class=\"notes\" v-for=\"note in notes[data.day.toString()]\">\r\n                        <span :class=\"note.status === 1 ? 'text-success' : 'text-danger'\"></span>\r\n                        <div class=\"note-title\">{{ note.title }}</div>\r\n                    </div>\r\n                </div>\r\n            </template>\r\n        </el-calendar>\r\n    </div>\r\n</template>\r\n\r\n<script lang=\"ts\" setup>\r\nimport { ref } from 'vue';\r\n\r\nconst today = new Date();\r\nconst yesterday = new Date(today.getTime() - 24 * 60 * 60 * 1000);\r\nconst value = ref(today);\r\n\r\nconst todayDate = today.toISOString().slice(0, 10);\r\nconst yesterdayDate = yesterday.toISOString().slice(0, 10);\r\n\r\nconst notes: any = {\r\n    [todayDate]: [\r\n        { title: '吃饭', status: 1 },\r\n        { title: '睡觉', status: 0 },\r\n        { title: '吃饭', status: 1 },\r\n        { title: '睡觉', status: 0 },\r\n        { title: '吃饭', status: 1 },\r\n        { title: '睡觉', status: 0 },\r\n    ],\r\n    [yesterdayDate]: [{ title: '参加会议', status: 0 }],\r\n};\r\n</script>\r\n\r\n<style scoped>\r\n.notes-container {\r\n    height: 60px;\r\n    overflow-y: auto;\r\n}\r\n\r\n.notes-container::-webkit-scrollbar {\r\n    width: 0;\r\n}\r\n\r\n.notes {\r\n    display: flex;\r\n    align-items: center;\r\n    width: 100%;\r\n    font-size: 12px;\r\n}\r\n\r\n.notes:hover {\r\n    background-color: #eee;\r\n}\r\n\r\n.note-title {\r\n    flex: 1;\r\n    text-overflow: ellipsis;\r\n    white-space: nowrap;\r\n    overflow: hidden;\r\n}\r\n\r\n.notes span {\r\n    width: 8px;\r\n    height: 8px;\r\n    border-radius: 50%;\r\n    margin-right: 5px;\r\n}\r\n\r\n.text-success {\r\n    background-color: #5cb85c;\r\n}\r\n\r\n.text-danger {\r\n    background-color: #d9534f;\r\n}\r\n</style>\r\n"
  },
  {
    "path": "src/views/element/carousel.vue",
    "content": "<template>\r\n    <div>\r\n        <el-card class=\"mgb20\">\r\n            <template #header>基础用法</template>\r\n            <el-carousel height=\"400px\">\r\n                <el-carousel-item v-for=\"item in 4\" :key=\"item\">\r\n                    <h3>{{ item }}</h3>\r\n                </el-carousel-item>\r\n            </el-carousel>\r\n        </el-card>\r\n\r\n        <el-row :gutter=\"20\">\r\n            <el-col :span=\"12\">\r\n                <el-card class=\"mgb20\">\r\n                    <template #header>轮播图</template>\r\n                    <el-carousel height=\"300px\">\r\n                        <el-carousel-item v-for=\"item in imgs\" :key=\"item\">\r\n                            <el-image class=\"carousel-img\" :src=\"item\" fit=\"cover\" />\r\n                        </el-carousel-item>\r\n                    </el-carousel>\r\n                </el-card>\r\n            </el-col>\r\n            <el-col :span=\"12\">\r\n                <el-card class=\"mgb20\">\r\n                    <template #header>卡片模式</template>\r\n                    <el-carousel height=\"300px\" type=\"card\">\r\n                        <el-carousel-item v-for=\"item in imgs\" :key=\"item\">\r\n                            <el-image class=\"carousel-img\" :src=\"item\" fit=\"cover\" />\r\n                        </el-carousel-item>\r\n                    </el-carousel>\r\n                </el-card>\r\n            </el-col>\r\n        </el-row>\r\n    </div>\r\n</template>\r\n\r\n<script lang=\"ts\" setup>\r\nconst imgs = [\r\n    'https://cdn.pixabay.com/photo/2017/08/07/08/23/sea-2601374_640.jpg',\r\n    'https://cdn.pixabay.com/photo/2020/02/11/10/24/lake-4839058_640.jpg',\r\n    'https://cdn.pixabay.com/photo/2024/02/21/08/06/coast-8587004_640.jpg',\r\n    'https://cdn.pixabay.com/photo/2023/07/29/10/21/grasshopper-8156626_640.jpg',\r\n];\r\n</script>\r\n\r\n<style scoped>\r\n.el-carousel__item h3 {\r\n    color: #475669;\r\n    line-height: 400px;\r\n    margin: 0;\r\n    text-align: center;\r\n}\r\n\r\n.el-carousel__item:nth-child(2n) {\r\n    background-color: #99a9bf;\r\n}\r\n\r\n.el-carousel__item:nth-child(2n + 1) {\r\n    background-color: #d3dce6;\r\n}\r\n\r\n.carousel-img {\r\n    width: 100%;\r\n    height: 100%;\r\n}\r\n</style>\r\n"
  },
  {
    "path": "src/views/element/form.vue",
    "content": "<template>\r\n    <div class=\"container\">\r\n        <el-radio-group class=\"mgb20\" v-model=\"labelPosition\">\r\n            <el-radio-button value=\"left\">Left</el-radio-button>\r\n            <el-radio-button value=\"right\">Right</el-radio-button>\r\n            <el-radio-button value=\"top\">Top</el-radio-button>\r\n        </el-radio-group>\r\n        <el-form ref=\"formRef\" :rules=\"rules\" :model=\"form\" label-width=\"120px\" :label-position=\"labelPosition\">\r\n            <el-row :gutter=\"50\">\r\n                <el-col :span=\"10\">\r\n                    <el-form-item label=\"文本框\" prop=\"name\">\r\n                        <el-input v-model=\"form.name\"></el-input>\r\n                    </el-form-item>\r\n                    <el-form-item label=\"数字框\" prop=\"num\">\r\n                        <el-input-number v-model=\"form.num\" :min=\"1\" :max=\"10\" />\r\n                    </el-form-item>\r\n                    <el-form-item label=\"日期选择\" prop=\"date\">\r\n                        <el-date-picker type=\"date\" placeholder=\"选择日期\" v-model=\"form.date\"></el-date-picker>\r\n                    </el-form-item>\r\n                    <el-form-item label=\"时间选择\" prop=\"time\">\r\n                        <el-time-picker placeholder=\"选择时间\" v-model=\"form.time\">\r\n                        </el-time-picker>\r\n                    </el-form-item>\r\n                    <el-form-item label=\"选择器\" prop=\"region\">\r\n                        <el-select v-model=\"form.region\" placeholder=\"请选择\">\r\n                            <el-option key=\"小明\" label=\"小明\" value=\"小明\"></el-option>\r\n                            <el-option key=\"小红\" label=\"小红\" value=\"小红\"></el-option>\r\n                            <el-option key=\"小白\" label=\"小白\" value=\"小白\"></el-option>\r\n                        </el-select>\r\n                    </el-form-item>\r\n                    <el-form-item label=\"城市级联\" prop=\"options\">\r\n                        <el-cascader :options=\"options\" v-model=\"form.options\"></el-cascader>\r\n                    </el-form-item>\r\n                    <el-form-item label=\"文本框\" prop=\"desc\">\r\n                        <el-input type=\"textarea\" rows=\"5\" v-model=\"form.desc\"></el-input>\r\n                    </el-form-item>\r\n                </el-col>\r\n                <el-col :span=\"12\">\r\n                    <el-form-item label=\"评分\" prop=\"rate\">\r\n                        <el-rate v-model=\"form.rate\" allow-half />\r\n                    </el-form-item>\r\n                    <el-form-item label=\"滑块\" prop=\"num\">\r\n                        <el-slider v-model=\"form.num\" :step=\"1\" show-stops :max=\"10\" />\r\n                    </el-form-item>\r\n                    <el-form-item label=\"开关\" prop=\"delivery\">\r\n                        <el-switch v-model=\"form.delivery\"></el-switch>\r\n                    </el-form-item>\r\n                    <el-form-item label=\"颜色选择\" prop=\"color\">\r\n                        <el-color-picker v-model=\"form.color\" />\r\n                    </el-form-item>\r\n                    <el-form-item label=\"多选框\" prop=\"type\">\r\n                        <el-checkbox-group v-model=\"form.type\">\r\n                            <el-checkbox label=\"小明\" value=\"小明\" name=\"type\"></el-checkbox>\r\n                            <el-checkbox label=\"小红\" value=\"小红\" name=\"type\"></el-checkbox>\r\n                            <el-checkbox label=\"小白\" value=\"小白\" name=\"type\"></el-checkbox>\r\n                        </el-checkbox-group>\r\n                    </el-form-item>\r\n                    <el-form-item label=\"单选框\" prop=\"resource\">\r\n                        <el-radio-group v-model=\"form.resource\">\r\n                            <el-radio label=\"小明\" value=\"小明\"></el-radio>\r\n                            <el-radio label=\"小红\" value=\"小红\"></el-radio>\r\n                            <el-radio label=\"小白\" value=\"小白\"></el-radio>\r\n                        </el-radio-group>\r\n                    </el-form-item>\r\n                    <el-form-item label=\"穿梭框\" prop=\"transfer\">\r\n                        <el-transfer v-model=\"form.transfer\" :data=\"transferData\" />\r\n                    </el-form-item>\r\n                </el-col>\r\n\r\n                <el-col :span=\"24\">\r\n                    <el-form-item>\r\n                        <el-button type=\"primary\" @click=\"onSubmit(formRef)\">表单提交</el-button>\r\n                        <el-button @click=\"onReset(formRef)\">重置表单</el-button>\r\n                    </el-form-item>\r\n                </el-col>\r\n            </el-row>\r\n        </el-form>\r\n    </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\" name=\"forms\">\r\nimport { reactive, ref } from 'vue';\r\nimport { ElMessage } from 'element-plus';\r\nimport type { FormInstance, FormProps, FormRules } from 'element-plus';\r\nconst labelPosition = ref<FormProps['labelPosition']>('right')\r\nconst options = [\r\n    {\r\n        value: 'guangdong',\r\n        label: '广东省',\r\n        children: [\r\n            {\r\n                value: 'guangzhou',\r\n                label: '广州市',\r\n                children: [\r\n                    {\r\n                        value: 'tianhe',\r\n                        label: '天河区',\r\n                    },\r\n                    {\r\n                        value: 'haizhu',\r\n                        label: '海珠区',\r\n                    },\r\n                ],\r\n            },\r\n            {\r\n                value: 'dongguan',\r\n                label: '东莞市',\r\n                children: [\r\n                    {\r\n                        value: 'changan',\r\n                        label: '长安镇',\r\n                    },\r\n                    {\r\n                        value: 'humen',\r\n                        label: '虎门镇',\r\n                    },\r\n                ],\r\n            },\r\n        ],\r\n    },\r\n    {\r\n        value: 'hunan',\r\n        label: '湖南省',\r\n        children: [\r\n            {\r\n                value: 'changsha',\r\n                label: '长沙市',\r\n                children: [\r\n                    {\r\n                        value: 'yuelu',\r\n                        label: '岳麓区',\r\n                    },\r\n                ],\r\n            },\r\n        ],\r\n    },\r\n];\r\nconst rules: FormRules = {\r\n    name: [{ required: true, message: '请输入表单名称', trigger: 'blur' }],\r\n};\r\nconst formRef = ref<FormInstance>();\r\nconst form = reactive({\r\n    name: '',\r\n    region: '',\r\n    date: '',\r\n    time: '',\r\n    delivery: true,\r\n    type: ['小明'],\r\n    resource: '小红',\r\n    desc: '',\r\n    options: [],\r\n    color: '',\r\n    num: 1,\r\n    rate: 0,\r\n    transfer: [],\r\n\r\n});\r\nconst generateData = () => {\r\n    const data = []\r\n    for (let i = 1; i <= 15; i++) {\r\n        data.push({\r\n            key: i,\r\n            label: `Option ${i}`,\r\n            disabled: i % 4 === 0,\r\n        })\r\n    }\r\n    return data\r\n}\r\n\r\nconst transferData = ref(generateData())\r\n// 提交\r\nconst onSubmit = (formEl: FormInstance | undefined) => {\r\n    // 表单校验\r\n    if (!formEl) return;\r\n    formEl.validate((valid) => {\r\n        if (valid) {\r\n            console.log(form);\r\n            ElMessage.success('提交成功！');\r\n        } else {\r\n            return false;\r\n        }\r\n    });\r\n};\r\n// 重置\r\nconst onReset = (formEl: FormInstance | undefined) => {\r\n    if (!formEl) return;\r\n    formEl.resetFields();\r\n};\r\n</script>"
  },
  {
    "path": "src/views/element/statistic.vue",
    "content": "<template>\r\n    <div>\r\n\r\n\r\n        <el-card class=\"mgb20\" shadow=\"hover\">\r\n            <template #header>基础用法</template>\r\n            <el-row>\r\n                <el-col :span=\"6\" style=\"text-align: center\">\r\n                    <el-statistic title=\"Daily active users\" :value=\"268500\" />\r\n                </el-col>\r\n                <el-col :span=\"6\" style=\"text-align: center\">\r\n                    <el-statistic :value=\"138\">\r\n                        <template #title>\r\n                            <div style=\"display: inline-flex; align-items: center\">\r\n                                Ratio of men to women\r\n                            </div>\r\n                        </template>\r\n                        <template #suffix>/100</template>\r\n                    </el-statistic>\r\n                </el-col>\r\n                <el-col :span=\"6\" style=\"text-align: center\">\r\n                    <el-statistic title=\"数字滚动\" :value=\"outputValue\" />\r\n                </el-col>\r\n                <el-col :span=\"6\" style=\"text-align: center\">\r\n                    <el-countdown title=\"倒计时\" :value=\"value\" />\r\n                </el-col>\r\n            </el-row>\r\n        </el-card>\r\n\r\n        <el-card class=\"mgb20\" shadow=\"hover\">\r\n            <template #header>CountUp.js</template>\r\n            <div class=\"plugins-tips\">\r\n                countup.js：用于快速创建以更有趣的方式显示数字数据的动画。 访问地址：\r\n                <a href=\"https://github.com/inorganik/countUp.js\" target=\"_blank\">countUp.js</a>\r\n            </div>\r\n            <el-row>\r\n                <el-col :span=\"8\" style=\"text-align: center\">\r\n                    <p>基础用法</p>\r\n                    <countup class=\"countup\" :end=\"6666\" />\r\n                </el-col>\r\n                <el-col :span=\"8\" style=\"text-align: center\">\r\n                    <p>具体配置</p>\r\n                    <countup class=\"countup\" :end=\"8888.5\" :options=\"options\" />\r\n                </el-col>\r\n                <el-col :span=\"8\" style=\"text-align: center\">\r\n                    <p>更新数值</p>\r\n                    <countup class=\"countup\" :end=\"value1\" />\r\n                </el-col>\r\n            </el-row>\r\n        </el-card>\r\n        <el-card class=\"mgb20\" shadow=\"never\">\r\n            <template #header>统计卡片</template>\r\n\r\n            <el-row :gutter=\"20\" class=\"mgb20\">\r\n                <el-col :span=\"6\">\r\n                    <el-card shadow=\"hover\" body-class=\"card-body\">\r\n                        <el-icon class=\"card-icon color1\">\r\n                            <User />\r\n                        </el-icon>\r\n                        <div class=\"card-content text-right\">\r\n                            <el-statistic title=\"日活跃用户量\" :value=\"268500\" />\r\n                        </div>\r\n                    </el-card>\r\n                </el-col>\r\n                <el-col :span=\"6\">\r\n                    <el-card shadow=\"hover\" body-class=\"card-body\">\r\n                        <el-icon class=\"card-icon color2\">\r\n                            <ChatDotRound />\r\n                        </el-icon>\r\n                        <div class=\"card-content text-right\">\r\n                            <el-statistic title=\"系统消息\" :value=\"16800\" />\r\n                        </div>\r\n                    </el-card>\r\n                </el-col>\r\n                <el-col :span=\"6\">\r\n                    <el-card shadow=\"hover\" body-class=\"card-body\">\r\n                        <el-icon class=\"card-icon color3\">\r\n                            <Goods />\r\n                        </el-icon>\r\n                        <div class=\"card-content text-right\">\r\n                            <el-statistic title=\"商品数量\" :value=\"8888\" />\r\n                        </div>\r\n                    </el-card>\r\n                </el-col>\r\n                <el-col :span=\"6\">\r\n                    <el-card shadow=\"hover\" body-class=\"card-body\">\r\n                        <el-icon class=\"card-icon color4\">\r\n                            <ShoppingCartFull />\r\n                        </el-icon>\r\n                        <div class=\"card-content text-right\">\r\n                            <el-statistic title=\"今日订单量\" :value=\"56888\" />\r\n                        </div>\r\n                    </el-card>\r\n                </el-col>\r\n            </el-row>\r\n            <el-row :gutter=\"20\" class=\"mgb20\">\r\n                <el-col :span=\"6\">\r\n                    <el-card shadow=\"hover\" body-class=\"card-body\">\r\n                        <div class=\"card-content text-left\">\r\n                            <el-statistic :value-style=\"{ color: '#2d8cf0' }\" title=\"日活跃用户量\" :value=\"268500\" />\r\n                        </div>\r\n                        <el-icon class=\"card-icon color1\">\r\n                            <User />\r\n                        </el-icon>\r\n                    </el-card>\r\n                </el-col>\r\n                <el-col :span=\"6\">\r\n                    <el-card shadow=\"hover\" body-class=\"card-body\">\r\n                        <div class=\"card-content text-left\">\r\n                            <el-statistic :value-style=\"{ color: '#64d572' }\" title=\"系统消息\" :value=\"16800\" />\r\n                        </div>\r\n                        <el-icon class=\"card-icon color2\">\r\n                            <ChatDotRound />\r\n                        </el-icon>\r\n                    </el-card>\r\n                </el-col>\r\n                <el-col :span=\"6\">\r\n                    <el-card shadow=\"hover\" body-class=\"card-body\">\r\n                        <div class=\"card-content text-left\">\r\n                            <el-statistic :value-style=\"{ color: '#f25e43' }\" title=\"商品数量\" :value=\"8888\" />\r\n                        </div>\r\n                        <el-icon class=\"card-icon color3\">\r\n                            <Goods />\r\n                        </el-icon>\r\n                    </el-card>\r\n                </el-col>\r\n                <el-col :span=\"6\">\r\n                    <el-card shadow=\"hover\" body-class=\"card-body\">\r\n                        <div class=\"card-content text-left\">\r\n                            <el-statistic :value-style=\"{ color: '#e9a745' }\" title=\"今日订单量\" :value=\"56888\" />\r\n                        </div>\r\n                        <el-icon class=\"card-icon color4\">\r\n                            <ShoppingCartFull />\r\n                        </el-icon>\r\n                    </el-card>\r\n                </el-col>\r\n            </el-row>\r\n            <el-row :gutter=\"20\" class=\"mgb20\">\r\n                <el-col :span=\"6\">\r\n                    <el-card shadow=\"hover\" body-class=\"card-body\">\r\n                        <el-icon class=\"card-icon bg1\">\r\n                            <User />\r\n                        </el-icon>\r\n                        <div class=\"card-content\">\r\n                            <countup class=\"card-num color1\" :end=\"6666\" />\r\n                            <div>用户访问量</div>\r\n                        </div>\r\n                    </el-card>\r\n                </el-col>\r\n                <el-col :span=\"6\">\r\n                    <el-card shadow=\"hover\" body-class=\"card-body\">\r\n                        <el-icon class=\"card-icon bg2\">\r\n                            <ChatDotRound />\r\n                        </el-icon>\r\n                        <div class=\"card-content\">\r\n                            <countup class=\"card-num color2\" :end=\"168\" />\r\n                            <div>系统消息</div>\r\n                        </div>\r\n                    </el-card>\r\n                </el-col>\r\n                <el-col :span=\"6\">\r\n                    <el-card shadow=\"hover\" body-class=\"card-body\">\r\n                        <el-icon class=\"card-icon bg3\">\r\n                            <Goods />\r\n                        </el-icon>\r\n                        <div class=\"card-content\">\r\n                            <countup class=\"card-num color3\" :end=\"8888\" />\r\n                            <div>商品数量</div>\r\n                        </div>\r\n                    </el-card>\r\n                </el-col>\r\n                <el-col :span=\"6\">\r\n                    <el-card shadow=\"hover\" body-class=\"card-body\">\r\n                        <el-icon class=\"card-icon bg4\">\r\n                            <ShoppingCartFull />\r\n                        </el-icon>\r\n                        <div class=\"card-content\">\r\n                            <countup class=\"card-num color4\" :end=\"568\" />\r\n                            <div>今日订单量</div>\r\n                        </div>\r\n                    </el-card>\r\n                </el-col>\r\n            </el-row>\r\n            <el-row :gutter=\"20\" class=\"mgb20\">\r\n                <el-col :span=\"6\">\r\n                    <el-card shadow=\"hover\" body-class=\"card-body bg1\">\r\n                        <el-icon class=\"card-icon \">\r\n                            <User />\r\n                        </el-icon>\r\n                        <div class=\"card-content color0\">\r\n                            <countup class=\"card-num\" :end=\"6666\" />\r\n                            <div>用户访问量</div>\r\n                        </div>\r\n                    </el-card>\r\n                </el-col>\r\n                <el-col :span=\"6\">\r\n                    <el-card shadow=\"hover\" body-class=\"card-body bg2\">\r\n                        <el-icon class=\"card-icon\">\r\n                            <ChatDotRound />\r\n                        </el-icon>\r\n                        <div class=\"card-content color0\">\r\n                            <countup class=\"card-num\" :end=\"168\" />\r\n                            <div>系统消息</div>\r\n                        </div>\r\n                    </el-card>\r\n                </el-col>\r\n                <el-col :span=\"6\">\r\n                    <el-card shadow=\"hover\" body-class=\"card-body bg3\">\r\n                        <el-icon class=\"card-icon\">\r\n                            <Goods />\r\n                        </el-icon>\r\n                        <div class=\"card-content color0\">\r\n                            <countup class=\"card-num \" :end=\"8888\" />\r\n                            <div>商品数量</div>\r\n                        </div>\r\n                    </el-card>\r\n                </el-col>\r\n                <el-col :span=\"6\">\r\n                    <el-card shadow=\"hover\" body-class=\"card-body bg4\">\r\n                        <el-icon class=\"card-icon\">\r\n                            <ShoppingCartFull />\r\n                        </el-icon>\r\n                        <div class=\"card-content color0\">\r\n                            <countup class=\"card-num \" :end=\"568\" />\r\n                            <div>今日订单量</div>\r\n                        </div>\r\n                    </el-card>\r\n                </el-col>\r\n            </el-row>\r\n        </el-card>\r\n    </div>\r\n</template>\r\n\r\n<script lang=\"ts\" setup>\r\nimport { ref } from 'vue'\r\nimport { useTransition } from '@vueuse/core'\r\nimport countup from '@/components/countup.vue';\r\n\r\nconst source = ref(0)\r\nconst outputValue = useTransition(source, {\r\n    duration: 1500,\r\n})\r\nsource.value = 172000\r\n\r\nconst value = ref(Date.now() + 1000 * 60 * 60 * 7)\r\nconst value1 = ref(1000);\r\nsetTimeout(() => {\r\n    value1.value = 8000;\r\n}, 5000);\r\nconst options = {\r\n    startVal: 1000,\r\n    decimalPlaces: 2,\r\n    duration: 5,\r\n    useGrouping: false,\r\n    prefix: '$',\r\n    separator: ',',\r\n    decimal: '.',\r\n    suffix: '',\r\n}\r\n</script>\r\n\r\n<style>\r\n.card-body {\r\n    display: flex;\r\n    align-items: center;\r\n    height: 100px;\r\n    padding: 0;\r\n}\r\n\r\n.bg1 {\r\n    background: #2d8cf0;\r\n}\r\n\r\n.bg2 {\r\n    background: #64d572;\r\n}\r\n\r\n.bg3 {\r\n    background: #f25e43;\r\n}\r\n\r\n.bg4 {\r\n    background: #e9a745;\r\n}\r\n</style>\r\n<style scoped>\r\n.countup {\r\n    font-size: 24px;\r\n}\r\n\r\n.card-content {\r\n    flex: 1;\r\n    text-align: center;\r\n    font-size: 14px;\r\n    color: #999;\r\n    padding: 0 20px;\r\n}\r\n\r\n.card-num {\r\n    font-size: 30px;\r\n}\r\n\r\n.card-icon {\r\n    font-size: 50px;\r\n    width: 100px;\r\n    height: 100px;\r\n    text-align: center;\r\n    line-height: 100px;\r\n    color: #fff;\r\n}\r\n\r\n\r\n.color0 {\r\n    color: #fff;\r\n}\r\n\r\n.color1 {\r\n    color: #2d8cf0;\r\n}\r\n\r\n.color2 {\r\n    color: #64d572;\r\n}\r\n\r\n.color3 {\r\n    color: #f25e43;\r\n}\r\n\r\n.color4 {\r\n    color: #e9a745;\r\n}\r\n\r\n.text-right {\r\n    text-align: right;\r\n}\r\n\r\n.text-left {\r\n    text-align: left;\r\n}\r\n</style>"
  },
  {
    "path": "src/views/element/steps.vue",
    "content": "<template>\r\n    <div class=\"container\">\r\n        <div class=\"step-div\" v-if=\"step === 0\">\r\n            <p>输入注册时的邮箱，我们会发送验证码到您的邮箱</p>\r\n            <el-input placeholder=\"请输入邮箱\"></el-input>\r\n            <el-button class=\"step-btn\" type=\"primary\" @click=\"step++\">下一步</el-button>\r\n        </div>\r\n        <div class=\"step-div\" v-else-if=\"step === 1\">\r\n            <p>验证码已发送至您的邮箱，请输入验证码</p>\r\n            <el-input placeholder=\"请输入验证码\"></el-input>\r\n            <el-button class=\"step-btn\" type=\"primary\" @click=\"step++\">下一步</el-button>\r\n        </div>\r\n\r\n        <div class=\"step-div\" v-else-if=\"step === 2\">\r\n            <p>请输入6位以上密码</p>\r\n            <el-input placeholder=\"请输入新密码\"></el-input>\r\n            <el-button class=\"step-btn\" type=\"primary\" @click=\"step++\">保存</el-button>\r\n        </div>\r\n        <div v-else>\r\n            <el-result icon=\"success\" title=\"保存成功\" sub-title=\"请退出后重新登录\"></el-result>\r\n        </div>\r\n        <el-steps class=\"step-style\" :active=\"step\" align-center finish-status=\"success\">\r\n            <el-step title=\"Step 1\" description=\"填写邮箱\" />\r\n            <el-step title=\"Step 2\" description=\"填写验证码\" />\r\n            <el-step title=\"Step 3\" description=\"修改密码\" />\r\n        </el-steps>\r\n        <el-steps class=\"step-style\" :active=\"step\" finish-status=\"success\" simple>\r\n            <el-step title=\"填写邮箱\" />\r\n            <el-step title=\"填写验证码\" />\r\n            <el-step title=\"修改密码\" />\r\n        </el-steps>\r\n    </div>\r\n</template>\r\n\r\n<script lang=\"ts\" setup>\r\nimport { ref } from 'vue';\r\nconst step = ref(0)\r\n</script>\r\n\r\n<style scoped>\r\n.step-div {\r\n    max-width: 500px;\r\n    margin: 0 auto;\r\n}\r\n\r\n.step-div p {\r\n    margin-bottom: 20px;\r\n    color: #787878;\r\n}\r\n\r\n.step-btn {\r\n    display: block;\r\n    width: 100%;\r\n    margin: 20px 0;\r\n}\r\n\r\n.step-style {\r\n    max-width: 800px;\r\n    margin: 40px auto;\r\n}\r\n</style>"
  },
  {
    "path": "src/views/element/tabs.vue",
    "content": "<template>\r\n\t<el-tabs v-model=\"message\" type=\"card\">\r\n\t\t<el-tab-pane :label=\"`未读消息(${state.unread.length})`\" name=\"first\">\r\n\t\t\t<el-table :data=\"state.unread\" :show-header=\"false\" style=\"width: 100%\">\r\n\t\t\t\t<el-table-column>\r\n\t\t\t\t\t<template #default=\"scope\">\r\n\t\t\t\t\t\t<span class=\"message-title\">{{ scope.row.title }}</span>\r\n\t\t\t\t\t</template>\r\n\t\t\t\t</el-table-column>\r\n\t\t\t\t<el-table-column prop=\"date\" width=\"180\"></el-table-column>\r\n\t\t\t\t<el-table-column width=\"120\">\r\n\t\t\t\t\t<template #default=\"scope\">\r\n\t\t\t\t\t\t<el-button size=\"small\" @click=\"handleRead(scope.$index)\">标为已读</el-button>\r\n\t\t\t\t\t</template>\r\n\t\t\t\t</el-table-column>\r\n\t\t\t</el-table>\r\n\t\t\t<div class=\"handle-row\">\r\n\t\t\t\t<el-button type=\"primary\">全部标为已读</el-button>\r\n\t\t\t</div>\r\n\t\t</el-tab-pane>\r\n\t\t<el-tab-pane :label=\"`已读消息(${state.read.length})`\" name=\"second\">\r\n\t\t\t<template v-if=\"message === 'second'\">\r\n\t\t\t\t<el-table :data=\"state.read\" :show-header=\"false\" style=\"width: 100%\">\r\n\t\t\t\t\t<el-table-column>\r\n\t\t\t\t\t\t<template #default=\"scope\">\r\n\t\t\t\t\t\t\t<span class=\"message-title\">{{ scope.row.title }}</span>\r\n\t\t\t\t\t\t</template>\r\n\t\t\t\t\t</el-table-column>\r\n\t\t\t\t\t<el-table-column prop=\"date\" width=\"180\"></el-table-column>\r\n\t\t\t\t\t<el-table-column width=\"120\">\r\n\t\t\t\t\t\t<template #default=\"scope\">\r\n\t\t\t\t\t\t\t<el-button type=\"danger\" size=\"small\" @click=\"handleDel(scope.$index)\">删除</el-button>\r\n\t\t\t\t\t\t</template>\r\n\t\t\t\t\t</el-table-column>\r\n\t\t\t\t</el-table>\r\n\t\t\t\t<div class=\"handle-row\">\r\n\t\t\t\t\t<el-button type=\"danger\">删除全部</el-button>\r\n\t\t\t\t</div>\r\n\t\t\t</template>\r\n\t\t</el-tab-pane>\r\n\t\t<el-tab-pane :label=\"`回收站(${state.recycle.length})`\" name=\"third\">\r\n\t\t\t<template v-if=\"message === 'third'\">\r\n\t\t\t\t<el-table :data=\"state.recycle\" :show-header=\"false\" style=\"width: 100%\">\r\n\t\t\t\t\t<el-table-column>\r\n\t\t\t\t\t\t<template #default=\"scope\">\r\n\t\t\t\t\t\t\t<span class=\"message-title\">{{ scope.row.title }}</span>\r\n\t\t\t\t\t\t</template>\r\n\t\t\t\t\t</el-table-column>\r\n\t\t\t\t\t<el-table-column prop=\"date\" width=\"180\"></el-table-column>\r\n\t\t\t\t\t<el-table-column width=\"120\">\r\n\t\t\t\t\t\t<template #default=\"scope\">\r\n\t\t\t\t\t\t\t<el-button size=\"small\" @click=\"handleRestore(scope.$index)\">还原</el-button>\r\n\t\t\t\t\t\t</template>\r\n\t\t\t\t\t</el-table-column>\r\n\t\t\t\t</el-table>\r\n\t\t\t\t<div class=\"handle-row\">\r\n\t\t\t\t\t<el-button type=\"danger\">清空回收站</el-button>\r\n\t\t\t\t</div>\r\n\t\t\t</template>\r\n\t\t</el-tab-pane>\r\n\t</el-tabs>\r\n</template>\r\n\r\n<script setup lang=\"ts\" name=\"tabs\">\r\nimport { ref, reactive } from 'vue';\r\n\r\nconst message = ref('first');\r\nconst state = reactive({\r\n\tunread: [\r\n\t\t{\r\n\t\t\tdate: '2018-04-19 20:00:00',\r\n\t\t\ttitle: '【系统通知】该系统将于今晚凌晨2点到5点进行升级维护'\r\n\t\t},\r\n\t\t{\r\n\t\t\tdate: '2018-04-19 21:00:00',\r\n\t\t\ttitle: '今晚12点整发大红包，先到先得'\r\n\t\t}\r\n\t],\r\n\tread: [\r\n\t\t{\r\n\t\t\tdate: '2018-04-19 20:00:00',\r\n\t\t\ttitle: '【系统通知】该系统将于今晚凌晨2点到5点进行升级维护'\r\n\t\t}\r\n\t],\r\n\trecycle: [\r\n\t\t{\r\n\t\t\tdate: '2018-04-19 20:00:00',\r\n\t\t\ttitle: '【系统通知】该系统将于今晚凌晨2点到5点进行升级维护'\r\n\t\t}\r\n\t]\r\n});\r\n\r\nconst handleRead = (index: number) => {\r\n\tconst item = state.unread.splice(index, 1);\r\n\tstate.read = item.concat(state.read);\r\n};\r\nconst handleDel = (index: number) => {\r\n\tconst item = state.read.splice(index, 1);\r\n\tstate.recycle = item.concat(state.recycle);\r\n};\r\nconst handleRestore = (index: number) => {\r\n\tconst item = state.recycle.splice(index, 1);\r\n\tstate.read = item.concat(state.read);\r\n};\r\n</script>\r\n\r\n<style>\r\n.message-title {\r\n\tcursor: pointer;\r\n\tcolor: var(--el-color-primary);\r\n}\r\n\r\n.handle-row {\r\n\tmargin-top: 30px;\r\n}\r\n</style>\r\n"
  },
  {
    "path": "src/views/element/tour.vue",
    "content": "<template>\r\n    <div class=\"container\">\r\n        <el-button type=\"primary\" @click=\"open = true\">开始引导</el-button>\r\n\r\n        <el-divider />\r\n\r\n        <el-space>\r\n            <el-button ref=\"ref1\">上传</el-button>\r\n            <el-button ref=\"ref2\" type=\"primary\">保存</el-button>\r\n            <el-button ref=\"ref3\" :icon=\"MoreFilled\" />\r\n        </el-space>\r\n\r\n        <el-tour v-model=\"open\">\r\n            <el-tour-step :target=\"ref1?.$el\" title=\"上传文件\">\r\n                <img style=\"width: 120px\" src=\"../../assets/img/img.jpg\" alt=\"tour.png\" />\r\n                <div>点击这里选择文件</div>\r\n            </el-tour-step>\r\n            <el-tour-step :target=\"ref2?.$el\" title=\"保存\" description=\"点击进行上传\" />\r\n            <el-tour-step :target=\"ref3?.$el\" title=\"更多操作\" description=\"点击查看更多操作\" />\r\n        </el-tour>\r\n    </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref } from 'vue'\r\nimport { MoreFilled } from '@element-plus/icons-vue'\r\n\r\nconst ref1 = ref()\r\nconst ref2 = ref()\r\nconst ref3 = ref()\r\n\r\nconst open = ref(false)\r\n</script>"
  },
  {
    "path": "src/views/element/upload.vue",
    "content": "<template>\r\n    <div class=\"container\">\r\n        <div class=\"content-title\">支持拖拽</div>\r\n        <div class=\"plugins-tips\">\r\n            Element Plus自带上传组件。 访问地址：\r\n            <a href=\"https://element-plus.org/zh-CN/component/upload.html\" target=\"_blank\">Element Plus Upload</a>\r\n        </div>\r\n        <el-upload class=\"upload-demo\" drag action=\"http://jsonplaceholder.typicode.com/api/posts/\" multiple\r\n            :on-change=\"handle\">\r\n            <el-icon class=\"el-icon--upload\"><upload-filled /></el-icon>\r\n            <div class=\"el-upload__text\">\r\n                将文件拖到此处，或\r\n                <em>点击上传</em>\r\n            </div>\r\n        </el-upload>\r\n\r\n        <div class=\"content-title\">支持裁剪</div>\r\n        <div class=\"plugins-tips\">\r\n            vue-cropper：一个简单的vue图片裁剪插件。 访问地址：\r\n            <a href=\"https://github.com/xyxiao001/vue-cropper\" target=\"_blank\">vue-cropper</a>。 示例请查看\r\n            <router-link to=\"/ucenter\">个人中心-我的头像</router-link>\r\n        </div>\r\n    </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nconst handle = (rawFile: any) => {\r\n    console.log(rawFile);\r\n};\r\n</script>\r\n\r\n<style scoped>\r\n.content-title {\r\n    font-weight: 400;\r\n    line-height: 50px;\r\n    margin: 10px 0;\r\n    font-size: 22px;\r\n    color: #1f2f3d;\r\n}\r\n\r\n.upload-demo {\r\n    width: 360px;\r\n}\r\n</style>\r\n"
  },
  {
    "path": "src/views/element/watermark.vue",
    "content": "<template>\r\n    <div class=\"container\">\r\n        <el-row :gutter=\"20\">\r\n            <el-col :span=\"18\">\r\n                <el-watermark :content=\"config.content\" :font=\"config.font\" :z-index=\"config.zIndex\"\r\n                    :rotate=\"config.rotate\" :gap=\"config.gap\" :offset=\"config.offset\">\r\n                    <div style=\"height: 600px\" />\r\n                </el-watermark>\r\n            </el-col>\r\n            <el-col :span=\"6\">\r\n                <el-form class=\"form\" :model=\"config\" label-position=\"top\" label-width=\"50px\">\r\n                    <el-form-item label=\"Content\">\r\n                        <el-input v-model=\"config.content\" />\r\n                    </el-form-item>\r\n                    <el-form-item label=\"Color\">\r\n                        <el-color-picker v-model=\"config.font.color\" show-alpha />\r\n                    </el-form-item>\r\n                    <el-form-item label=\"FontSize\">\r\n                        <el-slider v-model=\"config.font.fontSize\" />\r\n                    </el-form-item>\r\n                    <el-form-item label=\"zIndex\">\r\n                        <el-slider v-model=\"config.zIndex\" />\r\n                    </el-form-item>\r\n                    <el-form-item label=\"Rotate\">\r\n                        <el-slider v-model=\"config.rotate\" :min=\"-180\" :max=\"180\" />\r\n                    </el-form-item>\r\n                    <el-form-item label=\"Gap\">\r\n                        <el-space>\r\n                            <el-input-number v-model=\"config.gap[0]\" controls-position=\"right\" />\r\n                            <el-input-number v-model=\"config.gap[1]\" controls-position=\"right\" />\r\n                        </el-space>\r\n                    </el-form-item>\r\n                    <el-form-item label=\"Offset\">\r\n                        <el-space>\r\n                            <el-input-number v-model=\"config.offset[0]\" placeholder=\"offsetLeft\"\r\n                                controls-position=\"right\" />\r\n                            <el-input-number v-model=\"config.offset[1]\" placeholder=\"offsetTop\"\r\n                                controls-position=\"right\" />\r\n                        </el-space>\r\n                    </el-form-item>\r\n                </el-form>\r\n            </el-col>\r\n        </el-row>\r\n\r\n    </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { reactive } from 'vue'\r\n\r\nconst config = reactive({\r\n    content: 'vue-manage-system',\r\n    font: {\r\n        fontSize: 16,\r\n        color: 'rgba(0, 0, 0, 0.15)',\r\n    },\r\n    zIndex: -1,\r\n    rotate: -22,\r\n    gap: [100, 100] as [number, number],\r\n    offset: [] as unknown as [number, number],\r\n})\r\n</script>"
  },
  {
    "path": "src/views/home.vue",
    "content": "<template>\r\n    <div class=\"wrapper\">\r\n        <v-header />\r\n        <v-sidebar />\r\n        <div class=\"content-box\" :class=\"{ 'content-collapse': sidebar.collapse }\">\r\n            <v-tabs></v-tabs>\r\n            <div class=\"content\">\r\n                <router-view v-slot=\"{ Component }\">\r\n                    <transition name=\"move\" mode=\"out-in\">\r\n                        <keep-alive :include=\"tabs.nameList\">\r\n                            <component :is=\"Component\"></component>\r\n                        </keep-alive>\r\n                    </transition>\r\n                </router-view>\r\n            </div>\r\n        </div>\r\n    </div>\r\n</template>\r\n<script setup lang=\"ts\">\r\nimport { useSidebarStore } from '@/store/sidebar';\r\nimport { useTabsStore } from '@/store/tabs';\r\nimport vHeader from '@/components/header.vue';\r\nimport vSidebar from '@/components/sidebar.vue';\r\nimport vTabs from '@/components/tabs.vue';\r\n\r\nconst sidebar = useSidebarStore();\r\nconst tabs = useTabsStore();\r\n</script>\r\n\r\n<style>\r\n.wrapper {\r\n    height: 100vh;\r\n    overflow: hidden;\r\n}\r\n.content-box {\r\n    position: absolute;\r\n    left: 250px;\r\n    right: 0;\r\n    top: 70px;\r\n    bottom: 0;\r\n    padding-bottom: 30px;\r\n    -webkit-transition: left 0.3s ease-in-out;\r\n    transition: left 0.3s ease-in-out;\r\n    background: #eef0fc;\r\n    overflow: hidden;\r\n}\r\n\r\n.content {\r\n    width: auto;\r\n    height: 100%;\r\n    padding: 20px;\r\n    overflow-y: scroll;\r\n    box-sizing: border-box;\r\n}\r\n\r\n.content::-webkit-scrollbar {\r\n    width: 0;\r\n}\r\n\r\n.content-collapse {\r\n    left: 65px;\r\n}\r\n</style>\r\n"
  },
  {
    "path": "src/views/pages/403.vue",
    "content": "<template>\r\n    <div class=\"error-page\">\r\n        <div class=\"error-box\">\r\n            <div class=\"error-code\">403</div>\r\n            <div class=\"error-desc\">啊哦~ 你没有权限访问该页面哦</div>\r\n            <div class=\"error-handle\">\r\n                <router-link to=\"/\">\r\n                    <el-button type=\"primary\" size=\"large\">返回首页</el-button>\r\n                </router-link>\r\n                <el-button class=\"error-btn\" size=\"large\" @click=\"goBack\">返回上一页</el-button>\r\n            </div>\r\n        </div>\r\n    </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\" name=\"403\">\r\nimport { useRouter } from 'vue-router';\r\n\r\nconst router = useRouter();\r\nconst goBack = () => {\r\n    router.go(-2);\r\n};\r\n</script>\r\n\r\n<style scoped>\r\n.error-page {\r\n    display: flex;\r\n    justify-content: center;\r\n    align-items: center;\r\n    flex-direction: column;\r\n    width: 100%;\r\n    height: 100vh;\r\n    background: #eef0fc;\r\n    box-sizing: border-box;\r\n}\r\n\r\n.error-box {\r\n    width: 400px;\r\n    background-color: #fff;\r\n    padding: 80px 50px;\r\n    border-radius: 5px;\r\n}\r\n\r\n.error-code {\r\n    line-height: 1;\r\n    font-size: 100px;\r\n    font-weight: bold;\r\n    color: var(--el-color-primary);\r\n    margin-bottom: 20px;\r\n    text-align: center;\r\n}\r\n\r\n.error-desc {\r\n    font-size: 20px;\r\n    color: #777;\r\n    text-align: center;\r\n}\r\n\r\n.error-handle {\r\n    margin-top: 50px;\r\n    text-align: center;\r\n}\r\n\r\n.error-btn {\r\n    margin-left: 100px;\r\n}\r\n</style>\r\n"
  },
  {
    "path": "src/views/pages/404.vue",
    "content": "<template>\r\n    <div class=\"error-page\">\r\n        <div class=\"error-box\">\r\n            <div class=\"error-code\">404</div>\r\n            <div class=\"error-desc\">啊哦~ 你所访问的页面不存在</div>\r\n            <div class=\"error-handle\">\r\n                <router-link to=\"/\">\r\n                    <el-button type=\"primary\" size=\"large\">返回首页</el-button>\r\n                </router-link>\r\n                <el-button class=\"error-btn\" size=\"large\" @click=\"goBack\">返回上一页</el-button>\r\n            </div>\r\n        </div>\r\n    </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\" name=\"404\">\r\nimport { useRouter } from 'vue-router';\r\n\r\nconst router = useRouter();\r\nconst goBack = () => {\r\n    router.go(-1);\r\n};\r\n</script>\r\n\r\n<style scoped>\r\n.error-page {\r\n    display: flex;\r\n    justify-content: center;\r\n    align-items: center;\r\n    flex-direction: column;\r\n    width: 100%;\r\n    height: 100vh;\r\n    background: #eef0fc;\r\n    box-sizing: border-box;\r\n}\r\n\r\n.error-box {\r\n    width: 400px;\r\n    background-color: #fff;\r\n    padding: 80px 50px;\r\n    border-radius: 5px;\r\n}\r\n\r\n.error-code {\r\n    line-height: 1;\r\n    font-size: 100px;\r\n    font-weight: bold;\r\n    color: var(--el-color-primary);\r\n    margin-bottom: 20px;\r\n    text-align: center;\r\n}\r\n\r\n.error-desc {\r\n    font-size: 20px;\r\n    color: #777;\r\n    text-align: center;\r\n}\r\n\r\n.error-handle {\r\n    margin-top: 50px;\r\n    text-align: center;\r\n}\r\n\r\n.error-btn {\r\n    margin-left: 100px;\r\n}\r\n</style>\r\n"
  },
  {
    "path": "src/views/pages/editor.vue",
    "content": "<template>\r\n    <div class=\"container\">\r\n        <div class=\"plugins-tips\">\r\n            wangEditor：轻量级 web 富文本编辑器，配置方便，使用简单。 访问地址：\r\n            <a href=\"https://www.wangeditor.com/doc/\" target=\"_blank\">wangEditor</a>\r\n        </div>\r\n        <div style=\"border: 1px solid #ccc; margin-bottom: 10px\">\r\n            <Toolbar style=\"border-bottom: 1px solid #ccc\" :editor=\"editorRef\" :defaultConfig=\"toolbarConfig\" />\r\n            <Editor\r\n                style=\"height: 500px; overflow-y: hidden\"\r\n                v-model=\"valueHtml\"\r\n                :defaultConfig=\"editorConfig\"\r\n                @onCreated=\"handleCreated\"\r\n            />\r\n        </div>\r\n        <el-button type=\"primary\" @click=\"syncHTML\">提交</el-button>\r\n    </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\" name=\"editor\">\r\nimport '@wangeditor/editor/dist/css/style.css'; // 引入 css\r\nimport { onBeforeUnmount, ref, reactive, shallowRef, onMounted } from 'vue';\r\nimport { Editor, Toolbar } from '@wangeditor/editor-for-vue';\r\n// 编辑器实例，必须用 shallowRef\r\nconst editorRef = shallowRef();\r\n\r\n// 内容 HTML\r\nconst valueHtml = ref('<p>hello</p>');\r\n\r\n// 模拟 ajax 异步获取内容\r\nonMounted(() => {\r\n    setTimeout(() => {\r\n        valueHtml.value = '<p>模拟 Ajax 异步设置内容</p>';\r\n    }, 1500);\r\n});\r\n\r\nconst toolbarConfig = {};\r\nconst editorConfig = { placeholder: '请输入内容...' };\r\n\r\n// 组件销毁时，也及时销毁编辑器\r\nonBeforeUnmount(() => {\r\n    const editor = editorRef.value;\r\n    if (editor == null) return;\r\n    editor.destroy();\r\n});\r\n\r\nconst handleCreated = (editor: any) => {\r\n    editorRef.value = editor; // 记录 editor 实例，重要！\r\n};\r\nconst syncHTML = () => {\r\n    console.log(valueHtml.value);\r\n};\r\n</script>\r\n\r\n<style></style>\r\n"
  },
  {
    "path": "src/views/pages/icon.vue",
    "content": "<template>\r\n\r\n\t<el-tabs type=\"border-card\">\r\n\t\t<el-tab-pane label=\"自定义图标\">\r\n\t\t\t<h2>使用方法</h2>\r\n\t\t\t<p style=\"line-height: 50px\">\r\n\t\t\t\t直接通过设置类名为 el-icon-lx-iconName 来使用即可。例如：（共{{ iconList.length }}个图标）\r\n\t\t\t</p>\r\n\t\t\t<p class=\"example-p\">\r\n\t\t\t\t<i class=\"el-icon-lx-redpacket_fill\" style=\"font-size: 30px; color: #ff5900\"></i>\r\n\t\t\t\t<span>&lt;i class=&quot;el-icon-lx-redpacket_fill&quot;&gt;&lt;/i&gt;</span>\r\n\t\t\t</p>\r\n\t\t\t<p class=\"example-p\">\r\n\t\t\t\t<i class=\"el-icon-lx-weibo\" style=\"font-size: 30px; color: #fd5656\"></i>\r\n\t\t\t\t<span>&lt;i class=&quot;el-icon-lx-weibo&quot;&gt;&lt;/i&gt;</span>\r\n\t\t\t</p>\r\n\t\t\t<p class=\"example-p\">\r\n\t\t\t\t<i class=\"el-icon-lx-emojifill\" style=\"font-size: 30px; color: #ffc300\"></i>\r\n\t\t\t\t<span>&lt;i class=&quot;el-icon-lx-emojifill&quot;&gt;&lt;/i&gt;</span>\r\n\t\t\t</p>\r\n\t\t\t<br />\r\n\t\t\t<h2>图标</h2>\r\n\t\t\t<div class=\"search-box\">\r\n\t\t\t\t<el-input class=\"search\" size=\"large\" v-model=\"keyword\" clearable placeholder=\"请输入图标名称\"></el-input>\r\n\t\t\t</div>\r\n\t\t\t<ul>\r\n\t\t\t\t<li class=\"icon-li\" v-for=\"(item, index) in list\" :key=\"index\">\r\n\t\t\t\t\t<div class=\"icon-li-content\">\r\n\t\t\t\t\t\t<i :class=\"`el-icon-lx-${item}`\"></i>\r\n\t\t\t\t\t\t<span>{{ item }}</span>\r\n\t\t\t\t\t</div>\r\n\t\t\t\t</li>\r\n\t\t\t</ul>\r\n\t\t</el-tab-pane>\r\n\t\t<el-tab-pane label=\"Element图标\">\r\n\t\t\t<el-link type=\"primary\" href=\"https://element-plus.org/zh-CN/component/icon.html#icon-collection\"\r\n\t\t\t\ttarget=\"_blank\">前往官方文档查看</el-link>\r\n\t\t</el-tab-pane>\r\n\t</el-tabs>\r\n</template>\r\n\r\n<script setup lang=\"ts\" name=\"icon\">\r\nimport { computed, ref } from 'vue';\r\n\r\nconst iconList: Array<string> = [\r\n\t'attentionforbid',\r\n\t'attentionforbidfill',\r\n\t'attention',\r\n\t'attentionfill',\r\n\t'tag',\r\n\t'tagfill',\r\n\t'people',\r\n\t'peoplefill',\r\n\t'notice',\r\n\t'noticefill',\r\n\t'mobile',\r\n\t'mobilefill',\r\n\t'voice',\r\n\t'voicefill',\r\n\t'unlock',\r\n\t'lock',\r\n\t'home',\r\n\t'homefill',\r\n\t'delete',\r\n\t'deletefill',\r\n\t'notification',\r\n\t'notificationfill',\r\n\t'notificationforbidfill',\r\n\t'like',\r\n\t'likefill',\r\n\t'comment',\r\n\t'commentfill',\r\n\t'camera',\r\n\t'camerafill',\r\n\t'warn',\r\n\t'warnfill',\r\n\t'time',\r\n\t'timefill',\r\n\t'location',\r\n\t'locationfill',\r\n\t'favor',\r\n\t'favorfill',\r\n\t'skin',\r\n\t'skinfill',\r\n\t'news',\r\n\t'newsfill',\r\n\t'record',\r\n\t'recordfill',\r\n\t'emoji',\r\n\t'emojifill',\r\n\t'message',\r\n\t'messagefill',\r\n\t'goods',\r\n\t'goodsfill',\r\n\t'crown',\r\n\t'crownfill',\r\n\t'move',\r\n\t'add',\r\n\t'hot',\r\n\t'hotfill',\r\n\t'service',\r\n\t'servicefill',\r\n\t'present',\r\n\t'presentfill',\r\n\t'pic',\r\n\t'picfill',\r\n\t'rank',\r\n\t'rankfill',\r\n\t'male',\r\n\t'female',\r\n\t'down',\r\n\t'top',\r\n\t'recharge',\r\n\t'rechargefill',\r\n\t'forward',\r\n\t'forwardfill',\r\n\t'info',\r\n\t'infofill',\r\n\t'redpacket',\r\n\t'redpacket_fill',\r\n\t'roundadd',\r\n\t'roundaddfill',\r\n\t'friendadd',\r\n\t'friendaddfill',\r\n\t'cart',\r\n\t'cartfill',\r\n\t'more',\r\n\t'moreandroid',\r\n\t'back',\r\n\t'right',\r\n\t'shop',\r\n\t'shopfill',\r\n\t'question',\r\n\t'questionfill',\r\n\t'roundclose',\r\n\t'roundclosefill',\r\n\t'roundcheck',\r\n\t'roundcheckfill',\r\n\t'global',\r\n\t'mail',\r\n\t'punch',\r\n\t'exit',\r\n\t'upload',\r\n\t'read',\r\n\t'file',\r\n\t'link',\r\n\t'full',\r\n\t'group',\r\n\t'friend',\r\n\t'profile',\r\n\t'addressbook',\r\n\t'calendar',\r\n\t'text',\r\n\t'copy',\r\n\t'share',\r\n\t'wifi',\r\n\t'vipcard',\r\n\t'weibo',\r\n\t'remind',\r\n\t'refresh',\r\n\t'filter',\r\n\t'settings',\r\n\t'scan',\r\n\t'qrcode',\r\n\t'cascades',\r\n\t'apps',\r\n\t'sort',\r\n\t'searchlist',\r\n\t'search',\r\n\t'edit',\r\n\t'apple-line',\r\n\t'baidu-fill',\r\n\t'amazon-fill',\r\n\t'netease-cloud-music-fill',\r\n\t'qq-line',\r\n\t'wechat-fill',\r\n\t'alipay-fill',\r\n\t'android-fill',\r\n\t'android-line',\r\n\t'whatsapp-line',\r\n\t'whatsapp-fill',\r\n\t'bilibili-fill',\r\n\t'chrome-fill',\r\n\t'dingding-fill',\r\n\t'dingding-line',\r\n\t'apple-fill',\r\n\t'github-fill',\r\n\t'qq-fill',\r\n\t'wechat-pay-fill',\r\n\t'windows-line',\r\n\t'windows-fill',\r\n\t'youtube-line',\r\n\t'youtube-fill',\r\n\t'wechat-pay-line',\r\n\t'zhihu-line'\r\n];\r\n\r\nconst keyword = ref('');\r\nconst list = computed(() => {\r\n\treturn iconList.filter(item => {\r\n\t\treturn item.indexOf(keyword.value) !== -1;\r\n\t});\r\n});\r\n</script>\r\n\r\n<style scoped>\r\n.example-p {\r\n\theight: 45px;\r\n\tdisplay: flex;\r\n\talign-items: center;\r\n}\r\n\r\n.search-box {\r\n\ttext-align: center;\r\n\tmargin-top: 10px;\r\n}\r\n\r\n.search {\r\n\twidth: 300px;\r\n}\r\n\r\nul,\r\nli {\r\n\tlist-style: none;\r\n}\r\n\r\n.icon-li {\r\n\tdisplay: inline-block;\r\n\tpadding: 10px;\r\n\twidth: 120px;\r\n\theight: 120px;\r\n}\r\n\r\n.icon-li-content {\r\n\tdisplay: flex;\r\n\theight: 100%;\r\n\tflex-direction: column;\r\n\talign-items: center;\r\n\tjustify-content: center;\r\n\tcursor: pointer;\r\n}\r\n\r\n.icon-li-content i {\r\n\tfont-size: 36px;\r\n\tcolor: #606266;\r\n}\r\n\r\n.icon-li-content span {\r\n\tmargin-top: 10px;\r\n\tcolor: #787878;\r\n}\r\n\r\n.iframe {\r\n\twidth: 100%;\r\n\theight: 700px;\r\n}\r\n</style>\r\n"
  },
  {
    "path": "src/views/pages/login.vue",
    "content": "<template>\r\n    <div class=\"login-bg\">\r\n        <div class=\"login-container\">\r\n            <div class=\"login-header\">\r\n                <img class=\"logo mr10\" src=\"../../assets/img/logo.svg\" alt=\"\" />\r\n                <div class=\"login-title\">后台管理系统</div>\r\n            </div>\r\n            <el-form :model=\"param\" :rules=\"rules\" ref=\"login\" size=\"large\">\r\n                <el-form-item prop=\"username\">\r\n                    <el-input v-model=\"param.username\" placeholder=\"用户名\">\r\n                        <template #prepend>\r\n                            <el-icon>\r\n                                <User />\r\n                            </el-icon>\r\n                        </template>\r\n                    </el-input>\r\n                </el-form-item>\r\n                <el-form-item prop=\"password\">\r\n                    <el-input\r\n                        type=\"password\"\r\n                        placeholder=\"密码\"\r\n                        v-model=\"param.password\"\r\n                        @keyup.enter=\"submitForm(login)\"\r\n                    >\r\n                        <template #prepend>\r\n                            <el-icon>\r\n                                <Lock />\r\n                            </el-icon>\r\n                        </template>\r\n                    </el-input>\r\n                </el-form-item>\r\n                <div class=\"pwd-tips\">\r\n                    <el-checkbox class=\"pwd-checkbox\" v-model=\"checked\" label=\"记住密码\" />\r\n                    <el-link type=\"primary\" @click=\"$router.push('/reset-pwd')\">忘记密码</el-link>\r\n                </div>\r\n                <el-button class=\"login-btn\" type=\"primary\" size=\"large\" @click=\"submitForm(login)\">登录</el-button>\r\n                <p class=\"login-tips\">Tips : 用户名和密码随便填。</p>\r\n                <p class=\"login-text\">\r\n                    没有账号？<el-link type=\"primary\" @click=\"$router.push('/register')\">立即注册</el-link>\r\n                </p>\r\n            </el-form>\r\n        </div>\r\n    </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, reactive } from 'vue';\r\nimport { useTabsStore } from '@/store/tabs';\r\nimport { usePermissStore } from '@/store/permiss';\r\nimport { useRouter } from 'vue-router';\r\nimport { ElMessage } from 'element-plus';\r\nimport type { FormInstance, FormRules } from 'element-plus';\r\n\r\ninterface LoginInfo {\r\n    username: string;\r\n    password: string;\r\n}\r\n\r\nconst lgStr = localStorage.getItem('login-param');\r\nconst defParam = lgStr ? JSON.parse(lgStr) : null;\r\nconst checked = ref(lgStr ? true : false);\r\n\r\nconst router = useRouter();\r\nconst param = reactive<LoginInfo>({\r\n    username: defParam ? defParam.username : '',\r\n    password: defParam ? defParam.password : '',\r\n});\r\n\r\nconst rules: FormRules = {\r\n    username: [\r\n        {\r\n            required: true,\r\n            message: '请输入用户名',\r\n            trigger: 'blur',\r\n        },\r\n    ],\r\n    password: [{ required: true, message: '请输入密码', trigger: 'blur' }],\r\n};\r\nconst permiss = usePermissStore();\r\nconst login = ref<FormInstance>();\r\nconst submitForm = (formEl: FormInstance | undefined) => {\r\n    if (!formEl) return;\r\n    formEl.validate((valid: boolean) => {\r\n        if (valid) {\r\n            ElMessage.success('登录成功');\r\n            localStorage.setItem('vuems_name', param.username);\r\n            const keys = permiss.defaultList[param.username == 'admin' ? 'admin' : 'user'];\r\n            permiss.handleSet(keys);\r\n            router.push('/');\r\n            if (checked.value) {\r\n                localStorage.setItem('login-param', JSON.stringify(param));\r\n            } else {\r\n                localStorage.removeItem('login-param');\r\n            }\r\n        } else {\r\n            ElMessage.error('登录失败');\r\n            return false;\r\n        }\r\n    });\r\n};\r\n\r\nconst tabs = useTabsStore();\r\ntabs.clearTabs();\r\n</script>\r\n\r\n<style scoped>\r\n.login-bg {\r\n    display: flex;\r\n    align-items: center;\r\n    justify-content: center;\r\n    width: 100%;\r\n    height: 100vh;\r\n    background: url(../../assets/img/login-bg.jpg) center/cover no-repeat;\r\n}\r\n\r\n.login-header {\r\n    display: flex;\r\n    align-items: center;\r\n    justify-content: center;\r\n    margin-bottom: 40px;\r\n}\r\n\r\n.logo {\r\n    width: 35px;\r\n}\r\n\r\n.login-title {\r\n    font-size: 22px;\r\n    color: #333;\r\n    font-weight: bold;\r\n}\r\n\r\n.login-container {\r\n    width: 450px;\r\n    border-radius: 5px;\r\n    background: #fff;\r\n    padding: 40px 50px 50px;\r\n    box-sizing: border-box;\r\n}\r\n\r\n.pwd-tips {\r\n    display: flex;\r\n    justify-content: space-between;\r\n    align-items: center;\r\n    font-size: 14px;\r\n    margin: -10px 0 10px;\r\n    color: #787878;\r\n}\r\n\r\n.pwd-checkbox {\r\n    height: auto;\r\n}\r\n\r\n.login-btn {\r\n    display: block;\r\n    width: 100%;\r\n}\r\n\r\n.login-tips {\r\n    font-size: 12px;\r\n    color: #999;\r\n}\r\n\r\n.login-text {\r\n    display: flex;\r\n    align-items: center;\r\n    margin-top: 20px;\r\n    font-size: 14px;\r\n    color: #787878;\r\n}\r\n</style>\r\n"
  },
  {
    "path": "src/views/pages/markdown.vue",
    "content": "<template>\r\n\t<div class=\"container\">\r\n\t\t<div class=\"plugins-tips\">\r\n\t\t\tmd-editor-v3：vue3版本的 markdown 编辑器，配置丰富，请详看文档。 访问地址：\r\n\t\t\t<a href=\"https://imzbf.github.io/md-editor-v3/index\" target=\"_blank\">md-editor-v3</a>\r\n\t\t</div>\r\n\t\t<md-editor class=\"mgb20\" v-model=\"text\" @on-upload-img=\"onUploadImg\" />\r\n\t\t<el-button type=\"primary\">提交</el-button>\r\n\t</div>\r\n</template>\r\n\r\n<script setup lang=\"ts\" name=\"md\">\r\nimport { ref } from 'vue';\r\nimport MdEditor from 'md-editor-v3';\r\nimport 'md-editor-v3/lib/style.css';\r\n\r\nconst text = ref('Hello Editor!');\r\nconst onUploadImg = (files: any) => {\r\n\tconsole.log(files);\r\n};\r\n</script>\r\n"
  },
  {
    "path": "src/views/pages/register.vue",
    "content": "<template>\r\n    <div class=\"login-bg\">\r\n        <div class=\"login-container\">\r\n            <div class=\"login-header\">\r\n                <img class=\"logo mr10\" src=\"../../assets/img/logo.svg\" alt=\"\" />\r\n                <div class=\"login-title\">后台管理系统</div>\r\n            </div>\r\n            <el-form :model=\"param\" :rules=\"rules\" ref=\"register\" size=\"large\">\r\n                <el-form-item prop=\"username\">\r\n                    <el-input v-model=\"param.username\" placeholder=\"用户名\">\r\n                        <template #prepend>\r\n                            <el-icon>\r\n                                <User />\r\n                            </el-icon>\r\n                        </template>\r\n                    </el-input>\r\n                </el-form-item>\r\n                <el-form-item prop=\"email\">\r\n                    <el-input v-model=\"param.email\" placeholder=\"邮箱\">\r\n                        <template #prepend>\r\n                            <el-icon>\r\n                                <Message />\r\n                            </el-icon>\r\n                        </template>\r\n                    </el-input>\r\n                </el-form-item>\r\n                <el-form-item prop=\"password\">\r\n                    <el-input\r\n                        type=\"password\"\r\n                        placeholder=\"密码\"\r\n                        v-model=\"param.password\"\r\n                        @keyup.enter=\"submitForm(register)\"\r\n                    >\r\n                        <template #prepend>\r\n                            <el-icon>\r\n                                <Lock />\r\n                            </el-icon>\r\n                        </template>\r\n                    </el-input>\r\n                </el-form-item>\r\n                <el-button class=\"login-btn\" type=\"primary\" size=\"large\" @click=\"submitForm(register)\">注册</el-button>\r\n                <p class=\"login-text\">\r\n                    已有账号，<el-link type=\"primary\" @click=\"$router.push('/login')\">立即登录</el-link>\r\n                </p>\r\n            </el-form>\r\n        </div>\r\n    </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, reactive } from 'vue';\r\nimport { useRouter } from 'vue-router';\r\nimport { ElMessage, type FormInstance, type FormRules } from 'element-plus';\r\nimport { Register } from '@/types/user';\r\n\r\nconst router = useRouter();\r\nconst param = reactive<Register>({\r\n    username: '',\r\n    password: '',\r\n    email: '',\r\n});\r\n\r\nconst rules: FormRules = {\r\n    username: [\r\n        {\r\n            required: true,\r\n            message: '请输入用户名',\r\n            trigger: 'blur',\r\n        },\r\n    ],\r\n    password: [{ required: true, message: '请输入密码', trigger: 'blur' }],\r\n    email: [{ required: true, message: '请输入邮箱', trigger: 'blur' }],\r\n};\r\nconst register = ref<FormInstance>();\r\nconst submitForm = (formEl: FormInstance | undefined) => {\r\n    if (!formEl) return;\r\n    formEl.validate((valid: boolean) => {\r\n        if (valid) {\r\n            ElMessage.success('注册成功，请登录');\r\n            router.push('/login');\r\n        } else {\r\n            return false;\r\n        }\r\n    });\r\n};\r\n</script>\r\n\r\n<style scoped>\r\n.login-bg {\r\n    display: flex;\r\n    align-items: center;\r\n    justify-content: center;\r\n    width: 100%;\r\n    height: 100vh;\r\n    background: url(../../assets/img/login-bg.jpg) center/cover no-repeat;\r\n}\r\n\r\n.login-header {\r\n    display: flex;\r\n    align-items: center;\r\n    justify-content: center;\r\n    margin-bottom: 40px;\r\n}\r\n\r\n.logo {\r\n    width: 35px;\r\n}\r\n\r\n.login-title {\r\n    font-size: 22px;\r\n    color: #333;\r\n    font-weight: bold;\r\n}\r\n\r\n.login-container {\r\n    width: 450px;\r\n    border-radius: 5px;\r\n    background: #fff;\r\n    padding: 40px 50px 50px;\r\n    box-sizing: border-box;\r\n}\r\n\r\n.login-btn {\r\n    display: block;\r\n    width: 100%;\r\n}\r\n\r\n.login-text {\r\n    display: flex;\r\n    align-items: center;\r\n    margin-top: 20px;\r\n    font-size: 14px;\r\n    color: #787878;\r\n}\r\n</style>\r\n"
  },
  {
    "path": "src/views/pages/reset-pwd.vue",
    "content": "<template>\r\n    <div class=\"login-bg\">\r\n        <div class=\"login-container\">\r\n            <div class=\"reset-title\">重置密码</div>\r\n            <p class=\"reset-text\">输入你的邮箱，我们将发送重置密码邮件</p>\r\n            <el-form :model=\"param\" :rules=\"rules\" ref=\"register\" size=\"large\">\r\n                <el-form-item prop=\"email\">\r\n                    <el-input v-model=\"param.email\" placeholder=\"邮箱\">\r\n                        <template #prepend>\r\n                            <el-icon>\r\n                                <Message />\r\n                            </el-icon>\r\n                        </template>\r\n                    </el-input>\r\n                </el-form-item>\r\n                <el-button class=\"login-btn\" type=\"primary\" size=\"large\" @click=\"submitForm(register)\"\r\n                    >发送邮件</el-button\r\n                >\r\n                <p class=\"login-text\"><el-link type=\"primary\" @click=\"$router.push('/login')\">返回登录</el-link></p>\r\n            </el-form>\r\n        </div>\r\n    </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref } from 'vue';\r\nimport { ElMessage, type FormInstance, type FormRules } from 'element-plus';\r\n\r\nconst param = ref({\r\n    email: '',\r\n});\r\n\r\nconst rules: FormRules = {\r\n    email: [\r\n        { required: true, message: '请输入邮箱', trigger: 'blur' },\r\n        {\r\n            pattern: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$/,\r\n            message: '请输入正确的邮箱格式',\r\n            trigger: 'blur',\r\n        },\r\n    ],\r\n};\r\nconst register = ref<FormInstance>();\r\nconst submitForm = (formEl: FormInstance | undefined) => {\r\n    if (!formEl) return;\r\n    formEl.validate((valid: boolean) => {\r\n        if (valid) {\r\n            ElMessage.success('邮件已发送，请注意查收');\r\n        } else {\r\n            return false;\r\n        }\r\n    });\r\n};\r\n</script>\r\n\r\n<style scoped>\r\n.login-bg {\r\n    display: flex;\r\n    align-items: center;\r\n    justify-content: center;\r\n    width: 100%;\r\n    height: 100vh;\r\n    background: url(../../assets/img/login-bg.jpg) center/cover no-repeat;\r\n}\r\n\r\n.reset-title {\r\n    text-align: center;\r\n    font-size: 22px;\r\n    color: #333;\r\n    font-weight: bold;\r\n    margin-bottom: 10px;\r\n}\r\n\r\n.reset-text {\r\n    text-align: center;\r\n    font-size: 14px;\r\n    color: #787878;\r\n    margin-bottom: 40px;\r\n}\r\n\r\n.login-container {\r\n    width: 450px;\r\n    border-radius: 5px;\r\n    background: #fff;\r\n    padding: 40px 50px 50px;\r\n    box-sizing: border-box;\r\n}\r\n\r\n.login-btn {\r\n    display: block;\r\n    width: 100%;\r\n}\r\n\r\n.login-text {\r\n    display: flex;\r\n    align-items: center;\r\n    justify-content: center;\r\n    margin-top: 20px;\r\n    font-size: 14px;\r\n    color: #333;\r\n}\r\n</style>\r\n"
  },
  {
    "path": "src/views/pages/theme.vue",
    "content": "<template>\r\n    <div>\r\n        <el-card class=\"mgb20\" shadow=\"hover\">\r\n            <template #header>\r\n                <div class=\"content-title\">系统主题</div>\r\n            </template>\r\n            <div class=\"theme-list mgb20\">\r\n                <div class=\"theme-item\" @click=\"setSystemTheme(item)\" v-for=\"item in system\"\r\n                    :style=\"{ backgroundColor: item.color, color: '#fff' }\">{{ item.name }}\r\n                </div>\r\n            </div>\r\n            <div class=\"flex-center\">\r\n                <el-button @click=\"resetSystemTheme\">重置主题</el-button>\r\n            </div>\r\n        </el-card>\r\n        <el-card class=\"mgb20\" shadow=\"hover\">\r\n            <template #header>\r\n                <div class=\"content-title\">Element-Plus主题</div>\r\n            </template>\r\n            <div class=\"theme-list mgb20\">\r\n                <div class=\"theme-item\" v-for=\"theme in themes\">\r\n                    <el-button :type=\"theme.name\">{{ theme.name }}</el-button>\r\n                    <div class=\"theme-color\">{{ theme.color }}</div>\r\n                    <el-color-picker v-model=\"color[theme.name]\" @change=\"changeColor(theme.name)\" />\r\n                </div>\r\n            </div>\r\n            <div class=\"flex-center\">\r\n                <el-button @click=\"resetTheme\">重置主题</el-button>\r\n            </div>\r\n        </el-card>\r\n\r\n        <el-row :gutter=\"50\">\r\n            <el-col :span=\"12\">\r\n                <el-card class=\"mgb20\" shadow=\"hover\">\r\n                    <template #header>\r\n                        <div class=\"content-title\">头部主题</div>\r\n                    </template>\r\n                    <div class=\"theme-list mgb20\">\r\n                        <div class=\"theme-item\">\r\n                            <el-button :color=\"color.headerBgColor\">背景颜色</el-button>\r\n                            <div class=\"theme-color\">{{ color.headerBgColor }}</div>\r\n                            <el-color-picker v-model=\"color.headerBgColor\"\r\n                                @change=\"themeStore.setHeaderBgColor(color.headerBgColor)\" />\r\n                        </div>\r\n                        <div class=\"theme-item\">\r\n                            <el-button :color=\"color.headerTextColor\">文字颜色</el-button>\r\n                            <div class=\"theme-color\">{{ color.headerTextColor }}</div>\r\n                            <el-color-picker v-model=\"color.headerTextColor\"\r\n                                @change=\"themeStore.setHeaderTextColor(color.headerTextColor)\" />\r\n                        </div>\r\n                    </div>\r\n                    <div class=\"flex-center\">\r\n                        <el-button @click=\"resetHeader\">重置主题</el-button>\r\n                    </div>\r\n                </el-card>\r\n            </el-col>\r\n\r\n            <el-col :span=\"12\">\r\n                <el-card class=\"mgb20\" shadow=\"hover\">\r\n                    <template #header>\r\n                        <div class=\"content-title\">菜单主题</div>\r\n                    </template>\r\n                    <div class=\"theme-list mgb20\">\r\n                        <div class=\"theme-item\">\r\n                            <el-button :color=\"sidebar.bgColor\">背景颜色</el-button>\r\n                            <div class=\"theme-color\">{{ sidebar.bgColor }}</div>\r\n                            <el-color-picker v-model=\"sidebarColor.bgColor\"\r\n                                @change=\"sidebar.setBgColor(sidebarColor.bgColor)\" />\r\n                        </div>\r\n                        <div class=\"theme-item\">\r\n                            <el-button :color=\"sidebar.textColor\">文字颜色</el-button>\r\n                            <div class=\"theme-color\">{{ sidebar.textColor }}</div>\r\n                            <el-color-picker v-model=\"sidebarColor.textColor\"\r\n                                @change=\"sidebar.setTextColor(sidebarColor.textColor)\" />\r\n                        </div>\r\n                    </div>\r\n                    <div class=\"flex-center\">\r\n                        <el-button @click=\"resetSidebar\">重置主题</el-button>\r\n                    </div>\r\n                </el-card>\r\n            </el-col>\r\n        </el-row>\r\n\r\n    </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { useSidebarStore } from '@/store/sidebar';\r\nimport { useThemeStore } from '@/store/theme'\r\nimport { reactive } from 'vue';\r\nconst themeStore = useThemeStore();\r\nconst sidebar = useSidebarStore();\r\n\r\nconst color = reactive({\r\n    primary: localStorage.getItem('theme-primary') || '#409eff',\r\n    success: localStorage.getItem('theme-success') || '#67c23a',\r\n    warning: localStorage.getItem('theme-warning') || '#e6a23c',\r\n    danger: localStorage.getItem('theme-danger') || '#f56c6c',\r\n    info: localStorage.getItem('theme-info') || '#909399',\r\n    headerBgColor: themeStore.headerBgColor,\r\n    headerTextColor: themeStore.headerTextColor,\r\n})\r\nconst sidebarColor = reactive({\r\n    bgColor: sidebar.bgColor,\r\n    textColor: sidebar.textColor\r\n})\r\nconst themes = [\r\n    {\r\n        name: 'primary',\r\n        color: themeStore.primary || color.primary\r\n    },\r\n    {\r\n        name: 'success',\r\n        color: themeStore.success || color.success\r\n    },\r\n    {\r\n        name: 'warning',\r\n        color: themeStore.warning || color.warning\r\n    },\r\n    {\r\n        name: 'danger',\r\n        color: themeStore.danger || color.danger\r\n    },\r\n    {\r\n        name: 'info',\r\n        color: themeStore.info || color.info\r\n    }\r\n]\r\n\r\nconst changeColor = (name: string) => {\r\n    themeStore.setPropertyColor(color[name], name)\r\n}\r\n\r\nconst resetTheme = () => {\r\n    themeStore.resetTheme()\r\n}\r\nconst resetHeader = () => {\r\n    localStorage.removeItem('header-bg-color')\r\n    localStorage.removeItem('header-text-color')\r\n    location.reload()\r\n}\r\nconst resetSidebar = () => {\r\n    localStorage.removeItem('sidebar-bg-color')\r\n    localStorage.removeItem('sidebar-text-color')\r\n    location.reload()\r\n}\r\nconst system = [\r\n    {\r\n        name: '默认',\r\n        color: '#242f42'\r\n    },\r\n    {\r\n        name: '健康',\r\n        color: '#1ABC9C'\r\n    },\r\n    {\r\n        name: '优雅',\r\n        color: '#722ed1'\r\n    },\r\n    {\r\n        name: '热情',\r\n        color: '#f44336'\r\n    },\r\n    {\r\n        name: '宁静',\r\n        color: '#00bcd4'\r\n    }\r\n]\r\nconst setSystemTheme = (data: any) => {\r\n    if (data.name === '默认') {\r\n        resetSystemTheme()\r\n    } else {\r\n        themeStore.setHeaderBgColor(data.color)\r\n        themeStore.setHeaderTextColor('#fff')\r\n        sidebar.setBgColor('#fff')\r\n        sidebar.setTextColor('#5b6e88')\r\n        themeStore.setPropertyColor(data.color, 'primary')\r\n    }\r\n}\r\nconst resetSystemTheme = () => {\r\n    resetTheme();\r\n    resetHeader();\r\n    resetSidebar();\r\n}\r\n</script>\r\n\r\n<style scoped>\r\n.theme-list {\r\n    display: flex;\r\n    justify-content: center;\r\n}\r\n\r\n.theme-item {\r\n    margin-right: 20px;\r\n    padding: 30px;\r\n    border: 1px solid #dcdfe6;\r\n    border-radius: 4px;\r\n    text-align: center;\r\n}\r\n\r\n.theme-color {\r\n    color: #787878;\r\n    margin: 20px 0;\r\n}\r\n</style>\r\n"
  },
  {
    "path": "src/views/pages/ucenter.vue",
    "content": "<template>\r\n    <div>\r\n        <div class=\"user-container\">\r\n            <el-card class=\"user-profile\" shadow=\"hover\" :body-style=\"{ padding: '0px' }\">\r\n                <div class=\"user-profile-bg\"></div>\r\n                <div class=\"user-avatar-wrap\">\r\n                    <el-avatar class=\"user-avatar\" :size=\"120\" :src=\"avatarImg\" />\r\n                </div>\r\n                <div class=\"user-info\">\r\n                    <div class=\"info-name\">{{ name }}</div>\r\n                    <div class=\"info-desc\">\r\n                        <span>@lin-xin</span>\r\n                        <el-divider direction=\"vertical\" />\r\n                        <el-link href=\"https://lin-xin.gitee.io\" target=\"_blank\">lin-xin.gitee.io</el-link>\r\n                    </div>\r\n                    <div class=\"info-desc\">FE Developer</div>\r\n                    <div class=\"info-icon\">\r\n                        <a href=\"https://github.com/lin-xin\" target=\"_blank\"> <i class=\"el-icon-lx-github-fill\"></i></a>\r\n                        <i class=\"el-icon-lx-qq-fill\"></i>\r\n                        <i class=\"el-icon-lx-facebook-fill\"></i>\r\n                        <i class=\"el-icon-lx-twitter-fill\"></i>\r\n                    </div>\r\n                </div>\r\n                <div class=\"user-footer\">\r\n                    <div class=\"user-footer-item\">\r\n                        <el-statistic title=\"Follower\" :value=\"1800\" />\r\n                    </div>\r\n                    <div class=\"user-footer-item\">\r\n                        <el-statistic title=\"Following\" :value=\"666\" />\r\n                    </div>\r\n                    <div class=\"user-footer-item\">\r\n                        <el-statistic title=\"Total Post\" :value=\"888\" />\r\n                    </div>\r\n                </div>\r\n            </el-card>\r\n            <el-card\r\n                class=\"user-content\"\r\n                shadow=\"hover\"\r\n                :body-style=\"{ padding: '20px 50px', height: '100%', boxSizing: 'border-box' }\"\r\n            >\r\n                <el-tabs tab-position=\"left\" v-model=\"activeName\">\r\n                    <el-tab-pane name=\"label1\" label=\"消息通知\" class=\"user-tabpane\">\r\n                        <TabsComp />\r\n                    </el-tab-pane>\r\n                    <el-tab-pane name=\"label2\" label=\"我的头像\" class=\"user-tabpane\">\r\n                        <div class=\"crop-wrap\" v-if=\"activeName === 'label2'\">\r\n                            <vueCropper\r\n                                ref=\"cropper\"\r\n                                :img=\"imgSrc\"\r\n                                :autoCrop=\"true\"\r\n                                :centerBox=\"true\"\r\n                                :full=\"true\"\r\n                                mode=\"contain\"\r\n                            >\r\n                            </vueCropper>\r\n                        </div>\r\n                        <el-button class=\"crop-demo-btn\" type=\"primary\"\r\n                            >选择图片\r\n                            <input class=\"crop-input\" type=\"file\" name=\"image\" accept=\"image/*\" @change=\"setImage\" />\r\n                        </el-button>\r\n                        <el-button type=\"success\" @click=\"saveAvatar\">上传并保存</el-button>\r\n                    </el-tab-pane>\r\n                    <el-tab-pane name=\"label3\" label=\"修改密码\" class=\"user-tabpane\">\r\n                        <el-form class=\"w500\" label-position=\"top\">\r\n                            <el-form-item label=\"旧密码：\">\r\n                                <el-input type=\"password\" v-model=\"form.old\"></el-input>\r\n                            </el-form-item>\r\n                            <el-form-item label=\"新密码：\">\r\n                                <el-input type=\"password\" v-model=\"form.new\"></el-input>\r\n                            </el-form-item>\r\n                            <el-form-item label=\"确认新密码：\">\r\n                                <el-input type=\"password\" v-model=\"form.new1\"></el-input>\r\n                            </el-form-item>\r\n                            <el-form-item>\r\n                                <el-button type=\"primary\" @click=\"onSubmit\">保存</el-button>\r\n                            </el-form-item>\r\n                        </el-form>\r\n                    </el-tab-pane>\r\n                    <el-tab-pane name=\"label4\" label=\"赞赏作者\" class=\"user-tabpane\">\r\n                        <div class=\"plugins-tips\">\r\n                            如果该框架\r\n                            <el-link href=\"https://github.com/lin-xin/vue-manage-system\" target=\"_blank\"\r\n                                >vue-manage-system</el-link\r\n                            >\r\n                            对你有帮助，那就请作者喝杯饮料吧！<el-icon>\r\n                                <ColdDrink />\r\n                            </el-icon>\r\n                            加微信号 linxin_20 探讨问题。\r\n                        </div>\r\n                        <div>\r\n                            <img src=\"https://lin-xin.gitee.io/images/weixin.jpg\" />\r\n                        </div>\r\n                    </el-tab-pane>\r\n                </el-tabs>\r\n            </el-card>\r\n        </div>\r\n    </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\" name=\"ucenter\">\r\nimport { reactive, ref } from 'vue';\r\nimport { VueCropper } from 'vue-cropper';\r\nimport 'vue-cropper/dist/index.css';\r\nimport avatar from '@/assets/img/img.jpg';\r\nimport TabsComp from '../element/tabs.vue';\r\n\r\nconst name = localStorage.getItem('vuems_name');\r\nconst form = reactive({\r\n    new1: '',\r\n    new: '',\r\n    old: '',\r\n});\r\nconst onSubmit = () => {};\r\n\r\nconst activeName = ref('label1');\r\n\r\nconst avatarImg = ref(avatar);\r\nconst imgSrc = ref(avatar);\r\nconst cropImg = ref('');\r\nconst cropper: any = ref();\r\n\r\nconst setImage = (e: any) => {\r\n    const file = e.target.files[0];\r\n    if (!file.type.includes('image/')) {\r\n        return;\r\n    }\r\n    const reader = new FileReader();\r\n    reader.onload = (event: any) => {\r\n        imgSrc.value = event.target.result;\r\n        cropper.value && cropper.value.replace(event.target.result);\r\n    };\r\n    reader.readAsDataURL(file);\r\n};\r\n\r\nconst cropImage = () => {\r\n    cropImg.value = cropper.value?.getCroppedCanvas().toDataURL();\r\n};\r\n\r\nconst saveAvatar = () => {\r\n    avatarImg.value = cropImg.value;\r\n};\r\n</script>\r\n\r\n<style scoped>\r\n.user-container {\r\n    display: flex;\r\n}\r\n\r\n.user-profile {\r\n    position: relative;\r\n}\r\n\r\n.user-profile-bg {\r\n    width: 100%;\r\n    height: 200px;\r\n    background-image: url('../../assets/img/ucenter-bg.jpg');\r\n    background-size: cover;\r\n    background-position: center;\r\n    background-repeat: no-repeat;\r\n}\r\n\r\n.user-profile {\r\n    width: 500px;\r\n    margin-right: 20px;\r\n    flex: 0 0 auto;\r\n    align-self: flex-start;\r\n}\r\n\r\n.user-avatar-wrap {\r\n    position: absolute;\r\n    top: 135px;\r\n    width: 100%;\r\n    text-align: center;\r\n}\r\n\r\n.user-avatar {\r\n    border: 5px solid #fff;\r\n    border-radius: 50%;\r\n    overflow: hidden;\r\n    box-shadow: 0 7px 12px 0 rgba(62, 57, 107, 0.16);\r\n}\r\n\r\n.user-info {\r\n    text-align: center;\r\n    padding: 80px 0 30px;\r\n}\r\n\r\n.info-name {\r\n    margin: 0 0 20px;\r\n    font-size: 22px;\r\n    font-weight: 500;\r\n    color: #373a3c;\r\n}\r\n\r\n.info-desc {\r\n    display: flex;\r\n    align-items: center;\r\n    justify-content: center;\r\n    margin-bottom: 5px;\r\n}\r\n\r\n.info-desc,\r\n.info-desc a {\r\n    font-size: 18px;\r\n    color: #55595c;\r\n}\r\n\r\n.info-icon {\r\n    margin-top: 10px;\r\n}\r\n\r\n.info-icon i {\r\n    font-size: 30px;\r\n    margin: 0 10px;\r\n    color: #343434;\r\n}\r\n\r\n.user-content {\r\n    flex: 1;\r\n}\r\n\r\n.user-tabpane {\r\n    padding: 10px 20px;\r\n}\r\n\r\n.crop-wrap {\r\n    width: 600px;\r\n    height: 350px;\r\n    margin-bottom: 20px;\r\n}\r\n\r\n.crop-demo-btn {\r\n    position: relative;\r\n}\r\n\r\n.crop-input {\r\n    position: absolute;\r\n    width: 100px;\r\n    height: 40px;\r\n    left: 0;\r\n    top: 0;\r\n    opacity: 0;\r\n    cursor: pointer;\r\n}\r\n\r\n.w500 {\r\n    width: 500px;\r\n}\r\n\r\n.user-footer {\r\n    display: flex;\r\n    border-top: 1px solid rgba(83, 70, 134, 0.1);\r\n}\r\n\r\n.user-footer-item {\r\n    padding: 20px 0;\r\n    width: 33.3333333333%;\r\n    text-align: center;\r\n}\r\n\r\n.user-footer > div + div {\r\n    border-left: 1px solid rgba(83, 70, 134, 0.1);\r\n}\r\n</style>\r\n\r\n<style>\r\n.el-tabs.el-tabs--left {\r\n    height: 100%;\r\n}\r\n</style>\r\n"
  },
  {
    "path": "src/views/system/menu.vue",
    "content": "<template>\r\n    <div>\r\n        <div class=\"container\">\r\n            <TableCustom :columns=\"columns\" :tableData=\"menuData\" row-key=\"index\" :has-pagination=\"false\"\r\n                :viewFunc=\"handleView\" :delFunc=\"handleDelete\" :editFunc=\"handleEdit\">\r\n                <template #toolbarBtn>\r\n                    <el-button type=\"warning\" :icon=\"CirclePlusFilled\" @click=\"visible = true\">新增</el-button>\r\n                </template>\r\n                <template #icon=\"{ rows }\">\r\n                    <el-icon>\r\n                        <component :is=\"rows.icon\"></component>\r\n                    </el-icon>\r\n                </template>\r\n            </TableCustom>\r\n\r\n        </div>\r\n        <el-dialog :title=\"isEdit ? '编辑' : '新增'\" v-model=\"visible\" width=\"700px\" destroy-on-close\r\n            :close-on-click-modal=\"false\" @close=\"closeDialog\">\r\n            <TableEdit :form-data=\"rowData\" :options=\"options\" :edit=\"isEdit\" :update=\"updateData\">\r\n                <template #parent>\r\n                    <el-cascader v-model=\"rowData.pid\" :options=\"cascaderOptions\" :props=\"{ checkStrictly: true }\"\r\n                        clearable />\r\n                </template>\r\n            </TableEdit>\r\n        </el-dialog>\r\n        <el-dialog title=\"查看详情\" v-model=\"visible1\" width=\"700px\" destroy-on-close>\r\n            <TableDetail :data=\"viewData\">\r\n                <template #icon=\"{ rows }\">\r\n                    <el-icon>\r\n                        <component :is=\"rows.icon\"></component>\r\n                    </el-icon>\r\n                </template>\r\n            </TableDetail>\r\n        </el-dialog>\r\n    </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\" name=\"system-menu\">\r\nimport { ref } from 'vue';\r\nimport { ElMessage } from 'element-plus';\r\nimport { CirclePlusFilled } from '@element-plus/icons-vue';\r\nimport { Menus } from '@/types/menu';\r\nimport TableCustom from '@/components/table-custom.vue';\r\nimport TableDetail from '@/components/table-detail.vue';\r\nimport { FormOption } from '@/types/form-option';\r\nimport { menuData } from '@/components/menu';\r\n\r\n// 表格相关\r\nlet columns = ref([\r\n    { prop: 'title', label: '菜单名称', align: 'left' },\r\n    { prop: 'icon', label: '图标' },\r\n    { prop: 'index', label: '路由路径' },\r\n    { prop: 'permiss', label: '权限标识' },\r\n    { prop: 'operator', label: '操作', width: 250 },\r\n])\r\n\r\nconst getOptions = (data: any) => {\r\n    return data.map(item => {\r\n        const a: any = {\r\n            label: item.title,\r\n            value: item.id,\r\n        }\r\n        if (item.children) {\r\n            a.children = getOptions(item.children)\r\n        }\r\n        return a\r\n    })\r\n}\r\nconst cascaderOptions = ref(getOptions(menuData));\r\n\r\n\r\n// 新增/编辑弹窗相关\r\nlet options = ref<FormOption>({\r\n    labelWidth: '100px',\r\n    span: 12,\r\n    list: [\r\n        { type: 'input', label: '菜单名称', prop: 'title', required: true },\r\n        { type: 'input', label: '路由路径', prop: 'index', required: true },\r\n        { type: 'input', label: '图标', prop: 'icon' },\r\n        { type: 'input', label: '权限标识', prop: 'permiss' },\r\n        { type: 'parent', label: '父菜单', prop: 'parent' },\r\n    ]\r\n})\r\nconst visible = ref(false);\r\nconst isEdit = ref(false);\r\nconst rowData = ref<any>({});\r\nconst handleEdit = (row: Menus) => {\r\n    rowData.value = { ...row };\r\n    isEdit.value = true;\r\n    visible.value = true;\r\n};\r\nconst updateData = () => {\r\n    closeDialog();\r\n};\r\n\r\nconst closeDialog = () => {\r\n    visible.value = false;\r\n    isEdit.value = false;\r\n};\r\n\r\n// 查看详情弹窗相关\r\nconst visible1 = ref(false);\r\nconst viewData = ref({\r\n    row: {},\r\n    list: []\r\n});\r\nconst handleView = (row: Menus) => {\r\n    viewData.value.row = { ...row }\r\n    viewData.value.list = [\r\n        {\r\n            prop: 'id',\r\n            label: '菜单ID',\r\n        },\r\n        {\r\n            prop: 'pid',\r\n            label: '父菜单ID',\r\n        },\r\n        {\r\n            prop: 'title',\r\n            label: '菜单名称',\r\n        },\r\n        {\r\n            prop: 'index',\r\n            label: '路由路径',\r\n        },\r\n        {\r\n            prop: 'permiss',\r\n            label: '权限标识',\r\n        },\r\n        {\r\n            prop: 'icon',\r\n            label: '图标',\r\n        },\r\n    ]\r\n    visible1.value = true;\r\n};\r\n\r\n// 删除相关\r\nconst handleDelete = (row: Menus) => {\r\n    ElMessage.success('删除成功');\r\n}\r\n</script>\r\n\r\n<style scoped></style>"
  },
  {
    "path": "src/views/system/role-permission.vue",
    "content": "<template>\r\n    <div>\r\n        <el-tree\r\n            class=\"mgb10\"\r\n            ref=\"tree\"\r\n            :data=\"data\"\r\n            node-key=\"id\"\r\n            default-expand-all\r\n            show-checkbox\r\n            :default-checked-keys=\"checkedKeys\"\r\n        />\r\n        <el-button type=\"primary\" @click=\"onSubmit\">保存权限</el-button>\r\n    </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref } from 'vue';\r\nimport { ElTree } from 'element-plus';\r\nimport { menuData } from '@/components/menu';\r\n\r\nconst props = defineProps({\r\n    permissOptions: {\r\n        type: Object,\r\n        required: true,\r\n    },\r\n});\r\n\r\nconst menuObj = ref({});\r\n// const data = menuData.map((item) => {\r\n//     if (item.children) {\r\n//         menuObj.value[item.id] = item.children.map((sub) => sub.id);\r\n//     }\r\n//     return {\r\n//         id: item.id,\r\n//         label: item.title,\r\n//         children: item.children?.map((child) => {\r\n//             return {\r\n//                 id: child.id,\r\n//                 label: child.title,\r\n//             };\r\n//         }),\r\n//     };\r\n// });\r\n\r\nconst getTreeData = (data) => {\r\n    return data.map((item) => {\r\n        const obj: any = {\r\n            id: item.id,\r\n            label: item.title,\r\n        };\r\n        if (item.children) {\r\n            menuObj.value[item.id] = item.children.map((sub) => sub.id);\r\n            obj.children = getTreeData(item.children);\r\n        }\r\n        return obj;\r\n    });\r\n};\r\nconst data = getTreeData(menuData);\r\nconst checkData = (data: string[]) => {\r\n    return data.filter((item) => {\r\n        return !menuObj.value[item] || data.toString().includes(menuObj.value[item].toString());\r\n    });\r\n};\r\n// 获取当前权限\r\nconst checkedKeys = ref<string[]>(checkData(props.permissOptions.permiss));\r\n\r\n// 保存权限\r\nconst tree = ref<InstanceType<typeof ElTree>>();\r\nconst onSubmit = () => {\r\n    // 获取选中的权限\r\n    const keys = [...tree.value!.getCheckedKeys(false), ...tree.value!.getHalfCheckedKeys()] as number[];\r\n    console.log(keys);\r\n};\r\n</script>\r\n\r\n<style scoped></style>\r\n"
  },
  {
    "path": "src/views/system/role.vue",
    "content": "<template>\r\n    <div>\r\n        <TableSearch :query=\"query\" :options=\"searchOpt\" :search=\"handleSearch\" />\r\n        <div class=\"container\">\r\n\r\n            <TableCustom :columns=\"columns\" :tableData=\"tableData\" :total=\"page.total\" :viewFunc=\"handleView\"\r\n                :delFunc=\"handleDelete\" :page-change=\"changePage\" :editFunc=\"handleEdit\">\r\n                <template #toolbarBtn>\r\n                    <el-button type=\"warning\" :icon=\"CirclePlusFilled\" @click=\"visible = true\">新增</el-button>\r\n                </template>\r\n                <template #status=\"{ rows }\">\r\n                    <el-tag type=\"success\" v-if=\"rows.status\">启用</el-tag>\r\n                    <el-tag type=\"danger\" v-else>禁用</el-tag>\r\n                </template>\r\n                <template #permissions=\"{ rows }\">\r\n                    <el-button type=\"primary\" size=\"small\" plain @click=\"handlePermission(rows)\">管理</el-button>\r\n                </template>\r\n            </TableCustom>\r\n        </div>\r\n        <el-dialog :title=\"isEdit ? '编辑' : '新增'\" v-model=\"visible\" width=\"700px\" destroy-on-close\r\n            :close-on-click-modal=\"false\" @close=\"closeDialog\">\r\n            <TableEdit :form-data=\"rowData\" :options=\"options\" :edit=\"isEdit\" :update=\"updateData\" />\r\n        </el-dialog>\r\n        <el-dialog title=\"查看详情\" v-model=\"visible1\" width=\"700px\" destroy-on-close>\r\n            <TableDetail :data=\"viewData\">\r\n                <template #status=\"{ rows }\">\r\n                    <el-tag type=\"success\" v-if=\"rows.status\">启用</el-tag>\r\n                    <el-tag type=\"danger\" v-else>禁用</el-tag>\r\n                </template>\r\n            </TableDetail>\r\n        </el-dialog>\r\n        <el-dialog title=\"权限管理\" v-model=\"visible2\" width=\"500px\" destroy-on-close>\r\n            <RolePermission :permiss-options=\"permissOptions\" />\r\n        </el-dialog>\r\n    </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\" name=\"system-role\">\r\nimport { ref, reactive } from 'vue';\r\nimport { ElMessage } from 'element-plus';\r\nimport { Role } from '@/types/role';\r\nimport { fetchRoleData } from '@/api';\r\nimport TableCustom from '@/components/table-custom.vue';\r\nimport TableDetail from '@/components/table-detail.vue';\r\nimport RolePermission from './role-permission.vue'\r\nimport { CirclePlusFilled } from '@element-plus/icons-vue';\r\nimport { FormOption, FormOptionList } from '@/types/form-option';\r\n\r\n// 查询相关\r\nconst query = reactive({\r\n    name: '',\r\n});\r\nconst searchOpt = ref<FormOptionList[]>([\r\n    { type: 'input', label: '角色名称：', prop: 'name' }\r\n])\r\nconst handleSearch = () => {\r\n    changePage(1);\r\n};\r\n\r\n// 表格相关\r\nlet columns = ref([\r\n    { type: 'index', label: '序号', width: 55, align: 'center' },\r\n    { prop: 'name', label: '角色名称' },\r\n    { prop: 'key', label: '角色标识' },\r\n    { prop: 'status', label: '状态' },\r\n    { prop: 'permissions', label: '权限管理' },\r\n    { prop: 'operator', label: '操作', width: 250 },\r\n])\r\nconst page = reactive({\r\n    index: 1,\r\n    size: 10,\r\n    total: 0,\r\n})\r\nconst tableData = ref<Role[]>([]);\r\nconst getData = async () => {\r\n    const res = await fetchRoleData()\r\n    tableData.value = res.data.list;\r\n    page.total = res.data.pageTotal;\r\n};\r\ngetData();\r\nconst changePage = (val: number) => {\r\n    page.index = val;\r\n    getData();\r\n};\r\n\r\n// 新增/编辑弹窗相关\r\nconst options = ref<FormOption>({\r\n    labelWidth: '100px',\r\n    span: 24,\r\n    list: [\r\n        { type: 'input', label: '角色名称', prop: 'name', required: true },\r\n        { type: 'input', label: '角色标识', prop: 'key', required: true },\r\n        { type: 'switch', label: '状态', prop: 'status', required: false, activeText: '启用', inactiveText: '禁用' },\r\n    ]\r\n})\r\nconst visible = ref(false);\r\nconst isEdit = ref(false);\r\nconst rowData = ref({});\r\nconst handleEdit = (row: Role) => {\r\n    rowData.value = { ...row };\r\n    isEdit.value = true;\r\n    visible.value = true;\r\n};\r\nconst updateData = () => {\r\n    closeDialog();\r\n    getData();\r\n};\r\nconst closeDialog = () => {\r\n    visible.value = false;\r\n    isEdit.value = false;\r\n    rowData.value = {};\r\n};\r\n\r\n// 查看详情弹窗相关\r\nconst visible1 = ref(false);\r\nconst viewData = ref({\r\n    row: {},\r\n    list: [],\r\n    column: 1\r\n});\r\nconst handleView = (row: Role) => {\r\n    viewData.value.row = { ...row }\r\n    viewData.value.list = [\r\n        {\r\n            prop: 'id',\r\n            label: '角色ID',\r\n        },\r\n        {\r\n            prop: 'name',\r\n            label: '角色名称',\r\n        },\r\n        {\r\n            prop: 'key',\r\n            label: '角色标识',\r\n        },\r\n        {\r\n            prop: 'status',\r\n            label: '角色状态',\r\n        },\r\n    ]\r\n    visible1.value = true;\r\n};\r\n\r\n// 删除相关\r\nconst handleDelete = (row: Role) => {\r\n    ElMessage.success('删除成功');\r\n}\r\n\r\n\r\n// 权限管理弹窗相关\r\nconst visible2 = ref(false);\r\nconst permissOptions = ref({})\r\nconst handlePermission = (row: Role) => {\r\n    visible2.value = true;\r\n    permissOptions.value = {\r\n        id: row.id,\r\n        permiss: row.permiss\r\n    };\r\n}\r\n</script>\r\n\r\n<style scoped></style>"
  },
  {
    "path": "src/views/system/user.vue",
    "content": "<template>\r\n    <div>\r\n        <TableSearch :query=\"query\" :options=\"searchOpt\" :search=\"handleSearch\" />\r\n        <div class=\"container\">\r\n            <TableCustom :columns=\"columns\" :tableData=\"tableData\" :total=\"page.total\" :viewFunc=\"handleView\"\r\n                :delFunc=\"handleDelete\" :page-change=\"changePage\" :editFunc=\"handleEdit\">\r\n                <template #toolbarBtn>\r\n                    <el-button type=\"warning\" :icon=\"CirclePlusFilled\" @click=\"visible = true\">新增</el-button>\r\n                </template>\r\n            </TableCustom>\r\n\r\n        </div>\r\n        <el-dialog :title=\"isEdit ? '编辑' : '新增'\" v-model=\"visible\" width=\"700px\" destroy-on-close\r\n            :close-on-click-modal=\"false\" @close=\"closeDialog\">\r\n            <TableEdit :form-data=\"rowData\" :options=\"options\" :edit=\"isEdit\" :update=\"updateData\" />\r\n        </el-dialog>\r\n        <el-dialog title=\"查看详情\" v-model=\"visible1\" width=\"700px\" destroy-on-close>\r\n            <TableDetail :data=\"viewData\"></TableDetail>\r\n        </el-dialog>\r\n    </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\" name=\"system-user\">\r\nimport { ref, reactive } from 'vue';\r\nimport { ElMessage } from 'element-plus';\r\nimport { CirclePlusFilled } from '@element-plus/icons-vue';\r\nimport { User } from '@/types/user';\r\nimport { fetchUserData } from '@/api';\r\nimport TableCustom from '@/components/table-custom.vue';\r\nimport TableDetail from '@/components/table-detail.vue';\r\nimport TableSearch from '@/components/table-search.vue';\r\nimport { FormOption, FormOptionList } from '@/types/form-option';\r\n\r\n// 查询相关\r\nconst query = reactive({\r\n    name: '',\r\n});\r\nconst searchOpt = ref<FormOptionList[]>([\r\n    { type: 'input', label: '用户名：', prop: 'name' }\r\n])\r\nconst handleSearch = () => {\r\n    changePage(1);\r\n};\r\n\r\n// 表格相关\r\nlet columns = ref([\r\n    { type: 'index', label: '序号', width: 55, align: 'center' },\r\n    { prop: 'name', label: '用户名' },\r\n    { prop: 'phone', label: '手机号' },\r\n    { prop: 'role', label: '角色' },\r\n    { prop: 'operator', label: '操作', width: 250 },\r\n])\r\nconst page = reactive({\r\n    index: 1,\r\n    size: 10,\r\n    total: 0,\r\n})\r\nconst tableData = ref<User[]>([]);\r\nconst getData = async () => {\r\n    const res = await fetchUserData()\r\n    tableData.value = res.data.list;\r\n    page.total = res.data.pageTotal;\r\n};\r\ngetData();\r\n\r\nconst changePage = (val: number) => {\r\n    page.index = val;\r\n    getData();\r\n};\r\n\r\n// 新增/编辑弹窗相关\r\nlet options = ref<FormOption>({\r\n    labelWidth: '100px',\r\n    span: 12,\r\n    list: [\r\n        { type: 'input', label: '用户名', prop: 'name', required: true },\r\n        { type: 'input', label: '手机号', prop: 'phone', required: true },\r\n        { type: 'input', label: '密码', prop: 'password', required: true },\r\n        { type: 'input', label: '邮箱', prop: 'email', required: true },\r\n        { type: 'input', label: '角色', prop: 'role', required: true },\r\n    ]\r\n})\r\nconst visible = ref(false);\r\nconst isEdit = ref(false);\r\nconst rowData = ref({});\r\nconst handleEdit = (row: User) => {\r\n    rowData.value = { ...row };\r\n    isEdit.value = true;\r\n    visible.value = true;\r\n};\r\nconst updateData = () => {\r\n    closeDialog();\r\n    getData();\r\n};\r\n\r\nconst closeDialog = () => {\r\n    visible.value = false;\r\n    isEdit.value = false;\r\n};\r\n\r\n// 查看详情弹窗相关\r\nconst visible1 = ref(false);\r\nconst viewData = ref({\r\n    row: {},\r\n    list: []\r\n});\r\nconst handleView = (row: User) => {\r\n    viewData.value.row = { ...row }\r\n    viewData.value.list = [\r\n        {\r\n            prop: 'id',\r\n            label: '用户ID',\r\n        },\r\n        {\r\n            prop: 'name',\r\n            label: '用户名',\r\n        },\r\n        {\r\n            prop: 'password',\r\n            label: '密码',\r\n        },\r\n        {\r\n            prop: 'email',\r\n            label: '邮箱',\r\n        },\r\n        {\r\n            prop: 'phone',\r\n            label: '电话',\r\n        },\r\n        {\r\n            prop: 'role',\r\n            label: '角色',\r\n        },\r\n        {\r\n            prop: 'date',\r\n            label: '注册日期',\r\n        },\r\n    ]\r\n    visible1.value = true;\r\n};\r\n\r\n// 删除相关\r\nconst handleDelete = (row: User) => {\r\n    ElMessage.success('删除成功');\r\n}\r\n</script>\r\n\r\n<style scoped></style>"
  },
  {
    "path": "src/views/table/basetable.vue",
    "content": "<template>\r\n\t<div>\r\n\t\t<TableSearch :query=\"query\" :options=\"searchOpt\" :search=\"handleSearch\" />\r\n\t\t<div class=\"container\">\r\n\t\t\t<TableCustom :columns=\"columns\" :tableData=\"tableData\" :total=\"page.total\" :viewFunc=\"handleView\"\r\n\t\t\t\t:delFunc=\"handleDelete\" :editFunc=\"handleEdit\" :refresh=\"getData\" :currentPage=\"page.index\"\r\n\t\t\t\t:changePage=\"changePage\">\r\n\t\t\t\t<template #toolbarBtn>\r\n\t\t\t\t\t<el-button type=\"warning\" :icon=\"CirclePlusFilled\" @click=\"visible = true\">新增</el-button>\r\n\t\t\t\t</template>\r\n\t\t\t\t<template #money=\"{ rows }\">\r\n\t\t\t\t\t￥{{ rows.money }}\r\n\t\t\t\t</template>\r\n\t\t\t\t<template #thumb=\"{ rows }\">\r\n\t\t\t\t\t<el-image class=\"table-td-thumb\" :src=\"rows.thumb\" :z-index=\"10\" :preview-src-list=\"[rows.thumb]\"\r\n\t\t\t\t\t\tpreview-teleported>\r\n\t\t\t\t\t</el-image>\r\n\t\t\t\t</template>\r\n\t\t\t\t<template #state=\"{ rows }\">\r\n\t\t\t\t\t<el-tag :type=\"rows.state ? 'success' : 'danger'\">\r\n\t\t\t\t\t\t{{ rows.state ? '正常' : '异常' }}\r\n\t\t\t\t\t</el-tag>\r\n\t\t\t\t</template>\r\n\t\t\t</TableCustom>\r\n\r\n\t\t</div>\r\n\t\t<el-dialog :title=\"isEdit ? '编辑' : '新增'\" v-model=\"visible\" width=\"700px\" destroy-on-close\r\n\t\t\t:close-on-click-modal=\"false\" @close=\"closeDialog\">\r\n\t\t\t<TableEdit :form-data=\"rowData\" :options=\"options\" :edit=\"isEdit\" :update=\"updateData\">\r\n\t\t\t\t<template #thumb=\"{ rows }\">\r\n\t\t\t\t\t<img class=\"table-td-thumb\" :src=\"rows.thumb\"></img>\r\n\t\t\t\t</template>\r\n\t\t\t</TableEdit>\r\n\t\t</el-dialog>\r\n\t\t<el-dialog title=\"查看详情\" v-model=\"visible1\" width=\"700px\" destroy-on-close>\r\n\t\t\t<TableDetail :data=\"viewData\">\r\n\t\t\t\t<template #thumb=\"{ rows }\">\r\n\t\t\t\t\t<el-image :src=\"rows.thumb\"></el-image>\r\n\t\t\t\t</template>\r\n\t\t\t</TableDetail>\r\n\t\t</el-dialog>\r\n\t</div>\r\n</template>\r\n\r\n<script setup lang=\"ts\" name=\"basetable\">\r\nimport { ref, reactive } from 'vue';\r\nimport { ElMessage, } from 'element-plus';\r\nimport { CirclePlusFilled } from '@element-plus/icons-vue';\r\nimport { fetchData } from '@/api/index';\r\nimport TableCustom from '@/components/table-custom.vue';\r\nimport TableDetail from '@/components/table-detail.vue';\r\nimport TableSearch from '@/components/table-search.vue';\r\nimport { TableItem } from '@/types/table';\r\nimport { FormOption, FormOptionList } from '@/types/form-option';\r\n\r\n// 查询相关\r\nconst query = reactive({\r\n\tname: '',\r\n});\r\nconst searchOpt = ref<FormOptionList[]>([\r\n\t{ type: 'input', label: '用户名：', prop: 'name' }\r\n])\r\nconst handleSearch = () => {\r\n\tchangePage(1);\r\n};\r\n\r\n// 表格相关\r\nlet columns = ref([\r\n\t{ type: 'selection' },\r\n\t{ type: 'index', label: '序号', width: 55, align: 'center' },\r\n\t{ prop: 'name', label: '用户名' },\r\n\t{ prop: 'money', label: '账户余额' },\r\n\t{ prop: 'thumb', label: '头像' },\r\n\t{ prop: 'state', label: '账户状态' },\r\n\t{ prop: 'operator', label: '操作', width: 250 },\r\n])\r\nconst page = reactive({\r\n\tindex: 1,\r\n\tsize: 10,\r\n\ttotal: 200,\r\n})\r\nconst tableData = ref<TableItem[]>([]);\r\nconst getData = async () => {\r\n\tconst res = await fetchData()\r\n\ttableData.value = res.data.list;\r\n};\r\ngetData();\r\n\r\nconst changePage = (val: number) => {\r\n\tpage.index = val;\r\n\tgetData();\r\n};\r\n\r\n// 新增/编辑弹窗相关\r\nlet options = ref<FormOption>({\r\n\tlabelWidth: '100px',\r\n\tspan: 24,\r\n\tlist: [\r\n\t\t{ type: 'input', label: '用户名', prop: 'name', required: true },\r\n\t\t{ type: 'number', label: '账户余额', prop: 'money', required: true },\r\n\t\t{ type: 'switch', activeText: '正常', inactiveText: '异常', label: '账户状态', prop: 'state', required: true },\r\n\t\t{ type: 'upload', label: '头像', prop: 'thumb', required: true },\r\n\t]\r\n})\r\nconst visible = ref(false);\r\nconst isEdit = ref(false);\r\nconst rowData = ref({});\r\nconst handleEdit = (row: TableItem) => {\r\n\trowData.value = { ...row };\r\n\tisEdit.value = true;\r\n\tvisible.value = true;\r\n};\r\nconst updateData = () => {\r\n\tcloseDialog();\r\n\tgetData();\r\n};\r\n\r\nconst closeDialog = () => {\r\n\tvisible.value = false;\r\n\tisEdit.value = false;\r\n};\r\n\r\n// 查看详情弹窗相关\r\nconst visible1 = ref(false);\r\nconst viewData = ref({\r\n\trow: {},\r\n\tlist: []\r\n});\r\nconst handleView = (row: TableItem) => {\r\n\tviewData.value.row = { ...row }\r\n\tviewData.value.list = [\r\n\t\t{\r\n\t\t\tprop: 'id',\r\n\t\t\tlabel: '用户ID',\r\n\t\t},\r\n\t\t{\r\n\t\t\tprop: 'name',\r\n\t\t\tlabel: '用户名',\r\n\t\t},\r\n\t\t{\r\n\t\t\tprop: 'money',\r\n\t\t\tlabel: '账户余额',\r\n\t\t},\r\n\t\t{\r\n\t\t\tprop: 'state',\r\n\t\t\tlabel: '账户状态',\r\n\t\t},\r\n\t\t{\r\n\t\t\tprop: 'thumb',\r\n\t\t\tlabel: '头像',\r\n\t\t},\r\n\t]\r\n\tvisible1.value = true;\r\n};\r\n\r\n// 删除相关\r\nconst handleDelete = (row: TableItem) => {\r\n\tElMessage.success('删除成功');\r\n}\r\n</script>\r\n\r\n<style scoped>\r\n.table-td-thumb {\r\n\tdisplay: block;\r\n\tmargin: auto;\r\n\twidth: 40px;\r\n\theight: 40px;\r\n}\r\n</style>\r\n"
  },
  {
    "path": "src/views/table/export.vue",
    "content": "<template>\r\n    <div>\r\n        <div class=\"container\">\r\n            <div class=\"handle-box\">\r\n                <el-button type=\"primary\" @click=\"exportXlsx\">导出Excel</el-button>\r\n            </div>\r\n            <el-table :data=\"tableData\" border class=\"table\" header-cell-class-name=\"table-header\">\r\n                <el-table-column prop=\"id\" label=\"ID\" width=\"55\" align=\"center\"></el-table-column>\r\n                <el-table-column prop=\"name\" label=\"姓名\"></el-table-column>\r\n                <el-table-column prop=\"sno\" label=\"学号\"></el-table-column>\r\n                <el-table-column prop=\"class\" label=\"班级\"></el-table-column>\r\n                <el-table-column prop=\"age\" label=\"年龄\"></el-table-column>\r\n                <el-table-column prop=\"sex\" label=\"性别\"></el-table-column>\r\n            </el-table>\r\n        </div>\r\n    </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\" name=\"export\">\r\nimport { ref } from 'vue';\r\nimport * as XLSX from 'xlsx';\r\n\r\ninterface TableItem {\r\n    id: number;\r\n    name: string;\r\n    sno: string;\r\n    class: string;\r\n    age: string;\r\n    sex: string;\r\n}\r\n\r\nconst tableData = ref<TableItem[]>([]);\r\n// 获取表格数据\r\nconst getData = () => {\r\n    tableData.value = [\r\n        {\r\n            id: 1,\r\n            name: '小明',\r\n            sno: 'S001',\r\n            class: '一班',\r\n            age: '10',\r\n            sex: '男',\r\n        },\r\n        {\r\n            id: 2,\r\n            name: '小红',\r\n            sno: 'S002',\r\n            class: '一班',\r\n            age: '9',\r\n            sex: '女',\r\n        },\r\n    ];\r\n};\r\ngetData();\r\n\r\nconst list = [['序号', '姓名', '学号', '班级', '年龄', '性别']];\r\nconst exportXlsx = () => {\r\n    tableData.value.map((item: any, i: number) => {\r\n        const arr: any[] = [i + 1];\r\n        arr.push(...[item.name, item.sno, item.class, item.age, item.sex]);\r\n        list.push(arr);\r\n    });\r\n    let WorkSheet = XLSX.utils.aoa_to_sheet(list);\r\n    let new_workbook = XLSX.utils.book_new();\r\n    XLSX.utils.book_append_sheet(new_workbook, WorkSheet, '第一页');\r\n    XLSX.writeFile(new_workbook, `表格.xlsx`);\r\n};\r\n</script>\r\n\r\n<style scoped>\r\n.handle-box {\r\n    margin-bottom: 20px;\r\n}\r\n\r\n.handle-select {\r\n    width: 120px;\r\n}\r\n\r\n.handle-input {\r\n    width: 300px;\r\n}\r\n\r\n.table {\r\n    width: 100%;\r\n    font-size: 14px;\r\n}\r\n\r\n.red {\r\n    color: #f56c6c;\r\n}\r\n\r\n.table-td-thumb {\r\n    display: block;\r\n    margin: auto;\r\n    width: 40px;\r\n    height: 40px;\r\n}\r\n</style>\r\n"
  },
  {
    "path": "src/views/table/import.vue",
    "content": "<template>\r\n    <div>\r\n        <div class=\"container\">\r\n            <div class=\"handle-box\">\r\n                <el-upload action=\"#\" :limit=\"1\" accept=\".xlsx, .xls\" :show-file-list=\"false\"\r\n                    :before-upload=\"beforeUpload\" :http-request=\"handleMany\">\r\n                    <el-button class=\"mr10\" type=\"success\">批量导入</el-button>\r\n                </el-upload>\r\n                <el-link href=\"/template.xlsx\" target=\"_blank\">下载模板</el-link>\r\n            </div>\r\n            <el-table :data=\"tableData\" border class=\"table\" header-cell-class-name=\"table-header\">\r\n                <el-table-column prop=\"id\" label=\"ID\" width=\"55\" align=\"center\"></el-table-column>\r\n                <el-table-column prop=\"name\" label=\"姓名\"></el-table-column>\r\n                <el-table-column prop=\"sno\" label=\"学号\"></el-table-column>\r\n                <el-table-column prop=\"class\" label=\"班级\"></el-table-column>\r\n                <el-table-column prop=\"age\" label=\"年龄\"></el-table-column>\r\n                <el-table-column prop=\"sex\" label=\"性别\"></el-table-column>\r\n            </el-table>\r\n        </div>\r\n    </div>\r\n</template>\r\n\r\n<script setup lang=\"ts\" name=\"import\">\r\nimport { UploadProps } from 'element-plus';\r\nimport { ref, reactive } from 'vue';\r\nimport * as XLSX from 'xlsx';\r\n\r\ninterface TableItem {\r\n    id: number;\r\n    name: string;\r\n    sno: string;\r\n    class: string;\r\n    age: string;\r\n    sex: string;\r\n}\r\n\r\nconst tableData = ref<TableItem[]>([]);\r\n// 获取表格数据\r\nconst getData = () => {\r\n    tableData.value = [\r\n        {\r\n            id: 1,\r\n            name: '小明',\r\n            sno: 'S001',\r\n            class: '一班',\r\n            age: '10',\r\n            sex: '男',\r\n        },\r\n        {\r\n            id: 2,\r\n            name: '小红',\r\n            sno: 'S002',\r\n            class: '一班',\r\n            age: '9',\r\n            sex: '女',\r\n        },\r\n    ];\r\n};\r\ngetData();\r\n\r\nconst importList = ref<any>([]);\r\nconst beforeUpload: UploadProps['beforeUpload'] = async (rawFile) => {\r\n    importList.value = await analysisExcel(rawFile);\r\n    return true;\r\n};\r\nconst analysisExcel = (file: any) => {\r\n    return new Promise(function (resolve, reject) {\r\n        const reader = new FileReader();\r\n        reader.onload = function (e: any) {\r\n            const data = e.target.result;\r\n            let datajson = XLSX.read(data, {\r\n                type: 'binary',\r\n            });\r\n\r\n            const sheetName = datajson.SheetNames[0];\r\n            const result = XLSX.utils.sheet_to_json(datajson.Sheets[sheetName]);\r\n            resolve(result);\r\n        };\r\n        reader.readAsBinaryString(file);\r\n    });\r\n};\r\n\r\nconst handleMany = async () => {\r\n    // 把数据传给服务器后获取最新列表，这里只是示例，不做请求\r\n    const list = importList.value.map((item: any, index: number) => {\r\n        return {\r\n            id: index,\r\n            name: item['姓名'],\r\n            sno: item['学号'],\r\n            class: item['班级'],\r\n            age: item['年龄'],\r\n            sex: item['性别'],\r\n        };\r\n    });\r\n    tableData.value.push(...list);\r\n};\r\n</script>\r\n\r\n<style scoped>\r\n.handle-box {\r\n    display: flex;\r\n    margin-bottom: 20px;\r\n}\r\n\r\n.table {\r\n    width: 100%;\r\n    font-size: 14px;\r\n}\r\n</style>\r\n"
  },
  {
    "path": "src/views/table/table-editor.vue",
    "content": "<template>\r\n\t<div class=\"container\">\r\n\t\t<TableCustom :columns=\"columns\" :tableData=\"tableData\" :hasToolbar=\"false\" :hasPagination=\"false\">\r\n\t\t\t<template #name=\"{ rows }\">\r\n\t\t\t\t<el-input v-if=\"rows.editing\" v-model=\"rows.name\"></el-input>\r\n\t\t\t\t<span v-else>{{ rows.name }}</span>\r\n\t\t\t</template>\r\n\t\t\t<template #password=\"{ rows }\">\r\n\t\t\t\t<el-input v-if=\"rows.editing\" v-model=\"rows.password\"></el-input>\r\n\t\t\t\t<span v-else>{{ rows.password }}</span>\r\n\t\t\t</template>\r\n\t\t\t<template #email=\"{ rows }\">\r\n\t\t\t\t<el-input v-if=\"rows.editing\" v-model=\"rows.email\"></el-input>\r\n\t\t\t\t<span v-else>{{ rows.email }}</span>\r\n\t\t\t</template>\r\n\t\t\t<template #role=\"{ rows }\">\r\n\t\t\t\t<el-select v-if=\"rows.editing\" v-model=\"rows.role\">\r\n\t\t\t\t\t<el-option label=\"管理员\" value=\"管理员\"></el-option>\r\n\t\t\t\t\t<el-option label=\"普通用户\" value=\"普通用户\"></el-option>\r\n\t\t\t\t</el-select>\r\n\t\t\t\t<span v-else>{{ rows.role }}</span>\r\n\t\t\t</template>\r\n\t\t\t<template #operator=\"{ rows, index }\">\r\n\t\t\t\t<template v-if=\"!rows.editing\">\r\n\t\t\t\t\t<el-button type=\"primary\" size=\"small\" :icon=\"Edit\" @click=\"handleEdit(rows)\">\r\n\t\t\t\t\t\t编辑\r\n\t\t\t\t\t</el-button>\r\n\t\t\t\t\t<el-button type=\"danger\" size=\"small\" :icon=\"Delete\" @click=\"\">\r\n\t\t\t\t\t\t删除\r\n\t\t\t\t\t</el-button>\r\n\t\t\t\t</template>\r\n\t\t\t\t<template v-else>\r\n\t\t\t\t\t<el-button type=\"success\" size=\"small\" :icon=\"Select\" @click=\"rows.editing = false\">\r\n\t\t\t\t\t\t保存\r\n\t\t\t\t\t</el-button>\r\n\t\t\t\t\t<el-button type=\"default\" size=\"small\" :icon=\"CloseBold\" @click=\"handleCancel(rows, index)\">\r\n\t\t\t\t\t\t取消\r\n\t\t\t\t\t</el-button>\r\n\t\t\t\t</template>\r\n\t\t\t</template>\r\n\t\t</TableCustom>\r\n\t</div>\r\n</template>\r\n\r\n<script setup lang=\"ts\" name=\"table-editor\">\r\nimport { ref } from 'vue';\r\nimport { Delete, Edit, CloseBold, Select } from '@element-plus/icons-vue';\r\nimport TableCustom from '@/components/table-custom.vue';\r\nimport { fetchUserData } from '@/api/index';\r\n\r\nlet columns = ref([\r\n\t{ type: 'index', label: '序号', width: 55, align: 'center' },\r\n\t{ prop: 'name', label: '用户名' },\r\n\t{ prop: 'password', label: '密码' },\r\n\t{ prop: 'email', label: '邮箱' },\r\n\t{ prop: 'role', label: '角色' },\r\n\t{ prop: 'operator', label: '操作', width: 180 },\r\n])\r\nconst tableData = ref([]);\r\nconst getData = async () => {\r\n\tconst res = await fetchUserData();\r\n\ttableData.value = res.data.list;\r\n};\r\ngetData();\r\n\r\nconst rowData = ref({})\r\n\r\nconst handleEdit = (row) => {\r\n\trowData.value = { ...row };\r\n\trow.editing = true;\r\n};\r\n\r\nconst handleCancel = (row, index) => {\r\n\trow.editing = false;\r\n\ttableData.value[index] = { ...rowData.value };\r\n};\r\n</script>\r\n\r\n<style scoped></style>\r\n"
  },
  {
    "path": "src/vite-env.d.ts",
    "content": "/// <reference types=\"vite/client\" />\r\n\r\ndeclare module '*.vue' {\r\n  import type { DefineComponent } from 'vue'\r\n  const component: DefineComponent<{}, {}, any>\r\n  export default component\r\n}\r\n\r\ndeclare module 'vue-schart';\r\ndeclare module 'nprogress'"
  },
  {
    "path": "tsconfig.json",
    "content": "{\r\n  \"compilerOptions\": {\r\n    \"target\": \"ESNext\",\r\n    \"useDefineForClassFields\": true,\r\n    \"module\": \"ESNext\",\r\n    \"moduleResolution\": \"Node\",\r\n    \"strict\": false,\r\n    \"jsx\": \"preserve\",\r\n    \"sourceMap\": true,\r\n    \"resolveJsonModule\": true,\r\n    \"isolatedModules\": true,\r\n    \"esModuleInterop\": true,\r\n    \"lib\": [\"ESNext\", \"DOM\"],\r\n    \"skipLibCheck\": true,\r\n    \"baseUrl\": \"./\",\r\n    \"paths\": {\r\n      \"@/*\": [\"src/*\"]\r\n    }\r\n  },\r\n  \"include\": [\"src/**/*.ts\", \"src/**/*.d.ts\",\"src/**/*.vue\"],\r\n  \"references\": [{ \"path\": \"./tsconfig.node.json\" }]\r\n}\r\n"
  },
  {
    "path": "tsconfig.node.json",
    "content": "{\r\n  \"compilerOptions\": {\r\n    \"composite\": true,\r\n    \"module\": \"ESNext\",\r\n    \"moduleResolution\": \"Node\",\r\n    \"allowSyntheticDefaultImports\": true\r\n  },\r\n  \"include\": [\"vite.config.ts\"]\r\n}\r\n"
  },
  {
    "path": "vite.config.ts",
    "content": "import { defineConfig } from 'vite';\r\nimport vue from '@vitejs/plugin-vue';\r\nimport VueSetupExtend from 'vite-plugin-vue-setup-extend';\r\nimport AutoImport from 'unplugin-auto-import/vite';\r\nimport Components from 'unplugin-vue-components/vite';\r\nimport { ElementPlusResolver } from 'unplugin-vue-components/resolvers';\r\nexport default defineConfig({\r\n\tbase: './',\r\n\tplugins: [\r\n\t\tvue(),\r\n\t\tVueSetupExtend(),\r\n\t\tAutoImport({\r\n\t\t\tresolvers: [ElementPlusResolver()]\r\n\t\t}),\r\n\t\tComponents({\r\n\t\t\tresolvers: [ElementPlusResolver()]\r\n\t\t})\r\n\t],\r\n\toptimizeDeps: {\r\n\t\tinclude: ['schart.js']\r\n\t},\r\n\tresolve: {\r\n\t\talias: {\r\n\t\t\t'@': '/src',\r\n\t\t\t'~': '/src/assets'\r\n\t\t}\r\n\t},\r\n\tdefine: {\r\n\t\t__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: \"true\",\r\n\t},\r\n});\r\n"
  }
]