[
  {
    "path": ".browserslistrc",
    "content": "> 1%\nlast 2 versions\nnot ie <= 10\n"
  },
  {
    "path": ".editorconfig",
    "content": "[*]\ncharset=utf-8\nend_of_line=lf\ninsert_final_newline=false\nindent_style=space\nindent_size=2\n\n[{*.ng,*.sht,*.html,*.shtm,*.shtml,*.htm}]\nindent_style=space\nindent_size=2\n\n[{*.jhm,*.xslt,*.xul,*.rng,*.xsl,*.xsd,*.ant,*.tld,*.fxml,*.jrxml,*.xml,*.jnlp,*.wsdl}]\nindent_style=space\nindent_size=2\n\n[{.babelrc,.stylelintrc,jest.config,.eslintrc,.prettierrc,*.json,*.jsb3,*.jsb2,*.bowerrc}]\nindent_style=space\nindent_size=2\n\n[*.svg]\nindent_style=space\nindent_size=2\n\n[*.js.map]\nindent_style=space\nindent_size=2\n\n[*.less]\nindent_style=space\nindent_size=2\n\n[*.vue]\nindent_style=space\nindent_size=2\n\n[{.analysis_options,*.yml,*.yaml}]\nindent_style=space\nindent_size=2\n\n"
  },
  {
    "path": ".eslintrc.js",
    "content": "module.exports = {\n  root: true,\n  env: {\n    node: true\n  },\n  'extends': [\n    'plugin:vue/strongly-recommended',\n    '@vue/standard'\n  ],\n  rules: {\n    'no-console': 'off',\n    'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',\n    'generator-star-spacing': 'off',\n    'no-mixed-operators': 0,\n    'vue/max-attributes-per-line': [\n      2,\n      {\n        'singleline': 5,\n        'multiline': {\n          'max': 1,\n          'allowFirstLine': false\n        }\n      }\n    ],\n    'vue/attribute-hyphenation': 0,\n    'vue/html-self-closing': 0,\n    'vue/component-name-in-template-casing': 0,\n    'vue/html-closing-bracket-spacing': 0,\n    'vue/singleline-html-element-content-newline': 0,\n    'vue/no-unused-components': 0,\n    'vue/multiline-html-element-content-newline': 0,\n    'vue/no-use-v-if-with-v-for': 0,\n    'vue/html-closing-bracket-newline': 0,\n    'vue/no-parsing-error': 0,\n    'no-tabs': 0,\n    'quotes': [\n      2,\n      'single',\n      {\n        'avoidEscape': true,\n        'allowTemplateLiterals': true\n      }\n    ],\n    'semi': [\n      2,\n      'never',\n      {\n        'beforeStatementContinuationChars': 'never'\n      }\n    ],\n    'no-delete-var': 2,\n    'prefer-const': [\n      2,\n      {\n        'ignoreReadBeforeAssign': false\n      }\n    ],\n    'template-curly-spacing': 'off',\n    'indent': 'off'\n  },\n  parserOptions: {\n    parser: 'babel-eslint'\n  },\n  overrides: [\n    {\n      files: [\n        '**/__tests__/*.{j,t}s?(x)',\n        '**/tests/unit/**/*.spec.{j,t}s?(x)'\n      ],\n      env: {\n        jest: true\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": ".eslintrc.json",
    "content": "{\n  \"rules\": {\n    \"space-before-function-paren\": 0\n  }\n}\n"
  },
  {
    "path": ".gitattributes",
    "content": "public/* linguist-vendored\n\n# Automatically normalize line endings (to LF) for all text-based files.\n* text=auto eol=lf\n\n# Declare files that will always have CRLF line endings on checkout.\n*.{cmd,[cC][mM][dD]} text eol=crlf\n*.{bat,[bB][aA][tT]} text eol=crlf\n\n# Denote all files that are truly binary and should not be modified.\n*.{ico,png,jpg,jpeg,gif,webp,svg,woff,woff2} binary"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve（Bug 反馈）\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Describe the bug （描述 Bug）**\n\nA clear and concise description of what the bug is.\n\n\n\n**To Reproduce （重现步骤）**\nSteps to reproduce the behavior:\n\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n4. See error\n\n\n\n**Expected behavior（你期待的是什么?）**\nA clear and concise description of what you expected to happen.\n\n\n\n**Screenshots（截图）**\nIf applicable, add screenshots to help explain your problem.\n\n\n\n**Desktop (please complete the following information):**\n\n - OS: [e.g. iOS]\n - Browser [e.g. chrome, safari]\n - Version [e.g. 22]\n\n\n\n**Smartphone (please complete the following information):**\n\n - Device: [e.g. iPhone6]\n - OS: [e.g. iOS8.1]\n - Browser [e.g. stock browser, safari]\n - Version [e.g. 22]\n\n\n\n**Additional context（附加信息）**\nAdd any other context about the problem here."
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Is your feature request related to a problem? Please describe.**\nA clear and concise description of what the problem is. Ex. I'm always frustrated when [...]\n\n**Describe the solution you'd like**\nA clear and concise description of what you want to happen.\n\n**Describe alternatives you've considered**\nA clear and concise description of any alternative solutions or features you've considered.\n\n**Additional context**\nAdd any other context or screenshots about the feature request here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/need-help-issue.md",
    "content": "---\nname: Need help issue\nabout: Question for use（问题求助）\ntitle: ''\nlabels: question\nassignees: ''\n\n---\n\n**Question （问题描述）**\nHow to use component `s-table` paging\n\n**Describe the solution you'd like （你期待的是什么？）**\nA clear and concise description of what you want to happen.\n\n**Additional context（附加信息）**\nAdd any other context or screenshots about the feature request here.\n"
  },
  {
    "path": ".github/pull_request_template.md",
    "content": "First of all, thank you for your contribution! 😄\n\nPull request will be merged after one of collaborators approve.\nPlease makes sure that these form are filled before submitting your pull request, thank you!\n\n\n### 这个变动的性质是\n\n- [ ] 新特性提交\n- [ ] 日常 bug 修复\n- [ ] 文档改进\n- [ ] 组件样式改进\n- [ ] 重构\n- [ ] 代码风格优化\n- [ ] 分支合并\n- [ ] 其他改动（是关于什么的改动？）\n\n### 需求背景\n\n> 1. 描述相关需求的来源。\n> 2. 要解决的问题。\n> 3. 相关的 issue 讨论链接。\n\n### 实现方案和 API（非新功能可选）\n\n> 1. 基本的解决思路和其他可选方案。\n> 2. 列出最终的 API 实现和用法。\n> 3. 涉及UI/交互变动需要有截图或 GIF。\n\n### 对用户的影响和可能的风险（非新功能可选）\n\n> 1. 这个改动对用户端是否有影响？影响的方面有哪些？\n> 2. 是否有可能隐含的 break change 和其他风险？\n\n### Changelog 描述（非新功能可选）\n\n> 1. 英文描述\n> 2. 中文描述（可选）\n\n### 请求合并前的自查清单\n\n- [ ] 文档已补充或无须补充\n- [ ] 代码演示已提供或无须提供\n- [ ] Changelog 已提供或无须提供\n\n### 后续计划（非新功能可选）\n\n> 如果这个提交后面还有相关的其他提交和跟进信息，可以写在这里。"
  },
  {
    "path": ".github/workflows/cloudflare.yml",
    "content": "name: Build and Deploy to Cloudflare\non:\n  push:\n    branches: [ master ]\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    name: Build Application\n    permissions:\n      contents: read\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v5\n        with:\n          fetch-depth: 0\n\n      - name: Setup Node\n        uses: actions/setup-node@v4\n        with:\n          node-version: 20\n\n      - name: Install dependencies\n        run: npm install --force\n\n      - name: Build application\n        run: npm run build:preview\n\n      - name: Upload build artifacts\n        uses: actions/upload-artifact@v4\n        with:\n          name: build-files\n          path: dist/\n          retention-days: 1\n\n  deploy:\n    runs-on: ubuntu-latest\n    name: Deploy to Cloudflare\n    needs: build\n    permissions:\n      contents: read\n      deployments: write\n    steps:\n      - name: Checkout (for config files)\n        uses: actions/checkout@v5\n        with:\n          sparse-checkout: |\n            wrangler.jsonc\n          sparse-checkout-cone-mode: false\n\n      - name: Download build artifacts\n        uses: actions/download-artifact@v4\n        with:\n          name: build-files\n          path: dist/\n\n      - name: Deploy (Workers + Static Assets)\n        uses: cloudflare/wrangler-action@v3.14.1\n        with:\n          apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} \n          accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}\n          command: deploy --config wrangler.jsonc\n          gitHubToken: ${{ secrets.GITHUB_TOKEN }}\n"
  },
  {
    "path": ".gitignore",
    "content": ".DS_Store\nnode_modules\n/dist\n\n# local env files\n.env.local\n.env.*.local\n\n# Log files\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# Editor directories and files\n.idea\n.vscode\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw*\npackage-lock.json\n"
  },
  {
    "path": ".husky/.gitignore",
    "content": "_\n"
  },
  {
    "path": ".husky/commit-msg",
    "content": "#!/bin/sh\n. \"$(dirname \"$0\")/_/husky.sh\"\n\nnpx --no-install commitlint --edit \"$1\""
  },
  {
    "path": ".husky/pre-commit",
    "content": "#!/bin/sh\n. \"$(dirname \"$0\")/_/husky.sh\"\n\nnpm run lint"
  },
  {
    "path": ".lintstagedrc.json",
    "content": "{\n  \"*.js\": \"eslint --fix\",\n  \"*.{css,less}\": \"stylelint --fix\"\n}"
  },
  {
    "path": ".prettierrc",
    "content": "{\n  \"printWidth\": 120,\n  \"semi\": false,\n  \"singleQuote\": true,\n  \"prettier.spaceBeforeFunctionParen\": true\n}\n"
  },
  {
    "path": ".stylelintrc.js",
    "content": "module.exports = {\n    processors: [],\n    plugins: ['stylelint-order'],\n    extends: [\n        'stylelint-config-standard',\n        'stylelint-config-css-modules'\n    ],\n    rules: {\n        'selector-class-pattern': null,\n        'string-quotes': 'single', // 单引号\n        'at-rule-empty-line-before': null,\n        'at-rule-no-unknown': null,\n        'at-rule-name-case': 'lower', // 指定@规则名的大小写\n        'length-zero-no-unit': true, // 禁止零长度的单位（可自动修复）\n        'shorthand-property-no-redundant-values': true, // 简写属性\n        'number-leading-zero': 'never', // 小数不带0\n        'declaration-block-no-duplicate-properties': null, // 禁止声明快重复属性\n        'no-descending-specificity': null, // 禁止在具有较高优先级的选择器后出现被其覆盖的较低优先级的选择器。\n        'selector-max-id': 3, // 限制一个选择器中 ID 选择器的数量\n        'max-nesting-depth': 4,\n        'indentation': [2, { // 指定缩进  warning 提醒\n            'severity': 'warning'\n        }],\n        'order/properties-order': [ // 规则顺序\n            'position',\n            'top',\n            'right',\n            'bottom',\n            'left',\n            'z-index',\n            'display',\n            'float',\n            'width',\n            'height',\n            'max-width',\n            'max-height',\n            'min-width',\n            'min-height',\n            'padding',\n            'padding-top',\n            'padding-right',\n            'padding-bottom',\n            'padding-left',\n            'margin',\n            'margin-top',\n            'margin-right',\n            'margin-bottom',\n            'margin-left',\n            'margin-collapse',\n            'margin-top-collapse',\n            'margin-right-collapse',\n            'margin-bottom-collapse',\n            'margin-left-collapse',\n            'overflow',\n            'overflow-x',\n            'overflow-y',\n            'clip',\n            'clear',\n            'font',\n            'font-family',\n            'font-size',\n            'font-smoothing',\n            'osx-font-smoothing',\n            'font-style',\n            'font-weight',\n            'line-height',\n            'letter-spacing',\n            'word-spacing',\n            'color',\n            'text-align',\n            'text-decoration',\n            'text-indent',\n            'text-overflow',\n            'text-rendering',\n            'text-size-adjust',\n            'text-shadow',\n            'text-transform',\n            'word-break',\n            'word-wrap',\n            'white-space',\n            'vertical-align',\n            'list-style',\n            'list-style-type',\n            'list-style-position',\n            'list-style-image',\n            'pointer-events',\n            'cursor',\n            'background',\n            'background-color',\n            'border',\n            'border-radius',\n            'content',\n            'outline',\n            'outline-offset',\n            'opacity',\n            'filter',\n            'visibility',\n            'size',\n            'transform'\n        ]\n    }\n}\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: node_js\nnode_js:\n  - 10.15.0\ncache: yarn\nscript:\n  - yarn\n  - yarn run lint --no-fix && yarn run build\n"
  },
  {
    "path": "Dockerfile",
    "content": "FROM nginx\n\nRUN rm /etc/nginx/conf.d/default.conf\n\nADD deploy/nginx.conf /etc/nginx/conf.d/default.conf\nCOPY dist/ /usr/share/nginx/html/\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2018 Anan Yang\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
  },
  {
    "path": "README.md",
    "content": "English | [简体中文](./README.zh-CN.md)\n\n<h1 align=\"center\">Ant Design Vue Pro for Vue 2</h1>\n<div align=\"center\">\nAn out-of-box UI solution for enterprise applications as a Vue boilerplate. based on  <a href=\"https://vuecomponent.github.io/ant-design-vue/docs/vue/introduce-cn/\" target=\"_blank\">Ant Design of Vue</a>\n</div>\n\n<div align=\"center\">\n  If you are looking for the Vue 3 version, please visit [Ant Design Vue Pro for Vue 3](https://store.antdv.com/items/admin-pro)\n</div>\n\n<div align=\"center\">\n\n[![License](https://img.shields.io/npm/l/package.json.svg?style=flat)](https://github.com/vueComponent/ant-design-vue-pro/blob/master/LICENSE)\n[![Release](https://img.shields.io/github/release/vueComponent/ant-design-vue-pro.svg?style=flat)](https://github.com/vueComponent/ant-design-vue-pro/releases/latest)\n[![Support Vue Version](https://img.shields.io/badge/Support-Vue2-green?style=flat)](https://github.com/vueComponent/ant-design-vue-pro/releases/latest)\n[![Travis branch](https://travis-ci.org/vueComponent/ant-design-vue-pro.svg?branch=master)](https://travis-ci.org/vueComponent/ant-design-vue-pro)\n\n</div>\n\n- Preview: https://preview.pro.antdv.com\n- Home Page: https://pro.antdv.com\n- Documentation: https://pro.antdv.com/docs/getting-started\n- ChangeLog: https://pro.antdv.com/docs/changelog\n- FAQ: https://pro.antdv.com/docs/faq\n- Vue3 ProLayout: https://github.com/vueComponent/pro-layout\n\n## Overview\n\n![dashboard](https://static-2.loacg.com/open/static/github/SP1.png)\n\n### Env and dependencies\n\n- node\n- yarn\n- webpack\n- eslint\n- @vue/cli\n- [ant-design-vue@1.x](https://github.com/vueComponent/ant-design-vue) - Ant Design Of Vue\n- [vue-cropper](https://github.com/xyxiao001/vue-cropper) - Picture edit\n- [@antv/g2](https://antv.alipay.com/zh-cn/index.html) - AntV G2\n- [Viser-vue](https://viserjs.github.io/docs.html#/viser/guide/installation) - Antv/G2 of Vue\n\n> Note: [Yarn](https://yarnpkg.com/) package management is recommended, the exact same version loaded with the demo site of this project (yarn.lock) . but you can also use npm\n\n### Project setup\n\n- Clone repo\n\n```bash\ngit clone https://github.com/vueComponent/ant-design-vue-pro.git\ncd ant-design-vue-pro\n```\n\n- Install dependencies\n\n```\nyarn install\n```\n\n- Compiles and hot-reloads for development\n\n```\nyarn run serve\n```\n\n- Compiles and minifies for production\n\n```\nyarn run build\n```\n\n- Lints and fixes files\n\n```\nyarn run lint\n```\n\n### Other\n\n- **IMPORTANT : Issue feedback !! when opening Issue read [Issue / PR Contributing](https://github.com/vueComponent/ant-design-vue-pro/issues/90)**\n\n- [Vue-cli3](https://cli.vuejs.org/guide/) used by the project.\n\n- Disable Eslint (not recommended): remove `eslintConfig` field in `package.json` and `vue.config.js` field `lintOnSave: false`\n\n- Load on Demand `/src/main.js` L14, in `import './core/lazy_use'`, `import './core/use''`. more [load-on-demand.md](./docs/load-on-demand.md)\n\n- Customize Theme: [Custom Theme Config (@kokoroli)](https://github.com/kokoroli/antd-awesome/blob/master/docs/Ant_Design_%E6%A0%B7%E5%BC%8F%E8%A6%86%E7%9B%96.md)\n\n- I18n: [locales (@musnow)](./src/locales/index.js)\n\n- Production env `mock` is disabled. use `src/mock/index.js`\n\n- pls use `release` version\n\n## Browsers support\n\nModern browsers and IE10.\n\n| [<img src=\"https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png\" alt=\"IE / Edge\" width=\"24px\" height=\"24px\" />](http://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src=\"https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png\" alt=\"Firefox\" width=\"24px\" height=\"24px\" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src=\"https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png\" alt=\"Chrome\" width=\"24px\" height=\"24px\" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src=\"https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png\" alt=\"Safari\" width=\"24px\" height=\"24px\" />](http://godban.github.io/browsers-support-badges/)</br>Safari | [<img src=\"https://raw.githubusercontent.com/alrra/browser-logos/master/src/opera/opera_48x48.png\" alt=\"Opera\" width=\"24px\" height=\"24px\" />](http://godban.github.io/browsers-support-badges/)</br>Opera |\n| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| IE10, Edge                                                                                                                                                                                                      | last 2 versions                                                                                                                                                                                                   | last 2 versions                                                                                                                                                                                               | last 2 versions                                                                                                                                                                                               | last 2 versions                                                                                                                                                                                           |\n\n## Contributors\n\nThis project exists thanks to all the people who contribute.\n<a href=\"https://github.com/vueComponent/ant-design-vue-pro/graphs/contributors\"><img src=\"https://opencollective.com/ant-design-pro-vue/contributors.svg?width=890&button=false\" /></a>\n"
  },
  {
    "path": "README.zh-CN.md",
    "content": "[English](./README.md) | 简体中文\n\n<h1 align=\"center\">Ant Design Vue Pro for Vue 2</h1>\n<div align=\"center\">\nAn out-of-box UI solution for enterprise applications as a Vue boilerplate. based on  <a href=\"https://vuecomponent.github.io/ant-design-vue/docs/vue/introduce-cn/\" target=\"_blank\">Ant Design of Vue</a>\n</div>\n\n<div align=\"center\">\n  如果需要 Vue 3 版本，请访问 [Ant Design Vue Pro for Vue 3](https://store.antdv.com/items/admin-pro)\n</div>\n\n<div align=\"center\">\n\n[![License](https://img.shields.io/npm/l/package.json.svg?style=flat)](https://github.com/vueComponent/ant-design-vue-pro/blob/master/LICENSE)\n[![Release](https://img.shields.io/github/release/vueComponent/ant-design-vue-pro.svg?style=flat)](https://github.com/vueComponent/ant-design-vue-pro/releases/latest)\n[![Support Vue Version](https://img.shields.io/badge/Support-Vue2-green?style=flat)](https://github.com/vueComponent/ant-design-vue-pro/releases/latest)\n[![Travis branch](https://travis-ci.org/vueComponent/ant-design-vue-pro.svg?branch=master)](https://travis-ci.org/vueComponent/ant-design-vue-pro)\n\n</div>\n\n- 预览: https://preview.pro.antdv.com\n- 首页: https://pro.antdv.com\n- 文档: https://pro.antdv.com/docs/getting-started\n- 更新日志: https://pro.antdv.com/docs/changelog\n- 常见问题: https://pro.antdv.com/docs/faq\n- Vue3 ProLayout: https://github.com/vueComponent/pro-layout\n\n## Overview\n\n基于 [Ant Design of Vue](https://vuecomponent.github.io/ant-design-vue/docs/vue/introduce-cn/) 实现的 [Ant Design Pro](https://pro.ant.design/)\n\n![dashboard](https://static-2.loacg.com/open/static/github/SP1.png)\n\n## 环境和依赖\n\n- node\n- yarn\n- webpack\n- eslint\n- @vue/cli\n- [ant-design-vue@1.x](https://github.com/vueComponent/ant-design-vue) - Ant Design Of Vue 实现\n- [vue-cropper](https://github.com/xyxiao001/vue-cropper) - 头像裁剪组件\n- [@antv/g2](https://antv.alipay.com/zh-cn/index.html) - Alipay AntV 数据可视化图表\n- [Viser-vue](https://viserjs.github.io/docs.html#/viser/guide/installation) - antv/g2 封装实现\n\n> 请注意，我们强烈建议本项目使用 [Yarn](https://yarnpkg.com/) 包管理工具，这样可以与本项目演示站所加载完全相同的依赖版本 (yarn.lock) 。由于我们没有对依赖进行强制的版本控制，采用非 yarn 包管理进行引入时，可能由于 Pro 所依赖的库已经升级版本而引入了新版本所导致的问题。作者可能会由于时间问题无法及时排查而导致您采用本项目作为基项目而出现问题。\n\n## 项目下载和运行\n\n- 拉取项目代码\n\n```bash\ngit clone https://github.com/vueComponent/ant-design-vue-pro.git\ncd ant-design-vue-pro\n```\n\n- 安装依赖\n\n```\nyarn install\n```\n\n- 开发模式运行\n\n```\nyarn run serve\n```\n\n- 编译项目\n\n```\nyarn run build\n```\n\n- Lints and fixes files\n\n```\nyarn run lint\n```\n\n## 其他说明\n\n- **关于 Issue 反馈 (重要!重要!重要!) 请在开 _Issue_ 前，先阅读该内容：[Issue / PR 编写建议](https://github.com/vueComponent/ant-design-vue-pro/issues/90)**\n\n- 项目使用的 [vue-cli3](https://cli.vuejs.org/guide/), 请确保你所使用的 vue-cli 是新版，并且已经学习 cli 官方文档使用教程\n\n- 关闭 Eslint (不推荐) 移除 `package.json` 中 `eslintConfig` 整个节点代码, `vue.config.js` 下的 `lintOnSave` 值改为 `false`\n\n- 组件按需加载 `/src/main.js` L14 相关代码 `import './core/lazy_use'` / `import './core/use'`\n\n- [修改 Ant Design 配色 (@kokoroli)](https://github.com/kokoroli/antd-awesome/blob/master/docs/Ant_Design_%E6%A0%B7%E5%BC%8F%E8%A6%86%E7%9B%96.md)\n\n- I18n: [多语言支持 (@musnow)](./src/locales/index.js)\n\n- 生产环境默认不加载 `mock`，更多详情请看 `src/mock/index.js`\n\n- **用于生产环境，请使用 `release` 版本代码，使用 master 代码出现的任何问题需要你自行解决**\n\n## 浏览器兼容\n\nModern browsers and IE10.\n\n| [<img src=\"https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png\" alt=\"IE / Edge\" width=\"24px\" height=\"24px\" />](http://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src=\"https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png\" alt=\"Firefox\" width=\"24px\" height=\"24px\" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src=\"https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png\" alt=\"Chrome\" width=\"24px\" height=\"24px\" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src=\"https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png\" alt=\"Safari\" width=\"24px\" height=\"24px\" />](http://godban.github.io/browsers-support-badges/)</br>Safari | [<img src=\"https://raw.githubusercontent.com/alrra/browser-logos/master/src/opera/opera_48x48.png\" alt=\"Opera\" width=\"24px\" height=\"24px\" />](http://godban.github.io/browsers-support-badges/)</br>Opera |\n| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| IE10, Edge                                                                                                                                                                                                      | last 2 versions                                                                                                                                                                                                   | last 2 versions                                                                                                                                                                                               | last 2 versions                                                                                                                                                                                               | last 2 versions                                                                                                                                                                                           |\n\n## Contributors\n\nThis project exists thanks to all the people who contribute.\n<a href=\"https://github.com/vueComponent/ant-design-vue-pro/graphs/contributors\"><img src=\"https://opencollective.com/ant-design-pro-vue/contributors.svg?width=890&button=false\" /></a>\n"
  },
  {
    "path": "babel.config.js",
    "content": "const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV)\nconst IS_PREVIEW = process.env.VUE_APP_PREVIEW === 'true'\n\nconst plugins = []\nif (IS_PROD && !IS_PREVIEW) {\n  // 去除日志的插件，\n  plugins.push('transform-remove-console')\n}\n\n// lazy load ant-design-vue\n// if your use import on Demand, Use this code\nplugins.push(['import', {\n  'libraryName': 'ant-design-vue',\n  'libraryDirectory': 'es',\n  'style': true // `style: true` 会加载 less 文件\n}])\n\nmodule.exports = {\n  presets: [\n    '@vue/cli-plugin-babel/preset',\n    [\n      '@babel/preset-env',\n      {\n        'useBuiltIns': 'entry',\n        'corejs': 3\n      }\n    ]\n  ],\n  plugins\n}\n"
  },
  {
    "path": "commitlint.config.js",
    "content": "/**\n * feat：新增功能\n * fix：bug 修复\n * docs：文档更新\n * style：不影响程序逻辑的代码修改(修改空白字符，格式缩进，补全缺失的分号等，没有改变代码逻辑)\n * refactor：重构代码(既没有新增功能，也没有修复 bug)\n * perf：性能, 体验优化\n * test：新增测试用例或是更新现有测试\n * build：主要目的是修改项目构建系统(例如 glup，webpack，rollup 的配置等)的提交\n * ci：主要目的是修改项目继续集成流程(例如 Travis，Jenkins，GitLab CI，Circle等)的提交\n * chore：不属于以上类型的其他类型，比如构建流程, 依赖管理\n * revert：回滚某个更早之前的提交\n */\n\nmodule.exports = {\n  extends: ['@commitlint/config-conventional'],\n  rules: {\n    'type-enum': [\n      2,\n      'always',\n      ['feat', 'fix', 'docs', 'style', 'refactor', 'test', 'chore', 'revert']\n    ],\n    'subject-full-stop': [0, 'never'],\n    'subject-case': [0, 'never']\n  }\n}\n"
  },
  {
    "path": "config/plugin.config.js",
    "content": "const ThemeColorReplacer = require('webpack-theme-color-replacer')\nconst generate = require('@ant-design/colors/lib/generate').default\n\nconst getAntdSerials = (color) => {\n  // 淡化（即less的tint）\n  const lightens = new Array(9).fill().map((t, i) => {\n    return ThemeColorReplacer.varyColor.lighten(color, i / 10)\n  })\n  const colorPalettes = generate(color)\n  const rgb = ThemeColorReplacer.varyColor.toNum3(color.replace('#', '')).join(',')\n  return lightens.concat(colorPalettes).concat(rgb)\n}\n\nconst themePluginOption = {\n  fileName: 'css/theme-colors-[contenthash:8].css',\n  matchColors: getAntdSerials('#1890ff'), // 主色系列\n  // 改变样式选择器，解决样式覆盖问题\n  changeSelector (selector) {\n    switch (selector) {\n      case '.ant-calendar-today .ant-calendar-date':\n        return ':not(.ant-calendar-selected-date):not(.ant-calendar-selected-day)' + selector\n      case '.ant-btn:focus,.ant-btn:hover':\n        return '.ant-btn:focus:not(.ant-btn-primary):not(.ant-btn-danger),.ant-btn:hover:not(.ant-btn-primary):not(.ant-btn-danger)'\n      case '.ant-btn.active,.ant-btn:active':\n        return '.ant-btn.active:not(.ant-btn-primary):not(.ant-btn-danger),.ant-btn:active:not(.ant-btn-primary):not(.ant-btn-danger)'\n      case '.ant-steps-item-process .ant-steps-item-icon > .ant-steps-icon':\n      case '.ant-steps-item-process .ant-steps-item-icon>.ant-steps-icon':\n        return ':not(.ant-steps-item-process)' + selector\n      // fixed https://github.com/vueComponent/ant-design-vue-pro/issues/876\n      case '.ant-steps-item-process .ant-steps-item-icon':\n        return ':not(.ant-steps-item-custom)' + selector\n      case '.ant-menu-horizontal>.ant-menu-item-active,.ant-menu-horizontal>.ant-menu-item-open,.ant-menu-horizontal>.ant-menu-item-selected,.ant-menu-horizontal>.ant-menu-item:hover,.ant-menu-horizontal>.ant-menu-submenu-active,.ant-menu-horizontal>.ant-menu-submenu-open,.ant-menu-horizontal>.ant-menu-submenu-selected,.ant-menu-horizontal>.ant-menu-submenu:hover':\n      case '.ant-menu-horizontal > .ant-menu-item-active,.ant-menu-horizontal > .ant-menu-item-open,.ant-menu-horizontal > .ant-menu-item-selected,.ant-menu-horizontal > .ant-menu-item:hover,.ant-menu-horizontal > .ant-menu-submenu-active,.ant-menu-horizontal > .ant-menu-submenu-open,.ant-menu-horizontal > .ant-menu-submenu-selected,.ant-menu-horizontal > .ant-menu-submenu:hover':\n        return '.ant-menu-horizontal > .ant-menu-item-active,.ant-menu-horizontal > .ant-menu-item-open,.ant-menu-horizontal > .ant-menu-item-selected,.ant-menu-horizontal:not(.ant-menu-dark) > .ant-menu-item:hover,.ant-menu-horizontal > .ant-menu-submenu-active,.ant-menu-horizontal > .ant-menu-submenu-open,.ant-menu-horizontal:not(.ant-menu-dark) > .ant-menu-submenu-selected,.ant-menu-horizontal:not(.ant-menu-dark) > .ant-menu-submenu:hover'\n      case '.ant-menu-horizontal > .ant-menu-item-selected > a':\n      case '.ant-menu-horizontal>.ant-menu-item-selected>a':\n        return '.ant-menu-horizontal:not(ant-menu-light):not(.ant-menu-dark) > .ant-menu-item-selected > a'\n      case '.ant-menu-horizontal > .ant-menu-item > a:hover':\n      case '.ant-menu-horizontal>.ant-menu-item>a:hover':\n        return '.ant-menu-horizontal:not(ant-menu-light):not(.ant-menu-dark) > .ant-menu-item > a:hover'\n      default :\n        return selector\n    }\n  }\n}\n\nconst createThemeColorReplacerPlugin = () => new ThemeColorReplacer(themePluginOption)\n\nmodule.exports = createThemeColorReplacerPlugin\n"
  },
  {
    "path": "config/themePluginConfig.js",
    "content": "export default {\n  theme: [\n    {\n      key: 'dark',\n      fileName: 'dark.css',\n      theme: 'dark'\n    },\n    {\n      key: '#F5222D',\n      fileName: '#F5222D.css',\n      modifyVars: {\n        '@primary-color': '#F5222D'\n      }\n    },\n    {\n      key: '#FA541C',\n      fileName: '#FA541C.css',\n      modifyVars: {\n        '@primary-color': '#FA541C'\n      }\n    },\n    {\n      key: '#FAAD14',\n      fileName: '#FAAD14.css',\n      modifyVars: {\n        '@primary-color': '#FAAD14'\n      }\n    },\n    {\n      key: '#13C2C2',\n      fileName: '#13C2C2.css',\n      modifyVars: {\n        '@primary-color': '#13C2C2'\n      }\n    },\n    {\n      key: '#52C41A',\n      fileName: '#52C41A.css',\n      modifyVars: {\n        '@primary-color': '#52C41A'\n      }\n    },\n    {\n      key: '#2F54EB',\n      fileName: '#2F54EB.css',\n      modifyVars: {\n        '@primary-color': '#2F54EB'\n      }\n    },\n    {\n      key: '#722ED1',\n      fileName: '#722ED1.css',\n      modifyVars: {\n        '@primary-color': '#722ED1'\n      }\n    },\n\n    {\n      key: '#F5222D',\n      theme: 'dark',\n      fileName: 'dark-#F5222D.css',\n      modifyVars: {\n        '@primary-color': '#F5222D'\n      }\n    },\n    {\n      key: '#FA541C',\n      theme: 'dark',\n      fileName: 'dark-#FA541C.css',\n      modifyVars: {\n        '@primary-color': '#FA541C'\n      }\n    },\n    {\n      key: '#FAAD14',\n      theme: 'dark',\n      fileName: 'dark-#FAAD14.css',\n      modifyVars: {\n        '@primary-color': '#FAAD14'\n      }\n    },\n    {\n      key: '#13C2C2',\n      theme: 'dark',\n      fileName: 'dark-#13C2C2.css',\n      modifyVars: {\n        '@primary-color': '#13C2C2'\n      }\n    },\n    {\n      key: '#52C41A',\n      theme: 'dark',\n      fileName: 'dark-#52C41A.css',\n      modifyVars: {\n        '@primary-color': '#52C41A'\n      }\n    },\n    {\n      key: '#2F54EB',\n      theme: 'dark',\n      fileName: 'dark-#2F54EB.css',\n      modifyVars: {\n        '@primary-color': '#2F54EB'\n      }\n    },\n    {\n      key: '#722ED1',\n      theme: 'dark',\n      fileName: 'dark-#722ED1.css',\n      modifyVars: {\n        '@primary-color': '#722ED1'\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "deploy/caddy.conf",
    "content": "0.0.0.0:80 {\n  gzip\n  root /usr/share/nginx/html\n\n  rewrite {\n    r .*\n    to {path} /\n  }\n}"
  },
  {
    "path": "deploy/nginx.conf",
    "content": "server {\n    listen 80;\n    server_name  _;\n    # gzip config\n    gzip on;\n    gzip_min_length 1k;\n    gzip_comp_level 6;\n    gzip_types text/plain text/css text/javascript application/json application/javascript application/x-javascript application/xml;\n    gzip_vary on;\n    gzip_disable \"MSIE [1-6]\\.\";\n\n    root /usr/share/nginx/html;\n    include /etc/nginx/mime.types;\n\n    location / {\n        try_files $uri $uri/ /index.html;\n    }\n\n#    location /api {\n#        proxy_pass https://preview.pro.antdv.com/api;\n#        proxy_set_header   X-Forwarded-Proto $scheme;\n#        proxy_set_header   X-Real-IP         $remote_addr;\n#    }\n}\n"
  },
  {
    "path": "docs/add-page-loading-animate.md",
    "content": "为首屏增加 加载动画\n====\n\n\n\n## 需求\n\n> 为了缓解用户第一次访问时，加载 JS 过大所导致用户等待白屏时间过长导致的用户体验不好，进行的一个优化动效。\n\n\n\n## 实现方案\n\n1. 将 动画加载 dom 元素放在 #app 内，Vue 生命周期开始时，会自动清掉 #app 下的所有元素。\n2. 将 动画加载 dom 元素放在 body 下，Vue 生命周期开始时 App.vue (created, mounted) 调用 `@/utils/utll` 下的 removeLoadingAnimate(#id, timeout) 则会移除加载动画\n\n最后一步：\n​\t将样式插入到 `public/index.html` 文件的 `<head></head>` 最好写成内联 `<style>动画样式</style>` \n\n\n\n----\n\n目前提供有两个样式，均在 `public/loading` 文件夹内。且 pro 已经默认使用了一套 loading 动画方案，可以直接参考 `public/index.html`\n\n\n## 写在最后\n\n目前 pro 有页面 overflow 显示出浏览器滚动条时，页面会抖动一下的问题。\n\n欢迎各位提供能解决的方案和实现 demo。如果在条件允许的情况下，建议请直接使用 pro 进行改造，也欢迎直接 PR 到 pro 的仓库\n"
  },
  {
    "path": "docs/webpack-bundle-analyzer.md",
    "content": "先增加依赖\n\n```bash\n// npm\n$ npm install --save-dev webpack-bundle-analyzer\n\n// or yarn\n$ yarn add webpack-bundle-analyzer -D\n```\n\n配置文件 `vue.config.js` 增加 `configureWebpack.plugins` 参数\n\n```\nconst path = require('path')\nconst webpack = require('webpack')\nconst BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin\n\nfunction resolve (dir) {\n  return path.join(__dirname, dir)\n}\n\n// vue.config.js\nmodule.exports = {\n  configureWebpack: {\n    plugins: [\n      // Ignore all locale files of moment.js\n      new webpack.IgnorePlugin(/^\\.\\/locale$/, /moment$/),\n      // 依赖大小分析工具\n      new BundleAnalyzerPlugin(),\n    ]\n  },\n  \n  \n  ...\n}\n```\n\n\n\n启动 `cli` 的 `build` 命令进行项目编译，编译完成时，会自动运行一个 http://localhost:8888 的地址，完整显示了支持库依赖"
  },
  {
    "path": "jest.config.js",
    "content": "module.exports = {\n  moduleFileExtensions: [\n    'js',\n    'jsx',\n    'json',\n    'vue'\n  ],\n  transform: {\n    '^.+\\\\.vue$': 'vue-jest',\n    '.+\\\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub',\n    '^.+\\\\.jsx?$': 'babel-jest'\n  },\n  moduleNameMapper: {\n    '^@/(.*)$': '<rootDir>/src/$1'\n  },\n  snapshotSerializers: [\n    'jest-serializer-vue'\n  ],\n  testMatch: [\n    '**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'\n  ],\n  testURL: 'http://localhost/'\n}\n"
  },
  {
    "path": "jsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"es6\",\n    \"baseUrl\": \".\",\n    \"paths\": {\n      \"@/*\": [\"src/*\"]\n    }\n  },\n  \"exclude\": [\"node_modules\", \"dist\"],\n  \"include\": [\"src/**/*\"]\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"vue-antd-pro\",\n  \"version\": \"3.0.4\",\n  \"private\": true,\n  \"scripts\": {\n    \"serve\": \"vue-cli-service serve\",\n    \"build\": \"vue-cli-service build --no-module\",\n    \"test:unit\": \"vue-cli-service test:unit\",\n    \"lint\": \"vue-cli-service lint\",\n    \"build:preview\": \"vue-cli-service build --no-module --mode preview\",\n    \"lint:nofix\": \"vue-cli-service lint --no-fix\",\n    \"lint:js\": \"eslint src/**/*.js --fix\",\n    \"lint:css\": \"stylelint src/**/*.*ss --fix  --custom-syntax postcss-less\",\n    \"prepare\": \"husky install\"\n  },\n  \"dependencies\": {\n    \"@ant-design-vue/pro-layout\": \"^1.0.12\",\n    \"@antv/data-set\": \"^0.10.2\",\n    \"ant-design-vue\": \"^1.7.8\",\n    \"axios\": \"^0.26.1\",\n    \"babel-loader\": \"8\",\n    \"core-js\": \"^3.21.1\",\n    \"enquire.js\": \"^2.1.6\",\n    \"lodash.clonedeep\": \"^4.5.0\",\n    \"lodash.get\": \"^4.4.2\",\n    \"lodash.pick\": \"^4.4.0\",\n    \"md5\": \"^2.3.0\",\n    \"mockjs2\": \"1.0.8\",\n    \"moment\": \"^2.29.2\",\n    \"nprogress\": \"^0.2.0\",\n    \"store\": \"^2.0.12\",\n    \"viser-vue\": \"^2.4.8\",\n    \"vue\": \"^2.6.14\",\n    \"vue-clipboard2\": \"^0.2.1\",\n    \"vue-cropper\": \"0.4.9\",\n    \"vue-i18n\": \"^8.27.1\",\n    \"vue-quill-editor\": \"^3.0.6\",\n    \"vue-router\": \"^3.5.3\",\n    \"vue-svg-component-runtime\": \"^1.0.1\",\n    \"vue-template-compiler\": \"^2.6.14\",\n    \"vuex\": \"^3.6.2\",\n    \"wangeditor\": \"^3.1.1\"\n  },\n  \"devDependencies\": {\n    \"@ant-design/colors\": \"^3.2.2\",\n    \"@commitlint/cli\": \"^12.1.4\",\n    \"@commitlint/config-conventional\": \"^12.1.4\",\n    \"@vue/babel-helper-vue-jsx-merge-props\": \"^1.2.1\",\n    \"@vue/cli-plugin-babel\": \"~5.0.8\",\n    \"@vue/cli-plugin-eslint\": \"~5.0.8\",\n    \"@vue/cli-plugin-router\": \"~5.0.8\",\n    \"@vue/cli-plugin-unit-jest\": \"~5.0.8\",\n    \"@vue/cli-plugin-vuex\": \"~5.0.8\",\n    \"@vue/cli-service\": \"~5.0.8\",\n    \"@vue/eslint-config-standard\": \"^4.0.0\",\n    \"@vue/test-utils\": \"^1.3.0\",\n    \"babel-eslint\": \"^10.1.0\",\n    \"babel-plugin-import\": \"^1.13.3\",\n    \"babel-plugin-transform-remove-console\": \"^6.9.4\",\n    \"commitizen\": \"^4.2.4\",\n    \"cz-conventional-changelog\": \"^3.3.0\",\n    \"eslint\": \"^7.0.0\",\n    \"eslint-plugin-html\": \"^5.0.5\",\n    \"eslint-plugin-vue\": \"^5.2.3\",\n    \"file-loader\": \"^6.2.0\",\n    \"git-revision-webpack-plugin\": \"^3.0.6\",\n    \"husky\": \"^6.0.0\",\n    \"less\": \"^3.13.1\",\n    \"less-loader\": \"^5.0.0\",\n    \"lint-staged\": \"^12.5.0\",\n    \"postcss\": \"^8.3.5\",\n    \"postcss-less\": \"^6.0.0\",\n    \"regenerator-runtime\": \"^0.13.9\",\n    \"stylelint\": \"^14.8.5\",\n    \"stylelint-config-css-modules\": \"^4.1.0\",\n    \"stylelint-config-recess-order\": \"^3.0.0\",\n    \"stylelint-config-recommended\": \"^7.0.0\",\n    \"stylelint-config-standard\": \"^25.0.0\",\n    \"stylelint-order\": \"^5.0.0\",\n    \"vue-svg-icon-loader\": \"^2.1.1\",\n    \"vue-svg-loader\": \"0.16.0\",\n    \"webpack\": \"^5.74.0\",\n    \"webpack-theme-color-replacer\": \"^1.3.26\"\n  },\n  \"config\": {\n    \"commitizen\": {\n      \"path\": \"./node_modules/cz-conventional-changelog\"\n    }\n  },\n  \"husky\": {\n    \"hooks\": {\n      \"commit-msg\": \"commitlint -E HUSKY_GIT_PARAMS\"\n    }\n  },\n  \"gitHooks\": {\n    \"pre-commit\": \"lint-staged\"\n  }\n}\n"
  },
  {
    "path": "postcss.config.js",
    "content": "module.exports = {\n  plugins: {\n    autoprefixer: {}\n  }\n}\n"
  },
  {
    "path": "public/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"zh-cmn-Hans\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n    <meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\">\n    <link rel=\"icon\" href=\"<%= BASE_URL %>logo.png\">\n    <title>Ant Design Pro</title>\n    <style>.first-loading-wrp{display:flex;justify-content:center;align-items:center;flex-direction:column;min-height:420px;height:100%}.first-loading-wrp>h1{font-size:128px}.first-loading-wrp .loading-wrp{padding:98px;display:flex;justify-content:center;align-items:center}.dot{animation:antRotate 1.2s infinite linear;transform:rotate(45deg);position:relative;display:inline-block;font-size:32px;width:32px;height:32px;box-sizing:border-box}.dot i{width:14px;height:14px;position:absolute;display:block;background-color:#1890ff;border-radius:100%;transform:scale(.75);transform-origin:50% 50%;opacity:.3;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:.4s;animation-delay:.4s}.dot i:nth-child(3){right:0;bottom:0;-webkit-animation-delay:.8s;animation-delay:.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}}</style>\n    <!-- require cdn assets css -->\n    <% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.css) { %>\n    <link rel=\"stylesheet\" href=\"<%= htmlWebpackPlugin.options.cdn.css[i] %>\" />\n    <% } %>\n  </head>\n  <body>\n    <noscript>\n      <strong>We're sorry but vue-antd-pro doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>\n    </noscript>\n    <div id=\"app\">\n      <div class=\"first-loading-wrp\">\n        <h1>Pro</h1>\n        <div class=\"loading-wrp\">\n          <span class=\"dot dot-spin\"><i></i><i></i><i></i><i></i></span>\n        </div>\n        <div style=\"display: flex; justify-content: center; align-items: center;\">Ant Design</div>\n      </div>\n    </div>\n    <!-- require cdn assets js -->\n    <% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.js) { %>\n    <script type=\"text/javascript\" src=\"<%= htmlWebpackPlugin.options.cdn.js[i] %>\"></script>\n    <% } %>\n    <!-- built files will be auto injected -->\n  </body>\n</html>\n"
  },
  {
    "path": "src/App.vue",
    "content": "<template>\n  <a-config-provider :locale=\"locale\">\n    <div id=\"app\">\n      <router-view/>\n    </div>\n  </a-config-provider>\n</template>\n\n<script>\nimport { domTitle, setDocumentTitle } from '@/utils/domUtil'\nimport { i18nRender } from '@/locales'\n\nexport default {\n  data () {\n    return {\n    }\n  },\n  computed: {\n    locale () {\n      // 只是为了切换语言时，更新标题\n      const { title } = this.$route.meta\n      title && (setDocumentTitle(`${i18nRender(title)} - ${domTitle}`))\n\n      return this.$i18n.getLocaleMessage(this.$store.getters.lang).antLocale\n    }\n  }\n}\n</script>\n"
  },
  {
    "path": "src/api/login.js",
    "content": "import request from '@/utils/request'\n\nconst userApi = {\n  Login: '/auth/login',\n  Logout: '/auth/logout',\n  ForgePassword: '/auth/forge-password',\n  Register: '/auth/register',\n  twoStepCode: '/auth/2step-code',\n  SendSms: '/account/sms',\n  SendSmsErr: '/account/sms_err',\n  // get my info\n  UserInfo: '/user/info',\n  UserMenu: '/user/nav'\n}\n\n/**\n * login func\n * parameter: {\n *     username: '',\n *     password: '',\n *     remember_me: true,\n *     captcha: '12345'\n * }\n * @param parameter\n * @returns {*}\n */\nexport function login (parameter) {\n  return request({\n    url: userApi.Login,\n    method: 'post',\n    data: parameter\n  })\n}\n\nexport function getSmsCaptcha (parameter) {\n  return request({\n    url: userApi.SendSms,\n    method: 'post',\n    data: parameter\n  })\n}\n\nexport function getInfo () {\n  return request({\n    url: userApi.UserInfo,\n    method: 'get',\n    headers: {\n      'Content-Type': 'application/json;charset=UTF-8'\n    }\n  })\n}\n\nexport function getCurrentUserNav () {\n  return request({\n    url: userApi.UserMenu,\n    method: 'get'\n  })\n}\n\nexport function logout () {\n  return request({\n    url: userApi.Logout,\n    method: 'post',\n    headers: {\n      'Content-Type': 'application/json;charset=UTF-8'\n    }\n  })\n}\n\n/**\n * get user 2step code open?\n * @param parameter {*}\n */\nexport function get2step (parameter) {\n  return request({\n    url: userApi.twoStepCode,\n    method: 'post',\n    data: parameter\n  })\n}\n"
  },
  {
    "path": "src/api/manage.js",
    "content": "import request from '@/utils/request'\n\nconst api = {\n  user: '/user',\n  role: '/role',\n  service: '/service',\n  permission: '/permission',\n  permissionNoPager: '/permission/no-pager',\n  orgTree: '/org/tree'\n}\n\nexport default api\n\nexport function getUserList (parameter) {\n  return request({\n    url: api.user,\n    method: 'get',\n    params: parameter\n  })\n}\n\nexport function getRoleList (parameter) {\n  return request({\n    url: api.role,\n    method: 'get',\n    params: parameter\n  })\n}\n\nexport function getServiceList (parameter) {\n  return request({\n    url: api.service,\n    method: 'get',\n    params: parameter\n  })\n}\n\nexport function getPermissions (parameter) {\n  return request({\n    url: api.permissionNoPager,\n    method: 'get',\n    params: parameter\n  })\n}\n\nexport function getOrgTree (parameter) {\n  return request({\n    url: api.orgTree,\n    method: 'get',\n    params: parameter\n  })\n}\n\n// id == 0 add     post\n// id != 0 update  put\nexport function saveService (parameter) {\n  return request({\n    url: api.service,\n    method: parameter.id === 0 ? 'post' : 'put',\n    data: parameter\n  })\n}\n\nexport function saveSub (sub) {\n  return request({\n    url: '/sub',\n    method: sub.id === 0 ? 'post' : 'put',\n    data: sub\n  })\n}\n"
  },
  {
    "path": "src/components/ArticleListContent/ArticleListContent.vue",
    "content": "<template>\n  <div class=\"antd-pro-components-article-list-content-index-listContent\">\n    <div class=\"description\">\n      <slot>\n        {{ description }}\n      </slot>\n    </div>\n    <div class=\"extra\">\n      <a-avatar :src=\"avatar\" size=\"small\" />\n      <a :href=\"href\">{{ owner }}</a> 发布在 <a :href=\"href\">{{ href }}</a>\n      <em>{{ updateAt | moment }}</em>\n    </div>\n  </div>\n</template>\n\n<script>\nexport default {\n  name: 'ArticleListContent',\n  props: {\n    prefixCls: {\n      type: String,\n      default: 'antd-pro-components-article-list-content-index-listContent'\n    },\n    description: {\n      type: String,\n      default: ''\n    },\n    owner: {\n      type: String,\n      required: true\n    },\n    avatar: {\n      type: String,\n      required: true\n    },\n    href: {\n      type: String,\n      required: true\n    },\n    updateAt: {\n      type: String,\n      required: true\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n@import '../index.less';\n\n.antd-pro-components-article-list-content-index-listContent {\n  .description {\n    max-width: 720px;\n    line-height: 22px;\n  }\n  .extra {\n    margin-top: 16px;\n    color: @text-color-secondary;\n    line-height: 22px;\n\n    & :deep(.ant-avatar) {\n      position: relative;\n      top: 1px;\n      width: 20px;\n      height: 20px;\n      margin-right: 8px;\n      vertical-align: top;\n    }\n\n    & > em {\n      margin-left: 16px;\n      color: @disabled-color;\n      font-style: normal;\n    }\n  }\n}\n\n@media screen and (max-width: @screen-xs) {\n  .antd-pro-components-article-list-content-index-listContent {\n    .extra {\n      & > em {\n        display: block;\n        margin-top: 8px;\n        margin-left: 0;\n      }\n    }\n  }\n}\n</style>\n"
  },
  {
    "path": "src/components/ArticleListContent/index.js",
    "content": "import ArticleListContent from './ArticleListContent'\n\nexport default ArticleListContent\n"
  },
  {
    "path": "src/components/AvatarList/Item.jsx",
    "content": "import PropTypes from 'ant-design-vue/es/_util/vue-types'\nimport { Tooltip, Avatar } from 'ant-design-vue'\nimport { getSlotOptions } from 'ant-design-vue/lib/_util/props-util'\nimport { warning } from 'ant-design-vue/lib/vc-util/warning'\n\nexport const AvatarListItemProps = {\n  tips: PropTypes.string,\n  src: PropTypes.string.def('')\n}\n\nconst Item = {\n  __ANT_AVATAR_CHILDREN: true,\n  name: 'AvatarListItem',\n  props: AvatarListItemProps,\n  created () {\n    warning(getSlotOptions(this.$parent).__ANT_AVATAR_LIST, 'AvatarListItem must be a subcomponent of AvatarList')\n  },\n  render () {\n    const size = this.$parent.size === 'mini' ? 'small' : this.$parent.size\n    const AvatarDom = <Avatar size={size || 'small'} src={this.src} />\n    return (this.tips && <Tooltip title={this.tips}>{AvatarDom}</Tooltip>) || <AvatarDom />\n  }\n}\n\nexport default Item\n"
  },
  {
    "path": "src/components/AvatarList/List.jsx",
    "content": "import './index.less'\n\nimport PropTypes from 'ant-design-vue/es/_util/vue-types'\nimport Avatar from 'ant-design-vue/es/avatar'\nimport Item from './Item.jsx'\nimport { filterEmpty } from '@/components/_util/util'\n\n/**\n * size: `number`、 `large`、`small`、`default` 默认值: default\n * maxLength: number\n * excessItemsStyle: CSSProperties\n */\nconst AvatarListProps = {\n  prefixCls: PropTypes.string.def('ant-pro-avatar-list'),\n  size: {\n    validator: val => {\n      return typeof val === 'number' || ['small', 'large', 'default'].includes(val)\n    },\n    default: 'default'\n  },\n  maxLength: PropTypes.number.def(0),\n  excessItemsStyle: PropTypes.object.def({\n    color: '#f56a00',\n    backgroundColor: '#fde3cf'\n  })\n}\n\nconst AvatarList = {\n  __ANT_AVATAR_LIST: true,\n  Item,\n  name: 'AvatarList',\n  props: AvatarListProps,\n  render (h) {\n    const { prefixCls, size } = this.$props\n    const className = {\n      [`${prefixCls}`]: true,\n      [`${size}`]: true\n    }\n\n    const items = filterEmpty(this.$slots.default)\n    const itemsDom = items && items.length ? <ul class={`${prefixCls}-items`}>{this.getItems(items)}</ul> : null\n    return (\n      <div class={className}>\n        {itemsDom}\n      </div>\n    )\n  },\n  methods: {\n    getItems (items) {\n      const className = {\n        [`${this.prefixCls}-item`]: true,\n        [`${this.size}`]: true\n      }\n      const totalSize = items.length\n\n      if (this.maxLength > 0) {\n        items = items.slice(0, this.maxLength)\n        items.push((<Avatar size={this.size === 'mini' ? 'small' : this.size} style={this.excessItemsStyle}>{`+${totalSize - this.maxLength}`}</Avatar>))\n      }\n      return items.map((item) => (\n        <li class={className}>{item}</li>\n      ))\n    }\n  }\n}\n\nAvatarList.install = function (Vue) {\n  Vue.component(AvatarList.name, AvatarList)\n  Vue.component(AvatarList.Item.name, AvatarList.Item)\n}\n\nexport default AvatarList\n"
  },
  {
    "path": "src/components/AvatarList/index.js",
    "content": "import AvatarList from './List'\nimport Item from './Item'\n\nexport {\n  AvatarList,\n  Item as AvatarListItem\n}\n\nexport default AvatarList\n"
  },
  {
    "path": "src/components/AvatarList/index.less",
    "content": "@import '../index';\n\n@avatar-list-prefix-cls: ~\"@{ant-pro-prefix}-avatar-list\";\n@avatar-list-item-prefix-cls: ~\"@{ant-pro-prefix}-avatar-list-item\";\n\n.@{avatar-list-prefix-cls} {\n  display: inline-block;\n\n  ul {\n    display: inline-block;\n    padding: 0;\n    margin: 0 0 0 8px;\n    font-size: 0;\n    list-style: none;\n  }\n}\n\n.@{avatar-list-item-prefix-cls} {\n  display: inline-block;\n  width: @avatar-size-base;\n  height: @avatar-size-base;\n  margin-left: -8px;\n  font-size: @font-size-base;\n\n  :global {\n    .ant-avatar {\n      cursor: pointer;\n      border: 1px solid #fff;\n    }\n  }\n\n  &.large {\n    width: @avatar-size-lg;\n    height: @avatar-size-lg;\n  }\n\n  &.small {\n    width: @avatar-size-sm;\n    height: @avatar-size-sm;\n  }\n\n  &.mini {\n    width: 20px;\n    height: 20px;\n\n    :global {\n      .ant-avatar {\n        width: 20px;\n        height: 20px;\n        line-height: 20px;\n\n        .ant-avatar-string {\n          font-size: 12px;\n          line-height: 18px;\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/components/AvatarList/index.md",
    "content": "# AvatarList 用户头像列表\n\n\n一组用户头像，常用在项目/团队成员列表。可通过设置 `size` 属性来指定头像大小。\n\n\n\n引用方式：\n\n```javascript\nimport AvatarList from '@/components/AvatarList'\nconst AvatarListItem = AvatarList.Item\n\nexport default {\n    components: {\n        AvatarList,\n        AvatarListItem\n    }\n}\n```\n\n\n\n## 代码演示  [demo](https://pro.loacg.com/test/home)\n\n```html\n<avatar-list size=\"mini\">\n    <avatar-list-item tips=\"Jake\" src=\"https://gw.alipayobjects.com/zos/rmsportal/zOsKZmFRdUtvpqCImOVY.png\" />\n    <avatar-list-item tips=\"Andy\" src=\"https://gw.alipayobjects.com/zos/rmsportal/sfjbOqnsXXJgNCjCzDBL.png\" />\n    <avatar-list-item tips=\"Niko\" src=\"https://gw.alipayobjects.com/zos/rmsportal/kZzEzemZyKLKFsojXItE.png\" />\n</avatar-list>\n```\n或\n```html\n<avatar-list :max-length=\"3\">\n    <avatar-list-item tips=\"Jake\" src=\"https://gw.alipayobjects.com/zos/rmsportal/zOsKZmFRdUtvpqCImOVY.png\" />\n    <avatar-list-item tips=\"Andy\" src=\"https://gw.alipayobjects.com/zos/rmsportal/sfjbOqnsXXJgNCjCzDBL.png\" />\n    <avatar-list-item tips=\"Niko\" src=\"https://gw.alipayobjects.com/zos/rmsportal/kZzEzemZyKLKFsojXItE.png\" />\n    <avatar-list-item tips=\"Niko\" src=\"https://gw.alipayobjects.com/zos/rmsportal/kZzEzemZyKLKFsojXItE.png\" />\n    <avatar-list-item tips=\"Niko\" src=\"https://gw.alipayobjects.com/zos/rmsportal/kZzEzemZyKLKFsojXItE.png\" />\n    <avatar-list-item tips=\"Niko\" src=\"https://gw.alipayobjects.com/zos/rmsportal/kZzEzemZyKLKFsojXItE.png\" />\n    <avatar-list-item tips=\"Niko\" src=\"https://gw.alipayobjects.com/zos/rmsportal/kZzEzemZyKLKFsojXItE.png\" />\n</avatar-list>\n```\n\n\n\n## API\n\n### AvatarList\n\n| 参数               | 说明       | 类型                                 | 默认值       |\n| ---------------- | -------- | ---------------------------------- | --------- |\n| size             | 头像大小     | `large`、`small` 、`mini`, `default` | `default` |\n| maxLength        | 要显示的最大项目 | number                             | -         |\n| excessItemsStyle | 多余的项目风格  | CSSProperties                      | -         |\n\n### AvatarList.Item\n\n| 参数   | 说明     | 类型        | 默认值 |\n| ---- | ------ | --------- | --- |\n| tips | 头像展示文案 | string | -   |\n| src  | 头像图片连接 | string    | -   |\n\n"
  },
  {
    "path": "src/components/Charts/Bar.vue",
    "content": "<template>\n  <div :style=\"{ padding: '0 0 32px 32px' }\">\n    <h4 :style=\"{ marginBottom: '20px' }\">{{ title }}</h4>\n    <v-chart\n      height=\"254\"\n      :data=\"data\"\n      :forceFit=\"true\"\n      :padding=\"['auto', 'auto', '40', '50']\">\n      <v-tooltip />\n      <v-axis />\n      <v-bar position=\"x*y\"/>\n    </v-chart>\n  </div>\n</template>\n\n<script>\nexport default {\n  name: 'Bar',\n  props: {\n    title: {\n      type: String,\n      default: ''\n    },\n    data: {\n      type: Array,\n      default: () => {\n        return []\n      }\n    },\n    scale: {\n      type: Array,\n      default: () => {\n        return [{\n          dataKey: 'x',\n          min: 2\n        }, {\n          dataKey: 'y',\n          title: '时间',\n          min: 1,\n          max: 22\n        }]\n      }\n    },\n    tooltip: {\n      type: Array,\n      default: () => {\n        return [\n          'x*y',\n          (x, y) => ({\n            name: x,\n            value: y\n          })\n        ]\n      }\n    }\n  },\n  data () {\n    return {\n    }\n  }\n}\n</script>\n"
  },
  {
    "path": "src/components/Charts/ChartCard.vue",
    "content": "<template>\n  <a-card :loading=\"loading\" :body-style=\"{ padding: '20px 24px 8px' }\" :bordered=\"false\">\n    <div class=\"chart-card-header\">\n      <div class=\"meta\">\n        <span class=\"chart-card-title\">\n          <slot name=\"title\">\n            {{ title }}\n          </slot>\n        </span>\n        <span class=\"chart-card-action\">\n          <slot name=\"action\"></slot>\n        </span>\n      </div>\n      <div class=\"total\">\n        <slot name=\"total\">\n          <span>{{ typeof total === 'function' && total() || total }}</span>\n        </slot>\n      </div>\n    </div>\n    <div class=\"chart-card-content\">\n      <div class=\"content-fix\">\n        <slot></slot>\n      </div>\n    </div>\n    <div class=\"chart-card-footer\">\n      <div class=\"field\">\n        <slot name=\"footer\"></slot>\n      </div>\n    </div>\n  </a-card>\n</template>\n\n<script>\nexport default {\n  name: 'ChartCard',\n  props: {\n    title: {\n      type: String,\n      default: ''\n    },\n    total: {\n      type: [Function, Number, String],\n      required: false,\n      default: null\n    },\n    loading: {\n      type: Boolean,\n      default: false\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n  .chart-card-header {\n    position: relative;\n    overflow: hidden;\n    width: 100%;\n\n    .meta {\n      position: relative;\n      overflow: hidden;\n      width: 100%;\n      color: rgba(0, 0, 0, .45);\n      font-size: 14px;\n      line-height: 22px;\n    }\n  }\n\n  .chart-card-action {\n    cursor: pointer;\n    position: absolute;\n    top: 0;\n    right: 0;\n  }\n\n  .chart-card-footer {\n    border-top: 1px solid #e8e8e8;\n    padding-top: 9px;\n    margin-top: 8px;\n\n    > * {\n      position: relative;\n    }\n\n    .field {\n      white-space: nowrap;\n      overflow: hidden;\n      text-overflow: ellipsis;\n      margin: 0;\n    }\n  }\n\n  .chart-card-content {\n    margin-bottom: 12px;\n    position: relative;\n    height: 46px;\n    width: 100%;\n\n    .content-fix {\n      position: absolute;\n      left: 0;\n      bottom: 0;\n      width: 100%;\n    }\n  }\n\n  .total {\n    overflow: hidden;\n    text-overflow: ellipsis;\n    word-break: break-all;\n    white-space: nowrap;\n    color: #000;\n    margin-top: 4px;\n    margin-bottom: 0;\n    font-size: 30px;\n    line-height: 38px;\n    height: 38px;\n  }\n</style>\n"
  },
  {
    "path": "src/components/Charts/Liquid.vue",
    "content": "<template>\n  <div>\n    <v-chart\n      :forceFit=\"true\"\n      :height=\"height\"\n      :width=\"width\"\n      :data=\"data\"\n      :scale=\"scale\"\n      :padding=\"0\">\n      <v-tooltip />\n      <v-interval\n        :shape=\"['liquid-fill-gauge']\"\n        position=\"transfer*value\"\n        color=\"\"\n        :v-style=\"{\n          lineWidth: 10,\n          opacity: 0.75\n        }\"\n        :tooltip=\"[\n          'transfer*value',\n          (transfer, value) => {\n            return {\n              name: transfer,\n              value,\n            };\n          },\n        ]\"\n      ></v-interval>\n      <v-guide\n        v-for=\"(row, index) in data\"\n        :key=\"index\"\n        type=\"text\"\n        :top=\"true\"\n        :position=\"{\n          gender: row.transfer,\n          value: 45\n        }\"\n        :content=\"row.value + '%'\"\n        :v-style=\"{\n          fontSize: 100,\n          textAlign: 'center',\n          opacity: 0.75,\n        }\"\n      />\n    </v-chart>\n  </div>\n</template>\n\n<script>\nexport default {\n  name: 'Liquid',\n  props: {\n    height: {\n      type: Number,\n      default: 0\n    },\n    width: {\n      type: Number,\n      default: 0\n    }\n  }\n}\n</script>\n\n<style scoped>\n\n</style>\n"
  },
  {
    "path": "src/components/Charts/MiniArea.vue",
    "content": "<template>\n  <div class=\"antv-chart-mini\">\n    <div class=\"chart-wrapper\" :style=\"{ height: 46 }\">\n      <v-chart :force-fit=\"true\" :height=\"height\" :data=\"data\" :padding=\"[36, 0, 18, 0]\">\n        <v-tooltip />\n        <v-smooth-area position=\"x*y\" />\n      </v-chart>\n    </div>\n  </div>\n</template>\n\n<script>\nimport moment from 'moment'\nconst data = []\nconst beginDay = new Date().getTime()\n\nfor (let i = 0; i < 10; i++) {\n  data.push({\n    x: moment(new Date(beginDay + 1000 * 60 * 60 * 24 * i)).format('YYYY-MM-DD'),\n    y: Math.round(Math.random() * 10)\n  })\n}\n\nconst tooltip = [\n  'x*y',\n  (x, y) => ({\n    name: x,\n    value: y\n  })\n]\nconst scale = [{\n  dataKey: 'x',\n  min: 2\n}, {\n  dataKey: 'y',\n  title: '时间',\n  min: 1,\n  max: 22\n}]\n\nexport default {\n  name: 'MiniArea',\n  data () {\n    return {\n      data,\n      tooltip,\n      scale,\n      height: 100\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n  @import \"chart\";\n</style>\n"
  },
  {
    "path": "src/components/Charts/MiniBar.vue",
    "content": "<template>\n  <div class=\"antv-chart-mini\">\n    <div class=\"chart-wrapper\" :style=\"{ height: 46 }\">\n      <v-chart :force-fit=\"true\" :height=\"height\" :data=\"data\" :padding=\"[36, 5, 18, 5]\">\n        <v-tooltip />\n        <v-bar position=\"x*y\" />\n      </v-chart>\n    </div>\n  </div>\n</template>\n\n<script>\nimport moment from 'moment'\nconst data = []\nconst beginDay = new Date().getTime()\n\nfor (let i = 0; i < 10; i++) {\n  data.push({\n    x: moment(new Date(beginDay + 1000 * 60 * 60 * 24 * i)).format('YYYY-MM-DD'),\n    y: Math.round(Math.random() * 10)\n  })\n}\n\nconst tooltip = [\n  'x*y',\n  (x, y) => ({\n    name: x,\n    value: y\n  })\n]\n\nconst scale = [{\n  dataKey: 'x',\n  min: 2\n}, {\n  dataKey: 'y',\n  title: '时间',\n  min: 1,\n  max: 30\n}]\n\nexport default {\n  name: 'MiniBar',\n  data () {\n    return {\n      data,\n      tooltip,\n      scale,\n      height: 100\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n  @import \"chart\";\n</style>\n"
  },
  {
    "path": "src/components/Charts/MiniProgress.vue",
    "content": "<template>\n  <div class=\"chart-mini-progress\">\n    <div class=\"target\" :style=\"{ left: target + '%'}\">\n      <span :style=\"{ backgroundColor: color }\" />\n      <span :style=\"{ backgroundColor: color }\"/>\n    </div>\n    <div class=\"progress-wrapper\">\n      <div class=\"progress\" :style=\"{ backgroundColor: color, width: percentage + '%', height: height }\"></div>\n    </div>\n  </div>\n</template>\n\n<script>\nexport default {\n  name: 'MiniProgress',\n  props: {\n    target: {\n      type: Number,\n      default: 0\n    },\n    height: {\n      type: String,\n      default: '10px'\n    },\n    color: {\n      type: String,\n      default: '#13C2C2'\n    },\n    percentage: {\n      type: Number,\n      default: 0\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n  .chart-mini-progress {\n    padding: 5px 0;\n    position: relative;\n    width: 100%;\n\n    .target {\n      position: absolute;\n      top: 0;\n      bottom: 0;\n\n      span {\n        border-radius: 100px;\n        position: absolute;\n        top: 0;\n        left: 0;\n        height: 4px;\n        width: 2px;\n\n        &:last-child {\n          top: auto;\n          bottom: 0;\n        }\n      }\n    }\n    .progress-wrapper {\n      background-color: #f5f5f5;\n      position: relative;\n\n      .progress {\n        transition: all .4s cubic-bezier(.08,.82,.17,1) 0s;\n        border-radius: 1px 0 0 1px;\n        background-color: #1890ff;\n        width: 0;\n        height: 100%;\n      }\n    }\n  }\n</style>\n"
  },
  {
    "path": "src/components/Charts/MiniSmoothArea.vue",
    "content": "<template>\n  <div :class=\"prefixCls\">\n    <div class=\"chart-wrapper\" :style=\"{ height: 46 }\">\n      <v-chart :force-fit=\"true\" :height=\"100\" :data=\"dataSource\" :scale=\"scale\" :padding=\"[36, 0, 18, 0]\">\n        <v-tooltip />\n        <v-smooth-line position=\"x*y\" :size=\"2\" />\n        <v-smooth-area position=\"x*y\" />\n      </v-chart>\n    </div>\n  </div>\n</template>\n\n<script>\nexport default {\n  name: 'MiniSmoothArea',\n  props: {\n    prefixCls: {\n      type: String,\n      default: 'ant-pro-smooth-area'\n    },\n    scale: {\n      type: [Object, Array],\n      required: true\n    },\n    dataSource: {\n      type: Array,\n      required: true\n    }\n  },\n  data () {\n    return {\n      height: 100\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n  @import \"smooth.area.less\";\n</style>\n"
  },
  {
    "path": "src/components/Charts/Radar.vue",
    "content": "<template>\n  <v-chart :forceFit=\"true\" height=\"400\" :data=\"data\" :padding=\"[20, 20, 95, 20]\" :scale=\"scale\">\n    <v-tooltip></v-tooltip>\n    <v-axis :dataKey=\"axis1Opts.dataKey\" :line=\"axis1Opts.line\" :tickLine=\"axis1Opts.tickLine\" :grid=\"axis1Opts.grid\" />\n    <v-axis :dataKey=\"axis2Opts.dataKey\" :line=\"axis2Opts.line\" :tickLine=\"axis2Opts.tickLine\" :grid=\"axis2Opts.grid\" />\n    <v-legend dataKey=\"user\" marker=\"circle\" :offset=\"30\" />\n    <v-coord type=\"polar\" radius=\"0.8\" />\n    <v-line position=\"item*score\" color=\"user\" :size=\"2\" />\n    <v-point position=\"item*score\" color=\"user\" :size=\"4\" shape=\"circle\" />\n  </v-chart>\n</template>\n\n<script>\nconst axis1Opts = {\n  dataKey: 'item',\n  line: null,\n  tickLine: null,\n  grid: {\n    lineStyle: {\n      lineDash: null\n    },\n    hideFirstLine: false\n  }\n}\nconst axis2Opts = {\n  dataKey: 'score',\n  line: null,\n  tickLine: null,\n  grid: {\n    type: 'polygon',\n    lineStyle: {\n      lineDash: null\n    }\n  }\n}\n\nconst scale = [\n  {\n    dataKey: 'score',\n    min: 0,\n    max: 80\n  }, {\n    dataKey: 'user',\n    alias: '类型'\n  }\n]\n\nexport default {\n  name: 'Radar',\n  props: {\n    data: {\n      type: Array,\n      default: null\n    }\n  },\n  data () {\n    return {\n      axis1Opts,\n      axis2Opts,\n      scale\n    }\n  }\n}\n</script>\n\n<style scoped>\n\n</style>\n"
  },
  {
    "path": "src/components/Charts/RankList.vue",
    "content": "<template>\n  <div class=\"rank\">\n    <h4 class=\"title\">{{ title }}</h4>\n    <ul class=\"list\">\n      <li :key=\"index\" v-for=\"(item, index) in list\">\n        <span :class=\"index < 3 ? 'active' : null\">{{ index + 1 }}</span>\n        <span>{{ item.name }}</span>\n        <span>{{ item.total }}</span>\n      </li>\n    </ul>\n  </div>\n</template>\n\n<script>\nexport default {\n  name: 'RankList',\n  // ['title', 'list']\n  props: {\n    title: {\n      type: String,\n      default: ''\n    },\n    list: {\n      type: Array,\n      default: null\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n\n  .rank {\n    padding: 0 32px 32px 72px;\n\n    .list {\n      margin: 25px 0 0;\n      padding: 0;\n      list-style: none;\n\n      li {\n        margin-top: 16px;\n\n        span {\n          color: rgba(0, 0, 0, .65);\n          font-size: 14px;\n          line-height: 22px;\n\n          &:first-child {\n            background-color: #f5f5f5;\n            border-radius: 20px;\n            display: inline-block;\n            font-size: 12px;\n            font-weight: 600;\n            margin-right: 24px;\n            height: 20px;\n            line-height: 20px;\n            width: 20px;\n            text-align: center;\n          }\n          &.active {\n            background-color: #314659;\n            color: #fff;\n          }\n          &:last-child {\n            float: right;\n          }\n        }\n      }\n    }\n  }\n\n  .mobile .rank {\n    padding: 0 32px 32px 32px;\n  }\n\n</style>\n"
  },
  {
    "path": "src/components/Charts/TagCloud.vue",
    "content": "<template>\n  <v-chart :width=\"width\" :height=\"height\" :padding=\"[0]\" :data=\"data\" :scale=\"scale\">\n    <v-tooltip :show-title=\"false\" />\n    <v-coord type=\"rect\" direction=\"TL\" />\n    <v-point position=\"x*y\" color=\"category\" shape=\"cloud\" tooltip=\"value*category\" />\n  </v-chart>\n</template>\n\n<script>\nimport { registerShape } from 'viser-vue'\nconst DataSet = require('@antv/data-set')\n\nconst imgUrl = 'https://gw.alipayobjects.com/zos/rmsportal/gWyeGLCdFFRavBGIDzWk.png'\n\nconst scale = [\n  { dataKey: 'x', nice: false },\n  { dataKey: 'y', nice: false }\n]\n\nregisterShape('point', 'cloud', {\n  draw (cfg, container) {\n    return container.addShape('text', {\n      attrs: {\n        fillOpacity: cfg.opacity,\n        fontSize: cfg.origin._origin.size,\n        rotate: cfg.origin._origin.rotate,\n        text: cfg.origin._origin.text,\n        textAlign: 'center',\n        fontFamily: cfg.origin._origin.font,\n        fill: cfg.color,\n        textBaseline: 'Alphabetic',\n        ...cfg.style,\n        x: cfg.x,\n        y: cfg.y\n      }\n    })\n  }\n})\n\nexport default {\n  name: 'TagCloud',\n  props: {\n    tagList: {\n      type: Array,\n      required: true\n    },\n    height: {\n      type: Number,\n      default: 400\n    },\n    width: {\n      type: Number,\n      default: 640\n    }\n  },\n  data () {\n    return {\n      data: [],\n      scale\n    }\n  },\n  watch: {\n    tagList: function (val) {\n      if (val.length > 0) {\n        this.initTagCloud(val)\n      }\n    }\n  },\n  mounted () {\n    if (this.tagList.length > 0) {\n      this.initTagCloud(this.tagList)\n    }\n  },\n  methods: {\n    initTagCloud (dataSource) {\n      const { height, width } = this\n\n      const dv = new DataSet.View().source(dataSource)\n      const range = dv.range('value')\n      const min = range[0]\n      const max = range[1]\n      const imageMask = new Image()\n      imageMask.crossOrigin = ''\n      imageMask.src = imgUrl\n      imageMask.onload = () => {\n        dv.transform({\n          type: 'tag-cloud',\n          fields: ['name', 'value'],\n          size: [width, height],\n          imageMask,\n          font: 'Verdana',\n          padding: 0,\n          timeInterval: 5000, // max execute time\n          rotate () {\n            let random = ~~(Math.random() * 4) % 4\n            if (random === 2) {\n              random = 0\n            }\n            return random * 90 // 0, 90, 270\n          },\n          fontSize (d) {\n            if (d.value) {\n              return ((d.value - min) / (max - min)) * (32 - 8) + 8\n            }\n            return 0\n          }\n        })\n        this.data = dv.rows\n      }\n    }\n  }\n}\n</script>\n"
  },
  {
    "path": "src/components/Charts/TransferBar.vue",
    "content": "<template>\n  <div :style=\"{ padding: '0 0 32px 32px' }\">\n    <h4 :style=\"{ marginBottom: '20px' }\">{{ title }}</h4>\n    <v-chart\n      height=\"254\"\n      :data=\"data\"\n      :scale=\"scale\"\n      :forceFit=\"true\"\n      :padding=\"['auto', 'auto', '40', '50']\">\n      <v-tooltip />\n      <v-axis />\n      <v-bar position=\"x*y\"/>\n    </v-chart>\n  </div>\n</template>\n\n<script>\nconst tooltip = [\n  'x*y',\n  (x, y) => ({\n    name: x,\n    value: y\n  })\n]\nconst scale = [{\n  dataKey: 'x',\n  title: '日期(天)',\n  alias: '日期(天)',\n  min: 2\n}, {\n  dataKey: 'y',\n  title: '流量(Gb)',\n  alias: '流量(Gb)',\n  min: 1\n}]\n\nexport default {\n  name: 'Bar',\n  props: {\n    title: {\n      type: String,\n      default: ''\n    }\n  },\n  data () {\n    return {\n      data: [],\n      scale,\n      tooltip\n    }\n  },\n  created () {\n    this.getMonthBar()\n  },\n  methods: {\n    getMonthBar () {\n      this.$http.get('/analysis/month-bar')\n        .then(res => {\n          this.data = res.result\n        })\n    }\n  }\n}\n</script>\n"
  },
  {
    "path": "src/components/Charts/Trend.vue",
    "content": "<template>\n  <div class=\"chart-trend\">\n    {{ term }}\n    <span>{{ rate }}%</span>\n    <span :class=\"['trend-icon', trend]\"><a-icon :type=\"'caret-' + trend\"/></span>\n  </div>\n</template>\n\n<script>\nexport default {\n  name: 'Trend',\n  props: {\n    term: {\n      type: String,\n      default: '',\n      required: true\n    },\n    percentage: {\n      type: Number,\n      default: null\n    },\n    type: {\n      type: Boolean,\n      default: null\n    },\n    target: {\n      type: Number,\n      default: 0\n    },\n    value: {\n      type: Number,\n      default: 0\n    },\n    fixed: {\n      type: Number,\n      default: 2\n    }\n  },\n  data () {\n    return {\n      trend: this.type && 'up' || 'down',\n      rate: this.percentage\n    }\n  },\n  created () {\n    const type = this.type === null ? this.value >= this.target : this.type\n    this.trend = type ? 'up' : 'down'\n    this.rate = (this.percentage === null ? Math.abs(this.value - this.target) * 100 / this.target : this.percentage).toFixed(this.fixed)\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n  .chart-trend {\n    display: inline-block;\n    font-size: 14px;\n    line-height: 22px;\n\n    .trend-icon {\n      font-size: 12px;\n\n      &.up, &.down {\n        margin-left: 4px;\n        position: relative;\n        top: 1px;\n\n        i {\n          font-size: 12px;\n          transform: scale(.83);\n        }\n      }\n\n      &.up {\n        color: #f5222d;\n      }\n      &.down {\n        color: #52c41a;\n        top: -1px;\n      }\n    }\n  }\n</style>\n"
  },
  {
    "path": "src/components/Charts/chart.less",
    "content": ".antv-chart-mini {\n  position: relative;\n  width: 100%;\n\n  .chart-wrapper {\n    position: absolute;\n    bottom: -28px;\n    width: 100%;\n\n    /*    margin: 0 -5px;\n    overflow: hidden; */\n  }\n}\n"
  },
  {
    "path": "src/components/Charts/smooth.area.less",
    "content": "@import '../index';\n\n@smoothArea-prefix-cls: ~\"@{ant-pro-prefix}-smooth-area\";\n\n.@{smoothArea-prefix-cls} {\n  position: relative;\n  width: 100%;\n\n  .chart-wrapper {\n    position: absolute;\n    bottom: -28px;\n    width: 100%;\n  }\n}\n"
  },
  {
    "path": "src/components/Dialog.js",
    "content": "import Modal from 'ant-design-vue/es/modal'\nexport default (Vue) => {\n  function dialog (component, componentProps, modalProps) {\n    const _vm = this\n    modalProps = modalProps || {}\n    if (!_vm || !_vm._isVue) {\n      return\n    }\n    let dialogDiv = document.querySelector('body>div[type=dialog]')\n    if (!dialogDiv) {\n      dialogDiv = document.createElement('div')\n      dialogDiv.setAttribute('type', 'dialog')\n      document.body.appendChild(dialogDiv)\n    }\n\n    const handle = function (checkFunction, afterHandel) {\n      if (checkFunction instanceof Function) {\n        const res = checkFunction()\n        if (res instanceof Promise) {\n          res.then(c => {\n            c && afterHandel()\n          })\n        } else {\n          res && afterHandel()\n        }\n      } else {\n        // checkFunction && afterHandel()\n        checkFunction || afterHandel()\n      }\n    }\n\n    const dialogInstance = new Vue({\n      data () {\n        return {\n          visible: true\n        }\n      },\n      router: _vm.$router,\n      store: _vm.$store,\n      mounted () {\n        this.$on('close', (v) => {\n          this.handleClose()\n        })\n      },\n      methods: {\n        handleClose () {\n          handle(this.$refs._component.onCancel, () => {\n            this.visible = false\n            this.$refs._component.$emit('close')\n            this.$refs._component.$emit('cancel')\n            dialogInstance.$destroy()\n          })\n        },\n        handleOk () {\n          handle(this.$refs._component.onOK || this.$refs._component.onOk, () => {\n            this.visible = false\n            this.$refs._component.$emit('close')\n            this.$refs._component.$emit('ok')\n            dialogInstance.$destroy()\n          })\n        }\n      },\n      render: function (h) {\n        const that = this\n        const modalModel = modalProps && modalProps.model\n        if (modalModel) {\n          delete modalProps.model\n        }\n        const ModalProps = Object.assign({}, modalModel && { model: modalModel } || {}, {\n          attrs: Object.assign({}, {\n            ...(modalProps.attrs || modalProps)\n          }, {\n            visible: this.visible\n          }),\n          on: Object.assign({}, {\n            ...(modalProps.on || modalProps)\n          }, {\n            ok: () => {\n              that.handleOk()\n            },\n            cancel: () => {\n              that.handleClose()\n            }\n          })\n        })\n\n        const componentModel = componentProps && componentProps.model\n        if (componentModel) {\n          delete componentProps.model\n        }\n        const ComponentProps = Object.assign({}, componentModel && { model: componentModel } || {}, {\n          ref: '_component',\n          attrs: Object.assign({}, {\n            ...((componentProps && componentProps.attrs) || componentProps)\n          }),\n          on: Object.assign({}, {\n            ...((componentProps && componentProps.on) || componentProps)\n          })\n        })\n\n        return h(Modal, ModalProps, [h(component, ComponentProps)])\n      }\n    }).$mount(dialogDiv)\n  }\n\n  Object.defineProperty(Vue.prototype, '$dialog', {\n    get: () => {\n      return function () {\n        dialog.apply(this, arguments)\n      }\n    }\n  })\n}\n"
  },
  {
    "path": "src/components/Editor/QuillEditor.vue",
    "content": "<template>\n  <div :class=\"prefixCls\">\n    <quill-editor\n      v-model=\"content\"\n      ref=\"myQuillEditor\"\n      :options=\"editorOption\"\n      @blur=\"onEditorBlur($event)\"\n      @focus=\"onEditorFocus($event)\"\n      @ready=\"onEditorReady($event)\"\n      @change=\"onEditorChange($event)\">\n    </quill-editor>\n\n  </div>\n</template>\n\n<script>\nimport 'quill/dist/quill.core.css'\nimport 'quill/dist/quill.snow.css'\nimport 'quill/dist/quill.bubble.css'\n\nimport { quillEditor } from 'vue-quill-editor'\n\nexport default {\n  name: 'QuillEditor',\n  components: {\n    quillEditor\n  },\n  props: {\n    prefixCls: {\n      type: String,\n      default: 'ant-editor-quill'\n    },\n    // 表单校验用字段\n    // eslint-disable-next-line\n    value: {\n      type: String\n    }\n  },\n  data () {\n    return {\n      content: null,\n      editorOption: {\n        // some quill options\n      }\n    }\n  },\n  methods: {\n    onEditorBlur (quill) {\n      console.log('editor blur!', quill)\n    },\n    onEditorFocus (quill) {\n      console.log('editor focus!', quill)\n    },\n    onEditorReady (quill) {\n      console.log('editor ready!', quill)\n    },\n    onEditorChange ({ quill, html, text }) {\n      console.log('editor change!', quill, html, text)\n      this.$emit('change', html)\n    }\n  },\n  watch: {\n    value (val) {\n      this.content = val\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n@import url('../index.less');\n\n/* 覆盖 quill 默认边框圆角为 ant 默认圆角，用于统一 ant 组件风格 */\n.ant-editor-quill {\n  line-height: initial;\n  :deep(.ql-toolbar.ql-snow) {\n    border-radius: @border-radius-base @border-radius-base 0 0;\n  }\n  :deep(.ql-container.ql-snow) {\n    border-radius: 0 0 @border-radius-base @border-radius-base;\n  }\n}\n</style>\n"
  },
  {
    "path": "src/components/Editor/WangEditor.vue",
    "content": "<template>\n  <div :class=\"prefixCls\">\n    <div ref=\"editor\" class=\"editor-wrapper\"></div>\n  </div>\n</template>\n\n<script>\nimport WEditor from 'wangeditor'\n\nexport default {\n  name: 'WangEditor',\n  props: {\n    prefixCls: {\n      type: String,\n      default: 'ant-editor-wang'\n    },\n    // eslint-disable-next-line\n    value: {\n      type: String\n    }\n  },\n  data () {\n    return {\n      editor: null,\n      editorContent: null\n    }\n  },\n  watch: {\n    value (val) {\n      this.editorContent = val\n      this.editor.txt.html(val)\n    }\n  },\n  mounted () {\n    this.initEditor()\n  },\n  methods: {\n    initEditor () {\n      this.editor = new WEditor(this.$refs.editor)\n      // this.editor.onchangeTimeout = 200\n      this.editor.customConfig.onchange = (html) => {\n        this.editorContent = html\n        this.$emit('change', this.editorContent)\n      }\n      this.editor.create()\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n.ant-editor-wang {\n  .editor-wrapper {\n    text-align: left;\n  }\n}\n</style>\n"
  },
  {
    "path": "src/components/Ellipsis/Ellipsis.vue",
    "content": "<script>\nimport Tooltip from 'ant-design-vue/es/tooltip'\nimport { cutStrByFullLength, getStrFullLength } from '@/components/_util/util'\n/*\n    const isSupportLineClamp = document.body.style.webkitLineClamp !== undefined;\n\n    const TooltipOverlayStyle = {\n      overflowWrap: 'break-word',\n      wordWrap: 'break-word',\n    };\n  */\n\nexport default {\n  name: 'Ellipsis',\n  components: {\n    Tooltip\n  },\n  props: {\n    prefixCls: {\n      type: String,\n      default: 'ant-pro-ellipsis'\n    },\n    tooltip: {\n      type: Boolean\n    },\n    length: {\n      type: Number,\n      required: true\n    },\n    lines: {\n      type: Number,\n      default: 1\n    },\n    fullWidthRecognition: {\n      type: Boolean,\n      default: false\n    }\n  },\n  methods: {\n    getStrDom (str, fullLength) {\n      return (\n        <span>{ cutStrByFullLength(str, this.length) + (fullLength > this.length ? '...' : '') }</span>\n      )\n    },\n    getTooltip (fullStr, fullLength) {\n      return (\n        <Tooltip>\n          <template slot=\"title\">{ fullStr }</template>\n          { this.getStrDom(fullStr, fullLength) }\n        </Tooltip>\n      )\n    }\n  },\n  render () {\n    const { tooltip, length } = this.$props\n    const str = this.$slots.default.map(vNode => vNode.text).join('')\n    const fullLength = getStrFullLength(str)\n    const strDom = tooltip && fullLength > length ? this.getTooltip(str, fullLength) : this.getStrDom(str, fullLength)\n    return (\n      strDom\n    )\n  }\n}\n</script>\n"
  },
  {
    "path": "src/components/Ellipsis/index.js",
    "content": "import Ellipsis from './Ellipsis'\n\nexport default Ellipsis\n"
  },
  {
    "path": "src/components/Ellipsis/index.md",
    "content": "# Ellipsis 文本自动省略号\n\n文本过长自动处理省略号，支持按照文本长度和最大行数两种方式截取。\n\n\n\n引用方式：\n\n```javascript\nimport Ellipsis from '@/components/Ellipsis'\n\nexport default {\n    components: {\n        Ellipsis\n    }\n}\n```\n\n\n\n## 代码演示  [demo](https://pro.loacg.com/test/home)\n\n```html\n<ellipsis :length=\"100\" tooltip>\n        There were injuries alleged in three cases in 2015, and a\n        fourth incident in September, according to the safety recall report. After meeting with US regulators in October, the firm decided to issue a voluntary recall.\n</ellipsis>\n```\n\n\n\n## API\n\n\n参数 | 说明 | 类型 | 默认值\n----|------|-----|------\ntooltip | 移动到文本展示完整内容的提示 | boolean | -\nlength | 在按照长度截取下的文本最大字符数，超过则截取省略 | number | -"
  },
  {
    "path": "src/components/FooterToolbar/FooterToolBar.vue",
    "content": "<template>\n  <div :class=\"prefixCls\" :style=\"{ width: barWidth, transition: '0.3s all' }\">\n    <div style=\"float: left\">\n      <slot name=\"extra\">{{ extra }}</slot>\n    </div>\n    <div style=\"float: right\">\n      <slot></slot>\n    </div>\n  </div>\n</template>\n\n<script>\nexport default {\n  name: 'FooterToolBar',\n  props: {\n    prefixCls: {\n      type: String,\n      default: 'ant-pro-footer-toolbar'\n    },\n    collapsed: {\n      type: Boolean,\n      default: false\n    },\n    isMobile: {\n      type: Boolean,\n      default: false\n    },\n    siderWidth: {\n      type: Number,\n      default: undefined\n    },\n    extra: {\n      type: [String, Object],\n      default: ''\n    }\n  },\n  computed: {\n    barWidth () {\n      return this.isMobile ? undefined : `calc(100% - ${this.collapsed ? 80 : this.siderWidth || 256}px)`\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n\n</style>\n"
  },
  {
    "path": "src/components/FooterToolbar/index.js",
    "content": "import FooterToolBar from './FooterToolBar'\nimport './index.less'\n\nexport default FooterToolBar\n"
  },
  {
    "path": "src/components/FooterToolbar/index.less",
    "content": "@import '../index';\n\n@footer-toolbar-prefix-cls: ~\"@{ant-pro-prefix}-footer-toolbar\";\n\n.@{footer-toolbar-prefix-cls} {\n  position: fixed;\n  right: 0;\n  bottom: 0;\n  z-index: 9;\n  width: 100%;\n  height: 56px;\n  padding: 0 24px;\n  line-height: 56px;\n  background: #fff;\n  box-shadow: 0 -1px 2px rgb(0 0 0 / 3%);\n  border-top: 1px solid #e8e8e8;\n\n  &::after {\n    display: block;\n    clear: both;\n    content: '';\n  }\n}\n"
  },
  {
    "path": "src/components/FooterToolbar/index.md",
    "content": "# FooterToolbar 底部工具栏\n\n固定在底部的工具栏。\n\n\n\n## 何时使用\n\n固定在内容区域的底部，不随滚动条移动，常用于长页面的数据搜集和提交工作。\n\n\n\n引用方式：\n\n```javascript\nimport FooterToolBar from '@/components/FooterToolbar'\n\nexport default {\n    components: {\n        FooterToolBar\n    }\n}\n```\n\n\n\n## 代码演示\n\n```html\n<footer-tool-bar>\n    <a-button type=\"primary\" @click=\"validate\" :loading=\"loading\">提交</a-button>\n</footer-tool-bar>\n```\n或\n```html\n<footer-tool-bar extra=\"扩展信息提示\">\n    <a-button type=\"primary\" @click=\"validate\" :loading=\"loading\">提交</a-button>\n</footer-tool-bar>\n```\n\n\n## API\n\n参数 | 说明 | 类型 | 默认值\n----|------|-----|------\nchildren (slot) | 工具栏内容，向右对齐 | - | -\nextra | 额外信息，向左对齐 | String, Object | -\n\n"
  },
  {
    "path": "src/components/GlobalFooter/index.vue",
    "content": "<template>\n  <global-footer class=\"footer custom-render\">\n    <template v-slot:links>\n      <a href=\"https://www.github.com/vueComponent/pro-layout\" target=\"_blank\">Pro Layout</a>\n      <a href=\"https://www.github.com/vueComponent/ant-design-vue-pro\" target=\"_blank\">Github</a>\n      <a href=\"https://www.github.com/sendya/\" target=\"_blank\">@Sendya</a>\n    </template>\n    <template v-slot:copyright>\n      <a href=\"https://github.com/vueComponent\" target=\"_blank\">vueComponent</a>\n    </template>\n  </global-footer>\n</template>\n\n<script>\nimport { GlobalFooter } from '@ant-design-vue/pro-layout'\n\nexport default {\n  name: 'ProGlobalFooter',\n  components: {\n    GlobalFooter\n  }\n}\n</script>\n"
  },
  {
    "path": "src/components/GlobalHeader/AvatarDropdown.vue",
    "content": "<template>\n  <a-dropdown v-if=\"currentUser && currentUser.name\" placement=\"bottomRight\">\n    <span class=\"ant-pro-account-avatar\">\n      <a-avatar size=\"small\" src=\"https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png\" class=\"antd-pro-global-header-index-avatar\" />\n      <span>{{ currentUser.name }}</span>\n    </span>\n    <template v-slot:overlay>\n      <a-menu class=\"ant-pro-drop-down menu\" :selected-keys=\"[]\">\n        <a-menu-item v-if=\"menu\" key=\"center\" @click=\"handleToCenter\">\n          <a-icon type=\"user\" />\n          {{ $t('menu.account.center') }}\n        </a-menu-item>\n        <a-menu-item v-if=\"menu\" key=\"settings\" @click=\"handleToSettings\">\n          <a-icon type=\"setting\" />\n          {{ $t('menu.account.settings') }}\n        </a-menu-item>\n        <a-menu-divider v-if=\"menu\" />\n        <a-menu-item key=\"logout\" @click=\"handleLogout\">\n          <a-icon type=\"logout\" />\n          {{ $t('menu.account.logout') }}\n        </a-menu-item>\n      </a-menu>\n    </template>\n  </a-dropdown>\n  <span v-else>\n    <a-spin size=\"small\" :style=\"{ marginLeft: 8, marginRight: 8 }\" />\n  </span>\n</template>\n\n<script>\nimport { Modal } from 'ant-design-vue'\n\nexport default {\n  name: 'AvatarDropdown',\n  props: {\n    currentUser: {\n      type: Object,\n      default: () => null\n    },\n    menu: {\n      type: Boolean,\n      default: true\n    }\n  },\n  methods: {\n    handleToCenter () {\n      this.$router.push({ path: '/account/center' })\n    },\n    handleToSettings () {\n      this.$router.push({ path: '/account/settings' })\n    },\n    handleLogout (e) {\n      Modal.confirm({\n        title: this.$t('layouts.usermenu.dialog.title'),\n        content: this.$t('layouts.usermenu.dialog.content'),\n        onOk: () => {\n          // return new Promise((resolve, reject) => {\n          //   setTimeout(Math.random() > 0.5 ? resolve : reject, 1500)\n          // }).catch(() => console.log('Oops errors!'))\n          return this.$store.dispatch('Logout').then(() => {\n            this.$router.push({ name: 'login' })\n          })\n        },\n        onCancel () {}\n      })\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n.ant-pro-drop-down {\n  :deep(.action) {\n    margin-right: 8px;\n  }\n  :deep(.ant-dropdown-menu-item) {\n    min-width: 160px;\n  }\n}\n</style>\n"
  },
  {
    "path": "src/components/GlobalHeader/RightContent.vue",
    "content": "<template>\n  <div :class=\"wrpCls\">\n    <avatar-dropdown :menu=\"showMenu\" :current-user=\"currentUser\" :class=\"prefixCls\" />\n    <select-lang :class=\"prefixCls\" />\n  </div>\n</template>\n\n<script>\nimport AvatarDropdown from './AvatarDropdown'\nimport SelectLang from '@/components/SelectLang'\n\nexport default {\n  name: 'RightContent',\n  components: {\n    AvatarDropdown,\n    SelectLang\n  },\n  props: {\n    prefixCls: {\n      type: String,\n      default: 'ant-pro-global-header-index-action'\n    },\n    isMobile: {\n      type: Boolean,\n      default: () => false\n    },\n    topMenu: {\n      type: Boolean,\n      required: true\n    },\n    theme: {\n      type: String,\n      required: true\n    }\n  },\n  data () {\n    return {\n      showMenu: true,\n      currentUser: {}\n    }\n  },\n  computed: {\n    wrpCls () {\n      return {\n        'ant-pro-global-header-index-right': true,\n        [`ant-pro-global-header-index-${(this.isMobile || !this.topMenu) ? 'light' : this.theme}`]: true\n      }\n    }\n  },\n  mounted () {\n    setTimeout(() => {\n      this.currentUser = {\n        name: 'Serati Ma'\n      }\n    }, 1500)\n  }\n}\n</script>\n"
  },
  {
    "path": "src/components/IconSelector/IconSelector.vue",
    "content": "<template>\n  <div :class=\"prefixCls\">\n    <a-tabs v-model=\"currentTab\" @change=\"handleTabChange\">\n      <a-tab-pane v-for=\"v in icons\" :tab=\"v.title\" :key=\"v.key\">\n        <ul>\n          <li v-for=\"(icon, key) in v.icons\" :key=\"`${v.key}-${key}`\" :class=\"{ 'active': selectedIcon==icon }\" @click=\"handleSelectedIcon(icon)\" >\n            <a-icon :type=\"icon\" :style=\"{ fontSize: '36px' }\" />\n          </li>\n        </ul>\n      </a-tab-pane>\n    </a-tabs>\n  </div>\n</template>\n\n<script>\nimport icons from './icons'\n\nexport default {\n  name: 'IconSelect',\n  props: {\n    prefixCls: {\n      type: String,\n      default: 'ant-pro-icon-selector'\n    },\n    // eslint-disable-next-line\n    value: {\n      type: String\n    }\n  },\n  data () {\n    return {\n      selectedIcon: this.value || '',\n      currentTab: 'directional',\n      icons\n    }\n  },\n  watch: {\n    value (val) {\n      this.selectedIcon = val\n      this.autoSwitchTab()\n    }\n  },\n  created () {\n    if (this.value) {\n      this.autoSwitchTab()\n    }\n  },\n  methods: {\n    handleSelectedIcon (icon) {\n      this.selectedIcon = icon\n      this.$emit('change', icon)\n    },\n    handleTabChange (activeKey) {\n      this.currentTab = activeKey\n    },\n    autoSwitchTab () {\n      icons.some(item => item.icons.some(icon => icon === this.value) && (this.currentTab = item.key))\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n  @import \"../index.less\";\n\n  ul{\n    list-style: none;\n    padding: 0;\n    overflow-y: scroll;\n    height: 250px;\n\n    li{\n      display: inline-block;\n      padding: @padding-sm;\n      margin: 3px 0;\n      border-radius: @border-radius-base;\n\n      &:hover, &.active{\n        // box-shadow: 0px 0px 5px 2px @primary-color;\n        cursor: pointer;\n        color: @white;\n        background-color: @primary-color;\n      }\n    }\n  }\n</style>\n"
  },
  {
    "path": "src/components/IconSelector/README.md",
    "content": "IconSelector\n====\n\n> 图标选择组件，常用于为某一个数据设定一个图标时使用\n> eg: 设定菜单列表时，为每个菜单设定一个图标\n\n该组件由 [@Saraka](https://github.com/saraka-tsukai) 封装\n\n\n\n### 使用方式\n\n```vue\n<template>\n\t<div>\n       <icon-selector @change=\"handleIconChange\"/>\n    </div>\n</template>\n\n<script>\nimport IconSelector from '@/components/IconSelector'\n\nexport default {\n  name: 'YourView',\n  components: {\n    IconSelector\n  },\n  data () {\n    return {\n    }\n  },\n  methods: {\n    handleIconChange (icon) {\n      console.log('change Icon', icon)\n    }\n  }\n}\n</script>\n```\n\n\n\n### 事件\n\n\n| 名称   | 说明                       | 类型   | 默认值 |\n| ------ | -------------------------- | ------ | ------ |\n| change | 当改变了 `icon` 选中项触发 | String | -      |\n"
  },
  {
    "path": "src/components/IconSelector/icons.js",
    "content": "/**\n * 增加新的图标时，请遵循以下数据结构\n * Adding new icon please follow the data structure below\n */\nexport default [\n  {\n    key: 'directional',\n    title: '方向性图标',\n    icons: ['step-backward', 'step-forward', 'fast-backward', 'fast-forward', 'shrink', 'arrows-alt', 'down', 'up', 'left', 'right', 'caret-up', 'caret-down', 'caret-left', 'caret-right', 'up-circle', 'down-circle', 'left-circle', 'right-circle', 'double-right', 'double-left', 'vertical-left', 'vertical-right', 'forward', 'backward', 'rollback', 'enter', 'retweet', 'swap', 'swap-left', 'swap-right', 'arrow-up', 'arrow-down', 'arrow-left', 'arrow-right', 'play-circle', 'up-square', 'down-square', 'left-square', 'right-square', 'login', 'logout', 'menu-fold', 'menu-unfold', 'border-bottom', 'border-horizontal', 'border-inner', 'border-left', 'border-right', 'border-top', 'border-verticle', 'pic-center', 'pic-left', 'pic-right', 'radius-bottomleft', 'radius-bottomright', 'radius-upleft', 'fullscreen', 'fullscreen-exit']\n  },\n  {\n    key: 'suggested',\n    title: '提示建议性图标',\n    icons: ['question', 'question-circle', 'plus', 'plus-circle', 'pause', 'pause-circle', 'minus', 'minus-circle', 'plus-square', 'minus-square', 'info', 'info-circle', 'exclamation', 'exclamation-circle', 'close', 'close-circle', 'close-square', 'check', 'check-circle', 'check-square', 'clock-circle', 'warning', 'issues-close', 'stop']\n  },\n  {\n    key: 'editor',\n    title: '编辑类图标',\n    icons: ['edit', 'form', 'copy', 'scissor', 'delete', 'snippets', 'diff', 'highlight', 'align-center', 'align-left', 'align-right', 'bg-colors', 'bold', 'italic', 'underline', 'strikethrough', 'redo', 'undo', 'zoom-in', 'zoom-out', 'font-colors', 'font-size', 'line-height', 'colum-height', 'dash', 'small-dash', 'sort-ascending', 'sort-descending', 'drag', 'ordered-list', 'radius-setting']\n  },\n  {\n    key: 'data',\n    title: '数据类图标',\n    icons: ['area-chart', 'pie-chart', 'bar-chart', 'dot-chart', 'line-chart', 'radar-chart', 'heat-map', 'fall', 'rise', 'stock', 'box-plot', 'fund', 'sliders']\n  },\n  {\n    key: 'brand_logo',\n    title: '网站通用图标',\n    icons: ['lock', 'unlock', 'bars', 'book', 'calendar', 'cloud', 'cloud-download', 'code', 'copy', 'credit-card', 'delete', 'desktop', 'download', 'ellipsis', 'file', 'file-text', 'file-unknown', 'file-pdf', 'file-word', 'file-excel', 'file-jpg', 'file-ppt', 'file-markdown', 'file-add', 'folder', 'folder-open', 'folder-add', 'hdd', 'frown', 'meh', 'smile', 'inbox', 'laptop', 'appstore', 'link', 'mail', 'mobile', 'notification', 'paper-clip', 'picture', 'poweroff', 'reload', 'search', 'setting', 'share-alt', 'shopping-cart', 'tablet', 'tag', 'tags', 'to-top', 'upload', 'user', 'video-camera', 'home', 'loading', 'loading-3-quarters', 'cloud-upload', 'star', 'heart', 'environment', 'eye', 'camera', 'save', 'team', 'solution', 'phone', 'filter', 'exception', 'export', 'customer-service', 'qrcode', 'scan', 'like', 'dislike', 'message', 'pay-circle', 'calculator', 'pushpin', 'bulb', 'select', 'switcher', 'rocket', 'bell', 'disconnect', 'database', 'compass', 'barcode', 'hourglass', 'key', 'flag', 'layout', 'printer', 'sound', 'usb', 'skin', 'tool', 'sync', 'wifi', 'car', 'schedule', 'user-add', 'user-delete', 'usergroup-add', 'usergroup-delete', 'man', 'woman', 'shop', 'gift', 'idcard', 'medicine-box', 'red-envelope', 'coffee', 'copyright', 'trademark', 'safety', 'wallet', 'bank', 'trophy', 'contacts', 'global', 'shake', 'api', 'fork', 'dashboard', 'table', 'profile', 'alert', 'audit', 'branches', 'build', 'border', 'crown', 'experiment', 'fire', 'money-collect', 'property-safety', 'read', 'reconciliation', 'rest', 'security-scan', 'insurance', 'interation', 'safety-certificate', 'project', 'thunderbolt', 'block', 'cluster', 'deployment-unit', 'dollar', 'euro', 'pound', 'file-done', 'file-exclamation', 'file-protect', 'file-search', 'file-sync', 'gateway', 'gold', 'robot', 'shopping']\n  },\n  {\n    key: 'application',\n    title: '品牌和标识',\n    icons: ['android', 'apple', 'windows', 'ie', 'chrome', 'github', 'aliwangwang', 'dingding', 'weibo-square', 'weibo-circle', 'taobao-circle', 'html5', 'weibo', 'twitter', 'wechat', 'youtube', 'alipay-circle', 'taobao', 'skype', 'qq', 'medium-workmark', 'gitlab', 'medium', 'linkedin', 'google-plus', 'dropbox', 'facebook', 'codepen', 'code-sandbox', 'amazon', 'google', 'codepen-circle', 'alipay', 'ant-design', 'aliyun', 'zhihu', 'slack', 'slack-square', 'behance', 'behance-square', 'dribbble', 'dribbble-square', 'instagram', 'yuque', 'alibaba', 'yahoo']\n  }\n]\n"
  },
  {
    "path": "src/components/IconSelector/index.js",
    "content": "import IconSelector from './IconSelector'\nexport default IconSelector\n"
  },
  {
    "path": "src/components/MultiTab/MultiTab.vue",
    "content": "<script>\nimport events from './events'\n\nexport default {\n  name: 'MultiTab',\n  data () {\n    return {\n      fullPathList: [],\n      pages: [],\n      activeKey: '',\n      newTabIndex: 0\n    }\n  },\n  created () {\n    // bind event\n    events.$on('open', val => {\n      if (!val) {\n        throw new Error(`multi-tab: open tab ${val} err`)\n      }\n      this.activeKey = val\n    }).$on('close', val => {\n      if (!val) {\n        this.closeThat(this.activeKey)\n        return\n      }\n      this.closeThat(val)\n    }).$on('rename', ({ key, name }) => {\n      console.log('rename', key, name)\n      try {\n        const item = this.pages.find(item => item.path === key)\n        item.meta.customTitle = name\n        this.$forceUpdate()\n      } catch (e) {\n      }\n    })\n\n    this.pages.push(this.$route)\n    this.fullPathList.push(this.$route.fullPath)\n    this.selectedLastPath()\n  },\n  methods: {\n    onEdit (targetKey, action) {\n      this[action](targetKey)\n    },\n    remove (targetKey) {\n      this.pages = this.pages.filter(page => page.fullPath !== targetKey)\n      this.fullPathList = this.fullPathList.filter(path => path !== targetKey)\n      // 判断当前标签是否关闭，若关闭则跳转到最后一个还存在的标签页\n      if (!this.fullPathList.includes(this.activeKey)) {\n        this.selectedLastPath()\n      }\n    },\n    selectedLastPath () {\n      this.activeKey = this.fullPathList[this.fullPathList.length - 1]\n    },\n\n    // content menu\n    closeThat (e) {\n      // 判断是否为最后一个标签页，如果是最后一个，则无法被关闭\n      if (this.fullPathList.length > 1) {\n        this.remove(e)\n      } else {\n        this.$message.info('这是最后一个标签了, 无法被关闭')\n      }\n    },\n    closeLeft (e) {\n      const currentIndex = this.fullPathList.indexOf(e)\n      if (currentIndex > 0) {\n        this.fullPathList.forEach((item, index) => {\n          if (index < currentIndex) {\n            this.remove(item)\n          }\n        })\n      } else {\n        this.$message.info('左侧没有标签')\n      }\n    },\n    closeRight (e) {\n      const currentIndex = this.fullPathList.indexOf(e)\n      if (currentIndex < (this.fullPathList.length - 1)) {\n        this.fullPathList.forEach((item, index) => {\n          if (index > currentIndex) {\n            this.remove(item)\n          }\n        })\n      } else {\n        this.$message.info('右侧没有标签')\n      }\n    },\n    closeAll (e) {\n      const currentIndex = this.fullPathList.indexOf(e)\n      this.fullPathList.forEach((item, index) => {\n        if (index !== currentIndex) {\n          this.remove(item)\n        }\n      })\n    },\n    closeMenuClick (key, route) {\n      this[key](route)\n    },\n    renderTabPaneMenu (e) {\n      return (\n        <a-menu {...{ on: { click: ({ key, item, domEvent }) => { this.closeMenuClick(key, e) } } }}>\n          <a-menu-item key=\"closeThat\">关闭当前标签</a-menu-item>\n          <a-menu-item key=\"closeRight\">关闭右侧</a-menu-item>\n          <a-menu-item key=\"closeLeft\">关闭左侧</a-menu-item>\n          <a-menu-item key=\"closeAll\">关闭全部</a-menu-item>\n        </a-menu>\n      )\n    },\n    // render\n    renderTabPane (title, keyPath) {\n      const menu = this.renderTabPaneMenu(keyPath)\n\n      return (\n        <a-dropdown overlay={menu} trigger={['contextmenu']}>\n          <span style={{ userSelect: 'none' }}>{ title }</span>\n        </a-dropdown>\n      )\n    }\n  },\n  watch: {\n    '$route': function (newVal) {\n      this.activeKey = newVal.fullPath\n      if (this.fullPathList.indexOf(newVal.fullPath) < 0) {\n        this.fullPathList.push(newVal.fullPath)\n        this.pages.push(newVal)\n      }\n    },\n    activeKey: function (newPathKey) {\n      this.$router.push({ path: newPathKey })\n    }\n  },\n  render () {\n    const { onEdit, $data: { pages } } = this\n    const panes = pages.map(page => {\n      return (\n        <a-tab-pane\n          style={{ height: 0 }}\n          tab={this.renderTabPane(page.meta.customTitle || page.meta.title, page.fullPath)}\n          key={page.fullPath} closable={pages.length > 1}\n        >\n        </a-tab-pane>)\n    })\n\n    return (\n      <div class=\"ant-pro-multi-tab\">\n        <div class=\"ant-pro-multi-tab-wrapper\">\n          <a-tabs\n            hideAdd\n            type={'editable-card'}\n            v-model={this.activeKey}\n            tabBarStyle={{ background: '#FFF', margin: 0, paddingLeft: '16px', paddingTop: '1px' }}\n            {...{ on: { edit: onEdit } }}>\n            {panes}\n          </a-tabs>\n        </div>\n      </div>\n    )\n  }\n}\n</script>\n"
  },
  {
    "path": "src/components/MultiTab/events.js",
    "content": "import Vue from 'vue'\nexport default new Vue()\n"
  },
  {
    "path": "src/components/MultiTab/index.js",
    "content": "import events from './events'\nimport MultiTab from './MultiTab'\nimport './index.less'\n\nconst api = {\n  /**\n   * open new tab on route fullPath\n   * @param config\n   */\n  open: function (config) {\n    events.$emit('open', config)\n  },\n  rename: function (key, name) {\n    events.$emit('rename', { key: key, name: name })\n  },\n  /**\n   * close current page\n   */\n  closeCurrentPage: function () {\n    this.close()\n  },\n  /**\n   * close route fullPath tab\n   * @param config\n   */\n  close: function (config) {\n    events.$emit('close', config)\n  }\n}\n\nMultiTab.install = function (Vue) {\n  if (Vue.prototype.$multiTab) {\n    return\n  }\n  api.instance = events\n  Vue.prototype.$multiTab = api\n  Vue.component('multi-tab', MultiTab)\n}\n\nexport default MultiTab\n"
  },
  {
    "path": "src/components/MultiTab/index.less",
    "content": "@import '../index';\n\n@multi-tab-prefix-cls: ~\"@{ant-pro-prefix}-multi-tab\";\n@multi-tab-wrapper-prefix-cls: ~\"@{ant-pro-prefix}-multi-tab-wrapper\";\n\n/*\n.topmenu .@{multi-tab-prefix-cls} {\n  max-width: 1200px;\n  margin: -23px auto 24px auto;\n}\n*/\n.@{multi-tab-prefix-cls} {\n  margin: -23px -24px 24px;\n  background: #fff;\n}\n\n.topmenu .@{multi-tab-wrapper-prefix-cls} {\n  max-width: 1200px;\n  margin: 0 auto;\n}\n\n.topmenu.content-width-Fluid .@{multi-tab-wrapper-prefix-cls} {\n  max-width: 100%;\n  margin: 0 auto;\n}\n"
  },
  {
    "path": "src/components/NProgress/nprogress.less",
    "content": "@import url('../index.less');\n\n/* Make clicks pass-through */\n#nprogress {\n  pointer-events: none;\n}\n\n#nprogress .bar {\n  position: fixed;\n  top: 0;\n  left: 0;\n  z-index: 1031;\n  width: 100%;\n  height: 2px;\n  background: @primary-color;\n}\n\n/* Fancy blur effect */\n#nprogress .peg {\n  position: absolute;\n  right: 0;\n  display: block;\n  width: 100px;\n  height: 100%;\n  opacity: 1;\n  transform: rotate(3deg) translate(0, -4px);\n  transform: rotate(3deg) translate(0, -4px);\n  transform: rotate(3deg) translate(0, -4px);\n  box-shadow: 0 0 10px @primary-color, 0 0 5px @primary-color;\n}\n\n/* Remove these to get rid of the spinner */\n#nprogress .spinner {\n  position: fixed;\n  top: 15px;\n  right: 15px;\n  z-index: 1031;\n  display: block;\n}\n\n#nprogress .spinner-icon {\n  width: 18px;\n  height: 18px;\n  box-sizing: border-box;\n  border: solid 2px transparent;\n  border-top-color: @primary-color;\n  border-left-color: @primary-color;\n  border-radius: 50%;\n  animation: nprogress-spinner 400ms linear infinite;\n  animation: nprogress-spinner 400ms linear infinite;\n}\n\n.nprogress-custom-parent {\n  position: relative;\n  overflow: hidden;\n}\n\n.nprogress-custom-parent #nprogress .spinner,\n.nprogress-custom-parent #nprogress .bar {\n  position: absolute;\n}\n\n@keyframes nprogress-spinner {\n  0% { transform: rotate(0deg); }\n  100% { transform: rotate(360deg); }\n}\n@keyframes nprogress-spinner {\n  0% { transform: rotate(0deg); }\n  100% { transform: rotate(360deg); }\n}\n"
  },
  {
    "path": "src/components/NoticeIcon/NoticeIcon.vue",
    "content": "<template>\n  <a-popover\n    v-model=\"visible\"\n    trigger=\"click\"\n    placement=\"bottomRight\"\n    overlayClassName=\"header-notice-wrapper\"\n    :getPopupContainer=\"() => $refs.noticeRef.parentElement\"\n    :autoAdjustOverflow=\"true\"\n    :arrowPointAtCenter=\"true\"\n    :overlayStyle=\"{ width: '300px', top: '50px' }\"\n  >\n    <template slot=\"content\">\n      <a-spin :spinning=\"loading\">\n        <a-tabs>\n          <a-tab-pane tab=\"通知\" key=\"1\">\n            <a-list>\n              <a-list-item>\n                <a-list-item-meta title=\"你收到了 14 份新周报\" description=\"一年前\">\n                  <a-avatar style=\"background-color: white\" slot=\"avatar\" src=\"https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png\"/>\n                </a-list-item-meta>\n              </a-list-item>\n              <a-list-item>\n                <a-list-item-meta title=\"你推荐的 曲妮妮 已通过第三轮面试\" description=\"一年前\">\n                  <a-avatar style=\"background-color: white\" slot=\"avatar\" src=\"https://gw.alipayobjects.com/zos/rmsportal/OKJXDXrmkNshAMvwtvhu.png\"/>\n                </a-list-item-meta>\n              </a-list-item>\n              <a-list-item>\n                <a-list-item-meta title=\"这种模板可以区分多种通知类型\" description=\"一年前\">\n                  <a-avatar style=\"background-color: white\" slot=\"avatar\" src=\"https://gw.alipayobjects.com/zos/rmsportal/kISTdvpyTAhtGxpovNWd.png\"/>\n                </a-list-item-meta>\n              </a-list-item>\n            </a-list>\n          </a-tab-pane>\n          <a-tab-pane tab=\"消息\" key=\"2\">\n            123\n          </a-tab-pane>\n          <a-tab-pane tab=\"待办\" key=\"3\">\n            123\n          </a-tab-pane>\n        </a-tabs>\n      </a-spin>\n    </template>\n    <span @click=\"fetchNotice\" class=\"header-notice\" ref=\"noticeRef\" style=\"padding: 0 18px\">\n      <a-badge count=\"12\">\n        <a-icon style=\"font-size: 16px; padding: 4px\" type=\"bell\" />\n      </a-badge>\n    </span>\n  </a-popover>\n</template>\n\n<script>\nexport default {\n  name: 'HeaderNotice',\n  data () {\n    return {\n      loading: false,\n      visible: false\n    }\n  },\n  methods: {\n    fetchNotice () {\n      if (!this.visible) {\n        this.loading = true\n        setTimeout(() => {\n          this.loading = false\n        }, 2000)\n      } else {\n        this.loading = false\n      }\n      this.visible = !this.visible\n    }\n  }\n}\n</script>\n\n<style lang=\"css\">\n  .header-notice-wrapper {\n    top: 50px !important;\n  }\n</style>\n<style lang=\"less\" scoped>\n  .header-notice{\n    display: inline-block;\n    transition: all 0.3s;\n\n    span {\n      vertical-align: initial;\n    }\n  }\n</style>\n"
  },
  {
    "path": "src/components/NoticeIcon/index.js",
    "content": "import NoticeIcon from './NoticeIcon'\nexport default NoticeIcon\n"
  },
  {
    "path": "src/components/NumberInfo/NumberInfo.vue",
    "content": "<template>\n  <div :class=\"[prefixCls]\">\n    <slot name=\"subtitle\">\n      <div :class=\"[`${prefixCls}-subtitle`]\">{{ typeof subTitle === 'string' ? subTitle : subTitle() }}</div>\n    </slot>\n    <div class=\"number-info-value\">\n      <span>{{ total }}</span>\n      <span class=\"sub-total\">\n        {{ subTotal }}\n        <icon :type=\"`caret-${status}`\" />\n      </span>\n    </div>\n  </div>\n</template>\n\n<script>\nimport Icon from 'ant-design-vue/es/icon'\n\nexport default {\n  name: 'NumberInfo',\n  props: {\n    prefixCls: {\n      type: String,\n      default: 'ant-pro-number-info'\n    },\n    total: {\n      type: Number,\n      required: true\n    },\n    subTotal: {\n      type: Number,\n      required: true\n    },\n    subTitle: {\n      type: [String, Function],\n      default: ''\n    },\n    status: {\n      type: String,\n      default: 'up'\n    }\n  },\n  components: {\n    Icon\n  },\n  data () {\n    return {}\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n  @import \"index\";\n</style>\n"
  },
  {
    "path": "src/components/NumberInfo/index.js",
    "content": "import NumberInfo from './NumberInfo'\n\nexport default NumberInfo\n"
  },
  {
    "path": "src/components/NumberInfo/index.less",
    "content": "@import '../index';\n\n@numberInfo-prefix-cls: ~\"@{ant-pro-prefix}-number-info\";\n\n.@{numberInfo-prefix-cls} {\n  .ant-pro-number-info-subtitle {\n    height: 22px;\n    overflow: hidden;\n    font-size: @font-size-base;\n    line-height: 22px;\n    color: @text-color-secondary;\n    text-overflow: ellipsis;\n    word-break: break-all;\n    white-space: nowrap;\n  }\n\n  .number-info-value {\n    margin-top: 4px;\n    overflow: hidden;\n    font-size: 0;\n    text-overflow: ellipsis;\n    word-break: break-all;\n    white-space: nowrap;\n\n    & > span {\n      display: inline-block;\n      height: 32px;\n      margin-right: 32px;\n      font-size: 24px;\n      line-height: 32px;\n      color: @heading-color;\n    }\n\n    .sub-total {\n      margin-right: 0;\n      font-size: @font-size-lg;\n      color: @text-color-secondary;\n      vertical-align: top;\n\n      i {\n        margin-left: 4px;\n        font-size: 12px;\n        transform: scale(.82);\n      }\n      \n      .anticon-caret-up {\n        color: @red-6;\n      }\n\n      .anticon-caret-down {\n        color: @green-6;\n      }      \n    }\n  }\n}\n"
  },
  {
    "path": "src/components/NumberInfo/index.md",
    "content": "# NumberInfo 数据文本\n\n常用在数据卡片中，用于突出展示某个业务数据。\n\n\n\n引用方式：\n\n```javascript\nimport NumberInfo from '@/components/NumberInfo'\n\nexport default {\n    components: {\n        NumberInfo\n    }\n}\n```\n\n\n\n## 代码演示  [demo](https://pro.loacg.com/test/home)\n\n```html\n<number-info\n    :sub-title=\"() => { return 'Visits this week' }\"\n    :total=\"12321\"\n    status=\"up\"\n    :sub-total=\"17.1\"></number-info>\n```\n\n\n\n## API\n\n参数 | 说明 | 类型 | 默认值\n----|------|-----|------\ntitle | 标题 | ReactNode\\|string | -\nsubTitle | 子标题 | ReactNode\\|string | -\ntotal | 总量 | ReactNode\\|string | -\nsubTotal | 子总量 | ReactNode\\|string | -\nstatus | 增加状态 | 'up \\| down' | -\ntheme | 状态样式 | string | 'light'\ngap | 设置数字和描述之间的间距（像素）| number | 8\n"
  },
  {
    "path": "src/components/Other/CarbonAds.vue",
    "content": "<script>\nconst googleAdsUrl = 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js'\nexport default {\n  props: {\n    isMobile: Boolean\n  },\n  // watch: {\n  //   $route (e, t) {\n  //     const adId = '#adsbygoogle'\n  //     // if(isGitee) {\n  //     //   adId = '#cf';\n  //     // }\n  //     if (e.path !== t.path && this.$el.querySelector(adId)) {\n  //       this.$el.innerHTML = ''\n  //       this.load()\n  //     }\n  //     this.adInterval && clearInterval(this.adInterval)\n  //     this.adInterval = setInterval(() => {\n  //       if (!this.$el.querySelector(adId)) {\n  //         this.$el.innerHTML = ''\n  //         this.load()\n  //       }\n  //     }, 20000)\n  //   }\n  // },\n  mounted () {\n    // this.load()\n  },\n  methods: {\n    load () {\n      if (googleAdsUrl) {\n        /* eslint-disable */\n        let adsbygoogle = []\n        const e = document.createElement('script')\n        e.id = '_adsbygoogle_js'\n        e.src = googleAdsUrl\n        this.$el.appendChild(e)\n        setTimeout(() => {\n          (adsbygoogle = window.adsbygoogle || []).push({})\n        }, 2000)\n      }\n    }\n  },\n  render () {\n    // return <ins class=\"adsbygoogle\" style=\"display:inline-block;width:728px;height:90px\" data-ad-client=\"ca-pub-4801326429087140\" data-ad-slot=\"6929057621\" />\n    return <div class=\"business-pro-ad\"><a href=\"https://store.antdv.com/pro/\" target=\"_blank\">(推荐) 企业级商用版 Admin Pro 现已发售，采用 Vue3 + TS 欢迎购买。</a></div>;\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n.business-pro-ad {\n  position: fixed;\n  background: rgba(255,255,255,0.25);\n  left: 0;\n  bottom: 0;\n  padding: 0 12px;\n  height: 48px;\n  width: 258px;\n  z-index: 99;\n}\n</style>\n"
  },
  {
    "path": "src/components/PageLoading/index.jsx",
    "content": "import { Spin } from 'ant-design-vue'\n\nexport const PageLoading = {\n  name: 'PageLoading',\n  props: {\n    tip: {\n      type: String,\n      default: 'Loading..'\n    },\n    size: {\n      type: String,\n      default: 'large'\n    }\n  },\n  render () {\n    const style = {\n      textAlign: 'center',\n      background: 'rgba(0,0,0,0.6)',\n      position: 'fixed',\n      top: 0,\n      bottom: 0,\n      left: 0,\n      right: 0,\n      zIndex: 1100\n    }\n    const spinStyle = {\n      position: 'absolute',\n      left: '50%',\n      top: '40%',\n      transform: 'translate(-50%, -50%)'\n    }\n    return (<div style={style}>\n      <Spin size={this.size} style={spinStyle} tip={this.tip} />\n    </div>)\n  }\n}\n\nconst version = '0.0.1'\nconst loading = {}\n\nloading.newInstance = (Vue, options) => {\n  let loadingElement = document.querySelector('body>div[type=loading]')\n  if (!loadingElement) {\n    loadingElement = document.createElement('div')\n    loadingElement.setAttribute('type', 'loading')\n    loadingElement.setAttribute('class', 'ant-loading-wrapper')\n    document.body.appendChild(loadingElement)\n  }\n\n  const cdProps = Object.assign({ visible: false, size: 'large', tip: 'Loading...' }, options)\n\n  const instance = new Vue({\n    data () {\n      return {\n        ...cdProps\n      }\n    },\n    render () {\n      const { tip } = this\n      const props = {}\n      this.tip && (props.tip = tip)\n      if (this.visible) {\n        return <PageLoading { ...{ props } } />\n      }\n      return null\n    }\n  }).$mount(loadingElement)\n\n  function update (config) {\n    const { visible, size, tip } = { ...cdProps, ...config }\n    instance.$set(instance, 'visible', visible)\n    if (tip) {\n      instance.$set(instance, 'tip', tip)\n    }\n    if (size) {\n      instance.$set(instance, 'size', size)\n    }\n  }\n\n  return {\n    instance,\n    update\n  }\n}\n\nconst api = {\n  show: function (options) {\n    this.instance.update({ ...options, visible: true })\n  },\n  hide: function () {\n    this.instance.update({ visible: false })\n  }\n}\n\nconst install = function (Vue, options) {\n  if (Vue.prototype.$loading) {\n    return\n  }\n  api.instance = loading.newInstance(Vue, options)\n  Vue.prototype.$loading = api\n}\n\nexport default {\n  version,\n  install\n}\n"
  },
  {
    "path": "src/components/Search/GlobalSearch.jsx",
    "content": "import { Select } from 'ant-design-vue'\nimport './index.less'\n\nconst GlobalSearch = {\n  name: 'GlobalSearch',\n  data () {\n    return {\n      visible: false\n    }\n  },\n  mounted () {\n    const keyboardHandle = (e) => {\n      e.preventDefault()\n      e.stopPropagation()\n      const { ctrlKey, shiftKey, altKey, keyCode } = e\n      console.log('keyCode:', e.keyCode, e)\n      // key is `K` and hold ctrl\n      if (keyCode === 75 && ctrlKey && !shiftKey && !altKey) {\n        this.visible = !this.visible\n      }\n    }\n    document.addEventListener('keydown', keyboardHandle)\n  },\n  render () {\n    const { visible } = this\n    const handleSearch = (e) => {\n      this.$emit('search', e)\n    }\n\n    const handleChange = (e) => {\n      this.$emit('change', e)\n    }\n    if (!visible) {\n      return null\n    }\n    return (\n      <div class={'global-search global-search-wrapper'}>\n        <div class={'global-search-box'}>\n          <Select\n            size={'large'}\n            showSearch\n            placeholder=\"Input search text..\"\n            style={{ width: '100%' }}\n            defaultActiveFirstOption={false}\n            showArrow={false}\n            filterOption={false}\n            onSearch={handleSearch}\n            onChange={handleChange}\n            notFoundContent={null}\n          >\n          </Select>\n          <div class={'global-search-tips'}>Open with Ctrl/⌘ + K</div>\n        </div>\n      </div>\n    )\n  }\n}\n\nGlobalSearch.install = function (Vue) {\n  Vue.component(GlobalSearch.name, GlobalSearch)\n}\n\nexport default GlobalSearch\n"
  },
  {
    "path": "src/components/Search/index.less",
    "content": "@import '~ant-design-vue/es/style/themes/default';\n\n.global-search-wrapper {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: @zindex-modal-mask;\n  background: @modal-mask-bg;\n\n  .global-search-box {\n    position: absolute;\n    top: 20%;\n    left: 50%;\n    width: 450px;\n    transform: translate(-50%, -50%);\n\n    .global-search-tips {\n      font-size: @font-size-lg;\n      color: @white;\n      text-align: right;\n    }\n  }\n}\n"
  },
  {
    "path": "src/components/SelectLang/index.jsx",
    "content": "import './index.less'\n\nimport { Icon, Menu, Dropdown } from 'ant-design-vue'\nimport { i18nRender } from '@/locales'\nimport i18nMixin from '@/store/i18n-mixin'\n\nconst locales = ['zh-CN', 'en-US']\nconst languageLabels = {\n  'zh-CN': '简体中文',\n  'en-US': 'English'\n}\n// eslint-disable-next-line\nconst languageIcons = {\n  'zh-CN': '🇨🇳',\n  'en-US': '🇺🇸'\n}\n\nconst SelectLang = {\n  props: {\n    prefixCls: {\n      type: String,\n      default: 'ant-pro-drop-down'\n    }\n  },\n  name: 'SelectLang',\n  mixins: [i18nMixin],\n  render () {\n    const { prefixCls } = this\n    const changeLang = ({ key }) => {\n      this.setLang(key)\n    }\n    const langMenu = (\n      <Menu class={['menu', 'ant-pro-header-menu']} selectedKeys={[this.currentLang]} onClick={changeLang}>\n        {locales.map(locale => (\n          <Menu.Item key={locale}>\n            <span role=\"img\" aria-label={languageLabels[locale]}>\n              {languageIcons[locale]}\n            </span>{' '}\n            {languageLabels[locale]}\n          </Menu.Item>\n        ))}\n      </Menu>\n    )\n    return (\n      <Dropdown overlay={langMenu} placement=\"bottomRight\">\n        <span class={prefixCls}>\n          <Icon type=\"global\" title={i18nRender('navBar.lang')} />\n        </span>\n      </Dropdown>\n    )\n  }\n}\n\nexport default SelectLang\n"
  },
  {
    "path": "src/components/SelectLang/index.less",
    "content": "@import '~ant-design-vue/es/style/themes/default';\n\n@header-menu-prefix-cls: ~'@{ant-prefix}-pro-header-menu';\n@header-drop-down-prefix-cls: ~'@{ant-prefix}-pro-drop-down';\n\n.@{header-menu-prefix-cls} {\n  .anticon {\n    margin-right: 8px;\n  }\n\n  .ant-dropdown-menu-item {\n    min-width: 160px;\n  }\n}\n\n.@{header-drop-down-prefix-cls} {\n  line-height: @layout-header-height;\n  vertical-align: top;\n  cursor: pointer;\n\n  > i {\n    font-size: 16px !important;\n    transform: none !important;\n\n    svg {\n      position: relative;\n      top: -1px;\n    }\n  }\n}\n"
  },
  {
    "path": "src/components/SettingDrawer/SettingDrawer.vue",
    "content": "<template>\n  <div class=\"setting-drawer\">\n    <a-drawer\n      width=\"300\"\n      placement=\"right\"\n      @close=\"onClose\"\n      :closable=\"false\"\n      :visible=\"visible\"\n      :drawer-style=\"{ position: 'absolute' }\"\n      style=\"position: absolute\"\n    >\n      <div class=\"setting-drawer-index-content\">\n\n        <div :style=\"{ marginBottom: '24px' }\">\n          <h3 class=\"setting-drawer-index-title\">整体风格设置</h3>\n\n          <div class=\"setting-drawer-index-blockChecbox\">\n            <a-tooltip>\n              <template slot=\"title\">\n                暗色菜单风格\n              </template>\n              <div class=\"setting-drawer-index-item\" @click=\"handleMenuTheme('dark')\">\n                <img src=\"https://gw.alipayobjects.com/zos/rmsportal/LCkqqYNmvBEbokSDscrm.svg\" alt=\"dark\">\n                <div class=\"setting-drawer-index-selectIcon\" v-if=\"navTheme === 'dark'\">\n                  <a-icon type=\"check\"/>\n                </div>\n              </div>\n            </a-tooltip>\n\n            <a-tooltip>\n              <template slot=\"title\">\n                亮色菜单风格\n              </template>\n              <div class=\"setting-drawer-index-item\" @click=\"handleMenuTheme('light')\">\n                <img src=\"https://gw.alipayobjects.com/zos/rmsportal/jpRkZQMyYRryryPNtyIC.svg\" alt=\"light\">\n                <div class=\"setting-drawer-index-selectIcon\" v-if=\"navTheme !== 'dark'\">\n                  <a-icon type=\"check\"/>\n                </div>\n              </div>\n            </a-tooltip>\n          </div>\n        </div>\n\n        <div :style=\"{ marginBottom: '24px' }\">\n          <h3 class=\"setting-drawer-index-title\">主题色</h3>\n\n          <div style=\"height: 20px\">\n            <a-tooltip class=\"setting-drawer-theme-color-colorBlock\" v-for=\"(item, index) in colorList\" :key=\"index\">\n              <template slot=\"title\">\n                {{ item.key }}\n              </template>\n              <a-tag :color=\"item.color\" @click=\"changeColor(item.color)\">\n                <a-icon type=\"check\" v-if=\"item.color === primaryColor\"></a-icon>\n              </a-tag>\n            </a-tooltip>\n\n          </div>\n        </div>\n        <a-divider />\n\n        <div :style=\"{ marginBottom: '24px' }\">\n          <h3 class=\"setting-drawer-index-title\">导航模式</h3>\n\n          <div class=\"setting-drawer-index-blockChecbox\">\n            <a-tooltip>\n              <template slot=\"title\">\n                侧边栏导航\n              </template>\n              <div class=\"setting-drawer-index-item\" @click=\"handleLayout('sidemenu')\">\n                <img src=\"https://gw.alipayobjects.com/zos/rmsportal/JopDzEhOqwOjeNTXkoje.svg\" alt=\"sidemenu\">\n                <div class=\"setting-drawer-index-selectIcon\" v-if=\"layoutMode === 'sidemenu'\">\n                  <a-icon type=\"check\"/>\n                </div>\n              </div>\n            </a-tooltip>\n\n            <a-tooltip>\n              <template slot=\"title\">\n                顶部栏导航\n              </template>\n              <div class=\"setting-drawer-index-item\" @click=\"handleLayout('topmenu')\">\n                <img src=\"https://gw.alipayobjects.com/zos/rmsportal/KDNDBbriJhLwuqMoxcAr.svg\" alt=\"topmenu\">\n                <div class=\"setting-drawer-index-selectIcon\" v-if=\"layoutMode !== 'sidemenu'\">\n                  <a-icon type=\"check\"/>\n                </div>\n              </div>\n            </a-tooltip>\n          </div>\n          <div :style=\"{ marginTop: '24px' }\">\n            <a-list :split=\"false\">\n              <a-list-item>\n                <a-tooltip slot=\"actions\">\n                  <template slot=\"title\">\n                    该设定仅 [顶部栏导航] 时有效\n                  </template>\n                  <a-select size=\"small\" style=\"width: 80px;\" :defaultValue=\"contentWidth\" @change=\"handleContentWidthChange\">\n                    <a-select-option value=\"Fixed\">固定</a-select-option>\n                    <a-select-option value=\"Fluid\" v-if=\"layoutMode !== 'sidemenu'\">流式</a-select-option>\n                  </a-select>\n                </a-tooltip>\n                <a-list-item-meta>\n                  <div slot=\"title\">内容区域宽度</div>\n                </a-list-item-meta>\n              </a-list-item>\n              <a-list-item>\n                <a-switch slot=\"actions\" size=\"small\" :defaultChecked=\"fixedHeader\" @change=\"handleFixedHeader\" />\n                <a-list-item-meta>\n                  <div slot=\"title\">固定 Header</div>\n                </a-list-item-meta>\n              </a-list-item>\n              <a-list-item>\n                <a-switch slot=\"actions\" size=\"small\" :disabled=\"!fixedHeader\" :defaultChecked=\"autoHideHeader\" @change=\"handleFixedHeaderHidden\" />\n                <a-list-item-meta>\n                  <a-tooltip slot=\"title\" placement=\"left\">\n                    <template slot=\"title\">固定 Header 时可配置</template>\n                    <div :style=\"{ opacity: !fixedHeader ? '0.5' : '1' }\">下滑时隐藏 Header</div>\n                  </a-tooltip>\n                </a-list-item-meta>\n              </a-list-item>\n              <a-list-item >\n                <a-switch slot=\"actions\" size=\"small\" :disabled=\"(layoutMode === 'topmenu')\" :defaultChecked=\"fixSiderbar\" @change=\"handleFixSiderbar\" />\n                <a-list-item-meta>\n                  <div slot=\"title\" :style=\"{ textDecoration: layoutMode === 'topmenu' ? 'line-through' : 'unset' }\">固定侧边菜单</div>\n                </a-list-item-meta>\n              </a-list-item>\n            </a-list>\n          </div>\n        </div>\n        <a-divider />\n\n        <div :style=\"{ marginBottom: '24px' }\">\n          <h3 class=\"setting-drawer-index-title\">其他设置</h3>\n          <div>\n            <a-list :split=\"false\">\n              <a-list-item>\n                <a-switch slot=\"actions\" size=\"small\" :defaultChecked=\"colorWeak\" @change=\"onColorWeak\" />\n                <a-list-item-meta>\n                  <div slot=\"title\">色弱模式</div>\n                </a-list-item-meta>\n              </a-list-item>\n              <a-list-item>\n                <a-switch slot=\"actions\" size=\"small\" :defaultChecked=\"multiTab\" @change=\"onMultiTab\" />\n                <a-list-item-meta>\n                  <div slot=\"title\">多页签模式</div>\n                </a-list-item-meta>\n              </a-list-item>\n            </a-list>\n          </div>\n        </div>\n        <a-divider />\n        <div :style=\"{ marginBottom: '24px' }\">\n          <a-button\n            @click=\"doCopy\"\n            icon=\"copy\"\n            block\n          >拷贝设置</a-button>\n          <a-alert type=\"warning\" :style=\"{ marginTop: '24px' }\">\n            <span slot=\"message\">\n              配置栏只在开发环境用于预览，生产环境不会展现，请手动修改配置文件。修改配置文件后，需要清空本地缓存和LocalStorage\n              <a href=\"https://github.com/sendya/ant-design-pro-vue/blob/master/src/config/defaultSettings.js\" target=\"_blank\">src/config/defaultSettings.js</a>\n            </span>\n          </a-alert>\n        </div>\n      </div>\n      <div class=\"setting-drawer-index-handle\" @click=\"toggle\" slot=\"handle\">\n        <a-icon type=\"setting\" v-if=\"!visible\"/>\n        <a-icon type=\"close\" v-else/>\n      </div>\n    </a-drawer>\n  </div>\n</template>\n\n<script>\nimport SettingItem from './SettingItem'\nimport config from '@/config/defaultSettings'\nimport { updateTheme, updateColorWeak, colorList } from './settingConfig'\n\nexport default {\n  components: {\n    SettingItem\n  },\n  mixins: [],\n  data () {\n    return {\n      visible: false,\n      colorList\n    }\n  },\n  watch: {\n\n  },\n  mounted () {\n    updateTheme(this.primaryColor)\n    if (this.colorWeak !== config.colorWeak) {\n      updateColorWeak(this.colorWeak)\n    }\n  },\n  methods: {\n    showDrawer () {\n      this.visible = true\n    },\n    onClose () {\n      this.visible = false\n    },\n    toggle () {\n      this.visible = !this.visible\n    },\n    onColorWeak (checked) {\n      this.$store.dispatch('ToggleWeak', checked)\n      updateColorWeak(checked)\n    },\n    onMultiTab (checked) {\n      this.$store.dispatch('ToggleMultiTab', checked)\n    },\n    handleMenuTheme (theme) {\n      this.$store.dispatch('ToggleTheme', theme)\n    },\n    doCopy () {\n      // get current settings from mixin or this.$store.state.app, pay attention to the property name\n      const text = `export default {\n  primaryColor: '${this.primaryColor}', // primary color of ant design\n  navTheme: '${this.navTheme}', // theme for nav menu\n  layout: '${this.layoutMode}', // nav menu position: sidemenu or topmenu\n  contentWidth: '${this.contentWidth}', // layout of content: Fluid or Fixed, only works when layout is topmenu\n  fixedHeader: ${this.fixedHeader}, // sticky header\n  fixSiderbar: ${this.fixSiderbar}, // sticky siderbar\n  autoHideHeader: ${this.autoHideHeader}, //  auto hide header\n  colorWeak: ${this.colorWeak},\n  multiTab: ${this.multiTab},\n  production: process.env.NODE_ENV === 'production' && process.env.VUE_APP_PREVIEW !== 'true'\n}`\n      this.$copyText(text).then(message => {\n        console.log('copy', message)\n        this.$message.success('复制完毕')\n      }).catch(err => {\n        console.log('copy.err', err)\n        this.$message.error('复制失败')\n      })\n    },\n    handleLayout (mode) {\n      this.$store.dispatch('ToggleLayoutMode', mode)\n      // 因为顶部菜单不能固定左侧菜单栏，所以强制关闭\n      this.handleFixSiderbar(false)\n    },\n    handleContentWidthChange (type) {\n      this.$store.dispatch('ToggleContentWidth', type)\n    },\n    changeColor (color) {\n      if (this.primaryColor !== color) {\n        this.$store.dispatch('ToggleColor', color)\n        updateTheme(color)\n      }\n    },\n    handleFixedHeader (fixed) {\n      this.$store.dispatch('ToggleFixedHeader', fixed)\n    },\n    handleFixedHeaderHidden (autoHidden) {\n      this.$store.dispatch('ToggleFixedHeaderHidden', autoHidden)\n    },\n    handleFixSiderbar (fixed) {\n      if (this.layoutMode === 'topmenu') {\n        this.$store.dispatch('ToggleFixSiderbar', false)\n        return\n      }\n      this.$store.dispatch('ToggleFixSiderbar', fixed)\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n\n  .setting-drawer-index-content {\n\n    .setting-drawer-index-blockChecbox {\n      display: flex;\n\n      .setting-drawer-index-item {\n        margin-right: 16px;\n        position: relative;\n        border-radius: 4px;\n        cursor: pointer;\n\n        img {\n          width: 48px;\n        }\n\n        .setting-drawer-index-selectIcon {\n          position: absolute;\n          top: 0;\n          right: 0;\n          width: 100%;\n          padding-top: 15px;\n          padding-left: 24px;\n          height: 100%;\n          color: #1890ff;\n          font-size: 14px;\n          font-weight: 700;\n        }\n      }\n    }\n    .setting-drawer-theme-color-colorBlock {\n      width: 20px;\n      height: 20px;\n      border-radius: 2px;\n      float: left;\n      cursor: pointer;\n      margin-right: 8px;\n      padding-left: 0px;\n      padding-right: 0px;\n      text-align: center;\n      color: #fff;\n      font-weight: 700;\n\n      i {\n        font-size: 14px;\n      }\n    }\n  }\n\n  .setting-drawer-index-handle {\n    position: absolute;\n    top: 240px;\n    background: #1890ff;\n    width: 48px;\n    height: 48px;\n    right: 300px;\n    display: flex;\n    justify-content: center;\n    align-items: center;\n    cursor: pointer;\n    pointer-events: auto;\n    z-index: 1001;\n    text-align: center;\n    font-size: 16px;\n    border-radius: 4px 0 0 4px;\n\n    i {\n      color: rgb(255, 255, 255);\n      font-size: 20px;\n    }\n  }\n</style>\n"
  },
  {
    "path": "src/components/SettingDrawer/SettingItem.vue",
    "content": "<template>\n  <div class=\"setting-drawer-index-item\">\n    <h3 class=\"setting-drawer-index-title\">{{ title }}</h3>\n    <slot></slot>\n    <a-divider v-if=\"divider\"/>\n  </div>\n</template>\n\n<script>\nexport default {\n  name: 'SettingItem',\n  props: {\n    title: {\n      type: String,\n      default: ''\n    },\n    divider: {\n      type: Boolean,\n      default: false\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n\n  .setting-drawer-index-item {\n    margin-bottom: 24px;\n\n    .setting-drawer-index-title {\n      font-size: 14px;\n      color: rgba(0, 0, 0, .85);\n      line-height: 22px;\n      margin-bottom: 12px;\n    }\n\n  }\n</style>\n"
  },
  {
    "path": "src/components/SettingDrawer/index.js",
    "content": "import SettingDrawer from './SettingDrawer'\nexport default SettingDrawer\n"
  },
  {
    "path": "src/components/SettingDrawer/settingConfig.js",
    "content": "import message from 'ant-design-vue/es/message'\n// import defaultSettings from '../defaultSettings';\nimport themeColor from './themeColor.js'\n\n// let lessNodesAppended\nconst colorList = [\n  {\n    key: '薄暮', color: '#F5222D'\n  },\n  {\n    key: '火山', color: '#FA541C'\n  },\n  {\n    key: '日暮', color: '#FAAD14'\n  },\n  {\n    key: '明青', color: '#13C2C2'\n  },\n  {\n    key: '极光绿', color: '#52C41A'\n  },\n  {\n    key: '拂晓蓝（默认）', color: '#1890FF'\n  },\n  {\n    key: '极客蓝', color: '#2F54EB'\n  },\n  {\n    key: '酱紫', color: '#722ED1'\n  }\n]\n\nconst updateTheme = newPrimaryColor => {\n  const hideMessage = message.loading('正在切换主题！', 0)\n  themeColor.changeColor(newPrimaryColor).finally(() => {\n    setTimeout(() => {\n      hideMessage()\n    }, 10)\n  })\n}\n\nconst updateColorWeak = colorWeak => {\n  // document.body.className = colorWeak ? 'colorWeak' : '';\n  const app = document.body.querySelector('#app')\n  colorWeak ? app.classList.add('colorWeak') : app.classList.remove('colorWeak')\n}\n\nexport { updateTheme, colorList, updateColorWeak }\n"
  },
  {
    "path": "src/components/SettingDrawer/themeColor.js",
    "content": "import client from 'webpack-theme-color-replacer/client'\nimport generate from '@ant-design/colors/lib/generate'\n\nexport default {\n  getAntdSerials (color) {\n    // 淡化（即less的tint）\n    const lightens = new Array(9).fill().map((t, i) => {\n      return client.varyColor.lighten(color, i / 10)\n    })\n    // colorPalette变换得到颜色值\n    const colorPalettes = generate(color)\n    const rgb = client.varyColor.toNum3(color.replace('#', '')).join(',')\n    return lightens.concat(colorPalettes).concat(rgb)\n  },\n  changeColor (newColor) {\n    var options = {\n      newColors: this.getAntdSerials(newColor), // new colors array, one-to-one corresponde with `matchColors`\n      changeUrl (cssUrl) {\n        return `/${cssUrl}` // while router is not `hash` mode, it needs absolute path\n      }\n    }\n    return client.changer.changeColor(options, Promise)\n  }\n}\n"
  },
  {
    "path": "src/components/StandardFormRow/StandardFormRow.vue",
    "content": "<template>\n  <div :class=\"[prefixCls, lastCls, blockCls, gridCls]\">\n    <div v-if=\"title\" class=\"antd-pro-components-standard-form-row-index-label\">\n      <span>{{ title }}</span>\n    </div>\n    <div class=\"antd-pro-components-standard-form-row-index-content\">\n      <slot></slot>\n    </div>\n  </div>\n</template>\n\n<script>\nconst classes = [\n  'antd-pro-components-standard-form-row-index-standardFormRowBlock',\n  'antd-pro-components-standard-form-row-index-standardFormRowGrid',\n  'antd-pro-components-standard-form-row-index-standardFormRowLast'\n]\nexport default {\n  name: 'StandardFormRow',\n  props: {\n    prefixCls: {\n      type: String,\n      default: 'antd-pro-components-standard-form-row-index-standardFormRow'\n    },\n    title: {\n      type: String,\n      default: undefined\n    },\n    last: {\n      type: Boolean\n    },\n    block: {\n      type: Boolean\n    },\n    grid: {\n      type: Boolean\n    }\n  },\n  computed: {\n    lastCls () {\n      return this.last ? classes[2] : null\n    },\n    blockCls () {\n      return this.block ? classes[0] : null\n    },\n    gridCls () {\n      return this.grid ? classes[1] : null\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n@import '../index.less';\n\n.antd-pro-components-standard-form-row-index-standardFormRow {\n  display: flex;\n  margin-bottom: 16px;\n  padding-bottom: 16px;\n  border-bottom: 1px dashed @border-color-split;\n\n  :deep(.ant-form-item ) {\n    margin-right: 24px;\n  }\n  :deep(.ant-form-item-label label) {\n    margin-right: 0;\n    color: @text-color;\n  }\n  :deep(.ant-form-item-label,\n  .ant-form-item-control) {\n    padding: 0;\n    line-height: 32px;\n  }\n\n  .antd-pro-components-standard-form-row-index-label {\n    flex: 0 0 auto;\n    margin-right: 24px;\n    color: @heading-color;\n    font-size: @font-size-base;\n    text-align: right;\n    & > span {\n      display: inline-block;\n      height: 32px;\n      line-height: 32px;\n      &::after {\n        content: '：';\n      }\n    }\n  }\n\n  .antd-pro-components-standard-form-row-index-content {\n    flex: 1 1 0;\n    :deep(.ant-form-item:last-child) {\n      margin-right: 0;\n    }\n  }\n\n  &.antd-pro-components-standard-form-row-index-standardFormRowLast {\n    margin-bottom: 0;\n    padding-bottom: 0;\n    border: none;\n  }\n\n  &.antd-pro-components-standard-form-row-index-standardFormRowBlock {\n    :deep(.ant-form-item,\n    div.ant-form-item-control-wrapper) {\n      display: block;\n    }\n  }\n\n  &.antd-pro-components-standard-form-row-index-standardFormRowGrid {\n      :deep(.ant-form-item,\n      div.ant-form-item-control-wrapper) {\n        display: block;\n      }\n      :deep(.ant-form-item-label) {\n        float: left;\n      }\n  }\n}\n\n</style>\n"
  },
  {
    "path": "src/components/StandardFormRow/index.js",
    "content": "import StandardFormRow from './StandardFormRow'\n\nexport default StandardFormRow\n"
  },
  {
    "path": "src/components/Table/README.md",
    "content": "Table 重封装组件说明\n====\n\n\n封装说明\n----\n\n>  基础的使用方式与 API 与 [官方版(Table)](https://vuecomponent.github.io/ant-design-vue/components/table-cn/) 本一致，在其基础上，封装了加载数据的方法。\n>\n> 你无需在你是用表格的页面进行分页逻辑处理，仅需向 Table 组件传递绑定 `:data=\"Promise\"` 对象即可\n\n该 `table` 由 [@Saraka](https://github.com/saraka-tsukai) 完成封装\n\n\n例子1\n----\n（基础使用）\n\n```vue\n\n<template>\n  <s-table\n    ref=\"table\"\n    size=\"default\"\n    :rowKey=\"(record) => record.data.id\"\n    :columns=\"columns\"\n    :data=\"loadData\"\n    :rowSelection=\"{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange }\"\n  >\n  </s-table>\n</template>\n\n<script>\n  import STable from '@/components'\n\n  export default {\n    components: {\n      STable\n    },\n    data() {\n      return {\n        columns: [\n          {\n            title: '规则编号',\n            dataIndex: 'no'\n          },\n          {\n            title: '描述',\n            dataIndex: 'description'\n          },\n          {\n            title: '服务调用次数',\n            dataIndex: 'callNo',\n            sorter: true,\n            needTotal: true,\n            customRender: (text) => text + ' 次'\n          },\n          {\n            title: '状态',\n            dataIndex: 'status',\n            needTotal: true\n          },\n          {\n            title: '更新时间',\n            dataIndex: 'updatedAt',\n            sorter: true\n          }\n        ],\n        // 查询条件参数\n        queryParam: {},\n        // 加载数据方法 必须为 Promise 对象\n        loadData: parameter => {\n          return this.$http.get('/service', {\n            params: Object.assign(parameter, this.queryParam)\n          }).then(res => {\n            return res.result\n          })\n        },\n        selectedRowKeys: [],\n        selectedRows: []\n      }\n    },\n    methods: {\n      onSelectChange (selectedRowKeys, selectedRows) {\n         this.selectedRowKeys = selectedRowKeys\n         this.selectedRows = selectedRows\n       }\n    }\n  }\n</script>\n\n```\n\n\n\n例子2\n----\n\n（简单的表格，最后一列是各种操作）\n\n```vue\n<template>\n  <s-table\n    ref=\"table\"\n    size=\"default\"\n    :columns=\"columns\"\n    :data=\"loadData\"\n  >\n    <span slot=\"action\" slot-scope=\"text, record\">\n      <a>编辑</a>\n      <a-divider type=\"vertical\"/>\n      <a-dropdown>\n        <a class=\"ant-dropdown-link\">\n          更多 <a-icon type=\"down\"/>\n        </a>\n        <a-menu slot=\"overlay\">\n          <a-menu-item>\n            <a href=\"javascript:;\">1st menu item</a>\n          </a-menu-item>\n          <a-menu-item>\n            <a href=\"javascript:;\">2nd menu item</a>\n          </a-menu-item>\n          <a-menu-item>\n            <a href=\"javascript:;\">3rd menu item</a>\n          </a-menu-item>\n        </a-menu>\n      </a-dropdown>\n    </span>\n  </s-table>\n</template>\n\n<script>\n  import STable from '@/components/table/'\n\n  export default {\n    components: {\n      STable\n    },\n    data() {\n      return {\n        columns: [\n          {\n            title: '规则编号',\n            dataIndex: 'no'\n          },\n          {\n            title: '描述',\n            dataIndex: 'description'\n          },\n          {\n            title: '服务调用次数',\n            dataIndex: 'callNo',\n          },\n          {\n            title: '状态',\n            dataIndex: 'status',\n          },\n          {\n            title: '更新时间',\n            dataIndex: 'updatedAt',\n          },\n          {\n            table: '操作',\n            dataIndex: 'action',\n            scopedSlots: {customRender: 'action'},\n          }\n        ],\n        // 查询条件参数\n        queryParam: {},\n        // 加载数据方法 必须为 Promise 对象\n        loadData: parameter => {\n          return this.$http.get('/service', {\n            params: Object.assign(parameter, this.queryParam)\n          }).then(res => {\n            return res.result\n          })\n        },\n      }\n    },\n    methods: {\n      edit(row) {\n        // axios 发送数据到后端 修改数据成功后\n        // 调用 refresh() 重新加载列表数据\n        // 这里 setTimeout 模拟发起请求的网络延迟..\n        setTimeout(() => {\n          this.$refs.table.refresh() // refresh() 不传参默认值 false 不刷新到分页第一页\n        }, 1500)\n\n      }\n    }\n  }\n</script>\n```\n\n\n\n内置方法\n----\n\n通过 `this.$refs.table` 调用\n\n`this.$refs.table.refresh(true)` 刷新列表 (用户新增/修改数据后，重载列表数据)\n\n> 注意：要调用 `refresh(bool)` 需要给表格组件设定 `ref` 值\n>\n> `refresh()` 方法可以传一个 `bool` 值，当有传值 或值为 `true` 时，则刷新时会强制刷新到第一页（常用户页面 搜索 按钮进行搜索时，结果从第一页开始分页）\n\n\n内置属性\n----\n> 除去 `a-table` 自带属性外，还而外提供了一些额外属性属性  \n\n\n| 属性           | 说明                                            | 类型              | 默认值 |\n| -------------- | ----------------------------------------------- | ----------------- | ------ |\n| alert          | 设置是否显示表格信息栏                          | [object, boolean] | null   |\n| showPagination | 显示分页选择器，可传 'auto' \\| boolean          | [string, boolean] | 'auto' |\n| data           | 加载数据方法 必须为 `Promise` 对象 **必须绑定** | Promise           | -      |\n\n\n`alert` 属性对象：\n\n```javascript\nalert: {\n  show: Boolean, \n  clear: [Function, Boolean]\n}\n```\n\n注意事项\n----\n\n> 你可能需要为了与后端提供的接口返回结果一致而去修改以下代码：\n> (需要注意的是，这里的修改是全局性的，意味着整个项目所有使用该 table 组件都需要遵守这个返回结果定义的字段。)\n>\n> 文档中的结构有可能由于组件 bug 进行修正而改动。实际修改请以当时最新版本为准\n\n修改 `@/components/table/index.js`  第 156 行起\n\n\n\n```javascript\nresult.then(r => {\n          this.localPagination = this.showPagination && Object.assign({}, this.localPagination, {\n            current: r.pageNo, // 返回结果中的当前分页数\n            total: r.totalCount, // 返回结果中的总记录数\n            showSizeChanger: this.showSizeChanger,\n            pageSize: (pagination && pagination.pageSize) ||\n              this.localPagination.pageSize\n          }) || false\n          // 为防止删除数据后导致页面当前页面数据长度为 0 ,自动翻页到上一页\n          if (r.data.length === 0 && this.showPagination && this.localPagination.current > 1) {\n            this.localPagination.current--\n            this.loadData()\n            return\n          }\n\n          // 这里用于判断接口是否有返回 r.totalCount 且 this.showPagination = true 且 pageNo 和 pageSize 存在 且 totalCount 小于等于 pageNo * pageSize 的大小\n          // 当情况满足时，表示数据不满足分页大小，关闭 table 分页功能\n          try {\n            if ((['auto', true].includes(this.showPagination) && r.totalCount <= (r.pageNo * this.localPagination.pageSize))) {\n              this.localPagination.hideOnSinglePage = true\n            }\n          } catch (e) {\n            this.localPagination = false\n          }\n          console.log('loadData -> this.localPagination', this.localPagination)\n          this.localDataSource = r.data // 返回结果中的数组数据\n          this.localLoading = false\n        })\n```\n返回 JSON 例子：\n```json\n{\n  \"message\": \"\",\n  \"result\": {\n    \"data\": [{\n        id: 1,\n        cover: 'https://gw.alipayobjects.com/zos/rmsportal/WdGqmHpayyMjiEhcKoVE.png',\n        title: 'Alipay',\n        description: '那是一种内在的东西， 他们到达不了，也无法触及的',\n        status: 1,\n        updatedAt: '2018-07-26 00:00:00'\n      },\n      {\n        id: 2,\n        cover: 'https://gw.alipayobjects.com/zos/rmsportal/zOsKZmFRdUtvpqCImOVY.png',\n        title: 'Angular',\n        description: '希望是一个好东西，也许是最好的，好东西是不会消亡的',\n        status: 1,\n        updatedAt: '2018-07-26 00:00:00'\n      },\n      {\n        id: 3,\n        cover: 'https://gw.alipayobjects.com/zos/rmsportal/dURIMkkrRFpPgTuzkwnB.png',\n        title: 'Ant Design',\n        description: '城镇中有那么多的酒馆，她却偏偏走进了我的酒馆',\n        status: 1,\n        updatedAt: '2018-07-26 00:00:00'\n      },\n      {\n        id: 4,\n        cover: 'https://gw.alipayobjects.com/zos/rmsportal/sfjbOqnsXXJgNCjCzDBL.png',\n        title: 'Ant Design Pro',\n        description: '那时候我只会想自己想要什么，从不想自己拥有什么',\n        status: 1,\n        updatedAt: '2018-07-26 00:00:00'\n      },\n      {\n        id: 5,\n        cover: 'https://gw.alipayobjects.com/zos/rmsportal/siCrBXXhmvTQGWPNLBow.png',\n        title: 'Bootstrap',\n        description: '凛冬将至',\n        status: 1,\n        updatedAt: '2018-07-26 00:00:00'\n      },\n      {\n        id: 6,\n        cover: 'https://gw.alipayobjects.com/zos/rmsportal/ComBAopevLwENQdKWiIn.png',\n        title: 'Vue',\n        description: '生命就像一盒巧克力，结果往往出人意料',\n        status: 1,\n        updatedAt: '2018-07-26 00:00:00'\n      }\n    ],\n    \"pageSize\": 10,\n    \"pageNo\": 0,\n    \"totalPage\": 6,\n    \"totalCount\": 57\n  },\n  \"status\": 200,\n  \"timestamp\": 1534955098193\n}\n```\n\n\n\n更新时间\n----\n\n该文档最后更新于： 2019-06-23 PM 17:19"
  },
  {
    "path": "src/components/Table/index.js",
    "content": "import T from 'ant-design-vue/es/table/Table'\nimport get from 'lodash.get'\n\nexport default {\n  data () {\n    return {\n      needTotalList: [],\n\n      selectedRows: [],\n      selectedRowKeys: [],\n\n      localLoading: false,\n      localDataSource: [],\n      localPagination: Object.assign({}, this.pagination),\n\n      // 存储表格onchange时的filters， sorter对象\n      filters: {},\n      sorter: {}\n    }\n  },\n  props: Object.assign({}, T.props, {\n    rowKey: {\n      type: [String, Function],\n      default: 'key'\n    },\n    data: {\n      type: Function,\n      required: true\n    },\n    pageNum: {\n      type: Number,\n      default: 1\n    },\n    pageSize: {\n      type: Number,\n      default: 10\n    },\n    showSizeChanger: {\n      type: Boolean,\n      default: true\n    },\n    size: {\n      type: String,\n      default: 'default'\n    },\n    /**\n     * alert: {\n     *   show: true,\n     *   clear: Function\n     * }\n     */\n    alert: {\n      type: [Object, Boolean],\n      default: null\n    },\n    rowSelection: {\n      type: Object,\n      default: null\n    },\n    /** @Deprecated */\n    showAlertInfo: {\n      type: Boolean,\n      default: false\n    },\n    showPagination: {\n      type: String | Boolean,\n      default: 'auto'\n    },\n    /**\n     * enable page URI mode\n     *\n     * e.g:\n     * /users/1\n     * /users/2\n     * /users/3?queryParam=test\n     * ...\n     */\n    pageURI: {\n      type: Boolean,\n      default: false\n    }\n  }),\n  watch: {\n    'localPagination.current' (val) {\n      this.pageURI && this.$router.push({\n        ...this.$route,\n        name: this.$route.name,\n        params: Object.assign({}, this.$route.params, {\n          pageNo: val\n        })\n      })\n      // change pagination, reset total data\n      this.needTotalList = this.initTotalList(this.columns)\n      this.selectedRowKeys = []\n      this.selectedRows = []\n    },\n    pageNum (val) {\n      Object.assign(this.localPagination, {\n        current: val\n      })\n    },\n    pageSize (val) {\n      Object.assign(this.localPagination, {\n        pageSize: val\n      })\n    },\n    showSizeChanger (val) {\n      Object.assign(this.localPagination, {\n        showSizeChanger: val\n      })\n    }\n  },\n  created () {\n    const { pageNo } = this.$route.params\n    const localPageNum = this.pageURI && (pageNo && parseInt(pageNo)) || this.pageNum\n    this.localPagination = ['auto', true].includes(this.showPagination) && Object.assign({}, this.localPagination, {\n      current: localPageNum,\n      pageSize: this.pageSize,\n      showSizeChanger: this.showSizeChanger\n    }) || false\n    this.needTotalList = this.initTotalList(this.columns)\n    this.loadData()\n  },\n  methods: {\n    /**\n     * 表格重新加载方法\n     * 如果参数为 true, 则强制刷新到第一页\n     * @param Boolean bool\n     */\n    refresh (bool = false) {\n      bool && (this.localPagination = Object.assign({}, {\n        current: 1, pageSize: this.pageSize\n      }))\n      this.loadData()\n    },\n    /**\n     * 加载数据方法\n     * @param {Object} pagination 分页选项器\n     * @param {Object} filters 过滤条件\n     * @param {Object} sorter 排序条件\n     */\n    loadData (pagination, filters = this.filters, sorter = this.sorter) {\n      this.filters = filters\n      this.sorter = sorter\n\n      this.localLoading = true\n      const parameter = Object.assign({\n        pageNo: (pagination && pagination.current) ||\n          this.showPagination && this.localPagination.current || this.pageNum,\n        pageSize: (pagination && pagination.pageSize) ||\n          this.showPagination && this.localPagination.pageSize || this.pageSize\n      },\n      (sorter && sorter.field && {\n        sortField: sorter.field\n      }) || {},\n      (sorter && sorter.order && {\n        sortOrder: sorter.order\n      }) || {}, {\n        ...filters\n      }\n      )\n      const result = this.data(parameter)\n      // 对接自己的通用数据接口需要修改下方代码中的 r.pageNo, r.totalCount, r.data\n      // eslint-disable-next-line\n      if ((typeof result === 'object' || typeof result === 'function') && typeof result.then === 'function') {\n        result.then(r => {\n          this.localPagination = this.showPagination && Object.assign({}, this.localPagination, {\n            current: r.pageNo, // 返回结果中的当前分页数\n            total: r.totalCount, // 返回结果中的总记录数\n            showSizeChanger: this.showSizeChanger,\n            pageSize: (pagination && pagination.pageSize) ||\n              this.localPagination.pageSize\n          }) || false\n          // 为防止删除数据后导致页面当前页面数据长度为 0 ,自动翻页到上一页\n          if (r.data.length === 0 && this.showPagination && this.localPagination.current > 1) {\n            this.localPagination.current--\n            this.loadData()\n            return\n          }\n\n          // 这里用于判断接口是否有返回 r.totalCount 且 this.showPagination = true 且 pageNo 和 pageSize 存在 且 totalCount 小于等于 pageNo * pageSize 的大小\n          // 当情况满足时，表示数据不满足分页大小，关闭 table 分页功能\n          try {\n            if ((['auto', true].includes(this.showPagination) && r.totalCount <= (r.pageNo * this.localPagination.pageSize))) {\n              this.localPagination.hideOnSinglePage = true\n            }\n          } catch (e) {\n            this.localPagination = false\n          }\n          this.localDataSource = r.data // 返回结果中的数组数据\n        })\n        .finally(() => {\n          this.localLoading = false\n        })\n      }\n    },\n    initTotalList (columns) {\n      const totalList = []\n      columns && columns instanceof Array && columns.forEach(column => {\n        if (column.needTotal) {\n          totalList.push({\n            ...column,\n            total: 0\n          })\n        }\n      })\n      return totalList\n    },\n    /**\n     * 用于更新已选中的列表数据 total 统计\n     * @param selectedRowKeys\n     * @param selectedRows\n     */\n    updateSelect (selectedRowKeys, selectedRows) {\n      this.selectedRows = selectedRows\n      this.selectedRowKeys = selectedRowKeys\n      const list = this.needTotalList\n      this.needTotalList = list.map(item => {\n        return {\n          ...item,\n          total: selectedRows.reduce((sum, val) => {\n            const total = sum + parseInt(get(val, item.dataIndex))\n            return isNaN(total) ? 0 : total\n          }, 0)\n        }\n      })\n    },\n    /**\n     * 清空 table 已选中项\n     */\n    clearSelected () {\n      if (this.rowSelection) {\n        this.rowSelection.onChange([], [])\n        this.updateSelect([], [])\n      }\n    },\n    /**\n     * 处理交给 table 使用者去处理 clear 事件时，内部选中统计同时调用\n     * @param callback\n     * @returns {*}\n     */\n    renderClear (callback) {\n      if (this.selectedRowKeys.length <= 0) return null\n      return (\n        <a style=\"margin-left: 24px\" onClick={() => {\n          callback()\n          this.clearSelected()\n        }}>清空</a>\n      )\n    },\n    renderAlert () {\n      // 绘制统计列数据\n      const needTotalItems = this.needTotalList.map((item) => {\n        return (<span style=\"margin-right: 12px\">\n          {item.title}总计 <a style=\"font-weight: 600\">{!item.customRender ? item.total : item.customRender(item.total)}</a>\n        </span>)\n      })\n\n      // 绘制 清空 按钮\n      const clearItem = (typeof this.alert.clear === 'boolean' && this.alert.clear) ? (\n        this.renderClear(this.clearSelected)\n      ) : (this.alert !== null && typeof this.alert.clear === 'function') ? (\n        this.renderClear(this.alert.clear)\n      ) : null\n\n      // 绘制 alert 组件\n      return (\n        <a-alert showIcon={true} style=\"margin-bottom: 16px\">\n          <template slot=\"message\">\n            <span style=\"margin-right: 12px\">已选择: <a style=\"font-weight: 600\">{this.selectedRows.length}</a></span>\n            {needTotalItems}\n            {clearItem}\n          </template>\n        </a-alert>\n      )\n    }\n  },\n\n  render () {\n    const props = {}\n    const localKeys = Object.keys(this.$data)\n    const showAlert = (typeof this.alert === 'object' && this.alert !== null && this.alert.show) && typeof this.rowSelection.selectedRowKeys !== 'undefined' || this.alert\n\n    Object.keys(T.props).forEach(k => {\n      const localKey = `local${k.substring(0, 1).toUpperCase()}${k.substring(1)}`\n      if (localKeys.includes(localKey)) {\n        props[k] = this[localKey]\n        return props[k]\n      }\n      if (k === 'rowSelection') {\n        if (showAlert && this.rowSelection) {\n          // 如果需要使用alert，则重新绑定 rowSelection 事件\n          props[k] = {\n            ...this.rowSelection,\n            selectedRows: this.selectedRows,\n            selectedRowKeys: this.selectedRowKeys,\n            onChange: (selectedRowKeys, selectedRows) => {\n              this.updateSelect(selectedRowKeys, selectedRows)\n              typeof this[k].onChange !== 'undefined' && this[k].onChange(selectedRowKeys, selectedRows)\n            }\n          }\n          return props[k]\n        } else if (!this.rowSelection) {\n          // 如果没打算开启 rowSelection 则清空默认的选择项\n          props[k] = null\n          return props[k]\n        }\n      }\n      this[k] && (props[k] = this[k])\n      return props[k]\n    })\n    const table = (\n      <a-table {...{ props, scopedSlots: { ...this.$scopedSlots } }} onChange={this.loadData} onExpand={ (expanded, record) => { this.$emit('expand', expanded, record) } }>\n        { Object.keys(this.$slots).map(name => (<template slot={name}>{this.$slots[name]}</template>)) }\n      </a-table>\n    )\n\n    return (\n      <div class=\"table-wrapper\">\n        { showAlert ? this.renderAlert() : null }\n        { table }\n      </div>\n    )\n  }\n}\n"
  },
  {
    "path": "src/components/TagSelect/TagSelectOption.jsx",
    "content": "import { Tag } from 'ant-design-vue'\nconst { CheckableTag } = Tag\n\nexport default {\n  name: 'TagSelectOption',\n  props: {\n    prefixCls: {\n      type: String,\n      default: 'ant-pro-tag-select-option'\n    },\n    value: {\n      type: [String, Number, Object],\n      default: ''\n    },\n    checked: {\n      type: Boolean,\n      default: false\n    }\n  },\n  data () {\n    return {\n      localChecked: this.checked || false\n    }\n  },\n  watch: {\n    'checked' (val) {\n      this.localChecked = val\n    },\n    '$parent.items': {\n      handler: function (val) {\n        this.value && val.hasOwnProperty(this.value) && (this.localChecked = val[this.value])\n      },\n      deep: true\n    }\n  },\n  render () {\n    const { $slots, value } = this\n    const onChange = (checked) => {\n      this.$emit('change', { value, checked })\n    }\n    return (<CheckableTag key={value} vModel={this.localChecked} onChange={onChange}>\n      {$slots.default}\n    </CheckableTag>)\n  }\n}\n"
  },
  {
    "path": "src/components/TagSelect/index.jsx",
    "content": "import PropTypes from 'ant-design-vue/es/_util/vue-types'\nimport Option from './TagSelectOption.jsx'\nimport { filterEmpty } from '@/components/_util/util'\n\nexport default {\n  Option,\n  name: 'TagSelect',\n  model: {\n    prop: 'checked',\n    event: 'change'\n  },\n  props: {\n    prefixCls: {\n      type: String,\n      default: 'ant-pro-tag-select'\n    },\n    defaultValue: {\n      type: PropTypes.array,\n      default: null\n    },\n    value: {\n      type: PropTypes.array,\n      default: null\n    },\n    expandable: {\n      type: Boolean,\n      default: false\n    },\n    hideCheckAll: {\n      type: Boolean,\n      default: false\n    }\n  },\n  data () {\n    return {\n      expand: false,\n      localCheckAll: false,\n      items: this.getItemsKey(filterEmpty(this.$slots.default)),\n      val: this.value || this.defaultValue || []\n    }\n  },\n  methods: {\n    onChange (checked) {\n      const key = Object.keys(this.items).filter(key => key === checked.value)\n      this.items[key] = checked.checked\n      const bool = Object.values(this.items).lastIndexOf(false)\n      if (bool === -1) {\n        this.localCheckAll = true\n      } else {\n        this.localCheckAll = false\n      }\n    },\n    onCheckAll (checked) {\n      Object.keys(this.items).forEach(v => {\n        this.items[v] = checked.checked\n      })\n      this.localCheckAll = checked.checked\n    },\n    getItemsKey (items) {\n      const totalItem = {}\n      items.forEach(item => {\n        totalItem[item.componentOptions.propsData && item.componentOptions.propsData.value] = false\n      })\n      return totalItem\n    },\n    // CheckAll Button\n    renderCheckAll () {\n      const props = {\n        on: {\n          change: (checked) => {\n            this.onCheckAll(checked)\n            checked.value = 'total'\n            this.$emit('change', checked)\n          }\n        }\n      }\n      const checkAllElement = <Option key={'total'} checked={this.localCheckAll} {...props}>All</Option>\n      return !this.hideCheckAll && checkAllElement || null\n    },\n    // expandable\n    renderExpandable () {\n\n    },\n    // render option\n    renderTags (items) {\n      const listeners = {\n        change: (checked) => {\n          this.onChange(checked)\n          this.$emit('change', checked)\n        }\n      }\n\n      return items.map(vnode => {\n        const options = vnode.componentOptions\n        options.listeners = listeners\n        return vnode\n      })\n    }\n  },\n  render () {\n    const { $props: { prefixCls } } = this\n    const classString = {\n      [`${prefixCls}`]: true\n    }\n    const tagItems = filterEmpty(this.$slots.default)\n    return (\n      <div class={classString}>\n        {this.renderCheckAll()}\n        {this.renderTags(tagItems)}\n      </div>\n    )\n  }\n}\n"
  },
  {
    "path": "src/components/TextArea/index.jsx",
    "content": "import './style.less'\nimport { getStrFullLength, cutStrByFullLength } from '../_util/util'\nimport Input from 'ant-design-vue/es/input'\nconst TextArea = Input.TextArea\n\nexport default {\n  name: 'LimitTextArea',\n  model: {\n    prop: 'value',\n    event: 'change'\n  },\n  props: Object.assign({}, TextArea.props, {\n    prefixCls: {\n      type: String,\n      default: 'ant-textarea-limit'\n    },\n    // eslint-disable-next-line\n    value: {\n      type: String\n    },\n    limit: {\n      type: Number,\n      default: 200\n    }\n  }),\n  data () {\n    return {\n      currentLimit: 0\n    }\n  },\n  watch: {\n    value (val) {\n      this.calcLimitNum(val)\n    }\n  },\n  created () {\n    this.calcLimitNum(this.value)\n  },\n  methods: {\n    handleChange (e) {\n      const value = e.target.value\n      const len = getStrFullLength(value)\n      if (len <= this.limit) {\n        this.currentLimit = len\n        this.$emit('change', value)\n        return\n      } else {\n        const str = cutStrByFullLength(value, this.limit)\n        this.currentLimit = getStrFullLength(str)\n        this.$emit('change', str)\n      }\n      console.error('limit out! currentLimit:', this.currentLimit)\n    },\n    calcLimitNum (val) {\n      const len = getStrFullLength(val)\n      this.currentLimit = len\n    }\n  },\n  render () {\n    const { prefixCls, ...props } = this.$props\n    return (\n      <div class={this.prefixCls}>\n        <TextArea {...{ props }} value={this.value} onChange={this.handleChange}>\n        </TextArea>\n        <span class=\"limit\">{this.currentLimit}/{this.limit}</span>\n      </div>\n    )\n  }\n}\n"
  },
  {
    "path": "src/components/TextArea/style.less",
    "content": ".ant-textarea-limit {\n  position: relative;\n\n  .limit {\n    position: absolute;\n    right: 10px;\n    bottom: 5px;\n    font-size: 12px;\n    color: #909399;\n    background: #fff;\n  }\n}\n"
  },
  {
    "path": "src/components/Tree/Tree.jsx",
    "content": "import { Menu, Icon, Input } from 'ant-design-vue'\n\nconst { Item, ItemGroup, SubMenu } = Menu\nconst { Search } = Input\n\nexport default {\n  name: 'Tree',\n  props: {\n    dataSource: {\n      type: Array,\n      required: true\n    },\n    openKeys: {\n      type: Array,\n      default: () => []\n    },\n    search: {\n      type: Boolean,\n      default: false\n    }\n  },\n  created () {\n    this.localOpenKeys = this.openKeys.slice(0)\n  },\n  data () {\n    return {\n      localOpenKeys: []\n    }\n  },\n  methods: {\n    handlePlus (item) {\n      this.$emit('add', item)\n    },\n    handleTitleClick (...args) {\n      this.$emit('titleClick', { args })\n    },\n\n    renderSearch () {\n      return (\n        <Search\n          placeholder=\"input search text\"\n          style=\"width: 100%; margin-bottom: 1rem\"\n        />\n      )\n    },\n    renderIcon (icon) {\n      return icon && (<Icon type={icon} />) || null\n    },\n    renderMenuItem (item) {\n      return (\n        <Item key={item.key}>\n          { this.renderIcon(item.icon) }\n          { item.title }\n          <a class=\"btn\" style=\"width: 20px;z-index:1300\" {...{ on: { click: () => this.handlePlus(item) } }}><a-icon type=\"plus\"/></a>\n        </Item>\n      )\n    },\n    renderItem (item) {\n      return item.children ? this.renderSubItem(item, item.key) : this.renderMenuItem(item, item.key)\n    },\n    renderItemGroup (item) {\n      const childrenItems = item.children.map(o => {\n        return this.renderItem(o, o.key)\n      })\n\n      return (\n        <ItemGroup key={item.key}>\n          <template slot=\"title\">\n            <span>{ item.title }</span>\n            <a-dropdown>\n              <a class=\"btn\"><a-icon type=\"ellipsis\" /></a>\n              <a-menu slot=\"overlay\">\n                <a-menu-item key=\"1\">新增</a-menu-item>\n                <a-menu-item key=\"2\">合并</a-menu-item>\n                <a-menu-item key=\"3\">移除</a-menu-item>\n              </a-menu>\n            </a-dropdown>\n          </template>\n          { childrenItems }\n        </ItemGroup>\n      )\n    },\n    renderSubItem (item, key) {\n      const childrenItems = item.children && item.children.map(o => {\n        return this.renderItem(o, o.key)\n      })\n\n      const title = (\n        <span slot=\"title\">\n          { this.renderIcon(item.icon) }\n          <span>{ item.title }</span>\n        </span>\n      )\n\n      if (item.group) {\n        return this.renderItemGroup(item)\n      }\n      // titleClick={this.handleTitleClick(item)}\n      return (\n        <SubMenu key={key}>\n          { title }\n          { childrenItems }\n        </SubMenu>\n      )\n    }\n  },\n  render () {\n    const { dataSource, search } = this.$props\n\n    // this.localOpenKeys = openKeys.slice(0)\n    const list = dataSource.map(item => {\n      return this.renderItem(item)\n    })\n\n    return (\n      <div class=\"tree-wrapper\">\n        { search ? this.renderSearch() : null }\n        <Menu mode=\"inline\" class=\"custom-tree\" {...{ on: { click: item => this.$emit('click', item), 'update:openKeys': val => { this.localOpenKeys = val } } }} openKeys={this.localOpenKeys}>\n          { list }\n        </Menu>\n      </div>\n    )\n  }\n}\n"
  },
  {
    "path": "src/components/Trend/Trend.vue",
    "content": "<template>\n  <div :class=\"[prefixCls, reverseColor && 'reverse-color' ]\">\n    <span>\n      <slot name=\"term\"></slot>\n      <span class=\"item-text\">\n        <slot></slot>\n      </span>\n    </span>\n    <span :class=\"[flag]\"><a-icon :type=\"`caret-${flag}`\"/></span>\n  </div>\n</template>\n\n<script>\nexport default {\n  name: 'Trend',\n  props: {\n    prefixCls: {\n      type: String,\n      default: 'ant-pro-trend'\n    },\n    /**\n       * 上升下降标识：up|down\n       */\n    flag: {\n      type: String,\n      required: true\n    },\n    /**\n       * 颜色反转\n       */\n    reverseColor: {\n      type: Boolean,\n      default: false\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n  @import \"index\";\n</style>\n"
  },
  {
    "path": "src/components/Trend/index.js",
    "content": "import Trend from './Trend.vue'\n\nexport default Trend\n"
  },
  {
    "path": "src/components/Trend/index.less",
    "content": "@import '../index';\n\n@trend-prefix-cls: ~\"@{ant-pro-prefix}-trend\";\n\n.@{trend-prefix-cls} {\n  display: inline-block;\n  font-size: @font-size-base;\n  line-height: 22px;\n\n  .up,\n  .down {\n    position: relative;\n    top: 1px;\n    margin-left: 4px;\n\n    i {\n      font-size: 12px;\n      transform: scale(.83);\n    }\n  }\n\n  .item-text {\n    display: inline-block;\n    margin-left: 8px;\n    color: rgb(0 0 0 / 85%);\n  }\n\n  .up {\n    color: @red-6;\n  }\n\n  .down {\n    top: -1px;\n    color: @green-6;\n  }\n\n  &.reverse-color .up {\n    color: @green-6;\n  }\n\n  &.reverse-color .down {\n    color: @red-6;\n  }\n}\n"
  },
  {
    "path": "src/components/Trend/index.md",
    "content": "# Trend 趋势标记\n\n趋势符号，标记上升和下降趋势。通常用绿色代表“好”，红色代表“不好”，股票涨跌场景除外。\n\n\n\n引用方式：\n\n```javascript\nimport Trend from '@/components/Trend'\n\nexport default {\n    components: {\n        Trend\n    }\n}\n```\n\n\n\n## 代码演示  [demo](https://pro.loacg.com/test/home)\n\n```html\n<trend flag=\"up\">5%</trend>\n```\n或\n```html\n<trend flag=\"up\">\n    <span slot=\"term\">工资</span>\n    5%\n</trend>\n```\n或\n```html\n<trend flag=\"up\" term=\"工资\">5%</trend>\n```\n\n\n## API\n\n| 参数      | 说明                                      | 类型         | 默认值 |\n|----------|------------------------------------------|-------------|-------|\n| flag | 上升下降标识：`up|down` | string | - |\n| reverseColor | 颜色反转 | Boolean | false |\n\n"
  },
  {
    "path": "src/components/_util/util.js",
    "content": "/**\n * components util\n */\n\n/**\n * 清理空值，对象\n * @param children\n * @returns {*[]}\n */\nexport function filterEmpty (children = []) {\n  return children.filter(c => c.tag || (c.text && c.text.trim() !== ''))\n}\n\n/**\n * 获取字符串长度，英文字符 长度1，中文字符长度2\n * @param {*} str\n */\nexport const getStrFullLength = (str = '') =>\n  str.split('').reduce((pre, cur) => {\n    const charCode = cur.charCodeAt(0)\n    if (charCode >= 0 && charCode <= 128) {\n      return pre + 1\n    }\n    return pre + 2\n  }, 0)\n\n/**\n * 截取字符串，根据 maxLength 截取后返回\n * @param {*} str\n * @param {*} maxLength\n */\nexport const cutStrByFullLength = (str = '', maxLength) => {\n  let showLength = 0\n  return str.split('').reduce((pre, cur) => {\n    const charCode = cur.charCodeAt(0)\n    if (charCode >= 0 && charCode <= 128) {\n      showLength += 1\n    } else {\n      showLength += 2\n    }\n    if (showLength <= maxLength) {\n      return pre + cur\n    }\n    return pre\n  }, '')\n}\n"
  },
  {
    "path": "src/components/index.js",
    "content": "// chart\nimport Bar from '@/components/Charts/Bar'\nimport ChartCard from '@/components/Charts/ChartCard'\nimport Liquid from '@/components/Charts/Liquid'\nimport MiniArea from '@/components/Charts/MiniArea'\nimport MiniSmoothArea from '@/components/Charts/MiniSmoothArea'\nimport MiniBar from '@/components/Charts/MiniBar'\nimport MiniProgress from '@/components/Charts/MiniProgress'\nimport Radar from '@/components/Charts/Radar'\nimport RankList from '@/components/Charts/RankList'\nimport TransferBar from '@/components/Charts/TransferBar'\nimport TagCloud from '@/components/Charts/TagCloud'\n\n// pro components\nimport AvatarList from '@/components/AvatarList'\nimport Ellipsis from '@/components/Ellipsis'\nimport FooterToolbar from '@/components/FooterToolbar'\nimport NumberInfo from '@/components/NumberInfo'\nimport Tree from '@/components/Tree/Tree'\nimport Trend from '@/components/Trend'\nimport STable from '@/components/Table'\nimport MultiTab from '@/components/MultiTab'\nimport IconSelector from '@/components/IconSelector'\nimport TagSelect from '@/components/TagSelect'\nimport StandardFormRow from '@/components/StandardFormRow'\nimport ArticleListContent from '@/components/ArticleListContent'\n\nimport Dialog from '@/components/Dialog'\n\nexport {\n  AvatarList,\n  Bar,\n  ChartCard,\n  Liquid,\n  MiniArea,\n  MiniSmoothArea,\n  MiniBar,\n  MiniProgress,\n  Radar,\n  TagCloud,\n  RankList,\n  TransferBar,\n  Trend,\n  Ellipsis,\n  FooterToolbar,\n  NumberInfo,\n  Tree,\n  STable,\n  MultiTab,\n  IconSelector,\n  TagSelect,\n  StandardFormRow,\n  ArticleListContent,\n\n  Dialog\n}\n"
  },
  {
    "path": "src/components/index.less",
    "content": "@import '~ant-design-vue/lib/style/index';\n\n// The prefix to use on all css classes from ant-pro.\n@ant-pro-prefix : ant-pro;\n@ant-global-sider-zindex : 106;\n@ant-global-header-zindex : 105;\n"
  },
  {
    "path": "src/components/tools/TwoStepCaptcha.vue",
    "content": "<template>\n  <!-- 两步验证 -->\n  <a-modal\n    centered\n    v-model=\"visible\"\n    @cancel=\"handleCancel\"\n    :maskClosable=\"false\"\n  >\n    <div slot=\"title\" :style=\"{ textAlign: 'center' }\">两步验证</div>\n    <template slot=\"footer\">\n      <div :style=\"{ textAlign: 'center' }\">\n        <a-button key=\"back\" @click=\"handleCancel\">返回</a-button>\n        <a-button key=\"submit\" type=\"primary\" :loading=\"stepLoading\" @click=\"handleStepOk\">\n          继续\n        </a-button>\n      </div>\n    </template>\n\n    <a-spin :spinning=\"stepLoading\">\n      <a-form layout=\"vertical\" :auto-form-create=\"(form)=>{this.form = form}\">\n        <div class=\"step-form-wrapper\">\n          <p style=\"text-align: center\" v-if=\"!stepLoading\">请在手机中打开 Google Authenticator 或两步验证 APP<br />输入 6 位动态码</p>\n          <p style=\"text-align: center\" v-else>正在验证..<br/>请稍后</p>\n          <a-form-item\n            :style=\"{ textAlign: 'center' }\"\n            hasFeedback\n            fieldDecoratorId=\"stepCode\"\n            :fieldDecoratorOptions=\"{rules: [{ required: true, message: '请输入 6 位动态码!', pattern: /^\\d{6}$/, len: 6 }]}\"\n          >\n            <a-input :style=\"{ textAlign: 'center' }\" @keyup.enter.native=\"handleStepOk\" placeholder=\"000000\" />\n          </a-form-item>\n          <p style=\"text-align: center\">\n            <a @click=\"onForgeStepCode\">遗失手机?</a>\n          </p>\n        </div>\n      </a-form>\n    </a-spin>\n  </a-modal>\n</template>\n\n<script>\nexport default {\n  props: {\n    visible: {\n      type: Boolean,\n      default: false\n    }\n  },\n  data () {\n    return {\n      stepLoading: false,\n\n      form: null\n    }\n  },\n  methods: {\n    handleStepOk () {\n      const vm = this\n      this.stepLoading = true\n      this.form.validateFields((err, values) => {\n        if (!err) {\n          console.log('values', values)\n          setTimeout(() => {\n            vm.stepLoading = false\n            vm.$emit('success', { values })\n          }, 2000)\n          return\n        }\n        this.stepLoading = false\n        this.$emit('error', { err })\n      })\n    },\n    handleCancel () {\n      this.visible = false\n      this.$emit('cancel')\n    },\n    onForgeStepCode () {\n\n    }\n  }\n}\n</script>\n<style lang=\"less\" scoped>\n  .step-form-wrapper {\n    margin: 0 auto;\n    width: 80%;\n    max-width: 400px;\n  }\n</style>\n"
  },
  {
    "path": "src/config/defaultSettings.js",
    "content": "/**\n * 项目默认配置项\n * primaryColor - 默认主题色, 如果修改颜色不生效，请清理 localStorage\n * navTheme - sidebar theme ['dark', 'light'] 两种主题\n * colorWeak - 色盲模式\n * layout - 整体布局方式 ['sidemenu', 'topmenu'] 两种布局\n * fixedHeader - 固定 Header : boolean\n * fixSiderbar - 固定左侧菜单栏 ： boolean\n * contentWidth - 内容区布局： 流式 |  固定\n *\n * storageOptions: {} - Vue-ls 插件配置项 (localStorage/sessionStorage)\n *\n */\n\nexport default {\n  navTheme: 'dark', // theme for nav menu\n  primaryColor: '#1890ff', // '#F5222D', // primary color of ant design\n  layout: 'sidemenu', // nav menu position: `sidemenu` or `topmenu`\n  contentWidth: 'Fluid', // layout of content: `Fluid` or `Fixed`, only works when layout is topmenu\n  fixedHeader: false, // sticky header\n  fixSiderbar: false, // sticky siderbar\n  colorWeak: false,\n  menu: {\n    locale: true\n  },\n  title: 'Ant Design Pro',\n  pwa: false,\n  iconfontUrl: '',\n  production: process.env.NODE_ENV === 'production' && process.env.VUE_APP_PREVIEW !== 'true'\n}\n"
  },
  {
    "path": "src/config/router.config.js",
    "content": "// eslint-disable-next-line\nimport { UserLayout, BasicLayout, BlankLayout } from '@/layouts'\nimport { bxAnaalyse } from '@/core/icons'\n\nconst RouteView = {\n  name: 'RouteView',\n  render: h => h('router-view')\n}\n\nexport const asyncRouterMap = [\n  {\n    path: '/',\n    name: 'index',\n    component: BasicLayout,\n    meta: { title: 'menu.home' },\n    redirect: '/dashboard/workplace',\n    children: [\n      // dashboard\n      {\n        path: '/dashboard',\n        name: 'dashboard',\n        redirect: '/dashboard/workplace',\n        component: RouteView,\n        meta: { title: 'menu.dashboard', keepAlive: true, icon: bxAnaalyse, permission: ['dashboard'] },\n        children: [\n          {\n            path: '/dashboard/analysis/:pageNo([1-9]\\\\d*)?',\n            name: 'Analysis',\n            component: () => import('@/views/dashboard/Analysis'),\n            meta: { title: 'menu.dashboard.analysis', keepAlive: false, permission: ['dashboard'] }\n          },\n          // 外部链接\n          // {\n          //   path: 'https://www.baidu.com/',\n          //   name: 'Monitor',\n          //   meta: { title: 'menu.dashboard.monitor', target: '_blank' }\n          // },\n          {\n            path: '/dashboard/workplace',\n            name: 'Workplace',\n            component: () => import('@/views/dashboard/Workplace'),\n            meta: { title: 'menu.dashboard.workplace', keepAlive: true, permission: ['dashboard'] }\n          }\n        ]\n      },\n      // forms\n      {\n        path: '/form',\n        redirect: '/form/base-form',\n        component: RouteView,\n        meta: { title: 'menu.form', icon: 'form', permission: ['form'] },\n        children: [\n          {\n            path: '/form/base-form',\n            name: 'BaseForm',\n            component: () => import('@/views/form/basicForm'),\n            meta: { title: 'menu.form.basic-form', keepAlive: true, permission: ['form'] }\n          },\n          {\n            path: '/form/step-form',\n            name: 'StepForm',\n            component: () => import('@/views/form/stepForm/StepForm'),\n            meta: { title: 'menu.form.step-form', keepAlive: true, permission: ['form'] }\n          },\n          {\n            path: '/form/advanced-form',\n            name: 'AdvanceForm',\n            component: () => import('@/views/form/advancedForm/AdvancedForm'),\n            meta: { title: 'menu.form.advanced-form', keepAlive: true, permission: ['form'] }\n          }\n        ]\n      },\n      // list\n      {\n        path: '/list',\n        name: 'list',\n        component: RouteView,\n        redirect: '/list/table-list',\n        meta: { title: 'menu.list', icon: 'table', permission: ['table'] },\n        children: [\n          {\n            path: '/list/table-list/:pageNo([1-9]\\\\d*)?',\n            name: 'TableListWrapper',\n            hideChildrenInMenu: true, // 强制显示 MenuItem 而不是 SubMenu\n            component: () => import('@/views/list/TableList'),\n            meta: { title: 'menu.list.table-list', keepAlive: true, permission: ['table'] }\n          },\n          {\n            path: '/list/basic-list',\n            name: 'BasicList',\n            component: () => import('@/views/list/BasicList'),\n            meta: { title: 'menu.list.basic-list', keepAlive: true, permission: ['table'] }\n          },\n          {\n            path: '/list/card',\n            name: 'CardList',\n            component: () => import('@/views/list/CardList'),\n            meta: { title: 'menu.list.card-list', keepAlive: true, permission: ['table'] }\n          },\n          {\n            path: '/list/search',\n            name: 'SearchList',\n            component: () => import('@/views/list/search/SearchLayout'),\n            redirect: '/list/search/article',\n            meta: { title: 'menu.list.search-list', keepAlive: true, permission: ['table'] },\n            children: [\n              {\n                path: '/list/search/article',\n                name: 'SearchArticles',\n                component: () => import('../views/list/search/Article'),\n                meta: { title: 'menu.list.search-list.articles', permission: ['table'] }\n              },\n              {\n                path: '/list/search/project',\n                name: 'SearchProjects',\n                component: () => import('../views/list/search/Projects'),\n                meta: { title: 'menu.list.search-list.projects', permission: ['table'] }\n              },\n              {\n                path: '/list/search/application',\n                name: 'SearchApplications',\n                component: () => import('../views/list/search/Applications'),\n                meta: { title: 'menu.list.search-list.applications', permission: ['table'] }\n              }\n            ]\n          }\n        ]\n      },\n\n      // profile\n      {\n        path: '/profile',\n        name: 'profile',\n        component: RouteView,\n        redirect: '/profile/basic',\n        meta: { title: 'menu.profile', icon: 'profile', permission: ['profile'] },\n        children: [\n          {\n            path: '/profile/basic',\n            name: 'ProfileBasic',\n            component: () => import('@/views/profile/basic'),\n            meta: { title: 'menu.profile.basic', permission: ['profile'] }\n          },\n          {\n            path: '/profile/advanced',\n            name: 'ProfileAdvanced',\n            component: () => import('@/views/profile/advanced/Advanced'),\n            meta: { title: 'menu.profile.advanced', permission: ['profile'] }\n          }\n        ]\n      },\n\n      // result\n      {\n        path: '/result',\n        name: 'result',\n        component: RouteView,\n        redirect: '/result/success',\n        meta: { title: 'menu.result', icon: 'check-circle-o', permission: ['result'] },\n        children: [\n          {\n            path: '/result/success',\n            name: 'ResultSuccess',\n            component: () => import(/* webpackChunkName: \"result\" */ '@/views/result/Success'),\n            meta: { title: 'menu.result.success', keepAlive: false, hiddenHeaderContent: true, permission: ['result'] }\n          },\n          {\n            path: '/result/fail',\n            name: 'ResultFail',\n            component: () => import(/* webpackChunkName: \"result\" */ '@/views/result/Error'),\n            meta: { title: 'menu.result.fail', keepAlive: false, hiddenHeaderContent: true, permission: ['result'] }\n          }\n        ]\n      },\n\n      // Exception\n      {\n        path: '/exception',\n        name: 'exception',\n        component: RouteView,\n        redirect: '/exception/403',\n        meta: { title: 'menu.exception', icon: 'warning', permission: ['exception'] },\n        children: [\n          {\n            path: '/exception/403',\n            name: 'Exception403',\n            component: () => import(/* webpackChunkName: \"fail\" */ '@/views/exception/403'),\n            meta: { title: 'menu.exception.not-permission', permission: ['exception'] }\n          },\n          {\n            path: '/exception/404',\n            name: 'Exception404',\n            component: () => import(/* webpackChunkName: \"fail\" */ '@/views/exception/404'),\n            meta: { title: 'menu.exception.not-find', permission: ['exception'] }\n          },\n          {\n            path: '/exception/500',\n            name: 'Exception500',\n            component: () => import(/* webpackChunkName: \"fail\" */ '@/views/exception/500'),\n            meta: { title: 'menu.exception.server-error', permission: ['exception'] }\n          }\n        ]\n      },\n\n      // account\n      {\n        path: '/account',\n        component: RouteView,\n        redirect: '/account/center',\n        name: 'account',\n        meta: { title: 'menu.account', icon: 'user', keepAlive: true, permission: ['user'] },\n        children: [\n          {\n            path: '/account/center',\n            name: 'center',\n            component: () => import('@/views/account/center'),\n            meta: { title: 'menu.account.center', keepAlive: true, permission: ['user'] }\n          },\n          {\n            path: '/account/settings',\n            name: 'settings',\n            component: () => import('@/views/account/settings/Index'),\n            meta: { title: 'menu.account.settings', hideHeader: true, permission: ['user'] },\n            redirect: '/account/settings/basic',\n            hideChildrenInMenu: true,\n            children: [\n              {\n                path: '/account/settings/basic',\n                name: 'BasicSettings',\n                component: () => import('@/views/account/settings/BasicSetting'),\n                meta: { title: 'account.settings.menuMap.basic', hidden: true, permission: ['user'] }\n              },\n              {\n                path: '/account/settings/security',\n                name: 'SecuritySettings',\n                component: () => import('@/views/account/settings/Security'),\n                meta: {\n                  title: 'account.settings.menuMap.security',\n                  hidden: true,\n                  keepAlive: true,\n                  permission: ['user']\n                }\n              },\n              {\n                path: '/account/settings/custom',\n                name: 'CustomSettings',\n                component: () => import('@/views/account/settings/Custom'),\n                meta: { title: 'account.settings.menuMap.custom', hidden: true, keepAlive: true, permission: ['user'] }\n              },\n              {\n                path: '/account/settings/binding',\n                name: 'BindingSettings',\n                component: () => import('@/views/account/settings/Binding'),\n                meta: { title: 'account.settings.menuMap.binding', hidden: true, keepAlive: true, permission: ['user'] }\n              },\n              {\n                path: '/account/settings/notification',\n                name: 'NotificationSettings',\n                component: () => import('@/views/account/settings/Notification'),\n                meta: {\n                  title: 'account.settings.menuMap.notification',\n                  hidden: true,\n                  keepAlive: true,\n                  permission: ['user']\n                }\n              }\n            ]\n          }\n        ]\n      }\n\n      // other\n      /*\n      {\n        path: '/other',\n        name: 'otherPage',\n        component: PageView,\n        meta: { title: '其他组件', icon: 'slack', permission: [ 'dashboard' ] },\n        redirect: '/other/icon-selector',\n        children: [\n          {\n            path: '/other/icon-selector',\n            name: 'TestIconSelect',\n            component: () => import('@/views/other/IconSelectorView'),\n            meta: { title: 'IconSelector', icon: 'tool', keepAlive: true, permission: [ 'dashboard' ] }\n          },\n          {\n            path: '/other/list',\n            component: RouteView,\n            meta: { title: '业务布局', icon: 'layout', permission: [ 'support' ] },\n            redirect: '/other/list/tree-list',\n            children: [\n              {\n                path: '/other/list/tree-list',\n                name: 'TreeList',\n                component: () => import('@/views/other/TreeList'),\n                meta: { title: '树目录表格', keepAlive: true }\n              },\n              {\n                path: '/other/list/edit-table',\n                name: 'EditList',\n                component: () => import('@/views/other/TableInnerEditList'),\n                meta: { title: '内联编辑表格', keepAlive: true }\n              },\n              {\n                path: '/other/list/user-list',\n                name: 'UserList',\n                component: () => import('@/views/other/UserList'),\n                meta: { title: '用户列表', keepAlive: true }\n              },\n              {\n                path: '/other/list/role-list',\n                name: 'RoleList',\n                component: () => import('@/views/other/RoleList'),\n                meta: { title: '角色列表', keepAlive: true }\n              },\n              {\n                path: '/other/list/system-role',\n                name: 'SystemRole',\n                component: () => import('@/views/role/RoleList'),\n                meta: { title: '角色列表2', keepAlive: true }\n              },\n              {\n                path: '/other/list/permission-list',\n                name: 'PermissionList',\n                component: () => import('@/views/other/PermissionList'),\n                meta: { title: '权限列表', keepAlive: true }\n              }\n            ]\n          }\n        ]\n      }\n      */\n    ]\n  },\n  {\n    path: '*',\n    redirect: '/404',\n    hidden: true\n  }\n]\n\n/**\n * 基础路由\n * @type { *[] }\n */\nexport const constantRouterMap = [\n  {\n    path: '/user',\n    component: UserLayout,\n    redirect: '/user/login',\n    hidden: true,\n    children: [\n      {\n        path: 'login',\n        name: 'login',\n        component: () => import(/* webpackChunkName: \"user\" */ '@/views/user/Login')\n      },\n      {\n        path: 'register',\n        name: 'register',\n        component: () => import(/* webpackChunkName: \"user\" */ '@/views/user/Register')\n      },\n      {\n        path: 'register-result',\n        name: 'registerResult',\n        component: () => import(/* webpackChunkName: \"user\" */ '@/views/user/RegisterResult')\n      },\n      {\n        path: 'recover',\n        name: 'recover',\n        component: undefined\n      }\n    ]\n  },\n\n  {\n    path: '/404',\n    component: () => import(/* webpackChunkName: \"fail\" */ '@/views/exception/404')\n  }\n]\n"
  },
  {
    "path": "src/core/bootstrap.js",
    "content": "import store from '@/store'\nimport storage from 'store'\nimport {\n  ACCESS_TOKEN,\n  APP_LANGUAGE,\n  TOGGLE_CONTENT_WIDTH,\n  TOGGLE_FIXED_HEADER,\n  TOGGLE_FIXED_SIDEBAR, TOGGLE_HIDE_HEADER,\n  TOGGLE_LAYOUT, TOGGLE_NAV_THEME, TOGGLE_WEAK,\n  TOGGLE_COLOR, TOGGLE_MULTI_TAB\n} from '@/store/mutation-types'\nimport { printANSI } from '@/utils/screenLog'\nimport defaultSettings from '@/config/defaultSettings'\n\nexport default function Initializer () {\n  printANSI() // 请自行移除该行.  please remove this line\n\n  store.commit(TOGGLE_LAYOUT, storage.get(TOGGLE_LAYOUT, defaultSettings.layout))\n  store.commit(TOGGLE_FIXED_HEADER, storage.get(TOGGLE_FIXED_HEADER, defaultSettings.fixedHeader))\n  store.commit(TOGGLE_FIXED_SIDEBAR, storage.get(TOGGLE_FIXED_SIDEBAR, defaultSettings.fixSiderbar))\n  store.commit(TOGGLE_CONTENT_WIDTH, storage.get(TOGGLE_CONTENT_WIDTH, defaultSettings.contentWidth))\n  store.commit(TOGGLE_HIDE_HEADER, storage.get(TOGGLE_HIDE_HEADER, defaultSettings.autoHideHeader))\n  store.commit(TOGGLE_NAV_THEME, storage.get(TOGGLE_NAV_THEME, defaultSettings.navTheme))\n  store.commit(TOGGLE_WEAK, storage.get(TOGGLE_WEAK, defaultSettings.colorWeak))\n  store.commit(TOGGLE_COLOR, storage.get(TOGGLE_COLOR, defaultSettings.primaryColor))\n  store.commit(TOGGLE_MULTI_TAB, storage.get(TOGGLE_MULTI_TAB, defaultSettings.multiTab))\n  store.commit('SET_TOKEN', storage.get(ACCESS_TOKEN))\n\n  store.dispatch('setLang', storage.get(APP_LANGUAGE, 'en-US'))\n  // last step\n}\n"
  },
  {
    "path": "src/core/directives/action.js",
    "content": "import Vue from 'vue'\nimport store from '@/store'\n\n/**\n * Action 权限指令\n * 指令用法：\n *  - 在需要控制 action 级别权限的组件上使用 v-action:[method] , 如下：\n *    <i-button v-action:add >添加用户</a-button>\n *    <a-button v-action:delete>删除用户</a-button>\n *    <a v-action:edit @click=\"edit(record)\">修改</a>\n *\n *  - 当前用户没有权限时，组件上使用了该指令则会被隐藏\n *  - 当后台权限跟 pro 提供的模式不同时，只需要针对这里的权限过滤进行修改即可\n *\n *  @see https://github.com/vueComponent/ant-design-vue-pro/pull/53\n */\nconst action = Vue.directive('action', {\n  inserted: function (el, binding, vnode) {\n    const actionName = binding.arg\n    const roles = store.getters.roles\n    const elVal = vnode.context.$route.meta.permission\n    const permissionId = Object.prototype.toString.call(elVal) === '[object String]' && [elVal] || elVal\n    roles.permissions.forEach(p => {\n      if (!permissionId.includes(p.permissionId)) {\n        return\n      }\n      if (p.actionList && !p.actionList.includes(actionName)) {\n        el.parentNode && el.parentNode.removeChild(el) || (el.style.display = 'none')\n      }\n    })\n  }\n})\n\nexport default action\n"
  },
  {
    "path": "src/core/icons.js",
    "content": "/**\n * Custom icon list\n * All icons are loaded here for easy management\n * @see https://vue.ant.design/components/icon/#Custom-Font-Icon\n *\n * 自定义图标加载表\n * 所有图标均从这里加载，方便管理\n */\nimport bxAnaalyse from '@/assets/icons/bx-analyse.svg?inline' // path to your '*.svg?inline' file.\n\nexport { bxAnaalyse }\n"
  },
  {
    "path": "src/core/lazy_use.js",
    "content": "import Vue from 'vue'\n\n// base library\nimport {\n  ConfigProvider,\n  Layout,\n  Input,\n  InputNumber,\n  Button,\n  Switch,\n  Radio,\n  Checkbox,\n  Select,\n  Card,\n  Form,\n  Row,\n  Col,\n  Modal,\n  Table,\n  Tabs,\n  Icon,\n  Badge,\n  Popover,\n  Dropdown,\n  List,\n  Avatar,\n  Breadcrumb,\n  Steps,\n  Spin,\n  Menu,\n  Drawer,\n  Tooltip,\n  Alert,\n  Tag,\n  Divider,\n  DatePicker,\n  TimePicker,\n  Upload,\n  Progress,\n  Skeleton,\n  Popconfirm,\n  PageHeader,\n  Result,\n  Statistic,\n  Descriptions,\n  Space,\n  message,\n  notification\n} from 'ant-design-vue'\nimport Viser from 'viser-vue'\n\n// ext library\nimport VueCropper from 'vue-cropper'\nimport Dialog from '@/components/Dialog'\nimport MultiTab from '@/components/MultiTab'\nimport PageLoading from '@/components/PageLoading'\nimport PermissionHelper from '@/core/permission/permission'\nimport './directives/action'\n\nVue.use(ConfigProvider)\nVue.use(Layout)\nVue.use(Input)\nVue.use(InputNumber)\nVue.use(Button)\nVue.use(Switch)\nVue.use(Radio)\nVue.use(Checkbox)\nVue.use(Select)\nVue.use(Card)\nVue.use(Form)\nVue.use(Row)\nVue.use(Col)\nVue.use(Modal)\nVue.use(Table)\nVue.use(Tabs)\nVue.use(Icon)\nVue.use(Badge)\nVue.use(Popover)\nVue.use(Dropdown)\nVue.use(List)\nVue.use(Avatar)\nVue.use(Breadcrumb)\nVue.use(Steps)\nVue.use(Spin)\nVue.use(Menu)\nVue.use(Drawer)\nVue.use(Tooltip)\nVue.use(Alert)\nVue.use(Tag)\nVue.use(Divider)\nVue.use(DatePicker)\nVue.use(TimePicker)\nVue.use(Upload)\nVue.use(Progress)\nVue.use(Skeleton)\nVue.use(Popconfirm)\nVue.use(PageHeader)\nVue.use(Result)\nVue.use(Statistic)\nVue.use(Descriptions)\nVue.use(Space)\n\nVue.prototype.$confirm = Modal.confirm\nVue.prototype.$message = message\nVue.prototype.$notification = notification\nVue.prototype.$info = Modal.info\nVue.prototype.$success = Modal.success\nVue.prototype.$error = Modal.error\nVue.prototype.$warning = Modal.warning\n\nVue.use(Viser)\nVue.use(Dialog) // this.$dialog func\nVue.use(MultiTab)\nVue.use(PageLoading)\nVue.use(PermissionHelper)\nVue.use(VueCropper)\n\nprocess.env.NODE_ENV !== 'production' && console.warn('[antd-pro] NOTICE: Antd use lazy-load.')\n"
  },
  {
    "path": "src/core/permission/permission.js",
    "content": "export const PERMISSION_ENUM = {\n  'add': { key: 'add', label: '新增' },\n  'delete': { key: 'delete', label: '删除' },\n  'edit': { key: 'edit', label: '修改' },\n  'query': { key: 'query', label: '查询' },\n  'get': { key: 'get', label: '详情' },\n  'enable': { key: 'enable', label: '启用' },\n  'disable': { key: 'disable', label: '禁用' },\n  'import': { key: 'import', label: '导入' },\n  'export': { key: 'export', label: '导出' }\n}\n\n/**\n * <a-button v-if=\"$auth('form.edit')\">Button</a-button>\n * @param Vue\n */\nfunction plugin (Vue) {\n  if (plugin.installed) {\n    return\n  }\n\n  !Vue.prototype.$auth && Object.defineProperties(Vue.prototype, {\n    $auth: {\n      get () {\n        const _this = this\n        return (permissions) => {\n          const [permission, action] = permissions.split('.')\n          const permissionList = _this.$store.getters.roles.permissions\n          return permissionList.find((val) => {\n            return val.permissionId === permission\n          }).actionList.findIndex((val) => {\n            return val === action\n          }) > -1\n        }\n      }\n    }\n  })\n\n  !Vue.prototype.$enum && Object.defineProperties(Vue.prototype, {\n    $enum: {\n      get () {\n        // const _this = this;\n        return (val) => {\n          let result = PERMISSION_ENUM\n          val && val.split('.').forEach(v => {\n            result = result && result[v] || null\n          })\n          return result\n        }\n      }\n    }\n  })\n}\n\nexport default plugin\n"
  },
  {
    "path": "src/core/use.js",
    "content": "import Vue from 'vue'\n\n// base library\nimport Antd from 'ant-design-vue'\nimport Viser from 'viser-vue'\nimport VueCropper from 'vue-cropper'\nimport 'ant-design-vue/dist/antd.less'\n\n// ext library\nimport VueClipboard from 'vue-clipboard2'\nimport MultiTab from '@/components/MultiTab'\nimport PageLoading from '@/components/PageLoading'\nimport PermissionHelper from '@/core/permission/permission'\n// import '@/components/use'\nimport './directives/action'\n\nVueClipboard.config.autoSetContainer = true\n\nVue.use(Antd)\nVue.use(Viser)\nVue.use(MultiTab)\nVue.use(PageLoading)\nVue.use(VueClipboard)\nVue.use(PermissionHelper)\nVue.use(VueCropper)\n\nprocess.env.NODE_ENV !== 'production' && console.warn('[antd-pro] WARNING: Antd now use fulled imported.')\n"
  },
  {
    "path": "src/global.less",
    "content": "@import '~ant-design-vue/es/style/themes/default.less';\n\nhtml,\nbody,\n#app,\n#root {\n  height: 100%;\n}\n\n.colorWeak {\n  filter: invert(80%);\n}\n\n.ant-layout.layout-basic {\n  height: 100vh;\n  min-height: 100vh;\n}\n\ncanvas {\n  display: block;\n}\n\nbody {\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  text-rendering: optimizelegibility;\n}\n\nul,\nol {\n  list-style: none;\n}\n\n// 数据列表 样式\n.table-alert {\n  margin-bottom: 16px;\n}\n// 数据列表 操作\n.table-operator {\n  margin-bottom: 18px;\n\n  button {\n    margin-right: 8px;\n  }\n}\n// 数据列表 搜索条件\n.table-page-search-wrapper {\n  .ant-form-inline {\n    .ant-form-item {\n      display: flex;\n      margin-right: 0;\n      margin-bottom: 24px;\n\n      .ant-form-item-control-wrapper {\n        flex: 1 1;\n        display: inline-block;\n        vertical-align: middle;\n      }\n\n      > .ant-form-item-label {\n        width: auto;\n        padding-right: 8px;\n        line-height: 32px;\n      }\n\n      .ant-form-item-control {\n        height: 32px;\n        line-height: 32px;\n      }\n    }\n  }\n\n  .table-page-search-submitButtons {\n    display: block;\n    margin-bottom: 24px;\n    white-space: nowrap;\n  }\n}\n\n@media (max-width: @screen-xs) {\n  .ant-table {\n    width: 100%;\n    overflow-x: auto;\n\n    &-thead > tr,\n    &-tbody > tr {\n      > th,\n      > td {\n        white-space: pre;\n\n        > span {\n          display: block;\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/layouts/BasicLayout.less",
    "content": "@import '~ant-design-vue/es/style/themes/default.less';\n\n.ant-pro-global-header-index-right {\n  margin-right: 8px;\n\n  &.ant-pro-global-header-index-dark {\n    .ant-pro-global-header-index-action {\n      color: hsl(0deg 0% 100% / 85%);\n\n      &:hover {\n        background: #1890ff;\n      }\n    }\n  }\n\n  .ant-pro-account-avatar {\n    .antd-pro-global-header-index-avatar {\n      margin: ~'calc((@{layout-header-height} - 24px) / 2)' 0;\n      margin-right: 8px;\n      color: @primary-color;\n      vertical-align: top;\n      background: rgb(255 255 255 / 85%);\n    }\n  }\n\n  .menu {\n    .anticon {\n      margin-right: 8px;\n    }\n\n    .ant-dropdown-menu-item {\n      min-width: 100px;\n    }\n  }\n}\n"
  },
  {
    "path": "src/layouts/BasicLayout.vue",
    "content": "<template>\n  <pro-layout\n    :menus=\"menus\"\n    :collapsed=\"collapsed\"\n    :mediaQuery=\"query\"\n    :isMobile=\"isMobile\"\n    :handleMediaQuery=\"handleMediaQuery\"\n    :handleCollapse=\"handleCollapse\"\n    :i18nRender=\"i18nRender\"\n    v-bind=\"settings\"\n  >\n    <!-- Ads begin\n      广告代码 真实项目中请移除\n      production remove this Ads\n    -->\n    <ads v-if=\"isProPreviewSite && !collapsed\"/>\n    <!-- Ads end -->\n\n    <!-- 1.0.0+ 版本 pro-layout 提供 API，\n          我们推荐使用这种方式进行 LOGO 和 title 自定义\n    -->\n    <template v-slot:menuHeaderRender>\n      <div>\n        <img src=\"@/assets/logo.svg\" />\n        <h1>{{ title }}</h1>\n      </div>\n    </template>\n    <!-- 1.0.0+ 版本 pro-layout 提供 API,\n          增加 Header 左侧内容区自定义\n    -->\n    <template v-slot:headerContentRender>\n      <div>\n        <a-tooltip title=\"刷新页面\">\n          <a-icon type=\"reload\" style=\"font-size: 18px;cursor: pointer;\" @click=\"() => { $message.info('只是一个DEMO') }\" />\n        </a-tooltip>\n      </div>\n    </template>\n\n    <setting-drawer v-if=\"isDev\" :settings=\"settings\" @change=\"handleSettingChange\">\n      <div style=\"margin: 12px 0;\">\n        This is SettingDrawer custom footer content.\n      </div>\n    </setting-drawer>\n    <template v-slot:rightContentRender>\n      <right-content :top-menu=\"settings.layout === 'topmenu'\" :is-mobile=\"isMobile\" :theme=\"settings.theme\" />\n    </template>\n    <!-- custom footer / 自定义Footer -->\n    <template v-slot:footerRender>\n      <global-footer />\n    </template>\n    <router-view />\n  </pro-layout>\n</template>\n\n<script>\nimport { SettingDrawer, updateTheme } from '@ant-design-vue/pro-layout'\nimport { i18nRender } from '@/locales'\nimport { mapState } from 'vuex'\nimport { CONTENT_WIDTH_TYPE, SIDEBAR_TYPE, TOGGLE_MOBILE_TYPE } from '@/store/mutation-types'\n\nimport defaultSettings from '@/config/defaultSettings'\nimport RightContent from '@/components/GlobalHeader/RightContent'\nimport GlobalFooter from '@/components/GlobalFooter'\nimport Ads from '@/components/Other/CarbonAds'\n\nexport default {\n  name: 'BasicLayout',\n  components: {\n    SettingDrawer,\n    RightContent,\n    GlobalFooter,\n    Ads\n  },\n  data () {\n    return {\n      // preview.pro.antdv.com only use.\n      isProPreviewSite: process.env.VUE_APP_PREVIEW === 'true' && process.env.NODE_ENV !== 'development',\n      // end\n      isDev: process.env.NODE_ENV === 'development' || process.env.VUE_APP_PREVIEW === 'true',\n\n      // base\n      menus: [],\n      // 侧栏收起状态\n      collapsed: false,\n      title: defaultSettings.title,\n      settings: {\n        // 布局类型\n        layout: defaultSettings.layout, // 'sidemenu', 'topmenu'\n        // CONTENT_WIDTH_TYPE\n        contentWidth: defaultSettings.layout === 'sidemenu' ? CONTENT_WIDTH_TYPE.Fluid : defaultSettings.contentWidth,\n        // 主题 'dark' | 'light'\n        theme: defaultSettings.navTheme,\n        // 主色调\n        primaryColor: defaultSettings.primaryColor,\n        fixedHeader: defaultSettings.fixedHeader,\n        fixSiderbar: defaultSettings.fixSiderbar,\n        colorWeak: defaultSettings.colorWeak,\n\n        hideHintAlert: false,\n        hideCopyButton: false\n      },\n      // 媒体查询\n      query: {},\n\n      // 是否手机模式\n      isMobile: false\n    }\n  },\n  computed: {\n    ...mapState({\n      // 动态主路由\n      mainMenu: state => state.permission.addRouters\n    })\n  },\n  created () {\n    const routes = this.mainMenu.find(item => item.path === '/')\n    this.menus = (routes && routes.children) || []\n    // 处理侧栏收起状态\n    this.$watch('collapsed', () => {\n      this.$store.commit(SIDEBAR_TYPE, this.collapsed)\n    })\n    this.$watch('isMobile', () => {\n      this.$store.commit(TOGGLE_MOBILE_TYPE, this.isMobile)\n    })\n  },\n  mounted () {\n    const userAgent = navigator.userAgent\n    if (userAgent.indexOf('Edge') > -1) {\n      this.$nextTick(() => {\n        this.collapsed = !this.collapsed\n        setTimeout(() => {\n          this.collapsed = !this.collapsed\n        }, 16)\n      })\n    }\n\n    // first update color\n    // TIPS: THEME COLOR HANDLER!! PLEASE CHECK THAT!!\n    if (process.env.NODE_ENV !== 'production' || process.env.VUE_APP_PREVIEW === 'true') {\n      updateTheme(this.settings.primaryColor)\n    }\n  },\n  methods: {\n    i18nRender,\n    handleMediaQuery (val) {\n      this.query = val\n      if (this.isMobile && !val['screen-xs']) {\n        this.isMobile = false\n        return\n      }\n      if (!this.isMobile && val['screen-xs']) {\n        this.isMobile = true\n        this.collapsed = false\n        this.settings.contentWidth = CONTENT_WIDTH_TYPE.Fluid\n        // this.settings.fixSiderbar = false\n      }\n    },\n    handleCollapse (val) {\n      this.collapsed = val\n    },\n    handleSettingChange ({ type, value }) {\n      console.log('type', type, value)\n      type && (this.settings[type] = value)\n      switch (type) {\n        case 'contentWidth':\n          this.settings[type] = value\n          break\n        case 'layout':\n          if (value === 'sidemenu') {\n            this.settings.contentWidth = CONTENT_WIDTH_TYPE.Fluid\n          } else {\n            this.settings.fixSiderbar = false\n            this.settings.contentWidth = CONTENT_WIDTH_TYPE.Fixed\n          }\n          break\n      }\n    }\n  }\n}\n</script>\n\n<style lang=\"less\">\n@import \"./BasicLayout.less\";\n</style>\n"
  },
  {
    "path": "src/layouts/BlankLayout.vue",
    "content": "<template>\n  <div>\n    <router-view />\n  </div>\n</template>\n\n<script>\n\nexport default {\n  name: 'BlankLayout'\n}\n</script>\n\n<style scoped>\n\n</style>\n"
  },
  {
    "path": "src/layouts/PageView.vue",
    "content": "<template>\n  <page-header-wrapper>\n    <router-view />\n  </page-header-wrapper>\n</template>\n\n<script>\n\nexport default {\n  name: 'PageView'\n}\n</script>\n"
  },
  {
    "path": "src/layouts/RouteView.vue",
    "content": "<script>\nexport default {\n  name: 'RouteView',\n  props: {\n    keepAlive: {\n      type: Boolean,\n      default: true\n    }\n  },\n  data () {\n    return {}\n  },\n  render () {\n    const { $route: { meta }, $store: { getters } } = this\n    const inKeep = (\n      <keep-alive>\n        <router-view />\n      </keep-alive>\n    )\n    const notKeep = (\n      <router-view />\n    )\n    // 这里增加了 multiTab 的判断，当开启了 multiTab 时\n    // 应当全部组件皆缓存，否则会导致切换页面后页面还原成原始状态\n    // 若确实不需要，可改为 return meta.keepAlive ? inKeep : notKeep\n    if (!getters.multiTab && !meta.keepAlive) {\n      return notKeep\n    }\n    return this.keepAlive || getters.multiTab || meta.keepAlive ? inKeep : notKeep\n  }\n}\n</script>\n"
  },
  {
    "path": "src/layouts/UserLayout.vue",
    "content": "<template>\n\n  <div id=\"userLayout\" :class=\"['user-layout-wrapper', isMobile && 'mobile']\">\n    <div class=\"container\">\n      <div class=\"user-layout-lang\">\n        <select-lang class=\"select-lang-trigger\" />\n      </div>\n      <div class=\"user-layout-content\">\n        <div class=\"top\">\n          <div class=\"header\">\n            <a href=\"/\">\n              <img src=\"~@/assets/logo.svg\" class=\"logo\" alt=\"logo\">\n              <span class=\"title\">Ant Design</span>\n            </a>\n          </div>\n          <div class=\"desc\">\n            {{ $t('layouts.userLayout.title') }}\n          </div>\n        </div>\n\n        <router-view />\n\n        <div class=\"footer\">\n          <div class=\"links\">\n            <a href=\"_self\">帮助</a>\n            <a href=\"_self\">隐私</a>\n            <a href=\"_self\">条款</a>\n          </div>\n          <div class=\"copyright\">\n            Copyright &copy; 2018 vueComponent\n          </div>\n        </div>\n      </div>\n    </div>\n  </div>\n</template>\n\n<script>\nimport { deviceMixin } from '@/store/device-mixin'\nimport SelectLang from '@/components/SelectLang'\n\nexport default {\n  name: 'UserLayout',\n  components: {\n    SelectLang\n  },\n  mixins: [deviceMixin],\n  mounted () {\n    document.body.classList.add('userLayout')\n  },\n  beforeDestroy () {\n    document.body.classList.remove('userLayout')\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n#userLayout.user-layout-wrapper {\n  height: 100%;\n\n  &.mobile {\n    .container {\n      .main {\n        max-width: 368px;\n        width: 98%;\n      }\n    }\n  }\n\n  .container {\n    width: 100%;\n    min-height: 100%;\n    background: #f0f2f5 url(~@/assets/background.svg) no-repeat 50%;\n    background-size: 100%;\n    //padding: 50px 0 84px;\n    position: relative;\n\n    .user-layout-lang {\n      width: 100%;\n      height: 40px;\n      line-height: 44px;\n      text-align: right;\n\n      .select-lang-trigger {\n        cursor: pointer;\n        padding: 12px;\n        margin-right: 24px;\n        display: inline-flex;\n        align-items: center;\n        justify-content: center;\n        font-size: 18px;\n        vertical-align: middle;\n      }\n    }\n\n    .user-layout-content {\n      padding: 32px 0 24px;\n\n      .top {\n        text-align: center;\n\n        .header {\n          height: 44px;\n          line-height: 44px;\n\n          .badge {\n            position: absolute;\n            display: inline-block;\n            line-height: 1;\n            vertical-align: middle;\n            margin-left: -12px;\n            margin-top: -10px;\n            opacity: 0.8;\n          }\n\n          .logo {\n            height: 44px;\n            vertical-align: top;\n            margin-right: 16px;\n            border-style: none;\n          }\n\n          .title {\n            font-size: 33px;\n            color: rgba(0, 0, 0, .85);\n            font-family: Avenir, 'Helvetica Neue', Arial, Helvetica, sans-serif;\n            font-weight: 600;\n            position: relative;\n            top: 2px;\n          }\n        }\n        .desc {\n          font-size: 14px;\n          color: rgba(0, 0, 0, 0.45);\n          margin-top: 12px;\n          margin-bottom: 40px;\n        }\n      }\n\n      .main {\n        min-width: 260px;\n        width: 368px;\n        margin: 0 auto;\n      }\n\n      .footer {\n        // position: absolute;\n        width: 100%;\n        bottom: 0;\n        padding: 0 16px;\n        margin: 48px 0 24px;\n        text-align: center;\n\n        .links {\n          margin-bottom: 8px;\n          font-size: 14px;\n          a {\n            color: rgba(0, 0, 0, 0.45);\n            transition: all 0.3s;\n            &:not(:last-child) {\n              margin-right: 40px;\n            }\n          }\n        }\n        .copyright {\n          color: rgba(0, 0, 0, 0.45);\n          font-size: 14px;\n        }\n      }\n    }\n\n    a {\n      text-decoration: none;\n    }\n\n  }\n}\n</style>\n"
  },
  {
    "path": "src/layouts/index.js",
    "content": "import UserLayout from './UserLayout'\nimport BlankLayout from './BlankLayout'\nimport BasicLayout from './BasicLayout'\nimport RouteView from './RouteView'\nimport PageView from './PageView'\n\nexport { UserLayout, BasicLayout, BlankLayout, RouteView, PageView }\n"
  },
  {
    "path": "src/locales/index.js",
    "content": "import Vue from 'vue'\nimport VueI18n from 'vue-i18n'\nimport storage from 'store'\nimport moment from 'moment'\n\n// default lang\nimport enUS from './lang/en-US'\n\nVue.use(VueI18n)\n\nexport const defaultLang = 'en-US'\n\nconst messages = {\n  'en-US': {\n    ...enUS\n  }\n}\n\nconst i18n = new VueI18n({\n  silentTranslationWarn: true,\n  locale: defaultLang,\n  fallbackLocale: defaultLang,\n  messages\n})\n\nconst loadedLanguages = [defaultLang]\n\nfunction setI18nLanguage (lang) {\n  i18n.locale = lang\n  // request.headers['Accept-Language'] = lang\n  document.querySelector('html').setAttribute('lang', lang)\n  return lang\n}\n\nexport function loadLanguageAsync (lang = defaultLang) {\n  return new Promise(resolve => {\n    // 缓存语言设置\n    storage.set('lang', lang)\n    if (i18n.locale !== lang) {\n      if (!loadedLanguages.includes(lang)) {\n        return import(/* webpackChunkName: \"lang-[request]\" */ `./lang/${lang}`).then(msg => {\n          const locale = msg.default\n          i18n.setLocaleMessage(lang, locale)\n          loadedLanguages.push(lang)\n          moment.updateLocale(locale.momentName, locale.momentLocale)\n          return setI18nLanguage(lang)\n        })\n      }\n      return resolve(setI18nLanguage(lang))\n    }\n    return resolve(lang)\n  })\n}\n\nexport function i18nRender (key) {\n  return i18n.t(`${key}`)\n}\n\nexport default i18n\n"
  },
  {
    "path": "src/locales/lang/en-US/account/settings.js",
    "content": "export default {\n  'account.settings.menuMap.basic': 'Basic Settings',\n  'account.settings.menuMap.security': 'Security Settings',\n  'account.settings.menuMap.custom': 'Custom Settings',\n  'account.settings.menuMap.binding': 'Account Binding',\n  'account.settings.menuMap.notification': 'New Message Notification',\n  'account.settings.basic.avatar': 'Avatar',\n  'account.settings.basic.change-avatar': 'Change avatar',\n  'account.settings.basic.email': 'Email',\n  'account.settings.basic.email-message': 'Please input your email!',\n  'account.settings.basic.nickname': 'Nickname',\n  'account.settings.basic.nickname-message': 'Please input your Nickname!',\n  'account.settings.basic.profile': 'Personal profile',\n  'account.settings.basic.profile-message': 'Please input your personal profile!',\n  'account.settings.basic.profile-placeholder': 'Brief introduction to yourself',\n  'account.settings.basic.country': 'Country/Region',\n  'account.settings.basic.country-message': 'Please input your country!',\n  'account.settings.basic.geographic': 'Province or city',\n  'account.settings.basic.geographic-message': 'Please input your geographic info!',\n  'account.settings.basic.address': 'Street Address',\n  'account.settings.basic.address-message': 'Please input your address!',\n  'account.settings.basic.phone': 'Phone Number',\n  'account.settings.basic.phone-message': 'Please input your phone!',\n  'account.settings.basic.update': 'Update Information',\n  'account.settings.basic.update.success': 'Update basic information successfully',\n  'account.settings.security.strong': 'Strong',\n  'account.settings.security.medium': 'Medium',\n  'account.settings.security.weak': 'Weak',\n  'account.settings.security.password': 'Account Password',\n  'account.settings.security.password-description': 'Current password strength：',\n  'account.settings.security.phone': 'Security Phone',\n  'account.settings.security.phone-description': 'Bound phone：',\n  'account.settings.security.question': 'Security Question',\n  'account.settings.security.question-description':\n    'The security question is not set, and the security policy can effectively protect the account security',\n  'account.settings.security.email': 'Backup Email',\n  'account.settings.security.email-description': 'Bound Email：',\n  'account.settings.security.mfa': 'MFA Device',\n  'account.settings.security.mfa-description':\n    'Unbound MFA device, after binding, can be confirmed twice',\n  'account.settings.security.modify': 'Modify',\n  'account.settings.security.set': 'Set',\n  'account.settings.security.bind': 'Bind',\n  'account.settings.binding.taobao': 'Binding Taobao',\n  'account.settings.binding.taobao-description': 'Currently unbound Taobao account',\n  'account.settings.binding.alipay': 'Binding Alipay',\n  'account.settings.binding.alipay-description': 'Currently unbound Alipay account',\n  'account.settings.binding.dingding': 'Binding DingTalk',\n  'account.settings.binding.dingding-description': 'Currently unbound DingTalk account',\n  'account.settings.binding.bind': 'Bind',\n  'account.settings.notification.password': 'Account Password',\n  'account.settings.notification.password-description':\n    'Messages from other users will be notified in the form of a station letter',\n  'account.settings.notification.messages': 'System Messages',\n  'account.settings.notification.messages-description':\n    'System messages will be notified in the form of a station letter',\n  'account.settings.notification.todo': 'To-do Notification',\n  'account.settings.notification.todo-description':\n    'The to-do list will be notified in the form of a letter from the station',\n  'account.settings.settings.open': 'Open',\n  'account.settings.settings.close': 'Close'\n}\n"
  },
  {
    "path": "src/locales/lang/en-US/account.js",
    "content": "import settings from './account/settings'\n\nexport default {\n    ...settings\n  }\n"
  },
  {
    "path": "src/locales/lang/en-US/dashboard/analysis.js",
    "content": "export default {\n  'dashboard.analysis.test': 'Gongzhuan No.{no} shop',\n  'dashboard.analysis.introduce': 'Introduce',\n  'dashboard.analysis.total-sales': 'Total Sales',\n  'dashboard.analysis.day-sales': 'Daily Sales',\n  'dashboard.analysis.visits': 'Visits',\n  'dashboard.analysis.visits-trend': 'Visits Trend',\n  'dashboard.analysis.visits-ranking': 'Visits Ranking',\n  'dashboard.analysis.day-visits': 'Daily Visits',\n  'dashboard.analysis.week': 'WoW Change',\n  'dashboard.analysis.day': 'DoD Change',\n  'dashboard.analysis.payments': 'Payments',\n  'dashboard.analysis.conversion-rate': 'Conversion Rate',\n  'dashboard.analysis.operational-effect': 'Operational Effect',\n  'dashboard.analysis.sales-trend': 'Stores Sales Trend',\n  'dashboard.analysis.sales-ranking': 'Sales Ranking',\n  'dashboard.analysis.all-year': 'All Year',\n  'dashboard.analysis.all-month': 'All Month',\n  'dashboard.analysis.all-week': 'All Week',\n  'dashboard.analysis.all-day': 'All day',\n  'dashboard.analysis.search-users': 'Search Users',\n  'dashboard.analysis.per-capita-search': 'Per Capita Search',\n  'dashboard.analysis.online-top-search': 'Online Top Search',\n  'dashboard.analysis.the-proportion-of-sales': 'The Proportion Of Sales',\n  'dashboard.analysis.dropdown-option-one': 'Operation one',\n  'dashboard.analysis.dropdown-option-two': 'Operation two',\n  'dashboard.analysis.channel.all': 'ALL',\n  'dashboard.analysis.channel.online': 'Online',\n  'dashboard.analysis.channel.stores': 'Stores',\n  'dashboard.analysis.sales': 'Sales',\n  'dashboard.analysis.traffic': 'Traffic',\n  'dashboard.analysis.table.rank': 'Rank',\n  'dashboard.analysis.table.search-keyword': 'Keyword',\n  'dashboard.analysis.table.users': 'Users',\n  'dashboard.analysis.table.weekly-range': 'Weekly Range'\n}\n"
  },
  {
    "path": "src/locales/lang/en-US/dashboard.js",
    "content": "import analysis from './dashboard/analysis'\n\nexport default {\n    ...analysis\n  }\n"
  },
  {
    "path": "src/locales/lang/en-US/form/basicForm.js",
    "content": "export default {\n  'form.basic-form.basic.title': 'Basic form',\n  'form.basic-form.basic.description':\n   'Form pages are used to collect or verify information to users, and basic forms are common in scenarios where there are fewer data items.',\n  'form.basic-form.title.label': 'Title',\n  'form.basic-form.title.placeholder': 'Give the target a name',\n  'form.basic-form.title.required': 'Please enter a title',\n  'form.basic-form.date.label': 'Start and end date',\n  'form.basic-form.placeholder.start': 'Start date',\n  'form.basic-form.placeholder.end': 'End date',\n  'form.basic-form.date.required': 'Please select the start and end date',\n  'form.basic-form.goal.label': 'Goal description',\n  'form.basic-form.goal.placeholder': 'Please enter your work goals',\n  'form.basic-form.goal.required': 'Please enter a description of the goal',\n  'form.basic-form.standard.label': 'Metrics',\n  'form.basic-form.standard.placeholder': 'Please enter a metric',\n  'form.basic-form.standard.required': 'Please enter a metric',\n  'form.basic-form.client.label': 'Client',\n  'form.basic-form.label.tooltip': 'Target service object',\n  'form.basic-form.client.placeholder':\n    'Please describe your customer service, internal customers directly @ Name / job number',\n  'form.basic-form.client.required': 'Please describe the customers you serve',\n  'form.basic-form.invites.label': 'Inviting critics',\n  'form.basic-form.invites.placeholder':\n    'Please direct @ Name / job number, you can invite up to 5 people',\n  'form.basic-form.weight.label': 'Weight',\n  'form.basic-form.weight.placeholder': 'Please enter weight',\n  'form.basic-form.public.label': 'Target disclosure',\n  'form.basic-form.label.help': 'Customers and invitees are shared by default',\n  'form.basic-form.radio.public': 'Public',\n  'form.basic-form.radio.partially-public': 'Partially public',\n  'form.basic-form.radio.private': 'Private',\n  'form.basic-form.publicUsers.placeholder': 'Open to',\n  'form.basic-form.option.A': 'Colleague A',\n  'form.basic-form.option.B': 'Colleague B',\n  'form.basic-form.option.C': 'Colleague C',\n  'form.basic-form.email.required': 'Please enter your email!',\n  'form.basic-form.email.wrong-format': 'The email address is in the wrong format!',\n  'form.basic-form.userName.required': 'Please enter your userName!',\n  'form.basic-form.password.required': 'Please enter your password!',\n  'form.basic-form.password.twice': 'The passwords entered twice do not match!',\n  'form.basic-form.strength.msg':\n    \"Please enter at least 6 characters and don't use passwords that are easy to guess.\",\n  'form.basic-form.strength.strong': 'Strength: strong',\n  'form.basic-form.strength.medium': 'Strength: medium',\n  'form.basic-form.strength.short': 'Strength: too short',\n  'form.basic-form.confirm-password.required': 'Please confirm your password!',\n  'form.basic-form.phone-number.required': 'Please enter your phone number!',\n  'form.basic-form.phone-number.wrong-format': 'Malformed phone number!',\n  'form.basic-form.verification-code.required': 'Please enter the verification code!',\n  'form.basic-form.form.get-captcha': 'Get Captcha',\n  'form.basic-form.captcha.second': 'sec',\n  'form.basic-form.form.optional': ' (optional) ',\n  'form.basic-form.form.submit': 'Submit',\n  'form.basic-form.form.save': 'Save',\n  'form.basic-form.email.placeholder': 'Email',\n  'form.basic-form.password.placeholder': 'Password',\n  'form.basic-form.confirm-password.placeholder': 'Confirm password',\n  'form.basic-form.phone-number.placeholder': 'Phone number',\n  'form.basic-form.verification-code.placeholder': 'Verification code'\n}\n"
  },
  {
    "path": "src/locales/lang/en-US/form.js",
    "content": "import basicForm from './form/basicForm'\n\nexport default {\n    ...basicForm\n  }\n"
  },
  {
    "path": "src/locales/lang/en-US/global.js",
    "content": "export default {\n  submit: 'Submit',\n  save: 'Save',\n  'submit.ok': 'Submit successfully',\n  'save.ok': 'Saved successfully'\n}\n"
  },
  {
    "path": "src/locales/lang/en-US/menu.js",
    "content": "export default {\n    'menu.welcome': 'Welcome',\n    'menu.home': 'Home',\n    'menu.dashboard': 'Dashboard',\n    'menu.dashboard.analysis': 'Analysis',\n    'menu.dashboard.monitor': 'Monitor',\n    'menu.dashboard.workplace': 'Workplace',\n    'menu.form': 'Form',\n    'menu.form.basic-form': 'Basic Form',\n    'menu.form.step-form': 'Step Form',\n    'menu.form.step-form.info': 'Step Form(write transfer information)',\n    'menu.form.step-form.confirm': 'Step Form(confirm transfer information)',\n    'menu.form.step-form.result': 'Step Form(finished)',\n    'menu.form.advanced-form': 'Advanced Form',\n    'menu.list': 'List',\n    'menu.list.table-list': 'Search Table',\n    'menu.list.basic-list': 'Basic List',\n    'menu.list.card-list': 'Card List',\n    'menu.list.search-list': 'Search List',\n    'menu.list.search-list.articles': 'Search List(articles)',\n    'menu.list.search-list.projects': 'Search List(projects)',\n    'menu.list.search-list.applications': 'Search List(applications)',\n    'menu.profile': 'Profile',\n    'menu.profile.basic': 'Basic Profile',\n    'menu.profile.advanced': 'Advanced Profile',\n    'menu.result': 'Result',\n    'menu.result.success': 'Success',\n    'menu.result.fail': 'Fail',\n    'menu.exception': 'Exception',\n    'menu.exception.not-permission': '403',\n    'menu.exception.not-find': '404',\n    'menu.exception.server-error': '500',\n    'menu.exception.trigger': 'Trigger',\n    'menu.account': 'Account',\n    'menu.account.center': 'Account Center',\n    'menu.account.settings': 'Account Settings',\n    'menu.account.trigger': 'Trigger Error',\n    'menu.account.logout': 'Logout'\n}\n"
  },
  {
    "path": "src/locales/lang/en-US/result/fail.js",
    "content": "export default {\n  'result.fail.error.title': 'Submission Failed',\n  'result.fail.error.description':\n    'Please check and modify the following information before resubmitting.',\n  'result.fail.error.hint-title': 'The content you submitted has the following error:',\n  'result.fail.error.hint-text1': 'Your account has been frozen',\n  'result.fail.error.hint-btn1': 'Thaw immediately',\n  'result.fail.error.hint-text2': 'Your account is not yet eligible to apply',\n  'result.fail.error.hint-btn2': 'Upgrade immediately',\n  'result.fail.error.btn-text': 'Return to modify'\n}\n"
  },
  {
    "path": "src/locales/lang/en-US/result/success.js",
    "content": "export default {\n  'result.success.title': 'Submission Success',\n  'result.success.description':\n    'The submission results page is used to feed back the results of a series of operational tasks. If it is a simple operation, use the Message global prompt feedback. This text area can show a simple supplementary explanation. If there is a similar requirement for displaying “documents”, the following gray area can present more complicated content.',\n  'result.success.operate-title': 'Project Name',\n  'result.success.operate-id': 'Project ID',\n  'result.success.principal': 'Principal',\n  'result.success.operate-time': 'Effective time',\n  'result.success.step1-title': 'Create project',\n  'result.success.step1-operator': 'Qu Lili',\n  'result.success.step2-title': 'Departmental preliminary review',\n  'result.success.step2-operator': 'Zhou Maomao',\n  'result.success.step2-extra': 'Urge',\n  'result.success.step3-title': 'Financial review',\n  'result.success.step4-title': 'Finish',\n  'result.success.btn-return': 'Back List',\n  'result.success.btn-project': 'View Project',\n  'result.success.btn-print': 'Print'\n}\n"
  },
  {
    "path": "src/locales/lang/en-US/result.js",
    "content": "import success from './result/success'\nimport fail from './result/fail'\n\nexport default {\n    ...success,\n    ...fail\n  }\n"
  },
  {
    "path": "src/locales/lang/en-US/setting.js",
    "content": "export default {\n  'app.setting.pagestyle': 'Page style setting',\n  'app.setting.pagestyle.light': 'Light style',\n  'app.setting.pagestyle.dark': 'Dark style',\n  'app.setting.pagestyle.realdark': 'RealDark style',\n  'app.setting.themecolor': 'Theme Color',\n  'app.setting.navigationmode': 'Navigation Mode',\n  'app.setting.content-width': 'Content Width',\n  'app.setting.fixedheader': 'Fixed Header',\n  'app.setting.fixedsidebar': 'Fixed Sidebar',\n  'app.setting.sidemenu': 'Side Menu Layout',\n  'app.setting.topmenu': 'Top Menu Layout',\n  'app.setting.content-width.fixed': 'Fixed',\n  'app.setting.content-width.fluid': 'Fluid',\n  'app.setting.othersettings': 'Other Settings',\n  'app.setting.weakmode': 'Weak Mode',\n  'app.setting.copy': 'Copy Setting',\n  'app.setting.loading': 'Loading theme',\n  'app.setting.copyinfo': 'copy success，please replace defaultSettings in src/config/defaultSettings.js',\n  'app.setting.production.hint': 'Setting panel shows in development environment only, please manually modify',\n  'app.setting.themecolor.daybreak': 'Daybreak Blue',\n  'app.setting.themecolor.dust': 'Dust Red',\n  'app.setting.themecolor.volcano': 'Volcano',\n  'app.setting.themecolor.sunset': 'Sunset Orange',\n  'app.setting.themecolor.cyan': 'Cyan',\n  'app.setting.themecolor.green': 'Polar Green',\n  'app.setting.themecolor.geekblue': 'Geek Blue',\n  'app.setting.themecolor.purple': 'Golden Purple'\n}\n"
  },
  {
    "path": "src/locales/lang/en-US/user.js",
    "content": "export default {\n  'user.login.userName': 'userName',\n  'user.login.password': 'password',\n  'user.login.username.placeholder': 'Account: admin',\n  'user.login.password.placeholder': 'password: admin or ant.design',\n  'user.login.message-invalid-credentials':\n    'Invalid username or password（admin/ant.design）',\n  'user.login.message-invalid-verification-code': 'Invalid verification code',\n  'user.login.tab-login-credentials': 'Credentials',\n  'user.login.tab-login-mobile': 'Mobile number',\n  'user.login.mobile.placeholder': 'Mobile number',\n  'user.login.mobile.verification-code.placeholder': 'Verification code',\n  'user.login.remember-me': 'Remember me',\n  'user.login.forgot-password': 'Forgot your password?',\n  'user.login.sign-in-with': 'Sign in with',\n  'user.login.signup': 'Sign up',\n  'user.login.login': 'Login',\n  'user.register.register': 'Register',\n  'user.register.email.placeholder': 'Email',\n  'user.register.password.placeholder': 'Password ',\n  'user.register.password.popover-message': 'Please enter at least 6 characters. Please do not use passwords that are easy to guess. ',\n  'user.register.confirm-password.placeholder': 'Confirm password',\n  'user.register.get-verification-code': 'Get code',\n  'user.register.sign-in': 'Already have an account?',\n  'user.register-result.msg': 'Account：registered at {email}',\n  'user.register-result.activation-email':\n    'The activation email has been sent to your email address and is valid for 24 hours. Please log in to the email in time and click on the link in the email to activate the account.',\n  'user.register-result.back-home': 'Back to home',\n  'user.register-result.view-mailbox': 'View mailbox',\n  'user.email.required': 'Please enter your email!',\n  'user.email.wrong-format': 'The email address is in the wrong format!',\n  'user.userName.required': 'Please enter account name or email address',\n  'user.password.required': 'Please enter your password!',\n  'user.password.twice.msg': 'The passwords entered twice do not match!',\n  'user.password.strength.msg':\n    'The password is not strong enough',\n  'user.password.strength.strong': 'Strength: strong',\n  'user.password.strength.medium': 'Strength: medium',\n  'user.password.strength.low': 'Strength: low',\n  'user.password.strength.short': 'Strength: too short',\n  'user.confirm-password.required': 'Please confirm your password!',\n  'user.phone-number.required': 'Please enter your phone number!',\n  'user.phone-number.wrong-format': 'Please enter a valid phone number',\n  'user.verification-code.required': 'Please enter the verification code!'\n}\n"
  },
  {
    "path": "src/locales/lang/en-US.js",
    "content": "import antdEnUS from 'ant-design-vue/es/locale-provider/en_US'\nimport momentEU from 'moment/locale/eu'\nimport global from './en-US/global'\n\nimport menu from './en-US/menu'\nimport setting from './en-US/setting'\nimport user from './en-US/user'\n\nimport dashboard from './en-US/dashboard'\nimport form from './en-US/form'\nimport result from './en-US/result'\nimport account from './en-US/account'\n\nconst components = {\n  antLocale: antdEnUS,\n  momentName: 'eu',\n  momentLocale: momentEU\n}\n\nexport default {\n  message: '-',\n\n  'layouts.usermenu.dialog.title': 'Message',\n  'layouts.usermenu.dialog.content': 'Are you sure you would like to logout?',\n  'layouts.userLayout.title': 'Ant Design is the most influential web design specification in Xihu district',\n  ...components,\n  ...global,\n  ...menu,\n  ...setting,\n  ...user,\n  ...dashboard,\n  ...form,\n  ...result,\n  ...account\n}\n"
  },
  {
    "path": "src/locales/lang/zh-CN/account/settings.js",
    "content": "export default {\n  'account.settings.menuMap.basic': '基本设置',\n  'account.settings.menuMap.security': '安全设置',\n  'account.settings.menuMap.custom': '个性化',\n  'account.settings.menuMap.binding': '账号绑定',\n  'account.settings.menuMap.notification': '新消息通知',\n  'account.settings.basic.avatar': '头像',\n  'account.settings.basic.change-avatar': '更换头像',\n  'account.settings.basic.email': '邮箱',\n  'account.settings.basic.email-message': '请输入您的邮箱!',\n  'account.settings.basic.nickname': '昵称',\n  'account.settings.basic.nickname-message': '请输入您的昵称!',\n  'account.settings.basic.profile': '个人简介',\n  'account.settings.basic.profile-message': '请输入个人简介!',\n  'account.settings.basic.profile-placeholder': '个人简介',\n  'account.settings.basic.country': '国家/地区',\n  'account.settings.basic.country-message': '请输入您的国家或地区!',\n  'account.settings.basic.geographic': '所在省市',\n  'account.settings.basic.geographic-message': '请输入您的所在省市!',\n  'account.settings.basic.address': '街道地址',\n  'account.settings.basic.address-message': '请输入您的街道地址!',\n  'account.settings.basic.phone': '联系电话',\n  'account.settings.basic.phone-message': '请输入您的联系电话!',\n  'account.settings.basic.update': '更新基本信息',\n  'account.settings.basic.update.success': '更新基本信息成功',\n  'account.settings.security.strong': '强',\n  'account.settings.security.medium': '中',\n  'account.settings.security.weak': '弱',\n  'account.settings.security.password': '账户密码',\n  'account.settings.security.password-description': '当前密码强度：',\n  'account.settings.security.phone': '密保手机',\n  'account.settings.security.phone-description': '已绑定手机：',\n  'account.settings.security.question': '密保问题',\n  'account.settings.security.question-description': '未设置密保问题，密保问题可有效保护账户安全',\n  'account.settings.security.email': '备用邮箱',\n  'account.settings.security.email-description': '已绑定邮箱：',\n  'account.settings.security.mfa': 'MFA 设备',\n  'account.settings.security.mfa-description': '未绑定 MFA 设备，绑定后，可以进行二次确认',\n  'account.settings.security.modify': '修改',\n  'account.settings.security.set': '设置',\n  'account.settings.security.bind': '绑定',\n  'account.settings.binding.taobao': '绑定淘宝',\n  'account.settings.binding.taobao-description': '当前未绑定淘宝账号',\n  'account.settings.binding.alipay': '绑定支付宝',\n  'account.settings.binding.alipay-description': '当前未绑定支付宝账号',\n  'account.settings.binding.dingding': '绑定钉钉',\n  'account.settings.binding.dingding-description': '当前未绑定钉钉账号',\n  'account.settings.binding.bind': '绑定',\n  'account.settings.notification.password': '账户密码',\n  'account.settings.notification.password-description': '其他用户的消息将以站内信的形式通知',\n  'account.settings.notification.messages': '系统消息',\n  'account.settings.notification.messages-description': '系统消息将以站内信的形式通知',\n  'account.settings.notification.todo': '待办任务',\n  'account.settings.notification.todo-description': '待办任务将以站内信的形式通知',\n  'account.settings.settings.open': '开',\n  'account.settings.settings.close': '关'\n}\n"
  },
  {
    "path": "src/locales/lang/zh-CN/account.js",
    "content": "import settings from './account/settings'\n\nexport default {\n    ...settings\n  }\n"
  },
  {
    "path": "src/locales/lang/zh-CN/dashboard/analysis.js",
    "content": "export default {\n  'dashboard.analysis.test': '工专路 {no} 号店',\n  'dashboard.analysis.introduce': '指标说明',\n  'dashboard.analysis.total-sales': '总销售额',\n  'dashboard.analysis.day-sales': '日均销售额￥',\n  'dashboard.analysis.visits': '访问量',\n  'dashboard.analysis.visits-trend': '访问量趋势',\n  'dashboard.analysis.visits-ranking': '门店访问量排名',\n  'dashboard.analysis.day-visits': '日访问量',\n  'dashboard.analysis.week': '周同比',\n  'dashboard.analysis.day': '日同比',\n  'dashboard.analysis.payments': '支付笔数',\n  'dashboard.analysis.conversion-rate': '转化率',\n  'dashboard.analysis.operational-effect': '运营活动效果',\n  'dashboard.analysis.sales-trend': '销售趋势',\n  'dashboard.analysis.sales-ranking': '门店销售额排名',\n  'dashboard.analysis.all-year': '全年',\n  'dashboard.analysis.all-month': '本月',\n  'dashboard.analysis.all-week': '本周',\n  'dashboard.analysis.all-day': '今日',\n  'dashboard.analysis.search-users': '搜索用户数',\n  'dashboard.analysis.per-capita-search': '人均搜索次数',\n  'dashboard.analysis.online-top-search': '线上热门搜索',\n  'dashboard.analysis.the-proportion-of-sales': '销售额类别占比',\n  'dashboard.analysis.dropdown-option-one': '操作一',\n  'dashboard.analysis.dropdown-option-two': '操作二',\n  'dashboard.analysis.channel.all': '全部渠道',\n  'dashboard.analysis.channel.online': '线上',\n  'dashboard.analysis.channel.stores': '门店',\n  'dashboard.analysis.sales': '销售额',\n  'dashboard.analysis.traffic': '客流量',\n  'dashboard.analysis.table.rank': '排名',\n  'dashboard.analysis.table.search-keyword': '搜索关键词',\n  'dashboard.analysis.table.users': '用户数',\n  'dashboard.analysis.table.weekly-range': '周涨幅'\n}\n"
  },
  {
    "path": "src/locales/lang/zh-CN/dashboard.js",
    "content": "import analysis from './dashboard/analysis'\n\nexport default {\n    ...analysis\n  }\n"
  },
  {
    "path": "src/locales/lang/zh-CN/form/basicForm.js",
    "content": "export default {\n  'form.basic-form.basic.title': '基础表单',\n  'form.basic-form.basic.description':\n    '表单页用于向用户收集或验证信息，基础表单常见于数据项较少的表单场景。',\n  'form.basic-form.title.label': '标题',\n  'form.basic-form.title.placeholder': '给目标起个名字',\n  'form.basic-form.title.required': '请输入标题',\n  'form.basic-form.date.label': '起止日期',\n  'form.basic-form.placeholder.start': '开始日期',\n  'form.basic-form.placeholder.end': '结束日期',\n  'form.basic-form.date.required': '请选择起止日期',\n  'form.basic-form.goal.label': '目标描述',\n  'form.basic-form.goal.placeholder': '请输入你的阶段性工作目标',\n  'form.basic-form.goal.required': '请输入目标描述',\n  'form.basic-form.standard.label': '衡量标准',\n  'form.basic-form.standard.placeholder': '请输入衡量标准',\n  'form.basic-form.standard.required': '请输入衡量标准',\n  'form.basic-form.client.label': '客户',\n  'form.basic-form.client.required': '请描述你服务的客户',\n  'form.basic-form.label.tooltip': '目标的服务对象',\n  'form.basic-form.client.placeholder': '请描述你服务的客户，内部客户直接 @姓名／工号',\n  'form.basic-form.invites.label': '邀评人',\n  'form.basic-form.invites.placeholder': '请直接 @姓名／工号，最多可邀请 5 人',\n  'form.basic-form.weight.label': '权重',\n  'form.basic-form.weight.placeholder': '请输入',\n  'form.basic-form.public.label': '目标公开',\n  'form.basic-form.label.help': '客户、邀评人默认被分享',\n  'form.basic-form.radio.public': '公开',\n  'form.basic-form.radio.partially-public': '部分公开',\n  'form.basic-form.radio.private': '不公开',\n  'form.basic-form.publicUsers.placeholder': '公开给',\n  'form.basic-form.option.A': '同事一',\n  'form.basic-form.option.B': '同事二',\n  'form.basic-form.option.C': '同事三',\n  'form.basic-form.email.required': '请输入邮箱地址！',\n  'form.basic-form.email.wrong-format': '邮箱地址格式错误！',\n  'form.basic-form.userName.required': '请输入用户名!',\n  'form.basic-form.password.required': '请输入密码！',\n  'form.basic-form.password.twice': '两次输入的密码不匹配!',\n  'form.basic-form.strength.msg': '请至少输入 6 个字符。请不要使用容易被猜到的密码。',\n  'form.basic-form.strength.strong': '强度：强',\n  'form.basic-form.strength.medium': '强度：中',\n  'form.basic-form.strength.short': '强度：太短',\n  'form.basic-form.confirm-password.required': '请确认密码！',\n  'form.basic-form.phone-number.required': '请输入手机号！',\n  'form.basic-form.phone-number.wrong-format': '手机号格式错误！',\n  'form.basic-form.verification-code.required': '请输入验证码！',\n  'form.basic-form.form.get-captcha': '获取验证码',\n  'form.basic-form.captcha.second': '秒',\n  'form.basic-form.form.optional': '（选填）',\n  'form.basic-form.form.submit': '提交',\n  'form.basic-form.form.save': '保存',\n  'form.basic-form.email.placeholder': '邮箱',\n  'form.basic-form.password.placeholder': '至少6位密码，区分大小写',\n  'form.basic-form.confirm-password.placeholder': '确认密码',\n  'form.basic-form.phone-number.placeholder': '手机号',\n  'form.basic-form.verification-code.placeholder': '验证码'\n}\n"
  },
  {
    "path": "src/locales/lang/zh-CN/form.js",
    "content": "import basicForm from './form/basicForm'\n\nexport default {\n    ...basicForm\n  }\n"
  },
  {
    "path": "src/locales/lang/zh-CN/global.js",
    "content": "export default {\n  submit: '提交',\n  save: '保存',\n  'submit.ok': '提交成功',\n  'save.ok': '保存成功'\n}\n"
  },
  {
    "path": "src/locales/lang/zh-CN/menu.js",
    "content": "export default {\n    'menu.welcome': '欢迎',\n    'menu.home': '主页',\n    'menu.dashboard': '仪表盘',\n    'menu.dashboard.analysis': '分析页',\n    'menu.dashboard.monitor': '监控页',\n    'menu.dashboard.workplace': '工作台',\n    'menu.form': '表单页',\n    'menu.form.basic-form': '基础表单',\n    'menu.form.step-form': '分步表单',\n    'menu.form.step-form.info': '分步表单（填写转账信息）',\n    'menu.form.step-form.confirm': '分步表单（确认转账信息）',\n    'menu.form.step-form.result': '分步表单（完成）',\n    'menu.form.advanced-form': '高级表单',\n    'menu.list': '列表页',\n    'menu.list.table-list': '查询表格',\n    'menu.list.basic-list': '标准列表',\n    'menu.list.card-list': '卡片列表',\n    'menu.list.search-list': '搜索列表',\n    'menu.list.search-list.articles': '搜索列表（文章）',\n    'menu.list.search-list.projects': '搜索列表（项目）',\n    'menu.list.search-list.applications': '搜索列表（应用）',\n    'menu.profile': '详情页',\n    'menu.profile.basic': '基础详情页',\n    'menu.profile.advanced': '高级详情页',\n    'menu.result': '结果页',\n    'menu.result.success': '成功页',\n    'menu.result.fail': '失败页',\n    'menu.exception': '异常页',\n    'menu.exception.not-permission': '403',\n    'menu.exception.not-find': '404',\n    'menu.exception.server-error': '500',\n    'menu.exception.trigger': '触发错误',\n    'menu.account': '个人页',\n    'menu.account.center': '个人中心',\n    'menu.account.settings': '个人设置',\n    'menu.account.trigger': '触发报错',\n    'menu.account.logout': '退出登录'\n}\n"
  },
  {
    "path": "src/locales/lang/zh-CN/result/fail.js",
    "content": "export default {\n  'result.fail.error.title': '提交失败',\n  'result.fail.error.description': '请核对并修改以下信息后，再重新提交。',\n  'result.fail.error.hint-title': '您提交的内容有如下错误：',\n  'result.fail.error.hint-text1': '您的账户已被冻结',\n  'result.fail.error.hint-btn1': '立即解冻',\n  'result.fail.error.hint-text2': '您的账户还不具备申请资格',\n  'result.fail.error.hint-btn2': '立即升级',\n  'result.fail.error.btn-text': '返回修改'\n}\n"
  },
  {
    "path": "src/locales/lang/zh-CN/result/success.js",
    "content": "export default {\n  'result.success.title': '提交成功',\n  'result.success.description':\n    '提交结果页用于反馈一系列操作任务的处理结果， 如果仅是简单操作，使用 Message 全局提示反馈即可。 本文字区域可以展示简单的补充说明，如果有类似展示 “单据”的需求，下面这个灰色区域可以呈现比较复杂的内容。',\n  'result.success.operate-title': '项目名称',\n  'result.success.operate-id': '项目 ID',\n  'result.success.principal': '负责人',\n  'result.success.operate-time': '生效时间',\n  'result.success.step1-title': '创建项目',\n  'result.success.step1-operator': '曲丽丽',\n  'result.success.step2-title': '部门初审',\n  'result.success.step2-operator': '周毛毛',\n  'result.success.step2-extra': '催一下',\n  'result.success.step3-title': '财务复核',\n  'result.success.step4-title': '完成',\n  'result.success.btn-return': '返回列表',\n  'result.success.btn-project': '查看项目',\n  'result.success.btn-print': '打印'\n}\n"
  },
  {
    "path": "src/locales/lang/zh-CN/result.js",
    "content": "import success from './result/success'\nimport fail from './result/fail'\n\nexport default {\n    ...success,\n    ...fail\n  }\n"
  },
  {
    "path": "src/locales/lang/zh-CN/setting.js",
    "content": "export default {\n  'app.setting.pagestyle': '整体风格设置',\n  'app.setting.pagestyle.light': '亮色菜单风格',\n  'app.setting.pagestyle.dark': '暗色菜单风格',\n  'app.setting.pagestyle.realdark': '暗黑模式',\n  'app.setting.themecolor': '主题色',\n  'app.setting.navigationmode': '导航模式',\n  'app.setting.content-width': '内容区域宽度',\n  'app.setting.fixedheader': '固定 Header',\n  'app.setting.fixedsidebar': '固定侧边栏',\n  'app.setting.sidemenu': '侧边菜单布局',\n  'app.setting.topmenu': '顶部菜单布局',\n  'app.setting.content-width.fixed': 'Fixed',\n  'app.setting.content-width.fluid': 'Fluid',\n  'app.setting.othersettings': '其他设置',\n  'app.setting.weakmode': '色弱模式',\n  'app.setting.copy': '拷贝设置',\n  'app.setting.loading': '加载主题中',\n  'app.setting.copyinfo': '拷贝设置成功 src/config/defaultSettings.js',\n  'app.setting.production.hint': '配置栏只在开发环境用于预览，生产环境不会展现，请拷贝后手动修改配置文件',\n  'app.setting.themecolor.daybreak': '拂晓蓝',\n  'app.setting.themecolor.dust': '薄暮',\n  'app.setting.themecolor.volcano': '火山',\n  'app.setting.themecolor.sunset': '日暮',\n  'app.setting.themecolor.cyan': '明青',\n  'app.setting.themecolor.green': '极光绿',\n  'app.setting.themecolor.geekblue': '极客蓝',\n  'app.setting.themecolor.purple': '酱紫'\n}\n"
  },
  {
    "path": "src/locales/lang/zh-CN/user.js",
    "content": "export default {\n  'user.login.userName': '用户名',\n  'user.login.password': '密码',\n  'user.login.username.placeholder': '账户: admin',\n  'user.login.password.placeholder': '密码: admin or ant.design',\n  'user.login.message-invalid-credentials': '账户或密码错误（admin/ant.design）',\n  'user.login.message-invalid-verification-code': '验证码错误',\n  'user.login.tab-login-credentials': '账户密码登录',\n  'user.login.tab-login-mobile': '手机号登录',\n  'user.login.mobile.placeholder': '手机号',\n  'user.login.mobile.verification-code.placeholder': '验证码',\n  'user.login.remember-me': '自动登录',\n  'user.login.forgot-password': '忘记密码',\n  'user.login.sign-in-with': '其他登录方式',\n  'user.login.signup': '注册账户',\n  'user.login.login': '登录',\n  'user.register.register': '注册',\n  'user.register.email.placeholder': '邮箱',\n  'user.register.password.placeholder': '请至少输入 6 个字符。请不要使用容易被猜到的密码。',\n  'user.register.password.popover-message': '请至少输入 6 个字符。请不要使用容易被猜到的密码。',\n  'user.register.confirm-password.placeholder': '确认密码',\n  'user.register.get-verification-code': '获取验证码',\n  'user.register.sign-in': '使用已有账户登录',\n  'user.register-result.msg': '你的账户：{email} 注册成功',\n  'user.register-result.activation-email':\n    '激活邮件已发送到你的邮箱中，邮件有效期为24小时。请及时登录邮箱，点击邮件中的链接激活帐户。',\n  'user.register-result.back-home': '返回首页',\n  'user.register-result.view-mailbox': '查看邮箱',\n  'user.email.required': '请输入邮箱地址！',\n  'user.email.wrong-format': '邮箱地址格式错误！',\n  'user.userName.required': '请输入帐户名或邮箱地址',\n  'user.password.required': '请输入密码！',\n  'user.password.twice.msg': '两次输入的密码不匹配!',\n  'user.password.strength.msg': '密码强度不够 ',\n  'user.password.strength.strong': '强度：强',\n  'user.password.strength.medium': '强度：中',\n  'user.password.strength.low': '强度：低',\n  'user.password.strength.short': '强度：太短',\n  'user.confirm-password.required': '请确认密码！',\n  'user.phone-number.required': '请输入正确的手机号',\n  'user.phone-number.wrong-format': '手机号格式错误！',\n  'user.verification-code.required': '请输入验证码！'\n}\n"
  },
  {
    "path": "src/locales/lang/zh-CN.js",
    "content": "import antd from 'ant-design-vue/es/locale-provider/zh_CN'\nimport momentCN from 'moment/locale/zh-cn'\nimport global from './zh-CN/global'\n\nimport menu from './zh-CN/menu'\nimport setting from './zh-CN/setting'\nimport user from './zh-CN/user'\nimport dashboard from './zh-CN/dashboard'\nimport form from './zh-CN/form'\nimport result from './zh-CN/result'\nimport account from './zh-CN/account'\n\nconst components = {\n  antLocale: antd,\n  momentName: 'zh-cn',\n  momentLocale: momentCN\n}\n\nexport default {\n  message: '-',\n\n  'layouts.usermenu.dialog.title': '信息',\n  'layouts.usermenu.dialog.content': '您确定要注销吗？',\n  'layouts.userLayout.title': 'Ant Design 是西湖区最具影响力的 Web 设计规范',\n  ...components,\n  ...global,\n  ...menu,\n  ...setting,\n  ...user,\n  ...dashboard,\n  ...form,\n  ...result,\n  ...account\n}\n"
  },
  {
    "path": "src/main.js",
    "content": "// with polyfills\nimport 'core-js/stable'\nimport 'regenerator-runtime/runtime'\n\nimport Vue from 'vue'\nimport App from './App.vue'\nimport router from './router'\nimport store from './store/'\nimport i18n from './locales'\nimport { VueAxios } from './utils/request'\nimport ProLayout, { PageHeaderWrapper } from '@ant-design-vue/pro-layout'\nimport themePluginConfig from '../config/themePluginConfig'\n\n// mock\n// WARNING: `mockjs` NOT SUPPORT `IE` PLEASE DO NOT USE IN `production` ENV.\nimport './mock'\n\nimport bootstrap from './core/bootstrap'\nimport './core/lazy_use' // use lazy load components\nimport './permission' // permission control\nimport './utils/filter' // global filter\nimport './global.less' // global style\n\nVue.config.productionTip = false\n\n// mount axios to `Vue.$http` and `this.$http`\nVue.use(VueAxios)\n// use pro-layout components\nVue.component('pro-layout', ProLayout)\nVue.component('page-container', PageHeaderWrapper)\nVue.component('page-header-wrapper', PageHeaderWrapper)\n\nwindow.umi_plugin_ant_themeVar = themePluginConfig.theme\n\nnew Vue({\n  router,\n  store,\n  i18n,\n  // init localstorage, vuex, Logo message\n  created: bootstrap,\n  render: h => h(App)\n}).$mount('#app')\n"
  },
  {
    "path": "src/mock/index.js",
    "content": "import { isIE } from '@/utils/util'\n\n// 判断环境不是 prod 或者 preview 是 true 时，加载 mock 服务\nif (process.env.NODE_ENV !== 'production' || process.env.VUE_APP_PREVIEW === 'true') {\n  if (isIE()) {\n    console.error('[antd-pro] ERROR: `mockjs` NOT SUPPORT `IE` PLEASE DO NOT USE IN `production` ENV.')\n  }\n  // 使用同步加载依赖\n  // 防止 vuex 中的 GetInfo 早于 mock 运行，导致无法 mock 请求返回结果\n  console.log('[antd-pro] mock mounting')\n  const Mock = require('mockjs2')\n  require('./services/auth')\n  require('./services/user')\n  require('./services/manage')\n  require('./services/other')\n  require('./services/tagCloud')\n  require('./services/article')\n\n  Mock.setup({\n    timeout: 800 // setter delay time\n  })\n  console.log('[antd-pro] mock mounted')\n}\n"
  },
  {
    "path": "src/mock/services/article.js",
    "content": "import Mock from 'mockjs2'\nimport { builder, getQueryParameters } from '../util'\n\nconst titles = [\n  'Alipay',\n  'Angular',\n  'Ant Design',\n  'Ant Design Pro',\n  'Bootstrap',\n  'React',\n  'Vue',\n  'Webpack'\n]\n\nconst avatar = ['https://gw.alipayobjects.com/zos/rmsportal/WdGqmHpayyMjiEhcKoVE.png',\n  'https://gw.alipayobjects.com/zos/rmsportal/zOsKZmFRdUtvpqCImOVY.png',\n  'https://gw.alipayobjects.com/zos/rmsportal/dURIMkkrRFpPgTuzkwnB.png',\n  'https://gw.alipayobjects.com/zos/rmsportal/sfjbOqnsXXJgNCjCzDBL.png',\n  'https://gw.alipayobjects.com/zos/rmsportal/siCrBXXhmvTQGWPNLBow.png'\n]\n\nconst covers = [\n  'https://gw.alipayobjects.com/zos/rmsportal/uMfMFlvUuceEyPpotzlq.png',\n  'https://gw.alipayobjects.com/zos/rmsportal/iZBVOIhGJiAnhplqjvZW.png',\n  'https://gw.alipayobjects.com/zos/rmsportal/iXjVmWVHbCJAyqvDxdtx.png',\n  'https://gw.alipayobjects.com/zos/rmsportal/gLaIAoVWTtLbBWZNYEMg.png'\n]\n\nconst owner = [\n  '付小小',\n  '吴加好',\n  '周星星',\n  '林东东',\n  '曲丽丽'\n]\n\nconst content = '段落示意：蚂蚁金服设计平台 ant.design，用最小的工作量，无缝接入蚂蚁金服生态，提供跨越设计与开发的体验解决方案。蚂蚁金服设计平台 ant.design，用最小的工作量，无缝接入蚂蚁金服生态，提供跨越设计与开发的体验解决方案。'\nconst description = '在中台产品的研发过程中，会出现不同的设计规范和实现方式，但其中往往存在很多类似的页面和组件，这些类似的组件会被抽离成一套标准规范。'\nconst href = 'https://ant.design'\n\nconst article = (options) => {\n  const queryParameters = getQueryParameters(options)\n  console.log('queryParameters', queryParameters)\n  if (queryParameters && !queryParameters.count) {\n    queryParameters.count = 5\n  }\n  const data = []\n  for (let i = 0; i < queryParameters.count; i++) {\n    const tmpKey = i + 1\n    const num = parseInt(Math.random() * (4 + 1), 10)\n    data.push({\n      id: tmpKey,\n      avatar: avatar[num],\n      owner: owner[num],\n      content: content,\n      star: Mock.mock('@integer(1, 999)'),\n      percent: Mock.mock('@integer(1, 999)'),\n      like: Mock.mock('@integer(1, 999)'),\n      message: Mock.mock('@integer(1, 999)'),\n      description: description,\n      href: href,\n      title: titles[ i % 8 ],\n      updatedAt: Mock.mock('@datetime'),\n      members: [\n        {\n          avatar: 'https://gw.alipayobjects.com/zos/rmsportal/ZiESqWwCXBRQoaPONSJe.png',\n          name: '曲丽丽',\n          id: 'member1'\n        },\n        {\n          avatar: 'https://gw.alipayobjects.com/zos/rmsportal/tBOxZPlITHqwlGjsJWaF.png',\n          name: '王昭君',\n          id: 'member2'\n        },\n        {\n          avatar: 'https://gw.alipayobjects.com/zos/rmsportal/sBxjgqiuHMGRkIjqlQCd.png',\n          name: '董娜娜',\n          id: 'member3'\n        }\n      ],\n      activeUser: Math.ceil(Math.random() * 100000) + 100000,\n      newUser: Math.ceil(Math.random() * 1000) + 1000,\n      cover: parseInt(i / 4, 10) % 2 === 0 ? covers[i % 4] : covers[3 - (i % 4)]\n    })\n  }\n  return builder(data)\n}\n\nMock.mock(/\\/list\\/article/, 'get', article)\n"
  },
  {
    "path": "src/mock/services/auth.js",
    "content": "import Mock from 'mockjs2'\nimport { builder, getBody } from '../util'\n\nconst username = ['admin', 'super']\n// 强硬要求 ant.design 相同密码\n// '21232f297a57a5a743894a0e4a801fc3',\nconst password = ['8914de686ab28dc22f30d3d8e107ff6c', '21232f297a57a5a743894a0e4a801fc3'] // admin, ant.design\n\nconst login = (options) => {\n  const body = getBody(options)\n  console.log('mock: body', body)\n  if (!username.includes(body.username) || !password.includes(body.password)) {\n    return builder({ isLogin: true }, '账户或密码错误', 401)\n  }\n\n  return builder({\n    'id': Mock.mock('@guid'),\n    'name': Mock.mock('@name'),\n    'username': 'admin',\n    'password': '',\n    'avatar': 'https://gw.alipayobjects.com/zos/rmsportal/jZUIxmJycoymBprLOUbT.png',\n    'status': 1,\n    'telephone': '',\n    'lastLoginIp': '27.154.74.117',\n    'lastLoginTime': 1534837621348,\n    'creatorId': 'admin',\n    'createTime': 1497160610259,\n    'deleted': 0,\n    'roleId': 'admin',\n    'lang': 'zh-CN',\n    'token': '4291d7da9005377ec9aec4a71ea837f'\n  }, '', 200, { 'Custom-Header': Mock.mock('@guid') })\n}\n\nconst logout = () => {\n  return builder({}, '[测试接口] 注销成功')\n}\n\nconst smsCaptcha = () => {\n  return builder({ captcha: Mock.mock('@integer(10000, 99999)') })\n}\n\nconst twofactor = () => {\n  return builder({ stepCode: Mock.mock('@integer(0, 1)') })\n}\n\nMock.mock(/\\/auth\\/login/, 'post', login)\nMock.mock(/\\/auth\\/logout/, 'post', logout)\nMock.mock(/\\/account\\/sms/, 'post', smsCaptcha)\nMock.mock(/\\/auth\\/2step-code/, 'post', twofactor)\n"
  },
  {
    "path": "src/mock/services/manage.js",
    "content": "import Mock from 'mockjs2'\nimport { builder, getQueryParameters } from '../util'\n\nconst totalCount = 5701\n\nconst serverList = (options) => {\n  const parameters = getQueryParameters(options)\n\n  const result = []\n  const pageNo = parseInt(parameters.pageNo)\n  const pageSize = parseInt(parameters.pageSize)\n  const totalPage = Math.ceil(totalCount / pageSize)\n  const key = (pageNo - 1) * pageSize\n  const next = (pageNo >= totalPage ? (totalCount % pageSize) : pageSize) + 1\n\n  for (let i = 1; i < next; i++) {\n    const tmpKey = key + i\n    result.push({\n      key: tmpKey,\n      id: tmpKey,\n      no: 'No ' + tmpKey,\n      description: '这是一段描述',\n      callNo: Mock.mock('@integer(1, 999)'),\n      status: Mock.mock('@integer(0, 3)'),\n      updatedAt: Mock.mock('@datetime'),\n      editable: false\n    })\n  }\n\n  return builder({\n    pageSize: pageSize,\n    pageNo: pageNo,\n    totalCount: totalCount,\n    totalPage: totalPage,\n    data: result\n  })\n}\n\nconst projects = () => {\n  return builder({\n    'data': [{\n      id: 1,\n      cover: 'https://gw.alipayobjects.com/zos/rmsportal/WdGqmHpayyMjiEhcKoVE.png',\n      title: 'Alipay',\n      description: '那是一种内在的东西， 他们到达不了，也无法触及的',\n      status: 1,\n      updatedAt: '2018-07-26 00:00:00'\n    },\n    {\n      id: 2,\n      cover: 'https://gw.alipayobjects.com/zos/rmsportal/zOsKZmFRdUtvpqCImOVY.png',\n      title: 'Angular',\n      description: '希望是一个好东西，也许是最好的，好东西是不会消亡的',\n      status: 1,\n      updatedAt: '2018-07-26 00:00:00'\n    },\n    {\n      id: 3,\n      cover: 'https://gw.alipayobjects.com/zos/rmsportal/dURIMkkrRFpPgTuzkwnB.png',\n      title: 'Ant Design',\n      description: '城镇中有那么多的酒馆，她却偏偏走进了我的酒馆',\n      status: 1,\n      updatedAt: '2018-07-26 00:00:00'\n    },\n    {\n      id: 4,\n      cover: 'https://gw.alipayobjects.com/zos/rmsportal/sfjbOqnsXXJgNCjCzDBL.png',\n      title: 'Ant Design Pro',\n      description: '那时候我只会想自己想要什么，从不想自己拥有什么',\n      status: 1,\n      updatedAt: '2018-07-26 00:00:00'\n    },\n    {\n      id: 5,\n      cover: 'https://gw.alipayobjects.com/zos/rmsportal/siCrBXXhmvTQGWPNLBow.png',\n      title: 'Bootstrap',\n      description: '凛冬将至',\n      status: 1,\n      updatedAt: '2018-07-26 00:00:00'\n    },\n    {\n      id: 6,\n      cover: 'https://gw.alipayobjects.com/zos/rmsportal/ComBAopevLwENQdKWiIn.png',\n      title: 'Vue',\n      description: '生命就像一盒巧克力，结果往往出人意料',\n      status: 1,\n      updatedAt: '2018-07-26 00:00:00'\n    }\n    ],\n    'pageSize': 10,\n    'pageNo': 0,\n    'totalPage': 6,\n    'totalCount': 57\n  })\n}\n\nconst activity = () => {\n  return builder([{\n    id: 1,\n    user: {\n      nickname: '@name',\n      avatar: 'https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png'\n    },\n    project: {\n      name: '白鹭酱油开发组',\n      action: '更新',\n      event: '番组计划'\n    },\n    time: '2018-08-23 14:47:00'\n  },\n  {\n    id: 1,\n    user: {\n      nickname: '蓝莓酱',\n      avatar: 'https://gw.alipayobjects.com/zos/rmsportal/jZUIxmJycoymBprLOUbT.png'\n    },\n    project: {\n      name: '白鹭酱油开发组',\n      action: '更新',\n      event: '番组计划'\n    },\n    time: '2018-08-23 09:35:37'\n  },\n  {\n    id: 1,\n    user: {\n      nickname: '@name',\n      avatar: '@image(64x64)'\n    },\n    project: {\n      name: '白鹭酱油开发组',\n      action: '创建',\n      event: '番组计划'\n    },\n    time: '2017-05-27 00:00:00'\n  },\n  {\n    id: 1,\n    user: {\n      nickname: '曲丽丽',\n      avatar: '@image(64x64)'\n    },\n    project: {\n      name: '高逼格设计天团',\n      action: '更新',\n      event: '六月迭代'\n    },\n    time: '2018-08-23 14:47:00'\n  },\n  {\n    id: 1,\n    user: {\n      nickname: '@name',\n      avatar: '@image(64x64)'\n    },\n    project: {\n      name: '高逼格设计天团',\n      action: 'created',\n      event: '六月迭代'\n    },\n    time: '2018-08-23 14:47:00'\n  },\n  {\n    id: 1,\n    user: {\n      nickname: '曲丽丽',\n      avatar: 'https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png'\n    },\n    project: {\n      name: '高逼格设计天团',\n      action: 'created',\n      event: '六月迭代'\n    },\n    time: '2018-08-23 14:47:00'\n  }\n  ])\n}\n\nconst teams = () => {\n  return builder([{\n    id: 1,\n    name: '科学搬砖组',\n    avatar: 'https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png'\n  },\n  {\n    id: 2,\n    name: '程序员日常',\n    avatar: 'https://gw.alipayobjects.com/zos/rmsportal/cnrhVkzwxjPwAaCfPbdc.png'\n  },\n  {\n    id: 1,\n    name: '设计天团',\n    avatar: 'https://gw.alipayobjects.com/zos/rmsportal/gaOngJwsRYRaVAuXXcmB.png'\n  },\n  {\n    id: 1,\n    name: '中二少女团',\n    avatar: 'https://gw.alipayobjects.com/zos/rmsportal/ubnKSIfAJTxIgXOKlciN.png'\n  },\n  {\n    id: 1,\n    name: '骗你学计算机',\n    avatar: 'https://gw.alipayobjects.com/zos/rmsportal/WhxKECPNujWoWEFNdnJE.png'\n  }\n  ])\n}\n\nconst radar = () => {\n  return builder([{\n    item: '引用',\n    '个人': 70,\n    '团队': 30,\n    '部门': 40\n  },\n  {\n    item: '口碑',\n    '个人': 60,\n    '团队': 70,\n    '部门': 40\n  },\n  {\n    item: '产量',\n    '个人': 50,\n    '团队': 60,\n    '部门': 40\n  },\n  {\n    item: '贡献',\n    '个人': 40,\n    '团队': 50,\n    '部门': 40\n  },\n  {\n    item: '热度',\n    '个人': 60,\n    '团队': 70,\n    '部门': 40\n  },\n  {\n    item: '引用',\n    '个人': 70,\n    '团队': 50,\n    '部门': 40\n  }\n  ])\n}\n\nMock.mock(/\\/service/, 'get', serverList)\nMock.mock(/\\/list\\/search\\/projects/, 'get', projects)\nMock.mock(/\\/workplace\\/activity/, 'get', activity)\nMock.mock(/\\/workplace\\/teams/, 'get', teams)\nMock.mock(/\\/workplace\\/radar/, 'get', radar)\n"
  },
  {
    "path": "src/mock/services/other.js",
    "content": "import Mock from 'mockjs2'\nimport { builder } from '../util'\n\nconst orgTree = () => {\n  return builder([{\n    'key': 'key-01',\n    'title': '研发中心',\n    'icon': 'mail',\n    'children': [{\n      'key': 'key-01-01',\n      'title': '后端组',\n      'icon': null,\n      'group': true,\n      children: [{\n        'key': 'key-01-01-01',\n        'title': 'JAVA',\n        'icon': null\n      },\n      {\n        'key': 'key-01-01-02',\n        'title': 'PHP',\n        'icon': null\n      },\n      {\n        'key': 'key-01-01-03',\n        'title': 'Golang',\n        'icon': null\n      }\n      ]\n    }, {\n      'key': 'key-01-02',\n      'title': '前端组',\n      'icon': null,\n      'group': true,\n      children: [{\n        'key': 'key-01-02-01',\n        'title': 'React',\n        'icon': null\n      },\n      {\n        'key': 'key-01-02-02',\n        'title': 'Vue',\n        'icon': null\n      },\n      {\n        'key': 'key-01-02-03',\n        'title': 'Angular',\n        'icon': null\n      }\n      ]\n    }]\n  }, {\n    'key': 'key-02',\n    'title': '财务部',\n    'icon': 'dollar',\n    'children': [{\n      'key': 'key-02-01',\n      'title': '会计核算',\n      'icon': null\n    }, {\n      'key': 'key-02-02',\n      'title': '成本控制',\n      'icon': null\n    }, {\n      'key': 'key-02-03',\n      'title': '内部控制',\n      'icon': null,\n      'children': [{\n        'key': 'key-02-03-01',\n        'title': '财务制度建设',\n        'icon': null\n      },\n      {\n        'key': 'key-02-03-02',\n        'title': '会计核算',\n        'icon': null\n      }\n      ]\n    }]\n  }])\n}\n\nconst role = () => {\n  return builder({\n    'data': [{\n      'id': 'admin',\n      'name': '管理员',\n      'describe': '拥有所有权限',\n      'status': 1,\n      'creatorId': 'system',\n      'createTime': 1497160610259,\n      'deleted': 0,\n      'permissions': [{\n        'roleId': 'admin',\n        'permissionId': 'comment',\n        'permissionName': '评论管理',\n        'actions': '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"query\",\"defaultCheck\":false,\"describe\":\"查询\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"edit\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"}]',\n        'actionEntitySet': [{\n          'action': 'add',\n          'describe': '新增',\n          'defaultCheck': false\n        },\n        {\n          'action': 'query',\n          'describe': '查询',\n          'defaultCheck': false\n        },\n        {\n          'action': 'get',\n          'describe': '详情',\n          'defaultCheck': false\n        },\n        {\n          'action': 'edit',\n          'describe': '修改',\n          'defaultCheck': false\n        },\n        {\n          'action': 'delete',\n          'describe': '删除',\n          'defaultCheck': false\n        }],\n        'actionList': ['delete', 'edit'],\n        'dataAccess': null\n      },\n      {\n        'roleId': 'admin',\n        'permissionId': 'member',\n        'permissionName': '会员管理',\n        'actions': '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"query\",\"defaultCheck\":false,\"describe\":\"查询\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"edit\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"}]',\n        'actionEntitySet': [{\n          'action': 'add',\n          'describe': '新增',\n          'defaultCheck': false\n        },\n        {\n          'action': 'query',\n          'describe': '查询',\n          'defaultCheck': false\n        },\n        {\n          'action': 'get',\n          'describe': '详情',\n          'defaultCheck': false\n        },\n        {\n          'action': 'edit',\n          'describe': '修改',\n          'defaultCheck': false\n        },\n        {\n          'action': 'delete',\n          'describe': '删除',\n          'defaultCheck': false\n        }\n        ],\n        'actionList': ['query', 'get', 'edit', 'delete'],\n        'dataAccess': null\n      },\n      {\n        'roleId': 'admin',\n        'permissionId': 'menu',\n        'permissionName': '菜单管理',\n        'actions': '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"import\",\"defaultCheck\":false,\"describe\":\"导入\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"edit\",\"defaultCheck\":false,\"describe\":\"修改\"}]',\n        'actionEntitySet': [{\n          'action': 'add',\n          'describe': '新增',\n          'defaultCheck': false\n        },\n        {\n          'action': 'import',\n          'describe': '导入',\n          'defaultCheck': false\n        },\n        {\n          'action': 'get',\n          'describe': '详情',\n          'defaultCheck': false\n        },\n        {\n          'action': 'edit',\n          'describe': '修改',\n          'defaultCheck': false\n        }\n        ],\n        'actionList': ['add', 'import'],\n        'dataAccess': null\n      },\n      {\n        'roleId': 'admin',\n        'permissionId': 'order',\n        'permissionName': '订单管理',\n        'actions': '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"query\",\"defaultCheck\":false,\"describe\":\"查询\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"edit\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"}]',\n        'actionEntitySet': [{\n          'action': 'add',\n          'describe': '新增',\n          'defaultCheck': false\n        },\n        {\n          'action': 'query',\n          'describe': '查询',\n          'defaultCheck': false\n        },\n        {\n          'action': 'get',\n          'describe': '详情',\n          'defaultCheck': false\n        },\n        {\n          'action': 'edit',\n          'describe': '修改',\n          'defaultCheck': false\n        },\n        {\n          'action': 'delete',\n          'describe': '删除',\n          'defaultCheck': false\n        }\n        ],\n        'actionList': ['query', 'add', 'get'],\n        'dataAccess': null\n      },\n      {\n        'roleId': 'admin',\n        'permissionId': 'permission',\n        'permissionName': '权限管理',\n        'actions': '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"edit\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"}]',\n        'actionEntitySet': [{\n          'action': 'add',\n          'describe': '新增',\n          'defaultCheck': false\n        },\n        {\n          'action': 'get',\n          'describe': '详情',\n          'defaultCheck': false\n        },\n        {\n          'action': 'edit',\n          'describe': '修改',\n          'defaultCheck': false\n        },\n        {\n          'action': 'delete',\n          'describe': '删除',\n          'defaultCheck': false\n        }\n        ],\n        'actionList': ['add', 'get', 'edit', 'delete'],\n        'dataAccess': null\n      },\n      {\n        'roleId': 'admin',\n        'permissionId': 'role',\n        'permissionName': '角色管理',\n        'actions': '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"edit\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"}]',\n        'actionEntitySet': [{\n          'action': 'add',\n          'describe': '新增',\n          'defaultCheck': false\n        },\n        {\n          'action': 'get',\n          'describe': '详情',\n          'defaultCheck': false\n        },\n        {\n          'action': 'edit',\n          'describe': '修改',\n          'defaultCheck': false\n        },\n        {\n          'action': 'delete',\n          'describe': '删除',\n          'defaultCheck': false\n        }\n        ],\n        'actionList': null,\n        'dataAccess': null\n      },\n      {\n        'roleId': 'admin',\n        'permissionId': 'test',\n        'permissionName': '测试权限',\n        'actions': '[]',\n        'actionEntitySet': [],\n        'actionList': null,\n        'dataAccess': null\n      },\n      {\n        'roleId': 'admin',\n        'permissionId': 'user',\n        'permissionName': '用户管理',\n        'actions': '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"import\",\"defaultCheck\":false,\"describe\":\"导入\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"edit\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"},{\"action\":\"export\",\"defaultCheck\":false,\"describe\":\"导出\"}]',\n        'actionEntitySet': [{\n          'action': 'add',\n          'describe': '新增',\n          'defaultCheck': false\n        },\n        {\n          'action': 'import',\n          'describe': '导入',\n          'defaultCheck': false\n        },\n        {\n          'action': 'get',\n          'describe': '详情',\n          'defaultCheck': false\n        },\n        {\n          'action': 'edit',\n          'describe': '修改',\n          'defaultCheck': false\n        },\n        {\n          'action': 'delete',\n          'describe': '删除',\n          'defaultCheck': false\n        },\n        {\n          'action': 'export',\n          'describe': '导出',\n          'defaultCheck': false\n        }\n        ],\n        'actionList': ['add', 'get'],\n        'dataAccess': null\n      }\n      ]\n    },\n    {\n      'id': 'svip',\n      'name': 'SVIP',\n      'describe': '超级会员',\n      'status': 1,\n      'creatorId': 'system',\n      'createTime': 1532417744846,\n      'deleted': 0,\n      'permissions': [{\n        'roleId': 'admin',\n        'permissionId': 'comment',\n        'permissionName': '评论管理',\n        'actions': '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"query\",\"defaultCheck\":false,\"describe\":\"查询\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"edit\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"}]',\n        'actionEntitySet': [{\n          'action': 'add',\n          'describe': '新增',\n          'defaultCheck': false\n        },\n        {\n          'action': 'query',\n          'describe': '查询',\n          'defaultCheck': false\n        },\n        {\n          'action': 'get',\n          'describe': '详情',\n          'defaultCheck': false\n        },\n        {\n          'action': 'edit',\n          'describe': '修改',\n          'defaultCheck': false\n        },\n        {\n          'action': 'delete',\n          'describe': '删除',\n          'defaultCheck': false\n        }\n        ],\n        'actionList': ['add', 'get', 'delete'],\n        'dataAccess': null\n      },\n      {\n        'roleId': 'admin',\n        'permissionId': 'member',\n        'permissionName': '会员管理',\n        'actions': '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"query\",\"defaultCheck\":false,\"describe\":\"查询\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"edit\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"}]',\n        'actionEntitySet': [{\n          'action': 'add',\n          'describe': '新增',\n          'defaultCheck': false\n        },\n        {\n          'action': 'query',\n          'describe': '查询',\n          'defaultCheck': false\n        },\n        {\n          'action': 'get',\n          'describe': '详情',\n          'defaultCheck': false\n        }\n        ],\n        'actionList': ['add', 'query', 'get'],\n        'dataAccess': null\n      },\n      {\n        'roleId': 'admin',\n        'permissionId': 'menu',\n        'permissionName': '菜单管理',\n        'actions': '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"import\",\"defaultCheck\":false,\"describe\":\"导入\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"edit\",\"defaultCheck\":false,\"describe\":\"修改\"}]',\n        'actionEntitySet': [{\n          'action': 'add',\n          'describe': '新增',\n          'defaultCheck': false\n        },\n        {\n          'action': 'import',\n          'describe': '导入',\n          'defaultCheck': false\n        },\n        {\n          'action': 'get',\n          'describe': '详情',\n          'defaultCheck': false\n        }\n        ],\n        'actionList': ['add', 'get'],\n        'dataAccess': null\n      },\n      {\n        'roleId': 'admin',\n        'permissionId': 'order',\n        'permissionName': '订单管理',\n        'actions': '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"query\",\"defaultCheck\":false,\"describe\":\"查询\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"edit\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"}]',\n        'actionEntitySet': [{\n          'action': 'add',\n          'describe': '新增',\n          'defaultCheck': false\n        },\n        {\n          'action': 'query',\n          'describe': '查询',\n          'defaultCheck': false\n        },\n        {\n          'action': 'get',\n          'describe': '详情',\n          'defaultCheck': false\n        },\n        {\n          'action': 'edit',\n          'describe': '修改',\n          'defaultCheck': false\n        }\n        ],\n        'actionList': ['add', 'query'],\n        'dataAccess': null\n      },\n      {\n        'roleId': 'admin',\n        'permissionId': 'permission',\n        'permissionName': '权限管理',\n        'actions': '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"edit\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"}]',\n        'actionEntitySet': [{\n          'action': 'add',\n          'describe': '新增',\n          'defaultCheck': false\n        },\n        {\n          'action': 'get',\n          'describe': '详情',\n          'defaultCheck': false\n        },\n        {\n          'action': 'edit',\n          'describe': '修改',\n          'defaultCheck': false\n        }\n        ],\n        'actionList': ['add', 'get', 'edit'],\n        'dataAccess': null\n      },\n      {\n        'roleId': 'admin',\n        'permissionId': 'role',\n        'permissionName': '角色管理',\n        'actions': '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"edit\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"}]',\n        'actionEntitySet': [{\n          'action': 'add',\n          'describe': '新增',\n          'defaultCheck': false\n        },\n        {\n          'action': 'edit',\n          'describe': '修改',\n          'defaultCheck': false\n        },\n        {\n          'action': 'delete',\n          'describe': '删除',\n          'defaultCheck': false\n        }\n        ],\n        'actionList': null,\n        'dataAccess': null\n      },\n      {\n        'roleId': 'admin',\n        'permissionId': 'test',\n        'permissionName': '测试权限',\n        'actions': '[]',\n        'actionEntitySet': [],\n        'actionList': ['add', 'edit'],\n        'dataAccess': null\n      },\n      {\n        'roleId': 'admin',\n        'permissionId': 'user',\n        'permissionName': '用户管理',\n        'actions': '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"import\",\"defaultCheck\":false,\"describe\":\"导入\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"edit\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"},{\"action\":\"export\",\"defaultCheck\":false,\"describe\":\"导出\"}]',\n        'actionEntitySet': [{\n          'action': 'add',\n          'describe': '新增',\n          'defaultCheck': false\n        },\n        {\n          'action': 'import',\n          'describe': '导入',\n          'defaultCheck': false\n        },\n        {\n          'action': 'get',\n          'describe': '详情',\n          'defaultCheck': false\n        },\n        {\n          'action': 'edit',\n          'describe': '修改',\n          'defaultCheck': false\n        }\n        ],\n        'actionList': ['add'],\n        'dataAccess': null\n      }\n      ]\n    },\n    {\n      'id': 'user',\n      'name': '普通会员',\n      'describe': '普通用户，只能查询',\n      'status': 1,\n      'creatorId': 'system',\n      'createTime': 1497160610259,\n      'deleted': 0,\n      'permissions': [{\n        'roleId': 'user',\n        'permissionId': 'comment',\n        'permissionName': '评论管理',\n        'actions': '[{\"action\":\"query\",\"defaultCheck\":false,\"describe\":\"查询\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"}]',\n        'actionEntitySet': [{\n          'action': 'query',\n          'describe': '查询',\n          'defaultCheck': false\n        },\n        {\n          'action': 'get',\n          'describe': '详情',\n          'defaultCheck': false\n        }\n        ],\n        'actionList': ['query'],\n        'dataAccess': null\n      },\n\n      {\n        'roleId': 'user',\n        'permissionId': 'marketing',\n        'permissionName': '营销管理',\n        'actions': '[]',\n        'actionEntitySet': [],\n        'actionList': null,\n        'dataAccess': null\n      },\n      {\n        'roleId': 'user',\n        'permissionId': 'member',\n        'permissionName': '会员管理',\n        'actions': '[{\"action\":\"query\",\"defaultCheck\":false,\"describe\":\"查询\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"}]',\n        'actionEntitySet': [{\n          'action': 'query',\n          'describe': '查询',\n          'defaultCheck': false\n        },\n        {\n          'action': 'get',\n          'describe': '详情',\n          'defaultCheck': false\n        }\n        ],\n        'actionList': null,\n        'dataAccess': null\n      },\n      {\n        'roleId': 'user',\n        'permissionId': 'menu',\n        'permissionName': '菜单管理',\n        'actions': '[]',\n        'actionEntitySet': [],\n        'actionList': null,\n        'dataAccess': null\n      },\n\n      {\n        'roleId': 'user',\n        'permissionId': 'order',\n        'permissionName': '订单管理',\n        'actions': '[{\"action\":\"query\",\"defaultCheck\":false,\"describe\":\"查询\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"}]',\n        'actionEntitySet': [{\n          'action': 'query',\n          'describe': '查询',\n          'defaultCheck': false\n        },\n        {\n          'action': 'get',\n          'describe': '详情',\n          'defaultCheck': false\n        }\n        ],\n        'actionList': null,\n        'dataAccess': null\n      },\n      {\n        'roleId': 'user',\n        'permissionId': 'permission',\n        'permissionName': '权限管理',\n        'actions': '[]',\n        'actionEntitySet': [],\n        'actionList': null,\n        'dataAccess': null\n      },\n      {\n        'roleId': 'user',\n        'permissionId': 'role',\n        'permissionName': '角色管理',\n        'actions': '[]',\n        'actionEntitySet': [],\n        'actionList': null,\n        'dataAccess': null\n      },\n\n      {\n        'roleId': 'user',\n        'permissionId': 'test',\n        'permissionName': '测试权限',\n        'actions': '[]',\n        'actionEntitySet': [],\n        'actionList': null,\n        'dataAccess': null\n      },\n      {\n        'roleId': 'user',\n        'permissionId': 'user',\n        'permissionName': '用户管理',\n        'actions': '[]',\n        'actionEntitySet': [],\n        'actionList': null,\n        'dataAccess': null\n      }\n      ]\n    }\n    ],\n    'pageSize': 10,\n    'pageNo': 0,\n    'totalPage': 1,\n    'totalCount': 5\n  })\n}\n\nconst permissionNoPager = () => {\n  return builder([{\n    'id': 'marketing',\n    'name': '营销管理',\n    'describe': null,\n    'status': 1,\n    'actionData': '[{\"action\":\"query\",\"defaultCheck\":false,\"describe\":\"查询\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"edit\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"}]',\n    'sptDaTypes': null,\n    'optionalFields': null,\n    'parents': null,\n    'type': null,\n    'deleted': 0,\n    'actions': [\n      'add',\n      'query',\n      'get',\n      'edit',\n      'delete'\n    ]\n  },\n  {\n    'id': 'member',\n    'name': '会员管理',\n    'describe': null,\n    'status': 1,\n    'actionData': '[{\"action\":\"query\",\"defaultCheck\":false,\"describe\":\"查询\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"edit\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"}]',\n    'sptDaTypes': null,\n    'optionalFields': '[]',\n    'parents': null,\n    'type': 'default',\n    'deleted': 0,\n    'actions': [\n      'add',\n      'query',\n      'get',\n      'edit',\n      'delete'\n    ]\n  },\n  {\n    'id': 'menu',\n    'name': '菜单管理',\n    'describe': null,\n    'status': 1,\n    'actionData': '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"import\",\"defaultCheck\":false,\"describe\":\"导入\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"查询\"},{\"action\":\"edit\",\"defaultCheck\":false,\"describe\":\"修改\"}]',\n    'sptDaTypes': null,\n    'optionalFields': '[]',\n    'parents': null,\n    'type': 'default',\n    'deleted': 0,\n    'actions': [\n      'add',\n      'import',\n      'get',\n      'edit'\n    ]\n  },\n  {\n    'id': 'order',\n    'name': '订单管理',\n    'describe': null,\n    'status': 1,\n    'actionData': '[{\"action\":\"query\",\"defaultCheck\":false,\"describe\":\"查询\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"edit\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"}]',\n    'sptDaTypes': null,\n    'optionalFields': '[]',\n    'parents': null,\n    'type': 'default',\n    'deleted': 0,\n    'actions': [\n      'add',\n      'query',\n      'get',\n      'edit',\n      'delete'\n    ]\n  },\n  {\n    'id': 'permission',\n    'name': '权限管理',\n    'describe': null,\n    'status': 1,\n    'actionData': '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"查询\"},{\"action\":\"edit\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"}]',\n    'sptDaTypes': null,\n    'optionalFields': '[]',\n    'parents': null,\n    'type': 'default',\n    'deleted': 0,\n    'actions': [\n      'add',\n      'get',\n      'edit',\n      'delete'\n    ]\n  },\n  {\n    'id': 'role',\n    'name': '角色管理',\n    'describe': null,\n    'status': 1,\n    'actionData': '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"查询\"},{\"action\":\"edit\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"}]',\n    'sptDaTypes': null,\n    'optionalFields': '[]',\n    'parents': null,\n    'type': 'default',\n    'deleted': 0,\n    'actions': [\n      'add',\n      'get',\n      'edit',\n      'delete'\n    ]\n  },\n  {\n    'id': 'test',\n    'name': '测试权限',\n    'describe': null,\n    'status': 1,\n    'actionData': '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"}]',\n    'sptDaTypes': null,\n    'optionalFields': '[]',\n    'parents': null,\n    'type': 'default',\n    'deleted': 0,\n    'actions': [\n      'add',\n      'get'\n    ]\n  },\n  {\n    'id': 'user',\n    'name': '用户管理',\n    'describe': null,\n    'status': 1,\n    'actionData': '[{\"action\":\"query\",\"defaultCheck\":false,\"describe\":\"查询\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"edit\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"},{\"action\":\"import\",\"defaultCheck\":false,\"describe\":\"导入\"},{\"action\":\"export\",\"defaultCheck\":false,\"describe\":\"导出\"}]',\n    'sptDaTypes': null,\n    'optionalFields': '[]',\n    'parents': null,\n    'type': 'default',\n    'deleted': 0,\n    'actions': [\n      'add',\n      'get'\n    ]\n  }\n  ])\n}\n\nconst permissions = () => {\n  return builder({\n    'data': [{\n      'id': 'marketing',\n      'name': '营销管理',\n      'describe': null,\n      'status': 1,\n      'actionData': '[{\"action\":\"query\",\"defaultCheck\":false,\"describe\":\"查询\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"edit\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"}]',\n      'sptDaTypes': null,\n      'optionalFields': null,\n      'parents': null,\n      'type': null,\n      'deleted': 0,\n      'actions': [\n        'add',\n        'query',\n        'get',\n        'edit',\n        'delete'\n      ]\n    },\n    {\n      'id': 'member',\n      'name': '会员管理',\n      'describe': null,\n      'status': 1,\n      'actionData': '[{\"action\":\"query\",\"defaultCheck\":false,\"describe\":\"查询\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"edit\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"}]',\n      'sptDaTypes': null,\n      'optionalFields': '[]',\n      'parents': null,\n      'type': 'default',\n      'deleted': 0,\n      'actions': [\n        'add',\n        'query',\n        'get',\n        'edit',\n        'delete'\n      ]\n    },\n    {\n      'id': 'menu',\n      'name': '菜单管理',\n      'describe': null,\n      'status': 1,\n      'actionData': '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"import\",\"defaultCheck\":false,\"describe\":\"导入\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"查询\"},{\"action\":\"edit\",\"defaultCheck\":false,\"describe\":\"修改\"}]',\n      'sptDaTypes': null,\n      'optionalFields': '[]',\n      'parents': null,\n      'type': 'default',\n      'deleted': 0,\n      'actions': [\n        'add',\n        'import',\n        'get',\n        'edit'\n      ]\n    },\n    {\n      'id': 'order',\n      'name': '订单管理',\n      'describe': null,\n      'status': 1,\n      'actionData': '[{\"action\":\"query\",\"defaultCheck\":false,\"describe\":\"查询\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"edit\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"}]',\n      'sptDaTypes': null,\n      'optionalFields': '[]',\n      'parents': null,\n      'type': 'default',\n      'deleted': 0,\n      'actions': [\n        'add',\n        'query',\n        'get',\n        'edit',\n        'delete'\n      ]\n    },\n    {\n      'id': 'permission',\n      'name': '权限管理',\n      'describe': null,\n      'status': 1,\n      'actionData': '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"查询\"},{\"action\":\"edit\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"}]',\n      'sptDaTypes': null,\n      'optionalFields': '[]',\n      'parents': null,\n      'type': 'default',\n      'deleted': 0,\n      'actions': [\n        'add',\n        'get',\n        'edit',\n        'delete'\n      ]\n    },\n    {\n      'id': 'role',\n      'name': '角色管理',\n      'describe': null,\n      'status': 1,\n      'actionData': '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"查询\"},{\"action\":\"edit\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"}]',\n      'sptDaTypes': null,\n      'optionalFields': '[]',\n      'parents': null,\n      'type': 'default',\n      'deleted': 0,\n      'actions': [\n        'add',\n        'get',\n        'edit',\n        'delete'\n      ]\n    },\n    {\n      'id': 'test',\n      'name': '测试权限',\n      'describe': null,\n      'status': 1,\n      'actionData': '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"}]',\n      'sptDaTypes': null,\n      'optionalFields': '[]',\n      'parents': null,\n      'type': 'default',\n      'deleted': 0,\n      'actions': [\n        'add',\n        'get'\n      ]\n    },\n    {\n      'id': 'user',\n      'name': '用户管理',\n      'describe': null,\n      'status': 1,\n      'actionData': '[{\"action\":\"add\",\"describe\":\"新增\",\"defaultCheck\":false},{\"action\":\"get\",\"describe\":\"查询\",\"defaultCheck\":false}]',\n      'sptDaTypes': null,\n      'optionalFields': '[]',\n      'parents': null,\n      'type': 'default',\n      'deleted': 0,\n      'actions': [\n        'add',\n        'get'\n      ]\n    }\n    ],\n    'pageSize': 10,\n    'pageNo': 0,\n    'totalPage': 1,\n    'totalCount': 5\n  })\n}\n\nMock.mock(/\\/org\\/tree/, 'get', orgTree)\nMock.mock(/\\/role/, 'get', role)\nMock.mock(/\\/permission\\/no-pager/, 'get', permissionNoPager)\nMock.mock(/\\/permission/, 'get', permissions)\n"
  },
  {
    "path": "src/mock/services/tagCloud.js",
    "content": "import Mock from 'mockjs2'\nimport { builder } from '../util'\n\n//\nconst tagCloudData = () => {\n  return builder([{ 'value': 9, 'name': 'AntV' }, { 'value': 8, 'name': 'F2' }, { 'value': 8, 'name': 'G2' }, { 'value': 8, 'name': 'G6' }, { 'value': 8, 'name': 'DataSet' }, { 'value': 8, 'name': '墨者学院' }, { 'value': 6, 'name': 'Analysis' }, { 'value': 6, 'name': 'Data Mining' }, { 'value': 6, 'name': 'Data Vis' }, { 'value': 6, 'name': 'Design' }, { 'value': 6, 'name': 'Grammar' }, { 'value': 6, 'name': 'Graphics' }, { 'value': 6, 'name': 'Graph' }, { 'value': 6, 'name': 'Hierarchy' }, { 'value': 6, 'name': 'Labeling' }, { 'value': 6, 'name': 'Layout' }, { 'value': 6, 'name': 'Quantitative' }, { 'value': 6, 'name': 'Relation' }, { 'value': 6, 'name': 'Statistics' }, { 'value': 6, 'name': '可视化' }, { 'value': 6, 'name': '数据' }, { 'value': 6, 'name': '数据可视化' }, { 'value': 4, 'name': 'Arc Diagram' }, { 'value': 4, 'name': 'Bar Chart' }, { 'value': 4, 'name': 'Canvas' }, { 'value': 4, 'name': 'Chart' }, { 'value': 4, 'name': 'DAG' }, { 'value': 4, 'name': 'DG' }, { 'value': 4, 'name': 'Facet' }, { 'value': 4, 'name': 'Geo' }, { 'value': 4, 'name': 'Line' }, { 'value': 4, 'name': 'MindMap' }, { 'value': 4, 'name': 'Pie' }, { 'value': 4, 'name': 'Pizza Chart' }, { 'value': 4, 'name': 'Punch Card' }, { 'value': 4, 'name': 'SVG' }, { 'value': 4, 'name': 'Sunburst' }, { 'value': 4, 'name': 'Tree' }, { 'value': 4, 'name': 'UML' }, { 'value': 3, 'name': 'Chart' }, { 'value': 3, 'name': 'View' }, { 'value': 3, 'name': 'Geom' }, { 'value': 3, 'name': 'Shape' }, { 'value': 3, 'name': 'Scale' }, { 'value': 3, 'name': 'Animate' }, { 'value': 3, 'name': 'Global' }, { 'value': 3, 'name': 'Slider' }, { 'value': 3, 'name': 'Connector' }, { 'value': 3, 'name': 'Transform' }, { 'value': 3, 'name': 'Util' }, { 'value': 3, 'name': 'DomUtil' }, { 'value': 3, 'name': 'MatrixUtil' }, { 'value': 3, 'name': 'PathUtil' }, { 'value': 3, 'name': 'G' }, { 'value': 3, 'name': '2D' }, { 'value': 3, 'name': '3D' }, { 'value': 3, 'name': 'Line' }, { 'value': 3, 'name': 'Area' }, { 'value': 3, 'name': 'Interval' }, { 'value': 3, 'name': 'Schema' }, { 'value': 3, 'name': 'Edge' }, { 'value': 3, 'name': 'Polygon' }, { 'value': 3, 'name': 'Heatmap' }, { 'value': 3, 'name': 'Render' }, { 'value': 3, 'name': 'Tooltip' }, { 'value': 3, 'name': 'Axis' }, { 'value': 3, 'name': 'Guide' }, { 'value': 3, 'name': 'Coord' }, { 'value': 3, 'name': 'Legend' }, { 'value': 3, 'name': 'Path' }, { 'value': 3, 'name': 'Helix' }, { 'value': 3, 'name': 'Theta' }, { 'value': 3, 'name': 'Rect' }, { 'value': 3, 'name': 'Polar' }, { 'value': 3, 'name': 'Dsv' }, { 'value': 3, 'name': 'Csv' }, { 'value': 3, 'name': 'Tsv' }, { 'value': 3, 'name': 'GeoJSON' }, { 'value': 3, 'name': 'TopoJSON' }, { 'value': 3, 'name': 'Filter' }, { 'value': 3, 'name': 'Map' }, { 'value': 3, 'name': 'Pick' }, { 'value': 3, 'name': 'Rename' }, { 'value': 3, 'name': 'Filter' }, { 'value': 3, 'name': 'Map' }, { 'value': 3, 'name': 'Pick' }, { 'value': 3, 'name': 'Rename' }, { 'value': 3, 'name': 'Reverse' }, { 'value': 3, 'name': 'sort' }, { 'value': 3, 'name': 'Subset' }, { 'value': 3, 'name': 'Partition' }, { 'value': 3, 'name': 'Imputation' }, { 'value': 3, 'name': 'Fold' }, { 'value': 3, 'name': 'Aggregate' }, { 'value': 3, 'name': 'Proportion' }, { 'value': 3, 'name': 'Histogram' }, { 'value': 3, 'name': 'Quantile' }, { 'value': 3, 'name': 'Treemap' }, { 'value': 3, 'name': 'Hexagon' }, { 'value': 3, 'name': 'Binning' }, { 'value': 3, 'name': 'kernel' }, { 'value': 3, 'name': 'Regression' }, { 'value': 3, 'name': 'Density' }, { 'value': 3, 'name': 'Sankey' }, { 'value': 3, 'name': 'Voronoi' }, { 'value': 3, 'name': 'Projection' }, { 'value': 3, 'name': 'Centroid' }, { 'value': 3, 'name': 'H5' }, { 'value': 3, 'name': 'Mobile' }, { 'value': 3, 'name': 'K线图' }, { 'value': 3, 'name': '关系图' }, { 'value': 3, 'name': '烛形图' }, { 'value': 3, 'name': '股票图' }, { 'value': 3, 'name': '直方图' }, { 'value': 3, 'name': '金字塔图' }, { 'value': 3, 'name': '分面' }, { 'value': 3, 'name': '南丁格尔玫瑰图' }, { 'value': 3, 'name': '饼图' }, { 'value': 3, 'name': '线图' }, { 'value': 3, 'name': '点图' }, { 'value': 3, 'name': '散点图' }, { 'value': 3, 'name': '子弹图' }, { 'value': 3, 'name': '柱状图' }, { 'value': 3, 'name': '仪表盘' }, { 'value': 3, 'name': '气泡图' }, { 'value': 3, 'name': '漏斗图' }, { 'value': 3, 'name': '热力图' }, { 'value': 3, 'name': '玉玦图' }, { 'value': 3, 'name': '直方图' }, { 'value': 3, 'name': '矩形树图' }, { 'value': 3, 'name': '箱形图' }, { 'value': 3, 'name': '色块图' }, { 'value': 3, 'name': '螺旋图' }, { 'value': 3, 'name': '词云' }, { 'value': 3, 'name': '词云图' }, { 'value': 3, 'name': '雷达图' }, { 'value': 3, 'name': '面积图' }, { 'value': 3, 'name': '马赛克图' }, { 'value': 3, 'name': '盒须图' }, { 'value': 3, 'name': '坐标轴' }, { 'value': 3, 'name': '' }, { 'value': 3, 'name': 'Jacques Bertin' }, { 'value': 3, 'name': 'Leland Wilkinson' }, { 'value': 3, 'name': 'William Playfair' }, { 'value': 3, 'name': '关联' }, { 'value': 3, 'name': '分布' }, { 'value': 3, 'name': '区间' }, { 'value': 3, 'name': '占比' }, { 'value': 3, 'name': '地图' }, { 'value': 3, 'name': '时间' }, { 'value': 3, 'name': '比较' }, { 'value': 3, 'name': '流程' }, { 'value': 3, 'name': '趋势' }, { 'value': 2, 'name': '亦叶' }, { 'value': 2, 'name': '再飞' }, { 'value': 2, 'name': '完白' }, { 'value': 2, 'name': '巴思' }, { 'value': 2, 'name': '张初尘' }, { 'value': 2, 'name': '御术' }, { 'value': 2, 'name': '有田' }, { 'value': 2, 'name': '沉鱼' }, { 'value': 2, 'name': '玉伯' }, { 'value': 2, 'name': '画康' }, { 'value': 2, 'name': '祯逸' }, { 'value': 2, 'name': '绝云' }, { 'value': 2, 'name': '罗宪' }, { 'value': 2, 'name': '萧庆' }, { 'value': 2, 'name': '董珊珊' }, { 'value': 2, 'name': '陆沉' }, { 'value': 2, 'name': '顾倾' }, { 'value': 2, 'name': 'Domo' }, { 'value': 2, 'name': 'GPL' }, { 'value': 2, 'name': 'PAI' }, { 'value': 2, 'name': 'SPSS' }, { 'value': 2, 'name': 'SYSTAT' }, { 'value': 2, 'name': 'Tableau' }, { 'value': 2, 'name': 'D3' }, { 'value': 2, 'name': 'Vega' }, { 'value': 2, 'name': '统计图表' }])\n}\n\nMock.mock(/\\/data\\/antv\\/tag-cloud/, 'get', tagCloudData)\n"
  },
  {
    "path": "src/mock/services/user.js",
    "content": "import Mock from 'mockjs2'\nimport { builder } from '../util'\n\nconst info = options => {\n  console.log('options', options)\n  const userInfo = {\n    id: '4291d7da9005377ec9aec4a71ea837f',\n    name: '天野远子',\n    username: 'admin',\n    password: '',\n    avatar: '/avatar2.jpg',\n    status: 1,\n    telephone: '',\n    lastLoginIp: '27.154.74.117',\n    lastLoginTime: 1534837621348,\n    creatorId: 'admin',\n    createTime: 1497160610259,\n    merchantCode: 'TLif2btpzg079h15bk',\n    deleted: 0,\n    roleId: 'admin',\n    role: {}\n  }\n  // role\n  const roleObj = {\n    id: 'admin',\n    name: '管理员',\n    describe: '拥有所有权限',\n    status: 1,\n    creatorId: 'system',\n    createTime: 1497160610259,\n    deleted: 0,\n    permissions: [\n      {\n        roleId: 'admin',\n        permissionId: 'dashboard',\n        permissionName: '仪表盘',\n        actions:\n          '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"query\",\"defaultCheck\":false,\"describe\":\"查询\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"update\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"}]',\n        actionEntitySet: [\n          {\n            action: 'add',\n            describe: '新增',\n            defaultCheck: false\n          },\n          {\n            action: 'query',\n            describe: '查询',\n            defaultCheck: false\n          },\n          {\n            action: 'get',\n            describe: '详情',\n            defaultCheck: false\n          },\n          {\n            action: 'update',\n            describe: '修改',\n            defaultCheck: false\n          },\n          {\n            action: 'delete',\n            describe: '删除',\n            defaultCheck: false\n          }\n        ],\n        actionList: null,\n        dataAccess: null\n      },\n      {\n        roleId: 'admin',\n        permissionId: 'exception',\n        permissionName: '异常页面权限',\n        actions:\n          '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"query\",\"defaultCheck\":false,\"describe\":\"查询\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"update\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"}]',\n        actionEntitySet: [\n          {\n            action: 'add',\n            describe: '新增',\n            defaultCheck: false\n          },\n          {\n            action: 'query',\n            describe: '查询',\n            defaultCheck: false\n          },\n          {\n            action: 'get',\n            describe: '详情',\n            defaultCheck: false\n          },\n          {\n            action: 'update',\n            describe: '修改',\n            defaultCheck: false\n          },\n          {\n            action: 'delete',\n            describe: '删除',\n            defaultCheck: false\n          }\n        ],\n        actionList: null,\n        dataAccess: null\n      },\n      {\n        roleId: 'admin',\n        permissionId: 'result',\n        permissionName: '结果权限',\n        actions:\n          '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"query\",\"defaultCheck\":false,\"describe\":\"查询\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"update\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"}]',\n        actionEntitySet: [\n          {\n            action: 'add',\n            describe: '新增',\n            defaultCheck: false\n          },\n          {\n            action: 'query',\n            describe: '查询',\n            defaultCheck: false\n          },\n          {\n            action: 'get',\n            describe: '详情',\n            defaultCheck: false\n          },\n          {\n            action: 'update',\n            describe: '修改',\n            defaultCheck: false\n          },\n          {\n            action: 'delete',\n            describe: '删除',\n            defaultCheck: false\n          }\n        ],\n        actionList: null,\n        dataAccess: null\n      },\n      {\n        roleId: 'admin',\n        permissionId: 'profile',\n        permissionName: '详细页权限',\n        actions:\n          '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"query\",\"defaultCheck\":false,\"describe\":\"查询\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"update\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"}]',\n        actionEntitySet: [\n          {\n            action: 'add',\n            describe: '新增',\n            defaultCheck: false\n          },\n          {\n            action: 'query',\n            describe: '查询',\n            defaultCheck: false\n          },\n          {\n            action: 'get',\n            describe: '详情',\n            defaultCheck: false\n          },\n          {\n            action: 'update',\n            describe: '修改',\n            defaultCheck: false\n          },\n          {\n            action: 'delete',\n            describe: '删除',\n            defaultCheck: false\n          }\n        ],\n        actionList: null,\n        dataAccess: null\n      },\n      {\n        roleId: 'admin',\n        permissionId: 'table',\n        permissionName: '表格权限',\n        actions:\n          '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"import\",\"defaultCheck\":false,\"describe\":\"导入\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"update\",\"defaultCheck\":false,\"describe\":\"修改\"}]',\n        actionEntitySet: [\n          {\n            action: 'add',\n            describe: '新增',\n            defaultCheck: false\n          },\n          {\n            action: 'import',\n            describe: '导入',\n            defaultCheck: false\n          },\n          {\n            action: 'get',\n            describe: '详情',\n            defaultCheck: false\n          },\n          {\n            action: 'update',\n            describe: '修改',\n            defaultCheck: false\n          }\n        ],\n        actionList: null,\n        dataAccess: null\n      },\n      {\n        roleId: 'admin',\n        permissionId: 'form',\n        permissionName: '表单权限',\n        actions:\n          '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"query\",\"defaultCheck\":false,\"describe\":\"查询\"},{\"action\":\"update\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"}]',\n        actionEntitySet: [\n          {\n            action: 'add',\n            describe: '新增',\n            defaultCheck: false\n          },\n          {\n            action: 'get',\n            describe: '详情',\n            defaultCheck: false\n          },\n          {\n            action: 'query',\n            describe: '查询',\n            defaultCheck: false\n          },\n          {\n            action: 'update',\n            describe: '修改',\n            defaultCheck: false\n          },\n          {\n            action: 'delete',\n            describe: '删除',\n            defaultCheck: false\n          }\n        ],\n        actionList: null,\n        dataAccess: null\n      },\n      {\n        roleId: 'admin',\n        permissionId: 'order',\n        permissionName: '订单管理',\n        actions:\n          '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"query\",\"defaultCheck\":false,\"describe\":\"查询\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"update\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"}]',\n        actionEntitySet: [\n          {\n            action: 'add',\n            describe: '新增',\n            defaultCheck: false\n          },\n          {\n            action: 'query',\n            describe: '查询',\n            defaultCheck: false\n          },\n          {\n            action: 'get',\n            describe: '详情',\n            defaultCheck: false\n          },\n          {\n            action: 'update',\n            describe: '修改',\n            defaultCheck: false\n          },\n          {\n            action: 'delete',\n            describe: '删除',\n            defaultCheck: false\n          }\n        ],\n        actionList: null,\n        dataAccess: null\n      },\n      {\n        roleId: 'admin',\n        permissionId: 'permission',\n        permissionName: '权限管理',\n        actions:\n          '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"update\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"}]',\n        actionEntitySet: [\n          {\n            action: 'add',\n            describe: '新增',\n            defaultCheck: false\n          },\n          {\n            action: 'get',\n            describe: '详情',\n            defaultCheck: false\n          },\n          {\n            action: 'update',\n            describe: '修改',\n            defaultCheck: false\n          },\n          {\n            action: 'delete',\n            describe: '删除',\n            defaultCheck: false\n          }\n        ],\n        actionList: null,\n        dataAccess: null\n      },\n      {\n        roleId: 'admin',\n        permissionId: 'role',\n        permissionName: '角色管理',\n        actions:\n          '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"update\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"}]',\n        actionEntitySet: [\n          {\n            action: 'add',\n            describe: '新增',\n            defaultCheck: false\n          },\n          {\n            action: 'get',\n            describe: '详情',\n            defaultCheck: false\n          },\n          {\n            action: 'update',\n            describe: '修改',\n            defaultCheck: false\n          },\n          {\n            action: 'delete',\n            describe: '删除',\n            defaultCheck: false\n          }\n        ],\n        actionList: null,\n        dataAccess: null\n      },\n      {\n        roleId: 'admin',\n        permissionId: 'table',\n        permissionName: '桌子管理',\n        actions:\n          '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"query\",\"defaultCheck\":false,\"describe\":\"查询\"},{\"action\":\"update\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"}]',\n        actionEntitySet: [\n          {\n            action: 'add',\n            describe: '新增',\n            defaultCheck: false\n          },\n          {\n            action: 'get',\n            describe: '详情',\n            defaultCheck: false\n          },\n          {\n            action: 'query',\n            describe: '查询',\n            defaultCheck: false\n          },\n          {\n            action: 'update',\n            describe: '修改',\n            defaultCheck: false\n          },\n          {\n            action: 'delete',\n            describe: '删除',\n            defaultCheck: false\n          }\n        ],\n        actionList: null,\n        dataAccess: null\n      },\n      {\n        roleId: 'admin',\n        permissionId: 'user',\n        permissionName: '用户管理',\n        actions:\n          '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"import\",\"defaultCheck\":false,\"describe\":\"导入\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"update\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"},{\"action\":\"export\",\"defaultCheck\":false,\"describe\":\"导出\"}]',\n        actionEntitySet: [\n          {\n            action: 'add',\n            describe: '新增',\n            defaultCheck: false\n          },\n          {\n            action: 'import',\n            describe: '导入',\n            defaultCheck: false\n          },\n          {\n            action: 'get',\n            describe: '详情',\n            defaultCheck: false\n          },\n          {\n            action: 'update',\n            describe: '修改',\n            defaultCheck: false\n          },\n          {\n            action: 'delete',\n            describe: '删除',\n            defaultCheck: false\n          },\n          {\n            action: 'export',\n            describe: '导出',\n            defaultCheck: false\n          }\n        ],\n        actionList: null,\n        dataAccess: null\n      }\n    ]\n  }\n\n  roleObj.permissions.push({\n    roleId: 'admin',\n    permissionId: 'support',\n    permissionName: '超级模块',\n    actions:\n      '[{\"action\":\"add\",\"defaultCheck\":false,\"describe\":\"新增\"},{\"action\":\"import\",\"defaultCheck\":false,\"describe\":\"导入\"},{\"action\":\"get\",\"defaultCheck\":false,\"describe\":\"详情\"},{\"action\":\"update\",\"defaultCheck\":false,\"describe\":\"修改\"},{\"action\":\"delete\",\"defaultCheck\":false,\"describe\":\"删除\"},{\"action\":\"export\",\"defaultCheck\":false,\"describe\":\"导出\"}]',\n    actionEntitySet: [\n      {\n        action: 'add',\n        describe: '新增',\n        defaultCheck: false\n      },\n      {\n        action: 'import',\n        describe: '导入',\n        defaultCheck: false\n      },\n      {\n        action: 'get',\n        describe: '详情',\n        defaultCheck: false\n      },\n      {\n        action: 'update',\n        describe: '修改',\n        defaultCheck: false\n      },\n      {\n        action: 'delete',\n        describe: '删除',\n        defaultCheck: false\n      },\n      {\n        action: 'export',\n        describe: '导出',\n        defaultCheck: false\n      }\n    ],\n    actionList: null,\n    dataAccess: null\n  })\n\n  userInfo.role = roleObj\n  return builder(userInfo)\n}\n\n/**\n * 使用 用户登录的 token 获取用户有权限的菜单\n * 返回结构必须按照这个结构体形式处理，或根据\n * /src/router/generator-routers.js  文件的菜单结构处理函数对应即可\n * @param {*} options\n * @returns\n */\nconst userNav = options => {\n  const nav = [\n    // dashboard\n    {\n      name: 'dashboard',\n      parentId: 0,\n      id: 1,\n      meta: {\n        title: 'menu.dashboard',\n        icon: 'dashboard',\n        show: true\n      },\n      component: 'RouteView',\n      redirect: '/dashboard/workplace'\n    },\n    {\n      name: 'workplace',\n      parentId: 1,\n      id: 7,\n      meta: {\n        title: 'menu.dashboard.monitor',\n        show: true\n      },\n      component: 'Workplace'\n    },\n    {\n      name: 'monitor',\n      path: 'https://www.baidu.com/',\n      parentId: 1,\n      id: 3,\n      meta: {\n        title: 'menu.dashboard.workplace',\n        target: '_blank',\n        show: true\n      }\n    },\n    {\n      name: 'Analysis',\n      parentId: 1,\n      id: 2,\n      meta: {\n        title: 'menu.dashboard.analysis',\n        show: true\n      },\n      component: 'Analysis',\n      path: '/dashboard/analysis'\n    },\n\n    // form\n    {\n      name: 'form',\n      parentId: 0,\n      id: 10,\n      meta: {\n        icon: 'form',\n        title: 'menu.form'\n      },\n      redirect: '/form/base-form',\n      component: 'RouteView'\n    },\n    {\n      name: 'basic-form',\n      parentId: 10,\n      id: 6,\n      meta: {\n        title: 'menu.form.basic-form'\n      },\n      component: 'BasicForm'\n    },\n    {\n      name: 'step-form',\n      parentId: 10,\n      id: 5,\n      meta: {\n        title: 'menu.form.step-form'\n      },\n      component: 'StepForm'\n    },\n    {\n      name: 'advanced-form',\n      parentId: 10,\n      id: 4,\n      meta: {\n        title: 'menu.form.advanced-form'\n      },\n      component: 'AdvanceForm'\n    },\n\n    // list\n    {\n      name: 'list',\n      parentId: 0,\n      id: 10010,\n      meta: {\n        icon: 'table',\n        title: 'menu.list',\n        show: true\n      },\n      redirect: '/list/table-list',\n      component: 'RouteView'\n    },\n    {\n      name: 'table-list',\n      parentId: 10010,\n      id: 10011,\n      path: '/list/table-list/:pageNo([1-9]\\\\d*)?',\n      meta: {\n        title: 'menu.list.table-list',\n        show: true\n      },\n      component: 'TableList'\n    },\n    {\n      name: 'basic-list',\n      parentId: 10010,\n      id: 10012,\n      meta: {\n        title: 'menu.list.basic-list',\n        show: true\n      },\n      component: 'StandardList'\n    },\n    {\n      name: 'card',\n      parentId: 10010,\n      id: 10013,\n      meta: {\n        title: 'menu.list.card-list',\n        show: true\n      },\n      component: 'CardList'\n    },\n    {\n      name: 'search',\n      parentId: 10010,\n      id: 10014,\n      meta: {\n        title: 'menu.list.search-list',\n        show: true\n      },\n      redirect: '/list/search/article',\n      component: 'SearchLayout'\n    },\n    {\n      name: 'article',\n      parentId: 10014,\n      id: 10015,\n      meta: {\n        title: 'menu.list.search-list.articles',\n        show: true\n      },\n      component: 'SearchArticles'\n    },\n    {\n      name: 'project',\n      parentId: 10014,\n      id: 10016,\n      meta: {\n        title: 'menu.list.search-list.projects',\n        show: true\n      },\n      component: 'SearchProjects'\n    },\n    {\n      name: 'application',\n      parentId: 10014,\n      id: 10017,\n      meta: {\n        title: 'menu.list.search-list.applications',\n        show: true\n      },\n      component: 'SearchApplications'\n    },\n\n    // profile\n    {\n      name: 'profile',\n      parentId: 0,\n      id: 10018,\n      meta: {\n        title: 'menu.profile',\n        icon: 'profile',\n        show: true\n      },\n      redirect: '/profile/basic',\n      component: 'RouteView'\n    },\n    {\n      name: 'basic',\n      parentId: 10018,\n      id: 10019,\n      meta: {\n        title: 'menu.profile.basic',\n        show: true\n      },\n      component: 'ProfileBasic'\n    },\n    {\n      name: 'advanced',\n      parentId: 10018,\n      id: 10020,\n      meta: {\n        title: 'menu.profile.advanced',\n        show: true\n      },\n      component: 'ProfileAdvanced'\n    },\n\n    // result\n    {\n      name: 'result',\n      parentId: 0,\n      id: 10021,\n      meta: {\n        title: 'menu.result',\n        icon: 'check-circle-o',\n        show: true\n      },\n      redirect: '/result/success',\n      component: 'PageView'\n    },\n    {\n      name: 'success',\n      parentId: 10021,\n      id: 10022,\n      meta: {\n        title: 'menu.result.success',\n        hiddenHeaderContent: true,\n        show: true\n      },\n      component: 'ResultSuccess'\n    },\n    {\n      name: 'fail',\n      parentId: 10021,\n      id: 10023,\n      meta: {\n        title: 'menu.result.fail',\n        hiddenHeaderContent: true,\n        show: true\n      },\n      component: 'ResultFail'\n    },\n\n    // Exception\n    {\n      name: 'exception',\n      parentId: 0,\n      id: 10024,\n      meta: {\n        title: 'menu.exception',\n        icon: 'warning',\n        show: true\n      },\n      redirect: '/exception/403',\n      component: 'RouteView'\n    },\n    {\n      name: '403',\n      parentId: 10024,\n      id: 10025,\n      meta: {\n        title: 'menu.exception.not-permission',\n        show: true\n      },\n      component: 'Exception403'\n    },\n    {\n      name: '404',\n      parentId: 10024,\n      id: 10026,\n      meta: {\n        title: 'menu.exception.not-find',\n        show: true\n      },\n      component: 'Exception404'\n    },\n    {\n      name: '500',\n      parentId: 10024,\n      id: 10027,\n      meta: {\n        title: 'menu.exception.server-error',\n        show: true\n      },\n      component: 'Exception500'\n    },\n\n    // account\n    {\n      name: 'account',\n      parentId: 0,\n      id: 10028,\n      meta: {\n        title: 'menu.account',\n        icon: 'user',\n        show: true\n      },\n      redirect: '/account/center',\n      component: 'RouteView'\n    },\n    {\n      name: 'center',\n      parentId: 10028,\n      id: 10029,\n      meta: {\n        title: 'menu.account.center',\n        show: true\n      },\n      component: 'AccountCenter'\n    },\n    // 特殊三级菜单\n    {\n      name: 'settings',\n      parentId: 10028,\n      id: 10030,\n      meta: {\n        title: 'menu.account.settings',\n        hideHeader: true,\n        hideChildren: true,\n        show: true\n      },\n      redirect: '/account/settings/basic',\n      component: 'AccountSettings'\n    },\n    {\n      name: 'BasicSettings',\n      path: '/account/settings/basic',\n      parentId: 10030,\n      id: 10031,\n      meta: {\n        title: 'account.settings.menuMap.basic',\n        show: false\n      },\n      component: 'BasicSetting'\n    },\n    {\n      name: 'SecuritySettings',\n      path: '/account/settings/security',\n      parentId: 10030,\n      id: 10032,\n      meta: {\n        title: 'account.settings.menuMap.security',\n        show: false\n      },\n      component: 'SecuritySettings'\n    },\n    {\n      name: 'CustomSettings',\n      path: '/account/settings/custom',\n      parentId: 10030,\n      id: 10033,\n      meta: {\n        title: 'account.settings.menuMap.custom',\n        show: false\n      },\n      component: 'CustomSettings'\n    },\n    {\n      name: 'BindingSettings',\n      path: '/account/settings/binding',\n      parentId: 10030,\n      id: 10034,\n      meta: {\n        title: 'account.settings.menuMap.binding',\n        show: false\n      },\n      component: 'BindingSettings'\n    },\n    {\n      name: 'NotificationSettings',\n      path: '/account/settings/notification',\n      parentId: 10030,\n      id: 10034,\n      meta: {\n        title: 'account.settings.menuMap.notification',\n        show: false\n      },\n      component: 'NotificationSettings'\n    }\n  ]\n  const json = builder(nav)\n  console.log('json', json)\n  return json\n}\n\nMock.mock(/\\/api\\/user\\/info/, 'get', info)\nMock.mock(/\\/api\\/user\\/nav/, 'get', userNav)\n"
  },
  {
    "path": "src/mock/util.js",
    "content": "const responseBody = {\n  message: '',\n  timestamp: 0,\n  result: null,\n  code: 0\n}\n\nexport const builder = (data, message, code = 0, headers = {}) => {\n  responseBody.result = data\n  if (message !== undefined && message !== null) {\n    responseBody.message = message\n  }\n  if (code !== undefined && code !== 0) {\n    responseBody.code = code\n    responseBody._status = code\n  }\n  if (headers !== null && typeof headers === 'object' && Object.keys(headers).length > 0) {\n    responseBody._headers = headers\n  }\n  responseBody.timestamp = new Date().getTime()\n  return responseBody\n}\n\nexport const getQueryParameters = (options) => {\n  const url = options.url\n  const search = url.split('?')[1]\n  if (!search) {\n    return {}\n  }\n  return JSON.parse('{\"' + decodeURIComponent(search)\n    .replace(/\"/g, '\\\\\"')\n    .replace(/&/g, '\",\"')\n    .replace(/=/g, '\":\"') + '\"}')\n}\n\nexport const getBody = (options) => {\n  return options.body && JSON.parse(options.body)\n}\n"
  },
  {
    "path": "src/permission.js",
    "content": "import router, { resetRouter } from './router'\nimport store from './store'\nimport storage from 'store'\nimport NProgress from 'nprogress' // progress bar\nimport '@/components/NProgress/nprogress.less' // progress bar custom style\nimport notification from 'ant-design-vue/es/notification'\nimport { setDocumentTitle, domTitle } from '@/utils/domUtil'\nimport { ACCESS_TOKEN } from '@/store/mutation-types'\nimport { i18nRender } from '@/locales'\n\nNProgress.configure({ showSpinner: false }) // NProgress Configuration\n\nconst allowList = ['login', 'register', 'registerResult'] // no redirect allowList\nconst loginRoutePath = '/user/login'\nconst defaultRoutePath = '/dashboard/workplace'\n\nrouter.beforeEach((to, from, next) => {\n  NProgress.start() // start progress bar\n  to.meta && typeof to.meta.title !== 'undefined' && setDocumentTitle(`${i18nRender(to.meta.title)} - ${domTitle}`)\n  /* has token */\n  const token = storage.get(ACCESS_TOKEN)\n  if (token) {\n    if (to.path === loginRoutePath) {\n      next({ path: defaultRoutePath })\n      NProgress.done()\n    } else {\n      // check login user.roles is null\n      if (store.getters.roles.length === 0) {\n        // request login userInfo\n        store\n          .dispatch('GetInfo')\n          .then(res => {\n            console.log('res', res)\n            // 根据用户权限信息生成可访问的路由表\n            store.dispatch('GenerateRoutes', { token, ...res }).then(() => {\n              // 动态添加可访问路由表\n              // VueRouter@3.5.0+ New API\n              resetRouter() // 重置路由 防止退出重新登录或者 token 过期后页面未刷新，导致的路由重复添加\n              store.getters.addRouters.forEach(r => {\n                router.addRoute(r)\n              })\n              // 请求带有 redirect 重定向时，登录自动重定向到该地址\n              const redirect = decodeURIComponent(from.query.redirect || to.path)\n              if (to.path === redirect) {\n                // set the replace: true so the navigation will not leave a history record\n                next({ ...to, replace: true })\n              } else {\n                // 跳转到目的路由\n                next({ path: redirect })\n              }\n            })\n          })\n          .catch(() => {\n            notification.error({\n              message: '错误',\n              description: '请求用户信息失败，请重试'\n            })\n            // 失败时，获取用户信息失败时，调用登出，来清空历史保留信息\n            store.dispatch('Logout').then(() => {\n              next({ path: loginRoutePath, query: { redirect: to.fullPath } })\n            })\n          })\n      } else {\n        next()\n      }\n    }\n  } else {\n    if (allowList.includes(to.name)) {\n      // 在免登录名单，直接进入\n      next()\n    } else {\n      next({ path: loginRoutePath, query: { redirect: to.fullPath } })\n      NProgress.done() // if current page is login will not trigger afterEach hook, so manually handle it\n    }\n  }\n})\n\nrouter.afterEach(() => {\n  NProgress.done() // finish progress bar\n})\n"
  },
  {
    "path": "src/router/README.md",
    "content": "路由/菜单说明\n====\n\n\n格式和说明\n----\n\n```ecmascript 6\nconst routerObject = {\n  redirect: noredirect,\n  name: 'router-name',\n  hidden: true,\n  meta: {\n    title: 'title',\n    icon: 'a-icon',\n    target: '_blank|_self|_top|_parent',\n    keepAlive: true,\n    hiddenHeaderContent: true,\n  }\n}\n```\n\n\n\n`{ Route }` 对象\n\n| 参数     | 说明                                      | 类型    | 默认值 |\n| -------- | ----------------------------------------- | ------- | ------ |\n| hidden   | 控制路由是否显示在 sidebar                | boolean | false |\n| redirect | 重定向地址, 访问这个路由时,自定进行重定向 | string  | -      |\n| name     | 路由名称, 必须设置,且不能重名           | string  | -      |\n| meta     | 路由元信息（路由附带扩展信息）            | object  | {}     |\n| hideChildrenInMenu | 强制菜单显示为Item而不是SubItem(配合 meta.hidden) | boolean  | -   |\n\n\n`{ Meta }` 路由元信息对象\n\n| 参数                | 说明                                                         | 类型    | 默认值 |\n| ------------------- | ------------------------------------------------------------ | ------- | ------ |\n| title               | 路由标题, 用于显示面包屑, 页面标题 *推荐设置                 | string  | -      |\n| icon                | 路由在 menu 上显示的图标                                     | [string,svg]  | -      |\n| keepAlive           | 缓存该路由                                                   | boolean | false  |\n| target              | 菜单链接跳转目标（参考 html a 标记）                          | string | -  |\n| hidden              | 配合`hideChildrenInMenu`使用，用于隐藏菜单时，提供递归到父菜单显示 选中菜单项_（可参考 个人页 配置方式）_ | boolean | false  |\n| hiddenHeaderContent | *特殊 隐藏 [PageHeader](https://github.com/vueComponent/ant-design-vue-pro/blob/master/src/components/PageHeader/PageHeader.vue#L6) 组件中的页面带的 面包屑和页面标题栏 | boolean | false  |\n| permission          | 与项目提供的权限拦截匹配的权限，如果不匹配，则会被禁止访问该路由页面 | array   | []     |\n\n> 路由自定义 `Icon` 请引入自定义 `svg` Icon 文件，然后传递给路由的 `meta.icon` 参数即可\n\n路由构建例子方案1\n\n路由例子\n----\n\n```ecmascript 6\nconst asyncRouterMap = [\n  {\n    path: '/',\n    name: 'index',\n    component: BasicLayout,\n    meta: { title: '首页' },\n    redirect: '/dashboard/analysis',\n    children: [\n      {\n        path: '/dashboard',\n        component: RouteView,\n        name: 'dashboard',\n        redirect: '/dashboard/workplace',\n        meta: {title: '仪表盘', icon: 'dashboard', permission: ['dashboard']},\n        children: [\n          {\n            path: '/dashboard/analysis',\n            name: 'Analysis',\n            component: () => import('@/views/dashboard/Analysis'),\n            meta: {title: '分析页', permission: ['dashboard']}\n          },\n          {\n            path: '/dashboard/monitor',\n            name: 'Monitor',\n            hidden: true,\n            component: () => import('@/views/dashboard/Monitor'),\n            meta: {title: '监控页', permission: ['dashboard']}\n          },\n          {\n            path: '/dashboard/workplace',\n            name: 'Workplace',\n            component: () => import('@/views/dashboard/Workplace'),\n            meta: {title: '工作台', permission: ['dashboard']}\n          }\n        ]\n      },\n\n      // result\n      {\n        path: '/result',\n        name: 'result',\n        component: PageView,\n        redirect: '/result/success',\n        meta: { title: '结果页', icon: 'check-circle-o', permission: [ 'result' ] },\n        children: [\n          {\n            path: '/result/success',\n            name: 'ResultSuccess',\n            component: () => import(/* webpackChunkName: \"result\" */ '@/views/result/Success'),\n            // 该页面隐藏面包屑和页面标题栏\n            meta: { title: '成功', hiddenHeaderContent: true, permission: [ 'result' ] }\n          },\n          {\n            path: '/result/fail',\n            name: 'ResultFail',\n            component: () => import(/* webpackChunkName: \"result\" */ '@/views/result/Error'),\n            // 该页面隐藏面包屑和页面标题栏\n            meta: { title: '失败', hiddenHeaderContent: true, permission: [ 'result' ] }\n          }\n        ]\n      },\n      ...\n    ]\n  },\n]\n```\n\n> 1. 请注意 `component: () => import('..') ` 方式引入路由的页面组件为 懒加载模式。具体可以看 [Vue 官方文档](https://router.vuejs.org/zh/guide/advanced/lazy-loading.html)\n> 2. 增加新的路由应该增加在 '/' (index) 路由的 `children` 内\n> 3. 子路由的父级路由必须有 `router-view` 才能让子路由渲染出来，请仔细查阅 vue-router 文档\n> 4. `permission` 可以进行自定义修改，只需要对这个模块进行自定义修改即可 [src/store/modules/permission.js#L10](https://github.com/vueComponent/ant-design-vue-pro/blob/master/src/store/modules/permission.js#L10)\n\n\n附权限路由结构：\n\n![权限结构](https://static-2.loacg.com/open/static/github/permissions.png)\n\n\n第二种前端路由由后端动态生成的设计，可以前往官网文档 https://pro.antdv.com/docs/authority-management 参考\n"
  },
  {
    "path": "src/router/generator-routers.js",
    "content": "// eslint-disable-next-line\nimport * as loginService from '@/api/login'\n// eslint-disable-next-line\nimport { BasicLayout, BlankLayout, PageView, RouteView } from '@/layouts'\n\n// 前端路由表 (基于动态)\nconst constantRouterComponents = {\n  // 基础页面 layout 必须引入\n  BasicLayout: BasicLayout,\n  BlankLayout: BlankLayout,\n  RouteView: RouteView,\n  PageView: PageView,\n  '403': () => import(/* webpackChunkName: \"error\" */ '@/views/exception/403'),\n  '404': () => import(/* webpackChunkName: \"error\" */ '@/views/exception/404'),\n  '500': () => import(/* webpackChunkName: \"error\" */ '@/views/exception/500'),\n\n  // 你需要动态引入的页面组件\n  Workplace: () => import('@/views/dashboard/Workplace'),\n  Analysis: () => import('@/views/dashboard/Analysis'),\n\n  // form\n  BasicForm: () => import('@/views/form/basicForm'),\n  StepForm: () => import('@/views/form/stepForm/StepForm'),\n  AdvanceForm: () => import('@/views/form/advancedForm/AdvancedForm'),\n\n  // list\n  TableList: () => import('@/views/list/TableList'),\n  StandardList: () => import('@/views/list/BasicList'),\n  CardList: () => import('@/views/list/CardList'),\n  SearchLayout: () => import('@/views/list/search/SearchLayout'),\n  SearchArticles: () => import('@/views/list/search/Article'),\n  SearchProjects: () => import('@/views/list/search/Projects'),\n  SearchApplications: () => import('@/views/list/search/Applications'),\n  ProfileBasic: () => import('@/views/profile/basic'),\n  ProfileAdvanced: () => import('@/views/profile/advanced/Advanced'),\n\n  // result\n  ResultSuccess: () => import(/* webpackChunkName: \"result\" */ '@/views/result/Success'),\n  ResultFail: () => import(/* webpackChunkName: \"result\" */ '@/views/result/Error'),\n\n  // exception\n  Exception403: () => import(/* webpackChunkName: \"fail\" */ '@/views/exception/403'),\n  Exception404: () => import(/* webpackChunkName: \"fail\" */ '@/views/exception/404'),\n  Exception500: () => import(/* webpackChunkName: \"fail\" */ '@/views/exception/500'),\n\n  // account\n  AccountCenter: () => import('@/views/account/center'),\n  AccountSettings: () => import('@/views/account/settings/Index'),\n  BasicSetting: () => import('@/views/account/settings/BasicSetting'),\n  SecuritySettings: () => import('@/views/account/settings/Security'),\n  CustomSettings: () => import('@/views/account/settings/Custom'),\n  BindingSettings: () => import('@/views/account/settings/Binding'),\n  NotificationSettings: () => import('@/views/account/settings/Notification')\n\n  // 'TestWork': () => import(/* webpackChunkName: \"TestWork\" */ '@/views/dashboard/TestWork')\n}\n\n// 前端未找到页面路由（固定不用改）\nconst notFoundRouter = {\n  path: '*',\n  redirect: '/404',\n  hidden: true\n}\n\n// 根级菜单\nconst rootRouter = {\n  key: '',\n  name: 'index',\n  path: '',\n  component: 'BasicLayout',\n  redirect: '/dashboard',\n  meta: {\n    title: '首页'\n  },\n  children: []\n}\n\n// export const generatorStaticRouter = () => {\n\n// }\n\n/**\n * 动态生成菜单\n * @param token\n * @returns {Promise<Router>}\n */\nexport const generatorDynamicRouter = token => {\n  return new Promise((resolve, reject) => {\n    loginService\n      .getCurrentUserNav(token)\n      .then(res => {\n        console.log('generatorDynamicRouter response:', res)\n        const { result } = res\n        const menuNav = []\n        const childrenNav = []\n        //      后端数据, 根级树数组,  根级 PID\n        listToTree(result, childrenNav, 0)\n        rootRouter.children = childrenNav\n        menuNav.push(rootRouter)\n        console.log('menuNav', menuNav)\n        const routers = generator(menuNav)\n        routers.push(notFoundRouter)\n        console.log('routers', routers)\n        resolve(routers)\n      })\n      .catch(err => {\n        reject(err)\n      })\n  })\n}\n\n/**\n * 格式化树形结构数据 生成 vue-router 层级路由表\n *\n * @param routerMap\n * @param parent\n * @returns {*}\n */\nexport const generator = (routerMap, parent) => {\n  return routerMap.map(item => {\n    const { title, show, hideChildren, hiddenHeaderContent, target, icon } = item.meta || {}\n    const currentRouter = {\n      // 如果路由设置了 path，则作为默认 path，否则 路由地址 动态拼接生成如 /dashboard/workplace\n      path: item.path || `${(parent && parent.path) || ''}/${item.key}`,\n      // 路由名称，建议唯一\n      name: item.name || item.key || '',\n      // 该路由对应页面的 组件 :方案1\n      // component: constantRouterComponents[item.component || item.key],\n      // 该路由对应页面的 组件 :方案2 (动态加载)\n      component: constantRouterComponents[item.component || item.key] || (() => import(`@/views/${item.component}`)),\n\n      // meta: 页面标题, 菜单图标, 页面权限(供指令权限用，可去掉)\n      meta: {\n        title: title,\n        icon: icon || undefined,\n        hiddenHeaderContent: hiddenHeaderContent,\n        target: target,\n        permission: item.name\n      }\n    }\n    // 是否设置了隐藏菜单\n    if (show === false) {\n      currentRouter.hidden = true\n    }\n    // 是否设置了隐藏子菜单\n    if (hideChildren) {\n      currentRouter.hideChildrenInMenu = true\n    }\n    // 为了防止出现后端返回结果不规范，处理有可能出现拼接出两个 反斜杠\n    if (!currentRouter.path.startsWith('http')) {\n      currentRouter.path = currentRouter.path.replace('//', '/')\n    }\n    // 重定向\n    item.redirect && (currentRouter.redirect = item.redirect)\n    // 是否有子菜单，并递归处理\n    if (item.children && item.children.length > 0) {\n      // Recursion\n      currentRouter.children = generator(item.children, currentRouter)\n    }\n    return currentRouter\n  })\n}\n\n/**\n * 数组转树形结构\n * @param list 源数组\n * @param tree 树\n * @param parentId 父ID\n */\nconst listToTree = (list, tree, parentId) => {\n  list.forEach(item => {\n    // 判断是否为父级菜单\n    if (item.parentId === parentId) {\n      const child = {\n        ...item,\n        key: item.key || item.name,\n        children: []\n      }\n      // 迭代 list， 找到当前菜单相符合的所有子菜单\n      listToTree(list, child.children, item.id)\n      // 删掉不存在 children 值的属性\n      if (child.children.length <= 0) {\n        delete child.children\n      }\n      // 加入到树中\n      tree.push(child)\n    }\n  })\n}\n"
  },
  {
    "path": "src/router/index.js",
    "content": "import Vue from 'vue'\nimport Router from 'vue-router'\nimport { constantRouterMap } from '@/config/router.config'\n\n// hack router push callback\nconst originalPush = Router.prototype.push\nRouter.prototype.push = function push (location, onResolve, onReject) {\n  if (onResolve || onReject) return originalPush.call(this, location, onResolve, onReject)\n  return originalPush.call(this, location).catch(err => err)\n}\n\nVue.use(Router)\n\nconst createRouter = () =>\n  new Router({\n    mode: 'history',\n    routes: constantRouterMap\n  })\n\nconst router = createRouter()\n\n// 定义一个resetRouter 方法，在退出登录后或token过期后 需要重新登录时，调用即可\nexport function resetRouter () {\n  const newRouter = createRouter()\n  router.matcher = newRouter.matcher\n}\n\nexport default router\n"
  },
  {
    "path": "src/store/app-mixin.js",
    "content": "import { mapState } from 'vuex'\n\nconst baseMixin = {\n  computed: {\n    ...mapState({\n      layout: state => state.app.layout,\n      navTheme: state => state.app.theme,\n      primaryColor: state => state.app.color,\n      colorWeak: state => state.app.weak,\n      fixedHeader: state => state.app.fixedHeader,\n      fixedSidebar: state => state.app.fixedSidebar,\n      contentWidth: state => state.app.contentWidth,\n      autoHideHeader: state => state.app.autoHideHeader,\n\n      isMobile: state => state.app.isMobile,\n      sideCollapsed: state => state.app.sideCollapsed,\n      multiTab: state => state.app.multiTab\n    }),\n    isTopMenu () {\n      return this.layout === 'topmenu'\n    }\n  },\n  methods: {\n    isSideMenu () {\n      return !this.isTopMenu\n    }\n  }\n}\n\nexport {\n  baseMixin\n}\n"
  },
  {
    "path": "src/store/device-mixin.js",
    "content": "import { mapState } from 'vuex'\n\nconst deviceMixin = {\n  computed: {\n    ...mapState({\n      isMobile: state => state.app.isMobile\n    })\n  }\n}\n\nexport { deviceMixin }\n"
  },
  {
    "path": "src/store/getters.js",
    "content": "const getters = {\n  isMobile: state => state.app.isMobile,\n  lang: state => state.app.lang,\n  theme: state => state.app.theme,\n  color: state => state.app.color,\n  token: state => state.user.token,\n  avatar: state => state.user.avatar,\n  nickname: state => state.user.name,\n  welcome: state => state.user.welcome,\n  roles: state => state.user.roles,\n  userInfo: state => state.user.info,\n  addRouters: state => state.permission.addRouters,\n  multiTab: state => state.app.multiTab\n}\n\nexport default getters\n"
  },
  {
    "path": "src/store/i18n-mixin.js",
    "content": "import { mapState } from 'vuex'\n\nconst i18nMixin = {\n  computed: {\n    ...mapState({\n      currentLang: state => state.app.lang\n    })\n  },\n  methods: {\n    setLang (lang) {\n      this.$store.dispatch('setLang', lang)\n    }\n  }\n}\n\nexport default i18nMixin\n"
  },
  {
    "path": "src/store/index.js",
    "content": "import Vue from 'vue'\nimport Vuex from 'vuex'\n\nimport app from './modules/app'\nimport user from './modules/user'\n\n// default router permission control\n// 默认路由模式为静态路由 (router.config.js)\nimport permission from './modules/static-router'\n\n// dynamic router permission control (Experimental)\n// 动态路由模式（api请求后端生成）\n// import permission from './modules/async-router'\n\nimport getters from './getters'\n\nVue.use(Vuex)\n\nexport default new Vuex.Store({\n  modules: {\n    app,\n    user,\n    permission\n  },\n  state: {},\n  mutations: {},\n  actions: {},\n  getters\n})\n"
  },
  {
    "path": "src/store/modules/app.js",
    "content": "import storage from 'store'\nimport {\n  SIDEBAR_TYPE,\n  TOGGLE_MOBILE_TYPE,\n  TOGGLE_NAV_THEME,\n  TOGGLE_LAYOUT,\n  TOGGLE_FIXED_HEADER,\n  TOGGLE_FIXED_SIDEBAR,\n  TOGGLE_CONTENT_WIDTH,\n  TOGGLE_HIDE_HEADER,\n  TOGGLE_COLOR,\n  TOGGLE_WEAK,\n  TOGGLE_MULTI_TAB,\n  // i18n\n  APP_LANGUAGE\n} from '@/store/mutation-types'\nimport { loadLanguageAsync } from '@/locales'\n\nconst app = {\n  state: {\n    sideCollapsed: false,\n    isMobile: false,\n    theme: 'dark',\n    layout: '',\n    contentWidth: '',\n    fixedHeader: false,\n    fixedSidebar: false,\n    autoHideHeader: false,\n    color: '',\n    weak: false,\n    multiTab: true,\n    lang: 'en-US',\n    _antLocale: {}\n  },\n  mutations: {\n    [SIDEBAR_TYPE]: (state, type) => {\n      state.sideCollapsed = type\n      storage.set(SIDEBAR_TYPE, type)\n    },\n    [TOGGLE_MOBILE_TYPE]: (state, isMobile) => {\n      state.isMobile = isMobile\n    },\n    [TOGGLE_NAV_THEME]: (state, theme) => {\n      state.theme = theme\n      storage.set(TOGGLE_NAV_THEME, theme)\n    },\n    [TOGGLE_LAYOUT]: (state, mode) => {\n      state.layout = mode\n      storage.set(TOGGLE_LAYOUT, mode)\n    },\n    [TOGGLE_FIXED_HEADER]: (state, mode) => {\n      state.fixedHeader = mode\n      storage.set(TOGGLE_FIXED_HEADER, mode)\n    },\n    [TOGGLE_FIXED_SIDEBAR]: (state, mode) => {\n      state.fixedSidebar = mode\n      storage.set(TOGGLE_FIXED_SIDEBAR, mode)\n    },\n    [TOGGLE_CONTENT_WIDTH]: (state, type) => {\n      state.contentWidth = type\n      storage.set(TOGGLE_CONTENT_WIDTH, type)\n    },\n    [TOGGLE_HIDE_HEADER]: (state, type) => {\n      state.autoHideHeader = type\n      storage.set(TOGGLE_HIDE_HEADER, type)\n    },\n    [TOGGLE_COLOR]: (state, color) => {\n      state.color = color\n      storage.set(TOGGLE_COLOR, color)\n    },\n    [TOGGLE_WEAK]: (state, mode) => {\n      state.weak = mode\n      storage.set(TOGGLE_WEAK, mode)\n    },\n    [APP_LANGUAGE]: (state, lang, antd = {}) => {\n      state.lang = lang\n      state._antLocale = antd\n      storage.set(APP_LANGUAGE, lang)\n    },\n    [TOGGLE_MULTI_TAB]: (state, bool) => {\n      storage.set(TOGGLE_MULTI_TAB, bool)\n      state.multiTab = bool\n    }\n  },\n  actions: {\n    setLang ({ commit }, lang) {\n      return new Promise((resolve, reject) => {\n        commit(APP_LANGUAGE, lang)\n        loadLanguageAsync(lang).then(() => {\n          resolve()\n        }).catch((e) => {\n          reject(e)\n        })\n      })\n    }\n  }\n}\n\nexport default app\n"
  },
  {
    "path": "src/store/modules/async-router.js",
    "content": "/**\n * 向后端请求用户的菜单，动态生成路由\n */\nimport { constantRouterMap } from '@/config/router.config'\nimport { generatorDynamicRouter } from '@/router/generator-routers'\n\nconst permission = {\n  state: {\n    routers: constantRouterMap,\n    addRouters: []\n  },\n  mutations: {\n    SET_ROUTERS: (state, routers) => {\n      state.addRouters = routers\n      state.routers = constantRouterMap.concat(routers)\n    }\n  },\n  actions: {\n    GenerateRoutes ({ commit }, data) {\n      return new Promise((resolve, reject) => {\n        const { token } = data\n        generatorDynamicRouter(token).then(routers => {\n          commit('SET_ROUTERS', routers)\n          resolve()\n        }).catch(e => {\n          reject(e)\n        })\n      })\n    }\n  }\n}\n\nexport default permission\n"
  },
  {
    "path": "src/store/modules/static-router.js",
    "content": "import { asyncRouterMap, constantRouterMap } from '@/config/router.config'\nimport cloneDeep from 'lodash.clonedeep'\n\n/**\n * 过滤账户是否拥有某一个权限，并将菜单从加载列表移除\n *\n * @param permission\n * @param route\n * @returns {boolean}\n */\nfunction hasPermission (permission, route) {\n  if (route.meta && route.meta.permission) {\n    console.log('hasPermission', permission)\n    if (permission === undefined) {\n      return false\n    }\n    let flag = false\n    for (let i = 0, len = permission.length; i < len; i++) {\n      flag = route.meta.permission.includes(permission[i])\n      if (flag) {\n        return true\n      }\n    }\n    return false\n  }\n  return true\n}\n\n/**\n * 单账户多角色时，使用该方法可过滤角色不存在的菜单\n *\n * @param roles\n * @param route\n * @returns {*}\n */\n// eslint-disable-next-line\nfunction hasRole(roles, route) {\n  if (route.meta && route.meta.roles) {\n    return route.meta.roles.includes(roles.id)\n  } else {\n    return true\n  }\n}\n\nfunction filterAsyncRouter (routerMap, role) {\n  const accessedRouters = routerMap.filter(route => {\n    if (hasPermission(role.permissionList, route)) {\n      if (route.children && route.children.length) {\n        route.children = filterAsyncRouter(route.children, role)\n      }\n      return true\n    }\n    return false\n  })\n  return accessedRouters\n}\n\nconst permission = {\n  state: {\n    routers: constantRouterMap,\n    addRouters: []\n  },\n  mutations: {\n    SET_ROUTERS: (state, routers) => {\n      state.addRouters = routers\n      state.routers = constantRouterMap.concat(routers)\n    }\n  },\n  actions: {\n    GenerateRoutes ({ commit }, data) {\n      return new Promise(resolve => {\n        const { role } = data\n        const routerMap = cloneDeep(asyncRouterMap)\n        const accessedRouters = filterAsyncRouter(routerMap, role)\n        commit('SET_ROUTERS', accessedRouters)\n        resolve()\n      })\n    }\n  }\n}\n\nexport default permission\n"
  },
  {
    "path": "src/store/modules/user.js",
    "content": "import storage from 'store'\nimport expirePlugin from 'store/plugins/expire'\nimport { login, getInfo, logout } from '@/api/login'\nimport { ACCESS_TOKEN } from '@/store/mutation-types'\nimport { welcome } from '@/utils/util'\n\nstorage.addPlugin(expirePlugin)\nconst user = {\n  state: {\n    token: '',\n    name: '',\n    welcome: '',\n    avatar: '',\n    roles: [],\n    info: {}\n  },\n\n  mutations: {\n    SET_TOKEN: (state, token) => {\n      state.token = token\n    },\n    SET_NAME: (state, { name, welcome }) => {\n      state.name = name\n      state.welcome = welcome\n    },\n    SET_AVATAR: (state, avatar) => {\n      state.avatar = avatar\n    },\n    SET_ROLES: (state, roles) => {\n      state.roles = roles\n    },\n    SET_INFO: (state, info) => {\n      state.info = info\n    }\n  },\n\n  actions: {\n    // 登录\n    Login ({ commit }, userInfo) {\n      return new Promise((resolve, reject) => {\n        login(userInfo).then(response => {\n          const result = response.result\n          storage.set(ACCESS_TOKEN, result.token, new Date().getTime() + 7 * 24 * 60 * 60 * 1000)\n          commit('SET_TOKEN', result.token)\n          resolve()\n        }).catch(error => {\n          reject(error)\n        })\n      })\n    },\n\n    // 获取用户信息\n    GetInfo ({ commit }) {\n      return new Promise((resolve, reject) => {\n        // 请求后端获取用户信息 /api/user/info\n        getInfo().then(response => {\n          const { result } = response\n          if (result.role && result.role.permissions.length > 0) {\n            const role = { ...result.role }\n            role.permissions = result.role.permissions.map(permission => {\n              const per = {\n                ...permission,\n                actionList: (permission.actionEntitySet || {}).map(item => item.action)\n               }\n              return per\n            })\n            role.permissionList = role.permissions.map(permission => { return permission.permissionId })\n            // 覆盖响应体的 role, 供下游使用\n            result.role = role\n\n            commit('SET_ROLES', role)\n            commit('SET_INFO', result)\n            commit('SET_NAME', { name: result.name, welcome: welcome() })\n            commit('SET_AVATAR', result.avatar)\n            // 下游\n            resolve(result)\n          } else {\n            reject(new Error('getInfo: roles must be a non-null array !'))\n          }\n        }).catch(error => {\n          reject(error)\n        })\n      })\n    },\n\n    // 登出\n    Logout ({ commit, state }) {\n      return new Promise((resolve) => {\n        logout(state.token).then(() => {\n          commit('SET_TOKEN', '')\n          commit('SET_ROLES', [])\n          storage.remove(ACCESS_TOKEN)\n          resolve()\n        }).catch((err) => {\n          console.log('logout fail:', err)\n          // resolve()\n        }).finally(() => {\n        })\n      })\n    }\n\n  }\n}\n\nexport default user\n"
  },
  {
    "path": "src/store/mutation-types.js",
    "content": "export const ACCESS_TOKEN = 'Access-Token'\n\nexport const SIDEBAR_TYPE = 'sidebar_type'\nexport const TOGGLE_MOBILE_TYPE = 'is_mobile'\nexport const TOGGLE_NAV_THEME = 'nav_theme'\nexport const TOGGLE_LAYOUT = 'layout'\nexport const TOGGLE_FIXED_HEADER = 'fixed_header'\nexport const TOGGLE_FIXED_SIDEBAR = 'fixed_sidebar'\nexport const TOGGLE_CONTENT_WIDTH = 'content_width'\nexport const TOGGLE_HIDE_HEADER = 'auto_hide_header'\nexport const TOGGLE_COLOR = 'color'\nexport const TOGGLE_WEAK = 'weak'\nexport const TOGGLE_MULTI_TAB = 'multi_tab'\nexport const APP_LANGUAGE = 'app_language'\n\nexport const CONTENT_WIDTH_TYPE = {\n  Fluid: 'Fluid',\n  Fixed: 'Fixed'\n}\n\nexport const NAV_THEME = {\n  LIGHT: 'light',\n  DARK: 'dark'\n}\n"
  },
  {
    "path": "src/utils/axios.js",
    "content": "const VueAxios = {\n  vm: {},\n  // eslint-disable-next-line no-unused-vars\n  install (Vue, instance) {\n    if (this.installed) {\n      return\n    }\n    this.installed = true\n\n    if (!instance) {\n      // eslint-disable-next-line no-console\n      console.error('You have to install axios')\n      return\n    }\n\n    Vue.axios = instance\n\n    Object.defineProperties(Vue.prototype, {\n      axios: {\n        get: function get () {\n          return instance\n        }\n      },\n      $http: {\n        get: function get () {\n          return instance\n        }\n      }\n    })\n  }\n}\n\nexport {\n  VueAxios\n}\n"
  },
  {
    "path": "src/utils/domUtil.js",
    "content": "import config from '@/config/defaultSettings'\n\nexport const setDocumentTitle = function (title) {\n  document.title = title\n  const ua = navigator.userAgent\n  // eslint-disable-next-line\n  const regex = /\\bMicroMessenger\\/([\\d\\.]+)/\n  if (regex.test(ua) && /ip(hone|od|ad)/i.test(ua)) {\n    const i = document.createElement('iframe')\n    i.src = '/favicon.ico'\n    i.style.display = 'none'\n    i.onload = function () {\n      setTimeout(function () {\n        i.remove()\n      }, 9)\n    }\n    document.body.appendChild(i)\n  }\n}\n\nexport const domTitle = config.title\n"
  },
  {
    "path": "src/utils/filter.js",
    "content": "import Vue from 'vue'\nimport moment from 'moment'\nimport 'moment/locale/zh-cn'\nmoment.locale('zh-cn')\n\nVue.filter('NumberFormat', function (value) {\n  if (!value) {\n    return '0'\n  }\n  const intPartFormat = value.toString().replace(/(\\d)(?=(?:\\d{3})+$)/g, '$1,') // 将整数部分逢三一断\n  return intPartFormat\n})\n\nVue.filter('dayjs', function (dataStr, pattern = 'YYYY-MM-DD HH:mm:ss') {\n  return moment(dataStr).format(pattern)\n})\n\nVue.filter('moment', function (dataStr, pattern = 'YYYY-MM-DD HH:mm:ss') {\n  return moment(dataStr).format(pattern)\n})\n"
  },
  {
    "path": "src/utils/request.js",
    "content": "import axios from 'axios'\nimport store from '@/store'\nimport storage from 'store'\nimport notification from 'ant-design-vue/es/notification'\nimport { VueAxios } from './axios'\nimport { ACCESS_TOKEN } from '@/store/mutation-types'\n\n// 创建 axios 实例\nconst request = axios.create({\n  // API 请求的默认前缀\n  baseURL: process.env.VUE_APP_API_BASE_URL,\n  timeout: 6000 // 请求超时时间\n})\n\n// 异常拦截处理器\nconst errorHandler = (error) => {\n  if (error.response) {\n    const data = error.response.data\n    // 从 localstorage 获取 token\n    const token = storage.get(ACCESS_TOKEN)\n    if (error.response.status === 403) {\n      notification.error({\n        message: 'Forbidden',\n        description: data.message\n      })\n    }\n    if (error.response.status === 401 && !(data.result && data.result.isLogin)) {\n      notification.error({\n        message: 'Unauthorized',\n        description: 'Authorization verification failed'\n      })\n      if (token) {\n        store.dispatch('Logout').then(() => {\n          setTimeout(() => {\n            window.location.reload()\n          }, 1500)\n        })\n      }\n    }\n  }\n  return Promise.reject(error)\n}\n\n// request interceptor\nrequest.interceptors.request.use(config => {\n  const token = storage.get(ACCESS_TOKEN)\n  // 如果 token 存在\n  // 让每个请求携带自定义 token 请根据实际情况自行修改\n  if (token) {\n    config.headers[ACCESS_TOKEN] = token\n  }\n  return config\n}, errorHandler)\n\n// response interceptor\nrequest.interceptors.response.use((response) => {\n  return response.data\n}, errorHandler)\n\nconst installer = {\n  vm: {},\n  install (Vue) {\n    Vue.use(VueAxios, request)\n  }\n}\n\nexport default request\n\nexport {\n  installer as VueAxios,\n  request as axios\n}\n"
  },
  {
    "path": "src/utils/routeConvert.js",
    "content": "import cloneDeep from 'lodash.clonedeep'\n\nexport function convertRoutes (nodes) {\n  if (!nodes) return null\n\n  nodes = cloneDeep(nodes)\n\n  let queue = Array.isArray(nodes) ? nodes.concat() : [nodes]\n\n  while (queue.length) {\n    const levelSize = queue.length\n\n    for (let i = 0; i < levelSize; i++) {\n      const node = queue.shift()\n\n      if (!node.children || !node.children.length) continue\n\n      node.children.forEach(child => {\n        // 转化相对路径\n        if (child.path[0] !== '/' && !child.path.startsWith('http')) {\n          child.path = node.path.replace(/(\\w*)[/]*$/, `$1/${child.path}`)\n        }\n      })\n\n      queue = queue.concat(node.children)\n    }\n  }\n\n  return nodes\n}\n"
  },
  {
    "path": "src/utils/screenLog.js",
    "content": "/* eslint-disable */\nexport const printANSI = () => {\n  // console.clear()\n  console.log('[antd pro] created()')\n  // ASCII - ANSI Shadow\n  let text = `\n █████╗ ███╗   ██╗████████╗██████╗     ██████╗ ██████╗  ██████╗ \n██╔══██╗████╗  ██║╚══██╔══╝██╔══██╗    ██╔══██╗██╔══██╗██╔═══██╗\n███████║██╔██╗ ██║   ██║   ██║  ██║    ██████╔╝██████╔╝██║   ██║\n██╔══██║██║╚██╗██║   ██║   ██║  ██║    ██╔═══╝ ██╔══██╗██║   ██║\n██║  ██║██║ ╚████║   ██║   ██████╔╝    ██║     ██║  ██║╚██████╔╝\n╚═╝  ╚═╝╚═╝  ╚═══╝   ╚═╝   ╚═════╝     ╚═╝     ╚═╝  ╚═╝ ╚═════╝ \n\\t\\t\\t\\t\\tPublished ${APP_VERSION}-${GIT_HASH} @ antdv.com\n\\t\\t\\t\\t\\tBuild date: ${BUILD_DATE}`\n  console.log(`%c${text}`, 'color: #fc4d50')\n  console.log('%c感谢使用 antd pro!', 'color: #000; font-size: 14px;    font-family: Hiragino Sans GB,Microsoft YaHei,\\\\\\\\5FAE\\\\8F6F\\\\96C5\\\\9ED1,Droid Sans Fallback,Source Sans,Wenquanyi Micro Hei,WenQuanYi Micro Hei Mono,WenQuanYi Zen Hei,Apple LiGothic Medium,SimHei,ST Heiti,WenQuanYi Zen Hei Sharp,sans-serif;')\n  console.log('%cThanks for using antd pro!', 'color: #fff; font-size: 14px; font-weight: 300; text-shadow:#000 1px 0 0,#000 0 1px 0,#000 -1px 0 0,#000 0 -1px 0;')\n  console.log('')\n  console.log('%c默认使用的路由初始化模式可能是 静态路由 / 动态路由, 请前往 src/store/index.js 确认 import permission from 哪一个文件.', 'color: #000; font-size: 14px;    font-family: Hiragino Sans GB,Microsoft YaHei,\\\\\\\\5FAE\\\\8F6F\\\\96C5\\\\9ED1,Droid Sans Fallback,Source Sans,Wenquanyi Micro Hei,WenQuanYi Micro Hei Mono,WenQuanYi Zen Hei,Apple LiGothic Medium,SimHei,ST Heiti,WenQuanYi Zen Hei Sharp,sans-serif;')\n  console.log('')\n}\n"
  },
  {
    "path": "src/utils/util.js",
    "content": "export function timeFix () {\n  const time = new Date()\n  const hour = time.getHours()\n  return hour < 9 ? '早上好' : hour <= 11 ? '上午好' : hour <= 13 ? '中午好' : hour < 20 ? '下午好' : '晚上好'\n}\n\nexport function welcome () {\n  const arr = ['休息一会儿吧', '准备吃什么呢?', '要不要打一把 DOTA', '我猜你可能累了']\n  const index = Math.floor(Math.random() * arr.length)\n  return arr[index]\n}\n\n/**\n * 触发 window.resize\n */\nexport function triggerWindowResizeEvent () {\n  const event = document.createEvent('HTMLEvents')\n  event.initEvent('resize', true, true)\n  event.eventType = 'message'\n  window.dispatchEvent(event)\n}\n\nexport function handleScrollHeader (callback) {\n  let timer = 0\n\n  let beforeScrollTop = window.pageYOffset\n  callback = callback || function () {}\n  window.addEventListener(\n    'scroll',\n    event => {\n      clearTimeout(timer)\n      timer = setTimeout(() => {\n        let direction = 'up'\n        const afterScrollTop = window.pageYOffset\n        const delta = afterScrollTop - beforeScrollTop\n        if (delta === 0) {\n          return false\n        }\n        direction = delta > 0 ? 'down' : 'up'\n        callback(direction)\n        beforeScrollTop = afterScrollTop\n      }, 50)\n    },\n    false\n  )\n}\n\nexport function isIE () {\n  const bw = window.navigator.userAgent\n  const compare = (s) => bw.indexOf(s) >= 0\n  const ie11 = (() => 'ActiveXObject' in window)()\n  return compare('MSIE') || ie11\n}\n\n/**\n * Remove loading animate\n * @param id parent element id or class\n * @param timeout\n */\nexport function removeLoadingAnimate (id = '', timeout = 1500) {\n  if (id === '') {\n    return\n  }\n  setTimeout(() => {\n    document.body.removeChild(document.getElementById(id))\n  }, timeout)\n}\nexport function scorePassword (pass) {\n  let score = 0\n  if (!pass) {\n    return score\n  }\n  // award every unique letter until 5 repetitions\n  const letters = {}\n  for (let i = 0; i < pass.length; i++) {\n      letters[pass[i]] = (letters[pass[i]] || 0) + 1\n      score += 5.0 / letters[pass[i]]\n  }\n\n  // bonus points for mixing it up\n  const variations = {\n      digits: /\\d/.test(pass),\n      lower: /[a-z]/.test(pass),\n      upper: /[A-Z]/.test(pass),\n      nonWords: /\\W/.test(pass)\n  }\n\n  let variationCount = 0\n  for (var check in variations) {\n      variationCount += (variations[check] === true) ? 1 : 0\n  }\n  score += (variationCount - 1) * 10\n\n  return parseInt(score)\n}\n"
  },
  {
    "path": "src/utils/utils.less",
    "content": ".textOverflow() {\n  overflow: hidden;\n  text-overflow: ellipsis;\n  word-break: break-all;\n  white-space: nowrap;\n}\n\n.textOverflowMulti(@line: 3, @bg: #fff) {\n  position: relative;\n  max-height: @line * 1.5em;\n  padding-right: 1em;\n  margin-right: -1em;\n  overflow: hidden;\n  line-height: 1.5em;\n  text-align: justify;\n\n  &::before {\n    position: absolute;\n    right: 14px;\n    bottom: 0;\n    padding: 0 1px;\n    background: @bg;\n    content: '...';\n  }\n\n  &::after {\n    position: absolute;\n    right: 14px;\n    width: 1em;\n    height: 1em;\n    margin-top: .2em;\n    background: white;\n    content: '';\n  }\n}\n\n// mixins for clearfix\n// ------------------------\n.clearfix() {\n  zoom: 1;\n\n  &::before,\n  &::after {\n    display: table;\n    content: ' ';\n  }\n\n  &::after {\n    height: 0;\n    clear: both;\n    font-size: 0;\n    visibility: hidden;\n  }\n}\n"
  },
  {
    "path": "src/views/404.vue",
    "content": "<template>\n  <div>\n    404 page\n  </div>\n</template>\n\n<script>\nexport default {\n  name: '404'\n}\n</script>\n\n<style scoped>\n\n</style>\n"
  },
  {
    "path": "src/views/account/center/index.vue",
    "content": "<template>\n  <div class=\"page-header-index-wide page-header-wrapper-grid-content-main\">\n    <a-row :gutter=\"24\">\n      <a-col :md=\"24\" :lg=\"7\">\n        <a-card :bordered=\"false\">\n          <div class=\"account-center-avatarHolder\">\n            <div class=\"avatar\">\n              <img :src=\"avatar\">\n            </div>\n            <div class=\"username\">{{ nickname }}</div>\n            <div class=\"bio\">海纳百川，有容乃大</div>\n          </div>\n          <div class=\"account-center-detail\">\n            <p>\n              <i class=\"title\"></i>交互专家\n            </p>\n            <p>\n              <i class=\"group\"></i>蚂蚁金服－某某某事业群－某某平台部－某某技术部－UED\n            </p>\n            <p>\n              <i class=\"address\"></i>\n              <span>浙江省</span>\n              <span>杭州市</span>\n            </p>\n          </div>\n          <a-divider/>\n\n          <div class=\"account-center-tags\">\n            <div class=\"tagsTitle\">标签</div>\n            <div>\n              <template v-for=\"(tag, index) in tags\">\n                <a-tooltip v-if=\"tag.length > 20\" :key=\"tag\" :title=\"tag\">\n                  <a-tag\n                    :key=\"tag\"\n                    :closable=\"index !== 0\"\n                    :close=\"() => handleTagClose(tag)\"\n                  >{{ `${tag.slice(0, 20)}...` }}</a-tag>\n                </a-tooltip>\n                <a-tag\n                  v-else\n                  :key=\"tag\"\n                  :closable=\"index !== 0\"\n                  :close=\"() => handleTagClose(tag)\"\n                >{{ tag }}</a-tag>\n              </template>\n              <a-input\n                v-if=\"tagInputVisible\"\n                ref=\"tagInput\"\n                type=\"text\"\n                size=\"small\"\n                :style=\"{ width: '78px' }\"\n                :value=\"tagInputValue\"\n                @change=\"handleInputChange\"\n                @blur=\"handleTagInputConfirm\"\n                @keyup.enter=\"handleTagInputConfirm\"\n              />\n              <a-tag v-else @click=\"showTagInput\" style=\"background: #fff; borderStyle: dashed;\">\n                <a-icon type=\"plus\"/>New Tag\n              </a-tag>\n            </div>\n          </div>\n          <a-divider :dashed=\"true\"/>\n\n          <div class=\"account-center-team\">\n            <div class=\"teamTitle\">团队</div>\n            <a-spin :spinning=\"teamSpinning\">\n              <div class=\"members\">\n                <a-row>\n                  <a-col :span=\"12\" v-for=\"(item, index) in teams\" :key=\"index\">\n                    <a>\n                      <a-avatar size=\"small\" :src=\"item.avatar\"/>\n                      <span class=\"member\">{{ item.name }}</span>\n                    </a>\n                  </a-col>\n                </a-row>\n              </div>\n            </a-spin>\n          </div>\n        </a-card>\n      </a-col>\n      <a-col :md=\"24\" :lg=\"17\">\n        <a-card\n          style=\"width:100%\"\n          :bordered=\"false\"\n          :tabList=\"tabListNoTitle\"\n          :activeTabKey=\"noTitleKey\"\n          @tabChange=\"key => handleTabChange(key, 'noTitleKey')\"\n        >\n          <article-page v-if=\"noTitleKey === 'article'\"></article-page>\n          <app-page v-else-if=\"noTitleKey === 'app'\"></app-page>\n          <project-page v-else-if=\"noTitleKey === 'project'\"></project-page>\n        </a-card>\n      </a-col>\n    </a-row>\n  </div>\n</template>\n\n<script>\nimport { PageView, RouteView } from '@/layouts'\nimport { AppPage, ArticlePage, ProjectPage } from './page'\n\nimport { mapGetters } from 'vuex'\n\nexport default {\n  components: {\n    RouteView,\n    PageView,\n    AppPage,\n    ArticlePage,\n    ProjectPage\n  },\n  data () {\n    return {\n      tags: ['很有想法的', '专注设计', '辣~', '大长腿', '川妹子', '海纳百川'],\n\n      tagInputVisible: false,\n      tagInputValue: '',\n\n      teams: [],\n      teamSpinning: true,\n\n      tabListNoTitle: [\n        {\n          key: 'article',\n          tab: '文章(8)'\n        },\n        {\n          key: 'app',\n          tab: '应用(8)'\n        },\n        {\n          key: 'project',\n          tab: '项目(8)'\n        }\n      ],\n      noTitleKey: 'app'\n    }\n  },\n  computed: {\n    ...mapGetters(['nickname', 'avatar'])\n  },\n  mounted () {\n    this.getTeams()\n  },\n  methods: {\n    getTeams () {\n      this.$http.get('/workplace/teams').then(res => {\n        this.teams = res.result\n        this.teamSpinning = false\n      })\n    },\n\n    handleTabChange (key, type) {\n      this[type] = key\n    },\n\n    handleTagClose (removeTag) {\n      const tags = this.tags.filter(tag => tag !== removeTag)\n      this.tags = tags\n    },\n\n    showTagInput () {\n      this.tagInputVisible = true\n      this.$nextTick(() => {\n        this.$refs.tagInput.focus()\n      })\n    },\n\n    handleInputChange (e) {\n      this.tagInputValue = e.target.value\n    },\n\n    handleTagInputConfirm () {\n      const inputValue = this.tagInputValue\n      let tags = this.tags\n      if (inputValue && !tags.includes(inputValue)) {\n        tags = [...tags, inputValue]\n      }\n\n      Object.assign(this, {\n        tags,\n        tagInputVisible: false,\n        tagInputValue: ''\n      })\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n.page-header-wrapper-grid-content-main {\n  width: 100%;\n  height: 100%;\n  min-height: 100%;\n  transition: 0.3s;\n\n  .account-center-avatarHolder {\n    text-align: center;\n    margin-bottom: 24px;\n\n    & > .avatar {\n      margin: 0 auto;\n      width: 104px;\n      height: 104px;\n      margin-bottom: 20px;\n      border-radius: 50%;\n      overflow: hidden;\n      img {\n        height: 100%;\n        width: 100%;\n      }\n    }\n\n    .username {\n      color: rgba(0, 0, 0, 0.85);\n      font-size: 20px;\n      line-height: 28px;\n      font-weight: 500;\n      margin-bottom: 4px;\n    }\n  }\n\n  .account-center-detail {\n    p {\n      margin-bottom: 8px;\n      padding-left: 26px;\n      position: relative;\n    }\n\n    i {\n      position: absolute;\n      height: 14px;\n      width: 14px;\n      left: 0;\n      top: 4px;\n      background: url(https://gw.alipayobjects.com/zos/rmsportal/pBjWzVAHnOOtAUvZmZfy.svg);\n    }\n\n    .title {\n      background-position: 0 0;\n    }\n    .group {\n      background-position: 0 -22px;\n    }\n    .address {\n      background-position: 0 -44px;\n    }\n  }\n\n  .account-center-tags {\n    .ant-tag {\n      margin-bottom: 8px;\n    }\n  }\n\n  .account-center-team {\n    .members {\n      a {\n        display: block;\n        margin: 12px 0;\n        line-height: 24px;\n        height: 24px;\n        .member {\n          font-size: 14px;\n          color: rgba(0, 0, 0, 0.65);\n          line-height: 24px;\n          max-width: 100px;\n          vertical-align: top;\n          margin-left: 12px;\n          transition: all 0.3s;\n          display: inline-block;\n        }\n        &:hover {\n          span {\n            color: #1890ff;\n          }\n        }\n      }\n    }\n  }\n\n  .tagsTitle,\n  .teamTitle {\n    font-weight: 500;\n    color: rgba(0, 0, 0, 0.85);\n    margin-bottom: 12px;\n  }\n}\n</style>\n"
  },
  {
    "path": "src/views/account/center/page/App.vue",
    "content": "<template>\n  <div class=\"app-list\">\n    <a-list\n      :grid=\"{ gutter: 24, lg: 3, md: 2, sm: 1, xs: 1 }\"\n      :dataSource=\"dataSource\">\n      <a-list-item slot=\"renderItem\" slot-scope=\"item\">\n        <a-card :hoverable=\"true\">\n          <a-card-meta>\n            <div style=\"margin-bottom: 3px\" slot=\"title\">{{ item.title }}</div>\n            <a-avatar class=\"card-avatar\" slot=\"avatar\" :src=\"item.avatar\" size=\"small\"/>\n            <div class=\"meta-cardInfo\" slot=\"description\">\n              <div>\n                <p>活跃用户</p>\n                <p>\n                  <span>{{ item.activeUser }}<span>万</span></span>\n                </p>\n              </div>\n              <div>\n                <p>新增用户</p>\n                <p>{{ item.newUser | NumberFormat }}</p>\n              </div>\n            </div>\n          </a-card-meta>\n          <template class=\"ant-card-actions\" slot=\"actions\">\n            <a>\n              <a-icon type=\"download\"/>\n            </a>\n            <a>\n              <a-icon type=\"edit\"/>\n            </a>\n            <a>\n              <a-icon type=\"share-alt\"/>\n            </a>\n            <a>\n              <a-dropdown>\n                <a class=\"ant-dropdown-link\" href=\"javascript:;\">\n                  <a-icon type=\"ellipsis\"/>\n                </a>\n                <a-menu slot=\"overlay\">\n                  <a-menu-item>\n                    <a href=\"javascript:;\">1st menu item</a>\n                  </a-menu-item>\n                  <a-menu-item>\n                    <a href=\"javascript:;\">2nd menu item</a>\n                  </a-menu-item>\n                  <a-menu-item>\n                    <a href=\"javascript:;\">3rd menu item</a>\n                  </a-menu-item>\n                </a-menu>\n              </a-dropdown>\n            </a>\n          </template>\n        </a-card>\n      </a-list-item>\n    </a-list>\n\n  </div>\n</template>\n\n<script>\nconst dataSource = []\nfor (let i = 0; i < 11; i++) {\n  dataSource.push({\n    title: 'Alipay',\n    avatar: 'https://gw.alipayobjects.com/zos/rmsportal/WdGqmHpayyMjiEhcKoVE.png',\n    activeUser: 17,\n    newUser: 1700\n  })\n}\n\nexport default {\n  name: 'Article',\n  components: {},\n  data () {\n    return {\n      dataSource\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n\n  .app-list {\n\n    .meta-cardInfo {\n      zoom: 1;\n      margin-top: 16px;\n\n      > div {\n        position: relative;\n        text-align: left;\n        float: left;\n        width: 50%;\n\n        p {\n          line-height: 32px;\n          font-size: 24px;\n          margin: 0;\n\n          &:first-child {\n            color: rgba(0, 0, 0, .45);\n            font-size: 12px;\n            line-height: 20px;\n            margin-bottom: 4px;\n          }\n        }\n\n      }\n    }\n  }\n\n</style>\n"
  },
  {
    "path": "src/views/account/center/page/Article.vue",
    "content": "<template>\n  <a-list\n    size=\"large\"\n    rowKey=\"id\"\n    :loading=\"loading\"\n    itemLayout=\"vertical\"\n    :dataSource=\"data\"\n  >\n    <a-list-item :key=\"item.id\" slot=\"renderItem\" slot-scope=\"item\">\n      <template slot=\"actions\">\n        <icon-text type=\"star-o\" :text=\"item.star\" />\n        <icon-text type=\"like-o\" :text=\"item.like\" />\n        <icon-text type=\"message\" :text=\"item.message\" />\n      </template>\n      <a-list-item-meta>\n        <a slot=\"title\" href=\"https://vue.ant.design/\">{{ item.title }}</a>\n        <template slot=\"description\">\n          <span>\n            <a-tag>Ant Design</a-tag>\n            <a-tag>设计语言</a-tag>\n            <a-tag>蚂蚁金服</a-tag>\n          </span>\n        </template>\n      </a-list-item-meta>\n      <article-list-content :description=\"item.description\" :owner=\"item.owner\" :avatar=\"item.avatar\" :href=\"item.href\" :updateAt=\"item.updatedAt\" />\n    </a-list-item>\n    <div slot=\"footer\" v-if=\"data.length > 0\" style=\"text-align: center; margin-top: 16px;\">\n      <a-button @click=\"loadMore\" :loading=\"loadingMore\">加载更多</a-button>\n    </div>\n  </a-list>\n</template>\n\n<script>\nimport { ArticleListContent } from '@/components'\nimport IconText from '@/views/list/search/components/IconText'\n\nexport default {\n  name: 'Article',\n  components: {\n    IconText,\n    ArticleListContent\n  },\n  data () {\n    return {\n      loading: true,\n      loadingMore: false,\n      data: []\n    }\n  },\n  mounted () {\n    this.getList()\n  },\n  methods: {\n    getList () {\n      this.$http.get('/list/article').then(res => {\n        console.log('res', res)\n        this.data = res.result\n        this.loading = false\n      })\n    },\n    loadMore () {\n      this.loadingMore = true\n      this.$http.get('/list/article').then(res => {\n        this.data = this.data.concat(res.result)\n      }).finally(() => {\n        this.loadingMore = false\n      })\n    }\n  }\n}\n</script>\n\n<style scoped>\n\n</style>\n"
  },
  {
    "path": "src/views/account/center/page/Project.vue",
    "content": "<template>\n  <div class=\"ant-pro-pages-account-projects-cardList\">\n    <a-list :loading=\"loading\" :data-source=\"data\" :grid=\"{ gutter: 24, xxl: 3, xl: 2, lg: 2, md: 2, sm: 2, xs: 1 }\">\n      <a-list-item slot=\"renderItem\" slot-scope=\"item\">\n        <a-card class=\"ant-pro-pages-account-projects-card\" hoverable>\n          <img slot=\"cover\" :src=\"item.cover\" :alt=\"item.title\" />\n          <a-card-meta :title=\"item.title\">\n            <template slot=\"description\">\n              <ellipsis :length=\"50\">{{ item.description }}</ellipsis>\n            </template>\n          </a-card-meta>\n          <div class=\"cardItemContent\">\n            <span>{{ item.updatedAt | fromNow }}</span>\n            <div class=\"avatarList\">\n              <avatar-list size=\"small\">\n                <avatar-list-item\n                  v-for=\"(member, i) in item.members\"\n                  :key=\"`${item.id}-avatar-${i}`\"\n                  :src=\"member.avatar\"\n                  :tips=\"member.name\"\n                />\n              </avatar-list>\n            </div>\n          </div>\n        </a-card>\n      </a-list-item>\n    </a-list>\n  </div>\n</template>\n\n<script>\nimport moment from 'moment'\nimport { TagSelect, StandardFormRow, Ellipsis, AvatarList } from '@/components'\nconst TagSelectOption = TagSelect.Option\nconst AvatarListItem = AvatarList.Item\n\nexport default {\n  name: 'Project',\n  components: {\n    AvatarList,\n    AvatarListItem,\n    Ellipsis,\n    TagSelect,\n    TagSelectOption,\n    StandardFormRow\n  },\n  data () {\n    return {\n      data: [],\n      form: this.$form.createForm(this),\n      loading: true\n    }\n  },\n  filters: {\n    fromNow (date) {\n      return moment(date).fromNow()\n    }\n  },\n  mounted () {\n    this.getList()\n  },\n  methods: {\n    handleChange (value) {\n      console.log(`selected ${value}`)\n    },\n    getList () {\n      this.$http.get('/list/article', { params: { count: 8 } }).then(res => {\n        console.log('res', res)\n        this.data = res.result\n        this.loading = false\n      })\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n  .ant-pro-pages-account-projects-cardList {\n    margin-top: 24px;\n\n    :deep(.ant-card-meta-title) {\n      margin-bottom: 4px;\n    }\n\n    :deep(.ant-card-meta-description) {\n      height: 44px;\n      overflow: hidden;\n      line-height: 22px;\n    }\n\n    .cardItemContent {\n      display: flex;\n      height: 20px;\n      margin-top: 16px;\n      margin-bottom: -4px;\n      line-height: 20px;\n\n      > span {\n        flex: 1 1;\n        color: rgba(0,0,0,.45);\n        font-size: 12px;\n      }\n\n      :deep(.ant-pro-avatar-list) {\n        flex: 0 1 auto;\n      }\n    }\n  }\n</style>\n"
  },
  {
    "path": "src/views/account/center/page/index.js",
    "content": "import AppPage from './App'\nimport ArticlePage from './Article'\nimport ProjectPage from './Project'\n\nexport { AppPage, ArticlePage, ProjectPage }\n"
  },
  {
    "path": "src/views/account/settings/AvatarModal.vue",
    "content": "<template>\n\n  <a-modal\n    title=\"修改头像\"\n    :visible=\"visible\"\n    :maskClosable=\"false\"\n    :confirmLoading=\"confirmLoading\"\n    :width=\"800\"\n    :footer=\"null\"\n    @cancel=\"cancelHandel\">\n    <a-row>\n      <a-col :xs=\"24\" :md=\"12\" :style=\"{height: '350px'}\">\n        <vue-cropper\n          ref=\"cropper\"\n          :img=\"options.img\"\n          :info=\"true\"\n          :autoCrop=\"options.autoCrop\"\n          :autoCropWidth=\"options.autoCropWidth\"\n          :autoCropHeight=\"options.autoCropHeight\"\n          :fixedBox=\"options.fixedBox\"\n          @realTime=\"realTime\"\n        >\n        </vue-cropper>\n      </a-col>\n      <a-col :xs=\"24\" :md=\"12\" :style=\"{height: '350px'}\">\n        <div class=\"avatar-upload-preview\">\n          <img :src=\"previews.url\" :style=\"previews.img\"/>\n        </div>\n      </a-col>\n    </a-row>\n    <br>\n    <a-row>\n      <a-col :lg=\"2\" :md=\"2\">\n        <a-upload name=\"file\" :beforeUpload=\"beforeUpload\" :showUploadList=\"false\">\n          <a-button icon=\"upload\">选择图片</a-button>\n        </a-upload>\n      </a-col>\n      <a-col :lg=\"{span: 1, offset: 2}\" :md=\"2\">\n        <a-button icon=\"plus\" @click=\"changeScale(1)\"/>\n      </a-col>\n      <a-col :lg=\"{span: 1, offset: 1}\" :md=\"2\">\n        <a-button icon=\"minus\" @click=\"changeScale(-1)\"/>\n      </a-col>\n      <a-col :lg=\"{span: 1, offset: 1}\" :md=\"2\">\n        <a-button icon=\"undo\" @click=\"rotateLeft\"/>\n      </a-col>\n      <a-col :lg=\"{span: 1, offset: 1}\" :md=\"2\">\n        <a-button icon=\"redo\" @click=\"rotateRight\"/>\n      </a-col>\n      <a-col :lg=\"{span: 2, offset: 6}\" :md=\"2\">\n        <a-button type=\"primary\" @click=\"finish('blob')\">保存</a-button>\n      </a-col>\n    </a-row>\n  </a-modal>\n\n</template>\n<script>\nexport default {\n  data () {\n    return {\n      visible: false,\n      id: null,\n      confirmLoading: false,\n      fileList: [],\n      uploading: false,\n      options: {\n        // img: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',\n        img: '',\n        autoCrop: true,\n        autoCropWidth: 200,\n        autoCropHeight: 200,\n        fixedBox: true\n      },\n      previews: {}\n    }\n  },\n  methods: {\n    edit (id) {\n      this.visible = true\n      this.id = id\n      /* 获取原始头像 */\n    },\n    close () {\n      this.id = null\n      this.visible = false\n    },\n    cancelHandel () {\n      this.close()\n    },\n    changeScale (num) {\n      num = num || 1\n      this.$refs.cropper.changeScale(num)\n    },\n    rotateLeft () {\n      this.$refs.cropper.rotateLeft()\n    },\n    rotateRight () {\n      this.$refs.cropper.rotateRight()\n    },\n    beforeUpload (file) {\n      const reader = new FileReader()\n      // 把Array Buffer转化为blob 如果是base64不需要\n      // 转化为base64\n      reader.readAsDataURL(file)\n      reader.onload = () => {\n        this.options.img = reader.result\n      }\n      // 转化为blob\n      // reader.readAsArrayBuffer(file)\n\n      return false\n    },\n\n    // 上传图片（点击上传按钮）\n    finish (type) {\n      console.log('finish')\n      const _this = this\n      const formData = new FormData()\n      // 输出\n      if (type === 'blob') {\n        this.$refs.cropper.getCropBlob((data) => {\n          const img = window.URL.createObjectURL(data)\n          this.model = true\n          this.modelSrc = img\n          formData.append('file', data, this.fileName)\n          this.$http.post('https://www.mocky.io/v2/5cc8019d300000980a055e76', formData, { contentType: false, processData: false, headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })\n            .then((response) => {\n              console.log('upload response:', response)\n              // var res = response.data\n              // if (response.status === 'done') {\n              //   _this.imgFile = ''\n              //   _this.headImg = res.realPathList[0] // 完整路径\n              //   _this.uploadImgRelaPath = res.relaPathList[0] // 非完整路径\n              //   _this.$message.success('上传成功')\n              //   this.visible = false\n              // }\n              _this.$message.success('上传成功')\n              _this.$emit('ok', response.url)\n              _this.visible = false\n            })\n        })\n      } else {\n        this.$refs.cropper.getCropData((data) => {\n          this.model = true\n          this.modelSrc = data\n        })\n      }\n    },\n    okHandel () {\n      const vm = this\n\n      vm.confirmLoading = true\n      setTimeout(() => {\n        vm.confirmLoading = false\n        vm.close()\n        vm.$message.success('上传头像成功')\n      }, 2000)\n    },\n\n    realTime (data) {\n      this.previews = data\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n\n  .avatar-upload-preview {\n    position: absolute;\n    top: 50%;\n    transform: translate(50%, -50%);\n    width: 180px;\n    height: 180px;\n    border-radius: 50%;\n    box-shadow: 0 0 4px #ccc;\n    overflow: hidden;\n\n    img {\n      width: 100%;\n      height: 100%;\n    }\n  }\n</style>\n"
  },
  {
    "path": "src/views/account/settings/BasicSetting.vue",
    "content": "<template>\n  <div class=\"account-settings-info-view\">\n    <a-row :gutter=\"16\" type=\"flex\" justify=\"center\">\n      <a-col :order=\"isMobile ? 2 : 1\" :md=\"24\" :lg=\"16\">\n\n        <a-form layout=\"vertical\">\n          <a-form-item\n            :label=\"$t('account.settings.basic.nickname')\"\n          >\n            <a-input :placeholder=\"$t('account.settings.basic.nickname-message')\" />\n          </a-form-item>\n          <a-form-item\n            :label=\"$t('account.settings.basic.profile')\"\n          >\n            <a-textarea rows=\"4\" :placeholder=\"$t('account.settings.basic.profile-message')\"/>\n          </a-form-item>\n\n          <a-form-item\n            :label=\"$t('account.settings.basic.email')\"\n            :required=\"false\"\n          >\n            <a-input placeholder=\"example@ant.design\"/>\n          </a-form-item>\n\n          <a-form-item>\n            <a-button type=\"primary\">{{ $t('account.settings.basic.update') }}</a-button>\n          </a-form-item>\n        </a-form>\n\n      </a-col>\n      <a-col :order=\"1\" :md=\"24\" :lg=\"8\" :style=\"{ minHeight: '180px' }\">\n        <div class=\"ant-upload-preview\" @click=\"$refs.modal.edit(1)\" >\n          <a-icon type=\"cloud-upload-o\" class=\"upload-icon\"/>\n          <div class=\"mask\">\n            <a-icon type=\"plus\" />\n          </div>\n          <img :src=\"option.img\"/>\n        </div>\n      </a-col>\n\n    </a-row>\n\n    <avatar-modal ref=\"modal\" @ok=\"setavatar\"/>\n\n  </div>\n</template>\n\n<script>\nimport AvatarModal from './AvatarModal'\nimport { baseMixin } from '@/store/app-mixin'\n\nexport default {\n  mixins: [baseMixin],\n  components: {\n    AvatarModal\n  },\n  data () {\n    return {\n      // cropper\n      preview: {},\n      option: {\n        img: '/avatar2.jpg',\n        info: true,\n        size: 1,\n        outputType: 'jpeg',\n        canScale: false,\n        autoCrop: true,\n        // 只有自动截图开启 宽度高度才生效\n        autoCropWidth: 180,\n        autoCropHeight: 180,\n        fixedBox: true,\n        // 开启宽度和高度比例\n        fixed: true,\n        fixedNumber: [1, 1]\n      }\n    }\n  },\n  methods: {\n    setavatar (url) {\n      this.option.img = url\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n\n  .avatar-upload-wrapper {\n    height: 200px;\n    width: 100%;\n  }\n\n  .ant-upload-preview {\n    position: relative;\n    margin: 0 auto;\n    width: 100%;\n    max-width: 180px;\n    border-radius: 50%;\n    box-shadow: 0 0 4px #ccc;\n\n    .upload-icon {\n      position: absolute;\n      top: 0;\n      right: 10px;\n      font-size: 1.4rem;\n      padding: 0.5rem;\n      background: rgba(222, 221, 221, 0.7);\n      border-radius: 50%;\n      border: 1px solid rgba(0, 0, 0, 0.2);\n    }\n    .mask {\n      opacity: 0;\n      position: absolute;\n      background: rgba(0,0,0,0.4);\n      cursor: pointer;\n      transition: opacity 0.4s;\n\n      &:hover {\n        opacity: 1;\n      }\n\n      i {\n        font-size: 2rem;\n        position: absolute;\n        top: 50%;\n        left: 50%;\n        margin-left: -1rem;\n        margin-top: -1rem;\n        color: #d6d6d6;\n      }\n    }\n\n    img, .mask {\n      width: 100%;\n      max-width: 180px;\n      height: 100%;\n      border-radius: 50%;\n      overflow: hidden;\n    }\n  }\n</style>\n"
  },
  {
    "path": "src/views/account/settings/Binding.vue",
    "content": "<template>\n  <a-list\n    itemLayout=\"horizontal\"\n    :dataSource=\"data\"\n  >\n\n  </a-list>\n</template>\n\n<script>\nexport default {\n  data () {\n    return {\n      data: []\n    }\n  },\n  methods: {\n\n  }\n}\n</script>\n\n<style scoped>\n\n</style>\n"
  },
  {
    "path": "src/views/account/settings/Custom.vue",
    "content": "<template>\n  <a-list itemLayout=\"horizontal\">\n    <a-list-item>\n      <a-list-item-meta>\n        <template v-slot:title>\n          <a>风格配色</a>\n        </template>\n        <template v-slot:description>\n          <span>\n            整体风格配色设置\n          </span>\n        </template>\n      </a-list-item-meta>\n      <template v-slot:actions>\n        <a-switch checkedChildren=\"暗色\" unCheckedChildren=\"白色\" :defaultChecked=\"navTheme === 'dark' && true || false\" @change=\"onChange\" />\n      </template>\n    </a-list-item>\n    <a-list-item>\n      <a-list-item-meta>\n        <template v-slot:title>\n          <a>主题色</a>\n        </template>\n        <template v-slot:description>\n          <span>\n            页面风格配色： <a>{{ colorFilter(primaryColor) }}</a>\n          </span>\n        </template>\n      </a-list-item-meta>\n    </a-list-item>\n  </a-list>\n</template>\n<script>\nimport { colorList } from '@/components/SettingDrawer/settingConfig'\nimport { baseMixin } from '@/store/app-mixin'\nimport { NAV_THEME, TOGGLE_NAV_THEME } from '@/store/mutation-types'\n\nconst themeMap = {\n  'dark': '暗色',\n  'light': '白色'\n}\n\nexport default {\n  mixins: [baseMixin],\n  data () {\n    return {\n    }\n  },\n  filters: {\n    themeFilter (theme) {\n      return themeMap[theme]\n    }\n  },\n  methods: {\n    colorFilter (color) {\n      const c = colorList.find(o => o.color === color)\n      return c && c.key\n    },\n\n    onChange (checked) {\n      if (checked) {\n        this.$store.commit(TOGGLE_NAV_THEME, NAV_THEME.DARK)\n      } else {\n        this.$store.commit(TOGGLE_NAV_THEME, NAV_THEME.LIGHT)\n      }\n    }\n  }\n}\n</script>\n"
  },
  {
    "path": "src/views/account/settings/Index.vue",
    "content": "<template>\n  <div class=\"page-header-index-wide\">\n    <a-card :bordered=\"false\" :bodyStyle=\"{ padding: '16px 0', height: '100%' }\" :style=\"{ height: '100%' }\">\n      <div class=\"account-settings-info-main\" :class=\"{ 'mobile': isMobile }\">\n        <div class=\"account-settings-info-left\">\n          <a-menu\n            :mode=\"isMobile ? 'horizontal' : 'inline'\"\n            :style=\"{ border: '0', width: isMobile ? '560px' : 'auto'}\"\n            :selectedKeys=\"selectedKeys\"\n            type=\"inner\"\n            @openChange=\"onOpenChange\"\n          >\n            <a-menu-item key=\"/account/settings/basic\">\n              <router-link :to=\"{ name: 'BasicSettings' }\">\n                {{ $t('account.settings.menuMap.basic') }}\n              </router-link>\n            </a-menu-item>\n            <a-menu-item key=\"/account/settings/security\">\n              <router-link :to=\"{ name: 'SecuritySettings' }\">\n                {{ $t('account.settings.menuMap.security') }}\n              </router-link>\n            </a-menu-item>\n            <a-menu-item key=\"/account/settings/custom\">\n              <router-link :to=\"{ name: 'CustomSettings' }\">\n                {{ $t('account.settings.menuMap.custom') }}\n              </router-link>\n            </a-menu-item>\n            <a-menu-item key=\"/account/settings/binding\">\n              <router-link :to=\"{ name: 'BindingSettings' }\">\n                {{ $t('account.settings.menuMap.binding') }}\n              </router-link>\n            </a-menu-item>\n            <a-menu-item key=\"/account/settings/notification\">\n              <router-link :to=\"{ name: 'NotificationSettings' }\">\n                {{ $t('account.settings.menuMap.notification') }}\n              </router-link>\n            </a-menu-item>\n          </a-menu>\n        </div>\n        <div class=\"account-settings-info-right\">\n          <div class=\"account-settings-info-title\">\n            <span>{{ $t($route.meta.title) }}</span>\n          </div>\n          <route-view></route-view>\n        </div>\n      </div>\n    </a-card>\n  </div>\n</template>\n\n<script>\nimport { RouteView } from '@/layouts'\nimport { baseMixin } from '@/store/app-mixin'\n\nexport default {\n  components: {\n    RouteView\n  },\n  mixins: [baseMixin],\n  data () {\n    return {\n      // horizontal  inline\n      mode: 'inline',\n\n      openKeys: [],\n      selectedKeys: [],\n\n      // cropper\n      preview: {},\n      option: {\n        img: '/avatar2.jpg',\n        info: true,\n        size: 1,\n        outputType: 'jpeg',\n        canScale: false,\n        autoCrop: true,\n        // 只有自动截图开启 宽度高度才生效\n        autoCropWidth: 180,\n        autoCropHeight: 180,\n        fixedBox: true,\n        // 开启宽度和高度比例\n        fixed: true,\n        fixedNumber: [1, 1]\n      },\n\n      pageTitle: ''\n    }\n  },\n  mounted () {\n    this.updateMenu()\n  },\n  methods: {\n    onOpenChange (openKeys) {\n      this.openKeys = openKeys\n    },\n    updateMenu () {\n      const routes = this.$route.matched.concat()\n      this.selectedKeys = [ routes.pop().path ]\n    }\n  },\n  watch: {\n    '$route' (val) {\n      this.updateMenu()\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n  .account-settings-info-main {\n    width: 100%;\n    display: flex;\n    height: 100%;\n    overflow: auto;\n\n    &.mobile {\n      display: block;\n\n      .account-settings-info-left {\n        border-right: unset;\n        border-bottom: 1px solid #e8e8e8;\n        width: 100%;\n        height: 50px;\n        overflow-x: auto;\n        overflow-y: scroll;\n      }\n      .account-settings-info-right {\n        padding: 20px 40px;\n      }\n    }\n\n    .account-settings-info-left {\n      border-right: 1px solid #e8e8e8;\n      width: 224px;\n    }\n\n    .account-settings-info-right {\n      flex: 1 1;\n      padding: 8px 40px;\n\n      .account-settings-info-title {\n        color: rgba(0,0,0,.85);\n        font-size: 20px;\n        font-weight: 500;\n        line-height: 28px;\n        margin-bottom: 12px;\n      }\n      .account-settings-info-view {\n        padding-top: 12px;\n      }\n    }\n  }\n\n</style>\n"
  },
  {
    "path": "src/views/account/settings/Notification.vue",
    "content": "<template>\n  <a-list\n    itemLayout=\"horizontal\"\n    :dataSource=\"data\"\n  >\n\n  </a-list>\n</template>\n\n<script>\nexport default {\n  data () {\n    return {\n      data: []\n    }\n  },\n  methods: {\n\n  }\n}\n</script>\n\n<style scoped>\n\n</style>\n"
  },
  {
    "path": "src/views/account/settings/Security.vue",
    "content": "<template>\n  <a-list\n    itemLayout=\"horizontal\"\n    :dataSource=\"data\"\n  >\n    <a-list-item slot=\"renderItem\" slot-scope=\"item, index\" :key=\"index\">\n      <a-list-item-meta>\n        <a slot=\"title\">{{ item.title }}</a>\n        <span slot=\"description\">\n          <span class=\"security-list-description\">{{ item.description }}</span>\n          <span v-if=\"item.value\"> : </span>\n          <span class=\"security-list-value\">{{ item.value }}</span>\n        </span>\n      </a-list-item-meta>\n      <template v-if=\"item.actions\">\n        <a slot=\"actions\" @click=\"item.actions.callback\">{{ item.actions.title }}</a>\n      </template>\n\n    </a-list-item>\n  </a-list>\n</template>\n\n<script>\nexport default {\ncomputed: {\n    data () {\n        return [\n        { title: this.$t('account.settings.security.password'), description: this.$t('account.settings.security.password-description'), value: '强', actions: { title: this.$t('account.settings.security.modify'), callback: () => { this.$message.info('This is a normal message') } } },\n        { title: this.$t('account.settings.security.phone'), description: this.$t('account.settings.security.phone-description'), value: '138****8293', actions: { title: this.$t('account.settings.security.modify'), callback: () => { this.$message.success('This is a message of success') } } },\n        { title: this.$t('account.settings.security.question'), description: this.$t('account.settings.security.question-description'), value: '', actions: { title: this.$t('account.settings.security.set'), callback: () => { this.$message.error('This is a message of error') } } },\n        { title: this.$t('account.settings.security.email'), description: this.$t('account.settings.security.email-description'), value: 'ant***sign.com', actions: { title: this.$t('account.settings.security.modify'), callback: () => { this.$message.warning('This is message of warning') } } },\n        { title: this.$t('account.settings.security.mfa'), description: this.$t('account.settings.security.mfa-description'), value: '', actions: { title: this.$t('account.settings.security.bind'), callback: () => { this.$message.info('This is a normal message') } } }\n      ]\n    }\n  }\n}\n</script>\n\n<style scoped>\n\n</style>\n"
  },
  {
    "path": "src/views/dashboard/Analysis.vue",
    "content": "<template>\n  <div>\n    <a-row :gutter=\"24\">\n      <a-col :sm=\"24\" :md=\"12\" :xl=\"6\" :style=\"{ marginBottom: '24px' }\">\n        <chart-card :loading=\"loading\" :title=\"$t('dashboard.analysis.total-sales')\" total=\"￥126,560\">\n          <a-tooltip :title=\"$t('dashboard.analysis.introduce')\" slot=\"action\">\n            <a-icon type=\"info-circle-o\" />\n          </a-tooltip>\n          <div>\n            <trend flag=\"up\" style=\"margin-right: 16px;\">\n              <span slot=\"term\">{{ $t('dashboard.analysis.week') }}</span>\n              12%\n            </trend>\n            <trend flag=\"down\">\n              <span slot=\"term\">{{ $t('dashboard.analysis.day') }}</span>\n              11%\n            </trend>\n          </div>\n          <template slot=\"footer\">{{ $t('dashboard.analysis.day-sales') }}<span>￥ 234.56</span></template>\n        </chart-card>\n      </a-col>\n      <a-col :sm=\"24\" :md=\"12\" :xl=\"6\" :style=\"{ marginBottom: '24px' }\">\n        <chart-card :loading=\"loading\" :title=\"$t('dashboard.analysis.visits')\" :total=\"8846 | NumberFormat\">\n          <a-tooltip :title=\"$t('dashboard.analysis.introduce')\" slot=\"action\">\n            <a-icon type=\"info-circle-o\" />\n          </a-tooltip>\n          <div>\n            <mini-area />\n          </div>\n          <template slot=\"footer\">{{ $t('dashboard.analysis.day-visits') }}<span> {{ '1234' | NumberFormat }}</span></template>\n        </chart-card>\n      </a-col>\n      <a-col :sm=\"24\" :md=\"12\" :xl=\"6\" :style=\"{ marginBottom: '24px' }\">\n        <chart-card :loading=\"loading\" :title=\"$t('dashboard.analysis.payments')\" :total=\"6560 | NumberFormat\">\n          <a-tooltip :title=\"$t('dashboard.analysis.introduce')\" slot=\"action\">\n            <a-icon type=\"info-circle-o\" />\n          </a-tooltip>\n          <div>\n            <mini-bar />\n          </div>\n          <template slot=\"footer\">{{ $t('dashboard.analysis.conversion-rate') }} <span>60%</span></template>\n        </chart-card>\n      </a-col>\n      <a-col :sm=\"24\" :md=\"12\" :xl=\"6\" :style=\"{ marginBottom: '24px' }\">\n        <chart-card :loading=\"loading\" :title=\"$t('dashboard.analysis.operational-effect')\" total=\"78%\">\n          <a-tooltip :title=\"$t('dashboard.analysis.introduce')\" slot=\"action\">\n            <a-icon type=\"info-circle-o\" />\n          </a-tooltip>\n          <div>\n            <mini-progress color=\"rgb(19, 194, 194)\" :target=\"80\" :percentage=\"78\" height=\"8px\" />\n          </div>\n          <template slot=\"footer\">\n            <trend flag=\"down\" style=\"margin-right: 16px;\">\n              <span slot=\"term\">{{ $t('dashboard.analysis.week') }}</span>\n              12%\n            </trend>\n            <trend flag=\"up\">\n              <span slot=\"term\">{{ $t('dashboard.analysis.day') }}</span>\n              80%\n            </trend>\n          </template>\n        </chart-card>\n      </a-col>\n    </a-row>\n\n    <a-card :loading=\"loading\" :bordered=\"false\" :body-style=\"{padding: '0'}\">\n      <div class=\"salesCard\">\n        <a-tabs default-active-key=\"1\" size=\"large\" :tab-bar-style=\"{marginBottom: '24px', paddingLeft: '16px'}\">\n          <div class=\"extra-wrapper\" slot=\"tabBarExtraContent\">\n            <div class=\"extra-item\">\n              <a>{{ $t('dashboard.analysis.all-day') }}</a>\n              <a>{{ $t('dashboard.analysis.all-week') }}</a>\n              <a>{{ $t('dashboard.analysis.all-month') }}</a>\n              <a>{{ $t('dashboard.analysis.all-year') }}</a>\n            </div>\n            <a-range-picker :style=\"{width: '256px'}\" />\n          </div>\n          <a-tab-pane loading=\"true\" :tab=\"$t('dashboard.analysis.sales')\" key=\"1\">\n            <a-row>\n              <a-col :xl=\"16\" :lg=\"12\" :md=\"12\" :sm=\"24\" :xs=\"24\">\n                <bar :data=\"barData\" :title=\"$t('dashboard.analysis.sales-trend')\" />\n              </a-col>\n              <a-col :xl=\"8\" :lg=\"12\" :md=\"12\" :sm=\"24\" :xs=\"24\">\n                <rank-list :title=\"$t('dashboard.analysis.sales-ranking')\" :list=\"rankList\"/>\n              </a-col>\n            </a-row>\n          </a-tab-pane>\n          <a-tab-pane :tab=\"$t('dashboard.analysis.visits')\" key=\"2\">\n            <a-row>\n              <a-col :xl=\"16\" :lg=\"12\" :md=\"12\" :sm=\"24\" :xs=\"24\">\n                <bar :data=\"barData2\" :title=\"$t('dashboard.analysis.visits-trend')\" />\n              </a-col>\n              <a-col :xl=\"8\" :lg=\"12\" :md=\"12\" :sm=\"24\" :xs=\"24\">\n                <rank-list :title=\"$t('dashboard.analysis.visits-ranking')\" :list=\"rankList\"/>\n              </a-col>\n            </a-row>\n          </a-tab-pane>\n        </a-tabs>\n      </div>\n    </a-card>\n\n    <div class=\"antd-pro-pages-dashboard-analysis-twoColLayout\" :class=\"!isMobile && 'desktop'\">\n      <a-row :gutter=\"24\" type=\"flex\" :style=\"{ marginTop: '24px' }\">\n        <a-col :xl=\"12\" :lg=\"24\" :md=\"24\" :sm=\"24\" :xs=\"24\">\n          <a-card :loading=\"loading\" :bordered=\"false\" :title=\"$t('dashboard.analysis.online-top-search')\" :style=\"{ height: '100%' }\">\n            <a-dropdown :trigger=\"['click']\" placement=\"bottomLeft\" slot=\"extra\">\n              <a class=\"ant-dropdown-link\" href=\"#\">\n                <a-icon type=\"ellipsis\" />\n              </a>\n              <a-menu slot=\"overlay\">\n                <a-menu-item>\n                  <a href=\"javascript:;\">{{ $t('dashboard.analysis.dropdown-option-one') }}</a>\n                </a-menu-item>\n                <a-menu-item>\n                  <a href=\"javascript:;\">{{ $t('dashboard.analysis.dropdown-option-two') }}</a>\n                </a-menu-item>\n              </a-menu>\n            </a-dropdown>\n            <a-row :gutter=\"68\">\n              <a-col :xs=\"24\" :sm=\"12\" :style=\"{ marginBottom: ' 24px'}\">\n                <number-info :total=\"12321\" :sub-total=\"17.1\">\n                  <span slot=\"subtitle\">\n                    <span>{{ $t('dashboard.analysis.search-users') }}</span>\n                    <a-tooltip :title=\"$t('dashboard.analysis.introduce')\" slot=\"action\">\n                      <a-icon type=\"info-circle-o\" :style=\"{ marginLeft: '8px' }\" />\n                    </a-tooltip>\n                  </span>\n                </number-info>\n                <!-- miniChart -->\n                <div>\n                  <mini-smooth-area :style=\"{ height: '45px' }\" :dataSource=\"searchUserData\" :scale=\"searchUserScale\" />\n                </div>\n              </a-col>\n              <a-col :xs=\"24\" :sm=\"12\" :style=\"{ marginBottom: ' 24px'}\">\n                <number-info :total=\"2.7\" :sub-total=\"26.2\" status=\"down\">\n                  <span slot=\"subtitle\">\n                    <span>{{ $t('dashboard.analysis.per-capita-search') }}</span>\n                    <a-tooltip :title=\"$t('dashboard.analysis.introduce')\" slot=\"action\">\n                      <a-icon type=\"info-circle-o\" :style=\"{ marginLeft: '8px' }\" />\n                    </a-tooltip>\n                  </span>\n                </number-info>\n                <!-- miniChart -->\n                <div>\n                  <mini-smooth-area :style=\"{ height: '45px' }\" :dataSource=\"searchUserData\" :scale=\"searchUserScale\" />\n                </div>\n              </a-col>\n            </a-row>\n            <div class=\"ant-table-wrapper\">\n              <a-table\n                row-key=\"index\"\n                size=\"small\"\n                :columns=\"searchTableColumns\"\n                :dataSource=\"searchData\"\n                :pagination=\"{ pageSize: 5 }\"\n              >\n                <span slot=\"range\" slot-scope=\"text, record\">\n                  <trend :flag=\"record.status === 0 ? 'up' : 'down'\">\n                    {{ text }}%\n                  </trend>\n                </span>\n              </a-table>\n            </div>\n          </a-card>\n        </a-col>\n        <a-col :xl=\"12\" :lg=\"24\" :md=\"24\" :sm=\"24\" :xs=\"24\">\n          <a-card class=\"antd-pro-pages-dashboard-analysis-salesCard\" :loading=\"loading\" :bordered=\"false\" :title=\"$t('dashboard.analysis.the-proportion-of-sales')\" :style=\"{ height: '100%' }\">\n            <div slot=\"extra\" style=\"height: inherit;\">\n              <!-- style=\"bottom: 12px;display: inline-block;\" -->\n              <span class=\"dashboard-analysis-iconGroup\">\n                <a-dropdown :trigger=\"['click']\" placement=\"bottomLeft\">\n                  <a-icon type=\"ellipsis\" class=\"ant-dropdown-link\" />\n                  <a-menu slot=\"overlay\">\n                    <a-menu-item>\n                      <a href=\"javascript:;\">{{ $t('dashboard.analysis.dropdown-option-one') }}</a>\n                    </a-menu-item>\n                    <a-menu-item>\n                      <a href=\"javascript:;\">{{ $t('dashboard.analysis.dropdown-option-two') }}</a>\n                    </a-menu-item>\n                  </a-menu>\n                </a-dropdown>\n              </span>\n              <div class=\"analysis-salesTypeRadio\">\n                <a-radio-group defaultValue=\"a\">\n                  <a-radio-button value=\"a\">{{ $t('dashboard.analysis.channel.all') }}</a-radio-button>\n                  <a-radio-button value=\"b\">{{ $t('dashboard.analysis.channel.online') }}</a-radio-button>\n                  <a-radio-button value=\"c\">{{ $t('dashboard.analysis.channel.stores') }}</a-radio-button>\n                </a-radio-group>\n              </div>\n\n            </div>\n            <h4>{{ $t('dashboard.analysis.sales') }}</h4>\n            <div>\n              <!-- style=\"width: calc(100% - 240px);\" -->\n              <div>\n                <v-chart :force-fit=\"true\" :height=\"405\" :data=\"pieData\" :scale=\"pieScale\">\n                  <v-tooltip :showTitle=\"false\" dataKey=\"item*percent\" />\n                  <v-axis />\n                  <!-- position=\"right\" :offsetX=\"-140\" -->\n                  <v-legend dataKey=\"item\"/>\n                  <v-pie position=\"percent\" color=\"item\" :vStyle=\"pieStyle\" />\n                  <v-coord type=\"theta\" :radius=\"0.75\" :innerRadius=\"0.6\" />\n                </v-chart>\n              </div>\n\n            </div>\n          </a-card>\n        </a-col>\n      </a-row>\n    </div>\n  </div>\n</template>\n\n<script>\nimport moment from 'moment'\nimport {\n  ChartCard,\n  MiniArea,\n  MiniBar,\n  MiniProgress,\n  RankList,\n  Bar,\n  Trend,\n  NumberInfo,\n  MiniSmoothArea\n} from '@/components'\nimport { baseMixin } from '@/store/app-mixin'\n\nconst barData = []\nconst barData2 = []\nfor (let i = 0; i < 12; i += 1) {\n  barData.push({\n    x: `${i + 1}月`,\n    y: Math.floor(Math.random() * 1000) + 200\n  })\n  barData2.push({\n    x: `${i + 1}月`,\n    y: Math.floor(Math.random() * 1000) + 200\n  })\n}\n\nconst rankList = []\nfor (let i = 0; i < 7; i++) {\n  rankList.push({\n    name: '白鹭岛 ' + (i + 1) + ' 号店',\n    total: 1234.56 - i * 100\n  })\n}\n\nconst searchUserData = []\nfor (let i = 0; i < 7; i++) {\n  searchUserData.push({\n    x: moment().add(i, 'days').format('YYYY-MM-DD'),\n    y: Math.ceil(Math.random() * 10)\n  })\n}\nconst searchUserScale = [\n  {\n    dataKey: 'x',\n    alias: '时间'\n  },\n  {\n    dataKey: 'y',\n    alias: '用户数',\n    min: 0,\n    max: 10\n  }]\n\nconst searchData = []\nfor (let i = 0; i < 50; i += 1) {\n  searchData.push({\n    index: i + 1,\n    keyword: `搜索关键词-${i}`,\n    count: Math.floor(Math.random() * 1000),\n    range: Math.floor(Math.random() * 100),\n    status: Math.floor((Math.random() * 10) % 2)\n  })\n}\n\nconst DataSet = require('@antv/data-set')\n\nconst sourceData = [\n  { item: '家用电器', count: 32.2 },\n  { item: '食用酒水', count: 21 },\n  { item: '个护健康', count: 17 },\n  { item: '服饰箱包', count: 13 },\n  { item: '母婴产品', count: 9 },\n  { item: '其他', count: 7.8 }\n]\n\nconst pieScale = [{\n  dataKey: 'percent',\n  min: 0,\n  formatter: '.0%'\n}]\n\nconst dv = new DataSet.View().source(sourceData)\ndv.transform({\n  type: 'percent',\n  field: 'count',\n  dimension: 'item',\n  as: 'percent'\n})\nconst pieData = dv.rows\n\nexport default {\n  name: 'Analysis',\n  mixins: [baseMixin],\n  components: {\n    ChartCard,\n    MiniArea,\n    MiniBar,\n    MiniProgress,\n    RankList,\n    Bar,\n    Trend,\n    NumberInfo,\n    MiniSmoothArea\n  },\n  data () {\n    return {\n      loading: true,\n      rankList,\n\n      // 搜索用户数\n      searchUserData,\n      searchUserScale,\n      searchData,\n\n      barData,\n      barData2,\n\n      //\n      pieScale,\n      pieData,\n      sourceData,\n      pieStyle: {\n        stroke: '#fff',\n        lineWidth: 1\n      }\n    }\n  },\n  computed: {\n    searchTableColumns () {\n        return [\n      {\n        dataIndex: 'index',\n        title: this.$t('dashboard.analysis.table.rank'),\n        width: 90\n      },\n      {\n        dataIndex: 'keyword',\n        title: this.$t('dashboard.analysis.table.search-keyword')\n      },\n      {\n        dataIndex: 'count',\n        title: this.$t('dashboard.analysis.table.users')\n      },\n      {\n        dataIndex: 'range',\n        title: this.$t('dashboard.analysis.table.weekly-range'),\n        align: 'right',\n        sorter: (a, b) => a.range - b.range,\n        scopedSlots: { customRender: 'range' }\n      }\n      ]\n    }\n  },\n  created () {\n    setTimeout(() => {\n      this.loading = !this.loading\n    }, 1000)\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n  .extra-wrapper {\n    line-height: 55px;\n    padding-right: 24px;\n\n    .extra-item {\n      display: inline-block;\n      margin-right: 24px;\n\n      a {\n        margin-left: 24px;\n      }\n    }\n  }\n\n  .antd-pro-pages-dashboard-analysis-twoColLayout {\n    position: relative;\n    display: flex;\n    display: block;\n    flex-flow: row wrap;\n  }\n\n  .antd-pro-pages-dashboard-analysis-salesCard {\n    height: calc(100% - 24px);\n    :deep(.ant-card-head) {\n      position: relative;\n    }\n  }\n\n  .dashboard-analysis-iconGroup {\n    i {\n      margin-left: 16px;\n      color: rgba(0,0,0,.45);\n      cursor: pointer;\n      transition: color .32s;\n      color: black;\n    }\n  }\n  .analysis-salesTypeRadio {\n    position: absolute;\n    right: 54px;\n    bottom: 12px;\n  }\n</style>\n"
  },
  {
    "path": "src/views/dashboard/Monitor.vue",
    "content": "<template>\n  <div>\n    Monitor\n  </div>\n</template>\n\n<script>\nexport default {\n  name: 'Monitor'\n}\n</script>\n\n<style scoped>\n\n</style>\n"
  },
  {
    "path": "src/views/dashboard/TestWork.vue",
    "content": "<template>\n  <div>\n    <h2>本页面内容均为测试功能，暂不提供稳定性保证</h2>\n    <a-divider />\n    <div class=\"multi-tab-test\">\n      <h4>多标签组件测试功能</h4>\n      <a-button @click=\"handleCloseCurrentTab\" style=\"margin-right: 16px;\">关闭当前页</a-button>\n      <a-button @click=\"handleOpenTab\" style=\"margin-right: 16px;\">打开 任务列表</a-button>\n      <a-popconfirm :visible=\"visible\" @confirm=\"confirm\" @cancel=\"cancel\" okText=\"确定\" cancelText=\"取消\">\n        <template v-slot:title>\n          <div>\n            <a-form :form=\"form\" layout=\"inline\">\n              <a-form-item label=\"自定义名称\">\n                <a-input v-decorator=\"['tabName', {rules: [{required: true, message: '请输入新的 Tab 名称'}]}]\"/>\n              </a-form-item>\n            </a-form>\n          </div>\n        </template>\n        <a-button @click=\"() => visible = !visible\" style=\"margin-right: 16px;\">修改当前 Tab 名称</a-button>\n      </a-popconfirm>\n\n      <a-popconfirm :visible=\"visible2\" @confirm=\"confirm2\" @cancel=\"() => visible2 = false\" okText=\"确定\" cancelText=\"取消\">\n        <template v-slot:title>\n          <div>\n            <p>页面 KEY 是由页面的路由 <code>path</code> 决定的</p>\n            <p>如果要修改某一个页面标题，该页面必须已经被打开在 Tab 栏</p>\n            <p>后期可以考虑优化到编程式 Tab 栏，就可以没有这种限制</p>\n            <a-form :form=\"form2\" layout=\"inline\">\n              <a-form-item label=\"页面KEY\">\n                <a-input v-decorator=\"['tabKey', { initialValue: '/dashboard/workplace' }]\" />\n              </a-form-item>\n              <a-form-item label=\"自定义名称\">\n                <a-input v-decorator=\"['tabName', {rules: [{required: true, message: '请输入新的 Tab 名称'}]}]\"/>\n              </a-form-item>\n            </a-form>\n          </div>\n        </template>\n        <a-button @click=\"() => visible2 = !visible2\">修改某一个 Tab 名称</a-button>\n      </a-popconfirm>\n    </div>\n    <a-divider />\n    <div class=\"page-loading-test\">\n      <h4>全局遮罩测试</h4>\n      <a-button @click=\"handleOpenLoading\" style=\"margin-right: 16px;\">打开遮罩(5s 自动关闭)</a-button>\n      <a-button @click=\"handleOpenLoadingCustomTip\">打开遮罩(自定义提示语)</a-button>\n    </div>\n  </div>\n</template>\n\n<script>\nexport default {\n  name: 'TestWork',\n  data () {\n    return {\n      visible: false,\n      visible2: false\n    }\n  },\n  created () {\n    this.form = this.$form.createForm(this)\n    this.form2 = this.$form.createForm(this)\n  },\n  methods: {\n    handleCloseCurrentTab () {\n      this.$multiTab.closeCurrentPage() // or this.$multiTab.close()\n    },\n    handleOpenTab () {\n      this.$multiTab.open('/features/task')\n    },\n\n    handleOpenLoading () {\n      this.$nextTick(function () {\n        console.log('this', this)\n        console.log('this.$refs.tInput', this.$refs.tInput)\n      })\n      this.$loading.show()\n      setTimeout(() => {\n        this.$loading.hide()\n      }, 5000)\n    },\n    handleOpenLoadingCustomTip () {\n      this.$loading.show({ tip: '自定义提示语' })\n      setTimeout(() => {\n        this.$loading.hide()\n      }, 5000)\n    },\n\n    // confirm\n    confirm (e) {\n      e.stopPropagation()\n      const { path } = this.$route\n      this.form.validateFields((err, values) => {\n        if (!err) {\n          this.$multiTab.rename(path, values.tabName)\n          this.visible = false\n        }\n      })\n    },\n    cancel () {\n      this.visible = false\n    },\n    confirm2 (e) {\n      e.stopPropagation()\n      this.form2.validateFields((err, values) => {\n        if (!err) {\n          this.$multiTab.rename(values.tabKey, values.tabName)\n          this.visible2 = false\n        }\n      })\n    }\n  }\n}\n</script>\n\n<style scoped>\n\n</style>\n"
  },
  {
    "path": "src/views/dashboard/Workplace.less",
    "content": "@import '~ant-design-vue/es/style/themes/default.less';\n\n.text-overflow() {\n  overflow: hidden;\n  text-overflow: ellipsis;\n  word-break: break-all;\n  white-space: nowrap;\n}\n\n// mixins for clearfix\n// ------------------------\n.clearfix() {\n  zoom: 1;\n\n  &::before,\n  &::after {\n    display: table;\n    content: ' ';\n  }\n\n  &::after {\n    height: 0;\n    clear: both;\n    font-size: 0;\n    visibility: hidden;\n  }\n}\n\n.page-header-content {\n  display: flex;\n\n  .avatar {\n    flex: 0 1 72px;\n\n    & > span {\n      display: block;\n      width: 72px;\n      height: 72px;\n      border-radius: 72px;\n    }\n  }\n\n  .content {\n    position: relative;\n    top: 4px;\n    margin-left: 24px;\n    line-height: 22px;\n    color: @text-color-secondary;\n    flex: 1 1 auto;\n\n    .content-title {\n      margin-bottom: 12px;\n      font-size: 20px;\n      font-weight: 500;\n      line-height: 28px;\n      color: @heading-color;\n    }\n  }\n}\n\n.extra-content {\n  .clearfix();\n\n  float: right;\n  white-space: nowrap;\n\n  .stat-item {\n    position: relative;\n    display: inline-block;\n    padding: 0 32px;\n\n    > p:first-child {\n      margin-bottom: 4px;\n      font-size: @font-size-base;\n      line-height: 22px;\n      color: @text-color-secondary;\n    }\n\n    > p {\n      margin: 0;\n      font-size: 30px;\n      line-height: 38px;\n      color: @heading-color;\n\n      > span {\n        font-size: 20px;\n        color: @text-color-secondary;\n      }\n    }\n\n    &::after {\n      position: absolute;\n      top: 8px;\n      right: 0;\n      width: 1px;\n      height: 40px;\n      background-color: @border-color-split;\n      content: '';\n    }\n\n    &:last-child {\n      padding-right: 0;\n\n      &::after {\n        display: none;\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/views/dashboard/Workplace.vue",
    "content": "<template>\n  <page-header-wrapper>\n    <template v-slot:content>\n      <div class=\"page-header-content\">\n        <div class=\"avatar\">\n          <a-avatar size=\"large\" :src=\"currentUser.avatar\" />\n        </div>\n        <div class=\"content\">\n          <div class=\"content-title\">\n            {{ timeFix }}，{{ user.name }}<span class=\"welcome-text\">，{{ welcome }}</span>\n          </div>\n          <div>前端工程师 | 蚂蚁金服 - 某某某事业群 - VUE平台</div>\n        </div>\n      </div>\n    </template>\n    <template v-slot:extraContent>\n      <div class=\"extra-content\">\n        <div class=\"stat-item\">\n          <a-statistic title=\"项目数\" :value=\"56\" />\n        </div>\n        <div class=\"stat-item\">\n          <a-statistic title=\"团队内排名\" :value=\"8\" suffix=\"/ 24\" />\n        </div>\n        <div class=\"stat-item\">\n          <a-statistic title=\"项目访问\" :value=\"2223\" />\n        </div>\n      </div>\n    </template>\n\n    <div>\n      <a-row :gutter=\"24\">\n        <a-col :xl=\"16\" :lg=\"24\" :md=\"24\" :sm=\"24\" :xs=\"24\">\n          <a-card\n            class=\"project-list\"\n            :loading=\"loading\"\n            style=\"margin-bottom: 24px;\"\n            :bordered=\"false\"\n            title=\"进行中的项目\"\n            :body-style=\"{ padding: 0 }\"\n          >\n            <a slot=\"extra\">全部项目</a>\n            <div>\n              <a-card-grid class=\"project-card-grid\" :key=\"i\" v-for=\"(item, i) in projects\">\n                <a-card :bordered=\"false\" :body-style=\"{ padding: 0 }\">\n                  <a-card-meta>\n                    <div slot=\"title\" class=\"card-title\">\n                      <a-avatar size=\"small\" :src=\"item.cover\" />\n                      <a>{{ item.title }}</a>\n                    </div>\n                    <div slot=\"description\" class=\"card-description\">\n                      {{ item.description }}\n                    </div>\n                  </a-card-meta>\n                  <div class=\"project-item\">\n                    <a href=\"/#/\">科学搬砖组</a>\n                    <span class=\"datetime\">9小时前</span>\n                  </div>\n                </a-card>\n              </a-card-grid>\n            </div>\n          </a-card>\n\n          <a-card :loading=\"loading\" title=\"动态\" :bordered=\"false\">\n            <a-list>\n              <a-list-item :key=\"index\" v-for=\"(item, index) in activities\">\n                <a-list-item-meta>\n                  <a-avatar slot=\"avatar\" size=\"small\" :src=\"item.user.avatar\" />\n                  <div slot=\"title\">\n                    <span>{{ item.user.nickname }}</span\n                    >&nbsp; 在&nbsp;<a href=\"#\">{{ item.project.name }}</a\n                    >&nbsp; <span>{{ item.project.action }}</span\n                    >&nbsp;\n                    <a href=\"#\">{{ item.project.event }}</a>\n                  </div>\n                  <div slot=\"description\">{{ item.time }}</div>\n                </a-list-item-meta>\n              </a-list-item>\n            </a-list>\n          </a-card>\n        </a-col>\n        <a-col\n          style=\"padding: 0 12px\"\n          :xl=\"8\"\n          :lg=\"24\"\n          :md=\"24\"\n          :sm=\"24\"\n          :xs=\"24\">\n          <a-card\n            title=\"快速开始 / 便捷导航\"\n            style=\"margin-bottom: 24px\"\n            :bordered=\"false\"\n            :body-style=\"{ padding: 0 }\"\n          >\n            <div class=\"item-group\">\n              <a>操作一</a>\n              <a>操作二</a>\n              <a>操作三</a>\n              <a>操作四</a>\n              <a>操作五</a>\n              <a>操作六</a>\n              <a-button size=\"small\" type=\"primary\" ghost icon=\"plus\">添加</a-button>\n            </div>\n          </a-card>\n          <a-card\n            title=\"XX 指数\"\n            style=\"margin-bottom: 24px\"\n            :loading=\"radarLoading\"\n            :bordered=\"false\"\n            :body-style=\"{ padding: 0 }\"\n          >\n            <div style=\"min-height: 400px;\">\n              <!-- :scale=\"scale\" :axis1Opts=\"axis1Opts\" :axis2Opts=\"axis2Opts\"  -->\n              <radar :data=\"radarData\" />\n            </div>\n          </a-card>\n          <a-card :loading=\"loading\" title=\"团队\" :bordered=\"false\">\n            <div class=\"members\">\n              <a-row>\n                <a-col :span=\"12\" v-for=\"(item, index) in teams\" :key=\"index\">\n                  <a>\n                    <a-avatar size=\"small\" :src=\"item.avatar\" />\n                    <span class=\"member\">{{ item.name }}</span>\n                  </a>\n                </a-col>\n              </a-row>\n            </div>\n          </a-card>\n        </a-col>\n      </a-row>\n    </div>\n  </page-header-wrapper>\n</template>\n\n<script>\nimport { timeFix } from '@/utils/util'\nimport { mapState } from 'vuex'\nimport { PageHeaderWrapper } from '@ant-design-vue/pro-layout'\nimport { Radar } from '@/components'\n\nimport { getRoleList, getServiceList } from '@/api/manage'\n\nconst DataSet = require('@antv/data-set')\n\nexport default {\n  name: 'Workplace',\n  components: {\n    PageHeaderWrapper,\n    Radar\n  },\n  data () {\n    return {\n      timeFix: timeFix(),\n      avatar: '',\n      user: {},\n\n      projects: [],\n      loading: true,\n      radarLoading: true,\n      activities: [],\n      teams: [],\n\n      // data\n      axis1Opts: {\n        dataKey: 'item',\n        line: null,\n        tickLine: null,\n        grid: {\n          lineStyle: {\n            lineDash: null\n          },\n          hideFirstLine: false\n        }\n      },\n      axis2Opts: {\n        dataKey: 'score',\n        line: null,\n        tickLine: null,\n        grid: {\n          type: 'polygon',\n          lineStyle: {\n            lineDash: null\n          }\n        }\n      },\n      scale: [\n        {\n          dataKey: 'score',\n          min: 0,\n          max: 80\n        }\n      ],\n      axisData: [\n        { item: '引用', a: 70, b: 30, c: 40 },\n        { item: '口碑', a: 60, b: 70, c: 40 },\n        { item: '产量', a: 50, b: 60, c: 40 },\n        { item: '贡献', a: 40, b: 50, c: 40 },\n        { item: '热度', a: 60, b: 70, c: 40 },\n        { item: '引用', a: 70, b: 50, c: 40 }\n      ],\n      radarData: []\n    }\n  },\n  computed: {\n    ...mapState({\n      nickname: state => state.user.nickname,\n      welcome: state => state.user.welcome\n    }),\n    currentUser () {\n      return {\n        name: 'Serati Ma',\n        avatar: 'https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png'\n      }\n    },\n    userInfo () {\n      return this.$store.getters.userInfo\n    }\n  },\n  created () {\n    this.user = this.userInfo\n    this.avatar = this.userInfo.avatar\n\n    getRoleList().then(res => {\n      // console.log('workplace -> call getRoleList()', res)\n    })\n\n    getServiceList().then(res => {\n      // console.log('workplace -> call getServiceList()', res)\n    })\n  },\n  mounted () {\n    this.getProjects()\n    this.getActivity()\n    this.getTeams()\n    this.initRadar()\n  },\n  methods: {\n    getProjects () {\n      this.$http.get('/list/search/projects').then(res => {\n        this.projects = res.result && res.result.data\n        this.loading = false\n      })\n    },\n    getActivity () {\n      this.$http.get('/workplace/activity').then(res => {\n        this.activities = res.result\n      })\n    },\n    getTeams () {\n      this.$http.get('/workplace/teams').then(res => {\n        this.teams = res.result\n      })\n    },\n    initRadar () {\n      this.radarLoading = true\n\n      this.$http.get('/workplace/radar').then(res => {\n        const dv = new DataSet.View().source(res.result)\n        dv.transform({\n          type: 'fold',\n          fields: ['个人', '团队', '部门'],\n          key: 'user',\n          value: 'score'\n        })\n\n        this.radarData = dv.rows\n        this.radarLoading = false\n      })\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n@import './Workplace.less';\n\n.project-list {\n  .card-title {\n    font-size: 0;\n\n    a {\n      color: rgba(0, 0, 0, 0.85);\n      margin-left: 12px;\n      line-height: 24px;\n      height: 24px;\n      display: inline-block;\n      vertical-align: top;\n      font-size: 14px;\n\n      &:hover {\n        color: #1890ff;\n      }\n    }\n  }\n\n  .card-description {\n    color: rgba(0, 0, 0, 0.45);\n    height: 44px;\n    line-height: 22px;\n    overflow: hidden;\n  }\n\n  .project-item {\n    display: flex;\n    margin-top: 8px;\n    overflow: hidden;\n    font-size: 12px;\n    height: 20px;\n    line-height: 20px;\n\n    a {\n      color: rgba(0, 0, 0, 0.45);\n      display: inline-block;\n      flex: 1 1 0;\n\n      &:hover {\n        color: #1890ff;\n      }\n    }\n\n    .datetime {\n      color: rgba(0, 0, 0, 0.25);\n      flex: 0 0 auto;\n      float: right;\n    }\n  }\n\n  .ant-card-meta-description {\n    color: rgba(0, 0, 0, 0.45);\n    height: 44px;\n    line-height: 22px;\n    overflow: hidden;\n  }\n}\n\n.item-group {\n  padding: 20px 0 8px 24px;\n  font-size: 0;\n\n  a {\n    color: rgba(0, 0, 0, 0.65);\n    display: inline-block;\n    font-size: 14px;\n    margin-bottom: 13px;\n    width: 25%;\n  }\n}\n\n.members {\n  a {\n    display: block;\n    margin: 12px 0;\n    line-height: 24px;\n    height: 24px;\n\n    .member {\n      font-size: 14px;\n      color: rgba(0, 0, 0, 0.65);\n      line-height: 24px;\n      max-width: 100px;\n      vertical-align: top;\n      margin-left: 12px;\n      transition: all 0.3s;\n      display: inline-block;\n    }\n\n    &:hover {\n      span {\n        color: #1890ff;\n      }\n    }\n  }\n}\n\n.mobile {\n  .project-list {\n    .project-card-grid {\n      width: 100%;\n    }\n  }\n\n  .more-info {\n    border: 0;\n    padding-top: 16px;\n    margin: 16px 0 16px;\n  }\n\n  .headerContent .title .welcome-text {\n    display: none;\n  }\n}\n</style>\n"
  },
  {
    "path": "src/views/exception/403.vue",
    "content": "<template>\n  <a-result status=\"403\" title=\"403\" sub-title=\"Sorry, you don't have access to this page.\">\n    <template #extra>\n      <a-button type=\"primary\" @click=\"toHome\">\n        Back Home\n      </a-button>\n    </template>\n  </a-result>\n</template>\n\n<script>\nexport default {\n  name: 'Exception403',\n  methods: {\n    toHome () {\n      this.$router.push({ path: '/' })\n    }\n  }\n}\n</script>\n"
  },
  {
    "path": "src/views/exception/404.vue",
    "content": "<template>\n  <a-result status=\"404\" title=\"404\" sub-title=\"Sorry, the page you visited does not exist.\">\n    <template #extra>\n      <a-button type=\"primary\" @click=\"toHome\">\n        Back Home\n      </a-button>\n    </template>\n  </a-result>\n</template>\n\n<script>\nexport default {\n  name: 'Exception404',\n  methods: {\n    toHome () {\n      this.$router.push({ path: '/' })\n    }\n  }\n}\n</script>\n"
  },
  {
    "path": "src/views/exception/500.vue",
    "content": "<template>\n  <a-result status=\"500\" title=\"500\" sub-title=\"Sorry, the server is reporting an error.\">\n    <template #extra>\n      <a-button type=\"primary\" @click=\"toHome\">\n        Back Home\n      </a-button>\n    </template>\n  </a-result>\n</template>\n\n<script>\n  export default {\n    name: 'Exception500',\n    methods: {\n      toHome () {\n        this.$router.push({ path: '/' })\n      }\n    }\n  }\n</script>\n"
  },
  {
    "path": "src/views/form/advancedForm/AdvancedForm.vue",
    "content": "<template>\n  <page-header-wrapper content=\"高级表单常见于一次性输入和提交大批量数据的场景\">\n    <a-card class=\"card\" title=\"仓库管理\" :bordered=\"false\">\n      <repository-form ref=\"repository\" :showSubmit=\"false\" />\n    </a-card>\n    <a-card class=\"card\" title=\"任务管理\" :bordered=\"false\">\n      <task-form ref=\"task\" :showSubmit=\"false\" />\n    </a-card>\n\n    <!-- table -->\n    <a-card>\n      <a-table\n        :columns=\"columns\"\n        :dataSource=\"data\"\n        :pagination=\"false\"\n        :loading=\"memberLoading\"\n      >\n        <template v-for=\"(col, i) in ['name', 'workId', 'department']\" :slot=\"col\" slot-scope=\"text, record\">\n          <a-input\n            :key=\"col\"\n            v-if=\"record.editable\"\n            style=\"margin: -5px 0\"\n            :value=\"text\"\n            :placeholder=\"columns[i].title\"\n            @change=\"e => handleChange(e.target.value, record.key, col)\"\n          />\n          <template v-else>{{ text }}</template>\n        </template>\n        <template slot=\"operation\" slot-scope=\"text, record\">\n          <template v-if=\"record.editable\">\n            <span v-if=\"record.isNew\">\n              <a @click=\"saveRow(record)\">添加</a>\n              <a-divider type=\"vertical\" />\n              <a-popconfirm title=\"是否要删除此行？\" @confirm=\"remove(record.key)\">\n                <a>删除</a>\n              </a-popconfirm>\n            </span>\n            <span v-else>\n              <a @click=\"saveRow(record)\">保存</a>\n              <a-divider type=\"vertical\" />\n              <a @click=\"cancel(record.key)\">取消</a>\n            </span>\n          </template>\n          <span v-else>\n            <a @click=\"toggle(record.key)\">编辑</a>\n            <a-divider type=\"vertical\" />\n            <a-popconfirm title=\"是否要删除此行？\" @confirm=\"remove(record.key)\">\n              <a>删除</a>\n            </a-popconfirm>\n          </span>\n        </template>\n      </a-table>\n      <a-button style=\"width: 100%; margin-top: 16px; margin-bottom: 8px\" type=\"dashed\" icon=\"plus\" @click=\"newMember\">新增成员</a-button>\n    </a-card>\n\n    <!-- fixed footer toolbar -->\n    <footer-tool-bar :is-mobile=\"isMobile\" :collapsed=\"sideCollapsed\">\n      <span class=\"popover-wrapper\">\n        <a-popover title=\"表单校验信息\" overlayClassName=\"antd-pro-pages-forms-style-errorPopover\" trigger=\"click\" :getPopupContainer=\"trigger => trigger.parentNode\">\n          <template slot=\"content\">\n            <li v-for=\"item in errors\" :key=\"item.key\" @click=\"scrollToField(item.key)\" class=\"antd-pro-pages-forms-style-errorListItem\">\n              <a-icon type=\"cross-circle-o\" class=\"antd-pro-pages-forms-style-errorIcon\" />\n              <div class=\"\">{{ item.message }}</div>\n              <div class=\"antd-pro-pages-forms-style-errorField\">{{ item.fieldLabel }}</div>\n            </li>\n          </template>\n          <span class=\"antd-pro-pages-forms-style-errorIcon\" v-if=\"errors.length > 0\">\n            <a-icon type=\"exclamation-circle\" />{{ errors.length }}\n          </span>\n        </a-popover>\n      </span>\n      <a-button type=\"primary\" @click=\"validate\" :loading=\"loading\">提交</a-button>\n    </footer-tool-bar>\n  </page-header-wrapper>\n</template>\n\n<script>\nimport RepositoryForm from './RepositoryForm'\nimport TaskForm from './TaskForm'\nimport FooterToolBar from '@/components/FooterToolbar'\nimport { baseMixin } from '@/store/app-mixin'\n\nconst fieldLabels = {\n  name: '仓库名',\n  url: '仓库域名',\n  owner: '仓库管理员',\n  approver: '审批人',\n  dateRange: '生效日期',\n  type: '仓库类型',\n  name2: '任务名',\n  url2: '任务描述',\n  owner2: '执行人',\n  approver2: '责任人',\n  dateRange2: '生效日期',\n  type2: '任务类型'\n}\n\nexport default {\n  name: 'AdvancedForm',\n  mixins: [baseMixin],\n  components: {\n    FooterToolBar,\n    RepositoryForm,\n    TaskForm\n  },\n  data () {\n    return {\n      loading: false,\n      memberLoading: false,\n\n      // table\n      columns: [\n        {\n          title: '成员姓名',\n          dataIndex: 'name',\n          key: 'name',\n          width: '20%',\n          scopedSlots: { customRender: 'name' }\n        },\n        {\n          title: '工号',\n          dataIndex: 'workId',\n          key: 'workId',\n          width: '20%',\n          scopedSlots: { customRender: 'workId' }\n        },\n        {\n          title: '所属部门',\n          dataIndex: 'department',\n          key: 'department',\n          width: '40%',\n          scopedSlots: { customRender: 'department' }\n        },\n        {\n          title: '操作',\n          key: 'action',\n          scopedSlots: { customRender: 'operation' }\n        }\n      ],\n      data: [\n        {\n          key: '1',\n          name: '小明',\n          workId: '001',\n          editable: false,\n          department: '行政部'\n        },\n        {\n          key: '2',\n          name: '李莉',\n          workId: '002',\n          editable: false,\n          department: 'IT部'\n        },\n        {\n          key: '3',\n          name: '王小帅',\n          workId: '003',\n          editable: false,\n          department: '财务部'\n        }\n      ],\n\n      errors: []\n    }\n  },\n  methods: {\n    handleSubmit (e) {\n      e.preventDefault()\n    },\n    newMember () {\n      const length = this.data.length\n      this.data.push({\n        key: length === 0 ? '1' : (parseInt(this.data[length - 1].key) + 1).toString(),\n        name: '',\n        workId: '',\n        department: '',\n        editable: true,\n        isNew: true\n      })\n    },\n    remove (key) {\n      const newData = this.data.filter(item => item.key !== key)\n      this.data = newData\n    },\n    saveRow (record) {\n      this.memberLoading = true\n      const { key, name, workId, department } = record\n      if (!name || !workId || !department) {\n        this.memberLoading = false\n        this.$message.error('请填写完整成员信息。')\n        return\n      }\n      // 模拟网络请求、卡顿 800ms\n      new Promise((resolve) => {\n        setTimeout(() => {\n          resolve({ loop: false })\n        }, 800)\n      }).then(() => {\n        const target = this.data.find(item => item.key === key)\n        target.editable = false\n        target.isNew = false\n        this.memberLoading = false\n      })\n    },\n    toggle (key) {\n      const target = this.data.find(item => item.key === key)\n      target._originalData = { ...target }\n      target.editable = !target.editable\n    },\n    getRowByKey (key, newData) {\n      const data = this.data\n      return (newData || data).find(item => item.key === key)\n    },\n    cancel (key) {\n      const target = this.data.find(item => item.key === key)\n      Object.keys(target).forEach(key => { target[key] = target._originalData[key] })\n      target._originalData = undefined\n    },\n    handleChange (value, key, column) {\n      const newData = [...this.data]\n      const target = newData.find(item => key === item.key)\n      if (target) {\n        target[column] = value\n        this.data = newData\n      }\n    },\n\n    // 最终全页面提交\n    validate () {\n      const { $refs: { repository, task }, $notification } = this\n      const repositoryForm = new Promise((resolve, reject) => {\n        repository.form.validateFields((err, values) => {\n          if (err) {\n            reject(err)\n            return\n          }\n          resolve(values)\n        })\n      })\n      const taskForm = new Promise((resolve, reject) => {\n        task.form.validateFields((err, values) => {\n          if (err) {\n            reject(err)\n            return\n          }\n          resolve(values)\n        })\n      })\n\n      // clean this.errors\n      this.errors = []\n      Promise.all([repositoryForm, taskForm]).then(values => {\n        $notification['error']({\n          message: 'Received values of form:',\n          description: JSON.stringify(values)\n        })\n      }).catch(() => {\n        const errors = Object.assign({}, repository.form.getFieldsError(), task.form.getFieldsError())\n        const tmp = { ...errors }\n        this.errorList(tmp)\n      })\n    },\n    errorList (errors) {\n      if (!errors || errors.length === 0) {\n        return\n      }\n      this.errors = Object.keys(errors)\n        .filter(key => errors[key])\n        .map(key => ({\n          key: key,\n          message: errors[key][0],\n          fieldLabel: fieldLabels[key]\n        }))\n    },\n    scrollToField (fieldKey) {\n      const labelNode = document.querySelector(`label[for=\"${fieldKey}\"]`)\n      if (labelNode) {\n        labelNode.scrollIntoView(true)\n      }\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n  .card{\n    margin-bottom: 24px;\n  }\n  .popover-wrapper {\n    :deep(.antd-pro-pages-forms-style-errorPopover .ant-popover-inner-content) {\n      min-width: 256px;\n      max-height: 290px;\n      padding: 0;\n      overflow: auto;\n    }\n  }\n  .antd-pro-pages-forms-style-errorIcon {\n    user-select: none;\n    margin-right: 24px;\n    color: #f5222d;\n    cursor: pointer;\n    i {\n          margin-right: 4px;\n    }\n  }\n  .antd-pro-pages-forms-style-errorListItem {\n    padding: 8px 16px;\n    list-style: none;\n    border-bottom: 1px solid #e8e8e8;\n    cursor: pointer;\n    transition: all .3s;\n\n    &:hover {\n      background: #e6f7ff;\n    }\n    .antd-pro-pages-forms-style-errorIcon {\n      float: left;\n      margin-top: 4px;\n      margin-right: 12px;\n      padding-bottom: 22px;\n      color: #f5222d;\n    }\n    .antd-pro-pages-forms-style-errorField {\n      margin-top: 2px;\n      color: rgba(0,0,0,.45);\n      font-size: 12px;\n    }\n  }\n</style>\n"
  },
  {
    "path": "src/views/form/advancedForm/RepositoryForm.vue",
    "content": "<template>\n  <a-form @submit=\"handleSubmit\" :form=\"form\" class=\"form\">\n    <a-row class=\"form-row\" :gutter=\"16\">\n      <a-col :lg=\"6\" :md=\"12\" :sm=\"24\">\n        <a-form-item label=\"仓库名\">\n          <a-input\n            placeholder=\"请输入仓库名称\"\n            v-decorator=\"[\n              'name',\n              {rules: [{ required: true, message: '请输入仓库名称', whitespace: true}]}\n            ]\" />\n        </a-form-item>\n      </a-col>\n      <a-col :xl=\"{span: 7, offset: 1}\" :lg=\"{span: 8}\" :md=\"{span: 12}\" :sm=\"24\">\n        <a-form-item\n          label=\"仓库域名\">\n          <a-input\n            addonBefore=\"http://\"\n            addonAfter=\".com\"\n            placeholder=\"请输入\"\n            v-decorator=\"[\n              'url',\n              {rules: [{ required: true, message: '请输入仓库域名', whitespace: true}, {validator: validate}]}\n            ]\" />\n        </a-form-item>\n      </a-col>\n      <a-col :xl=\"{span: 9, offset: 1}\" :lg=\"{span: 10}\" :md=\"{span: 24}\" :sm=\"24\">\n        <a-form-item\n          label=\"仓库管理员\">\n          <a-select placeholder=\"请选择管理员\" v-decorator=\"[ 'owner', {rules: [{ required: true, message: '请选择管理员'}]} ]\">\n            <a-select-option value=\"王同学\">王同学</a-select-option>\n            <a-select-option value=\"李同学\">李同学</a-select-option>\n            <a-select-option value=\"黄同学\">黄同学</a-select-option>\n          </a-select>\n        </a-form-item>\n      </a-col>\n    </a-row>\n    <a-row class=\"form-row\" :gutter=\"16\">\n      <a-col :lg=\"6\" :md=\"12\" :sm=\"24\">\n        <a-form-item\n          label=\"审批人\">\n          <a-select placeholder=\"请选择审批员\" v-decorator=\"[ 'approver', {rules: [{ required: true, message: '请选择审批员'}]} ]\">\n            <a-select-option value=\"王晓丽\">王晓丽</a-select-option>\n            <a-select-option value=\"李军\">李军</a-select-option>\n          </a-select>\n        </a-form-item>\n      </a-col>\n      <a-col :xl=\"{span: 7, offset: 1}\" :lg=\"{span: 8}\" :md=\"{span: 12}\" :sm=\"24\">\n        <a-form-item\n          label=\"生效日期\">\n          <a-range-picker\n            style=\"width: 100%\"\n            v-decorator=\"[\n              'dateRange',\n              {rules: [{ required: true, message: '请选择生效日期'}]}\n            ]\" />\n        </a-form-item>\n      </a-col>\n      <a-col :xl=\"{span: 9, offset: 1}\" :lg=\"{span: 10}\" :md=\"{span: 24}\" :sm=\"24\">\n        <a-form-item\n          label=\"仓库类型\">\n          <a-select\n            placeholder=\"请选择仓库类型\"\n            v-decorator=\"[\n              'type',\n              {rules: [{ required: true, message: '请选择仓库类型'}]}\n            ]\" >\n            <a-select-option value=\"公开\">公开</a-select-option>\n            <a-select-option value=\"私密\">私密</a-select-option>\n          </a-select>\n        </a-form-item>\n      </a-col>\n    </a-row>\n    <a-form-item v-if=\"showSubmit\">\n      <a-button htmlType=\"submit\" >Submit</a-button>\n    </a-form-item>\n  </a-form>\n</template>\n\n<script>\nexport default {\n  name: 'RepositoryForm',\n  props: {\n    showSubmit: {\n      type: Boolean,\n      default: false\n    }\n  },\n  data () {\n    return {\n      form: this.$form.createForm(this)\n    }\n  },\n  methods: {\n    handleSubmit (e) {\n      e.preventDefault()\n      this.form.validateFields((err, values) => {\n        if (!err) {\n          this.$notification['error']({\n            message: 'Received values of form:',\n            description: values\n          })\n        }\n      })\n    },\n    validate (rule, value, callback) {\n      const regex = /^user-(.*)$/\n      if (!regex.test(value)) {\n        callback(new Error('需要以 user- 开头'))\n      }\n      callback()\n    }\n  }\n}\n</script>\n\n<style scoped>\n\n</style>\n"
  },
  {
    "path": "src/views/form/advancedForm/TaskForm.vue",
    "content": "<template>\n  <a-form @submit=\"handleSubmit\" :form=\"form\" class=\"form\">\n    <a-row class=\"form-row\" :gutter=\"16\">\n      <a-col :lg=\"6\" :md=\"12\" :sm=\"24\">\n        <a-form-item\n          label=\"任务名\">\n          <a-input placeholder=\"请输入任务名称\" v-decorator=\"[ 'name2', {rules: [{ required: true, message: '请输入任务名称', whitespace: true}]} ]\" />\n        </a-form-item>\n      </a-col>\n      <a-col :xl=\"{span: 7, offset: 1}\" :lg=\"{span: 8}\" :md=\"{span: 12}\" :sm=\"24\">\n        <a-form-item\n          label=\"任务描述\">\n          <a-input placeholder=\"请输入任务描述\" v-decorator=\"[ 'url2', {rules: [{ required: true, message: '请输入任务描述', whitespace: true}]} ]\" />\n        </a-form-item>\n      </a-col>\n      <a-col :xl=\"{span: 9, offset: 1}\" :lg=\"{span: 10}\" :md=\"{span: 24}\" :sm=\"24\">\n        <a-form-item\n          label=\"执行人\">\n          <a-select\n            placeholder=\"请选择执行人\"\n            v-decorator=\"[\n              'owner2',\n              {rules: [{ required: true, message: '请选择执行人'}]}\n            ]\" >\n            <a-select-option value=\"黄丽丽\">黄丽丽</a-select-option>\n            <a-select-option value=\"李大刀\">李大刀</a-select-option>\n          </a-select>\n        </a-form-item>\n      </a-col>\n    </a-row>\n    <a-row class=\"form-row\" :gutter=\"16\">\n      <a-col :lg=\"6\" :md=\"12\" :sm=\"24\">\n        <a-form-item\n          label=\"责任人\">\n          <a-select\n            placeholder=\"请选择责任人\"\n            v-decorator=\"[\n              'approver2',\n              {rules: [{ required: true, message: '请选择责任人'}]}\n            ]\" >\n            <a-select-option value=\"王伟\">王伟</a-select-option>\n            <a-select-option value=\"李红军\">李红军</a-select-option>\n          </a-select>\n        </a-form-item>\n      </a-col>\n      <a-col :xl=\"{span: 7, offset: 1}\" :lg=\"{span: 8}\" :md=\"{span: 12}\" :sm=\"24\">\n        <a-form-item\n          label=\"提醒时间\">\n          <a-time-picker\n            style=\"width: 100%\"\n            v-decorator=\"[\n              'dateRange2',\n              {rules: [{ required: true, message: '请选择提醒时间'}]}\n            ]\" />\n        </a-form-item>\n      </a-col>\n      <a-col :xl=\"{span: 9, offset: 1}\" :lg=\"{span: 10}\" :md=\"{span: 24}\" :sm=\"24\">\n        <a-form-item\n          label=\"任务类型\">\n          <a-select\n            placeholder=\"请选择任务类型\"\n            v-decorator=\"[ 'type2', {rules: [{ required: true, message: '请选择任务类型'}]} ]\" >\n            <a-select-option value=\"定时执行\">定时执行</a-select-option>\n            <a-select-option value=\"周期执行\">周期执行</a-select-option>\n          </a-select>\n        </a-form-item>\n      </a-col>\n    </a-row>\n    <a-form-item v-if=\"showSubmit\">\n      <a-button htmlType=\"submit\" >Submit</a-button>\n    </a-form-item>\n  </a-form>\n</template>\n\n<script>\nexport default {\n  name: 'TaskForm',\n  props: {\n    showSubmit: {\n      type: Boolean,\n      default: false\n    }\n  },\n  data () {\n    return {\n      form: this.$form.createForm(this)\n    }\n  },\n  methods: {\n    handleSubmit (e) {\n      e.preventDefault()\n      this.form.validateFields((err, values) => {\n        if (!err) {\n          this.$notification['error']({\n            message: 'Received values of form:',\n            description: values\n          })\n        }\n      })\n    }\n  }\n}\n</script>\n\n<style scoped>\n\n</style>\n"
  },
  {
    "path": "src/views/form/basicForm/index.vue",
    "content": "<template>\n  <!-- hidden PageHeaderWrapper title demo -->\n  <page-header-wrapper :title=\"false\" :content=\"$t('form.basic-form.basic.description')\">\n    <a-card :body-style=\"{padding: '24px 32px'}\" :bordered=\"false\">\n      <a-form @submit=\"handleSubmit\" :form=\"form\">\n        <a-form-item\n          :label=\"$t('form.basic-form.title.label')\"\n          :labelCol=\"{lg: {span: 7}, sm: {span: 7}}\"\n          :wrapperCol=\"{lg: {span: 10}, sm: {span: 17} }\">\n          <a-input\n            v-decorator=\"[\n              'name',\n              {rules: [{ required: true, message: $t('form.basic-form.title.required') }]}\n            ]\"\n            name=\"name\"\n            :placeholder=\"$t('form.basic-form.title.placeholder')\" />\n        </a-form-item>\n        <a-form-item\n          :label=\"$t('form.basic-form.date.label')\"\n          :labelCol=\"{lg: {span: 7}, sm: {span: 7}}\"\n          :wrapperCol=\"{lg: {span: 10}, sm: {span: 17} }\">\n          <a-range-picker\n            name=\"buildTime\"\n            style=\"width: 100%\"\n            v-decorator=\"[\n              'buildTime',\n              {rules: [{ required: true, message: $t('form.basic-form.date.required') }]}\n            ]\" />\n        </a-form-item>\n        <a-form-item\n          :label=\"$t('form.basic-form.goal.label')\"\n          :labelCol=\"{lg: {span: 7}, sm: {span: 7}}\"\n          :wrapperCol=\"{lg: {span: 10}, sm: {span: 17} }\">\n          <a-textarea\n            rows=\"4\"\n            :placeholder=\"$t('form.basic-form.goal.placeholder')\"\n            v-decorator=\"[\n              'description',\n              {rules: [{ required: true, message: $t('form.basic-form.goal.required') }]}\n            ]\" />\n        </a-form-item>\n        <a-form-item\n          :label=\"$t('form.basic-form.standard.label')\"\n          :labelCol=\"{lg: {span: 7}, sm: {span: 7}}\"\n          :wrapperCol=\"{lg: {span: 10}, sm: {span: 17} }\">\n          <a-textarea\n            rows=\"4\"\n            :placeholder=\"$t('form.basic-form.standard.placeholder')\"\n            v-decorator=\"[\n              'type',\n              {rules: [{ required: true, message: $t('form.basic-form.standard.required') }]}\n            ]\" />\n        </a-form-item>\n        <a-form-item\n          :label=\"$t('form.basic-form.client.label')\"\n          :labelCol=\"{lg: {span: 7}, sm: {span: 7}}\"\n          :wrapperCol=\"{lg: {span: 10}, sm: {span: 17} }\">\n          <a-input\n            :placeholder=\"$t('form.basic-form.client.placeholder')\"\n            v-decorator=\"[\n              'customer',\n              {rules: [{ required: true, message: $t('form.basic-form.client.required') }]}\n            ]\" />\n        </a-form-item>\n        <a-form-item\n          :label=\"$t('form.basic-form.invites.label')\"\n          :labelCol=\"{lg: {span: 7}, sm: {span: 7}}\"\n          :wrapperCol=\"{lg: {span: 10}, sm: {span: 17} }\"\n          :required=\"false\"\n        >\n          <a-input :placeholder=\"$t('form.basic-form.invites.placeholder')\" />\n        </a-form-item>\n        <a-form-item\n          :label=\"$t('form.basic-form.weight.label')\"\n          :labelCol=\"{lg: {span: 7}, sm: {span: 7}}\"\n          :wrapperCol=\"{lg: {span: 10}, sm: {span: 17} }\"\n          :required=\"false\"\n        >\n          <a-input-number :min=\"0\" :max=\"100\" />\n          <span> %</span>\n        </a-form-item>\n        <a-form-item\n          :label=\"$t('form.basic-form.public.label')\"\n          :labelCol=\"{lg: {span: 7}, sm: {span: 7}}\"\n          :wrapperCol=\"{lg: {span: 10}, sm: {span: 17} }\"\n          :required=\"false\"\n          :help=\"$t('form.basic-form.label.help')\"\n        >\n          <a-radio-group v-decorator=\"['target', { initialValue: 1 }]\">\n            <a-radio :value=\"1\">{{ $t('form.basic-form.radio.public') }}</a-radio>\n            <a-radio :value=\"2\">{{ $t('form.basic-form.radio.partially-public') }}</a-radio>\n            <a-radio :value=\"3\">{{ $t('form.basic-form.radio.private') }}</a-radio>\n          </a-radio-group>\n          <a-form-item v-show=\"form.getFieldValue('target') === 2\">\n            <a-select mode=\"multiple\">\n              <a-select-option value=\"4\">{{ $t('form.basic-form.option.A') }}</a-select-option>\n              <a-select-option value=\"5\">{{ $t('form.basic-form.option.B') }}</a-select-option>\n              <a-select-option value=\"6\">{{ $t('form.basic-form.option.C') }}</a-select-option>\n            </a-select>\n          </a-form-item>\n        </a-form-item>\n        <a-form-item\n          :wrapperCol=\"{ span: 24 }\"\n          style=\"text-align: center\"\n        >\n          <a-button htmlType=\"submit\" type=\"primary\">{{ $t('form.basic-form.form.submit') }}</a-button>\n          <a-button style=\"margin-left: 8px\">{{ $t('form.basic-form.form.save') }}</a-button>\n        </a-form-item>\n      </a-form>\n    </a-card>\n  </page-header-wrapper>\n</template>\n\n<script>\nexport default {\n  name: 'BaseForm',\n  data () {\n    return {\n      form: this.$form.createForm(this)\n    }\n  },\n  methods: {\n    // handler\n    handleSubmit (e) {\n      e.preventDefault()\n      this.form.validateFields((err, values) => {\n        if (!err) {\n          console.log('Received values of form: ', values)\n        }\n      })\n    }\n  }\n}\n</script>\n"
  },
  {
    "path": "src/views/form/stepForm/Step1.vue",
    "content": "<template>\n  <div>\n    <a-form :form=\"form\" style=\"max-width: 500px; margin: 40px auto 0;\">\n      <a-form-item\n        label=\"付款账户\"\n        :labelCol=\"labelCol\"\n        :wrapperCol=\"wrapperCol\"\n      >\n        <a-select\n          placeholder=\"ant-design@alipay.com\"\n          v-decorator=\"['paymentUser', { rules: [{required: true, message: '付款账户必须填写'}] }]\">\n          <a-select-option value=\"1\">ant-design@alipay.com</a-select-option>\n        </a-select>\n      </a-form-item>\n      <a-form-item\n        label=\"收款账户\"\n        :labelCol=\"labelCol\"\n        :wrapperCol=\"wrapperCol\"\n      >\n        <a-input-group\n          style=\"display: inline-block; vertical-align: middle\"\n          :compact=\"true\"\n        >\n          <a-select defaultValue=\"alipay\" style=\"width: 100px\">\n            <a-select-option value=\"alipay\">支付宝</a-select-option>\n            <a-select-option value=\"wexinpay\">微信</a-select-option>\n          </a-select>\n          <a-input\n            :style=\"{width: 'calc(100% - 100px)'}\"\n            v-decorator=\"['payType', { initialValue: 'test@example.com', rules: [{required: true, message: '收款账户必须填写'}]}]\"\n          />\n        </a-input-group>\n      </a-form-item>\n      <a-form-item\n        label=\"收款人姓名\"\n        :labelCol=\"labelCol\"\n        :wrapperCol=\"wrapperCol\"\n      >\n        <a-input v-decorator=\"['name', { initialValue: 'Alex', rules: [{required: true, message: '收款人名称必须核对'}] }]\"/>\n      </a-form-item>\n      <a-form-item\n        label=\"转账金额\"\n        :labelCol=\"labelCol\"\n        :wrapperCol=\"wrapperCol\"\n      >\n        <a-input prefix=\"￥\" v-decorator=\"['momey', { initialValue: '5000', rules: [{required: true, message: '转账金额必须填写'}] }]\"/>\n      </a-form-item>\n      <a-form-item :wrapperCol=\"{span: 19, offset: 5}\">\n        <a-button type=\"primary\" @click=\"nextStep\">下一步</a-button>\n      </a-form-item>\n    </a-form>\n    <a-divider />\n    <div class=\"step-form-style-desc\">\n      <h3>说明</h3>\n      <h4>转账到支付宝账户</h4>\n      <p>如果需要，这里可以放一些关于产品的常见问题说明。如果需要，这里可以放一些关于产品的常见问题说明。如果需要，这里可以放一些关于产品的常见问题说明。</p>\n      <h4>转账到银行卡</h4>\n      <p>如果需要，这里可以放一些关于产品的常见问题说明。如果需要，这里可以放一些关于产品的常见问题说明。如果需要，这里可以放一些关于产品的常见问题说明。</p>\n    </div>\n  </div>\n</template>\n\n<script>\nexport default {\n  name: 'Step1',\n  data () {\n    return {\n      labelCol: { lg: { span: 5 }, sm: { span: 5 } },\n      wrapperCol: { lg: { span: 19 }, sm: { span: 19 } },\n      form: this.$form.createForm(this)\n    }\n  },\n  methods: {\n    nextStep () {\n      const { form: { validateFields } } = this\n      // 先校验，通过表单校验后，才进入下一步\n      validateFields((err, values) => {\n        if (!err) {\n          this.$emit('nextStep')\n        }\n      })\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n.step-form-style-desc {\n  padding: 0 56px;\n  color: rgba(0,0,0,.45);\n\n  h3 {\n    margin: 0 0 12px;\n    color: rgba(0,0,0,.45);\n    font-size: 16px;\n    line-height: 32px;\n  }\n\n  h4 {\n    margin: 0 0 4px;\n    color: rgba(0,0,0,.45);\n    font-size: 14px;\n    line-height: 22px;\n  }\n\n  p {\n    margin-top: 0;\n    margin-bottom: 12px;\n    line-height: 22px;\n  }\n}\n</style>\n"
  },
  {
    "path": "src/views/form/stepForm/Step2.vue",
    "content": "<template>\n  <div>\n    <a-form :form=\"form\" style=\"max-width: 500px; margin: 40px auto 0;\">\n      <a-alert\n        :closable=\"true\"\n        message=\"确认转账后，资金将直接打入对方账户，无法退回。\"\n        style=\"margin-bottom: 24px;\"\n      />\n      <a-form-item\n        label=\"付款账户\"\n        :labelCol=\"labelCol\"\n        :wrapperCol=\"wrapperCol\"\n        class=\"stepFormText\"\n      >\n        ant-design@alipay.com\n      </a-form-item>\n      <a-form-item\n        label=\"收款账户\"\n        :labelCol=\"labelCol\"\n        :wrapperCol=\"wrapperCol\"\n        class=\"stepFormText\"\n      >\n        test@example.com\n      </a-form-item>\n      <a-form-item\n        label=\"收款人姓名\"\n        :labelCol=\"labelCol\"\n        :wrapperCol=\"wrapperCol\"\n        class=\"stepFormText\"\n      >\n        Alex\n      </a-form-item>\n      <a-form-item\n        label=\"转账金额\"\n        :labelCol=\"labelCol\"\n        :wrapperCol=\"wrapperCol\"\n        class=\"stepFormText\"\n      >\n        ￥ 5,000.00\n      </a-form-item>\n      <a-divider />\n      <a-form-item\n        label=\"支付密码\"\n        :labelCol=\"labelCol\"\n        :wrapperCol=\"wrapperCol\"\n        class=\"stepFormText\"\n      >\n        <a-input\n          type=\"password\"\n          style=\"width: 80%;\"\n          v-decorator=\"['paymentPassword', { initialValue: '123456', rules: [{required: true, message: '请输入支付密码'}] }]\" />\n      </a-form-item>\n      <a-form-item :wrapperCol=\"{span: 19, offset: 5}\">\n        <a-button :loading=\"loading\" type=\"primary\" @click=\"nextStep\">提交</a-button>\n        <a-button style=\"margin-left: 8px\" @click=\"prevStep\">上一步</a-button>\n      </a-form-item>\n    </a-form>\n  </div>\n</template>\n\n<script>\nexport default {\n  name: 'Step2',\n  data () {\n    return {\n      labelCol: { lg: { span: 5 }, sm: { span: 5 } },\n      wrapperCol: { lg: { span: 19 }, sm: { span: 19 } },\n      form: this.$form.createForm(this),\n      loading: false,\n      timer: 0\n    }\n  },\n  methods: {\n    nextStep () {\n      const that = this\n      const { form: { validateFields } } = this\n      that.loading = true\n      validateFields((err, values) => {\n        if (!err) {\n          console.log('表单 values', values)\n          that.timer = setTimeout(function () {\n            that.loading = false\n            that.$emit('nextStep')\n          }, 1500)\n        } else {\n          that.loading = false\n        }\n      })\n    },\n    prevStep () {\n      this.$emit('prevStep')\n    }\n  },\n  beforeDestroy () {\n    clearTimeout(this.timer)\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n  .stepFormText {\n    margin-bottom: 24px;\n\n    .ant-form-item-label,\n    .ant-form-item-control {\n      line-height: 22px;\n    }\n  }\n\n</style>\n"
  },
  {
    "path": "src/views/form/stepForm/Step3.vue",
    "content": "<template>\n  <div>\n    <a-form>\n      <a-result title=\"操作成功\" :is-success=\"true\" sub-title=\"预计两小时内到账\" style=\"max-width: 560px; margin: 40px auto 0;\">\n        <div class=\"information\">\n          <a-row>\n            <a-col :sm=\"8\" :xs=\"24\">付款账户：</a-col>\n            <a-col :sm=\"16\" :xs=\"24\">ant-design@alipay.com</a-col>\n          </a-row>\n          <a-row>\n            <a-col :sm=\"8\" :xs=\"24\">收款账户：</a-col>\n            <a-col :sm=\"16\" :xs=\"24\">test@example.com</a-col>\n          </a-row>\n          <a-row>\n            <a-col :sm=\"8\" :xs=\"24\">收款人姓名：</a-col>\n            <a-col :sm=\"16\" :xs=\"24\">辉夜</a-col>\n          </a-row>\n          <a-row>\n            <a-col :sm=\"8\" :xs=\"24\">转账金额：</a-col>\n            <a-col :sm=\"16\" :xs=\"24\"><span class=\"money\">500</span> 元</a-col>\n          </a-row>\n        </div>\n        <template #extra>\n          <a-button type=\"primary\" @click=\"finish\">再转一笔</a-button>\n          <a-button style=\"margin-left: 8px\" @click=\"toOrderList\">查看账单</a-button>\n        </template>\n      </a-result>\n    </a-form>\n  </div>\n</template>\n\n<script>\nexport default {\n  name: 'Step3',\n  data () {\n    return {\n      loading: false\n    }\n  },\n  methods: {\n    finish () {\n      this.$emit('finish')\n    },\n    toOrderList () {\n      this.$router.push('/list/table-list')\n    }\n  }\n}\n</script>\n<style lang=\"less\" scoped>\n  .information {\n    line-height: 22px;\n\n    .ant-row:not(:last-child) {\n      margin-bottom: 24px;\n    }\n  }\n  .money {\n    font-family: \"Helvetica Neue\",sans-serif;\n    font-weight: 500;\n    font-size: 20px;\n    line-height: 14px;\n  }\n</style>\n"
  },
  {
    "path": "src/views/form/stepForm/StepForm.vue",
    "content": "<template>\n  <page-header-wrapper>\n    <!-- PageHeader 第二种使用方式 (v-slot) -->\n    <template v-slot:content>\n      将一个冗长或用户不熟悉的表单任务分成多个步骤，指导用户完成。\n    </template>\n    <a-card :bordered=\"false\">\n      <a-steps class=\"steps\" :current=\"currentTab\">\n        <a-step title=\"填写转账信息\" />\n        <a-step title=\"确认转账信息\" />\n        <a-step title=\"完成\" />\n      </a-steps>\n      <div class=\"content\">\n        <step1 v-if=\"currentTab === 0\" @nextStep=\"nextStep\"/>\n        <step2 v-if=\"currentTab === 1\" @nextStep=\"nextStep\" @prevStep=\"prevStep\"/>\n        <step3 v-if=\"currentTab === 2\" @prevStep=\"prevStep\" @finish=\"finish\"/>\n      </div>\n    </a-card>\n  </page-header-wrapper>\n</template>\n\n<script>\nimport Step1 from './Step1'\nimport Step2 from './Step2'\nimport Step3 from './Step3'\n\nexport default {\n  name: 'StepForm',\n  components: {\n    Step1,\n    Step2,\n    Step3\n  },\n  data () {\n    return {\n      currentTab: 0,\n      // form\n      form: null\n    }\n  },\n  methods: {\n\n    // handler\n    nextStep () {\n      if (this.currentTab < 2) {\n        this.currentTab += 1\n      }\n    },\n    prevStep () {\n      if (this.currentTab > 0) {\n        this.currentTab -= 1\n      }\n    },\n    finish () {\n      this.currentTab = 0\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n  .steps {\n    max-width: 750px;\n    margin: 16px auto;\n  }\n</style>\n"
  },
  {
    "path": "src/views/list/BasicList.vue",
    "content": "<template>\n  <page-header-wrapper>\n    <a-card :bordered=\"false\">\n      <a-row>\n        <a-col :sm=\"8\" :xs=\"24\">\n          <info title=\"我的待办\" value=\"8个任务\" :bordered=\"true\" />\n        </a-col>\n        <a-col :sm=\"8\" :xs=\"24\">\n          <info title=\"本周任务平均处理时间\" value=\"32分钟\" :bordered=\"true\" />\n        </a-col>\n        <a-col :sm=\"8\" :xs=\"24\">\n          <info title=\"本周完成任务数\" value=\"24个\" />\n        </a-col>\n      </a-row>\n    </a-card>\n\n    <a-card\n      style=\"margin-top: 24px\"\n      :bordered=\"false\"\n      title=\"标准列表\">\n\n      <div slot=\"extra\">\n        <a-radio-group v-model=\"status\">\n          <a-radio-button value=\"all\">全部</a-radio-button>\n          <a-radio-button value=\"processing\">进行中</a-radio-button>\n          <a-radio-button value=\"waiting\">等待中</a-radio-button>\n        </a-radio-group>\n        <a-input-search style=\"margin-left: 16px; width: 272px;\" />\n      </div>\n\n      <div class=\"operate\">\n        <a-button type=\"dashed\" style=\"width: 100%\" icon=\"plus\" @click=\"add\">添加</a-button>\n      </div>\n\n      <a-list size=\"large\" :pagination=\"{showSizeChanger: true, showQuickJumper: true, pageSize: 5, total: 50}\">\n        <a-list-item :key=\"index\" v-for=\"(item, index) in data\">\n          <a-list-item-meta :description=\"item.description\">\n            <a-avatar slot=\"avatar\" size=\"large\" shape=\"square\" :src=\"item.avatar\"/>\n            <a slot=\"title\">{{ item.title }}</a>\n          </a-list-item-meta>\n          <div slot=\"actions\">\n            <a @click=\"edit(item)\">编辑</a>\n          </div>\n          <div slot=\"actions\">\n            <a-dropdown>\n              <a-menu slot=\"overlay\">\n                <a-menu-item><a>编辑</a></a-menu-item>\n                <a-menu-item><a>删除</a></a-menu-item>\n              </a-menu>\n              <a>更多<a-icon type=\"down\"/></a>\n            </a-dropdown>\n          </div>\n          <div class=\"list-content\">\n            <div class=\"list-content-item\">\n              <span>Owner</span>\n              <p>{{ item.owner }}</p>\n            </div>\n            <div class=\"list-content-item\">\n              <span>开始时间</span>\n              <p>{{ item.startAt }}</p>\n            </div>\n            <div class=\"list-content-item\">\n              <a-progress :percent=\"item.progress.value\" :status=\"!item.progress.status ? null : item.progress.status\" style=\"width: 180px\" />\n            </div>\n          </div>\n        </a-list-item>\n      </a-list>\n    </a-card>\n  </page-header-wrapper>\n</template>\n\n<script>\n// 演示如何使用 this.$dialog 封装 modal 组件\nimport TaskForm from './modules/TaskForm'\nimport Info from './components/Info'\n\nconst data = []\ndata.push({\n  title: 'Alipay',\n  avatar: 'https://gw.alipayobjects.com/zos/rmsportal/WdGqmHpayyMjiEhcKoVE.png',\n  description: '那是一种内在的东西， 他们到达不了，也无法触及的',\n  owner: '付晓晓',\n  startAt: '2018-07-26 22:44',\n  progress: {\n    value: 90\n  }\n})\ndata.push({\n  title: 'Angular',\n  avatar: 'https://gw.alipayobjects.com/zos/rmsportal/zOsKZmFRdUtvpqCImOVY.png',\n  description: '希望是一个好东西，也许是最好的，好东西是不会消亡的',\n  owner: '曲丽丽',\n  startAt: '2018-07-26 22:44',\n  progress: {\n    value: 54\n  }\n})\ndata.push({\n  title: 'Ant Design',\n  avatar: 'https://gw.alipayobjects.com/zos/rmsportal/dURIMkkrRFpPgTuzkwnB.png',\n  description: '生命就像一盒巧克力，结果往往出人意料',\n  owner: '林东东',\n  startAt: '2018-07-26 22:44',\n  progress: {\n    value: 66\n  }\n})\ndata.push({\n  title: 'Ant Design Pro',\n  avatar: 'https://gw.alipayobjects.com/zos/rmsportal/sfjbOqnsXXJgNCjCzDBL.png',\n  description: '城镇中有那么多的酒馆，她却偏偏走进了我的酒馆',\n  owner: '周星星',\n  startAt: '2018-07-26 22:44',\n  progress: {\n    value: 30\n  }\n})\ndata.push({\n  title: 'Bootstrap',\n  avatar: 'https://gw.alipayobjects.com/zos/rmsportal/siCrBXXhmvTQGWPNLBow.png',\n  description: '那时候我只会想自己想要什么，从不想自己拥有什么',\n  owner: '吴加好',\n  startAt: '2018-07-26 22:44',\n  progress: {\n    status: 'exception',\n    value: 100\n  }\n})\n\nexport default {\n  name: 'StandardList',\n  components: {\n    TaskForm,\n    Info\n  },\n  data () {\n    return {\n      data,\n      status: 'all'\n    }\n  },\n  methods: {\n    add () {\n      this.$dialog(TaskForm,\n        // component props\n        {\n          record: {},\n          on: {\n            ok () {\n              console.log('ok 回调')\n            },\n            cancel () {\n              console.log('cancel 回调')\n            },\n            close () {\n              console.log('modal close 回调')\n            }\n          }\n        },\n        // modal props\n        {\n          title: '新增',\n          width: 700,\n          centered: true,\n          maskClosable: false\n        })\n    },\n    edit (record) {\n      console.log('record', record)\n      this.$dialog(TaskForm,\n        // component props\n        {\n          record,\n          on: {\n            ok () {\n              console.log('ok 回调')\n            },\n            cancel () {\n              console.log('cancel 回调')\n            },\n            close () {\n              console.log('modal close 回调')\n            }\n          }\n        },\n        // modal props\n        {\n          title: '操作',\n          width: 700,\n          centered: true,\n          maskClosable: false\n        })\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n.ant-avatar-lg {\n    width: 48px;\n    height: 48px;\n    line-height: 48px;\n}\n\n.list-content-item {\n    color: rgba(0, 0, 0, .45);\n    display: inline-block;\n    vertical-align: middle;\n    font-size: 14px;\n    margin-left: 40px;\n    span {\n        line-height: 20px;\n    }\n    p {\n        margin-top: 4px;\n        margin-bottom: 0;\n        line-height: 22px;\n    }\n}\n</style>\n"
  },
  {
    "path": "src/views/list/CardList.vue",
    "content": "<template>\n  <page-header-wrapper\n    :tab-list=\"tabList\"\n    :tab-active-key=\"tabActiveKey\"\n    :tab-change=\"(key) => {\n      this.tabActiveKey = key\n    }\"\n    content=\"段落示意：蚂蚁金服务设计平台 ant.design，用最小的工作量，无缝接入蚂蚁金服生态， 提供跨越设计与开发的体验解决方案。\"\n  >\n    <template v-slot:extraContent>\n      <div style=\"width: 155px; margin-top: -20px;\"><img style=\"width: 100%\" :src=\"extraImage\" /></div>\n    </template>\n    <a-list\n      rowKey=\"id\"\n      :grid=\"{gutter: 24, lg: 3, md: 2, sm: 1, xs: 1}\"\n      :dataSource=\"dataSource\"\n      class=\"card-list\"\n    >\n      <a-list-item slot=\"renderItem\" slot-scope=\"item\">\n        <template v-if=\"!item || item.id === undefined\">\n          <a-button class=\"new-btn\" type=\"dashed\">\n            <a-icon type=\"plus\"/>\n            新增产品\n          </a-button>\n        </template>\n        <template v-else>\n          <a-card :hoverable=\"true\">\n            <a-card-meta>\n              <a slot=\"title\">{{ item.title }}</a>\n              <a-avatar class=\"card-avatar\" slot=\"avatar\" :src=\"item.avatar\" size=\"large\"/>\n              <div class=\"meta-content\" slot=\"description\">{{ item.content }}</div>\n            </a-card-meta>\n            <template class=\"ant-card-actions\" slot=\"actions\">\n              <a>操作一</a>\n              <a>操作二</a>\n            </template>\n          </a-card>\n        </template>\n      </a-list-item>\n    </a-list>\n  </page-header-wrapper>\n</template>\n\n<script>\n\nconst dataSource = []\ndataSource.push({})\nfor (let i = 0; i < 11; i++) {\n  dataSource.push({\n    id: i,\n    title: 'Alipay',\n    avatar: 'https://gw.alipayobjects.com/zos/rmsportal/WdGqmHpayyMjiEhcKoVE.png',\n    content: '在中台产品的研发过程中，会出现不同的设计规范和实现方式，但其中往往存在很多类似的页面和组件，这些类似的组件会被抽离成一套标准规范。'\n  })\n}\n\nexport default {\n  name: 'CardList',\n  data () {\n    this.tabList = [\n      { key: 'tab1', tab: '快速开始' },\n      { key: 'tab2', tab: '产品简介' },\n      { key: 'tab3', tab: '产品文档' }\n    ]\n    return {\n      tabActiveKey: 'tab1',\n\n      extraImage: 'https://gw.alipayobjects.com/zos/rmsportal/RzwpdLnhmvDJToTdfDPe.png',\n      dataSource\n    }\n  },\n  methods: {\n    testFun () {\n      this.$message.info('快速开始被点击！')\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n  @import \"~@/components/index.less\";\n\n  .card-list {\n    :deep(.ant-card-body:hover) {\n      .ant-card-meta-title>a {\n        color: @primary-color;\n      }\n    }\n\n    :deep(.ant-card-meta-title) {\n      margin-bottom: 12px;\n\n      &>a {\n        display: inline-block;\n        max-width: 100%;\n        color: rgba(0,0,0,.85);\n      }\n    }\n\n    :deep(.meta-content) {\n      position: relative;\n      overflow: hidden;\n      text-overflow: ellipsis;\n      display: -webkit-box;\n      height: 64px;\n      -webkit-line-clamp: 3;\n      -webkit-box-orient: vertical;\n\n      margin-bottom: 1em;\n    }\n  }\n\n  .card-avatar {\n    width: 48px;\n    height: 48px;\n    border-radius: 48px;\n  }\n\n  .ant-card-actions {\n    background: #f7f9fa;\n\n    li {\n      float: left;\n      text-align: center;\n      margin: 12px 0;\n      color: rgba(0, 0, 0, 0.45);\n      width: 50%;\n\n      &:not(:last-child) {\n        border-right: 1px solid #e8e8e8;\n      }\n\n      a {\n        color: rgba(0, 0, 0, .45);\n        line-height: 22px;\n        display: inline-block;\n        width: 100%;\n        &:hover {\n          color: @primary-color;\n        }\n      }\n    }\n  }\n\n  .new-btn {\n    background-color: #fff;\n    border-radius: 2px;\n    width: 100%;\n    height: 188px;\n  }\n\n</style>\n"
  },
  {
    "path": "src/views/list/QueryList.vue",
    "content": "<template>\n  <a-card :bordered=\"false\">\n    <component @onEdit=\"handleEdit\" @onGoBack=\"handleGoBack\" :record=\"record\" :is=\"currentComponet\"></component>\n  </a-card>\n</template>\n\n<script>\n\nimport ATextarea from 'ant-design-vue/es/input/TextArea'\nimport AInput from 'ant-design-vue/es/input/Input'\n// 动态切换组件\nimport List from '@/views/list/table/List'\nimport Edit from '@/views/list/table/Edit'\n\nexport default {\n  name: 'TableListWrapper',\n  components: {\n    AInput,\n    ATextarea,\n    List,\n    Edit\n  },\n  data () {\n    return {\n      currentComponet: 'List',\n      record: ''\n    }\n  },\n  created () {\n\n  },\n  methods: {\n    handleEdit (record) {\n      this.record = record || ''\n      this.currentComponet = 'Edit'\n      console.log(record)\n    },\n    handleGoBack () {\n      this.record = ''\n      this.currentComponet = 'List'\n    }\n  },\n  watch: {\n    '$route.path' () {\n      this.record = ''\n      this.currentComponet = 'List'\n    }\n  }\n}\n</script>\n"
  },
  {
    "path": "src/views/list/TableList.vue",
    "content": "<template>\n  <page-header-wrapper>\n    <a-card :bordered=\"false\">\n      <div class=\"table-page-search-wrapper\">\n        <a-form layout=\"inline\">\n          <a-row :gutter=\"48\">\n            <a-col :md=\"8\" :sm=\"24\">\n              <a-form-item label=\"规则编号\">\n                <a-input v-model=\"queryParam.id\" placeholder=\"\"/>\n              </a-form-item>\n            </a-col>\n            <a-col :md=\"8\" :sm=\"24\">\n              <a-form-item label=\"使用状态\">\n                <a-select v-model=\"queryParam.status\" placeholder=\"请选择\" default-value=\"0\">\n                  <a-select-option value=\"0\">全部</a-select-option>\n                  <a-select-option value=\"1\">关闭</a-select-option>\n                  <a-select-option value=\"2\">运行中</a-select-option>\n                </a-select>\n              </a-form-item>\n            </a-col>\n            <template v-if=\"advanced\">\n              <a-col :md=\"8\" :sm=\"24\">\n                <a-form-item label=\"调用次数\">\n                  <a-input-number v-model=\"queryParam.callNo\" style=\"width: 100%\"/>\n                </a-form-item>\n              </a-col>\n              <a-col :md=\"8\" :sm=\"24\">\n                <a-form-item label=\"更新日期\">\n                  <a-date-picker v-model=\"queryParam.date\" style=\"width: 100%\" placeholder=\"请输入更新日期\"/>\n                </a-form-item>\n              </a-col>\n              <a-col :md=\"8\" :sm=\"24\">\n                <a-form-item label=\"使用状态\">\n                  <a-select v-model=\"queryParam.useStatus\" placeholder=\"请选择\" default-value=\"0\">\n                    <a-select-option value=\"0\">全部</a-select-option>\n                    <a-select-option value=\"1\">关闭</a-select-option>\n                    <a-select-option value=\"2\">运行中</a-select-option>\n                  </a-select>\n                </a-form-item>\n              </a-col>\n              <a-col :md=\"8\" :sm=\"24\">\n                <a-form-item label=\"使用状态\">\n                  <a-select placeholder=\"请选择\" default-value=\"0\">\n                    <a-select-option value=\"0\">全部</a-select-option>\n                    <a-select-option value=\"1\">关闭</a-select-option>\n                    <a-select-option value=\"2\">运行中</a-select-option>\n                  </a-select>\n                </a-form-item>\n              </a-col>\n            </template>\n            <a-col :md=\"!advanced && 8 || 24\" :sm=\"24\">\n              <span class=\"table-page-search-submitButtons\" :style=\"advanced && { float: 'right', overflow: 'hidden' } || {} \">\n                <a-button type=\"primary\" @click=\"$refs.table.refresh(true)\">查询</a-button>\n                <a-button style=\"margin-left: 8px\" @click=\"() => this.queryParam = {}\">重置</a-button>\n                <a @click=\"toggleAdvanced\" style=\"margin-left: 8px\">\n                  {{ advanced ? '收起' : '展开' }}\n                  <a-icon :type=\"advanced ? 'up' : 'down'\"/>\n                </a>\n              </span>\n            </a-col>\n          </a-row>\n        </a-form>\n      </div>\n\n      <div class=\"table-operator\">\n        <a-button type=\"primary\" icon=\"plus\" @click=\"handleAdd\">新建</a-button>\n        <a-dropdown v-action:edit v-if=\"selectedRowKeys.length > 0\">\n          <a-menu slot=\"overlay\">\n            <a-menu-item key=\"1\"><a-icon type=\"delete\" />删除</a-menu-item>\n            <!-- lock | unlock -->\n            <a-menu-item key=\"2\"><a-icon type=\"lock\" />锁定</a-menu-item>\n          </a-menu>\n          <a-button style=\"margin-left: 8px\">\n            批量操作 <a-icon type=\"down\" />\n          </a-button>\n        </a-dropdown>\n      </div>\n\n      <s-table\n        ref=\"table\"\n        size=\"default\"\n        rowKey=\"key\"\n        :columns=\"columns\"\n        :data=\"loadData\"\n        :alert=\"true\"\n        :rowSelection=\"rowSelection\"\n        showPagination=\"auto\"\n      >\n        <span slot=\"serial\" slot-scope=\"text, record, index\">\n          {{ index + 1 }}\n        </span>\n        <span slot=\"status\" slot-scope=\"text\">\n          <a-badge :status=\"text | statusTypeFilter\" :text=\"text | statusFilter\" />\n        </span>\n        <span slot=\"description\" slot-scope=\"text\">\n          <ellipsis :length=\"4\" tooltip>{{ text }}</ellipsis>\n        </span>\n\n        <span slot=\"action\" slot-scope=\"text, record\">\n          <template>\n            <a @click=\"handleEdit(record)\">配置</a>\n            <a-divider type=\"vertical\" />\n            <a @click=\"handleSub(record)\">订阅报警</a>\n          </template>\n        </span>\n      </s-table>\n\n      <create-form\n        ref=\"createModal\"\n        :visible=\"visible\"\n        :loading=\"confirmLoading\"\n        :model=\"mdl\"\n        @cancel=\"handleCancel\"\n        @ok=\"handleOk\"\n      />\n      <step-by-step-modal ref=\"modal\" @ok=\"handleOk\"/>\n    </a-card>\n  </page-header-wrapper>\n</template>\n\n<script>\nimport moment from 'moment'\nimport { STable, Ellipsis } from '@/components'\nimport { getRoleList, getServiceList } from '@/api/manage'\n\nimport StepByStepModal from './modules/StepByStepModal'\nimport CreateForm from './modules/CreateForm'\n\nconst columns = [\n  {\n    title: '#',\n    scopedSlots: { customRender: 'serial' }\n  },\n  {\n    title: '规则编号',\n    dataIndex: 'no'\n  },\n  {\n    title: '描述',\n    dataIndex: 'description',\n    scopedSlots: { customRender: 'description' }\n  },\n  {\n    title: '服务调用次数',\n    dataIndex: 'callNo',\n    sorter: true,\n    needTotal: true,\n    customRender: (text) => text + ' 次'\n  },\n  {\n    title: '状态',\n    dataIndex: 'status',\n    scopedSlots: { customRender: 'status' }\n  },\n  {\n    title: '更新时间',\n    dataIndex: 'updatedAt',\n    sorter: true\n  },\n  {\n    title: '操作',\n    dataIndex: 'action',\n    width: '150px',\n    scopedSlots: { customRender: 'action' }\n  }\n]\n\nconst statusMap = {\n  0: {\n    status: 'default',\n    text: '关闭'\n  },\n  1: {\n    status: 'processing',\n    text: '运行中'\n  },\n  2: {\n    status: 'success',\n    text: '已上线'\n  },\n  3: {\n    status: 'error',\n    text: '异常'\n  }\n}\n\nexport default {\n  name: 'TableList',\n  components: {\n    STable,\n    Ellipsis,\n    CreateForm,\n    StepByStepModal\n  },\n  data () {\n    this.columns = columns\n    return {\n      // create model\n      visible: false,\n      confirmLoading: false,\n      mdl: null,\n      // 高级搜索 展开/关闭\n      advanced: false,\n      // 查询参数\n      queryParam: {},\n      // 加载数据方法 必须为 Promise 对象\n      loadData: parameter => {\n        const requestParameters = Object.assign({}, parameter, this.queryParam)\n        console.log('loadData request parameters:', requestParameters)\n        return getServiceList(requestParameters)\n          .then(res => {\n            return res.result\n          })\n      },\n      selectedRowKeys: [],\n      selectedRows: []\n    }\n  },\n  filters: {\n    statusFilter (type) {\n      return statusMap[type].text\n    },\n    statusTypeFilter (type) {\n      return statusMap[type].status\n    }\n  },\n  created () {\n    getRoleList({ t: new Date() })\n  },\n  computed: {\n    rowSelection () {\n      return {\n        selectedRowKeys: this.selectedRowKeys,\n        onChange: this.onSelectChange\n      }\n    }\n  },\n  methods: {\n    handleAdd () {\n      this.mdl = null\n      this.visible = true\n    },\n    handleEdit (record) {\n      this.visible = true\n      this.mdl = { ...record }\n    },\n    handleOk () {\n      const form = this.$refs.createModal.form\n      this.confirmLoading = true\n      form.validateFields((errors, values) => {\n        if (!errors) {\n          console.log('values', values)\n          if (values.id > 0) {\n            // 修改 e.g.\n            new Promise((resolve, reject) => {\n              setTimeout(() => {\n                resolve()\n              }, 1000)\n            }).then(res => {\n              this.visible = false\n              this.confirmLoading = false\n              // 重置表单数据\n              form.resetFields()\n              // 刷新表格\n              this.$refs.table.refresh()\n\n              this.$message.info('修改成功')\n            })\n          } else {\n            // 新增\n            new Promise((resolve, reject) => {\n              setTimeout(() => {\n                resolve()\n              }, 1000)\n            }).then(res => {\n              this.visible = false\n              this.confirmLoading = false\n              // 重置表单数据\n              form.resetFields()\n              // 刷新表格\n              this.$refs.table.refresh()\n\n              this.$message.info('新增成功')\n            })\n          }\n        } else {\n          this.confirmLoading = false\n        }\n      })\n    },\n    handleCancel () {\n      this.visible = false\n\n      const form = this.$refs.createModal.form\n      form.resetFields() // 清理表单数据（可不做）\n    },\n    handleSub (record) {\n      if (record.status !== 0) {\n        this.$message.info(`${record.no} 订阅成功`)\n      } else {\n        this.$message.error(`${record.no} 订阅失败，规则已关闭`)\n      }\n    },\n    onSelectChange (selectedRowKeys, selectedRows) {\n      this.selectedRowKeys = selectedRowKeys\n      this.selectedRows = selectedRows\n    },\n    toggleAdvanced () {\n      this.advanced = !this.advanced\n    },\n    resetSearchForm () {\n      this.queryParam = {\n        date: moment(new Date())\n      }\n    }\n  }\n}\n</script>\n"
  },
  {
    "path": "src/views/list/components/Info.vue",
    "content": "<template>\n  <div class=\"header-info\">\n    <span>{{ title }}</span>\n    <p>{{ value }}</p>\n    <em v-if=\"bordered\" />\n  </div>\n</template>\n\n<script>\nexport default {\n  name: 'Info',\n  props: {\n    title: {\n      type: String,\n      default: ''\n    },\n    value: {\n      type: String,\n      default: ''\n    },\n    bordered: {\n      type: Boolean,\n      default: false\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n@import \"~ant-design-vue/es/style/themes/default.less\";\n\n.header-info {\n  position: relative;\n  text-align: center;\n  & > span {\n    display: inline-block;\n    margin-bottom: 4px;\n    color: @text-color-secondary;\n    font-size: @font-size-base;\n    line-height: 22px;\n  }\n  & > p {\n    margin: 0;\n    color: @heading-color;\n    font-size: 24px;\n    line-height: 32px;\n  }\n  & > em {\n    position: absolute;\n    top: 0;\n    right: 0;\n    width: 1px;\n    height: 56px;\n    background-color: @border-color-split;\n  }\n}\n</style>\n"
  },
  {
    "path": "src/views/list/modules/CreateForm.vue",
    "content": "<template>\n  <a-modal\n    title=\"新建规则\"\n    :width=\"640\"\n    :visible=\"visible\"\n    :confirmLoading=\"loading\"\n    @ok=\"() => { $emit('ok') }\"\n    @cancel=\"() => { $emit('cancel') }\"\n  >\n    <a-spin :spinning=\"loading\">\n      <a-form :form=\"form\" v-bind=\"formLayout\">\n        <!-- 检查是否有 id 并且大于0，大于0是修改。其他是新增，新增不显示主键ID -->\n        <a-form-item v-show=\"model && model.id > 0\" label=\"主键ID\">\n          <a-input v-decorator=\"['id', { initialValue: 0 }]\" disabled />\n        </a-form-item>\n        <a-form-item label=\"描述\">\n          <a-input v-decorator=\"['description', {rules: [{required: true, min: 5, message: '请输入至少五个字符的规则描述！'}]}]\" />\n        </a-form-item>\n      </a-form>\n    </a-spin>\n  </a-modal>\n</template>\n\n<script>\nimport pick from 'lodash.pick'\n\n// 表单字段\nconst fields = ['description', 'id']\n\nexport default {\n  props: {\n    visible: {\n      type: Boolean,\n      required: true\n    },\n    loading: {\n      type: Boolean,\n      default: () => false\n    },\n    model: {\n      type: Object,\n      default: () => null\n    }\n  },\n  data () {\n    this.formLayout = {\n      labelCol: {\n        xs: { span: 24 },\n        sm: { span: 7 }\n      },\n      wrapperCol: {\n        xs: { span: 24 },\n        sm: { span: 13 }\n      }\n    }\n    return {\n      form: this.$form.createForm(this)\n    }\n  },\n  created () {\n    console.log('custom modal created')\n\n    // 防止表单未注册\n    fields.forEach(v => this.form.getFieldDecorator(v))\n\n    // 当 model 发生改变时，为表单设置值\n    this.$watch('model', () => {\n      this.model && this.form.setFieldsValue(pick(this.model, fields))\n    })\n  }\n}\n</script>\n"
  },
  {
    "path": "src/views/list/modules/StepByStepModal.vue",
    "content": "<template>\n  <a-modal\n    title=\"分步对话框\"\n    :width=\"640\"\n    :visible=\"visible\"\n    :confirmLoading=\"confirmLoading\"\n    @cancel=\"handleCancel\"\n  >\n    <a-spin :spinning=\"confirmLoading\">\n      <a-steps :current=\"currentStep\" :style=\"{ marginBottom: '28px' }\" size=\"small\">\n        <a-step title=\"基本信息\" />\n        <a-step title=\"配置规则属性\" />\n        <a-step title=\"设定调度周期\" />\n      </a-steps>\n      <a-form :form=\"form\">\n        <!-- step1 -->\n        <div v-show=\"currentStep === 0\">\n          <a-form-item\n            label=\"规则名称\"\n            :labelCol=\"labelCol\"\n            :wrapperCol=\"wrapperCol\"\n          >\n            <a-input v-decorator=\"['name', {rules: [{required: true}]}]\" />\n          </a-form-item>\n          <a-form-item\n            label=\"规则描述\"\n            :labelCol=\"labelCol\"\n            :wrapperCol=\"wrapperCol\"\n          >\n            <a-textarea :rows=\"4\" v-decorator=\"['desc', {rules: [{required: true}]}]\"></a-textarea>\n          </a-form-item>\n        </div>\n        <div v-show=\"currentStep === 1\">\n          <a-form-item\n            label=\"监控对象\"\n            :labelCol=\"labelCol\"\n            :wrapperCol=\"wrapperCol\"\n          >\n            <a-select v-decorator=\"['target', {initialValue: 0, rules: [{required: true}]}]\" style=\"width: 100%\">\n              <a-select-option :value=\"0\">表一</a-select-option>\n              <a-select-option :value=\"1\">表二</a-select-option>\n            </a-select>\n          </a-form-item>\n\n          <a-form-item\n            label=\"规则模板\"\n            :labelCol=\"labelCol\"\n            :wrapperCol=\"wrapperCol\"\n          >\n            <a-select v-decorator=\"['template', { initialValue: 0, rules: [{required: true}]}]\" style=\"width: 100%\">\n              <a-select-option :value=\"0\">规则模板一</a-select-option>\n              <a-select-option :value=\"1\">规则模板二</a-select-option>\n            </a-select>\n          </a-form-item>\n\n          <a-form-item\n            label=\"规则类型\"\n            :labelCol=\"labelCol\"\n            :wrapperCol=\"wrapperCol\"\n          >\n            <a-radio-group v-decorator=\"['type', {initialValue: 0, rules: [{required: true}]}]\" style=\"width: 100%\">\n              <a-radio :value=\"0\">强</a-radio>\n              <a-radio :value=\"1\">弱</a-radio>\n            </a-radio-group>\n          </a-form-item>\n        </div>\n\n        <div v-show=\"currentStep === 2\">\n          <a-form-item\n            label=\"开始时间\"\n            :labelCol=\"labelCol\"\n            :wrapperCol=\"wrapperCol\"\n          >\n            <a-date-picker v-decorator=\"['time', {rules: [{ type: 'object', required: true, message: 'Please select time!' }]}]\" style=\"width: 100%\" />\n          </a-form-item>\n          <a-form-item\n            label=\"调度周期\"\n            :labelCol=\"labelCol\"\n            :wrapperCol=\"wrapperCol\"\n          >\n            <a-select v-decorator=\"['frequency', { initialValue: 'month', rules: [{required: true}]}]\" style=\"width: 100%\">\n              <a-select-option value=\"month\">月</a-select-option>\n              <a-select-option value=\"week\">周</a-select-option>\n            </a-select>\n          </a-form-item>\n        </div>\n        <!-- step1 end -->\n      </a-form>\n    </a-spin>\n    <template slot=\"footer\">\n      <a-button key=\"back\" @click=\"backward\" v-if=\"currentStep > 0\" :style=\"{ float: 'left' }\" >上一步</a-button>\n      <a-button key=\"cancel\" @click=\"handleCancel\">取消</a-button>\n      <a-button key=\"forward\" :loading=\"confirmLoading\" type=\"primary\" @click=\"handleNext(currentStep)\">{{ currentStep === 2 && '完成' || '下一步' }}</a-button>\n    </template>\n  </a-modal>\n</template>\n\n<script>\nimport pick from 'lodash.pick'\n\nconst stepForms = [\n  ['name', 'desc'],\n  ['target', 'template', 'type'],\n  ['time', 'frequency']\n]\n\nexport default {\n  name: 'StepByStepModal',\n  data () {\n    return {\n      labelCol: {\n        xs: { span: 24 },\n        sm: { span: 7 }\n      },\n      wrapperCol: {\n        xs: { span: 24 },\n        sm: { span: 13 }\n      },\n      visible: false,\n      confirmLoading: false,\n      currentStep: 0,\n      mdl: {},\n\n      form: this.$form.createForm(this)\n    }\n  },\n  methods: {\n    edit (record) {\n      this.visible = true\n      const { form: { setFieldsValue } } = this\n      this.$nextTick(() => {\n        setFieldsValue(pick(record, []))\n      })\n    },\n    handleNext (step) {\n      const { form: { validateFields } } = this\n      const currentStep = step + 1\n      if (currentStep <= 2) {\n        // stepForms\n        validateFields(stepForms[ this.currentStep ], (errors, values) => {\n          if (!errors) {\n            this.currentStep = currentStep\n          }\n        })\n        return\n      }\n      // last step\n      this.confirmLoading = true\n      validateFields((errors, values) => {\n        console.log('errors:', errors, 'val:', values)\n        if (!errors) {\n          console.log('values:', values)\n          setTimeout(() => {\n            this.confirmLoading = false\n            this.$emit('ok', values)\n          }, 1500)\n        } else {\n          this.confirmLoading = false\n        }\n      })\n    },\n    backward () {\n      this.currentStep--\n    },\n    handleCancel () {\n      // clear form & currentStep\n      this.visible = false\n      this.currentStep = 0\n    }\n  }\n}\n</script>\n"
  },
  {
    "path": "src/views/list/modules/TaskForm.vue",
    "content": "<template>\n  <a-form @submit=\"handleSubmit\" :form=\"form\">\n    <a-form-item\n      label=\"任务名称\"\n      :labelCol=\"labelCol\"\n      :wrapperCol=\"wrapperCol\"\n    >\n      <a-input v-decorator=\"['title', {rules:[{required: true, message: '请输入任务名称'}]}]\" />\n    </a-form-item>\n    <a-form-item\n      label=\"开始时间\"\n      :labelCol=\"labelCol\"\n      :wrapperCol=\"wrapperCol\"\n    >\n      <a-date-picker\n        style=\"width: 100%\"\n        valueFormat=\"YYYY-MM-DD HH:mm\"\n        v-decorator=\"['startAt', {rules:[{required: true, message: '请选择开始时间'}]}]\"\n      />\n    </a-form-item>\n    <a-form-item\n      label=\"任务负责人\"\n      :labelCol=\"labelCol\"\n      :wrapperCol=\"wrapperCol\"\n    >\n      <a-select v-decorator=\"['owner', {rules:[{required: true, message: '请选择开始时间'}]}]\">\n        <a-select-option :value=\"0\">付晓晓</a-select-option>\n        <a-select-option :value=\"1\">周毛毛</a-select-option>\n      </a-select>\n    </a-form-item>\n    <a-form-item\n      label=\"产品描述\"\n      :labelCol=\"labelCol\"\n      :wrapperCol=\"wrapperCol\"\n    >\n      <a-textarea v-decorator=\"['description']\"></a-textarea>\n    </a-form-item>\n  </a-form>\n</template>\n\n<script>\nimport pick from 'lodash.pick'\n\nconst fields = ['title', 'startAt', 'owner', 'description']\n\nexport default {\n  name: 'TaskForm',\n  props: {\n    record: {\n      type: Object,\n      default: null\n    }\n  },\n  data () {\n    return {\n      labelCol: {\n        xs: { span: 24 },\n        sm: { span: 7 }\n      },\n      wrapperCol: {\n        xs: { span: 24 },\n        sm: { span: 13 }\n      },\n      form: this.$form.createForm(this)\n    }\n  },\n  mounted () {\n    this.record && this.form.setFieldsValue(pick(this.record, fields))\n  },\n  methods: {\n    onOk () {\n      console.log('监听了 modal ok 事件')\n      return new Promise(resolve => {\n        resolve(true)\n      })\n    },\n    onCancel () {\n      console.log('监听了 modal cancel 事件')\n      return new Promise(resolve => {\n        resolve(true)\n      })\n    },\n    handleSubmit () {\n      const { form: { validateFields } } = this\n      this.visible = true\n      validateFields((errors, values) => {\n        if (!errors) {\n          console.log('values', values)\n        }\n      })\n    }\n  }\n}\n</script>\n"
  },
  {
    "path": "src/views/list/search/Applications.vue",
    "content": "<template>\n  <div>\n    <a-card :bordered=\"false\" class=\"ant-pro-components-tag-select\">\n      <a-form :form=\"form\" layout=\"inline\">\n        <standard-form-row title=\"所属类目\" block style=\"padding-bottom: 11px;\">\n          <a-form-item>\n            <tag-select>\n              <tag-select-option value=\"Category1\">类目一</tag-select-option>\n              <tag-select-option value=\"Category2\">类目二</tag-select-option>\n              <tag-select-option value=\"Category3\">类目三</tag-select-option>\n              <tag-select-option value=\"Category4\">类目四</tag-select-option>\n              <tag-select-option value=\"Category5\">类目五</tag-select-option>\n              <tag-select-option value=\"Category6\">类目六</tag-select-option>\n              <tag-select-option value=\"Category7\">类目七</tag-select-option>\n              <tag-select-option value=\"Category8\">类目八</tag-select-option>\n              <tag-select-option value=\"Category9\">类目九</tag-select-option>\n              <tag-select-option value=\"Category10\">类目十</tag-select-option>\n            </tag-select>\n          </a-form-item>\n        </standard-form-row>\n\n        <standard-form-row title=\"其它选项\" grid last>\n          <a-row>\n            <a-col :lg=\"8\" :md=\"10\" :sm=\"10\" :xs=\"24\">\n              <a-form-item :wrapper-col=\"{ sm: { span: 16 }, xs: { span: 24 } }\" label=\"作者\">\n                <a-select\n                  style=\"max-width: 200px; width: 100%;\"\n                  mode=\"multiple\"\n                  placeholder=\"不限\"\n                  v-decorator=\"['author']\"\n                  @change=\"handleChange\"\n                >\n                  <a-select-option value=\"lisa\">王昭君</a-select-option>\n                </a-select>\n              </a-form-item>\n            </a-col>\n            <a-col :lg=\"8\" :md=\"10\" :sm=\"10\" :xs=\"24\">\n              <a-form-item :wrapper-col=\"{ sm: { span: 16 }, xs: { span: 24 } }\" label=\"好评度\">\n                <a-select style=\"max-width: 200px; width: 100%;\" placeholder=\"不限\" v-decorator=\"['rate']\">\n                  <a-select-option value=\"good\">优秀</a-select-option>\n                  <a-select-option value=\"normal\">普通</a-select-option>\n                </a-select>\n              </a-form-item>\n            </a-col>\n          </a-row>\n        </standard-form-row>\n      </a-form>\n    </a-card>\n\n    <div class=\"ant-pro-pages-list-applications-filterCardList\">\n      <a-list\n        :loading=\"loading\"\n        :data-source=\"data\"\n        :grid=\"{ gutter: 24, xl: 4, lg: 3, md: 3, sm: 2, xs: 1 }\"\n        style=\"margin-top: 24px;\"\n      >\n        <a-list-item slot=\"renderItem\" slot-scope=\"item\">\n          <a-card :body-style=\"{ paddingBottom: 20 }\" hoverable>\n            <a-card-meta :title=\"item.title\">\n              <template slot=\"avatar\">\n                <a-avatar size=\"small\" :src=\"item.avatar\" />\n              </template>\n            </a-card-meta>\n            <template slot=\"actions\">\n              <a-tooltip title=\"下载\">\n                <a-icon type=\"download\" />\n              </a-tooltip>\n              <a-tooltip title=\"编辑\">\n                <a-icon type=\"edit\" />\n              </a-tooltip>\n              <a-tooltip title=\"分享\">\n                <a-icon type=\"share-alt\" />\n              </a-tooltip>\n              <a-dropdown>\n                <a class=\"ant-dropdown-link\">\n                  <a-icon type=\"ellipsis\" />\n                </a>\n                <a-menu slot=\"overlay\">\n                  <a-menu-item>\n                    <a href=\"javascript:;\">1st menu item</a>\n                  </a-menu-item>\n                  <a-menu-item>\n                    <a href=\"javascript:;\">2nd menu item</a>\n                  </a-menu-item>\n                  <a-menu-item>\n                    <a href=\"javascript:;\">3rd menu item</a>\n                  </a-menu-item>\n                </a-menu>\n              </a-dropdown>\n            </template>\n            <div class=\"\">\n              <card-info active-user=\"100\" new-user=\"999\"></card-info>\n            </div>\n          </a-card>\n        </a-list-item>\n      </a-list>\n    </div>\n  </div>\n</template>\n\n<script>\nimport moment from 'moment'\nimport { TagSelect, StandardFormRow, Ellipsis, AvatarList } from '@/components'\nimport CardInfo from './components/CardInfo'\nconst TagSelectOption = TagSelect.Option\nconst AvatarListItem = AvatarList.Item\n\nexport default {\n  components: {\n    AvatarList,\n    AvatarListItem,\n    Ellipsis,\n    TagSelect,\n    TagSelectOption,\n    StandardFormRow,\n    CardInfo\n  },\n  data () {\n    return {\n      data: [],\n      form: this.$form.createForm(this),\n      loading: true\n    }\n  },\n  filters: {\n    fromNow (date) {\n      return moment(date).fromNow()\n    }\n  },\n  mounted () {\n    this.getList()\n  },\n  methods: {\n    handleChange (value) {\n      console.log(`selected ${value}`)\n    },\n    getList () {\n      this.$http.get('/list/article', { params: { count: 8 } }).then(res => {\n        console.log('res', res)\n        this.data = res.result\n        this.loading = false\n      })\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n.ant-pro-components-tag-select {\n  :deep(.ant-pro-tag-select .ant-tag) {\n    margin-right: 24px;\n    padding: 0 8px;\n    font-size: 14px;\n  }\n}\n.ant-pro-pages-list-projects-cardList {\n  margin-top: 24px;\n\n  :deep(.ant-card-meta-title) {\n    margin-bottom: 4px;\n  }\n\n  :deep(.ant-card-meta-description) {\n    height: 44px;\n    overflow: hidden;\n    line-height: 22px;\n  }\n\n  .cardItemContent {\n    display: flex;\n    height: 20px;\n    margin-top: 16px;\n    margin-bottom: -4px;\n    line-height: 20px;\n\n    > span {\n      flex: 1 1;\n      color: rgba(0, 0, 0, 0.45);\n      font-size: 12px;\n    }\n\n    :deep(.ant-pro-avatar-list) {\n      flex: 0 1 auto;\n    }\n  }\n}\n</style>\n"
  },
  {
    "path": "src/views/list/search/Article.vue",
    "content": "<template>\n  <div>\n    <a-card :bordered=\"false\" class=\"ant-pro-components-tag-select\">\n      <a-form :form=\"form\" layout=\"inline\">\n        <standard-form-row title=\"所属类目\" block style=\"padding-bottom: 11px;\">\n          <a-form-item>\n            <tag-select>\n              <tag-select-option value=\"Category1\">类目一</tag-select-option>\n              <tag-select-option value=\"Category2\">类目二</tag-select-option>\n              <tag-select-option value=\"Category3\">类目三</tag-select-option>\n              <tag-select-option value=\"Category4\">类目四</tag-select-option>\n              <tag-select-option value=\"Category5\">类目五</tag-select-option>\n              <tag-select-option value=\"Category6\">类目六</tag-select-option>\n              <tag-select-option value=\"Category7\">类目七</tag-select-option>\n              <tag-select-option value=\"Category8\">类目八</tag-select-option>\n              <tag-select-option value=\"Category9\">类目九</tag-select-option>\n              <tag-select-option value=\"Category10\">类目十</tag-select-option>\n            </tag-select>\n          </a-form-item>\n        </standard-form-row>\n\n        <standard-form-row title=\"owner\" grid>\n          <a-row>\n            <a-col :md=\"24\">\n              <a-form-item :wrapper-col=\"{ span: 24 }\">\n                <a-select\n                  style=\"max-width: 268px; width: 100%;\"\n                  mode=\"multiple\"\n                  placeholder=\"选择 onwer\"\n                  v-decorator=\"['owner']\"\n                  @change=\"handleChange\"\n                >\n                  <a-select-option v-for=\"item in owners\" :key=\"item.id\">{{ item.name }}</a-select-option>\n                </a-select>\n                <a class=\"list-articles-trigger\" @click=\"setOwner\">只看自己的</a>\n              </a-form-item>\n            </a-col>\n          </a-row>\n        </standard-form-row>\n\n        <standard-form-row title=\"其它选项\" grid last>\n          <a-row :gutter=\"16\">\n            <a-col :xs=\"24\" :sm=\"24\" :md=\"12\" :lg=\"10\" :xl=\"8\">\n              <a-form-item label=\"活跃用户\" :wrapper-col=\"{ xs: 24, sm: 24, md: 12 }\">\n                <a-select placeholder=\"不限\" style=\"max-width: 200px; width: 100%;\">\n                  <a-select-option value=\"李三\">李三</a-select-option>\n                </a-select>\n              </a-form-item>\n            </a-col>\n            <a-col :xs=\"24\" :sm=\"24\" :md=\"12\" :lg=\"10\" :xl=\"8\">\n              <a-form-item label=\"好评度\" :wrapper-col=\"{ xs: 24, sm: 24, md: 12 }\">\n                <a-select placeholder=\"不限\" style=\"max-width: 200px; width: 100%;\">\n                  <a-select-option value=\"优秀\">优秀</a-select-option>\n                </a-select>\n              </a-form-item>\n            </a-col>\n          </a-row>\n        </standard-form-row>\n      </a-form>\n    </a-card>\n\n    <a-card style=\"margin-top: 24px;\" :bordered=\"false\">\n      <a-list\n        size=\"large\"\n        rowKey=\"id\"\n        :loading=\"loading\"\n        itemLayout=\"vertical\"\n        :dataSource=\"data\"\n      >\n        <a-list-item :key=\"item.id\" slot=\"renderItem\" slot-scope=\"item\">\n          <template slot=\"actions\">\n            <icon-text type=\"star-o\" :text=\"item.star\" />\n            <icon-text type=\"like-o\" :text=\"item.like\" />\n            <icon-text type=\"message\" :text=\"item.message\" />\n          </template>\n          <a-list-item-meta>\n            <a slot=\"title\" href=\"https://vue.ant.design/\">{{ item.title }}</a>\n            <template slot=\"description\">\n              <span>\n                <a-tag>Ant Design</a-tag>\n                <a-tag>设计语言</a-tag>\n                <a-tag>蚂蚁金服</a-tag>\n              </span>\n            </template>\n          </a-list-item-meta>\n          <article-list-content :description=\"item.description\" :owner=\"item.owner\" :avatar=\"item.avatar\" :href=\"item.href\" :updateAt=\"item.updatedAt\" />\n        </a-list-item>\n        <div slot=\"footer\" v-if=\"data.length > 0\" style=\"text-align: center; margin-top: 16px;\">\n          <a-button @click=\"loadMore\" :loading=\"loadingMore\">加载更多</a-button>\n        </div>\n      </a-list>\n    </a-card>\n  </div>\n</template>\n\n<script>\nimport { TagSelect, StandardFormRow, ArticleListContent } from '@/components'\nimport IconText from './components/IconText'\nconst TagSelectOption = TagSelect.Option\n\nconst owners = [\n  {\n    id: 'wzj',\n    name: '我自己'\n  },\n  {\n    id: 'wjh',\n    name: '吴家豪'\n  },\n  {\n    id: 'zxx',\n    name: '周星星'\n  },\n  {\n    id: 'zly',\n    name: '赵丽颖'\n  },\n  {\n    id: 'ym',\n    name: '姚明'\n  }\n]\n\nexport default {\n  components: {\n    TagSelect,\n    TagSelectOption,\n    StandardFormRow,\n    ArticleListContent,\n    IconText\n  },\n  data () {\n    return {\n      owners,\n      loading: true,\n      loadingMore: false,\n      data: [],\n      form: this.$form.createForm(this)\n    }\n  },\n  mounted () {\n    this.getList()\n  },\n  methods: {\n    handleChange (value) {\n      console.log(`selected ${value}`)\n    },\n    getList () {\n      this.$http.get('/list/article').then(res => {\n        console.log('res', res)\n        this.data = res.result\n        this.loading = false\n      })\n    },\n    loadMore () {\n      this.loadingMore = true\n      this.$http.get('/list/article').then(res => {\n        this.data = this.data.concat(res.result)\n      }).finally(() => {\n        this.loadingMore = false\n      })\n    },\n    setOwner () {\n      const { form: { setFieldsValue } } = this\n      setFieldsValue({\n        owner: ['wzj']\n      })\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n.ant-pro-components-tag-select {\n  :deep(.ant-pro-tag-select .ant-tag) {\n    margin-right: 24px;\n    padding: 0 8px;\n    font-size: 14px;\n  }\n}\n\n.list-articles-trigger {\n  margin-left: 12px;\n}\n</style>\n"
  },
  {
    "path": "src/views/list/search/Projects.vue",
    "content": "<template>\n  <div>\n    <a-card :bordered=\"false\" class=\"ant-pro-components-tag-select\">\n      <a-form :form=\"form\" layout=\"inline\">\n        <standard-form-row title=\"所属类目\" block style=\"padding-bottom: 11px;\">\n          <a-form-item>\n            <tag-select>\n              <tag-select-option value=\"Category1\">类目一</tag-select-option>\n              <tag-select-option value=\"Category2\">类目二</tag-select-option>\n              <tag-select-option value=\"Category3\">类目三</tag-select-option>\n              <tag-select-option value=\"Category4\">类目四</tag-select-option>\n              <tag-select-option value=\"Category5\">类目五</tag-select-option>\n              <tag-select-option value=\"Category6\">类目六</tag-select-option>\n              <tag-select-option value=\"Category7\">类目七</tag-select-option>\n              <tag-select-option value=\"Category8\">类目八</tag-select-option>\n              <tag-select-option value=\"Category9\">类目九</tag-select-option>\n              <tag-select-option value=\"Category10\">类目十</tag-select-option>\n            </tag-select>\n          </a-form-item>\n        </standard-form-row>\n\n        <standard-form-row title=\"其它选项\" grid last>\n          <a-row>\n            <a-col :lg=\"8\" :md=\"10\" :sm=\"10\" :xs=\"24\">\n              <a-form-item :wrapper-col=\"{ sm: { span: 16 }, xs: { span: 24 } }\" label=\"作者\">\n                <a-select\n                  style=\"max-width: 200px; width: 100%;\"\n                  mode=\"multiple\"\n                  placeholder=\"不限\"\n                  v-decorator=\"['author']\"\n                  @change=\"handleChange\"\n                >\n                  <a-select-option value=\"lisa\">王昭君</a-select-option>\n                </a-select>\n              </a-form-item>\n            </a-col>\n            <a-col :lg=\"8\" :md=\"10\" :sm=\"10\" :xs=\"24\">\n              <a-form-item :wrapper-col=\"{ sm: { span: 16 }, xs: { span: 24 } }\" label=\"好评度\">\n                <a-select\n                  style=\"max-width: 200px; width: 100%;\"\n                  placeholder=\"不限\"\n                  v-decorator=\"['rate']\"\n                >\n                  <a-select-option value=\"good\">优秀</a-select-option>\n                  <a-select-option value=\"normal\">普通</a-select-option>\n                </a-select>\n              </a-form-item>\n            </a-col>\n          </a-row>\n        </standard-form-row>\n      </a-form>\n    </a-card>\n\n    <div class=\"ant-pro-pages-list-projects-cardList\">\n      <a-list :loading=\"loading\" :data-source=\"data\" :grid=\"{ gutter: 24, xl: 4, lg: 3, md: 3, sm: 2, xs: 1 }\">\n        <a-list-item slot=\"renderItem\" slot-scope=\"item\">\n          <a-card class=\"ant-pro-pages-list-projects-card\" hoverable>\n            <img slot=\"cover\" :src=\"item.cover\" :alt=\"item.title\" />\n            <a-card-meta :title=\"item.title\">\n              <template slot=\"description\">\n                <ellipsis :length=\"50\">{{ item.description }}</ellipsis>\n              </template>\n            </a-card-meta>\n            <div class=\"cardItemContent\">\n              <span>{{ item.updatedAt | fromNow }}</span>\n              <div class=\"avatarList\">\n                <avatar-list size=\"small\" :max-length=\"2\">\n                  <avatar-list-item\n                    v-for=\"(member, i) in item.members\"\n                    :key=\"`${item.id}-avatar-${i}`\"\n                    :src=\"member.avatar\"\n                    :tips=\"member.name\"\n                  />\n                </avatar-list>\n              </div>\n            </div>\n          </a-card>\n        </a-list-item>\n      </a-list>\n    </div>\n  </div>\n</template>\n\n<script>\nimport moment from 'moment'\nimport { TagSelect, StandardFormRow, Ellipsis, AvatarList } from '@/components'\nconst TagSelectOption = TagSelect.Option\nconst AvatarListItem = AvatarList.Item\n\nexport default {\n  components: {\n    AvatarList,\n    AvatarListItem,\n    Ellipsis,\n    TagSelect,\n    TagSelectOption,\n    StandardFormRow\n  },\n  data () {\n    return {\n      data: [],\n      form: this.$form.createForm(this),\n      loading: true\n    }\n  },\n  filters: {\n    fromNow (date) {\n      return moment(date).fromNow()\n    }\n  },\n  mounted () {\n    this.getList()\n  },\n  methods: {\n    handleChange (value) {\n      console.log(`selected ${value}`)\n    },\n    getList () {\n      this.$http.get('/list/article', { params: { count: 8 } }).then(res => {\n        console.log('res', res)\n        this.data = res.result\n        this.loading = false\n      })\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n.ant-pro-components-tag-select {\n  :deep(.ant-pro-tag-select .ant-tag) {\n    margin-right: 24px;\n    padding: 0 8px;\n    font-size: 14px;\n  }\n}\n.ant-pro-pages-list-projects-cardList {\n  margin-top: 24px;\n\n  :deep(.ant-card-meta-title) {\n    margin-bottom: 4px;\n  }\n\n  :deep(.ant-card-meta-description) {\n    height: 44px;\n    overflow: hidden;\n    line-height: 22px;\n  }\n\n  .cardItemContent {\n    display: flex;\n    height: 20px;\n    margin-top: 16px;\n    margin-bottom: -4px;\n    line-height: 20px;\n\n    > span {\n      flex: 1 1;\n      color: rgba(0,0,0,.45);\n      font-size: 12px;\n    }\n\n    :deep(.ant-pro-avatar-list) {\n      flex: 0 1 auto;\n    }\n  }\n}\n</style>\n"
  },
  {
    "path": "src/views/list/search/SearchLayout.vue",
    "content": "<template>\n  <page-header-wrapper\n    :tab-list=\"tabList\"\n    :tab-active-key=\"tabActiveKey\"\n    :tab-change=\"handleTabChange\"\n  >\n    <template v-slot:content>\n      <div class=\"ant-pro-page-header-search\">\n        <a-input-search size=\"large\" style=\"width: 80%; max-width: 522px;\">\n          <template v-slot:enterButton>\n            搜索\n          </template>\n        </a-input-search>\n      </div>\n    </template>\n    <router-view />\n  </page-header-wrapper>\n</template>\n\n<script>\nconst getActiveKey = (path) => {\n  switch (path) {\n    case '/list/search/article':\n      return '1'\n    case '/list/search/project':\n      return '2'\n    case '/list/search/application':\n      return '3'\n    default:\n      return '1'\n  }\n}\nexport default {\n  name: 'SearchLayout',\n  data () {\n    return {\n      tabList: [\n        { key: '1', tab: '文章' },\n        { key: '2', tab: '项目' },\n        { key: '3', tab: '应用' }\n      ],\n      tabActiveKey: '1',\n      search: true\n    }\n  },\n  created () {\n    this.tabActiveKey = getActiveKey(this.$route.path)\n\n    this.$watch('$route', (val) => {\n      this.tabActiveKey = getActiveKey(val.path)\n    })\n  },\n  methods: {\n    handleTabChange (key) {\n      this.tabActiveKey = key\n      switch (key) {\n        case '1':\n          this.$router.push('/list/search/article')\n          break\n        case '2':\n          this.$router.push('/list/search/project')\n          break\n        case '3':\n          this.$router.push('/list/search/application')\n          break\n        default:\n          this.$router.push('/workplace')\n      }\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n.ant-pro-page-header-search {\n  text-align: center;\n  margin-bottom: 16px;\n}\n</style>\n"
  },
  {
    "path": "src/views/list/search/components/CardInfo.vue",
    "content": "<template>\n  <div class=\"cardInfo\">\n    <div>\n      <p>活跃用户</p>\n      <p>{{ activeUser }}</p>\n    </div>\n    <div>\n      <p>新增用户</p>\n      <p>{{ newUser }}</p>\n    </div>\n  </div>\n</template>\n\n<script>\nexport default {\n  name: 'CardInfo',\n  props: {\n    activeUser: {\n      type: [String, Number],\n      default: 0\n    },\n    newUser: {\n      type: [String, Number],\n      default: 0\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n@import \"~@/components/index.less\";\n@import \"~@/utils/utils.less\";\n\n.cardInfo {\n\n  .clearfix();\n\n  margin-top: 16px;\n  margin-left: 40px;\n  & > div {\n    position: relative;\n    float: left;\n    width: 50%;\n    text-align: left;\n    p {\n      margin: 0;\n      font-size: 24px;\n      line-height: 32px;\n    }\n    p:first-child {\n      margin-bottom: 4px;\n      color: @text-color-secondary;\n      font-size: 12px;\n      line-height: 20px;\n    }\n  }\n}\n</style>\n"
  },
  {
    "path": "src/views/list/search/components/IconText.vue",
    "content": "<template>\n  <span>\n    <a-icon :type=\"type\" style=\"margin-right: 8px\" />\n    {{ text }}\n  </span>\n</template>\n\n<script>\nexport default {\n  name: 'IconText',\n  props: {\n    'type': {\n      type: String,\n      required: true\n    },\n    text: {\n      type: [String, Number],\n      required: true\n    }\n  }\n}\n</script>\n"
  },
  {
    "path": "src/views/list/table/Edit.vue",
    "content": "<template>\n  <div>\n    <a-form :form=\"form\" @submit=\"handleSubmit\">\n\n      <a-form-item\n        :labelCol=\"labelCol\"\n        :wrapperCol=\"wrapperCol\"\n        label=\"规则编号\"\n        hasFeedback\n        validateStatus=\"success\"\n      >\n        <a-input\n          placeholder=\"规则编号\"\n          v-decorator=\"[\n            'no',\n            {rules: [{ required: true, message: '请输入规则编号' }]}\n          ]\"\n          :disabled=\"true\"\n        ></a-input>\n      </a-form-item>\n\n      <a-form-item\n        :labelCol=\"labelCol\"\n        :wrapperCol=\"wrapperCol\"\n        label=\"服务调用次数\"\n        hasFeedback\n        validateStatus=\"success\"\n      >\n        <a-input-number :min=\"1\" style=\"width: 100%\" v-decorator=\"['callNo', {rules: [{ required: true }]}]\" />\n      </a-form-item>\n\n      <a-form-item\n        :labelCol=\"labelCol\"\n        :wrapperCol=\"wrapperCol\"\n        label=\"状态\"\n        hasFeedback\n        validateStatus=\"warning\"\n      >\n        <a-select v-decorator=\"['status', {rules: [{ required: true, message: '请选择状态' }], initialValue: '1'}]\">\n          <a-select-option :value=\"1\">Option 1</a-select-option>\n          <a-select-option :value=\"2\">Option 2</a-select-option>\n          <a-select-option :value=\"3\">Option 3</a-select-option>\n        </a-select>\n      </a-form-item>\n\n      <a-form-item\n        :labelCol=\"labelCol\"\n        :wrapperCol=\"wrapperCol\"\n        label=\"描述\"\n        hasFeedback\n        help=\"请填写一段描述\"\n      >\n        <a-textarea :rows=\"5\" placeholder=\"...\" v-decorator=\"['description', {rules: [{ required: true }]}]\" />\n      </a-form-item>\n\n      <a-form-item\n        :labelCol=\"labelCol\"\n        :wrapperCol=\"wrapperCol\"\n        label=\"更新时间\"\n        hasFeedback\n        validateStatus=\"error\"\n      >\n        <a-date-picker\n          style=\"width: 100%\"\n          showTime\n          format=\"YYYY-MM-DD HH:mm:ss\"\n          placeholder=\"Select Time\"\n          v-decorator=\"['updatedAt']\"\n        />\n      </a-form-item>\n\n      <a-form-item\n        v-bind=\"buttonCol\"\n      >\n        <a-row>\n          <a-col span=\"6\">\n            <a-button type=\"primary\" html-type=\"submit\">提交</a-button>\n          </a-col>\n          <a-col span=\"10\">\n            <a-button @click=\"handleGoBack\">返回</a-button>\n          </a-col>\n          <a-col span=\"8\"></a-col>\n        </a-row>\n      </a-form-item>\n    </a-form>\n  </div>\n</template>\n\n<script>\nimport moment from 'moment'\nimport pick from 'lodash.pick'\n\nexport default {\n  name: 'TableEdit',\n  props: {\n    record: {\n      type: [Object, String],\n      default: ''\n    }\n  },\n  data () {\n    return {\n      labelCol: {\n        xs: { span: 24 },\n        sm: { span: 5 }\n      },\n      wrapperCol: {\n        xs: { span: 24 },\n        sm: { span: 12 }\n      },\n      buttonCol: {\n        wrapperCol: {\n          xs: { span: 24 },\n          sm: { span: 12, offset: 5 }\n        }\n      },\n      form: this.$form.createForm(this),\n      id: 0\n    }\n  },\n  // beforeCreate () {\n  //   this.form = this.$form.createForm(this)\n  // },\n  mounted () {\n    this.$nextTick(() => {\n      this.loadEditInfo(this.record)\n    })\n  },\n  methods: {\n    handleGoBack () {\n      this.$emit('onGoBack')\n    },\n    handleSubmit () {\n      const { form: { validateFields } } = this\n      validateFields((err, values) => {\n        if (!err) {\n          // eslint-disable-next-line no-console\n          console.log('Received values of form: ', values)\n        }\n      })\n    },\n    handleGetInfo () {\n\n    },\n    loadEditInfo (data) {\n      const { form } = this\n      // ajax\n      console.log(`将加载 ${this.id} 信息到表单`)\n      new Promise((resolve) => {\n        setTimeout(resolve, 1500)\n      }).then(() => {\n        const formData = pick(data, ['no', 'callNo', 'status', 'description', 'updatedAt'])\n        formData.updatedAt = moment(data.updatedAt)\n        console.log('formData', formData)\n        form.setFieldsValue(formData)\n      })\n    }\n  }\n}\n</script>\n"
  },
  {
    "path": "src/views/list/table/List.vue",
    "content": "<template>\n  <div>\n    <div class=\"table-page-search-wrapper\">\n      <a-form layout=\"inline\">\n        <a-row :gutter=\"48\">\n          <a-col :md=\"8\" :sm=\"24\">\n            <a-form-item label=\"规则编号\">\n              <a-input v-model=\"queryParam.id\" placeholder=\"\"/>\n            </a-form-item>\n          </a-col>\n          <a-col :md=\"8\" :sm=\"24\">\n            <a-form-item label=\"使用状态\">\n              <a-select v-model=\"queryParam.status\" placeholder=\"请选择\" default-value=\"0\">\n                <a-select-option value=\"0\">全部</a-select-option>\n                <a-select-option value=\"1\">关闭</a-select-option>\n                <a-select-option value=\"2\">运行中</a-select-option>\n              </a-select>\n            </a-form-item>\n          </a-col>\n          <template v-if=\"advanced\">\n            <a-col :md=\"8\" :sm=\"24\">\n              <a-form-item label=\"调用次数\">\n                <a-input-number v-model=\"queryParam.callNo\" style=\"width: 100%\"/>\n              </a-form-item>\n            </a-col>\n            <a-col :md=\"8\" :sm=\"24\">\n              <a-form-item label=\"更新日期\">\n                <a-date-picker v-model=\"queryParam.date\" style=\"width: 100%\" placeholder=\"请输入更新日期\"/>\n              </a-form-item>\n            </a-col>\n            <a-col :md=\"8\" :sm=\"24\">\n              <a-form-item label=\"使用状态\">\n                <a-select v-model=\"queryParam.useStatus\" placeholder=\"请选择\" default-value=\"0\">\n                  <a-select-option value=\"0\">全部</a-select-option>\n                  <a-select-option value=\"1\">关闭</a-select-option>\n                  <a-select-option value=\"2\">运行中</a-select-option>\n                </a-select>\n              </a-form-item>\n            </a-col>\n            <a-col :md=\"8\" :sm=\"24\">\n              <a-form-item label=\"使用状态\">\n                <a-select placeholder=\"请选择\" default-value=\"0\">\n                  <a-select-option value=\"0\">全部</a-select-option>\n                  <a-select-option value=\"1\">关闭</a-select-option>\n                  <a-select-option value=\"2\">运行中</a-select-option>\n                </a-select>\n              </a-form-item>\n            </a-col>\n          </template>\n          <a-col :md=\"!advanced && 8 || 24\" :sm=\"24\">\n            <span class=\"table-page-search-submitButtons\" :style=\"advanced && { float: 'right', overflow: 'hidden' } || {} \">\n              <a-button type=\"primary\" @click=\"$refs.table.refresh(true)\">查询</a-button>\n              <a-button style=\"margin-left: 8px\" @click=\"() => queryParam = {}\">重置</a-button>\n              <a @click=\"toggleAdvanced\" style=\"margin-left: 8px\">\n                {{ advanced ? '收起' : '展开' }}\n                <a-icon :type=\"advanced ? 'up' : 'down'\"/>\n              </a>\n            </span>\n          </a-col>\n        </a-row>\n      </a-form>\n    </div>\n\n    <div class=\"table-operator\">\n      <a-button type=\"primary\" icon=\"plus\" @click=\"handleEdit()\">新建</a-button>\n      <a-button type=\"dashed\" @click=\"tableOption\">{{ optionAlertShow && '关闭' || '开启' }} alert</a-button>\n      <a-dropdown v-action:edit v-if=\"selectedRowKeys.length > 0\">\n        <a-menu slot=\"overlay\">\n          <a-menu-item key=\"1\"><a-icon type=\"delete\" />删除</a-menu-item>\n          <!-- lock | unlock -->\n          <a-menu-item key=\"2\"><a-icon type=\"lock\" />锁定</a-menu-item>\n        </a-menu>\n        <a-button style=\"margin-left: 8px\">\n          批量操作 <a-icon type=\"down\" />\n        </a-button>\n      </a-dropdown>\n    </div>\n\n    <s-table\n      ref=\"table\"\n      size=\"default\"\n      rowKey=\"key\"\n      :columns=\"columns\"\n      :data=\"loadData\"\n      :alert=\"options.alert\"\n      :rowSelection=\"options.rowSelection\"\n    >\n      <span slot=\"serial\" slot-scope=\"text, record, index\">\n        {{ index + 1 }}\n      </span>\n      <span slot=\"action\" slot-scope=\"text, record\">\n        <template>\n          <a @click=\"handleEdit(record)\">编辑</a>\n          <a-divider type=\"vertical\" />\n        </template>\n        <a-dropdown>\n          <a class=\"ant-dropdown-link\">\n            更多 <a-icon type=\"down\" />\n          </a>\n          <a-menu slot=\"overlay\">\n            <a-menu-item>\n              <a href=\"javascript:;\">详情</a>\n            </a-menu-item>\n            <a-menu-item v-if=\"$auth('table.disable')\">\n              <a href=\"javascript:;\">禁用</a>\n            </a-menu-item>\n            <a-menu-item v-if=\"$auth('table.delete')\">\n              <a href=\"javascript:;\">删除</a>\n            </a-menu-item>\n          </a-menu>\n        </a-dropdown>\n      </span>\n    </s-table>\n  </div>\n</template>\n\n<script>\nimport moment from 'moment'\nimport { STable } from '@/components'\nimport { getRoleList, getServiceList } from '@/api/manage'\n\nexport default {\n  name: 'TableList',\n  components: {\n    STable\n  },\n  data () {\n    return {\n      mdl: {},\n      // 高级搜索 展开/关闭\n      advanced: false,\n      // 查询参数\n      queryParam: {},\n      // 表头\n      columns: [\n        {\n          title: '#',\n          scopedSlots: { customRender: 'serial' }\n        },\n        {\n          title: '规则编号',\n          dataIndex: 'no'\n        },\n        {\n          title: '描述',\n          dataIndex: 'description'\n        },\n        {\n          title: '服务调用次数',\n          dataIndex: 'callNo',\n          sorter: true,\n          needTotal: true,\n          customRender: (text) => text + ' 次'\n        },\n        {\n          title: '状态',\n          dataIndex: 'status',\n          needTotal: true\n        },\n        {\n          title: '更新时间',\n          dataIndex: 'updatedAt',\n          sorter: true\n        },\n        {\n          title: '操作',\n          dataIndex: 'action',\n          width: '150px',\n          scopedSlots: { customRender: 'action' }\n        }\n      ],\n      // 加载数据方法 必须为 Promise 对象\n      loadData: parameter => {\n        console.log('loadData.parameter', parameter)\n        return getServiceList(Object.assign(parameter, this.queryParam))\n          .then(res => {\n            return res.result\n          })\n      },\n      selectedRowKeys: [],\n      selectedRows: [],\n\n      // custom table alert & rowSelection\n      options: {\n        alert: { show: true, clear: () => { this.selectedRowKeys = [] } },\n        rowSelection: {\n          selectedRowKeys: this.selectedRowKeys,\n          onChange: this.onSelectChange\n        }\n      },\n      optionAlertShow: false\n    }\n  },\n  created () {\n    this.tableOption()\n    getRoleList({ t: new Date() })\n  },\n  methods: {\n    tableOption () {\n      if (!this.optionAlertShow) {\n        this.options = {\n          alert: { show: true, clear: () => { this.selectedRowKeys = [] } },\n          rowSelection: {\n            selectedRowKeys: this.selectedRowKeys,\n            onChange: this.onSelectChange\n          }\n        }\n        this.optionAlertShow = true\n      } else {\n        this.options = {\n          alert: false,\n          rowSelection: null\n        }\n        this.optionAlertShow = false\n      }\n    },\n\n    handleEdit (record) {\n      this.$emit('onEdit', record)\n    },\n    handleOk () {\n\n    },\n\n    onSelectChange (selectedRowKeys, selectedRows) {\n      this.selectedRowKeys = selectedRowKeys\n      this.selectedRows = selectedRows\n    },\n    toggleAdvanced () {\n      this.advanced = !this.advanced\n    },\n\n    resetSearchForm () {\n      this.queryParam = {\n        date: moment(new Date())\n      }\n    }\n  }\n}\n</script>\n"
  },
  {
    "path": "src/views/other/BigForm.vue",
    "content": "<template>\n  <a-card :bordered=\"false\">\n    <a-form :form=\"form1\" :self-update=\"true\" @submit=\"handleForm1Submit\">\n      <a-row class=\"form-row\" :gutter=\"16\">\n        <a-col :lg=\"6\" :md=\"12\" :sm=\"24\">\n          <a-form-item label=\"仓库名\">\n            <a-input\n              placeholder=\"请输入仓库名称\"\n              v-decorator=\"[\n                'name',\n                {rules: [{ required: true, message: '请输入仓库名称', whitespace: true}]}\n              ]\" />\n          </a-form-item>\n        </a-col>\n        <a-col :xl=\"{span: 7, offset: 1}\" :lg=\"{span: 8}\" :md=\"{span: 12}\" :sm=\"24\">\n          <a-form-item\n            label=\"仓库域名\">\n            <a-input\n              addonBefore=\"http://\"\n              addonAfter=\".com\"\n              placeholder=\"请输入\"\n              v-decorator=\"[\n                'url',\n                {rules: [{ required: true, message: '请输入仓库域名', whitespace: true}]}\n              ]\" />\n          </a-form-item>\n        </a-col>\n        <a-col :xl=\"{span: 9, offset: 1}\" :lg=\"{span: 10}\" :md=\"{span: 24}\" :sm=\"24\">\n          <a-form-item\n            label=\"仓库管理员\">\n            <a-select placeholder=\"请选择管理员\" v-decorator=\"[ 'owner', {rules: [{ required: true, message: '请选择管理员'}]} ]\">\n              <a-select-option value=\"王同学\">王同学</a-select-option>\n              <a-select-option value=\"李同学\">李同学</a-select-option>\n              <a-select-option value=\"黄同学\">黄同学</a-select-option>\n            </a-select>\n          </a-form-item>\n        </a-col>\n      </a-row>\n      <a-row class=\"form-row\" :gutter=\"16\">\n        <a-col :lg=\"6\" :md=\"12\" :sm=\"24\">\n          <a-form-item\n            label=\"审批人\">\n            <a-select placeholder=\"请选择审批员\" v-decorator=\"[ 'approver', {rules: [{ required: true, message: '请选择审批员'}]} ]\">\n              <a-select-option value=\"王晓丽\">王晓丽</a-select-option>\n              <a-select-option value=\"李军\">李军</a-select-option>\n            </a-select>\n          </a-form-item>\n        </a-col>\n        <a-col :xl=\"{span: 7, offset: 1}\" :lg=\"{span: 8}\" :md=\"{span: 12}\" :sm=\"24\">\n          <a-form-item\n            label=\"生效日期\">\n            <a-range-picker\n              style=\"width: 100%\"\n              v-decorator=\"[\n                'dateRange',\n                {rules: [{ required: true, message: '请选择生效日期'}]}\n              ]\" />\n          </a-form-item>\n        </a-col>\n        <a-col :xl=\"{span: 9, offset: 1}\" :lg=\"{span: 10}\" :md=\"{span: 24}\" :sm=\"24\">\n          <a-form-item\n            label=\"仓库类型\">\n            <a-select\n              placeholder=\"请选择仓库类型\"\n              v-decorator=\"[\n                'type',\n                {rules: [{ required: true, message: '请选择仓库类型'}]}\n              ]\" >\n              <a-select-option value=\"公开\">公开</a-select-option>\n              <a-select-option value=\"私密\">私密</a-select-option>\n            </a-select>\n          </a-form-item>\n        </a-col>\n      </a-row>\n      <a-form-item v-if=\"showSubmit\">\n        <a-button htmlType=\"submit\" >Submit</a-button>\n      </a-form-item>\n    </a-form>\n\n    <a-form :form=\"form2\" :self-update=\"true\" @submit=\"handleForm2Submit\">\n      <a-row class=\"form-row\" :gutter=\"16\">\n        <a-col :lg=\"6\" :md=\"12\" :sm=\"24\">\n          <a-form-item label=\"仓库名\">\n            <a-input\n              placeholder=\"请输入仓库名称\"\n              v-decorator=\"[\n                'name',\n                {rules: [{ required: true, message: '请输入仓库名称', whitespace: true}]}\n              ]\" />\n          </a-form-item>\n        </a-col>\n        <a-col :xl=\"{span: 7, offset: 1}\" :lg=\"{span: 8}\" :md=\"{span: 12}\" :sm=\"24\">\n          <a-form-item\n            label=\"仓库域名\">\n            <a-input\n              addonBefore=\"http://\"\n              addonAfter=\".com\"\n              placeholder=\"请输入\"\n              v-decorator=\"[\n                'url',\n                {rules: [{ required: true, message: '请输入仓库域名', whitespace: true}]}\n              ]\" />\n          </a-form-item>\n        </a-col>\n        <a-col :xl=\"{span: 9, offset: 1}\" :lg=\"{span: 10}\" :md=\"{span: 24}\" :sm=\"24\">\n          <a-form-item\n            label=\"仓库管理员\">\n            <a-select placeholder=\"请选择管理员\" v-decorator=\"[ 'owner', {rules: [{ required: true, message: '请选择管理员'}]} ]\">\n              <a-select-option value=\"王同学\">王同学</a-select-option>\n              <a-select-option value=\"李同学\">李同学</a-select-option>\n              <a-select-option value=\"黄同学\">黄同学</a-select-option>\n            </a-select>\n          </a-form-item>\n        </a-col>\n      </a-row>\n      <a-row class=\"form-row\" :gutter=\"16\">\n        <a-col :lg=\"6\" :md=\"12\" :sm=\"24\">\n          <a-form-item\n            label=\"审批人\">\n            <a-select placeholder=\"请选择审批员\" v-decorator=\"[ 'approver', {rules: [{ required: true, message: '请选择审批员'}]} ]\">\n              <a-select-option value=\"王晓丽\">王晓丽</a-select-option>\n              <a-select-option value=\"李军\">李军</a-select-option>\n            </a-select>\n          </a-form-item>\n        </a-col>\n        <a-col :xl=\"{span: 7, offset: 1}\" :lg=\"{span: 8}\" :md=\"{span: 12}\" :sm=\"24\">\n          <a-form-item\n            label=\"生效日期\">\n            <a-range-picker\n              style=\"width: 100%\"\n              v-decorator=\"[\n                'dateRange',\n                {rules: [{ required: true, message: '请选择生效日期'}]}\n              ]\" />\n          </a-form-item>\n        </a-col>\n        <a-col :xl=\"{span: 9, offset: 1}\" :lg=\"{span: 10}\" :md=\"{span: 24}\" :sm=\"24\">\n          <a-form-item\n            label=\"仓库类型\">\n            <a-select\n              placeholder=\"请选择仓库类型\"\n              v-decorator=\"[\n                'type',\n                {rules: [{ required: true, message: '请选择仓库类型'}]}\n              ]\" >\n              <a-select-option value=\"公开\">公开</a-select-option>\n              <a-select-option value=\"私密\">私密</a-select-option>\n            </a-select>\n          </a-form-item>\n        </a-col>\n      </a-row>\n      <a-form-item v-if=\"showSubmit\">\n        <a-button htmlType=\"submit\" >Submit</a-button>\n      </a-form-item>\n    </a-form>\n\n    <a-form :form=\"form3\" :self-update=\"true\" @submit=\"handleForm2Submit\">\n      <a-row class=\"form-row\" :gutter=\"16\">\n        <a-col :lg=\"6\" :md=\"12\" :sm=\"24\">\n          <a-form-item label=\"仓库名\">\n            <a-input\n              placeholder=\"请输入仓库名称\"\n              v-decorator=\"[\n                'name',\n                {rules: [{ required: true, message: '请输入仓库名称', whitespace: true}]}\n              ]\" />\n          </a-form-item>\n        </a-col>\n        <a-col :xl=\"{span: 7, offset: 1}\" :lg=\"{span: 8}\" :md=\"{span: 12}\" :sm=\"24\">\n          <a-form-item\n            label=\"仓库域名\">\n            <a-input\n              addonBefore=\"http://\"\n              addonAfter=\".com\"\n              placeholder=\"请输入\"\n              v-decorator=\"[\n                'url',\n                {rules: [{ required: true, message: '请输入仓库域名', whitespace: true}]}\n              ]\" />\n          </a-form-item>\n        </a-col>\n        <a-col :xl=\"{span: 9, offset: 1}\" :lg=\"{span: 10}\" :md=\"{span: 24}\" :sm=\"24\">\n          <a-form-item\n            label=\"仓库管理员\">\n            <a-select placeholder=\"请选择管理员\" v-decorator=\"[ 'owner', {rules: [{ required: true, message: '请选择管理员'}]} ]\">\n              <a-select-option value=\"王同学\">王同学</a-select-option>\n              <a-select-option value=\"李同学\">李同学</a-select-option>\n              <a-select-option value=\"黄同学\">黄同学</a-select-option>\n            </a-select>\n          </a-form-item>\n        </a-col>\n      </a-row>\n      <a-row class=\"form-row\" :gutter=\"16\">\n        <a-col :lg=\"6\" :md=\"12\" :sm=\"24\">\n          <a-form-item\n            label=\"审批人\">\n            <a-select placeholder=\"请选择审批员\" v-decorator=\"[ 'approver', {rules: [{ required: true, message: '请选择审批员'}]} ]\">\n              <a-select-option value=\"王晓丽\">王晓丽</a-select-option>\n              <a-select-option value=\"李军\">李军</a-select-option>\n            </a-select>\n          </a-form-item>\n        </a-col>\n        <a-col :xl=\"{span: 7, offset: 1}\" :lg=\"{span: 8}\" :md=\"{span: 12}\" :sm=\"24\">\n          <a-form-item\n            label=\"生效日期\">\n            <a-range-picker\n              style=\"width: 100%\"\n              v-decorator=\"[\n                'dateRange',\n                {rules: [{ required: true, message: '请选择生效日期'}]}\n              ]\" />\n          </a-form-item>\n        </a-col>\n        <a-col :xl=\"{span: 9, offset: 1}\" :lg=\"{span: 10}\" :md=\"{span: 24}\" :sm=\"24\">\n          <a-form-item\n            label=\"仓库类型\">\n            <a-select\n              placeholder=\"请选择仓库类型\"\n              v-decorator=\"[\n                'type',\n                {rules: [{ required: true, message: '请选择仓库类型'}]}\n              ]\" >\n              <a-select-option value=\"公开\">公开</a-select-option>\n              <a-select-option value=\"私密\">私密</a-select-option>\n            </a-select>\n          </a-form-item>\n        </a-col>\n      </a-row>\n      <a-form-item v-if=\"showSubmit\">\n        <a-button htmlType=\"submit\" >Submit</a-button>\n      </a-form-item>\n    </a-form>\n\n    <a-form :form=\"form4\" :self-update=\"true\" @submit=\"handleForm2Submit\">\n      <a-row class=\"form-row\" :gutter=\"16\">\n        <a-col :lg=\"6\" :md=\"12\" :sm=\"24\">\n          <a-form-item label=\"仓库名\">\n            <a-input\n              placeholder=\"请输入仓库名称\"\n              v-decorator=\"[\n                'name',\n                {rules: [{ required: true, message: '请输入仓库名称', whitespace: true}]}\n              ]\" />\n          </a-form-item>\n        </a-col>\n        <a-col :xl=\"{span: 7, offset: 1}\" :lg=\"{span: 8}\" :md=\"{span: 12}\" :sm=\"24\">\n          <a-form-item\n            label=\"仓库域名\">\n            <a-input\n              addonBefore=\"http://\"\n              addonAfter=\".com\"\n              placeholder=\"请输入\"\n              v-decorator=\"[\n                'url',\n                {rules: [{ required: true, message: '请输入仓库域名', whitespace: true}]}\n              ]\" />\n          </a-form-item>\n        </a-col>\n        <a-col :xl=\"{span: 9, offset: 1}\" :lg=\"{span: 10}\" :md=\"{span: 24}\" :sm=\"24\">\n          <a-form-item\n            label=\"仓库管理员\">\n            <a-select placeholder=\"请选择管理员\" v-decorator=\"[ 'owner', {rules: [{ required: true, message: '请选择管理员'}]} ]\">\n              <a-select-option value=\"王同学\">王同学</a-select-option>\n              <a-select-option value=\"李同学\">李同学</a-select-option>\n              <a-select-option value=\"黄同学\">黄同学</a-select-option>\n            </a-select>\n          </a-form-item>\n        </a-col>\n      </a-row>\n      <a-row class=\"form-row\" :gutter=\"16\">\n        <a-col :lg=\"6\" :md=\"12\" :sm=\"24\">\n          <a-form-item\n            label=\"审批人\">\n            <a-select placeholder=\"请选择审批员\" v-decorator=\"[ 'approver', {rules: [{ required: true, message: '请选择审批员'}]} ]\">\n              <a-select-option value=\"王晓丽\">王晓丽</a-select-option>\n              <a-select-option value=\"李军\">李军</a-select-option>\n            </a-select>\n          </a-form-item>\n        </a-col>\n        <a-col :xl=\"{span: 7, offset: 1}\" :lg=\"{span: 8}\" :md=\"{span: 12}\" :sm=\"24\">\n          <a-form-item\n            label=\"生效日期\">\n            <a-range-picker\n              style=\"width: 100%\"\n              v-decorator=\"[\n                'dateRange',\n                {rules: [{ required: true, message: '请选择生效日期'}]}\n              ]\" />\n          </a-form-item>\n        </a-col>\n        <a-col :xl=\"{span: 9, offset: 1}\" :lg=\"{span: 10}\" :md=\"{span: 24}\" :sm=\"24\">\n          <a-form-item\n            label=\"仓库类型\">\n            <a-select\n              placeholder=\"请选择仓库类型\"\n              v-decorator=\"[\n                'type',\n                {rules: [{ required: true, message: '请选择仓库类型'}]}\n              ]\" >\n              <a-select-option value=\"公开\">公开</a-select-option>\n              <a-select-option value=\"私密\">私密</a-select-option>\n            </a-select>\n          </a-form-item>\n        </a-col>\n      </a-row>\n      <a-form-item v-if=\"showSubmit\">\n        <a-button htmlType=\"submit\" >Submit</a-button>\n      </a-form-item>\n    </a-form>\n\n    <a-form :form=\"form5\" :self-update=\"true\" @submit=\"handleForm2Submit\">\n      <a-row class=\"form-row\" :gutter=\"16\">\n        <a-col :lg=\"6\" :md=\"12\" :sm=\"24\">\n          <a-form-item label=\"仓库名\">\n            <a-input\n              placeholder=\"请输入仓库名称\"\n              v-decorator=\"[\n                'name',\n                {rules: [{ required: true, message: '请输入仓库名称', whitespace: true}]}\n              ]\" />\n          </a-form-item>\n        </a-col>\n        <a-col :xl=\"{span: 7, offset: 1}\" :lg=\"{span: 8}\" :md=\"{span: 12}\" :sm=\"24\">\n          <a-form-item\n            label=\"仓库域名\">\n            <a-input\n              addonBefore=\"http://\"\n              addonAfter=\".com\"\n              placeholder=\"请输入\"\n              v-decorator=\"[\n                'url',\n                {rules: [{ required: true, message: '请输入仓库域名', whitespace: true}]}\n              ]\" />\n          </a-form-item>\n        </a-col>\n        <a-col :xl=\"{span: 9, offset: 1}\" :lg=\"{span: 10}\" :md=\"{span: 24}\" :sm=\"24\">\n          <a-form-item\n            label=\"仓库管理员\">\n            <a-select placeholder=\"请选择管理员\" v-decorator=\"[ 'owner', {rules: [{ required: true, message: '请选择管理员'}]} ]\">\n              <a-select-option value=\"王同学\">王同学</a-select-option>\n              <a-select-option value=\"李同学\">李同学</a-select-option>\n              <a-select-option value=\"黄同学\">黄同学</a-select-option>\n            </a-select>\n          </a-form-item>\n        </a-col>\n      </a-row>\n      <a-row class=\"form-row\" :gutter=\"16\">\n        <a-col :lg=\"6\" :md=\"12\" :sm=\"24\">\n          <a-form-item\n            label=\"审批人\">\n            <a-select placeholder=\"请选择审批员\" v-decorator=\"[ 'approver', {rules: [{ required: true, message: '请选择审批员'}]} ]\">\n              <a-select-option value=\"王晓丽\">王晓丽</a-select-option>\n              <a-select-option value=\"李军\">李军</a-select-option>\n            </a-select>\n          </a-form-item>\n        </a-col>\n        <a-col :xl=\"{span: 7, offset: 1}\" :lg=\"{span: 8}\" :md=\"{span: 12}\" :sm=\"24\">\n          <a-form-item\n            label=\"生效日期\">\n            <a-range-picker\n              style=\"width: 100%\"\n              v-decorator=\"[\n                'dateRange',\n                {rules: [{ required: true, message: '请选择生效日期'}]}\n              ]\" />\n          </a-form-item>\n        </a-col>\n        <a-col :xl=\"{span: 9, offset: 1}\" :lg=\"{span: 10}\" :md=\"{span: 24}\" :sm=\"24\">\n          <a-form-item\n            label=\"仓库类型\">\n            <a-select\n              placeholder=\"请选择仓库类型\"\n              v-decorator=\"[\n                'type',\n                {rules: [{ required: true, message: '请选择仓库类型'}]}\n              ]\" >\n              <a-select-option value=\"公开\">公开</a-select-option>\n              <a-select-option value=\"私密\">私密</a-select-option>\n            </a-select>\n          </a-form-item>\n        </a-col>\n      </a-row>\n      <a-form-item v-if=\"showSubmit\">\n        <a-button htmlType=\"submit\" >Submit</a-button>\n      </a-form-item>\n    </a-form>\n\n    <a-divider />\n\n    <a-table\n      :columns=\"columns\"\n      :dataSource=\"data\"\n      :pagination=\"false\"\n      :loading=\"tableLoading\"\n    >\n      <template v-for=\"(col, i) in ['name', 'workId', 'department']\" :slot=\"col\" slot-scope=\"text, record\">\n        <a-input\n          :key=\"col\"\n          v-if=\"record.editable\"\n          style=\"margin: -5px 0\"\n          :value=\"text\"\n          :placeholder=\"columns[i].title\"\n          @change=\"e => handleChange(e.target.value, record.key, col)\"\n        />\n        <template v-else>{{ text }}</template>\n      </template>\n      <template slot=\"operation\" slot-scope=\"text, record\">\n        <template v-if=\"record.editable\">\n          <span v-if=\"record.isNew\">\n            <a @click=\"saveRow(record)\">添加</a>\n            <a-divider type=\"vertical\" />\n            <a-popconfirm title=\"是否要删除此行？\" @confirm=\"remove(record.key)\">\n              <a>删除</a>\n            </a-popconfirm>\n          </span>\n          <span v-else>\n            <a @click=\"saveRow(record)\">保存</a>\n            <a-divider type=\"vertical\" />\n            <a @click=\"cancel(record.key)\">取消</a>\n          </span>\n        </template>\n        <span v-else>\n          <a @click=\"toggle(record.key)\">编辑</a>\n          <a-divider type=\"vertical\" />\n          <a-popconfirm title=\"是否要删除此行？\" @confirm=\"remove(record.key)\">\n            <a>删除</a>\n          </a-popconfirm>\n        </span>\n      </template>\n    </a-table>\n    <a-button style=\"width: 100%; margin-top: 16px; margin-bottom: 8px\" type=\"dashed\" icon=\"plus\" @click=\"newMember\">新增成员</a-button>\n\n  </a-card>\n</template>\n\n<script>\nconst columns = [\n  {\n    title: '成员姓名',\n    dataIndex: 'name',\n    key: 'name',\n    width: '20%',\n    scopedSlots: { customRender: 'name' }\n  },\n  {\n    title: '工号',\n    dataIndex: 'workId',\n    key: 'workId',\n    width: '20%',\n    scopedSlots: { customRender: 'workId' }\n  },\n  {\n    title: '所属部门',\n    dataIndex: 'department',\n    key: 'department',\n    width: '40%',\n    scopedSlots: { customRender: 'department' }\n  },\n  {\n    title: '操作',\n    key: 'action',\n    scopedSlots: { customRender: 'operation' }\n  }\n]\n\nexport default {\n  name: 'BigForm',\n  data () {\n    return {\n      showSubmit: true,\n      form1: this.$form.createForm(this),\n      form2: this.$form.createForm(this),\n      form3: this.$form.createForm(this),\n      form4: this.$form.createForm(this),\n      form5: this.$form.createForm(this),\n      tableLoading: false,\n      columns,\n      data: [{\n        key: '1',\n        name: '小明',\n        workId: '001',\n        editable: false,\n        department: '行政部'\n      },\n        {\n          key: '2',\n          name: '李莉',\n          workId: '002',\n          editable: false,\n          department: 'IT部'\n        },\n        {\n          key: '3',\n          name: '王小帅',\n          workId: '003',\n          editable: false,\n          department: '财务部'\n        }]\n    }\n  },\n  mounted () {\n    // 加 10 个表单行\n    new Array(10).fill(0).forEach(() => {\n      this.newMember()\n    })\n  },\n  methods: {\n    handleForm1Submit (e) {\n      e.preventDefault()\n      this.form1.validateFields()\n    },\n    handleForm2Submit (e) {\n      e.preventDefault()\n      this.form2.validateFields()\n    },\n\n    handleChange (value, key, column) {\n      const target = this.data.find(item => key === item.key)\n      if (target) {\n        target[column] = value\n      }\n    },\n\n    toggle (record) {\n\n    },\n    saveRow (record) {\n\n    },\n    cancel (key) {\n\n    },\n    remove (key) {\n      this.data = this.data.filter(item => item.key !== key)\n    },\n\n    newMember () {\n      const length = this.data.length\n      this.data.push({\n        key: length === 0 ? '1' : (parseInt(this.data[length - 1].key) + 1).toString(),\n        name: '',\n        workId: '',\n        department: '',\n        editable: true,\n        isNew: true\n      })\n    }\n  }\n}\n</script>\n\n<style scoped>\n\n</style>\n"
  },
  {
    "path": "src/views/other/IconSelectorView.vue",
    "content": "<template>\n  <a-card :body-style=\"{padding: '24px 32px'}\" :bordered=\"false\">\n    <icon-selector v-model=\"currentSelectedIcon\" @change=\"handleIconChange\"/>\n\n    <a-divider />\n    <p>测试 IconSelector 组件 v-model 功能</p>\n    <a-button @click=\"changeIcon('down')\">改变 Icon-down</a-button>\n    <a-divider type=\"vertical\" />\n    <a-button @click=\"changeIcon('cloud-download')\">改变 Icon-cloud-download</a-button>\n  </a-card>\n</template>\n\n<script>\nimport IconSelector from '@/components/IconSelector'\n\nexport default {\n  name: 'IconSelectorView',\n  components: {\n    IconSelector\n  },\n  data () {\n    return {\n      currentSelectedIcon: 'pause-circle'\n    }\n  },\n  methods: {\n    handleIconChange (icon) {\n      console.log('change Icon', icon)\n      this.$message.info(<span>选中图标 <code>{icon}</code></span>)\n    },\n    changeIcon (type) {\n      this.currentSelectedIcon = type\n    }\n  }\n}\n</script>\n"
  },
  {
    "path": "src/views/other/PermissionList.vue",
    "content": "<template>\n  <a-card :bordered=\"false\">\n    <div class=\"table-page-search-wrapper\">\n      <a-form layout=\"inline\">\n        <a-row :gutter=\"48\">\n          <a-col :md=\"8\" :sm=\"24\">\n            <a-form-item label=\"角色ID\">\n              <a-input placeholder=\"请输入\"/>\n            </a-form-item>\n          </a-col>\n          <a-col :md=\"8\" :sm=\"24\">\n            <a-form-item label=\"状态\">\n              <a-select placeholder=\"请选择\" default-value=\"0\">\n                <a-select-option value=\"0\">全部</a-select-option>\n                <a-select-option value=\"1\">关闭</a-select-option>\n                <a-select-option value=\"2\">运行中</a-select-option>\n              </a-select>\n            </a-form-item>\n          </a-col>\n          <a-col :md=\"8\" :sm=\"24\">\n            <span class=\"table-page-search-submitButtons\">\n              <a-button type=\"primary\">查询</a-button>\n              <a-button style=\"margin-left: 8px\">重置</a-button>\n            </span>\n          </a-col>\n        </a-row>\n      </a-form>\n    </div>\n\n    <s-table :columns=\"columns\" :data=\"loadData\">\n\n      <span slot=\"actions\" slot-scope=\"text, record\">\n        <a-tag v-for=\"(action, index) in record.actionList\" :key=\"index\">{{ action.describe }}</a-tag>\n      </span>\n\n      <span slot=\"status\" slot-scope=\"text\">\n        {{ text | statusFilter }}\n      </span>\n\n      <span slot=\"action\" slot-scope=\"text, record\">\n        <a @click=\"handleEdit(record)\">编辑</a>\n        <a-divider type=\"vertical\" />\n        <a-dropdown>\n          <a class=\"ant-dropdown-link\">\n            更多 <a-icon type=\"down\" />\n          </a>\n          <a-menu slot=\"overlay\">\n            <a-menu-item>\n              <a href=\"javascript:;\">详情</a>\n            </a-menu-item>\n            <a-menu-item>\n              <a href=\"javascript:;\">禁用</a>\n            </a-menu-item>\n            <a-menu-item>\n              <a href=\"javascript:;\">删除</a>\n            </a-menu-item>\n          </a-menu>\n        </a-dropdown>\n      </span>\n    </s-table>\n\n    <a-modal\n      title=\"操作\"\n      :width=\"800\"\n      v-model=\"visible\"\n      @ok=\"handleOk\"\n    >\n      <a-form :autoFormCreate=\"(form)=>{this.form = form}\">\n\n        <a-form-item\n          :labelCol=\"labelCol\"\n          :wrapperCol=\"wrapperCol\"\n          label=\"唯一识别码\"\n          hasFeedback\n          validateStatus=\"success\"\n        >\n          <a-input placeholder=\"唯一识别码\" v-model=\"mdl.id\" id=\"no\" disabled=\"disabled\" />\n        </a-form-item>\n\n        <a-form-item\n          :labelCol=\"labelCol\"\n          :wrapperCol=\"wrapperCol\"\n          label=\"权限名称\"\n          hasFeedback\n          validateStatus=\"success\"\n        >\n          <a-input placeholder=\"起一个名字\" v-model=\"mdl.name\" id=\"permission_name\" />\n        </a-form-item>\n\n        <a-form-item\n          :labelCol=\"labelCol\"\n          :wrapperCol=\"wrapperCol\"\n          label=\"状态\"\n          hasFeedback\n          validateStatus=\"warning\"\n        >\n          <a-select v-model=\"mdl.status\">\n            <a-select-option value=\"1\">正常</a-select-option>\n            <a-select-option value=\"2\">禁用</a-select-option>\n          </a-select>\n        </a-form-item>\n\n        <a-form-item\n          :labelCol=\"labelCol\"\n          :wrapperCol=\"wrapperCol\"\n          label=\"描述\"\n          hasFeedback\n        >\n          <a-textarea :rows=\"5\" v-model=\"mdl.describe\" placeholder=\"...\" id=\"describe\"/>\n        </a-form-item>\n\n        <a-divider />\n\n        <a-form-item\n          :labelCol=\"labelCol\"\n          :wrapperCol=\"wrapperCol\"\n          label=\"赋予权限\"\n          hasFeedback\n        >\n          <a-select\n            style=\"width: 100%\"\n            mode=\"multiple\"\n            v-model=\"mdl.actions\"\n            :allowClear=\"true\"\n          >\n            <a-select-option v-for=\"(action, index) in permissionList\" :key=\"index\" :value=\"action.value\">{{ action.label }}</a-select-option>\n          </a-select>\n        </a-form-item>\n\n      </a-form>\n    </a-modal>\n\n  </a-card>\n</template>\n\n<script>\nimport { STable } from '@/components'\n\nexport default {\n  name: 'TableList',\n  components: {\n    STable\n  },\n  data () {\n    return {\n      description: '列表使用场景：后台管理中的权限管理以及角色管理，可用于基于 RBAC 设计的角色权限控制，颗粒度细到每一个操作类型。',\n\n      visible: false,\n      labelCol: {\n        xs: { span: 24 },\n        sm: { span: 5 }\n      },\n      wrapperCol: {\n        xs: { span: 24 },\n        sm: { span: 16 }\n      },\n      form: null,\n      mdl: {},\n\n      // 高级搜索 展开/关闭\n      advanced: false,\n      // 查询参数\n      queryParam: {},\n      // 表头\n      columns: [\n        {\n          title: '唯一识别码',\n          dataIndex: 'id'\n        },\n        {\n          title: '权限名称',\n          dataIndex: 'name'\n        },\n        {\n          title: '可操作权限',\n          dataIndex: 'actions',\n          scopedSlots: { customRender: 'actions' }\n        },\n        {\n          title: '状态',\n          dataIndex: 'status',\n          scopedSlots: { customRender: 'status' }\n        },\n        {\n          title: '操作',\n          width: '150px',\n          dataIndex: 'action',\n          scopedSlots: { customRender: 'action' }\n        }\n      ],\n      // 向后端拉取可以用的操作列表\n      permissionList: null,\n      // 加载数据方法 必须为 Promise 对象\n      loadData: parameter => {\n        return this.$http.get('/permission', {\n          params: Object.assign(parameter, this.queryParam)\n        }).then(res => {\n          const result = res.result\n          result.data.map(permission => {\n            permission.actionList = JSON.parse(permission.actionData)\n            return permission\n          })\n          return result\n        })\n      },\n\n      selectedRowKeys: [],\n      selectedRows: []\n    }\n  },\n  filters: {\n    statusFilter (status) {\n      const statusMap = {\n        1: '正常',\n        2: '禁用'\n      }\n      return statusMap[status]\n    }\n  },\n  created () {\n    this.loadPermissionList()\n  },\n  methods: {\n    loadPermissionList () {\n      // permissionList\n      new Promise(resolve => {\n        const data = [\n          { label: '新增', value: 'add', defaultChecked: false },\n          { label: '查询', value: 'get', defaultChecked: false },\n          { label: '修改', value: 'update', defaultChecked: false },\n          { label: '列表', value: 'query', defaultChecked: false },\n          { label: '删除', value: 'delete', defaultChecked: false },\n          { label: '导入', value: 'import', defaultChecked: false },\n          { label: '导出', value: 'export', defaultChecked: false }\n        ]\n        setTimeout(resolve(data), 1500)\n      }).then(res => {\n        this.permissionList = res\n      })\n    },\n    handleEdit (record) {\n      this.mdl = Object.assign({}, record)\n      console.log(this.mdl)\n      this.visible = true\n    },\n    handleOk () {\n\n    },\n    onChange (selectedRowKeys, selectedRows) {\n      this.selectedRowKeys = selectedRowKeys\n      this.selectedRows = selectedRows\n    },\n    toggleAdvanced () {\n      this.advanced = !this.advanced\n    }\n  },\n  watch: {\n    /*\n      'selectedRows': function (selectedRows) {\n        this.needTotalList = this.needTotalList.map(item => {\n          return {\n            ...item,\n            total: selectedRows.reduce( (sum, val) => {\n              return sum + val[item.dataIndex]\n            }, 0)\n          }\n        })\n      }\n      */\n  }\n}\n</script>\n"
  },
  {
    "path": "src/views/other/RoleList.vue",
    "content": "<template>\n  <a-card :bordered=\"false\">\n    <div class=\"table-page-search-wrapper\">\n      <a-form layout=\"inline\">\n        <a-row :gutter=\"48\">\n          <a-col :md=\"8\" :sm=\"24\">\n            <a-form-item label=\"角色ID\">\n              <a-input placeholder=\"请输入\"/>\n            </a-form-item>\n          </a-col>\n          <a-col :md=\"8\" :sm=\"24\">\n            <a-form-item label=\"状态\">\n              <a-select placeholder=\"请选择\" default-value=\"0\">\n                <a-select-option value=\"0\">全部</a-select-option>\n                <a-select-option value=\"1\">正常</a-select-option>\n                <a-select-option value=\"2\">禁用</a-select-option>\n              </a-select>\n            </a-form-item>\n          </a-col>\n          <a-col :md=\"8\" :sm=\"24\">\n            <span class=\"table-page-search-submitButtons\">\n              <a-button type=\"primary\">查询</a-button>\n              <a-button style=\"margin-left: 8px\">重置</a-button>\n            </span>\n          </a-col>\n        </a-row>\n      </a-form>\n    </div>\n\n    <s-table\n      ref=\"table\"\n      size=\"default\"\n      :columns=\"columns\"\n      :data=\"loadData\"\n    >\n      <div\n        slot=\"expandedRowRender\"\n        slot-scope=\"record\"\n        style=\"margin: 0\">\n        <a-row\n          :gutter=\"24\"\n          :style=\"{ marginBottom: '12px' }\">\n          <a-col :span=\"12\" v-for=\"(role, index) in record.permissions\" :key=\"index\" :style=\"{ marginBottom: '12px' }\">\n            <a-col :span=\"4\">\n              <span>{{ role.permissionName }}：</span>\n            </a-col>\n            <a-col :span=\"20\" v-if=\"role.actionEntitySet.length > 0\">\n              <a-tag color=\"cyan\" v-for=\"(action, k) in role.actionEntitySet\" :key=\"k\">{{ action.describe }}</a-tag>\n            </a-col>\n            <a-col :span=\"20\" v-else>-</a-col>\n          </a-col>\n        </a-row>\n      </div>\n      <span slot=\"action\" slot-scope=\"text, record\">\n        <a @click=\"$refs.modal.edit(record)\">编辑</a>\n        <a-divider type=\"vertical\" />\n        <a-dropdown>\n          <a class=\"ant-dropdown-link\">\n            更多 <a-icon type=\"down\" />\n          </a>\n          <a-menu slot=\"overlay\">\n            <a-menu-item>\n              <a href=\"javascript:;\">详情</a>\n            </a-menu-item>\n            <a-menu-item>\n              <a href=\"javascript:;\">禁用</a>\n            </a-menu-item>\n            <a-menu-item>\n              <a href=\"javascript:;\">删除</a>\n            </a-menu-item>\n          </a-menu>\n        </a-dropdown>\n      </span>\n    </s-table>\n\n    <role-modal ref=\"modal\" @ok=\"handleOk\"></role-modal>\n\n  </a-card>\n</template>\n\n<script>\nimport { STable } from '@/components'\nimport RoleModal from './modules/RoleModal'\n\nexport default {\n  name: 'TableList',\n  components: {\n    STable,\n    RoleModal\n  },\n  data () {\n    return {\n      description: '列表使用场景：后台管理中的权限管理以及角色管理，可用于基于 RBAC 设计的角色权限控制，颗粒度细到每一个操作类型。',\n\n      visible: false,\n\n      form: null,\n      mdl: {},\n\n      // 高级搜索 展开/关闭\n      advanced: false,\n      // 查询参数\n      queryParam: {},\n      // 表头\n      columns: [\n        {\n          title: '唯一识别码',\n          dataIndex: 'id'\n        },\n        {\n          title: '角色名称',\n          dataIndex: 'name'\n        },\n        {\n          title: '状态',\n          dataIndex: 'status'\n        },\n        {\n          title: '创建时间',\n          dataIndex: 'createTime',\n          sorter: true\n        }, {\n          title: '操作',\n          width: '150px',\n          dataIndex: 'action',\n          scopedSlots: { customRender: 'action' }\n        }\n      ],\n      // 加载数据方法 必须为 Promise 对象\n      loadData: parameter => {\n        return this.$http.get('/role', {\n          params: Object.assign(parameter, this.queryParam)\n        }).then(res => {\n          return res.result\n        })\n      },\n\n      selectedRowKeys: [],\n      selectedRows: []\n    }\n  },\n  methods: {\n    handleEdit (record) {\n      this.mdl = Object.assign({}, record)\n\n      this.mdl.permissions.forEach(permission => {\n        permission.actionsOptions = permission.actionEntitySet.map(action => {\n          return { label: action.describe, value: action.action, defaultCheck: action.defaultCheck }\n        })\n      })\n\n      console.log(this.mdl)\n      this.visible = true\n    },\n    handleOk () {\n      // 新增/修改 成功时，重载列表\n      this.$refs.table.refresh()\n    },\n    onChange (selectedRowKeys, selectedRows) {\n      this.selectedRowKeys = selectedRowKeys\n      this.selectedRows = selectedRows\n    },\n    toggleAdvanced () {\n      this.advanced = !this.advanced\n    }\n  },\n  watch: {\n    /*\n      'selectedRows': function (selectedRows) {\n        this.needTotalList = this.needTotalList.map(item => {\n          return {\n            ...item,\n            total: selectedRows.reduce( (sum, val) => {\n              return sum + val[item.dataIndex]\n            }, 0)\n          }\n        })\n      }\n      */\n  }\n}\n</script>\n"
  },
  {
    "path": "src/views/other/TableInnerEditList.vue",
    "content": "<template>\n  <a-card :bordered=\"false\">\n    <div class=\"table-page-search-wrapper\">\n      <a-form layout=\"inline\">\n        <a-row :gutter=\"48\">\n          <a-col :md=\"8\" :sm=\"24\">\n            <a-form-item label=\"规则编号\">\n              <a-input placeholder=\"\"/>\n            </a-form-item>\n          </a-col>\n          <a-col :md=\"8\" :sm=\"24\">\n            <a-form-item label=\"使用状态\">\n              <a-select placeholder=\"请选择\" default-value=\"0\">\n                <a-select-option value=\"0\">全部</a-select-option>\n                <a-select-option value=\"1\">关闭</a-select-option>\n                <a-select-option value=\"2\">运行中</a-select-option>\n              </a-select>\n            </a-form-item>\n          </a-col>\n          <template v-if=\"advanced\">\n            <a-col :md=\"8\" :sm=\"24\">\n              <a-form-item label=\"调用次数\">\n                <a-input-number style=\"width: 100%\"/>\n              </a-form-item>\n            </a-col>\n            <a-col :md=\"8\" :sm=\"24\">\n              <a-form-item label=\"更新日期\">\n                <a-date-picker style=\"width: 100%\" placeholder=\"请输入更新日期\"/>\n              </a-form-item>\n            </a-col>\n            <a-col :md=\"8\" :sm=\"24\">\n              <a-form-item label=\"使用状态\">\n                <a-select placeholder=\"请选择\" default-value=\"0\">\n                  <a-select-option value=\"0\">全部</a-select-option>\n                  <a-select-option value=\"1\">关闭</a-select-option>\n                  <a-select-option value=\"2\">运行中</a-select-option>\n                </a-select>\n              </a-form-item>\n            </a-col>\n            <a-col :md=\"8\" :sm=\"24\">\n              <a-form-item label=\"使用状态\">\n                <a-select placeholder=\"请选择\" default-value=\"0\">\n                  <a-select-option value=\"0\">全部</a-select-option>\n                  <a-select-option value=\"1\">关闭</a-select-option>\n                  <a-select-option value=\"2\">运行中</a-select-option>\n                </a-select>\n              </a-form-item>\n            </a-col>\n          </template>\n          <a-col :md=\"!advanced && 8 || 24\" :sm=\"24\">\n            <span class=\"table-page-search-submitButtons\" :style=\"advanced && { float: 'right', overflow: 'hidden' } || {} \">\n              <a-button type=\"primary\">查询</a-button>\n              <a-button style=\"margin-left: 8px\">重置</a-button>\n              <a @click=\"toggleAdvanced\" style=\"margin-left: 8px\">\n                {{ advanced ? '收起' : '展开' }}\n                <a-icon :type=\"advanced ? 'up' : 'down'\"/>\n              </a>\n            </span>\n          </a-col>\n        </a-row>\n      </a-form>\n    </div>\n\n    <div class=\"table-operator\">\n      <a-button type=\"primary\" icon=\"plus\">新建</a-button>\n      <a-dropdown v-if=\"selectedRowKeys.length > 0\">\n        <a-menu slot=\"overlay\">\n          <a-menu-item key=\"1\"><a-icon type=\"delete\" />删除</a-menu-item>\n          <!-- lock | unlock -->\n          <a-menu-item key=\"2\"><a-icon type=\"lock\" />锁定</a-menu-item>\n        </a-menu>\n        <a-button style=\"margin-left: 8px\">\n          批量操作 <a-icon type=\"down\" />\n        </a-button>\n      </a-dropdown>\n    </div>\n\n    <s-table\n      ref=\"table\"\n      size=\"default\"\n      :columns=\"columns\"\n      :data=\"loadData\"\n      :alert=\"{ show: true, clear: true }\"\n      :rowSelection=\"{ selectedRowKeys: this.selectedRowKeys, onChange: this.onSelectChange }\"\n    >\n      <template v-for=\"(col, index) in columns\" v-if=\"col.scopedSlots\" :slot=\"col.dataIndex\" slot-scope=\"text, record\">\n        <div :key=\"index\">\n          <a-input\n            v-if=\"record.editable\"\n            style=\"margin: -5px 0\"\n            :value=\"text\"\n            @change=\"e => handleChange(e.target.value, record.key, col, record)\"\n          />\n          <template v-else>{{ text }}</template>\n        </div>\n      </template>\n      <template slot=\"action\" slot-scope=\"text, record\">\n        <div class=\"editable-row-operations\">\n          <span v-if=\"record.editable\">\n            <a @click=\"() => save(record)\">保存</a>\n            <a-divider type=\"vertical\" />\n            <a-popconfirm title=\"真的放弃编辑吗?\" @confirm=\"() => cancel(record)\">\n              <a>取消</a>\n            </a-popconfirm>\n          </span>\n          <span v-else>\n            <a class=\"edit\" @click=\"() => edit(record)\">修改</a>\n            <a-divider type=\"vertical\" />\n            <a class=\"delete\" @click=\"() => del(record)\">删除</a>\n          </span>\n        </div>\n      </template>\n    </s-table>\n\n  </a-card>\n</template>\n\n<script>\nimport { STable } from '@/components'\n\nexport default {\n  name: 'TableList',\n  components: {\n    STable\n  },\n  data () {\n    return {\n      // 高级搜索 展开/关闭\n      advanced: false,\n      // 查询参数\n      queryParam: {},\n      // 表头\n      columns: [\n        {\n          title: '规则编号',\n          dataIndex: 'no',\n          width: 90\n        },\n        {\n          title: '描述',\n          dataIndex: 'description',\n          scopedSlots: { customRender: 'description' }\n        },\n        {\n          title: '服务调用次数',\n          dataIndex: 'callNo',\n          width: '150px',\n          sorter: true,\n          needTotal: true,\n          scopedSlots: { customRender: 'callNo' }\n          // customRender: (text) => text + ' 次'\n        },\n        {\n          title: '状态',\n          dataIndex: 'status',\n          width: '100px',\n          needTotal: true,\n          scopedSlots: { customRender: 'status' }\n        },\n        {\n          title: '更新时间',\n          dataIndex: 'updatedAt',\n          width: '200px',\n          sorter: true,\n          scopedSlots: { customRender: 'updatedAt' }\n        },\n        {\n          table: '操作',\n          dataIndex: 'action',\n          width: '120px',\n          scopedSlots: { customRender: 'action' }\n        }\n      ],\n      // 加载数据方法 必须为 Promise 对象\n      loadData: parameter => {\n        return this.$http.get('/service', {\n          params: Object.assign(parameter, this.queryParam)\n        }).then(res => {\n          return res.result\n        })\n      },\n\n      selectedRowKeys: [],\n      selectedRows: []\n    }\n  },\n  methods: {\n\n    handleChange (value, key, column, record) {\n      console.log(value, key, column)\n      record[column.dataIndex] = value\n    },\n    edit (row) {\n      row.editable = true\n      // row = Object.assign({}, row)\n    },\n    // eslint-disable-next-line\n    del (row) {\n      this.$confirm({\n        title: '警告',\n        content: `真的要删除 ${row.no} 吗?`,\n        okText: '删除',\n        okType: 'danger',\n        cancelText: '取消',\n        onOk () {\n          console.log('OK')\n          // 在这里调用删除接口\n          return new Promise((resolve, reject) => {\n            setTimeout(Math.random() > 0.5 ? resolve : reject, 1000)\n          }).catch(() => console.log('Oops errors!'))\n        },\n        onCancel () {\n          console.log('Cancel')\n        }\n      })\n    },\n    save (row) {\n      row.editable = false\n    },\n    cancel (row) {\n      row.editable = false\n    },\n\n    onSelectChange (selectedRowKeys, selectedRows) {\n      this.selectedRowKeys = selectedRowKeys\n      this.selectedRows = selectedRows\n    },\n    toggleAdvanced () {\n      this.advanced = !this.advanced\n    }\n  },\n  watch: {\n    /*\n      'selectedRows': function (selectedRows) {\n        this.needTotalList = this.needTotalList.map(item => {\n          return {\n            ...item,\n            total: selectedRows.reduce( (sum, val) => {\n              return sum + val[item.dataIndex]\n            }, 0)\n          }\n        })\n      }\n      */\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n  .search {\n    margin-bottom: 54px;\n  }\n\n  .fold {\n    width: calc(100% - 216px);\n    display: inline-block\n  }\n\n  .operator {\n    margin-bottom: 18px;\n  }\n\n  @media screen and (max-width: 900px) {\n    .fold {\n      width: 100%;\n    }\n  }\n</style>\n"
  },
  {
    "path": "src/views/other/TreeList.vue",
    "content": "<template>\n  <a-card :bordered=\"false\">\n    <a-row :gutter=\"8\">\n      <a-col :span=\"5\">\n        <s-tree\n          :dataSource=\"orgTree\"\n          :openKeys.sync=\"openKeys\"\n          :search=\"true\"\n          @click=\"handleClick\"\n          @add=\"handleAdd\"\n          @titleClick=\"handleTitleClick\"></s-tree>\n      </a-col>\n      <a-col :span=\"19\">\n        <s-table\n          ref=\"table\"\n          size=\"default\"\n          :columns=\"columns\"\n          :data=\"loadData\"\n          :alert=\"false\"\n          :rowSelection=\"{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange }\"\n        >\n          <span slot=\"action\" slot-scope=\"text, record\">\n            <template v-if=\"$auth('table.update')\">\n              <a @click=\"handleEdit(record)\">编辑</a>\n              <a-divider type=\"vertical\" />\n            </template>\n            <a-dropdown>\n              <a class=\"ant-dropdown-link\">\n                更多 <a-icon type=\"down\" />\n              </a>\n              <a-menu slot=\"overlay\">\n                <a-menu-item>\n                  <a href=\"javascript:;\">详情</a>\n                </a-menu-item>\n                <a-menu-item v-if=\"$auth('table.disable')\">\n                  <a href=\"javascript:;\">禁用</a>\n                </a-menu-item>\n                <a-menu-item v-if=\"$auth('table.delete')\">\n                  <a href=\"javascript:;\">删除</a>\n                </a-menu-item>\n              </a-menu>\n            </a-dropdown>\n          </span>\n        </s-table>\n      </a-col>\n    </a-row>\n\n    <org-modal ref=\"modal\" @ok=\"handleSaveOk\" @close=\"handleSaveClose\" />\n  </a-card>\n</template>\n\n<script>\nimport STree from '@/components/Tree/Tree'\nimport { STable } from '@/components'\nimport OrgModal from './modules/OrgModal'\nimport { getOrgTree, getServiceList } from '@/api/manage'\n\nexport default {\n  name: 'TreeList',\n  components: {\n    STable,\n    STree,\n    OrgModal\n  },\n  data () {\n    return {\n      openKeys: ['key-01'],\n\n      // 查询参数\n      queryParam: {},\n      // 表头\n      columns: [\n        {\n          title: '#',\n          dataIndex: 'no'\n        },\n        {\n          title: '成员名称',\n          dataIndex: 'description'\n        },\n        {\n          title: '登录次数',\n          dataIndex: 'callNo',\n          sorter: true,\n          needTotal: true,\n          customRender: (text) => text + ' 次'\n        },\n        {\n          title: '状态',\n          dataIndex: 'status',\n          needTotal: true\n        },\n        {\n          title: '更新时间',\n          dataIndex: 'updatedAt',\n          sorter: true\n        },\n        {\n          title: '操作',\n          dataIndex: 'action',\n          width: '150px',\n          scopedSlots: { customRender: 'action' }\n        }\n      ],\n      // 加载数据方法 必须为 Promise 对象\n      loadData: parameter => {\n        return getServiceList(Object.assign(parameter, this.queryParam))\n          .then(res => {\n            return res.result\n          })\n      },\n      orgTree: [],\n      selectedRowKeys: [],\n      selectedRows: []\n    }\n  },\n  created () {\n    getOrgTree().then(res => {\n      this.orgTree = res.result\n    })\n  },\n  methods: {\n    handleClick (e) {\n      console.log('handleClick', e)\n      this.queryParam = {\n        key: e.key\n      }\n      this.$refs.table.refresh(true)\n    },\n    handleAdd (item) {\n      console.log('add button, item', item)\n      this.$message.info(`提示：你点了 ${item.key} - ${item.title} `)\n      this.$refs.modal.add(item.key)\n    },\n    handleTitleClick (item) {\n      console.log('handleTitleClick', item)\n    },\n    titleClick (e) {\n      console.log('titleClick', e)\n    },\n    handleSaveOk () {\n\n    },\n    handleSaveClose () {\n\n    },\n\n    onSelectChange (selectedRowKeys, selectedRows) {\n      this.selectedRowKeys = selectedRowKeys\n      this.selectedRows = selectedRows\n    }\n  }\n}\n</script>\n\n<style lang=\"less\">\n  .custom-tree {\n\n    :deep(.ant-menu-item-group-title) {\n      position: relative;\n      &:hover {\n        .btn {\n          display: block;\n        }\n      }\n    }\n\n    :deep(.ant-menu-item) {\n      &:hover {\n        .btn {\n          display: block;\n        }\n      }\n    }\n\n    :deep(.btn) {\n      display: none;\n      position: absolute;\n      top: 0;\n      right: 10px;\n      width: 20px;\n      height: 40px;\n      line-height: 40px;\n      z-index: 1050;\n\n      &:hover {\n        transform: scale(1.2);\n        transition: 0.5s all;\n      }\n    }\n  }\n</style>\n"
  },
  {
    "path": "src/views/other/UserList.vue",
    "content": "<template>\n  <a-card :bordered=\"false\">\n    <div class=\"table-page-search-wrapper\">\n      <a-form layout=\"inline\">\n        <a-row :gutter=\"48\">\n          <a-col :md=\"8\" :sm=\"24\">\n            <a-form-item label=\"角色ID\">\n              <a-input placeholder=\"请输入\"/>\n            </a-form-item>\n          </a-col>\n          <a-col :md=\"8\" :sm=\"24\">\n            <a-form-item label=\"状态\">\n              <a-select placeholder=\"请选择\" default-value=\"0\">\n                <a-select-option value=\"0\">全部</a-select-option>\n                <a-select-option value=\"1\">关闭</a-select-option>\n                <a-select-option value=\"2\">运行中</a-select-option>\n              </a-select>\n            </a-form-item>\n          </a-col>\n          <a-col :md=\"8\" :sm=\"24\">\n            <span class=\"table-page-search-submitButtons\">\n              <a-button type=\"primary\">查询</a-button>\n              <a-button style=\"margin-left: 8px\">重置</a-button>\n            </span>\n          </a-col>\n        </a-row>\n      </a-form>\n    </div>\n\n    <s-table\n      row-key=\"id\"\n      size=\"default\"\n      :columns=\"columns\"\n      :data=\"loadData\"\n      :expandedRowKeys=\"expandedRowKeys\"\n      @expand=\"handleExpand\"\n    >\n      <div\n        slot=\"expandedRowRender\"\n        slot-scope=\"record\"\n        style=\"margin: 0\">\n        <a-row\n          :gutter=\"24\"\n          :style=\"{ marginBottom: '12px' }\">\n          <a-col :span=\"12\" v-for=\"(role, index) in record.permissions\" :key=\"index\" :style=\"{ marginBottom: '12px', height: '23px' }\">\n            <a-col :lg=\"4\" :md=\"24\">\n              <span>{{ role.permissionName }}：</span>\n            </a-col>\n            <a-col :lg=\"20\" :md=\"24\" v-if=\"role.actionList && role.actionList.length > 0\">\n              <a-tag color=\"cyan\" v-for=\"action in role.actionList\" :key=\"action\">{{ action | permissionFilter }}</a-tag>\n            </a-col>\n            <a-col :span=\"20\" v-else>-</a-col>\n          </a-col>\n        </a-row>\n      </div>\n      <a-tag color=\"blue\" slot=\"status\" slot-scope=\"text\">{{ text | statusFilter }}</a-tag>\n      <span slot=\"createTime\" slot-scope=\"text\">{{ text | moment }}</span>\n      <span slot=\"action\" slot-scope=\"text, record\">\n        <a @click=\"handleEdit(record)\">编辑</a>\n        <a-divider type=\"vertical\" />\n        <a-dropdown>\n          <a class=\"ant-dropdown-link\">\n            更多 <a-icon type=\"down\" />\n          </a>\n          <a-menu slot=\"overlay\">\n            <a-menu-item>\n              <a href=\"javascript:;\">详情</a>\n            </a-menu-item>\n            <a-menu-item>\n              <a href=\"javascript:;\">禁用</a>\n            </a-menu-item>\n            <a-menu-item>\n              <a href=\"javascript:;\">删除</a>\n            </a-menu-item>\n          </a-menu>\n        </a-dropdown>\n      </span>\n    </s-table>\n\n    <a-modal\n      title=\"操作\"\n      style=\"top: 20px;\"\n      :width=\"800\"\n      v-model=\"visible\"\n      @ok=\"handleOk\"\n    >\n      <a-form class=\"permission-form\" :form=\"form\">\n\n        <a-form-item\n          :labelCol=\"labelCol\"\n          :wrapperCol=\"wrapperCol\"\n          label=\"唯一识别码\"\n          hasFeedback\n          validateStatus=\"success\"\n        >\n          <a-input\n            placeholder=\"唯一识别码\"\n            disabled=\"disabled\"\n            v-decorator=\"['id']\"\n          />\n        </a-form-item>\n\n        <a-form-item\n          :labelCol=\"labelCol\"\n          :wrapperCol=\"wrapperCol\"\n          label=\"角色名称\"\n          hasFeedback\n          validateStatus=\"success\"\n        >\n          <a-input\n            placeholder=\"起一个名字\"\n            v-decorator=\"['name']\"\n          />\n        </a-form-item>\n\n        <a-form-item\n          :labelCol=\"labelCol\"\n          :wrapperCol=\"wrapperCol\"\n          label=\"状态\"\n          hasFeedback\n          validateStatus=\"warning\"\n        >\n          <a-select v-decorator=\"['status', { initialValue: 1 }]\">\n            <a-select-option :value=\"1\">正常</a-select-option>\n            <a-select-option :value=\"2\">禁用</a-select-option>\n          </a-select>\n        </a-form-item>\n\n        <a-form-item\n          :labelCol=\"labelCol\"\n          :wrapperCol=\"wrapperCol\"\n          label=\"描述\"\n          hasFeedback\n        >\n          <a-textarea\n            :rows=\"5\"\n            placeholder=\"...\"\n            id=\"describe\"\n            v-decorator=\"['describe']\"\n          />\n        </a-form-item>\n\n        <a-divider>拥有权限</a-divider>\n        <template v-for=\"permission in permissions\">\n          <a-form-item\n            class=\"permission-group\"\n            v-if=\"permission.actionsOptions && permission.actionsOptions.length > 0\"\n            :labelCol=\"labelCol\"\n            :wrapperCol=\"wrapperCol\"\n            :key=\"permission.permissionId\"\n            :label=\"permission.permissionName\"\n          >\n            <a-checkbox>全选</a-checkbox>\n            <a-checkbox-group v-decorator=\"[`permissions.${permission.permissionId}`]\" :options=\"permission.actionsOptions\"/>\n          </a-form-item>\n        </template>\n\n      </a-form>\n    </a-modal>\n\n  </a-card>\n</template>\n\n<script>\nimport pick from 'lodash.pick'\nimport { STable } from '@/components'\nimport { getRoleList, getServiceList } from '@/api/manage'\nimport { PERMISSION_ENUM } from '@/core/permission/permission'\n\nconst STATUS = {\n  1: '启用',\n  2: '禁用'\n}\n\nconst columns = [\n  {\n    title: '唯一识别码',\n    dataIndex: 'id'\n  },\n  {\n    title: '角色名称',\n    dataIndex: 'name'\n  },\n  {\n    title: '状态',\n    dataIndex: 'status',\n    scopedSlots: { customRender: 'status' }\n  },\n  {\n    title: '创建时间',\n    dataIndex: 'createTime',\n    scopedSlots: { customRender: 'createTime' },\n    sorter: true\n  }, {\n    title: '操作',\n    width: '150px',\n    dataIndex: 'action',\n    scopedSlots: { customRender: 'action' }\n  }\n]\n\nexport default {\n  name: 'TableList',\n  components: {\n    STable\n  },\n  data () {\n    return {\n      description: '列表使用场景：后台管理中的权限管理以及角色管理，可用于基于 RBAC 设计的角色权限控制，颗粒度细到每一个操作类型。',\n\n      visible: false,\n      labelCol: {\n        xs: { span: 24 },\n        sm: { span: 5 }\n      },\n      wrapperCol: {\n        xs: { span: 24 },\n        sm: { span: 16 }\n      },\n      form: this.$form.createForm(this),\n      permissions: [],\n\n      // 高级搜索 展开/关闭\n      advanced: false,\n      // 查询参数\n      queryParam: {},\n      // 表头\n      columns,\n      // 加载数据方法 必须为 Promise 对象\n      loadData: parameter => {\n        return getRoleList(parameter)\n          .then(res => {\n            console.log('getRoleList', res)\n            // 展开全部行\n            this.expandedRowKeys = res.result.data.map(item => item.id)\n            return res.result\n          })\n      },\n\n      expandedRowKeys: [],\n      selectedRowKeys: [],\n      selectedRows: []\n    }\n  },\n  filters: {\n    statusFilter (key) {\n      return STATUS[key]\n    },\n    permissionFilter (key) {\n      const permission = PERMISSION_ENUM[key]\n      return permission && permission.label\n    }\n  },\n  created () {\n    getServiceList().then(res => {\n      console.log('getServiceList.call()', res)\n    })\n\n    getRoleList().then(res => {\n      console.log('getRoleList.call()', res)\n    })\n  },\n  methods: {\n    handleEdit (record) {\n      this.visible = true\n      console.log('record', record)\n\n      const checkboxGroup = {}\n      this.permissions = record.permissions.map(permission => {\n        const groupKey = `permissions.${permission.permissionId}`\n        checkboxGroup[groupKey] = permission.actionList\n        const actionsOptions = permission.actionEntitySet.map(action => {\n          return {\n            label: action.describe,\n            value: action.action,\n            defaultCheck: action.defaultCheck\n          }\n        })\n        return {\n          ...permission,\n          actionsOptions\n        }\n      })\n\n      this.$nextTick(() => {\n        console.log('permissions', this.permissions)\n        console.log('checkboxGroup', checkboxGroup)\n\n        this.form.setFieldsValue(pick(record, ['id', 'status', 'describe', 'name']))\n        this.form.setFieldsValue(checkboxGroup)\n      })\n    },\n    handleOk (e) {\n      e.preventDefault()\n      this.form.validateFields((err, values) => {\n        console.log(err, values)\n      })\n    },\n    onChange (selectedRowKeys, selectedRows) {\n      this.selectedRowKeys = selectedRowKeys\n      this.selectedRows = selectedRows\n    },\n    handleExpand (expanded, record) {\n      console.log('expanded', expanded, record)\n      if (expanded) {\n        this.expandedRowKeys.push(record.id)\n      } else {\n        this.expandedRowKeys = this.expandedRowKeys.filter(item => record.id !== item)\n      }\n    },\n    toggleAdvanced () {\n      this.advanced = !this.advanced\n    }\n  },\n  watch: {\n    /*\n      'selectedRows': function (selectedRows) {\n        this.needTotalList = this.needTotalList.map(item => {\n          return {\n            ...item,\n            total: selectedRows.reduce( (sum, val) => {\n              return sum + val[item.dataIndex]\n            }, 0)\n          }\n        })\n      }\n      */\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n.permission-form {\n  :deep(.permission-group) {\n    margin-top: 0;\n    margin-bottom: 0;\n  }\n}\n\n</style>\n"
  },
  {
    "path": "src/views/other/modules/OrgModal.vue",
    "content": "<template>\n  <a-modal\n    title=\"操作\"\n    :width=\"600\"\n    :visible=\"visible\"\n    :confirmLoading=\"confirmLoading\"\n    @ok=\"handleOk\"\n    @cancel=\"handleCancel\"\n  >\n    <a-spin :spinning=\"confirmLoading\">\n      <a-form :form=\"form\">\n\n        <a-form-item\n          label=\"父级ID\"\n        >\n          <a-input v-decorator=\"['parentId', {}]\" disabled />\n        </a-form-item>\n\n        <a-form-item\n          label=\"机构名称\"\n        >\n          <a-input v-decorator=\"['orgName', {}]\" />\n        </a-form-item>\n      </a-form>\n    </a-spin>\n  </a-modal>\n</template>\n\n<script>\nexport default {\n  name: 'OrgModal',\n  data () {\n    return {\n      labelCol: {\n        xs: { span: 24 },\n        sm: { span: 5 }\n      },\n      wrapperCol: {\n        xs: { span: 24 },\n        sm: { span: 16 }\n      },\n      visible: false,\n      confirmLoading: false,\n      mdl: {}\n    }\n  },\n  beforeCreate () {\n    this.form = this.$form.createForm(this)\n    console.log('form::', this.form)\n  },\n  created () {\n\n  },\n  methods: {\n    add (id) {\n      this.edit({ parentId: id })\n    },\n    edit (record) {\n      this.mdl = Object.assign({}, record)\n      this.visible = true\n      this.$nextTick(() => {\n        this.form.setFieldsValue({ ...record })\n      })\n    },\n    close () {\n      this.$emit('close')\n      this.visible = false\n    },\n    handleOk () {\n      const _this = this\n      // 触发表单验证\n      this.form.validateFields((err, values) => {\n        // 验证表单没错误\n        if (!err) {\n          console.log('form values', values)\n\n          _this.confirmLoading = true\n          // 模拟后端请求 2000 毫秒延迟\n          new Promise((resolve) => {\n            setTimeout(() => resolve(), 2000)\n          }).then(() => {\n            // Do something\n            _this.$message.success('保存成功')\n            _this.$emit('ok')\n          }).catch(() => {\n            // Do something\n          }).finally(() => {\n            _this.confirmLoading = false\n            _this.close()\n          })\n        }\n      })\n    },\n    handleCancel () {\n      this.close()\n    }\n\n  }\n}\n</script>\n"
  },
  {
    "path": "src/views/other/modules/RoleModal.vue",
    "content": "<template>\n  <a-modal\n    title=\"操作\"\n    :width=\"800\"\n    :visible=\"visible\"\n    :confirmLoading=\"confirmLoading\"\n    @ok=\"handleOk\"\n    @cancel=\"handleCancel\"\n  >\n    <a-steps :current=\"1\">\n      <a-step>\n        <!-- <span slot=\"title\">Finished</span> -->\n        <template slot=\"title\">\n          Finished\n        </template>\n        <span slot=\"description\">This is a description.</span>\n      </a-step>\n      <a-step title=\"In Progress\" description=\"This is a description.\" />\n      <a-step title=\"Waiting\" description=\"This is a description.\" />\n    </a-steps>\n  </a-modal>\n</template>\n\n<script>\nimport { getPermissions } from '@/api/manage'\nimport pick from 'lodash.pick'\n\nexport default {\n  name: 'RoleModal',\n  data () {\n    return {\n      labelCol: {\n        xs: { span: 24 },\n        sm: { span: 5 }\n      },\n      wrapperCol: {\n        xs: { span: 24 },\n        sm: { span: 16 }\n      },\n      visible: false,\n      confirmLoading: false,\n      mdl: {},\n\n      form: this.$form.createForm(this),\n      permissions: []\n    }\n  },\n  created () {\n    this.loadPermissions()\n  },\n  methods: {\n    add () {\n      this.edit({ id: 0 })\n    },\n    edit (record) {\n      this.mdl = Object.assign({}, record)\n      this.visible = true\n\n      // 有权限表，处理勾选\n      if (this.mdl.permissions && this.permissions) {\n        // 先处理要勾选的权限结构\n        const permissionsAction = {}\n        this.mdl.permissions.forEach(permission => {\n          permissionsAction[permission.permissionId] = permission.actionEntitySet.map(entity => entity.action)\n        })\n        // 把权限表遍历一遍，设定要勾选的权限 action\n        this.permissions.forEach(permission => {\n          permission.selected = permissionsAction[permission.id] || []\n        })\n      }\n\n      this.$nextTick(() => {\n        this.form.setFieldsValue(pick(this.mdl, 'id', 'name', 'status', 'describe'))\n      })\n      console.log('this.mdl', this.mdl)\n    },\n    close () {\n      this.$emit('close')\n      this.visible = false\n    },\n    handleOk () {\n      const _this = this\n      // 触发表单验证\n      this.form.validateFields((err, values) => {\n        // 验证表单没错误\n        if (!err) {\n          console.log('form values', values)\n\n          _this.confirmLoading = true\n          // 模拟后端请求 2000 毫秒延迟\n          new Promise((resolve) => {\n            setTimeout(() => resolve(), 2000)\n          }).then(() => {\n            // Do something\n            _this.$message.success('保存成功')\n            _this.$emit('ok')\n          }).catch(() => {\n            // Do something\n          }).finally(() => {\n            _this.confirmLoading = false\n            _this.close()\n          })\n        }\n      })\n    },\n    handleCancel () {\n      this.close()\n    },\n    onChangeCheck (permission) {\n      permission.indeterminate = !!permission.selected.length && (permission.selected.length < permission.actionsOptions.length)\n      permission.checkedAll = permission.selected.length === permission.actionsOptions.length\n    },\n    onChangeCheckAll (e, permission) {\n      Object.assign(permission, {\n        selected: e.target.checked ? permission.actionsOptions.map(obj => obj.value) : [],\n        indeterminate: false,\n        checkedAll: e.target.checked\n      })\n    },\n    loadPermissions () {\n      const that = this\n      getPermissions().then(res => {\n        const result = res.result\n        that.permissions = result.map(permission => {\n          const options = JSON.parse(permission.actionData) || []\n          permission.checkedAll = false\n          permission.selected = []\n          permission.indeterminate = false\n          permission.actionsOptions = options.map(option => {\n            return {\n              label: option.describe,\n              value: option.action\n            }\n          })\n          return permission\n        })\n      })\n    }\n\n  }\n}\n</script>\n\n<style scoped>\n\n</style>\n"
  },
  {
    "path": "src/views/profile/advanced/Advanced.vue",
    "content": "<template>\n  <page-header-wrapper\n    title=\"单号：234231029431\"\n    :tab-list=\"tabList\"\n    :tab-active-key=\"tabActiveKey\"\n    @tabChange=\"handleTabChange\"\n  >\n    <template v-slot:content>\n      <a-descriptions size=\"small\" :column=\"isMobile ? 1 : 2\">\n        <a-descriptions-item label=\"创建人\">曲丽丽</a-descriptions-item>\n        <a-descriptions-item label=\"订购产品\">XX 服务</a-descriptions-item>\n        <a-descriptions-item label=\"创建时间\">2017-07-07</a-descriptions-item>\n        <a-descriptions-item label=\"关联单据\">\n          <a href=\"\">12421</a>\n        </a-descriptions-item>\n        <a-descriptions-item label=\"生效日期\">2017-07-07 ~ 2017-08-08</a-descriptions-item>\n        <a-descriptions-item label=\"备注\">请于两个工作日内确认</a-descriptions-item>\n      </a-descriptions>\n    </template>\n\n    <!-- actions -->\n    <template v-slot:extra>\n      <a-button-group style=\"margin-right: 4px;\">\n        <a-button>操作</a-button>\n        <a-button>操作</a-button>\n        <a-button><a-icon type=\"ellipsis\"/></a-button>\n      </a-button-group>\n      <a-button type=\"primary\" >主操作</a-button>\n    </template>\n\n    <template v-slot:extraContent>\n      <a-row class=\"status-list\">\n        <a-col :xs=\"12\" :sm=\"12\">\n          <div class=\"text\">状态</div>\n          <div class=\"heading\">待审批</div>\n        </a-col>\n        <a-col :xs=\"12\" :sm=\"12\">\n          <div class=\"text\">订单金额</div>\n          <div class=\"heading\">¥ 568.08</div>\n        </a-col>\n      </a-row>\n    </template>\n\n    <a-card :bordered=\"false\" title=\"流程进度\">\n      <a-steps :direction=\"isMobile && 'vertical' || 'horizontal'\" :current=\"1\" progressDot>\n        <a-step>\n          <template v-slot:title>\n            <span>创建项目</span>\n          </template>\n          <template v-slot:description>\n            <div class=\"antd-pro-pages-profile-advanced-style-stepDescription\">\n              曲丽丽<a-icon type=\"dingding\" style=\"margin-left: 8px;\" />\n              <div>2016-12-12 12:32</div>\n            </div>\n          </template>\n        </a-step>\n        <a-step>\n          <template v-slot:title>\n            <span>部门初审</span>\n          </template>\n          <template v-slot:description>\n            <div class=\"antd-pro-pages-profile-advanced-style-stepDescription\">\n              周毛毛<a-icon type=\"dingding\" style=\"color: rgb(0, 160, 233); margin-left: 8px;\" />\n              <div><a>催一下</a></div>\n            </div>\n          </template>\n        </a-step>\n        <a-step title=\"财务复核\" />\n        <a-step title=\"完成\" />\n      </a-steps>\n    </a-card>\n\n    <a-card style=\"margin-top: 24px\" :bordered=\"false\" title=\"用户信息\">\n      <a-descriptions>\n        <a-descriptions-item label=\"用户姓名\">付晓晓</a-descriptions-item>\n        <a-descriptions-item label=\"会员卡号\">32943898021309809423</a-descriptions-item>\n        <a-descriptions-item label=\"身份证\">3321944288191034921</a-descriptions-item>\n        <a-descriptions-item label=\"联系方式\">18112345678</a-descriptions-item>\n        <a-descriptions-item label=\"联系地址\">浙江省杭州市西湖区黄姑山路工专路交叉路口</a-descriptions-item>\n      </a-descriptions>\n      <a-descriptions title=\"信息组\">\n        <a-descriptions-item label=\"某某数据\">725</a-descriptions-item>\n        <a-descriptions-item label=\"该数据更新时间\">2018-08-08</a-descriptions-item>\n        <a-descriptions-item ></a-descriptions-item>\n        <a-descriptions-item label=\"某某数据\">725</a-descriptions-item>\n        <a-descriptions-item label=\"该数据更新时间\">2018-08-08</a-descriptions-item>\n        <a-descriptions-item ></a-descriptions-item>\n      </a-descriptions>\n      <a-card type=\"inner\" title=\"多层信息组\">\n        <a-descriptions title=\"组名称\" size=\"small\">\n          <a-descriptions-item label=\"负责人\">林东东</a-descriptions-item>\n          <a-descriptions-item label=\"角色码\">1234567</a-descriptions-item>\n          <a-descriptions-item label=\"所属部门\">XX公司-YY部</a-descriptions-item>\n          <a-descriptions-item label=\"过期时间\">2018-08-08</a-descriptions-item>\n          <a-descriptions-item label=\"描述\">这段描述很长很长很长很长很长很长很长很长很长很长很长很长很长很长...</a-descriptions-item>\n        </a-descriptions>\n        <a-divider style=\"margin: 16px 0\" />\n        <a-descriptions title=\"组名称\" size=\"small\" :col=\"1\">\n          <a-descriptions-item label=\"学名\">\tCitrullus lanatus (Thunb.) Matsum. et Nakai一年生蔓生藤本；茎、枝粗壮，具明显的棱。卷须较粗..</a-descriptions-item>\n        </a-descriptions>\n        <a-divider style=\"margin: 16px 0\" />\n        <a-descriptions title=\"组名称\" size=\"small\" :col=\"2\">\n          <a-descriptions-item label=\"负责人\">付小小</a-descriptions-item>\n          <a-descriptions-item label=\"角色码\">1234567</a-descriptions-item>\n        </a-descriptions>\n      </a-card>\n\n    </a-card>\n\n    <a-card style=\"margin-top: 24px\" :bordered=\"false\" title=\"用户近半年来电记录\">\n      <div class=\"no-data\"><a-icon type=\"frown-o\"/>暂无数据</div>\n    </a-card>\n\n    <!-- 操作 -->\n    <a-card\n      style=\"margin-top: 24px\"\n      :bordered=\"false\"\n      :tabList=\"operationTabList\"\n      :activeTabKey=\"operationActiveTabKey\"\n      @tabChange=\"(key) => {this.operationActiveTabKey = key}\"\n    >\n      <a-table\n        v-if=\"operationActiveTabKey === '1'\"\n        :columns=\"operationColumns\"\n        :dataSource=\"operation1\"\n        :pagination=\"false\"\n      >\n        <template\n          slot=\"status\"\n          slot-scope=\"status\">\n          <a-badge :status=\"status | statusTypeFilter\" :text=\"status | statusFilter\"/>\n        </template>\n      </a-table>\n      <a-table\n        v-if=\"operationActiveTabKey === '2'\"\n        :columns=\"operationColumns\"\n        :dataSource=\"operation2\"\n        :pagination=\"false\"\n      >\n        <template\n          slot=\"status\"\n          slot-scope=\"status\">\n          <a-badge :status=\"status | statusTypeFilter\" :text=\"status | statusFilter\"/>\n        </template>\n      </a-table>\n      <a-table\n        v-if=\"operationActiveTabKey === '3'\"\n        :columns=\"operationColumns\"\n        :dataSource=\"operation3\"\n        :pagination=\"false\"\n      >\n        <template\n          slot=\"status\"\n          slot-scope=\"status\">\n          <a-badge :status=\"status | statusTypeFilter\" :text=\"status | statusFilter\"/>\n        </template>\n      </a-table>\n    </a-card>\n\n  </page-header-wrapper>\n</template>\n\n<script>\nimport { baseMixin } from '@/store/app-mixin'\n\nexport default {\n  name: 'Advanced',\n  mixins: [baseMixin],\n  data () {\n    return {\n      tabList: [\n        { key: 'detail', tab: '详情' },\n        { key: 'rule', tab: '规则' }\n      ],\n      tabActiveKey: 'detail',\n\n      operationTabList: [\n        {\n          key: '1',\n          tab: '操作日志一'\n        },\n        {\n          key: '2',\n          tab: '操作日志二'\n        },\n        {\n          key: '3',\n          tab: '操作日志三'\n        }\n      ],\n      operationActiveTabKey: '1',\n\n      operationColumns: [\n        {\n          title: '操作类型',\n          dataIndex: 'type',\n          key: 'type'\n        },\n        {\n          title: '操作人',\n          dataIndex: 'name',\n          key: 'name'\n        },\n        {\n          title: '执行结果',\n          dataIndex: 'status',\n          key: 'status',\n          scopedSlots: { customRender: 'status' }\n        },\n        {\n          title: '操作时间',\n          dataIndex: 'updatedAt',\n          key: 'updatedAt'\n        },\n        {\n          title: '备注',\n          dataIndex: 'remark',\n          key: 'remark'\n        }\n      ],\n      operation1: [\n        {\n          key: 'op1',\n          type: '订购关系生效',\n          name: '曲丽丽',\n          status: 'agree',\n          updatedAt: '2017-10-03  19:23:12',\n          remark: '-'\n        },\n        {\n          key: 'op2',\n          type: '财务复审',\n          name: '付小小',\n          status: 'reject',\n          updatedAt: '2017-10-03  19:23:12',\n          remark: '不通过原因'\n        },\n        {\n          key: 'op3',\n          type: '部门初审',\n          name: '周毛毛',\n          status: 'agree',\n          updatedAt: '2017-10-03  19:23:12',\n          remark: '-'\n        },\n        {\n          key: 'op4',\n          type: '提交订单',\n          name: '林东东',\n          status: 'agree',\n          updatedAt: '2017-10-03  19:23:12',\n          remark: '很棒'\n        },\n        {\n          key: 'op5',\n          type: '创建订单',\n          name: '汗牙牙',\n          status: 'agree',\n          updatedAt: '2017-10-03  19:23:12',\n          remark: '-'\n        }\n      ],\n      operation2: [\n        {\n          key: 'op2',\n          type: '财务复审',\n          name: '付小小',\n          status: 'reject',\n          updatedAt: '2017-10-03  19:23:12',\n          remark: '不通过原因'\n        },\n        {\n          key: 'op3',\n          type: '部门初审',\n          name: '周毛毛',\n          status: 'agree',\n          updatedAt: '2017-10-03  19:23:12',\n          remark: '-'\n        },\n        {\n          key: 'op4',\n          type: '提交订单',\n          name: '林东东',\n          status: 'agree',\n          updatedAt: '2017-10-03  19:23:12',\n          remark: '很棒'\n        }\n      ],\n      operation3: [\n        {\n          key: 'op2',\n          type: '财务复审',\n          name: '付小小',\n          status: 'reject',\n          updatedAt: '2017-10-03  19:23:12',\n          remark: '不通过原因'\n        },\n        {\n          key: 'op3',\n          type: '部门初审',\n          name: '周毛毛',\n          status: 'agree',\n          updatedAt: '2017-10-03  19:23:12',\n          remark: '-'\n        }\n      ]\n    }\n  },\n  filters: {\n    statusFilter (status) {\n      const statusMap = {\n        'agree': '成功',\n        'reject': '驳回'\n      }\n      return statusMap[status]\n    },\n    statusTypeFilter (type) {\n      const statusTypeMap = {\n        'agree': 'success',\n        'reject': 'error'\n      }\n      return statusTypeMap[type]\n    }\n  },\n  methods: {\n    handleTabChange (key) {\n      console.log('')\n      this.tabActiveKey = key\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n\n  .detail-layout {\n    margin-left: 44px;\n  }\n  .text {\n    color: rgba(0, 0, 0, .45);\n  }\n\n  .heading {\n    color: rgba(0, 0, 0, .85);\n    font-size: 20px;\n  }\n\n  .no-data {\n    color: rgba(0, 0, 0, .25);\n    text-align: center;\n    line-height: 64px;\n    font-size: 16px;\n\n    i {\n      font-size: 24px;\n      margin-right: 16px;\n      position: relative;\n      top: 3px;\n    }\n  }\n\n  .mobile {\n    .detail-layout {\n      margin-left: unset;\n    }\n    .text {\n\n    }\n    .status-list {\n      text-align: left;\n    }\n  }\n</style>\n"
  },
  {
    "path": "src/views/profile/basic/index.vue",
    "content": "<template>\n  <page-header-wrapper>\n    <a-card :bordered=\"false\">\n      <a-descriptions title=\"退款申请\">\n        <a-descriptions-item label=\"取货单号\">1000000000</a-descriptions-item>\n        <a-descriptions-item label=\"状态\">已取货</a-descriptions-item>\n        <a-descriptions-item label=\"销售单号\">1234123421</a-descriptions-item>\n        <a-descriptions-item label=\"子订单\">3214321432</a-descriptions-item>\n      </a-descriptions>\n      <a-divider style=\"margin-bottom: 32px\"/>\n      <a-descriptions title=\"用户信息\">\n        <a-descriptions-item label=\"用户姓名\">付小小</a-descriptions-item>\n        <a-descriptions-item label=\"联系电话\">18100000000</a-descriptions-item>\n        <a-descriptions-item label=\"常用快递\">菜鸟仓储</a-descriptions-item>\n        <a-descriptions-item label=\"取货地址\">浙江省杭州市西湖区万塘路18号</a-descriptions-item>\n        <a-descriptions-item label=\"备注\">\t无</a-descriptions-item>\n      </a-descriptions>\n      <a-divider style=\"margin-bottom: 32px\"/>\n\n      <div class=\"title\">退货商品</div>\n      <s-table\n        style=\"margin-bottom: 24px\"\n        row-key=\"id\"\n        :columns=\"goodsColumns\"\n        :data=\"loadGoodsData\">\n\n      </s-table>\n\n      <div class=\"title\">退货进度</div>\n      <s-table\n        style=\"margin-bottom: 24px\"\n        row-key=\"key\"\n        :columns=\"scheduleColumns\"\n        :data=\"loadScheduleData\">\n\n        <template\n          slot=\"status\"\n          slot-scope=\"status\">\n          <a-badge :status=\"status\" :text=\"status | statusFilter\"/>\n        </template>\n\n      </s-table>\n    </a-card>\n  </page-header-wrapper>\n</template>\n\n<script>\nimport { STable } from '@/components'\n\nexport default {\n  components: {\n    STable\n  },\n  data () {\n    return {\n      goodsColumns: [\n        {\n          title: '商品编号',\n          dataIndex: 'id',\n          key: 'id'\n        },\n        {\n          title: '商品名称',\n          dataIndex: 'name',\n          key: 'name'\n        },\n        {\n          title: '商品条码',\n          dataIndex: 'barcode',\n          key: 'barcode'\n        },\n        {\n          title: '单价',\n          dataIndex: 'price',\n          key: 'price',\n          align: 'right'\n        },\n        {\n          title: '数量（件）',\n          dataIndex: 'num',\n          key: 'num',\n          align: 'right'\n        },\n        {\n          title: '金额',\n          dataIndex: 'amount',\n          key: 'amount',\n          align: 'right'\n        }\n      ],\n      // 加载数据方法 必须为 Promise 对象\n      loadGoodsData: () => {\n        return new Promise(resolve => {\n          resolve({\n            data: [\n              {\n                id: '1234561',\n                name: '矿泉水 550ml',\n                barcode: '12421432143214321',\n                price: '2.00',\n                num: '1',\n                amount: '2.00'\n              },\n              {\n                id: '1234562',\n                name: '凉茶 300ml',\n                barcode: '12421432143214322',\n                price: '3.00',\n                num: '2',\n                amount: '6.00'\n              },\n              {\n                id: '1234563',\n                name: '好吃的薯片',\n                barcode: '12421432143214323',\n                price: '7.00',\n                num: '4',\n                amount: '28.00'\n              },\n              {\n                id: '1234564',\n                name: '特别好吃的蛋卷',\n                barcode: '12421432143214324',\n                price: '8.50',\n                num: '3',\n                amount: '25.50'\n              }\n            ],\n            pageSize: 10,\n            pageNo: 1,\n            totalPage: 1,\n            totalCount: 10\n          })\n        }).then(res => {\n          return res\n        })\n      },\n\n      scheduleColumns: [\n        {\n          title: '时间',\n          dataIndex: 'time',\n          key: 'time'\n        },\n        {\n          title: '当前进度',\n          dataIndex: 'rate',\n          key: 'rate'\n        },\n        {\n          title: '状态',\n          dataIndex: 'status',\n          key: 'status',\n          scopedSlots: { customRender: 'status' }\n        },\n        {\n          title: '操作员ID',\n          dataIndex: 'operator',\n          key: 'operator'\n        },\n        {\n          title: '耗时',\n          dataIndex: 'cost',\n          key: 'cost'\n        }\n      ],\n      loadScheduleData: () => {\n        return new Promise(resolve => {\n          resolve({\n            data: [\n              {\n                key: '1',\n                time: '2017-10-01 14:10',\n                rate: '联系客户',\n                status: 'processing',\n                operator: '取货员 ID1234',\n                cost: '5mins'\n              },\n              {\n                key: '2',\n                time: '2017-10-01 14:05',\n                rate: '取货员出发',\n                status: 'success',\n                operator: '取货员 ID1234',\n                cost: '1h'\n              },\n              {\n                key: '3',\n                time: '2017-10-01 13:05',\n                rate: '取货员接单',\n                status: 'success',\n                operator: '取货员 ID1234',\n                cost: '5mins'\n              },\n              {\n                key: '4',\n                time: '2017-10-01 13:00',\n                rate: '申请审批通过',\n                status: 'success',\n                operator: '系统',\n                cost: '1h'\n              },\n              {\n                key: '5',\n                time: '2017-10-01 12:00',\n                rate: '发起退货申请',\n                status: 'success',\n                operator: '用户',\n                cost: '5mins'\n              }\n            ],\n            pageSize: 10,\n            pageNo: 1,\n            totalPage: 1,\n            totalCount: 10\n          })\n        }).then(res => {\n          return res\n        })\n      }\n    }\n  },\n  filters: {\n    statusFilter (status) {\n      const statusMap = {\n        'processing': '进行中',\n        'success': '完成',\n        'failed': '失败'\n      }\n      return statusMap[status]\n    }\n  },\n  computed: {\n    title () {\n      return this.$route.meta.title\n    }\n  }\n\n}\n</script>\n\n<style lang=\"less\" scoped>\n  .title {\n    color: rgba(0,0,0,.85);\n    font-size: 16px;\n    font-weight: 500;\n    margin-bottom: 16px;\n  }\n</style>\n"
  },
  {
    "path": "src/views/result/Error.vue",
    "content": "<template>\n  <a-card :bordered=\"false\">\n    <a-result status=\"error\" :title=\"result.title\" :sub-title=\"result.description\">\n      <template #extra>\n        <a-button type=\"primary\" >{{ $t('result.fail.error.btn-text') }}</a-button>\n      </template>\n      <div class=\"desc\">\n        <div style=\"font-size: 16px; color: rgba(0, 0, 0, 0.85); font-weight: 500; margin-bottom: 16px\">\n          {{ $t('result.fail.error.hint-title') }}\n        </div>\n        <div style=\"margin-bottom: 16px\">\n          <a-icon type=\"close-circle-o\" style=\"color: #f5222d; margin-right: 8px\"/>\n          {{ $t('result.fail.error.hint-text1') }}\n          <a style=\"margin-left: 16px\">{{ $t('result.fail.error.hint-btn1') }} <a-icon type=\"right\" /></a>\n        </div>\n        <div>\n          <a-icon type=\"close-circle-o\" style=\"color: #f5222d; margin-right: 8px\"/>\n          {{ $t('result.fail.error.hint-text2') }}\n          <a style=\"margin-left: 16px\">{{ $t('result.fail.error.hint-btn2') }} <a-icon type=\"right\" /></a>\n        </div>\n      </div>\n    </a-result>\n  </a-card>\n</template>\n\n<script>\n\nexport default {\n  name: 'Error',\n  computed: {\n    result () {\n      return {\n      title: this.$t('result.fail.error.title'),\n      description: this.$t('result.fail.error.description')\n      }\n    }\n  }\n}\n</script>\n"
  },
  {
    "path": "src/views/result/Success.vue",
    "content": "<template>\n  <a-card :bordered=\"false\">\n    <a-result status=\"success\" :title=\"result.title\" :sub-title=\"result.description\">\n      <template #extra>\n        <a-button type=\"primary\">{{ $t('result.success.btn-return') }}</a-button>\n        <a-button style=\"margin-left: 8px\">{{ $t('result.success.btn-project') }}</a-button>\n        <a-button style=\"margin-left: 8px\">{{ $t('result.success.btn-print') }}</a-button>\n      </template>\n      <div class=\"content\">\n        <div style=\"font-size: 16px; color: rgba(0, 0, 0, 0.85); font-weight: 500; margin-bottom: 20px;\">{{ $t('result.success.operate-title') }}</div>\n        <a-row style=\"margin-bottom: 16px\">\n          <a-col :xs=\"24\" :sm=\"12\" :md=\"12\" :lg=\"12\" :xl=\"6\">\n            <span style=\"color: rgba(0, 0, 0, 0.85)\">{{ $t('result.success.operate-id') }}：</span>\n            20180724089\n          </a-col>\n          <a-col :xs=\"24\" :sm=\"12\" :md=\"12\" :lg=\"12\" :xl=\"6\">\n            <span style=\"color: rgba(0, 0, 0, 0.85)\">{{ $t('result.success.principal') }}：</span>\n            曲丽丽是谁？\n          </a-col>\n          <a-col :xs=\"24\" :sm=\"24\" :md=\"24\" :lg=\"24\" :xl=\"12\">\n            <span style=\"color: rgba(0, 0, 0, 0.85)\">{{ $t('result.success.operate-time') }}：</span>\n            2016-12-12 ~ 2017-12-12\n          </a-col>\n        </a-row>\n        <a-steps :current=\"1\" :direction=\"isMobile && directionType.vertical || directionType.horizontal\" progressDot>\n          <a-step :title=\"$t('result.success.step1-title')\">\n            <span style=\"font-size: 14px\" slot=\"title\">{{ $t('result.success.step1-title') }}</span>\n            <template slot=\"description\">\n              <div style=\"fontSize: 12px; color: rgba(0, 0, 0, 0.45); position: relative; left: 42px;text-align: left;\" slot=\"description\" >\n                <div style=\"margin: 8px 0 4px\">\n                  曲丽丽\n                  <a-icon style=\"margin-left: 8px\" type=\"dingding-o\" />\n                </div>\n                <div>2016-12-12 12:32</div>\n              </div>\n            </template>\n          </a-step>\n          <a-step :title=\"$t('result.success.step2-title')\">\n            <span style=\"font-size: 14px\" slot=\"title\">{{ $t('result.success.step2-title') }}</span>\n            <template slot=\"description\">\n              <div style=\"fontSize: 12px; color: rgba(0, 0, 0, 0.45); position: relative; left: 42px;text-align: left;\" slot=\"description\" >\n                <div style=\"margin: 8px 0 4px\">\n                  周毛毛\n                  <a-icon style=\"margin-left: 8px; color: #00A0E9\" type=\"dingding-o\" />\n                </div>\n                <div><a href=\"\">催一下</a></div>\n              </div>\n            </template>\n          </a-step>\n          <a-step :title=\"$t('result.success.step3-title')\">\n            <span style=\"font-size: 14px\" slot=\"title\">{{ $t('result.success.step3-title') }}</span>\n          </a-step>\n          <a-step :title=\"$t('result.success.step4-title')\" >\n            <span style=\"font-size: 14px\" slot=\"title\">{{ $t('result.success.step4-title') }}</span>\n          </a-step>\n        </a-steps>\n      </div>\n    </a-result>\n  </a-card>\n</template>\n\n<script>\nimport { baseMixin } from '@/store/app-mixin'\n\nconst directionType = {\n  horizontal: 'horizontal',\n  vertical: 'vertical'\n}\n\nexport default {\n  name: 'Success',\n  mixins: [baseMixin],\n  data () {\n    this.directionType = directionType\n    return {\n      // title: this.$t('result.success.title'),\n      // description: this.$t('result.success.description')\n    }\n  },\n  computed: {\n    result () {\n      return {\n      title: this.$t('result.success.title'),\n      description: this.$t('result.success.description')\n      }\n    }\n  }\n}\n</script>\n"
  },
  {
    "path": "src/views/user/Login.vue",
    "content": "<template>\n  <div class=\"main\">\n    <a-form\n      id=\"formLogin\"\n      class=\"user-layout-login\"\n      ref=\"formLogin\"\n      :form=\"form\"\n      @submit=\"handleSubmit\"\n    >\n      <a-tabs\n        :activeKey=\"customActiveKey\"\n        :tabBarStyle=\"{ textAlign: 'center', borderBottom: 'unset' }\"\n        @change=\"handleTabClick\"\n      >\n        <a-tab-pane key=\"tab1\" :tab=\"$t('user.login.tab-login-credentials')\">\n          <a-alert v-if=\"isLoginError\" type=\"error\" showIcon style=\"margin-bottom: 24px;\" :message=\"$t('user.login.message-invalid-credentials')\" />\n          <a-form-item>\n            <a-input\n              size=\"large\"\n              type=\"text\"\n              :placeholder=\"$t('user.login.username.placeholder')\"\n              v-decorator=\"[\n                'username',\n                {rules: [{ required: true, message: $t('user.userName.required') }, { validator: handleUsernameOrEmail }], validateTrigger: 'change'}\n              ]\"\n            >\n              <a-icon slot=\"prefix\" type=\"user\" :style=\"{ color: 'rgba(0,0,0,.25)' }\"/>\n            </a-input>\n          </a-form-item>\n\n          <a-form-item>\n            <a-input-password\n              size=\"large\"\n              :placeholder=\"$t('user.login.password.placeholder')\"\n              v-decorator=\"[\n                'password',\n                {rules: [{ required: true, message: $t('user.password.required') }], validateTrigger: 'blur'}\n              ]\"\n            >\n              <a-icon slot=\"prefix\" type=\"lock\" :style=\"{ color: 'rgba(0,0,0,.25)' }\"/>\n            </a-input-password>\n          </a-form-item>\n        </a-tab-pane>\n        <a-tab-pane key=\"tab2\" :tab=\"$t('user.login.tab-login-mobile')\">\n          <a-form-item>\n            <a-input size=\"large\" type=\"text\" :placeholder=\"$t('user.login.mobile.placeholder')\" v-decorator=\"['mobile', {rules: [{ required: true, pattern: /^1[34578]\\d{9}$/, message: $t('user.login.mobile.placeholder') }], validateTrigger: 'change'}]\">\n              <a-icon slot=\"prefix\" type=\"mobile\" :style=\"{ color: 'rgba(0,0,0,.25)' }\"/>\n            </a-input>\n          </a-form-item>\n\n          <a-row :gutter=\"16\">\n            <a-col class=\"gutter-row\" :span=\"16\">\n              <a-form-item>\n                <a-input size=\"large\" type=\"text\" :placeholder=\"$t('user.login.mobile.verification-code.placeholder')\" v-decorator=\"['captcha', {rules: [{ required: true, message: $t('user.verification-code.required') }], validateTrigger: 'blur'}]\">\n                  <a-icon slot=\"prefix\" type=\"mail\" :style=\"{ color: 'rgba(0,0,0,.25)' }\"/>\n                </a-input>\n              </a-form-item>\n            </a-col>\n            <a-col class=\"gutter-row\" :span=\"8\">\n              <a-button\n                class=\"getCaptcha\"\n                tabindex=\"-1\"\n                :disabled=\"state.smsSendBtn\"\n                @click.stop.prevent=\"getCaptcha\"\n                v-text=\"!state.smsSendBtn && $t('user.register.get-verification-code') || (state.time+' s')\"\n              ></a-button>\n            </a-col>\n          </a-row>\n        </a-tab-pane>\n      </a-tabs>\n\n      <a-form-item>\n        <a-checkbox v-decorator=\"['rememberMe', { valuePropName: 'checked' }]\">{{ $t('user.login.remember-me') }}</a-checkbox>\n        <router-link\n          :to=\"{ name: 'recover', params: { user: 'aaa'} }\"\n          class=\"forge-password\"\n          style=\"float: right;\"\n        >{{ $t('user.login.forgot-password') }}</router-link>\n      </a-form-item>\n\n      <a-form-item style=\"margin-top:24px\">\n        <a-button\n          size=\"large\"\n          type=\"primary\"\n          htmlType=\"submit\"\n          class=\"login-button\"\n          :loading=\"state.loginBtn\"\n          :disabled=\"state.loginBtn\"\n        >{{ $t('user.login.login') }}</a-button>\n      </a-form-item>\n\n      <div class=\"user-login-other\">\n        <span>{{ $t('user.login.sign-in-with') }}</span>\n        <a>\n          <a-icon class=\"item-icon\" type=\"alipay-circle\"></a-icon>\n        </a>\n        <a>\n          <a-icon class=\"item-icon\" type=\"taobao-circle\"></a-icon>\n        </a>\n        <a>\n          <a-icon class=\"item-icon\" type=\"weibo-circle\"></a-icon>\n        </a>\n        <router-link class=\"register\" :to=\"{ name: 'register' }\">{{ $t('user.login.signup') }}</router-link>\n      </div>\n    </a-form>\n\n    <two-step-captcha\n      v-if=\"requiredTwoStepCaptcha\"\n      :visible=\"stepCaptchaVisible\"\n      @success=\"stepCaptchaSuccess\"\n      @cancel=\"stepCaptchaCancel\"\n    ></two-step-captcha>\n  </div>\n</template>\n\n<script>\nimport md5 from 'md5'\nimport TwoStepCaptcha from '@/components/tools/TwoStepCaptcha'\nimport { mapActions } from 'vuex'\nimport { timeFix } from '@/utils/util'\nimport { getSmsCaptcha, get2step } from '@/api/login'\n\nexport default {\n  components: {\n    TwoStepCaptcha\n  },\n  data () {\n    return {\n      customActiveKey: 'tab1',\n      loginBtn: false,\n      // login type: 0 email, 1 username, 2 telephone\n      loginType: 0,\n      isLoginError: false,\n      requiredTwoStepCaptcha: false,\n      stepCaptchaVisible: false,\n      form: this.$form.createForm(this),\n      state: {\n        time: 60,\n        loginBtn: false,\n        // login type: 0 email, 1 username, 2 telephone\n        loginType: 0,\n        smsSendBtn: false\n      }\n    }\n  },\n  created () {\n    get2step({ })\n      .then(res => {\n        this.requiredTwoStepCaptcha = res.result.stepCode\n      })\n      .catch(() => {\n        this.requiredTwoStepCaptcha = false\n      })\n    // this.requiredTwoStepCaptcha = true\n  },\n  methods: {\n    ...mapActions(['Login', 'Logout']),\n    // handler\n    handleUsernameOrEmail (rule, value, callback) {\n      const { state } = this\n      const regex = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((\\.[a-zA-Z0-9_-]{2,3}){1,2})$/\n      if (regex.test(value)) {\n        state.loginType = 0\n      } else {\n        state.loginType = 1\n      }\n      callback()\n    },\n    handleTabClick (key) {\n      this.customActiveKey = key\n      // this.form.resetFields()\n    },\n    handleSubmit (e) {\n      e.preventDefault()\n      const {\n        form: { validateFields },\n        state,\n        customActiveKey,\n        Login\n      } = this\n\n      state.loginBtn = true\n\n      const validateFieldsKey = customActiveKey === 'tab1' ? ['username', 'password'] : ['mobile', 'captcha']\n\n      validateFields(validateFieldsKey, { force: true }, (err, values) => {\n        if (!err) {\n          console.log('login form', values)\n          const loginParams = { ...values }\n          delete loginParams.username\n          loginParams[!state.loginType ? 'email' : 'username'] = values.username\n          loginParams.password = md5(values.password)\n          Login(loginParams)\n            .then((res) => this.loginSuccess(res))\n            .catch(err => this.requestFailed(err))\n            .finally(() => {\n              state.loginBtn = false\n            })\n        } else {\n          setTimeout(() => {\n            state.loginBtn = false\n          }, 600)\n        }\n      })\n    },\n    getCaptcha (e) {\n      e.preventDefault()\n      const { form: { validateFields }, state } = this\n\n      validateFields(['mobile'], { force: true }, (err, values) => {\n        if (!err) {\n          state.smsSendBtn = true\n\n          const interval = window.setInterval(() => {\n            if (state.time-- <= 0) {\n              state.time = 60\n              state.smsSendBtn = false\n              window.clearInterval(interval)\n            }\n          }, 1000)\n\n          const hide = this.$message.loading('验证码发送中..', 0)\n          getSmsCaptcha({ mobile: values.mobile }).then(res => {\n            setTimeout(hide, 2500)\n            this.$notification['success']({\n              message: '提示',\n              description: '验证码获取成功，您的验证码为：' + res.result.captcha,\n              duration: 8\n            })\n          }).catch(err => {\n            setTimeout(hide, 1)\n            clearInterval(interval)\n            state.time = 60\n            state.smsSendBtn = false\n            this.requestFailed(err)\n          })\n        }\n      })\n    },\n    stepCaptchaSuccess () {\n      this.loginSuccess()\n    },\n    stepCaptchaCancel () {\n      this.Logout().then(() => {\n        this.loginBtn = false\n        this.stepCaptchaVisible = false\n      })\n    },\n    loginSuccess (res) {\n      console.log(res)\n      // check res.homePage define, set $router.push name res.homePage\n      // Why not enter onComplete\n      /*\n      this.$router.push({ name: 'analysis' }, () => {\n        console.log('onComplete')\n        this.$notification.success({\n          message: '欢迎',\n          description: `${timeFix()}，欢迎回来`\n        })\n      })\n      */\n      this.$router.push({ path: '/' })\n      // 延迟 1 秒显示欢迎信息\n      setTimeout(() => {\n        this.$notification.success({\n          message: '欢迎',\n          description: `${timeFix()}，欢迎回来`\n        })\n      }, 1000)\n      this.isLoginError = false\n    },\n    requestFailed (err) {\n      this.isLoginError = true\n      this.$notification['error']({\n        message: '错误',\n        description: ((err.response || {}).data || {}).message || '请求出现错误，请稍后再试',\n        duration: 4\n      })\n    }\n  }\n}\n</script>\n\n<style lang=\"less\" scoped>\n.user-layout-login {\n  label {\n    font-size: 14px;\n  }\n\n  .getCaptcha {\n    display: block;\n    width: 100%;\n    height: 40px;\n  }\n\n  .forge-password {\n    font-size: 14px;\n  }\n\n  button.login-button {\n    padding: 0 15px;\n    font-size: 16px;\n    height: 40px;\n    width: 100%;\n  }\n\n  .user-login-other {\n    text-align: left;\n    margin-top: 24px;\n    line-height: 22px;\n\n    .item-icon {\n      font-size: 24px;\n      color: rgba(0, 0, 0, 0.2);\n      margin-left: 16px;\n      vertical-align: middle;\n      cursor: pointer;\n      transition: color 0.3s;\n\n      &:hover {\n        color: #1890ff;\n      }\n    }\n\n    .register {\n      float: right;\n    }\n  }\n}\n</style>\n"
  },
  {
    "path": "src/views/user/Register.vue",
    "content": "<template>\n  <div class=\"main user-layout-register\">\n    <h3><span>{{ $t('user.register.register') }}</span></h3>\n    <a-form ref=\"formRegister\" :form=\"form\" id=\"formRegister\">\n      <a-form-item>\n        <a-input\n          size=\"large\"\n          type=\"text\"\n          :placeholder=\"$t('user.register.email.placeholder')\"\n          v-decorator=\"['email', {rules: [{ required: true, type: 'email', message: $t('user.email.required') }], validateTrigger: ['change', 'blur']}]\"\n        ></a-input>\n      </a-form-item>\n\n      <a-popover\n        placement=\"rightTop\"\n        :trigger=\"['focus']\"\n        :getPopupContainer=\"(trigger) => trigger.parentElement\"\n        v-model=\"state.passwordLevelChecked\">\n        <template slot=\"content\">\n          <div :style=\"{ width: '240px' }\" >\n            <div :class=\"['user-register', passwordLevelClass]\">{{ $t(passwordLevelName) }}</div>\n            <a-progress :percent=\"state.percent\" :showInfo=\"false\" :strokeColor=\" passwordLevelColor \" />\n            <div style=\"margin-top: 10px;\">\n              <span>{{ $t('user.register.password.popover-message') }}\n              </span>\n            </div>\n          </div>\n        </template>\n        <a-form-item>\n          <a-input-password\n            size=\"large\"\n            @click=\"handlePasswordInputClick\"\n            :placeholder=\"$t('user.register.password.placeholder')\"\n            v-decorator=\"['password', {rules: [{ required: true, message: $t('user.password.required') }, { validator: this.handlePasswordLevel }], validateTrigger: ['change', 'blur']}]\"\n          ></a-input-password>\n        </a-form-item>\n      </a-popover>\n\n      <a-form-item>\n        <a-input-password\n          size=\"large\"\n          :placeholder=\"$t('user.register.confirm-password.placeholder')\"\n          v-decorator=\"['password2', {rules: [{ required: true, message: $t('user.password.required') }, { validator: this.handlePasswordCheck }], validateTrigger: ['change', 'blur']}]\"\n        ></a-input-password>\n      </a-form-item>\n\n      <a-form-item>\n        <a-input size=\"large\" :placeholder=\"$t('user.login.mobile.placeholder')\" v-decorator=\"['mobile', {rules: [{ required: true, message: $t('user.phone-number.required'), pattern: /^1[3456789]\\d{9}$/ }, { validator: this.handlePhoneCheck } ], validateTrigger: ['change', 'blur'] }]\">\n          <a-select slot=\"addonBefore\" size=\"large\" defaultValue=\"+86\">\n            <a-select-option value=\"+86\">+86</a-select-option>\n            <a-select-option value=\"+87\">+87</a-select-option>\n          </a-select>\n        </a-input>\n      </a-form-item>\n      <!--<a-input-group size=\"large\" compact>\n            <a-select style=\"width: 20%\" size=\"large\" defaultValue=\"+86\">\n              <a-select-option value=\"+86\">+86</a-select-option>\n              <a-select-option value=\"+87\">+87</a-select-option>\n            </a-select>\n            <a-input style=\"width: 80%\" size=\"large\" placeholder=\"11 位手机号\"></a-input>\n          </a-input-group>-->\n\n      <a-row :gutter=\"16\">\n        <a-col class=\"gutter-row\" :span=\"16\">\n          <a-form-item>\n            <a-input size=\"large\" type=\"text\" :placeholder=\"$t('user.login.mobile.verification-code.placeholder')\" v-decorator=\"['captcha', {rules: [{ required: true, message: '请输入验证码' }], validateTrigger: 'blur'}]\">\n              <a-icon slot=\"prefix\" type=\"mail\" :style=\"{ color: 'rgba(0,0,0,.25)' }\"/>\n            </a-input>\n          </a-form-item>\n        </a-col>\n        <a-col class=\"gutter-row\" :span=\"8\">\n          <a-button\n            class=\"getCaptcha\"\n            size=\"large\"\n            :disabled=\"state.smsSendBtn\"\n            @click.stop.prevent=\"getCaptcha\"\n            v-text=\"!state.smsSendBtn && $t('user.register.get-verification-code')||(state.time+' s')\"></a-button>\n        </a-col>\n      </a-row>\n\n      <a-form-item>\n        <a-button\n          size=\"large\"\n          type=\"primary\"\n          htmlType=\"submit\"\n          class=\"register-button\"\n          :loading=\"registerBtn\"\n          @click.stop.prevent=\"handleSubmit\"\n          :disabled=\"registerBtn\">{{ $t('user.register.register') }}\n        </a-button>\n        <router-link class=\"login\" :to=\"{ name: 'login' }\">{{ $t('user.register.sign-in') }}</router-link>\n      </a-form-item>\n\n    </a-form>\n  </div>\n</template>\n\n<script>\nimport { getSmsCaptcha } from '@/api/login'\nimport { deviceMixin } from '@/store/device-mixin'\nimport { scorePassword } from '@/utils/util'\n\nconst levelNames = {\n  0: 'user.password.strength.short',\n  1: 'user.password.strength.low',\n  2: 'user.password.strength.medium',\n  3: 'user.password.strength.strong'\n}\nconst levelClass = {\n  0: 'error',\n  1: 'error',\n  2: 'warning',\n  3: 'success'\n}\nconst levelColor = {\n  0: '#ff0000',\n  1: '#ff0000',\n  2: '#ff7e05',\n  3: '#52c41a'\n}\nexport default {\n  name: 'Register',\n  components: {\n  },\n  mixins: [deviceMixin],\n  data () {\n    return {\n      form: this.$form.createForm(this),\n\n      state: {\n        time: 60,\n        level: 0,\n        smsSendBtn: false,\n        passwordLevel: 0,\n        passwordLevelChecked: false,\n        percent: 10,\n        progressColor: '#FF0000'\n      },\n      registerBtn: false\n    }\n  },\n  computed: {\n    passwordLevelClass () {\n      return levelClass[this.state.passwordLevel]\n    },\n    passwordLevelName () {\n      return levelNames[this.state.passwordLevel]\n    },\n    passwordLevelColor () {\n      return levelColor[this.state.passwordLevel]\n    }\n  },\n  methods: {\n    handlePasswordLevel (rule, value, callback) {\n      if (!value) {\n       return callback()\n      }\n      console.log('scorePassword ; ', scorePassword(value))\n      if (value.length >= 6) {\n        if (scorePassword(value) >= 30) {\n          this.state.level = 1\n        }\n        if (scorePassword(value) >= 60) {\n        this.state.level = 2\n        }\n        if (scorePassword(value) >= 80) {\n        this.state.level = 3\n        }\n      } else {\n        this.state.level = 0\n        callback(new Error(this.$t('user.password.strength.msg')))\n      }\n      this.state.passwordLevel = this.state.level\n      this.state.percent = this.state.level * 33\n\n      callback()\n    },\n\n    handlePasswordCheck (rule, value, callback) {\n      const password = this.form.getFieldValue('password')\n      // console.log('value', value)\n      if (value === undefined) {\n        callback(new Error(this.$t('user.password.required')))\n      }\n      if (value && password && value.trim() !== password.trim()) {\n        callback(new Error(this.$t('user.password.twice.msg')))\n      }\n      callback()\n    },\n\n    handlePhoneCheck (rule, value, callback) {\n      console.log('handlePhoneCheck, rule:', rule)\n      console.log('handlePhoneCheck, value', value)\n      console.log('handlePhoneCheck, callback', callback)\n\n      callback()\n    },\n\n    handlePasswordInputClick () {\n      if (!this.isMobile) {\n        this.state.passwordLevelChecked = true\n        return\n      }\n      this.state.passwordLevelChecked = false\n    },\n\n    handleSubmit () {\n      const { form: { validateFields }, state, $router } = this\n      validateFields({ force: true }, (err, values) => {\n        if (!err) {\n          state.passwordLevelChecked = false\n          $router.push({ name: 'registerResult', params: { ...values } })\n        }\n      })\n    },\n\n    getCaptcha (e) {\n      e.preventDefault()\n      const { form: { validateFields }, state, $message, $notification } = this\n\n      validateFields(['mobile'], { force: true },\n        (err, values) => {\n          if (!err) {\n            state.smsSendBtn = true\n\n            const interval = window.setInterval(() => {\n              if (state.time-- <= 0) {\n                state.time = 60\n                state.smsSendBtn = false\n                window.clearInterval(interval)\n              }\n            }, 1000)\n\n            const hide = $message.loading('验证码发送中..', 0)\n\n            getSmsCaptcha({ mobile: values.mobile }).then(res => {\n              setTimeout(hide, 2500)\n              $notification['success']({\n                message: '提示',\n                description: '验证码获取成功，您的验证码为：' + res.result.captcha,\n                duration: 8\n              })\n            }).catch(err => {\n              setTimeout(hide, 1)\n              clearInterval(interval)\n              state.time = 60\n              state.smsSendBtn = false\n              this.requestFailed(err)\n            })\n          }\n        }\n      )\n    },\n    requestFailed (err) {\n      this.$notification['error']({\n        message: '错误',\n        description: ((err.response || {}).data || {}).message || '请求出现错误，请稍后再试',\n        duration: 4\n      })\n      this.registerBtn = false\n    }\n  },\n  watch: {\n    'state.passwordLevel' (val) {\n      console.log(val)\n    }\n  }\n}\n</script>\n<style lang=\"less\">\n  .user-register {\n\n    &.error {\n      color: #ff0000;\n    }\n\n    &.warning {\n      color: #ff7e05;\n    }\n\n    &.success {\n      color: #52c41a;\n    }\n\n  }\n\n  .user-layout-register {\n    .ant-input-group-addon:first-child {\n      background-color: #fff;\n    }\n  }\n</style>\n<style lang=\"less\" scoped>\n  .user-layout-register {\n\n    & > h3 {\n      font-size: 16px;\n      margin-bottom: 20px;\n    }\n\n    .getCaptcha {\n      display: block;\n      width: 100%;\n      height: 40px;\n    }\n\n    .register-button {\n      width: 50%;\n    }\n\n    .login {\n      float: right;\n      line-height: 40px;\n    }\n  }\n</style>\n"
  },
  {
    "path": "src/views/user/RegisterResult.vue",
    "content": "<template>\n  <a-result\n    :isSuccess=\"true\"\n    :content=\"false\"\n    :title=\"email\"\n    :sub-title=\"description\">\n\n    <template #extra>\n      <a-button size=\"large\" type=\"primary\">查看邮箱</a-button>\n      <a-button size=\"large\" style=\"margin-left: 8px\" @click=\"goHomeHandle\">返回首页</a-button>\n    </template>\n\n  </a-result>\n</template>\n\n<script>\nexport default {\n  name: 'RegisterResult',\n  data () {\n    return {\n      description: '激活邮件已发送到你的邮箱中，邮件有效期为24小时。请及时登录邮箱，点击邮件中的链接激活帐户。',\n      form: {}\n    }\n  },\n  computed: {\n    email () {\n      const v = this.form && this.form.email || 'xxx'\n      return `你的账户：${v} 注册成功`\n    }\n  },\n  created () {\n    this.form = this.$route.params\n  },\n  methods: {\n    goHomeHandle () {\n      this.$router.push({ name: 'login' })\n    }\n  }\n}\n</script>\n\n<style scoped>\n\n</style>\n"
  },
  {
    "path": "tests/unit/.eslintrc.js",
    "content": "module.exports = {\n  env: {\n    jest: true\n  }\n}\n"
  },
  {
    "path": "vue.config.js",
    "content": "const path = require('path')\nconst webpack = require('webpack')\nconst packageJson = require('./package.json')\nconst GitRevisionPlugin = require('git-revision-webpack-plugin')\nconst GitRevision = new GitRevisionPlugin()\nconst buildDate = JSON.stringify(new Date().toLocaleString())\nconst createThemeColorReplacerPlugin = require('./config/plugin.config')\n\nfunction resolve (dir) {\n  return path.join(__dirname, dir)\n}\n\n// check Git\nfunction getGitHash () {\n  try {\n    return GitRevision.version()\n  } catch (e) {}\n  return 'unknown'\n}\n// eslint-disable-next-line no-unused-vars\nconst isProd = process.env.NODE_ENV === 'production'\n// eslint-disable-next-line no-unused-vars\nconst assetsCDN = {\n  // webpack build externals\n  externals: {\n    vue: 'Vue',\n    'vue-router': 'VueRouter',\n    vuex: 'Vuex',\n    axios: 'axios'\n  },\n  css: [],\n  // https://unpkg.com/browse/vue@2.6.10/\n  js: [\n    '//cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js',\n    '//cdn.jsdelivr.net/npm/vue-router@3.5.1/dist/vue-router.min.js',\n    '//cdn.jsdelivr.net/npm/vuex@3.1.1/dist/vuex.min.js',\n    '//cdn.jsdelivr.net/npm/axios@0.21.1/dist/axios.min.js'\n  ]\n}\n\n// vue.config.js\nconst vueConfig = {\n  configureWebpack: {\n    // webpack plugins\n    plugins: [\n      // Ignore all locale files of moment.js - disabled for webpack 5 compatibility\n      // new webpack.IgnorePlugin(/^\\.\\/locale$/, /moment$/),\n      new webpack.DefinePlugin({\n        APP_VERSION: `\"${packageJson.version}\"`,\n        GIT_HASH: JSON.stringify(getGitHash()),\n        BUILD_DATE: buildDate\n      })\n    ]\n    // en_US: `if prod, add externals`\n    // zh_CN: `这里是用来控制编译忽略外部依赖的，与 config.plugin('html') 配合可以编译时引入外部CDN文件依赖`\n    // externals: isProd ? assetsCDN.externals : {}\n  },\n\n  chainWebpack: config => {\n    config.resolve.alias.set('@$', resolve('src'))\n    \n    // Ignore moment.js locale files to reduce bundle size (webpack 5 compatible)\n    config.resolve.alias.set('moment/locale', false)\n\n    // fixed svg-loader by https://github.com/damianstasik/vue-svg-loader/issues/185#issuecomment-1126721069\n\t\tconst svgRule = config.module.rule('svg')\n\t\t// Remove regular svg config from root rules list\n\t\tconfig.module.rules.delete('svg')\n\n\t\tconfig.module.rule('svg')\n\t\t\t// Use svg component rule\n\t\t\t.oneOf('svg_as_component')\n\t\t\t\t.resourceQuery(/inline/)\n\t\t\t\t.test(/\\.(svg)(\\?.*)?$/)\n\t\t\t\t.use('babel-loader')\n\t\t\t\t\t.loader('babel-loader')\n\t\t\t\t\t.end()\n\t\t\t\t.use('vue-svg-loader')\n\t\t\t\t\t.loader('vue-svg-loader')\n\t\t\t\t\t.options({\n\t\t\t\t\t\tsvgo: {\n\t\t\t\t\t\t\tplugins: [\n\t\t\t\t\t\t\t\t{ prefixIds: true },\n\t\t\t\t\t\t\t\t{ cleanupIDs: true },\n\t\t\t\t\t\t\t\t{ convertShapeToPath: false },\n\t\t\t\t\t\t\t\t{ convertStyleToAttrs: true }\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t\t.end()\n\t\t\t\t.end()\n\t\t\t// Otherwise use original svg rule\n\t\t\t.oneOf('svg_as_regular')\n\t\t\t\t.merge(svgRule.toConfig())\n\t\t\t\t.end()\n\n    // en_US: If prod is on assets require on cdn\n    // zh_CN: 如果是 prod 模式，则引入 CDN 依赖文件，有需要减少包大小请自行解除依赖\n    //\n    // if (isProd) {\n    //   config.plugin('html').tap(args => {\n    //     args[0].cdn = assetsCDN\n    //     return args\n    //   })\n    // }\n  },\n\n  css: {\n    loaderOptions: {\n      less: {\n        modifyVars: {\n          // less vars，customize ant design theme\n\n          // 'primary-color': '#F5222D',\n          // 'link-color': '#F5222D',\n          'border-radius-base': '2px'\n        },\n        // DO NOT REMOVE THIS LINE\n        javascriptEnabled: true\n      }\n    }\n  },\n\n  devServer: {\n    // development server port 8000\n    port: 8000,\n    // If you want to turn on the proxy, please remove the mockjs /src/main.jsL11\n    // proxy: {\n    //   '/api': {\n    //     target: 'https://mock.ihx.me/mock/5baf3052f7da7e07e04a5116/antd-pro',\n    //     ws: false,\n    //     changeOrigin: true\n    //   }\n    // }\n  },\n\n  // disable source map in production\n  productionSourceMap: false,\n  lintOnSave: undefined,\n  // babel-loader no-ignore node_modules/*\n  transpileDependencies: []\n}\n\n// preview.pro.loacg.com only do not use in your production;\nif (process.env.VUE_APP_PREVIEW === 'true') {\n  // add `ThemeColorReplacer` plugin to webpack plugins\n  vueConfig.configureWebpack.plugins.push(createThemeColorReplacerPlugin())\n}\n\nmodule.exports = vueConfig\n"
  },
  {
    "path": "wrangler.jsonc",
    "content": "{\n  \"name\": \"antdv-vue2-pro-preview\",\n  \"compatibility_date\": \"2025-09-19\",\n  \"assets\": {\n    \"directory\": \"./dist\",\n    \"not_found_handling\": \"single-page-application\"\n  },\n  \"routes\": [\n    {\n      \"pattern\": \"preview.pro.antdv.com/*\",\n      \"zone_name\": \"antdv.com\"\n    }\n  ]\n}\n"
  }
]