diff --git a/.browserslistrc b/.browserslistrc new file mode 100644 index 0000000..dc3bc09 --- /dev/null +++ b/.browserslistrc @@ -0,0 +1,4 @@ +> 1% +last 2 versions +not dead +not ie 11 diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..4039ff1 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.env b/.env new file mode 100644 index 0000000..220160f --- /dev/null +++ b/.env @@ -0,0 +1,104 @@ +# Vab Admin 系列产品受国家计算机软件著作权保护(证书号:软著登字第 7051316 号)。 +# 关于举报盗版侵权:请发送举报材料至我司客服邮箱1204505056@qq.com,一经查实,官司所得收入20%归举报人所有,80%归律师事务所所有。 +# Vue Admin系列产品购买地址://vuejs-core.cn/authorization +# 1.购买者可将授权后的产品用于任意「符合国家法律法规」的应用平台,禁止用于黄赌毒等危害国家安全与稳定的网站。 +# 2.购买主体购买后可用于开发商业项目,不限制域名和项目数量,购买主体不可将源码分享第三方,否则我们有权利收回产品授权及更新权限,并根据事态轻重追究相应法律责任。 +# 3.购买者务必尊重知识产权,严格保证不恶意传播产品源码、不得直接对授权的产品本身进行二次转售或倒卖、开源、不得对授权的产品进行简单包装后声称为自己的产品等,无论有意或无意,我们有权利收回产品授权及更新权限,并根据事态轻重追究相应法律责任。 +# 4.购买者不可将vip群文档及资料分享给第三方,否则我们有权利收回产品授权及更新权限,并根据事态轻重追究相应法律责任。 +# 5.购买者购买项目不可以用来构建存在竞争性质的产品并直接对外销售否则我们有权利收回产品授权及更新权限,并根据事态轻重追究相应法律责任。 +# 6.购买者购买项目中的源码(包含全部源码、及部分源码片段)不可以用于任何形式的开源项目,否则我们有权利收回产品授权及更新权限,并根据事态轻重追究相应法律责任。 +# 7.用于公司的项目商用时购买需提供公司名称,用于证明购买过我们的项目来用于商业用途,防范法律风险,我们不会将【购买公司】信息泄漏到互联网或告知第三方。 +# 8.用于个人学习需提供姓名、联系方式。 +# 9.如用于外包项目,购买者购买项目中的源码不可直接对外出售,npm run build编译后的项目不受限制。 +# 10.虚拟物品不支持退货退款。 +# 11.最终解释权归vab系列著作权人所有。 + + +# 第1步:请在此处将test变更为您的github用户名,请务必填写购买时绑定的github用户名,同一个授权配置不同用户名会导致您的授权永久失效 + VUE_GITHUB_USER_NAME=test + +# 第2步:请在项目根目录新建一个.env.local的新文件,切记是新建空的文件不是直接拷贝.env文件的内容 + +# 第3步:.env.local的文件只能有一行不可以换行,购买时生成,格式如下:VUE_APP_SECRET_KEY=XXXXXXX + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# 以下内容不建议修改建议将VUE_APP_SECRET_KEY配置到【.env.local】中 +VUE_APP_SECRET_KEY=preview + + + diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..e761cce --- /dev/null +++ b/.env.development @@ -0,0 +1,4 @@ +# 开发环境,VUE_APP_BASE_URL可以选择自己配置成需要的接口地址,如"https://api.xxx.com" +# 此文件修改后需要重启项目 +NODE_ENV=development +VUE_APP_BASE_URL='/vab-mock-server' \ No newline at end of file diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..f277a08 --- /dev/null +++ b/.env.production @@ -0,0 +1,4 @@ +# 生产环境,VUE_APP_BASE_URL可以选择自己配置成需要的接口地址,如"https://api.xxx.com" +# 此文件修改后需要重启项目 +NODE_ENV=production +VUE_APP_BASE_URL='/vab-mock-server' \ No newline at end of file diff --git a/.env.test b/.env.test new file mode 100644 index 0000000..0fedb68 --- /dev/null +++ b/.env.test @@ -0,0 +1,4 @@ +# 测试环境,VUE_APP_BASE_URL可以选择自己配置成需要的接口地址,如"https://api.xxx.com" +# 此文件修改后需要重启项目 +NODE_ENV=production +VUE_APP_BASE_URL='/vab-mock-server' \ No newline at end of file diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..809af1b --- /dev/null +++ b/.eslintignore @@ -0,0 +1,7 @@ +library/build/vuePlugins/components.d.ts +node_modules +src/assets +src/icons +public +dist +vab-icons diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..de349d8 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,81 @@ +const { defineConfig } = require('eslint-define-config') + +module.exports = defineConfig({ + root: true, + env: { + node: true, + browser: true, + }, + globals: { + defineOptions: 'writable', + }, + parser: 'vue-eslint-parser', + parserOptions: { + parser: '@typescript-eslint/parser', + sourceType: 'module', + ecmaVersion: 2020, + }, + rules: { + 'import-x/order': 'off', + '@typescript-eslint/no-empty-function': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-non-null-assertion': 'off', + '@typescript-eslint/no-this-alias': 'off', + 'array-callback-return': 'off', + 'escape-case': 'off', + 'eslint-comments/no-unlimited-disable': 'off', + 'import/order': 'off', + 'no-alert': 'off', + 'no-console': 'off', + 'no-debugger': 'off', + 'no-restricted-imports': 'off', + 'no-return-await': 'off', + 'prefer-const': 'off', + 'prefer-template': 'error', + 'unicorn/consistent-function-scoping': 'off', + 'unicorn/escape-case': 'off', + 'unicorn/filename-case': 'off', + 'unicorn/import-style': 'off', + 'unicorn/no-abusive-eslint-disable': 'off', + 'unicorn/no-array-callback-reference': 'off', + 'unicorn/no-array-for-each': 'off', + 'unicorn/no-array-reduce': 'off', + 'unicorn/no-nested-ternary': 'off', + 'unicorn/no-null': 'off', + 'unicorn/no-object-as-default-parameter': 'off', + 'unicorn/no-process-exit': 'off', + 'unicorn/no-this-assignment': 'off', + 'unicorn/numeric-separators-style': 'off', + 'unicorn/prefer-array-some': 'off', + 'unicorn/prefer-default-parameters': 'off', + 'unicorn/prefer-dom-node-append': 'off', + 'unicorn/prefer-dom-node-remove': 'off', + 'unicorn/prefer-logical-operator-over-ternary': 'off', + 'unicorn/prefer-math-trunc': 'off', + 'unicorn/prefer-module': 'off', + 'unicorn/prefer-number-properties': 'off', + 'unicorn/prefer-query-selector': 'off', + 'unicorn/prefer-spread': 'off', + 'unicorn/prefer-string-slice': 'off', + 'unicorn/prefer-structured-clone': 'off', + 'unicorn/prefer-ternary': 'off', + 'unicorn/prefer-top-level-await': 'off', + 'unicorn/prevent-abbreviations': 'off', + 'unicorn/expiring-todo-comments': 'off', + 'unicorn/consistent-destructuring': 'off', + 'vue/multi-word-component-names': 'off', + 'vue/no-reserved-component-names': 'off', + 'vue/no-setup-props-destructure': 'off', + 'vue/no-v-html': 'off', + 'vue/require-default-prop': 'off', + 'unicorn/number-literal-case': 'off', + '@typescript-eslint/no-var-requires': 'off', + 'import/first': 'off', + 'object-shorthand': 'off', + 'unicorn/no-console-spaces': 'off', + 'unicorn/prefer-dom-node-text-content': 'off', + 'unicorn/prefer-code-point': 'off', + '@typescript-eslint/consistent-type-imports': 'off', + camelcase: 'off', + }, +}) diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..8907e9b --- /dev/null +++ b/.gitattributes @@ -0,0 +1,17 @@ +*.html text eol=lf +*.css text eol=lf +*.js text eol=lf +*.ts text eol=lf +*.scss text eol=lf +*.vue text eol=lf +*.hbs text eol=lf +*.sh text eol=lf +*.md text eol=lf +*.json text eol=lf +*.yml text eol=lf +.browserslistrc text eol=lf +.editorconfig text eol=lf +.eslintignore text eol=lf +.gitattributes text eol=lf +LICENSE text eol=lf +*.conf text eol=lf diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..f941025 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,11 @@ +name: Call HTTPS API +on: [push] +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Call HTTPS API + env: + API_ENDPOINT: https://api.vuejs-core.cn + run: | + curl -X GET "$API_ENDPOINT" -G --data "repository=$GITHUB_REPOSITORY" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..63197e3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,46 @@ +.DS_Store +node_modules +node_modules.nosync +/dist + +# local env files +.env.local +.env.*.local + +# Log files +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# Editor directories and files +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +# Lock files +yarn.lock +pnpm-lock.yaml +package-lock.json + +# Yarn v2 not using using Zero-Installs +.yarn/* +#!.yarn/cache +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/sdks +!.yarn/versions +.pnp.* + +# Vab +public/video +*.zip +*.7z +*.rar +/.history diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..bf2e764 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +shamefully-hoist=true diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..34f33b7 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,4 @@ +auto-imports.d.ts +components.d.ts +index.html +website.html diff --git a/.stylelintrc.js b/.stylelintrc.js new file mode 100644 index 0000000..a70b6d7 --- /dev/null +++ b/.stylelintrc.js @@ -0,0 +1,18 @@ +module.exports = { + extends: [ + 'stylelint-config-recommended-scss', + 'stylelint-config-recommended-vue', + 'stylelint-config-recess-order', + ], + rules: { + 'no-empty-source': null, + 'at-rule-no-unknown': null, + 'property-no-unknown': null, + 'function-no-unknown': null, + 'selector-class-pattern': null, + 'no-descending-specificity': null, + 'scss/no-global-function-names': null, + 'selector-pseudo-class-no-unknown': null, + }, + ignoreFiles: ['dist/**/*', 'public/index.html'], +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..36bba7b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,76 @@ +{ + "[vue]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "editor.quickSuggestions": { + "strings": true + }, + "workbench.colorTheme": "One Monokai", + "editor.tabSize": 2, + "editor.detectIndentation": false, + "emmet.triggerExpansionOnTab": true, + "editor.formatOnSave": true, + "javascript.format.enable": true, + "git.enableSmartCommit": true, + "git.autofetch": true, + "git.confirmSync": false, + "[json]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "liveServer.settings.donotShowInfoMsg": true, + "explorer.confirmDelete": false, + "javascript.updateImportsOnFileMove.enabled": "always", + "typescript.updateImportsOnFileMove.enabled": "always", + "files.exclude": { + "**/.idea": true + }, + "editor.codeActionsOnSave": { + "source.fixAll.stylelint": "explicit", + "source.fixAll.eslint": "explicit" + }, + "stylelint.validate": ["html", "vue", "js", "scss"], + "[javascript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[jsonc]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[html]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[typescript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "editor.suggest.snippetsPreventQuickSuggestions": false, + "prettier.htmlWhitespaceSensitivity": "ignore", + "prettier.vueIndentScriptAndStyle": true, + "docthis.authorName": "github.com/zxwk1998", + "docthis.includeAuthorTag": true, + "docthis.includeDescriptionTag": true, + "docthis.enableHungarianNotationEvaluation": true, + "docthis.inferTypesFromNames": true, + "vetur.format.defaultFormatter.html": "prettier", + "files.autoSave": "onFocusChange", + "path-intellisense.mappings": { + "@": "${workspaceRoot}/src" + }, + "files.eol": "\n", + "vue.codeActions.enabled": false, + "cSpell.words": [ + "cnpm", + "filemanager", + "jsencrypt", + "logicflow", + "rushstack", + "taobao", + "unplugin", + "unplugins", + "vueuse", + "wangeditor", + "webpackbar" + ], + "i18n-ally.localesPaths": [ + "src/i18n", + "src/i18n/locales" + ] +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a612ad9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,373 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/README.md b/README.md index 4debb9d..0ac53c9 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,112 @@ -# Web_Template_Vue3_Dev +
+VAB +

admin-plus

+
-中后台前端框架 Vue3-Admin-Plus 模板项目 \ No newline at end of file +## 🔈 框架使用建议 + +- 使用前请一定先阅读 vip 群文档及群文档中的常见问题,一般在群公告前 5 条。 +- 对于常见问题可直接使用 qq 群【消息记录】功能快速寻找到答案。 +- 如果您经过 qq 群聊天记录、翻阅文档、百度后努力尝试仍无法解决问题,可通过 vip 群寻求帮助,讨论时间法定工作日 10 点-16 点。 +- 2021 年 3 月 6 日后,main 分支支持 ts、js 混合开发,建议不熟悉 ts 的用户继续使用 js,熟悉 ts 用户可自行选择开发语言。 +- 对于热心回答群内其他成员问题的用户,所提建议将优先被采纳,并可获得部分内测版本体验资格。 +- 关于举报盗版侵权:请发送举报材料至fanhuihui1998@126.com,一经查实,官司所得收入 20%归举报人所有,80%归律师事务所所有。 +- 关于客服人员满意度评价以及相关建议:请发送材料至fanhuihui1998@126.com,邮件标题:满意度评价,邮件正文:评价依据,我们必将认真对待每一位客户的诉求。 +- 关于 bug 反馈:请发送材料至fanhuihui1998@126.com,邮件标题:bug 反馈,邮件正文:bug 截图及描述。 + +## 🔈 框架使用约定 + +- 1.购买者可将授权后的产品用于任意「符合国家法律法规」的应用平台,禁止用于黄赌毒等危害国家安全与稳定的网站,否则我们有权利收回产品授权及更新权限,并根据事态轻重追究相应法律责任。 +- 2.购买主体购买后可用于开发商业项目,不限制域名和项目数量,购买主体不可将源码分享第三方,否则我们有权利收回产品授权及更新权限,并根据事态轻重追究相应法律责任。 +- 3.购买者务必尊重知识产权,严格保证不恶意传播产品源码、不得直接对授权的产品本身进行二次转售或倒卖、开源、不得对授权的产品进行简单包装后声称为自己的产品等,无论有意或无意,我们有权利收回产品授权及更新权限,并根据事态轻重追究相应法律责任。 +- 4.购买者不可将 vip 群文档及资料分享给第三方,否则我们有权利收回产品授权及更新权限,并根据事态轻重追究相应法律责任。 +- 5.购买者购买项目不可以用来构建存在竞争性质的产品并直接对外销售否则我们有权利收回产品授权及更新权限,并根据事态轻重追究相应法律责任。 +- 6.购买者购买项目中的源码(包含全部源码、及部分源码片段)不可以用于任何形式的开源项目,不可将源码放置于码云、github等开源平台,否则我们有权利收回产品授权及更新权限,并根据事态轻重追究相应法律责任。 +- 7.购买者用于公司的项目商用时购买必须提供公司名称,用于证明购买过我们的项目来进行商业用途,防范法律风险,我们承诺对购买公司信息信息严格保密,不会泄漏到互联网或用于产品宣传。 +- 8.购买者用于个人学习需提供姓名、手机联系方式进行实名认证,如无法提供请勿下单。 +- 9.如用于外包项目,购买者购买项目中的源码不可直接对外出售,npm run build 编译后的项目不受限制。 +- 10.如果您的公司基于 Vab Admin 系列自行研发的产品(如 OA、ERP、SASS 等)需对外销售,并且产品中包含我们框架的前端源码,那么您无法购买以上版本,需联系客服购买专属定制版本(不为第三方提供前端框架代码请忽略本条)。 +- 11.虚拟物品下单后不支持退货退款。 +- 12.购买者需遵守以上约定,最终解释权归 vab 系列著作权人所有,如果您无法遵守以上约定,请勿下单。 + +``` +注:以上协议以 //vuejs-core.cn/authorization/ 底部为准 +``` + +## 🔗 链接 + +- 💻 常规版演示地址:[admin-plus](//vuejs-core.cn/admin-plus/) +- 📝 使用文档:(文档地址及密码请查看 vip 群群公告第一条) +- 🗃 更新日志:[Releases](https://github.com/zxwk2024/admin-plus/releases) +- 📌 付费版及 vip 群购买地址:[购买地址](//vuejs-core.cn/authorization/) + + + +## ✅ 版权须知 + +Vab Admin 系列产品受国家计算机软件著作权保护(证书号:软著登字第 7051316 号), +禁止公开及传播产品源文件、二次出售等, +违者将承担相应的法律责任,并影响自身使用。 + +## 🧑‍💻 增值服务 + +### vip 群 + +- 每位购买 Admin 的用户均可获得 1 个免费的 vip 互助群免费入群资格,可反馈 bug、协助框架问题解答,无需额外购买 + +- 免费名额之外,额外加入 vip 群 (100/人 仅限已购买框架的的公司员工加入,购买后联系 微信 zxwk-bfq 即可) + +- [购买地址,网页右下角切换付款码即可](//vuejs-core.cn/authorization/) + +### 定制开发 + +- 承接各类基于 vab 开发的前端项目 +- 承接项目范围 3K+ 至 无上限 +- 支持签订合同 +- 支持提供发票 +- 结算流程:前期款(50%)- 中期款(30%)- 尾款(20%) +- 联系方式:见当前页底部 + +### 企业一对一远程培训 + +- 承接一对一远程培训服务(支持提供发票) +- 承接时间: 周一至周六上午 10 点 - 晚上 10 点 +- 价格:400 - 10000 +- 承接方式:单次、包月、包年 +- 联系方式:见当前页底部 + +### 个人一对一技术指导 + +- 承接时间: 周一至周六上午 10 点 - 晚上 10 点 +- 价格:300 - 500 +- 承接方式:单日 +- 支持零基础远程教学(学员需学习刻苦,有上进心) +- 学员需完成老师布置的任务 +- 联系方式:见当前页底部 + +### 联系方式 + +```txt + +微信客服:zxwk-bfq (备注来意) + + +邮件标题:企业一对一远程培训 - 公司名称,定制开发 - 公司名称,一对一技术支持 - 公司名称 + +邮件内容:大致描述 + 联系方式 + 预估需要时间 + 预算 + +后续: 收到邮件后,工作人员会于第一时间回复 + +``` diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 0000000..f47f7db --- /dev/null +++ b/babel.config.js @@ -0,0 +1,3 @@ +module.exports = { + presets: ['@vue/cli-plugin-babel/preset'], +} diff --git a/git.sh b/git.sh new file mode 100644 index 0000000..601d88f --- /dev/null +++ b/git.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +set -e +git config --global http.proxy http://127.0.0.1:4780; +git config --global https.proxy https://127.0.0.1:4780; + +exec /bin/bash \ No newline at end of file diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 0000000..c2c6000 --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "baseUrl": "./", + "moduleResolution": "node", + "allowSyntheticDefaultImports": true, + "paths": { + "~/*": ["*"], + "@/*": ["src/*"], + "/#/*": ["types/*"], + "@vab/*": ["library/*"], + "@gp": ["library/plugins/vab"] + }, + "lib": ["esnext", "dom", "dom.iterable", "scripthost"] + }, + "exclude": ["node_modules", "dist"] +} diff --git a/library/build/chainWebpack/banner/config.ts b/library/build/chainWebpack/banner/config.ts new file mode 100644 index 0000000..0c5b4fa --- /dev/null +++ b/library/build/chainWebpack/banner/config.ts @@ -0,0 +1,6 @@ +module.exports = { + webpackBanner: + ' build: Vue Admin' + + ' Plus \n copyright: vue-admin-' + + 'beautiful.com \n time: ', +} diff --git a/library/build/chainWebpack/banner/index.ts b/library/build/chainWebpack/banner/index.ts new file mode 100644 index 0000000..30230d1 --- /dev/null +++ b/library/build/chainWebpack/banner/index.ts @@ -0,0 +1,12 @@ +const Webpack = require('webpack') +const { webpackBanner } = require('./config.ts') + +module.exports = { + createBanner: (config) => { + config + .plugin('banner') + .use(Webpack.BannerPlugin, [ + `${webpackBanner}${process.env.VUE_APP_UPDATE_TIME}`, + ]) + }, +} diff --git a/library/build/chainWebpack/build7z/index.ts b/library/build/chainWebpack/build7z/index.ts new file mode 100644 index 0000000..3d85d0f --- /dev/null +++ b/library/build/chainWebpack/build7z/index.ts @@ -0,0 +1,22 @@ +const dayjs = require('dayjs') +const { outputDir, abbreviation } = require('../../../../src/config') +const FileManagerPlugin = require('filemanager-webpack-plugin') + +module.exports = { + createBuild7z: (config) => { + config.plugin('fileManager').use(FileManagerPlugin, [ + { + events: { + onEnd: { + archive: [ + { + source: `./${outputDir}`, + destination: `./${outputDir}/${abbreviation}_${dayjs().unix()}.zip`, + }, + ], + }, + }, + }, + ]) + }, +} diff --git a/library/build/chainWebpack/gzip/index.ts b/library/build/chainWebpack/gzip/index.ts new file mode 100644 index 0000000..f8b8c27 --- /dev/null +++ b/library/build/chainWebpack/gzip/index.ts @@ -0,0 +1,16 @@ +const productionGzipExtensions = ['html', 'js', 'css', 'svg'] +const CompressionWebpackPlugin = require('compression-webpack-plugin') + +module.exports = { + createGzip: (config) => { + config.plugin('compression').use(CompressionWebpackPlugin, [ + { + filename: '[path][base].gz[query]', + algorithm: 'gzip', + test: new RegExp(`\\.(${productionGzipExtensions.join('|')})$`), + threshold: 8192, + minRatio: 0.8, + }, + ]) + }, +} diff --git a/library/build/chainWebpack/imageCompression/index.ts b/library/build/chainWebpack/imageCompression/index.ts new file mode 100644 index 0000000..9f818b5 --- /dev/null +++ b/library/build/chainWebpack/imageCompression/index.ts @@ -0,0 +1,12 @@ +module.exports = { + createImageCompression: (config) => { + config.module + .rule('images') + .use('image-webpack-loader') + .loader('image-webpack-loader') + .options({ + bypassOnDebug: true, + }) + .end() + }, +} diff --git a/library/build/chainWebpack/index.ts b/library/build/chainWebpack/index.ts new file mode 100644 index 0000000..e928719 --- /dev/null +++ b/library/build/chainWebpack/index.ts @@ -0,0 +1,43 @@ +const { createGzip } = require('./gzip/index.ts') +const { createBanner } = require('./banner/index.ts') +const { createBuild7z } = require('./build7z/index.ts') +const { createSvgSprite } = require('./svgSprite/index.ts') +const { createOptimization } = require('./optimization/index.ts') +const { createSourceInjector } = require('./sourceInjector/index.ts') +const { createImageCompression } = require('./imageCompression/index.ts') +const { build7z, buildGzip, imageCompression } = require('../../../src/config') +const path = require('path') + +module.exports = { + createChainWebpack: (env, config) => { + config.resolve.symlinks(true) + createBanner(config) + createSvgSprite(config) + if (env === 'production') { + if (build7z) createBuild7z(config) + if (buildGzip) createGzip(config) + if (imageCompression && process.env.VAB_VARIABLE !== 'website') + createImageCompression(config) + createOptimization(config) + } + if (env === 'development') config.devtool('cheap-module-source-map') + createSourceInjector(config) + + // 添加一些构建优化 + // 避免处理node_modules中已经编译过的文件 + config.module + .rule('js') + .include.add(path.resolve('src')) + .add(path.resolve('library')) + .end() + .exclude.add(/node_modules/) + .end() + + // 优化构建性能 + config.plugin('fork-ts-checker').tap((options) => { + options[0].formatter = 'codeframe' + options[0].async = false + return options + }) + }, +} diff --git a/library/build/chainWebpack/optimization/index.ts b/library/build/chainWebpack/optimization/index.ts new file mode 100644 index 0000000..aea1950 --- /dev/null +++ b/library/build/chainWebpack/optimization/index.ts @@ -0,0 +1,74 @@ +const rely = require('call-' + 'rely') +const { resolve } = require('path') + +module.exports = { + createOptimization: (config) => { + process.env['VUE_AP' + 'P_RELY'] = rely + config.performance.set('hints', false) + config.optimization.splitChunks({ + automaticNameDelimiter: '-', + chunks: 'all', + cacheGroups: { + // 默认缓存组 + default: { + minChunks: 2, + priority: -20, + reuseExistingChunk: true, + }, + // 公共chunk + common: { + name: 'vab-common', + minChunks: 2, + priority: -10, + chunks: 'initial', + maxInitialRequests: 5, + minSize: 0, + }, + chunk: { + name: 'vab-chunk', + test: /[\\/]node_modules[\\/]/, + minSize: 131072, + maxSize: 524288, + chunks: 'initial', + minChunks: 2, + priority: 10, + }, + vue: { + name: 'vue', + test: /[\\/]node_modules[\\/](vue(.*)|core-js)[\\/]/, + chunks: 'initial', + priority: 20, + }, + elementPlus: { + name: 'element-plus', + test: /[\\/]node_modules[\\/]_?element-plus(.*)/, + priority: 30, + chunks: 'all', + }, + extra: { + name: 'vab-plugins', + test: resolve('src/plugins'), + priority: 40, + }, + components: { + name: 'vab-components', + test: resolve('library/components'), + priority: 50, + }, + xlsx: { + name: 'xlsx', + test: /[\\/]node_modules[\\/]_?xlsx(.*)/, + priority: 60, + }, + echarts: { + name: 'echarts', + test: /[\\/]node_modules[\\/](echarts|zrender)[\\/]/, + priority: 65, + chunks: 'all', + }, + }, + }) + // 配置runtimeChunk + config.optimization.runtimeChunk('single') + }, +} diff --git a/library/build/chainWebpack/sourceInjector/index.ts b/library/build/chainWebpack/sourceInjector/index.ts new file mode 100644 index 0000000..a680994 --- /dev/null +++ b/library/build/chainWebpack/sourceInjector/index.ts @@ -0,0 +1,11 @@ +const injector = require.resolve('./injector.ts') + +module.exports = { + createSourceInjector: (config) => { + config.module + .rule('vue') + .use('vue-filename-injector') + .loader(injector) + .after('vue-loader') + }, +} diff --git a/library/build/chainWebpack/sourceInjector/injector.ts b/library/build/chainWebpack/sourceInjector/injector.ts new file mode 100644 index 0000000..ca817f6 --- /dev/null +++ b/library/build/chainWebpack/sourceInjector/injector.ts @@ -0,0 +1,14 @@ +const { relative } = require('path') + +const blockName = 'vue-filename-injector' +module.exports = function (content) { + const { rootContext, resourcePath } = this + const context = rootContext || process.cwd() + const filePath = relative(context, resourcePath).replace(/\\/g, '/') + content += `<${blockName}> + export default function (Component) { + Component.__source = ${JSON.stringify(filePath)} + } + ` + return content +} diff --git a/library/build/chainWebpack/svgSprite/index.ts b/library/build/chainWebpack/svgSprite/index.ts new file mode 100644 index 0000000..e4e4fec --- /dev/null +++ b/library/build/chainWebpack/svgSprite/index.ts @@ -0,0 +1,15 @@ +const { resolve } = require('path') + +module.exports = { + createSvgSprite: (config) => { + config.module.rule('svg').exclude.add(resolve('src/icon')) + config.module + .rule('vabIcon') + .test(/\.svg$/) + .include.add(resolve('src/icon')) + .end() + .use('svg-sprite-loader') + .loader('svg-sprite-loader') + .options({ symbolId: 'vab-icon-[name]' }) + }, +} diff --git a/library/build/index.ts b/library/build/index.ts new file mode 100644 index 0000000..46b6960 --- /dev/null +++ b/library/build/index.ts @@ -0,0 +1,7 @@ +const { createVuePlugin } = require('./vuePlugins/index.ts') +const { createChainWebpack } = require('./chainWebpack/index.ts') + +module.exports = { + createVuePlugin, + createChainWebpack, +} diff --git a/library/build/vuePlugins/auto-imports.d.ts b/library/build/vuePlugins/auto-imports.d.ts new file mode 100644 index 0000000..6b8ace5 --- /dev/null +++ b/library/build/vuePlugins/auto-imports.d.ts @@ -0,0 +1,322 @@ +/* eslint-disable */ +/* prettier-ignore */ +// @ts-nocheck +// noinspection JSUnusedGlobalSymbols +// Generated by unplugin-auto-import +export {} +declare global { + const EffectScope: typeof import('vue')['EffectScope'] + const ElLoading: typeof import('element-plus/es')['ElLoading'] + const ElMessage: typeof import('element-plus/es')['ElMessage'] + const ElMessageBox: typeof import('element-plus/es')['ElMessageBox'] + const ElNotification: typeof import('element-plus/es')['ElNotification'] + const acceptHMRUpdate: typeof import('pinia')['acceptHMRUpdate'] + const asyncComputed: typeof import('@vueuse/core')['asyncComputed'] + const autoResetRef: typeof import('@vueuse/core')['autoResetRef'] + const axios: typeof import('axios')['default'] + const computed: typeof import('vue')['computed'] + const computedAsync: typeof import('@vueuse/core')['computedAsync'] + const computedEager: typeof import('@vueuse/core')['computedEager'] + const computedInject: typeof import('@vueuse/core')['computedInject'] + const computedWithControl: typeof import('@vueuse/core')['computedWithControl'] + const controlledComputed: typeof import('@vueuse/core')['controlledComputed'] + const controlledRef: typeof import('@vueuse/core')['controlledRef'] + const createApp: typeof import('vue')['createApp'] + const createEventHook: typeof import('@vueuse/core')['createEventHook'] + const createGlobalState: typeof import('@vueuse/core')['createGlobalState'] + const createInjectionState: typeof import('@vueuse/core')['createInjectionState'] + const createPinia: typeof import('pinia')['createPinia'] + const createReactiveFn: typeof import('@vueuse/core')['createReactiveFn'] + const createRef: typeof import('@vueuse/core')['createRef'] + const createReusableTemplate: typeof import('@vueuse/core')['createReusableTemplate'] + const createSharedComposable: typeof import('@vueuse/core')['createSharedComposable'] + const createTemplatePromise: typeof import('@vueuse/core')['createTemplatePromise'] + const createUnrefFn: typeof import('@vueuse/core')['createUnrefFn'] + const customRef: typeof import('vue')['customRef'] + const debouncedRef: typeof import('@vueuse/core')['debouncedRef'] + const debouncedWatch: typeof import('@vueuse/core')['debouncedWatch'] + const defineAsyncComponent: typeof import('vue')['defineAsyncComponent'] + const defineComponent: typeof import('vue')['defineComponent'] + const defineStore: typeof import('pinia')['defineStore'] + const eagerComputed: typeof import('@vueuse/core')['eagerComputed'] + const effectScope: typeof import('vue')['effectScope'] + const extendRef: typeof import('@vueuse/core')['extendRef'] + const getActivePinia: typeof import('pinia')['getActivePinia'] + const getCurrentInstance: typeof import('vue')['getCurrentInstance'] + const getCurrentScope: typeof import('vue')['getCurrentScope'] + const h: typeof import('vue')['h'] + const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch'] + const inject: typeof import('vue')['inject'] + const injectLocal: typeof import('@vueuse/core')['injectLocal'] + const isDefined: typeof import('@vueuse/core')['isDefined'] + const isProxy: typeof import('vue')['isProxy'] + const isReactive: typeof import('vue')['isReactive'] + const isReadonly: typeof import('vue')['isReadonly'] + const isRef: typeof import('vue')['isRef'] + const makeDestructurable: typeof import('@vueuse/core')['makeDestructurable'] + const manualResetRef: typeof import('@vueuse/core')['manualResetRef'] + const mapActions: typeof import('pinia')['mapActions'] + const mapGetters: typeof import('pinia')['mapGetters'] + const mapState: typeof import('pinia')['mapState'] + const mapStores: typeof import('pinia')['mapStores'] + const mapWritableState: typeof import('pinia')['mapWritableState'] + const markRaw: typeof import('vue')['markRaw'] + const nextTick: typeof import('vue')['nextTick'] + const onActivated: typeof import('vue')['onActivated'] + const onBeforeMount: typeof import('vue')['onBeforeMount'] + const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave'] + const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate'] + const onBeforeUnmount: typeof import('vue')['onBeforeUnmount'] + const onBeforeUpdate: typeof import('vue')['onBeforeUpdate'] + const onClickOutside: typeof import('@vueuse/core')['onClickOutside'] + const onDeactivated: typeof import('vue')['onDeactivated'] + const onElementRemoval: typeof import('@vueuse/core')['onElementRemoval'] + const onErrorCaptured: typeof import('vue')['onErrorCaptured'] + const onKeyStroke: typeof import('@vueuse/core')['onKeyStroke'] + const onLongPress: typeof import('@vueuse/core')['onLongPress'] + const onMounted: typeof import('vue')['onMounted'] + const onRenderTracked: typeof import('vue')['onRenderTracked'] + const onRenderTriggered: typeof import('vue')['onRenderTriggered'] + const onScopeDispose: typeof import('vue')['onScopeDispose'] + const onServerPrefetch: typeof import('vue')['onServerPrefetch'] + const onStartTyping: typeof import('@vueuse/core')['onStartTyping'] + const onUnmounted: typeof import('vue')['onUnmounted'] + const onUpdated: typeof import('vue')['onUpdated'] + const onWatcherCleanup: typeof import('vue')['onWatcherCleanup'] + const pausableWatch: typeof import('@vueuse/core')['pausableWatch'] + const provide: typeof import('vue')['provide'] + const provideLocal: typeof import('@vueuse/core')['provideLocal'] + const reactify: typeof import('@vueuse/core')['reactify'] + const reactifyObject: typeof import('@vueuse/core')['reactifyObject'] + const reactive: typeof import('vue')['reactive'] + const reactiveComputed: typeof import('@vueuse/core')['reactiveComputed'] + const reactiveOmit: typeof import('@vueuse/core')['reactiveOmit'] + const reactivePick: typeof import('@vueuse/core')['reactivePick'] + const readonly: typeof import('vue')['readonly'] + const ref: typeof import('vue')['ref'] + const refAutoReset: typeof import('@vueuse/core')['refAutoReset'] + const refDebounced: typeof import('@vueuse/core')['refDebounced'] + const refDefault: typeof import('@vueuse/core')['refDefault'] + const refManualReset: typeof import('@vueuse/core')['refManualReset'] + const refThrottled: typeof import('@vueuse/core')['refThrottled'] + const refWithControl: typeof import('@vueuse/core')['refWithControl'] + const resolveComponent: typeof import('vue')['resolveComponent'] + const resolveRef: typeof import('@vueuse/core')['resolveRef'] + const resolveUnref: typeof import('@vueuse/core')['resolveUnref'] + const setActivePinia: typeof import('pinia')['setActivePinia'] + const setMapStoreSuffix: typeof import('pinia')['setMapStoreSuffix'] + const shallowReactive: typeof import('vue')['shallowReactive'] + const shallowReadonly: typeof import('vue')['shallowReadonly'] + const shallowRef: typeof import('vue')['shallowRef'] + const storeToRefs: typeof import('pinia')['storeToRefs'] + const syncRef: typeof import('@vueuse/core')['syncRef'] + const syncRefs: typeof import('@vueuse/core')['syncRefs'] + const templateRef: typeof import('@vueuse/core')['templateRef'] + const throttledRef: typeof import('@vueuse/core')['throttledRef'] + const throttledWatch: typeof import('@vueuse/core')['throttledWatch'] + const toRaw: typeof import('vue')['toRaw'] + const toReactive: typeof import('@vueuse/core')['toReactive'] + const toRef: typeof import('vue')['toRef'] + const toRefs: typeof import('vue')['toRefs'] + const toValue: typeof import('vue')['toValue'] + const triggerRef: typeof import('vue')['triggerRef'] + const tryOnBeforeMount: typeof import('@vueuse/core')['tryOnBeforeMount'] + const tryOnBeforeUnmount: typeof import('@vueuse/core')['tryOnBeforeUnmount'] + const tryOnMounted: typeof import('@vueuse/core')['tryOnMounted'] + const tryOnScopeDispose: typeof import('@vueuse/core')['tryOnScopeDispose'] + const tryOnUnmounted: typeof import('@vueuse/core')['tryOnUnmounted'] + const unref: typeof import('vue')['unref'] + const unrefElement: typeof import('@vueuse/core')['unrefElement'] + const until: typeof import('@vueuse/core')['until'] + const useActiveElement: typeof import('@vueuse/core')['useActiveElement'] + const useAnimate: typeof import('@vueuse/core')['useAnimate'] + const useArrayDifference: typeof import('@vueuse/core')['useArrayDifference'] + const useArrayEvery: typeof import('@vueuse/core')['useArrayEvery'] + const useArrayFilter: typeof import('@vueuse/core')['useArrayFilter'] + const useArrayFind: typeof import('@vueuse/core')['useArrayFind'] + const useArrayFindIndex: typeof import('@vueuse/core')['useArrayFindIndex'] + const useArrayFindLast: typeof import('@vueuse/core')['useArrayFindLast'] + const useArrayIncludes: typeof import('@vueuse/core')['useArrayIncludes'] + const useArrayJoin: typeof import('@vueuse/core')['useArrayJoin'] + const useArrayMap: typeof import('@vueuse/core')['useArrayMap'] + const useArrayReduce: typeof import('@vueuse/core')['useArrayReduce'] + const useArraySome: typeof import('@vueuse/core')['useArraySome'] + const useArrayUnique: typeof import('@vueuse/core')['useArrayUnique'] + const useAsyncQueue: typeof import('@vueuse/core')['useAsyncQueue'] + const useAsyncState: typeof import('@vueuse/core')['useAsyncState'] + const useAttrs: typeof import('vue')['useAttrs'] + const useBase64: typeof import('@vueuse/core')['useBase64'] + const useBattery: typeof import('@vueuse/core')['useBattery'] + const useBluetooth: typeof import('@vueuse/core')['useBluetooth'] + const useBreakpoints: typeof import('@vueuse/core')['useBreakpoints'] + const useBroadcastChannel: typeof import('@vueuse/core')['useBroadcastChannel'] + const useBrowserLocation: typeof import('@vueuse/core')['useBrowserLocation'] + const useCached: typeof import('@vueuse/core')['useCached'] + const useClipboard: typeof import('@vueuse/core')['useClipboard'] + const useClipboardItems: typeof import('@vueuse/core')['useClipboardItems'] + const useCloned: typeof import('@vueuse/core')['useCloned'] + const useColorMode: typeof import('@vueuse/core')['useColorMode'] + const useConfirmDialog: typeof import('@vueuse/core')['useConfirmDialog'] + const useCountdown: typeof import('@vueuse/core')['useCountdown'] + const useCounter: typeof import('@vueuse/core')['useCounter'] + const useCssModule: typeof import('vue')['useCssModule'] + const useCssVar: typeof import('@vueuse/core')['useCssVar'] + const useCssVars: typeof import('vue')['useCssVars'] + const useCurrentElement: typeof import('@vueuse/core')['useCurrentElement'] + const useCycleList: typeof import('@vueuse/core')['useCycleList'] + const useDark: typeof import('@vueuse/core')['useDark'] + const useDateFormat: typeof import('@vueuse/core')['useDateFormat'] + const useDebounce: typeof import('@vueuse/core')['useDebounce'] + const useDebounceFn: typeof import('@vueuse/core')['useDebounceFn'] + const useDebouncedRefHistory: typeof import('@vueuse/core')['useDebouncedRefHistory'] + const useDeviceMotion: typeof import('@vueuse/core')['useDeviceMotion'] + const useDeviceOrientation: typeof import('@vueuse/core')['useDeviceOrientation'] + const useDevicePixelRatio: typeof import('@vueuse/core')['useDevicePixelRatio'] + const useDevicesList: typeof import('@vueuse/core')['useDevicesList'] + const useDisplayMedia: typeof import('@vueuse/core')['useDisplayMedia'] + const useDocumentVisibility: typeof import('@vueuse/core')['useDocumentVisibility'] + const useDraggable: typeof import('@vueuse/core')['useDraggable'] + const useDropZone: typeof import('@vueuse/core')['useDropZone'] + const useElementBounding: typeof import('@vueuse/core')['useElementBounding'] + const useElementByPoint: typeof import('@vueuse/core')['useElementByPoint'] + const useElementHover: typeof import('@vueuse/core')['useElementHover'] + const useElementSize: typeof import('@vueuse/core')['useElementSize'] + const useElementVisibility: typeof import('@vueuse/core')['useElementVisibility'] + const useEventBus: typeof import('@vueuse/core')['useEventBus'] + const useEventListener: typeof import('@vueuse/core')['useEventListener'] + const useEventSource: typeof import('@vueuse/core')['useEventSource'] + const useEyeDropper: typeof import('@vueuse/core')['useEyeDropper'] + const useFavicon: typeof import('@vueuse/core')['useFavicon'] + const useFetch: typeof import('@vueuse/core')['useFetch'] + const useFileDialog: typeof import('@vueuse/core')['useFileDialog'] + const useFileSystemAccess: typeof import('@vueuse/core')['useFileSystemAccess'] + const useFocus: typeof import('@vueuse/core')['useFocus'] + const useFocusWithin: typeof import('@vueuse/core')['useFocusWithin'] + const useFps: typeof import('@vueuse/core')['useFps'] + const useFullscreen: typeof import('@vueuse/core')['useFullscreen'] + const useGamepad: typeof import('@vueuse/core')['useGamepad'] + const useGeolocation: typeof import('@vueuse/core')['useGeolocation'] + const useI18n: typeof import('vue-i18n')['useI18n'] + const useId: typeof import('vue')['useId'] + const useIdle: typeof import('@vueuse/core')['useIdle'] + const useImage: typeof import('@vueuse/core')['useImage'] + const useInfiniteScroll: typeof import('@vueuse/core')['useInfiniteScroll'] + const useIntersectionObserver: typeof import('@vueuse/core')['useIntersectionObserver'] + const useInterval: typeof import('@vueuse/core')['useInterval'] + const useIntervalFn: typeof import('@vueuse/core')['useIntervalFn'] + const useKeyModifier: typeof import('@vueuse/core')['useKeyModifier'] + const useLastChanged: typeof import('@vueuse/core')['useLastChanged'] + const useLink: typeof import('vue-router')['useLink'] + const useLocalStorage: typeof import('@vueuse/core')['useLocalStorage'] + const useMagicKeys: typeof import('@vueuse/core')['useMagicKeys'] + const useManualRefHistory: typeof import('@vueuse/core')['useManualRefHistory'] + const useMediaControls: typeof import('@vueuse/core')['useMediaControls'] + const useMediaQuery: typeof import('@vueuse/core')['useMediaQuery'] + const useMemoize: typeof import('@vueuse/core')['useMemoize'] + const useMemory: typeof import('@vueuse/core')['useMemory'] + const useModel: typeof import('vue')['useModel'] + const useMounted: typeof import('@vueuse/core')['useMounted'] + const useMouse: typeof import('@vueuse/core')['useMouse'] + const useMouseInElement: typeof import('@vueuse/core')['useMouseInElement'] + const useMousePressed: typeof import('@vueuse/core')['useMousePressed'] + const useMutationObserver: typeof import('@vueuse/core')['useMutationObserver'] + const useNavigatorLanguage: typeof import('@vueuse/core')['useNavigatorLanguage'] + const useNetwork: typeof import('@vueuse/core')['useNetwork'] + const useNow: typeof import('@vueuse/core')['useNow'] + const useObjectUrl: typeof import('@vueuse/core')['useObjectUrl'] + const useOffsetPagination: typeof import('@vueuse/core')['useOffsetPagination'] + const useOnline: typeof import('@vueuse/core')['useOnline'] + const usePageLeave: typeof import('@vueuse/core')['usePageLeave'] + const useParallax: typeof import('@vueuse/core')['useParallax'] + const useParentElement: typeof import('@vueuse/core')['useParentElement'] + const usePerformanceObserver: typeof import('@vueuse/core')['usePerformanceObserver'] + const usePermission: typeof import('@vueuse/core')['usePermission'] + const usePointer: typeof import('@vueuse/core')['usePointer'] + const usePointerLock: typeof import('@vueuse/core')['usePointerLock'] + const usePointerSwipe: typeof import('@vueuse/core')['usePointerSwipe'] + const usePreferredColorScheme: typeof import('@vueuse/core')['usePreferredColorScheme'] + const usePreferredContrast: typeof import('@vueuse/core')['usePreferredContrast'] + const usePreferredDark: typeof import('@vueuse/core')['usePreferredDark'] + const usePreferredLanguages: typeof import('@vueuse/core')['usePreferredLanguages'] + const usePreferredReducedMotion: typeof import('@vueuse/core')['usePreferredReducedMotion'] + const usePreferredReducedTransparency: typeof import('@vueuse/core')['usePreferredReducedTransparency'] + const usePrevious: typeof import('@vueuse/core')['usePrevious'] + const useRafFn: typeof import('@vueuse/core')['useRafFn'] + const useRefHistory: typeof import('@vueuse/core')['useRefHistory'] + const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver'] + const useRoute: typeof import('vue-router')['useRoute'] + const useRouter: typeof import('vue-router')['useRouter'] + const useSSRWidth: typeof import('@vueuse/core')['useSSRWidth'] + const useScreenOrientation: typeof import('@vueuse/core')['useScreenOrientation'] + const useScreenSafeArea: typeof import('@vueuse/core')['useScreenSafeArea'] + const useScriptTag: typeof import('@vueuse/core')['useScriptTag'] + const useScroll: typeof import('@vueuse/core')['useScroll'] + const useScrollLock: typeof import('@vueuse/core')['useScrollLock'] + const useSessionStorage: typeof import('@vueuse/core')['useSessionStorage'] + const useShare: typeof import('@vueuse/core')['useShare'] + const useSlots: typeof import('vue')['useSlots'] + const useSorted: typeof import('@vueuse/core')['useSorted'] + const useSpeechRecognition: typeof import('@vueuse/core')['useSpeechRecognition'] + const useSpeechSynthesis: typeof import('@vueuse/core')['useSpeechSynthesis'] + const useStepper: typeof import('@vueuse/core')['useStepper'] + const useStorage: typeof import('@vueuse/core')['useStorage'] + const useStorageAsync: typeof import('@vueuse/core')['useStorageAsync'] + const useStyleTag: typeof import('@vueuse/core')['useStyleTag'] + const useSupported: typeof import('@vueuse/core')['useSupported'] + const useSwipe: typeof import('@vueuse/core')['useSwipe'] + const useTemplateRef: typeof import('vue')['useTemplateRef'] + const useTemplateRefsList: typeof import('@vueuse/core')['useTemplateRefsList'] + const useTextDirection: typeof import('@vueuse/core')['useTextDirection'] + const useTextSelection: typeof import('@vueuse/core')['useTextSelection'] + const useTextareaAutosize: typeof import('@vueuse/core')['useTextareaAutosize'] + const useThrottle: typeof import('@vueuse/core')['useThrottle'] + const useThrottleFn: typeof import('@vueuse/core')['useThrottleFn'] + const useThrottledRefHistory: typeof import('@vueuse/core')['useThrottledRefHistory'] + const useTimeAgo: typeof import('@vueuse/core')['useTimeAgo'] + const useTimeAgoIntl: typeof import('@vueuse/core')['useTimeAgoIntl'] + const useTimeout: typeof import('@vueuse/core')['useTimeout'] + const useTimeoutFn: typeof import('@vueuse/core')['useTimeoutFn'] + const useTimeoutPoll: typeof import('@vueuse/core')['useTimeoutPoll'] + const useTimestamp: typeof import('@vueuse/core')['useTimestamp'] + const useTitle: typeof import('@vueuse/core')['useTitle'] + const useToNumber: typeof import('@vueuse/core')['useToNumber'] + const useToString: typeof import('@vueuse/core')['useToString'] + const useToggle: typeof import('@vueuse/core')['useToggle'] + const useTransition: typeof import('@vueuse/core')['useTransition'] + const useUrlSearchParams: typeof import('@vueuse/core')['useUrlSearchParams'] + const useUserMedia: typeof import('@vueuse/core')['useUserMedia'] + const useVModel: typeof import('@vueuse/core')['useVModel'] + const useVModels: typeof import('@vueuse/core')['useVModels'] + const useVibrate: typeof import('@vueuse/core')['useVibrate'] + const useVirtualList: typeof import('@vueuse/core')['useVirtualList'] + const useWakeLock: typeof import('@vueuse/core')['useWakeLock'] + const useWebNotification: typeof import('@vueuse/core')['useWebNotification'] + const useWebSocket: typeof import('@vueuse/core')['useWebSocket'] + const useWebWorker: typeof import('@vueuse/core')['useWebWorker'] + const useWebWorkerFn: typeof import('@vueuse/core')['useWebWorkerFn'] + const useWindowFocus: typeof import('@vueuse/core')['useWindowFocus'] + const useWindowScroll: typeof import('@vueuse/core')['useWindowScroll'] + const useWindowSize: typeof import('@vueuse/core')['useWindowSize'] + const watch: typeof import('vue')['watch'] + const watchArray: typeof import('@vueuse/core')['watchArray'] + const watchAtMost: typeof import('@vueuse/core')['watchAtMost'] + const watchDebounced: typeof import('@vueuse/core')['watchDebounced'] + const watchDeep: typeof import('@vueuse/core')['watchDeep'] + const watchEffect: typeof import('vue')['watchEffect'] + const watchIgnorable: typeof import('@vueuse/core')['watchIgnorable'] + const watchImmediate: typeof import('@vueuse/core')['watchImmediate'] + const watchOnce: typeof import('@vueuse/core')['watchOnce'] + const watchPausable: typeof import('@vueuse/core')['watchPausable'] + const watchPostEffect: typeof import('vue')['watchPostEffect'] + const watchSyncEffect: typeof import('vue')['watchSyncEffect'] + const watchThrottled: typeof import('@vueuse/core')['watchThrottled'] + const watchTriggerable: typeof import('@vueuse/core')['watchTriggerable'] + const watchWithFilter: typeof import('@vueuse/core')['watchWithFilter'] + const whenever: typeof import('@vueuse/core')['whenever'] +} +// for type re-export +declare global { + // @ts-ignore + export type { Component, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue' + import('vue') +} diff --git a/library/build/vuePlugins/components.d.ts b/library/build/vuePlugins/components.d.ts new file mode 100644 index 0000000..ee6da4e --- /dev/null +++ b/library/build/vuePlugins/components.d.ts @@ -0,0 +1,123 @@ +/* eslint-disable */ +/* prettier-ignore */ +// @ts-nocheck +// Generated by unplugin-vue-components +// Read more: https://github.com/vuejs/core/pull/3399 +export {} + +declare module 'vue' { + export interface GlobalComponents { + ElAlert: typeof import('element-plus/es')['ElAlert'] + ElAvatar: typeof import('element-plus/es')['ElAvatar'] + ElBacktop: typeof import('element-plus/es')['ElBacktop'] + ElBadge: typeof import('element-plus/es')['ElBadge'] + ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb'] + ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem'] + ElButton: typeof import('element-plus/es')['ElButton'] + ElButtonGroup: typeof import('element-plus/es')['ElButtonGroup'] + ElCalendar: typeof import('element-plus/es')['ElCalendar'] + ElCard: typeof import('element-plus/es')['ElCard'] + ElCarousel: typeof import('element-plus/es')['ElCarousel'] + ElCarouselItem: typeof import('element-plus/es')['ElCarouselItem'] + ElCascader: typeof import('element-plus/es')['ElCascader'] + ElCheckbox: typeof import('element-plus/es')['ElCheckbox'] + ElCheckboxButton: typeof import('element-plus/es')['ElCheckboxButton'] + ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup'] + ElCol: typeof import('element-plus/es')['ElCol'] + ElCollapse: typeof import('element-plus/es')['ElCollapse'] + ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem'] + ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider'] + ElDatePicker: typeof import('element-plus/es')['ElDatePicker'] + ElDescriptions: typeof import('element-plus/es')['ElDescriptions'] + ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem'] + ElDialog: typeof import('element-plus/es')['ElDialog'] + ElDivider: typeof import('element-plus/es')['ElDivider'] + ElDrawer: typeof import('element-plus/es')['ElDrawer'] + ElDropdown: typeof import('element-plus/es')['ElDropdown'] + ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem'] + ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu'] + ElEmpty: typeof import('element-plus/es')['ElEmpty'] + ElForm: typeof import('element-plus/es')['ElForm'] + ElFormItem: typeof import('element-plus/es')['ElFormItem'] + ElIcon: typeof import('element-plus/es')['ElIcon'] + ElImage: typeof import('element-plus/es')['ElImage'] + ElInput: typeof import('element-plus/es')['ElInput'] + ElInputNumber: typeof import('element-plus/es')['ElInputNumber'] + ElLink: typeof import('element-plus/es')['ElLink'] + ElMenu: typeof import('element-plus/es')['ElMenu'] + ElMenuItem: typeof import('element-plus/es')['ElMenuItem'] + ElOption: typeof import('element-plus/es')['ElOption'] + ElPageHeader: typeof import('element-plus/es')['ElPageHeader'] + ElPagination: typeof import('element-plus/es')['ElPagination'] + ElPopconfirm: typeof import('element-plus/es')['ElPopconfirm'] + ElPopover: typeof import('element-plus/es')['ElPopover'] + ElProgress: typeof import('element-plus/es')['ElProgress'] + ElRadio: typeof import('element-plus/es')['ElRadio'] + ElRadioButton: typeof import('element-plus/es')['ElRadioButton'] + ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup'] + ElRate: typeof import('element-plus/es')['ElRate'] + ElResult: typeof import('element-plus/es')['ElResult'] + ElRow: typeof import('element-plus/es')['ElRow'] + ElScrollbar: typeof import('element-plus/es')['ElScrollbar'] + ElSelect: typeof import('element-plus/es')['ElSelect'] + ElSkeleton: typeof import('element-plus/es')['ElSkeleton'] + ElSlider: typeof import('element-plus/es')['ElSlider'] + ElStep: typeof import('element-plus/es')['ElStep'] + ElSteps: typeof import('element-plus/es')['ElSteps'] + ElSubMenu: typeof import('element-plus/es')['ElSubMenu'] + ElSwitch: typeof import('element-plus/es')['ElSwitch'] + ElTable: typeof import('element-plus/es')['ElTable'] + ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] + ElTabPane: typeof import('element-plus/es')['ElTabPane'] + ElTabs: typeof import('element-plus/es')['ElTabs'] + ElTag: typeof import('element-plus/es')['ElTag'] + ElTimeline: typeof import('element-plus/es')['ElTimeline'] + ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem'] + ElTimePicker: typeof import('element-plus/es')['ElTimePicker'] + ElTimeSelect: typeof import('element-plus/es')['ElTimeSelect'] + ElTooltip: typeof import('element-plus/es')['ElTooltip'] + ElTransfer: typeof import('element-plus/es')['ElTransfer'] + ElTree: typeof import('element-plus/es')['ElTree'] + ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect'] + ElUpload: typeof import('element-plus/es')['ElUpload'] + RouterLink: typeof import('vue-router')['RouterLink'] + RouterView: typeof import('vue-router')['RouterView'] + VabApp: typeof import('./../../components/VabApp/index.vue')['default'] + VabAppMain: typeof import('./../../components/VabAppMain/index.vue')['default'] + VabAvatar: typeof import('./../../components/VabAvatar/index.vue')['default'] + VabBreadcrumb: typeof import('./../../components/VabBreadcrumb/index.vue')['default'] + VabCard: typeof import('./../../components/VabCard/index.vue')['default'] + VabColorfulCard: typeof import('./../../components/VabColorfulCard/index.vue')['default'] + VabColumnBar: typeof import('./../../components/VabColumnBar/index.vue')['default'] + VabErrorLog: typeof import('./../../components/VabErrorLog/index.vue')['default'] + VabFold: typeof import('./../../components/VabFold/index.vue')['default'] + VabFooter: typeof import('./../../components/VabFooter/index.vue')['default'] + VabFullScreen: typeof import('./../../components/VabFullScreen/index.vue')['default'] + VabHeader: typeof import('./../../components/VabHeader/index.vue')['default'] + VabLanguage: typeof import('./../../components/VabLanguage/index.vue')['default'] + VabLink: typeof import('./../../components/VabLink/index.vue')['default'] + VabLock: typeof import('./../../components/VabLock/index.vue')['default'] + VabLogo: typeof import('./../../components/VabLogo/index.vue')['default'] + VabMenu: typeof import('./../../components/VabMenu/index.vue')['default'] + VabMenuItem: typeof import('./../../components/VabMenu/components/VabMenuItem.vue')['default'] + VabNav: typeof import('./../../components/VabNav/index.vue')['default'] + VabNotice: typeof import('./../../components/VabNotice/index.vue')['default'] + VabQueryForm: typeof import('./../../components/VabQueryForm/index.vue')['default'] + VabQueryFormBottomPanel: typeof import('./../../components/VabQueryForm/components/VabQueryFormBottomPanel.vue')['default'] + VabQueryFormLeftPanel: typeof import('./../../components/VabQueryForm/components/VabQueryFormLeftPanel.vue')['default'] + VabQueryFormRightPanel: typeof import('./../../components/VabQueryForm/components/VabQueryFormRightPanel.vue')['default'] + VabQueryFormTopPanel: typeof import('./../../components/VabQueryForm/components/VabQueryFormTopPanel.vue')['default'] + VabRefresh: typeof import('./../../components/VabRefresh/index.vue')['default'] + VabRouterView: typeof import('./../../components/VabRouterView/index.vue')['default'] + VabSearch: typeof import('./../../components/VabSearch/index.vue')['default'] + VabSideBar: typeof import('./../../components/VabSideBar/index.vue')['default'] + VabSubMenu: typeof import('./../../components/VabMenu/components/VabSubMenu.vue')['default'] + VabTabs: typeof import('./../../components/VabTabs/index.vue')['default'] + VabTheme: typeof import('./../../components/VabTheme/index.vue')['default'] + VabThemeDrawer: typeof import('./../../components/VabTheme/components/VabThemeDrawer.vue')['default'] + VabThemeSetting: typeof import('./../../components/VabTheme/components/VabThemeSetting.vue')['default'] + } + export interface ComponentCustomProperties { + vLoading: typeof import('element-plus/es')['ElLoadingDirective'] + } +} diff --git a/library/build/vuePlugins/defineOptions/index.ts b/library/build/vuePlugins/defineOptions/index.ts new file mode 100644 index 0000000..c97547f --- /dev/null +++ b/library/build/vuePlugins/defineOptions/index.ts @@ -0,0 +1,5 @@ +module.exports = { + createDefineOptions: () => [ + require('unplugin-vue-define-options/webpack')(), + ], +} diff --git a/library/build/vuePlugins/definePlugin/index.ts b/library/build/vuePlugins/definePlugin/index.ts new file mode 100644 index 0000000..a3b3861 --- /dev/null +++ b/library/build/vuePlugins/definePlugin/index.ts @@ -0,0 +1,10 @@ +// @ts-ignore +const Webpack = require('webpack') + +module.exports = { + createDefinePlugin: () => [ + new Webpack.DefinePlugin({ + __APP_INFO__: process.env.VUE_APP_INFO, + }), + ], +} diff --git a/library/build/vuePlugins/index.ts b/library/build/vuePlugins/index.ts new file mode 100644 index 0000000..e1fb4fa --- /dev/null +++ b/library/build/vuePlugins/index.ts @@ -0,0 +1,19 @@ +const { createUnPlugin } = require('vue-' + 'unplugins') +const { createWebpackBar } = require('./webpack' + 'Bar/index.ts') +const { createDefineOptions } = require('./defineOptions/index.ts') +const { createDefinePlugin } = require('./definePlugin/index.ts') +const { createProvidePlugin } = require('./providePlugin/index.ts') +const { createMinChunkSizePlugin } = require('./minChunkSizePlugin/index.ts') + +const dev = process.env.NODE_ENV === 'development' +module.exports = { + createVuePlugin: () => [ + ...createDefineOptions(), + ...createUnPlugin(), + require('unplugin-element-plus/webpack')(), + ...createWebpackBar(), + ...createDefinePlugin(), + ...createProvidePlugin(), + ...(dev ? [] : createMinChunkSizePlugin()), + ], +} diff --git a/library/build/vuePlugins/minChunkSizePlugin/index.ts b/library/build/vuePlugins/minChunkSizePlugin/index.ts new file mode 100644 index 0000000..ed650a6 --- /dev/null +++ b/library/build/vuePlugins/minChunkSizePlugin/index.ts @@ -0,0 +1,14 @@ +// @ts-ignore +const Webpack = require('webpack') +const { buildOptimize } = require('../../../../src/config') + +module.exports = { + createMinChunkSizePlugin: () => + buildOptimize + ? [] + : [ + new Webpack.optimize.MinChunkSizePlugin({ + minChunkSize: 1024 * 300, + }), + ], +} diff --git a/library/build/vuePlugins/providePlugin/index.ts b/library/build/vuePlugins/providePlugin/index.ts new file mode 100644 index 0000000..42817e0 --- /dev/null +++ b/library/build/vuePlugins/providePlugin/index.ts @@ -0,0 +1,7 @@ +// @ts-ignore +const Webpack = require('webpack') +const { providePlugin } = require('../../../../src/config') + +module.exports = { + createProvidePlugin: () => [new Webpack.ProvidePlugin(providePlugin)], +} diff --git a/library/build/vuePlugins/webpackBar/index.ts b/library/build/vuePlugins/webpackBar/index.ts new file mode 100644 index 0000000..4b3b0aa --- /dev/null +++ b/library/build/vuePlugins/webpackBar/index.ts @@ -0,0 +1,10 @@ +const WebpackBar = require('webpackbar') +const { version } = require('../../../../package.json') + +module.exports = { + createWebpackBar: () => [ + new WebpackBar({ + name: `Vue-` + `Admin` + `-Plus ${version}`, + }), + ], +} diff --git a/library/components/VabApp/index.vue b/library/components/VabApp/index.vue new file mode 100644 index 0000000..9a51ebe --- /dev/null +++ b/library/components/VabApp/index.vue @@ -0,0 +1,45 @@ + + + diff --git a/library/components/VabAppMain/index.vue b/library/components/VabAppMain/index.vue new file mode 100644 index 0000000..5a523bd --- /dev/null +++ b/library/components/VabAppMain/index.vue @@ -0,0 +1,28 @@ + + + diff --git a/library/components/VabAvatar/index.vue b/library/components/VabAvatar/index.vue new file mode 100644 index 0000000..a977101 --- /dev/null +++ b/library/components/VabAvatar/index.vue @@ -0,0 +1,109 @@ + + + + + diff --git a/library/components/VabBreadcrumb/index.vue b/library/components/VabBreadcrumb/index.vue new file mode 100644 index 0000000..88db40e --- /dev/null +++ b/library/components/VabBreadcrumb/index.vue @@ -0,0 +1,65 @@ + + + + + diff --git a/library/components/VabCard/index.vue b/library/components/VabCard/index.vue new file mode 100644 index 0000000..50fa7e4 --- /dev/null +++ b/library/components/VabCard/index.vue @@ -0,0 +1,65 @@ + + + + + diff --git a/library/components/VabColorfulCard/index.vue b/library/components/VabColorfulCard/index.vue new file mode 100644 index 0000000..bffb1f6 --- /dev/null +++ b/library/components/VabColorfulCard/index.vue @@ -0,0 +1,69 @@ + + + + + diff --git a/library/components/VabColumnBar/index.vue b/library/components/VabColumnBar/index.vue new file mode 100644 index 0000000..c6ba066 --- /dev/null +++ b/library/components/VabColumnBar/index.vue @@ -0,0 +1,392 @@ + + + + + diff --git a/library/components/VabErrorLog/index.vue b/library/components/VabErrorLog/index.vue new file mode 100644 index 0000000..a2b1059 --- /dev/null +++ b/library/components/VabErrorLog/index.vue @@ -0,0 +1,104 @@ + + + + + diff --git a/library/components/VabFold/index.vue b/library/components/VabFold/index.vue new file mode 100644 index 0000000..7640720 --- /dev/null +++ b/library/components/VabFold/index.vue @@ -0,0 +1,22 @@ + + + + + diff --git a/library/components/VabFooter/index.vue b/library/components/VabFooter/index.vue new file mode 100644 index 0000000..2a731a3 --- /dev/null +++ b/library/components/VabFooter/index.vue @@ -0,0 +1,47 @@ + + + + + diff --git a/library/components/VabFullScreen/index.vue b/library/components/VabFullScreen/index.vue new file mode 100644 index 0000000..afc24ba --- /dev/null +++ b/library/components/VabFullScreen/index.vue @@ -0,0 +1,16 @@ + + + diff --git a/library/components/VabHeader/index.vue b/library/components/VabHeader/index.vue new file mode 100644 index 0000000..78327fe --- /dev/null +++ b/library/components/VabHeader/index.vue @@ -0,0 +1,233 @@ + + + + + diff --git a/library/components/VabLanguage/index.vue b/library/components/VabLanguage/index.vue new file mode 100644 index 0000000..35cf37e --- /dev/null +++ b/library/components/VabLanguage/index.vue @@ -0,0 +1,30 @@ + + + diff --git a/library/components/VabLink/index.vue b/library/components/VabLink/index.vue new file mode 100644 index 0000000..f400ed2 --- /dev/null +++ b/library/components/VabLink/index.vue @@ -0,0 +1,27 @@ + + + diff --git a/library/components/VabLock/index.vue b/library/components/VabLock/index.vue new file mode 100644 index 0000000..a0a71ec --- /dev/null +++ b/library/components/VabLock/index.vue @@ -0,0 +1,225 @@ + + + + + diff --git a/library/components/VabLogo/index.vue b/library/components/VabLogo/index.vue new file mode 100644 index 0000000..becdac3 --- /dev/null +++ b/library/components/VabLogo/index.vue @@ -0,0 +1,123 @@ + + + + + diff --git a/library/components/VabMenu/components/VabMenuItem.vue b/library/components/VabMenu/components/VabMenuItem.vue new file mode 100644 index 0000000..fee9da3 --- /dev/null +++ b/library/components/VabMenu/components/VabMenuItem.vue @@ -0,0 +1,82 @@ + + + + + diff --git a/library/components/VabMenu/components/VabSubMenu.vue b/library/components/VabMenu/components/VabSubMenu.vue new file mode 100644 index 0000000..45c3f9f --- /dev/null +++ b/library/components/VabMenu/components/VabSubMenu.vue @@ -0,0 +1,36 @@ + + + diff --git a/library/components/VabMenu/index.vue b/library/components/VabMenu/index.vue new file mode 100644 index 0000000..aa79dd3 --- /dev/null +++ b/library/components/VabMenu/index.vue @@ -0,0 +1,83 @@ + + + + + + + + diff --git a/library/components/VabNav/index.vue b/library/components/VabNav/index.vue new file mode 100644 index 0000000..4150ca1 --- /dev/null +++ b/library/components/VabNav/index.vue @@ -0,0 +1,165 @@ + + + + + diff --git a/library/components/VabNotice/index.vue b/library/components/VabNotice/index.vue new file mode 100644 index 0000000..b9bff9c --- /dev/null +++ b/library/components/VabNotice/index.vue @@ -0,0 +1,356 @@ + + + + + + + diff --git a/library/components/VabQueryForm/components/VabQueryFormBottomPanel.vue b/library/components/VabQueryForm/components/VabQueryFormBottomPanel.vue new file mode 100644 index 0000000..9f38ee6 --- /dev/null +++ b/library/components/VabQueryForm/components/VabQueryFormBottomPanel.vue @@ -0,0 +1,7 @@ + diff --git a/library/components/VabQueryForm/components/VabQueryFormLeftPanel.vue b/library/components/VabQueryForm/components/VabQueryFormLeftPanel.vue new file mode 100644 index 0000000..64f94e7 --- /dev/null +++ b/library/components/VabQueryForm/components/VabQueryFormLeftPanel.vue @@ -0,0 +1,16 @@ + + + diff --git a/library/components/VabQueryForm/components/VabQueryFormRightPanel.vue b/library/components/VabQueryForm/components/VabQueryFormRightPanel.vue new file mode 100644 index 0000000..2a2b781 --- /dev/null +++ b/library/components/VabQueryForm/components/VabQueryFormRightPanel.vue @@ -0,0 +1,16 @@ + + + diff --git a/library/components/VabQueryForm/components/VabQueryFormTopPanel.vue b/library/components/VabQueryForm/components/VabQueryFormTopPanel.vue new file mode 100644 index 0000000..e56c758 --- /dev/null +++ b/library/components/VabQueryForm/components/VabQueryFormTopPanel.vue @@ -0,0 +1,7 @@ + diff --git a/library/components/VabQueryForm/index.vue b/library/components/VabQueryForm/index.vue new file mode 100644 index 0000000..3ff6216 --- /dev/null +++ b/library/components/VabQueryForm/index.vue @@ -0,0 +1,60 @@ + + + diff --git a/library/components/VabRefresh/index.vue b/library/components/VabRefresh/index.vue new file mode 100644 index 0000000..dbea8e7 --- /dev/null +++ b/library/components/VabRefresh/index.vue @@ -0,0 +1,20 @@ + + + diff --git a/library/components/VabRouterView/index.vue b/library/components/VabRouterView/index.vue new file mode 100644 index 0000000..a517ee3 --- /dev/null +++ b/library/components/VabRouterView/index.vue @@ -0,0 +1,80 @@ + + + diff --git a/library/components/VabSearch/index.vue b/library/components/VabSearch/index.vue new file mode 100644 index 0000000..8feec2f --- /dev/null +++ b/library/components/VabSearch/index.vue @@ -0,0 +1,517 @@ + + + + + diff --git a/library/components/VabSideBar/index.vue b/library/components/VabSideBar/index.vue new file mode 100644 index 0000000..fbc88d9 --- /dev/null +++ b/library/components/VabSideBar/index.vue @@ -0,0 +1,214 @@ + + + + + + + + diff --git a/library/components/VabTabs/index.vue b/library/components/VabTabs/index.vue new file mode 100644 index 0000000..e621af2 --- /dev/null +++ b/library/components/VabTabs/index.vue @@ -0,0 +1,614 @@ + + + + + diff --git a/library/components/VabTheme/components/VabThemeDrawer.vue b/library/components/VabTheme/components/VabThemeDrawer.vue new file mode 100644 index 0000000..4af40a9 --- /dev/null +++ b/library/components/VabTheme/components/VabThemeDrawer.vue @@ -0,0 +1,515 @@ + + + + + diff --git a/library/components/VabTheme/components/VabThemeSetting.vue b/library/components/VabTheme/components/VabThemeSetting.vue new file mode 100644 index 0000000..b027fd8 --- /dev/null +++ b/library/components/VabTheme/components/VabThemeSetting.vue @@ -0,0 +1,168 @@ + + + + + diff --git a/library/components/VabTheme/index.vue b/library/components/VabTheme/index.vue new file mode 100644 index 0000000..c57614d --- /dev/null +++ b/library/components/VabTheme/index.vue @@ -0,0 +1,18 @@ + + + diff --git a/library/index.ts b/library/index.ts new file mode 100644 index 0000000..7c1c85f --- /dev/null +++ b/library/index.ts @@ -0,0 +1,39 @@ +import { App } from 'vue' + +// 加载雪碧图 +import '@/icon' +// 加载全局样式样式 +import './styles/vab.scss' + +import { createHead } from '@vueuse/head' + +// 加载Icon +import VabIcon from 'vab-icons' +import 'vab-icons/lib/vab-icons.css' +import * as ElementPlusIconsVue from '@element-plus/icons-vue' + +const name = process['env']['VUE_' + 'APP_' + 'GITHUB_' + 'USER_' + 'NAME'] +const noTest = name !== 'test' +const noEmpty = name !== 'undefined' +const dev = process['env']['NODE_' + 'ENV'] === 'dev' + 'elop' + 'ment' + +export function setupVab(app: App) { + if ((noTest && noEmpty && !dev && VabIcon) || (dev && VabIcon)) { + app.use(createHead()) + + app.component('VabIcon', VabIcon) + for (const [key, component] of Object.entries(ElementPlusIconsVue)) { + app.component(key, component) + } + + // 加载背景 + const Themes = require.context('./styles/background', false, /\.scss$/) + Themes.keys().map(Themes) + + // 加载插件 + const Plugins = require.context('./plugins', true, /\.ts$/) + Plugins.keys().forEach((key) => { + app.use(Plugins(key).default) + }) + } +} diff --git a/library/layouts/VabLayoutColumn/index.vue b/library/layouts/VabLayoutColumn/index.vue new file mode 100644 index 0000000..127937c --- /dev/null +++ b/library/layouts/VabLayoutColumn/index.vue @@ -0,0 +1,78 @@ + + + + + + diff --git a/library/layouts/VabLayoutCommon/index.vue b/library/layouts/VabLayoutCommon/index.vue new file mode 100644 index 0000000..1598883 --- /dev/null +++ b/library/layouts/VabLayoutCommon/index.vue @@ -0,0 +1,88 @@ + + + + + + diff --git a/library/layouts/VabLayoutComprehensive/index.vue b/library/layouts/VabLayoutComprehensive/index.vue new file mode 100644 index 0000000..7a35ecc --- /dev/null +++ b/library/layouts/VabLayoutComprehensive/index.vue @@ -0,0 +1,58 @@ + + + + diff --git a/library/layouts/VabLayoutFloat/index.vue b/library/layouts/VabLayoutFloat/index.vue new file mode 100644 index 0000000..c8aed38 --- /dev/null +++ b/library/layouts/VabLayoutFloat/index.vue @@ -0,0 +1,98 @@ + + + + + + + diff --git a/library/layouts/VabLayoutHorizontal/index.vue b/library/layouts/VabLayoutHorizontal/index.vue new file mode 100644 index 0000000..6db795b --- /dev/null +++ b/library/layouts/VabLayoutHorizontal/index.vue @@ -0,0 +1,83 @@ + + + + + + diff --git a/library/layouts/VabLayoutVertical/index.vue b/library/layouts/VabLayoutVertical/index.vue new file mode 100644 index 0000000..976a08f --- /dev/null +++ b/library/layouts/VabLayoutVertical/index.vue @@ -0,0 +1,68 @@ + + + + diff --git a/library/layouts/index.vue b/library/layouts/index.vue new file mode 100644 index 0000000..94f8820 --- /dev/null +++ b/library/layouts/index.vue @@ -0,0 +1,162 @@ + + + + + diff --git a/library/plugins/directive.ts b/library/plugins/directive.ts new file mode 100644 index 0000000..d41a8d1 --- /dev/null +++ b/library/plugins/directive.ts @@ -0,0 +1,19 @@ +import type { App, DirectiveBinding } from 'vue' + +import { hasPermission } from '@/utils/permission' + +export default { + install(app: App) { + /** + * @description 自定义指令v-permissions + */ + app.directive('permissions', { + mounted(el: any, binding: DirectiveBinding) { + const { value } = binding + if (value) + if (!hasPermission(value)) + el.parentNode && el.parentNode.removeChild(el) + }, + }) + }, +} diff --git a/library/plugins/errorLog.ts b/library/plugins/errorLog.ts new file mode 100644 index 0000000..d064b07 --- /dev/null +++ b/library/plugins/errorLog.ts @@ -0,0 +1,30 @@ +import { App } from 'vue' +import pinia from '@/store' +import { useErrorLogStore } from '@/store/modules/errorLog' +import { errorLog } from '@/config' +import { isArray, isString } from '@/utils/validate' + +export const needErrorLog = () => { + const errorLogArray = isArray(errorLog) + ? [...errorLog] + : isString(errorLog) + ? [...[errorLog]] + : [] + return errorLogArray.includes(process.env.NODE_ENV as string) +} + +export const addErrorLog = (err: any) => { + // eslint-disable-next-line no-console + if (!err.isRequest) console.error('vue-admin-better错误拦截:', err) + const url = window.location.href + const { addErrorLog } = useErrorLogStore(pinia) + addErrorLog({ err, url }) +} + +export default { + install(app: App) { + if (needErrorLog()) { + app.config.errorHandler = addErrorLog + } + }, +} diff --git a/library/plugins/support.ts b/library/plugins/support.ts new file mode 100644 index 0000000..66b9dbb --- /dev/null +++ b/library/plugins/support.ts @@ -0,0 +1,26 @@ +import { App } from 'vue' +import pinia from '@/store' +import { useSettingsStore } from '@/store/modules/settings' + +export default { + install(app: App) { + if (process.env.NODE_ENV !== 'development') { + const { title } = useSettingsStore(pinia) + // eslint-disable-next-line no-console + console.log( + ` %c ${title} %c 基于admin-plus ${__APP_INFO__['version']} 构建 `, + 'color: #fadfa3; background: #030307; padding:5px 0;', + 'background: #fadfa3; padding:5px 0;' + ) + } + if (process.env.NODE_ENV !== 'development') { + const str = '\u0076\u0061\u0062\u002d\u0069\u0063\u006f\u006e\u0073' + const key = decodeURI(str.replace(/\\u/g, '%u')) + if (!__APP_INFO__['dependencies'][key]) { + // eslint-disable-next-line + // @ts-ignore + app.config.globalProperties = null + } + } + }, +} diff --git a/library/plugins/vab.ts b/library/plugins/vab.ts new file mode 100644 index 0000000..f8f9e7d --- /dev/null +++ b/library/plugins/vab.ts @@ -0,0 +1,172 @@ +import { App } from 'vue' +import mitt from 'mitt' +import _ from 'lodash' +import { loadingText, messageDuration } from '@/config' +import { globalPropertiesType } from '/#/library' + +export let gp: globalPropertiesType + +export default { + install(app: App) { + gp = { + /** + * @description 全局加载层 + * @param {number} index 自定义加载图标类名ID + * @param {string} text 显示在加载图标下方的加载文案 + */ + $baseLoading: (index = undefined, text = loadingText) => { + return ElLoading.service({ + lock: true, + text, + spinner: index ? `vab-loading-type${index}` : index, + background: 'hsla(0,0%,100%,.8)', + }) + }, + /** + * @description 全局Message + * @param {string} message 消息文字 + * @param {'success'|'warning'|'info'|'error'} type 主题 + * @param {string} customClass 自定义类名 + * @param {boolean} dangerouslyUseHTMLString 是否将message属性作为HTML片段处理 + */ + $baseMessage: ( + message, + type = 'info', + customClass, + dangerouslyUseHTMLString + ) => { + ElMessage({ + message, + type, + customClass, + duration: messageDuration, + dangerouslyUseHTMLString, + showClose: true, + }) + }, + /** + * @description 全局Alert + * @param {string|VNode} content 消息正文内容 + * @param {string} title 标题 + * @param {function} callback 若不使用Promise,可以使用此参数指定MessageBox关闭后的回调 + */ + $baseAlert: (content, title = '温馨提示', callback = undefined) => { + if (title && typeof title == 'function') { + callback = title + title = '温馨提示' + } + ElMessageBox.alert(content, title, { + confirmButtonText: '确定', + dangerouslyUseHTMLString: true, // 此处可能引起跨站攻击,建议配置为false + callback: () => { + if (callback) callback() + }, + }).then(() => {}) + }, + /** + * @description 全局Confirm + * @param {string|VNode} content 消息正文内容 + * @param {string} title 标题 + * @param {function} callback1 确认回调 + * @param {function} callback2 关闭或取消回调 + * @param {string} confirmButtonText 确定按钮的文本内容 + * @param {string} cancelButtonText 取消按钮的自定义类名 + */ + $baseConfirm: ( + content, + title, + callback1, + callback2, + confirmButtonText = '确定', + cancelButtonText = '取消' + ) => { + ElMessageBox.confirm(content, title || '温馨提示', { + confirmButtonText, + cancelButtonText, + closeOnClickModal: false, + type: 'warning', + lockScroll: false, + }) + .then(() => { + if (callback1) { + callback1() + } + }) + .catch(() => { + if (callback2) { + callback2() + } + }) + }, + /** + * @description 全局Notification + * @param {string} message 说明文字 + * @param {string} title 标题 + * @param {'success'|'warning'|'info'|'error'} type 主题样式,如果不在可选值内将被忽略 + * @param {'top-right'|'top-left'|'bottom-right'|'bottom-left'} position 自定义弹出位置 + * @param duration 显示时间,毫秒 + */ + $baseNotify: ( + message, + title, + type = 'success', + position = 'top-right', + duration = messageDuration + ) => { + ElNotification({ + title, + message, + type, + duration, + position, + }) + }, + /** + * @description 表格高度 + * @param {*} formType + */ + $baseTableHeight: (formType) => { + let height = window.innerHeight + const paddingHeight = 291 + const formHeight = 60 + + if ('number' === typeof formType) { + height = height - paddingHeight - formHeight * formType + } else { + height = height - paddingHeight + } + return height + }, + $pub: (...args: any[]) => { + _emitter.emit(_.head(args), args[1]) + }, + $sub: function () { + // eslint-disable-next-line prefer-rest-params + Reflect.apply(_emitter.on, _emitter, _.toArray(arguments)) + }, + $unsub: function () { + // eslint-disable-next-line prefer-rest-params + Reflect.apply(_emitter.off, _emitter, _.toArray(arguments)) + }, + } + + const _emitter = mitt() + Object.keys(gp).forEach((key) => { + app.provide(key, gp[key as keyof typeof gp]) + // 允许vue3下继续使用vue2中的this调用vab方法 + app.config.globalProperties[key] = gp[key as keyof typeof gp] + }) + + if (process.env['NODE_' + 'ENV'] !== `${'deve' + 'lopme' + 'nt'}`) { + const key = 'vab-' + 'icons' + if (!__APP_INFO__['dependencies'][key]) { + // @ts-ignore + app.config.globalProperties = null + } + if (!process.env['VUE_' + 'APP_' + 'SECRET_' + 'KEY']) { + // @ts-ignore + app.config.globalProperties = null + } + } + }, +} diff --git a/library/shims-vab.d.ts b/library/shims-vab.d.ts new file mode 100644 index 0000000..c8b3c92 --- /dev/null +++ b/library/shims-vab.d.ts @@ -0,0 +1,12 @@ +declare let __APP_INFO__: any + +// CSS +type CSSModuleClasses = { readonly [key: string]: string } +declare module '*.module.scss' { + const classes: CSSModuleClasses + export default classes +} +declare module '*.scss' { + const css: string + export default css +} diff --git a/library/styles/background/black.scss b/library/styles/background/black.scss new file mode 100644 index 0000000..1d95aef --- /dev/null +++ b/library/styles/background/black.scss @@ -0,0 +1,251 @@ +/** + * @description 黑 + */ + +body.vab-theme-black { + $base-menu-background: #282c34; + + @mixin container { + color: var(--el-color-white) !important; + background: $base-menu-background !important; + } + + @mixin active { + &:hover { + color: var(--el-color-white) !important; + background-color: var(--el-color-primary) !important; + } + + &.is-active { + color: var(--el-color-white) !important; + background-color: var(--el-color-primary) !important; + } + } + + .logo-container-vertical, + .logo-container-horizontal, + .logo-container-comprehensive, + .logo-container-float { + @include container; + } + + .logo-container-column { + .logo { + @include container; + } + } + + .vab-column-bar-container.el-scrollbar { + .el-tabs { + .el-tabs__nav-wrap.is-left { + @include container; + } + + .el-tabs__nav { + @include container; + } + + .el-tabs__item.is-active { + background: var(--el-color-primary) !important; + } + } + + .el-menu { + .el-menu-item.is-active, + .el-sub-menu__title.is-active, + .el-menu-item:hover, + .el-sub-menu__title:hover { + i { + color: var(--el-color-primary) !important; + } + + color: var(--el-color-primary) !important; + background-color: var(--el-color-primary-light-9) !important; + } + } + } + + .vab-column-bar-container-card.el-scrollbar { + .el-tabs { + .el-tabs__item.is-active { + background: transparent !important; + + .vab-column-grid { + background: var(--el-color-primary) !important; + } + } + } + } + + .vab-column-bar-container-arrow.el-scrollbar { + .el-tabs { + .el-tabs__item.is-active { + background: transparent !important; + + .vab-column-grid { + background: transparent !important; + } + } + } + } + + .vab-layout-float, + .vab-layout-common, + .vab-layout-vertical, + .vab-layout-horizontal, + .vab-layout-comprehensive { + .el-menu { + @include container; + + .el-sub-menu .el-sub-menu__title, + .el-menu-item { + @include container; + } + } + + .vab-side-bar, + .comprehensive-bar-container { + @include container; + + .el-menu-item { + @include active; + } + } + } + + .vab-layout-float { + .el-scrollbar__view + .el-menu--collapse.el-menu + li.el-sub-menu.is-active { + .el-sub-menu__title { + background-color: transparent !important; + } + + > .el-sub-menu__title { + background-color: var(--el-color-primary) !important; + } + } + } + + .vab-header { + @include container; + + .vab-main { + @include container; + + .right-panel { + .el-menu { + &--horizontal { + .el-sub-menu .el-sub-menu__title, + .el-menu-item { + @include active; + } + } + } + [role='menubar'].el-menu--horizontal { + > .el-sub-menu.is-active[tabindex='0'] { + > .el-sub-menu__title { + color: var(--el-color-white) !important; + background-color: var( + --el-color-primary + ) !important; + } + } + } + } + } + } + + .vab-tabs { + &-more { + &-active, + &:hover { + .vab-tabs-more-icon { + .box:before, + .box:after { + background: var(--el-color-primary) !important; + } + } + } + } + + .vab-tabs-content-card { + .el-tabs__header { + .el-tabs__item { + &.is-active { + color: var(--el-color-primary) !important; + background: var(--el-color-primary-light-9) !important; + border: 1px solid var(--el-color-primary) !important; + } + + &:hover { + border: 1px solid var(--el-color-primary) !important; + } + } + } + } + + .vab-tabs-content-smart { + .el-tabs__header { + .el-tabs__item { + &.is-active { + background: var(--el-color-primary-light-9) !important; + } + + &:after { + background-color: var(--el-color-primary) !important; + } + + &:hover { + background: var(--el-color-primary-light-9) !important; + } + } + } + } + + .vab-tabs-content-smooth { + .el-tabs__header { + .el-tabs__item { + &.is-active { + color: var(--el-color-primary) !important; + background: var(--el-color-primary-light-9) !important; + + &:hover { + color: var(--el-color-primary) !important; + background: var( + --el-color-primary-light-9 + ) !important; + } + } + + &:hover { + color: var(--el-color-black) !important; + } + } + } + } + } + + .vab-nav { + .el-tabs__item.is-active, + .el-tabs__item:hover { + color: var(--el-color-primary) !important; + } + + .el-tabs__active-bar { + background-color: var(--el-color-primary) !important; + } + } + + #nprogress { + .bar { + background: var(--el-color-primary) !important; + } + + .peg { + box-shadow: + 0 0 10px var(--el-color-primary), + 0 0 5px var(--el-color-primary) !important; + } + } +} diff --git a/library/styles/background/image.scss b/library/styles/background/image.scss new file mode 100644 index 0000000..2e460ca --- /dev/null +++ b/library/styles/background/image.scss @@ -0,0 +1,108 @@ +/** + * @description 菜单背景 + */ + +body.vab-background > #app { + $base-menu-background: url('~@/assets/theme_images/background-1.png') + no-repeat; + + @mixin container { + color: $base-color-white !important; + background: $base-menu-background !important; + background-size: auto 100% !important; + } + @mixin transparent { + color: $base-color-white !important; + background: transparent !important; + } + @mixin active { + span { + color: $base-color-white !important; + } + + &:hover { + color: $base-color-white !important; + background-color: rgba(0, 0, 0, 0.3) !important; + } + + &.is-active { + color: $base-color-white !important; + background-color: rgba(0, 0, 0, 0.3) !important; + } + } + + .vab-side-bar:not(.is-collapse), + .comprehensive-bar-container { + @include container; + + .el-menu { + @include transparent; + + .el-menu-item, + .el-sub-menu__title { + @include transparent; + @include active; + + i, + svg { + @include transparent; + } + } + } + + .logo-container-vertical, + .logo-container-comprehensive, + .logo-container-float { + @include transparent; + + .logo .vab-icon, + .title { + @include transparent; + } + } + } + + .vab-column-bar-container { + &.el-scrollbar { + .logo-container-column { + .logo { + @include container; + background: #034291 !important; + + .vab-icon { + @include transparent; + } + } + } + + .el-tabs { + .el-tabs__nav-wrap.is-left { + @include container; + } + + .el-tabs__nav, + .el-tabs__item { + @include transparent; + + &.is-active { + color: $base-color-white !important; + background-color: rgba(0, 0, 0, 0.3) !important; + } + } + } + + &.vab-column-bar-container-card { + .el-tabs { + .el-tabs__item { + &.is-active { + background: transparent !important; + .vab-column-grid { + background-color: rgba(0, 0, 0, 0.3) !important; + } + } + } + } + } + } + } +} diff --git a/library/styles/background/ocean.scss b/library/styles/background/ocean.scss new file mode 100644 index 0000000..db2eca8 --- /dev/null +++ b/library/styles/background/ocean.scss @@ -0,0 +1,181 @@ +/** + * @description 渐变 + */ + +body.vab-theme-ocean { + $base-color-blue: #1890ff; + $base-color-blue-active: #399efd; + + @mixin container { + background: linear-gradient(to right, #006cff, #399efd) !important; + } + + @mixin active { + &:hover { + color: $base-color-white; + background-color: $base-color-blue-active !important; + } + + &.is-active { + color: $base-color-white; + background-color: $base-color-blue-active !important; + } + } + + .logo-container-horizontal { + background: var(--el-color-primary) !important; + } + + .logo-container-vertical, + .logo-container-comprehensive, + .logo-container-float { + @include container; + } + + .logo-container-column { + .logo { + @include container; + } + } + + .vab-column-bar-container { + .el-tabs { + .el-tabs__nav-wrap.is-left { + @include container; + } + + .el-tabs__nav { + @include container; + } + } + + .el-menu { + .el-menu-item.is-active, + .el-sub-menu__title.is-active, + .el-menu-item:hover, + .el-sub-menu__title:hover { + i { + color: var(--el-color-primary) !important; + } + + color: var(--el-color-primary) !important; + background-color: var(--el-color-primary-light-9) !important; + } + } + + &-card { + .el-tabs { + .el-tabs__item { + &.is-active { + background: transparent !important; + } + } + } + } + } + + .vab-layout-horizontal { + .vab-header { + background: var(--el-color-primary) !important; + } + + .el-menu { + background: var(--el-color-primary) !important; + + .el-sub-menu__title { + background: var(--el-color-primary) !important; + } + + .el-menu-item { + background: var(--el-color-primary) !important; + } + } + + .vab-side-bar, + .comprehensive-bar-container { + background: var(--el-color-primary) !important; + + .el-menu-item { + @include active; + } + } + } + + .vab-layout-vertical, + .vab-layout-comprehensive, + .vab-layout-common, + .vab-layout-float { + .vab-side-bar, + .comprehensive-bar-container { + @include container; + + .el-menu { + @include container; + @include active; + + .el-sub-menu__title, + .el-menu-item { + background-color: transparent !important; + @include active; + + &.is-active { + background-color: $base-color-blue-active !important; + } + } + } + } + } + + .vab-layout-float { + .el-scrollbar__view + .el-menu--collapse.el-menu + li.el-sub-menu.is-active { + .el-sub-menu__title { + background-color: transparent !important; + } + + > .el-sub-menu__title { + background-color: var(--el-color-primary) !important; + } + } + } + + .vab-header { + background-color: var(--el-color-primary) !important; + + .vab-main { + .el-menu.el-menu { + background-color: var(--el-color-primary) !important; + + &--horizontal { + .el-sub-menu, + .el-menu-item { + background-color: var(--el-color-primary) !important; + + &.is-active { + color: $base-color-white !important; + background-color: $base-color-blue-active !important; + } + } + + > .el-menu-item, + .el-sub-menu__title, + > .el-menu-item:hover, + > .el-sub-menu__title:hover { + color: $base-color-white !important; + background-color: var(--el-color-primary) !important; + + i { + color: $base-color-white !important; + } + + &.is-active { + color: $base-color-white !important; + background-color: $base-color-blue-active !important; + } + } + } + } + } + } +} diff --git a/library/styles/background/white.scss b/library/styles/background/white.scss new file mode 100644 index 0000000..0634500 --- /dev/null +++ b/library/styles/background/white.scss @@ -0,0 +1,293 @@ +/** + * @description 白 + */ + +body.vab-theme-white { + $base-menu-background: #fff; + + @mixin container { + color: #515a6e !important; + background: $base-menu-background !important; + } + + @mixin active { + &:hover { + color: var(--el-color-primary) !important; + background-color: var(--el-color-primary-light-9) !important; + + i, + svg, + span[title] { + color: var(--el-color-primary) !important; + } + } + + &.is-active { + color: var(--el-color-primary) !important; + background-color: var(--el-color-primary-light-9) !important; + + i, + svg, + span[title] { + color: var(--el-color-primary) !important; + } + } + } + + .logo-container-common, + .logo-container-vertical, + .logo-container-horizontal, + .logo-container-comprehensive, + .logo-container-float { + @include container; + + .title, + .vab-icon { + @include container; + } + } + + .logo-container-column { + @include container; + + .title { + @include container; + } + + .logo, + .vab-icon { + @include container; + } + } + + .vab-column-bar-container { + .el-tabs { + @include container; + + .el-tabs__nav-wrap.is-left { + background: #f7faff !important; + } + + .el-tabs__item, + .el-tabs__nav { + @include container; + } + + .el-tabs__item.is-active { + color: var(--el-color-white) !important; + background: var(--el-color-primary) !important; + } + } + + .el-menu { + .el-menu-item.is-active, + .el-sub-menu__title.is-active, + .el-menu-item:hover, + .el-sub-menu__title:hover { + i { + color: var(--el-color-primary) !important; + } + + color: var(--el-color-primary) !important; + background-color: var(--el-color-primary-light-9) !important; + } + } + + &-card { + .el-tabs { + .el-tabs__item { + &.is-active { + background: transparent !important; + } + } + } + } + + &-arrow { + .el-tabs { + .el-tabs__item { + &.is-active { + color: var(--el-color-black) !important; + background: transparent !important; + + .vab-column-grid { + background: transparent !important; + } + } + } + } + } + } + + .vab-layout-float, + .vab-layout-common, + .vab-layout-vertical, + .vab-layout-horizontal, + .vab-layout-comprehensive { + .el-menu { + @include container; + + .el-sub-menu .el-sub-menu__title, + .el-menu-item { + @include container; + } + + .el-menu-item.is-active, + .el-sub-menu__title.is-active, + .el-menu-item:hover, + .el-sub-menu__title:hover { + i { + color: var(--el-color-primary) !important; + } + + color: var(--el-color-primary) !important; + background-color: var(--el-color-primary-light-9) !important; + } + } + + .vab-side-bar, + .comprehensive-bar-container { + @include container; + + .el-menu-item { + @include active; + } + } + } + + .vab-layout-float { + .el-scrollbar__view + .el-menu--collapse.el-menu + li.el-sub-menu.is-active { + .el-sub-menu__title { + background-color: transparent !important; + } + + > .el-sub-menu__title { + color: var(--el-color-primary) !important; + background-color: var(--el-color-primary-light-9) !important; + } + } + } + + .vab-header { + @include container; + + .vab-main { + @include container; + + .right-panel { + .user-name, + .user-name *, + > i, + > div > i, + > span > i, + > div > span > i, + > svg, + > div > svg, + > span > svg, + > div > span > svg, + .ri-notification-line, + .ri-translate, + .ri-bug-line { + @include container; + } + + .el-menu { + &--horizontal { + .el-sub-menu .el-sub-menu__title, + .el-menu-item { + @include active; + } + + .el-sub-menu, + .el-menu-item { + &.is-active { + @include active; + } + } + + > .el-sub-menu.is-active { + > .el-sub-menu__title { + background-color: var( + --el-color-primary-light-9 + ) !important; + @include active; + } + } + } + } + } + } + } + + .vab-tabs { + &-more { + &-active, + &:hover { + .vab-tabs-more-icon { + .box:before, + .box:after { + background: var(--el-color-primary) !important; + } + } + } + } + + .vab-tabs-content-card { + .el-tabs__header { + .el-tabs__item { + &.is-active { + color: var(--el-color-primary) !important; + background: var(--el-color-primary-light-9) !important; + border: 1px solid var(--el-color-primary) !important; + } + + &:hover { + border: 1px solid var(--el-color-primary) !important; + } + } + } + } + + .vab-tabs-content-smart { + .el-tabs__header { + .el-tabs__item { + &.is-active { + background: var(--el-color-primary-light-9) !important; + } + + &:after { + background-color: var(--el-color-primary) !important; + } + + &:hover { + background: var(--el-color-primary-light-9) !important; + } + } + } + } + + .vab-tabs-content-smooth { + .el-tabs__header { + .el-tabs__item { + &.is-active { + color: var(--el-color-primary) !important; + background: var(--el-color-primary-light-9) !important; + + &:hover { + color: var(--el-color-primary) !important; + background: var( + --el-color-primary-light-9 + ) !important; + } + } + + &:hover { + color: var(--el-color-black) !important; + } + } + } + } + } +} diff --git a/library/styles/loading/dots.css b/library/styles/loading/dots.css new file mode 100644 index 0000000..0049258 --- /dev/null +++ b/library/styles/loading/dots.css @@ -0,0 +1,124 @@ +.dots-loader:not(:required) { + position: relative; + display: inline-block; + width: 7px; + height: 7px; + margin-bottom: 30px; + overflow: hidden; + text-indent: -9999px; + background: transparent; + border-radius: 100%; + box-shadow: + #f86 -14px -14px 0 7px, + #fc6 14px -14px 0 7px, + #6d7 14px 14px 0 7px, + #4ae -14px 14px 0 7px; + transform-origin: 50% 50%; + animation: dots-loader 5s infinite ease-in-out; +} + +@keyframes dots-loader { + 0% { + box-shadow: + #f86 -14px -14px 0 7px, + #fc6 14px -14px 0 7px, + #6d7 14px 14px 0 7px, + #4ae -14px 14px 0 7px; + } + + 8.33% { + box-shadow: + #f86 14px -14px 0 7px, + #fc6 14px -14px 0 7px, + #6d7 14px 14px 0 7px, + #4ae -14px 14px 0 7px; + } + + 16.67% { + box-shadow: + #f86 14px 14px 0 7px, + #fc6 14px 14px 0 7px, + #6d7 14px 14px 0 7px, + #4ae -14px 14px 0 7px; + } + + 25% { + box-shadow: + #f86 -14px 14px 0 7px, + #fc6 -14px 14px 0 7px, + #6d7 -14px 14px 0 7px, + #4ae -14px 14px 0 7px; + } + + 33.33% { + box-shadow: + #f86 -14px -14px 0 7px, + #fc6 -14px 14px 0 7px, + #6d7 -14px -14px 0 7px, + #4ae -14px -14px 0 7px; + } + + 41.67% { + box-shadow: + #f86 14px -14px 0 7px, + #fc6 -14px 14px 0 7px, + #6d7 -14px -14px 0 7px, + #4ae 14px -14px 0 7px; + } + + 50% { + box-shadow: + #f86 14px 14px 0 7px, + #fc6 -14px 14px 0 7px, + #6d7 -14px -14px 0 7px, + #4ae 14px -14px 0 7px; + } + + 58.33% { + box-shadow: + #f86 -14px 14px 0 7px, + #fc6 -14px 14px 0 7px, + #6d7 -14px -14px 0 7px, + #4ae 14px -14px 0 7px; + } + + 66.67% { + box-shadow: + #f86 -14px -14px 0 7px, + #fc6 -14px -14px 0 7px, + #6d7 -14px -14px 0 7px, + #4ae 14px -14px 0 7px; + } + + 75% { + box-shadow: + #f86 14px -14px 0 7px, + #fc6 14px -14px 0 7px, + #6d7 14px -14px 0 7px, + #4ae 14px -14px 0 7px; + } + + 83.33% { + box-shadow: + #f86 14px 14px 0 7px, + #fc6 14px -14px 0 7px, + #6d7 14px 14px 0 7px, + #4ae 14px 14px 0 7px; + } + + 91.67% { + box-shadow: + #f86 -14px 14px 0 7px, + #fc6 14px -14px 0 7px, + #6d7 14px 14px 0 7px, + #4ae -14px 14px 0 7px; + } + + 100% { + box-shadow: + #f86 -14px -14px 0 7px, + #fc6 14px -14px 0 7px, + #6d7 14px 14px 0 7px, + #4ae -14px 14px 0 7px; + } +} diff --git a/library/styles/loading/gauge.css b/library/styles/loading/gauge.css new file mode 100644 index 0000000..401f8d8 --- /dev/null +++ b/library/styles/loading/gauge.css @@ -0,0 +1,104 @@ +.gauge-loader:not(:required) { + position: relative; + display: inline-block; + width: 64px; + height: 32px; + margin-bottom: 10px; + overflow: hidden; + text-indent: -9999px; + background: #6ca; + border-top-left-radius: 32px; + border-top-right-radius: 32px; +} + +.gauge-loader:not(:required)::before { + position: absolute; + top: 5px; + left: 30px; + width: 4px; + height: 27px; + content: ''; + background: white; + border-radius: 2px; + transform-origin: 50% 100%; + animation: gauge-loader 4000ms infinite ease; +} + +.gauge-loader:not(:required)::after { + position: absolute; + top: 26px; + left: 26px; + width: 13px; + height: 13px; + content: ''; + background: white; + -moz-border-radius: 8px; + -webkit-border-radius: 8px; + border-radius: 8px; +} + +@keyframes gauge-loader { + 0% { + transform: rotate(-50deg); + } + + 10% { + transform: rotate(20deg); + } + + 20% { + transform: rotate(60deg); + } + + 24% { + transform: rotate(60deg); + } + + 40% { + transform: rotate(-20deg); + } + + 54% { + transform: rotate(70deg); + } + + 56% { + transform: rotate(78deg); + } + + 58% { + transform: rotate(73deg); + } + + 60% { + transform: rotate(75deg); + } + + 62% { + transform: rotate(70deg); + } + + 70% { + transform: rotate(-20deg); + } + + 80% { + transform: rotate(20deg); + } + + 83% { + transform: rotate(25deg); + } + + 86% { + transform: rotate(20deg); + } + + 89% { + transform: rotate(25deg); + } + + 100% { + transform: rotate(-50deg); + } +} diff --git a/library/styles/loading/inner-circles.css b/library/styles/loading/inner-circles.css new file mode 100644 index 0000000..d753d66 --- /dev/null +++ b/library/styles/loading/inner-circles.css @@ -0,0 +1,51 @@ +.inner-circles-loader:not(:required) { + position: relative; + display: inline-block; + width: 50px; + height: 50px; + margin-bottom: 10px; + overflow: hidden; + text-indent: -9999px; + background: rgba(25, 165, 152, 0.5); + border-radius: 50%; + transform: translate3d(0, 0, 0); +} + +.inner-circles-loader:not(:required)::before, +.inner-circles-loader:not(:required)::after { + position: absolute; + top: 0; + display: inline-block; + width: 50px; + height: 50px; + content: ''; + border-radius: 50%; +} + +.inner-circles-loader:not(:required)::before { + left: 0; + background: #c7efcf; + transform-origin: 0 50%; + animation: inner-circles-loader 3s infinite; +} + +.inner-circles-loader:not(:required)::after { + right: 0; + background: #eef5db; + transform-origin: 100% 50%; + animation: inner-circles-loader 3s 0.2s reverse infinite; +} + +@keyframes inner-circles-loader { + 0% { + transform: rotate(0deg); + } + + 50% { + transform: rotate(360deg); + } + + 100% { + transform: rotate(0deg); + } +} diff --git a/library/styles/loading/plus.css b/library/styles/loading/plus.css new file mode 100644 index 0000000..28b6951 --- /dev/null +++ b/library/styles/loading/plus.css @@ -0,0 +1,341 @@ +.plus-loader:not(:required) { + position: relative; + display: inline-block; + width: 48px; + height: 48px; + margin-bottom: 10px; + overflow: hidden; + text-indent: -9999px; + background: #f86; + -moz-border-radius: 24px; + -webkit-border-radius: 24px; + border-radius: 24px; + -moz-transform: rotateZ(90deg); + -ms-transform: rotateZ(90deg); + -webkit-transform: rotateZ(90deg); + transform: rotateZ(90deg); + -moz-transform-origin: 50% 50%; + -ms-transform-origin: 50% 50%; + -webkit-transform-origin: 50% 50%; + transform-origin: 50% 50%; + -moz-animation: plus-loader-background 3s infinite ease-in-out; + -webkit-animation: plus-loader-background 3s infinite ease-in-out; + animation: plus-loader-background 3s infinite ease-in-out; +} + +.plus-loader:not(:required)::after { + position: absolute; + top: 0; + right: 50%; + width: 50%; + height: 100%; + content: ''; + background: #f86; + -moz-border-radius: 24px 0 0 24px; + -webkit-border-radius: 24px; + border-radius: 24px 0 0 24px; + -moz-transform-origin: 100% 50%; + -ms-transform-origin: 100% 50%; + -webkit-transform-origin: 100% 50%; + transform-origin: 100% 50%; + -moz-animation: plus-loader-top 3s infinite linear; + -webkit-animation: plus-loader-top 3s infinite linear; + animation: plus-loader-top 3s infinite linear; +} + +.plus-loader:not(:required)::before { + position: absolute; + top: 0; + right: 50%; + width: 50%; + height: 100%; + content: ''; + background: #fc6; + -moz-border-radius: 24px 0 0 24px; + -webkit-border-radius: 24px; + border-radius: 24px 0 0 24px; + -moz-transform-origin: 100% 50%; + -ms-transform-origin: 100% 50%; + -webkit-transform-origin: 100% 50%; + transform-origin: 100% 50%; + -moz-animation: plus-loader-bottom 3s infinite linear; + -webkit-animation: plus-loader-bottom 3s infinite linear; + animation: plus-loader-bottom 3s infinite linear; +} + +@keyframes plus-loader-top { + 2.5% { + background: #f86; + -moz-transform: rotateY(0deg); + -ms-transform: rotateY(0deg); + -webkit-transform: rotateY(0deg); + transform: rotateY(0deg); + -moz-animation-timing-function: ease-in; + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 13.75% { + background: #ff430d; + -moz-transform: rotateY(90deg); + -ms-transform: rotateY(90deg); + -webkit-transform: rotateY(90deg); + transform: rotateY(90deg); + -moz-animation-timing-function: step-start; + -webkit-animation-timing-function: step-start; + animation-timing-function: step-start; + } + + 13.76% { + background: #ffae0d; + -moz-transform: rotateY(90deg); + -ms-transform: rotateY(90deg); + -webkit-transform: rotateY(90deg); + transform: rotateY(90deg); + -moz-animation-timing-function: ease-out; + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; + } + + 25% { + background: #fc6; + -moz-transform: rotateY(180deg); + -ms-transform: rotateY(180deg); + -webkit-transform: rotateY(180deg); + transform: rotateY(180deg); + } + + 27.5% { + background: #fc6; + -moz-transform: rotateY(180deg); + -ms-transform: rotateY(180deg); + -webkit-transform: rotateY(180deg); + transform: rotateY(180deg); + -moz-animation-timing-function: ease-in; + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 41.25% { + background: #ffae0d; + -moz-transform: rotateY(90deg); + -ms-transform: rotateY(90deg); + -webkit-transform: rotateY(90deg); + transform: rotateY(90deg); + -moz-animation-timing-function: step-start; + -webkit-animation-timing-function: step-start; + animation-timing-function: step-start; + } + + 41.26% { + background: #2cc642; + -moz-transform: rotateY(90deg); + -ms-transform: rotateY(90deg); + -webkit-transform: rotateY(90deg); + transform: rotateY(90deg); + -moz-animation-timing-function: ease-out; + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; + } + + 50% { + background: #6d7; + -moz-transform: rotateY(0deg); + -ms-transform: rotateY(0deg); + -webkit-transform: rotateY(0deg); + transform: rotateY(0deg); + } + + 52.5% { + background: #6d7; + -moz-transform: rotateY(0deg); + -ms-transform: rotateY(0deg); + -webkit-transform: rotateY(0deg); + transform: rotateY(0deg); + -moz-animation-timing-function: ease-in; + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 63.75% { + background: #2cc642; + -moz-transform: rotateY(90deg); + -ms-transform: rotateY(90deg); + -webkit-transform: rotateY(90deg); + transform: rotateY(90deg); + -moz-animation-timing-function: step-start; + -webkit-animation-timing-function: step-start; + animation-timing-function: step-start; + } + + 63.76% { + background: #1386d2; + -moz-transform: rotateY(90deg); + -ms-transform: rotateY(90deg); + -webkit-transform: rotateY(90deg); + transform: rotateY(90deg); + -moz-animation-timing-function: ease-out; + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; + } + + 75% { + background: #4ae; + -moz-transform: rotateY(180deg); + -ms-transform: rotateY(180deg); + -webkit-transform: rotateY(180deg); + transform: rotateY(180deg); + } + + 77.5% { + background: #4ae; + -moz-transform: rotateY(180deg); + -ms-transform: rotateY(180deg); + -webkit-transform: rotateY(180deg); + transform: rotateY(180deg); + -moz-animation-timing-function: ease-in; + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 91.25% { + background: #1386d2; + -moz-transform: rotateY(90deg); + -ms-transform: rotateY(90deg); + -webkit-transform: rotateY(90deg); + transform: rotateY(90deg); + -moz-animation-timing-function: step-start; + -webkit-animation-timing-function: step-start; + animation-timing-function: step-start; + } + + 91.26% { + background: #ff430d; + -moz-transform: rotateY(90deg); + -ms-transform: rotateY(90deg); + -webkit-transform: rotateY(90deg); + transform: rotateY(90deg); + -moz-animation-timing-function: ease-in; + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in; + } + + 100% { + background: #f86; + -moz-transform: rotateY(0deg); + -ms-transform: rotateY(0deg); + -webkit-transform: rotateY(0deg); + transform: rotateY(0deg); + -moz-animation-timing-function: step-start; + -webkit-animation-timing-function: step-start; + animation-timing-function: step-start; + } +} + +@keyframes plus-loader-bottom { + 0% { + background: #fc6; + -moz-animation-timing-function: step-start; + -webkit-animation-timing-function: step-start; + animation-timing-function: step-start; + } + + 50% { + background: #fc6; + -moz-animation-timing-function: step-start; + -webkit-animation-timing-function: step-start; + animation-timing-function: step-start; + } + + 75% { + background: #4ae; + -moz-animation-timing-function: step-start; + -webkit-animation-timing-function: step-start; + animation-timing-function: step-start; + } + + 100% { + background: #4ae; + -moz-animation-timing-function: step-start; + -webkit-animation-timing-function: step-start; + animation-timing-function: step-start; + } +} + +@keyframes plus-loader-background { + 0% { + background: #f86; + -moz-transform: rotateZ(180deg); + -ms-transform: rotateZ(180deg); + -webkit-transform: rotateZ(180deg); + transform: rotateZ(180deg); + } + + 25% { + background: #f86; + -moz-transform: rotateZ(180deg); + -ms-transform: rotateZ(180deg); + -webkit-transform: rotateZ(180deg); + transform: rotateZ(180deg); + -moz-animation-timing-function: step-start; + -webkit-animation-timing-function: step-start; + animation-timing-function: step-start; + } + + 27.5% { + background: #6d7; + -moz-transform: rotateZ(90deg); + -ms-transform: rotateZ(90deg); + -webkit-transform: rotateZ(90deg); + transform: rotateZ(90deg); + } + + 50% { + background: #6d7; + -moz-transform: rotateZ(90deg); + -ms-transform: rotateZ(90deg); + -webkit-transform: rotateZ(90deg); + transform: rotateZ(90deg); + -moz-animation-timing-function: step-start; + -webkit-animation-timing-function: step-start; + animation-timing-function: step-start; + } + + 52.5% { + background: #6d7; + -moz-transform: rotateZ(0deg); + -ms-transform: rotateZ(0deg); + -webkit-transform: rotateZ(0deg); + transform: rotateZ(0deg); + } + + 75% { + background: #6d7; + -moz-transform: rotateZ(0deg); + -ms-transform: rotateZ(0deg); + -webkit-transform: rotateZ(0deg); + transform: rotateZ(0deg); + -moz-animation-timing-function: step-start; + -webkit-animation-timing-function: step-start; + animation-timing-function: step-start; + } + + 77.5% { + background: #f86; + -moz-transform: rotateZ(270deg); + -ms-transform: rotateZ(270deg); + -webkit-transform: rotateZ(270deg); + transform: rotateZ(270deg); + } + + 100% { + background: #f86; + -moz-transform: rotateZ(270deg); + -ms-transform: rotateZ(270deg); + -webkit-transform: rotateZ(270deg); + transform: rotateZ(270deg); + -moz-animation-timing-function: step-start; + -webkit-animation-timing-function: step-start; + animation-timing-function: step-start; + } +} diff --git a/library/styles/normalize.scss b/library/styles/normalize.scss new file mode 100644 index 0000000..f4c364d --- /dev/null +++ b/library/styles/normalize.scss @@ -0,0 +1,377 @@ +/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ + +/* Document + ========================================================================== */ + +/** + * 1. Correct the line height in all browsers. + * 2. Prevent adjustments of font size after orientation changes in iOS. + */ + +html { + line-height: 1.15; + /* 1 */ + -webkit-text-size-adjust: 100%; + /* 2 */ +} + +/* Sections + ========================================================================== */ + +/** + * Remove the margin in all browsers. + */ + +body { + margin: 0; +} + +/** + * Render the `main` element consistently in IE. + */ + +main { + display: block; +} + +/** + * Correct the font size and margin on `h1` elements within `section` and + * `article` contexts in Chrome, Firefox, and Safari. + */ + +h1 { + margin: 0.67em 0; + font-size: 2em; +} + +/* Grouping content + ========================================================================== */ + +/** + * 1. Add the correct box sizing in Firefox. + * 2. Show the overflow in Edge and IE. + */ + +hr { + box-sizing: content-box; + /* 1 */ + height: 0; + /* 1 */ + overflow: visible; + /* 2 */ +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +pre { + font-family: monospace; + /* 1 */ + font-size: 1em; + /* 2 */ +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Remove the gray background on active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * 1. Remove the bottom border in Chrome 57- + * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. + */ + +abbr[title] { + text-decoration: underline dotted; + /* 2 */ + border-bottom: none; + /* 1 */ +} + +/** + * Add the correct font weight in Chrome, Edge, and Safari. + */ + +b, +strong { + font-weight: bolder; +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +code, +kbd, +samp { + font-family: monospace; + /* 1 */ + font-size: 1em; + /* 2 */ +} + +/** + * Add the correct font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` elements from affecting the line height in + * all browsers. + */ + +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* Embedded content + ========================================================================== */ + +/** + * Remove the border on images inside links in IE 10. + */ + +img { + border-style: none; +} + +/* Forms + ========================================================================== */ + +/** + * 1. Change the font styles in all browsers. + * 2. Remove the margin in Firefox and Safari. + */ + +button, +input, +optgroup, +select, +textarea { + margin: 0; + /* 2 */ + font-family: inherit; + /* 1 */ + font-size: 100%; + /* 1 */ + line-height: 1.15; + /* 1 */ +} + +/** + * Show the overflow in IE. + * 1. Show the overflow in Edge. + */ + +button, +input { + /* 1 */ + overflow: visible; +} + +/** + * Remove the inheritance of text transform in Edge, Firefox, and IE. + * 1. Remove the inheritance of text transform in Firefox. + */ + +button, +select { + /* 1 */ + text-transform: none; +} + +/** + * Correct the inability to style clickable types in iOS and Safari. + */ + +button, +[type='button'], +[type='reset'], +[type='submit'] { + -webkit-appearance: button; +} + +/** + * Remove the inner border and padding in Firefox. + */ + +button::-moz-focus-inner, +[type='button']::-moz-focus-inner, +[type='reset']::-moz-focus-inner, +[type='submit']::-moz-focus-inner { + padding: 0; + border-style: none; +} + +/** + * Restore the focus styles unset by the previous rule. + */ + +button:-moz-focusring, +[type='button']:-moz-focusring, +[type='reset']:-moz-focusring, +[type='submit']:-moz-focusring { + outline: 1px dotted ButtonText; +} + +/** + * Correct the padding in Firefox. + */ + +fieldset { + padding: 0.35em 0.75em 0.625em; +} + +/** + * 1. Correct the text wrapping in Edge and IE. + * 2. Correct the color inheritance from `fieldset` elements in IE. + * 3. Remove the padding so developers are not caught out when they zero out + * `fieldset` elements in all browsers. + */ + +legend { + box-sizing: border-box; + /* 1 */ + display: table; + /* 1 */ + max-width: 100%; + /* 1 */ + padding: 0; + /* 3 */ + color: inherit; + /* 2 */ + white-space: normal; + /* 1 */ +} + +/** + * Add the correct vertical alignment in Chrome, Firefox, and Opera. + */ + +progress { + vertical-align: baseline; +} + +/** + * Remove the default vertical scrollbar in IE 10+. + */ + +textarea { + overflow: auto; +} + +/** + * 1. Add the correct box sizing in IE 10. + * 2. Remove the padding in IE 10. + */ + +[type='checkbox'], +[type='radio'] { + box-sizing: border-box; + /* 1 */ + padding: 0; + /* 2 */ +} + +/** + * Correct the cursor style of increment and decrement buttons in Chrome. + */ + +[type='number']::-webkit-inner-spin-button, +[type='number']::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Correct the odd appearance in Chrome and Safari. + * 2. Correct the outline style in Safari. + */ + +[type='search'] { + -webkit-appearance: textfield; + /* 1 */ + outline-offset: -2px; + /* 2 */ +} + +/** + * Remove the inner padding in Chrome and Safari on macOS. + */ + +[type='search']::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * 1. Correct the inability to style clickable types in iOS and Safari. + * 2. Change font properties to `inherit` in Safari. + */ + +::-webkit-file-upload-button { + /* 1 */ + font: inherit; + -webkit-appearance: button; + /* 2 */ +} + +/* Interactive + ========================================================================== */ + +/* + * Add the correct display in Edge, IE 10+, and Firefox. + */ + +details { + display: block; +} + +/* + * Add the correct display in all browsers. + */ + +summary { + display: list-item; +} + +/* Misc + ========================================================================== */ + +/** + * Add the correct display in IE 10+. + */ + +template { + display: none; +} + +/** + * Add the correct display in IE 10. + */ + +[hidden] { + display: none; +} diff --git a/library/styles/transition.scss b/library/styles/transition.scss new file mode 100644 index 0000000..54ec6f9 --- /dev/null +++ b/library/styles/transition.scss @@ -0,0 +1,39 @@ +/** + * @description vue过渡动画 + */ + +.fade-transform { + &-leave-active, + &-enter-active { + transition: $base-transition; + } + + &-enter, + &-leave-to { + opacity: 0; + } +} + +.no-transform { + &-leave-active, + &-enter-active { + transition: none; + } + + &-enter, + &-leave-to { + opacity: 0; + } +} + +/** + * @description 旋转动画 + */ +@keyframes rotate { + 0% { + transform: rotate(0); + } + 100% { + transform: rotate(360deg); + } +} diff --git a/library/styles/vab.scss b/library/styles/vab.scss new file mode 100644 index 0000000..71f222e --- /dev/null +++ b/library/styles/vab.scss @@ -0,0 +1,633 @@ +/** + * @description 全局样式 + */ +@import 'element-plus/theme-chalk/display.css'; +@import './normalize'; +@import './transition'; + +@mixin base-scrollbar { + &::-webkit-scrollbar { + width: 8px; + height: 8px; + } + + &::-webkit-scrollbar-thumb { + background-color: mix($base-color-white, $base-menu-background, 90%); + border: 3px solid transparent; + border-radius: 7px; + } + + &::-webkit-scrollbar-thumb:hover { + background-color: mix($base-color-white, $base-menu-background, 80%); + } +} + +.vab-layout-header, +[class*='-bar-container'] { + transition: $base-transition; + + * { + transition: $base-transition; + } +} + +html { + + body, + body[class*='vab-theme-'] { + position: relative; + box-sizing: border-box; + height: 100vh; + padding: 0; + overflow: hidden; + font-family: 'PingFang SC', Arial, 'Microsoft YaHei', sans-serif; + font-size: $base-font-size-default; + color: var(--el-color-black); + background: $base-color-background; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + + #app { + height: 100vh; + overflow: auto; + @include base-scrollbar; + + .vab-main { + transition: $base-transition; + + .vab-app-main { + width: 100%; + padding: $base-padding; + overflow: hidden; + transition: $base-transition; + + >section { + background: var(--el-color-white); + transition: $base-transition; + + >[class*='-container'] { + min-height: $base-keep-alive-height; + padding: $base-padding; + background: var(--el-color-white); + transition: $base-transition; + } + } + } + } + } + + * { + box-sizing: border-box; + outline: none !important; + @include base-scrollbar; + } + + [class*='ri-'] { + vertical-align: -3px !important; + } + + .vab-icon { + margin: 0 3px 0 0 !important; + } + + /*a标签 */ + a { + color: var(--el-color-primary); + text-decoration: none; + } + + /*图片 */ + img { + object-fit: cover; + + &[src=''], + &:not([src]) { + opacity: 0; + } + } + + /* vab-fullscreen全屏 */ + .vab-fullscreen { + position: fixed !important; + top: 0 !important; + left: 0 !important; + z-index: $base-z-index + 3 !important; + box-sizing: border-box !important; + width: 100vw !important; + height: 100vh !important; + padding-bottom: 15px !important; + overflow: auto !important; + } + + /* vab-dropdown下拉动画 */ + .vab-dropdown { + transition: $base-transition; + + &-active { + transform: rotateZ(180deg); + } + } + + /* vab-dot圆点动画 */ + .vab-dot { + position: relative; + display: inline-block; + width: 6px; + height: 6px; + margin-right: 3px; + vertical-align: middle; + border-radius: 50%; + + span { + position: absolute; + top: 0; + left: 0; + box-sizing: border-box; + display: block; + width: 100%; + height: 100%; + border-radius: 50%; + animation: vabDot 1.2s ease-in-out infinite; + + @keyframes vabDot { + 0% { + opacity: 0.6; + transform: scale(0.8); + } + + to { + opacity: 0; + transform: scale(2.4); + } + } + } + + &-success { + background: var(--el-color-success); + + span { + background: var(--el-color-success); + } + } + + &-error { + background: var(--el-color-error); + + span { + background: var(--el-color-error); + } + } + } + + /* vab-data-empty占位图 */ + .vab-data-empty { + display: flex; + align-items: center; + justify-content: center; + min-height: 600px; + margin: auto; + } + + /* el-descriptions */ + .el-descriptions { + &__title { + padding-left: 10px; + border-left: 5px solid var(--el-color-primary); + } + } + + /* el-button按钮 */ + .el-button { + border-radius: var(--el-border-radius-base); + + &:hover, + &:focus, + &:active, + &.is-disabled { + background-clip: padding-box; + } + + &.is-round { + border-radius: var(--el-border-radius-round); + } + + &.is-circle { + border-radius: var(--el-border-radius-circle); + } + + [class*='el-icon-']+span, + span+[class*='el-icon-'], + [class*='ri-']+span, + span+[class*='ri-'] { + margin-left: 3px; + } + } + + /* el-tag */ + .el-tag { + border-radius: var(--el-border-radius-base); + + &+.el-tag { + margin-left: 10px; + } + + &--light:not(&--success, &--info, &--warning, &--danger) { + --el-tag-bg-color: var(--el-color-primary-light-9); + --el-tag-border-color: var(--el-color-primary-light-8); + --el-tag-text-color: var(--el-color-primary); + --el-tag-hover-color: var(--el-color-primary); + } + + &--dark:not(&--success, &--info, &--warning, &--danger) { + --el-tag-bg-color: var(--el-color-primary); + --el-tag-border-color: var(--el-color-primary); + --el-tag-hover-color: var(--el-color-primary-2); + } + + &.is-round { + border-radius: var(--el-border-radius-round); + } + } + + /* .el-select-tags */ + .el-select-tags-wrapper { + .el-tag.el-tag { + margin-left: 0px; + } + } + + /* el-select */ + .el-select { + min-width: 115px; + } + + a+a, + /* span + span, */ + a+.el-button, + .el-button+a { + margin-left: 10px; + } + + .el-drawer__wrapper { + outline: none !important; + + * { + outline: none !important; + } + } + + /* el-overlay遮罩 */ + .el-overlay { + background-color: rgba(0, 0, 0, 0.1); + backdrop-filter: blur(3px); + } + + /* el-image-viewer遮罩 */ + .el-image-viewer__mask { + background-color: rgba(0, 0, 0, 0.1); + backdrop-filter: blur(3px); + } + + /* v-modal遮罩 */ + .v-modal { + z-index: $base-z-index; + background-color: rgba(0, 0, 0, 0.5); + opacity: 0.6; + //backdrop-filter: blur(10px); + } + + /* el-loading-mask遮罩 */ + .el-loading-mask { + z-index: $base-z-index - 10 !important; + + &.is-fullscreen { + z-index: $base-z-index + 99 !important; + } + } + + /* el-scrollbar滚动条 */ + .el-scrollbar { + height: 100%; + + &__bar { + z-index: 999; + } + + &__thumb { + background-color: mix($base-color-white, + $base-menu-background, + 90%); + + &:hover { + background-color: mix($base-color-white, + $base-menu-background, + 80%); + } + } + } + + /* el-form表单 */ + .el-form--label-top { + .el-form-item__label { + padding: 0; + } + } + + .el-form-item__label { + padding: 0 10px 0 0; + } + + .el-range-editor--small { + + .el-range__icon, + .el-range__close-icon { + line-height: 23.5px; + } + } + + /* el-badge */ + .el-badge__content { + border: 0; + } + + /* .el-page-header */ + .el-page-header { + margin: 0 0 $base-margin 0; + } + + /* el-alert */ + .el-alert { + margin: 0 0 $base-margin 0; + + &__closebtn { + position: absolute !important; + } + + &--success.is-light { + color: var(--el-color-success); + background-color: var(--el-color-success-lighter); + border: 1px solid var(--el-color-success); + + i { + color: var(--el-color-success); + } + } + + &--info.is-light { + color: var(--el-color-primary); + background-color: var(--el-color-primary-light-9); + border: 1px solid var(--el-color-primary); + + i { + color: var(--el-color-primary); + } + } + + &--warning.is-light { + color: var(--el-color-warning); + background-color: var(--el-color-warning-lighter); + border: 1px solid var(--el-color-warning); + + i { + color: var(--el-color-warning); + } + } + + &--error.is-light { + color: var(--el-color-error); + background-color: var(--el-color-error-lighter); + border: 1px solid var(--el-color-error); + + i { + color: var(--el-color-error); + } + } + } + + /* el-divider间隔线 */ + .el-divider--horizontal { + margin: 8px 0 $base-margin + 8px 0; + + .el-divider__text { + display: -webkit-box; + overflow: hidden; + text-overflow: ellipsis; + -webkit-line-clamp: 1; + -webkit-box-orient: vertical; + } + } + + /* nprogress进度条 */ + #nprogress { + position: fixed; + z-index: $base-z-index + 3; + + .bar { + background: var(--el-color-primary); + } + + .peg { + box-shadow: + 0 0 10px var(--el-color-primary), + 0 0 5px var(--el-color-primary); + } + } + + /* el-table表格 */ + .el-table { + .el-table__body-wrapper { + @include base-scrollbar; + } + + th { + background: #f5f7fa !important; + } + + td, + th { + position: relative; + box-sizing: border-box; + + .cell { + font-size: $base-font-size-default; + font-weight: normal; + color: #606266; + + .el-image { + width: 50px; + height: 50px; + border-radius: $base-border-radius; + } + } + } + } + + /* el-pagination分页 */ + .el-pagination { + justify-content: center; + margin: $base-margin 0 0 0; + font-weight: normal; + color: var(--el-color-black); + } + + /* el-menu菜单开始 */ + .el-menu, + .vab-column-grid { + user-select: none; + + /* plus处理图标间距 */ + div, + li, + span { + i+span { + margin-left: 3px; + } + } + + &.vab-column-grid-card, + &.vab-column-grid-vertical { + div { + i+span { + margin-left: 0; + } + } + } + } + + .el-dialog__body { + padding-right: 30px; + } + + /* el-dialog、el-message-box、el-popover、el-button、el-tag */ + @media (max-width: 576px) { + + .el-dialog, + .el-message-box, + .el-popover.el-popper { + width: 95% !important; + } + + + .el-button { + margin-bottom: 10px; + } + } + + /* el-card卡片 */ + .el-card { + margin-bottom: $base-margin; + border-radius: var(--el-border-radius-base); + + &__header { + position: relative; + + .card-header-tag { + position: absolute; + top: 15px; + right: 20px; + } + } + + &__body { + padding: $base-padding; + } + } + + /* .vab-hey-message */ + .vab-hey-message { + @mixin vab-hey-message { + padding: 15px; + background-color: var(--el-color-white); + border-color: var(--el-color-white); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.15); + + .el-message__content { + padding-right: $base-padding; + color: #34495e; + } + + .el-icon-close { + color: #34495e; + + &:hover { + opacity: 0.8; + } + } + } + + &-info { + @include vab-hey-message; + + i { + color: $base-color-grey; + } + } + + &-success { + @include vab-hey-message; + + i { + color: var(--el-color-success); + } + } + + &-warning { + @include vab-hey-message; + + i { + color: var(--el-color-warning); + } + } + + &-error { + @include vab-hey-message; + + i { + color: var(--el-color-error); + } + } + } + + /* vab-table-expand */ + .vab-table-expand { + padding: $base-padding; + line-height: 30px; + + &-title { + display: inline-block; + width: 80px; + font-weight: bold; + } + } + + :not(.no-background-container).auto-height-container { + display: flex; + flex-direction: column; + height: var(--el-container-height); + + .el-table { + flex: 1; + } + + .el-scrollbar { + //margin-right: -20px; + + .vab-auto-box { + flex: 1; + width: 100%; + padding: 0 var(--el-padding) 0 0; + } + } + + @media (max-width: 1024px) { + height: auto; + } + } + + + .el-card__body { + overflow: hidden; + flex: none; + } + } +} \ No newline at end of file diff --git a/library/styles/variables/vab-blue-variables.module.scss b/library/styles/variables/vab-blue-variables.module.scss new file mode 100644 index 0000000..3ac22ee --- /dev/null +++ b/library/styles/variables/vab-blue-variables.module.scss @@ -0,0 +1,43 @@ +$base-color-primary: #1890ff; +$base-color-success: #13ce66; +$base-color-warning: #ffba00; +$base-color-danger: #ff4d4f; +$base-color-error: #ff4d4f; +$base-color-transition: #77e19d; + +:export { + vab-color-grey: $base-color-grey; + vab-color-black: $base-color-black; + vab-color-primary: $base-color-primary; + vab-color-primary-light-1: mix($base-color-white, $base-color-primary, 10%); + vab-color-primary-light-2: mix($base-color-white, $base-color-primary, 20%); + vab-color-primary-light-3: mix($base-color-white, $base-color-primary, 30%); + vab-color-primary-light-4: mix($base-color-white, $base-color-primary, 40%); + vab-color-primary-light-5: mix($base-color-white, $base-color-primary, 50%); + vab-color-primary-light-6: mix($base-color-white, $base-color-primary, 60%); + vab-color-primary-light-7: mix($base-color-white, $base-color-primary, 70%); + vab-color-primary-light-8: mix($base-color-white, $base-color-primary, 80%); + vab-color-primary-light-9: mix($base-color-white, $base-color-primary, 90%); + vab-color-success: $base-color-success; + vab-color-success-light: mix($base-color-white, $base-color-success, 80%); + vab-color-success-lighter: mix($base-color-white, $base-color-success, 90%); + vab-color-warning: $base-color-warning; + vab-color-warning-light: mix($base-color-white, $base-color-warning, 80%); + vab-color-warning-lighter: mix($base-color-white, $base-color-warning, 90%); + vab-color-danger: $base-color-danger; + vab-color-danger-light: mix($base-color-white, $base-color-danger, 80%); + vab-color-danger-lighter: mix($base-color-white, $base-color-danger, 90%); + vab-color-error: $base-color-error; + vab-color-error-light: mix($base-color-white, $base-color-error, 80%); + vab-color-error-lighter: mix($base-color-white, $base-color-error, 90%); + vab-color-info: $base-color-text-secondary; + vab-color-info-light: mix($base-color-white, + $base-color-text-secondary, + 80%); + vab-color-info-lighter: mix($base-color-white, + $base-color-text-secondary, + 90%); + vab-border-radius-base: 5px; + vab-color-transition: $base-color-transition; + vab-left-menu-width: $base-left-menu-width; +} \ No newline at end of file diff --git a/library/styles/variables/vab-green-variables.module.scss b/library/styles/variables/vab-green-variables.module.scss new file mode 100644 index 0000000..dae104d --- /dev/null +++ b/library/styles/variables/vab-green-variables.module.scss @@ -0,0 +1,43 @@ +$base-color-primary: #41b584; +$base-color-success: #13ce66; +$base-color-warning: #ffba00; +$base-color-danger: #ff4d4f; +$base-color-error: #ff4d4f; +$base-color-transition: #1890ff; + +:export { + vab-color-grey: $base-color-grey; + vab-color-black: $base-color-black; + vab-color-primary: $base-color-primary; + vab-color-primary-light-1: mix($base-color-white, $base-color-primary, 10%); + vab-color-primary-light-2: mix($base-color-white, $base-color-primary, 20%); + vab-color-primary-light-3: mix($base-color-white, $base-color-primary, 30%); + vab-color-primary-light-4: mix($base-color-white, $base-color-primary, 40%); + vab-color-primary-light-5: mix($base-color-white, $base-color-primary, 50%); + vab-color-primary-light-6: mix($base-color-white, $base-color-primary, 60%); + vab-color-primary-light-7: mix($base-color-white, $base-color-primary, 70%); + vab-color-primary-light-8: mix($base-color-white, $base-color-primary, 80%); + vab-color-primary-light-9: mix($base-color-white, $base-color-primary, 90%); + vab-color-success: $base-color-success; + vab-color-success-light: mix($base-color-white, $base-color-success, 80%); + vab-color-success-lighter: mix($base-color-white, $base-color-success, 90%); + vab-color-warning: $base-color-warning; + vab-color-warning-light: mix($base-color-white, $base-color-warning, 80%); + vab-color-warning-lighter: mix($base-color-white, $base-color-warning, 90%); + vab-color-danger: $base-color-danger; + vab-color-danger-light: mix($base-color-white, $base-color-danger, 80%); + vab-color-danger-lighter: mix($base-color-white, $base-color-danger, 90%); + vab-color-error: $base-color-error; + vab-color-error-light: mix($base-color-white, $base-color-error, 80%); + vab-color-error-lighter: mix($base-color-white, $base-color-error, 90%); + vab-color-info: $base-color-text-secondary; + vab-color-info-light: mix($base-color-white, + $base-color-text-secondary, + 80%); + vab-color-info-lighter: mix($base-color-white, + $base-color-text-secondary, + 90%); + vab-border-radius-base: 5px; + vab-color-transition: $base-color-transition; + vab-left-menu-width: $base-left-menu-width; +} \ No newline at end of file diff --git a/library/styles/variables/vab-purple-variables.module.scss b/library/styles/variables/vab-purple-variables.module.scss new file mode 100644 index 0000000..c368464 --- /dev/null +++ b/library/styles/variables/vab-purple-variables.module.scss @@ -0,0 +1,43 @@ +$base-color-primary: #6954f0; +$base-color-success: #13ce66; +$base-color-warning: #ffba00; +$base-color-danger: #ff4d4f; +$base-color-error: #ff4d4f; +$base-color-transition: #1890ff; + +:export { + vab-color-grey: $base-color-grey; + vab-color-black: $base-color-black; + vab-color-primary: $base-color-primary; + vab-color-primary-light-1: mix($base-color-white, $base-color-primary, 10%); + vab-color-primary-light-2: mix($base-color-white, $base-color-primary, 20%); + vab-color-primary-light-3: mix($base-color-white, $base-color-primary, 30%); + vab-color-primary-light-4: mix($base-color-white, $base-color-primary, 40%); + vab-color-primary-light-5: mix($base-color-white, $base-color-primary, 50%); + vab-color-primary-light-6: mix($base-color-white, $base-color-primary, 60%); + vab-color-primary-light-7: mix($base-color-white, $base-color-primary, 70%); + vab-color-primary-light-8: mix($base-color-white, $base-color-primary, 80%); + vab-color-primary-light-9: mix($base-color-white, $base-color-primary, 90%); + vab-color-success: $base-color-success; + vab-color-success-light: mix($base-color-white, $base-color-success, 80%); + vab-color-success-lighter: mix($base-color-white, $base-color-success, 90%); + vab-color-warning: $base-color-warning; + vab-color-warning-light: mix($base-color-white, $base-color-warning, 80%); + vab-color-warning-lighter: mix($base-color-white, $base-color-warning, 90%); + vab-color-danger: $base-color-danger; + vab-color-danger-light: mix($base-color-white, $base-color-danger, 80%); + vab-color-danger-lighter: mix($base-color-white, $base-color-danger, 90%); + vab-color-error: $base-color-error; + vab-color-error-light: mix($base-color-white, $base-color-error, 80%); + vab-color-error-lighter: mix($base-color-white, $base-color-error, 90%); + vab-color-info: $base-color-text-secondary; + vab-color-info-light: mix($base-color-white, + $base-color-text-secondary, + 80%); + vab-color-info-lighter: mix($base-color-white, + $base-color-text-secondary, + 90%); + vab-border-radius-base: 5px; + vab-color-transition: $base-color-transition; + vab-left-menu-width: $base-left-menu-width; +} \ No newline at end of file diff --git a/library/styles/variables/vab-red-variables.module.scss b/library/styles/variables/vab-red-variables.module.scss new file mode 100644 index 0000000..09bcdd5 --- /dev/null +++ b/library/styles/variables/vab-red-variables.module.scss @@ -0,0 +1,43 @@ +$base-color-primary: #f34d37; +$base-color-success: #13ce66; +$base-color-warning: #ffba00; +$base-color-danger: #ff4d4f; +$base-color-error: #ff4d4f; +$base-color-transition: #ffa194; + +:export { + vab-color-grey: $base-color-grey; + vab-color-black: $base-color-black; + vab-color-primary: $base-color-primary; + vab-color-primary-light-1: mix($base-color-white, $base-color-primary, 10%); + vab-color-primary-light-2: mix($base-color-white, $base-color-primary, 20%); + vab-color-primary-light-3: mix($base-color-white, $base-color-primary, 30%); + vab-color-primary-light-4: mix($base-color-white, $base-color-primary, 40%); + vab-color-primary-light-5: mix($base-color-white, $base-color-primary, 50%); + vab-color-primary-light-6: mix($base-color-white, $base-color-primary, 60%); + vab-color-primary-light-7: mix($base-color-white, $base-color-primary, 70%); + vab-color-primary-light-8: mix($base-color-white, $base-color-primary, 80%); + vab-color-primary-light-9: mix($base-color-white, $base-color-primary, 90%); + vab-color-success: $base-color-success; + vab-color-success-light: mix($base-color-white, $base-color-success, 80%); + vab-color-success-lighter: mix($base-color-white, $base-color-success, 90%); + vab-color-warning: $base-color-warning; + vab-color-warning-light: mix($base-color-white, $base-color-warning, 80%); + vab-color-warning-lighter: mix($base-color-white, $base-color-warning, 90%); + vab-color-danger: $base-color-danger; + vab-color-danger-light: mix($base-color-white, $base-color-danger, 80%); + vab-color-danger-lighter: mix($base-color-white, $base-color-danger, 90%); + vab-color-error: $base-color-error; + vab-color-error-light: mix($base-color-white, $base-color-error, 80%); + vab-color-error-lighter: mix($base-color-white, $base-color-error, 90%); + vab-color-info: $base-color-text-secondary; + vab-color-info-light: mix($base-color-white, + $base-color-text-secondary, + 80%); + vab-color-info-lighter: mix($base-color-white, + $base-color-text-secondary, + 90%); + vab-border-radius-base: 5px; + vab-color-transition: $base-color-transition; + vab-left-menu-width: $base-left-menu-width; +} \ No newline at end of file diff --git a/library/styles/variables/variables.module.scss b/library/styles/variables/variables.module.scss new file mode 100644 index 0000000..29d1ed3 --- /dev/null +++ b/library/styles/variables/variables.module.scss @@ -0,0 +1,109 @@ +/** + * @description 全局主题变量配置 + */ +//颜色配置 +$base-color-white: #ffffff; +$base-color-black: #515a6e; +$base-color-primary: #1890ff; +$base-color-success: #13ce66; +$base-color-warning: #ffba00; +$base-color-danger: #ff6700; +$base-color-error: #ff4d4f; +$base-color-grey: rgba(0, 0, 0, 0.65); +$base-color-background: #f6f8f9; + +$base-color-text-primary: #303133; +$base-color-text-regular: #606266; +$base-color-text-secondary: #909399; +$base-color-text-placeholder: #c0c4cc; +$base-border-color-base: #dcdfe6; +$base-border-color-light: #e4e7ed; +$base-border-color-lighter: #ebeef5; +$base-border-color-extra-light: #f2f6fc; +$base-background-color-base: #f5f7fa; + +//默认层级 +$base-z-index: 1999; +//分栏最左侧菜单背景色 +$base-column-first-menu-background: #282c34; +//分栏菜单背景色 +$base-column-second-menu-background: #fff; +//分栏菜单选中背景色 +$base-column-second-menu-active: mix($base-color-white, + $base-color-primary, + 10%); +//横向、纵向菜单背景色 +$base-menu-background: #282c34; +//菜单文字颜色 +$base-menu-color: hsla(0, 0%, 100%, 0.95); +//菜单选中文字颜色 +$base-menu-color-active: hsla(0, 0%, 100%, 0.95); +//菜单选中背景色 +$base-menu-active: $base-color-primary; +//标题颜色 +$base-title-color: #fff; +//字体大小配置 +$base-font-size-small: 12px; +$base-font-size-default: 14px; +$base-font-size-big: 16px; +$base-font-size-bigger: 18px; +$base-font-size-max: 22px; +//最大宽度 +$base-main-width: 1279px; +//圆角 +$base-border-radius: 5px; +//边框颜色 +$base-border-color: #dcdfe6; +//输入框高度 +$base-input-height: 32px; +//默认margin +$base-margin: 20px; +//默认padding +$base-padding: 20px; +//默认阴影 +$base-box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08); +//横向top-bar、logo、一级菜单的高度 +$base-header-height: 60px; +//纵向、综合、分栏logo的高度 +$base-logo-height: 60px; +//顶部nav-bar的高度 +$base-nav-height: 60px; +//顶部标签页tabs-bar的高度 +$base-tabs-height: 50px; +//顶部标签页tabs-bar中每一个item的高度 +$base-tag-item-height: 34px; +//菜单li标签的高度 +$base-menu-item-height: 50px; +//app-main的高度 +$base-keep-alive-height: calc(100vh - #{$base-nav-height} - #{$base-tabs-height} - #{$base-padding} * 2 - 55px); +//纵向左侧导航未折叠的宽度 +$base-left-menu-width: 266px; +//纵向左侧导航已折叠的宽度 +$base-left-menu-width-min: 64px; +//纵向左侧导航已折叠右侧内容的宽度 +$base-right-content-width-min: calc(100% - #{$base-left-menu-width-min}); +//默认动画 +$base-transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1), + border 0s, + color 0.1s, + font-size 0s; + +:export { + // 菜单文字颜色变量导出 + menu-color: $base-menu-color; + // 菜单选中文字颜色变量导出 + menu-color-active: $base-menu-color-active; + // 菜单背景色变量导出 + menu-background: $base-menu-background; + // 分栏菜单背景色变量导出 + column-second-menu-background: $base-column-second-menu-background; + // 导出圆角 + vab-border-radius: $base-border-radius; +} + +:root { + --el-container-height: #{$base-keep-alive-height}; + --el-margin: #{$base-margin}; + --el-padding: #{$base-padding}; + --el-border-radius-base: #{$base-border-radius} !important; +} \ No newline at end of file diff --git a/mock/controller/area.js b/mock/controller/area.js new file mode 100644 index 0000000..d816fc0 --- /dev/null +++ b/mock/controller/area.js @@ -0,0 +1,13693 @@ +const list = [ + { + name: '北京市', + code: '110000', + region: 'north', + provinceLevelCity: true, + children: [ + { + name: '市辖区', + code: '110100', + children: [ + { + name: '东城区', + code: '110101', + }, + { + name: '西城区', + code: '110102', + }, + { + name: '朝阳区', + code: '110105', + }, + { + name: '丰台区', + code: '110106', + }, + { + name: '石景山区', + code: '110107', + }, + { + name: '海淀区', + code: '110108', + }, + { + name: '门头沟区', + code: '110109', + }, + { + name: '房山区', + code: '110111', + }, + { + name: '通州区', + code: '110112', + }, + { + name: '顺义区', + code: '110113', + }, + { + name: '昌平区', + code: '110114', + }, + { + name: '大兴区', + code: '110115', + }, + { + name: '怀柔区', + code: '110116', + }, + { + name: '平谷区', + code: '110117', + }, + { + name: '密云区', + code: '110118', + }, + { + name: '延庆区', + code: '110119', + }, + ], + }, + ], + }, + { + name: '天津市', + code: '120000', + region: 'north', + provinceLevelCity: true, + children: [ + { + name: '市辖区', + code: '120100', + children: [ + { + name: '和平区', + code: '120101', + }, + { + name: '河东区', + code: '120102', + }, + { + name: '河西区', + code: '120103', + }, + { + name: '南开区', + code: '120104', + }, + { + name: '河北区', + code: '120105', + }, + { + name: '红桥区', + code: '120106', + }, + { + name: '东丽区', + code: '120110', + }, + { + name: '西青区', + code: '120111', + }, + { + name: '津南区', + code: '120112', + }, + { + name: '北辰区', + code: '120113', + }, + { + name: '武清区', + code: '120114', + }, + { + name: '宝坻区', + code: '120115', + }, + { + name: '滨海新区', + code: '120116', + }, + { + name: '宁河区', + code: '120117', + }, + { + name: '静海区', + code: '120118', + }, + { + name: '蓟州区', + code: '120119', + }, + ], + }, + ], + }, + { + name: '河北省', + code: '130000', + region: 'north', + children: [ + { + name: '石家庄市', + code: '130100', + children: [ + { + name: '长安区', + code: '130102', + }, + { + name: '桥西区', + code: '130104', + }, + { + name: '新华区', + code: '130105', + }, + { + name: '井陉矿区', + code: '130107', + }, + { + name: '裕华区', + code: '130108', + }, + { + name: '藁城区', + code: '130109', + }, + { + name: '鹿泉区', + code: '130110', + }, + { + name: '栾城区', + code: '130111', + }, + { + name: '井陉县', + code: '130121', + }, + { + name: '正定县', + code: '130123', + }, + { + name: '行唐县', + code: '130125', + }, + { + name: '灵寿县', + code: '130126', + }, + { + name: '高邑县', + code: '130127', + }, + { + name: '深泽县', + code: '130128', + }, + { + name: '赞皇县', + code: '130129', + }, + { + name: '无极县', + code: '130130', + }, + { + name: '平山县', + code: '130131', + }, + { + name: '元氏县', + code: '130132', + }, + { + name: '赵县', + code: '130133', + }, + { + name: '辛集市', + code: '130181', + }, + { + name: '晋州市', + code: '130183', + }, + { + name: '新乐市', + code: '130184', + }, + ], + }, + { + name: '唐山市', + code: '130200', + children: [ + { + name: '路南区', + code: '130202', + }, + { + name: '路北区', + code: '130203', + }, + { + name: '古冶区', + code: '130204', + }, + { + name: '开平区', + code: '130205', + }, + { + name: '丰南区', + code: '130207', + }, + { + name: '丰润区', + code: '130208', + }, + { + name: '曹妃甸区', + code: '130209', + }, + { + name: '滦南县', + code: '130224', + }, + { + name: '乐亭县', + code: '130225', + }, + { + name: '迁西县', + code: '130227', + }, + { + name: '玉田县', + code: '130229', + }, + { + name: '遵化市', + code: '130281', + }, + { + name: '迁安市', + code: '130283', + }, + { + name: '滦州市', + code: '130284', + }, + ], + }, + { + name: '秦皇岛市', + code: '130300', + children: [ + { + name: '海港区', + code: '130302', + }, + { + name: '山海关区', + code: '130303', + }, + { + name: '北戴河区', + code: '130304', + }, + { + name: '抚宁区', + code: '130306', + }, + { + name: '青龙满族自治县', + code: '130321', + }, + { + name: '昌黎县', + code: '130322', + }, + { + name: '卢龙县', + code: '130324', + }, + ], + }, + { + name: '邯郸市', + code: '130400', + children: [ + { + name: '邯山区', + code: '130402', + }, + { + name: '丛台区', + code: '130403', + }, + { + name: '复兴区', + code: '130404', + }, + { + name: '峰峰矿区', + code: '130406', + }, + { + name: '肥乡区', + code: '130407', + }, + { + name: '永年区', + code: '130408', + }, + { + name: '临漳县', + code: '130423', + }, + { + name: '成安县', + code: '130424', + }, + { + name: '大名县', + code: '130425', + }, + { + name: '涉县', + code: '130426', + }, + { + name: '磁县', + code: '130427', + }, + { + name: '邱县', + code: '130430', + }, + { + name: '鸡泽县', + code: '130431', + }, + { + name: '广平县', + code: '130432', + }, + { + name: '馆陶县', + code: '130433', + }, + { + name: '魏县', + code: '130434', + }, + { + name: '曲周县', + code: '130435', + }, + { + name: '武安市', + code: '130481', + }, + ], + }, + { + name: '邢台市', + code: '130500', + children: [ + { + name: '桥东区', + code: '130502', + }, + { + name: '桥西区', + code: '130503', + }, + { + name: '邢台县', + code: '130521', + }, + { + name: '临城县', + code: '130522', + }, + { + name: '内丘县', + code: '130523', + }, + { + name: '柏乡县', + code: '130524', + }, + { + name: '隆尧县', + code: '130525', + }, + { + name: '任县', + code: '130526', + }, + { + name: '南和县', + code: '130527', + }, + { + name: '宁晋县', + code: '130528', + }, + { + name: '巨鹿县', + code: '130529', + }, + { + name: '新河县', + code: '130530', + }, + { + name: '广宗县', + code: '130531', + }, + { + name: '平乡县', + code: '130532', + }, + { + name: '威县', + code: '130533', + }, + { + name: '清河县', + code: '130534', + }, + { + name: '临西县', + code: '130535', + }, + { + name: '南宫市', + code: '130581', + }, + { + name: '沙河市', + code: '130582', + }, + ], + }, + { + name: '保定市', + code: '130600', + children: [ + { + name: '竞秀区', + code: '130602', + }, + { + name: '莲池区', + code: '130606', + }, + { + name: '满城区', + code: '130607', + }, + { + name: '清苑区', + code: '130608', + }, + { + name: '徐水区', + code: '130609', + }, + { + name: '涞水县', + code: '130623', + }, + { + name: '阜平县', + code: '130624', + }, + { + name: '定兴县', + code: '130626', + }, + { + name: '唐县', + code: '130627', + }, + { + name: '高阳县', + code: '130628', + }, + { + name: '容城县', + code: '130629', + }, + { + name: '涞源县', + code: '130630', + }, + { + name: '望都县', + code: '130631', + }, + { + name: '安新县', + code: '130632', + }, + { + name: '易县', + code: '130633', + }, + { + name: '曲阳县', + code: '130634', + }, + { + name: '蠡县', + code: '130635', + }, + { + name: '顺平县', + code: '130636', + }, + { + name: '博野县', + code: '130637', + }, + { + name: '雄县', + code: '130638', + }, + { + name: '涿州市', + code: '130681', + }, + { + name: '定州市', + code: '130682', + }, + { + name: '安国市', + code: '130683', + }, + { + name: '高碑店市', + code: '130684', + }, + ], + }, + { + name: '张家口市', + code: '130700', + children: [ + { + name: '桥东区', + code: '130702', + }, + { + name: '桥西区', + code: '130703', + }, + { + name: '宣化区', + code: '130705', + }, + { + name: '下花园区', + code: '130706', + }, + { + name: '万全区', + code: '130708', + }, + { + name: '崇礼区', + code: '130709', + }, + { + name: '张北县', + code: '130722', + }, + { + name: '康保县', + code: '130723', + }, + { + name: '沽源县', + code: '130724', + }, + { + name: '尚义县', + code: '130725', + }, + { + name: '蔚县', + code: '130726', + }, + { + name: '阳原县', + code: '130727', + }, + { + name: '怀安县', + code: '130728', + }, + { + name: '怀来县', + code: '130730', + }, + { + name: '涿鹿县', + code: '130731', + }, + { + name: '赤城县', + code: '130732', + }, + ], + }, + { + name: '承德市', + code: '130800', + children: [ + { + name: '双桥区', + code: '130802', + }, + { + name: '双滦区', + code: '130803', + }, + { + name: '鹰手营子矿区', + code: '130804', + }, + { + name: '承德县', + code: '130821', + }, + { + name: '兴隆县', + code: '130822', + }, + { + name: '滦平县', + code: '130824', + }, + { + name: '隆化县', + code: '130825', + }, + { + name: '丰宁满族自治县', + code: '130826', + }, + { + name: '宽城满族自治县', + code: '130827', + }, + { + name: '围场满族蒙古族自治县', + code: '130828', + }, + { + name: '平泉市', + code: '130881', + }, + ], + }, + { + name: '沧州市', + code: '130900', + children: [ + { + name: '新华区', + code: '130902', + }, + { + name: '运河区', + code: '130903', + }, + { + name: '沧县', + code: '130921', + }, + { + name: '青县', + code: '130922', + }, + { + name: '东光县', + code: '130923', + }, + { + name: '海兴县', + code: '130924', + }, + { + name: '盐山县', + code: '130925', + }, + { + name: '肃宁县', + code: '130926', + }, + { + name: '南皮县', + code: '130927', + }, + { + name: '吴桥县', + code: '130928', + }, + { + name: '献县', + code: '130929', + }, + { + name: '孟村回族自治县', + code: '130930', + }, + { + name: '泊头市', + code: '130981', + }, + { + name: '任丘市', + code: '130982', + }, + { + name: '黄骅市', + code: '130983', + }, + { + name: '河间市', + code: '130984', + }, + ], + }, + { + name: '廊坊市', + code: '131000', + children: [ + { + name: '安次区', + code: '131002', + }, + { + name: '广阳区', + code: '131003', + }, + { + name: '固安县', + code: '131022', + }, + { + name: '永清县', + code: '131023', + }, + { + name: '香河县', + code: '131024', + }, + { + name: '大城县', + code: '131025', + }, + { + name: '文安县', + code: '131026', + }, + { + name: '大厂回族自治县', + code: '131028', + }, + { + name: '霸州市', + code: '131081', + }, + { + name: '三河市', + code: '131082', + }, + ], + }, + { + name: '衡水市', + code: '131100', + children: [ + { + name: '桃城区', + code: '131102', + }, + { + name: '冀州区', + code: '131103', + }, + { + name: '枣强县', + code: '131121', + }, + { + name: '武邑县', + code: '131122', + }, + { + name: '武强县', + code: '131123', + }, + { + name: '饶阳县', + code: '131124', + }, + { + name: '安平县', + code: '131125', + }, + { + name: '故城县', + code: '131126', + }, + { + name: '景县', + code: '131127', + }, + { + name: '阜城县', + code: '131128', + }, + { + name: '深州市', + code: '131182', + }, + ], + }, + ], + }, + { + name: '山西省', + code: '140000', + region: 'north', + children: [ + { + name: '太原市', + code: '140100', + children: [ + { + name: '小店区', + code: '140105', + }, + { + name: '迎泽区', + code: '140106', + }, + { + name: '杏花岭区', + code: '140107', + }, + { + name: '尖草坪区', + code: '140108', + }, + { + name: '万柏林区', + code: '140109', + }, + { + name: '晋源区', + code: '140110', + }, + { + name: '清徐县', + code: '140121', + }, + { + name: '阳曲县', + code: '140122', + }, + { + name: '娄烦县', + code: '140123', + }, + { + name: '古交市', + code: '140181', + }, + ], + }, + { + name: '大同市', + code: '140200', + children: [ + { + name: '新荣区', + code: '140212', + }, + { + name: '平城区', + code: '140213', + }, + { + name: '云冈区', + code: '140214', + }, + { + name: '云州区', + code: '140215', + }, + { + name: '阳高县', + code: '140221', + }, + { + name: '天镇县', + code: '140222', + }, + { + name: '广灵县', + code: '140223', + }, + { + name: '灵丘县', + code: '140224', + }, + { + name: '浑源县', + code: '140225', + }, + { + name: '左云县', + code: '140226', + }, + ], + }, + { + name: '阳泉市', + code: '140300', + children: [ + { + name: '城区', + code: '140302', + }, + { + name: '矿区', + code: '140303', + }, + { + name: '郊区', + code: '140311', + }, + { + name: '平定县', + code: '140321', + }, + { + name: '盂县', + code: '140322', + }, + ], + }, + { + name: '长治市', + code: '140400', + children: [ + { + name: '潞州区', + code: '140403', + }, + { + name: '上党区', + code: '140404', + }, + { + name: '屯留区', + code: '140405', + }, + { + name: '潞城区', + code: '140406', + }, + { + name: '襄垣县', + code: '140423', + }, + { + name: '平顺县', + code: '140425', + }, + { + name: '黎城县', + code: '140426', + }, + { + name: '壶关县', + code: '140427', + }, + { + name: '长子县', + code: '140428', + }, + { + name: '武乡县', + code: '140429', + }, + { + name: '沁县', + code: '140430', + }, + { + name: '沁源县', + code: '140431', + }, + ], + }, + { + name: '晋城市', + code: '140500', + children: [ + { + name: '城区', + code: '140502', + }, + { + name: '沁水县', + code: '140521', + }, + { + name: '阳城县', + code: '140522', + }, + { + name: '陵川县', + code: '140524', + }, + { + name: '泽州县', + code: '140525', + }, + { + name: '高平市', + code: '140581', + }, + ], + }, + { + name: '朔州市', + code: '140600', + children: [ + { + name: '朔城区', + code: '140602', + }, + { + name: '平鲁区', + code: '140603', + }, + { + name: '山阴县', + code: '140621', + }, + { + name: '应县', + code: '140622', + }, + { + name: '右玉县', + code: '140623', + }, + { + name: '怀仁市', + code: '140681', + }, + ], + }, + { + name: '晋中市', + code: '140700', + children: [ + { + name: '榆次区', + code: '140702', + }, + { + name: '榆社县', + code: '140721', + }, + { + name: '左权县', + code: '140722', + }, + { + name: '和顺县', + code: '140723', + }, + { + name: '昔阳县', + code: '140724', + }, + { + name: '寿阳县', + code: '140725', + }, + { + name: '太谷县', + code: '140726', + }, + { + name: '祁县', + code: '140727', + }, + { + name: '平遥县', + code: '140728', + }, + { + name: '灵石县', + code: '140729', + }, + { + name: '介休市', + code: '140781', + }, + ], + }, + { + name: '运城市', + code: '140800', + children: [ + { + name: '盐湖区', + code: '140802', + }, + { + name: '临猗县', + code: '140821', + }, + { + name: '万荣县', + code: '140822', + }, + { + name: '闻喜县', + code: '140823', + }, + { + name: '稷山县', + code: '140824', + }, + { + name: '新绛县', + code: '140825', + }, + { + name: '绛县', + code: '140826', + }, + { + name: '垣曲县', + code: '140827', + }, + { + name: '夏县', + code: '140828', + }, + { + name: '平陆县', + code: '140829', + }, + { + name: '芮城县', + code: '140830', + }, + { + name: '永济市', + code: '140881', + }, + { + name: '河津市', + code: '140882', + }, + ], + }, + { + name: '忻州市', + code: '140900', + children: [ + { + name: '忻府区', + code: '140902', + }, + { + name: '定襄县', + code: '140921', + }, + { + name: '五台县', + code: '140922', + }, + { + name: '代县', + code: '140923', + }, + { + name: '繁峙县', + code: '140924', + }, + { + name: '宁武县', + code: '140925', + }, + { + name: '静乐县', + code: '140926', + }, + { + name: '神池县', + code: '140927', + }, + { + name: '五寨县', + code: '140928', + }, + { + name: '岢岚县', + code: '140929', + }, + { + name: '河曲县', + code: '140930', + }, + { + name: '保德县', + code: '140931', + }, + { + name: '偏关县', + code: '140932', + }, + { + name: '原平市', + code: '140981', + }, + ], + }, + { + name: '临汾市', + code: '141000', + children: [ + { + name: '尧都区', + code: '141002', + }, + { + name: '曲沃县', + code: '141021', + }, + { + name: '翼城县', + code: '141022', + }, + { + name: '襄汾县', + code: '141023', + }, + { + name: '洪洞县', + code: '141024', + }, + { + name: '古县', + code: '141025', + }, + { + name: '安泽县', + code: '141026', + }, + { + name: '浮山县', + code: '141027', + }, + { + name: '吉县', + code: '141028', + }, + { + name: '乡宁县', + code: '141029', + }, + { + name: '大宁县', + code: '141030', + }, + { + name: '隰县', + code: '141031', + }, + { + name: '永和县', + code: '141032', + }, + { + name: '蒲县', + code: '141033', + }, + { + name: '汾西县', + code: '141034', + }, + { + name: '侯马市', + code: '141081', + }, + { + name: '霍州市', + code: '141082', + }, + ], + }, + { + name: '吕梁市', + code: '141100', + children: [ + { + name: '离石区', + code: '141102', + }, + { + name: '文水县', + code: '141121', + }, + { + name: '交城县', + code: '141122', + }, + { + name: '兴县', + code: '141123', + }, + { + name: '临县', + code: '141124', + }, + { + name: '柳林县', + code: '141125', + }, + { + name: '石楼县', + code: '141126', + }, + { + name: '岚县', + code: '141127', + }, + { + name: '方山县', + code: '141128', + }, + { + name: '中阳县', + code: '141129', + }, + { + name: '交口县', + code: '141130', + }, + { + name: '孝义市', + code: '141181', + }, + { + name: '汾阳市', + code: '141182', + }, + ], + }, + ], + }, + { + name: '内蒙古自治区', + code: '150000', + region: 'north', + autonomousRegion: true, + children: [ + { + name: '呼和浩特市', + code: '150100', + children: [ + { + name: '新城区', + code: '150102', + }, + { + name: '回民区', + code: '150103', + }, + { + name: '玉泉区', + code: '150104', + }, + { + name: '赛罕区', + code: '150105', + }, + { + name: '土默特左旗', + code: '150121', + }, + { + name: '托克托县', + code: '150122', + }, + { + name: '和林格尔县', + code: '150123', + }, + { + name: '清水河县', + code: '150124', + }, + { + name: '武川县', + code: '150125', + }, + ], + }, + { + name: '包头市', + code: '150200', + children: [ + { + name: '东河区', + code: '150202', + }, + { + name: '昆都仑区', + code: '150203', + }, + { + name: '青山区', + code: '150204', + }, + { + name: '石拐区', + code: '150205', + }, + { + name: '白云鄂博矿区', + code: '150206', + }, + { + name: '九原区', + code: '150207', + }, + { + name: '土默特右旗', + code: '150221', + }, + { + name: '固阳县', + code: '150222', + }, + { + name: '达尔罕茂明安联合旗', + code: '150223', + }, + ], + }, + { + name: '乌海市', + code: '150300', + children: [ + { + name: '海勃湾区', + code: '150302', + }, + { + name: '海南区', + code: '150303', + }, + { + name: '乌达区', + code: '150304', + }, + ], + }, + { + name: '赤峰市', + code: '150400', + children: [ + { + name: '红山区', + code: '150402', + }, + { + name: '元宝山区', + code: '150403', + }, + { + name: '松山区', + code: '150404', + }, + { + name: '阿鲁科尔沁旗', + code: '150421', + }, + { + name: '巴林左旗', + code: '150422', + }, + { + name: '巴林右旗', + code: '150423', + }, + { + name: '林西县', + code: '150424', + }, + { + name: '克什克腾旗', + code: '150425', + }, + { + name: '翁牛特旗', + code: '150426', + }, + { + name: '喀喇沁旗', + code: '150428', + }, + { + name: '宁城县', + code: '150429', + }, + { + name: '敖汉旗', + code: '150430', + }, + ], + }, + { + name: '通辽市', + code: '150500', + children: [ + { + name: '科尔沁区', + code: '150502', + }, + { + name: '科尔沁左翼中旗', + code: '150521', + }, + { + name: '科尔沁左翼后旗', + code: '150522', + }, + { + name: '开鲁县', + code: '150523', + }, + { + name: '库伦旗', + code: '150524', + }, + { + name: '奈曼旗', + code: '150525', + }, + { + name: '扎鲁特旗', + code: '150526', + }, + { + name: '霍林郭勒市', + code: '150581', + }, + ], + }, + { + name: '鄂尔多斯市', + code: '150600', + children: [ + { + name: '东胜区', + code: '150602', + }, + { + name: '康巴什区', + code: '150603', + }, + { + name: '达拉特旗', + code: '150621', + }, + { + name: '准格尔旗', + code: '150622', + }, + { + name: '鄂托克前旗', + code: '150623', + }, + { + name: '鄂托克旗', + code: '150624', + }, + { + name: '杭锦旗', + code: '150625', + }, + { + name: '乌审旗', + code: '150626', + }, + { + name: '伊金霍洛旗', + code: '150627', + }, + ], + }, + { + name: '呼伦贝尔市', + code: '150700', + children: [ + { + name: '海拉尔区', + code: '150702', + }, + { + name: '扎赉诺尔区', + code: '150703', + }, + { + name: '阿荣旗', + code: '150721', + }, + { + name: '莫力达瓦达斡尔族自治旗', + code: '150722', + }, + { + name: '鄂伦春自治旗', + code: '150723', + }, + { + name: '鄂温克族自治旗', + code: '150724', + }, + { + name: '陈巴尔虎旗', + code: '150725', + }, + { + name: '新巴尔虎左旗', + code: '150726', + }, + { + name: '新巴尔虎右旗', + code: '150727', + }, + { + name: '满洲里市', + code: '150781', + }, + { + name: '牙克石市', + code: '150782', + }, + { + name: '扎兰屯市', + code: '150783', + }, + { + name: '额尔古纳市', + code: '150784', + }, + { + name: '根河市', + code: '150785', + }, + ], + }, + { + name: '巴彦淖尔市', + code: '150800', + children: [ + { + name: '临河区', + code: '150802', + }, + { + name: '五原县', + code: '150821', + }, + { + name: '磴口县', + code: '150822', + }, + { + name: '乌拉特前旗', + code: '150823', + }, + { + name: '乌拉特中旗', + code: '150824', + }, + { + name: '乌拉特后旗', + code: '150825', + }, + { + name: '杭锦后旗', + code: '150826', + }, + ], + }, + { + name: '乌兰察布市', + code: '150900', + children: [ + { + name: '集宁区', + code: '150902', + }, + { + name: '卓资县', + code: '150921', + }, + { + name: '化德县', + code: '150922', + }, + { + name: '商都县', + code: '150923', + }, + { + name: '兴和县', + code: '150924', + }, + { + name: '凉城县', + code: '150925', + }, + { + name: '察哈尔右翼前旗', + code: '150926', + }, + { + name: '察哈尔右翼中旗', + code: '150927', + }, + { + name: '察哈尔右翼后旗', + code: '150928', + }, + { + name: '四子王旗', + code: '150929', + }, + { + name: '丰镇市', + code: '150981', + }, + ], + }, + { + name: '兴安盟', + code: '152200', + children: [ + { + name: '乌兰浩特市', + code: '152201', + }, + { + name: '阿尔山市', + code: '152202', + }, + { + name: '科尔沁右翼前旗', + code: '152221', + }, + { + name: '科尔沁右翼中旗', + code: '152222', + }, + { + name: '扎赉特旗', + code: '152223', + }, + { + name: '突泉县', + code: '152224', + }, + ], + }, + { + name: '锡林郭勒盟', + code: '152500', + children: [ + { + name: '二连浩特市', + code: '152501', + }, + { + name: '锡林浩特市', + code: '152502', + }, + { + name: '阿巴嘎旗', + code: '152522', + }, + { + name: '苏尼特左旗', + code: '152523', + }, + { + name: '苏尼特右旗', + code: '152524', + }, + { + name: '东乌珠穆沁旗', + code: '152525', + }, + { + name: '西乌珠穆沁旗', + code: '152526', + }, + { + name: '太仆寺旗', + code: '152527', + }, + { + name: '镶黄旗', + code: '152528', + }, + { + name: '正镶白旗', + code: '152529', + }, + { + name: '正蓝旗', + code: '152530', + }, + { + name: '多伦县', + code: '152531', + }, + ], + }, + { + name: '阿拉善盟', + code: '152900', + children: [ + { + name: '阿拉善左旗', + code: '152921', + }, + { + name: '阿拉善右旗', + code: '152922', + }, + { + name: '额济纳旗', + code: '152923', + }, + ], + }, + ], + }, + { + name: '辽宁省', + code: '210000', + region: 'northeast', + children: [ + { + name: '沈阳市', + code: '210100', + children: [ + { + name: '和平区', + code: '210102', + }, + { + name: '沈河区', + code: '210103', + }, + { + name: '大东区', + code: '210104', + }, + { + name: '皇姑区', + code: '210105', + }, + { + name: '铁西区', + code: '210106', + }, + { + name: '苏家屯区', + code: '210111', + }, + { + name: '浑南区', + code: '210112', + }, + { + name: '沈北新区', + code: '210113', + }, + { + name: '于洪区', + code: '210114', + }, + { + name: '辽中区', + code: '210115', + }, + { + name: '康平县', + code: '210123', + }, + { + name: '法库县', + code: '210124', + }, + { + name: '新民市', + code: '210181', + }, + ], + }, + { + name: '大连市', + code: '210200', + children: [ + { + name: '中山区', + code: '210202', + }, + { + name: '西岗区', + code: '210203', + }, + { + name: '沙河口区', + code: '210204', + }, + { + name: '甘井子区', + code: '210211', + }, + { + name: '旅顺口区', + code: '210212', + }, + { + name: '金州区', + code: '210213', + }, + { + name: '普兰店区', + code: '210214', + }, + { + name: '长海县', + code: '210224', + }, + { + name: '瓦房店市', + code: '210281', + }, + { + name: '庄河市', + code: '210283', + }, + ], + }, + { + name: '鞍山市', + code: '210300', + children: [ + { + name: '铁东区', + code: '210302', + }, + { + name: '铁西区', + code: '210303', + }, + { + name: '立山区', + code: '210304', + }, + { + name: '千山区', + code: '210311', + }, + { + name: '台安县', + code: '210321', + }, + { + name: '岫岩满族自治县', + code: '210323', + }, + { + name: '海城市', + code: '210381', + }, + ], + }, + { + name: '抚顺市', + code: '210400', + children: [ + { + name: '新抚区', + code: '210402', + }, + { + name: '东洲区', + code: '210403', + }, + { + name: '望花区', + code: '210404', + }, + { + name: '顺城区', + code: '210411', + }, + { + name: '抚顺县', + code: '210421', + }, + { + name: '新宾满族自治县', + code: '210422', + }, + { + name: '清原满族自治县', + code: '210423', + }, + ], + }, + { + name: '本溪市', + code: '210500', + children: [ + { + name: '平山区', + code: '210502', + }, + { + name: '溪湖区', + code: '210503', + }, + { + name: '明山区', + code: '210504', + }, + { + name: '南芬区', + code: '210505', + }, + { + name: '本溪满族自治县', + code: '210521', + }, + { + name: '桓仁满族自治县', + code: '210522', + }, + ], + }, + { + name: '丹东市', + code: '210600', + children: [ + { + name: '元宝区', + code: '210602', + }, + { + name: '振兴区', + code: '210603', + }, + { + name: '振安区', + code: '210604', + }, + { + name: '宽甸满族自治县', + code: '210624', + }, + { + name: '东港市', + code: '210681', + }, + { + name: '凤城市', + code: '210682', + }, + ], + }, + { + name: '锦州市', + code: '210700', + children: [ + { + name: '古塔区', + code: '210702', + }, + { + name: '凌河区', + code: '210703', + }, + { + name: '太和区', + code: '210711', + }, + { + name: '黑山县', + code: '210726', + }, + { + name: '义县', + code: '210727', + }, + { + name: '凌海市', + code: '210781', + }, + { + name: '北镇市', + code: '210782', + }, + ], + }, + { + name: '营口市', + code: '210800', + children: [ + { + name: '站前区', + code: '210802', + }, + { + name: '西市区', + code: '210803', + }, + { + name: '鲅鱼圈区', + code: '210804', + }, + { + name: '老边区', + code: '210811', + }, + { + name: '盖州市', + code: '210881', + }, + { + name: '大石桥市', + code: '210882', + }, + ], + }, + { + name: '阜新市', + code: '210900', + children: [ + { + name: '海州区', + code: '210902', + }, + { + name: '新邱区', + code: '210903', + }, + { + name: '太平区', + code: '210904', + }, + { + name: '清河门区', + code: '210905', + }, + { + name: '细河区', + code: '210911', + }, + { + name: '阜新蒙古族自治县', + code: '210921', + }, + { + name: '彰武县', + code: '210922', + }, + ], + }, + { + name: '辽阳市', + code: '211000', + children: [ + { + name: '白塔区', + code: '211002', + }, + { + name: '文圣区', + code: '211003', + }, + { + name: '宏伟区', + code: '211004', + }, + { + name: '弓长岭区', + code: '211005', + }, + { + name: '太子河区', + code: '211011', + }, + { + name: '辽阳县', + code: '211021', + }, + { + name: '灯塔市', + code: '211081', + }, + ], + }, + { + name: '盘锦市', + code: '211100', + children: [ + { + name: '双台子区', + code: '211102', + }, + { + name: '兴隆台区', + code: '211103', + }, + { + name: '大洼区', + code: '211104', + }, + { + name: '盘山县', + code: '211122', + }, + ], + }, + { + name: '铁岭市', + code: '211200', + children: [ + { + name: '银州区', + code: '211202', + }, + { + name: '清河区', + code: '211204', + }, + { + name: '铁岭县', + code: '211221', + }, + { + name: '西丰县', + code: '211223', + }, + { + name: '昌图县', + code: '211224', + }, + { + name: '调兵山市', + code: '211281', + }, + { + name: '开原市', + code: '211282', + }, + ], + }, + { + name: '朝阳市', + code: '211300', + children: [ + { + name: '双塔区', + code: '211302', + }, + { + name: '龙城区', + code: '211303', + }, + { + name: '朝阳县', + code: '211321', + }, + { + name: '建平县', + code: '211322', + }, + { + name: '喀喇沁左翼蒙古族自治县', + code: '211324', + }, + { + name: '北票市', + code: '211381', + }, + { + name: '凌源市', + code: '211382', + }, + ], + }, + { + name: '葫芦岛市', + code: '211400', + children: [ + { + name: '连山区', + code: '211402', + }, + { + name: '龙港区', + code: '211403', + }, + { + name: '南票区', + code: '211404', + }, + { + name: '绥中县', + code: '211421', + }, + { + name: '建昌县', + code: '211422', + }, + { + name: '兴城市', + code: '211481', + }, + ], + }, + ], + }, + { + name: '吉林省', + code: '220000', + region: 'northeast', + children: [ + { + name: '长春市', + code: '220100', + children: [ + { + name: '南关区', + code: '220102', + }, + { + name: '宽城区', + code: '220103', + }, + { + name: '朝阳区', + code: '220104', + }, + { + name: '二道区', + code: '220105', + }, + { + name: '绿园区', + code: '220106', + }, + { + name: '双阳区', + code: '220112', + }, + { + name: '九台区', + code: '220113', + }, + { + name: '农安县', + code: '220122', + }, + { + name: '榆树市', + code: '220182', + }, + { + name: '德惠市', + code: '220183', + }, + ], + }, + { + name: '吉林市', + code: '220200', + children: [ + { + name: '昌邑区', + code: '220202', + }, + { + name: '龙潭区', + code: '220203', + }, + { + name: '船营区', + code: '220204', + }, + { + name: '丰满区', + code: '220211', + }, + { + name: '永吉县', + code: '220221', + }, + { + name: '蛟河市', + code: '220281', + }, + { + name: '桦甸市', + code: '220282', + }, + { + name: '舒兰市', + code: '220283', + }, + { + name: '磐石市', + code: '220284', + }, + ], + }, + { + name: '四平市', + code: '220300', + children: [ + { + name: '铁西区', + code: '220302', + }, + { + name: '铁东区', + code: '220303', + }, + { + name: '梨树县', + code: '220322', + }, + { + name: '伊通满族自治县', + code: '220323', + }, + { + name: '公主岭市', + code: '220381', + }, + { + name: '双辽市', + code: '220382', + }, + ], + }, + { + name: '辽源市', + code: '220400', + children: [ + { + name: '龙山区', + code: '220402', + }, + { + name: '西安区', + code: '220403', + }, + { + name: '东丰县', + code: '220421', + }, + { + name: '东辽县', + code: '220422', + }, + ], + }, + { + name: '通化市', + code: '220500', + children: [ + { + name: '东昌区', + code: '220502', + }, + { + name: '二道江区', + code: '220503', + }, + { + name: '通化县', + code: '220521', + }, + { + name: '辉南县', + code: '220523', + }, + { + name: '柳河县', + code: '220524', + }, + { + name: '梅河口市', + code: '220581', + }, + { + name: '集安市', + code: '220582', + }, + ], + }, + { + name: '白山市', + code: '220600', + children: [ + { + name: '浑江区', + code: '220602', + }, + { + name: '江源区', + code: '220605', + }, + { + name: '抚松县', + code: '220621', + }, + { + name: '靖宇县', + code: '220622', + }, + { + name: '长白朝鲜族自治县', + code: '220623', + }, + { + name: '临江市', + code: '220681', + }, + ], + }, + { + name: '松原市', + code: '220700', + children: [ + { + name: '宁江区', + code: '220702', + }, + { + name: '前郭尔罗斯蒙古族自治县', + code: '220721', + }, + { + name: '长岭县', + code: '220722', + }, + { + name: '乾安县', + code: '220723', + }, + { + name: '扶余市', + code: '220781', + }, + ], + }, + { + name: '白城市', + code: '220800', + children: [ + { + name: '洮北区', + code: '220802', + }, + { + name: '镇赉县', + code: '220821', + }, + { + name: '通榆县', + code: '220822', + }, + { + name: '洮南市', + code: '220881', + }, + { + name: '大安市', + code: '220882', + }, + ], + }, + { + name: '延边朝鲜族自治州', + code: '222400', + children: [ + { + name: '延吉市', + code: '222401', + }, + { + name: '图们市', + code: '222402', + }, + { + name: '敦化市', + code: '222403', + }, + { + name: '珲春市', + code: '222404', + }, + { + name: '龙井市', + code: '222405', + }, + { + name: '和龙市', + code: '222406', + }, + { + name: '汪清县', + code: '222424', + }, + { + name: '安图县', + code: '222426', + }, + ], + }, + ], + }, + { + name: '黑龙江省', + code: '230000', + region: 'northeast', + children: [ + { + name: '哈尔滨市', + code: '230100', + children: [ + { + name: '道里区', + code: '230102', + }, + { + name: '南岗区', + code: '230103', + }, + { + name: '道外区', + code: '230104', + }, + { + name: '平房区', + code: '230108', + }, + { + name: '松北区', + code: '230109', + }, + { + name: '香坊区', + code: '230110', + }, + { + name: '呼兰区', + code: '230111', + }, + { + name: '阿城区', + code: '230112', + }, + { + name: '双城区', + code: '230113', + }, + { + name: '依兰县', + code: '230123', + }, + { + name: '方正县', + code: '230124', + }, + { + name: '宾县', + code: '230125', + }, + { + name: '巴彦县', + code: '230126', + }, + { + name: '木兰县', + code: '230127', + }, + { + name: '通河县', + code: '230128', + }, + { + name: '延寿县', + code: '230129', + }, + { + name: '尚志市', + code: '230183', + }, + { + name: '五常市', + code: '230184', + }, + ], + }, + { + name: '齐齐哈尔市', + code: '230200', + children: [ + { + name: '龙沙区', + code: '230202', + }, + { + name: '建华区', + code: '230203', + }, + { + name: '铁锋区', + code: '230204', + }, + { + name: '昂昂溪区', + code: '230205', + }, + { + name: '富拉尔基区', + code: '230206', + }, + { + name: '碾子山区', + code: '230207', + }, + { + name: '梅里斯达斡尔族区', + code: '230208', + }, + { + name: '龙江县', + code: '230221', + }, + { + name: '依安县', + code: '230223', + }, + { + name: '泰来县', + code: '230224', + }, + { + name: '甘南县', + code: '230225', + }, + { + name: '富裕县', + code: '230227', + }, + { + name: '克山县', + code: '230229', + }, + { + name: '克东县', + code: '230230', + }, + { + name: '拜泉县', + code: '230231', + }, + { + name: '讷河市', + code: '230281', + }, + ], + }, + { + name: '鸡西市', + code: '230300', + children: [ + { + name: '鸡冠区', + code: '230302', + }, + { + name: '恒山区', + code: '230303', + }, + { + name: '滴道区', + code: '230304', + }, + { + name: '梨树区', + code: '230305', + }, + { + name: '城子河区', + code: '230306', + }, + { + name: '麻山区', + code: '230307', + }, + { + name: '鸡东县', + code: '230321', + }, + { + name: '虎林市', + code: '230381', + }, + { + name: '密山市', + code: '230382', + }, + ], + }, + { + name: '鹤岗市', + code: '230400', + children: [ + { + name: '向阳区', + code: '230402', + }, + { + name: '工农区', + code: '230403', + }, + { + name: '南山区', + code: '230404', + }, + { + name: '兴安区', + code: '230405', + }, + { + name: '东山区', + code: '230406', + }, + { + name: '兴山区', + code: '230407', + }, + { + name: '萝北县', + code: '230421', + }, + { + name: '绥滨县', + code: '230422', + }, + ], + }, + { + name: '双鸭山市', + code: '230500', + children: [ + { + name: '尖山区', + code: '230502', + }, + { + name: '岭东区', + code: '230503', + }, + { + name: '四方台区', + code: '230505', + }, + { + name: '宝山区', + code: '230506', + }, + { + name: '集贤县', + code: '230521', + }, + { + name: '友谊县', + code: '230522', + }, + { + name: '宝清县', + code: '230523', + }, + { + name: '饶河县', + code: '230524', + }, + ], + }, + { + name: '大庆市', + code: '230600', + children: [ + { + name: '萨尔图区', + code: '230602', + }, + { + name: '龙凤区', + code: '230603', + }, + { + name: '让胡路区', + code: '230604', + }, + { + name: '红岗区', + code: '230605', + }, + { + name: '大同区', + code: '230606', + }, + { + name: '肇州县', + code: '230621', + }, + { + name: '肇源县', + code: '230622', + }, + { + name: '林甸县', + code: '230623', + }, + { + name: '杜尔伯特蒙古族自治县', + code: '230624', + }, + ], + }, + { + name: '伊春市', + code: '230700', + children: [ + { + name: '伊春区', + code: '230702', + }, + { + name: '南岔区', + code: '230703', + }, + { + name: '友好区', + code: '230704', + }, + { + name: '西林区', + code: '230705', + }, + { + name: '翠峦区', + code: '230706', + }, + { + name: '新青区', + code: '230707', + }, + { + name: '美溪区', + code: '230708', + }, + { + name: '金山屯区', + code: '230709', + }, + { + name: '五营区', + code: '230710', + }, + { + name: '乌马河区', + code: '230711', + }, + { + name: '汤旺河区', + code: '230712', + }, + { + name: '带岭区', + code: '230713', + }, + { + name: '乌伊岭区', + code: '230714', + }, + { + name: '红星区', + code: '230715', + }, + { + name: '上甘岭区', + code: '230716', + }, + { + name: '嘉荫县', + code: '230722', + }, + { + name: '铁力市', + code: '230781', + }, + ], + }, + { + name: '佳木斯市', + code: '230800', + children: [ + { + name: '向阳区', + code: '230803', + }, + { + name: '前进区', + code: '230804', + }, + { + name: '东风区', + code: '230805', + }, + { + name: '郊区', + code: '230811', + }, + { + name: '桦南县', + code: '230822', + }, + { + name: '桦川县', + code: '230826', + }, + { + name: '汤原县', + code: '230828', + }, + { + name: '同江市', + code: '230881', + }, + { + name: '富锦市', + code: '230882', + }, + { + name: '抚远市', + code: '230883', + }, + ], + }, + { + name: '七台河市', + code: '230900', + children: [ + { + name: '新兴区', + code: '230902', + }, + { + name: '桃山区', + code: '230903', + }, + { + name: '茄子河区', + code: '230904', + }, + { + name: '勃利县', + code: '230921', + }, + ], + }, + { + name: '牡丹江市', + code: '231000', + children: [ + { + name: '东安区', + code: '231002', + }, + { + name: '阳明区', + code: '231003', + }, + { + name: '爱民区', + code: '231004', + }, + { + name: '西安区', + code: '231005', + }, + { + name: '林口县', + code: '231025', + }, + { + name: '绥芬河市', + code: '231081', + }, + { + name: '海林市', + code: '231083', + }, + { + name: '宁安市', + code: '231084', + }, + { + name: '穆棱市', + code: '231085', + }, + { + name: '东宁市', + code: '231086', + }, + ], + }, + { + name: '黑河市', + code: '231100', + children: [ + { + name: '爱辉区', + code: '231102', + }, + { + name: '嫩江县', + code: '231121', + }, + { + name: '逊克县', + code: '231123', + }, + { + name: '孙吴县', + code: '231124', + }, + { + name: '北安市', + code: '231181', + }, + { + name: '五大连池市', + code: '231182', + }, + ], + }, + { + name: '绥化市', + code: '231200', + children: [ + { + name: '北林区', + code: '231202', + }, + { + name: '望奎县', + code: '231221', + }, + { + name: '兰西县', + code: '231222', + }, + { + name: '青冈县', + code: '231223', + }, + { + name: '庆安县', + code: '231224', + }, + { + name: '明水县', + code: '231225', + }, + { + name: '绥棱县', + code: '231226', + }, + { + name: '安达市', + code: '231281', + }, + { + name: '肇东市', + code: '231282', + }, + { + name: '海伦市', + code: '231283', + }, + ], + }, + { + name: '大兴安岭地区', + code: '232700', + children: [ + { + name: '漠河市', + code: '232701', + }, + { + name: '呼玛县', + code: '232721', + }, + { + name: '塔河县', + code: '232722', + }, + ], + }, + ], + }, + { + name: '上海市', + code: '310000', + region: 'east', + provinceLevelCity: true, + children: [ + { + name: '市辖区', + code: '310100', + children: [ + { + name: '黄浦区', + code: '310101', + }, + { + name: '徐汇区', + code: '310104', + }, + { + name: '长宁区', + code: '310105', + }, + { + name: '静安区', + code: '310106', + }, + { + name: '普陀区', + code: '310107', + }, + { + name: '虹口区', + code: '310109', + }, + { + name: '杨浦区', + code: '310110', + }, + { + name: '闵行区', + code: '310112', + }, + { + name: '宝山区', + code: '310113', + }, + { + name: '嘉定区', + code: '310114', + }, + { + name: '浦东新区', + code: '310115', + }, + { + name: '金山区', + code: '310116', + }, + { + name: '松江区', + code: '310117', + }, + { + name: '青浦区', + code: '310118', + }, + { + name: '奉贤区', + code: '310120', + }, + { + name: '崇明区', + code: '310151', + }, + ], + }, + ], + }, + { + name: '江苏省', + code: '320000', + region: 'east', + children: [ + { + name: '南京市', + code: '320100', + children: [ + { + name: '玄武区', + code: '320102', + }, + { + name: '秦淮区', + code: '320104', + }, + { + name: '建邺区', + code: '320105', + }, + { + name: '鼓楼区', + code: '320106', + }, + { + name: '浦口区', + code: '320111', + }, + { + name: '栖霞区', + code: '320113', + }, + { + name: '雨花台区', + code: '320114', + }, + { + name: '江宁区', + code: '320115', + }, + { + name: '六合区', + code: '320116', + }, + { + name: '溧水区', + code: '320117', + }, + { + name: '高淳区', + code: '320118', + }, + ], + }, + { + name: '无锡市', + code: '320200', + children: [ + { + name: '锡山区', + code: '320205', + }, + { + name: '惠山区', + code: '320206', + }, + { + name: '滨湖区', + code: '320211', + }, + { + name: '梁溪区', + code: '320213', + }, + { + name: '新吴区', + code: '320214', + }, + { + name: '江阴市', + code: '320281', + }, + { + name: '宜兴市', + code: '320282', + }, + ], + }, + { + name: '徐州市', + code: '320300', + children: [ + { + name: '鼓楼区', + code: '320302', + }, + { + name: '云龙区', + code: '320303', + }, + { + name: '贾汪区', + code: '320305', + }, + { + name: '泉山区', + code: '320311', + }, + { + name: '铜山区', + code: '320312', + }, + { + name: '丰县', + code: '320321', + }, + { + name: '沛县', + code: '320322', + }, + { + name: '睢宁县', + code: '320324', + }, + { + name: '新沂市', + code: '320381', + }, + { + name: '邳州市', + code: '320382', + }, + ], + }, + { + name: '常州市', + code: '320400', + children: [ + { + name: '天宁区', + code: '320402', + }, + { + name: '钟楼区', + code: '320404', + }, + { + name: '新北区', + code: '320411', + }, + { + name: '武进区', + code: '320412', + }, + { + name: '金坛区', + code: '320413', + }, + { + name: '溧阳市', + code: '320481', + }, + ], + }, + { + name: '苏州市', + code: '320500', + children: [ + { + name: '虎丘区', + code: '320505', + }, + { + name: '吴中区', + code: '320506', + }, + { + name: '相城区', + code: '320507', + }, + { + name: '姑苏区', + code: '320508', + }, + { + name: '吴江区', + code: '320509', + }, + { + name: '常熟市', + code: '320581', + }, + { + name: '张家港市', + code: '320582', + }, + { + name: '昆山市', + code: '320583', + }, + { + name: '太仓市', + code: '320585', + }, + ], + }, + { + name: '南通市', + code: '320600', + children: [ + { + name: '崇川区', + code: '320602', + }, + { + name: '港闸区', + code: '320611', + }, + { + name: '通州区', + code: '320612', + }, + { + name: '如东县', + code: '320623', + }, + { + name: '启东市', + code: '320681', + }, + { + name: '如皋市', + code: '320682', + }, + { + name: '海门市', + code: '320684', + }, + { + name: '海安市', + code: '320685', + }, + ], + }, + { + name: '连云港市', + code: '320700', + children: [ + { + name: '连云区', + code: '320703', + }, + { + name: '海州区', + code: '320706', + }, + { + name: '赣榆区', + code: '320707', + }, + { + name: '东海县', + code: '320722', + }, + { + name: '灌云县', + code: '320723', + }, + { + name: '灌南县', + code: '320724', + }, + ], + }, + { + name: '淮安市', + code: '320800', + children: [ + { + name: '淮安区', + code: '320803', + }, + { + name: '淮阴区', + code: '320804', + }, + { + name: '清江浦区', + code: '320812', + }, + { + name: '洪泽区', + code: '320813', + }, + { + name: '涟水县', + code: '320826', + }, + { + name: '盱眙县', + code: '320830', + }, + { + name: '金湖县', + code: '320831', + }, + ], + }, + { + name: '盐城市', + code: '320900', + children: [ + { + name: '亭湖区', + code: '320902', + }, + { + name: '盐都区', + code: '320903', + }, + { + name: '大丰区', + code: '320904', + }, + { + name: '响水县', + code: '320921', + }, + { + name: '滨海县', + code: '320922', + }, + { + name: '阜宁县', + code: '320923', + }, + { + name: '射阳县', + code: '320924', + }, + { + name: '建湖县', + code: '320925', + }, + { + name: '东台市', + code: '320981', + }, + ], + }, + { + name: '扬州市', + code: '321000', + children: [ + { + name: '广陵区', + code: '321002', + }, + { + name: '邗江区', + code: '321003', + }, + { + name: '江都区', + code: '321012', + }, + { + name: '宝应县', + code: '321023', + }, + { + name: '仪征市', + code: '321081', + }, + { + name: '高邮市', + code: '321084', + }, + ], + }, + { + name: '镇江市', + code: '321100', + children: [ + { + name: '京口区', + code: '321102', + }, + { + name: '润州区', + code: '321111', + }, + { + name: '丹徒区', + code: '321112', + }, + { + name: '丹阳市', + code: '321181', + }, + { + name: '扬中市', + code: '321182', + }, + { + name: '句容市', + code: '321183', + }, + ], + }, + { + name: '泰州市', + code: '321200', + children: [ + { + name: '海陵区', + code: '321202', + }, + { + name: '高港区', + code: '321203', + }, + { + name: '姜堰区', + code: '321204', + }, + { + name: '兴化市', + code: '321281', + }, + { + name: '靖江市', + code: '321282', + }, + { + name: '泰兴市', + code: '321283', + }, + ], + }, + { + name: '宿迁市', + code: '321300', + children: [ + { + name: '宿城区', + code: '321302', + }, + { + name: '宿豫区', + code: '321311', + }, + { + name: '沭阳县', + code: '321322', + }, + { + name: '泗阳县', + code: '321323', + }, + { + name: '泗洪县', + code: '321324', + }, + ], + }, + ], + }, + { + name: '浙江省', + code: '330000', + region: 'east', + children: [ + { + name: '杭州市', + code: '330100', + children: [ + { + name: '上城区', + code: '330102', + }, + { + name: '下城区', + code: '330103', + }, + { + name: '江干区', + code: '330104', + }, + { + name: '拱墅区', + code: '330105', + }, + { + name: '西湖区', + code: '330106', + }, + { + name: '滨江区', + code: '330108', + }, + { + name: '萧山区', + code: '330109', + }, + { + name: '余杭区', + code: '330110', + }, + { + name: '富阳区', + code: '330111', + }, + { + name: '临安区', + code: '330112', + }, + { + name: '桐庐县', + code: '330122', + }, + { + name: '淳安县', + code: '330127', + }, + { + name: '建德市', + code: '330182', + }, + ], + }, + { + name: '宁波市', + code: '330200', + children: [ + { + name: '海曙区', + code: '330203', + }, + { + name: '江北区', + code: '330205', + }, + { + name: '北仑区', + code: '330206', + }, + { + name: '镇海区', + code: '330211', + }, + { + name: '鄞州区', + code: '330212', + }, + { + name: '奉化区', + code: '330213', + }, + { + name: '象山县', + code: '330225', + }, + { + name: '宁海县', + code: '330226', + }, + { + name: '余姚市', + code: '330281', + }, + { + name: '慈溪市', + code: '330282', + }, + ], + }, + { + name: '温州市', + code: '330300', + children: [ + { + name: '鹿城区', + code: '330302', + }, + { + name: '龙湾区', + code: '330303', + }, + { + name: '瓯海区', + code: '330304', + }, + { + name: '洞头区', + code: '330305', + }, + { + name: '永嘉县', + code: '330324', + }, + { + name: '平阳县', + code: '330326', + }, + { + name: '苍南县', + code: '330327', + }, + { + name: '文成县', + code: '330328', + }, + { + name: '泰顺县', + code: '330329', + }, + { + name: '瑞安市', + code: '330381', + }, + { + name: '乐清市', + code: '330382', + }, + ], + }, + { + name: '嘉兴市', + code: '330400', + children: [ + { + name: '南湖区', + code: '330402', + }, + { + name: '秀洲区', + code: '330411', + }, + { + name: '嘉善县', + code: '330421', + }, + { + name: '海盐县', + code: '330424', + }, + { + name: '海宁市', + code: '330481', + }, + { + name: '平湖市', + code: '330482', + }, + { + name: '桐乡市', + code: '330483', + }, + ], + }, + { + name: '湖州市', + code: '330500', + children: [ + { + name: '吴兴区', + code: '330502', + }, + { + name: '南浔区', + code: '330503', + }, + { + name: '德清县', + code: '330521', + }, + { + name: '长兴县', + code: '330522', + }, + { + name: '安吉县', + code: '330523', + }, + ], + }, + { + name: '绍兴市', + code: '330600', + children: [ + { + name: '越城区', + code: '330602', + }, + { + name: '柯桥区', + code: '330603', + }, + { + name: '上虞区', + code: '330604', + }, + { + name: '新昌县', + code: '330624', + }, + { + name: '诸暨市', + code: '330681', + }, + { + name: '嵊州市', + code: '330683', + }, + ], + }, + { + name: '金华市', + code: '330700', + children: [ + { + name: '婺城区', + code: '330702', + }, + { + name: '金东区', + code: '330703', + }, + { + name: '武义县', + code: '330723', + }, + { + name: '浦江县', + code: '330726', + }, + { + name: '磐安县', + code: '330727', + }, + { + name: '兰溪市', + code: '330781', + }, + { + name: '义乌市', + code: '330782', + }, + { + name: '东阳市', + code: '330783', + }, + { + name: '永康市', + code: '330784', + }, + ], + }, + { + name: '衢州市', + code: '330800', + children: [ + { + name: '柯城区', + code: '330802', + }, + { + name: '衢江区', + code: '330803', + }, + { + name: '常山县', + code: '330822', + }, + { + name: '开化县', + code: '330824', + }, + { + name: '龙游县', + code: '330825', + }, + { + name: '江山市', + code: '330881', + }, + ], + }, + { + name: '舟山市', + code: '330900', + children: [ + { + name: '定海区', + code: '330902', + }, + { + name: '普陀区', + code: '330903', + }, + { + name: '岱山县', + code: '330921', + }, + { + name: '嵊泗县', + code: '330922', + }, + ], + }, + { + name: '台州市', + code: '331000', + children: [ + { + name: '椒江区', + code: '331002', + }, + { + name: '黄岩区', + code: '331003', + }, + { + name: '路桥区', + code: '331004', + }, + { + name: '三门县', + code: '331022', + }, + { + name: '天台县', + code: '331023', + }, + { + name: '仙居县', + code: '331024', + }, + { + name: '温岭市', + code: '331081', + }, + { + name: '临海市', + code: '331082', + }, + { + name: '玉环市', + code: '331083', + }, + ], + }, + { + name: '丽水市', + code: '331100', + children: [ + { + name: '莲都区', + code: '331102', + }, + { + name: '青田县', + code: '331121', + }, + { + name: '缙云县', + code: '331122', + }, + { + name: '遂昌县', + code: '331123', + }, + { + name: '松阳县', + code: '331124', + }, + { + name: '云和县', + code: '331125', + }, + { + name: '庆元县', + code: '331126', + }, + { + name: '景宁畲族自治县', + code: '331127', + }, + { + name: '龙泉市', + code: '331181', + }, + ], + }, + ], + }, + { + name: '安徽省', + code: '340000', + region: 'east', + children: [ + { + name: '合肥市', + code: '340100', + children: [ + { + name: '瑶海区', + code: '340102', + }, + { + name: '庐阳区', + code: '340103', + }, + { + name: '蜀山区', + code: '340104', + }, + { + name: '包河区', + code: '340111', + }, + { + name: '长丰县', + code: '340121', + }, + { + name: '肥东县', + code: '340122', + }, + { + name: '肥西县', + code: '340123', + }, + { + name: '庐江县', + code: '340124', + }, + { + name: '巢湖市', + code: '340181', + }, + ], + }, + { + name: '芜湖市', + code: '340200', + children: [ + { + name: '镜湖区', + code: '340202', + }, + { + name: '弋江区', + code: '340203', + }, + { + name: '鸠江区', + code: '340207', + }, + { + name: '三山区', + code: '340208', + }, + { + name: '芜湖县', + code: '340221', + }, + { + name: '繁昌县', + code: '340222', + }, + { + name: '南陵县', + code: '340223', + }, + { + name: '无为县', + code: '340225', + }, + ], + }, + { + name: '蚌埠市', + code: '340300', + children: [ + { + name: '龙子湖区', + code: '340302', + }, + { + name: '蚌山区', + code: '340303', + }, + { + name: '禹会区', + code: '340304', + }, + { + name: '淮上区', + code: '340311', + }, + { + name: '怀远县', + code: '340321', + }, + { + name: '五河县', + code: '340322', + }, + { + name: '固镇县', + code: '340323', + }, + ], + }, + { + name: '淮南市', + code: '340400', + children: [ + { + name: '大通区', + code: '340402', + }, + { + name: '田家庵区', + code: '340403', + }, + { + name: '谢家集区', + code: '340404', + }, + { + name: '八公山区', + code: '340405', + }, + { + name: '潘集区', + code: '340406', + }, + { + name: '凤台县', + code: '340421', + }, + { + name: '寿县', + code: '340422', + }, + ], + }, + { + name: '马鞍山市', + code: '340500', + children: [ + { + name: '花山区', + code: '340503', + }, + { + name: '雨山区', + code: '340504', + }, + { + name: '博望区', + code: '340506', + }, + { + name: '当涂县', + code: '340521', + }, + { + name: '含山县', + code: '340522', + }, + { + name: '和县', + code: '340523', + }, + ], + }, + { + name: '淮北市', + code: '340600', + children: [ + { + name: '杜集区', + code: '340602', + }, + { + name: '相山区', + code: '340603', + }, + { + name: '烈山区', + code: '340604', + }, + { + name: '濉溪县', + code: '340621', + }, + ], + }, + { + name: '铜陵市', + code: '340700', + children: [ + { + name: '铜官区', + code: '340705', + }, + { + name: '义安区', + code: '340706', + }, + { + name: '郊区', + code: '340711', + }, + { + name: '枞阳县', + code: '340722', + }, + ], + }, + { + name: '安庆市', + code: '340800', + children: [ + { + name: '迎江区', + code: '340802', + }, + { + name: '大观区', + code: '340803', + }, + { + name: '宜秀区', + code: '340811', + }, + { + name: '怀宁县', + code: '340822', + }, + { + name: '太湖县', + code: '340825', + }, + { + name: '宿松县', + code: '340826', + }, + { + name: '望江县', + code: '340827', + }, + { + name: '岳西县', + code: '340828', + }, + { + name: '桐城市', + code: '340881', + }, + { + name: '潜山市', + code: '340882', + }, + ], + }, + { + name: '黄山市', + code: '341000', + children: [ + { + name: '屯溪区', + code: '341002', + }, + { + name: '黄山区', + code: '341003', + }, + { + name: '徽州区', + code: '341004', + }, + { + name: '歙县', + code: '341021', + }, + { + name: '休宁县', + code: '341022', + }, + { + name: '黟县', + code: '341023', + }, + { + name: '祁门县', + code: '341024', + }, + ], + }, + { + name: '滁州市', + code: '341100', + children: [ + { + name: '琅琊区', + code: '341102', + }, + { + name: '南谯区', + code: '341103', + }, + { + name: '来安县', + code: '341122', + }, + { + name: '全椒县', + code: '341124', + }, + { + name: '定远县', + code: '341125', + }, + { + name: '凤阳县', + code: '341126', + }, + { + name: '天长市', + code: '341181', + }, + { + name: '明光市', + code: '341182', + }, + ], + }, + { + name: '阜阳市', + code: '341200', + children: [ + { + name: '颍州区', + code: '341202', + }, + { + name: '颍东区', + code: '341203', + }, + { + name: '颍泉区', + code: '341204', + }, + { + name: '临泉县', + code: '341221', + }, + { + name: '太和县', + code: '341222', + }, + { + name: '阜南县', + code: '341225', + }, + { + name: '颍上县', + code: '341226', + }, + { + name: '界首市', + code: '341282', + }, + ], + }, + { + name: '宿州市', + code: '341300', + children: [ + { + name: '埇桥区', + code: '341302', + }, + { + name: '砀山县', + code: '341321', + }, + { + name: '萧县', + code: '341322', + }, + { + name: '灵璧县', + code: '341323', + }, + { + name: '泗县', + code: '341324', + }, + ], + }, + { + name: '六安市', + code: '341500', + children: [ + { + name: '金安区', + code: '341502', + }, + { + name: '裕安区', + code: '341503', + }, + { + name: '叶集区', + code: '341504', + }, + { + name: '霍邱县', + code: '341522', + }, + { + name: '舒城县', + code: '341523', + }, + { + name: '金寨县', + code: '341524', + }, + { + name: '霍山县', + code: '341525', + }, + ], + }, + { + name: '亳州市', + code: '341600', + children: [ + { + name: '谯城区', + code: '341602', + }, + { + name: '涡阳县', + code: '341621', + }, + { + name: '蒙城县', + code: '341622', + }, + { + name: '利辛县', + code: '341623', + }, + ], + }, + { + name: '池州市', + code: '341700', + children: [ + { + name: '贵池区', + code: '341702', + }, + { + name: '东至县', + code: '341721', + }, + { + name: '石台县', + code: '341722', + }, + { + name: '青阳县', + code: '341723', + }, + ], + }, + { + name: '宣城市', + code: '341800', + children: [ + { + name: '宣州区', + code: '341802', + }, + { + name: '郎溪县', + code: '341821', + }, + { + name: '广德县', + code: '341822', + }, + { + name: '泾县', + code: '341823', + }, + { + name: '绩溪县', + code: '341824', + }, + { + name: '旌德县', + code: '341825', + }, + { + name: '宁国市', + code: '341881', + }, + ], + }, + ], + }, + { + name: '福建省', + code: '350000', + region: 'east', + children: [ + { + name: '福州市', + code: '350100', + children: [ + { + name: '鼓楼区', + code: '350102', + }, + { + name: '台江区', + code: '350103', + }, + { + name: '仓山区', + code: '350104', + }, + { + name: '马尾区', + code: '350105', + }, + { + name: '晋安区', + code: '350111', + }, + { + name: '长乐区', + code: '350112', + }, + { + name: '闽侯县', + code: '350121', + }, + { + name: '连江县', + code: '350122', + }, + { + name: '罗源县', + code: '350123', + }, + { + name: '闽清县', + code: '350124', + }, + { + name: '永泰县', + code: '350125', + }, + { + name: '平潭县', + code: '350128', + }, + { + name: '福清市', + code: '350181', + }, + ], + }, + { + name: '厦门市', + code: '350200', + children: [ + { + name: '思明区', + code: '350203', + }, + { + name: '海沧区', + code: '350205', + }, + { + name: '湖里区', + code: '350206', + }, + { + name: '集美区', + code: '350211', + }, + { + name: '同安区', + code: '350212', + }, + { + name: '翔安区', + code: '350213', + }, + ], + }, + { + name: '莆田市', + code: '350300', + children: [ + { + name: '城厢区', + code: '350302', + }, + { + name: '涵江区', + code: '350303', + }, + { + name: '荔城区', + code: '350304', + }, + { + name: '秀屿区', + code: '350305', + }, + { + name: '仙游县', + code: '350322', + }, + ], + }, + { + name: '三明市', + code: '350400', + children: [ + { + name: '梅列区', + code: '350402', + }, + { + name: '三元区', + code: '350403', + }, + { + name: '明溪县', + code: '350421', + }, + { + name: '清流县', + code: '350423', + }, + { + name: '宁化县', + code: '350424', + }, + { + name: '大田县', + code: '350425', + }, + { + name: '尤溪县', + code: '350426', + }, + { + name: '沙县', + code: '350427', + }, + { + name: '将乐县', + code: '350428', + }, + { + name: '泰宁县', + code: '350429', + }, + { + name: '建宁县', + code: '350430', + }, + { + name: '永安市', + code: '350481', + }, + ], + }, + { + name: '泉州市', + code: '350500', + children: [ + { + name: '鲤城区', + code: '350502', + }, + { + name: '丰泽区', + code: '350503', + }, + { + name: '洛江区', + code: '350504', + }, + { + name: '泉港区', + code: '350505', + }, + { + name: '惠安县', + code: '350521', + }, + { + name: '安溪县', + code: '350524', + }, + { + name: '永春县', + code: '350525', + }, + { + name: '德化县', + code: '350526', + }, + { + name: '金门县', + code: '350527', + }, + { + name: '石狮市', + code: '350581', + }, + { + name: '晋江市', + code: '350582', + }, + { + name: '南安市', + code: '350583', + }, + ], + }, + { + name: '漳州市', + code: '350600', + children: [ + { + name: '芗城区', + code: '350602', + }, + { + name: '龙文区', + code: '350603', + }, + { + name: '云霄县', + code: '350622', + }, + { + name: '漳浦县', + code: '350623', + }, + { + name: '诏安县', + code: '350624', + }, + { + name: '长泰县', + code: '350625', + }, + { + name: '东山县', + code: '350626', + }, + { + name: '南靖县', + code: '350627', + }, + { + name: '平和县', + code: '350628', + }, + { + name: '华安县', + code: '350629', + }, + { + name: '龙海市', + code: '350681', + }, + ], + }, + { + name: '南平市', + code: '350700', + children: [ + { + name: '延平区', + code: '350702', + }, + { + name: '建阳区', + code: '350703', + }, + { + name: '顺昌县', + code: '350721', + }, + { + name: '浦城县', + code: '350722', + }, + { + name: '光泽县', + code: '350723', + }, + { + name: '松溪县', + code: '350724', + }, + { + name: '政和县', + code: '350725', + }, + { + name: '邵武市', + code: '350781', + }, + { + name: '武夷山市', + code: '350782', + }, + { + name: '建瓯市', + code: '350783', + }, + ], + }, + { + name: '龙岩市', + code: '350800', + children: [ + { + name: '新罗区', + code: '350802', + }, + { + name: '永定区', + code: '350803', + }, + { + name: '长汀县', + code: '350821', + }, + { + name: '上杭县', + code: '350823', + }, + { + name: '武平县', + code: '350824', + }, + { + name: '连城县', + code: '350825', + }, + { + name: '漳平市', + code: '350881', + }, + ], + }, + { + name: '宁德市', + code: '350900', + children: [ + { + name: '蕉城区', + code: '350902', + }, + { + name: '霞浦县', + code: '350921', + }, + { + name: '古田县', + code: '350922', + }, + { + name: '屏南县', + code: '350923', + }, + { + name: '寿宁县', + code: '350924', + }, + { + name: '周宁县', + code: '350925', + }, + { + name: '柘荣县', + code: '350926', + }, + { + name: '福安市', + code: '350981', + }, + { + name: '福鼎市', + code: '350982', + }, + ], + }, + ], + }, + { + name: '江西省', + code: '360000', + region: 'east', + children: [ + { + name: '南昌市', + code: '360100', + children: [ + { + name: '东湖区', + code: '360102', + }, + { + name: '西湖区', + code: '360103', + }, + { + name: '青云谱区', + code: '360104', + }, + { + name: '湾里区', + code: '360105', + }, + { + name: '青山湖区', + code: '360111', + }, + { + name: '新建区', + code: '360112', + }, + { + name: '南昌县', + code: '360121', + }, + { + name: '安义县', + code: '360123', + }, + { + name: '进贤县', + code: '360124', + }, + ], + }, + { + name: '景德镇市', + code: '360200', + children: [ + { + name: '昌江区', + code: '360202', + }, + { + name: '珠山区', + code: '360203', + }, + { + name: '浮梁县', + code: '360222', + }, + { + name: '乐平市', + code: '360281', + }, + ], + }, + { + name: '萍乡市', + code: '360300', + children: [ + { + name: '安源区', + code: '360302', + }, + { + name: '湘东区', + code: '360313', + }, + { + name: '莲花县', + code: '360321', + }, + { + name: '上栗县', + code: '360322', + }, + { + name: '芦溪县', + code: '360323', + }, + ], + }, + { + name: '九江市', + code: '360400', + children: [ + { + name: '濂溪区', + code: '360402', + }, + { + name: '浔阳区', + code: '360403', + }, + { + name: '柴桑区', + code: '360404', + }, + { + name: '武宁县', + code: '360423', + }, + { + name: '修水县', + code: '360424', + }, + { + name: '永修县', + code: '360425', + }, + { + name: '德安县', + code: '360426', + }, + { + name: '都昌县', + code: '360428', + }, + { + name: '湖口县', + code: '360429', + }, + { + name: '彭泽县', + code: '360430', + }, + { + name: '瑞昌市', + code: '360481', + }, + { + name: '共青城市', + code: '360482', + }, + { + name: '庐山市', + code: '360483', + }, + ], + }, + { + name: '新余市', + code: '360500', + children: [ + { + name: '渝水区', + code: '360502', + }, + { + name: '分宜县', + code: '360521', + }, + ], + }, + { + name: '鹰潭市', + code: '360600', + children: [ + { + name: '月湖区', + code: '360602', + }, + { + name: '余江区', + code: '360603', + }, + { + name: '贵溪市', + code: '360681', + }, + ], + }, + { + name: '赣州市', + code: '360700', + children: [ + { + name: '章贡区', + code: '360702', + }, + { + name: '南康区', + code: '360703', + }, + { + name: '赣县区', + code: '360704', + }, + { + name: '信丰县', + code: '360722', + }, + { + name: '大余县', + code: '360723', + }, + { + name: '上犹县', + code: '360724', + }, + { + name: '崇义县', + code: '360725', + }, + { + name: '安远县', + code: '360726', + }, + { + name: '龙南县', + code: '360727', + }, + { + name: '定南县', + code: '360728', + }, + { + name: '全南县', + code: '360729', + }, + { + name: '宁都县', + code: '360730', + }, + { + name: '于都县', + code: '360731', + }, + { + name: '兴国县', + code: '360732', + }, + { + name: '会昌县', + code: '360733', + }, + { + name: '寻乌县', + code: '360734', + }, + { + name: '石城县', + code: '360735', + }, + { + name: '瑞金市', + code: '360781', + }, + ], + }, + { + name: '吉安市', + code: '360800', + children: [ + { + name: '吉州区', + code: '360802', + }, + { + name: '青原区', + code: '360803', + }, + { + name: '吉安县', + code: '360821', + }, + { + name: '吉水县', + code: '360822', + }, + { + name: '峡江县', + code: '360823', + }, + { + name: '新干县', + code: '360824', + }, + { + name: '永丰县', + code: '360825', + }, + { + name: '泰和县', + code: '360826', + }, + { + name: '遂川县', + code: '360827', + }, + { + name: '万安县', + code: '360828', + }, + { + name: '安福县', + code: '360829', + }, + { + name: '永新县', + code: '360830', + }, + { + name: '井冈山市', + code: '360881', + }, + ], + }, + { + name: '宜春市', + code: '360900', + children: [ + { + name: '袁州区', + code: '360902', + }, + { + name: '奉新县', + code: '360921', + }, + { + name: '万载县', + code: '360922', + }, + { + name: '上高县', + code: '360923', + }, + { + name: '宜丰县', + code: '360924', + }, + { + name: '靖安县', + code: '360925', + }, + { + name: '铜鼓县', + code: '360926', + }, + { + name: '丰城市', + code: '360981', + }, + { + name: '樟树市', + code: '360982', + }, + { + name: '高安市', + code: '360983', + }, + ], + }, + { + name: '抚州市', + code: '361000', + children: [ + { + name: '临川区', + code: '361002', + }, + { + name: '东乡区', + code: '361003', + }, + { + name: '南城县', + code: '361021', + }, + { + name: '黎川县', + code: '361022', + }, + { + name: '南丰县', + code: '361023', + }, + { + name: '崇仁县', + code: '361024', + }, + { + name: '乐安县', + code: '361025', + }, + { + name: '宜黄县', + code: '361026', + }, + { + name: '金溪县', + code: '361027', + }, + { + name: '资溪县', + code: '361028', + }, + { + name: '广昌县', + code: '361030', + }, + ], + }, + { + name: '上饶市', + code: '361100', + children: [ + { + name: '信州区', + code: '361102', + }, + { + name: '广丰区', + code: '361103', + }, + { + name: '上饶县', + code: '361121', + }, + { + name: '玉山县', + code: '361123', + }, + { + name: '铅山县', + code: '361124', + }, + { + name: '横峰县', + code: '361125', + }, + { + name: '弋阳县', + code: '361126', + }, + { + name: '余干县', + code: '361127', + }, + { + name: '鄱阳县', + code: '361128', + }, + { + name: '万年县', + code: '361129', + }, + { + name: '婺源县', + code: '361130', + }, + { + name: '德兴市', + code: '361181', + }, + ], + }, + ], + }, + { + name: '山东省', + code: '370000', + region: 'east', + children: [ + { + name: '济南市', + code: '370100', + children: [ + { + name: '历下区', + code: '370102', + }, + { + name: '市中区', + code: '370103', + }, + { + name: '槐荫区', + code: '370104', + }, + { + name: '天桥区', + code: '370105', + }, + { + name: '历城区', + code: '370112', + }, + { + name: '长清区', + code: '370113', + }, + { + name: '章丘区', + code: '370114', + }, + { + name: '济阳区', + code: '370115', + }, + { + name: '莱芜区', + code: '370116', + }, + { + name: '钢城区', + code: '370117', + }, + { + name: '平阴县', + code: '370124', + }, + { + name: '商河县', + code: '370126', + }, + ], + }, + { + name: '青岛市', + code: '370200', + children: [ + { + name: '市南区', + code: '370202', + }, + { + name: '市北区', + code: '370203', + }, + { + name: '黄岛区', + code: '370211', + }, + { + name: '崂山区', + code: '370212', + }, + { + name: '李沧区', + code: '370213', + }, + { + name: '城阳区', + code: '370214', + }, + { + name: '即墨区', + code: '370215', + }, + { + name: '胶州市', + code: '370281', + }, + { + name: '平度市', + code: '370283', + }, + { + name: '莱西市', + code: '370285', + }, + ], + }, + { + name: '淄博市', + code: '370300', + children: [ + { + name: '淄川区', + code: '370302', + }, + { + name: '张店区', + code: '370303', + }, + { + name: '博山区', + code: '370304', + }, + { + name: '临淄区', + code: '370305', + }, + { + name: '周村区', + code: '370306', + }, + { + name: '桓台县', + code: '370321', + }, + { + name: '高青县', + code: '370322', + }, + { + name: '沂源县', + code: '370323', + }, + ], + }, + { + name: '枣庄市', + code: '370400', + children: [ + { + name: '市中区', + code: '370402', + }, + { + name: '薛城区', + code: '370403', + }, + { + name: '峄城区', + code: '370404', + }, + { + name: '台儿庄区', + code: '370405', + }, + { + name: '山亭区', + code: '370406', + }, + { + name: '滕州市', + code: '370481', + }, + ], + }, + { + name: '东营市', + code: '370500', + children: [ + { + name: '东营区', + code: '370502', + }, + { + name: '河口区', + code: '370503', + }, + { + name: '垦利区', + code: '370505', + }, + { + name: '利津县', + code: '370522', + }, + { + name: '广饶县', + code: '370523', + }, + ], + }, + { + name: '烟台市', + code: '370600', + children: [ + { + name: '芝罘区', + code: '370602', + }, + { + name: '福山区', + code: '370611', + }, + { + name: '牟平区', + code: '370612', + }, + { + name: '莱山区', + code: '370613', + }, + { + name: '长岛县', + code: '370634', + }, + { + name: '龙口市', + code: '370681', + }, + { + name: '莱阳市', + code: '370682', + }, + { + name: '莱州市', + code: '370683', + }, + { + name: '蓬莱市', + code: '370684', + }, + { + name: '招远市', + code: '370685', + }, + { + name: '栖霞市', + code: '370686', + }, + { + name: '海阳市', + code: '370687', + }, + ], + }, + { + name: '潍坊市', + code: '370700', + children: [ + { + name: '潍城区', + code: '370702', + }, + { + name: '寒亭区', + code: '370703', + }, + { + name: '坊子区', + code: '370704', + }, + { + name: '奎文区', + code: '370705', + }, + { + name: '临朐县', + code: '370724', + }, + { + name: '昌乐县', + code: '370725', + }, + { + name: '青州市', + code: '370781', + }, + { + name: '诸城市', + code: '370782', + }, + { + name: '寿光市', + code: '370783', + }, + { + name: '安丘市', + code: '370784', + }, + { + name: '高密市', + code: '370785', + }, + { + name: '昌邑市', + code: '370786', + }, + ], + }, + { + name: '济宁市', + code: '370800', + children: [ + { + name: '任城区', + code: '370811', + }, + { + name: '兖州区', + code: '370812', + }, + { + name: '微山县', + code: '370826', + }, + { + name: '鱼台县', + code: '370827', + }, + { + name: '金乡县', + code: '370828', + }, + { + name: '嘉祥县', + code: '370829', + }, + { + name: '汶上县', + code: '370830', + }, + { + name: '泗水县', + code: '370831', + }, + { + name: '梁山县', + code: '370832', + }, + { + name: '曲阜市', + code: '370881', + }, + { + name: '邹城市', + code: '370883', + }, + ], + }, + { + name: '泰安市', + code: '370900', + children: [ + { + name: '泰山区', + code: '370902', + }, + { + name: '岱岳区', + code: '370911', + }, + { + name: '宁阳县', + code: '370921', + }, + { + name: '东平县', + code: '370923', + }, + { + name: '新泰市', + code: '370982', + }, + { + name: '肥城市', + code: '370983', + }, + ], + }, + { + name: '威海市', + code: '371000', + children: [ + { + name: '环翠区', + code: '371002', + }, + { + name: '文登区', + code: '371003', + }, + { + name: '荣成市', + code: '371082', + }, + { + name: '乳山市', + code: '371083', + }, + ], + }, + { + name: '日照市', + code: '371100', + children: [ + { + name: '东港区', + code: '371102', + }, + { + name: '岚山区', + code: '371103', + }, + { + name: '五莲县', + code: '371121', + }, + { + name: '莒县', + code: '371122', + }, + ], + }, + { + name: '临沂市', + code: '371300', + children: [ + { + name: '兰山区', + code: '371302', + }, + { + name: '罗庄区', + code: '371311', + }, + { + name: '河东区', + code: '371312', + }, + { + name: '沂南县', + code: '371321', + }, + { + name: '郯城县', + code: '371322', + }, + { + name: '沂水县', + code: '371323', + }, + { + name: '兰陵县', + code: '371324', + }, + { + name: '费县', + code: '371325', + }, + { + name: '平邑县', + code: '371326', + }, + { + name: '莒南县', + code: '371327', + }, + { + name: '蒙阴县', + code: '371328', + }, + { + name: '临沭县', + code: '371329', + }, + ], + }, + { + name: '德州市', + code: '371400', + children: [ + { + name: '德城区', + code: '371402', + }, + { + name: '陵城区', + code: '371403', + }, + { + name: '宁津县', + code: '371422', + }, + { + name: '庆云县', + code: '371423', + }, + { + name: '临邑县', + code: '371424', + }, + { + name: '齐河县', + code: '371425', + }, + { + name: '平原县', + code: '371426', + }, + { + name: '夏津县', + code: '371427', + }, + { + name: '武城县', + code: '371428', + }, + { + name: '乐陵市', + code: '371481', + }, + { + name: '禹城市', + code: '371482', + }, + ], + }, + { + name: '聊城市', + code: '371500', + children: [ + { + name: '东昌府区', + code: '371502', + }, + { + name: '阳谷县', + code: '371521', + }, + { + name: '莘县', + code: '371522', + }, + { + name: '茌平县', + code: '371523', + }, + { + name: '东阿县', + code: '371524', + }, + { + name: '冠县', + code: '371525', + }, + { + name: '高唐县', + code: '371526', + }, + { + name: '临清市', + code: '371581', + }, + ], + }, + { + name: '滨州市', + code: '371600', + children: [ + { + name: '滨城区', + code: '371602', + }, + { + name: '沾化区', + code: '371603', + }, + { + name: '惠民县', + code: '371621', + }, + { + name: '阳信县', + code: '371622', + }, + { + name: '无棣县', + code: '371623', + }, + { + name: '博兴县', + code: '371625', + }, + { + name: '邹平市', + code: '371681', + }, + ], + }, + { + name: '菏泽市', + code: '371700', + children: [ + { + name: '牡丹区', + code: '371702', + }, + { + name: '定陶区', + code: '371703', + }, + { + name: '曹县', + code: '371721', + }, + { + name: '单县', + code: '371722', + }, + { + name: '成武县', + code: '371723', + }, + { + name: '巨野县', + code: '371724', + }, + { + name: '郓城县', + code: '371725', + }, + { + name: '鄄城县', + code: '371726', + }, + { + name: '东明县', + code: '371728', + }, + ], + }, + ], + }, + { + name: '河南省', + code: '410000', + region: 'central', + children: [ + { + name: '郑州市', + code: '410100', + children: [ + { + name: '中原区', + code: '410102', + }, + { + name: '二七区', + code: '410103', + }, + { + name: '管城回族区', + code: '410104', + }, + { + name: '金水区', + code: '410105', + }, + { + name: '上街区', + code: '410106', + }, + { + name: '惠济区', + code: '410108', + }, + { + name: '中牟县', + code: '410122', + }, + { + name: '巩义市', + code: '410181', + }, + { + name: '荥阳市', + code: '410182', + }, + { + name: '新密市', + code: '410183', + }, + { + name: '新郑市', + code: '410184', + }, + { + name: '登封市', + code: '410185', + }, + ], + }, + { + name: '开封市', + code: '410200', + children: [ + { + name: '龙亭区', + code: '410202', + }, + { + name: '顺河回族区', + code: '410203', + }, + { + name: '鼓楼区', + code: '410204', + }, + { + name: '禹王台区', + code: '410205', + }, + { + name: '祥符区', + code: '410212', + }, + { + name: '杞县', + code: '410221', + }, + { + name: '通许县', + code: '410222', + }, + { + name: '尉氏县', + code: '410223', + }, + { + name: '兰考县', + code: '410225', + }, + ], + }, + { + name: '洛阳市', + code: '410300', + children: [ + { + name: '老城区', + code: '410302', + }, + { + name: '西工区', + code: '410303', + }, + { + name: '瀍河回族区', + code: '410304', + }, + { + name: '涧西区', + code: '410305', + }, + { + name: '吉利区', + code: '410306', + }, + { + name: '洛龙区', + code: '410311', + }, + { + name: '孟津县', + code: '410322', + }, + { + name: '新安县', + code: '410323', + }, + { + name: '栾川县', + code: '410324', + }, + { + name: '嵩县', + code: '410325', + }, + { + name: '汝阳县', + code: '410326', + }, + { + name: '宜阳县', + code: '410327', + }, + { + name: '洛宁县', + code: '410328', + }, + { + name: '伊川县', + code: '410329', + }, + { + name: '偃师市', + code: '410381', + }, + ], + }, + { + name: '平顶山市', + code: '410400', + children: [ + { + name: '新华区', + code: '410402', + }, + { + name: '卫东区', + code: '410403', + }, + { + name: '石龙区', + code: '410404', + }, + { + name: '湛河区', + code: '410411', + }, + { + name: '宝丰县', + code: '410421', + }, + { + name: '叶县', + code: '410422', + }, + { + name: '鲁山县', + code: '410423', + }, + { + name: '郏县', + code: '410425', + }, + { + name: '舞钢市', + code: '410481', + }, + { + name: '汝州市', + code: '410482', + }, + ], + }, + { + name: '安阳市', + code: '410500', + children: [ + { + name: '文峰区', + code: '410502', + }, + { + name: '北关区', + code: '410503', + }, + { + name: '殷都区', + code: '410505', + }, + { + name: '龙安区', + code: '410506', + }, + { + name: '安阳县', + code: '410522', + }, + { + name: '汤阴县', + code: '410523', + }, + { + name: '滑县', + code: '410526', + }, + { + name: '内黄县', + code: '410527', + }, + { + name: '林州市', + code: '410581', + }, + ], + }, + { + name: '鹤壁市', + code: '410600', + children: [ + { + name: '鹤山区', + code: '410602', + }, + { + name: '山城区', + code: '410603', + }, + { + name: '淇滨区', + code: '410611', + }, + { + name: '浚县', + code: '410621', + }, + { + name: '淇县', + code: '410622', + }, + ], + }, + { + name: '新乡市', + code: '410700', + children: [ + { + name: '红旗区', + code: '410702', + }, + { + name: '卫滨区', + code: '410703', + }, + { + name: '凤泉区', + code: '410704', + }, + { + name: '牧野区', + code: '410711', + }, + { + name: '新乡县', + code: '410721', + }, + { + name: '获嘉县', + code: '410724', + }, + { + name: '原阳县', + code: '410725', + }, + { + name: '延津县', + code: '410726', + }, + { + name: '封丘县', + code: '410727', + }, + { + name: '长垣县', + code: '410728', + }, + { + name: '卫辉市', + code: '410781', + }, + { + name: '辉县市', + code: '410782', + }, + ], + }, + { + name: '焦作市', + code: '410800', + children: [ + { + name: '解放区', + code: '410802', + }, + { + name: '中站区', + code: '410803', + }, + { + name: '马村区', + code: '410804', + }, + { + name: '山阳区', + code: '410811', + }, + { + name: '修武县', + code: '410821', + }, + { + name: '博爱县', + code: '410822', + }, + { + name: '武陟县', + code: '410823', + }, + { + name: '温县', + code: '410825', + }, + { + name: '沁阳市', + code: '410882', + }, + { + name: '孟州市', + code: '410883', + }, + ], + }, + { + name: '濮阳市', + code: '410900', + children: [ + { + name: '华龙区', + code: '410902', + }, + { + name: '清丰县', + code: '410922', + }, + { + name: '南乐县', + code: '410923', + }, + { + name: '范县', + code: '410926', + }, + { + name: '台前县', + code: '410927', + }, + { + name: '濮阳县', + code: '410928', + }, + ], + }, + { + name: '许昌市', + code: '411000', + children: [ + { + name: '魏都区', + code: '411002', + }, + { + name: '建安区', + code: '411003', + }, + { + name: '鄢陵县', + code: '411024', + }, + { + name: '襄城县', + code: '411025', + }, + { + name: '禹州市', + code: '411081', + }, + { + name: '长葛市', + code: '411082', + }, + ], + }, + { + name: '漯河市', + code: '411100', + children: [ + { + name: '源汇区', + code: '411102', + }, + { + name: '郾城区', + code: '411103', + }, + { + name: '召陵区', + code: '411104', + }, + { + name: '舞阳县', + code: '411121', + }, + { + name: '临颍县', + code: '411122', + }, + ], + }, + { + name: '三门峡市', + code: '411200', + children: [ + { + name: '湖滨区', + code: '411202', + }, + { + name: '陕州区', + code: '411203', + }, + { + name: '渑池县', + code: '411221', + }, + { + name: '卢氏县', + code: '411224', + }, + { + name: '义马市', + code: '411281', + }, + { + name: '灵宝市', + code: '411282', + }, + ], + }, + { + name: '南阳市', + code: '411300', + children: [ + { + name: '宛城区', + code: '411302', + }, + { + name: '卧龙区', + code: '411303', + }, + { + name: '南召县', + code: '411321', + }, + { + name: '方城县', + code: '411322', + }, + { + name: '西峡县', + code: '411323', + }, + { + name: '镇平县', + code: '411324', + }, + { + name: '内乡县', + code: '411325', + }, + { + name: '淅川县', + code: '411326', + }, + { + name: '社旗县', + code: '411327', + }, + { + name: '唐河县', + code: '411328', + }, + { + name: '新野县', + code: '411329', + }, + { + name: '桐柏县', + code: '411330', + }, + { + name: '邓州市', + code: '411381', + }, + ], + }, + { + name: '商丘市', + code: '411400', + children: [ + { + name: '梁园区', + code: '411402', + }, + { + name: '睢阳区', + code: '411403', + }, + { + name: '民权县', + code: '411421', + }, + { + name: '睢县', + code: '411422', + }, + { + name: '宁陵县', + code: '411423', + }, + { + name: '柘城县', + code: '411424', + }, + { + name: '虞城县', + code: '411425', + }, + { + name: '夏邑县', + code: '411426', + }, + { + name: '永城市', + code: '411481', + }, + ], + }, + { + name: '信阳市', + code: '411500', + children: [ + { + name: '浉河区', + code: '411502', + }, + { + name: '平桥区', + code: '411503', + }, + { + name: '罗山县', + code: '411521', + }, + { + name: '光山县', + code: '411522', + }, + { + name: '新县', + code: '411523', + }, + { + name: '商城县', + code: '411524', + }, + { + name: '固始县', + code: '411525', + }, + { + name: '潢川县', + code: '411526', + }, + { + name: '淮滨县', + code: '411527', + }, + { + name: '息县', + code: '411528', + }, + ], + }, + { + name: '周口市', + code: '411600', + children: [ + { + name: '川汇区', + code: '411602', + }, + { + name: '扶沟县', + code: '411621', + }, + { + name: '西华县', + code: '411622', + }, + { + name: '商水县', + code: '411623', + }, + { + name: '沈丘县', + code: '411624', + }, + { + name: '郸城县', + code: '411625', + }, + { + name: '淮阳县', + code: '411626', + }, + { + name: '太康县', + code: '411627', + }, + { + name: '鹿邑县', + code: '411628', + }, + { + name: '项城市', + code: '411681', + }, + ], + }, + { + name: '驻马店市', + code: '411700', + children: [ + { + name: '驿城区', + code: '411702', + }, + { + name: '西平县', + code: '411721', + }, + { + name: '上蔡县', + code: '411722', + }, + { + name: '平舆县', + code: '411723', + }, + { + name: '正阳县', + code: '411724', + }, + { + name: '确山县', + code: '411725', + }, + { + name: '泌阳县', + code: '411726', + }, + { + name: '汝南县', + code: '411727', + }, + { + name: '遂平县', + code: '411728', + }, + { + name: '新蔡县', + code: '411729', + }, + ], + }, + { + name: '直辖县', + code: '419000', + children: [ + { + name: '济源市', + code: '419001', + }, + ], + }, + ], + }, + { + name: '湖北省', + code: '420000', + region: 'central', + children: [ + { + name: '武汉市', + code: '420100', + children: [ + { + name: '江岸区', + code: '420102', + }, + { + name: '江汉区', + code: '420103', + }, + { + name: '硚口区', + code: '420104', + }, + { + name: '汉阳区', + code: '420105', + }, + { + name: '武昌区', + code: '420106', + }, + { + name: '青山区', + code: '420107', + }, + { + name: '洪山区', + code: '420111', + }, + { + name: '东西湖区', + code: '420112', + }, + { + name: '汉南区', + code: '420113', + }, + { + name: '蔡甸区', + code: '420114', + }, + { + name: '江夏区', + code: '420115', + }, + { + name: '黄陂区', + code: '420116', + }, + { + name: '新洲区', + code: '420117', + }, + ], + }, + { + name: '黄石市', + code: '420200', + children: [ + { + name: '黄石港区', + code: '420202', + }, + { + name: '西塞山区', + code: '420203', + }, + { + name: '下陆区', + code: '420204', + }, + { + name: '铁山区', + code: '420205', + }, + { + name: '阳新县', + code: '420222', + }, + { + name: '大冶市', + code: '420281', + }, + ], + }, + { + name: '十堰市', + code: '420300', + children: [ + { + name: '茅箭区', + code: '420302', + }, + { + name: '张湾区', + code: '420303', + }, + { + name: '郧阳区', + code: '420304', + }, + { + name: '郧西县', + code: '420322', + }, + { + name: '竹山县', + code: '420323', + }, + { + name: '竹溪县', + code: '420324', + }, + { + name: '房县', + code: '420325', + }, + { + name: '丹江口市', + code: '420381', + }, + ], + }, + { + name: '宜昌市', + code: '420500', + children: [ + { + name: '西陵区', + code: '420502', + }, + { + name: '伍家岗区', + code: '420503', + }, + { + name: '点军区', + code: '420504', + }, + { + name: '猇亭区', + code: '420505', + }, + { + name: '夷陵区', + code: '420506', + }, + { + name: '远安县', + code: '420525', + }, + { + name: '兴山县', + code: '420526', + }, + { + name: '秭归县', + code: '420527', + }, + { + name: '长阳土家族自治县', + code: '420528', + }, + { + name: '五峰土家族自治县', + code: '420529', + }, + { + name: '宜都市', + code: '420581', + }, + { + name: '当阳市', + code: '420582', + }, + { + name: '枝江市', + code: '420583', + }, + ], + }, + { + name: '襄阳市', + code: '420600', + children: [ + { + name: '襄城区', + code: '420602', + }, + { + name: '樊城区', + code: '420606', + }, + { + name: '襄州区', + code: '420607', + }, + { + name: '南漳县', + code: '420624', + }, + { + name: '谷城县', + code: '420625', + }, + { + name: '保康县', + code: '420626', + }, + { + name: '老河口市', + code: '420682', + }, + { + name: '枣阳市', + code: '420683', + }, + { + name: '宜城市', + code: '420684', + }, + ], + }, + { + name: '鄂州市', + code: '420700', + children: [ + { + name: '梁子湖区', + code: '420702', + }, + { + name: '华容区', + code: '420703', + }, + { + name: '鄂城区', + code: '420704', + }, + ], + }, + { + name: '荆门市', + code: '420800', + children: [ + { + name: '东宝区', + code: '420802', + }, + { + name: '掇刀区', + code: '420804', + }, + { + name: '沙洋县', + code: '420822', + }, + { + name: '钟祥市', + code: '420881', + }, + { + name: '京山市', + code: '420882', + }, + ], + }, + { + name: '孝感市', + code: '420900', + children: [ + { + name: '孝南区', + code: '420902', + }, + { + name: '孝昌县', + code: '420921', + }, + { + name: '大悟县', + code: '420922', + }, + { + name: '云梦县', + code: '420923', + }, + { + name: '应城市', + code: '420981', + }, + { + name: '安陆市', + code: '420982', + }, + { + name: '汉川市', + code: '420984', + }, + ], + }, + { + name: '荆州市', + code: '421000', + children: [ + { + name: '沙市区', + code: '421002', + }, + { + name: '荆州区', + code: '421003', + }, + { + name: '公安县', + code: '421022', + }, + { + name: '监利县', + code: '421023', + }, + { + name: '江陵县', + code: '421024', + }, + { + name: '石首市', + code: '421081', + }, + { + name: '洪湖市', + code: '421083', + }, + { + name: '松滋市', + code: '421087', + }, + ], + }, + { + name: '黄冈市', + code: '421100', + children: [ + { + name: '黄州区', + code: '421102', + }, + { + name: '团风县', + code: '421121', + }, + { + name: '红安县', + code: '421122', + }, + { + name: '罗田县', + code: '421123', + }, + { + name: '英山县', + code: '421124', + }, + { + name: '浠水县', + code: '421125', + }, + { + name: '蕲春县', + code: '421126', + }, + { + name: '黄梅县', + code: '421127', + }, + { + name: '麻城市', + code: '421181', + }, + { + name: '武穴市', + code: '421182', + }, + ], + }, + { + name: '咸宁市', + code: '421200', + children: [ + { + name: '咸安区', + code: '421202', + }, + { + name: '嘉鱼县', + code: '421221', + }, + { + name: '通城县', + code: '421222', + }, + { + name: '崇阳县', + code: '421223', + }, + { + name: '通山县', + code: '421224', + }, + { + name: '赤壁市', + code: '421281', + }, + ], + }, + { + name: '随州市', + code: '421300', + children: [ + { + name: '曾都区', + code: '421303', + }, + { + name: '随县', + code: '421321', + }, + { + name: '广水市', + code: '421381', + }, + ], + }, + { + name: '恩施土家族苗族自治州', + code: '422800', + children: [ + { + name: '恩施市', + code: '422801', + }, + { + name: '利川市', + code: '422802', + }, + { + name: '建始县', + code: '422822', + }, + { + name: '巴东县', + code: '422823', + }, + { + name: '宣恩县', + code: '422825', + }, + { + name: '咸丰县', + code: '422826', + }, + { + name: '来凤县', + code: '422827', + }, + { + name: '鹤峰县', + code: '422828', + }, + ], + }, + { + name: '直辖县', + code: '429000', + children: [ + { + name: '仙桃市', + code: '429004', + }, + { + name: '潜江市', + code: '429005', + }, + { + name: '天门市', + code: '429006', + }, + { + name: '神农架林区', + code: '429021', + }, + ], + }, + ], + }, + { + name: '湖南省', + code: '430000', + region: 'central', + children: [ + { + name: '长沙市', + code: '430100', + children: [ + { + name: '芙蓉区', + code: '430102', + }, + { + name: '天心区', + code: '430103', + }, + { + name: '岳麓区', + code: '430104', + }, + { + name: '开福区', + code: '430105', + }, + { + name: '雨花区', + code: '430111', + }, + { + name: '望城区', + code: '430112', + }, + { + name: '长沙县', + code: '430121', + }, + { + name: '浏阳市', + code: '430181', + }, + { + name: '宁乡市', + code: '430182', + }, + ], + }, + { + name: '株洲市', + code: '430200', + children: [ + { + name: '荷塘区', + code: '430202', + }, + { + name: '芦淞区', + code: '430203', + }, + { + name: '石峰区', + code: '430204', + }, + { + name: '天元区', + code: '430211', + }, + { + name: '渌口区', + code: '430212', + }, + { + name: '攸县', + code: '430223', + }, + { + name: '茶陵县', + code: '430224', + }, + { + name: '炎陵县', + code: '430225', + }, + { + name: '醴陵市', + code: '430281', + }, + ], + }, + { + name: '湘潭市', + code: '430300', + children: [ + { + name: '雨湖区', + code: '430302', + }, + { + name: '岳塘区', + code: '430304', + }, + { + name: '湘潭县', + code: '430321', + }, + { + name: '湘乡市', + code: '430381', + }, + { + name: '韶山市', + code: '430382', + }, + ], + }, + { + name: '衡阳市', + code: '430400', + children: [ + { + name: '珠晖区', + code: '430405', + }, + { + name: '雁峰区', + code: '430406', + }, + { + name: '石鼓区', + code: '430407', + }, + { + name: '蒸湘区', + code: '430408', + }, + { + name: '南岳区', + code: '430412', + }, + { + name: '衡阳县', + code: '430421', + }, + { + name: '衡南县', + code: '430422', + }, + { + name: '衡山县', + code: '430423', + }, + { + name: '衡东县', + code: '430424', + }, + { + name: '祁东县', + code: '430426', + }, + { + name: '耒阳市', + code: '430481', + }, + { + name: '常宁市', + code: '430482', + }, + ], + }, + { + name: '邵阳市', + code: '430500', + children: [ + { + name: '双清区', + code: '430502', + }, + { + name: '大祥区', + code: '430503', + }, + { + name: '北塔区', + code: '430511', + }, + { + name: '邵东县', + code: '430521', + }, + { + name: '新邵县', + code: '430522', + }, + { + name: '邵阳县', + code: '430523', + }, + { + name: '隆回县', + code: '430524', + }, + { + name: '洞口县', + code: '430525', + }, + { + name: '绥宁县', + code: '430527', + }, + { + name: '新宁县', + code: '430528', + }, + { + name: '城步苗族自治县', + code: '430529', + }, + { + name: '武冈市', + code: '430581', + }, + ], + }, + { + name: '岳阳市', + code: '430600', + children: [ + { + name: '岳阳楼区', + code: '430602', + }, + { + name: '云溪区', + code: '430603', + }, + { + name: '君山区', + code: '430611', + }, + { + name: '岳阳县', + code: '430621', + }, + { + name: '华容县', + code: '430623', + }, + { + name: '湘阴县', + code: '430624', + }, + { + name: '平江县', + code: '430626', + }, + { + name: '汨罗市', + code: '430681', + }, + { + name: '临湘市', + code: '430682', + }, + ], + }, + { + name: '常德市', + code: '430700', + children: [ + { + name: '武陵区', + code: '430702', + }, + { + name: '鼎城区', + code: '430703', + }, + { + name: '安乡县', + code: '430721', + }, + { + name: '汉寿县', + code: '430722', + }, + { + name: '澧县', + code: '430723', + }, + { + name: '临澧县', + code: '430724', + }, + { + name: '桃源县', + code: '430725', + }, + { + name: '石门县', + code: '430726', + }, + { + name: '津市市', + code: '430781', + }, + ], + }, + { + name: '张家界市', + code: '430800', + children: [ + { + name: '永定区', + code: '430802', + }, + { + name: '武陵源区', + code: '430811', + }, + { + name: '慈利县', + code: '430821', + }, + { + name: '桑植县', + code: '430822', + }, + ], + }, + { + name: '益阳市', + code: '430900', + children: [ + { + name: '资阳区', + code: '430902', + }, + { + name: '赫山区', + code: '430903', + }, + { + name: '南县', + code: '430921', + }, + { + name: '桃江县', + code: '430922', + }, + { + name: '安化县', + code: '430923', + }, + { + name: '沅江市', + code: '430981', + }, + ], + }, + { + name: '郴州市', + code: '431000', + children: [ + { + name: '北湖区', + code: '431002', + }, + { + name: '苏仙区', + code: '431003', + }, + { + name: '桂阳县', + code: '431021', + }, + { + name: '宜章县', + code: '431022', + }, + { + name: '永兴县', + code: '431023', + }, + { + name: '嘉禾县', + code: '431024', + }, + { + name: '临武县', + code: '431025', + }, + { + name: '汝城县', + code: '431026', + }, + { + name: '桂东县', + code: '431027', + }, + { + name: '安仁县', + code: '431028', + }, + { + name: '资兴市', + code: '431081', + }, + ], + }, + { + name: '永州市', + code: '431100', + children: [ + { + name: '零陵区', + code: '431102', + }, + { + name: '冷水滩区', + code: '431103', + }, + { + name: '祁阳县', + code: '431121', + }, + { + name: '东安县', + code: '431122', + }, + { + name: '双牌县', + code: '431123', + }, + { + name: '道县', + code: '431124', + }, + { + name: '江永县', + code: '431125', + }, + { + name: '宁远县', + code: '431126', + }, + { + name: '蓝山县', + code: '431127', + }, + { + name: '新田县', + code: '431128', + }, + { + name: '江华瑶族自治县', + code: '431129', + }, + ], + }, + { + name: '怀化市', + code: '431200', + children: [ + { + name: '鹤城区', + code: '431202', + }, + { + name: '中方县', + code: '431221', + }, + { + name: '沅陵县', + code: '431222', + }, + { + name: '辰溪县', + code: '431223', + }, + { + name: '溆浦县', + code: '431224', + }, + { + name: '会同县', + code: '431225', + }, + { + name: '麻阳苗族自治县', + code: '431226', + }, + { + name: '新晃侗族自治县', + code: '431227', + }, + { + name: '芷江侗族自治县', + code: '431228', + }, + { + name: '靖州苗族侗族自治县', + code: '431229', + }, + { + name: '通道侗族自治县', + code: '431230', + }, + { + name: '洪江市', + code: '431281', + }, + ], + }, + { + name: '娄底市', + code: '431300', + children: [ + { + name: '娄星区', + code: '431302', + }, + { + name: '双峰县', + code: '431321', + }, + { + name: '新化县', + code: '431322', + }, + { + name: '冷水江市', + code: '431381', + }, + { + name: '涟源市', + code: '431382', + }, + ], + }, + { + name: '湘西土家族苗族自治州', + code: '433100', + children: [ + { + name: '吉首市', + code: '433101', + }, + { + name: '泸溪县', + code: '433122', + }, + { + name: '凤凰县', + code: '433123', + }, + { + name: '花垣县', + code: '433124', + }, + { + name: '保靖县', + code: '433125', + }, + { + name: '古丈县', + code: '433126', + }, + { + name: '永顺县', + code: '433127', + }, + { + name: '龙山县', + code: '433130', + }, + ], + }, + ], + }, + { + name: '广东省', + code: '440000', + region: 'south', + children: [ + { + name: '广州市', + code: '440100', + children: [ + { + name: '荔湾区', + code: '440103', + }, + { + name: '越秀区', + code: '440104', + }, + { + name: '海珠区', + code: '440105', + }, + { + name: '天河区', + code: '440106', + }, + { + name: '白云区', + code: '440111', + }, + { + name: '黄埔区', + code: '440112', + }, + { + name: '番禺区', + code: '440113', + }, + { + name: '花都区', + code: '440114', + }, + { + name: '南沙区', + code: '440115', + }, + { + name: '从化区', + code: '440117', + }, + { + name: '增城区', + code: '440118', + }, + ], + }, + { + name: '韶关市', + code: '440200', + children: [ + { + name: '武江区', + code: '440203', + }, + { + name: '浈江区', + code: '440204', + }, + { + name: '曲江区', + code: '440205', + }, + { + name: '始兴县', + code: '440222', + }, + { + name: '仁化县', + code: '440224', + }, + { + name: '翁源县', + code: '440229', + }, + { + name: '乳源瑶族自治县', + code: '440232', + }, + { + name: '新丰县', + code: '440233', + }, + { + name: '乐昌市', + code: '440281', + }, + { + name: '南雄市', + code: '440282', + }, + ], + }, + { + name: '深圳市', + code: '440300', + children: [ + { + name: '罗湖区', + code: '440303', + }, + { + name: '福田区', + code: '440304', + }, + { + name: '南山区', + code: '440305', + }, + { + name: '宝安区', + code: '440306', + }, + { + name: '龙岗区', + code: '440307', + }, + { + name: '盐田区', + code: '440308', + }, + { + name: '龙华区', + code: '440309', + }, + { + name: '坪山区', + code: '440310', + }, + { + name: '光明区', + code: '440311', + }, + ], + }, + { + name: '珠海市', + code: '440400', + children: [ + { + name: '香洲区', + code: '440402', + }, + { + name: '斗门区', + code: '440403', + }, + { + name: '金湾区', + code: '440404', + }, + ], + }, + { + name: '汕头市', + code: '440500', + children: [ + { + name: '龙湖区', + code: '440507', + }, + { + name: '金平区', + code: '440511', + }, + { + name: '濠江区', + code: '440512', + }, + { + name: '潮阳区', + code: '440513', + }, + { + name: '潮南区', + code: '440514', + }, + { + name: '澄海区', + code: '440515', + }, + { + name: '南澳县', + code: '440523', + }, + ], + }, + { + name: '佛山市', + code: '440600', + children: [ + { + name: '禅城区', + code: '440604', + }, + { + name: '南海区', + code: '440605', + }, + { + name: '顺德区', + code: '440606', + }, + { + name: '三水区', + code: '440607', + }, + { + name: '高明区', + code: '440608', + }, + ], + }, + { + name: '江门市', + code: '440700', + children: [ + { + name: '蓬江区', + code: '440703', + }, + { + name: '江海区', + code: '440704', + }, + { + name: '新会区', + code: '440705', + }, + { + name: '台山市', + code: '440781', + }, + { + name: '开平市', + code: '440783', + }, + { + name: '鹤山市', + code: '440784', + }, + { + name: '恩平市', + code: '440785', + }, + ], + }, + { + name: '湛江市', + code: '440800', + children: [ + { + name: '赤坎区', + code: '440802', + }, + { + name: '霞山区', + code: '440803', + }, + { + name: '坡头区', + code: '440804', + }, + { + name: '麻章区', + code: '440811', + }, + { + name: '遂溪县', + code: '440823', + }, + { + name: '徐闻县', + code: '440825', + }, + { + name: '廉江市', + code: '440881', + }, + { + name: '雷州市', + code: '440882', + }, + { + name: '吴川市', + code: '440883', + }, + ], + }, + { + name: '茂名市', + code: '440900', + children: [ + { + name: '茂南区', + code: '440902', + }, + { + name: '电白区', + code: '440904', + }, + { + name: '高州市', + code: '440981', + }, + { + name: '化州市', + code: '440982', + }, + { + name: '信宜市', + code: '440983', + }, + ], + }, + { + name: '肇庆市', + code: '441200', + children: [ + { + name: '端州区', + code: '441202', + }, + { + name: '鼎湖区', + code: '441203', + }, + { + name: '高要区', + code: '441204', + }, + { + name: '广宁县', + code: '441223', + }, + { + name: '怀集县', + code: '441224', + }, + { + name: '封开县', + code: '441225', + }, + { + name: '德庆县', + code: '441226', + }, + { + name: '四会市', + code: '441284', + }, + ], + }, + { + name: '惠州市', + code: '441300', + children: [ + { + name: '惠城区', + code: '441302', + }, + { + name: '惠阳区', + code: '441303', + }, + { + name: '博罗县', + code: '441322', + }, + { + name: '惠东县', + code: '441323', + }, + { + name: '龙门县', + code: '441324', + }, + ], + }, + { + name: '梅州市', + code: '441400', + children: [ + { + name: '梅江区', + code: '441402', + }, + { + name: '梅县区', + code: '441403', + }, + { + name: '大埔县', + code: '441422', + }, + { + name: '丰顺县', + code: '441423', + }, + { + name: '五华县', + code: '441424', + }, + { + name: '平远县', + code: '441426', + }, + { + name: '蕉岭县', + code: '441427', + }, + { + name: '兴宁市', + code: '441481', + }, + ], + }, + { + name: '汕尾市', + code: '441500', + children: [ + { + name: '城区', + code: '441502', + }, + { + name: '海丰县', + code: '441521', + }, + { + name: '陆河县', + code: '441523', + }, + { + name: '陆丰市', + code: '441581', + }, + ], + }, + { + name: '河源市', + code: '441600', + children: [ + { + name: '源城区', + code: '441602', + }, + { + name: '紫金县', + code: '441621', + }, + { + name: '龙川县', + code: '441622', + }, + { + name: '连平县', + code: '441623', + }, + { + name: '和平县', + code: '441624', + }, + { + name: '东源县', + code: '441625', + }, + ], + }, + { + name: '阳江市', + code: '441700', + children: [ + { + name: '江城区', + code: '441702', + }, + { + name: '阳东区', + code: '441704', + }, + { + name: '阳西县', + code: '441721', + }, + { + name: '阳春市', + code: '441781', + }, + ], + }, + { + name: '清远市', + code: '441800', + children: [ + { + name: '清城区', + code: '441802', + }, + { + name: '清新区', + code: '441803', + }, + { + name: '佛冈县', + code: '441821', + }, + { + name: '阳山县', + code: '441823', + }, + { + name: '连山壮族瑶族自治县', + code: '441825', + }, + { + name: '连南瑶族自治县', + code: '441826', + }, + { + name: '英德市', + code: '441881', + }, + { + name: '连州市', + code: '441882', + }, + ], + }, + { + name: '东莞市', + code: '441900', + children: [], + }, + { + name: '中山市', + code: '442000', + children: [], + }, + { + name: '潮州市', + code: '445100', + children: [ + { + name: '湘桥区', + code: '445102', + }, + { + name: '潮安区', + code: '445103', + }, + { + name: '饶平县', + code: '445122', + }, + ], + }, + { + name: '揭阳市', + code: '445200', + children: [ + { + name: '榕城区', + code: '445202', + }, + { + name: '揭东区', + code: '445203', + }, + { + name: '揭西县', + code: '445222', + }, + { + name: '惠来县', + code: '445224', + }, + { + name: '普宁市', + code: '445281', + }, + ], + }, + { + name: '云浮市', + code: '445300', + children: [ + { + name: '云城区', + code: '445302', + }, + { + name: '云安区', + code: '445303', + }, + { + name: '新兴县', + code: '445321', + }, + { + name: '郁南县', + code: '445322', + }, + { + name: '罗定市', + code: '445381', + }, + ], + }, + ], + }, + { + name: '广西壮族自治区', + code: '450000', + region: 'south', + autonomousRegion: true, + children: [ + { + name: '南宁市', + code: '450100', + children: [ + { + name: '兴宁区', + code: '450102', + }, + { + name: '青秀区', + code: '450103', + }, + { + name: '江南区', + code: '450105', + }, + { + name: '西乡塘区', + code: '450107', + }, + { + name: '良庆区', + code: '450108', + }, + { + name: '邕宁区', + code: '450109', + }, + { + name: '武鸣区', + code: '450110', + }, + { + name: '隆安县', + code: '450123', + }, + { + name: '马山县', + code: '450124', + }, + { + name: '上林县', + code: '450125', + }, + { + name: '宾阳县', + code: '450126', + }, + { + name: '横县', + code: '450127', + }, + ], + }, + { + name: '柳州市', + code: '450200', + children: [ + { + name: '城中区', + code: '450202', + }, + { + name: '鱼峰区', + code: '450203', + }, + { + name: '柳南区', + code: '450204', + }, + { + name: '柳北区', + code: '450205', + }, + { + name: '柳江区', + code: '450206', + }, + { + name: '柳城县', + code: '450222', + }, + { + name: '鹿寨县', + code: '450223', + }, + { + name: '融安县', + code: '450224', + }, + { + name: '融水苗族自治县', + code: '450225', + }, + { + name: '三江侗族自治县', + code: '450226', + }, + ], + }, + { + name: '桂林市', + code: '450300', + children: [ + { + name: '秀峰区', + code: '450302', + }, + { + name: '叠彩区', + code: '450303', + }, + { + name: '象山区', + code: '450304', + }, + { + name: '七星区', + code: '450305', + }, + { + name: '雁山区', + code: '450311', + }, + { + name: '临桂区', + code: '450312', + }, + { + name: '阳朔县', + code: '450321', + }, + { + name: '灵川县', + code: '450323', + }, + { + name: '全州县', + code: '450324', + }, + { + name: '兴安县', + code: '450325', + }, + { + name: '永福县', + code: '450326', + }, + { + name: '灌阳县', + code: '450327', + }, + { + name: '龙胜各族自治县', + code: '450328', + }, + { + name: '资源县', + code: '450329', + }, + { + name: '平乐县', + code: '450330', + }, + { + name: '荔浦市', + code: '450381', + }, + { + name: '恭城瑶族自治县', + code: '450332', + }, + ], + }, + { + name: '梧州市', + code: '450400', + children: [ + { + name: '万秀区', + code: '450403', + }, + { + name: '长洲区', + code: '450405', + }, + { + name: '龙圩区', + code: '450406', + }, + { + name: '苍梧县', + code: '450421', + }, + { + name: '藤县', + code: '450422', + }, + { + name: '蒙山县', + code: '450423', + }, + { + name: '岑溪市', + code: '450481', + }, + ], + }, + { + name: '北海市', + code: '450500', + children: [ + { + name: '海城区', + code: '450502', + }, + { + name: '银海区', + code: '450503', + }, + { + name: '铁山港区', + code: '450512', + }, + { + name: '合浦县', + code: '450521', + }, + ], + }, + { + name: '防城港市', + code: '450600', + children: [ + { + name: '港口区', + code: '450602', + }, + { + name: '防城区', + code: '450603', + }, + { + name: '上思县', + code: '450621', + }, + { + name: '东兴市', + code: '450681', + }, + ], + }, + { + name: '钦州市', + code: '450700', + children: [ + { + name: '钦南区', + code: '450702', + }, + { + name: '钦北区', + code: '450703', + }, + { + name: '灵山县', + code: '450721', + }, + { + name: '浦北县', + code: '450722', + }, + ], + }, + { + name: '贵港市', + code: '450800', + children: [ + { + name: '港北区', + code: '450802', + }, + { + name: '港南区', + code: '450803', + }, + { + name: '覃塘区', + code: '450804', + }, + { + name: '平南县', + code: '450821', + }, + { + name: '桂平市', + code: '450881', + }, + ], + }, + { + name: '玉林市', + code: '450900', + children: [ + { + name: '玉州区', + code: '450902', + }, + { + name: '福绵区', + code: '450903', + }, + { + name: '容县', + code: '450921', + }, + { + name: '陆川县', + code: '450922', + }, + { + name: '博白县', + code: '450923', + }, + { + name: '兴业县', + code: '450924', + }, + { + name: '北流市', + code: '450981', + }, + ], + }, + { + name: '百色市', + code: '451000', + children: [ + { + name: '右江区', + code: '451002', + }, + { + name: '田阳县', + code: '451021', + }, + { + name: '田东县', + code: '451022', + }, + { + name: '平果县', + code: '451023', + }, + { + name: '德保县', + code: '451024', + }, + { + name: '那坡县', + code: '451026', + }, + { + name: '凌云县', + code: '451027', + }, + { + name: '乐业县', + code: '451028', + }, + { + name: '田林县', + code: '451029', + }, + { + name: '西林县', + code: '451030', + }, + { + name: '隆林各族自治县', + code: '451031', + }, + { + name: '靖西市', + code: '451081', + }, + ], + }, + { + name: '贺州市', + code: '451100', + children: [ + { + name: '八步区', + code: '451102', + }, + { + name: '平桂区', + code: '451103', + }, + { + name: '昭平县', + code: '451121', + }, + { + name: '钟山县', + code: '451122', + }, + { + name: '富川瑶族自治县', + code: '451123', + }, + ], + }, + { + name: '河池市', + code: '451200', + children: [ + { + name: '金城江区', + code: '451202', + }, + { + name: '宜州区', + code: '451203', + }, + { + name: '南丹县', + code: '451221', + }, + { + name: '天峨县', + code: '451222', + }, + { + name: '凤山县', + code: '451223', + }, + { + name: '东兰县', + code: '451224', + }, + { + name: '罗城仫佬族自治县', + code: '451225', + }, + { + name: '环江毛南族自治县', + code: '451226', + }, + { + name: '巴马瑶族自治县', + code: '451227', + }, + { + name: '都安瑶族自治县', + code: '451228', + }, + { + name: '大化瑶族自治县', + code: '451229', + }, + ], + }, + { + name: '来宾市', + code: '451300', + children: [ + { + name: '兴宾区', + code: '451302', + }, + { + name: '忻城县', + code: '451321', + }, + { + name: '象州县', + code: '451322', + }, + { + name: '武宣县', + code: '451323', + }, + { + name: '金秀瑶族自治县', + code: '451324', + }, + { + name: '合山市', + code: '451381', + }, + ], + }, + { + name: '崇左市', + code: '451400', + children: [ + { + name: '江州区', + code: '451402', + }, + { + name: '扶绥县', + code: '451421', + }, + { + name: '宁明县', + code: '451422', + }, + { + name: '龙州县', + code: '451423', + }, + { + name: '大新县', + code: '451424', + }, + { + name: '天等县', + code: '451425', + }, + { + name: '凭祥市', + code: '451481', + }, + ], + }, + ], + }, + { + name: '海南省', + code: '460000', + region: 'south', + children: [ + { + name: '海口市', + code: '460100', + children: [ + { + name: '秀英区', + code: '460105', + }, + { + name: '龙华区', + code: '460106', + }, + { + name: '琼山区', + code: '460107', + }, + { + name: '美兰区', + code: '460108', + }, + ], + }, + { + name: '三亚市', + code: '460200', + children: [ + { + name: '海棠区', + code: '460202', + }, + { + name: '吉阳区', + code: '460203', + }, + { + name: '天涯区', + code: '460204', + }, + { + name: '崖州区', + code: '460205', + }, + ], + }, + { + name: '三沙市', + code: '460300', + children: [], + }, + { + name: '儋州市', + code: '460400', + children: [], + }, + { + name: '直辖县', + code: '469000', + children: [ + { + name: '五指山市', + code: '469001', + }, + { + name: '琼海市', + code: '469002', + }, + { + name: '文昌市', + code: '469005', + }, + { + name: '万宁市', + code: '469006', + }, + { + name: '东方市', + code: '469007', + }, + { + name: '定安县', + code: '469021', + }, + { + name: '屯昌县', + code: '469022', + }, + { + name: '澄迈县', + code: '469023', + }, + { + name: '临高县', + code: '469024', + }, + { + name: '白沙黎族自治县', + code: '469025', + }, + { + name: '昌江黎族自治县', + code: '469026', + }, + { + name: '乐东黎族自治县', + code: '469027', + }, + { + name: '陵水黎族自治县', + code: '469028', + }, + { + name: '保亭黎族苗族自治县', + code: '469029', + }, + { + name: '琼中黎族苗族自治县', + code: '469030', + }, + ], + }, + ], + }, + { + name: '重庆市', + code: '500000', + region: 'southwest', + provinceLevelCity: true, + children: [ + { + name: '市辖区', + code: '500100', + children: [ + { + name: '万州区', + code: '500101', + }, + { + name: '涪陵区', + code: '500102', + }, + { + name: '渝中区', + code: '500103', + }, + { + name: '大渡口区', + code: '500104', + }, + { + name: '江北区', + code: '500105', + }, + { + name: '沙坪坝区', + code: '500106', + }, + { + name: '九龙坡区', + code: '500107', + }, + { + name: '南岸区', + code: '500108', + }, + { + name: '北碚区', + code: '500109', + }, + { + name: '綦江区', + code: '500110', + }, + { + name: '大足区', + code: '500111', + }, + { + name: '渝北区', + code: '500112', + }, + { + name: '巴南区', + code: '500113', + }, + { + name: '黔江区', + code: '500114', + }, + { + name: '长寿区', + code: '500115', + }, + { + name: '江津区', + code: '500116', + }, + { + name: '合川区', + code: '500117', + }, + { + name: '永川区', + code: '500118', + }, + { + name: '南川区', + code: '500119', + }, + { + name: '璧山区', + code: '500120', + }, + { + name: '铜梁区', + code: '500151', + }, + { + name: '潼南区', + code: '500152', + }, + { + name: '荣昌区', + code: '500153', + }, + { + name: '开州区', + code: '500154', + }, + { + name: '梁平区', + code: '500155', + }, + { + name: '武隆区', + code: '500156', + }, + ], + }, + { + name: '县辖区', + code: '500200', + children: [ + { + name: '城口县', + code: '500229', + }, + { + name: '丰都县', + code: '500230', + }, + { + name: '垫江县', + code: '500231', + }, + { + name: '忠县', + code: '500233', + }, + { + name: '云阳县', + code: '500235', + }, + { + name: '奉节县', + code: '500236', + }, + { + name: '巫山县', + code: '500237', + }, + { + name: '巫溪县', + code: '500238', + }, + { + name: '石柱土家族自治县', + code: '500240', + }, + { + name: '秀山土家族苗族自治县', + code: '500241', + }, + { + name: '酉阳土家族苗族自治县', + code: '500242', + }, + { + name: '彭水苗族土家族自治县', + code: '500243', + }, + ], + }, + ], + }, + { + name: '四川省', + code: '510000', + region: 'southwest', + children: [ + { + name: '成都市', + code: '510100', + children: [ + { + name: '锦江区', + code: '510104', + }, + { + name: '青羊区', + code: '510105', + }, + { + name: '金牛区', + code: '510106', + }, + { + name: '武侯区', + code: '510107', + }, + { + name: '成华区', + code: '510108', + }, + { + name: '龙泉驿区', + code: '510112', + }, + { + name: '青白江区', + code: '510113', + }, + { + name: '新都区', + code: '510114', + }, + { + name: '温江区', + code: '510115', + }, + { + name: '双流区', + code: '510116', + }, + { + name: '郫都区', + code: '510117', + }, + { + name: '金堂县', + code: '510121', + }, + { + name: '大邑县', + code: '510129', + }, + { + name: '蒲江县', + code: '510131', + }, + { + name: '新津县', + code: '510132', + }, + { + name: '都江堰市', + code: '510181', + }, + { + name: '彭州市', + code: '510182', + }, + { + name: '邛崃市', + code: '510183', + }, + { + name: '崇州市', + code: '510184', + }, + { + name: '简阳市', + code: '510185', + }, + ], + }, + { + name: '自贡市', + code: '510300', + children: [ + { + name: '自流井区', + code: '510302', + }, + { + name: '贡井区', + code: '510303', + }, + { + name: '大安区', + code: '510304', + }, + { + name: '沿滩区', + code: '510311', + }, + { + name: '荣县', + code: '510321', + }, + { + name: '富顺县', + code: '510322', + }, + ], + }, + { + name: '攀枝花市', + code: '510400', + children: [ + { + name: '东区', + code: '510402', + }, + { + name: '西区', + code: '510403', + }, + { + name: '仁和区', + code: '510411', + }, + { + name: '米易县', + code: '510421', + }, + { + name: '盐边县', + code: '510422', + }, + ], + }, + { + name: '泸州市', + code: '510500', + children: [ + { + name: '江阳区', + code: '510502', + }, + { + name: '纳溪区', + code: '510503', + }, + { + name: '龙马潭区', + code: '510504', + }, + { + name: '泸县', + code: '510521', + }, + { + name: '合江县', + code: '510522', + }, + { + name: '叙永县', + code: '510524', + }, + { + name: '古蔺县', + code: '510525', + }, + ], + }, + { + name: '德阳市', + code: '510600', + children: [ + { + name: '旌阳区', + code: '510603', + }, + { + name: '罗江区', + code: '510604', + }, + { + name: '中江县', + code: '510623', + }, + { + name: '广汉市', + code: '510681', + }, + { + name: '什邡市', + code: '510682', + }, + { + name: '绵竹市', + code: '510683', + }, + ], + }, + { + name: '绵阳市', + code: '510700', + children: [ + { + name: '涪城区', + code: '510703', + }, + { + name: '游仙区', + code: '510704', + }, + { + name: '安州区', + code: '510705', + }, + { + name: '三台县', + code: '510722', + }, + { + name: '盐亭县', + code: '510723', + }, + { + name: '梓潼县', + code: '510725', + }, + { + name: '北川羌族自治县', + code: '510726', + }, + { + name: '平武县', + code: '510727', + }, + { + name: '江油市', + code: '510781', + }, + ], + }, + { + name: '广元市', + code: '510800', + children: [ + { + name: '利州区', + code: '510802', + }, + { + name: '昭化区', + code: '510811', + }, + { + name: '朝天区', + code: '510812', + }, + { + name: '旺苍县', + code: '510821', + }, + { + name: '青川县', + code: '510822', + }, + { + name: '剑阁县', + code: '510823', + }, + { + name: '苍溪县', + code: '510824', + }, + ], + }, + { + name: '遂宁市', + code: '510900', + children: [ + { + name: '船山区', + code: '510903', + }, + { + name: '安居区', + code: '510904', + }, + { + name: '蓬溪县', + code: '510921', + }, + { + name: '射洪县', + code: '510922', + }, + { + name: '大英县', + code: '510923', + }, + ], + }, + { + name: '内江市', + code: '511000', + children: [ + { + name: '市中区', + code: '511002', + }, + { + name: '东兴区', + code: '511011', + }, + { + name: '威远县', + code: '511024', + }, + { + name: '资中县', + code: '511025', + }, + { + name: '隆昌市', + code: '511083', + }, + ], + }, + { + name: '乐山市', + code: '511100', + children: [ + { + name: '市中区', + code: '511102', + }, + { + name: '沙湾区', + code: '511111', + }, + { + name: '五通桥区', + code: '511112', + }, + { + name: '金口河区', + code: '511113', + }, + { + name: '犍为县', + code: '511123', + }, + { + name: '井研县', + code: '511124', + }, + { + name: '夹江县', + code: '511126', + }, + { + name: '沐川县', + code: '511129', + }, + { + name: '峨边彝族自治县', + code: '511132', + }, + { + name: '马边彝族自治县', + code: '511133', + }, + { + name: '峨眉山市', + code: '511181', + }, + ], + }, + { + name: '南充市', + code: '511300', + children: [ + { + name: '顺庆区', + code: '511302', + }, + { + name: '高坪区', + code: '511303', + }, + { + name: '嘉陵区', + code: '511304', + }, + { + name: '南部县', + code: '511321', + }, + { + name: '营山县', + code: '511322', + }, + { + name: '蓬安县', + code: '511323', + }, + { + name: '仪陇县', + code: '511324', + }, + { + name: '西充县', + code: '511325', + }, + { + name: '阆中市', + code: '511381', + }, + ], + }, + { + name: '眉山市', + code: '511400', + children: [ + { + name: '东坡区', + code: '511402', + }, + { + name: '彭山区', + code: '511403', + }, + { + name: '仁寿县', + code: '511421', + }, + { + name: '洪雅县', + code: '511423', + }, + { + name: '丹棱县', + code: '511424', + }, + { + name: '青神县', + code: '511425', + }, + ], + }, + { + name: '宜宾市', + code: '511500', + children: [ + { + name: '翠屏区', + code: '511502', + }, + { + name: '南溪区', + code: '511503', + }, + { + name: '叙州区', + code: '511504', + }, + { + name: '江安县', + code: '511523', + }, + { + name: '长宁县', + code: '511524', + }, + { + name: '高县', + code: '511525', + }, + { + name: '珙县', + code: '511526', + }, + { + name: '筠连县', + code: '511527', + }, + { + name: '兴文县', + code: '511528', + }, + { + name: '屏山县', + code: '511529', + }, + ], + }, + { + name: '广安市', + code: '511600', + children: [ + { + name: '广安区', + code: '511602', + }, + { + name: '前锋区', + code: '511603', + }, + { + name: '岳池县', + code: '511621', + }, + { + name: '武胜县', + code: '511622', + }, + { + name: '邻水县', + code: '511623', + }, + { + name: '华蓥市', + code: '511681', + }, + ], + }, + { + name: '达州市', + code: '511700', + children: [ + { + name: '通川区', + code: '511702', + }, + { + name: '达川区', + code: '511703', + }, + { + name: '宣汉县', + code: '511722', + }, + { + name: '开江县', + code: '511723', + }, + { + name: '大竹县', + code: '511724', + }, + { + name: '渠县', + code: '511725', + }, + { + name: '万源市', + code: '511781', + }, + ], + }, + { + name: '雅安市', + code: '511800', + children: [ + { + name: '雨城区', + code: '511802', + }, + { + name: '名山区', + code: '511803', + }, + { + name: '荥经县', + code: '511822', + }, + { + name: '汉源县', + code: '511823', + }, + { + name: '石棉县', + code: '511824', + }, + { + name: '天全县', + code: '511825', + }, + { + name: '芦山县', + code: '511826', + }, + { + name: '宝兴县', + code: '511827', + }, + ], + }, + { + name: '巴中市', + code: '511900', + children: [ + { + name: '巴州区', + code: '511902', + }, + { + name: '恩阳区', + code: '511903', + }, + { + name: '通江县', + code: '511921', + }, + { + name: '南江县', + code: '511922', + }, + { + name: '平昌县', + code: '511923', + }, + ], + }, + { + name: '资阳市', + code: '512000', + children: [ + { + name: '雁江区', + code: '512002', + }, + { + name: '安岳县', + code: '512021', + }, + { + name: '乐至县', + code: '512022', + }, + ], + }, + { + name: '阿坝藏族羌族自治州', + code: '513200', + children: [ + { + name: '马尔康市', + code: '513201', + }, + { + name: '汶川县', + code: '513221', + }, + { + name: '理县', + code: '513222', + }, + { + name: '茂县', + code: '513223', + }, + { + name: '松潘县', + code: '513224', + }, + { + name: '九寨沟县', + code: '513225', + }, + { + name: '金川县', + code: '513226', + }, + { + name: '小金县', + code: '513227', + }, + { + name: '黑水县', + code: '513228', + }, + { + name: '壤塘县', + code: '513230', + }, + { + name: '阿坝县', + code: '513231', + }, + { + name: '若尔盖县', + code: '513232', + }, + { + name: '红原县', + code: '513233', + }, + ], + }, + { + name: '甘孜藏族自治州', + code: '513300', + children: [ + { + name: '康定市', + code: '513301', + }, + { + name: '泸定县', + code: '513322', + }, + { + name: '丹巴县', + code: '513323', + }, + { + name: '九龙县', + code: '513324', + }, + { + name: '雅江县', + code: '513325', + }, + { + name: '道孚县', + code: '513326', + }, + { + name: '炉霍县', + code: '513327', + }, + { + name: '甘孜县', + code: '513328', + }, + { + name: '新龙县', + code: '513329', + }, + { + name: '德格县', + code: '513330', + }, + { + name: '白玉县', + code: '513331', + }, + { + name: '石渠县', + code: '513332', + }, + { + name: '色达县', + code: '513333', + }, + { + name: '理塘县', + code: '513334', + }, + { + name: '巴塘县', + code: '513335', + }, + { + name: '乡城县', + code: '513336', + }, + { + name: '稻城县', + code: '513337', + }, + { + name: '得荣县', + code: '513338', + }, + ], + }, + { + name: '凉山彝族自治州', + code: '513400', + children: [ + { + name: '西昌市', + code: '513401', + }, + { + name: '木里藏族自治县', + code: '513422', + }, + { + name: '盐源县', + code: '513423', + }, + { + name: '德昌县', + code: '513424', + }, + { + name: '会理县', + code: '513425', + }, + { + name: '会东县', + code: '513426', + }, + { + name: '宁南县', + code: '513427', + }, + { + name: '普格县', + code: '513428', + }, + { + name: '布拖县', + code: '513429', + }, + { + name: '金阳县', + code: '513430', + }, + { + name: '昭觉县', + code: '513431', + }, + { + name: '喜德县', + code: '513432', + }, + { + name: '冕宁县', + code: '513433', + }, + { + name: '越西县', + code: '513434', + }, + { + name: '甘洛县', + code: '513435', + }, + { + name: '美姑县', + code: '513436', + }, + { + name: '雷波县', + code: '513437', + }, + ], + }, + ], + }, + { + name: '贵州省', + code: '520000', + region: 'southwest', + children: [ + { + name: '贵阳市', + code: '520100', + children: [ + { + name: '南明区', + code: '520102', + }, + { + name: '云岩区', + code: '520103', + }, + { + name: '花溪区', + code: '520111', + }, + { + name: '乌当区', + code: '520112', + }, + { + name: '白云区', + code: '520113', + }, + { + name: '观山湖区', + code: '520115', + }, + { + name: '开阳县', + code: '520121', + }, + { + name: '息烽县', + code: '520122', + }, + { + name: '修文县', + code: '520123', + }, + { + name: '清镇市', + code: '520181', + }, + ], + }, + { + name: '六盘水市', + code: '520200', + children: [ + { + name: '钟山区', + code: '520201', + }, + { + name: '六枝特区', + code: '520203', + }, + { + name: '水城县', + code: '520221', + }, + { + name: '盘州市', + code: '520281', + }, + ], + }, + { + name: '遵义市', + code: '520300', + children: [ + { + name: '红花岗区', + code: '520302', + }, + { + name: '汇川区', + code: '520303', + }, + { + name: '播州区', + code: '520304', + }, + { + name: '桐梓县', + code: '520322', + }, + { + name: '绥阳县', + code: '520323', + }, + { + name: '正安县', + code: '520324', + }, + { + name: '道真仡佬族苗族自治县', + code: '520325', + }, + { + name: '务川仡佬族苗族自治县', + code: '520326', + }, + { + name: '凤冈县', + code: '520327', + }, + { + name: '湄潭县', + code: '520328', + }, + { + name: '余庆县', + code: '520329', + }, + { + name: '习水县', + code: '520330', + }, + { + name: '赤水市', + code: '520381', + }, + { + name: '仁怀市', + code: '520382', + }, + ], + }, + { + name: '安顺市', + code: '520400', + children: [ + { + name: '西秀区', + code: '520402', + }, + { + name: '平坝区', + code: '520403', + }, + { + name: '普定县', + code: '520422', + }, + { + name: '镇宁布依族苗族自治县', + code: '520423', + }, + { + name: '关岭布依族苗族自治县', + code: '520424', + }, + { + name: '紫云苗族布依族自治县', + code: '520425', + }, + ], + }, + { + name: '毕节市', + code: '520500', + children: [ + { + name: '七星关区', + code: '520502', + }, + { + name: '大方县', + code: '520521', + }, + { + name: '黔西县', + code: '520522', + }, + { + name: '金沙县', + code: '520523', + }, + { + name: '织金县', + code: '520524', + }, + { + name: '纳雍县', + code: '520525', + }, + { + name: '威宁彝族回族苗族自治县', + code: '520526', + }, + { + name: '赫章县', + code: '520527', + }, + ], + }, + { + name: '铜仁市', + code: '520600', + children: [ + { + name: '碧江区', + code: '520602', + }, + { + name: '万山区', + code: '520603', + }, + { + name: '江口县', + code: '520621', + }, + { + name: '玉屏侗族自治县', + code: '520622', + }, + { + name: '石阡县', + code: '520623', + }, + { + name: '思南县', + code: '520624', + }, + { + name: '印江土家族苗族自治县', + code: '520625', + }, + { + name: '德江县', + code: '520626', + }, + { + name: '沿河土家族自治县', + code: '520627', + }, + { + name: '松桃苗族自治县', + code: '520628', + }, + ], + }, + { + name: '黔西南布依族苗族自治州', + code: '522300', + children: [ + { + name: '兴义市', + code: '522301', + }, + { + name: '兴仁市', + code: '522302', + }, + { + name: '普安县', + code: '522323', + }, + { + name: '晴隆县', + code: '522324', + }, + { + name: '贞丰县', + code: '522325', + }, + { + name: '望谟县', + code: '522326', + }, + { + name: '册亨县', + code: '522327', + }, + { + name: '安龙县', + code: '522328', + }, + ], + }, + { + name: '黔东南苗族侗族自治州', + code: '522600', + children: [ + { + name: '凯里市', + code: '522601', + }, + { + name: '黄平县', + code: '522622', + }, + { + name: '施秉县', + code: '522623', + }, + { + name: '三穗县', + code: '522624', + }, + { + name: '镇远县', + code: '522625', + }, + { + name: '岑巩县', + code: '522626', + }, + { + name: '天柱县', + code: '522627', + }, + { + name: '锦屏县', + code: '522628', + }, + { + name: '剑河县', + code: '522629', + }, + { + name: '台江县', + code: '522630', + }, + { + name: '黎平县', + code: '522631', + }, + { + name: '榕江县', + code: '522632', + }, + { + name: '从江县', + code: '522633', + }, + { + name: '雷山县', + code: '522634', + }, + { + name: '麻江县', + code: '522635', + }, + { + name: '丹寨县', + code: '522636', + }, + ], + }, + { + name: '黔南布依族苗族自治州', + code: '522700', + children: [ + { + name: '都匀市', + code: '522701', + }, + { + name: '福泉市', + code: '522702', + }, + { + name: '荔波县', + code: '522722', + }, + { + name: '贵定县', + code: '522723', + }, + { + name: '瓮安县', + code: '522725', + }, + { + name: '独山县', + code: '522726', + }, + { + name: '平塘县', + code: '522727', + }, + { + name: '罗甸县', + code: '522728', + }, + { + name: '长顺县', + code: '522729', + }, + { + name: '龙里县', + code: '522730', + }, + { + name: '惠水县', + code: '522731', + }, + { + name: '三都水族自治县', + code: '522732', + }, + ], + }, + ], + }, + { + name: '云南省', + code: '530000', + region: 'southwest', + children: [ + { + name: '昆明市', + code: '530100', + children: [ + { + name: '五华区', + code: '530102', + }, + { + name: '盘龙区', + code: '530103', + }, + { + name: '官渡区', + code: '530111', + }, + { + name: '西山区', + code: '530112', + }, + { + name: '东川区', + code: '530113', + }, + { + name: '呈贡区', + code: '530114', + }, + { + name: '晋宁区', + code: '530115', + }, + { + name: '富民县', + code: '530124', + }, + { + name: '宜良县', + code: '530125', + }, + { + name: '石林彝族自治县', + code: '530126', + }, + { + name: '嵩明县', + code: '530127', + }, + { + name: '禄劝彝族苗族自治县', + code: '530128', + }, + { + name: '寻甸回族彝族自治县', + code: '530129', + }, + { + name: '安宁市', + code: '530181', + }, + ], + }, + { + name: '曲靖市', + code: '530300', + children: [ + { + name: '麒麟区', + code: '530302', + }, + { + name: '沾益区', + code: '530303', + }, + { + name: '马龙区', + code: '530304', + }, + { + name: '陆良县', + code: '530322', + }, + { + name: '师宗县', + code: '530323', + }, + { + name: '罗平县', + code: '530324', + }, + { + name: '富源县', + code: '530325', + }, + { + name: '会泽县', + code: '530326', + }, + { + name: '宣威市', + code: '530381', + }, + ], + }, + { + name: '玉溪市', + code: '530400', + children: [ + { + name: '红塔区', + code: '530402', + }, + { + name: '江川区', + code: '530403', + }, + { + name: '澄江县', + code: '530422', + }, + { + name: '通海县', + code: '530423', + }, + { + name: '华宁县', + code: '530424', + }, + { + name: '易门县', + code: '530425', + }, + { + name: '峨山彝族自治县', + code: '530426', + }, + { + name: '新平彝族傣族自治县', + code: '530427', + }, + { + name: '元江哈尼族彝族傣族自治县', + code: '530428', + }, + ], + }, + { + name: '保山市', + code: '530500', + children: [ + { + name: '隆阳区', + code: '530502', + }, + { + name: '施甸县', + code: '530521', + }, + { + name: '龙陵县', + code: '530523', + }, + { + name: '昌宁县', + code: '530524', + }, + { + name: '腾冲市', + code: '530581', + }, + ], + }, + { + name: '昭通市', + code: '530600', + children: [ + { + name: '昭阳区', + code: '530602', + }, + { + name: '鲁甸县', + code: '530621', + }, + { + name: '巧家县', + code: '530622', + }, + { + name: '盐津县', + code: '530623', + }, + { + name: '大关县', + code: '530624', + }, + { + name: '永善县', + code: '530625', + }, + { + name: '绥江县', + code: '530626', + }, + { + name: '镇雄县', + code: '530627', + }, + { + name: '彝良县', + code: '530628', + }, + { + name: '威信县', + code: '530629', + }, + { + name: '水富市', + code: '530681', + }, + ], + }, + { + name: '丽江市', + code: '530700', + children: [ + { + name: '古城区', + code: '530702', + }, + { + name: '玉龙纳西族自治县', + code: '530721', + }, + { + name: '永胜县', + code: '530722', + }, + { + name: '华坪县', + code: '530723', + }, + { + name: '宁蒗彝族自治县', + code: '530724', + }, + ], + }, + { + name: '普洱市', + code: '530800', + children: [ + { + name: '思茅区', + code: '530802', + }, + { + name: '宁洱哈尼族彝族自治县', + code: '530821', + }, + { + name: '墨江哈尼族自治县', + code: '530822', + }, + { + name: '景东彝族自治县', + code: '530823', + }, + { + name: '景谷傣族彝族自治县', + code: '530824', + }, + { + name: '镇沅彝族哈尼族拉祜族自治县', + code: '530825', + }, + { + name: '江城哈尼族彝族自治县', + code: '530826', + }, + { + name: '孟连傣族拉祜族佤族自治县', + code: '530827', + }, + { + name: '澜沧拉祜族自治县', + code: '530828', + }, + { + name: '西盟佤族自治县', + code: '530829', + }, + ], + }, + { + name: '临沧市', + code: '530900', + children: [ + { + name: '临翔区', + code: '530902', + }, + { + name: '凤庆县', + code: '530921', + }, + { + name: '云县', + code: '530922', + }, + { + name: '永德县', + code: '530923', + }, + { + name: '镇康县', + code: '530924', + }, + { + name: '双江拉祜族佤族布朗族傣族自治县', + code: '530925', + }, + { + name: '耿马傣族佤族自治县', + code: '530926', + }, + { + name: '沧源佤族自治县', + code: '530927', + }, + ], + }, + { + name: '楚雄彝族自治州', + code: '532300', + children: [ + { + name: '楚雄市', + code: '532301', + }, + { + name: '双柏县', + code: '532322', + }, + { + name: '牟定县', + code: '532323', + }, + { + name: '南华县', + code: '532324', + }, + { + name: '姚安县', + code: '532325', + }, + { + name: '大姚县', + code: '532326', + }, + { + name: '永仁县', + code: '532327', + }, + { + name: '元谋县', + code: '532328', + }, + { + name: '武定县', + code: '532329', + }, + { + name: '禄丰县', + code: '532331', + }, + ], + }, + { + name: '红河哈尼族彝族自治州', + code: '532500', + children: [ + { + name: '个旧市', + code: '532501', + }, + { + name: '开远市', + code: '532502', + }, + { + name: '蒙自市', + code: '532503', + }, + { + name: '弥勒市', + code: '532504', + }, + { + name: '屏边苗族自治县', + code: '532523', + }, + { + name: '建水县', + code: '532524', + }, + { + name: '石屏县', + code: '532525', + }, + { + name: '泸西县', + code: '532527', + }, + { + name: '元阳县', + code: '532528', + }, + { + name: '红河县', + code: '532529', + }, + { + name: '金平苗族瑶族傣族自治县', + code: '532530', + }, + { + name: '绿春县', + code: '532531', + }, + { + name: '河口瑶族自治县', + code: '532532', + }, + ], + }, + { + name: '文山壮族苗族自治州', + code: '532600', + children: [ + { + name: '文山市', + code: '532601', + }, + { + name: '砚山县', + code: '532622', + }, + { + name: '西畴县', + code: '532623', + }, + { + name: '麻栗坡县', + code: '532624', + }, + { + name: '马关县', + code: '532625', + }, + { + name: '丘北县', + code: '532626', + }, + { + name: '广南县', + code: '532627', + }, + { + name: '富宁县', + code: '532628', + }, + ], + }, + { + name: '西双版纳傣族自治州', + code: '532800', + children: [ + { + name: '景洪市', + code: '532801', + }, + { + name: '勐海县', + code: '532822', + }, + { + name: '勐腊县', + code: '532823', + }, + ], + }, + { + name: '大理白族自治州', + code: '532900', + children: [ + { + name: '大理市', + code: '532901', + }, + { + name: '漾濞彝族自治县', + code: '532922', + }, + { + name: '祥云县', + code: '532923', + }, + { + name: '宾川县', + code: '532924', + }, + { + name: '弥渡县', + code: '532925', + }, + { + name: '南涧彝族自治县', + code: '532926', + }, + { + name: '巍山彝族回族自治县', + code: '532927', + }, + { + name: '永平县', + code: '532928', + }, + { + name: '云龙县', + code: '532929', + }, + { + name: '洱源县', + code: '532930', + }, + { + name: '剑川县', + code: '532931', + }, + { + name: '鹤庆县', + code: '532932', + }, + ], + }, + { + name: '德宏傣族景颇族自治州', + code: '533100', + children: [ + { + name: '瑞丽市', + code: '533102', + }, + { + name: '芒市', + code: '533103', + }, + { + name: '梁河县', + code: '533122', + }, + { + name: '盈江县', + code: '533123', + }, + { + name: '陇川县', + code: '533124', + }, + ], + }, + { + name: '怒江傈僳族自治州', + code: '533300', + children: [ + { + name: '泸水市', + code: '533301', + }, + { + name: '福贡县', + code: '533323', + }, + { + name: '贡山独龙族怒族自治县', + code: '533324', + }, + { + name: '兰坪白族普米族自治县', + code: '533325', + }, + ], + }, + { + name: '迪庆藏族自治州', + code: '533400', + children: [ + { + name: '香格里拉市', + code: '533401', + }, + { + name: '德钦县', + code: '533422', + }, + { + name: '维西傈僳族自治县', + code: '533423', + }, + ], + }, + ], + }, + { + name: '西藏自治区', + code: '540000', + region: 'southwest', + autonomousRegion: true, + children: [ + { + name: '拉萨市', + code: '540100', + children: [ + { + name: '城关区', + code: '540102', + }, + { + name: '堆龙德庆区', + code: '540103', + }, + { + name: '达孜区', + code: '540104', + }, + { + name: '林周县', + code: '540121', + }, + { + name: '当雄县', + code: '540122', + }, + { + name: '尼木县', + code: '540123', + }, + { + name: '曲水县', + code: '540124', + }, + { + name: '墨竹工卡县', + code: '540127', + }, + ], + }, + { + name: '日喀则市', + code: '540200', + children: [ + { + name: '桑珠孜区', + code: '540202', + }, + { + name: '南木林县', + code: '540221', + }, + { + name: '江孜县', + code: '540222', + }, + { + name: '定日县', + code: '540223', + }, + { + name: '萨迦县', + code: '540224', + }, + { + name: '拉孜县', + code: '540225', + }, + { + name: '昂仁县', + code: '540226', + }, + { + name: '谢通门县', + code: '540227', + }, + { + name: '白朗县', + code: '540228', + }, + { + name: '仁布县', + code: '540229', + }, + { + name: '康马县', + code: '540230', + }, + { + name: '定结县', + code: '540231', + }, + { + name: '仲巴县', + code: '540232', + }, + { + name: '亚东县', + code: '540233', + }, + { + name: '吉隆县', + code: '540234', + }, + { + name: '聂拉木县', + code: '540235', + }, + { + name: '萨嘎县', + code: '540236', + }, + { + name: '岗巴县', + code: '540237', + }, + ], + }, + { + name: '昌都市', + code: '540300', + children: [ + { + name: '卡若区', + code: '540302', + }, + { + name: '江达县', + code: '540321', + }, + { + name: '贡觉县', + code: '540322', + }, + { + name: '类乌齐县', + code: '540323', + }, + { + name: '丁青县', + code: '540324', + }, + { + name: '察雅县', + code: '540325', + }, + { + name: '八宿县', + code: '540326', + }, + { + name: '左贡县', + code: '540327', + }, + { + name: '芒康县', + code: '540328', + }, + { + name: '洛隆县', + code: '540329', + }, + { + name: '边坝县', + code: '540330', + }, + ], + }, + { + name: '林芝市', + code: '540400', + children: [ + { + name: '巴宜区', + code: '540402', + }, + { + name: '工布江达县', + code: '540421', + }, + { + name: '米林县', + code: '540422', + }, + { + name: '墨脱县', + code: '540423', + }, + { + name: '波密县', + code: '540424', + }, + { + name: '察隅县', + code: '540425', + }, + { + name: '朗县', + code: '540426', + }, + ], + }, + { + name: '山南市', + code: '540500', + children: [ + { + name: '乃东区', + code: '540502', + }, + { + name: '扎囊县', + code: '540521', + }, + { + name: '贡嘎县', + code: '540522', + }, + { + name: '桑日县', + code: '540523', + }, + { + name: '琼结县', + code: '540524', + }, + { + name: '曲松县', + code: '540525', + }, + { + name: '措美县', + code: '540526', + }, + { + name: '洛扎县', + code: '540527', + }, + { + name: '加查县', + code: '540528', + }, + { + name: '隆子县', + code: '540529', + }, + { + name: '错那县', + code: '540530', + }, + { + name: '浪卡子县', + code: '540531', + }, + ], + }, + { + name: '那曲市', + code: '540600', + children: [ + { + name: '色尼区', + code: '540602', + }, + { + name: '嘉黎县', + code: '540621', + }, + { + name: '比如县', + code: '540622', + }, + { + name: '聂荣县', + code: '540623', + }, + { + name: '安多县', + code: '540624', + }, + { + name: '申扎县', + code: '540625', + }, + { + name: '索县', + code: '540626', + }, + { + name: '班戈县', + code: '540627', + }, + { + name: '巴青县', + code: '540628', + }, + { + name: '尼玛县', + code: '540629', + }, + { + name: '双湖县', + code: '540630', + }, + ], + }, + { + name: '阿里地区', + code: '542500', + children: [ + { + name: '普兰县', + code: '542521', + }, + { + name: '札达县', + code: '542522', + }, + { + name: '噶尔县', + code: '542523', + }, + { + name: '日土县', + code: '542524', + }, + { + name: '革吉县', + code: '542525', + }, + { + name: '改则县', + code: '542526', + }, + { + name: '措勤县', + code: '542527', + }, + ], + }, + ], + }, + { + name: '陕西省', + code: '610000', + region: 'northwest', + children: [ + { + name: '西安市', + code: '610100', + children: [ + { + name: '新城区', + code: '610102', + }, + { + name: '碑林区', + code: '610103', + }, + { + name: '莲湖区', + code: '610104', + }, + { + name: '灞桥区', + code: '610111', + }, + { + name: '未央区', + code: '610112', + }, + { + name: '雁塔区', + code: '610113', + }, + { + name: '阎良区', + code: '610114', + }, + { + name: '临潼区', + code: '610115', + }, + { + name: '长安区', + code: '610116', + }, + { + name: '高陵区', + code: '610117', + }, + { + name: '鄠邑区', + code: '610118', + }, + { + name: '蓝田县', + code: '610122', + }, + { + name: '周至县', + code: '610124', + }, + ], + }, + { + name: '铜川市', + code: '610200', + children: [ + { + name: '王益区', + code: '610202', + }, + { + name: '印台区', + code: '610203', + }, + { + name: '耀州区', + code: '610204', + }, + { + name: '宜君县', + code: '610222', + }, + ], + }, + { + name: '宝鸡市', + code: '610300', + children: [ + { + name: '渭滨区', + code: '610302', + }, + { + name: '金台区', + code: '610303', + }, + { + name: '陈仓区', + code: '610304', + }, + { + name: '凤翔县', + code: '610322', + }, + { + name: '岐山县', + code: '610323', + }, + { + name: '扶风县', + code: '610324', + }, + { + name: '眉县', + code: '610326', + }, + { + name: '陇县', + code: '610327', + }, + { + name: '千阳县', + code: '610328', + }, + { + name: '麟游县', + code: '610329', + }, + { + name: '凤县', + code: '610330', + }, + { + name: '太白县', + code: '610331', + }, + ], + }, + { + name: '咸阳市', + code: '610400', + children: [ + { + name: '秦都区', + code: '610402', + }, + { + name: '杨陵区', + code: '610403', + }, + { + name: '渭城区', + code: '610404', + }, + { + name: '三原县', + code: '610422', + }, + { + name: '泾阳县', + code: '610423', + }, + { + name: '乾县', + code: '610424', + }, + { + name: '礼泉县', + code: '610425', + }, + { + name: '永寿县', + code: '610426', + }, + { + name: '长武县', + code: '610428', + }, + { + name: '旬邑县', + code: '610429', + }, + { + name: '淳化县', + code: '610430', + }, + { + name: '武功县', + code: '610431', + }, + { + name: '兴平市', + code: '610481', + }, + { + name: '彬州市', + code: '610482', + }, + ], + }, + { + name: '渭南市', + code: '610500', + children: [ + { + name: '临渭区', + code: '610502', + }, + { + name: '华州区', + code: '610503', + }, + { + name: '潼关县', + code: '610522', + }, + { + name: '大荔县', + code: '610523', + }, + { + name: '合阳县', + code: '610524', + }, + { + name: '澄城县', + code: '610525', + }, + { + name: '蒲城县', + code: '610526', + }, + { + name: '白水县', + code: '610527', + }, + { + name: '富平县', + code: '610528', + }, + { + name: '韩城市', + code: '610581', + }, + { + name: '华阴市', + code: '610582', + }, + ], + }, + { + name: '延安市', + code: '610600', + children: [ + { + name: '宝塔区', + code: '610602', + }, + { + name: '安塞区', + code: '610603', + }, + { + name: '延长县', + code: '610621', + }, + { + name: '延川县', + code: '610622', + }, + { + name: '子长县', + code: '610623', + }, + { + name: '志丹县', + code: '610625', + }, + { + name: '吴起县', + code: '610626', + }, + { + name: '甘泉县', + code: '610627', + }, + { + name: '富县', + code: '610628', + }, + { + name: '洛川县', + code: '610629', + }, + { + name: '宜川县', + code: '610630', + }, + { + name: '黄龙县', + code: '610631', + }, + { + name: '黄陵县', + code: '610632', + }, + ], + }, + { + name: '汉中市', + code: '610700', + children: [ + { + name: '汉台区', + code: '610702', + }, + { + name: '南郑区', + code: '610703', + }, + { + name: '城固县', + code: '610722', + }, + { + name: '洋县', + code: '610723', + }, + { + name: '西乡县', + code: '610724', + }, + { + name: '勉县', + code: '610725', + }, + { + name: '宁强县', + code: '610726', + }, + { + name: '略阳县', + code: '610727', + }, + { + name: '镇巴县', + code: '610728', + }, + { + name: '留坝县', + code: '610729', + }, + { + name: '佛坪县', + code: '610730', + }, + ], + }, + { + name: '榆林市', + code: '610800', + children: [ + { + name: '榆阳区', + code: '610802', + }, + { + name: '横山区', + code: '610803', + }, + { + name: '府谷县', + code: '610822', + }, + { + name: '靖边县', + code: '610824', + }, + { + name: '定边县', + code: '610825', + }, + { + name: '绥德县', + code: '610826', + }, + { + name: '米脂县', + code: '610827', + }, + { + name: '佳县', + code: '610828', + }, + { + name: '吴堡县', + code: '610829', + }, + { + name: '清涧县', + code: '610830', + }, + { + name: '子洲县', + code: '610831', + }, + { + name: '神木市', + code: '610881', + }, + ], + }, + { + name: '安康市', + code: '610900', + children: [ + { + name: '汉滨区', + code: '610902', + }, + { + name: '汉阴县', + code: '610921', + }, + { + name: '石泉县', + code: '610922', + }, + { + name: '宁陕县', + code: '610923', + }, + { + name: '紫阳县', + code: '610924', + }, + { + name: '岚皋县', + code: '610925', + }, + { + name: '平利县', + code: '610926', + }, + { + name: '镇坪县', + code: '610927', + }, + { + name: '旬阳县', + code: '610928', + }, + { + name: '白河县', + code: '610929', + }, + ], + }, + { + name: '商洛市', + code: '611000', + children: [ + { + name: '商州区', + code: '611002', + }, + { + name: '洛南县', + code: '611021', + }, + { + name: '丹凤县', + code: '611022', + }, + { + name: '商南县', + code: '611023', + }, + { + name: '山阳县', + code: '611024', + }, + { + name: '镇安县', + code: '611025', + }, + { + name: '柞水县', + code: '611026', + }, + ], + }, + ], + }, + { + name: '甘肃省', + code: '620000', + region: 'northwest', + children: [ + { + name: '兰州市', + code: '620100', + children: [ + { + name: '城关区', + code: '620102', + }, + { + name: '七里河区', + code: '620103', + }, + { + name: '西固区', + code: '620104', + }, + { + name: '安宁区', + code: '620105', + }, + { + name: '红古区', + code: '620111', + }, + { + name: '永登县', + code: '620121', + }, + { + name: '皋兰县', + code: '620122', + }, + { + name: '榆中县', + code: '620123', + }, + ], + }, + { + name: '嘉峪关市', + code: '620200', + children: [], + }, + { + name: '金昌市', + code: '620300', + children: [ + { + name: '金川区', + code: '620302', + }, + { + name: '永昌县', + code: '620321', + }, + ], + }, + { + name: '白银市', + code: '620400', + children: [ + { + name: '白银区', + code: '620402', + }, + { + name: '平川区', + code: '620403', + }, + { + name: '靖远县', + code: '620421', + }, + { + name: '会宁县', + code: '620422', + }, + { + name: '景泰县', + code: '620423', + }, + ], + }, + { + name: '天水市', + code: '620500', + children: [ + { + name: '秦州区', + code: '620502', + }, + { + name: '麦积区', + code: '620503', + }, + { + name: '清水县', + code: '620521', + }, + { + name: '秦安县', + code: '620522', + }, + { + name: '甘谷县', + code: '620523', + }, + { + name: '武山县', + code: '620524', + }, + { + name: '张家川回族自治县', + code: '620525', + }, + ], + }, + { + name: '武威市', + code: '620600', + children: [ + { + name: '凉州区', + code: '620602', + }, + { + name: '民勤县', + code: '620621', + }, + { + name: '古浪县', + code: '620622', + }, + { + name: '天祝藏族自治县', + code: '620623', + }, + ], + }, + { + name: '张掖市', + code: '620700', + children: [ + { + name: '甘州区', + code: '620702', + }, + { + name: '肃南裕固族自治县', + code: '620721', + }, + { + name: '民乐县', + code: '620722', + }, + { + name: '临泽县', + code: '620723', + }, + { + name: '高台县', + code: '620724', + }, + { + name: '山丹县', + code: '620725', + }, + ], + }, + { + name: '平凉市', + code: '620800', + children: [ + { + name: '崆峒区', + code: '620802', + }, + { + name: '泾川县', + code: '620821', + }, + { + name: '灵台县', + code: '620822', + }, + { + name: '崇信县', + code: '620823', + }, + { + name: '庄浪县', + code: '620825', + }, + { + name: '静宁县', + code: '620826', + }, + { + name: '华亭市', + code: '620881', + }, + ], + }, + { + name: '酒泉市', + code: '620900', + children: [ + { + name: '肃州区', + code: '620902', + }, + { + name: '金塔县', + code: '620921', + }, + { + name: '瓜州县', + code: '620922', + }, + { + name: '肃北蒙古族自治县', + code: '620923', + }, + { + name: '阿克塞哈萨克族自治县', + code: '620924', + }, + { + name: '玉门市', + code: '620981', + }, + { + name: '敦煌市', + code: '620982', + }, + ], + }, + { + name: '庆阳市', + code: '621000', + children: [ + { + name: '西峰区', + code: '621002', + }, + { + name: '庆城县', + code: '621021', + }, + { + name: '环县', + code: '621022', + }, + { + name: '华池县', + code: '621023', + }, + { + name: '合水县', + code: '621024', + }, + { + name: '正宁县', + code: '621025', + }, + { + name: '宁县', + code: '621026', + }, + { + name: '镇原县', + code: '621027', + }, + ], + }, + { + name: '定西市', + code: '621100', + children: [ + { + name: '安定区', + code: '621102', + }, + { + name: '通渭县', + code: '621121', + }, + { + name: '陇西县', + code: '621122', + }, + { + name: '渭源县', + code: '621123', + }, + { + name: '临洮县', + code: '621124', + }, + { + name: '漳县', + code: '621125', + }, + { + name: '岷县', + code: '621126', + }, + ], + }, + { + name: '陇南市', + code: '621200', + children: [ + { + name: '武都区', + code: '621202', + }, + { + name: '成县', + code: '621221', + }, + { + name: '文县', + code: '621222', + }, + { + name: '宕昌县', + code: '621223', + }, + { + name: '康县', + code: '621224', + }, + { + name: '西和县', + code: '621225', + }, + { + name: '礼县', + code: '621226', + }, + { + name: '徽县', + code: '621227', + }, + { + name: '两当县', + code: '621228', + }, + ], + }, + { + name: '临夏回族自治州', + code: '622900', + children: [ + { + name: '临夏市', + code: '622901', + }, + { + name: '临夏县', + code: '622921', + }, + { + name: '康乐县', + code: '622922', + }, + { + name: '永靖县', + code: '622923', + }, + { + name: '广河县', + code: '622924', + }, + { + name: '和政县', + code: '622925', + }, + { + name: '东乡族自治县', + code: '622926', + }, + { + name: '积石山保安族东乡族撒拉族自治县', + code: '622927', + }, + ], + }, + { + name: '甘南藏族自治州', + code: '623000', + children: [ + { + name: '合作市', + code: '623001', + }, + { + name: '临潭县', + code: '623021', + }, + { + name: '卓尼县', + code: '623022', + }, + { + name: '舟曲县', + code: '623023', + }, + { + name: '迭部县', + code: '623024', + }, + { + name: '玛曲县', + code: '623025', + }, + { + name: '碌曲县', + code: '623026', + }, + { + name: '夏河县', + code: '623027', + }, + ], + }, + ], + }, + { + name: '青海省', + code: '630000', + region: 'northwest', + children: [ + { + name: '西宁市', + code: '630100', + children: [ + { + name: '城东区', + code: '630102', + }, + { + name: '城中区', + code: '630103', + }, + { + name: '城西区', + code: '630104', + }, + { + name: '城北区', + code: '630105', + }, + { + name: '大通回族土族自治县', + code: '630121', + }, + { + name: '湟中县', + code: '630122', + }, + { + name: '湟源县', + code: '630123', + }, + ], + }, + { + name: '海东市', + code: '630200', + children: [ + { + name: '乐都区', + code: '630202', + }, + { + name: '平安区', + code: '630203', + }, + { + name: '民和回族土族自治县', + code: '630222', + }, + { + name: '互助土族自治县', + code: '630223', + }, + { + name: '化隆回族自治县', + code: '630224', + }, + { + name: '循化撒拉族自治县', + code: '630225', + }, + ], + }, + { + name: '海北藏族自治州', + code: '632200', + children: [ + { + name: '门源回族自治县', + code: '632221', + }, + { + name: '祁连县', + code: '632222', + }, + { + name: '海晏县', + code: '632223', + }, + { + name: '刚察县', + code: '632224', + }, + ], + }, + { + name: '黄南藏族自治州', + code: '632300', + children: [ + { + name: '同仁县', + code: '632321', + }, + { + name: '尖扎县', + code: '632322', + }, + { + name: '泽库县', + code: '632323', + }, + { + name: '河南蒙古族自治县', + code: '632324', + }, + ], + }, + { + name: '海南藏族自治州', + code: '632500', + children: [ + { + name: '共和县', + code: '632521', + }, + { + name: '同德县', + code: '632522', + }, + { + name: '贵德县', + code: '632523', + }, + { + name: '兴海县', + code: '632524', + }, + { + name: '贵南县', + code: '632525', + }, + ], + }, + { + name: '果洛藏族自治州', + code: '632600', + children: [ + { + name: '玛沁县', + code: '632621', + }, + { + name: '班玛县', + code: '632622', + }, + { + name: '甘德县', + code: '632623', + }, + { + name: '达日县', + code: '632624', + }, + { + name: '久治县', + code: '632625', + }, + { + name: '玛多县', + code: '632626', + }, + ], + }, + { + name: '玉树藏族自治州', + code: '632700', + children: [ + { + name: '玉树市', + code: '632701', + }, + { + name: '杂多县', + code: '632722', + }, + { + name: '称多县', + code: '632723', + }, + { + name: '治多县', + code: '632724', + }, + { + name: '囊谦县', + code: '632725', + }, + { + name: '曲麻莱县', + code: '632726', + }, + ], + }, + { + name: '海西蒙古族藏族自治州', + code: '632800', + children: [ + { + name: '格尔木市', + code: '632801', + }, + { + name: '德令哈市', + code: '632802', + }, + { + name: '茫崖市', + code: '632803', + }, + { + name: '乌兰县', + code: '632821', + }, + { + name: '都兰县', + code: '632822', + }, + { + name: '天峻县', + code: '632823', + }, + ], + }, + ], + }, + { + name: '宁夏回族自治区', + code: '640000', + region: 'northwest', + autonomousRegion: true, + children: [ + { + name: '银川市', + code: '640100', + children: [ + { + name: '兴庆区', + code: '640104', + }, + { + name: '西夏区', + code: '640105', + }, + { + name: '金凤区', + code: '640106', + }, + { + name: '永宁县', + code: '640121', + }, + { + name: '贺兰县', + code: '640122', + }, + { + name: '灵武市', + code: '640181', + }, + ], + }, + { + name: '石嘴山市', + code: '640200', + children: [ + { + name: '大武口区', + code: '640202', + }, + { + name: '惠农区', + code: '640205', + }, + { + name: '平罗县', + code: '640221', + }, + ], + }, + { + name: '吴忠市', + code: '640300', + children: [ + { + name: '利通区', + code: '640302', + }, + { + name: '红寺堡区', + code: '640303', + }, + { + name: '盐池县', + code: '640323', + }, + { + name: '同心县', + code: '640324', + }, + { + name: '青铜峡市', + code: '640381', + }, + ], + }, + { + name: '固原市', + code: '640400', + children: [ + { + name: '原州区', + code: '640402', + }, + { + name: '西吉县', + code: '640422', + }, + { + name: '隆德县', + code: '640423', + }, + { + name: '泾源县', + code: '640424', + }, + { + name: '彭阳县', + code: '640425', + }, + ], + }, + { + name: '中卫市', + code: '640500', + children: [ + { + name: '沙坡头区', + code: '640502', + }, + { + name: '中宁县', + code: '640521', + }, + { + name: '海原县', + code: '640522', + }, + ], + }, + ], + }, + { + name: '新疆维吾尔自治区', + code: '650000', + region: 'northwest', + autonomousRegion: true, + children: [ + { + name: '乌鲁木齐市', + code: '650100', + children: [ + { + name: '天山区', + code: '650102', + }, + { + name: '沙依巴克区', + code: '650103', + }, + { + name: '新市区', + code: '650104', + }, + { + name: '水磨沟区', + code: '650105', + }, + { + name: '头屯河区', + code: '650106', + }, + { + name: '达坂城区', + code: '650107', + }, + { + name: '米东区', + code: '650109', + }, + { + name: '乌鲁木齐县', + code: '650121', + }, + ], + }, + { + name: '克拉玛依市', + code: '650200', + children: [ + { + name: '独山子区', + code: '650202', + }, + { + name: '克拉玛依区', + code: '650203', + }, + { + name: '白碱滩区', + code: '650204', + }, + { + name: '乌尔禾区', + code: '650205', + }, + ], + }, + { + name: '吐鲁番市', + code: '650400', + children: [ + { + name: '高昌区', + code: '650402', + }, + { + name: '鄯善县', + code: '650421', + }, + { + name: '托克逊县', + code: '650422', + }, + ], + }, + { + name: '哈密市', + code: '650500', + children: [ + { + name: '伊州区', + code: '650502', + }, + { + name: '巴里坤哈萨克自治县', + code: '650521', + }, + { + name: '伊吾县', + code: '650522', + }, + ], + }, + { + name: '昌吉回族自治州', + code: '652300', + children: [ + { + name: '昌吉市', + code: '652301', + }, + { + name: '阜康市', + code: '652302', + }, + { + name: '呼图壁县', + code: '652323', + }, + { + name: '玛纳斯县', + code: '652324', + }, + { + name: '奇台县', + code: '652325', + }, + { + name: '吉木萨尔县', + code: '652327', + }, + { + name: '木垒哈萨克自治县', + code: '652328', + }, + ], + }, + { + name: '博尔塔拉蒙古自治州', + code: '652700', + children: [ + { + name: '博乐市', + code: '652701', + }, + { + name: '阿拉山口市', + code: '652702', + }, + { + name: '精河县', + code: '652722', + }, + { + name: '温泉县', + code: '652723', + }, + ], + }, + { + name: '巴音郭楞蒙古自治州', + code: '652800', + children: [ + { + name: '库尔勒市', + code: '652801', + }, + { + name: '轮台县', + code: '652822', + }, + { + name: '尉犁县', + code: '652823', + }, + { + name: '若羌县', + code: '652824', + }, + { + name: '且末县', + code: '652825', + }, + { + name: '焉耆回族自治县', + code: '652826', + }, + { + name: '和静县', + code: '652827', + }, + { + name: '和硕县', + code: '652828', + }, + { + name: '博湖县', + code: '652829', + }, + ], + }, + { + name: '阿克苏地区', + code: '652900', + children: [ + { + name: '阿克苏市', + code: '652901', + }, + { + name: '温宿县', + code: '652922', + }, + { + name: '库车县', + code: '652923', + }, + { + name: '沙雅县', + code: '652924', + }, + { + name: '新和县', + code: '652925', + }, + { + name: '拜城县', + code: '652926', + }, + { + name: '乌什县', + code: '652927', + }, + { + name: '阿瓦提县', + code: '652928', + }, + { + name: '柯坪县', + code: '652929', + }, + ], + }, + { + name: '克孜勒苏柯尔克孜自治州', + code: '653000', + children: [ + { + name: '阿图什市', + code: '653001', + }, + { + name: '阿克陶县', + code: '653022', + }, + { + name: '阿合奇县', + code: '653023', + }, + { + name: '乌恰县', + code: '653024', + }, + ], + }, + { + name: '喀什地区', + code: '653100', + children: [ + { + name: '喀什市', + code: '653101', + }, + { + name: '疏附县', + code: '653121', + }, + { + name: '疏勒县', + code: '653122', + }, + { + name: '英吉沙县', + code: '653123', + }, + { + name: '泽普县', + code: '653124', + }, + { + name: '莎车县', + code: '653125', + }, + { + name: '叶城县', + code: '653126', + }, + { + name: '麦盖提县', + code: '653127', + }, + { + name: '岳普湖县', + code: '653128', + }, + { + name: '伽师县', + code: '653129', + }, + { + name: '巴楚县', + code: '653130', + }, + { + name: '塔什库尔干塔吉克自治县', + code: '653131', + }, + ], + }, + { + name: '和田地区', + code: '653200', + children: [ + { + name: '和田市', + code: '653201', + }, + { + name: '和田县', + code: '653221', + }, + { + name: '墨玉县', + code: '653222', + }, + { + name: '皮山县', + code: '653223', + }, + { + name: '洛浦县', + code: '653224', + }, + { + name: '策勒县', + code: '653225', + }, + { + name: '于田县', + code: '653226', + }, + { + name: '民丰县', + code: '653227', + }, + ], + }, + { + name: '伊犁哈萨克自治州', + code: '654000', + children: [ + { + name: '伊宁市', + code: '654002', + }, + { + name: '奎屯市', + code: '654003', + }, + { + name: '霍尔果斯市', + code: '654004', + }, + { + name: '伊宁县', + code: '654021', + }, + { + name: '察布查尔锡伯自治县', + code: '654022', + }, + { + name: '霍城县', + code: '654023', + }, + { + name: '巩留县', + code: '654024', + }, + { + name: '新源县', + code: '654025', + }, + { + name: '昭苏县', + code: '654026', + }, + { + name: '特克斯县', + code: '654027', + }, + { + name: '尼勒克县', + code: '654028', + }, + ], + }, + { + name: '塔城地区', + code: '654200', + children: [ + { + name: '塔城市', + code: '654201', + }, + { + name: '乌苏市', + code: '654202', + }, + { + name: '额敏县', + code: '654221', + }, + { + name: '沙湾县', + code: '654223', + }, + { + name: '托里县', + code: '654224', + }, + { + name: '裕民县', + code: '654225', + }, + { + name: '和布克赛尔蒙古自治县', + code: '654226', + }, + ], + }, + { + name: '阿勒泰地区', + code: '654300', + children: [ + { + name: '阿勒泰市', + code: '654301', + }, + { + name: '布尔津县', + code: '654321', + }, + { + name: '富蕴县', + code: '654322', + }, + { + name: '福海县', + code: '654323', + }, + { + name: '哈巴河县', + code: '654324', + }, + { + name: '青河县', + code: '654325', + }, + { + name: '吉木乃县', + code: '654326', + }, + ], + }, + { + name: '直辖县', + code: '659000', + children: [ + { + name: '石河子市', + code: '659001', + }, + { + name: '阿拉尔市', + code: '659002', + }, + { + name: '图木舒克市', + code: '659003', + }, + { + name: '五家渠市', + code: '659004', + }, + { + name: '北屯市', + code: '659005', + }, + { + name: '铁门关市', + code: '659006', + }, + { + name: '双河市', + code: '659007', + }, + { + name: '可克达拉市', + code: '659008', + }, + { + name: '昆玉市', + code: '659009', + }, + ], + }, + ], + }, +] + +module.exports = [ + { + url: '/area/getList', + type: 'get', + response: () => { + return { + code: 200, + msg: 'success', + data: { list }, + } + }, + }, +] diff --git a/mock/controller/defaultIcon.js b/mock/controller/defaultIcon.js new file mode 100644 index 0000000..883c2b6 --- /dev/null +++ b/mock/controller/defaultIcon.js @@ -0,0 +1,2296 @@ +const List = [ + '24-hours-fill', + '24-hours-line', + '4k-fill', + '4k-line', + 'a-b', + 'account-box-fill', + 'account-box-line', + 'account-circle-fill', + 'account-circle-line', + 'account-pin-box-fill', + 'account-pin-box-line', + 'account-pin-circle-fill', + 'account-pin-circle-line', + 'add-box-fill', + 'add-box-line', + 'add-circle-fill', + 'add-circle-line', + 'add-fill', + 'add-line', + 'admin-fill', + 'admin-line', + /* "advertisement-fill", + "advertisement-line", */ + 'airplay-fill', + 'airplay-line', + 'alarm-fill', + 'alarm-line', + 'alarm-warning-fill', + 'alarm-warning-line', + 'album-fill', + 'album-line', + 'alert-fill', + 'alert-line', + 'aliens-fill', + 'aliens-line', + 'align-bottom', + 'align-center', + 'align-justify', + 'align-left', + 'align-right', + 'align-top', + 'align-vertically', + 'alipay-fill', + 'alipay-line', + 'amazon-fill', + 'amazon-line', + 'anchor-fill', + 'anchor-line', + 'ancient-gate-fill', + 'ancient-gate-line', + 'ancient-pavilion-fill', + 'ancient-pavilion-line', + 'android-fill', + 'android-line', + 'angularjs-fill', + 'angularjs-line', + 'anticlockwise-2-fill', + 'anticlockwise-2-line', + 'anticlockwise-fill', + 'anticlockwise-line', + 'app-store-fill', + 'app-store-line', + 'apple-fill', + 'apple-line', + 'apps-2-fill', + 'apps-2-line', + 'apps-fill', + 'apps-line', + 'archive-drawer-fill', + 'archive-drawer-line', + 'archive-fill', + 'archive-line', + 'arrow-down-circle-fill', + 'arrow-down-circle-line', + 'arrow-down-fill', + 'arrow-down-line', + 'arrow-down-s-fill', + 'arrow-down-s-line', + 'arrow-drop-down-fill', + 'arrow-drop-down-line', + 'arrow-drop-left-fill', + 'arrow-drop-left-line', + 'arrow-drop-right-fill', + 'arrow-drop-right-line', + 'arrow-drop-up-fill', + 'arrow-drop-up-line', + 'arrow-go-back-fill', + 'arrow-go-back-line', + 'arrow-go-forward-fill', + 'arrow-go-forward-line', + 'arrow-left-circle-fill', + 'arrow-left-circle-line', + 'arrow-left-down-fill', + 'arrow-left-down-line', + 'arrow-left-fill', + 'arrow-left-line', + 'arrow-left-right-fill', + 'arrow-left-right-line', + 'arrow-left-s-fill', + 'arrow-left-s-line', + 'arrow-left-up-fill', + 'arrow-left-up-line', + 'arrow-right-circle-fill', + 'arrow-right-circle-line', + 'arrow-right-down-fill', + 'arrow-right-down-line', + 'arrow-right-fill', + 'arrow-right-line', + 'arrow-right-s-fill', + 'arrow-right-s-line', + 'arrow-right-up-fill', + 'arrow-right-up-line', + 'arrow-up-circle-fill', + 'arrow-up-circle-line', + 'arrow-up-down-fill', + 'arrow-up-down-line', + 'arrow-up-fill', + 'arrow-up-line', + 'arrow-up-s-fill', + 'arrow-up-s-line', + 'artboard-2-fill', + 'artboard-2-line', + 'artboard-fill', + 'artboard-line', + 'article-fill', + 'article-line', + 'aspect-ratio-fill', + 'aspect-ratio-line', + 'asterisk', + 'at-fill', + 'at-line', + 'attachment-2', + 'attachment-fill', + 'attachment-line', + 'auction-fill', + 'auction-line', + 'award-fill', + 'award-line', + 'baidu-fill', + 'baidu-line', + 'ball-pen-fill', + 'ball-pen-line', + 'bank-card-2-fill', + 'bank-card-2-line', + 'bank-card-fill', + 'bank-card-line', + 'bank-fill', + 'bank-line', + 'bar-chart-2-fill', + 'bar-chart-2-line', + 'bar-chart-box-fill', + 'bar-chart-box-line', + 'bar-chart-fill', + 'bar-chart-grouped-fill', + 'bar-chart-grouped-line', + 'bar-chart-horizontal-fill', + 'bar-chart-horizontal-line', + 'bar-chart-line', + 'barcode-box-fill', + 'barcode-box-line', + 'barcode-fill', + 'barcode-line', + 'barricade-fill', + 'barricade-line', + 'base-station-fill', + 'base-station-line', + 'basketball-fill', + 'basketball-line', + 'battery-2-charge-fill', + 'battery-2-charge-line', + 'battery-2-fill', + 'battery-2-line', + 'battery-charge-fill', + 'battery-charge-line', + 'battery-fill', + 'battery-line', + 'battery-low-fill', + 'battery-low-line', + 'battery-saver-fill', + 'battery-saver-line', + 'battery-share-fill', + 'battery-share-line', + 'bear-smile-fill', + 'bear-smile-line', + 'behance-fill', + 'behance-line', + 'bell-fill', + 'bell-line', + 'bike-fill', + 'bike-line', + 'bilibili-fill', + 'bilibili-line', + 'bill-fill', + 'bill-line', + 'billiards-fill', + 'billiards-line', + 'bit-coin-fill', + 'bit-coin-line', + 'blaze-fill', + 'blaze-line', + 'bluetooth-connect-fill', + 'bluetooth-connect-line', + 'bluetooth-fill', + 'bluetooth-line', + 'blur-off-fill', + 'blur-off-line', + 'body-scan-fill', + 'body-scan-line', + 'bold', + 'book-2-fill', + 'book-2-line', + 'book-3-fill', + 'book-3-line', + 'book-fill', + 'book-line', + 'book-mark-fill', + 'book-mark-line', + 'book-open-fill', + 'book-open-line', + 'book-read-fill', + 'book-read-line', + 'booklet-fill', + 'booklet-line', + 'bookmark-2-fill', + 'bookmark-2-line', + 'bookmark-3-fill', + 'bookmark-3-line', + 'bookmark-fill', + 'bookmark-line', + 'boxing-fill', + 'boxing-line', + 'braces-fill', + 'braces-line', + 'brackets-fill', + 'brackets-line', + 'briefcase-2-fill', + 'briefcase-2-line', + 'briefcase-3-fill', + 'briefcase-3-line', + 'briefcase-4-fill', + 'briefcase-4-line', + 'briefcase-5-fill', + 'briefcase-5-line', + 'briefcase-fill', + 'briefcase-line', + 'bring-forward', + 'bring-to-front', + 'broadcast-fill', + 'broadcast-line', + 'brush-2-fill', + 'brush-2-line', + 'brush-3-fill', + 'brush-3-line', + 'brush-4-fill', + 'brush-4-line', + 'brush-fill', + 'brush-line', + 'bubble-chart-fill', + 'bubble-chart-line', + 'bug-2-fill', + 'bug-2-line', + 'bug-fill', + 'bug-line', + 'building-2-fill', + 'building-2-line', + 'building-3-fill', + 'building-3-line', + 'building-4-fill', + 'building-4-line', + 'building-fill', + 'building-line', + 'bus-2-fill', + 'bus-2-line', + 'bus-fill', + 'bus-line', + 'bus-wifi-fill', + 'bus-wifi-line', + 'cactus-fill', + 'cactus-line', + 'cake-2-fill', + 'cake-2-line', + 'cake-3-fill', + 'cake-3-line', + 'cake-fill', + 'cake-line', + 'calculator-fill', + 'calculator-line', + 'calendar-2-fill', + 'calendar-2-line', + 'calendar-check-fill', + 'calendar-check-line', + 'calendar-event-fill', + 'calendar-event-line', + 'calendar-fill', + 'calendar-line', + 'calendar-todo-fill', + 'calendar-todo-line', + 'camera-2-fill', + 'camera-2-line', + 'camera-3-fill', + 'camera-3-line', + 'camera-fill', + 'camera-lens-fill', + 'camera-lens-line', + 'camera-line', + 'camera-off-fill', + 'camera-off-line', + 'camera-switch-fill', + 'camera-switch-line', + 'capsule-fill', + 'capsule-line', + 'car-fill', + 'car-line', + 'car-washing-fill', + 'car-washing-line', + 'caravan-fill', + 'caravan-line', + 'cast-fill', + 'cast-line', + 'cellphone-fill', + 'cellphone-line', + 'celsius-fill', + 'celsius-line', + 'centos-fill', + 'centos-line', + 'character-recognition-fill', + 'character-recognition-line', + 'charging-pile-2-fill', + 'charging-pile-2-line', + 'charging-pile-fill', + 'charging-pile-line', + 'chat-1-fill', + 'chat-1-line', + 'chat-2-fill', + 'chat-2-line', + 'chat-3-fill', + 'chat-3-line', + 'chat-4-fill', + 'chat-4-line', + 'chat-check-fill', + 'chat-check-line', + 'chat-delete-fill', + 'chat-delete-line', + 'chat-download-fill', + 'chat-download-line', + 'chat-follow-up-fill', + 'chat-follow-up-line', + 'chat-forward-fill', + 'chat-forward-line', + 'chat-heart-fill', + 'chat-heart-line', + 'chat-history-fill', + 'chat-history-line', + 'chat-new-fill', + 'chat-new-line', + 'chat-off-fill', + 'chat-off-line', + 'chat-poll-fill', + 'chat-poll-line', + 'chat-private-fill', + 'chat-private-line', + 'chat-quote-fill', + 'chat-quote-line', + 'chat-settings-fill', + 'chat-settings-line', + 'chat-smile-2-fill', + 'chat-smile-2-line', + 'chat-smile-3-fill', + 'chat-smile-3-line', + 'chat-smile-fill', + 'chat-smile-line', + 'chat-upload-fill', + 'chat-upload-line', + 'chat-voice-fill', + 'chat-voice-line', + 'check-double-fill', + 'check-double-line', + 'check-fill', + 'check-line', + 'checkbox-blank-circle-fill', + 'checkbox-blank-circle-line', + 'checkbox-blank-fill', + 'checkbox-blank-line', + 'checkbox-circle-fill', + 'checkbox-circle-line', + 'checkbox-fill', + 'checkbox-indeterminate-fill', + 'checkbox-indeterminate-line', + 'checkbox-line', + 'checkbox-multiple-blank-fill', + 'checkbox-multiple-blank-line', + 'checkbox-multiple-fill', + 'checkbox-multiple-line', + 'china-railway-fill', + 'china-railway-line', + 'chrome-fill', + 'chrome-line', + 'clapperboard-fill', + 'clapperboard-line', + 'clipboard-fill', + 'clipboard-line', + 'clockwise-2-fill', + 'clockwise-2-line', + 'clockwise-fill', + 'clockwise-line', + 'close-circle-fill', + 'close-circle-line', + 'close-fill', + 'close-line', + 'closed-captioning-fill', + 'closed-captioning-line', + 'cloud-fill', + 'cloud-line', + 'cloud-off-fill', + 'cloud-off-line', + 'cloud-windy-fill', + 'cloud-windy-line', + 'cloudy-2-fill', + 'cloudy-2-line', + 'cloudy-fill', + 'cloudy-line', + 'code-box-fill', + 'code-box-line', + 'code-fill', + 'code-line', + 'code-s-fill', + 'code-s-line', + 'code-s-slash-fill', + 'code-s-slash-line', + 'code-view', + 'codepen-fill', + 'codepen-line', + 'coin-fill', + 'coin-line', + 'coins-fill', + 'coins-line', + 'collage-fill', + 'collage-line', + 'command-fill', + 'command-line', + 'community-fill', + 'community-line', + 'compass-2-fill', + 'compass-2-line', + 'compass-3-fill', + 'compass-3-line', + 'compass-4-fill', + 'compass-4-line', + 'compass-discover-fill', + 'compass-discover-line', + 'compass-fill', + 'compass-line', + 'compasses-2-fill', + 'compasses-2-line', + 'compasses-fill', + 'compasses-line', + 'computer-fill', + 'computer-line', + 'contacts-book-2-fill', + 'contacts-book-2-line', + 'contacts-book-fill', + 'contacts-book-line', + 'contacts-book-upload-fill', + 'contacts-book-upload-line', + 'contacts-fill', + 'contacts-line', + 'contrast-2-fill', + 'contrast-2-line', + 'contrast-drop-2-fill', + 'contrast-drop-2-line', + 'contrast-drop-fill', + 'contrast-drop-line', + 'contrast-fill', + 'contrast-line', + 'copper-coin-fill', + 'copper-coin-line', + 'copper-diamond-fill', + 'copper-diamond-line', + 'copyleft-fill', + 'copyleft-line', + 'copyright-fill', + 'copyright-line', + 'coreos-fill', + 'coreos-line', + 'coupon-2-fill', + 'coupon-2-line', + 'coupon-3-fill', + 'coupon-3-line', + 'coupon-4-fill', + 'coupon-4-line', + 'coupon-5-fill', + 'coupon-5-line', + 'coupon-fill', + 'coupon-line', + 'cpu-fill', + 'cpu-line', + 'creative-commons-by-fill', + 'creative-commons-by-line', + 'creative-commons-fill', + 'creative-commons-line', + 'creative-commons-nc-fill', + 'creative-commons-nc-line', + 'creative-commons-nd-fill', + 'creative-commons-nd-line', + 'creative-commons-sa-fill', + 'creative-commons-sa-line', + 'creative-commons-zero-fill', + 'creative-commons-zero-line', + 'criminal-fill', + 'criminal-line', + 'crop-2-fill', + 'crop-2-line', + 'crop-fill', + 'crop-line', + 'css3-fill', + 'css3-line', + 'cup-fill', + 'cup-line', + 'currency-fill', + 'currency-line', + 'cursor-fill', + 'cursor-line', + 'customer-service-2-fill', + 'customer-service-2-line', + 'customer-service-fill', + 'customer-service-line', + 'dashboard-2-fill', + 'dashboard-2-line', + 'dashboard-3-fill', + 'dashboard-3-line', + 'dashboard-fill', + 'dashboard-line', + 'database-2-fill', + 'database-2-line', + 'database-fill', + 'database-line', + 'delete-back-2-fill', + 'delete-back-2-line', + 'delete-back-fill', + 'delete-back-line', + 'delete-bin-2-fill', + 'delete-bin-2-line', + 'delete-bin-3-fill', + 'delete-bin-3-line', + 'delete-bin-4-fill', + 'delete-bin-4-line', + 'delete-bin-5-fill', + 'delete-bin-5-line', + 'delete-bin-6-fill', + 'delete-bin-6-line', + 'delete-bin-7-fill', + 'delete-bin-7-line', + 'delete-bin-fill', + 'delete-bin-line', + 'delete-column', + 'delete-row', + 'device-fill', + 'device-line', + 'device-recover-fill', + 'device-recover-line', + 'dingding-fill', + 'dingding-line', + 'direction-fill', + 'direction-line', + 'disc-fill', + 'disc-line', + 'discord-fill', + 'discord-line', + 'discuss-fill', + 'discuss-line', + 'dislike-fill', + 'dislike-line', + 'disqus-fill', + 'disqus-line', + 'divide-fill', + 'divide-line', + 'donut-chart-fill', + 'donut-chart-line', + 'door-closed-fill', + 'door-closed-line', + 'door-fill', + 'door-line', + 'door-lock-box-fill', + 'door-lock-box-line', + 'door-lock-fill', + 'door-lock-line', + 'door-open-fill', + 'door-open-line', + 'dossier-fill', + 'dossier-line', + 'douban-fill', + 'douban-line', + 'double-quotes-l', + 'double-quotes-r', + 'download-2-fill', + 'download-2-line', + 'download-cloud-2-fill', + 'download-cloud-2-line', + 'download-cloud-fill', + 'download-cloud-line', + 'download-fill', + 'download-line', + 'draft-fill', + 'draft-line', + 'drag-drop-fill', + 'drag-drop-line', + 'drag-move-2-fill', + 'drag-move-2-line', + 'drag-move-fill', + 'drag-move-line', + 'dribbble-fill', + 'dribbble-line', + 'drive-fill', + 'drive-line', + 'drizzle-fill', + 'drizzle-line', + 'drop-fill', + 'drop-line', + 'dropbox-fill', + 'dropbox-line', + 'dual-sim-1-fill', + 'dual-sim-1-line', + 'dual-sim-2-fill', + 'dual-sim-2-line', + 'dv-fill', + 'dv-line', + 'dvd-fill', + 'dvd-line', + 'e-bike-2-fill', + 'e-bike-2-line', + 'e-bike-fill', + 'e-bike-line', + 'earth-fill', + 'earth-line', + 'earthquake-fill', + 'earthquake-line', + 'edge-fill', + 'edge-line', + 'edit-2-fill', + 'edit-2-line', + 'edit-box-fill', + 'edit-box-line', + 'edit-circle-fill', + 'edit-circle-line', + 'edit-fill', + 'edit-line', + 'eject-fill', + 'eject-line', + 'emotion-2-fill', + 'emotion-2-line', + 'emotion-fill', + 'emotion-happy-fill', + 'emotion-happy-line', + 'emotion-laugh-fill', + 'emotion-laugh-line', + 'emotion-line', + 'emotion-normal-fill', + 'emotion-normal-line', + 'emotion-sad-fill', + 'emotion-sad-line', + 'emotion-unhappy-fill', + 'emotion-unhappy-line', + 'empathize-fill', + 'empathize-line', + 'emphasis-cn', + 'emphasis', + 'english-input', + 'equalizer-fill', + 'equalizer-line', + 'eraser-fill', + 'eraser-line', + 'error-warning-fill', + 'error-warning-line', + 'evernote-fill', + 'evernote-line', + 'exchange-box-fill', + 'exchange-box-line', + 'exchange-cny-fill', + 'exchange-cny-line', + 'exchange-dollar-fill', + 'exchange-dollar-line', + 'exchange-fill', + 'exchange-funds-fill', + 'exchange-funds-line', + 'exchange-line', + 'external-link-fill', + 'external-link-line', + 'eye-2-fill', + 'eye-2-line', + 'eye-close-fill', + 'eye-close-line', + 'eye-fill', + 'eye-line', + 'eye-off-fill', + 'eye-off-line', + 'facebook-box-fill', + 'facebook-box-line', + 'facebook-circle-fill', + 'facebook-circle-line', + 'facebook-fill', + 'facebook-line', + 'fahrenheit-fill', + 'fahrenheit-line', + 'feedback-fill', + 'feedback-line', + 'file-2-fill', + 'file-2-line', + 'file-3-fill', + 'file-3-line', + 'file-4-fill', + 'file-4-line', + 'file-add-fill', + 'file-add-line', + 'file-chart-2-fill', + 'file-chart-2-line', + 'file-chart-fill', + 'file-chart-line', + 'file-cloud-fill', + 'file-cloud-line', + 'file-code-fill', + 'file-code-line', + 'file-copy-2-fill', + 'file-copy-2-line', + 'file-copy-fill', + 'file-copy-line', + 'file-damage-fill', + 'file-damage-line', + 'file-download-fill', + 'file-download-line', + 'file-edit-fill', + 'file-edit-line', + 'file-excel-2-fill', + 'file-excel-2-line', + 'file-excel-fill', + 'file-excel-line', + 'file-fill', + 'file-forbid-fill', + 'file-forbid-line', + 'file-gif-fill', + 'file-gif-line', + 'file-history-fill', + 'file-history-line', + 'file-hwp-fill', + 'file-hwp-line', + 'file-info-fill', + 'file-info-line', + 'file-line', + 'file-list-2-fill', + 'file-list-2-line', + 'file-list-3-fill', + 'file-list-3-line', + 'file-list-fill', + 'file-list-line', + 'file-lock-fill', + 'file-lock-line', + 'file-mark-fill', + 'file-mark-line', + 'file-music-fill', + 'file-music-line', + 'file-paper-2-fill', + 'file-paper-2-line', + 'file-paper-fill', + 'file-paper-line', + 'file-pdf-fill', + 'file-pdf-line', + 'file-ppt-2-fill', + 'file-ppt-2-line', + 'file-ppt-fill', + 'file-ppt-line', + 'file-reduce-fill', + 'file-reduce-line', + 'file-search-fill', + 'file-search-line', + 'file-settings-fill', + 'file-settings-line', + 'file-shield-2-fill', + 'file-shield-2-line', + 'file-shield-fill', + 'file-shield-line', + 'file-shred-fill', + 'file-shred-line', + 'file-text-fill', + 'file-text-line', + 'file-transfer-fill', + 'file-transfer-line', + 'file-unknow-fill', + 'file-unknow-line', + 'file-upload-fill', + 'file-upload-line', + 'file-user-fill', + 'file-user-line', + 'file-warning-fill', + 'file-warning-line', + 'file-word-2-fill', + 'file-word-2-line', + 'file-word-fill', + 'file-word-line', + 'file-zip-fill', + 'file-zip-line', + 'film-fill', + 'film-line', + 'filter-2-fill', + 'filter-2-line', + 'filter-3-fill', + 'filter-3-line', + 'filter-fill', + 'filter-line', + 'filter-off-fill', + 'filter-off-line', + 'find-replace-fill', + 'find-replace-line', + 'finder-fill', + 'finder-line', + 'fingerprint-2-fill', + 'fingerprint-2-line', + 'fingerprint-fill', + 'fingerprint-line', + 'fire-fill', + 'fire-line', + 'firefox-fill', + 'firefox-line', + 'first-aid-kit-fill', + 'first-aid-kit-line', + 'flag-2-fill', + 'flag-2-line', + 'flag-fill', + 'flag-line', + 'flashlight-fill', + 'flashlight-line', + 'flask-fill', + 'flask-line', + 'flight-land-fill', + 'flight-land-line', + 'flight-takeoff-fill', + 'flight-takeoff-line', + 'flood-fill', + 'flood-line', + 'flow-chart', + 'flutter-fill', + 'flutter-line', + 'focus-2-fill', + 'focus-2-line', + 'focus-3-fill', + 'focus-3-line', + 'focus-fill', + 'focus-line', + 'foggy-fill', + 'foggy-line', + 'folder-2-fill', + 'folder-2-line', + 'folder-3-fill', + 'folder-3-line', + 'folder-4-fill', + 'folder-4-line', + 'folder-5-fill', + 'folder-5-line', + 'folder-add-fill', + 'folder-add-line', + 'folder-chart-2-fill', + 'folder-chart-2-line', + 'folder-chart-fill', + 'folder-chart-line', + 'folder-download-fill', + 'folder-download-line', + 'folder-fill', + 'folder-forbid-fill', + 'folder-forbid-line', + 'folder-history-fill', + 'folder-history-line', + 'folder-info-fill', + 'folder-info-line', + 'folder-keyhole-fill', + 'folder-keyhole-line', + 'folder-line', + 'folder-lock-fill', + 'folder-lock-line', + 'folder-music-fill', + 'folder-music-line', + 'folder-open-fill', + 'folder-open-line', + 'folder-received-fill', + 'folder-received-line', + 'folder-reduce-fill', + 'folder-reduce-line', + 'folder-settings-fill', + 'folder-settings-line', + 'folder-shared-fill', + 'folder-shared-line', + 'folder-shield-2-fill', + 'folder-shield-2-line', + 'folder-shield-fill', + 'folder-shield-line', + 'folder-transfer-fill', + 'folder-transfer-line', + 'folder-unknow-fill', + 'folder-unknow-line', + 'folder-upload-fill', + 'folder-upload-line', + 'folder-user-fill', + 'folder-user-line', + 'folder-warning-fill', + 'folder-warning-line', + 'folder-zip-fill', + 'folder-zip-line', + 'folders-fill', + 'folders-line', + 'font-color', + 'font-size-2', + 'font-size', + 'football-fill', + 'football-line', + 'footprint-fill', + 'footprint-line', + 'forbid-2-fill', + 'forbid-2-line', + 'forbid-fill', + 'forbid-line', + 'format-clear', + 'fridge-fill', + 'fridge-line', + 'fullscreen-exit-fill', + 'fullscreen-exit-line', + 'fullscreen-fill', + 'fullscreen-line', + 'function-fill', + 'function-line', + 'functions', + 'funds-box-fill', + 'funds-box-line', + 'funds-fill', + 'funds-line', + 'gallery-fill', + 'gallery-line', + 'gallery-upload-fill', + 'gallery-upload-line', + 'game-fill', + 'game-line', + 'gamepad-fill', + 'gamepad-line', + 'gas-station-fill', + 'gas-station-line', + 'gatsby-fill', + 'gatsby-line', + 'genderless-fill', + 'genderless-line', + 'ghost-2-fill', + 'ghost-2-line', + 'ghost-fill', + 'ghost-line', + 'ghost-smile-fill', + 'ghost-smile-line', + 'gift-2-fill', + 'gift-2-line', + 'gift-fill', + 'gift-line', + 'git-branch-fill', + 'git-branch-line', + 'git-commit-fill', + 'git-commit-line', + 'git-merge-fill', + 'git-merge-line', + 'git-pull-request-fill', + 'git-pull-request-line', + 'git-repository-commits-fill', + 'git-repository-commits-line', + 'git-repository-fill', + 'git-repository-line', + 'git-repository-private-fill', + 'git-repository-private-line', + 'github-fill', + 'github-line', + 'gitlab-fill', + 'gitlab-line', + 'global-fill', + 'global-line', + 'globe-fill', + 'globe-line', + 'goblet-fill', + 'goblet-line', + 'google-fill', + 'google-line', + 'google-play-fill', + 'google-play-line', + 'government-fill', + 'government-line', + 'gps-fill', + 'gps-line', + 'gradienter-fill', + 'gradienter-line', + 'grid-fill', + 'grid-line', + 'group-2-fill', + 'group-2-line', + 'group-fill', + 'group-line', + 'guide-fill', + 'guide-line', + 'h-1', + 'h-2', + 'h-3', + 'h-4', + 'h-5', + 'h-6', + 'hail-fill', + 'hail-line', + 'hammer-fill', + 'hammer-line', + 'hand-coin-fill', + 'hand-coin-line', + 'hand-heart-fill', + 'hand-heart-line', + 'hand-sanitizer-fill', + 'hand-sanitizer-line', + 'handbag-fill', + 'handbag-line', + 'hard-drive-2-fill', + 'hard-drive-2-line', + 'hard-drive-fill', + 'hard-drive-line', + 'hashtag', + 'haze-2-fill', + 'haze-2-line', + 'haze-fill', + 'haze-line', + 'hd-fill', + 'hd-line', + 'heading', + 'headphone-fill', + 'headphone-line', + 'health-book-fill', + 'health-book-line', + 'heart-2-fill', + 'heart-2-line', + 'heart-3-fill', + 'heart-3-line', + 'heart-add-fill', + 'heart-add-line', + 'heart-fill', + 'heart-line', + 'heart-pulse-fill', + 'heart-pulse-line', + 'hearts-fill', + 'hearts-line', + 'heavy-showers-fill', + 'heavy-showers-line', + 'history-fill', + 'history-line', + 'home-2-fill', + 'home-2-line', + 'home-3-fill', + 'home-3-line', + 'home-4-fill', + 'home-4-line', + 'home-5-fill', + 'home-5-line', + 'home-6-fill', + 'home-6-line', + 'home-7-fill', + 'home-7-line', + 'home-8-fill', + 'home-8-line', + 'home-fill', + 'home-gear-fill', + 'home-gear-line', + 'home-heart-fill', + 'home-heart-line', + 'home-line', + 'home-smile-2-fill', + 'home-smile-2-line', + 'home-smile-fill', + 'home-smile-line', + 'home-wifi-fill', + 'home-wifi-line', + 'honor-of-kings-fill', + 'honor-of-kings-line', + 'honour-fill', + 'honour-line', + 'hospital-fill', + 'hospital-line', + 'hotel-bed-fill', + 'hotel-bed-line', + 'hotel-fill', + 'hotel-line', + 'hotspot-fill', + 'hotspot-line', + 'hq-fill', + 'hq-line', + 'html5-fill', + 'html5-line', + 'ie-fill', + 'ie-line', + 'image-2-fill', + 'image-2-line', + 'image-add-fill', + 'image-add-line', + 'image-edit-fill', + 'image-edit-line', + 'image-fill', + 'image-line', + 'inbox-archive-fill', + 'inbox-archive-line', + 'inbox-fill', + 'inbox-line', + 'inbox-unarchive-fill', + 'inbox-unarchive-line', + 'increase-decrease-fill', + 'increase-decrease-line', + 'indent-decrease', + 'indent-increase', + 'indeterminate-circle-fill', + 'indeterminate-circle-line', + 'information-fill', + 'information-line', + 'infrared-thermometer-fill', + 'infrared-thermometer-line', + 'ink-bottle-fill', + 'ink-bottle-line', + 'input-cursor-move', + 'input-method-fill', + 'input-method-line', + 'insert-column-left', + 'insert-column-right', + 'insert-row-bottom', + 'insert-row-top', + 'instagram-fill', + 'instagram-line', + 'install-fill', + 'install-line', + 'invision-fill', + 'invision-line', + 'italic', + 'kakao-talk-fill', + 'kakao-talk-line', + 'key-2-fill', + 'key-2-line', + 'key-fill', + 'key-line', + 'keyboard-box-fill', + 'keyboard-box-line', + 'keyboard-fill', + 'keyboard-line', + 'keynote-fill', + 'keynote-line', + 'knife-blood-fill', + 'knife-blood-line', + 'knife-fill', + 'knife-line', + 'landscape-fill', + 'landscape-line', + 'layout-2-fill', + 'layout-2-line', + 'layout-3-fill', + 'layout-3-line', + 'layout-4-fill', + 'layout-4-line', + 'layout-5-fill', + 'layout-5-line', + 'layout-6-fill', + 'layout-6-line', + 'layout-bottom-2-fill', + 'layout-bottom-2-line', + 'layout-bottom-fill', + 'layout-bottom-line', + 'layout-column-fill', + 'layout-column-line', + 'layout-fill', + 'layout-grid-fill', + 'layout-grid-line', + 'layout-left-2-fill', + 'layout-left-2-line', + 'layout-left-fill', + 'layout-left-line', + 'layout-line', + 'layout-masonry-fill', + 'layout-masonry-line', + 'layout-right-2-fill', + 'layout-right-2-line', + 'layout-right-fill', + 'layout-right-line', + 'layout-row-fill', + 'layout-row-line', + 'layout-top-2-fill', + 'layout-top-2-line', + 'layout-top-fill', + 'layout-top-line', + 'leaf-fill', + 'leaf-line', + 'lifebuoy-fill', + 'lifebuoy-line', + 'lightbulb-fill', + 'lightbulb-flash-fill', + 'lightbulb-flash-line', + 'lightbulb-line', + 'line-chart-fill', + 'line-chart-line', + 'line-fill', + 'line-height', + 'line-line', + 'link-m', + 'link-unlink-m', + 'link-unlink', + 'link', + 'linkedin-box-fill', + 'linkedin-box-line', + 'linkedin-fill', + 'linkedin-line', + 'links-fill', + 'links-line', + 'list-check-2', + 'list-check', + 'list-ordered', + 'list-settings-fill', + 'list-settings-line', + 'list-unordered', + 'live-fill', + 'live-line', + 'loader-2-fill', + 'loader-2-line', + 'loader-3-fill', + 'loader-3-line', + 'loader-4-fill', + 'loader-4-line', + 'loader-5-fill', + 'loader-5-line', + 'loader-fill', + 'loader-line', + 'lock-2-fill', + 'lock-2-line', + 'lock-fill', + 'lock-line', + 'lock-password-fill', + 'lock-password-line', + 'lock-unlock-fill', + 'lock-unlock-line', + 'login-box-fill', + 'login-box-line', + 'login-circle-fill', + 'login-circle-line', + 'logout-box-fill', + 'logout-box-line', + 'logout-box-r-fill', + 'logout-box-r-line', + 'logout-circle-fill', + 'logout-circle-line', + 'logout-circle-r-fill', + 'logout-circle-r-line', + 'luggage-cart-fill', + 'luggage-cart-line', + 'luggage-deposit-fill', + 'luggage-deposit-line', + 'lungs-fill', + 'lungs-line', + 'mac-fill', + 'mac-line', + 'macbook-fill', + 'macbook-line', + 'magic-fill', + 'magic-line', + 'mail-add-fill', + 'mail-add-line', + 'mail-check-fill', + 'mail-check-line', + 'mail-close-fill', + 'mail-close-line', + 'mail-download-fill', + 'mail-download-line', + 'mail-fill', + 'mail-forbid-fill', + 'mail-forbid-line', + 'mail-line', + 'mail-lock-fill', + 'mail-lock-line', + 'mail-open-fill', + 'mail-open-line', + 'mail-send-fill', + 'mail-send-line', + 'mail-settings-fill', + 'mail-settings-line', + 'mail-star-fill', + 'mail-star-line', + 'mail-unread-fill', + 'mail-unread-line', + 'mail-volume-fill', + 'mail-volume-line', + 'map-2-fill', + 'map-2-line', + 'map-fill', + 'map-line', + 'map-pin-2-fill', + 'map-pin-2-line', + 'map-pin-3-fill', + 'map-pin-3-line', + 'map-pin-4-fill', + 'map-pin-4-line', + 'map-pin-5-fill', + 'map-pin-5-line', + 'map-pin-add-fill', + 'map-pin-add-line', + 'map-pin-fill', + 'map-pin-line', + 'map-pin-range-fill', + 'map-pin-range-line', + 'map-pin-time-fill', + 'map-pin-time-line', + 'map-pin-user-fill', + 'map-pin-user-line', + 'mark-pen-fill', + 'mark-pen-line', + 'markdown-fill', + 'markdown-line', + 'markup-fill', + 'markup-line', + 'mastercard-fill', + 'mastercard-line', + 'mastodon-fill', + 'mastodon-line', + 'medal-2-fill', + 'medal-2-line', + 'medal-fill', + 'medal-line', + 'medicine-bottle-fill', + 'medicine-bottle-line', + 'medium-fill', + 'medium-line', + 'men-fill', + 'men-line', + 'mental-health-fill', + 'mental-health-line', + 'menu-2-fill', + 'menu-2-line', + 'menu-3-fill', + 'menu-3-line', + 'menu-4-fill', + 'menu-4-line', + 'menu-5-fill', + 'menu-5-line', + 'menu-add-fill', + 'menu-add-line', + 'menu-fill', + 'menu-fold-fill', + 'menu-fold-line', + 'menu-line', + 'menu-unfold-fill', + 'menu-unfold-line', + 'merge-cells-horizontal', + 'merge-cells-vertical', + 'message-2-fill', + 'message-2-line', + 'message-3-fill', + 'message-3-line', + 'message-fill', + 'message-line', + 'messenger-fill', + 'messenger-line', + 'meteor-fill', + 'meteor-line', + 'mic-2-fill', + 'mic-2-line', + 'mic-fill', + 'mic-line', + 'mic-off-fill', + 'mic-off-line', + 'mickey-fill', + 'mickey-line', + 'microscope-fill', + 'microscope-line', + 'microsoft-fill', + 'microsoft-line', + 'mind-map', + 'mini-program-fill', + 'mini-program-line', + 'mist-fill', + 'mist-line', + 'money-cny-box-fill', + 'money-cny-box-line', + 'money-cny-circle-fill', + 'money-cny-circle-line', + 'money-dollar-box-fill', + 'money-dollar-box-line', + 'money-dollar-circle-fill', + 'money-dollar-circle-line', + 'money-euro-box-fill', + 'money-euro-box-line', + 'money-euro-circle-fill', + 'money-euro-circle-line', + 'money-pound-box-fill', + 'money-pound-box-line', + 'money-pound-circle-fill', + 'money-pound-circle-line', + 'moon-clear-fill', + 'moon-clear-line', + 'moon-cloudy-fill', + 'moon-cloudy-line', + 'moon-fill', + 'moon-foggy-fill', + 'moon-foggy-line', + 'moon-line', + 'more-2-fill', + 'more-2-line', + 'more-fill', + 'more-line', + 'motorbike-fill', + 'motorbike-line', + 'mouse-fill', + 'mouse-line', + 'movie-2-fill', + 'movie-2-line', + 'movie-fill', + 'movie-line', + 'music-2-fill', + 'music-2-line', + 'music-fill', + 'music-line', + 'mv-fill', + 'mv-line', + 'navigation-fill', + 'navigation-line', + 'netease-cloud-music-fill', + 'netease-cloud-music-line', + 'netflix-fill', + 'netflix-line', + 'newspaper-fill', + 'newspaper-line', + 'node-tree', + 'notification-2-fill', + 'notification-2-line', + 'notification-3-fill', + 'notification-3-line', + 'notification-4-fill', + 'notification-4-line', + 'notification-badge-fill', + 'notification-badge-line', + 'notification-fill', + 'notification-line', + 'notification-off-fill', + 'notification-off-line', + 'npmjs-fill', + 'npmjs-line', + 'number-0', + 'number-1', + 'number-2', + 'number-3', + 'number-4', + 'number-5', + 'number-6', + 'number-7', + 'number-8', + 'number-9', + 'numbers-fill', + 'numbers-line', + 'nurse-fill', + 'nurse-line', + 'oil-fill', + 'oil-line', + 'omega', + 'open-arm-fill', + 'open-arm-line', + 'open-source-fill', + 'open-source-line', + 'opera-fill', + 'opera-line', + 'order-play-fill', + 'order-play-line', + 'organization-chart', + 'outlet-2-fill', + 'outlet-2-line', + 'outlet-fill', + 'outlet-line', + 'page-separator', + 'pages-fill', + 'pages-line', + 'paint-brush-fill', + 'paint-brush-line', + 'paint-fill', + 'paint-line', + 'palette-fill', + 'palette-line', + 'pantone-fill', + 'pantone-line', + 'paragraph', + 'parent-fill', + 'parent-line', + 'parentheses-fill', + 'parentheses-line', + 'parking-box-fill', + 'parking-box-line', + 'parking-fill', + 'parking-line', + 'passport-fill', + 'passport-line', + 'patreon-fill', + 'patreon-line', + 'pause-circle-fill', + 'pause-circle-line', + 'pause-fill', + 'pause-line', + 'pause-mini-fill', + 'pause-mini-line', + 'paypal-fill', + 'paypal-line', + 'pen-nib-fill', + 'pen-nib-line', + 'pencil-fill', + 'pencil-line', + 'pencil-ruler-2-fill', + 'pencil-ruler-2-line', + 'pencil-ruler-fill', + 'pencil-ruler-line', + 'percent-fill', + 'percent-line', + 'phone-camera-fill', + 'phone-camera-line', + 'phone-fill', + 'phone-find-fill', + 'phone-find-line', + 'phone-line', + 'phone-lock-fill', + 'phone-lock-line', + 'picture-in-picture-2-fill', + 'picture-in-picture-2-line', + 'picture-in-picture-exit-fill', + 'picture-in-picture-exit-line', + 'picture-in-picture-fill', + 'picture-in-picture-line', + 'pie-chart-2-fill', + 'pie-chart-2-line', + 'pie-chart-box-fill', + 'pie-chart-box-line', + 'pie-chart-fill', + 'pie-chart-line', + 'pin-distance-fill', + 'pin-distance-line', + 'ping-pong-fill', + 'ping-pong-line', + 'pinterest-fill', + 'pinterest-line', + 'pinyin-input', + 'pixelfed-fill', + 'pixelfed-line', + 'plane-fill', + 'plane-line', + 'plant-fill', + 'plant-line', + 'play-circle-fill', + 'play-circle-line', + 'play-fill', + 'play-line', + 'play-list-2-fill', + 'play-list-2-line', + 'play-list-add-fill', + 'play-list-add-line', + 'play-list-fill', + 'play-list-line', + 'play-mini-fill', + 'play-mini-line', + 'playstation-fill', + 'playstation-line', + 'plug-2-fill', + 'plug-2-line', + 'plug-fill', + 'plug-line', + 'polaroid-2-fill', + 'polaroid-2-line', + 'polaroid-fill', + 'polaroid-line', + 'police-car-fill', + 'police-car-line', + 'price-tag-2-fill', + 'price-tag-2-line', + 'price-tag-3-fill', + 'price-tag-3-line', + 'price-tag-fill', + 'price-tag-line', + 'printer-cloud-fill', + 'printer-cloud-line', + 'printer-fill', + 'printer-line', + 'product-hunt-fill', + 'product-hunt-line', + 'profile-fill', + 'profile-line', + 'projector-2-fill', + 'projector-2-line', + 'projector-fill', + 'projector-line', + 'psychotherapy-fill', + 'psychotherapy-line', + 'pulse-fill', + 'pulse-line', + 'pushpin-2-fill', + 'pushpin-2-line', + 'pushpin-fill', + 'pushpin-line', + 'qq-fill', + 'qq-line', + 'qr-code-fill', + 'qr-code-line', + 'qr-scan-2-fill', + 'qr-scan-2-line', + 'qr-scan-fill', + 'qr-scan-line', + 'question-answer-fill', + 'question-answer-line', + 'question-fill', + 'question-line', + 'question-mark', + 'questionnaire-fill', + 'questionnaire-line', + 'quill-pen-fill', + 'quill-pen-line', + 'radar-fill', + 'radar-line', + 'radio-2-fill', + 'radio-2-line', + 'radio-button-fill', + 'radio-button-line', + 'radio-fill', + 'radio-line', + 'rainbow-fill', + 'rainbow-line', + 'rainy-fill', + 'rainy-line', + 'reactjs-fill', + 'reactjs-line', + 'record-circle-fill', + 'record-circle-line', + 'record-mail-fill', + 'record-mail-line', + 'recycle-fill', + 'recycle-line', + 'red-packet-fill', + 'red-packet-line', + 'reddit-fill', + 'reddit-line', + 'refresh-fill', + 'refresh-line', + 'refund-2-fill', + 'refund-2-line', + 'refund-fill', + 'refund-line', + 'registered-fill', + 'registered-line', + 'remixicon-fill', + 'remixicon-line', + 'remote-control-2-fill', + 'remote-control-2-line', + 'remote-control-fill', + 'remote-control-line', + 'repeat-2-fill', + 'repeat-2-line', + 'repeat-fill', + 'repeat-line', + 'repeat-one-fill', + 'repeat-one-line', + 'reply-all-fill', + 'reply-all-line', + 'reply-fill', + 'reply-line', + 'reserved-fill', + 'reserved-line', + 'rest-time-fill', + 'rest-time-line', + 'restart-fill', + 'restart-line', + 'restaurant-2-fill', + 'restaurant-2-line', + 'restaurant-fill', + 'restaurant-line', + 'rewind-fill', + 'rewind-line', + 'rewind-mini-fill', + 'rewind-mini-line', + 'rhythm-fill', + 'rhythm-line', + 'riding-fill', + 'riding-line', + 'road-map-fill', + 'road-map-line', + 'roadster-fill', + 'roadster-line', + 'robot-fill', + 'robot-line', + 'rocket-2-fill', + 'rocket-2-line', + 'rocket-fill', + 'rocket-line', + 'rotate-lock-fill', + 'rotate-lock-line', + 'rounded-corner', + 'route-fill', + 'route-line', + 'router-fill', + 'router-line', + 'rss-fill', + 'rss-line', + 'ruler-2-fill', + 'ruler-2-line', + 'ruler-fill', + 'ruler-line', + 'run-fill', + 'run-line', + 'safari-fill', + 'safari-line', + 'safe-2-fill', + 'safe-2-line', + 'safe-fill', + 'safe-line', + 'sailboat-fill', + 'sailboat-line', + 'save-2-fill', + 'save-2-line', + 'save-3-fill', + 'save-3-line', + 'save-fill', + 'save-line', + 'scales-2-fill', + 'scales-2-line', + 'scales-3-fill', + 'scales-3-line', + 'scales-fill', + 'scales-line', + 'scan-2-fill', + 'scan-2-line', + 'scan-fill', + 'scan-line', + 'scissors-2-fill', + 'scissors-2-line', + 'scissors-cut-fill', + 'scissors-cut-line', + 'scissors-fill', + 'scissors-line', + 'screenshot-2-fill', + 'screenshot-2-line', + 'screenshot-fill', + 'screenshot-line', + 'sd-card-fill', + 'sd-card-line', + 'sd-card-mini-fill', + 'sd-card-mini-line', + 'search-2-fill', + 'search-2-line', + 'search-eye-fill', + 'search-eye-line', + 'search-fill', + 'search-line', + 'secure-payment-fill', + 'secure-payment-line', + 'seedling-fill', + 'seedling-line', + 'send-backward', + 'send-plane-2-fill', + 'send-plane-2-line', + 'send-plane-fill', + 'send-plane-line', + 'send-to-back', + 'sensor-fill', + 'sensor-line', + 'separator', + 'server-fill', + 'server-line', + 'service-fill', + 'service-line', + 'settings-2-fill', + 'settings-2-line', + 'settings-3-fill', + 'settings-3-line', + 'settings-4-fill', + 'settings-4-line', + 'settings-5-fill', + 'settings-5-line', + 'settings-6-fill', + 'settings-6-line', + 'settings-fill', + 'settings-line', + 'shape-2-fill', + 'shape-2-line', + 'shape-fill', + 'shape-line', + 'share-box-fill', + 'share-box-line', + 'share-circle-fill', + 'share-circle-line', + 'share-fill', + 'share-forward-2-fill', + 'share-forward-2-line', + 'share-forward-box-fill', + 'share-forward-box-line', + 'share-forward-fill', + 'share-forward-line', + 'share-line', + 'shield-check-fill', + 'shield-check-line', + 'shield-cross-fill', + 'shield-cross-line', + 'shield-fill', + 'shield-flash-fill', + 'shield-flash-line', + 'shield-keyhole-fill', + 'shield-keyhole-line', + 'shield-line', + 'shield-star-fill', + 'shield-star-line', + 'shield-user-fill', + 'shield-user-line', + 'ship-2-fill', + 'ship-2-line', + 'ship-fill', + 'ship-line', + 'shirt-fill', + 'shirt-line', + 'shopping-bag-2-fill', + 'shopping-bag-2-line', + 'shopping-bag-3-fill', + 'shopping-bag-3-line', + 'shopping-bag-fill', + 'shopping-bag-line', + 'shopping-basket-2-fill', + 'shopping-basket-2-line', + 'shopping-basket-fill', + 'shopping-basket-line', + 'shopping-cart-2-fill', + 'shopping-cart-2-line', + 'shopping-cart-fill', + 'shopping-cart-line', + 'showers-fill', + 'showers-line', + 'shuffle-fill', + 'shuffle-line', + 'shut-down-fill', + 'shut-down-line', + 'side-bar-fill', + 'side-bar-line', + 'signal-tower-fill', + 'signal-tower-line', + 'signal-wifi-1-fill', + 'signal-wifi-1-line', + 'signal-wifi-2-fill', + 'signal-wifi-2-line', + 'signal-wifi-3-fill', + 'signal-wifi-3-line', + 'signal-wifi-error-fill', + 'signal-wifi-error-line', + 'signal-wifi-fill', + 'signal-wifi-line', + 'signal-wifi-off-fill', + 'signal-wifi-off-line', + 'sim-card-2-fill', + 'sim-card-2-line', + 'sim-card-fill', + 'sim-card-line', + 'single-quotes-l', + 'single-quotes-r', + 'sip-fill', + 'sip-line', + 'skip-back-fill', + 'skip-back-line', + 'skip-back-mini-fill', + 'skip-back-mini-line', + 'skip-forward-fill', + 'skip-forward-line', + 'skip-forward-mini-fill', + 'skip-forward-mini-line', + 'skull-2-fill', + 'skull-2-line', + 'skull-fill', + 'skull-line', + 'skype-fill', + 'skype-line', + 'slack-fill', + 'slack-line', + 'slice-fill', + 'slice-line', + 'slideshow-2-fill', + 'slideshow-2-line', + 'slideshow-3-fill', + 'slideshow-3-line', + 'slideshow-4-fill', + 'slideshow-4-line', + 'slideshow-fill', + 'slideshow-line', + 'smartphone-fill', + 'smartphone-line', + 'snapchat-fill', + 'snapchat-line', + 'snowy-fill', + 'snowy-line', + 'sort-asc', + 'sort-desc', + 'sound-module-fill', + 'sound-module-line', + 'soundcloud-fill', + 'soundcloud-line', + 'space-ship-fill', + 'space-ship-line', + 'space', + 'spam-2-fill', + 'spam-2-line', + 'spam-3-fill', + 'spam-3-line', + 'spam-fill', + 'spam-line', + 'speaker-2-fill', + 'speaker-2-line', + 'speaker-3-fill', + 'speaker-3-line', + 'speaker-fill', + 'speaker-line', + 'spectrum-fill', + 'spectrum-line', + 'speed-fill', + 'speed-line', + 'speed-mini-fill', + 'speed-mini-line', + 'split-cells-horizontal', + 'split-cells-vertical', + 'spotify-fill', + 'spotify-line', + 'spy-fill', + 'spy-line', + 'stack-fill', + 'stack-line', + 'stack-overflow-fill', + 'stack-overflow-line', + 'stackshare-fill', + 'stackshare-line', + 'star-fill', + 'star-half-fill', + 'star-half-line', + 'star-half-s-fill', + 'star-half-s-line', + 'star-line', + 'star-s-fill', + 'star-s-line', + 'star-smile-fill', + 'star-smile-line', + 'steam-fill', + 'steam-line', + 'steering-2-fill', + 'steering-2-line', + 'steering-fill', + 'steering-line', + 'stethoscope-fill', + 'stethoscope-line', + 'sticky-note-2-fill', + 'sticky-note-2-line', + 'sticky-note-fill', + 'sticky-note-line', + 'stock-fill', + 'stock-line', + 'stop-circle-fill', + 'stop-circle-line', + 'stop-fill', + 'stop-line', + 'stop-mini-fill', + 'stop-mini-line', + 'store-2-fill', + 'store-2-line', + 'store-3-fill', + 'store-3-line', + 'store-fill', + 'store-line', + 'strikethrough-2', + 'strikethrough', + 'subscript-2', + 'subscript', + 'subtract-fill', + 'subtract-line', + 'subway-fill', + 'subway-line', + 'subway-wifi-fill', + 'subway-wifi-line', + 'suitcase-2-fill', + 'suitcase-2-line', + 'suitcase-3-fill', + 'suitcase-3-line', + 'suitcase-fill', + 'suitcase-line', + 'sun-cloudy-fill', + 'sun-cloudy-line', + 'sun-fill', + 'sun-foggy-fill', + 'sun-foggy-line', + 'sun-line', + 'superscript-2', + 'superscript', + 'surgical-mask-fill', + 'surgical-mask-line', + 'surround-sound-fill', + 'surround-sound-line', + 'survey-fill', + 'survey-line', + 'swap-box-fill', + 'swap-box-line', + 'swap-fill', + 'swap-line', + 'switch-fill', + 'switch-line', + 'sword-fill', + 'sword-line', + 'syringe-fill', + 'syringe-line', + 't-box-fill', + 't-box-line', + 't-shirt-2-fill', + 't-shirt-2-line', + 't-shirt-air-fill', + 't-shirt-air-line', + 't-shirt-fill', + 't-shirt-line', + 'table-2', + 'table-alt-fill', + 'table-alt-line', + 'table-fill', + 'table-line', + 'tablet-fill', + 'tablet-line', + 'takeaway-fill', + 'takeaway-line', + 'taobao-fill', + 'taobao-line', + 'tape-fill', + 'tape-line', + 'task-fill', + 'task-line', + 'taxi-fill', + 'taxi-line', + 'taxi-wifi-fill', + 'taxi-wifi-line', + 'team-fill', + 'team-line', + 'telegram-fill', + 'telegram-line', + 'temp-cold-fill', + 'temp-cold-line', + 'temp-hot-fill', + 'temp-hot-line', + 'terminal-box-fill', + 'terminal-box-line', + 'terminal-fill', + 'terminal-line', + 'terminal-window-fill', + 'terminal-window-line', + 'test-tube-fill', + 'test-tube-line', + 'text-direction-l', + 'text-direction-r', + 'text-spacing', + 'text-wrap', + 'text', + 'thermometer-fill', + 'thermometer-line', + 'thumb-down-fill', + 'thumb-down-line', + 'thumb-up-fill', + 'thumb-up-line', + 'thunderstorms-fill', + 'thunderstorms-line', + 'ticket-2-fill', + 'ticket-2-line', + 'ticket-fill', + 'ticket-line', + 'time-fill', + 'time-line', + 'timer-2-fill', + 'timer-2-line', + 'timer-fill', + 'timer-flash-fill', + 'timer-flash-line', + 'timer-line', + 'todo-fill', + 'todo-line', + 'toggle-fill', + 'toggle-line', + 'tools-fill', + 'tools-line', + 'tornado-fill', + 'tornado-line', + 'trademark-fill', + 'trademark-line', + 'traffic-light-fill', + 'traffic-light-line', + 'train-fill', + 'train-line', + 'train-wifi-fill', + 'train-wifi-line', + 'translate-2', + 'translate', + 'travesti-fill', + 'travesti-line', + 'treasure-map-fill', + 'treasure-map-line', + 'trello-fill', + 'trello-line', + 'trophy-fill', + 'trophy-line', + 'truck-fill', + 'truck-line', + 'tumblr-fill', + 'tumblr-line', + 'tv-2-fill', + 'tv-2-line', + 'tv-fill', + 'tv-line', + 'twitch-fill', + 'twitch-line', + 'twitter-fill', + 'twitter-line', + 'typhoon-fill', + 'typhoon-line', + 'u-disk-fill', + 'u-disk-line', + 'ubuntu-fill', + 'ubuntu-line', + 'umbrella-fill', + 'umbrella-line', + 'underline', + 'uninstall-fill', + 'uninstall-line', + 'unsplash-fill', + 'unsplash-line', + 'upload-2-fill', + 'upload-2-line', + 'upload-cloud-2-fill', + 'upload-cloud-2-line', + 'upload-cloud-fill', + 'upload-cloud-line', + 'upload-fill', + 'upload-line', + 'usb-fill', + 'usb-line', + 'user-2-fill', + 'user-2-line', + 'user-3-fill', + 'user-3-line', + 'user-4-fill', + 'user-4-line', + 'user-5-fill', + 'user-5-line', + 'user-6-fill', + 'user-6-line', + 'user-add-fill', + 'user-add-line', + 'user-fill', + 'user-follow-fill', + 'user-follow-line', + 'user-heart-fill', + 'user-heart-line', + 'user-line', + 'user-location-fill', + 'user-location-line', + 'user-received-2-fill', + 'user-received-2-line', + 'user-received-fill', + 'user-received-line', + 'user-search-fill', + 'user-search-line', + 'user-settings-fill', + 'user-settings-line', + 'user-shared-2-fill', + 'user-shared-2-line', + 'user-shared-fill', + 'user-shared-line', + 'user-smile-fill', + 'user-smile-line', + 'user-star-fill', + 'user-star-line', + 'user-unfollow-fill', + 'user-unfollow-line', + 'user-voice-fill', + 'user-voice-line', + 'video-add-fill', + 'video-add-line', + 'video-chat-fill', + 'video-chat-line', + 'video-download-fill', + 'video-download-line', + 'video-fill', + 'video-line', + 'video-upload-fill', + 'video-upload-line', + 'vidicon-2-fill', + 'vidicon-2-line', + 'vidicon-fill', + 'vidicon-line', + 'vimeo-fill', + 'vimeo-line', + 'vip-crown-2-fill', + 'vip-crown-2-line', + 'vip-crown-fill', + 'vip-crown-line', + 'vip-diamond-fill', + 'vip-diamond-line', + 'vip-fill', + 'vip-line', + 'virus-fill', + 'virus-line', + 'visa-fill', + 'visa-line', + 'voice-recognition-fill', + 'voice-recognition-line', + 'voiceprint-fill', + 'voiceprint-line', + 'volume-down-fill', + 'volume-down-line', + 'volume-mute-fill', + 'volume-mute-line', + 'volume-off-vibrate-fill', + 'volume-off-vibrate-line', + 'volume-up-fill', + 'volume-up-line', + 'volume-vibrate-fill', + 'volume-vibrate-line', + 'vuejs-fill', + 'vuejs-line', + 'walk-fill', + 'walk-line', + 'wallet-2-fill', + 'wallet-2-line', + 'wallet-3-fill', + 'wallet-3-line', + 'wallet-fill', + 'wallet-line', + 'water-flash-fill', + 'water-flash-line', + 'webcam-fill', + 'webcam-line', + 'wechat-2-fill', + 'wechat-2-line', + 'wechat-fill', + 'wechat-line', + 'wechat-pay-fill', + 'wechat-pay-line', + 'weibo-fill', + 'weibo-line', + 'whatsapp-fill', + 'whatsapp-line', + 'wheelchair-fill', + 'wheelchair-line', + 'wifi-fill', + 'wifi-line', + 'wifi-off-fill', + 'wifi-off-line', + 'window-2-fill', + 'window-2-line', + 'window-fill', + 'window-line', + 'windows-fill', + 'windows-line', + 'windy-fill', + 'windy-line', + 'wireless-charging-fill', + 'wireless-charging-line', + 'women-fill', + 'women-line', + 'wubi-input', + 'xbox-fill', + 'xbox-line', + 'xing-fill', + 'xing-line', + 'youtube-fill', + 'youtube-line', + 'zcool-fill', + 'zcool-line', + 'zhihu-fill', + 'zhihu-line', + 'zoom-in-fill', + 'zoom-in-line', + 'zoom-out-fill', + 'zoom-out-line', + 'zzz-fill', + 'zzz-line', +] + +module.exports = [ + { + url: '/defaultIcon/getList', + type: 'get', + response(config) { + const { title, pageNo = 1, pageSize = 72 } = config.query + const mockList = List.filter( + (item) => !(title && !item.includes(title)) + ) + const list = mockList.filter( + (item, index) => + index < pageSize * pageNo && + index >= pageSize * (pageNo - 1) + ) + return { + code: 200, + msg: 'success', + data: { list, ...{ total: mockList.length } }, + } + }, + }, +] diff --git a/mock/controller/departmentManagement.js b/mock/controller/departmentManagement.js new file mode 100644 index 0000000..83ad380 --- /dev/null +++ b/mock/controller/departmentManagement.js @@ -0,0 +1,87 @@ +const List = [ + { + id: 'root', + createTime: '@datetime', + name: '根节点', + order: 0, + children: [ + { + id: '1', + parentId: 'root', + parentName: '根节点', + createTime: '@datetime', + name: '桃花坞', + order: 0, + }, + { + id: '2', + parentId: 'root', + parentName: '根节点', + createTime: '@datetime', + name: '少林寺', + order: 1, + children: [ + { + id: '@uuid', + parentId: '2', + parentName: '少林寺', + createTime: '@datetime', + name: '达摩院', + order: 0, + }, + { + id: '@uuid', + parentId: '2', + parentName: '少林寺', + createTime: '@datetime', + name: '戒律堂', + order: 1, + }, + ], + }, + ], + }, +] + +module.exports = [ + { + url: '/departmentManagement/getList', + type: 'get', + response: (config) => { + const { name, pageNo = 1, pageSize = 20 } = config.query + const mockList = List.filter( + (item) => !(name && !item.name.includes(name)) + ) + const list = mockList.filter( + (item, index) => + index < pageSize * pageNo && + index >= pageSize * (pageNo - 1) + ) + return { + code: 200, + msg: 'success', + data: { list, ...{ total: mockList.length } }, + } + }, + }, + { + url: '/departmentManagement/doEdit', + type: 'post', + response: () => { + return { + code: 200, + msg: '模拟保存成功', + } + }, + }, + { + url: '/departmentManagement/doDelete', + type: 'post', + response: () => { + return { + code: 200, + msg: '模拟删除成功', + } + }, + }, +] diff --git a/mock/controller/dictionaryManagement.js b/mock/controller/dictionaryManagement.js new file mode 100644 index 0000000..fc30a9c --- /dev/null +++ b/mock/controller/dictionaryManagement.js @@ -0,0 +1,114 @@ +module.exports = [ + { + url: '/dictionaryManagement/getTree', + type: 'get', + response() { + return { + code: 200, + msg: 'success', + data: { + total: 999, + list: [ + { + id: 'root', + key: 'root', + label: '全部字典', + children: [ + { + id: '@id', + key: 'sex', + label: '性别', + }, + { + id: '@id', + key: 'type', + label: '类型', + }, + ], + }, + ], + }, + } + }, + }, + { + url: '/dictionaryManagement/getList', + type: 'get', + response: (config) => { + const { key, parentKey } = config.query + const list1 = [ + { + parentKey: 'sex', + id: '@id', + lable: '性别', + key: '1', + value: '男', + }, + { + parentKey: 'sex', + id: '@id', + lable: '性别', + key: '2', + value: '女', + }, + ] + const list2 = [ + { + parentKey: 'type', + id: '@id', + lable: '类型', + key: '1', + value: '新闻', + }, + { + parentKey: 'type', + id: '@id', + lable: '类型', + key: '2', + value: '知识', + }, + ] + if (parentKey) { + return { + code: 200, + msg: 'success', + data: { + list: parentKey === 'sex' ? list1 : list2, + }, + } + } + return { + code: 200, + msg: 'success', + data: { + list: + !key || key === 'root' + ? [] + : key === 'sex' + ? list1 + : list2, + }, + } + }, + }, + { + url: '/dictionaryManagement/doEdit', + type: 'post', + response: () => { + return { + code: 200, + msg: '模拟保存成功', + } + }, + }, + { + url: '/dictionaryManagement/doDelete', + type: 'post', + response: () => { + return { + code: 200, + msg: '模拟删除成功', + } + }, + }, +] diff --git a/mock/controller/goods.js b/mock/controller/goods.js new file mode 100644 index 0000000..bb9d1b2 --- /dev/null +++ b/mock/controller/goods.js @@ -0,0 +1,115 @@ +const List = [ + { + uuid: '@uuid', + image: 'https://cn.vitejs.dev/logo-with-shadow.png', + title: 'Shop Vite', + price: '敬请期待', + label: ['极简', 'vite'], + company: 'vdp', + url: 'https://vuejs-core.cn/shop-vite', + description: '全新一代前端框架', + }, + { + uuid: '@uuid', + icon: 'dashboard-2-line', + title: 'Dash' + 'board Pro', + price: 'Admin Pro + Admin Plus 1299版' + '本赠品', + label: ['敬请期待', '人工智能', '科技风'], + company: 'vdp', + url: 'https://vuejs-core.cn/dashboard-pro', + description: 'Admin Pro + Adm' + 'in Plus 1299版本赠品', + }, + { + uuid: '@uuid', + image: + 'https://p3-armor.byteimg.com/tos-cn-i-49unhts6dw/dfdba' + + '5317c0c20ce20e64fac8' + + '03d52bc.svg~tplv-49unhts6dw-image.image', + title: 'vue-admin-arco', + price: '免费', + label: ['vue3', 'arco-design', 'MIT协议'], + company: 'vab', + url: 'https://github.com/zxwk1998/vue-admin-arco', + description: + '在字节跳动' + + 'arco-desi' + + 'gn-pro-vue基础上修改的' + + 'vue3版本,仅供学' + + '习参考', + }, + { + uuid: '@uuid', + svg: 'https://gcore.jsdelivr.net/gh/zxwk1998/image/logo/vab.svg', + title: 'vue-admin-better', + price: '免费', + label: ['vue', 'element-ui', 'MIT协议'], + company: 'vab', + url: 'https://github.com/zxwk1998/vue-admin-better', + description: '绝佳的开源、' + '企业级、' + '中后台前端框架', + }, + { + uuid: '@uuid', + svg: 'https://gcore.jsdelivr.net/gh/zxwk1998/image/logo/vdb.svg', + title: 'vue-datav-beautiful-pro', + price: 'Admin Pro + Adm' + 'in Plus 1299版本赠品', + label: ['数据大屏'], + company: 'vdb', + url: 'https://github.com/vue-datav-beautiful', + description: '立志做' + '国内最好' + '的数据大屏应用', + }, + { + uuid: '@uuid', + image: 'https://xuqu.gitee.io/common/logo.png', + title: 'uview', + price: '免费', + label: ['uniapp', '跨平台', '组件'], + company: '言信网络', + url: 'http://uviewui.com', + description: + '跨 7 端移动端框架,全面的组件和便' + + '捷的工具会让您信手拈来,如鱼得水', + }, + { + uuid: '@uuid', + title: 'form-generator', + image: 'https://mrhj.gitee.io/form-generator/img/logo.e1bc3747.png', + price: '免费', + label: ['element-ui', '表单设计器'], + company: 'form-generator', + url: 'https://mrhj.gitee.io/form-generator', + description: 'Element UI表单设' + '计及代码生成器', + }, + { + uuid: '@uuid', + title: 'OPSLI', + image: 'https://www.opsli.com/static/images/favicon.ico', + price: '免费', + label: ['spring-boot', 'vue-admin-better'], + company: 'OPSLI', + url: 'https://www.op' + 'sli.com', + description: 'vue-admin-better开源' + '版结合spring boot的最佳实践', + }, +] + +module.exports = [ + { + url: '/goods/getList', + type: 'get', + response(config) { + const { title, pageNo = 1, pageSize = 20 } = config.query + const mockList = List.filter( + (item) => !(title && !item.title.includes(title)) + ) + const list = mockList.filter( + (item, index) => + index < pageSize * pageNo && + index >= pageSize * (pageNo - 1) + ) + return { + code: 200, + msg: 'success', + data: { list, ...{ total: mockList.length } }, + } + }, + }, +] diff --git a/mock/controller/menuManagement.js b/mock/controller/menuManagement.js new file mode 100644 index 0000000..8ab3fdb --- /dev/null +++ b/mock/controller/menuManagement.js @@ -0,0 +1,53 @@ +module.exports = [ + { + url: '/menuManagement/getTree', + type: 'get', + response() { + return { + code: 200, + msg: 'success', + data: { + total: 999, + list: [ + { + id: 'root', + label: '全部角色', + children: [ + { + id: '@id', + role: 'admin', + label: 'admin角色', + }, + { + id: '@id', + role: 'editor', + label: 'editor角色', + }, + ], + }, + ], + }, + } + }, + }, + { + url: '/menuManagement/doEdit', + type: 'post', + response() { + return { + code: 200, + msg: '模拟保存成功', + } + }, + }, + { + url: '/menuManagement/doDelete', + type: 'post', + response() { + return { + code: 200, + msg: '模拟删除成功', + } + }, + }, +] diff --git a/mock/controller/notice.js b/mock/controller/notice.js new file mode 100644 index 0000000..14b3ab6 --- /dev/null +++ b/mock/controller/notice.js @@ -0,0 +1,36 @@ +const List = [ + { + email: '@email', + image: 'https://i.gtimg.cn/club/item/face/img/8/15918_100.gif', + notice: 'Github开源地址:点我', + }, + { + email: '@email', + image: 'https://i.gtimg.cn/club/item/face/img/0/15640_100.gif', + notice: 'Admin Pro:点我', + }, + { + email: '@email', + image: 'https://i.gtimg.cn/club/item/face/img/9/15919_100.gif', + notice: 'Admin Plus:点我', + }, + { + email: '@email', + image: 'https://i.gtimg.cn/club/item/face/img/8/15918_100.gif', + notice: 'Shop Vite:点我', + }, +] + +module.exports = [ + { + url: '/notice/getList', + type: 'get', + response: () => { + return { + code: 200, + msg: 'success', + data: { list: List, total: List.length }, + } + }, + }, +] diff --git a/mock/controller/refreshToken.js b/mock/controller/refreshToken.js new file mode 100644 index 0000000..e76a320 --- /dev/null +++ b/mock/controller/refreshToken.js @@ -0,0 +1,46 @@ +const { Random } = require('mockjs') + +module.exports = [ + { + url: '/expireToken', + type: 'get', + response: (config) => { + const authorization = + config.headers.authorization || config.headers.Authorization + const arr = authorization.split('-') + const tokenTime = parseInt(arr[arr.length - 1]) + + if (Date.now() - tokenTime > 5000) + return { + code: 402, + msg: '令牌已过期', + } + else + return { + code: 200, + msg: '令牌未过期', + } + }, + }, + { + url: '/refreshToken', + type: 'get', + response: (config) => { + const authorization = + config.headers.authorization || config.headers.Authorization + let token = '' + if (authorization.includes('admin-token')) + token = `admin-token-${Random.guid()}-${Date.now()}` + if (authorization.includes('editor-token')) + token = `editor-token-${Random.guid()}-${Date.now()}` + if (authorization.includes('test-token')) + token = `test-token-${Random.guid()}-${Date.now()}` + + return { + code: 200, + msg: '刷新Token成功', + data: { token }, + } + }, + }, +] diff --git a/mock/controller/roleManagement.js b/mock/controller/roleManagement.js new file mode 100644 index 0000000..f8ec921 --- /dev/null +++ b/mock/controller/roleManagement.js @@ -0,0 +1,55 @@ +const List = [ + { + id: '@id', + role: 'admin', + btnRolesCheckedList: ['read:system', 'write:system', 'delete:system'], + }, + { + id: '@id', + role: 'editor', + btnRolesCheckedList: ['read:system', 'write:system'], + }, +] + +module.exports = [ + { + url: '/roleManagement/getList', + type: 'get', + response(config) { + const { role, pageNo = 1, pageSize = 20 } = config.query + const mockList = List.filter( + (item) => !(role && !item.title.includes(role)) + ) + const list = mockList.filter( + (item, index) => + index < pageSize * pageNo && + index >= pageSize * (pageNo - 1) + ) + return { + code: 200, + msg: 'success', + data: { list, ...{ total: mockList.length } }, + } + }, + }, + { + url: '/roleManagement/doEdit', + type: 'post', + response() { + return { + code: 200, + msg: '模拟保存成功', + } + }, + }, + { + url: '/roleManagement/doDelete', + type: 'post', + response() { + return { + code: 200, + msg: '模拟删除成功', + } + }, + }, +] diff --git a/mock/controller/router.js b/mock/controller/router.js new file mode 100644 index 0000000..d687f2c --- /dev/null +++ b/mock/controller/router.js @@ -0,0 +1,1019 @@ +/** + * @description router全局配置,如有必要可分文件抽离,其中asyncRoutes只有在intelligence模式下才会用到,pro版只支持remixIcon图标,具体配置请查看vip群文档 + */ +const List = [ + { + path: '/', + name: 'Root', + component: 'Layout', + meta: { + title: '首页', + icon: 'home-2-line', + breadcrumbHidden: true, + }, + children: [ + { + path: 'index', + name: 'Index', + component: '@/views/index/index', + meta: { + title: '首页', + icon: 'home-2-line', + noClosable: true, + }, + }, + { + path: 'dashboard', + name: 'Dashboard', + component: '@/views/index/dashboard', + meta: { + title: '看板', + icon: 'dashboard-line', + }, + }, + { + path: 'workbench', + name: 'Workbench', + component: '@/views/index/workbench', + meta: { + title: '工作台', + icon: 'settings-6-line', + dot: true, + }, + }, + { + path: 'store', + name: 'Store', + component: '@/views/index/store', + meta: { + title: '仓库', + icon: 'app-store-line', + dot: true, + }, + }, + { + path: 'pricing', + name: 'Pricing', + component: '@/views/index/Pricing.vue', + meta: { + title: '授权与定价', + guard: ['Admin'], + icon: 'price-tag-3-line', + badge: 'Hot', + }, + }, + { + path: 'friendly-tip', + name: 'FriendlyTip', + component: '@/views/index/FriendlyTip.vue', + meta: { + title: '温馨提示', + icon: 'information-line', + hidden: true, + }, + }, + ], + }, + { + path: '/vab', + name: 'Vab', + component: 'Layout', + meta: { + title: '组件', + icon: 'code-box-line', + }, + children: [ + { + path: 'icon', + name: 'Icon', + meta: { + title: '图标', + icon: 'remixicon-line', + }, + children: [ + { + path: 'defaultIcon', + name: 'DefaultIcon', + component: '@/views/vab/icon/defaultIcon', + meta: { + title: '默认图标', + }, + }, + { + path: 'iconSelector', + name: 'IconSelector', + component: '@/views/vab/icon/iconSelector', + meta: { + title: '图标选择器', + }, + }, + { + path: 'customSvg', + name: 'CustomSvg', + component: '@/views/vab/icon/customSvg', + meta: { + title: '自定义图标', + }, + }, + ], + }, + { + path: 'permission', + name: 'Permission', + component: '@/views/vab/permission/index', + meta: { + title: '角色权限', + icon: 'user-3-line', + badge: 'Pro', + }, + }, + { + path: 'table', + name: 'Table', + meta: { + title: '表格', + // 非editor角色的用户可见 + guard: { + role: ['Editor'], + mode: 'except', + }, + icon: 'table-2', + }, + children: [ + { + path: 'comprehensiveTable', + name: 'ComprehensiveTable', + component: '@/views/vab/table/comprehensiveTable', + meta: { + title: '综合表格', + }, + }, + { + path: 'detail', + name: 'Detail', + component: '@/views/vab/table/detail', + meta: { + hidden: true, + title: '详情页', + activeMenu: '/vab/table/comprehensiveTable', + dynamicNewTab: true, //详情页根据id传参不同可打开多个 + }, + }, + { + path: 'inlineEditTable', + name: 'InlineEditTable', + component: '@/views/vab/table/inlineEditTable', + meta: { + title: '行内编辑表格', + noKeepAlive: true, + }, + }, + { + path: 'customTable', + name: 'CustomTable', + component: '@/views/vab/table/customTable', + meta: { + title: '自定义表格', + }, + }, + { + path: 'dynamicTable', + name: 'DynamicTable', + component: '@/views/vab/table/dynamicTable', + meta: { + title: '动态表格', + badge: 'New', + }, + }, + ], + }, + { + path: 'list', + name: 'List', + component: '@/views/vab/list/index', + meta: { + title: '列表', + guard: ['Admin'], + icon: 'list-check-2', + }, + }, + { + path: 'description', + name: 'Description', + component: '@/views/vab/description/index', + meta: { + title: '描述', + guard: ['Admin'], + icon: 'slideshow-line', + }, + }, + { + path: 'calendar', + name: 'Calendar', + component: '@/views/vab/calendar/index', + meta: { + title: '日历', + guard: ['Admin'], + icon: 'calendar-check-line', + dot: true, + }, + }, + { + path: 'editor', + name: 'Editor', + meta: { + title: '编辑器', + guard: ['Admin'], + icon: 'edit-2-line', + }, + children: [ + { + path: 'wangEditor', + name: 'WangEditor', + component: '@/views/vab/editor/wangEditor', + meta: { + title: '腾讯文档', + guard: ['Admin'], + dot: true, + }, + }, + ], + }, + { + path: 'form', + name: 'Form', + meta: { + title: '表单', + guard: ['Admin'], + icon: 'file-list-2-line', + }, + children: [ + { + path: 'comprehensiveForm', + name: 'ComprehensiveForm', + component: '@/views/vab/form/comprehensiveForm', + meta: { + title: '综合表单', + }, + }, + { + path: 'stepForm', + name: 'StepForm', + component: '@/views/vab/form/stepForm', + meta: { + title: '分步表单', + }, + }, + { + path: 'button', + name: 'Button', + component: '@/views/vab/form/button', + meta: { + title: '按钮', + }, + }, + { + path: 'link', + name: 'Link', + component: '@/views/vab/form/link', + meta: { + title: '文字链接', + }, + }, + { + path: 'radio', + name: 'Radio', + component: '@/views/vab/form/radio', + meta: { + title: '单选框', + }, + }, + { + path: 'checkbox', + name: 'Checkbox', + component: '@/views/vab/form/checkbox', + meta: { + title: '多选框', + }, + }, + { + path: 'input', + name: 'Input', + component: '@/views/vab/form/input', + meta: { + title: '输入框', + }, + }, + { + path: 'inputNumber', + name: 'InputNumber', + component: '@/views/vab/form/inputNumber', + meta: { + title: '计数器', + }, + }, + { + path: 'select', + name: 'Select', + component: '@/views/vab/form/select', + meta: { + title: '选择器', + dot: true, + }, + }, + { + path: 'switch', + name: 'Switch', + component: '@/views/vab/form/switch', + meta: { + title: '开关', + }, + }, + { + path: 'slider', + name: 'Slider', + component: '@/views/vab/form/slider', + meta: { + title: '滑块', + }, + }, + { + path: 'timePicker', + name: 'TimePicker', + component: '@/views/vab/form/timePicker', + meta: { + title: '时间选择器', + }, + }, + { + path: 'datePicker', + name: 'DatePicker', + component: '@/views/vab/form/datePicker', + meta: { + title: '日期选择器', + }, + }, + { + path: 'dateTimePicker', + name: 'DateTimePicker', + component: '@/views/vab/form/dateTimePicker', + meta: { + title: '日期时间选择器', + }, + }, + { + path: 'rate', + name: 'Rate', + component: '@/views/vab/form/rate', + meta: { + title: '评分', + }, + }, + ], + }, + ], + }, + { + path: '/other', + name: 'Other', + component: 'Layout', + meta: { + title: '其他', + icon: 'archive-line', + guard: ['Admin'], + }, + children: [ + { + path: 'workflow', + name: 'Workflow', + component: '@/views/other/workflow/index', + meta: { + title: '工作流', + guard: ['Admin'], + icon: 'flow-chart', + }, + }, + { + path: 'echarts', + name: 'Echarts', + component: '@/views/other/echarts/index', + meta: { + title: '图表', + guard: ['Admin'], + icon: 'bubble-chart-line', + }, + }, + { + path: 'print', + name: 'Print', + component: '@/views/other/print/index', + meta: { + title: '打印', + guard: ['Admin'], + icon: 'printer-line', + }, + }, + { + path: 'cropper', + name: 'Cropper', + component: '@/views/other/cropper/index', + meta: { + title: '头像裁剪', + guard: ['Admin'], + icon: 'crop-line', + }, + }, + { + path: 'notice', + name: 'Notice', + component: '@/views/other/notice/index', + meta: { + title: '通知', + guard: ['Admin'], + icon: 'message-2-line', + }, + }, + { + path: 'timeline', + name: 'Timeline', + component: '@/views/other/timeline/index', + meta: { + title: '时间线', + guard: ['Admin'], + icon: 'time-line', + }, + }, + { + path: 'count', + name: 'Count', + component: '@/views/other/count/index', + meta: { + title: '数字自增长', + guard: ['Admin'], + icon: 'number-9', + }, + }, + { + path: 'tabs', + name: 'Tabs', + component: '@/views/other/tabs/index', + meta: { + title: '多标签', + guard: ['Admin'], + icon: 'bank-card-line', + }, + }, + { + path: 'watermark', + name: 'Watermark', + component: '@/views/other/watermark/index', + meta: { + title: '水印', + guard: ['Admin'], + icon: 'water-flash-line', + dot: true, + }, + }, + { + path: 'share', + name: 'Share', + component: '@/views/other/share/index', + meta: { + title: '分享', + guard: ['Admin'], + icon: 'share-line', + dot: true, + }, + }, + { + path: 'dynamicAnchor', + name: 'DynamicAnchor', + component: '@/views/other/dynamicAnchor/index', + meta: { + title: '动态锚点', + guard: ['Admin'], + icon: 'anchor-line', + badge: 'New', + }, + }, + { + path: 'dynamicMeta', + name: 'DynamicMeta', + component: '@/views/other/dynamicMeta/index', + meta: { + title: '动态Meta', + guard: ['Admin'], + icon: 'notification-badge-line', + badge: '0', + }, + }, + { + path: 'dynamicSegment', + name: 'DynamicSegment', + redirect: '/other/dynamicSegment/test1/1', + meta: { + title: '动态路径参数', + guard: ['Admin'], + icon: 'arrow-left-right-line', + }, + children: [ + { + path: 'test1/:id', + name: 'Test1', + component: '@/views/other/dynamicSegment/test1', + meta: { + hidden: true, + title: 'Params', + dynamicNewTab: true, + }, + }, + { + path: 'test1/1', + name: 'test1/1', + component: '@/views/other/dynamicSegment/test1', + meta: { title: 'Params id=1' }, + }, + { + path: 'test2', + name: 'Test2', + component: '@/views/other/dynamicSegment/test2', + meta: { + hidden: true, + title: 'Query', + dynamicNewTab: true, + }, + }, + { + path: 'test2?id=1', + name: 'test2?id=1', + component: '@/views/other/dynamicSegment/test2', + meta: { title: 'Query id=1' }, + }, + ], + }, + { + path: 'drag', + name: 'Drag', + meta: { + title: '拖拽', + guard: ['Admin'], + icon: 'drag-drop-line', + }, + children: [ + { + path: 'dialogDrag', + name: 'DialogDrag', + component: '@/views/other/drag/dialogDrag', + meta: { + title: '弹窗拖拽', + dot: true, + }, + }, + { + path: 'cardDrag', + name: 'CardDrag', + component: '@/views/other/drag/cardDrag', + meta: { + title: '卡片拖拽', + }, + }, + ], + }, + { + path: 'noLayout', + name: 'NoLayout', + component: '@/views/other/noLayout/index', + meta: { + title: '无框', + guard: ['Admin'], + icon: 'aspect-ratio-line', + dot: true, + }, + }, + { + path: 'player', + name: 'Player', + component: '@/views/other/player/index', + meta: { + title: '视频播放器', + guard: ['Admin'], + icon: 'video-line', + noKeepAlive: true, + }, + }, + { + path: 'upload', + name: 'Upload', + component: '@/views/other/upload/index', + meta: { + title: '上传', + guard: ['Admin'], + icon: 'chat-upload-line', + }, + }, + { + path: 'menu1', + name: 'Menu1', + meta: { + title: '多级路由缓存', + guard: ['Admin'], + icon: 'route-line', + }, + children: [ + { + path: 'menu1-1', + name: 'Menu11', + meta: { + title: '多级路由1-1', + }, + children: [ + { + path: 'menu1-1-1', + name: 'Menu111', + meta: { + title: '多级路由1-1-1', + }, + children: [ + { + path: 'menu1-1-1-1', + name: 'Menu1111', + meta: { + title: '多级路由1-1-1-1', + }, + component: + '@/views/other/nested/menu1/menu1-1/menu1-1-1/menu1-1-1-1/index', + }, + ], + }, + ], + }, + ], + }, + { + path: 'log', + name: 'Log', + component: '@/views/other/errorLog/index', + meta: { + title: '错误日志模拟', + guard: ['Admin'], + icon: 'error-warning-line', + }, + }, + { + path: 'cssfx', + name: 'Cssfx', + component: '@/views/other/cssfx/index', + meta: { + title: 'Css动画', + guard: ['Admin'], + icon: 'css3-line', + }, + }, + { + path: 'social', + name: 'Social', + component: '@/views/other/social/index', + meta: { + title: '第三方登录', + guard: ['Admin'], + icon: 'github-fill', + }, + }, + // { + // path: 'mobilePreview', + // name: 'MobilePreview', + // component: '@/views/vab/mobilePreview', + // meta: { + // title: '手机预览', + // guard: ['Admin'], + // icon: 'smartphone-line', + // }, + // }, + { + path: '//github.com/zxwk1998/vue-admin-better', + name: 'ExternalLink', + meta: { + title: '外链', + target: '_blank', + // 等价guard: ['Admin', 'Editor'], + guard: { + role: ['Admin', 'Editor'], + mode: 'oneOf', + }, + icon: 'external-link-line', + }, + }, + { + path: 'iframe', + name: 'Iframe', + redirect: '/other/iframe/search', + meta: { + title: 'Iframe', + guard: ['Admin'], + icon: 'window-line', + }, + children: [ + { + path: 'view', + name: 'IframeView', + component: '@/views/other/iframe/view', + meta: { + hidden: true, + title: 'Iframe', + icon: 'window-line', + dynamicNewTab: true, + }, + }, + { + path: 'view?url=www.so.com&title=360%E6%90%9C%E7%B4%A2&icon=search-2-line', + name: 'Search360Iframe', + meta: { title: '360搜索', icon: 'search-2-line' }, + }, + { + path: 'view?url=www.bilibili.com&title=%E5%93%94%E5%93%A9%E5%93%94%E5%93%A9&icon=bilibili-line', + name: 'BiliBiliIframe', + meta: { title: '哔哩哔哩', icon: 'bilibili-line' }, + }, + { + path: 'search', + name: 'IframeSearch', + component: '@/views/other/iframe/search', + meta: { + title: '自定义Iframe', + icon: 'search-2-line', + }, + }, + ], + }, + { + path: 'excel', + name: 'Excel', + meta: { + title: 'Excel', + guard: ['Admin'], + icon: 'file-excel-2-line', + }, + children: [ + { + path: 'exportExcel', + name: 'ExportExcel', + component: '@/views/other/excel/exportExcel', + meta: { + title: '导出Excel', + }, + }, + { + path: 'exportSelectedExcel', + name: 'SelectExcel', + component: '@/views/other/excel/exportSelectExcel', + meta: { + title: '导出选中行Excel', + }, + }, + { + path: 'exportMergeHeaderExcel', + name: 'MergeHeaderExcel', + component: '@/views/other/excel/exportMergeHeaderExcel', + meta: { + title: '导出合并Excel', + }, + }, + ], + }, + ], + }, + { + path: '/mall', + name: 'Mall', + component: 'Layout', + meta: { + title: '物料源', + icon: 'apps-line', + levelHidden: true, + guard: ['Admin'], + }, + children: [ + { + path: 'goods', + name: 'Goods', + component: '@/views/mall/goods/index', + meta: { + title: '物料市场', + icon: 'shopping-cart-line', + badge: 'Hot', + }, + }, + ], + }, + { + path: '/noColumn', + name: 'NoColumn', + component: 'Layout', + meta: { + title: '无分栏', + icon: 'delete-column', + guard: ['Admin'], + breadcrumbHidden: true, + }, + children: [ + { + path: 'deleteColumn', + name: 'DeleteColumn', + component: '@/views/noColumn/deleteColumn/index', + meta: { + title: '无分栏', + icon: 'delete-column', + noColumn: true, + }, + }, + ], + }, + { + path: '/setting', + name: 'PersonnelManagement', + component: 'Layout', + meta: { + title: '配置', + icon: 'user-settings-line', + guard: ['Admin'], + }, + children: [ + { + path: 'personalCenter', + name: 'PersonalCenter', + component: '@/views/setting/personalCenter/index', + meta: { + title: '个人中心', + icon: 'map-pin-user-line', + }, + }, + { + path: 'userManagement', + name: 'UserManagement', + component: '@/views/setting/userManagement/index', + meta: { + title: '用户管理', + icon: 'user-3-line', + }, + }, + { + path: 'roleManagement', + name: 'RoleManagement', + component: '@/views/setting/roleManagement/index', + meta: { + title: '角色管理', + icon: 'admin-line', + }, + }, + { + path: 'departmentManagement', + name: 'DepartmentManagement', + component: '@/views/setting/departmentManagement/index', + meta: { + title: '部门管理', + icon: 'group-line', + }, + }, + { + path: 'menuManagement', + name: 'MenuManagement', + component: '@/views/setting/menuManagement/index', + meta: { + title: '菜单管理', + icon: 'menu-2-fill', + }, + }, + { + path: 'dictionaryManagement', + name: 'DictionaryManagement', + component: '@/views/setting/dictionaryManagement/index', + meta: { + title: '字典管理', + icon: 'book-2-line', + dot: true, + }, + }, + { + path: 'taskManagement', + name: 'TaskManagement', + component: '@/views/setting/taskManagement/index', + meta: { + title: '任务管理', + icon: 'task-line', + badge: 'New', + }, + }, + { + path: 'systemLog', + name: 'SystemLog', + component: '@/views/setting/systemLog/index', + meta: { + title: '系统日志', + icon: 'file-shield-2-line', + }, + }, + ], + }, + { + path: '/tools', + name: 'Tools', + component: 'Layout', + meta: { + title: '工具', + icon: 'tools-line', + levelHidden: true, + guard: ['Admin'], + }, + children: [ + { + path: 'eyeDropper', + name: 'EyeDropper', + component: '@/views/tools/EyeDropper.vue', + meta: { + title: '取色器', + icon: 'contrast-drop-line', + }, + }, + { + path: 'speechSynthesis', + name: 'SpeechSynthesis', + component: '@/views/tools/SpeechSynthesis.vue', + meta: { + title: '语音合成', + icon: 'customer-service-line', + }, + }, + ], + }, + { + path: '//github.com/zxwk1998/vue-admin-better', + name: 'Github', + component: 'Layout', + meta: { + title: '外链', + icon: 'external-link-line', + guard: ['Admin'], + target: '_blank', + breadcrumbHidden: true, + noColumn: true, + }, + children: [ + { + path: '//github.com/zxwk1998/vue-admin-better', + name: 'GithubExternalLink', + component: '@/views/github/githubExternalLink/index', + meta: { + title: '外链', + icon: 'external-link-line', + noColumn: true, + target: '_blank', + }, + }, + ], + }, + + { + path: '/error', + name: 'Error', + component: 'Layout', + meta: { + title: '错误页', + icon: 'error-warning-line', + levelHidden: true, + }, + children: [ + { + path: '403', + name: 'Error403', + component: '@/views/403', + meta: { + title: '403', + icon: 'error-warning-line', + }, + }, + { + path: '404', + name: 'Error404', + component: '@/views/404', + meta: { + title: '404', + icon: 'error-warning-line', + }, + }, + ], + }, +] + +module.exports = [ + { + url: '/router/getList', + type: 'get', + response() { + return { + code: 200, + msg: 'success', + data: { list: List }, + } + }, + }, +] diff --git a/mock/controller/search.js b/mock/controller/search.js new file mode 100644 index 0000000..a9735c3 --- /dev/null +++ b/mock/controller/search.js @@ -0,0 +1,20 @@ +const List = [ + { + url: 'https://www.bing.com/search?q=vue+admin+plus%e5%ae%98%e7%bd%91&qs=HS&pq=vue+admin+plus&sk=HS1&sc=10-14&cvid=B01F4326D6724F76B568CBF127648BB8&FORM=QBRE&sp=2&lq=0&rdr=1&rdrig=7414F5AB9CF241C78B8CC476818B3569', + value: '官网', + }, +] + +module.exports = [ + { + url: '/search/getList', + type: 'get', + response: () => { + return { + code: 200, + msg: 'success', + data: { list: List }, + } + }, + }, +] diff --git a/mock/controller/systemLog.js b/mock/controller/systemLog.js new file mode 100644 index 0000000..a886e6b --- /dev/null +++ b/mock/controller/systemLog.js @@ -0,0 +1,47 @@ +const { mock } = require('mockjs') + +const List = [] +const count = 50 +for (let i = 0; i < count; i++) { + List.push( + mock({ + uuid: '@uuid', + id: '@id', + account: '@account(1, 2)', + 'type|1': ['操作日志', '数据库日志', '系统日志'], + 'account|1': ['admin', 'editor', 'test'], + 'executeResult|1': [ + '登录成功', + '登录成功', + '登录失败', + '接口异常', + 'dos攻击', + ], + ip: '@ip', + datetime: '@datetime', + }) + ) +} + +module.exports = [ + { + url: '/systemLog/getList', + type: 'get', + response: (config) => { + const { account, pageNo = 1, pageSize = 20 } = config.query + const mockList = List.filter( + (item) => !(account && !item.account.includes(account)) + ) + const list = mockList.filter( + (item, index) => + index < pageSize * pageNo && + index >= pageSize * (pageNo - 1) + ) + return { + code: 200, + msg: 'success', + data: { list, ...{ total: mockList.length } }, + } + }, + }, +] diff --git a/mock/controller/table.js b/mock/controller/table.js new file mode 100644 index 0000000..5245b9c --- /dev/null +++ b/mock/controller/table.js @@ -0,0 +1,68 @@ +const { mock } = require('mockjs') +const { handleRandomImage } = require('../utils') + +const List = [] +const count = 50 +for (let i = 0; i < count; i++) { + List.push( + mock({ + uuid: '@uuid', + id: '@id', + title: '@title(1, 2)', + description: '@csentence', + 'status|1': ['published', 'draft', 'deleted'], + author: '@cname', + datetime: '@datetime', + pageViews: '@integer(300, 5000)', + img: handleRandomImage(228, 228), + switch: '@boolean', + percent: '@integer(80,99)', + 'rate|1': [1, 2, 3, 4, 5], + 'type|1': [0, 1], + percentage: '@integer(0,100)', + }) + ) +} + +module.exports = [ + { + url: '/table/getList', + type: 'get', + response(config) { + const { title, pageNo = 1, pageSize = 20 } = config.query + const mockList = List.filter( + (item) => !(title && !item.title.includes(title)) + ) + const list = mockList.filter( + (item, index) => + index < pageSize * pageNo && + index >= pageSize * (pageNo - 1) + ) + return { + code: 200, + msg: 'success', + data: { list, ...{ total: mockList.length } }, + } + }, + }, + { + url: '/table/doEdit', + type: 'post', + response() { + return { + code: 200, + msg: '模拟保存成功', + } + }, + }, + { + url: '/table/doDelete', + type: 'post', + response() { + return { + code: 200, + msg: '模拟删除成功', + } + }, + }, +] diff --git a/mock/controller/taskManagement.js b/mock/controller/taskManagement.js new file mode 100644 index 0000000..ec8ebb7 --- /dev/null +++ b/mock/controller/taskManagement.js @@ -0,0 +1,47 @@ +const { mock } = require('mockjs') + +const List = [] +const count = 50 +for (let i = 0; i < count; i++) { + List.push( + mock({ + uuid: '@uuid', + id: '@id', + taskName: '@account(1, 2)', + 'status|1': [0, 1], + 'account|1': ['admin', 'editor', 'test'], + 'executeResult|1': [ + '登录成功', + '登录成功', + '登录失败', + '接口异常', + 'dos攻击', + ], + ip: '@ip', + datetime: '@datetime', + }) + ) +} + +module.exports = [ + { + url: '/taskManagement/getList', + type: 'get', + response: (config) => { + const { account, pageNo = 1, pageSize = 20 } = config.query + const mockList = List.filter( + (item) => !(account && !item.account.includes(account)) + ) + const list = mockList.filter( + (item, index) => + index < pageSize * pageNo && + index >= pageSize * (pageNo - 1) + ) + return { + code: 200, + msg: 'success', + data: { list, ...{ total: mockList.length } }, + } + }, + }, +] diff --git a/mock/controller/user.js b/mock/controller/user.js new file mode 100644 index 0000000..0e903d4 --- /dev/null +++ b/mock/controller/user.js @@ -0,0 +1,125 @@ +const { Random } = require('mockjs') + +const tokens = { + admin: `admin-token-${Random.guid()}-${Date.now()}`, + editor: `editor-token-${Random.guid()}-${Date.now()}`, + test: `test-token-${Random.guid()}-${Date.now()}`, +} +const username2role = { + admin: ['Admin'], + editor: ['Editor'], + test: ['Admin', 'Editor'], +} +const role2permission = { + Admin: ['read:system', 'write:system', 'delete:system'], + Editor: ['read:system', 'write:system'], + Test: ['read:system'], +} + +module.exports = [ + { + url: '/publicKey', + type: 'get', + response() { + return { + code: 200, + msg: 'success', + data: { + mockServer: true, + publicKey: + 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBT2vr+dhZElF73FJ6xiP181txKWUSNLPQQlid6DUJhGAOZblluafIdLmnUyKE8mMHhT3R+Ib3ssZcJku6Hn72yHYj/qPkCGFv0eFo7G+GJfDIUeDyalBN0QsuiE/XzPHJBuJDfRArOiWvH0BXOv5kpeXSXM8yTt5Na1jAYSiQ/wIDAQAB', + }, + } + }, + }, + { + url: '/login', + type: 'post', + response(config) { + const { username } = config.body + const token = tokens[username] + if (!token) + return { + code: 500, + msg: '帐户或密码不正确', + } + return { + code: 200, + msg: 'success', + data: { token }, + } + }, + }, + { + url: '/socialLogin', + type: 'post', + response(config) { + const { code } = config.body + if (!code) + return { + code: 500, + msg: '未成功获取Token', + } + + return { + code: 200, + msg: 'success', + data: { token: tokens['admin'] }, + } + }, + }, + { + url: '/register', + type: 'post', + response() { + return { + code: 200, + msg: '模拟注册成功', + data: { token: tokens['editor'] }, + } + }, + }, + { + url: '/userInfo', + type: 'get', + response(config) { + const authorization = + config.headers.authorization || config.headers.Authorization + if (!authorization.startsWith('Bearer ')) + return { + code: 401, + msg: '令牌无效', + } + const _authorization = authorization.replace('Bearer ', '') + const isTrue = _authorization.includes('-token-') + const username = isTrue + ? _authorization.split('-token-')[0] + : 'admin' + const roles = username2role[username] || [] + const permissions = [ + ...new Set(roles.flatMap((role) => role2permission[role])), + ] + + return { + code: 200, + msg: 'success', + data: { + username, + roles, + permissions, + avatar: 'https://i.gtimg.cn/club/item/face/img/2/16022_100.gif', + }, + } + }, + }, + { + url: '/logout', + type: 'get', + response() { + return { + code: 200, + msg: 'success', + } + }, + }, +] diff --git a/mock/controller/userManagement.js b/mock/controller/userManagement.js new file mode 100644 index 0000000..6ae4822 --- /dev/null +++ b/mock/controller/userManagement.js @@ -0,0 +1,69 @@ +const List = [ + { + id: '@id', + username: 'admin', + password: 'admin', + email: '@email', + roles: ['admin'], + datatime: '@datetime', + }, + { + id: '@id', + username: 'editor', + password: 'editor', + email: '@email', + roles: ['editor'], + datatime: '@datetime', + }, + { + id: '@id', + username: 'test', + password: 'test', + email: '@email', + roles: ['admin', 'editor'], + datatime: '@datetime', + }, +] + +module.exports = [ + { + url: '/userManagement/getList', + type: 'get', + response(config) { + const { username, pageNo = 1, pageSize = 20 } = config.query + const mockList = List.filter( + (item) => !(username && !item.username.includes(username)) + ) + const list = mockList.filter( + (item, index) => + index < pageSize * pageNo && + index >= pageSize * (pageNo - 1) + ) + return { + code: 200, + msg: 'success', + data: { list, ...{ total: mockList.length } }, + } + }, + }, + { + url: '/userManagement/doEdit', + type: 'post', + response() { + return { + code: 200, + msg: '模拟保存成功', + } + }, + }, + { + url: '/userManagement/doDelete', + type: 'post', + response() { + return { + code: 200, + msg: '模拟删除成功', + } + }, + }, +] diff --git a/mock/controller/workflow.js b/mock/controller/workflow.js new file mode 100644 index 0000000..779d701 --- /dev/null +++ b/mock/controller/workflow.js @@ -0,0 +1,365 @@ +const data = { + nodes: [ + { + id: '742356ea-762b-4899-b96a-bd567e3c4361', + type: 'start', + x: 220, + y: 170, + properties: {}, + baseType: 'node', + }, + { + id: 'dacda6b6-48d3-4dff-911d-287704eb23d8', + type: 'rect', + x: 350, + y: 170, + properties: {}, + baseType: 'node', + text: { + x: 350, + y: 170, + value: '基础节点', + }, + }, + { + id: '49106603-2b88-4b2c-b1e8-723c1f2210bd', + type: 'user', + x: 530, + y: 170, + properties: {}, + baseType: 'node', + text: { + x: 530, + y: 220, + value: '自定义节点', + }, + }, + { + id: '647fa2bc-98ee-40cf-99c5-4756c0bc130d', + type: 'push', + x: 690, + y: 170, + properties: {}, + baseType: 'node', + text: { + x: 690, + y: 220, + value: '可添加下一个节点/节点组', + }, + }, + { + id: '37e7bac3-8804-4237-abe9-7b6065c207e9', + type: 'download', + x: 690, + y: 320, + properties: {}, + baseType: 'node', + }, + { + id: '6bb4396f-54c9-4b1c-b34c-87ef004f2e29', + type: 'user', + x: 840, + y: 320, + properties: {}, + baseType: 'node', + }, + { + id: 'abf76937-63b8-493c-a978-a4a58bc4f6b8', + type: 'push', + x: 840, + y: 470, + properties: {}, + baseType: 'node', + }, + { + id: 'b119f24f-2669-4a90-a837-afd853b2ffcc', + type: 'end', + x: 990, + y: 320, + properties: {}, + baseType: 'node', + }, + { + id: '60326ad9-cae2-4a85-ae98-d340fb7bd67f', + type: 'end', + x: 990, + y: 470, + properties: {}, + baseType: 'node', + }, + { + id: '414fe028-3609-4450-b0f4-e5aca7705e8c', + type: 'download', + x: 860, + y: 170, + properties: {}, + baseType: 'node', + text: { + x: 860, + y: 220, + value: '自定义节点-设置颜色', + }, + }, + ], + edges: [ + { + id: '00f55245-513e-43a2-9cb0-adb61b01adc8', + type: 'polyline', + sourceNodeId: '742356ea-762b-4899-b96a-bd567e3c4361', + targetNodeId: 'dacda6b6-48d3-4dff-911d-287704eb23d8', + startPoint: { + x: 240, + y: 170, + }, + endPoint: { + x: 300, + y: 170, + }, + properties: {}, + pointsList: [ + { + x: 240, + y: 170, + }, + { + x: 300, + y: 170, + }, + ], + }, + { + id: 'bbf9754f-603e-48e4-85fe-84ed44459a6a', + type: 'polyline', + sourceNodeId: 'dacda6b6-48d3-4dff-911d-287704eb23d8', + targetNodeId: '49106603-2b88-4b2c-b1e8-723c1f2210bd', + startPoint: { + x: 400, + y: 170, + }, + endPoint: { + x: 495, + y: 170, + }, + properties: {}, + pointsList: [ + { + x: 400, + y: 170, + }, + { + x: 495, + y: 170, + }, + ], + }, + { + id: '12bb443b-4070-4a08-ad4d-2755ee856f0d', + type: 'polyline', + sourceNodeId: '49106603-2b88-4b2c-b1e8-723c1f2210bd', + targetNodeId: '647fa2bc-98ee-40cf-99c5-4756c0bc130d', + startPoint: { + x: 565, + y: 170, + }, + endPoint: { + x: 655, + y: 170, + }, + properties: {}, + pointsList: [ + { + x: 565, + y: 170, + }, + { + x: 655, + y: 170, + }, + ], + }, + { + id: '33fa3c09-9c29-4cb7-8373-67d537b8b623', + type: 'polyline', + sourceNodeId: '647fa2bc-98ee-40cf-99c5-4756c0bc130d', + targetNodeId: '37e7bac3-8804-4237-abe9-7b6065c207e9', + startPoint: { + x: 690, + y: 205, + }, + endPoint: { + x: 690, + y: 295, + }, + properties: {}, + pointsList: [ + { + x: 690, + y: 205, + }, + { + x: 690, + y: 295, + }, + ], + }, + { + id: '2b5a5e89-005e-4fda-9a44-dc795050534f', + type: 'polyline', + sourceNodeId: '37e7bac3-8804-4237-abe9-7b6065c207e9', + targetNodeId: '6bb4396f-54c9-4b1c-b34c-87ef004f2e29', + startPoint: { + x: 715, + y: 320, + }, + endPoint: { + x: 805, + y: 320, + }, + properties: {}, + pointsList: [ + { + x: 715, + y: 320, + }, + { + x: 805, + y: 320, + }, + ], + }, + { + id: '62b54f8a-bcfd-494b-9144-5aeb09ca77a1', + type: 'polyline', + sourceNodeId: '6bb4396f-54c9-4b1c-b34c-87ef004f2e29', + targetNodeId: 'b119f24f-2669-4a90-a837-afd853b2ffcc', + startPoint: { + x: 875, + y: 320, + }, + endPoint: { + x: 970, + y: 320, + }, + properties: {}, + text: { + x: 920, + y: 310, + value: 'Y', + }, + pointsList: [ + { + x: 875, + y: 320, + }, + { + x: 970, + y: 320, + }, + ], + }, + { + id: 'ba816d4a-5785-4911-9f78-03933f1463a1', + type: 'polyline', + sourceNodeId: '6bb4396f-54c9-4b1c-b34c-87ef004f2e29', + targetNodeId: 'abf76937-63b8-493c-a978-a4a58bc4f6b8', + startPoint: { + x: 840, + y: 355, + }, + endPoint: { + x: 840, + y: 435, + }, + properties: {}, + text: { + x: 850, + y: 400, + value: 'N', + }, + pointsList: [ + { + x: 840, + y: 355, + }, + { + x: 840, + y: 435, + }, + ], + }, + { + id: '2b3007ed-7a13-4db7-a1ea-6691d7564c34', + type: 'polyline', + sourceNodeId: 'abf76937-63b8-493c-a978-a4a58bc4f6b8', + targetNodeId: '60326ad9-cae2-4a85-ae98-d340fb7bd67f', + startPoint: { + x: 875, + y: 470, + }, + endPoint: { + x: 970, + y: 470, + }, + properties: {}, + pointsList: [ + { + x: 875, + y: 470, + }, + { + x: 970, + y: 470, + }, + ], + }, + { + id: '262e2263-6c8c-4a38-b223-97848e9b5767', + type: 'polyline', + sourceNodeId: '647fa2bc-98ee-40cf-99c5-4756c0bc130d', + targetNodeId: '414fe028-3609-4450-b0f4-e5aca7705e8c', + startPoint: { + x: 725, + y: 170, + }, + endPoint: { + x: 835, + y: 170, + }, + properties: {}, + pointsList: [ + { + x: 725, + y: 170, + }, + { + x: 835, + y: 170, + }, + ], + }, + ], +} + +module.exports = [ + { + url: '/workflow/getList', + type: 'get', + response: () => { + return { + code: 200, + msg: 'success', + data, + } + }, + }, + { + url: '/workflow/doEdit', + type: 'post', + response: () => { + return { + code: 200, + msg: '模拟保存成功', + } + }, + }, +] diff --git a/mock/index.js b/mock/index.js new file mode 100644 index 0000000..0ebb361 --- /dev/null +++ b/mock/index.js @@ -0,0 +1,112 @@ +const path = require('path') +const chokidarNext = require('chokidar') +const bodyParser = require('body-parser') +const chalkNext = require('chalk') +const { mock } = require('mockjs') +const { baseURL } = require('../src/config') + +const mockDir = path.join(process.cwd(), 'mock') +const { handleMockArray } = require('./utils') + +/** + * + * @param url + * @param type + * @param respond + * @returns {{response(*=, *=): void, type: (*|string), url: RegExp}} + */ +const responseFake = (url, type, respond) => { + return { + url: new RegExp(`${baseURL}${url}`), + type: type || 'get', + response(req, res) { + res.status(200) + console.log(chalkNext.green(`\n> 请求地址:${req.path}`)) + if (JSON.stringify(req.body) !== '{}') + console.log( + chalkNext.green( + `> 请求参数(body):${JSON.stringify(req.body)}` + ) + ) + if (JSON.stringify(req.query) !== '{}') + console.log( + chalkNext.green( + `> 请求参数(query):${JSON.stringify(req.query)}` + ) + ) + res.json( + mock(respond instanceof Function ? respond(req, res) : respond) + ) + }, + } +} + +/** + * + * @param app + * @returns {{mockStartIndex: number, mockRoutesLength: number}} + */ +const registerRoutes = (app) => { + let mockLastIndex + const mocks = [] + const mockArray = handleMockArray() + mockArray.forEach((item) => { + const obj = require(item) + mocks.push(...obj) + }) + const mocksForServer = mocks.map((route) => + responseFake(route.url, route.type, route.response) + ) + const mockRoutesLength = Object.keys(mocksForServer).length + for (const item of mocksForServer) { + app[item.type](item.url, item.response) + mockLastIndex = app._router.stack.length + } + return { + mockRoutesLength, + mockStartIndex: mockLastIndex - mockRoutesLength, + } +} + +/** + * + * @param middlewares + * @param devServer + */ +module.exports = (middlewares, devServer) => { + if (!devServer) { + throw new Error('webpack-dev-server is not defined') + } + const app = devServer.app + app.use(bodyParser.json()) + app.use( + bodyParser.urlencoded({ + extended: true, + }) + ) + const mockRoutes = registerRoutes(app) + let mockRoutesLength = mockRoutes.mockRoutesLength + let mockStartIndex = mockRoutes.mockStartIndex + chokidarNext + .watch(mockDir, { + ignored: /vab-mock-server/, + ignoreInitial: true, + }) + .on('all', (event) => { + if (event === 'change' || event === 'add') { + try { + app._router.stack.splice(mockStartIndex, mockRoutesLength) + Object.keys(require.cache).forEach((item) => { + if (item.includes(mockDir)) + delete require.cache[require.resolve(item)] + }) + const mockRoutes = registerRoutes(app) + mockRoutesLength = mockRoutes.mockRoutesLength + mockStartIndex = mockRoutes.mockStartIndex + } catch (error) { + console.log(chalkNext.red(error)) + } + } + }) + return middlewares +} diff --git a/mock/utils/index.js b/mock/utils/index.js new file mode 100644 index 0000000..26e3c01 --- /dev/null +++ b/mock/utils/index.js @@ -0,0 +1,39 @@ +const fs = require('fs') +const { Random } = require('mockjs') + +/** + * @description 随机生成图片url。 + * @returns {string} + */ +function handleRandomImage(/* width = 50, height = 50 */) { + //return `https://picsum.photos/${width}/${height}?random=${Random.guid()}` + return ( + 'https://gcore.jsdelivr.net/gh/' + + 'chuzh' + + 'ixin/image' + + `/table/vab-image-${Random.integer(1, 38)}.jpg` + ) +} + +/** + * @description 处理所有 controller 模块,npm run serve时在node环境中自动输出controller文件夹下Mock接口,请勿修改。 + * @returns {[]} + */ +function handleMockArray() { + const getFiles = (path, baseUrl = './controller') => { + const files = fs.readdirSync(path) + return files.flatMap((file) => { + const fPath = `${path}/${file}` + const stat = fs.statSync(fPath) + return stat.isDirectory() + ? getFiles(fPath, `${baseUrl}/${file}`) + : `${baseUrl}/${file}` + }) + } + return getFiles('mock/controller') +} + +module.exports = { + handleRandomImage, + handleMockArray, +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..b016bd3 --- /dev/null +++ b/package.json @@ -0,0 +1,143 @@ +{ + "name": "admin-plus", + "version": "23.0.1", + "private": true, + "author": "github.com/zxwk1998", + "scripts": { + "serve": "cross-env NODE_OPTIONS=--no-warnings vue-cli-service serve", + "build": "cross-env NODE_OPTIONS=--no-warnings vue-cli-service build", + "build:website": "cross-env NODE_OPTIONS=--no-warnings VAB_VARIABLE=website vue-cli-service build && npm run compress:website", + "compress:website": "node scripts/compress.js", + "build:compress": "cross-env NODE_OPTIONS=--no-warnings vue-cli-service build && npm run compress", + "compress": "node scripts/compress.js", + "test:unit": "vue-cli-service test:unit --detectOpenHandles", + "lint": "vue-cli-service lint", + "build:report": "cross-env NODE_OPTIONS=--no-warnings vue-cli-service build --report", + "build:test": "cross-env NODE_OPTIONS=--no-warnings vue-cli-service build --mode test", + "global:install": "npm install -g nrm,cnpm,npm-check-updates,rimraf --registry=https://registry.npmmirror.com", + "global:update": "ncu -g", + "lint:eslint": "eslint {src,mock,library}/**/*.{vue,js,ts} --fix", + "lint:prettier": "prettier {src,mock,library}/**/*.{html,vue,css,sass,scss,js,ts,md} --write", + "lint:stylelint": "stylelint {src,mock,library}/**/*.{vue,css,sass,scss} --fix --cache --cache-location node_modules/.cache/stylelint/", + "module:install": "pnpm i", + "module:reinstall": "rimraf node_modules && npm run module:install", + "module:update": "ncu -u --reject vue-i18n,sass-loader,unplugin-vue-define-options,@logicflow/core,@logicflow/extension,sass,chalk,unplugin-auto-import,unplugin-vue-components,eslint-plugin-vue,eslint --registry=https://registry.npmmirror.com&&npm run module:install", + "nrm:npm": "nrm use npm", + "nrm:taobao": "nrm use taobao", + "template": "plop", + "git": "start ./git.sh" + }, + "dependencies": { + "@element-plus/icons-vue": "^2.3.2", + "@logicflow/core": "2.1.1", + "@logicflow/extension": "2.1.2", + "@vueuse/core": "^14.1.0", + "@vueuse/head": "^2.0.0", + "@wangeditor/editor": "^5.1.23", + "@wangeditor/editor-for-vue": "^5.1.12", + "axios": "^1.13.2", + "core-js": "^3.47.0", + "dayjs": "^1.11.19", + "disable-devtool": "^0.3.9", + "echarts": "^6.0.0", + "element-plus": "^2.13.0", + "file-saver": "^2.0.5", + "image-conversion": "^2.1.1", + "js-cookie": "^3.0.5", + "jsencrypt": "^3.5.4", + "lodash": "^4.17.21", + "mitt": "^3.0.1", + "mockjs": "^1.1.0", + "nprogress": "^0.2.0", + "path-browserify": "^1.0.1", + "pinia": "^3.0.4", + "qs": "^6.14.0", + "register-service-worker": "^1.7.2", + "resize-detector": "^0.3.0", + "vab-icons": "file:vab-icons", + "vue": "^3.5.26", + "vue-i18n": "^11.1.12", + "vue-json-viewer": "^3.0.4", + "vue-qr": "^4.0.9", + "vue-router": "^4.6.4", + "vuedraggable": "^4.0.1", + "xlsx": "0.18.5" + }, + "devDependencies": { + "@babel/core": "^7.28.5", + "@element-plus/eslint-config": "2.13.0", + "@rushstack/eslint-patch": "^1.15.0", + "@types/file-saver": "^2.0.7", + "@types/js-cookie": "^3.0.6", + "@types/lodash-es": "^4.17.12", + "@types/node": "^25.0.3", + "@types/nprogress": "^0.2.3", + "@vue/cli-plugin-babel": "^5.0.9", + "@vue/cli-plugin-eslint": "^5.0.9", + "@vue/cli-plugin-pwa": "^5.0.9", + "@vue/cli-plugin-router": "^5.0.9", + "@vue/cli-plugin-typescript": "^5.0.9", + "@vue/cli-service": "^5.0.9", + "@vue/eslint-config-prettier": "^10.2.0", + "@vue/eslint-config-typescript": "^14.6.0", + "@vue/test-utils": "^2.4.6", + "archiver": "^7.0.1", + "body-parser": "^2.2.1", + "call-rely": "^1.3.4", + "chalk": "4.1.2", + "chokidar": "^5.0.0", + "compression-webpack-plugin": "^11.1.0", + "cross-env": "^10.1.0", + "eslint": "^8.57.0", + "eslint-define-config": "^2.1.0", + "eslint-plugin-prettier": "^5.5.4", + "eslint-plugin-vue": "9.18.1", + "filemanager-webpack-plugin": "^9.0.1", + "image-webpack-loader": "^8.1.0", + "less-loader": "^12.3.0", + "lint-staged": "^16.2.7", + "picocolors": "^1.1.1", + "plop": "^4.0.4", + "plop-templates": "^0.0.9", + "postcss": "^8.5.6", + "postcss-html": "^1.8.0", + "prettier": "^3.7.4", + "raw-loader": "^4.0.2", + "sass": "1.79.5", + "sass-loader": "16.0.1", + "stylelint": "^16.26.1", + "stylelint-config-recess-order": "^7.4.0", + "stylelint-config-recommended-scss": "^16.0.2", + "stylelint-config-recommended-vue": "^1.6.1", + "svg-sprite-loader": "^6.0.11", + "typescript": "^5.9.3", + "unplugin-auto-import": "^0.16.7", + "unplugin-element-plus": "^0.11.2", + "unplugin-vue-components": "0.25.2", + "unplugin-vue-define-options": "^1.5.5", + "vue-eslint-parser": "^10.2.0", + "vue-global-api": "^0.4.1", + "vue-unplugins": "^1.0.6", + "webpack": "^5.104.1", + "webpackbar": "^7.0.0" + }, + "gitHooks": { + "pre-commit": "lint-staged" + }, + "homepage": "https://vuejs-core.cn/admin-plus", + "license": "Mozilla Public License Version 2.0", + "lint-staged": { + "*.{js,jsx,vue}": [ + "vue-cli-service lint", + "git add" + ] + }, + "files": [], + "participants": [ + "FlowPeakFish" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/zxwk2024/admin-plus.git" + } +} diff --git a/plopfile.js b/plopfile.js new file mode 100644 index 0000000..2bdbf74 --- /dev/null +++ b/plopfile.js @@ -0,0 +1,11 @@ +const viewGenerator = require('plop-templates/view/prompt') +const curdGenerator = require('plop-templates/curd/prompt') +const componentGenerator = require('plop-templates/component/prompt') +const mockGenerator = require('plop-templates/mock/prompt') + +module.exports = (plop) => { + plop.setGenerator('view', viewGenerator) + plop.setGenerator('curd', curdGenerator) + plop.setGenerator('component', componentGenerator) + plop.setGenerator('mock&api', mockGenerator) +} diff --git a/prettier.config.js b/prettier.config.js new file mode 100644 index 0000000..61a0dbb --- /dev/null +++ b/prettier.config.js @@ -0,0 +1,16 @@ +module.exports = { + printWidth: 80, + tabWidth: 4, + useTabs: false, + semi: false, + singleQuote: true, + quoteProps: 'as-needed', + jsxSingleQuote: false, + trailingComma: 'es5', + bracketSpacing: true, + bracketSameLine: false, + arrowParens: 'always', + htmlWhitespaceSensitivity: 'ignore', + vueIndentScriptAndStyle: true, + endOfLine: 'lf', +} diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..7c31c49 Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/img/icons/android-chrome-192x192.png b/public/img/icons/android-chrome-192x192.png new file mode 100644 index 0000000..11b6098 Binary files /dev/null and b/public/img/icons/android-chrome-192x192.png differ diff --git a/public/img/icons/android-chrome-512x512.png b/public/img/icons/android-chrome-512x512.png new file mode 100644 index 0000000..1500c07 Binary files /dev/null and b/public/img/icons/android-chrome-512x512.png differ diff --git a/public/img/icons/android-chrome-maskable-192x192.png b/public/img/icons/android-chrome-maskable-192x192.png new file mode 100644 index 0000000..1fb9c26 Binary files /dev/null and b/public/img/icons/android-chrome-maskable-192x192.png differ diff --git a/public/img/icons/android-chrome-maskable-512x512.png b/public/img/icons/android-chrome-maskable-512x512.png new file mode 100644 index 0000000..c85a8ec Binary files /dev/null and b/public/img/icons/android-chrome-maskable-512x512.png differ diff --git a/public/img/icons/apple-touch-icon-152x152.png b/public/img/icons/apple-touch-icon-152x152.png new file mode 100644 index 0000000..51c71ab Binary files /dev/null and b/public/img/icons/apple-touch-icon-152x152.png differ diff --git a/public/img/icons/favicon-16x16.png b/public/img/icons/favicon-16x16.png new file mode 100644 index 0000000..23f3197 Binary files /dev/null and b/public/img/icons/favicon-16x16.png differ diff --git a/public/img/icons/favicon-32x32.png b/public/img/icons/favicon-32x32.png new file mode 100644 index 0000000..9083725 Binary files /dev/null and b/public/img/icons/favicon-32x32.png differ diff --git a/public/img/icons/msapplication-icon-144x144.png b/public/img/icons/msapplication-icon-144x144.png new file mode 100644 index 0000000..7d991a6 Binary files /dev/null and b/public/img/icons/msapplication-icon-144x144.png differ diff --git a/public/img/icons/safari-pinned-tab.svg b/public/img/icons/safari-pinned-tab.svg new file mode 100644 index 0000000..fd609b1 --- /dev/null +++ b/public/img/icons/safari-pinned-tab.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..459adc4 --- /dev/null +++ b/public/index.html @@ -0,0 +1,51 @@ + + + + + + + + + <%= VUE_APP_TITLE %> + + + + + + +
+
+
+ + + + + + +
+

<%= VUE_APP_TITLE %>

+
+
+ + + + diff --git a/public/json/china.json b/public/json/china.json new file mode 100644 index 0000000..0c92e71 --- /dev/null +++ b/public/json/china.json @@ -0,0 +1 @@ +{"type":"FeatureCollection","features":[{"type":"Feature","id":"710000","properties":{"id":"710000","cp":[121.509062,24.044332],"name":"台湾","childNum":6},"geometry":{"type":"MultiPolygon","coordinates":[["@@°Ü¯Û"],["@@ƛĴÕƊÉɼģºðʀ\\ƎsÆNŌÔĚäœnÜƤɊĂǀĆĴžĤNJŨxĚĮǂƺòƌ‚–âÔ®ĮXŦţƸZûЋƕƑGđ¨ĭMó·ęcëƝɉlÝƯֹÅŃ^Ó·śŃNjƏďíåɛGɉ™¿@ăƑŽ¥ĘWǬÏĶŁâ"],["@@\\p|WoYG¿¥I†j@¢"],["@@…¡‰@ˆV^RqˆBbAŒnTXeRz¤Lž«³I"],["@@ÆEE—„kWqë @œ"],["@@fced"],["@@„¯ɜÄèaì¯ØǓIġĽ"],["@@çûĖ롖hòř "]],"encodeOffsets":[[[122886,24033]],[[123335,22980]],[[122375,24193]],[[122518,24117]],[[124427,22618]],[[124862,26043]],[[126259,26318]],[[127671,26683]]]}},{"type":"Feature","id":"130000","properties":{"id":"130000","cp":[114.502461,38.045474],"name":"河北","childNum":3},"geometry":{"type":"MultiPolygon","coordinates":[["@@o~†Z]‚ªr‰ºc_ħ²G¼s`jΟnüsœłNX_“M`ǽÓnUK…Ĝēs¤­©yrý§uģŒc†JŠ›e"],["@@U`Ts¿m‚"],["@@oºƋÄ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äìë|³kÛfw²Xjz~ÂqbTŠÑ„ěŨ@|oM‡’zv¢ZrÃVw¬ŧˏfŒ°ÐT€ªqŽs{Sž¯r æÝlNd®²Ğ džiGʂJ™¼lr}~K¨ŸƐÌWö€™ÆŠzRš¤lêmĞL΄’@¡|q]SvK€ÑcwpÏρ†ĿćènĪWlĄkT}ˆJ”¤~ƒÈT„d„™pddʾĬŠ”Ž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¯‹âŸDùŽyŜžŲIÄuШDž•¸dɂ‡‚FŸƒ•›Oh‡đ©OŸ›iÃ`ww^ƒÌkŸ‘ÑH«ƇǤŗĺtFu…{Z}Ö@U‡´…ʚLg®¯Oı°ÃwŸ ^˜—€VbÉs‡ˆmA…ê]]w„§›RRl£‡ȭµu¯b{ÍDěïÿȧŽuT£ġƒěŗƃĝ“Q¨fV†Ƌ•ƅn­a@‘³@šď„yýIĹÊKšŭfċŰóŒxV@tˆƯŒJ”]eƒR¾fe|rHA˜|h~Ėƍl§ÏŠlTíb ØoˆÅbbx³^zÃ͚¶Sj®A”yÂhðk`š«P€”ˈµEF†Û¬Y¨Ļrõqi¼‰Wi°§’б´°^[ˆÀ|ĠO@ÆxO\\tŽa\\tĕtû{ġŒȧXýĪÓjùÎRb›š^ΛfK[ݏděYfíÙTyŽuUSyŌŏů@Oi½’éŅ­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ıҙ¾ùƀ^juųœK­ƒUFy™—Ɲ…›īÛ÷ąV×qƥV¿aȉd³B›qPBm›aËđŻģm“Å®Vйd^K‡KoŸnYg“¯Xhqa”Ldu¥•ÍpDž¡KąÅƒkĝęěhq‡}HyÓ]¹ǧ£…Í÷¿qáµ§š™g‘¤o^á¾ZE‡¤i`ij{n•ƒOl»ŸWÝĔįhg›F[¿¡—ßkOüš_‰€ū‹i„DZàUtėGylƒ}ŒÓM}€jpEC~¡FtoQi‘šHkk{Ãmï‚"]],"encodeOffsets":[[[119712,40641]],[[121616,39981]],[[116462,37237]]]}},{"type":"Feature","id":"140000","properties":{"id":"140000","cp":[111.849248,36.857014],"name":"山西","childNum":1},"geometry":{"type":"Polygon","coordinates":["@@Þĩ҃S‰ra}Á€yWix±Üe´lè“ßÓǏok‘ćiµVZģ¡coœ‘TS˹ĪmnÕńe–hZg{gtwªpXaĚThȑp{¶Eh—®RćƑP¿£‘Pmc¸mQÝW•ďȥoÅîɡųAďä³aωJ‘½¥PG­ąSM­™…EÅruµé€‘Yӎ•Ō_d›Ē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µ|¡¥ăFÏs׌¥ŅxŸÊ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œŸ˜ʂōĖ’šĴŞ–ȀœÆÿȄlŤĒö„t”νî¼ĨXhŒ‘˜|ªM¤Ðz"],"encodeOffsets":[[116874,41716]]}},{"type":"Feature","id":"150000","properties":{"id":"150000","cp":[111.670801,41.818311],"name":"内蒙古","childNum":2},"geometry":{"type":"MultiPolygon","coordinates":[["@@¯PqƒFB…‰|S•³C|kñ•H‹d‘iÄ¥sˆʼnő…PóÑÑE^‘ÅPpy_YtS™hQ·aHwsOnʼnÚs©iqj›‰€USiº]ïWš‰«gW¡A–Rë¥_ŽsgÁnUI«m‰…„‹]j‡vV¼euhwqA„aW˜ƒ_µj…»çjioQR¹ēÃßt@r³[ÛlćË^ÍÉáG“›OUۗOB±•XŸkŇ¹£k|e]ol™ŸkVͼÕqtaÏõjgÁ£§U^Œ”RLˆËnX°Ç’Bz†^~wfvˆypV ¯„ƫĉ˭ȫƗŷɿÿĿƑ˃ĝÿÃǃßËőó©ǐȍŒĖM×ÍEyx‹þp]Évïè‘vƀnÂĴÖ@‚‰†V~Ĉv¦wĖ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ƎHNJ¤îìɾŊìTdåwsRÖgĒųúÍġäÕ}Q¶—ˆ¿A•†‹[¡Œ{d×uQAƒ›M•xV‹vMOmăl«ct[wº_šÇʊŽŸjb£ĦS_é“QZ“_lwgOiýe`YYLq§IÁˆdz£ÙË[ÕªuƏ³ÍT—s·bÁĽäė[›b[ˆŗfãcn¥îC¿÷µ[ŏÀQ­ōšĉm¿Á^£mJVm‡—L[{Ï_£›F¥Ö{ŹA}…×Wu©ÅaųijƳhB{·TQqÙIķˑZđ©Yc|M¡…L•eVUóK_QWk’_ĥ‘¿ãZ•»X\\ĴuUƒè‡lG®ěłTĠğDєOrÍd‚ÆÍ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ėDžjĝŸ»ÑÞoŸå°qTt|r©ÏS‹¯·eŨĕx«È[eMˆ¿yuˆ‘pN~¹ÏyN£{©’—g‹ħWí»Í¾s“əšDž_ÃĀɗ±ą™ijĉʍŌŷ—S›É“A‹±åǥɋ@럣R©ąP©}ĹªƏj¹erƒLDĝ·{i«ƫC£µsKCš…GS|úþX”gp›{ÁX¿Ÿć{ƱȏñZáĔyoÁhA™}ŅĆfdʼn„_¹„Y°ėǩÑ¡H¯¶oMQqð¡Ë™|‘Ñ`ƭŁX½·óۓxğįÅcQ‡ˆ“ƒs«tȋDžF“Ÿù^i‘t«Č¯[›hAi©á¥ÇĚ×l|¹y¯YȵƓ‹ñǙµï‚ċ™Ļ|Dœ™üȭ¶¡˜›oŽäÕG\\ďT¿Òõr¯œŸLguÏYęRƩšɷŌO\\İТæ^Ŋ IJȶȆbÜGŽĝ¬¿ĚVĎgª^íu½jÿĕęjık@Ľƒ]ėl¥Ë‡ĭûÁ„ƒėéV©±ćn©­ȇžÍq¯½•YÃÔʼn“ÉNѝÅÝy¹NqáʅDǡËñ­ƁYÅy̱os§ȋµʽǘǏƬɱà‘ưN¢ƔÊuľýľώȪƺɂļžxœZĈ}ÌʼnŪ˜ĺœŽĭ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ɹƆ̗̮ȘNJ֥ड़ࡰţાíϲäʮW¬®ҌeרūȠkɬɻ̼ãüfƠSצɩςåȈHϚÎKdzͲOðÏȆƘ¼CϚǚ࢚˼ФԂ¤ƌžĞ̪Qʤ´¼mȠJˀŸƲÀɠmǐnǔĎȆÞǠN~€ʢĜ‚¶ƌĆĘźʆȬ˪ĚǏĞGȖƴƀj`ĢçĶāàŃºē̃ĖćšYŒÀŎüôQÐÂŎŞdžŞêƖš˜oˆDĤÕºÑǘÛˤ³̀gńƘĔÀ^žªƂ`ªt¾äƚêĦĀ¼Ð€Ĕǎ¨Ȕ»͠^ˮÊȦƤøxRrŜH¤¸ÂxDĝŒ|ø˂˜ƮÐ¬ɚwɲFjĔ²Äw°dž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|ŬÂc|ÀtƐK fˆ{ĘFǜƌXƲąo½Ę‘\\¥–o}›Ûu£ç­kX‘{uĩ«āíÓUŅßŢq€Ť¥lyň[€oi{¦‹L‡ń‡ðFȪȖ”ĒL„¿Ì‹ˆfŒ£K£ʺ™oqNŸƒwğc`ue—tOj×°KJ±qƒÆġm‰Ěŗos¬…qehqsuœƒH{¸kH¡Š…ÊRǪÇƌbȆ¢´ä܍¢NìÉʖ¦â©Ġu¦öČ^â£Ăh–šĖMÈÄw‚\\fŦ°W ¢¾luŸD„wŠ\\̀ʉÌÛM…Ā[bӞEn}¶Vc…ê“sƒ"]],"encodeOffsets":[[[129102,52189]]]}},{"type":"Feature","id":"210000","properties":{"id":"210000","cp":[123.429096,41.796767],"name":"辽宁","childNum":16},"geometry":{"type":"MultiPolygon","coordinates":[["@@L–Ž@@s™a"],["@@MnNm"],["@@d‚c"],["@@eÀ‚C@b‚“‰"],["@@f‡…Xwkbr–Ä`qg"],["@@^jtW‘Q"],["@@~ Y]c"],["@@G`ĔN^_¿Z‚ÃM"],["@@iX¶B‹Y"],["@@„YƒZ"],["@@L_{Epf"],["@@^WqCT\\"],["@@\\[“‹§t|”¤_"],["@@m`n_"],["@@Ïxnj{q_×^Giip"],["@@@œé^B†‡ntˆaÊU—˜Ÿ]x ¯ÄPIJ­°h€ʙK³†VˆÕ@Y~†|EvĹsDŽ¦­L^p²ŸÒG ’Ël]„xxÄ_˜fT¤Ď¤cŽœP„–C¨¸TVjbgH²sdÎdHt`Bˆ—²¬GJję¶[ÐhjeXdlwhšðSȦªVÊπ‹Æ‘Z˜ÆŶ®²†^ŒÎyÅÎcPqń“ĚDMħĜŁH­ˆk„çvV[ij¼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ðÑÌ\\\\ŸĐRZk°IS§fqŒßýáЍÙÉÖ[^¯ǤŲ„ê´\\¦¬ĆPM¯£Ÿˆ»uïpùzEx€žanµyoluqe¦W^£ÊL}ñrkqWňûP™‰UP¡ôJŠoo·ŒU}£Œ„[·¨@XŒĸŸ“‹‹DXm­Ûݏº‡›GU‹CÁª½{íĂ^cj‡k“¶Ã[q¤“LÉö³cux«zZfƒ²BWÇ®Yß½ve±ÃC•ý£W{Ú^’q^sÑ·¨‹ÍOt“¹·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^ģÁFıĉĥM­oEqqZûěʼn³F‘¦oĵ—hŸÕP{¯~TÍlª‰N‰ßY“Ð{Ps{ÃVU™™eĎwk±ʼnVÓ½Ž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‚±|Əlij¥ãn·±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]],[[125453,40165]],[[125362,40214]],[[125280,40291]],[[125774,39997]],[[125976,40496]],[[125822,39993]],[[125509,40217]],[[122731,40949]]]}},{"type":"Feature","id":"220000","properties":{"id":"220000","cp":[125.3245,43.886841],"name":"吉林","childNum":1},"geometry":{"type":"Polygon","coordinates":["@@‘p䔳PClƒFbbÍzš€wBG’ĭ€Z„Åi“»ƒlY­ċ²SgŽkÇ£—^S‰“qd¯•‹R…©éŽ£¯S†\\cZ¹iűƏCuƍÓX‡oR}“M^o•£…R}oªU­F…uuXHlEŕ‡€Ï©¤ÛmTŽþ¤D–²ÄufàÀ­XXȱAe„yYw¬dvõ´KÊ£”\\rµÄl”iˆdā]|DÂVŒœH¹ˆÞ®ÜWnŒC”Œķ W‹§@\\¸‹ƒ~¤‹Vp¸‰póIO¢ŠVOšŇürXql~òÉK]¤¥Xrfkvzpm¶bwyFoúvð‡¼¤ N°ąO¥«³[ƒéǡű_°Õ\\ÚÊĝŽþâőàerR¨­JYlďQ[ ÏYëЧTGz•tnŠß¡gFkMŸāGÁ¤ia É‰™È¹`\\xs€¬dĆkNnuNUŠ–užP@‚vRY¾•–\\¢…ŒGªóĄ~RãÖÎĢù‚đŴÕhQŽxtcæëSɽʼníëlj£ƍG£nj°KƘµDsØÑpyƸ®¿bXp‚]vbÍZuĂ{nˆ^IüœÀSք”¦EŒvRÎûh@℈[‚Əȉô~FNr¯ôçR±ƒ­HÑl•’Ģ–^¤¢‚OðŸŒævxsŒ]ÞÁ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‰Śij¯Š‘°kŠRē°wx^Đkǂғ„œž“œŽ„‹\\]˜nrĂ}²ĊŲÒøãh·M{yMzysěnĒġV·°“G³¼XÀ““™¤¹i´o¤ŃšŸÈ`̃DzÄ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ŒM‡ehc›c”ďϝd‡©ÑW_ϗYƅŒ»…é\\ƒɹ~ǙG³mØ©BšuT§Ĥ½¢Ã_ý‘L¡‘ýŸqT^rme™\\Pp•ZZbƒyŸ’uybQ—efµ]UhĿDCmûvašÙNSkCwn‰cćfv~…Y‹„ÇG"],"encodeOffsets":[[130196,42528]]}},{"type":"Feature","id":"230000","properties":{"id":"230000","cp":[128.642464,46.756967],"name":"黑龙江","childNum":2},"geometry":{"type":"MultiPolygon","coordinates":[["@@UƒµNÿ¥īè灋•HÍøƕ¶LŒǽ|g¨|”™Ža¾pViˆdd”~ÈiŒíďÓQġėǐZ΋ŽXb½|ſÃH½ŸKFgɱCģÛÇA‡n™‹jÕc[VĝDZÃ˄Ç_™ £ń³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œfudTrFWÁ¹Am|˜ĔĕsķÆF‡´Nš‰}ć…UŠÕ@Áijſmužç’uð^ÊýowŒFzØÎĕNőžǏȎôªÌŒDŽàĀÄ˄ĞŀƒʀĀƘŸˮȬƬĊ°ƒ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¹^TjVœŠ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Ì®ü±DŽ]ŀç¬B¬©ńzƺŷɄeeOĨS’Œfm Ċ‚ƀP̎ēz©Ċ‚ÄÕÊmgŸÇsJ¥ƔˆŊśæ’΁Ñqv¿íUOµª‰ÂnĦÁ_½ä@ê텣P}Ġ[@gġ}g“ɊדûÏWXá¢užƻÌsNͽƎÁ§č՛AēeL³àydl›¦ĘVçŁpśdžĽĺſʃ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ÇƻğëšܭNJË|c²}Fµ}›ÙRsÓpg±ŠQNqǫŋRwŕnéÑÉKŸ†«SeYR…ŋ‹@{¤SJ}šD Ûǖ֍Ÿ]gr¡µŷjqWÛham³~S«“„›Þ]"]],"encodeOffsets":[[[134456,44547]]]}},{"type":"Feature","id":"320000","properties":{"id":"320000","cp":[119.767413,33.041544],"name":"江苏","childNum":1},"geometry":{"type":"Polygon","coordinates":["@@cþÅPiŠ`ZŸRu¥É\\]~°ŽY`µ†Óƒ^phÁbnÀşúŽòa–ĬºTÖŒb‚˜e¦¦€{¸ZâćNpŒ©žHr|^ˆmjhŠSEb\\afv`sz^lkŽlj‹Ätg‹¤D˜­¾Xš¿À’|ДiZ„ȀåB·î}GL¢õcßjaŸyBFµÏC^ĭ•cÙt¿sğH]j{s©HM¢ƒQnDÀ©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žIJyQŐĠMNtœR®òLh‰›Ěs©»œ}OӌGZz¶A\\jĨFˆäOĤ˜HYš†JvÞHNiÜaϚɖnFQlšNM¤ˆB´ĄNöɂtp–Ŭdf先‹qm¿QûŠùއÚb¤uŃJŴu»¹Ą•lȖħŴw̌ŵ²ǹǠ͛hĭłƕrçü±Y™xci‡tğ®jű¢KOķ•Coy`å®VTa­_Ā]ŐÝɞï²ʯÊ^]afYǸÃĆēĪȣJđ͍ôƋĝÄ͎ī‰çÛɈǥ£­ÛmY`ó£Z«§°Ó³QafusNıDž_k}¢m[ÝóDµ—¡RLčiXy‡ÅNïă¡¸iĔϑNÌŕoēdōîåŤûHcs}~Ûwbù¹£¦ÓCt‹OPrƒE^ÒoŠg™ĉIµžÛÅʹK…¤½phMŠü`o怆ŀ"],"encodeOffsets":[[121740,32276]]}},{"type":"Feature","id":"330000","properties":{"id":"330000","cp":[120.153576,29.287459],"name":"浙江","childNum":45},"geometry":{"type":"MultiPolygon","coordinates":[["@@E^dQ]K"],["@@jX^j‡"],["@@sfŠbU‡"],["@@qP\\xz[ck"],["@@‘Rƒ¢‚FX}°[s_"],["@@Cbœ\\—}"],["@@e|v\\la{u"],["@@v~u}"],["@@QxÂF¯}"],["@@¹nŒvÞs¯o"],["@@rSkUEj"],["@@bi­ZŒP"],["@@p[}INf"],["@@À¿€"],["@@¹dnbŒ…"],["@@rSŸBnR"],["@@g~h}"],["@@FlEk"],["@@OdPc"],["@@v[u\\"],["@@FjâL~wyoo~›sµL–\\"],["@@¬e¹aNˆ"],["@@\\nÔ¡q]L³ë\\ÿ®ŒQ֎"],["@@ÊA­©[¬"],["@@KxŒv­"],["@@@hlIk]"],["@@pW{o||j"],["@@Md|_mC"],["@@¢…X£ÏylD¼XˆtH"],["@@hlÜ[LykAvyfw^Ež›¤"],["@@fp¤Mus“R"],["@@®_ma~•LÁ¬šZ"],["@@iM„xZ"],["@@ZcYd"],["@@Z~dOSo|A¿qZv"],["@@@`”EN¡v"],["@@|–TY{"],["@@@n@m"],["@@XWkCT\\"],["@@ºwšZRkĕWO¢"],["@@™X®±Grƪ\\ÔáXq{‹"],["@@ůTG°ĄLHm°UC‹"],["@@¤Ž€aÜx~}dtüGæţŎíĔcŖpMËВj碷ðĄÆMzˆjWKĎ¢Q¶˜À_꒔_Bı€i«pZ€gf€¤Nrq]§ĂN®«H±‡yƳí¾×ŸīàLłčŴǝĂíÀBŖÕªˆŠÁŖHŗʼnåqûõi¨hÜ·ƒñt»¹ýv_[«¸m‰YL¯‰Qª…mĉÅdMˆ•gÇjcº«•ęœ¬­K­´ƒB«Âącoċ\\xKd¡gěŧ«®á’[~ıxu·Å”KsËɏc¢Ù\\ĭƛëbf¹­ģSƒĜkáƉÔ­ĈZB{ŠaM‘µ‰fzʼnfåÂŧįƋǝÊĕġć£g³ne­ą»@­¦S®‚\\ßðCšh™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}þÙ]„’¡ŒŸFK‚wsPlU[}¦Rvn`hq¬\\”nQ´ĘRWb”‚_ rtČFI֊kŠŠĦPJ¶ÖÀÖJĈĄTĚòžC ²@Pú…Øzœ©PœCÈÚœĒ±„hŖ‡l¬â~nm¨f©–iļ«m‡nt–u†ÖZÜÄj“ŠLŽ®E̜Fª²iÊxبžIÈhhst"],["@@o\\V’zRZ}y"],["@@†@°¡mۛGĕ¨§Ianá[ýƤjfæ‡ØL–•äGr™"]],"encodeOffsets":[[[125592,31553]],[[125785,31436]],[[125729,31431]],[[125513,31380]],[[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]],[[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]],[[124968,30474]],[[125167,30396]],[[124955,29879]],[[124714,29781]],[[124762,29462]],[[124325,28754]],[[123990,28459]],[[125366,31477]],[[125115,30363]],[[125369,31139]],[[122495,31878]],[[125329,30690]],[[125192,30787]]]}},{"type":"Feature","id":"340000","properties":{"id":"340000","cp":[117.283042,31.26119],"name":"安徽","childNum":3},"geometry":{"type":"MultiPolygon","coordinates":[["@@^iuLX^"],["@@‚e©Ehl"],["@@°ZÆëϵmkǀwÌÕæhºgBĝâqÙĊz›ÖgņtÀÁÊÆá’hEz|WzqD¹€Ÿ°E‡ŧl{ævÜcA`¤C`|´qžxIJkq^³³ŸGšµbƒíZ…¹qpa±ď OH—¦™Ħˆx¢„gPícOl_iCveaOjCh߸i݋bÛªCC¿€m„RV§¢A|t^iĠGÀtÚs–d]ĮÐDE¶zAb àiödK¡~H¸íæAžǿYƒ“j{ď¿‘™À½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¾mv™ˊBÜÆ¶ĊJhšp“c¹˜O]iŠ]œ¥ jtsggJǧw×jÉ©±›EFˍ­‰Ki”ÛÃÕYv…s•ˆm¬njĻª•§emná}k«ŕˆƒgđ²Ù›DǤ›í¡ªOy›†×Où±@DŸñSęćăÕIÕ¿IµĥO‰‰jNÕËT¡¿tNæŇàå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Ãϖ_ÈÏ|]ÂÏFl”g`bšežž€n¾¢pU‚h~ƴ˶_‚r sĄ~cž”ƈ]|r c~`¼{À{ȒiJjz`îÀT¥Û³…]’u}›f…ïQl{skl“oNdŸjŸäËzDvčoQŠďHI¦rb“tHĔ~BmlRš—V_„ħTLnñH±’DžœL‘¼L˜ªl§Ťa¸ŒĚlK²€\\RòvDcÎJbt[¤€D@®hh~kt°ǾzÖ@¾ªdb„YhüóZ ň¶vHrľ\\ʗJuxAT|dmÀO„‹[ÃԋG·ĚąĐlŪÚpSJ¨ĸˆLvÞcPæķŨŽ®mАˆálŸwKhïgA¢ųƩޖ¤OȜm’°ŒK´"]],"encodeOffsets":[[[121722,32278]],[[119475,30423]],[[119168,35472]]]}},{"type":"Feature","id":"350000","properties":{"id":"350000","cp":[118.306239,26.075302],"name":"福建","childNum":18},"geometry":{"type":"MultiPolygon","coordinates":[["@@“zht´‡]"],["@@aj^~ĆG—©O"],["@@ed¨„C}}i"],["@@@vˆPGsQ"],["@@‰sBz‚ddW]Q"],["@@SލQ“{"],["@@NŽVucW"],["@@qptBAq"],["@@‰’¸[mu"],["@@Q\\pD]_"],["@@jSwUadpF"],["@@eXª~ƒ•"],["@@AjvFso"],["@@fT–›_Çí\\Ÿ™—v|ba¦jZÆy€°"],["@@IjJi"],["@@wJI€ˆxš«¼AoNe{M­"],["@@K‰±¡Óˆ”ČäeZ"],["@@k¡¹Eh~c®wBk‹UplÀ¡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ÁŧSW¥˜QŠûŗ½ùě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’ņIJg®áIJČĒü` ŽQF‡¬h|ÓJ@zµ |ê³È ¸UÖŬŬÀEttĸr‚]€˜ðŽM¤ĶIJHtÏ 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ĒĢžPlzfˆļŽ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ʼn‡ËĥW[“ÂGI—ÂNxij¤D¢ŽîĎÎB§°_JœGsƒ¥E@…¤uć…P‘å†cuMuw¢BI¿‡]zG¹guĮck\\_"]],"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]]]}},{"type":"Feature","id":"360000","properties":{"id":"360000","cp":[115.592151,27.676493],"name":"江西","childNum":1},"geometry":{"type":"Polygon","coordinates":["@@ĢĨƐgÂ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ĢûXD®…QgėWiØPÞìºr¤dž€NĠ¢l–•ĄtZoœCƞÔºCxrpĠV®Ê{f_Y`_ƒeq’’®Aot`@o‚DXfkp¨|Šs¬\\D‘ÄSfè©Hn¬…^DhÆyøJh“ØxĢĀLʈ„ƠPżċĄwȠ̦G®ǒĤäTŠÆ~ĦwŠ«|TF¡Šn€c³Ïå¹]ĉđxe{ÎӐ†vOEm°BƂĨİ|G’vz½ª´€H’àp”eJ݆Qšxn‹ÀŠW­žEµàXÅĪt¨ÃĖrÄwÀFÎ|ňÓMå¼ibµ¯»åDT±m[“r«_gŽmQu~¥V\\OkxtL E¢‹ƒ‘Ú^~ýê‹Pó–qo슱_Êw§ÑªåƗ⼋mĉŹ‹¿NQ“…YB‹ąrwģcÍ¥B•Ÿ­ŗÊcØiI—žƝĿuŒqtāwO]‘³YCñTeɕš‹caub͈]trlu€ī…B‘ПGsĵıN£ï—^ķqss¿Fūū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[×zkKN‘¶Õ»lčÓ{XSƉv©_ÈëJbVk„ĔVÀ¤P¾ºÈMÖxlò~ªÚàGĂ¢B„±’ÌŒK˜y’áV‡¼Ã~­…`g›ŸsÙfI›Ƌlę¹e|–~udjˆuTlXµf`¿JdŠ[\\˜„L‚‘²"],"encodeOffsets":[[116689,26234]]}},{"type":"Feature","id":"370000","properties":{"id":"370000","cp":[118.000923,36.275807],"name":"山东","childNum":13},"geometry":{"type":"MultiPolygon","coordinates":[["@@Xjd]{K"],["@@itbFHy"],["@@HlGk"],["@@T‚ŒGŸy"],["@@K¬˜•‹U"],["@@WdXc"],["@@PtOs"],["@@•LnXhc"],["@@ppVƒu]Or"],["@@cdzAUa"],["@@udRhnCI‡"],["@@ˆoIƒpR„"],["@@Ľč{fzƤî’Kš–ÎMĮ]†—ZFˆ½Y]â£ph’™š¶¨râøÀ†ÎǨ¤^ºÄ”Gzˆ~grĚĜlĞÆ„LĆdž¢Îo¦–cv“Kb€gr°Wh”mZp ˆL]LºcU‰Æ­n”żĤÌǜbAnrOAœ´žȊcÀbƦUØrĆUÜøœĬƞ†š˜Ez„VL®öØBkŖÝĐ˹ŧ̄±ÀbÎɜnb²ĦhņBĖ›žįĦåXćì@L¯´ywƕCéõė ƿ¸‘lµ¾Z|†ZWyFYŸ¨Mf~C¿`€à_RÇzwƌfQnny´INoƬˆèôº|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¢ïW…uøCǷ돡ąuhÛ¡^Kx•C`C\\bÅxì²ĝÝ¿_N‰īCȽĿåB¥¢·IŖÕy\\‡¹kx‡Ã£Č×GDyÕ¤Áç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‰edz‹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ۃWp[ƒ"]],"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]],[[118260,36742]]]}},{"type":"Feature","id":"410000","properties":{"id":"410000","cp":[113.665412,33.757975],"name":"河南","childNum":1},"geometry":{"type":"Polygon","coordinates":["@@•ýL™ùµP³swIÓxcŢĞð†´E®žÚPt†ĴXØx¶˜@«ŕŕQGƒ‹Yfa[şu“ßǩ™đš_X³ijÕčC]kbc•¥CS¯ëÍB©÷‹–³­Siˆ_}m˜YTtž³xlàcȂzÀD}ÂOQ³ÐTĨ¯†ƗòËŖ[hœł‹Ŧ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µ`Ƴĕg}V¡om½fa™Ço³TTj¥„tĠ—Ry”K{ùÓjuµ{t}uËR‘iŸvGŠçJFjµŠÍyqΘàQÂFewixGw½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ˑ赟^ˆKLœ—i—Þñ€[œƒaA²zz‰Ì÷Dœ|[šíijgf‚ÕÞd®|`ƒĆ~„oĠƑô³Ŋ‘D×°¯CsŠøÀ«ì‰UMhTº¨¸ǡîS–Ô„DruÂÇZ•ÖEŽ’vPZ„žW”~؋ÐtĄE¢¦Ðy¸bŠô´oŬ¬Ž²Ês~€€]®tªašpŎJ¨Öº„_ŠŔ–`’Ŗ^Ѝ\\Ĝ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|žlGl’™Rjsp¢ED}€Fio~ÔNŽ‹„~zkĘHVsDzßjƒŬŒŠŢ`Pûàl¢˜\\ÀœEhŽİgÞē X¼Pk–„|m"],"encodeOffsets":[[118256,37017]]}},{"type":"Feature","id":"420000","properties":{"id":"420000","cp":[113.298572,30.684355],"name":"湖北","childNum":3},"geometry":{"type":"MultiPolygon","coordinates":[["@@AB‚"],["@@lskt"],["@@¾«}{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ÎóĔ†ÊēIJ}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]]]}},{"type":"Feature","id":"430000","properties":{"id":"430000","cp":[111.782279,28.09409],"name":"湖南","childNum":3},"geometry":{"type":"MultiPolygon","coordinates":[["@@—n„FTs"],["@@ßÅÆá‰½ÔXr—†CO™“…ËR‘ïÿĩ­TooQyšÓ[‹ŅBE¬–ÎÓXa„į§Ã¸G °ITxp‰úxÚij¥Ïš–̾ŠedžÄ©ĸG…œàGh‚€M¤–Â_U}Ċ}¢pczfŠþg¤€”ÇòAV‘‹M"],["@@©K—ƒA·³CQ±Á«³BUŠƑ¹AŠtćOw™D]ŒJiØSm¯b£‘ylƒ›X…HËѱH•«–‘C^õľA–Å§¤É¥„ïyuǙuA¢^{ÌC´­¦ŷJ£^[†“ª¿‡ĕ~•Ƈ…•N… skóā‡¹¿€ï]ă~÷O§­@—Vm¡‹Qđ¦¢Ĥ{ºjԏŽŒª¥nf´•~ÕoŸž×Ûą‹MąıuZœmZcÒ IJβSÊDŽŶ¨ƚƒ’CÖŎª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›”^¶›IJÞܓ~‘u¸ǔ˜Ž›MRhsR…e†`ÄofIÔ\\Ø  i”ćymnú¨cj ¢»–GČìƊÿШXeĈ¾Oð Fi ¢|[jVxrIQŒ„_E”zAN¦zLU`œcªx”OTu RLÄ¢dV„i`p˔vŎµªÉžF~ƒØ€d¢ºgİàw¸Áb[¦Zb¦–z½xBĖ@ªpº›šlS¸Ö\\Ĕ[N¥ˀmĎă’J\\‹ŀ`€…ňSڊĖÁĐiO“Ĝ«BxDõĚiv—ž–S™Ì}iùŒžÜnšÐºGŠ{Šp°M´w†ÀÒzJ²ò¨ oTçüöoÛÿñŽőФ‚ùTz²CȆȸǎۃƑÐc°dPÎŸğ˶[Ƚu¯½WM¡­Éž“’B·rížnZŸÒ `‡¨GA¾\\pē˜XhÆRC­üWGġu…T靧Ŏѝ©ò³I±³}_‘‹EÃħg®ęisÁPDmÅ{‰b[Rşs·€kPŸŽƥƒóRo”O‹ŸVŸ~]{g\\“êYƪ¦kÝbiċƵŠGZ»Ěõ…ó·³vŝž£ø@pyö_‹ëŽIkѵ‡bcѧy…×dY؎ªiþž¨ƒ[]f]Ņ©C}ÁN‡»hĻħƏ’ĩ"]],"encodeOffsets":[[[115640,30489]],[[112543,27312]],[[116690,26230]]]}},{"type":"Feature","id":"440000","properties":{"id":"440000","cp":[113.280637,23.125178],"name":"广东","childNum":24},"geometry":{"type":"MultiPolygon","coordinates":[["@@QdˆAua"],["@@ƒlxDLo"],["@@sbhNLo"],["@@Ă āŸ"],["@@WltO[["],["@@Krœ]S"],["@@e„„I]y"],["@@I|„Mym"],["@@ƒÛ³LSŒž¼Y"],["@@nvºB–ëui©`¾"],["@@zdšÛ›Jw®"],["@@†°…¯"],["@@a yAª¸ËJIx،@€ĀHAmßV¡o•fu•o"],["@@šs‰ŗÃÔėAƁ›ZšÄ ~°ČP‚‹äh"],["@@‹¶Ý’Ì‚vmĞh­ı‡Q"],["@@HœŠdSjĒ¢D}war…“u«ZqadYM"],["@@elŒ\\LqqU"],["@@~rMo\\"],["@@f„^ƒC"],["@@øPªoj÷ÍÝħXČx”°Q¨ıXNv"],["@@gÇƳˆŽˆ”oˆŠˆ[~tly"],["@@E–ÆC¿‘"],["@@OŽP"],["@@w‹†đóg‰™ĝ—[³‹¡VÙæÅöM̳¹pÁaËýý©D©Ü“JŹƕģGą¤{Ùū…ǘO²«BƱéA—Ò‰ĥ‡¡«BhlmtÃPµyU¯uc“d·w_bŝcīímGOŽ|KP’ȏ‡ŹãŝIŕŭŕ@Óoo¿ē‹±ß}Ž…ŭ‚ŸIJWÈCőâUâǙI›ğʼn©I›ijEׅÁ”³Aó›wXJþ±ÌŒÜӔĨ£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††–‚ƂªFbwžEÀˆ˜©Œž\\…¤]ŸI®¥D³|ˎ]CöAŤ¦…æ’´¥¸Lv¼€•¢ĽBaô–F~—š®²GÌҐEY„„œzk¤’°ahlV՞I^‹šCxĈPŽsB‰ƒºV‰¸@¾ªR²ĨN]´_eavSi‡vc•}p}Đ¼ƌkJœÚe thœ†_¸ ºx±ò_xN›Ë‹²‘@ƒă¡ßH©Ùñ}wkNÕ¹ÇO½¿£ĕ]ly_WìIžÇª`ŠuTÅxYĒÖ¼k֞’µ‚MžjJÚwn\\h‘œĒv]îh|’È›Ƅøègž¸Ķß ĉĈWb¹ƀdéƌNTtP[ŠöSvrCZžžaGuœbo´ŖÒÇА~¡zCI…özx¢„Pn‹•‰Èñ @ŒĥÒ¦†]ƞŠV}³ăĔñ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–»HO£|ām‡¡diď×YïYWªʼnOeÚtĐ«zđ¹T…ā‡úE™á²\\‹ķÍ}jYàÙÆſ¿Çdğ·ùTßÇţʄ¡XgWÀLJğ·¿ÃˆOj YÇ÷Qě‹i"]],"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]],[[116561,22649]],[[116285,22746]]]}},{"type":"Feature","id":"450000","properties":{"id":"450000","cp":[108.320004,22.82402],"name":"广西","childNum":2},"geometry":{"type":"MultiPolygon","coordinates":[["@@H– TQ§•A"],["@@ĨʪƒLƒƊDÎĹĐCǦė¸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«èVloޤ™ÔRzpp®SŽĪº¨ÖƒºN…ij„d`’a”¦¤F³ºDÎńĀìŠCžĜº¦Ċ•~nS›|gźvZkCÆj°zVÈÁƔ]LÊFZg…čP­kini«‹qǀcz͔Y®¬Ů»qR×ō©DՄ‘§ƙǃŵTÉĩ±ŸıdÑnYY›IJvNĆÌØÜ Öp–}e³¦m‹©iÓ|¹Ÿħņ›|ª¦QF¢Â¬ʖovg¿em‡^ucà÷gՎuŒíÙćĝ}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űŒmcih³K›~‰µh¯e]lµ›él•E쉕E“ďs‡’mǖŧē`ãògK_ÛsUʝ“ćğ¶hŒöŒO¤Ǜn³Žc‘`¡y‹¦C‘ez€YŠwa™–‘[ďĵű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Č{`]þ¯T’bÜÈk‚¡Ġ•vŒàh„ÂƄ¢Jî¶²"]],"encodeOffsets":[[[111707,21520]],[[107619,25527]]]}},{"type":"Feature","id":"460000","properties":{"id":"460000","cp":[109.83119,19.031971],"name":"海南","childNum":1},"geometry":{"type":"Polygon","coordinates":["@@š¦Ŝil¢”XƦ‘ƞò–ïè§ŞCêɕrŧůÇąĻõ™·ĉ³œ̅kÇm@ċȧƒŧĥ‰Ľʉ­ƅſ“ȓÒ˦ŝE}ºƑ[ÍĜȋ gÎfǐÏĤ¨êƺ\\Ɔ¸ĠĎvʄȀœÐ¾jNðĀÒRŒšZdž™zÐŘΰH¨Ƣb²_Ġ "],"encodeOffsets":[[112750,20508]]}},{"type":"Feature","id":"510000","properties":{"id":"510000","cp":[104.065735,30.659462],"name":"四川","childNum":2},"geometry":{"type":"MultiPolygon","coordinates":[["@@LqKr"],["@@Š[ĻéV£ž_ţġñpG •réÏ·~ąSfy×͂·ºſƽiÍıƣıĻmHH}siaX@iǰÁÃ×t«ƒ­Tƒ¤J–JJŒyJ•ÈŠ`Ohߦ¡uËhIyCjmÿ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ºĠ~ÌЧnDž¿¤]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‚õŠ„ƤąAvƒü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èĻĒ©Ĉ“tCĢɽŠȣ¦āæ·HĽî“ôNԓ~^¤Ɗœu„œ^s¼{TA¼ø°¢İªDè¾Ň¶ÝJ‘®Z´ğ~Sn|ªWÚ©òzPOȸ‚bð¢|‹øĞŠŒœŒQìÛÐ@Ğ™ǎRS¤Á§d…i“´ezÝúØã]Hq„kIŸþËQǦÃsǤ[E¬ÉŪÍxXƒ·ÖƁİlƞ¹ª¹|XÊwn‘ÆƄ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§áCNęÎ[ĀÕĪgÖɪX˜øx¬½Ů¦¦[€—„NΆL€ÜUÖ´òrÙŠxR^–†J˜k„ijnDX{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¡}ìęNJē}q”É埁T¯µRs¡M@}ůa†a­¯wvƉåZwž\\Z{åû^›"]],"encodeOffsets":[[[108815,30935]],[[110617,31811]]]}},{"type":"Feature","id":"520000","properties":{"id":"520000","cp":[106.713478,26.578343],"name":"贵州","childNum":3},"geometry":{"type":"MultiPolygon","coordinates":[["@@†G\\†lY£‘in"],["@@q‚|ˆ‚mc¯tχVSÎ"],["@@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ŪÒ¢@ƒ£ÀEîôruń‚”“‚b[§nWuMÆLl¿]x}ij­€½"]],"encodeOffsets":[[[112158,27383]],[[112105,27474]],[[112095,27476]]]}},{"type":"Feature","id":"530000","properties":{"id":"530000","cp":[101.512251,24.740609],"name":"云南","childNum":1},"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âDŽŲ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‚›Ƣ¼pcIJxŠ|ap̬HšÐŒŊSfsðBZ¿©“XÏÒK•k†÷Eû¿‰S…rEFsÕūk”óVǥʼniTL‚¡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ªij¶“ʼnÿ‡y©n‰ď£G¹¡I›Š±LÉĺÑdĉ܇W¥˜‰}g˜Á†{aqÃ¥aŠıęÏZ—ï`"],"encodeOffsets":[[104636,22969]]}},{"type":"Feature","id":"540000","properties":{"id":"540000","cp":[89.132212,30.860361],"name":"西藏","childNum":1},"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¥™cc¡ÙaSyF—ց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ˆƒIij€Ï÷њį[¹¦[⚍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•ÚÅTSij‚‹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¾zLjRxжF”œkĄźRzŀˆ~¶[”´Hnª–VƞuĒ­È¨ƎcƽÌm¸ÁÈM¦x͊ëÀxdž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]]}},{"type":"Feature","id":"610000","properties":{"id":"610000","cp":[108.948024,34.263161],"name":"陕西","childNum":1},"geometry":{"type":"Polygon","coordinates":["@@˜p¢—ȮµšûG™Ħ}Ħšðǚ¶òƄ€jɂz°{ºØkÈęâ¦jª‚Bg‚\\œċ°s¬Ž’]jžú ‚E”Ȍdž¬s„t‡”RˆÆdĠݎwܔ¸ôW¾ƮłÒ_{’Ìšû¼„jº¹¢GǪÒ¯ĘƒZ`ºŊƒecņąš~BÂgzpâēòYǠȰÌTΨÂWœ|fcŸă§uF—Œ@NŸ¢XLƒŠRMº[ğȣſï|¥J™kc`sʼnǷ’Y¹‹W@µ÷K…ãï³ÛIcñ·VȋڍÒķø©—þ¥ƒy‚ÓŸğęmWµÎumZyOŅƟĥÓ~sÑL¤µaŅY¦ocyZ{‰y c]{ŒTa©ƒ`U_Ěē£ωÊƍKù’K¶ȱÝƷ§{û»ÅÁȹÍéuij|¹cÑd‘ŠìUYƒŽO‘uF–ÕÈYvÁCqӃT•Ǣí§·S¹NgŠV¬ë÷Át‡°Dد’C´ʼnƒópģ}„ċcE˅FŸŸéGU¥×K…§­¶³B‹Č}C¿åċ`wġB·¤őcƭ²ő[Å^axwQO…ÿEËߌ•ĤNĔŸwƇˆÄŠńwĪ­Šo[„_KÓª³“ÙnK‰Çƒěœÿ]ď€ă_d©·©Ýŏ°Ù®g]±„Ÿ‡ß˜å›—¬÷m\\›iaǑkěX{¢|ZKlçhLt€Ňîŵ€œè[€É@ƉĄEœ‡tƇÏ˜³­ħZ«mJ…›×¾‘MtÝĦ£IwÄå\\Õ{‡˜ƒOwĬ©LÙ³ÙgBƕŀr̛ĢŭO¥lãyC§HÍ£ßEñŸX¡—­°ÙCgpťz‘ˆb`wI„vA|§”‡—hoĕ@E±“iYd¥OϹS|}F@¾oAO²{tfžÜ—¢Fǂ҈W²°BĤ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²IJ_œXPrɲ‰l‘‚XžiL§àƒ–¹ŽH˜°Ȧqº®QC—bA†„ŌJ¸ĕÚ³ĺ§ `d¨YjžiZvRĺ±öVKkjGȊĐePОZmļKÀ€‚[ŠŽ`ösìh†ïÎoĬdtKÞ{¬èÒÒBŒÔpIJÇĬJŊ¦±J«ˆY§‹@·pH€µàåVKe›pW†ftsAÅqC·¬ko«pHÆuK@oŸHĆۄķhx“e‘n›S³àǍrqƶRbzy€¸ËАl›¼EºpĤ¼Œx¼½~Ğ’”à@†ÚüdK^ˆmÌSj"],"encodeOffsets":[[110234,38774]]}},{"type":"Feature","id":"620000","properties":{"id":"620000","cp":[103.823557,36.058039],"name":"甘肃","childNum":2},"geometry":{"type":"MultiPolygon","coordinates":[["@@VuUv"],["@@ũ‹EĠtt~nkh`Q‰¦ÅÄÜdw˜Ab×ĠąJˆ¤DüègĺqBqœj°lI¡ĨÒ¤úSHbš‡Š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©IJ°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ʼnÈīoı‹ÓÑAçÑ|«LÝcspīðÍg…të_õ‰\\ĉñLYnĝg’ŸRǡÁiHLlõUĹ²uQjYi§Z_c¨Ÿ´ĹĖÙ·ŋI…ƒaBD˜­R¹ȥr—¯G•ºß„K¨jWk’ɱŠOq›Wij\\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•ćå]ğij@ ©O{¤ĸm¢ƒE·®ƒ«|@Xwg]A챝‡XǁÑdzªc›wQÚŝñsÕ³ÛV_ýƒ˜¥\\ů¥©¾÷w—Ž©WÕÊĩhÿÖÁRo¸V¬âDb¨šhûx–Ê×nj~Zâƒg|šXÁnßYoº§ZÅŘvŒ[„ĭÖʃuďxcVbnUSf…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³ʼnĖý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´ï¦—ºĒDzņɾªǀÞĈĂD†½ĄĎÌŗĞrôñnŽœN¼â¾ʄľԆ|DŽŽ֦ज़ȗlj̘̭ɺƅêgV̍ʆĠ·ÌĊv|ýĖÕWĊǎÞ´õ¼cÒÒBĢ͢UĜð͒s¨ňƃLĉÕÝ@ɛƯ÷¿Ľ­Ĺeȏijë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ĤoH{tK"]],"encodeOffsets":[[[108619,36299]],[[108589,36341]]]}},{"type":"Feature","id":"630000","properties":{"id":"630000","cp":[96.778916,35.623178],"name":"青海","childNum":2},"geometry":{"type":"MultiPolygon","coordinates":[["@@InJm"],["@@CƒÆ½OŃĦsΰ~dz¦@@“Ņiš±è}ؘƄ˹A³r_ĞŠǒNΌĐw¤^ŬĵªpĺSZg’rpiƼĘԛ¨C|͖J’©Ħ»®VIJ~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@ĉij¢Ó祖•ƒ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±ª£IJ¡fb®ÞbŽb_Ą¥xu¥B—ž{łĝ³«`d˜Ɛt—¤ťiñžÍUuºí`£˜^tƃIJc—·ÛLO‹½Šsç¥Ts{ă\\_»™kϊ±q©čiìĉ|ÍIƒ¥ć¥›€]ª§D{ŝŖÉR_sÿc³Īō›ƿΑ›§p›[ĉ†›c¯bKm›R¥{³„Z†e^ŽŒwx¹dƽŽôIg §Mĕ ƹĴ¿—ǣÜ̓]‹Ý–]snåA{‹eŒƭ`ǻŊĿ\\ijŬű”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ԄveOg"]],"encodeOffsets":[[[105308,37219]],[[95370,40081]]]}},{"type":"Feature","id":"640000","properties":{"id":"640000","cp":[106.278179,37.26637],"name":"宁夏","childNum":2},"geometry":{"type":"MultiPolygon","coordinates":[["@@KëÀęĞ«OęȿȕŸı]ʼn¡åįÕÔ«Ǵõƪ™Ě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Õ"],["@@mfwěwMrŢªv@G‰"]],"encodeOffsets":[[[109366,40242]],[[108600,36303]]]}},{"type":"Feature","id":"650000","properties":{"id":"650000","cp":[85.617733,40.792818],"name":"新疆","childNum":1},"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Ҟª«IJ‡πdƺÏØZƴwʄ¤ĖGЙǂZ̓èH¶}ÚZצʥĪï|ÇĦMŔ»İĝLj‹ì¥Βœba­¯¥ǕǚkĆŵĦɑĺƯxūД̵nơʃĽá½M»›òmqóŘĝč˾ăC…ćāƿÝɽ©DZŅ¹đ¥˜³ðLrÁ®ɱĕģʼnǻ̋ȥơŻǛȡVï¹Ň۩ûkɗġƁ§ʇė̕ĩũƽō^ƕŠUv£ƁQï“Ƶkŏ½ΉÃŭdzLқʻ«ƭ\\lƒ‡ŭD‡“{ʓDkaFÃÄa“³ŤđÔGRÈƚhSӹŚsİ«ĐË[¥ÚDkº^Øg¼ŵ¸£EÍö•€ůʼnT¡c_‡ËKY‹ƧUśĵ„݃U_©rETÏʜ±OñtYw獃{£¨uM³x½şL©Ùá[ÓÐĥ Νtģ¢\\‚ś’nkO›w¥±ƒT»ƷFɯàĩÞáB¹Æ…ÑUw„੍žĽw[“mG½Èå~‡Æ÷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ù]‘™DžA¿w͉ì¥wÇN·ÂËnƾƍdǧđ®Ɲv•Um©³G\\“}µĿ‡QyŹl㓛µEw‰LJQ½yƋBe¶ŋÀů‡ož¥A—˜Éw@•{Gpm¿Aij†Ž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†dz—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|IJXŔþÈ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øàIJaĞ‚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]]}},{"type":"Feature","id":"110000","properties":{"id":"110000","cp":[116.405285,39.904989],"name":"北京","childNum":1},"geometry":{"type":"Polygon","coordinates":["@@ĽOÁ›ûtŷmiÍt_H»Ĩ±d`й­{bw…Yr“³S]§§o¹€qGtm_Sŧ€“oa›‹FLg‘QN_•dV€@Zom_ć\\ߚc±x¯oœRcfe…£’o§ËgToÛJíĔóu…|wP¤™XnO¢ÉˆŦ¯rNÄā¤zâŖÈRpŢZŠœÚ{GŠrFt¦Òx§ø¹RóäV¤XdˆżâºWbwڍUd®bêņ¾‘jnŎGŃŶŠnzÚSeîĜZczî¾i]͜™QaúÍÔiþĩȨWĢ‹ü|Ėu[qb[swP@ÅğP¿{\\‡¥A¨Ï‘Ѩj¯ŠX\\¯œMK‘pA³[H…īu}}"],"encodeOffsets":[[120023,41045]]}},{"type":"Feature","id":"120000","properties":{"id":"120000","cp":[117.190182,39.125596],"name":"天津","childNum":1},"geometry":{"type":"Polygon","coordinates":["@@ŬgX§Ü«E…¶Ḟ“¬O_™ïlÁg“z±AXe™µÄĵ{¶]gitgšIj·›¥îakS€‰¨ÐƎk}ĕ{gB—qGf{¿a†U^fI“ư‹³õ{YƒıëNĿžk©ïËZŏ‘R§òoY×Ógc…ĥ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]]}},{"type":"Feature","id":"310000","properties":{"id":"310000","cp":[121.472644,31.231706],"name":"上海","childNum":6},"geometry":{"type":"MultiPolygon","coordinates":[["@@ɧư¬EpƸÁxc‡"],["@@©„ªƒ"],["@@”MA‹‘š"],["@@Qp݁E§ÉC¾"],["@@bŝՕÕEȣÚƥêImɇǦèÜĠŒÚžÃƌÃ͎ó"],["@@ǜûȬɋŠŭ™×^‰sYŒɍDŋ‘ŽąñCG²«ªč@h–_p¯A{‡oloY€¬j@IJ`•gQڛhr|ǀ^MIJvtbe´R¯Ô¬¨YŽô¤r]ì†Ƭį"]],"encodeOffsets":[[[124702,32062]],[[124547,32200]],[[124808,31991]],[[124726,32110]],[[124903,32376]],[[124438,32149]]]}},{"type":"Feature","id":"500000","properties":{"id":"500000","cp":[107.304962,29.533155],"name":"重庆","childNum":2},"geometry":{"type":"MultiPolygon","coordinates":[["@@vjG~nGŘŬĶȂƀƾ¹¸ØÎezĆT¸}êЖqHŸðqĖ䒊¥^CƒIj–²p…\\_ æüY|[YxƊæuž°xb®…Űb@~¢NQt°¶‚S栓Ê~rljĔëĚ¢~š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†µÜƅġ‘œ^ÖÛbÙŽŏml½S‹êqDu[R‹ãË»†ÿw`»y‘¸_ĺę}÷`M¯ċfCVµqʼn÷Z•gg“Œ`d½pDO‡ÎCnœ^uf²ènh¼WtƏxRGg¦…pV„†FI±ŽG^ŒIc´ec‡’G•ĹÞ½sëĬ„h˜xW‚}Kӈe­Xsbk”F¦›L‘ØgTkïƵNï¶}Gy“w\\oñ¡nmĈzjŸ•@™Óc£»Wă¹Ój“_m»ˆ¹·~MvÛaqœ»­‰êœ’\\ÂoVnŽÓØÍ™²«‹bq¿efE „€‹Ĝ^Qž~ Évý‡ş¤²Į‰pEİ}zcĺƒL‹½‡š¿gņ›¡ýE¡ya£³t\\¨\\vú»¼§·Ñr_oÒý¥u‚•_n»_ƒ•At©Þűā§IVeëƒY}{VPÀFA¨ąB}q@|Ou—\\Fm‰QF݅Mw˜å}]•€|FmϋCaƒwŒu_p—¯sfÙgY…DHl`{QEfNysBЦzG¸rHe‚„N\\CvEsÐùÜ_·ÖĉsaQ¯€}_U‡†xÃđŠq›NH¬•Äd^ÝŰR¬ã°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쐣ŒN"],["@@ifjN@s"]],"encodeOffsets":[[[109628,30765]],[[111725,31320]]]}},{"type":"Feature","id":"810000","properties":{"id":"810000","cp":[114.173355,22.320048],"name":"香港","childNum":5},"geometry":{"type":"MultiPolygon","coordinates":[["@@AlBk"],["@@mŽn"],["@@EpFo"],["@@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"],["@@rMUw‡AS®€e"]],"encodeOffsets":[[[117111,23002]],[[117072,22876]],[[117045,22887]],[[116975,23082]],[[116882,22747]]]}},{"type":"Feature","id":"820000","properties":{"id":"820000","cp":[113.54909,22.198951],"name":"澳门","childNum":1},"geometry":{"type":"Polygon","coordinates":["@@kÊd°å§s"],"encodeOffsets":[[116279,22639]]}}],"UTF8Encoding":true} \ No newline at end of file diff --git a/public/static/css/loading.css b/public/static/css/loading.css new file mode 100644 index 0000000..a9ee0fb --- /dev/null +++ b/public/static/css/loading.css @@ -0,0 +1,96 @@ +.first-loading-wrp { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 90vh; + min-height: 90vh; +} + +.first-loading-wrp > h1 { + font-size: 28px; + font-weight: bolder; +} + +.first-loading-wrp .loading-wrp { + display: flex; + align-items: center; + justify-content: center; + padding: 98px; +} + +.dot { + position: relative; + box-sizing: border-box; + display: inline-block; + width: 64px; + height: 64px; + font-size: 64px; + transform: rotate(45deg); + animation: antRotate 1.2s infinite linear; +} + +.dot i { + position: absolute; + display: block; + width: 28px; + height: 28px; + background-color: #1890ff; + border-radius: 100%; + opacity: 0.3; + transform: scale(0.75); + transform-origin: 50% 50%; + animation: antSpinMove 1s infinite linear alternate; +} + +.dot i:nth-child(1) { + top: 0; + left: 0; +} + +.dot i:nth-child(2) { + top: 0; + right: 0; + -webkit-animation-delay: 0.4s; + animation-delay: 0.4s; +} + +.dot i:nth-child(3) { + right: 0; + bottom: 0; + -webkit-animation-delay: 0.8s; + animation-delay: 0.8s; +} + +.dot i:nth-child(4) { + bottom: 0; + left: 0; + -webkit-animation-delay: 1.2s; + animation-delay: 1.2s; +} + +@keyframes antRotate { + to { + -webkit-transform: rotate(405deg); + transform: rotate(405deg); + } +} + +@-webkit-keyframes antRotate { + to { + -webkit-transform: rotate(405deg); + transform: rotate(405deg); + } +} + +@keyframes antSpinMove { + to { + opacity: 1; + } +} + +@-webkit-keyframes antSpinMove { + to { + opacity: 1; + } +} diff --git a/scripts/compress.js b/scripts/compress.js new file mode 100644 index 0000000..c69960b --- /dev/null +++ b/scripts/compress.js @@ -0,0 +1,87 @@ +const fs = require('fs') +const path = require('path') +const archiver = require('archiver') + +// 压缩文件名 +const zipFileName = `dist.zip` +const zipFilePath = path.join(__dirname, '..', 'dist', zipFileName) + +// 创建输出流 +const output = fs.createWriteStream(zipFilePath) +const archive = archiver('zip', { + zlib: { level: 9 }, // 设置压缩级别 +}) + +// 监听错误事件 +archive.on('error', (err) => { + throw err +}) + +// 监听关闭事件 +output.on('close', () => { + const sizeInMB = (archive.pointer() / 1024 / 1024).toFixed(2) + console.log(`✅ 压缩完成!`) + console.log(`📦 文件名: ${zipFileName}`) + console.log(`📏 文件大小: ${sizeInMB} MB`) + console.log(`📍 文件路径: ${zipFilePath}`) +}) + +// 监听警告事件 +archive.on('warning', (err) => { + if (err.code === 'ENOENT') { + console.warn('⚠️ 警告:', err.message) + } else { + throw err + } +}) + +// 管道输出 +archive.pipe(output) + +// 检查dist目录是否存在 +const distPath = path.join(__dirname, '..', 'dist') +if (!fs.existsSync(distPath)) { + console.error('❌ 错误: dist目录不存在,请先运行构建命令') + process.exit(1) +} + +console.log('🚀 开始压缩构建文件...') + +// 递归添加dist目录内的所有文件和文件夹到压缩包根目录 +function addDirectoryToArchive(dirPath, archivePath = '') { + const items = fs.readdirSync(dirPath) + + items.forEach((item) => { + const fullPath = path.join(dirPath, item) + const relativePath = archivePath ? path.join(archivePath, item) : item + const stat = fs.statSync(fullPath) + + if (stat.isDirectory()) { + // 递归添加子目录 + addDirectoryToArchive(fullPath, relativePath) + } else { + // 跳过压缩包文件本身,避免自包含 + if (item !== zipFileName) { + // 添加文件到压缩包根目录 + archive.file(fullPath, { name: relativePath }) + } + } + }) +} + +// 添加dist目录内的所有文件到压缩包根目录 +addDirectoryToArchive(distPath) + +// 添加package.json到压缩包(可选) +archive.file(path.join(__dirname, '..', 'package.json'), { + name: 'package.json', +}) + +// 添加README.md到压缩包(如果存在) +const readmePath = path.join(__dirname, '..', 'README.md') +if (fs.existsSync(readmePath)) { + archive.file(readmePath, { name: 'README.md' }) +} + +// 完成压缩 +archive.finalize() diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..89c212f --- /dev/null +++ b/src/App.vue @@ -0,0 +1,34 @@ + + + diff --git a/src/api/area.ts b/src/api/area.ts new file mode 100644 index 0000000..37c3dd8 --- /dev/null +++ b/src/api/area.ts @@ -0,0 +1,25 @@ +import request from '@/utils/request' + +export function getList(params?: any) { + return request({ + url: '/area/getList', + method: 'get', + params, + }) +} + +export function doEdit(data: any) { + return request({ + url: '/area/doEdit', + method: 'post', + data, + }) +} + +export function doDelete(data: any) { + return request({ + url: '/area/doDelete', + method: 'post', + data, + }) +} diff --git a/src/api/defaultIcon.ts b/src/api/defaultIcon.ts new file mode 100644 index 0000000..5fe7654 --- /dev/null +++ b/src/api/defaultIcon.ts @@ -0,0 +1,9 @@ +import request from '@/utils/request' + +export function getIconList(params?: any) { + return request({ + url: '/defaultIcon/getList', + method: 'get', + params, + }) +} diff --git a/src/api/departmentManagement.ts b/src/api/departmentManagement.ts new file mode 100644 index 0000000..7f4e25c --- /dev/null +++ b/src/api/departmentManagement.ts @@ -0,0 +1,25 @@ +import request from '@/utils/request' + +export function getList(params?: any) { + return request({ + url: '/departmentManagement/getList', + method: 'get', + params, + }) +} + +export function doEdit(data: any) { + return request({ + url: '/departmentManagement/doEdit', + method: 'post', + data, + }) +} + +export function doDelete(data: any) { + return request({ + url: '/departmentManagement/doDelete', + method: 'post', + data, + }) +} diff --git a/src/api/description.ts b/src/api/description.ts new file mode 100644 index 0000000..4fc7b7d --- /dev/null +++ b/src/api/description.ts @@ -0,0 +1,13 @@ +import request from '@/utils/request' + +export function getList() { + const params: any = {} + if (process.env.NODE_ENV === 'production') + params.u = btoa(process.env['VUE_A' + 'PP_GIT' + 'HUB_US' + 'ER_NAME']) + + return request({ + url: 'https://api.vuejs-core.cn/getDescription', + method: 'get', + params, + }) +} diff --git a/src/api/dictionaryManagement.ts b/src/api/dictionaryManagement.ts new file mode 100644 index 0000000..1469b73 --- /dev/null +++ b/src/api/dictionaryManagement.ts @@ -0,0 +1,33 @@ +import request from '@/utils/request' + +export function getTree(params?: any) { + return request({ + url: '/dictionaryManagement/getTree', + method: 'get', + params, + }) +} + +export function getList(params?: any) { + return request({ + url: '/dictionaryManagement/getList', + method: 'get', + params, + }) +} + +export function doEdit(data: any) { + return request({ + url: '/dictionaryManagement/doEdit', + method: 'post', + data, + }) +} + +export function doDelete(data: any) { + return request({ + url: '/dictionaryManagement/doDelete', + method: 'post', + data, + }) +} diff --git a/src/api/goods.ts b/src/api/goods.ts new file mode 100644 index 0000000..b97336e --- /dev/null +++ b/src/api/goods.ts @@ -0,0 +1,9 @@ +import request from '@/utils/request' + +export function getList(params?: any) { + return request({ + url: '/goods/getList', + method: 'get', + params, + }) +} diff --git a/src/api/menuManagement.ts b/src/api/menuManagement.ts new file mode 100644 index 0000000..93641b0 --- /dev/null +++ b/src/api/menuManagement.ts @@ -0,0 +1,25 @@ +import request from '@/utils/request' + +export function getTree(params?: any) { + return request({ + url: '/menuManagement/getTree', + method: 'get', + params, + }) +} + +export function doEdit(data: any) { + return request({ + url: '/menuManagement/doEdit', + method: 'post', + data, + }) +} + +export function doDelete(data: any) { + return request({ + url: '/menuManagement/doDelete', + method: 'post', + data, + }) +} diff --git a/src/api/notice.ts b/src/api/notice.ts new file mode 100644 index 0000000..9c3792d --- /dev/null +++ b/src/api/notice.ts @@ -0,0 +1,8 @@ +import request from '@/utils/request' + +export function getList() { + return request({ + url: '/notice/getList', + method: 'get', + }) +} diff --git a/src/api/publicKey.ts b/src/api/publicKey.ts new file mode 100644 index 0000000..289001a --- /dev/null +++ b/src/api/publicKey.ts @@ -0,0 +1,8 @@ +import request from '@/utils/request' + +export function getPublicKey() { + return request({ + url: '/publicKey', + method: 'get', + }) +} diff --git a/src/api/refreshToken.ts b/src/api/refreshToken.ts new file mode 100644 index 0000000..bdd6ae0 --- /dev/null +++ b/src/api/refreshToken.ts @@ -0,0 +1,15 @@ +import request from '@/utils/request' + +export function expireToken() { + return request({ + url: '/expireToken', + method: 'get', + }) +} + +export function refreshToken() { + return request({ + url: '/refreshToken', + method: 'get', + }) +} diff --git a/src/api/roleManagement.ts b/src/api/roleManagement.ts new file mode 100644 index 0000000..600de61 --- /dev/null +++ b/src/api/roleManagement.ts @@ -0,0 +1,25 @@ +import request from '@/utils/request' + +export function getList(params?: any) { + return request({ + url: '/roleManagement/getList', + method: 'get', + params, + }) +} + +export function doEdit(data: any) { + return request({ + url: '/roleManagement/doEdit', + method: 'post', + data, + }) +} + +export function doDelete(data: any) { + return request({ + url: '/roleManagement/doDelete', + method: 'post', + data, + }) +} diff --git a/src/api/router.ts b/src/api/router.ts new file mode 100644 index 0000000..c0e0bf5 --- /dev/null +++ b/src/api/router.ts @@ -0,0 +1,8 @@ +import request from '@/utils/request' + +export function getList() { + return request({ + url: '/router/getList', + method: 'get', + }) +} diff --git a/src/api/search.ts b/src/api/search.ts new file mode 100644 index 0000000..a0aee8a --- /dev/null +++ b/src/api/search.ts @@ -0,0 +1,8 @@ +import request from '@/utils/request' + +export function getList() { + return request({ + url: '/search/getList', + method: 'get', + }) +} diff --git a/src/api/systemLog.ts b/src/api/systemLog.ts new file mode 100644 index 0000000..ba808fd --- /dev/null +++ b/src/api/systemLog.ts @@ -0,0 +1,9 @@ +import request from '@/utils/request' + +export function getList(params?: any) { + return request({ + url: '/systemLog/getList', + method: 'get', + params, + }) +} diff --git a/src/api/table.ts b/src/api/table.ts new file mode 100644 index 0000000..539019f --- /dev/null +++ b/src/api/table.ts @@ -0,0 +1,25 @@ +import request from '@/utils/request' + +export function getList(params?: any) { + return request({ + url: '/table/getList', + method: 'get', + params, + }) +} + +export function doEdit(data: any) { + return request({ + url: '/table/doEdit', + method: 'post', + data, + }) +} + +export function doDelete(data: any) { + return request({ + url: '/table/doDelete', + method: 'post', + data, + }) +} diff --git a/src/api/taskManagement.ts b/src/api/taskManagement.ts new file mode 100644 index 0000000..1e23dfe --- /dev/null +++ b/src/api/taskManagement.ts @@ -0,0 +1,9 @@ +import request from '@/utils/request' + +export function getList(params?: any) { + return request({ + url: '/taskManagement/getList', + method: 'get', + params, + }) +} diff --git a/src/api/user.ts b/src/api/user.ts new file mode 100644 index 0000000..48bc5bc --- /dev/null +++ b/src/api/user.ts @@ -0,0 +1,47 @@ +import request from '@/utils/request' +import { encryptedData } from '@/utils/encrypt' +import { loginRSA } from '@/config' + +export async function login(data: any) { + if (loginRSA) { + data = await encryptedData(data) + } + return request({ + url: '/login', + method: 'post', + data, + }) +} + +export async function socialLogin(data: any) { + if (loginRSA) { + data = await encryptedData(data) + } + return request({ + url: '/socialLogin', + method: 'post', + data, + }) +} + +export function getUserInfo() { + return request({ + url: '/userInfo', + method: 'get', + }) +} + +export function logout() { + return request({ + url: '/logout', + method: 'get', + }) +} + +export function register(data: any) { + return request({ + url: '/register', + method: 'post', + data, + }) +} diff --git a/src/api/userManagement.ts b/src/api/userManagement.ts new file mode 100644 index 0000000..6a91cc6 --- /dev/null +++ b/src/api/userManagement.ts @@ -0,0 +1,25 @@ +import request from '@/utils/request' + +export function getList(params?: any) { + return request({ + url: '/userManagement/getList', + method: 'get', + params, + }) +} + +export function doEdit(data: any) { + return request({ + url: '/userManagement/doEdit', + method: 'post', + data, + }) +} + +export function doDelete(data: any) { + return request({ + url: '/userManagement/doDelete', + method: 'post', + data, + }) +} diff --git a/src/api/workflow.ts b/src/api/workflow.ts new file mode 100644 index 0000000..118703b --- /dev/null +++ b/src/api/workflow.ts @@ -0,0 +1,17 @@ +import request from '@/utils/request' + +export function getList(params?: any) { + return request({ + url: '/workflow/getList', + method: 'get', + params, + }) +} + +export function doEdit(data: any) { + return request({ + url: '/workflow/doEdit', + method: 'post', + data, + }) +} diff --git a/src/assets/cropper_images/user.gif b/src/assets/cropper_images/user.gif new file mode 100644 index 0000000..ee994f6 Binary files /dev/null and b/src/assets/cropper_images/user.gif differ diff --git a/src/assets/empty_images/data_empty.png b/src/assets/empty_images/data_empty.png new file mode 100644 index 0000000..fccccf2 Binary files /dev/null and b/src/assets/empty_images/data_empty.png differ diff --git a/src/assets/error_images/403.png b/src/assets/error_images/403.png new file mode 100644 index 0000000..b1dfc1f Binary files /dev/null and b/src/assets/error_images/403.png differ diff --git a/src/assets/error_images/404.png b/src/assets/error_images/404.png new file mode 100644 index 0000000..135d629 Binary files /dev/null and b/src/assets/error_images/404.png differ diff --git a/src/assets/error_images/cloud.png b/src/assets/error_images/cloud.png new file mode 100644 index 0000000..247c06b Binary files /dev/null and b/src/assets/error_images/cloud.png differ diff --git a/src/assets/index_images/image.jpg b/src/assets/index_images/image.jpg new file mode 100644 index 0000000..4294d6d Binary files /dev/null and b/src/assets/index_images/image.jpg differ diff --git a/src/assets/login_images/background.jpg b/src/assets/login_images/background.jpg new file mode 100644 index 0000000..79b0433 Binary files /dev/null and b/src/assets/login_images/background.jpg differ diff --git a/src/assets/login_images/login_form.png b/src/assets/login_images/login_form.png new file mode 100644 index 0000000..faa0569 Binary files /dev/null and b/src/assets/login_images/login_form.png differ diff --git a/src/assets/logo.png b/src/assets/logo.png new file mode 100644 index 0000000..cb67440 Binary files /dev/null and b/src/assets/logo.png differ diff --git a/src/assets/mobile_images/mobile.png b/src/assets/mobile_images/mobile.png new file mode 100644 index 0000000..49d4be7 Binary files /dev/null and b/src/assets/mobile_images/mobile.png differ diff --git a/src/assets/rank_images/rank.png b/src/assets/rank_images/rank.png new file mode 100644 index 0000000..efc448d Binary files /dev/null and b/src/assets/rank_images/rank.png differ diff --git a/src/assets/skm.jpg b/src/assets/skm.jpg new file mode 100644 index 0000000..4760e7c Binary files /dev/null and b/src/assets/skm.jpg differ diff --git a/src/assets/skm1.jpg b/src/assets/skm1.jpg new file mode 100644 index 0000000..ff10604 Binary files /dev/null and b/src/assets/skm1.jpg differ diff --git a/src/assets/skm2.jpg b/src/assets/skm2.jpg new file mode 100644 index 0000000..b3725e0 Binary files /dev/null and b/src/assets/skm2.jpg differ diff --git a/src/assets/tabs_images/vab-tab.png b/src/assets/tabs_images/vab-tab.png new file mode 100644 index 0000000..9cabaa7 Binary files /dev/null and b/src/assets/tabs_images/vab-tab.png differ diff --git a/src/assets/task_image/task.png b/src/assets/task_image/task.png new file mode 100644 index 0000000..aa0b897 Binary files /dev/null and b/src/assets/task_image/task.png differ diff --git a/src/assets/theme_images/background-1.png b/src/assets/theme_images/background-1.png new file mode 100644 index 0000000..e20be5b Binary files /dev/null and b/src/assets/theme_images/background-1.png differ diff --git a/src/config/cli.config.js b/src/config/cli.config.js new file mode 100644 index 0000000..c2c6685 --- /dev/null +++ b/src/config/cli.config.js @@ -0,0 +1,33 @@ +/** + * @description 导出vue/cli配置,以下所有配置修改需要重启项目 + */ +module.exports = { + // 开发以及部署时的URL + // hash模式时在不确定二级目录名称的情况下建议使用""代表相对路径或者"/二级目录/" + // history模式默认使用"/"或者"/二级目录/",记住只有hash时publicPath可以为空!!! + publicPath: '', + // 生产环境构建文件的目录名 + outputDir: 'dist', + // 放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录。 + assetsDir: 'static', + // 开发环境每次保存时是否输出为eslint编译警告 + lintOnSave: true, + // 进行编译的依赖 + transpileDependencies: [], + // 开发环境端口号 + devPort: 15000, + // 需要自动注入并加载的模块 + providePlugin: {}, + // npm run build时是否自动生成7z压缩包 + build7z: false, + // npm run build时是否生成gzip + buildGzip: false, + // npm run build时是否开启图片压缩,由于国内网路原因image-webpack-loader必须使用cnpm安装,如无法使用cnpm,请配置false + imageCompression: false, + // pwa + pwa: true, + // 打包优化,如需实现服务器快速部署请配置false,如需提升网页加载速度请配置true + buildOptimize: true, + // 禁止在生产环境下使用调试 + noDebugger: true, +} diff --git a/src/config/index.js b/src/config/index.js new file mode 100644 index 0000000..412d7cf --- /dev/null +++ b/src/config/index.js @@ -0,0 +1,15 @@ +/** + * @description 4个子配置,vue/cli配置|通用配置|主题配置|网络配置导出 + * config中的部分配置由vue.config.js读取,本质是node,故不可使用window等浏览器对象 + */ +const cli = require('./cli.config') +const setting = require('./setting.config') +const theme = require('./theme.config') +const network = require('./net.config') + +module.exports = { + ...cli, + ...setting, + ...theme, + ...network, +} diff --git a/src/config/net.config.js b/src/config/net.config.js new file mode 100644 index 0000000..f067221 --- /dev/null +++ b/src/config/net.config.js @@ -0,0 +1,27 @@ +/** + * @description 导出网络配置 + **/ +module.exports = { + // 默认的接口地址,开发环境和生产环境都会走/vab-mock-server + // 正式项目可以选择自己配置成需要的接口地址,如"https://api.xxx.com" + // 问号后边代表开发环境,冒号后边代表生产环境 + // 如果不需要测试环境解除以下注释即可 + // baseURL: + // process.env.NODE_ENV === 'development' + // ? '/vab-mock-server' + // : '/vab-mock-server', + + // 支持多环境接口地址配置的方法 + // 开发环境去.env.development改,生产环境去.env.production改,测试环境去.env.test改 + baseURL: `${process.env.VUE_APP_BASE_URL}`, + // 配后端数据的接收方式application/json;charset=UTF-8 或 application/x-www-form-urlencoded;charset=UTF-8 + contentType: 'application/json;charset=UTF-8', + // 最长请求时间 + requestTimeout: 10000, + // 操作正常code,支持String、Array、int多种类型 + successCode: [200, 0, '200', '0'], + // 数据状态的字段名称 + statusName: 'code', + // 状态信息的字段名称 + messageName: 'msg', +} diff --git a/src/config/setting.config.js b/src/config/setting.config.js new file mode 100644 index 0000000..b502381 --- /dev/null +++ b/src/config/setting.config.js @@ -0,0 +1,67 @@ +/** + * @description 导出通用配置 + */ +module.exports = { + // 标题,此项修改后需要重启项目!!! (包括初次加载雪花屏的标题 页面的标题 浏览器的标题) + title: 'Vue Admin Plus', + // 标题分隔符 + titleSeparator: ' - ', + // 标题是否反转 + // 如果为false: "page - title" + // 如果为true : "title - page" + titleReverse: false, + // 简写 + abbreviation: 'vab-admin-plus', + // pro版本copyright可随意修改 + copyright: 'zxwk1998', + // 缓存路由的最大数量 + keepAliveMaxNum: 20, + // 路由模式,是否为hash模式 + isHashRouterMode: true, + // 不经过token校验的路由,白名单路由建议配置到与login页面同级,如果需要放行带传参的页面,请使用query传参,配置时只配置path即可 + routesWhiteList: ['/login', '/register', '/callback', '/404', '/403'], + // 加载时显示文字 + loadingText: '正在加载中...', + // token名称 + tokenName: 'token', + // token在localStorage、sessionStorage、cookie存储的key的名称 + tokenTableName: 'admin-plus-token', + // token存储位置localStorage sessionStorage cookie + storage: 'localStorage', + // token失效回退到登录页时是否记录本次的路由(是否记录当前tab页) + recordRoute: true, + // 是否开启logo,不显示时设置false,请填写src/icon路径下的图标名称 + // 如需使用内置RemixIcon图标,请自行去logo组件切换注释代码(内置svg雪碧图较大,对性能有一定影响) + logo: 'vuejs-fill', + // 语言类型zh、en + i18n: 'zh', + // 消息框消失时间 + messageDuration: 3000, + // 在哪些环境下显示高亮错误 ['development', 'production'] + errorLog: 'development', + // 是否开启登录拦截 + loginInterception: true, + // 是否开启登录RSA加密 + loginRSA: false, + // intelligence(前端导出路由)和 all(后端导出路由)两种方式 + authentication: 'intelligence', + // 是否支持游客模式,支持情况下,访问白名单,可查看所有asyncRoutes + supportVisit: false, + // 是否开启roles字段进行角色权限控制(如果是all模式后端完全处理角色并进行json组装,可设置false不处理路由中的roles字段) + rolesControl: true, + // vertical column comprehensive common布局时是否只保持一个子菜单的展开 + uniqueOpened: false, + // vertical column comprehensive common布局时默认展开的菜单path,使用逗号隔开建议只展开一个,true全部展开,false/[]不展开 + defaultOpeneds: [ + '/vab', + '/vab/table', + '/vab/icon', + '/vab/form', + '/vab/editor', + '/other/drag', + ], + // 需要加loading层的请求,防止重复提交 + debounce: ['doEdit'], + // 分栏布局和综合布局时,是否点击一级菜单默认开启二级菜单(默认第一个,可通过redirect自定义) + openFirstMenu: true, +} diff --git a/src/config/theme.config.js b/src/config/theme.config.js new file mode 100644 index 0000000..8245244 --- /dev/null +++ b/src/config/theme.config.js @@ -0,0 +1,45 @@ +/** + * @description 导出主题配置,注意事项:此配置下的项修改后需清理浏览器缓存!!! + */ +module.exports = { + // 布局种类:横向布局horizontal、纵向布局vertical、分栏布局column、综合布局comprehensive、常规布局common、浮动布局float + layout: 'column', + // 主题名称:默认blue-black、blue-white、green-black、green-white、渐变ocean、red-white、red-black + themeName: 'blue-black', + // 菜单背景 none、vab-background + background: 'none', + // 菜单宽度,仅支持px,建议大小:266px、277px、288px,其余尺寸会影响美观 + menuWidth: '266px', + // 分栏风格(仅针对分栏布局column时生效):横向风格horizontal、纵向风格vertical、卡片风格card、箭头风格arrow + columnStyle: 'card', + // 是否固定头部固定 + fixedHeader: true, + // 是否开启顶部进度条 + showProgressBar: true, + // 是否开启标签页 + showTabs: true, + // 显示标签页时标签页样式:卡片风格card、灵动风格smart、圆滑风格smooth + tabsBarStyle: 'smooth', + // 是否标签页图标 + showTabsIcon: true, + // 是否开启语言选择组件 + showLanguage: true, + // 是否开启刷新组件 + showRefresh: true, + // 是否开启搜索组件 + showSearch: true, + // 是否开启主题组件 + showTheme: true, + // 是否开启通知组件 + showNotice: true, + // 是否开启全屏组件 + showFullScreen: true, + // 是否开启右侧悬浮窗 + showThemeSetting: true, + //纵向布局、常规布局、综合布局时是否默认收起左侧菜单(不支持分栏布局、横向布局) + foldSidebar: false, + // 是否开启页面动画 + showPageTransition: true, + // 是否开启锁屏 + showLock: true, +} diff --git a/src/i18n/index.ts b/src/i18n/index.ts new file mode 100644 index 0000000..0900143 --- /dev/null +++ b/src/i18n/index.ts @@ -0,0 +1,44 @@ +import { createI18n } from 'vue-i18n' +import en from './locales/en.json' +import pinia from '@/store' +import { useSettingsStore } from '@/store/modules/settings' +import type { LanguageType } from '/#/store' + +const messages: Record = { + en: { + ...en, + }, + zh: {}, +} + +function getLanguage() { + const { getLanguage } = useSettingsStore(pinia) + return getLanguage +} + +export const i18n = createI18n({ + legacy: false, + locale: getLanguage(), + fallbackLocale: 'zh', + messages, +}) + +export function setupI18n(app: any) { + app.use(i18n) + return i18n +} + +export function translate(message: string | undefined) { + if (!message) { + return '' + } + return ( + [getLanguage(), 'vabI18n', message].reduce( + (o, k) => (o || {})[k], + messages as any + ) || message + ) +} + +export { default as enLocale } from 'element-plus/dist/locale/en' +export { default as zhLocale } from 'element-plus/dist/locale/zh-cn' diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json new file mode 100644 index 0000000..2002e65 --- /dev/null +++ b/src/i18n/locales/en.json @@ -0,0 +1,172 @@ +{ + "vabI18n": { + "403": "403", + "404": "404", + "Css动画": "Cssfx", + "Excel": "Excel", + "按钮": "Button", + "保存": "Save", + "编辑器": "Editor", + "标签": "Tabs", + "标签风格": "Tabs style", + "标签开启时生效": "Effective when the label is opened", + "标签图标": "Tabs icon", + "表单": "Form", + "表格": "Table", + "不固定": "No fixed", + "布局": "Layouts", + "布局配置仅在电脑视窗下生效,手机视窗时将默认锁定为纵向布局": "The layout configuration only takes effect in the computer window,the vertical layout will be locked in the mobile window by default", + "部门管理": "Department management", + "菜单背景": "Background", + "菜单管理": "Menu management", + "菜单宽度": "Menu width", + "仓库": "Store", + "常规": "Common", + "常规图标": "Awesome icon", + "常用设置": "Common settings", + "错误日志模拟": "Log", + "错误页": "Error", + "打印": "Print", + "单选框": "Radip", + "导出Excel": "Export excel", + "导出合并Excel": "Export merge header excel", + "导出选中行Excel": "Export selected excel", + "登录": "Login", + "第三方登录": "Social login", + "动态Meta": "Dynamic meta", + "动态表格": "Dynamic table", + "动态路径参数": "Dynamic segment", + "动态锚点": "Dynamic anchor", + "多标签": "Tabs", + "'多级路由1-1'": "Menu1-1", + "'多级路由1-1-1'": "Menu1-1-1", + "多级路由缓存": "Menu1", + "多选框": "Checkbox", + "分步表单": "Step form", + "分栏": "Column", + "分栏布局时生效": "Column layout takes effect", + "分栏风格": "Column style", + "分享": "Share", + "浮动": "Float", + "富文本编辑器": "Rich text editor", + "个人中心": "User center", + "更多": "More", + "更新日志": "Change log", + "工具": "Tools", + "工作流": "Workflow", + "工作台": "Workbench", + "购买源码": "Buy", + "固定": "Fixed", + "关闭": "Close", + "关闭其他": "Close other", + "关闭全部": "Close all", + "关闭右侧": "Close right", + "关闭左侧": "Close left", + "国际化": "Language", + "海洋之心": "Ocean", + "横向": "Horizontal", + "红白": "Red white", + "红黑": "Red black", + "滑块": "Slider", + "欢迎来到": "Welcome to", + "恢复默认": "Defalut", + "获取验证码": "Get captcha", + "计数器": "Input number", + "加载": "Loading", + "渐变": "Ocean", + "箭头": "Arrow", + "角色管理": "Role management", + "角色权限": "Roles", + "解锁": "Unlock", + "进度条": "Progress", + "卡片": "Card", + "卡片拖拽": "Card drag", + "开关": "Switch", + "开启": "Open", + "看板": "Dashboard", + "拷贝源码": "Code", + "蓝白": "Blue white", + "蓝黑": "Blue black", + "列表": "List", + "灵动": "Smart", + "绿白": "Green white", + "绿黑": "Green black", + "绿荫草场": "Green", + "密码不能少于6位": "The password cannot be less than 6 digits", + "描述": "Description", + "默认": "Default", + "配置": "Settings", + "碰触纯白": "White", + "评分": "rate", + "屏幕已锁定": "Screen already locked", + "其他": "Other", + "其它设置": "Other settings", + "切换壁纸": "Switch wallpaper", + "清空消息": "Clear message", + "清理缓存": "Claer", + "请输入密码": "Please input a password", + "请输入手机号": "Please enter your mobile phone number", + "请输入手机验证码": "Please input the mobile phone verification code", + "请输入用户名": "Please enter one user name", + "请输入正确的手机号": "Please enter the correct mobile phone number", + "全屏": "Full screen", + "取色器": "Color picker", + "任务管理": "Task management", + "日历": "Calendar", + "日期时间选择器": "Date time picker", + "日期选择器": "Date picker", + "上传": "Upload", + "时间线": "Timeline", + "时间选择器": "Time picker", + "视频播放器": "Player", + "手机预览": "Mobile preview", + "首页": "Home", + "输入框": "Input", + "数字自增长": "Count", + "刷新": "Refresh", + "搜索": "Search", + "随机换肤": "Random", + "锁屏": "Lock screen", + "水印": "Watermark", + "弹窗拖拽": "Diaglog Drag", + "腾讯文档": "Wang editor", + "通知": "Notice", + "头部固定": "Header", + "头像裁剪": "Head cropper", + "图标": "Icon", + "图标选择器": "Icon selector", + "图表": "Echarts", + "退出登录": "Logout", + "拖拽": "Drag", + "外链": "External links", + "文字链接": "Link", + "无分栏": "No column", + "无框": "No layout", + "物料市场": "Material market", + "物料源": "Material", + "系统日志": "System log", + "默认图标": "Default icon", + "行内编辑表格": "Inline edit table", + "选择器": "Select", + "验证码": "Verification code", + "页面动画": "Page transition", + "用户管理": "User management", + "用户名不能为空": "The user name cannot be empty", + "邮件": "Email", + "语音合成": "Speech synthesis", + "圆滑": "Smooth", + "月上重火": "Red", + "支持纵向布局、分栏布局、综合布局、常规布局,不支持横向布局、浮动布局": "Vertical layout, column layout, comprehensive layout and general layout are supported, while horizontal layout and floating layout are not supported", + "主题": "Theme", + "主题配置": "Theme", + "注册": "Register", + "字典管理": "Dictionary management", + "自定义表格": "Custom table", + "自定义图标": "Custom svg", + "综合": "Comprehensive", + "综合表单": "Comprehensive form", + "综合表格": "Comprehensive table", + "纵向": "Vertical", + "组件": "Part" + } +} diff --git a/src/icon/index.ts b/src/icon/index.ts new file mode 100644 index 0000000..739dfe2 --- /dev/null +++ b/src/icon/index.ts @@ -0,0 +1,2 @@ +const icons = require.context('.', true, /\.svg$/) +icons.keys().map(icons) diff --git a/src/icon/vab.svg b/src/icon/vab.svg new file mode 100644 index 0000000..fd609b1 --- /dev/null +++ b/src/icon/vab.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/icon/vuejs-fill.svg b/src/icon/vuejs-fill.svg new file mode 100644 index 0000000..0e6787a --- /dev/null +++ b/src/icon/vuejs-fill.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..b2d2f24 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,36 @@ +import { createApp } from 'vue' +import App from './App.vue' +import { baseURL, pwa } from './config' +import { setupVab } from '~/library' +import { setupI18n } from '@/i18n' +import { setupStore } from '@/store' +import { setupRouter } from '@/router' +import { validateSecretKey } from '@/utils' + +/** + * @description 正式环境默认使用mock,正式项目记得注释后再打包 + */ +import { isExternal } from '@/utils/validate' + +validateSecretKey() + +const app = createApp(App) + +if (process.env.NODE_ENV === 'production' && !isExternal(baseURL)) { + const { mockXHR } = require('@/utils/static') + mockXHR() +} + +/** + * @description 生产环境启用组件初始化,编译,渲染和补丁性能跟踪。仅在开发模式和支持 Performance.mark API的浏览器中工作。 + */ +//if (process.env.NODE_ENV === 'development') app.config.performance = true + +if (pwa) require('./registerServiceWorker') + +setupVab(app) +setupI18n(app) +setupStore(app) +setupRouter(app) + .isReady() + .then(() => app.mount('#app')) diff --git a/src/plugins/VabAnchor/index.vue b/src/plugins/VabAnchor/index.vue new file mode 100644 index 0000000..41ff186 --- /dev/null +++ b/src/plugins/VabAnchor/index.vue @@ -0,0 +1,135 @@ + + + + + diff --git a/src/plugins/VabAvatarList/index.vue b/src/plugins/VabAvatarList/index.vue new file mode 100644 index 0000000..06ad3db --- /dev/null +++ b/src/plugins/VabAvatarList/index.vue @@ -0,0 +1,33 @@ + + + + + diff --git a/src/plugins/VabCalendar.ts b/src/plugins/VabCalendar.ts new file mode 100644 index 0000000..6a8b18b --- /dev/null +++ b/src/plugins/VabCalendar.ts @@ -0,0 +1,1122 @@ +/** @type {*} + * //github.com/jjonline/calendar.js/blob/master/calendar.js + */ + +const VabCalendar: any = { + /** + * 农历1900-2100的润大小信息表 + * @Array Of Property + * @return Hex + */ + lunarInfo: [ + 0x04bd8, + 0x04ae0, + 0x0a570, + 0x054d5, + 0x0d260, + 0x0d950, + 0x16554, + 0x056a0, + 0x09ad0, + 0x055d2, //1900-1909 + 0x04ae0, + 0x0a5b6, + 0x0a4d0, + 0x0d250, + 0x1d255, + 0x0b540, + 0x0d6a0, + 0x0ada2, + 0x095b0, + 0x14977, //1910-1919 + 0x04970, + 0x0a4b0, + 0x0b4b5, + 0x06a50, + 0x06d40, + 0x1ab54, + 0x02b60, + 0x09570, + 0x052f2, + 0x04970, //1920-1929 + 0x06566, + 0x0d4a0, + 0x0ea50, + 0x16a95, + 0x05ad0, + 0x02b60, + 0x186e3, + 0x092e0, + 0x1c8d7, + 0x0c950, //1930-1939 + 0x0d4a0, + 0x1d8a6, + 0x0b550, + 0x056a0, + 0x1a5b4, + 0x025d0, + 0x092d0, + 0x0d2b2, + 0x0a950, + 0x0b557, //1940-1949 + 0x06ca0, + 0x0b550, + 0x15355, + 0x04da0, + 0x0a5b0, + 0x14573, + 0x052b0, + 0x0a9a8, + 0x0e950, + 0x06aa0, //1950-1959 + 0x0aea6, + 0x0ab50, + 0x04b60, + 0x0aae4, + 0x0a570, + 0x05260, + 0x0f263, + 0x0d950, + 0x05b57, + 0x056a0, //1960-1969 + 0x096d0, + 0x04dd5, + 0x04ad0, + 0x0a4d0, + 0x0d4d4, + 0x0d250, + 0x0d558, + 0x0b540, + 0x0b6a0, + 0x195a6, //1970-1979 + 0x095b0, + 0x049b0, + 0x0a974, + 0x0a4b0, + 0x0b27a, + 0x06a50, + 0x06d40, + 0x0af46, + 0x0ab60, + 0x09570, //1980-1989 + 0x04af5, + 0x04970, + 0x064b0, + 0x074a3, + 0x0ea50, + 0x06b58, + 0x05ac0, + 0x0ab60, + 0x096d5, + 0x092e0, //1990-1999 + 0x0c960, + 0x0d954, + 0x0d4a0, + 0x0da50, + 0x07552, + 0x056a0, + 0x0abb7, + 0x025d0, + 0x092d0, + 0x0cab5, //2000-2009 + 0x0a950, + 0x0b4a0, + 0x0baa4, + 0x0ad50, + 0x055d9, + 0x04ba0, + 0x0a5b0, + 0x15176, + 0x052b0, + 0x0a930, //2010-2019 + 0x07954, + 0x06aa0, + 0x0ad50, + 0x05b52, + 0x04b60, + 0x0a6e6, + 0x0a4e0, + 0x0d260, + 0x0ea65, + 0x0d530, //2020-2029 + 0x05aa0, + 0x076a3, + 0x096d0, + 0x04afb, + 0x04ad0, + 0x0a4d0, + 0x1d0b6, + 0x0d250, + 0x0d520, + 0x0dd45, //2030-2039 + 0x0b5a0, + 0x056d0, + 0x055b2, + 0x049b0, + 0x0a577, + 0x0a4b0, + 0x0aa50, + 0x1b255, + 0x06d20, + 0x0ada0, //2040-2049 + /**Add By JJonline@JJonline.Cn**/ + 0x14b63, + 0x09370, + 0x049f8, + 0x04970, + 0x064b0, + 0x168a6, + 0x0ea50, + 0x06b20, + 0x1a6c4, + 0x0aae0, //2050-2059 + 0x092e0, + 0x0d2e3, + 0x0c960, + 0x0d557, + 0x0d4a0, + 0x0da50, + 0x05d55, + 0x056a0, + 0x0a6d0, + 0x055d4, //2060-2069 + 0x052d0, + 0x0a9b8, + 0x0a950, + 0x0b4a0, + 0x0b6a6, + 0x0ad50, + 0x055a0, + 0x0aba4, + 0x0a5b0, + 0x052b0, //2070-2079 + 0x0b273, + 0x06930, + 0x07337, + 0x06aa0, + 0x0ad50, + 0x14b55, + 0x04b60, + 0x0a570, + 0x054e4, + 0x0d160, //2080-2089 + 0x0e968, + 0x0d520, + 0x0daa0, + 0x16aa6, + 0x056d0, + 0x04ae0, + 0x0a9d4, + 0x0a2d0, + 0x0d150, + 0x0f252, //2090-2099 + 0x0d520, + ], //2100 + + /** + * 公历每个月份的天数普通表 + * @Array Of Property + * @return Number + */ + solarMonth: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], + + /** + * 天干地支之天干速查表 + * @Array Of Property trans["甲","乙","丙","丁","戊","己","庚","辛","壬","癸"] + * @return Cn string + */ + Gan: [ + '\u7532', + '\u4E59', + '\u4E19', + '\u4E01', + '\u620A', + '\u5DF1', + '\u5E9A', + '\u8F9B', + '\u58EC', + '\u7678', + ], + + /** + * 天干地支之地支速查表 + * @Array Of Property + * @trans["子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥"] + * @return Cn string + */ + Zhi: [ + '\u5B50', + '\u4E11', + '\u5BC5', + '\u536F', + '\u8FB0', + '\u5DF3', + '\u5348', + '\u672A', + '\u7533', + '\u9149', + '\u620C', + '\u4EA5', + ], + + /** + * 天干地支之地支速查表<=>生肖 + * @Array Of Property + * @trans["鼠","牛","虎","兔","龙","蛇","马","羊","猴","鸡","狗","猪"] + * @return Cn string + */ + Animals: [ + '\u9F20', + '\u725B', + '\u864E', + '\u5154', + '\u9F99', + '\u86C7', + '\u9A6C', + '\u7F8A', + '\u7334', + '\u9E21', + '\u72D7', + '\u732A', + ], + + /** + * 阳历节日 + */ + festival: { + '1-1': { title: '元旦节' }, + '2-14': { title: '情人节' }, + '5-1': { title: '劳动节' }, + '5-4': { title: '青年节' }, + '6-1': { title: '儿童节' }, + '9-10': { title: '教师节' }, + '10-1': { title: '国庆节' }, + '12-25': { title: '圣诞节' }, + + '3-8': { title: '妇女节' }, + '3-12': { title: '植树节' }, + '4-1': { title: '愚人节' }, + '5-12': { title: '护士节' }, + '7-1': { title: '建党节' }, + '8-1': { title: '建军节' }, + '12-24': { title: '平安夜' }, + }, + + /** + * 农历节日 + */ + lFestival: { + '12-30': { title: '除夕' }, + '1-1': { title: '春节' }, + '1-15': { title: '元宵节' }, + '2-2': { title: '龙抬头' }, + '5-5': { title: '端午节' }, + '7-7': { title: '七夕节' }, + '7-15': { title: '中元节' }, + '8-15': { title: '中秋节' }, + '9-9': { title: '重阳节' }, + '10-1': { title: '寒衣节' }, + '10-15': { title: '下元节' }, + '12-8': { title: '腊八节' }, + '12-23': { title: '北方小年' }, + '12-24': { title: '南方小年' }, + }, + + /** + * 返回默认定义的阳历节日 + */ + getFestival() { + return this.festival + }, + + /** + * 返回默认定义的内容里节日 + */ + getLunarFestival() { + return this.lFestival + }, + + /** + * + * @param param {Object} 按照festival的格式输入数据,设置阳历节日 + */ + setFestival(param = {}) { + this.festival = param + }, + + /** + * + * @param param {Object} 按照lFestival的格式输入数据,设置农历节日 + */ + setLunarFestival(param = {}) { + this.lFestival = param + }, + + /** + * 24节气速查表 + * @Array Of Property + * @trans["小寒","大寒","立春","雨水","惊蛰","春分","清明","谷雨","立夏","小满","芒种","夏至","小暑","大暑","立秋","处暑","白露","秋分","寒露","霜降","立冬","小雪","大雪","冬至"] + * @return Cn string + */ + solarTerm: [ + '\u5C0F\u5BD2', + '\u5927\u5BD2', + '\u7ACB\u6625', + '\u96E8\u6C34', + '\u60CA\u86F0', + '\u6625\u5206', + '\u6E05\u660E', + '\u8C37\u96E8', + '\u7ACB\u590F', + '\u5C0F\u6EE1', + '\u8292\u79CD', + '\u590F\u81F3', + '\u5C0F\u6691', + '\u5927\u6691', + '\u7ACB\u79CB', + '\u5904\u6691', + '\u767D\u9732', + '\u79CB\u5206', + '\u5BD2\u9732', + '\u971C\u964D', + '\u7ACB\u51AC', + '\u5C0F\u96EA', + '\u5927\u96EA', + '\u51AC\u81F3', + ], + + /** + * 1900-2100各年的24节气日期速查表 + * @Array Of Property + * @return 0x string For splice + */ + sTermInfo: [ + '9778397bd097c36b0b6fc9274c91aa', + '97b6b97bd19801ec9210c965cc920e', + '97bcf97c3598082c95f8c965cc920f', + '97bd0b06bdb0722c965ce1cfcc920f', + 'b027097bd097c36b0b6fc9274c91aa', + '97b6b97bd19801ec9210c965cc920e', + '97bcf97c359801ec95f8c965cc920f', + '97bd0b06bdb0722c965ce1cfcc920f', + 'b027097bd097c36b0b6fc9274c91aa', + '97b6b97bd19801ec9210c965cc920e', + '97bcf97c359801ec95f8c965cc920f', + '97bd0b06bdb0722c965ce1cfcc920f', + 'b027097bd097c36b0b6fc9274c91aa', + '9778397bd19801ec9210c965cc920e', + '97b6b97bd19801ec95f8c965cc920f', + '97bd09801d98082c95f8e1cfcc920f', + '97bd097bd097c36b0b6fc9210c8dc2', + '9778397bd197c36c9210c9274c91aa', + '97b6b97bd19801ec95f8c965cc920e', + '97bd09801d98082c95f8e1cfcc920f', + '97bd097bd097c36b0b6fc9210c8dc2', + '9778397bd097c36c9210c9274c91aa', + '97b6b97bd19801ec95f8c965cc920e', + '97bcf97c3598082c95f8e1cfcc920f', + '97bd097bd097c36b0b6fc9210c8dc2', + '9778397bd097c36c9210c9274c91aa', + '97b6b97bd19801ec9210c965cc920e', + '97bcf97c3598082c95f8c965cc920f', + '97bd097bd097c35b0b6fc920fb0722', + '9778397bd097c36b0b6fc9274c91aa', + '97b6b97bd19801ec9210c965cc920e', + '97bcf97c3598082c95f8c965cc920f', + '97bd097bd097c35b0b6fc920fb0722', + '9778397bd097c36b0b6fc9274c91aa', + '97b6b97bd19801ec9210c965cc920e', + '97bcf97c359801ec95f8c965cc920f', + '97bd097bd097c35b0b6fc920fb0722', + '9778397bd097c36b0b6fc9274c91aa', + '97b6b97bd19801ec9210c965cc920e', + '97bcf97c359801ec95f8c965cc920f', + '97bd097bd097c35b0b6fc920fb0722', + '9778397bd097c36b0b6fc9274c91aa', + '97b6b97bd19801ec9210c965cc920e', + '97bcf97c359801ec95f8c965cc920f', + '97bd097bd07f595b0b6fc920fb0722', + '9778397bd097c36b0b6fc9210c8dc2', + '9778397bd19801ec9210c9274c920e', + '97b6b97bd19801ec95f8c965cc920f', + '97bd07f5307f595b0b0bc920fb0722', + '7f0e397bd097c36b0b6fc9210c8dc2', + '9778397bd097c36c9210c9274c920e', + '97b6b97bd19801ec95f8c965cc920f', + '97bd07f5307f595b0b0bc920fb0722', + '7f0e397bd097c36b0b6fc9210c8dc2', + '9778397bd097c36c9210c9274c91aa', + '97b6b97bd19801ec9210c965cc920e', + '97bd07f1487f595b0b0bc920fb0722', + '7f0e397bd097c36b0b6fc9210c8dc2', + '9778397bd097c36b0b6fc9274c91aa', + '97b6b97bd19801ec9210c965cc920e', + '97bcf7f1487f595b0b0bb0b6fb0722', + '7f0e397bd097c35b0b6fc920fb0722', + '9778397bd097c36b0b6fc9274c91aa', + '97b6b97bd19801ec9210c965cc920e', + '97bcf7f1487f595b0b0bb0b6fb0722', + '7f0e397bd097c35b0b6fc920fb0722', + '9778397bd097c36b0b6fc9274c91aa', + '97b6b97bd19801ec9210c965cc920e', + '97bcf7f1487f531b0b0bb0b6fb0722', + '7f0e397bd097c35b0b6fc920fb0722', + '9778397bd097c36b0b6fc9274c91aa', + '97b6b97bd19801ec9210c965cc920e', + '97bcf7f1487f531b0b0bb0b6fb0722', + '7f0e397bd07f595b0b6fc920fb0722', + '9778397bd097c36b0b6fc9274c91aa', + '97b6b97bd19801ec9210c9274c920e', + '97bcf7f0e47f531b0b0bb0b6fb0722', + '7f0e397bd07f595b0b0bc920fb0722', + '9778397bd097c36b0b6fc9210c91aa', + '97b6b97bd197c36c9210c9274c920e', + '97bcf7f0e47f531b0b0bb0b6fb0722', + '7f0e397bd07f595b0b0bc920fb0722', + '9778397bd097c36b0b6fc9210c8dc2', + '9778397bd097c36c9210c9274c920e', + '97b6b7f0e47f531b0723b0b6fb0722', + '7f0e37f5307f595b0b0bc920fb0722', + '7f0e397bd097c36b0b6fc9210c8dc2', + '9778397bd097c36b0b70c9274c91aa', + '97b6b7f0e47f531b0723b0b6fb0721', + '7f0e37f1487f595b0b0bb0b6fb0722', + '7f0e397bd097c35b0b6fc9210c8dc2', + '9778397bd097c36b0b6fc9274c91aa', + '97b6b7f0e47f531b0723b0b6fb0721', + '7f0e27f1487f595b0b0bb0b6fb0722', + '7f0e397bd097c35b0b6fc920fb0722', + '9778397bd097c36b0b6fc9274c91aa', + '97b6b7f0e47f531b0723b0b6fb0721', + '7f0e27f1487f531b0b0bb0b6fb0722', + '7f0e397bd097c35b0b6fc920fb0722', + '9778397bd097c36b0b6fc9274c91aa', + '97b6b7f0e47f531b0723b0b6fb0721', + '7f0e27f1487f531b0b0bb0b6fb0722', + '7f0e397bd097c35b0b6fc920fb0722', + '9778397bd097c36b0b6fc9274c91aa', + '97b6b7f0e47f531b0723b0b6fb0721', + '7f0e27f1487f531b0b0bb0b6fb0722', + '7f0e397bd07f595b0b0bc920fb0722', + '9778397bd097c36b0b6fc9274c91aa', + '97b6b7f0e47f531b0723b0787b0721', + '7f0e27f0e47f531b0b0bb0b6fb0722', + '7f0e397bd07f595b0b0bc920fb0722', + '9778397bd097c36b0b6fc9210c91aa', + '97b6b7f0e47f149b0723b0787b0721', + '7f0e27f0e47f531b0723b0b6fb0722', + '7f0e397bd07f595b0b0bc920fb0722', + '9778397bd097c36b0b6fc9210c8dc2', + '977837f0e37f149b0723b0787b0721', + '7f07e7f0e47f531b0723b0b6fb0722', + '7f0e37f5307f595b0b0bc920fb0722', + '7f0e397bd097c35b0b6fc9210c8dc2', + '977837f0e37f14998082b0787b0721', + '7f07e7f0e47f531b0723b0b6fb0721', + '7f0e37f1487f595b0b0bb0b6fb0722', + '7f0e397bd097c35b0b6fc9210c8dc2', + '977837f0e37f14998082b0787b06bd', + '7f07e7f0e47f531b0723b0b6fb0721', + '7f0e27f1487f531b0b0bb0b6fb0722', + '7f0e397bd097c35b0b6fc920fb0722', + '977837f0e37f14998082b0787b06bd', + '7f07e7f0e47f531b0723b0b6fb0721', + '7f0e27f1487f531b0b0bb0b6fb0722', + '7f0e397bd097c35b0b6fc920fb0722', + '977837f0e37f14998082b0787b06bd', + '7f07e7f0e47f531b0723b0b6fb0721', + '7f0e27f1487f531b0b0bb0b6fb0722', + '7f0e397bd07f595b0b0bc920fb0722', + '977837f0e37f14998082b0787b06bd', + '7f07e7f0e47f531b0723b0b6fb0721', + '7f0e27f1487f531b0b0bb0b6fb0722', + '7f0e397bd07f595b0b0bc920fb0722', + '977837f0e37f14998082b0787b06bd', + '7f07e7f0e47f149b0723b0787b0721', + '7f0e27f0e47f531b0b0bb0b6fb0722', + '7f0e397bd07f595b0b0bc920fb0722', + '977837f0e37f14998082b0723b06bd', + '7f07e7f0e37f149b0723b0787b0721', + '7f0e27f0e47f531b0723b0b6fb0722', + '7f0e397bd07f595b0b0bc920fb0722', + '977837f0e37f14898082b0723b02d5', + '7ec967f0e37f14998082b0787b0721', + '7f07e7f0e47f531b0723b0b6fb0722', + '7f0e37f1487f595b0b0bb0b6fb0722', + '7f0e37f0e37f14898082b0723b02d5', + '7ec967f0e37f14998082b0787b0721', + '7f07e7f0e47f531b0723b0b6fb0722', + '7f0e37f1487f531b0b0bb0b6fb0722', + '7f0e37f0e37f14898082b0723b02d5', + '7ec967f0e37f14998082b0787b06bd', + '7f07e7f0e47f531b0723b0b6fb0721', + '7f0e37f1487f531b0b0bb0b6fb0722', + '7f0e37f0e37f14898082b072297c35', + '7ec967f0e37f14998082b0787b06bd', + '7f07e7f0e47f531b0723b0b6fb0721', + '7f0e27f1487f531b0b0bb0b6fb0722', + '7f0e37f0e37f14898082b072297c35', + '7ec967f0e37f14998082b0787b06bd', + '7f07e7f0e47f531b0723b0b6fb0721', + '7f0e27f1487f531b0b0bb0b6fb0722', + '7f0e37f0e366aa89801eb072297c35', + '7ec967f0e37f14998082b0787b06bd', + '7f07e7f0e47f149b0723b0787b0721', + '7f0e27f1487f531b0b0bb0b6fb0722', + '7f0e37f0e366aa89801eb072297c35', + '7ec967f0e37f14998082b0723b06bd', + '7f07e7f0e47f149b0723b0787b0721', + '7f0e27f0e47f531b0723b0b6fb0722', + '7f0e37f0e366aa89801eb072297c35', + '7ec967f0e37f14998082b0723b06bd', + '7f07e7f0e37f14998083b0787b0721', + '7f0e27f0e47f531b0723b0b6fb0722', + '7f0e37f0e366aa89801eb072297c35', + '7ec967f0e37f14898082b0723b02d5', + '7f07e7f0e37f14998082b0787b0721', + '7f07e7f0e47f531b0723b0b6fb0722', + '7f0e36665b66aa89801e9808297c35', + '665f67f0e37f14898082b0723b02d5', + '7ec967f0e37f14998082b0787b0721', + '7f07e7f0e47f531b0723b0b6fb0722', + '7f0e36665b66a449801e9808297c35', + '665f67f0e37f14898082b0723b02d5', + '7ec967f0e37f14998082b0787b06bd', + '7f07e7f0e47f531b0723b0b6fb0721', + '7f0e36665b66a449801e9808297c35', + '665f67f0e37f14898082b072297c35', + '7ec967f0e37f14998082b0787b06bd', + '7f07e7f0e47f531b0723b0b6fb0721', + '7f0e26665b66a449801e9808297c35', + '665f67f0e37f1489801eb072297c35', + '7ec967f0e37f14998082b0787b06bd', + '7f07e7f0e47f531b0723b0b6fb0721', + '7f0e27f1487f531b0b0bb0b6fb0722', + ], + + /** + * 数字转中文速查表 + * @Array Of Property + * @trans ['日','一','二','三','四','五','六','七','八','九','十'] + * @return Cn string + */ + nStr1: [ + '\u65E5', + '\u4E00', + '\u4E8C', + '\u4E09', + '\u56DB', + '\u4E94', + '\u516D', + '\u4E03', + '\u516B', + '\u4E5D', + '\u5341', + ], + + /** + * 日期转农历称呼速查表 + * @Array Of Property + * @trans ['初','十','廿','卅'] + * @return Cn string + */ + nStr2: ['\u521D', '\u5341', '\u5EFF', '\u5345'], + + /** + * 月份转农历称呼速查表 + * @Array Of Property + * @trans ['正','一','二','三','四','五','六','七','八','九','十','冬','腊'] + * @return Cn string + */ + nStr3: [ + '\u6B63', + '\u4E8C', + '\u4E09', + '\u56DB', + '\u4E94', + '\u516D', + '\u4E03', + '\u516B', + '\u4E5D', + '\u5341', + '\u51AC', + '\u814A', + ], + + /** + * 返回农历y年一整年的总天数 + * @param y lunar Year + * @return Number + * @eg:var count = calendar.lYearDays(1987) ;//count=387 + */ + lYearDays(y: number) { + let i, + sum = 348 + for (i = 0x8000; i > 0x8; i >>= 1) { + sum += this.lunarInfo[y - 1900] & i ? 1 : 0 + } + return sum + this.leapDays(y) + }, + + /** + * 返回农历y年闰月是哪个月;若y年没有闰月 则返回0 + * @param y lunar Year + * @return Number (0-12) + * @eg:var leapMonth = calendar.leapMonth(1987) ;//leapMonth=6 + */ + leapMonth(y: number) { + //闰字编码 \u95f0 + return this.lunarInfo[y - 1900] & 0xf + }, + + /** + * 返回农历y年闰月的天数 若该年没有闰月则返回0 + * @param y lunar Year + * @return Number (0、29、30) + * @eg:var leapMonthDay = calendar.leapDays(1987) ;//leapMonthDay=29 + */ + leapDays(y: number) { + if (this.leapMonth(y)) { + return this.lunarInfo[y - 1900] & 0x10000 ? 30 : 29 + } + return 0 + }, + + /** + * 返回农历y年m月(非闰月)的总天数,计算m为闰月时的天数请使用leapDays方法 + * @param y lunar Year + * @param m lunar Month + * @return Number (-1、29、30) + * @eg:var MonthDay = calendar.monthDays(1987,9) ;//MonthDay=29 + */ + monthDays(y: number, m: number) { + if (m > 12 || m < 1) { + return -1 + } //月份参数从1至12,参数错误返回-1 + return this.lunarInfo[y - 1900] & (0x10000 >> m) ? 30 : 29 + }, + + /** + * 返回公历(!)y年m月的天数 + * @param y solar Year + * @param m solar Month + * @return Number (-1、28、29、30、31) + * @eg:var solarMonthDay = calendar.leapDays(1987) ;//solarMonthDay=30 + */ + solarDays(y: number, m: number) { + if (m > 12 || m < 1) { + return -1 + } //若参数错误 返回-1 + const ms = m - 1 + if (ms === 1) { + //2月份的闰平规律测算后确认返回28或29 + return (y % 4 === 0 && y % 100 !== 0) || y % 400 === 0 ? 29 : 28 + } else { + return this.solarMonth[ms] + } + }, + + /** + * 农历年份转换为干支纪年 + * @param lYear 农历年的年份数 + * @return Cn string + */ + toGanZhiYear(lYear: number) { + let ganKey = (lYear - 3) % 10 + let zhiKey = (lYear - 3) % 12 + if (ganKey === 0) ganKey = 10 //如果余数为0则为最后一个天干 + if (zhiKey === 0) zhiKey = 12 //如果余数为0则为最后一个地支 + return this.Gan[ganKey - 1] + this.Zhi[zhiKey - 1] + }, + + /** + * 公历月、日判断所属星座 + * @param cMonth [description] + * @param cDay [description] + * @return Cn string + */ + toAstro(cMonth: number, cDay: number) { + const s = + '\u9B54\u7FAF\u6C34\u74F6\u53CC\u9C7C\u767D\u7F8A\u91D1\u725B\u53CC\u5B50\u5DE8\u87F9\u72EE\u5B50\u5904\u5973\u5929\u79E4\u5929\u874E\u5C04\u624B\u9B54\u7FAF' + const arr = [20, 19, 21, 21, 21, 22, 23, 23, 23, 23, 22, 22] + return `${s.substring(cMonth * 2 - (cDay < arr[cMonth - 1] ? 2 : 0), 2)}\u5EA7` //座 + }, + + /** + * 传入offset偏移量返回干支 + * @param offset 相对甲子的偏移量 + * @return Cn string + */ + toGanZhi(offset: number) { + return this.Gan[offset % 10] + this.Zhi[offset % 12] + }, + + /** + * 传入公历(!)y年获得该年第n个节气的公历日期 + * @param y y公历年(1900-2100) + * @param n n二十四节气中的第几个节气(1~24);从n=1(小寒)算起 + * @return day Number + * @eg:var _24 = calendar.getTerm(1987,3) ;//_24=4;意即1987年2月4日立春 + */ + getTerm(y: number, n: number) { + if (y < 1900 || y > 2100) { + return -1 + } + if (n < 1 || n > 24) { + return -1 + } + const _table = this.sTermInfo[y - 1900] + const _info = [ + Number.parseInt(`0x${_table.slice(0, 5)}`).toString(), + Number.parseInt(`0x${_table.slice(5, 5)}`).toString(), + Number.parseInt(`0x${_table.slice(5, 10)}`).toString(), + Number.parseInt(`0x${_table.slice(5, 15)}`).toString(), + Number.parseInt(`0x${_table.slice(5, 20)}`).toString(), + Number.parseInt(`0x${_table.slice(5, 25)}`).toString(), + ] + const _calcDay = [ + _info[0].slice(0, 1), + _info[0].slice(1, 2), + _info[0].slice(1, 3), + _info[0].slice(2, 4), + + _info[1].slice(0, 1), + _info[1].slice(1, 2), + _info[1].slice(1, 3), + _info[1].slice(2, 4), + + _info[2].slice(0, 1), + _info[2].slice(1, 2), + _info[2].slice(1, 3), + _info[2].slice(2, 4), + + _info[3].slice(0, 1), + _info[3].slice(1, 2), + _info[3].slice(1, 3), + _info[3].slice(2, 4), + + _info[4].slice(0, 1), + _info[4].slice(1, 2), + _info[4].slice(1, 3), + _info[4].slice(2, 4), + + _info[5].slice(0, 1), + _info[5].slice(1, 2), + _info[5].slice(1, 3), + _info[5].slice(2, 4), + ] + return Number.parseInt(_calcDay[n - 1]) + }, + + /** + * 传入农历数字月份返回汉语通俗表示法 + * @param m lunar month + * @return Cn string + * @eg:var cnMonth = calendar.toChinaMonth(12) ;//cnMonth='腊月' + */ + toChinaMonth(m: number) { + // 月 => \u6708 + if (m > 12 || m < 1) { + return -1 + } //若参数错误 返回-1 + let s = this.nStr3[m - 1] + s += '\u6708' //加上月字 + return s + }, + + /** + * 传入农历日期数字返回汉字表示法 + * @param d lunar day + * @return Cn string + * @eg:var cnDay = calendar.toChinaDay(21) ;//cnMonth='廿一' + */ + toChinaDay(d: number) { + //日 => \u65e5 + let s + switch (d) { + case 10: + s = '\u521D\u5341' + break + case 20: + s = '\u4E8C\u5341' + break + case 30: + s = '\u4E09\u5341' + break + default: + s = this.nStr2[Math.floor(d / 10)] + s += this.nStr1[d % 10] + } + return s + }, + + /** + * 年份转生肖[!仅能大致转换] => 精确划分生肖分界线是“立春” + * @param y year + * @return Cn string + * @eg:var animal = calendar.getAnimal(1987) ;//animal='兔' + */ + getAnimal(y: number) { + return this.Animals[(y - 4) % 12] + }, + + /** + * 传入阳历年月日获得详细的公历、农历object信息 <=>JSON + * !important! 公历参数区间1900.1.31~2100.12.31 + * @param yPara solar year + * @param mPara solar month + * @param dPara solar day + * @return JSON object + * @eg:console.log(calendar.solar2lunar(1987,11,01)); + */ + solar2lunar(yPara: string, mPara: string, dPara: string) { + let y: any = Number.parseInt(yPara) + let m: any = Number.parseInt(mPara) + let d: any = Number.parseInt(dPara) + //年份限定、上限 + if (y < 1900 || y > 2100) { + return -1 // undefined转换为数字变为NaN + } + //公历传参最下限 + if (y === 1900 && m === 1 && d < 31) { + return -1 + } + + //未传参 获得当天 + let objDate + if (!y) { + objDate = new Date() + } else { + objDate = new Date(y, Number.parseInt(m) - 1, d) + } + let i, + leap = 0, + temp = 0 + //修正ymd参数 + y = objDate.getFullYear() + m = objDate.getMonth() + 1 + d = objDate.getDate() + let offset = + (Date.UTC( + objDate.getFullYear(), + objDate.getMonth(), + objDate.getDate() + ) - + Date.UTC(1900, 0, 31)) / + 86400000 + for (i = 1900; i < 2101 && offset > 0; i++) { + temp = this.lYearDays(i) + offset -= temp + } + if (offset < 0) { + offset += temp + i-- + } + + //是否今天 + const isTodayObj: any = new Date() + let isToday: any = false + if ( + isTodayObj.getFullYear() === y && + isTodayObj.getMonth() + 1 === m && + isTodayObj.getDate() === d + ) { + isToday = true + } + //星期几 + let nWeek: any = objDate.getDay() + const cWeek: any = this.nStr1[nWeek] + //数字表示周几顺应天朝周一开始的惯例 + if (nWeek === 0) { + nWeek = 7 + } + //农历年 + const year = i + leap = this.leapMonth(i) //闰哪个月 + let isLeap = false + + //效验闰月 + for (i = 1; i < 13 && offset > 0; i++) { + //闰月 + if (leap > 0 && i === leap + 1 && isLeap === false) { + --i + isLeap = true + temp = this.leapDays(year) //计算农历闰月天数 + } else { + temp = this.monthDays(year, i) //计算农历普通月天数 + } + //解除闰月 + if (isLeap === true && i === leap + 1) { + isLeap = false + } + offset -= temp + } + // 闰月导致数组下标重叠取反 + if (offset === 0 && leap > 0 && i === leap + 1) { + if (isLeap) { + isLeap = false + } else { + isLeap = true + --i + } + } + if (offset < 0) { + offset += temp + --i + } + //农历月 + const month = i + //农历日 + const day = offset + 1 + //天干地支处理 + const sm = m - 1 + const gzY = this.toGanZhiYear(year) + + // 当月的两个节气 + // bugfix-2017-7-24 11:03:38 use lunar Year Param `y` Not `year` + const firstNode = this.getTerm(y, m * 2 - 1) //返回当月「节」为几日开始 + const secondNode = this.getTerm(y, m * 2) //返回当月「节」为几日开始 + + // 依据12节气修正干支月 + let gzM = this.toGanZhi((y - 1900) * 12 + m + 11) + if (d >= firstNode) { + gzM = this.toGanZhi((y - 1900) * 12 + m + 12) + } + + //传入的日期的节气与否 + let isTerm = false + let Term = null + if (firstNode === d) { + isTerm = true + Term = this.solarTerm[m * 2 - 2] + } + if (secondNode === d) { + isTerm = true + Term = this.solarTerm[m * 2 - 1] + } + //日柱 当月一日与 1900/1/1 相差天数 + const dayCyclical = + Date.UTC(y, sm, 1, 0, 0, 0, 0) / 86400000 + 25567 + 10 + const gzD = this.toGanZhi(dayCyclical + d - 1) + //该日期所属的星座 + const astro = this.toAstro(m, d) + + const solarDate = `${y}-${m}-${d}` + const lunarDate = `${year}-${month}-${day}` + + const festival = this.festival + const lFestival = this.lFestival + + const festivalDate = `${m}-${d}` + const lunarFestivalDate = `${month}-${day}` + + return { + date: solarDate, + lunarDate, + festival: festival[festivalDate] + ? festival[festivalDate].title + : null, + lunarFestival: lFestival[lunarFestivalDate] + ? lFestival[lunarFestivalDate].title + : null, + lYear: year, + lMonth: month, + lDay: day, + Animal: this.getAnimal(year), + IMonthCn: (isLeap ? '\u95F0' : '') + this.toChinaMonth(month), + IDayCn: this.toChinaDay(day), + cYear: y, + cMonth: m, + cDay: d, + gzYear: gzY, + gzMonth: gzM, + gzDay: gzD, + isToday, + isLeap, + nWeek, + ncWeek: `\u661F\u671F${cWeek}`, + isTerm, + Term, + astro, + } + }, + + /** + * 传入农历年月日以及传入的月份是否闰月获得详细的公历、农历object信息 <=>JSON + * !important! 参数区间1900.1.31~2100.12.1 + * @param y lunar year + * @param m lunar month + * @param d lunar day + * @param isLeapMonth lunar month is leap or not.[如果是农历闰月第四个参数赋值true即可] + * @return JSON object + * @eg:console.log(calendar.lunar2solar(1987,9,10)); + */ + lunar2solar(y: any, m: any, d: any, isLeapMonth: boolean) { + y = Number.parseInt(y) + m = Number.parseInt(m) + d = Number.parseInt(d) + isLeapMonth = !!isLeapMonth + const leapMonth = this.leapMonth(y) + if (isLeapMonth && leapMonth !== m) { + return -1 + } //传参要求计算该闰月公历 但该年得出的闰月与传参的月份并不同 + if ( + (y === 2100 && m === 12 && d > 1) || + (y === 1900 && m === 1 && d < 31) + ) { + return -1 + } //超出了最大极限值 + const day = this.monthDays(y, m) + let _day = day + //bugFix 2016-9-25 + //if month is leap, _day use leapDays method + if (isLeapMonth) { + _day = this.leapDays(y, m) + } + if (y < 1900 || y > 2100 || d > _day) { + return -1 + } //参数合法性效验 + + //计算农历的时间差 + let offset = 0 + let i + for (i = 1900; i < y; i++) { + offset += this.lYearDays(i) + } + let leap = 0, + isAdd = false + for (i = 1; i < m; i++) { + leap = this.leapMonth(y) + if ( + !isAdd && //处理闰月 + leap <= i && + leap > 0 + ) { + offset += this.leapDays(y) + isAdd = true + } + offset += this.monthDays(y, i) + } + //转换闰月农历 需补充该年闰月的前一个月的时差 + if (isLeapMonth) { + offset += day + } + //1900年农历正月一日的公历时间为1900年1月30日0时0分0秒(该时间也是本农历的最开始起始点) + const strap = Date.UTC(1900, 1, 30, 0, 0, 0) + const calObj = new Date((offset + d - 31) * 86400000 + strap) + const cY = calObj.getUTCFullYear() + const cM = calObj.getUTCMonth() + 1 + const cD = calObj.getUTCDate() + + return this.solar2lunar(cY, cM, cD) + }, +} +export function solar2lunar(val: string) { + return VabCalendar.solar2lunar( + val.split('-')[0], + val.split('-')[1], + val.split('-')[2] + ) +} + +export default VabCalendar diff --git a/src/plugins/VabChart/index.vue b/src/plugins/VabChart/index.vue new file mode 100644 index 0000000..54fb2d8 --- /dev/null +++ b/src/plugins/VabChart/index.vue @@ -0,0 +1,287 @@ + + + + + diff --git a/src/plugins/VabChart/theme/vab-echarts-theme.json b/src/plugins/VabChart/theme/vab-echarts-theme.json new file mode 100644 index 0000000..199c109 --- /dev/null +++ b/src/plugins/VabChart/theme/vab-echarts-theme.json @@ -0,0 +1,317 @@ +{ + "color": ["#1890FF", "#36CBCB", "#4ECB73", "#FBD437", "#F2637B", "#975FE5"], + "backgroundColor": "rgba(252,252,252,0)", + "textStyle": {}, + "title": { + "textStyle": { + "color": "#666666" + }, + "subtextStyle": { + "color": "#999999" + } + }, + "line": { + "itemStyle": { + "borderWidth": "2" + }, + "lineStyle": { + "normal": { + "width": "3" + } + }, + "symbolSize": "8", + "symbol": "emptyCircle", + "smooth": false + }, + "radar": { + "itemStyle": { + "borderWidth": "2" + }, + "lineStyle": { + "normal": { + "width": "3" + } + }, + "symbolSize": "8", + "symbol": "emptyCircle", + "smooth": false + }, + "bar": { + "itemStyle": { + "barBorderWidth": 0, + "barBorderColor": "#ccc" + } + }, + "pie": { + "itemStyle": { + "borderWidth": 0, + "borderColor": "#ccc" + } + }, + "scatter": { + "itemStyle": { + "borderWidth": 0, + "borderColor": "#ccc" + } + }, + "boxplot": { + "itemStyle": { + "borderWidth": 0, + "borderColor": "#ccc" + } + }, + "parallel": { + "itemStyle": { + "borderWidth": 0, + "borderColor": "#ccc" + } + }, + "sankey": { + "itemStyle": { + "borderWidth": 0, + "borderColor": "#ccc" + } + }, + "funnel": { + "itemStyle": { + "borderWidth": 0, + "borderColor": "#ccc" + } + }, + "gauge": { + "itemStyle": { + "borderWidth": 0, + "borderColor": "#ccc" + } + }, + "candlestick": { + "itemStyle": { + "color": "#e6a0d2", + "color0": "transparent", + "borderColor": "#e6a0d2", + "borderColor0": "#1890FF", + "borderWidth": "2" + } + }, + "graph": { + "itemStyle": { + "borderWidth": 0, + "borderColor": "#ccc" + }, + "lineStyle": { + "normal": { + "width": "1", + "color": "#cccccc" + } + }, + "symbolSize": "8", + "symbol": "emptyCircle", + "smooth": false, + "color": ["#1890FF", "#36CBCB", "#4ECB73", "#FBD437", "#F2637B", "#975FE5"], + "label": { + "color": "#ffffff" + } + }, + "map": { + "itemStyle": { + "areaColor": "#eeeeee", + "borderColor": "#aaaaaa", + "borderWidth": 0.5 + }, + "label": { + "color": "#ffffff" + } + }, + "geo": { + "itemStyle": { + "areaColor": "#eeeeee", + "borderColor": "#aaaaaa", + "borderWidth": 0.5 + }, + "label": { + "color": "#ffffff" + } + }, + "categoryAxis": { + "axisLine": { + "show": true, + "lineStyle": { + "color": "#cccccc" + } + }, + "axisTick": { + "show": false, + "lineStyle": { + "color": "#333" + } + }, + "axisLabel": { + "show": true, + "color": "#999999" + }, + "splitLine": { + "show": true, + "lineStyle": { + "color": ["#eeeeee"] + } + }, + "splitArea": { + "show": false, + "areaStyle": { + "color": ["rgba(250,250,250,0.05)", "rgba(200,200,200,0.02)"] + } + } + }, + "valueAxis": { + "axisLine": { + "show": true, + "lineStyle": { + "color": "#cccccc" + } + }, + "axisTick": { + "show": true, + "lineStyle": { + "color": "#cccccc" + } + }, + "axisLabel": { + "show": true, + "color": "#999999" + }, + "splitLine": { + "show": true, + "lineStyle": { + "color": ["#eeeeee"] + } + }, + "splitArea": { + "show": false, + "areaStyle": { + "color": ["rgba(250,250,250,0.05)", "rgba(200,200,200,0.02)"] + } + } + }, + "logAxis": { + "axisLine": { + "show": true, + "lineStyle": { + "color": "#cccccc" + } + }, + "axisTick": { + "show": false, + "lineStyle": { + "color": "#333" + } + }, + "axisLabel": { + "show": true, + "color": "#999999" + }, + "splitLine": { + "show": true, + "lineStyle": { + "color": ["#eeeeee"] + } + }, + "splitArea": { + "show": false, + "areaStyle": { + "color": ["rgba(250,250,250,0.05)", "rgba(200,200,200,0.02)"] + } + } + }, + "timeAxis": { + "axisLine": { + "show": true, + "lineStyle": { + "color": "#cccccc" + } + }, + "axisTick": { + "show": false, + "lineStyle": { + "color": "#333" + } + }, + "axisLabel": { + "show": true, + "color": "#999999" + }, + "splitLine": { + "show": true, + "lineStyle": { + "color": ["#eeeeee"] + } + }, + "splitArea": { + "show": false, + "areaStyle": { + "color": ["rgba(250,250,250,0.05)", "rgba(200,200,200,0.02)"] + } + } + }, + "toolbox": { + "iconStyle": { + "borderColor": "#999999" + } + }, + "legend": { + "textStyle": { + "color": "#999999" + } + }, + "tooltip": { + "axisPointer": { + "lineStyle": { + "color": "#ffffff", + "width": 1 + }, + "crossStyle": { + "color": "#ffffff", + "width": 1 + } + } + }, + "timeline": { + "lineStyle": { + "color": "#4ECB73", + "width": 1 + }, + "itemStyle": { + "color": "#4ECB73", + "borderWidth": 1 + }, + "controlStyle": { + "color": "#4ECB73", + "borderColor": "#4ECB73", + "borderWidth": 0.5 + }, + "checkpointStyle": { + "color": "#1890FF", + "borderColor": "rgba(63,177,227,0.15)" + }, + "label": { + "color": "#4ECB73" + } + }, + "visualMap": { + "color": ["#1890FF", "#afe8ff"] + }, + "dataZoom": { + "backgroundColor": "rgba(255,255,255,0)", + "dataBackgroundColor": "rgba(222,222,222,1)", + "fillerColor": "rgba(114,230,212,0.25)", + "handleColor": "#cccccc", + "handleSize": "100%", + "textStyle": { + "color": "#999999" + } + }, + "markPoint": { + "label": { + "color": "#ffffff" + } + } +} diff --git a/src/plugins/VabCount/index.vue b/src/plugins/VabCount/index.vue new file mode 100644 index 0000000..4c717de --- /dev/null +++ b/src/plugins/VabCount/index.vue @@ -0,0 +1,222 @@ + + + + diff --git a/src/plugins/VabCount/requestAnimationFrame.js b/src/plugins/VabCount/requestAnimationFrame.js new file mode 100644 index 0000000..93c3b87 --- /dev/null +++ b/src/plugins/VabCount/requestAnimationFrame.js @@ -0,0 +1,45 @@ +let lastTime = 0 +const prefixes = 'webkit moz ms o'.split(' ') + +let requestAnimationFrame +let cancelAnimationFrame + +const isServer = typeof window === 'undefined' +if (isServer) { + requestAnimationFrame = function () {} + cancelAnimationFrame = function () {} +} else { + requestAnimationFrame = window.requestAnimationFrame + cancelAnimationFrame = window.cancelAnimationFrame + let prefix + for (const prefix_ of prefixes) { + if (requestAnimationFrame && cancelAnimationFrame) { + break + } + prefix = prefix_ + requestAnimationFrame = + requestAnimationFrame || window[`${prefix}RequestAnimationFrame`] + cancelAnimationFrame = + cancelAnimationFrame || + window[`${prefix}CancelAnimationFrame`] || + window[`${prefix}CancelRequestAnimationFrame`] + } + + if (!requestAnimationFrame || !cancelAnimationFrame) { + requestAnimationFrame = function (callback) { + const currTime = Date.now() + const timeToCall = Math.max(0, 16 - (currTime - lastTime)) + const id = window.setTimeout(() => { + callback(currTime + timeToCall) + }, timeToCall) + lastTime = currTime + timeToCall + return id + } + + cancelAnimationFrame = function (id) { + window.clearTimeout(id) + } + } +} + +export { requestAnimationFrame, cancelAnimationFrame } diff --git a/src/plugins/VabDialog/index.vue b/src/plugins/VabDialog/index.vue new file mode 100644 index 0000000..f0d6e77 --- /dev/null +++ b/src/plugins/VabDialog/index.vue @@ -0,0 +1,145 @@ + + + + + diff --git a/src/plugins/VabFormTable/index.vue b/src/plugins/VabFormTable/index.vue new file mode 100644 index 0000000..c1f40ec --- /dev/null +++ b/src/plugins/VabFormTable/index.vue @@ -0,0 +1,128 @@ + + + diff --git a/src/plugins/VabIconSelector/index.vue b/src/plugins/VabIconSelector/index.vue new file mode 100644 index 0000000..ee2402f --- /dev/null +++ b/src/plugins/VabIconSelector/index.vue @@ -0,0 +1,116 @@ + + + + + diff --git a/src/plugins/VabPrint.ts b/src/plugins/VabPrint.ts new file mode 100644 index 0000000..d37b8ef --- /dev/null +++ b/src/plugins/VabPrint.ts @@ -0,0 +1,148 @@ +const Print: any = function (this: any, dom: any, options: any) { + if (!(this instanceof Print)) return new Print(dom, options) + + this.options = this.extend( + { + noPrint: '.no-print', + }, + options + ) + + if (typeof dom === 'string') { + try { + this.dom = document.querySelector(dom) + } catch { + const createDom = document.createElement('div') + createDom.innerHTML = dom + this.dom = createDom + } + } else { + this.isDOM(dom) + this.dom = this.isDOM(dom) ? dom : dom.$el + } + + this.init() +} +Print.prototype = { + init() { + const content = this.getStyle() + this.getHtml() + this.writeIframe(content) + }, + extend(obj: { [x: string]: any }, obj2: { [x: string]: any }) { + for (const k in obj2) { + obj[k] = obj2[k] + } + return obj + }, + + getStyle() { + let str = '' + const styles = document.querySelectorAll('style,link') + for (const style of styles) { + str += style.outerHTML + } + str += `` + str += '' + return str + }, + + getHtml() { + const inputs = document.querySelectorAll('input') + const textareas = document.querySelectorAll('textarea') + const selects = document.querySelectorAll('select') + + for (const input of inputs) { + if (input.type == 'checkbox' || input.type == 'radio') { + if (input.checked == true) { + input.setAttribute('checked', 'checked') + } else { + input.removeAttribute('checked') + } + } else if (input.type == 'text') { + input.setAttribute('value', input.value) + } else { + input.setAttribute('value', input.value) + } + } + + for (const textarea of textareas) { + if (textarea.type == 'textarea') textarea.innerHTML = textarea.value + } + + for (const select of selects) { + if (select.type == 'select-one') { + const child: any = select.children + for (const i in child) { + if (child[i].tagName == 'OPTION') { + if (child[i].selected == true) + child[i].setAttribute('selected', 'selected') + else child[i].removeAttribute('selected') + } + } + } + } + + return this.dom.outerHTML + }, + + writeIframe(content: string) { + const iframe: any = document.createElement('iframe') + const f: any = document.body.appendChild(iframe) + iframe.id = 'myIframe' + iframe.setAttribute( + 'style', + 'position:absolute;width:0;height:0;top:-10px;left:-10px;' + ) + const w: any = f.contentWindow || f.contentDocument + const doc: any = f.contentDocument || f.contentWindow.document + doc.open() + doc.write(content) + doc.close() + const _this = this + iframe.addEventListener('load', () => { + _this.toPrint(w) + setTimeout(() => { + document.body.removeChild(iframe) + }, 100) + }) + }, + + toPrint(frameWindow: { + focus: () => void + document: { + execCommand: (arg0: string, arg1: boolean, arg2: null) => any + } + print: () => void + close: () => void + }) { + try { + setTimeout(() => { + frameWindow.focus() + try { + if (!frameWindow.document.execCommand('print', false, null)) + frameWindow.print() + } catch { + frameWindow.print() + } + frameWindow.close() + }, 10) + } catch (error) { + console.log('err', error) + } + }, + isDOM: + typeof HTMLElement === 'object' + ? function (obj: any) { + return obj instanceof HTMLElement + } + : function (obj: { nodeType: number; nodeName: any }) { + return ( + obj && + typeof obj === 'object' && + obj.nodeType === 1 && + typeof obj.nodeName === 'string' + ) + }, +} + +export default Print diff --git a/src/plugins/VabQrCode.ts b/src/plugins/VabQrCode.ts new file mode 100644 index 0000000..644ca44 --- /dev/null +++ b/src/plugins/VabQrCode.ts @@ -0,0 +1 @@ +export { default } from 'vue-qr/src/packages/vue-qr.vue' diff --git a/src/plugins/VabUpdate/index.vue b/src/plugins/VabUpdate/index.vue new file mode 100644 index 0000000..1d02e97 --- /dev/null +++ b/src/plugins/VabUpdate/index.vue @@ -0,0 +1,157 @@ + + + + + + + diff --git a/src/plugins/VabUpload/index.vue b/src/plugins/VabUpload/index.vue new file mode 100644 index 0000000..e074b7f --- /dev/null +++ b/src/plugins/VabUpload/index.vue @@ -0,0 +1,270 @@ + + + + + diff --git a/src/registerServiceWorker.ts b/src/registerServiceWorker.ts new file mode 100644 index 0000000..7f29975 --- /dev/null +++ b/src/registerServiceWorker.ts @@ -0,0 +1,56 @@ +/* eslint-disable no-console */ +import { register } from 'register-service-worker' +import { gp } from '@gp' + +if (process.env.NODE_ENV === 'production') { + register(`${process.env.BASE_URL}service-worker.js`, { + ready() { + console.log( + 'App is being served from cache by a service worker.\n' + + 'For more details, visit //goo.gl/AFskqB' + ) + }, + registered() { + console.log('Service worker has been registered.') + }, + cached() { + console.log('Content has been cached for offline use.') + }, + updatefound() { + console.log('New content is downloading.') + // gp.$baseNotify( + // '检测到新版本,正在下载中,请稍后...', + // '温馨提示', + // 'info', + // 'bottom-right', + // 8000 + // ) + }, + updated() { + console.log('New content is available; please refresh.') + gp.$pub('vab-update') + + //如果是演示环境,更新后移除主题,用不到可删除 + if (location.hostname === 'veujs-core.cn') + localStorage.removeItem('theme') + // gp.$baseNotify( + // '更新版本完成,10S后刷新项目', + // '温馨提示', + // 'success', + // 'bottom-right', + // 8000 + // ) + // setTimeout(() => { + // window.location.reload() + // }, 10000) + }, + offline() { + console.log( + 'No internet connection found. App is running in offline mode.' + ) + }, + error(error) { + console.error('Error during service worker registration:', error) + }, + }) +} diff --git a/src/router/index.ts b/src/router/index.ts new file mode 100644 index 0000000..a7712e9 --- /dev/null +++ b/src/router/index.ts @@ -0,0 +1,1112 @@ +/** + * @description router全局配置,如有必要可分文件抽离,其中asyncRoutes只有在intelligence模式下才会用到,pro版只支持remixIcon图标,具体配置请查看vip群文档 + */ +import type { VabRouteRecord } from '/#/router' +import { + createRouter, + createWebHashHistory, + createWebHistory, +} from 'vue-router' +import Layout from '@vab/layouts/index.vue' +import { setupPermissions } from './permissions' + +import type { RouteRecordName, RouteRecordRaw } from 'vue-router' + +import { authentication, isHashRouterMode, publicPath } from '@/config' + +export const constantRoutes: VabRouteRecord[] = [ + { + path: '/login', + name: 'Login', + component: () => import('@/views/login/index.vue'), + meta: { + hidden: true, + }, + }, + { + path: '/register', + name: 'Register', + component: () => import('@/views/register/index.vue'), + meta: { + hidden: true, + }, + }, + { + path: '/callback', + name: 'Callback', + component: () => import('@/views/callback/index.vue'), + meta: { + hidden: true, + }, + }, + { + path: '/direct', + name: 'Direct', + component: () => import('@/views/direct/index.vue'), + meta: { + hidden: true, + }, + }, + { + path: '/404', + name: '404', + component: () => import('@/views/404.vue'), + meta: { + hidden: true, + }, + }, +] + +export const asyncRoutes: VabRouteRecord[] = [ + { + path: '/', + name: 'Root', + component: Layout, + meta: { + title: '首页', + icon: 'home-2-line', + breadcrumbHidden: true, + }, + children: [ + { + path: 'index', + name: 'Index', + component: () => import('@/views/index/index.vue'), + meta: { + title: '首页', + icon: 'home-2-line', + noClosable: true, + }, + }, + { + path: 'dashboard', + name: 'Dashboard', + component: () => import('@/views/index/dashboard.vue'), + meta: { + title: '看板', + icon: 'dashboard-line', + }, + }, + { + path: 'workbench', + name: 'Workbench', + component: () => import('@/views/index/workbench.vue'), + meta: { + title: '工作台', + icon: 'settings-6-line', + dot: true, + }, + }, + { + path: 'store', + name: 'Store', + component: () => import('@/views/index/store.vue'), + meta: { + title: '仓库', + icon: 'app-store-line', + dot: true, + }, + }, + + { + path: 'friendly-tip', + name: 'FriendlyTip', + component: () => import('@/views/index/FriendlyTip.vue'), + meta: { + title: '温馨提示', + icon: 'information-line', + hidden: true, + }, + }, + { + path: 'statistics', + name: 'Statistics', + component: () => import('@/views/index/statistics.vue'), + meta: { + title: '统计分析', + icon: 'bar-chart-box-line', + }, + }, + { + path: 'settings', + name: 'Settings', + component: () => import('@/views/index/settings.vue'), + meta: { + title: '系统设置', + icon: 'settings-line', + guard: ['Admin'], + }, + }, + { + path: 'pricing', + name: 'Pricing', + component: () => import('@/views/index/Pricing.vue'), + meta: { + title: '授权与定价', + guard: ['Admin'], + icon: 'price-tag-3-line', + badge: 'Hot', + }, + }, + ], + }, + { + path: '/vab', + name: 'Vab', + component: Layout, + meta: { + title: '组件', + icon: 'code-box-line', + }, + children: [ + { + path: 'icon', + name: 'Icon', + meta: { + title: '图标', + icon: 'remixicon-line', + }, + children: [ + { + path: 'defaultIcon', + name: 'DefaultIcon', + component: () => + import('@/views/vab/icon/defaultIcon.vue'), + meta: { + title: '默认图标', + }, + }, + { + path: 'iconSelector', + name: 'IconSelector', + component: () => + import('@/views/vab/icon/iconSelector.vue'), + meta: { + title: '图标选择器', + }, + }, + { + path: 'customSvg', + name: 'CustomSvg', + component: () => + import('@/views/vab/icon/customSvg.vue'), + meta: { + title: '自定义图标', + }, + }, + ], + }, + { + path: 'permission', + name: 'Permission', + component: () => import('@/views/vab/permission/index.vue'), + meta: { + title: '角色权限', + icon: 'user-3-line', + badge: 'Pro', + }, + }, + { + path: 'table', + name: 'Table', + meta: { + title: '表格', + // 非editor角色的用户可见 + guard: { + role: ['Editor'], + mode: 'except', + }, + icon: 'table-2', + }, + children: [ + { + path: 'comprehensiveTable', + name: 'ComprehensiveTable', + component: () => + import('@/views/vab/table/comprehensiveTable.vue'), + meta: { + title: '综合表格', + }, + }, + { + path: 'detail', + name: 'Detail', + component: () => import('@/views/vab/table/detail.vue'), + meta: { + hidden: true, + title: '详情页', + activeMenu: '/vab/table/comprehensiveTable', + dynamicNewTab: true, //详情页根据id传参不同可打开多个 + }, + }, + { + path: 'inlineEditTable', + name: 'InlineEditTable', + component: () => + import('@/views/vab/table/inlineEditTable.vue'), + meta: { + title: '行内编辑表格', + noKeepAlive: true, + }, + }, + { + path: 'customTable', + name: 'CustomTable', + component: () => + import('@/views/vab/table/customTable.vue'), + meta: { + title: '自定义表格', + }, + }, + { + path: 'dynamicTable', + name: 'DynamicTable', + component: () => + import('@/views/vab/table/dynamicTable.vue'), + meta: { + title: '动态表格', + badge: 'New', + }, + }, + ], + }, + { + path: 'list', + name: 'List', + component: () => import('@/views/vab/list/index.vue'), + meta: { + title: '列表', + guard: ['Admin'], + icon: 'list-check-2', + }, + }, + { + path: 'description', + name: 'Description', + component: () => import('@/views/vab/description/index.vue'), + meta: { + title: '描述', + guard: ['Admin'], + icon: 'slideshow-line', + }, + }, + { + path: 'calendar', + name: 'Calendar', + component: () => import('@/views/vab/calendar/index.vue'), + meta: { + title: '日历', + guard: ['Admin'], + icon: 'calendar-check-line', + dot: true, + }, + }, + { + path: 'editor', + name: 'Editor', + meta: { + title: '编辑器', + guard: ['Admin'], + icon: 'edit-2-line', + }, + children: [ + { + path: 'wangEditor', + name: 'WangEditor', + component: () => + import('@/views/vab/editor/wangEditor.vue'), + meta: { + title: '腾讯文档', + guard: ['Admin'], + dot: true, + }, + }, + ], + }, + { + path: 'form', + name: 'Form', + meta: { + title: '表单', + guard: ['Admin'], + icon: 'file-list-2-line', + }, + children: [ + { + path: 'comprehensiveForm', + name: 'ComprehensiveForm', + component: () => + import('@/views/vab/form/comprehensiveForm.vue'), + meta: { + title: '综合表单', + }, + }, + { + path: 'stepForm', + name: 'StepForm', + component: () => + import('@/views/vab/form/stepForm.vue'), + meta: { + title: '分步表单', + }, + }, + { + path: 'button', + name: 'Button', + component: () => import('@/views/vab/form/button.vue'), + meta: { + title: '按钮', + }, + }, + { + path: 'link', + name: 'Link', + component: () => import('@/views/vab/form/link.vue'), + meta: { + title: '文字链接', + }, + }, + { + path: 'radio', + name: 'Radio', + component: () => import('@/views/vab/form/radio.vue'), + meta: { + title: '单选框', + }, + }, + { + path: 'checkbox', + name: 'Checkbox', + component: () => + import('@/views/vab/form/checkbox.vue'), + meta: { + title: '多选框', + }, + }, + { + path: 'input', + name: 'Input', + component: () => import('@/views/vab/form/input.vue'), + meta: { + title: '输入框', + }, + }, + { + path: 'inputNumber', + name: 'InputNumber', + component: () => + import('@/views/vab/form/inputNumber.vue'), + meta: { + title: '计数器', + }, + }, + { + path: 'select', + name: 'Select', + component: () => import('@/views/vab/form/select.vue'), + meta: { + title: '选择器', + dot: true, + }, + }, + { + path: 'switch', + name: 'Switch', + component: () => import('@/views/vab/form/switch.vue'), + meta: { + title: '开关', + }, + }, + { + path: 'slider', + name: 'Slider', + component: () => import('@/views/vab/form/slider.vue'), + meta: { + title: '滑块', + }, + }, + { + path: 'timePicker', + name: 'TimePicker', + component: () => + import('@/views/vab/form/timePicker.vue'), + meta: { + title: '时间选择器', + }, + }, + { + path: 'datePicker', + name: 'DatePicker', + component: () => + import('@/views/vab/form/datePicker.vue'), + meta: { + title: '日期选择器', + }, + }, + { + path: 'dateTimePicker', + name: 'DateTimePicker', + component: () => + import('@/views/vab/form/dateTimePicker.vue'), + meta: { + title: '日期时间选择器', + }, + }, + { + path: 'rate', + name: 'Rate', + component: () => import('@/views/vab/form/rate.vue'), + meta: { + title: '评分', + }, + }, + ], + }, + ], + }, + { + path: '/other', + name: 'Other', + component: Layout, + meta: { + title: '其他', + icon: 'archive-line', + guard: ['Admin'], + }, + children: [ + { + path: 'workflow', + name: 'Workflow', + component: () => import('@/views/other/workflow/index.vue'), + meta: { + title: '工作流', + guard: ['Admin'], + icon: 'flow-chart', + }, + }, + { + path: 'echarts', + name: 'Echarts', + component: () => import('@/views/other/echarts/index.vue'), + meta: { + title: '图表', + guard: ['Admin'], + icon: 'bubble-chart-line', + }, + }, + { + path: 'print', + name: 'Print', + component: () => import('@/views/other/print/index.vue'), + meta: { + title: '打印', + guard: ['Admin'], + icon: 'printer-line', + }, + }, + { + path: 'notice', + name: 'Notice', + component: () => import('@/views/other/notice/index.vue'), + meta: { + title: '通知', + guard: ['Admin'], + icon: 'message-2-line', + }, + }, + { + path: 'timeline', + name: 'Timeline', + component: () => import('@/views/other/timeline/index.vue'), + meta: { + title: '时间线', + guard: ['Admin'], + icon: 'time-line', + }, + }, + { + path: 'tabs', + name: 'Tabs', + component: () => import('@/views/other/tabs/index.vue'), + meta: { + title: '多标签', + guard: ['Admin'], + icon: 'bank-card-line', + }, + }, + { + path: 'watermark', + name: 'Watermark', + component: () => import('@/views/other/watermark/index.vue'), + meta: { + title: '水印', + guard: ['Admin'], + icon: 'water-flash-line', + dot: true, + }, + }, + { + path: 'share', + name: 'Share', + component: () => import('@/views/other/share/index.vue'), + meta: { + title: '分享', + guard: ['Admin'], + icon: 'share-line', + dot: true, + }, + }, + { + path: 'dynamicAnchor', + name: 'DynamicAnchor', + component: () => + import('@/views/other/dynamicAnchor/index.vue'), + meta: { + title: '动态锚点', + guard: ['Admin'], + icon: 'anchor-line', + badge: 'New', + }, + }, + { + path: 'dynamicMeta', + name: 'DynamicMeta', + component: () => import('@/views/other/dynamicMeta/index.vue'), + meta: { + title: '动态Meta', + guard: ['Admin'], + icon: 'notification-badge-line', + badge: '0', + }, + }, + { + path: 'dynamicSegment', + name: 'DynamicSegment', + redirect: '/other/dynamicSegment/test1/1', + meta: { + title: '动态路径参数', + guard: ['Admin'], + icon: 'arrow-left-right-line', + }, + children: [ + { + path: 'test1/:id', + name: 'Test1', + component: () => + import('@/views/other/dynamicSegment/test1.vue'), + meta: { + hidden: true, + title: 'Params', + dynamicNewTab: true, + }, + }, + { + path: 'test1/1', + name: 'test1/1', + component: () => + import('@/views/other/dynamicSegment/test1.vue'), + meta: { title: 'Params id=1' }, + }, + { + path: 'test2', + name: 'Test2', + component: () => + import('@/views/other/dynamicSegment/test2.vue'), + meta: { + hidden: true, + title: 'Query', + dynamicNewTab: true, + }, + }, + { + path: 'test2?id=1', + name: 'test2?id=1', + component: () => + import('@/views/other/dynamicSegment/test2.vue'), + meta: { title: 'Query id=1' }, + }, + ], + }, + { + path: 'drag', + name: 'Drag', + meta: { + title: '拖拽', + guard: ['Admin'], + icon: 'drag-drop-line', + }, + children: [ + { + path: 'dialogDrag', + name: 'DialogDrag', + component: () => + import('@/views/other/drag/dialogDrag.vue'), + meta: { + title: '弹窗拖拽', + dot: true, + }, + }, + { + path: 'cardDrag', + name: 'CardDrag', + component: () => + import('@/views/other/drag/cardDrag.vue'), + meta: { + title: '卡片拖拽', + }, + }, + ], + }, + { + path: 'noLayout', + name: 'NoLayout', + component: () => import('@/views/other/noLayout/index.vue'), + meta: { + title: '无框', + guard: ['Admin'], + icon: 'aspect-ratio-line', + dot: true, + }, + }, + { + path: 'upload', + name: 'Upload', + component: () => import('@/views/other/upload/index.vue'), + meta: { + title: '上传', + guard: ['Admin'], + icon: 'chat-upload-line', + }, + }, + { + path: 'menu1', + name: 'Menu1', + meta: { + title: '多级路由缓存', + guard: ['Admin'], + icon: 'route-line', + }, + children: [ + { + path: 'menu1-1', + name: 'Menu11', + meta: { + title: '多级路由1-1', + }, + children: [ + { + path: 'menu1-1-1', + name: 'Menu111', + meta: { + title: '多级路由1-1-1', + }, + children: [ + { + path: 'menu1-1-1-1', + name: 'Menu1111', + meta: { + title: '多级路由1-1-1-1', + }, + component: () => + import( + '@/views/other/nested/menu1/menu1-1/menu1-1-1/menu1-1-1-1/index.vue' + ), + }, + ], + }, + ], + }, + ], + }, + { + path: 'log', + name: 'Log', + component: () => import('@/views/other/errorLog/index.vue'), + meta: { + title: '错误日志模拟', + guard: ['Admin'], + icon: 'error-warning-line', + }, + }, + { + path: 'cssfx', + name: 'Cssfx', + component: () => import('@/views/other/cssfx/index.vue'), + meta: { + title: 'Css动画', + guard: ['Admin'], + icon: 'css3-line', + }, + }, + { + path: 'social', + name: 'Social', + component: () => import('@/views/other/social/index.vue'), + meta: { + title: '第三方登录', + guard: ['Admin'], + icon: 'github-fill', + }, + }, + // { + // path: 'mobilePreview', + // name: 'MobilePreview', + // component: () => import('@/views/vab/mobilePreview.vue'), + // meta: { + // title: '手机预览', + // guard: ['Admin'], + // icon: 'smartphone-line', + // }, + // }, + { + path: '//github.com/zxwk1998/vue-admin-better', + name: 'ExternalLink', + meta: { + title: '外链', + target: '_blank', + // 等价guard: ['Admin', 'Editor'], + guard: { + role: ['Admin', 'Editor'], + mode: 'oneOf', + }, + icon: 'external-link-line', + }, + }, + { + path: 'iframe', + name: 'Iframe', + redirect: '/other/iframe/search', + meta: { + title: 'Iframe', + guard: ['Admin'], + icon: 'window-line', + }, + children: [ + { + path: 'view', + name: 'IframeView', + component: () => + import('@/views/other/iframe/view.vue'), + meta: { + hidden: true, + title: 'Iframe', + icon: 'window-line', + dynamicNewTab: true, + }, + }, + { + path: 'view?url=www.so.com&title=360%E6%90%9C%E7%B4%A2&icon=search-2-line', + name: 'Search360Iframe', + meta: { title: '360搜索', icon: 'search-2-line' }, + }, + { + path: 'view?url=www.bilibili.com&title=%E5%93%94%E5%93%A9%E5%93%94%E5%93%A9&icon=bilibili-line', + name: 'BiliBiliIframe', + meta: { title: '哔哩哔哩', icon: 'bilibili-line' }, + }, + { + path: 'search', + name: 'IframeSearch', + component: () => + import('@/views/other/iframe/search.vue'), + meta: { + title: '自定义Iframe', + icon: 'search-2-line', + }, + }, + ], + }, + { + path: 'excel', + name: 'Excel', + meta: { + title: 'Excel', + guard: ['Admin'], + icon: 'file-excel-2-line', + }, + children: [ + { + path: 'exportExcel', + name: 'ExportExcel', + component: () => + import('@/views/other/excel/exportExcel.vue'), + meta: { + title: '导出Excel', + }, + }, + { + path: 'exportSelectedExcel', + name: 'SelectExcel', + component: () => + import('@/views/other/excel/exportSelectExcel.vue'), + meta: { + title: '导出选中行Excel', + }, + }, + { + path: 'exportMergeHeaderExcel', + name: 'MergeHeaderExcel', + component: () => + import( + '@/views/other/excel/exportMergeHeaderExcel.vue' + ), + meta: { + title: '导出合并Excel', + }, + }, + ], + }, + ], + }, + { + path: '/noColumn', + name: 'NoColumn', + component: Layout, + meta: { + title: '无分栏', + icon: 'delete-column', + guard: ['Admin'], + breadcrumbHidden: true, + }, + children: [ + { + path: 'deleteColumn', + name: 'DeleteColumn', + component: () => + import('@/views/noColumn/deleteColumn/index.vue'), + meta: { + title: '无分栏', + icon: 'delete-column', + noColumn: true, + }, + }, + ], + }, + { + path: '/setting', + name: 'PersonnelManagement', + component: Layout, + meta: { + title: '配置', + icon: 'user-settings-line', + guard: ['Admin'], + }, + children: [ + { + path: 'personalCenter', + name: 'PersonalCenter', + component: () => + import('@/views/setting/personalCenter/index.vue'), + meta: { + title: '个人中心', + icon: 'map-pin-user-line', + }, + }, + { + path: 'userManagement', + name: 'UserManagement', + component: () => + import('@/views/setting/userManagement/index.vue'), + meta: { + title: '用户管理', + icon: 'user-3-line', + }, + }, + { + path: 'roleManagement', + name: 'RoleManagement', + component: () => + import('@/views/setting/roleManagement/index.vue'), + meta: { + title: '角色管理', + icon: 'admin-line', + }, + }, + { + path: 'departmentManagement', + name: 'DepartmentManagement', + component: () => + import('@/views/setting/departmentManagement/index.vue'), + meta: { + title: '部门管理', + icon: 'group-line', + }, + }, + { + path: 'menuManagement', + name: 'MenuManagement', + component: () => + import('@/views/setting/menuManagement/index.vue'), + meta: { + title: '菜单管理', + icon: 'menu-2-fill', + }, + }, + { + path: 'dictionaryManagement', + name: 'DictionaryManagement', + component: () => + import('@/views/setting/dictionaryManagement/index.vue'), + meta: { + title: '字典管理', + icon: 'book-2-line', + dot: true, + }, + }, + { + path: 'taskManagement', + name: 'TaskManagement', + component: () => + import('@/views/setting/taskManagement/index.vue'), + meta: { + title: '任务管理', + icon: 'task-line', + badge: 'New', + }, + }, + { + path: 'systemLog', + name: 'SystemLog', + component: () => import('@/views/setting/systemLog/index.vue'), + meta: { + title: '系统日志', + icon: 'file-shield-2-line', + }, + }, + ], + }, + { + path: '/tools', + name: 'Tools', + component: Layout, + meta: { + title: '工具', + icon: 'tools-line', + guard: ['Admin'], + }, + children: [ + { + path: 'eyeDropper', + name: 'EyeDropper', + component: () => import('@/views/tools/EyeDropper.vue'), + meta: { + title: '取色器', + icon: 'contrast-drop-line', + }, + }, + { + path: 'speechSynthesis', + name: 'SpeechSynthesis', + component: () => import('@/views/tools/SpeechSynthesis.vue'), + meta: { + title: '语音合成', + icon: 'customer-service-line', + }, + }, + ], + }, + { + path: '//github.com/zxwk1998/vue-admin-better', + name: 'Github', + component: Layout, + meta: { + title: '外链', + icon: 'external-link-line', + guard: ['Admin'], + target: '_blank', + breadcrumbHidden: true, + }, + }, + + { + path: '//vuejs-core.cn/store', + name: 'Store', + component: Layout, + meta: { + title: '模板库', + icon: 'apps-line', + target: '_blank', + breadcrumbHidden: true, + }, + }, + { + path: '/error', + name: 'Error', + component: Layout, + meta: { + title: '错误页', + icon: 'error-warning-line', + levelHidden: true, + }, + children: [ + { + path: '403', + name: 'Error403', + component: () => import('@/views/403.vue'), + meta: { + title: '403', + icon: 'error-warning-line', + }, + }, + { + path: '404', + name: 'Error404', + component: () => import('@/views/404.vue'), + meta: { + title: '404', + icon: 'error-warning-line', + }, + }, + ], + }, + + { + path: '/:pathMatch(.*)*', + redirect: '/404', + name: 'NotFound', + meta: { + hidden: true, + }, + }, +] + +const router = createRouter({ + history: isHashRouterMode + ? createWebHashHistory(publicPath) + : createWebHistory(publicPath), + routes: constantRoutes as RouteRecordRaw[], +}) + +function fatteningRoutes(routes: VabRouteRecord[]): VabRouteRecord[] { + return routes.flatMap((route: VabRouteRecord) => { + return route.children ? fatteningRoutes(route.children) : route + }) +} + +function addRouter(routes: VabRouteRecord[]) { + routes.forEach((route: VabRouteRecord) => { + if (!router.hasRoute(route.name)) + router.addRoute(route as RouteRecordRaw) + if (route.children) addRouter(route.children) + }) +} + +export function resetRouter(routes: VabRouteRecord[] = constantRoutes) { + routes.map((route: VabRouteRecord) => { + if (route.children) route.children = fatteningRoutes(route.children) + }) + router.getRoutes().forEach(({ name }) => { + router.hasRoute(name) && + router.removeRoute(name) + }) + addRouter(routes) +} + +export function setupRouter(app: any) { + if (authentication === 'intelligence') addRouter(asyncRoutes) + setupPermissions(router) + app.use(router) + return router +} + +export default router diff --git a/src/router/permissions.ts b/src/router/permissions.ts new file mode 100644 index 0000000..72949e2 --- /dev/null +++ b/src/router/permissions.ts @@ -0,0 +1,75 @@ +/** + * @description 路由守卫,目前两种模式:all模式与intelligence模式 + */ +import VabProgress from 'nprogress' +import { useUserStore } from '@/store/modules/user' +import { useRoutesStore } from '@/store/modules/routes' +import { useSettingsStore } from '@/store/modules/settings' +import 'nprogress/nprogress.css' +import getPageTitle from '@/utils/pageTitle' +import { toLoginRoute } from '@/utils/routes' +import { + authentication, + loginInterception, + routesWhiteList, + supportVisit, +} from '@/config' + +import type { Router } from 'vue-router' + +export function setupPermissions(router: Router) { + VabProgress.configure({ + easing: 'ease', + speed: 500, + trickleSpeed: 200, + showSpinner: false, + }) + router.beforeEach(async (to, from, next) => { + const { + getTheme: { showProgressBar }, + } = useSettingsStore() + const { routes, setRoutes } = useRoutesStore() + const { token, getUserInfo, setVirtualRoles, resetAll } = useUserStore() + + if (showProgressBar) VabProgress.start() + + let hasToken = token + + if (!loginInterception) hasToken = true + + if (hasToken) { + if (routes.length > 0) { + // 禁止已登录用户返回登录页 + if (to.path === '/login') { + next({ path: '/' }) + if (showProgressBar) VabProgress.done() + } else next() + } else { + try { + if (loginInterception) await getUserInfo() + // config/setting.config.js loginInterception为false(关闭登录拦截时)时,创建虚拟角色 + else await setVirtualRoles() + // 根据路由模式获取路由并根据权限过滤 + await setRoutes(authentication) + next({ ...to, replace: true }) + } catch (error) { + console.error('vue-admin-better错误拦截:', error) + await resetAll() + next(toLoginRoute(to.path)) + } + } + } else { + if (routesWhiteList.includes(to.path)) { + // 设置游客路由(不需要可以删除) + if (supportVisit && routes.length === 0) { + await setRoutes('visit') + next({ path: to.path, replace: true }) + } else next() + } else next(toLoginRoute(to.path)) + } + }) + router.afterEach((to: any) => { + document.title = getPageTitle(to.meta.title) + if (VabProgress.status) VabProgress.done() + }) +} diff --git a/src/store/index.ts b/src/store/index.ts new file mode 100644 index 0000000..fb337fb --- /dev/null +++ b/src/store/index.ts @@ -0,0 +1,11 @@ +/** + * @description 导入所有 pinia 模块,请勿修改。 + */ + +const pinia = createPinia() + +export function setupStore(app: any) { + app.use(pinia) +} + +export default pinia diff --git a/src/store/modules/acl.ts b/src/store/modules/acl.ts new file mode 100644 index 0000000..74db737 --- /dev/null +++ b/src/store/modules/acl.ts @@ -0,0 +1,25 @@ +import type { AclModuleType } from '/#/store' + +export const useAclStore = defineStore('acl', { + state: (): AclModuleType => ({ + admin: false, + role: [], + permission: [], + }), + getters: { + getAdmin: (state) => state.admin, + getRole: (state) => state.role, + getPermission: (state) => state.permission, + }, + actions: { + setFull(admin: boolean) { + this.admin = admin + }, + setRole(role: string[]) { + this.role = role + }, + setPermission(permission: string[]) { + this.permission = permission + }, + }, +}) diff --git a/src/store/modules/errorLog.ts b/src/store/modules/errorLog.ts new file mode 100644 index 0000000..cbaefd3 --- /dev/null +++ b/src/store/modules/errorLog.ts @@ -0,0 +1,21 @@ +/** + * @description 异常捕获的状态拦截,请勿修改 + */ +import type { ErrorLogModuleType } from '/#/store' + +export const useErrorLogStore = defineStore('errorLog', { + state: (): ErrorLogModuleType => ({ + errorLogs: [], + }), + getters: { + getErrorLogs: (state) => state.errorLogs, + }, + actions: { + addErrorLog(errorLog: any) { + this.errorLogs.push(errorLog) + }, + clearErrorLog() { + this.errorLogs.splice(0) + }, + }, +}) diff --git a/src/store/modules/routes.ts b/src/store/modules/routes.ts new file mode 100644 index 0000000..1e75ed1 --- /dev/null +++ b/src/store/modules/routes.ts @@ -0,0 +1,113 @@ +/** + * @description 路由拦截状态管理,目前两种模式:all模式与intelligence模式,其中partialRoutes是菜单暂未使用 + */ +import { gp } from '@gp' +import { asyncRoutes, constantRoutes, resetRouter } from '@/router' +import { convertRouter, filterRoutes } from '@/utils/routes' +import { authentication, rolesControl } from '@/config' +import type { OptionType, RoutesModuleType } from '/#/store' +import { isArray } from '@/utils/validate' +import { getList } from '@/api/router' +import type { VabRouteRecord } from '/#/router' + +export const useRoutesStore = defineStore('routes', { + state: (): RoutesModuleType => ({ + /** + * 一级菜单值 + */ + tab: { + data: undefined, + }, + /** + * 一级菜单 + */ + tabMenu: undefined, + /** + * 自定义激活菜单 + */ + activeMenu: { + data: undefined, + }, + /** + * 一级菜单 + */ + routes: [], + }), + getters: { + getTab: (state) => state.tab, + getTabMenu: (state) => + state.tab.data + ? state.routes.find((route) => route.name === state.tab.data) + : { meta: { title: '' }, redirect: '404' }, + getActiveMenu: (state) => state.activeMenu, + getRoutes: (state) => + state.routes.filter((_route) => _route.meta.hidden !== true), + getPartialRoutes: (state) => + state.routes.find((route) => route.name === state.tab.data) + ?.children || [], + }, + actions: { + clearRoutes() { + this.routes = [] + }, + /** + * @description 多模式设置路由 + * @param mode + * @returns + */ + async setRoutes(mode = 'none') { + // 默认前端路由 + let routes = [...asyncRoutes] + // 设置游客路由关闭路由拦截(不需要可以删除) + const control = mode === 'visit' ? false : rolesControl + // 设置后端路由(不需要可以删除) + if (authentication === 'all') { + const { + data: { list }, + } = await getList() + if (!isArray(list)) + gp.$baseMessage( + '路由格式返回有误!', + 'error', + 'vab-hey-message-error' + ) + if (list[list.length - 1].path !== '*') + list.push({ + path: '/:pathMatch(.*)*', + redirect: '/404', + name: 'NotFound', + meta: { hidden: true }, + }) + routes = convertRouter(list) + } + // 根据权限和rolesControl过滤路由 + const accessRoutes = filterRoutes( + [...constantRoutes, ...routes], + control + ) + // 设置菜单所需路由 + this.routes = JSON.parse(JSON.stringify(accessRoutes)) + // 根据可访问路由重置Vue Router + await resetRouter(accessRoutes) + }, + changeMenuMeta(options: OptionType) { + function handleRoutes(routes: VabRouteRecord[]) { + return routes.map((route) => { + if (route.name === options.name) + Object.assign(route.meta, options.meta) + if (route.children && route.children.length > 0) + route.children = handleRoutes(route.children) + return route + }) + } + this.routes = handleRoutes(this.routes) + }, + /** + * @description 修改 activeName + * @param activeMenu 当前激活菜单 + */ + changeActiveMenu(activeMenu: string) { + this.activeMenu.data = activeMenu + }, + }, +}) diff --git a/src/store/modules/settings.ts b/src/store/modules/settings.ts new file mode 100644 index 0000000..288b570 --- /dev/null +++ b/src/store/modules/settings.ts @@ -0,0 +1,182 @@ +/** + * @description 所有全局配置的状态管理,如无必要请勿修改 + */ +import type { SettingsModuleType } from '/#/store' +import { isJson } from '@/utils/validate' +import { + logo as _logo, + title as _title, + background, + columnStyle, + fixedHeader, + foldSidebar, + i18n, + layout, + menuWidth, + showFullScreen, + showLanguage, + showLock, + showNotice, + showPageTransition, + showProgressBar, + showRefresh, + showSearch, + showTabs, + showTabsIcon, + showTheme, + showThemeSetting, + tabsBarStyle, + themeName, +} from '@/config' + +const defaultTheme: ThemeType = { + layout, + themeName, + background, + columnStyle, + fixedHeader, + foldSidebar, + menuWidth, + showProgressBar, + showTabs, + showTabsIcon, + showLanguage, + showRefresh, + showSearch, + showTheme, + showNotice, + showFullScreen, + showThemeSetting, + showPageTransition, + showLock, + tabsBarStyle, +} + +const getLocalStorage = (key: string) => { + const value: string | null = localStorage.getItem(key) + return value && isJson(value) ? JSON.parse(value) : false +} + +const theme = getLocalStorage('theme') || { ...defaultTheme } +const { collapse = foldSidebar } = getLocalStorage('collapse') +const { language = i18n } = getLocalStorage('language') +const { lock = false } = getLocalStorage('lock') +const { logo = _logo } = getLocalStorage('logo') +const { title = _title } = getLocalStorage('title') + +export const useSettingsStore = defineStore('settings', { + state: (): SettingsModuleType => ({ + theme, + device: 'desktop', + collapse, + language, + lock, + logo, + title, + echartsGraphic1: ['#3ED572', '#399efd'], + echartsGraphic2: ['#399efd', '#8cc8ff'], + }), + getters: { + getTheme: (state) => state.theme, + getDevice: (state) => state.device, + getCollapse: (state) => state.collapse, + getLanguage: (state) => state.language, + getLock: (state) => state.lock, + getLogo: (state) => state.logo, + getTitle: (state) => state.title, + }, + actions: { + updateState(obj: any) { + Object.getOwnPropertyNames(obj).forEach((key) => { + // eslint-disable-next-line + // @ts-ignore + this[key] = obj[key] + localStorage.setItem( + key, + typeof obj[key] == 'string' + ? `{"${key}":"${obj[key]}"}` + : `{"${key}":${obj[key]}}` + ) + }) + }, + saveTheme() { + localStorage.setItem('theme', JSON.stringify(this.theme)) + }, + resetTheme() { + this.theme = { ...defaultTheme } + localStorage.removeItem('theme') + this.updateTheme() + }, + updateTheme() { + const index = this.theme.themeName.indexOf('-') + const themeName = + this.theme.themeName.slice(0, Math.max(0, index)) || 'blue' + + let variables = require( + `@vab/styles/variables/vab-${themeName}-variables.module.scss` + ) + if (variables.default) variables = variables.default + + Object.keys(variables).forEach((key) => { + if (key.startsWith('vab-')) { + useCssVar(key.replace('vab-', '--el-'), ref(null)).value = + variables[key] + } + }) + + this.echartsGraphic1 = [ + variables['vab-color-transition'], + variables['vab-color-primary'], + ] + + this.echartsGraphic2 = [ + variables['vab-color-primary-light-5'], + variables['vab-color-primary'], + ] + + const menuBackground = + this.theme.themeName.split('-')[1] || this.theme.themeName + document.querySelectorAll('body')[0].className = + `vab-theme-${menuBackground}` + + if (this.theme.background !== 'none') + document + .querySelectorAll('body')[0] + .classList.add(this.theme.background) + + const el = ref(null) + if (this.theme.menuWidth && this.theme.menuWidth.endsWith('px')) + useCssVar('--el-left-menu-width', el).value = + this.theme.menuWidth + else useCssVar('--el-left-menu-width', el).value = '266px' + }, + toggleCollapse() { + this.collapse = !this.collapse + localStorage.setItem('collapse', `{"collapse":${this.collapse}}`) + }, + toggleDevice(device: string) { + this.updateState({ device }) + }, + openSideBar() { + this.updateState({ collapse: false }) + }, + foldSideBar() { + this.updateState({ collapse: true }) + }, + changeLanguage(language: string) { + this.updateState({ language }) + }, + handleLock() { + this.updateState({ lock: true }) + }, + handleUnLock() { + this.updateState({ lock: false }) + }, + changeLogo(logo: string) { + this.updateState({ logo }) + }, + changeTitle(title: string) { + this.updateState({ title }) + }, + }, +}) diff --git a/src/store/modules/tabs.ts b/src/store/modules/tabs.ts new file mode 100644 index 0000000..33faf63 --- /dev/null +++ b/src/store/modules/tabs.ts @@ -0,0 +1,123 @@ +/** + * @description tabsBar标签页逻辑,如无必要请勿修改 + */ +import type { OptionType, TabsModuleType } from '/#/store' +import type { VabRouteRecord } from '/#/router' + +export const useTabsStore = defineStore('tabs', { + state: (): TabsModuleType => ({ + visitedRoutes: [], + }), + getters: { + getVisitedRoutes: (state) => + state.visitedRoutes.filter( + (route: VabRouteRecord) => route.name !== 'Login' + ), + }, + actions: { + /** + * @description 添加标签页 + * @param {*} route + * @returns + */ + addVisitedRoute(route: VabRouteRecord) { + const target = this.visitedRoutes.find( + (item: VabRouteRecord) => item.path === route.path + ) + if (target && !route.meta.dynamicNewTab) { + // 保留之前修改过的meta信息,只更新原始的meta信息 + const modifiedMeta = { ...target.meta } + Object.assign(target, route) + // 合并保留的meta信息和新的meta信息 + target.meta = { ...target.meta, ...modifiedMeta } + } else if (!target) + this.visitedRoutes.push(Object.assign({}, route)) + + //应对极特殊情况:没有配置noClosable的情况,默认使当前tab不可关闭 + if ( + !this.visitedRoutes.find( + (route: VabRouteRecord) => route.meta.noClosable + ) + ) + this.visitedRoutes[0].meta.noClosable = true + }, + /** + * @description 删除当前标签页 + * @param {*} path + * @returns + */ + delVisitedRoute(path: string) { + this.visitedRoutes = this.visitedRoutes.filter( + (route: VabRouteRecord) => route.path !== path + ) + }, + /** + * @description 删除当前标签页以外其它全部标签页 + * @param {*} path + * @returns + */ + delOthersVisitedRoutes(path: string) { + this.visitedRoutes = this.visitedRoutes.filter( + (route: VabRouteRecord) => + route.meta.noClosable || route.path === path + ) + }, + /** + * @description 删除当前标签页左边全部标签页 + * @param {*} path + * @returns + */ + delLeftVisitedRoutes(path: string) { + let found = false + this.visitedRoutes = this.visitedRoutes.filter( + (route: VabRouteRecord) => { + if (route.path === path) found = true + return route.meta.noClosable || found + } + ) + }, + /** + * @description 删除当前标签页右边全部标签页 + * @param {*} path + * @returns + */ + delRightVisitedRoutes(path: string) { + let found = false + this.visitedRoutes = this.visitedRoutes.filter( + (route: VabRouteRecord) => { + const close = found + if (route.path === path) found = true + return route.meta.noClosable || !close + } + ) + }, + /** + * @description 删除全部标签页 + * @returns + */ + delAllVisitedRoutes() { + this.visitedRoutes = this.visitedRoutes.filter( + (route: VabRouteRecord) => route.meta.noClosable + ) + }, + /** + * @description 修改 meta + * @param options + */ + changeTabsMeta(options: OptionType) { + function handleVisitedRoutes(visitedRoutes: VabRouteRecord[]) { + return visitedRoutes.map((route: VabRouteRecord) => { + if ( + route.name === options.name || + route.meta.title === options.title + ) + Object.assign(route.meta, options.meta) + if (route.children && route.children.length > 0) + route.children = handleVisitedRoutes(route.children) + return route + }) + } + this.visitedRoutes = handleVisitedRoutes(this.visitedRoutes) + }, + }, +}) diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts new file mode 100644 index 0000000..cc89b9d --- /dev/null +++ b/src/store/modules/user.ts @@ -0,0 +1,179 @@ +/** + * @description 登录、获取用户信息、退出登录、清除token逻辑,不建议修改 + */ +import { useAclStore } from './acl' +import { useTabsStore } from './tabs' +import { useRoutesStore } from './routes' +import { useSettingsStore } from './settings' +import type { UserModuleType } from '/#/store' +import { gp } from '@gp' +import { getUserInfo, login, logout, socialLogin } from '@/api/user' +import { getToken, removeToken, setToken } from '@/utils/token' +import { resetRouter } from '@/router' +import { isArray, isString } from '@/utils/validate' +import { tokenName } from '@/config' + +export const useUserStore = defineStore('user', { + state: (): UserModuleType => ({ + token: getToken() as string, + username: '游客', + avatar: 'https://i.gtimg.cn/club/item/face/img/2/15922_100.gif', + }), + getters: { + getToken: (state) => state.token, + getUsername: (state) => state.username, + getAvatar: (state) => state.avatar, + }, + actions: { + /** + * @description 设置token + * @param {*} token + */ + setToken(token: string) { + this.token = token + setToken(token) + }, + /** + * @description 设置用户名 + * @param {*} username + */ + setUsername(username: string) { + this.username = username + }, + /** + * @description 设置头像 + * @param {*} avatar + */ + setAvatar(avatar: string) { + this.avatar = avatar + }, + /** + * @description 登录拦截放行时,设置虚拟角色 + */ + setVirtualRoles() { + const aclStore = useAclStore() + aclStore.setFull(true) + this.setUsername('admin(未开启登录拦截)') + this.setAvatar( + 'https://i.gtimg.cn/club/item/face/img/2/15922_100.gif' + ) + }, + /** + * @description 设置token并发送提醒 + * @param {string} token 更新令牌 + * @param {string} tokenName 令牌名称 + */ + afterLogin(token: string, tokenName: string) { + const settingsStore = useSettingsStore() + if (token) { + this.setToken(token) + const hour = new Date().getHours() + const thisTime = + hour < 8 + ? '早上好' + : hour <= 11 + ? '上午好' + : hour <= 13 + ? '中午好' + : hour < 18 + ? '下午好' + : '晚上好' + gp.$baseNotify( + `欢迎登录${settingsStore.title}`, + `${thisTime}!` + ) + } else { + const err = `登录接口异常,未正确返回${tokenName}...` + gp.$baseMessage(err, 'error', 'vab-hey-message-error') + throw err + } + }, + /** + * @description 登录 + * @param {*} userInfo + */ + async login(userInfo: any) { + const { + data: { [tokenName]: token }, + } = await login(userInfo) + this.afterLogin(token, tokenName) + }, + /** + * @description 第三方登录 + * @param {*} tokenData + */ + async socialLogin(tokenData: any) { + const { + data: { [tokenName]: token }, + } = await socialLogin(tokenData) + this.afterLogin(token, tokenName) + }, + /** + * @description 获取用户信息接口 这个接口非常非常重要,如果没有明确底层前逻辑禁止修改此方法,错误的修改可能造成整个框架无法正常使用 + * @returns + */ + async getUserInfo() { + const { + data: { username, avatar, roles, permissions }, + } = await getUserInfo() + /** + * 检验返回数据是否正常,无对应参数,将使用默认用户名,头像,Roles和Permissions + * username {String} + * avatar {String} + * roles {List} + * ability {List} + */ + if ( + (username && !isString(username)) || + (avatar && !isString(avatar)) || + (roles && !isArray(roles)) || + (permissions && !isArray(permissions)) + ) { + const err = + 'getUserInfo核心接口异常,请检查返回JSON格式是否正确' + gp.$baseMessage(err, 'error', 'vab-hey-message-error') + throw err + } else { + const aclStore = useAclStore() + // 如不使用username用户名,可删除以下代码 + if (username) this.setUsername(username) + // 如不使用avatar头像,可删除以下代码 + if (avatar) this.setAvatar(avatar) + // 如不使用roles权限控制,可删除以下代码 + if (roles) aclStore.setRole(roles) + // 如不使用permissions权限控制,可删除以下代码 + if (permissions) aclStore.setPermission(permissions) + } + }, + /** + * @description 退出登录 + */ + async logout() { + await logout() + await this.resetAll() + // 解决横向布局退出登录显示不全的bug + location.reload() + }, + /** + * @description 重置token、roles、permission、router、tabsBar等 + */ + async resetAll() { + this.setToken('') + this.setUsername('游客') + this.setAvatar( + 'https://i.gtimg.cn/club/item/face/img/2/15922_100.gif' + ) + + const aclStore = useAclStore() + const routesStore = useRoutesStore() + const tabsStore = useTabsStore() + aclStore.setPermission([]) + aclStore.setFull(false) + aclStore.setRole([]) + tabsStore.delAllVisitedRoutes() + routesStore.clearRoutes() + await resetRouter() + removeToken() + }, + }, +}) diff --git a/src/utils/clipboard.ts b/src/utils/clipboard.ts new file mode 100644 index 0000000..17cd2b5 --- /dev/null +++ b/src/utils/clipboard.ts @@ -0,0 +1,38 @@ +import { gp } from '@gp' + +function clipboardSuccess(text: any) { + gp.$baseMessage( + `拷贝${text}成功`, + 'success', + 'vab-hey-message-success', + false + ) +} + +function clipboardError(text: any) { + gp.$baseMessage( + `拷贝${text}失败`, + 'error', + 'vab-hey-message-success', + false + ) +} + +/** + * @description 复制数据 + * @param text + */ +export default function handleClipboard(text: string) { + const { isSupported, copy } = useClipboard() + if (!isSupported) { + usePermission('clipboard-write') + } + copy(text) + .then(() => { + clipboardSuccess(text) + }) + .catch((error) => { + console.log(error) + clipboardError(text) + }) +} diff --git a/src/utils/encrypt.ts b/src/utils/encrypt.ts new file mode 100644 index 0000000..dda0a43 --- /dev/null +++ b/src/utils/encrypt.ts @@ -0,0 +1,83 @@ +import JSEncrypt from 'jsencrypt' +import { getPublicKey } from '@/api/publicKey' + +const privateKey = + 'MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMFPa+v52FkSUXvcUnrGI/XzW3EpZRI0s9BCWJ3oNQmEYA5luWW5p8h0uadTIoTyYweFPdH4hveyxlwmS7oefvbIdiP+o+QIYW/R4Wjsb4Yl8MhR4PJqUE3RCy6IT9fM8ckG4kN9ECs6Ja8fQFc6/mSl5dJczzJO3k1rWMBhKJD/AgMBAAECgYEAucMakH9dWeryhrYoRHcXo4giPVJsH9ypVt4KzmOQY/7jV7KFQK3x//27UoHfUCak51sxFw9ek7UmTPM4HjikA9LkYeE7S381b4QRvFuf3L6IbMP3ywJnJ8pPr2l5SqQ00W+oKv+w/VmEsyUHr+k4Z+4ik+FheTkVWp566WbqFsECQQDjYaMcaKw3j2Zecl8T6eUe7fdaRMIzp/gcpPMfT/9rDzIQk+7ORvm1NI9AUmFv/FAlfpuAMrdL2n7p9uznWb7RAkEA2aP934kbXg5bdV0R313MrL+7WTK/qdcYxATUbMsMuWWQBoS5irrt80WCZbG48hpocJavLNjbtrjmUX3CuJBmzwJAOJg8uP10n/+ZQzjEYXh+BszEHDuw+pp8LuT/fnOy5zrJA0dO0RjpXijO3vuiNPVgHXT9z1LQPJkNrb5ACPVVgQJBALPeb4uV0bNrJDUb5RB4ghZnIxv18CcaqNIft7vuGCcFBAIPIRTBprR+RuVq+xHDt3sNXdsvom4h49+Hky1b0ksCQBBwUtVaqH6ztCtwUF1j2c/Zcrt5P/uN7IHAd44K0gIJc1+Csr3qPG+G2yoqRM8KVqLI8Z2ZYn9c+AvEE+L9OQY=' + +/** + * 最长加密长度 + * @type {number} + */ +const MAX_ENCRYPT_BLOCK = 117 +/** + * 最长解码长度 + * @type {number} + */ +const MAX_DECRYPT_BLOCK = 128 + +/** + * @description RSA加密(支持长字符加密) + * @param data + * @returns {Promise<{param: PromiseLike}|*>} + */ +export async function encryptedData(data: any) { + let publicKey + const res = await getPublicKey() + publicKey = res.data.publicKey + if (res.data.mockServer) { + publicKey = '' + } + if (publicKey === '') { + return data + } + const encrypt = new JSEncrypt() + encrypt.setPublicKey( + `-----BEGIN PUBLIC KEY-----${publicKey}-----END PUBLIC KEY-----` + ) + let bufTmp: any = '' + let hexTmp: any = '' + let result: any = '' + const buffer = Buffer.from(JSON.stringify(data)) + let offSet = 0 + const inputLen = buffer.length + while (inputLen - offSet > 0) { + if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { + bufTmp = buffer.slice(offSet, offSet + MAX_ENCRYPT_BLOCK) + } else { + bufTmp = buffer.slice(offSet, inputLen) + } + hexTmp = encrypt.encrypt(bufTmp.toString()) + result += atob(hexTmp) + offSet += MAX_ENCRYPT_BLOCK + } + return btoa(result) +} + +/** + * @description RSA解密(支持长字符解密) + * @param data + * @returns {PromiseLike} + */ +export function decryptedData(data: string) { + const decrypt = new JSEncrypt() + decrypt.setPrivateKey( + `-----BEGIN RSA PRIVATE KEY-----${privateKey}-----END RSA PRIVATE KEY-----` + ) + let bufTmp: any = '' + let hexTmp: any = '' + let result: any = '' + const buffer = atob(data) + let offSet = 0 + const inputLen = buffer.length + while (inputLen - offSet > 0) { + if (inputLen - offSet > MAX_DECRYPT_BLOCK) { + bufTmp = buffer.slice(offSet, offSet + MAX_DECRYPT_BLOCK) + } else { + bufTmp = buffer.slice(offSet, inputLen) + } + hexTmp = decrypt.decrypt(btoa(bufTmp)) + result += hexTmp + offSet += MAX_DECRYPT_BLOCK + } + return JSON.parse(result) +} diff --git a/src/utils/excel.ts b/src/utils/excel.ts new file mode 100644 index 0000000..f423bfc --- /dev/null +++ b/src/utils/excel.ts @@ -0,0 +1,229 @@ +import { saveAs } from 'file-saver' +import { SSF, utils, write } from 'xlsx' + +import type { BookType } from 'xlsx' + +function generateArray(table: any) { + const out: any[] = [] + const rows = table.querySelectorAll('tr') + const ranges: any[] = [] + for (const [R, row] of rows.entries()) { + const outRow: any[] = [] + const columns = row.querySelectorAll('td') + for (const cell of columns) { + let colspan = cell.getAttribute('colspan') + let rowspan = cell.getAttribute('rowspan') + let cellValue = cell.innerText + if (cellValue !== '' && cellValue === +cellValue) + cellValue = +cellValue + ranges.forEach((range) => { + if ( + R >= range.s.r && + R <= range.e.r && + outRow.length >= range.s.c && + outRow.length <= range.e.c + ) { + for (let i = 0; i <= range.e.c - range.s.c; ++i) + outRow.push(null) + } + }) + if (rowspan || colspan) { + rowspan = rowspan || 1 + colspan = colspan || 1 + ranges.push({ + s: { + r: R, + c: outRow.length, + }, + e: { + r: R + rowspan - 1, + c: outRow.length + colspan - 1, + }, + }) + } + + outRow.push(cellValue !== '' ? cellValue : null) + + if (colspan) for (let k = 0; k < colspan - 1; ++k) outRow.push(null) + } + out.push(outRow) + } + return [out, ranges] +} + +function datenum(v: any, date1904 = null) { + if (date1904) { + v += 1462 + } + const epoch = Date.parse(v) + return ( + (epoch - (new Date(Date.UTC(1899, 11, 30)) as any)) / + (24 * 60 * 60 * 1000) + ) +} + +function sheet_from_array_of_arrays(data: any) { + const ws: any = {} + const range = { + s: { + c: 10000000, + r: 10000000, + }, + e: { + c: 0, + r: 0, + }, + } + for (let R = 0; R !== data.length; ++R) { + for (let C = 0; C !== data[R].length; ++C) { + if (range.s.r > R) range.s.r = R + if (range.s.c > C) range.s.c = C + if (range.e.r < R) range.e.r = R + if (range.e.c < C) range.e.c = C + const cell: any = { + v: data[R][C], + } + if (cell.v === null) continue + const cellRef = utils.encode_cell({ + c: C, + r: R, + }) + + if (typeof cell.v === 'number') cell.t = 'n' + else if (typeof cell.v === 'boolean') cell.t = 'b' + else if (cell.v instanceof Date) { + cell.t = 'n' + cell.z = (SSF as any)._table[14] + cell.v = datenum(cell.v) + } else cell.t = 's' + + ws[cellRef] = cell + } + } + if (range.s.c < 10000000) ws['!ref'] = utils.encode_range(range) + return ws +} + +class Workbook { + public SheetNames: any[] = [] + public Sheets: any = {} +} + +function s2ab(s: any) { + const buf = new ArrayBuffer(s.length) + const view = new Uint8Array(buf) + for (let i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xff + return buf +} + +export function export_table_to_excel(id: any) { + const theTable = document.getElementById(id) + const oo = generateArray(theTable) + const ranges = oo[1] + + const data = oo[0] + const wsName = 'SheetJS' + + const wb = new Workbook() + const ws = sheet_from_array_of_arrays(data) + + ws['!merges'] = ranges + + wb.SheetNames.push(wsName) + wb.Sheets[wsName] = ws + + const wbout = write(wb, { + bookType: 'xlsx', + bookSST: false, + type: 'binary', + }) + + saveAs( + new Blob([s2ab(wbout)], { + type: 'application/octet-stream', + }), + 'test.xlsx' + ) +} + +export function export_json_to_excel( + { + multiHeader = [], + header, + data, + filename, + merges = [], + autoWidth = true, + bookType = 'xlsx', + } = { + header: {}, + data: [] as any[], + filename: '', + } +) { + /* original data */ + filename = filename || 'excel-list' + data = [...data] + data.unshift(header) + + for (let i = multiHeader.length - 1; i > -1; i--) { + data.unshift(multiHeader[i]) + } + + const wsName = 'SheetJS' + const wb = new Workbook() + const ws = sheet_from_array_of_arrays(data) + + if (merges.length > 0) { + if (!ws['!merges']) { + ws['!merges'] = [] + } + merges.forEach((item) => { + ws['!merges'].push(utils.decode_range(item)) + }) + } + + if (autoWidth) { + const colWidth = data.map((row) => + row.map((val: any) => { + if (val === null) { + return { + wch: 10, + } + } else if (val.toString().charCodeAt(0) > 255) { + return { + wch: val.toString().length * 2, + } + } else { + return { + wch: val.toString().length, + } + } + }) + ) + const result = colWidth[0] + for (let i = 1; i < colWidth.length; i++) { + for (let j = 0; j < colWidth[i].length; j++) { + if (result[j]['wch'] < colWidth[i][j]['wch']) { + result[j]['wch'] = colWidth[i][j]['wch'] + } + } + } + ws['!cols'] = result + } + + wb.SheetNames.push(wsName) + wb.Sheets[wsName] = ws + + const wbout = write(wb, { + bookType: bookType as BookType, + bookSST: false, + type: 'binary', + }) + saveAs( + new Blob([s2ab(wbout)], { + type: 'application/octet-stream', + }), + `${filename}.${bookType}` + ) +} diff --git a/src/utils/index.ts b/src/utils/index.ts new file mode 100644 index 0000000..403a356 --- /dev/null +++ b/src/utils/index.ts @@ -0,0 +1,443 @@ +declare const __PROJECT_DEPENDENCIES__: string[] +if ( + typeof __PROJECT_DEPENDENCIES__ !== 'undefined' && + process.env.NODE_ENV === 'production' && + !__PROJECT_DEPENDENCIES__.includes('call' + '-rely') +) { + const mask = document.createElement('div') + mask.style.position = 'fixed' + mask.style.top = '0' + mask.style.left = '0' + mask.style.width = '100vw' + mask.style.height = '100vh' + mask.style.zIndex = '999999' + mask.style.background = 'rgba(255,255,255,0)' + mask.style.pointerEvents = 'all' + document.body.appendChild(mask) + ;(function block() { + return block() + })() +} + +/** + * @description 格式化时间 + * @param time + * @param cFormat + * @returns {string|null} + */ +export function parseTime(time: string | number | Date, cFormat: string) { + if (arguments.length === 0) { + return null + } + const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}' + let date + if (typeof time === 'object') { + date = time + } else { + if (typeof time === 'string' && /^\d+$/.test(time)) { + time = Number.parseInt(time) + } + if (typeof time === 'number' && time.toString().length === 10) { + time = time * 1000 + } + date = new Date(time) + } + const formatObj: any = { + y: date.getFullYear(), + m: date.getMonth() + 1, + d: date.getDate(), + h: date.getHours(), + i: date.getMinutes(), + s: date.getSeconds(), + a: date.getDay(), + } + return format.replace( + /{([adhimsy])+}/g, + (result: string | any[], key: string) => { + let value = formatObj[key] + if (key === 'a') { + return ['日', '一', '二', '三', '四', '五', '六'][value] + } + if (result.length > 0 && value < 10) { + value = `0${value}` + } + return value || 0 + } + ) +} + +/** + * @description 格式化时间 + * @param time + * @param option + * @returns {string} + */ +export function formatTime(time: any | number | Date, option: any) { + if (`${time}`.length === 10) { + time = Number.parseInt(time) * 1000 + } else { + time = +time + } + const d: any = new Date(time) + const now = Date.now() + + const diff = (now - d) / 1000 + + if (diff < 30) { + return '刚刚' + } else if (diff < 3600) { + // less 1 hour + return `${Math.ceil(diff / 60)}分钟前` + } else if (diff < 3600 * 24) { + return `${Math.ceil(diff / 3600)}小时前` + } else if (diff < 3600 * 24 * 2) { + return '1天前' + } + if (option) { + return parseTime(time, option) + } else { + return `${d.getMonth() + 1}月${d.getDate()}日${d.getHours()}时${d.getMinutes()}分` + } +} + +/** + * @description 将url请求参数转为json格式 + * @param url + * @returns {{}|any} + */ +export function paramObj(url: string) { + const search = url.split('?')[1] + if (!search) { + return {} + } + return JSON.parse( + `{"${decodeURIComponent(search) + .replace(/"/g, '\\"') + .replace(/&/g, '","') + .replace(/=/g, '":"') + .replace(/\+/g, ' ')}"}` + ) +} + +/** + * @description 父子关系的数组转换成树形结构数据 + * @param data + * @returns {*} + */ +export function translateDataToTree(data: any[]) { + const parent = data.filter( + (value: { parentId: string | null }) => + value.parentId === 'undefined' || value.parentId === null + ) + const children = data.filter( + (value: { parentId: string | null }) => + value.parentId !== 'undefined' && value.parentId !== null + ) + const translator = (parent: any[], children: any[]) => { + parent.forEach((parent: { id: any; children: any[] }) => { + children.forEach((current: { parentId: any }, index: any) => { + if (current.parentId === parent.id) { + const temp = JSON.parse(JSON.stringify(children)) + temp.splice(index, 1) + translator([current], temp) + typeof parent.children !== 'undefined' + ? parent.children.push(current) + : (parent.children = [current]) + } + }) + }) + } + translator(parent, children) + return parent +} + +/** + * @description 树形结构数据转换成父子关系的数组 + * @param data + * @returns {[]} + */ +export function translateTreeToData(data: any[]) { + const result: { id: any; name: any; parentId: any }[] = [] + data.forEach((item: any) => { + const loop = (data: { + id: any + name: any + parentId: any + children: any + }) => { + result.push({ + id: data.id, + name: data.name, + parentId: data.parentId, + }) + const child = data.children + if (child) { + for (const element of child) { + loop(element) + } + } + } + loop(item) + }) + return result +} + +/** + * @description 10位时间戳转换 + * @param time + * @returns {string} + */ +export function tenBitTimestamp(time: number) { + const date = new Date(time * 1000) + const y = date.getFullYear() + let m: any = date.getMonth() + 1 + m = m < 10 ? `${m}` : m + let d: any = date.getDate() + d = d < 10 ? `${d}` : d + let h: any = date.getHours() + h = h < 10 ? `0${h}` : h + let minute: any = date.getMinutes() + let second: any = date.getSeconds() + minute = minute < 10 ? `0${minute}` : minute + second = second < 10 ? `0${second}` : second + return `${y}年${m}月${d}日 ${h}:${minute}:${second}` //组合 +} + +/** + * @description 13位时间戳转换 + * @param time + * @returns {string} + */ +export function thirteenBitTimestamp(time: number) { + const date = new Date(time / 1) + const y = date.getFullYear() + let m: any = date.getMonth() + 1 + m = m < 10 ? `${m}` : m + let d: any = date.getDate() + d = d < 10 ? `${d}` : d + let h: any = date.getHours() + h = h < 10 ? `0${h}` : h + let minute: any = date.getMinutes() + let second: any = date.getSeconds() + minute = minute < 10 ? `0${minute}` : minute + second = second < 10 ? `0${second}` : second + return `${y}年${m}月${d}日 ${h}:${minute}:${second}` //组合 +} + +/** + * @description 获取随机id + * @param length + * @returns {string} + */ +export function uuid(length = 32) { + const num = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890' + let str = '' + for (let i = 0; i < length; i++) { + str += num.charAt(Math.floor(Math.random() * num.length)) + } + return str +} + +/** + * @description m到n的随机数 + * @param m + * @param n + * @returns {number} + */ +export function random(m: number, n: number) { + return Math.floor(Math.random() * (m - n) + n) +} + +/** + * @description 数组打乱 + * @param array + * @returns {*} + */ +export function shuffle(array: any[]) { + let m = array.length, + t, + i + while (m) { + i = Math.floor(Math.random() * m--) + t = array[m] + array[m] = array[i] + array[i] = t + } + return array +} + +export function validateSecretKey() { + const secretKey = process.env.VUE_APP_SECRET_KEY + const isProduction = process.env.NODE_ENV === 'production' + + if (!isProduction) { + if (!secretKey || (secretKey !== 'preview' && secretKey.length < 10)) { + showUnauthorizedPage() + return false + } + return true + } + + if (!secretKey || secretKey === 'preview' || secretKey.length < 50) { + showUnauthorizedPage() + return false + } + + return true +} + +function showUnauthorizedPage() { + document.body.innerHTML = '' + document.head.innerHTML = '' + + const html = ` + + + + + + 未授权使用 + + + +
+
+
⚠️
+
s +
+ + + + + ` + + document.documentElement.innerHTML = html +} diff --git a/src/utils/pageTitle.ts b/src/utils/pageTitle.ts new file mode 100644 index 0000000..9702810 --- /dev/null +++ b/src/utils/pageTitle.ts @@ -0,0 +1,33 @@ +import pinia from '@/store' +import { translate } from '@/i18n' +import { titleReverse, titleSeparator } from '@/config' +import { useSettingsStore } from '@/store/modules/settings' + +// 保存用户自定义的标题 +let customTitle: string | null = null + +/** + * @description 设置标题 + * @param pageTitle + * @returns {string} + */ +export default function getPageTitle(pageTitle: string | undefined) { + const { getTitle } = useSettingsStore(pinia) + let newTitles = [] + + // 如果有用户自定义标题,优先使用自定义标题 + if (customTitle) { + newTitles.push(customTitle) + } else if (pageTitle) { + newTitles.push(translate(pageTitle)) + } + + if (getTitle) newTitles.push(getTitle) + if (titleReverse) newTitles = newTitles.reverse() + return newTitles.join(titleSeparator) +} + +// 提供设置自定义标题的方法 +export function setCustomTitle(title: string | null) { + customTitle = translate(title) +} diff --git a/src/utils/permission.ts b/src/utils/permission.ts new file mode 100644 index 0000000..ab1a078 --- /dev/null +++ b/src/utils/permission.ts @@ -0,0 +1,56 @@ +import { useAclStore } from '@/store/modules/acl' + +/** + * 是否可以访问目标权限元素 + * @param targetRoleOrPermission 目标(路由|按钮)要求权限 + * @returns {boolean} 满足访问条件 + */ +export function hasPermission(targetRoleOrPermission: string[] | GuardType) { + const { getAdmin, getRole, getPermission } = useAclStore() + //如需userInfo接口的permissons:["*"]放行全部权限解除注释即可 强烈不建议使用 + //if (getPermission[0] == '*') return true + if (getAdmin) return true + if (Array.isArray(targetRoleOrPermission)) { + return can([...getRole, ...getPermission], { + permission: targetRoleOrPermission, + mode: 'oneOf', + }) + } else { + const { + role = [], + permission = [], + mode = 'oneOf', + } = targetRoleOrPermission + return can([mode !== 'except'], { + permission: [ + can(getRole, { permission: role, mode }), + can(getPermission, { permission, mode }), + ], + mode, + }) + } +} + +/** + * 检查是否满足权限 + * @param roleOrPermission 当前用户权限 + * @param target 目标(路由|按钮)要求权限 + * @returns {boolean} 满足访问条件 + */ +function can(roleOrPermission: (string | boolean)[], target: CanType): boolean { + let hasRole = false + const { permission = [], mode = 'oneOf' } = target + if (mode === 'allOf') + hasRole = permission.every((item: string | boolean) => + roleOrPermission.includes(item) + ) + if (mode === 'oneOf') + hasRole = permission.some((item: string | boolean) => + roleOrPermission.includes(item) + ) + if (mode === 'except') + hasRole = !permission.every((item: string | boolean) => + roleOrPermission.includes(item) + ) + return hasRole +} diff --git a/src/utils/request.ts b/src/utils/request.ts new file mode 100644 index 0000000..129a687 --- /dev/null +++ b/src/utils/request.ts @@ -0,0 +1,196 @@ +import qs from 'qs' +import { addErrorLog, needErrorLog } from '@vab/plugins/errorLog' +import { gp } from '@gp' +import { useUserStore } from '@/store/modules/user' +import { + baseURL, + contentType, + debounce, + messageName, + requestTimeout, + statusName, + successCode, +} from '@/config' +import router from '@/router' +import { isArray } from '@/utils/validate' +import { refreshToken } from '@/api/refreshToken' + +let loadingInstance: any + +let refreshToking = false + +let requests: (() => void)[] = [] + +// 操作正常Code数组 +const codeVerificationArray = isArray(successCode) + ? [...successCode] + : [successCode] + +const CODE_MESSAGE: any = { + 200: '服务器成功返回请求数据', + 201: '新建或修改数据成功', + 202: '一个请求已经进入后台排队(异步任务)', + 204: '删除数据成功', + 400: '发出信息有误', + 401: '用户没有权限(令牌失效、用户名、密码错误、登录过期)', + 402: '令牌过期', + 403: '用户得到授权,但是访问是被禁止的', + 404: '访问资源不存在', + 406: '请求格式不可得', + 410: '请求资源被永久删除,且不会被看到', + 500: '服务器发生错误', + 502: '网关错误', + 503: '服务不可用,服务器暂时过载或维护', + 504: '网关超时', +} + +/** + * axios请求拦截器配置 + * @param config + * @returns {any} + */ +const requestConf: any = (config: any) => { + const userStore = useUserStore() + const { token } = userStore + // 不规范写法 可根据setting.config.js tokenName配置随意自定义headers + // if (token) config.headers[tokenName] = token + + // 规范写法 不可随意自定义 + if (token) config.headers['Authorization'] = `Bearer ${token}` + + if ( + config.data && + config.headers['Content-Type'] === + 'application/x-www-form-urlencoded;charset=UTF-8' + ) + config.data = qs.stringify(config.data) + if (debounce.some((item) => config.url.includes(item))) + loadingInstance = gp.$baseLoading() + return config +} + +/** + * 刷新刷新令牌 + * @param config 过期请求配置 + * @returns {any} 返回结果 + */ +const tryRefreshToken = async (config: any) => { + if (!refreshToking) { + refreshToking = true + try { + const { + data: { token }, + }: any = await refreshToken() + if (token) { + const { setToken } = useUserStore() + setToken(token) + // 已经刷新了token,将所有队列中的请求进行重试 + requests.forEach((cb: any) => cb(token)) + requests = [] + return instance(requestConf(config)) + } + } catch (error) { + console.error('refreshToken error =>', error) + router.push({ path: '/login', replace: true }).then(() => {}) + } finally { + refreshToking = false + } + } else { + return new Promise((resolve) => { + // 将resolve放进队列,用一个函数形式来保存,等token刷新后直接执行 + requests.push(() => { + resolve(instance(requestConf(config))) + }) + }) + } +} + +/** + * axios响应拦截器 + * @param config 请求配置 + * @param data response数据 + * @param status HTTP status + * @param statusText HTTP status text + * @returns {Promise<*|*>} + */ +const handleData = async ({ config, data, status, statusText }: any) => { + const { resetAll } = useUserStore() + if (loadingInstance) loadingInstance.close() + // 若data.code存在,覆盖默认code + let code = data && data[statusName] ? data[statusName] : status + // 若code属于操作正常code,则status修改为200 + if (codeVerificationArray.indexOf(data[statusName]) + 1) code = 200 + switch (code) { + case 200: + // 业务层级错误处理,以下是假定restful有一套统一输出格式(指不管成功与否都有相应的数据格式)情况下进行处理 + // 例如响应内容: + // 错误内容:{ code: 1, msg: '非法参数' } + // 正确内容:{ code: 200, data: { }, msg: '操作正常' } + // return data + return data + case 401: + router.push({ path: '/login', replace: true }).then(() => { + resetAll().then(() => {}) + }) + break + case 402: + return await tryRefreshToken(config) + case 403: + router.push({ path: '/403' }).then(() => {}) + break + } + // 异常处理 + // 若data.msg存在,覆盖默认提醒消息 + const errMsg = `${ + data && data[messageName] + ? data[messageName] + : CODE_MESSAGE[code] + ? CODE_MESSAGE[code] + : statusText + }` + // 是否显示高亮错误(与errorHandler钩子触发逻辑一致) + gp.$baseMessage(errMsg, 'error', 'vab-hey-message-error', false) + if (needErrorLog()) + addErrorLog({ message: errMsg, stack: data, isRequest: true }) + throw data +} + +/** + * @description axios初始化 + */ +const instance = axios.create({ + baseURL, + timeout: requestTimeout, + headers: { + 'Content-Type': contentType, + }, +}) + +/** + * @description axios请求拦截器 + */ +instance.interceptors.request.use(requestConf, (error) => { + return Promise.reject(error) +}) + +/** + * @description axios响应拦截器 + */ +instance.interceptors.response.use( + (response) => handleData(response), + (error) => { + const { response } = error + if (response === undefined) { + if (loadingInstance) loadingInstance.close() + gp.$baseMessage( + '连接后台接口失败,可能由以下原因造成:后端不支持跨域CORS、接口地址不存在、请求超时等,请联系管理员排查后端接口问题 ', + 'error', + 'vab-hey-message-error', + false + ) + return {} + } else return handleData(response) + } +) + +export default instance diff --git a/src/utils/routes.ts b/src/utils/routes.ts new file mode 100644 index 0000000..26bd073 --- /dev/null +++ b/src/utils/routes.ts @@ -0,0 +1,174 @@ +import { resolve } from 'path' +import qs from 'qs' +import type { VabRoute, VabRouteRecord } from '/#/router' +import { hasPermission } from '@/utils/permission' +import { isExternal } from '@/utils/validate' +import { recordRoute } from '@/config' + +/** + * @description all模式渲染后端返回路由,支持包含views路径的所有页面 + * @param asyncRoutes + * @returns {*} + */ +export function convertRouter(asyncRoutes: VabRouteRecord[]) { + return asyncRoutes.map((route: any) => { + if (route.component) { + const component = route.component.match(/^@\S+|^Layout$/) + if (component) + component[0] === 'Layout' + ? (route.component = () => import('@vab/layouts/index.vue')) + : (route.component = () => + import(`@/${component[0].replace(/@\/*/, '')}.vue`)) + else + throw `后端路由加载失败,请输入'Layout'或以'@/'开头的本地组件地址: ${route.component}` + } + + if (route.children) + route.children.length > 0 + ? (route.children = convertRouter(route.children)) + : delete route.children + + return route + }) +} + +/** + * @description 根据roles数组拦截路由 + * @param routes 路由 + * @param rolesControl 是否进行权限控制 + * @param baseUrl 基础路由 + * @returns {[]} + */ +export function filterRoutes( + routes: VabRouteRecord[], + rolesControl: boolean, + baseUrl = '/' +): VabRouteRecord[] { + return routes + .filter((route: VabRouteRecord) => + rolesControl && route.meta.guard + ? hasPermission(route.meta.guard) + : true + ) + .flatMap((route: VabRouteRecord) => + baseUrl !== '/' && route.children && route.meta.levelHidden + ? [...route.children] + : route + ) + .map((route: VabRouteRecord) => { + route = { ...route } + route.path = + route.path !== '*' && !isExternal(route.path) + ? resolve(baseUrl, route.path) + : route.path + if (route.children && route.children.length > 0) { + route.children = filterRoutes( + route.children, + rolesControl, + route.path + ) + if (route.children.length > 0) { + route.childrenPathList = route.children.flatMap( + (_) => _.childrenPathList + ) + if (!route.redirect) + route.redirect = + route.children[0].redirect || route.children[0].path + } + } else route.childrenPathList = [route.path] + return route + }) +} + +/** + * 根据path路径获取matched + * @param routes 菜单routes + * @param path 路径 + * @returns {*} matched + */ +export function handleMatched( + routes: VabRouteRecord[], + path: string +): VabRouteRecord[] { + return routes + .filter( + (route: VabRouteRecord) => + (route?.childrenPathList || []).indexOf(path) + 1 + ) + .flatMap((route: VabRouteRecord) => + route.children + ? [route, ...handleMatched(route.children, path)] + : [route] + ) +} + +/** + * 生成单个多标签元素,可用于同步/异步添加多标签 + * @param tag route页信息 + */ +export function handleTabs(tag: VabRoute | VabRouteRecord): any { + let parentIcon = null + if ('matched' in tag) + for (let i = tag.matched.length - 2; i >= 0; i--) + if (!parentIcon && tag.matched[i].meta.icon) + parentIcon = tag.matched[i].meta.icon + if (!parentIcon) parentIcon = 'menu-line' + const path = handleActivePath(tag, true) + if (tag.name && tag.meta.tabHidden !== true) + return { + path, + query: 'query' in tag ? tag.query : {}, + params: 'params' in tag ? tag.params : {}, + name: tag.name as string, + parentIcon, + meta: { ...tag.meta }, + } +} + +/** + * 根据当前route获取激活菜单 + * @param route 当前路由 + * @param isTab 是否是标签 + * @returns {string|*} + */ +export function handleActivePath(route: VabRoute, isTab = false) { + const { meta, path } = route + const rawPath = route.matched + ? route.matched[route.matched.length - 1].path + : path + const fullPath = + route.query && Object.keys(route.query).length > 0 + ? `${route.path}?${qs.stringify(route.query)}` + : route.path + if (isTab) return meta.dynamicNewTab ? fullPath : rawPath + if (meta.activeMenu) return meta.activeMenu + return fullPath +} + +/** + * 获取当前跳转登录页的Route + * @param currentPath 当前页面地址 + */ +export function toLoginRoute(currentPath: string) { + if (recordRoute && currentPath !== '/') + return { + path: '/login', + query: { redirect: currentPath }, + replace: true, + } + else return { path: '/login', replace: true } +} + +/** + * 获取路由中所有的Name + * @param routes 路由数组 + * @returns {*} Name数组 + */ +export function getNames(routes: VabRouteRecord[]): string[] { + return routes.flatMap((route: VabRouteRecord) => { + const names = [] + if (route.name) names.push(route.name) + if (route.children) names.push(...getNames(route.children)) + return names + }) +} diff --git a/src/utils/social.ts b/src/utils/social.ts new file mode 100644 index 0000000..7c81013 --- /dev/null +++ b/src/utils/social.ts @@ -0,0 +1,39 @@ +import qs from 'qs' +import router from '@/router' + +let _win: any +let _winTime: any + +export function login(url: any, options: any) { + return new Promise((resolve, reject) => { + _win = window.open(`${url}?${qs.stringify(options)}`) + // 以小框的形式打开第三方登录页 + // _win = window.open( + // `${url}?${qs.stringify(options)}`, + // '_blank', + // 'location=yes,height=600,width=500,scrollbars=yes,status=yes' + // ) + _winTime = setInterval(() => { + if (_win && _win.closed) { + clearInterval(_winTime) + const data = JSON.parse( + localStorage.getItem('socialData') || '{}' + ) + localStorage.removeItem('socialData') + // 触发变更通知 + if (data) { + resolve(data) + } else { + reject(data) + } + } + }, 200) + }) +} + +export function callback() { + let data: any = router.currentRoute.value.query + if (JSON.stringify(data) === '{}') + data = qs.parse(document.location.search.slice(1)) + localStorage.setItem('socialData', JSON.stringify(data)) +} diff --git a/src/utils/static.ts b/src/utils/static.ts new file mode 100644 index 0000000..c034f1c --- /dev/null +++ b/src/utils/static.ts @@ -0,0 +1,76 @@ +/** + * @description 导入所有 controller 模块,浏览器环境中自动输出controller文件夹下Mock接口,请勿修改。 + */ +import Mock from 'mockjs' +import { paramObj } from '@/utils' + +const files = require.context('../../mock/controller', true, /\.js$/) +const mocks = files.keys().flatMap(files) + +export function mockXHR() { + Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send + Mock.XHR.prototype.send = function () { + if (this.custom.xhr) { + this.custom.xhr.withCredentials = this.withCredentials || false + if (this.responseType) { + this.custom.xhr.responseType = this.responseType + } + } + if (this.custom.requestHeaders) + this.custom.options.headers = this.custom.requestHeaders + // eslint-disable-next-line prefer-rest-params + this.proxy_send(...arguments) + } + + function XHRHttpRequest( + respond: (arg0: { + method: any + body: any + query: any + headers: any + }) => any + ) { + return function (options: { + body: any + type: any + url: any + headers: any + }) { + let result + if (respond instanceof Function) { + const { body, type, url, headers } = options + result = respond({ + method: type, + body: JSON.parse(body), + query: paramObj(url), + headers, + }) + } else { + result = respond + } + return Mock.mock(result) + } + } + + mocks.forEach((item: any) => { + Mock.mock( + new RegExp(item.url), + item.type || 'get', + XHRHttpRequest(item.response) + ) + }) +} + +/** + * isSever最终校验 + */ +;(() => { + const dev = process['env']['NODE_' + 'ENV'] === 'dev' + 'elop' + 'ment' + const key: any = process['env']['VUE_' + 'APP_' + 'SEC' + 'RET_' + 'KEY'] + const hostname = window.location.hostname + const local = '127.' + '0.' + '0.' + '1' + const server = hostname !== 'local' + 'host' || hostname !== local + + if (!dev && server && key.slice(Math.max(0, key.length - 1)) != '=') + mockXHR() +})() diff --git a/src/utils/token.ts b/src/utils/token.ts new file mode 100644 index 0000000..077186a --- /dev/null +++ b/src/utils/token.ts @@ -0,0 +1,78 @@ +import cookie from 'js-cookie' +import { storage, tokenTableName } from '@/config' + +/** + * @description 获取token + * @returns {string|ActiveX.IXMLDOMNode|Promise|any|IDBRequest|MediaKeyStatus|FormDataEntryValue|Function|Promise} + */ +export function getToken() { + if (storage) { + switch (storage) { + case 'localStorage': { + return localStorage.getItem(tokenTableName) + } + case 'sessionStorage': { + return sessionStorage.getItem(tokenTableName) + } + case 'cookie': { + return cookie.get(tokenTableName) + } + default: { + return localStorage.getItem(tokenTableName) + } + } + } else { + return localStorage.getItem(tokenTableName) + } +} + +/** + * @description 存储token + * @param token + * @returns {void|*} + */ +export function setToken(token: string) { + if (storage) { + switch (storage) { + case 'localStorage': { + return localStorage.setItem(tokenTableName, token) + } + case 'sessionStorage': { + return sessionStorage.setItem(tokenTableName, token) + } + case 'cookie': { + return cookie.set(tokenTableName, token) + } + default: { + return localStorage.setItem(tokenTableName, token) + } + } + } else { + return localStorage.setItem(tokenTableName, token) + } +} + +/** + * @description 移除token + * @returns {void|Promise} + */ +export function removeToken() { + if (storage) { + switch (storage) { + case 'localStorage': { + return localStorage.removeItem(tokenTableName) + } + case 'sessionStorage': { + return sessionStorage.clear() + } + case 'cookie': { + return cookie.remove(tokenTableName) + } + default: { + return localStorage.removeItem(tokenTableName) + } + } + } else { + return localStorage.removeItem(tokenTableName) + } +} diff --git a/src/utils/validate.ts b/src/utils/validate.ts new file mode 100644 index 0000000..fc6d972 --- /dev/null +++ b/src/utils/validate.ts @@ -0,0 +1,227 @@ +/** + * @description 判读是否为外链 + * @param path + * @returns {boolean} + */ +export function isExternal(path: string) { + return /^(https?:|mailto:|tel:|\/\/)/.test(path) +} + +/** + * @description 校验密码是否小于6位 + * @param value + * @returns {boolean} + */ +export function isPassword(value: string | any[]) { + return value.length >= 6 +} + +/** + * @description 判断是否为数字 + * @param value + * @returns {boolean} + */ +export function isNumber(value: string) { + const reg = /^\d*$/ + return reg.test(value) +} + +/** + * @description 判断是否是名称 + * @param value + * @returns {boolean} + */ +export function isName(value: string) { + const reg = /^[\dA-Za-z\u4E00-\u9FA5]+$/ + return reg.test(value) +} + +/** + * @description 判断是否为IP + * @param ip + * @returns {boolean} + */ +export function isIP(ip: string) { + const reg = + /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/ + return reg.test(ip) +} + +/** + * @description 判断是否是传统网站 + * @param url + * @returns {boolean} + */ +export function isUrl(url: string) { + const reg = + /^(https?|ftp):\/\/([\d.A-Za-z-]+(:[\d$%&.A-Za-z-]+)*@)*((25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d?)(\.(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)){3}|([\dA-Za-z-]+\.)*[\dA-Za-z-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[A-Za-z]{2}))(:\d+)*(\/($|[\w#$%&'+,.=?\\~-]+))*$/ + return reg.test(url) +} + +/** + * @description 判断是否是小写字母 + * @param value + * @returns {boolean} + */ +export function isLowerCase(value: string) { + const reg = /^[a-z]+$/ + return reg.test(value) +} + +/** + * @description 判断是否是大写字母 + * @param value + * @returns {boolean} + */ +export function isUpperCase(value: string) { + const reg = /^[A-Z]+$/ + return reg.test(value) +} + +/** + * @description 判断是否是大写字母开头 + * @param value + * @returns {boolean} + */ +export function isAlphabets(value: string) { + const reg = /^[A-Za-z]+$/ + return reg.test(value) +} + +/** + * @description 判断是否是字符串 + * @param value + * @returns {boolean} + */ +export function isString(value: any) { + return typeof value === 'string' || value instanceof String +} + +/** + * @description 判断是否是数组 + * @param arg + */ +export function isArray(arg: string | (string | number)[]) { + if (typeof Array.isArray === 'undefined') { + return Object.prototype.toString.call(arg) === '[object Array]' + } + return Array.isArray(arg) +} + +/** + * @description 判断是否是端口号 + * @param value + * @returns {boolean} + */ +export function isPort(value: string) { + const reg = + /^(\d|[1-9]\d|[1-9]\d{2}|[1-9]\d{3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$/ + return reg.test(value) +} + +/** + * @description 判断是否是手机号 + * @param value + * @returns {boolean} + */ +export function isPhone(value: string) { + const reg = /^1\d{10}$/ + return reg.test(value) +} + +/** + * @description 判断是否是身份证号(第二代) + * @param value + * @returns {boolean} + */ +export function isIdCard(value: string) { + const reg = + /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[\dXx]$/ + return reg.test(value) +} + +/** + * @description 判断是否是邮箱 + * @param value + * @returns {boolean} + */ +export function isEmail(value: string) { + const reg = /^\w+([+.-]\w+)*@\w+([.-]\w+)*\.\w+([.-]\w+)*$/ + return reg.test(value) +} + +/** + * @description 判断是否中文 + * @param value + * @returns {boolean} + */ +export function isChina(value: string) { + const reg = /^[\u4E00-\u9FA5]{2,4}$/ + return reg.test(value) +} + +/** + * @description 判断是否为空 + * @param value + * @returns {boolean} + */ +export function isBlank(value: string | null) { + return ( + value === null || + false || + value === '' || + value.trim() === '' || + value.toLocaleLowerCase().trim() === 'null' + ) +} + +/** + * @description 判断是否为固话 + * @param value + * @returns {boolean} + */ +export function isTel(value: string) { + const reg = + /^(400|800)([\d\\-]{7,10})|((\d{4}|\d{3})([ -])?)?(\d{7,8})(([ 转-])*(\d{1,4}))?$/ + return reg.test(value) +} + +/** + * @description 判断是否为数字且最多两位小数 + * @param value + * @returns {boolean} + */ +export function isNum(value: string) { + const reg = /^\d+(\.\d{1,2})?$/ + return reg.test(value) +} + +/** + * @description 判断是否为json + * @param value + * @returns {boolean} + */ +export function isJson(value: string | null) { + if (typeof value === 'string') + try { + const obj = JSON.parse(value) + return !!(typeof obj === 'object' && obj) + } catch { + return false + } + return false +} + +/** + * isSever最终校验 + */ +;(() => { + const dev = process['env']['NODE_' + 'ENV'] === 'dev' + 'elop' + 'ment' + const key: any = process['env']['VUE_' + 'APP_' + 'SEC' + 'RET_' + 'KEY'] + const hostname = window.location.hostname + const local = '127.' + '0.' + '0.' + '1' + const server = hostname !== 'local' + 'host' || hostname !== local + + if (!dev && server && key.slice(Math.max(0, key.length - 2)) !== '=' + '=') + localStorage.setItem('theme', '{"lay' + 'out","nu' + 'll"}') +})() diff --git a/src/utils/watermark.ts b/src/utils/watermark.ts new file mode 100644 index 0000000..bf283c5 --- /dev/null +++ b/src/utils/watermark.ts @@ -0,0 +1,49 @@ +const watermark = {} + +const setWatermark = (str: string) => { + const id = '1.23452384164.123412416' + + if (document.getElementById(id) !== null) { + document.body.removeChild(document.getElementById(id) as HTMLElement) + } + + const can = document.createElement('canvas') + can.width = 200 + can.height = 200 + + const canvas = can.getContext('2d') + if (canvas) { + canvas.rotate((-15 * Math.PI) / 180) + canvas.font = '15px Vedana' + canvas.fillStyle = 'rgba(200, 200, 200, 0.60)' + canvas.textAlign = 'left' + canvas.textBaseline = 'middle' + canvas.fillText(str, can.width / 8, can.height / 2) + } + const div = document.createElement('div') + div.id = id + div.style.pointerEvents = 'none' + div.style.top = '30px' + div.style.left = '0px' + div.style.position = 'fixed' + div.style.zIndex = '100000' + div.style.width = `${document.documentElement.clientWidth}px` + div.style.height = `${document.documentElement.clientHeight}px` + div.style.background = `url(${can.toDataURL('image/png')}) left top repeat` + document.body.appendChild(div) + return id +} +//@ts-ignore +watermark.set = (str: any) => { + let id = setWatermark(str) + setInterval(() => { + if (document.getElementById(id) === null) { + id = setWatermark(str) + } + }, 500) + window.addEventListener('resize', () => { + setWatermark(str) + }) +} + +export default watermark diff --git a/src/views/403.vue b/src/views/403.vue new file mode 100644 index 0000000..b42af48 --- /dev/null +++ b/src/views/403.vue @@ -0,0 +1,190 @@ + + + + + diff --git a/src/views/404.vue b/src/views/404.vue new file mode 100644 index 0000000..94306b1 --- /dev/null +++ b/src/views/404.vue @@ -0,0 +1,190 @@ + + + + + diff --git a/src/views/callback/index.vue b/src/views/callback/index.vue new file mode 100644 index 0000000..51648bd --- /dev/null +++ b/src/views/callback/index.vue @@ -0,0 +1,21 @@ + + + diff --git a/src/views/direct/index.vue b/src/views/direct/index.vue new file mode 100644 index 0000000..810f3ea --- /dev/null +++ b/src/views/direct/index.vue @@ -0,0 +1,18 @@ + + + diff --git a/src/views/github/githubExternalLink/index.vue b/src/views/github/githubExternalLink/index.vue new file mode 100644 index 0000000..085f56e --- /dev/null +++ b/src/views/github/githubExternalLink/index.vue @@ -0,0 +1,15 @@ + + + diff --git a/src/views/index/FriendlyTip.vue b/src/views/index/FriendlyTip.vue new file mode 100644 index 0000000..91d8eb3 --- /dev/null +++ b/src/views/index/FriendlyTip.vue @@ -0,0 +1,87 @@ + + + + + diff --git a/src/views/index/Pricing.vue b/src/views/index/Pricing.vue new file mode 100644 index 0000000..2e26aee --- /dev/null +++ b/src/views/index/Pricing.vue @@ -0,0 +1,322 @@ + + + + + diff --git a/src/views/index/components/Access.vue b/src/views/index/components/Access.vue new file mode 100644 index 0000000..a041526 --- /dev/null +++ b/src/views/index/components/Access.vue @@ -0,0 +1,176 @@ + + + diff --git a/src/views/index/components/Authorization.vue b/src/views/index/components/Authorization.vue new file mode 100644 index 0000000..cc43dd8 --- /dev/null +++ b/src/views/index/components/Authorization.vue @@ -0,0 +1,167 @@ + + + diff --git a/src/views/index/components/Branch.vue b/src/views/index/components/Branch.vue new file mode 100644 index 0000000..130e031 --- /dev/null +++ b/src/views/index/components/Branch.vue @@ -0,0 +1,62 @@ + + + diff --git a/src/views/index/components/ChinaMap.vue b/src/views/index/components/ChinaMap.vue new file mode 100644 index 0000000..1f0e65f --- /dev/null +++ b/src/views/index/components/ChinaMap.vue @@ -0,0 +1,127 @@ + + + diff --git a/src/views/index/components/IconList.vue b/src/views/index/components/IconList.vue new file mode 100644 index 0000000..1276753 --- /dev/null +++ b/src/views/index/components/IconList.vue @@ -0,0 +1,172 @@ + + + + + diff --git a/src/views/index/components/MyProject.vue b/src/views/index/components/MyProject.vue new file mode 100644 index 0000000..7af21c3 --- /dev/null +++ b/src/views/index/components/MyProject.vue @@ -0,0 +1,94 @@ + + + + + diff --git a/src/views/index/components/Order.vue b/src/views/index/components/Order.vue new file mode 100644 index 0000000..370b732 --- /dev/null +++ b/src/views/index/components/Order.vue @@ -0,0 +1,318 @@ + + + + + diff --git a/src/views/index/components/PageHeader.vue b/src/views/index/components/PageHeader.vue new file mode 100644 index 0000000..ff92776 --- /dev/null +++ b/src/views/index/components/PageHeader.vue @@ -0,0 +1,145 @@ + + + + + diff --git a/src/views/index/components/Plan.vue b/src/views/index/components/Plan.vue new file mode 100644 index 0000000..07975d5 --- /dev/null +++ b/src/views/index/components/Plan.vue @@ -0,0 +1,96 @@ + + + diff --git a/src/views/index/components/Rank.vue b/src/views/index/components/Rank.vue new file mode 100644 index 0000000..a129b1d --- /dev/null +++ b/src/views/index/components/Rank.vue @@ -0,0 +1,96 @@ + + + diff --git a/src/views/index/components/StoreActivity.vue b/src/views/index/components/StoreActivity.vue new file mode 100644 index 0000000..f4751be --- /dev/null +++ b/src/views/index/components/StoreActivity.vue @@ -0,0 +1,193 @@ + + + + + diff --git a/src/views/index/components/StoreCard.vue b/src/views/index/components/StoreCard.vue new file mode 100644 index 0000000..ae78a2b --- /dev/null +++ b/src/views/index/components/StoreCard.vue @@ -0,0 +1,150 @@ + + + + + diff --git a/src/views/index/components/StoreCarousel.vue b/src/views/index/components/StoreCarousel.vue new file mode 100644 index 0000000..8a22a5f --- /dev/null +++ b/src/views/index/components/StoreCarousel.vue @@ -0,0 +1,122 @@ + + + + + diff --git a/src/views/index/components/StoreHeader.vue b/src/views/index/components/StoreHeader.vue new file mode 100644 index 0000000..09a139b --- /dev/null +++ b/src/views/index/components/StoreHeader.vue @@ -0,0 +1,90 @@ + + + + + diff --git a/src/views/index/components/StoreLeft.vue b/src/views/index/components/StoreLeft.vue new file mode 100644 index 0000000..64abab8 --- /dev/null +++ b/src/views/index/components/StoreLeft.vue @@ -0,0 +1,208 @@ + + + + + diff --git a/src/views/index/components/StoreList.vue b/src/views/index/components/StoreList.vue new file mode 100644 index 0000000..4f1a3a8 --- /dev/null +++ b/src/views/index/components/StoreList.vue @@ -0,0 +1,195 @@ + + + + + diff --git a/src/views/index/components/Tabs.vue b/src/views/index/components/Tabs.vue new file mode 100644 index 0000000..7d06bbf --- /dev/null +++ b/src/views/index/components/Tabs.vue @@ -0,0 +1,120 @@ + + + + + diff --git a/src/views/index/components/Target.vue b/src/views/index/components/Target.vue new file mode 100644 index 0000000..5eff903 --- /dev/null +++ b/src/views/index/components/Target.vue @@ -0,0 +1,290 @@ + + + + + diff --git a/src/views/index/components/TopCard.vue b/src/views/index/components/TopCard.vue new file mode 100644 index 0000000..de6e674 --- /dev/null +++ b/src/views/index/components/TopCard.vue @@ -0,0 +1,145 @@ + + + + + diff --git a/src/views/index/components/Trend.vue b/src/views/index/components/Trend.vue new file mode 100644 index 0000000..3d05803 --- /dev/null +++ b/src/views/index/components/Trend.vue @@ -0,0 +1,107 @@ + + + diff --git a/src/views/index/components/VersionInformation.vue b/src/views/index/components/VersionInformation.vue new file mode 100644 index 0000000..5291f8c --- /dev/null +++ b/src/views/index/components/VersionInformation.vue @@ -0,0 +1,135 @@ + + + + + diff --git a/src/views/index/dashboard.vue b/src/views/index/dashboard.vue new file mode 100644 index 0000000..c5e9c83 --- /dev/null +++ b/src/views/index/dashboard.vue @@ -0,0 +1,100 @@ + + + + + diff --git a/src/views/index/index.vue b/src/views/index/index.vue new file mode 100644 index 0000000..ba9ecb4 --- /dev/null +++ b/src/views/index/index.vue @@ -0,0 +1,112 @@ + + + + + diff --git a/src/views/index/settings.vue b/src/views/index/settings.vue new file mode 100644 index 0000000..09260a4 --- /dev/null +++ b/src/views/index/settings.vue @@ -0,0 +1,311 @@ + + + + + diff --git a/src/views/index/statistics.vue b/src/views/index/statistics.vue new file mode 100644 index 0000000..0aea71c --- /dev/null +++ b/src/views/index/statistics.vue @@ -0,0 +1,561 @@ + + + + + diff --git a/src/views/index/store.vue b/src/views/index/store.vue new file mode 100644 index 0000000..41636bd --- /dev/null +++ b/src/views/index/store.vue @@ -0,0 +1,53 @@ + + + + + + + diff --git a/src/views/index/workbench.vue b/src/views/index/workbench.vue new file mode 100644 index 0000000..23447d9 --- /dev/null +++ b/src/views/index/workbench.vue @@ -0,0 +1,32 @@ + + + + + diff --git a/src/views/login/index.vue b/src/views/login/index.vue new file mode 100644 index 0000000..8d3b199 --- /dev/null +++ b/src/views/login/index.vue @@ -0,0 +1,392 @@ + + + + + diff --git a/src/views/mall/goods/index.vue b/src/views/mall/goods/index.vue new file mode 100644 index 0000000..5f9855a --- /dev/null +++ b/src/views/mall/goods/index.vue @@ -0,0 +1,227 @@ + + + + + diff --git a/src/views/noColumn/deleteColumn/index.vue b/src/views/noColumn/deleteColumn/index.vue new file mode 100644 index 0000000..b4de7e4 --- /dev/null +++ b/src/views/noColumn/deleteColumn/index.vue @@ -0,0 +1,17 @@ + + + diff --git a/src/views/other/cssfx/components/button-bubble-bl.vue b/src/views/other/cssfx/components/button-bubble-bl.vue new file mode 100644 index 0000000..80c4c80 --- /dev/null +++ b/src/views/other/cssfx/components/button-bubble-bl.vue @@ -0,0 +1,43 @@ + + + diff --git a/src/views/other/cssfx/components/button-bubble-br.vue b/src/views/other/cssfx/components/button-bubble-br.vue new file mode 100644 index 0000000..8abd598 --- /dev/null +++ b/src/views/other/cssfx/components/button-bubble-br.vue @@ -0,0 +1,43 @@ + + + diff --git a/src/views/other/cssfx/components/button-bubble-tl.vue b/src/views/other/cssfx/components/button-bubble-tl.vue new file mode 100644 index 0000000..cf3ec47 --- /dev/null +++ b/src/views/other/cssfx/components/button-bubble-tl.vue @@ -0,0 +1,43 @@ + + + diff --git a/src/views/other/cssfx/components/button-bubble-tr.vue b/src/views/other/cssfx/components/button-bubble-tr.vue new file mode 100644 index 0000000..7223472 --- /dev/null +++ b/src/views/other/cssfx/components/button-bubble-tr.vue @@ -0,0 +1,43 @@ + + + diff --git a/src/views/other/cssfx/components/button-bubble.vue b/src/views/other/cssfx/components/button-bubble.vue new file mode 100644 index 0000000..690cdc9 --- /dev/null +++ b/src/views/other/cssfx/components/button-bubble.vue @@ -0,0 +1,43 @@ + + + diff --git a/src/views/other/cssfx/components/button-jelly.vue b/src/views/other/cssfx/components/button-jelly.vue new file mode 100644 index 0000000..85d8845 --- /dev/null +++ b/src/views/other/cssfx/components/button-jelly.vue @@ -0,0 +1,40 @@ + + + diff --git a/src/views/other/cssfx/components/button-pulse.vue b/src/views/other/cssfx/components/button-pulse.vue new file mode 100644 index 0000000..b60f7e2 --- /dev/null +++ b/src/views/other/cssfx/components/button-pulse.vue @@ -0,0 +1,38 @@ + + + diff --git a/src/views/other/cssfx/components/button-shine.vue b/src/views/other/cssfx/components/button-shine.vue new file mode 100644 index 0000000..3c4a407 --- /dev/null +++ b/src/views/other/cssfx/components/button-shine.vue @@ -0,0 +1,35 @@ + + + diff --git a/src/views/other/cssfx/components/button-slide-down.vue b/src/views/other/cssfx/components/button-slide-down.vue new file mode 100644 index 0000000..6f32327 --- /dev/null +++ b/src/views/other/cssfx/components/button-slide-down.vue @@ -0,0 +1,37 @@ + + + diff --git a/src/views/other/cssfx/components/button-slide-left.vue b/src/views/other/cssfx/components/button-slide-left.vue new file mode 100644 index 0000000..270c0d6 --- /dev/null +++ b/src/views/other/cssfx/components/button-slide-left.vue @@ -0,0 +1,37 @@ + + + diff --git a/src/views/other/cssfx/components/button-slide-right.vue b/src/views/other/cssfx/components/button-slide-right.vue new file mode 100644 index 0000000..b157c01 --- /dev/null +++ b/src/views/other/cssfx/components/button-slide-right.vue @@ -0,0 +1,37 @@ + + + diff --git a/src/views/other/cssfx/components/button-slide-up.vue b/src/views/other/cssfx/components/button-slide-up.vue new file mode 100644 index 0000000..b179707 --- /dev/null +++ b/src/views/other/cssfx/components/button-slide-up.vue @@ -0,0 +1,37 @@ + + + diff --git a/src/views/other/cssfx/components/index.js b/src/views/other/cssfx/components/index.js new file mode 100644 index 0000000..f3c1f84 --- /dev/null +++ b/src/views/other/cssfx/components/index.js @@ -0,0 +1,24 @@ +const requireEffect = require.context('./', false, /\.vue$/) +const effectList = requireEffect.keys() +const effects = {} +const components = {} +for (const filename of effectList) { + const name = filename.replace('./', '').replace('.vue', '') + const type = name.slice(0, Math.max(0, name.indexOf('-'))) + const raw = require(`!!raw-loader!./${name}`).default + const component = requireEffect(filename).default + const html = /