diff --git a/.browserslistrc b/.browserslistrc
new file mode 100644
index 0000000..8f96043
--- /dev/null
+++ b/.browserslistrc
@@ -0,0 +1,3 @@
+> 1%
+last 2 versions
+not ie <= 10
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..6f77dff
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,39 @@
+[*]
+charset=utf-8
+end_of_line=lf
+insert_final_newline=false
+indent_style=space
+indent_size=2
+
+[{*.ng,*.sht,*.html,*.shtm,*.shtml,*.htm}]
+indent_style=space
+indent_size=2
+
+[{*.jhm,*.xslt,*.xul,*.rng,*.xsl,*.xsd,*.ant,*.tld,*.fxml,*.jrxml,*.xml,*.jnlp,*.wsdl}]
+indent_style=space
+indent_size=2
+
+[{.babelrc,.stylelintrc,jest.config,.eslintrc,.prettierrc,*.json,*.jsb3,*.jsb2,*.bowerrc}]
+indent_style=space
+indent_size=2
+
+[*.svg]
+indent_style=space
+indent_size=2
+
+[*.js.map]
+indent_style=space
+indent_size=2
+
+[*.less]
+indent_style=space
+indent_size=2
+
+[*.vue]
+indent_style=space
+indent_size=2
+
+[{.analysis_options,*.yml,*.yaml}]
+indent_style=space
+indent_size=2
+
diff --git a/.env b/.env
new file mode 100644
index 0000000..b5c472a
--- /dev/null
+++ b/.env
@@ -0,0 +1,3 @@
+NODE_ENV=production
+VUE_APP_PREVIEW=false
+VUE_APP_API_BASE_URL=/api
\ No newline at end of file
diff --git a/.env.development b/.env.development
new file mode 100644
index 0000000..166c0bc
--- /dev/null
+++ b/.env.development
@@ -0,0 +1,3 @@
+NODE_ENV=development
+VUE_APP_PREVIEW=true
+VUE_APP_API_BASE_URL=/api
\ No newline at end of file
diff --git a/.env.preview b/.env.preview
new file mode 100644
index 0000000..a9e44c8
--- /dev/null
+++ b/.env.preview
@@ -0,0 +1,3 @@
+NODE_ENV=production
+VUE_APP_PREVIEW=true
+VUE_APP_API_BASE_URL=/api
\ No newline at end of file
diff --git a/.eslintrc.js b/.eslintrc.js
new file mode 100644
index 0000000..e926f87
--- /dev/null
+++ b/.eslintrc.js
@@ -0,0 +1,76 @@
+module.exports = {
+ root: true,
+ env: {
+ node: true
+ },
+ 'extends': [
+ 'plugin:vue/strongly-recommended',
+ '@vue/standard'
+ ],
+ rules: {
+ 'no-console': 'off',
+ 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
+ 'generator-star-spacing': 'off',
+ 'no-mixed-operators': 0,
+ 'vue/max-attributes-per-line': [
+ 2,
+ {
+ 'singleline': 5,
+ 'multiline': {
+ 'max': 1,
+ 'allowFirstLine': false
+ }
+ }
+ ],
+ 'vue/attribute-hyphenation': 0,
+ 'vue/html-self-closing': 0,
+ 'vue/component-name-in-template-casing': 0,
+ 'vue/html-closing-bracket-spacing': 0,
+ 'vue/singleline-html-element-content-newline': 0,
+ 'vue/no-unused-components': 0,
+ 'vue/multiline-html-element-content-newline': 0,
+ 'vue/no-use-v-if-with-v-for': 0,
+ 'vue/html-closing-bracket-newline': 0,
+ 'vue/no-parsing-error': 0,
+ 'no-tabs': 0,
+ 'quotes': [
+ 2,
+ 'single',
+ {
+ 'avoidEscape': true,
+ 'allowTemplateLiterals': true
+ }
+ ],
+ 'semi': [
+ 2,
+ 'never',
+ {
+ 'beforeStatementContinuationChars': 'never'
+ }
+ ],
+ 'no-delete-var': 2,
+ 'prefer-const': [
+ 2,
+ {
+ 'ignoreReadBeforeAssign': false
+ }
+ ],
+ 'template-curly-spacing': 'off',
+ 'indent': 'off',
+ 'standard/no-callback-literal': 0
+ },
+ parserOptions: {
+ parser: 'babel-eslint'
+ },
+ overrides: [
+ {
+ files: [
+ '**/__tests__/*.{j,t}s?(x)',
+ '**/tests/unit/**/*.spec.{j,t}s?(x)'
+ ],
+ env: {
+ jest: true
+ }
+ }
+ ]
+}
diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644
index 0000000..ed223c7
--- /dev/null
+++ b/.eslintrc.json
@@ -0,0 +1,5 @@
+{
+ "rules": {
+ "space-before-function-paren": 0
+ }
+}
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..e507319
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+public/* linguist-vendored
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..6b1e5e6
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,25 @@
+.DS_Store
+node_modules
+/dist
+
+# local env files
+.env.local
+.env.*.local
+
+# Log files
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw*
+package-lock.json
+yarn.lock
+.husky/.gitignore
+dist.zip
diff --git a/.lintstagedrc.json b/.lintstagedrc.json
new file mode 100644
index 0000000..bcffb34
--- /dev/null
+++ b/.lintstagedrc.json
@@ -0,0 +1,4 @@
+{
+ "*.js": "eslint --fix",
+ "*.{css,less}": "stylelint --fix"
+}
\ No newline at end of file
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000..b0e80f7
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,6 @@
+{
+ "printWidth": 120,
+ "semi": false,
+ "singleQuote": true,
+ "prettier.spaceBeforeFunctionParen": true
+}
diff --git a/.stylelintrc.js b/.stylelintrc.js
new file mode 100644
index 0000000..412e214
--- /dev/null
+++ b/.stylelintrc.js
@@ -0,0 +1,102 @@
+module.exports = {
+ processors: [],
+ plugins: ['stylelint-order'],
+ extends: [
+ 'stylelint-config-standard',
+ 'stylelint-config-css-modules'
+ ],
+ rules: {
+ 'selector-class-pattern': null,
+ 'string-quotes': 'single', // 单引号
+ 'at-rule-empty-line-before': null,
+ 'at-rule-no-unknown': null,
+ 'at-rule-name-case': 'lower', // 指定@规则名的大小写
+ 'length-zero-no-unit': true, // 禁止零长度的单位(可自动修复)
+ 'shorthand-property-no-redundant-values': true, // 简写属性
+ 'number-leading-zero': 'never', // 小数不带0
+ 'declaration-block-no-duplicate-properties': null, // 禁止声明快重复属性
+ 'no-descending-specificity': null, // 禁止在具有较高优先级的选择器后出现被其覆盖的较低优先级的选择器。
+ 'selector-max-id': 3, // 限制一个选择器中 ID 选择器的数量
+ 'max-nesting-depth': 4,
+ 'indentation': [2, { // 指定缩进 warning 提醒
+ 'severity': 'warning'
+ }],
+ 'order/properties-order': [ // 规则顺序
+ 'position',
+ 'top',
+ 'right',
+ 'bottom',
+ 'left',
+ 'z-index',
+ 'display',
+ 'float',
+ 'width',
+ 'height',
+ 'max-width',
+ 'max-height',
+ 'min-width',
+ 'min-height',
+ 'padding',
+ 'padding-top',
+ 'padding-right',
+ 'padding-bottom',
+ 'padding-left',
+ 'margin',
+ 'margin-top',
+ 'margin-right',
+ 'margin-bottom',
+ 'margin-left',
+ 'margin-collapse',
+ 'margin-top-collapse',
+ 'margin-right-collapse',
+ 'margin-bottom-collapse',
+ 'margin-left-collapse',
+ 'overflow',
+ 'overflow-x',
+ 'overflow-y',
+ 'clip',
+ 'clear',
+ 'font',
+ 'font-family',
+ 'font-size',
+ 'font-smoothing',
+ 'osx-font-smoothing',
+ 'font-style',
+ 'font-weight',
+ 'line-height',
+ 'letter-spacing',
+ 'word-spacing',
+ 'color',
+ 'text-align',
+ 'text-decoration',
+ 'text-indent',
+ 'text-overflow',
+ 'text-rendering',
+ 'text-size-adjust',
+ 'text-shadow',
+ 'text-transform',
+ 'word-break',
+ 'word-wrap',
+ 'white-space',
+ 'vertical-align',
+ 'list-style',
+ 'list-style-type',
+ 'list-style-position',
+ 'list-style-image',
+ 'pointer-events',
+ 'cursor',
+ 'background',
+ 'background-color',
+ 'border',
+ 'border-radius',
+ 'content',
+ 'outline',
+ 'outline-offset',
+ 'opacity',
+ 'filter',
+ 'visibility',
+ 'size',
+ 'transform'
+ ]
+ }
+}
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..a08bfcb
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,7 @@
+language: node_js
+node_js:
+ - 10.15.0
+cache: yarn
+script:
+ - yarn
+ - yarn run lint --no-fix && yarn run build
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..3ebc1f5
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,6 @@
+FROM nginx
+
+RUN rm /etc/nginx/conf.d/default.conf
+
+ADD deploy/nginx.conf /etc/nginx/conf.d/default.conf
+COPY dist/ /usr/share/nginx/html/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..66eef0b
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2018 Anan Yang
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..eb88edf
--- /dev/null
+++ b/README.md
@@ -0,0 +1,103 @@
+English | [简体中文](./README.zh-CN.md)
+
+
Ant Design Vue Pro
+
+An out-of-box UI solution for enterprise applications as a Vue boilerplate. based on
Ant Design of Vue
+
+
+
+
+[![License](https://img.shields.io/npm/l/package.json.svg?style=flat)](https://github.com/vueComponent/ant-design-vue-pro/blob/master/LICENSE)
+[![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)
+[![Support Vue Version](https://img.shields.io/badge/Support-Vue2-green?style=flat)](https://github.com/vueComponent/ant-design-vue-pro/releases/latest)
+[![Travis branch](https://travis-ci.org/vueComponent/ant-design-vue-pro.svg?branch=master)](https://travis-ci.org/vueComponent/ant-design-vue-pro)
+
+
+
+- Preview: https://preview.pro.antdv.com
+- Home Page: https://pro.antdv.com
+- Documentation: https://pro.antdv.com/docs/getting-started
+- ChangeLog: https://pro.antdv.com/docs/changelog
+- FAQ: https://pro.antdv.com/docs/faq
+- Vue3 ProLayout: https://github.com/vueComponent/pro-layout
+
+Overview
+----
+
+![dashboard](https://static-2.loacg.com/open/static/github/SP1.png)
+
+### Env and dependencies
+
+- node
+- yarn
+- webpack
+- eslint
+- @vue/cli
+- [ant-design-vue@1.x](https://github.com/vueComponent/ant-design-vue) - Ant Design Of Vue
+- [vue-cropper](https://github.com/xyxiao001/vue-cropper) - Picture edit
+- [@antv/g2](https://antv.alipay.com/zh-cn/index.html) - AntV G2
+- [Viser-vue](https://viserjs.github.io/docs.html#/viser/guide/installation) - Antv/G2 of Vue
+
+> 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
+
+
+### Project setup
+
+- Clone repo
+```bash
+git clone https://github.com/vueComponent/ant-design-vue-pro.git
+cd ant-design-vue-pro
+```
+
+- Install dependencies
+```
+yarn install
+```
+
+- Compiles and hot-reloads for development
+```
+yarn run serve
+```
+
+- Compiles and minifies for production
+```
+yarn run build
+```
+
+- Lints and fixes files
+```
+yarn run lint
+```
+
+
+### Other
+
+- **IMPORTANT : Issue feedback !! when opening Issue read [Issue / PR Contributing](https://github.com/vueComponent/ant-design-vue-pro/issues/90)**
+
+- [Vue-cli3](https://cli.vuejs.org/guide/) used by the project.
+
+- Disable Eslint (not recommended): remove `eslintConfig` field in `package.json` and `vue.config.js` field `lintOnSave: false`
+
+- 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)
+
+- 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)
+
+- I18n: [locales (@musnow)](./src/locales/index.js)
+
+- Production env `mock` is disabled. use `src/mock/index.js`
+
+- pls use `release` version
+
+## Browsers support
+
+Modern browsers and IE10.
+
+| [](http://godban.github.io/browsers-support-badges/)IE / Edge | [](http://godban.github.io/browsers-support-badges/)Firefox | [](http://godban.github.io/browsers-support-badges/)Chrome | [](http://godban.github.io/browsers-support-badges/)Safari | [](http://godban.github.io/browsers-support-badges/)Opera |
+| --- | --- | --- | --- | --- |
+| IE10, Edge | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
+
+
+## Contributors
+
+This project exists thanks to all the people who contribute.
+
diff --git a/README.zh-CN.md b/README.zh-CN.md
new file mode 100644
index 0000000..c21ecbd
--- /dev/null
+++ b/README.zh-CN.md
@@ -0,0 +1,110 @@
+[English](./README.md) | 简体中文
+
+Ant Design Vue Pro
+
+An out-of-box UI solution for enterprise applications as a Vue boilerplate. based on
Ant Design of Vue
+
+
+
+
+[![License](https://img.shields.io/npm/l/package.json.svg?style=flat)](https://github.com/vueComponent/ant-design-vue-pro/blob/master/LICENSE)
+[![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)
+[![Support Vue Version](https://img.shields.io/badge/Support-Vue2-green?style=flat)](https://github.com/vueComponent/ant-design-vue-pro/releases/latest)
+[![Travis branch](https://travis-ci.org/vueComponent/ant-design-vue-pro.svg?branch=master)](https://travis-ci.org/vueComponent/ant-design-vue-pro)
+
+
+
+- 预览: https://preview.pro.antdv.com
+- 首页: https://pro.antdv.com
+- 文档: https://pro.antdv.com/docs/getting-started
+- 更新日志: https://pro.antdv.com/docs/changelog
+- 常见问题: https://pro.antdv.com/docs/faq
+- Vue3 ProLayout: https://github.com/vueComponent/pro-layout
+
+Overview
+----
+
+基于 [Ant Design of Vue](https://vuecomponent.github.io/ant-design-vue/docs/vue/introduce-cn/) 实现的 [Ant Design Pro](https://pro.ant.design/)
+
+![dashboard](https://static-2.loacg.com/open/static/github/SP1.png)
+
+环境和依赖
+----
+
+- node
+- yarn
+- webpack
+- eslint
+- @vue/cli
+- [ant-design-vue@1.x](https://github.com/vueComponent/ant-design-vue) - Ant Design Of Vue 实现
+- [vue-cropper](https://github.com/xyxiao001/vue-cropper) - 头像裁剪组件
+- [@antv/g2](https://antv.alipay.com/zh-cn/index.html) - Alipay AntV 数据可视化图表
+- [Viser-vue](https://viserjs.github.io/docs.html#/viser/guide/installation) - antv/g2 封装实现
+
+> 请注意,我们强烈建议本项目使用 [Yarn](https://yarnpkg.com/) 包管理工具,这样可以与本项目演示站所加载完全相同的依赖版本 (yarn.lock) 。由于我们没有对依赖进行强制的版本控制,采用非 yarn 包管理进行引入时,可能由于 Pro 所依赖的库已经升级版本而引入了新版本所导致的问题。作者可能会由于时间问题无法及时排查而导致您采用本项目作为基项目而出现问题。
+
+
+
+项目下载和运行
+----
+
+- 拉取项目代码
+```bash
+git clone https://github.com/vueComponent/ant-design-vue-pro.git
+cd ant-design-vue-pro
+```
+
+- 安装依赖
+```
+yarn install
+```
+
+- 开发模式运行
+```
+yarn run serve
+```
+
+- 编译项目
+```
+yarn run build
+```
+
+- Lints and fixes files
+```
+yarn run lint
+```
+
+
+
+其他说明
+----
+
+- **关于 Issue 反馈 (重要!重要!重要!) 请在开 *Issue* 前,先阅读该内容:[Issue / PR 编写建议](https://github.com/vueComponent/ant-design-vue-pro/issues/90)**
+
+- 项目使用的 [vue-cli3](https://cli.vuejs.org/guide/), 请确保你所使用的 vue-cli 是新版,并且已经学习 cli 官方文档使用教程
+
+- 关闭 Eslint (不推荐) 移除 `package.json` 中 `eslintConfig` 整个节点代码, `vue.config.js` 下的 `lintOnSave` 值改为 `false`
+
+- 组件按需加载 `/src/main.js` L14 相关代码 `import './core/lazy_use'` / `import './core/use'`
+
+- [修改 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)
+
+- I18n: [多语言支持 (@musnow)](./src/locales/index.js)
+
+- 生产环境默认不加载 `mock`,更多详情请看 `src/mock/index.js`
+
+- **用于生产环境,请使用 `release` 版本代码,使用 master 代码出现的任何问题需要你自行解决**
+
+## 浏览器兼容
+
+Modern browsers and IE10.
+
+| [](http://godban.github.io/browsers-support-badges/)IE / Edge | [](http://godban.github.io/browsers-support-badges/)Firefox | [](http://godban.github.io/browsers-support-badges/)Chrome | [](http://godban.github.io/browsers-support-badges/)Safari | [](http://godban.github.io/browsers-support-badges/)Opera |
+| --- | --- | --- | --- | --- |
+| IE10, Edge | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
+
+
+## Contributors
+
+This project exists thanks to all the people who contribute.
+
diff --git a/babel.config.js b/babel.config.js
new file mode 100644
index 0000000..4fe6229
--- /dev/null
+++ b/babel.config.js
@@ -0,0 +1,30 @@
+const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV)
+const IS_PREVIEW = process.env.VUE_APP_PREVIEW === 'true'
+
+const plugins = []
+if (IS_PROD && !IS_PREVIEW) {
+ // 去除日志的插件,
+ plugins.push('transform-remove-console')
+}
+
+// lazy load ant-design-vue
+// if your use import on Demand, Use this code
+plugins.push(['import', {
+ 'libraryName': 'ant-design-vue',
+ 'libraryDirectory': 'es',
+ 'style': true // `style: true` 会加载 less 文件
+}])
+
+module.exports = {
+ presets: [
+ '@vue/cli-plugin-babel/preset',
+ [
+ '@babel/preset-env',
+ {
+ 'useBuiltIns': 'entry',
+ 'corejs': 3
+ }
+ ]
+ ],
+ plugins
+}
diff --git a/commitlint.config.js b/commitlint.config.js
new file mode 100644
index 0000000..56b63ec
--- /dev/null
+++ b/commitlint.config.js
@@ -0,0 +1,26 @@
+/**
+ * feat:新增功能
+ * fix:bug 修复
+ * docs:文档更新
+ * style:不影响程序逻辑的代码修改(修改空白字符,格式缩进,补全缺失的分号等,没有改变代码逻辑)
+ * refactor:重构代码(既没有新增功能,也没有修复 bug)
+ * perf:性能, 体验优化
+ * test:新增测试用例或是更新现有测试
+ * build:主要目的是修改项目构建系统(例如 glup,webpack,rollup 的配置等)的提交
+ * ci:主要目的是修改项目继续集成流程(例如 Travis,Jenkins,GitLab CI,Circle等)的提交
+ * chore:不属于以上类型的其他类型,比如构建流程, 依赖管理
+ * revert:回滚某个更早之前的提交
+ */
+
+module.exports = {
+ extends: ['@commitlint/config-conventional'],
+ rules: {
+ 'type-enum': [
+ 2,
+ 'always',
+ ['feat', 'fix', 'docs', 'style', 'refactor', 'test', 'chore', 'revert'],
+ ],
+ 'subject-full-stop': [0, 'never'],
+ 'subject-case': [0, 'never'],
+ },
+};
\ No newline at end of file
diff --git a/config/plugin.config.js b/config/plugin.config.js
new file mode 100644
index 0000000..bb51b98
--- /dev/null
+++ b/config/plugin.config.js
@@ -0,0 +1,49 @@
+const ThemeColorReplacer = require('webpack-theme-color-replacer')
+const generate = require('@ant-design/colors/lib/generate').default
+
+const getAntdSerials = (color) => {
+ // 淡化(即less的tint)
+ const lightens = new Array(9).fill().map((t, i) => {
+ return ThemeColorReplacer.varyColor.lighten(color, i / 10)
+ })
+ const colorPalettes = generate(color)
+ const rgb = ThemeColorReplacer.varyColor.toNum3(color.replace('#', '')).join(',')
+ return lightens.concat(colorPalettes).concat(rgb)
+}
+
+const themePluginOption = {
+ fileName: 'css/theme-colors-[contenthash:8].css',
+ matchColors: getAntdSerials('#1890ff'), // 主色系列
+ // 改变样式选择器,解决样式覆盖问题
+ changeSelector (selector) {
+ switch (selector) {
+ case '.ant-calendar-today .ant-calendar-date':
+ return ':not(.ant-calendar-selected-date):not(.ant-calendar-selected-day)' + selector
+ case '.ant-btn:focus,.ant-btn:hover':
+ return '.ant-btn:focus:not(.ant-btn-primary):not(.ant-btn-danger),.ant-btn:hover:not(.ant-btn-primary):not(.ant-btn-danger)'
+ case '.ant-btn.active,.ant-btn:active':
+ return '.ant-btn.active:not(.ant-btn-primary):not(.ant-btn-danger),.ant-btn:active:not(.ant-btn-primary):not(.ant-btn-danger)'
+ case '.ant-steps-item-process .ant-steps-item-icon > .ant-steps-icon':
+ case '.ant-steps-item-process .ant-steps-item-icon>.ant-steps-icon':
+ return ':not(.ant-steps-item-process)' + selector
+ // fixed https://github.com/vueComponent/ant-design-vue-pro/issues/876
+ case '.ant-steps-item-process .ant-steps-item-icon':
+ return ':not(.ant-steps-item-custom)' + selector
+ 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':
+ 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':
+ 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'
+ case '.ant-menu-horizontal > .ant-menu-item-selected > a':
+ case '.ant-menu-horizontal>.ant-menu-item-selected>a':
+ return '.ant-menu-horizontal:not(ant-menu-light):not(.ant-menu-dark) > .ant-menu-item-selected > a'
+ case '.ant-menu-horizontal > .ant-menu-item > a:hover':
+ case '.ant-menu-horizontal>.ant-menu-item>a:hover':
+ return '.ant-menu-horizontal:not(ant-menu-light):not(.ant-menu-dark) > .ant-menu-item > a:hover'
+ default :
+ return selector
+ }
+ }
+}
+
+const createThemeColorReplacerPlugin = () => new ThemeColorReplacer(themePluginOption)
+
+module.exports = createThemeColorReplacerPlugin
diff --git a/config/themePluginConfig.js b/config/themePluginConfig.js
new file mode 100644
index 0000000..d35ef8b
--- /dev/null
+++ b/config/themePluginConfig.js
@@ -0,0 +1,115 @@
+export default {
+ theme: [
+ {
+ key: 'dark',
+ fileName: 'dark.css',
+ theme: 'dark'
+ },
+ {
+ key: '#F5222D',
+ fileName: '#F5222D.css',
+ modifyVars: {
+ '@primary-color': '#F5222D'
+ }
+ },
+ {
+ key: '#FA541C',
+ fileName: '#FA541C.css',
+ modifyVars: {
+ '@primary-color': '#FA541C'
+ }
+ },
+ {
+ key: '#FAAD14',
+ fileName: '#FAAD14.css',
+ modifyVars: {
+ '@primary-color': '#FAAD14'
+ }
+ },
+ {
+ key: '#13C2C2',
+ fileName: '#13C2C2.css',
+ modifyVars: {
+ '@primary-color': '#13C2C2'
+ }
+ },
+ {
+ key: '#52C41A',
+ fileName: '#52C41A.css',
+ modifyVars: {
+ '@primary-color': '#52C41A'
+ }
+ },
+ {
+ key: '#2F54EB',
+ fileName: '#2F54EB.css',
+ modifyVars: {
+ '@primary-color': '#2F54EB'
+ }
+ },
+ {
+ key: '#722ED1',
+ fileName: '#722ED1.css',
+ modifyVars: {
+ '@primary-color': '#722ED1'
+ }
+ },
+
+ {
+ key: '#F5222D',
+ theme: 'dark',
+ fileName: 'dark-#F5222D.css',
+ modifyVars: {
+ '@primary-color': '#F5222D'
+ }
+ },
+ {
+ key: '#FA541C',
+ theme: 'dark',
+ fileName: 'dark-#FA541C.css',
+ modifyVars: {
+ '@primary-color': '#FA541C'
+ }
+ },
+ {
+ key: '#FAAD14',
+ theme: 'dark',
+ fileName: 'dark-#FAAD14.css',
+ modifyVars: {
+ '@primary-color': '#FAAD14'
+ }
+ },
+ {
+ key: '#13C2C2',
+ theme: 'dark',
+ fileName: 'dark-#13C2C2.css',
+ modifyVars: {
+ '@primary-color': '#13C2C2'
+ }
+ },
+ {
+ key: '#52C41A',
+ theme: 'dark',
+ fileName: 'dark-#52C41A.css',
+ modifyVars: {
+ '@primary-color': '#52C41A'
+ }
+ },
+ {
+ key: '#2F54EB',
+ theme: 'dark',
+ fileName: 'dark-#2F54EB.css',
+ modifyVars: {
+ '@primary-color': '#2F54EB'
+ }
+ },
+ {
+ key: '#722ED1',
+ theme: 'dark',
+ fileName: 'dark-#722ED1.css',
+ modifyVars: {
+ '@primary-color': '#722ED1'
+ }
+ }
+ ]
+}
diff --git a/deploy.bat b/deploy.bat
new file mode 100644
index 0000000..670706f
--- /dev/null
+++ b/deploy.bat
@@ -0,0 +1 @@
+npm i && npm run build && rmdir /s /q E:\AutoPublish\projectmanage\vue\documentcheck_web\dist && md E:\AutoPublish\projectmanage\vue\documentcheck_web\dist && xcopy C:\Windows\System32\config\systemprofile\AppData\Local\Jenkins\.jenkins\workspace\documentcheck_web\dist E:\AutoPublish\projectmanage\vue\documentcheck_web\dist /s /f /h
\ No newline at end of file
diff --git a/deploy/caddy.conf b/deploy/caddy.conf
new file mode 100644
index 0000000..acd5c0e
--- /dev/null
+++ b/deploy/caddy.conf
@@ -0,0 +1,9 @@
+0.0.0.0:80 {
+ gzip
+ root /usr/share/nginx/html
+
+ rewrite {
+ r .*
+ to {path} /
+ }
+}
\ No newline at end of file
diff --git a/deploy/nginx.conf b/deploy/nginx.conf
new file mode 100644
index 0000000..5ddb66d
--- /dev/null
+++ b/deploy/nginx.conf
@@ -0,0 +1,24 @@
+server {
+ listen 80;
+ server_name _;
+ # gzip config
+ gzip on;
+ gzip_min_length 1k;
+ gzip_comp_level 6;
+ gzip_types text/plain text/css text/javascript application/json application/javascript application/x-javascript application/xml;
+ gzip_vary on;
+ gzip_disable "MSIE [1-6]\.";
+
+ root /usr/share/nginx/html;
+ include /etc/nginx/mime.types;
+
+ location / {
+ try_files $uri $uri/ /index.html;
+ }
+
+# location /api {
+# proxy_pass https://preview.pro.antdv.com/api;
+# proxy_set_header X-Forwarded-Proto $scheme;
+# proxy_set_header X-Real-IP $remote_addr;
+# }
+}
diff --git a/docs/add-page-loading-animate.md b/docs/add-page-loading-animate.md
new file mode 100644
index 0000000..dfe4919
--- /dev/null
+++ b/docs/add-page-loading-animate.md
@@ -0,0 +1,31 @@
+为首屏增加 加载动画
+====
+
+
+
+## 需求
+
+> 为了缓解用户第一次访问时,加载 JS 过大所导致用户等待白屏时间过长导致的用户体验不好,进行的一个优化动效。
+
+
+
+## 实现方案
+
+1. 将 动画加载 dom 元素放在 #app 内,Vue 生命周期开始时,会自动清掉 #app 下的所有元素。
+2. 将 动画加载 dom 元素放在 body 下,Vue 生命周期开始时 App.vue (created, mounted) 调用 `@/utils/utll` 下的 removeLoadingAnimate(#id, timeout) 则会移除加载动画
+
+最后一步:
+ 将样式插入到 `public/index.html` 文件的 `` 最好写成内联 ``
+
+
+
+----
+
+目前提供有两个样式,均在 `public/loading` 文件夹内。且 pro 已经默认使用了一套 loading 动画方案,可以直接参考 `public/index.html`
+
+
+## 写在最后
+
+目前 pro 有页面 overflow 显示出浏览器滚动条时,页面会抖动一下的问题。
+
+欢迎各位提供能解决的方案和实现 demo。如果在条件允许的情况下,建议请直接使用 pro 进行改造,也欢迎直接 PR 到 pro 的仓库
diff --git a/docs/webpack-bundle-analyzer.md b/docs/webpack-bundle-analyzer.md
new file mode 100644
index 0000000..c313767
--- /dev/null
+++ b/docs/webpack-bundle-analyzer.md
@@ -0,0 +1,40 @@
+先增加依赖
+
+```bash
+// npm
+$ npm install --save-dev webpack-bundle-analyzer
+
+// or yarn
+$ yarn add webpack-bundle-analyzer -D
+```
+
+配置文件 `vue.config.js` 增加 `configureWebpack.plugins` 参数
+
+```
+const path = require('path')
+const webpack = require('webpack')
+const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
+
+function resolve (dir) {
+ return path.join(__dirname, dir)
+}
+
+// vue.config.js
+module.exports = {
+ configureWebpack: {
+ plugins: [
+ // Ignore all locale files of moment.js
+ new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
+ // 依赖大小分析工具
+ new BundleAnalyzerPlugin(),
+ ]
+ },
+
+
+ ...
+}
+```
+
+
+
+启动 `cli` 的 `build` 命令进行项目编译,编译完成时,会自动运行一个 http://localhost:8888 的地址,完整显示了支持库依赖
\ No newline at end of file
diff --git a/jest.config.js b/jest.config.js
new file mode 100644
index 0000000..29fee32
--- /dev/null
+++ b/jest.config.js
@@ -0,0 +1,23 @@
+module.exports = {
+ moduleFileExtensions: [
+ 'js',
+ 'jsx',
+ 'json',
+ 'vue'
+ ],
+ transform: {
+ '^.+\\.vue$': 'vue-jest',
+ '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub',
+ '^.+\\.jsx?$': 'babel-jest'
+ },
+ moduleNameMapper: {
+ '^@/(.*)$': '/src/$1'
+ },
+ snapshotSerializers: [
+ 'jest-serializer-vue'
+ ],
+ testMatch: [
+ '**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
+ ],
+ testURL: 'http://localhost/'
+}
diff --git a/jsconfig.json b/jsconfig.json
new file mode 100644
index 0000000..1bd0da4
--- /dev/null
+++ b/jsconfig.json
@@ -0,0 +1,11 @@
+{
+ "compilerOptions": {
+ "target": "es6",
+ "baseUrl": ".",
+ "paths": {
+ "@/*": ["src/*"]
+ }
+ },
+ "exclude": ["node_modules", "dist"],
+ "include": ["src/**/*"]
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..7c3c76b
--- /dev/null
+++ b/package.json
@@ -0,0 +1,108 @@
+{
+ "name": "vue-antd-pro",
+ "version": "3.0.2",
+ "private": true,
+ "scripts": {
+ "serve": "vue-cli-service serve",
+ "build": "vue-cli-service build",
+ "test:unit": "vue-cli-service test:unit",
+ "lint": "vue-cli-service lint",
+ "build:preview": "vue-cli-service build --mode preview",
+ "lint:nofix": "vue-cli-service lint --no-fix",
+ "lint:js": "eslint src/**/*.js --fix",
+ "lint:css": "stylelint src/**/*.*ss --fix --custom-syntax postcss-less",
+ "prepare": "husky install"
+ },
+ "dependencies": {
+ "@ant-design-vue/pro-layout": "^1.0.11",
+ "@antv/data-set": "^0.10.2",
+ "ant-design-vue": "^1.7.8",
+ "axios": "^0.26.1",
+ "core-js": "^3.21.1",
+ "dayjs": "^1.11.5",
+ "docx-preview": "^0.1.11",
+ "echarts": "^5.3.3",
+ "enquire.js": "^2.1.6",
+ "html2canvas": "^1.4.1",
+ "jspdf": "^2.5.1",
+ "lodash.clonedeep": "^4.5.0",
+ "lodash.get": "^4.4.2",
+ "lodash.pick": "^4.4.0",
+ "md5": "^2.3.0",
+ "mockjs2": "1.0.8",
+ "moment": "^2.29.2",
+ "nprogress": "^0.2.0",
+ "spark-md5": "^3.0.2",
+ "store": "^2.0.12",
+ "v-contextmenu": "^2.9.0",
+ "viser-vue": "^2.4.8",
+ "vue": "^2.6.14",
+ "vue-clipboard2": "^0.2.1",
+ "vue-cropper": "0.4.9",
+ "vue-echarts": "^6.2.3",
+ "vue-i18n": "^8.27.1",
+ "vue-json-viewer": "^2.2.19",
+ "vue-pdf": "^4.3.0",
+ "vue-pdf-embed": "^1.1.4",
+ "vue-print-nb": "^1.7.5",
+ "vue-quill-editor": "^3.0.6",
+ "vue-router": "^3.5.3",
+ "vue-runtime-helpers": "^1.1.2",
+ "vue-svg-component-runtime": "^1.0.1",
+ "vuescroll": "^4.17.5",
+ "vuex": "^3.6.2",
+ "wangeditor": "^3.1.1"
+ },
+ "devDependencies": {
+ "@ant-design/colors": "^3.2.2",
+ "@commitlint/cli": "^12.1.4",
+ "@commitlint/config-conventional": "^12.1.4",
+ "@vue/babel-helper-vue-jsx-merge-props": "^1.2.1",
+ "@vue/cli-plugin-babel": "^4.5.17",
+ "@vue/cli-plugin-eslint": "^4.5.17",
+ "@vue/cli-plugin-router": "^4.5.17",
+ "@vue/cli-plugin-unit-jest": "^4.5.17",
+ "@vue/cli-plugin-vuex": "^4.5.17",
+ "@vue/cli-service": "^4.5.17",
+ "@vue/eslint-config-standard": "^4.0.0",
+ "@vue/test-utils": "^1.3.0",
+ "babel-eslint": "^10.1.0",
+ "babel-plugin-import": "^1.13.3",
+ "babel-plugin-transform-remove-console": "^6.9.4",
+ "commitizen": "^4.2.4",
+ "cz-conventional-changelog": "^3.3.0",
+ "eslint": "^5.16.0",
+ "eslint-plugin-html": "^5.0.5",
+ "eslint-plugin-vue": "^5.2.3",
+ "file-loader": "^6.2.0",
+ "git-revision-webpack-plugin": "^3.0.6",
+ "husky": "^6.0.0",
+ "less": "^3.13.1",
+ "less-loader": "^5.0.0",
+ "lint-staged": "^12.5.0",
+ "postcss-less": "^6.0.0",
+ "regenerator-runtime": "^0.13.9",
+ "stylelint": "^14.8.5",
+ "stylelint-config-css-modules": "^4.1.0",
+ "stylelint-config-recess-order": "^3.0.0",
+ "stylelint-config-recommended": "^7.0.0",
+ "stylelint-config-standard": "^25.0.0",
+ "stylelint-order": "^5.0.0",
+ "vue-svg-icon-loader": "^2.1.1",
+ "vue-template-compiler": "^2.6.14",
+ "webpack-theme-color-replacer": "^1.3.26"
+ },
+ "config": {
+ "commitizen": {
+ "path": "./node_modules/cz-conventional-changelog"
+ }
+ },
+ "husky": {
+ "hooks": {
+ "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
+ }
+ },
+ "gitHooks": {
+ "pre-commit": "lint-staged"
+ }
+}
diff --git a/postcss.config.js b/postcss.config.js
new file mode 100644
index 0000000..961986e
--- /dev/null
+++ b/postcss.config.js
@@ -0,0 +1,5 @@
+module.exports = {
+ plugins: {
+ autoprefixer: {}
+ }
+}
diff --git a/public/avatar2.jpg b/public/avatar2.jpg
new file mode 100644
index 0000000..9adb2d1
Binary files /dev/null and b/public/avatar2.jpg differ
diff --git a/public/index.html b/public/index.html
new file mode 100644
index 0000000..690a9b6
--- /dev/null
+++ b/public/index.html
@@ -0,0 +1,133 @@
+
+
+
+
+
+
+
+
+ 智能图文查重比对数据系统
+
+
+ <% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.css) { %>
+
+ <% } %>
+
+
+
+
+
+
+ <% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.js) { %>
+
+ <% } %>
+
+
+
+
\ No newline at end of file
diff --git a/public/logo.ico b/public/logo.ico
new file mode 100644
index 0000000..90bf57f
Binary files /dev/null and b/public/logo.ico differ
diff --git a/src/App.vue b/src/App.vue
new file mode 100644
index 0000000..0d26f03
--- /dev/null
+++ b/src/App.vue
@@ -0,0 +1,101 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/api/analysis/biddingProject.js b/src/api/analysis/biddingProject.js
new file mode 100644
index 0000000..0e022df
--- /dev/null
+++ b/src/api/analysis/biddingProject.js
@@ -0,0 +1,67 @@
+import request from '@/utils/request'
+
+const api = {
+ projectNumber: '/project/projectAnalysis/statisticsProjectNumber',
+ projectAmount: '/project/projectAnalysis/statisticsProjectAmount',
+ winningNumber: '/project/projectAnalysis/statisticsWinningNumber',
+ supplierAmount: '/project/projectAnalysis/statisticsSupplierAmount',
+ participationCount: '/project/projectAnalysis/statisticsParticipationCount',
+ winningAmount: '/project/projectAnalysis/statisticsWinningAmount',
+ checkResult: '/project/projectAnalysis/statisticsCheckResult'
+}
+
+export function projectNumber (params) {
+ return request({
+ url: api.projectNumber,
+ method: 'GET',
+ params
+ })
+}
+
+export function projectAmount (params) {
+ return request({
+ url: api.projectAmount,
+ method: 'GET',
+ params
+ })
+}
+
+export function winningNumber (params) {
+ return request({
+ url: api.winningNumber,
+ method: 'GET',
+ params
+ })
+}
+
+export function supplierAmount (params) {
+ return request({
+ url: api.supplierAmount,
+ method: 'GET',
+ params
+ })
+}
+
+export function participationCount (params) {
+ return request({
+ url: api.participationCount,
+ method: 'GET',
+ params
+ })
+}
+
+export function winningAmount (params) {
+ return request({
+ url: api.winningAmount,
+ method: 'GET',
+ params
+ })
+}
+
+export function checkResult (params) {
+ return request({
+ url: api.checkResult,
+ method: 'GET',
+ params
+ })
+}
diff --git a/src/api/analysis/tenderProject.js b/src/api/analysis/tenderProject.js
new file mode 100644
index 0000000..8e34d75
--- /dev/null
+++ b/src/api/analysis/tenderProject.js
@@ -0,0 +1,103 @@
+import request from '@/utils/request'
+
+const api = {
+ yearTenderNumber: '/project/tenderAnalysis/statisticsYearTenderNumber',
+ tenderNumber: '/project/tenderAnalysis/statisticsRangeTenderNumber',
+ violationTimes: '/project/tenderAnalysis/statisticsViolationTimes',
+ statisticsViolationTimesPie: '/project/tenderAnalysis/statisticsViolationTimesPie',
+ involvedTenderNumber: '/project/tenderAnalysis/involvedTenderNumber',
+ winningAmountList: '/project/tenderAnalysis/statisticsWinningAmountList',
+ winningList: '/project/tenderAnalysis/statisticsWinningList',
+ getManyCompaniesBiddingList: '/project/tenderAnalysis/getManyCompaniesBiddingList',
+ statisticsWinningUnitList: '/project/tenderAnalysis/statisticsWinningUnitList',
+ statisticsWinningDeptList: '/project/tenderAnalysis/statisticsWinningDeptList',
+ getCompaniesBiddingTotalList: '/project/tenderAnalysis/getCompaniesBiddingTotalList'
+}
+
+export function yearTenderNumber (params) {
+ return request({
+ url: api.yearTenderNumber,
+ method: 'GET',
+ params
+ })
+}
+
+export function tenderNumber (params) {
+ return request({
+ url: api.tenderNumber,
+ method: 'GET',
+ params
+ })
+}
+
+export function violationTimes (params) {
+ return request({
+ url: api.violationTimes,
+ method: 'GET',
+ params
+ })
+}
+
+export function statisticsViolationTimesPie (params) {
+ return request({
+ url: api.statisticsViolationTimesPie,
+ method: 'GET',
+ params
+ })
+}
+
+export function involvedTenderNumber (params) {
+ return request({
+ url: api.involvedTenderNumber,
+ method: 'GET',
+ params
+ })
+}
+
+export function winningAmountList (params) {
+ return request({
+ url: api.winningAmountList,
+ method: 'GET',
+ params
+ })
+}
+
+export function winningList (params) {
+ return request({
+ url: api.winningList,
+ method: 'GET',
+ params
+ })
+}
+
+export function getManyCompaniesBiddingList (data) {
+ return request({
+ url: api.getManyCompaniesBiddingList,
+ method: 'POST',
+ data
+ })
+}
+
+export function statisticsWinningUnitList (data) {
+ return request({
+ url: api.statisticsWinningUnitList,
+ method: 'POST',
+ data
+ })
+}
+
+export function statisticsWinningDeptList (params) {
+ return request({
+ url: api.statisticsWinningDeptList,
+ method: 'GET',
+ params
+ })
+}
+
+export function getCompaniesBiddingTotalList (data) {
+ return request({
+ url: api.getCompaniesBiddingTotalList,
+ method: 'POST',
+ data
+ })
+}
diff --git a/src/api/db/table.js b/src/api/db/table.js
new file mode 100644
index 0000000..71d8d3d
--- /dev/null
+++ b/src/api/db/table.js
@@ -0,0 +1,22 @@
+import request from '@/utils/request'
+
+const deptApi = {
+ tableColumnList: '/db/table/tableColumnList',
+ tableList: '/db/table/tableList'
+}
+
+export function tableColumnList (params) {
+ return request({
+ url: deptApi.tableColumnList,
+ method: 'get',
+ params: params
+ })
+}
+
+export function tableList (params) {
+ return request({
+ url: deptApi.tableList,
+ method: 'get',
+ params: params
+ })
+}
diff --git a/src/api/login.js b/src/api/login.js
new file mode 100644
index 0000000..2fa3af6
--- /dev/null
+++ b/src/api/login.js
@@ -0,0 +1,55 @@
+import request from '@/utils/request'
+
+const userApi = {
+ Login: '/auth/login',
+ Logout: '/auth/logout',
+ // get my info
+ UserInfo: '/auth/userInfo',
+ UserMenu: '/user/nav'
+}
+
+/**
+ * login func
+ * params: {
+ * username: '',
+ * password: '',
+ * remember_me: true,
+ * captcha: '12345'
+ * }
+ * @param parameter
+ * @returns {*}
+ */
+export function login (parameter) {
+ return request({
+ url: userApi.Login,
+ method: 'post',
+ data: parameter
+ })
+}
+
+export function getInfo () {
+ return request({
+ url: userApi.UserInfo,
+ method: 'get',
+ headers: {
+ 'Content-Type': 'application/json;charset=UTF-8'
+ }
+ })
+}
+
+export function getCurrentUserNav () {
+ return request({
+ url: userApi.UserMenu,
+ method: 'get'
+ })
+}
+
+export function logout () {
+ return request({
+ url: userApi.Logout,
+ method: 'post',
+ headers: {
+ 'Content-Type': 'application/json;charset=UTF-8'
+ }
+ })
+}
diff --git a/src/api/manage.js b/src/api/manage.js
new file mode 100644
index 0000000..7462ccb
--- /dev/null
+++ b/src/api/manage.js
@@ -0,0 +1,131 @@
+import request from '@/utils/request'
+
+const api = {
+ user: '/user',
+ role: '/role',
+ service: '/service',
+ permission: '/permission',
+ permissionNoPager: '/permission/no-pager',
+ orgTree: '/org/tree'
+}
+
+export default api
+
+export function getUserList (parameter) {
+ return request({
+ url: api.user,
+ method: 'get',
+ params: parameter
+ })
+}
+
+export function getRoleList (parameter) {
+ return request({
+ url: api.role,
+ method: 'get',
+ params: parameter
+ })
+}
+
+export function getServiceList (parameter) {
+ return request({
+ url: api.service,
+ method: 'get',
+ params: parameter
+ })
+}
+
+export function getPermissions (parameter) {
+ return request({
+ url: api.permissionNoPager,
+ method: 'get',
+ params: parameter
+ })
+}
+
+export function getOrgTree (parameter) {
+ return request({
+ url: api.orgTree,
+ method: 'get',
+ params: parameter
+ })
+}
+
+// id == 0 add post
+// id != 0 update put
+export function saveService (parameter) {
+ return request({
+ url: api.service,
+ method: parameter.id === 0 ? 'post' : 'put',
+ data: parameter
+ })
+}
+
+export function saveSub (sub) {
+ return request({
+ url: '/sub',
+ method: sub.id === 0 ? 'post' : 'put',
+ data: sub
+ })
+}
+
+// post
+export function postAction (url, parameter) {
+ return request({
+ url: url,
+ method: 'post',
+ data: parameter
+ })
+}
+
+export function postAction1 (url, parameter) {
+ return request({
+ url: url,
+ method: 'post',
+ params: parameter
+ })
+}
+
+// post method= {post | put}
+export function httpAction (url, parameter, method) {
+ return request({
+ url: url,
+ method: method,
+ data: parameter
+ })
+}
+
+// put
+export function putAction (url, parameter) {
+ return request({
+ url: url,
+ method: 'put',
+ data: parameter
+ })
+}
+
+// get
+export function getAction (url, parameter) {
+ return request({
+ url: url,
+ method: 'get',
+ params: parameter
+ })
+}
+
+// deleteAction
+export function deleteAction (url, parameter) {
+ return request({
+ url: url,
+ method: 'delete',
+ params: parameter
+ })
+}
+
+export function deleteActionInBody (url, data) {
+ return request({
+ url: url,
+ method: 'delete',
+ data
+ })
+}
diff --git a/src/api/parseingPdf.js b/src/api/parseingPdf.js
new file mode 100644
index 0000000..9302a88
--- /dev/null
+++ b/src/api/parseingPdf.js
@@ -0,0 +1,34 @@
+
+import request from '@/utils/request'
+
+const api = {
+ list: '/pdf/parseingPdfList',
+ parseingPDFToWord: '/pdf/parseingPDFToWord',
+ download: '/pdf/download'
+}
+
+export function getList (params) {
+ return request({
+ url: api.list,
+ method: 'GET',
+ params
+ })
+}
+
+export function download (params) {
+ return request({
+ url: api.download,
+ method: 'GET',
+ isDownload: true,
+ params
+ })
+}
+
+export function parseingPDFToWord (data, params = {}) {
+ return request({
+ url: api.parseingPDFToWord,
+ method: 'POST',
+ data,
+ params
+ })
+}
diff --git a/src/api/project/biddingproject.js b/src/api/project/biddingproject.js
new file mode 100644
index 0000000..ccb710d
--- /dev/null
+++ b/src/api/project/biddingproject.js
@@ -0,0 +1,78 @@
+import request from '@/utils/request'
+
+export const api = {
+ getNotCheckProjectList: '/project/biddingproject/getNotCheckProjectList',
+ list: '/project/biddingproject/getList',
+ add: '/project/biddingproject/add',
+ edit: '/project/biddingproject/edit',
+ remove: '/project/biddingproject/remove',
+ checkName: '/project/biddingproject/checkNameUnique',
+ info: '/project/biddingproject/getInfo',
+ template: '/project/biddingproject/exportTemplate',
+ export: '/project/biddingproject/exportExcel',
+ import: '/project/biddingproject/importExcel'
+}
+
+export function getList (params) {
+ return request({
+ url: api.list,
+ method: 'GET',
+ params
+ })
+}
+
+export function getNotCheckProjectList (params) {
+ return request({
+ url: api.getNotCheckProjectList,
+ method: 'GET',
+ params
+ })
+}
+export function getInfo (params) {
+ return request({
+ url: api.info,
+ method: 'GET',
+ params
+ })
+}
+
+export function create (data) {
+ return request({
+ url: api.add,
+ method: 'POST',
+ data
+ })
+}
+
+export function edit (data) {
+ return request({
+ url: api.edit,
+ method: 'PUT',
+ data
+ })
+}
+
+export function checkNameUnique (params) {
+ return request({
+ url: api.checkName,
+ method: 'POST',
+ params
+ })
+}
+
+export function remove (params) {
+ return request({
+ url: api.remove,
+ method: 'DELETE',
+ params
+ })
+}
+
+export function exportExcel (data) {
+ return request({
+ url: api.export,
+ method: 'POST',
+ isDownload: true,
+ data
+ })
+}
diff --git a/src/api/project/tenderBook.js b/src/api/project/tenderBook.js
new file mode 100644
index 0000000..e550648
--- /dev/null
+++ b/src/api/project/tenderBook.js
@@ -0,0 +1,70 @@
+import request from '@/utils/request'
+
+export const api = {
+ list: '/project/tenderbook/getList',
+ add: '/project/tenderbook/add',
+ edit: '/project/tenderbook/edit',
+ remove: '/project/tenderbook/remove',
+ checkUnique: '/project/tenderbook/checkNameUnique',
+ info: '/project/tenderbook/getInfo',
+ template: '/project/tenderbook/exportTemplate',
+ export: '/project/tenderbook/exportExcel',
+ import: '/project/tenderbook/importExcel'
+}
+
+export function getList (params) {
+ return request({
+ url: api.list,
+ method: 'GET',
+ params
+ })
+}
+
+export function create (data) {
+ return request({
+ url: api.add,
+ method: 'POST',
+ data
+ })
+}
+
+export function edit (data) {
+ return request({
+ url: api.edit,
+ method: 'PUT',
+ data
+ })
+}
+
+export function remove (params) {
+ return request({
+ url: api.remove,
+ method: 'DELETE',
+ params
+ })
+}
+
+export function checkUnique (params) {
+ return request({
+ url: api.checkUnique,
+ method: 'POST',
+ params
+ })
+}
+
+export function getInfo (params) {
+ return request({
+ url: api.info,
+ method: 'GET',
+ params
+ })
+}
+
+export function exportExcel (data) {
+ return request({
+ url: api.export,
+ method: 'POST',
+ isDownload: true,
+ data
+ })
+}
diff --git a/src/api/project/tenderProject.js b/src/api/project/tenderProject.js
new file mode 100644
index 0000000..ccd311d
--- /dev/null
+++ b/src/api/project/tenderProject.js
@@ -0,0 +1,79 @@
+import request from '@/utils/request'
+
+export const api = {
+ add: '/project/tenderproject/add',
+ list: '/project/tenderproject/getList',
+ edit: '/project/tenderproject/edit',
+ remove: '/project/tenderproject/remove',
+ template: '/project/tenderproject/exportTemplate',
+ export: '/project/tenderproject/exportExcel',
+ import: '/project/tenderproject/importExcel',
+ checkName: '/project/tenderproject/checkNameUnique',
+ checkCode: '/project/tenderproject/checkCodeUnique',
+ getProjectNameList: '/project/tenderproject/getProjectNameList'
+}
+
+export function getList (params) {
+ return request({
+ url: api.list,
+ method: 'GET',
+ params
+ })
+}
+
+export function getProjectNameList (params) {
+ return request({
+ url: api.getProjectNameList,
+ method: 'GET',
+ params
+ })
+}
+
+export function create (data) {
+ return request({
+ url: api.add,
+ method: 'POST',
+ data
+ })
+}
+
+export function checkNameUnique (params) {
+ return request({
+ url: api.checkName,
+ method: 'POST',
+ params
+ })
+}
+
+export function checkCodeUnique (params) {
+ return request({
+ url: api.checkCode,
+ method: 'GET',
+ params
+ })
+}
+
+export function edit (data) {
+ return request({
+ url: api.edit,
+ method: 'PUT',
+ data
+ })
+}
+
+export function remove (params) {
+ return request({
+ url: api.remove,
+ method: 'DELETE',
+ params
+ })
+}
+
+export function exportExcel (data) {
+ return request({
+ url: api.export,
+ method: 'POST',
+ isDownload: true,
+ data
+ })
+}
diff --git a/src/api/recheck.js b/src/api/recheck.js
new file mode 100644
index 0000000..e30f2cc
--- /dev/null
+++ b/src/api/recheck.js
@@ -0,0 +1,308 @@
+import request from '@/utils/request'
+
+const api = {
+ uploadFile: '/Recheck/uploadFile',
+ getDocument: '/Recheck/getTotalTaskDocumentList',
+ articleDom: '/Recheck/getDocumentPage',
+ compareDetail: '/Recheck/compareStructDetail',
+ list: '/task/findReportPage',
+ compareDocumentDetail: '/Recheck/compareDocumentDetail',
+ createTotalTask: '/task/create',
+ getDocumentStructured: '/Recheck/getDocumentStructured',
+ docSearchList: '/file/findFilePage',
+ reportDetail: '/Recheck/getReport',
+ totalTask: '/task/findTaskPage',
+ analyzeDocument: '/task/reparseTask',
+ allDocument: '/Recheck/getAllDocument',
+ downloadConvertFile: '/file/downloadConvertFile',
+ getDocumentProperties: '/Recheck/getDocumentProperties',
+ remove: '/task/deleteTask', // 任务监控删除接口
+ removeTaskMonitor: '/task/deleteTaskMonitoring', // 任务监控删除接口
+ edit: '/Recheck/updateTotalTask',
+ getTaskFileViewById: '/task/findTaskDetail', // 获取任务详情
+ taskFileList: '/task/findFileList',
+ updateTotalTask: '/task/updateTask', // 文档查重页面重新上传接口
+ findCheckReport: '/task/findCheckReport',
+ updateSubmitState: '/task/updateSubmitState', // 提交接口
+ updateAuditStatus: '/project/biddingproject/updateAuditStatus', // 提交接口
+ findAllReport: '/task/findAllReport', // 总报告接口
+ stopTask: '/task/stopTask?', // 总报告接口
+ stickTask: '/task/updateTaskOrder', // 置顶
+ checkTaskDescription: '/checkTaskDescription/findList' // 总报告接口
+}
+
+export function uploadFile (data, params = {}) {
+ return request({
+ url: api.uploadFile,
+ method: 'POST',
+ data,
+ params
+ })
+}
+
+export function createTotalTask (data) {
+ return request({
+ url: api.createTotalTask,
+ method: 'POST',
+ data
+ })
+}
+
+/**
+ * 文档查重查询文件信息接口
+ * @param {*} taskId
+ * @returns
+ */
+export function getReportFileList (taskId) {
+ return request({
+ url: api.taskFileList,
+ method: 'GET',
+ params: {
+ taskId
+ }
+ })
+}
+
+/**
+ * 任务监控查询文件信息接口
+ * @param {*} taskId
+ * @returns
+ */
+export function getTaskFileList (taskId) {
+ return request({
+ url: api.taskFileList,
+ method: 'GET',
+ params: {
+ taskId
+ }
+ })
+}
+
+export function removeTaskMonitor (params) {
+ return request({
+ url: api.removeTaskMonitor,
+ method: 'DELETE',
+ params
+ })
+}
+
+/**
+ * 文档查重页面重新上传
+ * @param {*} data
+ * @returns
+ */
+export function updateTotalTask (data) {
+ return request({
+ url: api.updateTotalTask,
+ method: 'PUT',
+ data
+ })
+}
+
+/**
+ * 查看报告
+ * @param {*} taskId
+ * @param {*} fileId
+ * @returns
+ */
+export function findCheckReport (taskId, fileId) {
+ return request({
+ url: api.findCheckReport,
+ params: {
+ taskId,
+ fileId
+ }
+ })
+}
+
+export function updateSubmitState (taskId, submitState, description, analysis) {
+ return request({
+ url: api.updateSubmitState,
+ method: 'PUT',
+ params: {
+ taskId,
+ submitState,
+ description,
+ analysis
+ }
+ })
+}
+
+export function updateAuditStatus (projectId, auditStatus, unitIds, description) {
+ return request({
+ url: api.updateAuditStatus,
+ method: 'PUT',
+ params: {
+ projectId,
+ auditStatus,
+ unitIds,
+ description
+ }
+ })
+}
+export function getDocumentStructured (data) {
+ return request({
+ url: api.getDocumentStructured,
+ method: 'POST',
+ data
+ })
+}
+
+export function getList (params = {}) {
+ return request({
+ url: api.list,
+ method: 'GET',
+ params
+ })
+}
+
+export function getDocument (params = {}) {
+ return request({
+ url: api.getDocument,
+ method: 'GET',
+ params
+ })
+}
+
+export function getArticleDom (params = {}) {
+ return request({
+ url: api.articleDom,
+ method: 'GET',
+ params
+ })
+}
+export function getCompareDetail (params = {}) {
+ return request({
+ url: api.compareDetail,
+ method: 'GET',
+ params
+ })
+}
+
+export function getCompareDocumentDetail (params = {}) {
+ return request({
+ url: api.compareDocumentDetail,
+ method: 'GET',
+ params
+ })
+}
+
+export function docSearchList (params) {
+ return request({
+ url: api.docSearchList,
+ method: 'GET',
+ params
+ })
+}
+
+export function getReportDetail (params) {
+ return request({
+ url: api.reportDetail,
+ method: 'GET',
+ params
+ })
+}
+
+export function getTotalTask (params) {
+ return request({
+ url: api.totalTask,
+ method: 'GET',
+ params
+ })
+}
+
+export function analyzeDocument (params) {
+ return request({
+ url: api.analyzeDocument,
+ method: 'PUT',
+ params
+ })
+}
+
+export function getAllDocument (params) {
+ return request({
+ url: api.allDocument,
+ method: 'GET',
+ params
+ })
+}
+
+export function downloadConvertFile (params) {
+ return request({
+ url: api.downloadConvertFile,
+ method: 'get',
+ isRawData: true,
+ responseType: 'blob',
+ params
+ })
+}
+
+export function getDocumentProperties (params = {}) {
+ return request({
+ url: api.getDocumentProperties,
+ method: 'GET',
+ params
+ })
+}
+
+export function removeTotalTask (params) {
+ return request({
+ url: api.remove,
+ method: 'DELETE',
+ params
+ })
+}
+
+export function edit (data) {
+ return request({
+ url: api.edit,
+ method: 'PUT',
+ data
+ })
+}
+
+// 获取任务详细信息
+export function getTaskFileViewById (taskId) {
+ return request({
+ url: api.getTaskFileViewById,
+ params: {
+ taskId
+ }
+ })
+}
+export function stopTask (params) {
+ return request({
+ url: api.stopTask,
+ method: 'GET',
+ params
+ })
+}
+export function checkTaskDescription (taskId) {
+ return request({
+ url: api.checkTaskDescription,
+ params: {
+ taskId
+ }
+ })
+}
+export function findAllReport (taskId) {
+ return request({
+ url: api.findAllReport,
+ params: {
+ taskId
+ }
+ })
+}
+
+/**
+ * 置顶
+ * @param {*} params
+ * @returns
+ */
+export function stickTask (params) {
+ return request({
+ url: api.stickTask,
+ method: 'PUT',
+ params
+ })
+}
diff --git a/src/api/recheckSetting/otherSetting.js b/src/api/recheckSetting/otherSetting.js
new file mode 100644
index 0000000..a13c50e
--- /dev/null
+++ b/src/api/recheckSetting/otherSetting.js
@@ -0,0 +1,23 @@
+import request from '@/utils/request'
+
+const api = {
+ getHttpUrl: '/httpurl/getHttpUrl',
+ update: '/httpurl/update'
+}
+
+export function getHttpUrl (data, params = {}) {
+ return request({
+ url: api.getHttpUrl,
+ method: 'get',
+ data,
+ params
+ })
+}
+
+export function update (params) {
+ return request({
+ url: api.update,
+ method: 'put',
+ params
+ })
+}
diff --git a/src/api/sliceUpload.js b/src/api/sliceUpload.js
new file mode 100644
index 0000000..ca9c356
--- /dev/null
+++ b/src/api/sliceUpload.js
@@ -0,0 +1,204 @@
+import request from '@/utils/request'
+import { message } from 'ant-design-vue'
+
+export const fileApi = {
+ VerifyUpload: '/file/verifyFileExist',
+ MergeFile: '/file/mergeFile',
+ UpdateFolder: '/file/updateFolder',
+ GetUserFolderAndFiles: '/file/folder/getUserFolderAndFiles',
+ CreateFolder: '/file/folder/add',
+ GetFolderInfo: '/file/folder/getInfo',
+ EditFolder: '/file/folder/edit',
+ RemoveFolder: '/file/folder/remove',
+ GetFileSize: '/file/filesize',
+ FileDown: '/file/download',
+ downloadById: '/file/downloadById',
+
+ downloadTask: '/file/downloadTask', // 查重页下载相应的文件
+ downloadTaskById: '/file/downloadTaskById', // 查重页下载相应的文件
+ downloadTaskConvertFile: '/file/downloadTaskConvertFile', // 查重页下载相应的文件
+ exportProjectUnitToExcel: '/project/projectAnalysis/exportProjectUnitToExcel' // 查重页下载相应的文件
+}
+
+// 校验文件是否上传
+export function verifyUpload (params) {
+ return request({
+ url: fileApi.VerifyUpload,
+ params
+ })
+}
+
+// 合并文件
+export function mergeFile (data) {
+ return request({
+ url: fileApi.MergeFile,
+ method: 'post',
+ params: data
+ })
+}
+
+// 调整文件所属文件夹
+export function updateFolder (params) {
+ return request({
+ url: fileApi.UpdateFolder,
+ method: 'post',
+ params
+ })
+}
+
+// 获取当前用户的文件夹及文件
+export function getUserFolderAndFiles (params) {
+ return request({
+ url: fileApi.GetUserFolderAndFiles,
+ method: 'get',
+ params
+ })
+}
+// 创建文件夹
+export function createFolder (data) {
+ return request({
+ url: fileApi.CreateFolder,
+ method: 'post',
+ data
+ })
+}
+
+// 获取文件夹详情
+export function getFolderInfo (params) {
+ return request({
+ url: fileApi.GetFolderInfo,
+ method: 'get',
+ params
+ })
+}
+
+// 编辑文件夹信息
+export function editFolder (data) {
+ return request({
+ url: fileApi.EditFolder,
+ method: 'put',
+ data
+ })
+}
+
+// 删除文件夹
+export function removeFolder (params) {
+ return request({
+ url: fileApi.RemoveFolder,
+ method: 'delete',
+ params
+ })
+}
+
+// 获取文件大小
+export function getFileSize (params) {
+ return request({
+ url: fileApi.GetFileSize,
+ method: 'get',
+ params
+ })
+}
+
+// 下载文件
+export function fileDown (params, contentRage) {
+ return request({
+ url: fileApi.FileDown,
+ method: 'get',
+ params,
+ // headers: { Range: contentRage },
+ responseType: 'blob',
+ isRawData: true
+ })
+}
+/**
+* 下载文件 用于excel导出
+* @param url
+* @param parameter
+* @returns {*}
+*/
+export function downFile (url, parameter) {
+ return request({
+ url: url,
+ params: parameter,
+ method: 'get',
+ responseType: 'blob',
+ isRawData: true
+ })
+}
+
+/**
+* 下载文件
+* @param url 文件路径
+* @param fileName 文件名
+* @param parameter
+* @returns {*}
+*/
+export function downloadFile (fileName, parameter, downloadUrl) {
+ return downFile(downloadUrl || fileApi.FileDown, parameter).then((data) => {
+ if (!data || data.size === 0) {
+ console.error('文件下载失败')
+ return
+ }
+ if (typeof window.navigator.msSaveBlob !== 'undefined') {
+ window.navigator.msSaveBlob(new Blob([data]), fileName)
+ } else {
+ const url = window.URL.createObjectURL(new Blob([data]))
+ const link = document.createElement('a')
+ link.style.display = 'none'
+ link.href = url
+ link.setAttribute('download', fileName)
+ document.body.appendChild(link)
+ link.click()
+ document.body.removeChild(link) // 下载完成移除元素
+ window.URL.revokeObjectURL(url) // 释放掉blob对象
+ }
+ })
+}
+
+/**
+* 下载文件
+* @param url 文件路径
+* @param fileName 文件名
+* @param parameter
+* @returns {*}
+*/
+export function downloadFile2 (fileName, parameter, downloadUrl) {
+ return downFile(downloadUrl || fileApi.FileDown, parameter).then((data) => {
+ if (!data || data.size === 0) {
+ message.error('文件不存在,请重新上传文件')
+ return
+ }
+ if (typeof window.navigator.msSaveBlob !== 'undefined') {
+ window.navigator.msSaveBlob(new Blob([data]), fileName)
+ } else {
+ const url = window.URL.createObjectURL(new Blob([data]))
+ const link = document.createElement('a')
+ link.style.display = 'none'
+ link.href = url
+ link.setAttribute('download', fileName)
+ document.body.appendChild(link)
+ link.click()
+ document.body.removeChild(link) // 下载完成移除元素
+ window.URL.revokeObjectURL(url) // 释放掉blob对象
+ }
+ })
+}
+
+// post
+export function postAction (url, parameter) {
+ return request({
+ url: url,
+ method: 'post',
+ data: parameter
+ })
+}
+
+export function downloadById (params) {
+ return request({
+ url: fileApi.downloadById,
+ method: 'get',
+ isRawData: true,
+ responseType: 'blob',
+ params
+ })
+}
diff --git a/src/api/system/backup.js b/src/api/system/backup.js
new file mode 100644
index 0000000..bb6f7b8
--- /dev/null
+++ b/src/api/system/backup.js
@@ -0,0 +1,87 @@
+import request from '@/utils/request'
+
+export const ApiUri = {
+ list: '/backup/getBackupHistory',
+ doBackUp: '/backup/doBackUp',
+ download: '/backup/downloadFile',
+ setting: '/backup/updateBackupProperties',
+ getSetting: '/backup/getBackupProperties',
+ backUpByTableName: '/backup/backUpByTableName',
+ uploadSqlFile: '/backup/uploadSqlFile',
+ executionInitSql: '/backup/executionInitSql',
+ allTable: '/backup/getAllTable'
+}
+
+export function getList (params) {
+ return request({
+ url: ApiUri.list,
+ method: 'GET',
+ params
+ })
+}
+
+export function download (params) {
+ return request({
+ url: ApiUri.download,
+ method: 'GET',
+ params,
+ isDownload: true
+ })
+}
+
+export function doBackUp (data) {
+ return request({
+ url: ApiUri.doBackUp,
+ method: 'POST',
+ data
+ })
+}
+
+export function setting (data) {
+ return request({
+ url: ApiUri.setting,
+ method: 'PUT',
+ data
+ })
+}
+
+export function getSetting (data) {
+ return request({
+ url: ApiUri.getSetting,
+ method: 'GET',
+ data
+ })
+}
+
+export function backUpByTableName (params) {
+ return request({
+ url: ApiUri.backUpByTableName,
+ method: 'GET',
+ params,
+ isDownload: true
+ })
+}
+
+export function uploadSqlFile (data) {
+ return request({
+ url: ApiUri.uploadSqlFile,
+ method: 'POST',
+ data,
+ isDownload: true
+ })
+}
+
+export function executionInitSql (data) {
+ return request({
+ url: ApiUri.executionInitSql,
+ method: 'POST',
+ data
+ })
+}
+
+export function getAllTable () {
+ return request({
+ url: ApiUri.allTable,
+ method: 'GET'
+ })
+}
diff --git a/src/api/system/checkFilter.js b/src/api/system/checkFilter.js
new file mode 100644
index 0000000..d4c1794
--- /dev/null
+++ b/src/api/system/checkFilter.js
@@ -0,0 +1,54 @@
+import request from '@/utils/request'
+
+const api = {
+ checkFilter: '/checkFilter',
+ filterWord: '/checkFilter/word'
+}
+
+export function getConfig (params = {}) {
+ return request({
+ url: api.checkFilter,
+ method: 'GET',
+ params
+ })
+}
+
+export function edit (data) {
+ return request({
+ url: api.checkFilter,
+ method: 'PUT',
+ data
+ })
+}
+
+export function getWordList (data) {
+ return request({
+ url: api.filterWord,
+ method: 'GET',
+ data
+ })
+}
+
+export function createWord (params) {
+ return request({
+ url: api.filterWord,
+ method: 'POST',
+ params
+ })
+}
+
+export function editWord (params) {
+ return request({
+ url: api.filterWord,
+ method: 'PUT',
+ params
+ })
+}
+
+export function removeWord (params) {
+ return request({
+ url: api.filterWord,
+ method: 'DELETE',
+ params
+ })
+}
diff --git a/src/api/system/conclusion.js b/src/api/system/conclusion.js
new file mode 100644
index 0000000..d0a17d0
--- /dev/null
+++ b/src/api/system/conclusion.js
@@ -0,0 +1,39 @@
+import request from '@/utils/request'
+
+const api = {
+ checkThreshold: '/checkThreshold',
+ create: '/checkThreshold/add',
+ update: '/checkThreshold/update'
+}
+
+export function getList (params = {}) {
+ return request({
+ url: api.checkThreshold,
+ method: 'GET',
+ params
+ })
+}
+
+export function create (data) {
+ return request({
+ url: api.create,
+ method: 'POST',
+ data
+ })
+}
+
+export function edit (data) {
+ return request({
+ url: api.update,
+ method: 'POST',
+ data
+ })
+}
+
+export function remove (params) {
+ return request({
+ url: api.checkThreshold,
+ method: 'DELETE',
+ params
+ })
+}
diff --git a/src/api/system/dept.js b/src/api/system/dept.js
new file mode 100644
index 0000000..72b8bb9
--- /dev/null
+++ b/src/api/system/dept.js
@@ -0,0 +1,82 @@
+import request from '@/utils/request'
+
+const deptApi = {
+ create: '/system/dept/add',
+ remove: '/system/dept/remove',
+ getInfo: '/system/dept/getInfo',
+ edit: '/system/dept/edit',
+ list: '/system/dept/getList',
+ getTreeSelect: '/system/dept/getTreeSelect',
+ checkDeptNameUnique: '/system/dept/checkDeptNameUnique',
+ changeStatus: '/system/dept/changeStatus',
+ getChildren: '/system/dept/getChildren'
+}
+
+export function create (params) {
+ return request({
+ url: deptApi.create,
+ method: 'post',
+ data: params
+ })
+}
+
+export function remove (params) {
+ return request({
+ url: deptApi.remove,
+ method: 'delete',
+ params: params
+ })
+}
+
+export function getInfo (params) {
+ return request({
+ url: deptApi.getInfo,
+ method: 'get',
+ params: params
+ })
+}
+
+export function edit (params) {
+ return request({
+ url: deptApi.edit,
+ method: 'put',
+ data: params
+ })
+}
+
+export function getList (params) {
+ return request({
+ url: deptApi.list,
+ method: 'get',
+ params: params
+ })
+}
+export function getTreeSelect () {
+ return request({
+ url: deptApi.getTreeSelect,
+ method: 'get'
+ })
+}
+
+export function checkDeptNameUnique (params) {
+ return request({
+ url: deptApi.checkDeptNameUnique,
+ method: 'post',
+ params: params
+ })
+}
+export function changeStatus (params) {
+ return request({
+ url: deptApi.changeStatus,
+ method: 'post',
+ params: params
+ })
+}
+
+export function getChildren (params) {
+ return request({
+ url: deptApi.getChildren,
+ method: 'get',
+ params: params
+ })
+}
diff --git a/src/api/system/dict.js b/src/api/system/dict.js
new file mode 100644
index 0000000..44adbd8
--- /dev/null
+++ b/src/api/system/dict.js
@@ -0,0 +1,128 @@
+import request from '@/utils/request'
+
+const Api = {
+ add: '/system/dictType/add',
+ remove: '/system/dictType/remove',
+ getInfo: '/system/dictType/get',
+ edit: '/system/dictType/edit',
+ checkTypeNameUnique: '/system/dictType/checkTypeNameUnique',
+ checkTypeCodeUnique: '/system/dictType/checkTypeCodeUnique',
+ typeTreeNode: '/system/dictType/getTreeNodes',
+ typeList: '/system/dictType/getList',
+ addDict: '/system/dictData/add',
+ editDict: '/system/dictData/edit',
+ removeDict: '/system/dictData/remove',
+ getDictList: '/system/dictData/getList',
+ getDictInfo: '/system/dictData/get',
+ getDictOptions: '/system/dictData/getOptions'
+}
+
+export function addType (params) {
+ return request({
+ url: Api.add,
+ method: 'post',
+ data: params
+ })
+}
+
+export function editType (params) {
+ return request({
+ url: Api.edit,
+ method: 'put',
+ data: params
+ })
+}
+
+export function getType (params) {
+ return request({
+ url: Api.getInfo,
+ method: 'get',
+ params: params
+ })
+}
+
+export function removeType (params) {
+ return request({
+ url: Api.remove,
+ method: 'delete',
+ params: params
+ })
+}
+
+export function removeDict (params) {
+ return request({
+ url: Api.removeDict,
+ method: 'delete',
+ params: params
+ })
+}
+
+export function getTypeTreeNodes () {
+ return request({
+ url: Api.typeTreeNode,
+ method: 'get'
+ })
+}
+
+export function checkTypeNameUnique (params) {
+ return request({
+ url: Api.checkTypeNameUnique,
+ method: 'post',
+ params: params
+ })
+}
+
+export function checkTypeCodeUnique (params) {
+ return request({
+ url: Api.checkTypeCodeUnique,
+ method: 'post',
+ params: params
+ })
+}
+
+export function getTypeList () {
+ return request({
+ url: Api.typeList,
+ method: 'get'
+ })
+}
+
+export function addDict (params) {
+ return request({
+ url: Api.addDict,
+ method: 'post',
+ data: params
+ })
+}
+
+export function editDict (params) {
+ return request({
+ url: Api.editDict,
+ method: 'put',
+ data: params
+ })
+}
+
+export function getDictList (params) {
+ return request({
+ url: Api.getDictList,
+ method: 'get',
+ params: params
+ })
+}
+
+export function getDictInfo (params) {
+ return request({
+ url: Api.getDictInfo,
+ method: 'get',
+ params: params
+ })
+}
+
+export function getDictOptions (params) {
+ return request({
+ url: Api.getDictOptions,
+ method: 'get',
+ params: params
+ })
+}
diff --git a/src/api/system/log.js b/src/api/system/log.js
new file mode 100644
index 0000000..63f5906
--- /dev/null
+++ b/src/api/system/log.js
@@ -0,0 +1,31 @@
+import request from '@/utils/request'
+
+const Api = {
+ list: '/system/log/list',
+ getInfo: '/system/log/getInfo',
+ getLogFile: '/system/log/getLogFile'
+}
+
+export function getList (params) {
+ return request({
+ url: Api.list,
+ method: 'get',
+ params: params
+ })
+}
+export function getInfo (params) {
+ return request({
+ url: Api.getInfo,
+ method: 'get',
+ params: params
+ })
+}
+
+export function getLogFile (params) {
+ return request({
+ url: Api.getLogFile,
+ method: 'get',
+ params: params,
+ isDownload: true
+ })
+}
diff --git a/src/api/system/menu.js b/src/api/system/menu.js
new file mode 100644
index 0000000..b29551f
--- /dev/null
+++ b/src/api/system/menu.js
@@ -0,0 +1,74 @@
+import request from '@/utils/request'
+
+const menuApi = {
+ create: '/system/menu/add',
+ remove: '/system/menu/remove',
+ getInfo: '/system/menu/getInfo',
+ edit: '/system/menu/edit',
+ list: '/system/menu/getList',
+ getTreeSelect: '/system/menu/getTreeSelect',
+ checkDeptNameUnique: '/system/menu/checkDeptNameUnique',
+ changeStatus: '/system/menu/changeStatus',
+ getMenuPermission: '/system/menu/getMenuPermission'
+}
+
+export function create (params) {
+ return request({
+ url: menuApi.create,
+ method: 'post',
+ data: params
+ })
+}
+
+export function remove (params) {
+ return request({
+ url: menuApi.remove,
+ method: 'delete',
+ params: params
+ })
+}
+
+export function getInfo (params) {
+ return request({
+ url: menuApi.getInfo,
+ method: 'get',
+ params: params
+ })
+}
+
+export function edit (params) {
+ return request({
+ url: menuApi.edit,
+ method: 'put',
+ data: params
+ })
+}
+
+export function getList (params) {
+ return request({
+ url: menuApi.list,
+ method: 'get',
+ params: params
+ })
+}
+export function getTreeSelect () {
+ return request({
+ url: menuApi.getTreeSelect,
+ method: 'get'
+ })
+}
+
+// export function changeStatus (params) {
+// return request({
+// url: deptApi.changeStatus,
+// method: 'post',
+// params: params
+// })
+// }
+
+export function getMenuPermission () {
+ return request({
+ url: menuApi.getMenuPermission,
+ method: 'get'
+ })
+}
diff --git a/src/api/system/redis.js b/src/api/system/redis.js
new file mode 100644
index 0000000..1f89710
--- /dev/null
+++ b/src/api/system/redis.js
@@ -0,0 +1,14 @@
+
+import request from '@/utils/request'
+
+export const ApiUri = {
+ cleanKey: '/system/redis/cleanKey'
+}
+
+export function cleanKey (params) {
+ return request({
+ url: ApiUri.cleanKey,
+ method: 'POST',
+ params
+ })
+}
diff --git a/src/api/system/role.js b/src/api/system/role.js
new file mode 100644
index 0000000..de5fcaa
--- /dev/null
+++ b/src/api/system/role.js
@@ -0,0 +1,85 @@
+import request from '@/utils/request'
+
+const Api = {
+ add: '/system/role/add',
+ remove: '/system/role/remove',
+ getInfo: '/system/role/getInfo',
+ changeStatus: '/system/role/changeStatus',
+ edit: '/system/role/edit',
+ list: '/system/role/getList',
+ checkRoleNameUnique: '/system/role/checkRoleNameUnique',
+ getRoleOptions: '/system/role/getRoleOptions',
+ getPermissions: '/system/role/getPermissions',
+ setPermissions: '/system/role/setPermissions'
+}
+export function add (params) {
+ return request({
+ url: Api.add,
+ method: 'post',
+ data: params
+ })
+}
+
+export function edit (params) {
+ return request({
+ url: Api.edit,
+ method: 'put',
+ data: params
+ })
+}
+export function remove (params) {
+ return request({
+ url: Api.remove,
+ method: 'delete',
+ params: params
+ })
+}
+export function getList (parameter) {
+ return request({
+ url: Api.list,
+ method: 'get',
+ params: parameter
+ })
+}
+export function getInfo (parameter) {
+ return request({
+ url: Api.getInfo,
+ method: 'get',
+ params: parameter
+ })
+}
+export function checkRoleNameUnique (params) {
+ return request({
+ url: Api.checkRoleNameUnique,
+ method: 'post',
+ params: params
+ })
+}
+export function changeStatus (params) {
+ return request({
+ url: Api.changeStatus,
+ method: 'post',
+ params: params
+ })
+}
+export function getRoleOptions () {
+ return request({
+ url: Api.getRoleOptions,
+ method: 'get'
+ })
+}
+export function setPermissions (parmas) {
+ return request({
+ url: Api.setPermissions,
+ method: 'post',
+ data: parmas
+ })
+}
+
+export function getPermissions (parmas) {
+ return request({
+ url: Api.getPermissions,
+ method: 'get',
+ params: parmas
+ })
+}
diff --git a/src/api/system/user.js b/src/api/system/user.js
new file mode 100644
index 0000000..d74fcb3
--- /dev/null
+++ b/src/api/system/user.js
@@ -0,0 +1,85 @@
+import request from '@/utils/request'
+
+const userApi = {
+ Create: '/system/user/create',
+ GetInfo: '/system/user/getInfo',
+ Update: '/system/user/update',
+ ResetPwd: '/system/user/resetPwd',
+ Remove: '/system/user/delete',
+ List: '/system/user/list',
+ CheckUserNameUnique: '/system/user/checkUserNameUnique',
+ CheckPhoneUnique: '/system/user/checkPhoneUnique',
+ resetPwd: '/system/user/resetPwd',
+ changeStatus: '/system/user/changeStatus'
+}
+export function CheckPhoneUnique (parameter) {
+ return request({
+ url: userApi.CheckPhoneUnique,
+ method: 'post',
+ params: parameter
+ })
+}
+
+export function CheckUserNameUnique (parameter) {
+ return request({
+ url: userApi.CheckUserNameUnique,
+ method: 'post',
+ params: parameter
+ })
+}
+
+export function Create (parameter) {
+ return request({
+ url: userApi.Create,
+ method: 'post',
+ data: parameter
+ })
+}
+
+export function GetInfo (parameter) {
+ return request({
+ url: userApi.GetInfo,
+ method: 'get',
+ params: parameter
+ })
+}
+
+export function Update (parameter) {
+ return request({
+ url: userApi.Update,
+ method: 'put',
+ data: parameter
+ })
+}
+
+export function Remove (parameter) {
+ return request({
+ url: userApi.Remove,
+ method: 'delete',
+ params: parameter
+ })
+}
+
+export function List (parameter) {
+ return request({
+ url: userApi.List,
+ method: 'get',
+ params: parameter
+ })
+}
+
+export function resetPwd (parameter) {
+ return request({
+ url: userApi.resetPwd,
+ method: 'post',
+ params: parameter
+ })
+}
+
+export function changeStatus (parameter) {
+ return request({
+ url: userApi.changeStatus,
+ method: 'post',
+ params: parameter
+ })
+}
diff --git a/src/assets/MP3.png b/src/assets/MP3.png
new file mode 100644
index 0000000..f8359c1
Binary files /dev/null and b/src/assets/MP3.png differ
diff --git a/src/assets/PDF.png b/src/assets/PDF.png
new file mode 100644
index 0000000..c8cd579
Binary files /dev/null and b/src/assets/PDF.png differ
diff --git a/src/assets/SQL.png b/src/assets/SQL.png
new file mode 100644
index 0000000..3999c17
Binary files /dev/null and b/src/assets/SQL.png differ
diff --git a/src/assets/TXT.png b/src/assets/TXT.png
new file mode 100644
index 0000000..e0a3178
Binary files /dev/null and b/src/assets/TXT.png differ
diff --git a/src/assets/XLS.png b/src/assets/XLS.png
new file mode 100644
index 0000000..6a5ac4b
Binary files /dev/null and b/src/assets/XLS.png differ
diff --git a/src/assets/ZIP.png b/src/assets/ZIP.png
new file mode 100644
index 0000000..a9ff8ad
Binary files /dev/null and b/src/assets/ZIP.png differ
diff --git a/src/assets/background.png b/src/assets/background.png
new file mode 100644
index 0000000..3973438
Binary files /dev/null and b/src/assets/background.png differ
diff --git a/src/assets/background.svg b/src/assets/background.svg
new file mode 100644
index 0000000..89c2597
--- /dev/null
+++ b/src/assets/background.svg
@@ -0,0 +1,69 @@
+
+
\ No newline at end of file
diff --git a/src/assets/file_type/pdf.png b/src/assets/file_type/pdf.png
new file mode 100644
index 0000000..263bce1
Binary files /dev/null and b/src/assets/file_type/pdf.png differ
diff --git a/src/assets/file_type/photo.png b/src/assets/file_type/photo.png
new file mode 100644
index 0000000..858a0a7
Binary files /dev/null and b/src/assets/file_type/photo.png differ
diff --git a/src/assets/file_type/png.png b/src/assets/file_type/png.png
new file mode 100644
index 0000000..3603110
Binary files /dev/null and b/src/assets/file_type/png.png differ
diff --git a/src/assets/file_type/txt.png b/src/assets/file_type/txt.png
new file mode 100644
index 0000000..9a29668
Binary files /dev/null and b/src/assets/file_type/txt.png differ
diff --git a/src/assets/file_type/word.png b/src/assets/file_type/word.png
new file mode 100644
index 0000000..9a23a41
Binary files /dev/null and b/src/assets/file_type/word.png differ
diff --git a/src/assets/floder.png b/src/assets/floder.png
new file mode 100644
index 0000000..6d928be
Binary files /dev/null and b/src/assets/floder.png differ
diff --git a/src/assets/folder_close.png b/src/assets/folder_close.png
new file mode 100644
index 0000000..a81860a
Binary files /dev/null and b/src/assets/folder_close.png differ
diff --git a/src/assets/folder_open.png b/src/assets/folder_open.png
new file mode 100644
index 0000000..2cd24f3
Binary files /dev/null and b/src/assets/folder_open.png differ
diff --git a/src/assets/icons/bx-analyse.svg b/src/assets/icons/bx-analyse.svg
new file mode 100644
index 0000000..b02a8d6
--- /dev/null
+++ b/src/assets/icons/bx-analyse.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/assets/login_title.png b/src/assets/login_title.png
new file mode 100644
index 0000000..704ab31
Binary files /dev/null and b/src/assets/login_title.png differ
diff --git a/src/assets/login_wrapper.png b/src/assets/login_wrapper.png
new file mode 100644
index 0000000..354f3c7
Binary files /dev/null and b/src/assets/login_wrapper.png differ
diff --git a/src/assets/logo.png b/src/assets/logo.png
new file mode 100644
index 0000000..2eae963
Binary files /dev/null and b/src/assets/logo.png differ
diff --git a/src/assets/logo.svg b/src/assets/logo.svg
new file mode 100644
index 0000000..07ac542
--- /dev/null
+++ b/src/assets/logo.svg
@@ -0,0 +1,29 @@
+
+
\ No newline at end of file
diff --git a/src/assets/logo_blue.png b/src/assets/logo_blue.png
new file mode 100644
index 0000000..90bf57f
Binary files /dev/null and b/src/assets/logo_blue.png differ
diff --git a/src/assets/page/bg.png b/src/assets/page/bg.png
new file mode 100644
index 0000000..3b8cd05
Binary files /dev/null and b/src/assets/page/bg.png differ
diff --git a/src/assets/page/center-bottom.png b/src/assets/page/center-bottom.png
new file mode 100644
index 0000000..65c0727
Binary files /dev/null and b/src/assets/page/center-bottom.png differ
diff --git a/src/assets/page/center-repeat.png b/src/assets/page/center-repeat.png
new file mode 100644
index 0000000..ec7d3f7
Binary files /dev/null and b/src/assets/page/center-repeat.png differ
diff --git a/src/assets/page/center-top.png b/src/assets/page/center-top.png
new file mode 100644
index 0000000..44ef97f
Binary files /dev/null and b/src/assets/page/center-top.png differ
diff --git a/src/assets/page/header/bg.png b/src/assets/page/header/bg.png
new file mode 100644
index 0000000..70ddd39
Binary files /dev/null and b/src/assets/page/header/bg.png differ
diff --git a/src/assets/page/left-bottom.png b/src/assets/page/left-bottom.png
new file mode 100644
index 0000000..106b791
Binary files /dev/null and b/src/assets/page/left-bottom.png differ
diff --git a/src/assets/page/left-center.png b/src/assets/page/left-center.png
new file mode 100644
index 0000000..8dcf5aa
Binary files /dev/null and b/src/assets/page/left-center.png differ
diff --git a/src/assets/page/left-repeat.png b/src/assets/page/left-repeat.png
new file mode 100644
index 0000000..172972e
Binary files /dev/null and b/src/assets/page/left-repeat.png differ
diff --git a/src/assets/page/left-top.png b/src/assets/page/left-top.png
new file mode 100644
index 0000000..1767a27
Binary files /dev/null and b/src/assets/page/left-top.png differ
diff --git a/src/assets/page/right-bottom.png b/src/assets/page/right-bottom.png
new file mode 100644
index 0000000..36c32b3
Binary files /dev/null and b/src/assets/page/right-bottom.png differ
diff --git a/src/assets/page/right-center.png b/src/assets/page/right-center.png
new file mode 100644
index 0000000..777b9ea
Binary files /dev/null and b/src/assets/page/right-center.png differ
diff --git a/src/assets/page/right-repeat.png b/src/assets/page/right-repeat.png
new file mode 100644
index 0000000..20e4c40
Binary files /dev/null and b/src/assets/page/right-repeat.png differ
diff --git a/src/assets/page/right-top.png b/src/assets/page/right-top.png
new file mode 100644
index 0000000..433f6d8
Binary files /dev/null and b/src/assets/page/right-top.png differ
diff --git a/src/assets/shareFloder.png b/src/assets/shareFloder.png
new file mode 100644
index 0000000..a6c0fa6
Binary files /dev/null and b/src/assets/shareFloder.png differ
diff --git a/src/assets/threePoint.png b/src/assets/threePoint.png
new file mode 100644
index 0000000..9ed0308
Binary files /dev/null and b/src/assets/threePoint.png differ
diff --git a/src/assets/title_icon.png b/src/assets/title_icon.png
new file mode 100644
index 0000000..55adb9d
Binary files /dev/null and b/src/assets/title_icon.png differ
diff --git a/src/components/ArticleListContent/ArticleListContent.vue b/src/components/ArticleListContent/ArticleListContent.vue
new file mode 100644
index 0000000..8f39978
--- /dev/null
+++ b/src/components/ArticleListContent/ArticleListContent.vue
@@ -0,0 +1,89 @@
+
+
+
+
+ {{ description }}
+
+
+
+
+
+
+
+
+
diff --git a/src/components/ArticleListContent/index.js b/src/components/ArticleListContent/index.js
new file mode 100644
index 0000000..37d35c7
--- /dev/null
+++ b/src/components/ArticleListContent/index.js
@@ -0,0 +1,3 @@
+import ArticleListContent from './ArticleListContent'
+
+export default ArticleListContent
diff --git a/src/components/AvatarList/Item.jsx b/src/components/AvatarList/Item.jsx
new file mode 100644
index 0000000..8019fac
--- /dev/null
+++ b/src/components/AvatarList/Item.jsx
@@ -0,0 +1,25 @@
+import PropTypes from 'ant-design-vue/es/_util/vue-types'
+import { Tooltip, Avatar } from 'ant-design-vue'
+import { getSlotOptions } from 'ant-design-vue/lib/_util/props-util'
+import { warning } from 'ant-design-vue/lib/vc-util/warning'
+
+export const AvatarListItemProps = {
+ tips: PropTypes.string,
+ src: PropTypes.string.def('')
+}
+
+const Item = {
+ __ANT_AVATAR_CHILDREN: true,
+ name: 'AvatarListItem',
+ props: AvatarListItemProps,
+ created () {
+ warning(getSlotOptions(this.$parent).__ANT_AVATAR_LIST, 'AvatarListItem must be a subcomponent of AvatarList')
+ },
+ render () {
+ const size = this.$parent.size === 'mini' ? 'small' : this.$parent.size
+ const AvatarDom =
+ return (this.tips && {AvatarDom}) ||
+ }
+}
+
+export default Item
diff --git a/src/components/AvatarList/List.jsx b/src/components/AvatarList/List.jsx
new file mode 100644
index 0000000..bff7092
--- /dev/null
+++ b/src/components/AvatarList/List.jsx
@@ -0,0 +1,72 @@
+import './index.less'
+
+import PropTypes from 'ant-design-vue/es/_util/vue-types'
+import Avatar from 'ant-design-vue/es/avatar'
+import Item from './Item.jsx'
+import { filterEmpty } from '@/components/_util/util'
+
+/**
+ * size: `number`、 `large`、`small`、`default` 默认值: default
+ * maxLength: number
+ * excessItemsStyle: CSSProperties
+ */
+const AvatarListProps = {
+ prefixCls: PropTypes.string.def('ant-pro-avatar-list'),
+ size: {
+ validator: val => {
+ return typeof val === 'number' || ['small', 'large', 'default'].includes(val)
+ },
+ default: 'default'
+ },
+ maxLength: PropTypes.number.def(0),
+ excessItemsStyle: PropTypes.object.def({
+ color: '#f56a00',
+ backgroundColor: '#fde3cf'
+ })
+}
+
+const AvatarList = {
+ __ANT_AVATAR_LIST: true,
+ Item,
+ name: 'AvatarList',
+ props: AvatarListProps,
+ render (h) {
+ const { prefixCls, size } = this.$props
+ const className = {
+ [`${prefixCls}`]: true,
+ [`${size}`]: true
+ }
+
+ const items = filterEmpty(this.$slots.default)
+ const itemsDom = items && items.length ? : null
+ return (
+
+ {itemsDom}
+
+ )
+ },
+ methods: {
+ getItems (items) {
+ const className = {
+ [`${this.prefixCls}-item`]: true,
+ [`${this.size}`]: true
+ }
+ const totalSize = items.length
+
+ if (this.maxLength > 0) {
+ items = items.slice(0, this.maxLength)
+ items.push(({`+${totalSize - this.maxLength}`}))
+ }
+ return items.map((item) => (
+ {item}
+ ))
+ }
+ }
+}
+
+AvatarList.install = function (Vue) {
+ Vue.component(AvatarList.name, AvatarList)
+ Vue.component(AvatarList.Item.name, AvatarList.Item)
+}
+
+export default AvatarList
diff --git a/src/components/AvatarList/index.js b/src/components/AvatarList/index.js
new file mode 100644
index 0000000..b047432
--- /dev/null
+++ b/src/components/AvatarList/index.js
@@ -0,0 +1,9 @@
+import AvatarList from './List'
+import Item from './Item'
+
+export {
+ AvatarList,
+ Item as AvatarListItem
+}
+
+export default AvatarList
diff --git a/src/components/AvatarList/index.less b/src/components/AvatarList/index.less
new file mode 100644
index 0000000..87cc4b5
--- /dev/null
+++ b/src/components/AvatarList/index.less
@@ -0,0 +1,59 @@
+@import '../index';
+
+@avatar-list-prefix-cls: ~"@{ant-pro-prefix}-avatar-list";
+@avatar-list-item-prefix-cls: ~"@{ant-pro-prefix}-avatar-list-item";
+
+.@{avatar-list-prefix-cls} {
+ display: inline-block;
+
+ ul {
+ display: inline-block;
+ padding: 0;
+ margin: 0 0 0 8px;
+ font-size: 0;
+ list-style: none;
+ }
+}
+
+.@{avatar-list-item-prefix-cls} {
+ display: inline-block;
+ width: @avatar-size-base;
+ height: @avatar-size-base;
+ margin-left: -8px;
+ font-size: @font-size-base;
+
+ :global {
+ .ant-avatar {
+ cursor: pointer;
+ border: 1px solid #fff;
+ }
+ }
+
+ &.large {
+ width: @avatar-size-lg;
+ height: @avatar-size-lg;
+ }
+
+ &.small {
+ width: @avatar-size-sm;
+ height: @avatar-size-sm;
+ }
+
+ &.mini {
+ width: 20px;
+ height: 20px;
+
+ :global {
+ .ant-avatar {
+ width: 20px;
+ height: 20px;
+ line-height: 20px;
+
+ .ant-avatar-string {
+ font-size: 12px;
+ line-height: 18px;
+ }
+ }
+ }
+ }
+}
diff --git a/src/components/AvatarList/index.md b/src/components/AvatarList/index.md
new file mode 100644
index 0000000..75e022c
--- /dev/null
+++ b/src/components/AvatarList/index.md
@@ -0,0 +1,64 @@
+# AvatarList 用户头像列表
+
+
+一组用户头像,常用在项目/团队成员列表。可通过设置 `size` 属性来指定头像大小。
+
+
+
+引用方式:
+
+```javascript
+import AvatarList from '@/components/AvatarList'
+const AvatarListItem = AvatarList.Item
+
+export default {
+ components: {
+ AvatarList,
+ AvatarListItem
+ }
+}
+```
+
+
+
+## 代码演示 [demo](https://pro.loacg.com/test/home)
+
+```html
+
+
+
+
+
+```
+或
+```html
+
+
+
+
+
+
+
+
+
+```
+
+
+
+## API
+
+### AvatarList
+
+| 参数 | 说明 | 类型 | 默认值 |
+| ---------------- | -------- | ---------------------------------- | --------- |
+| size | 头像大小 | `large`、`small` 、`mini`, `default` | `default` |
+| maxLength | 要显示的最大项目 | number | - |
+| excessItemsStyle | 多余的项目风格 | CSSProperties | - |
+
+### AvatarList.Item
+
+| 参数 | 说明 | 类型 | 默认值 |
+| ---- | ------ | --------- | --- |
+| tips | 头像展示文案 | string | - |
+| src | 头像图片连接 | string | - |
+
diff --git a/src/components/Charts/Bar.vue b/src/components/Charts/Bar.vue
new file mode 100644
index 0000000..4482845
--- /dev/null
+++ b/src/components/Charts/Bar.vue
@@ -0,0 +1,62 @@
+
+
+
{{ title }}
+
+
+
+
+
+
+
+
+
diff --git a/src/components/Charts/ChartCard.vue b/src/components/Charts/ChartCard.vue
new file mode 100644
index 0000000..fc1f425
--- /dev/null
+++ b/src/components/Charts/ChartCard.vue
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/Charts/Liquid.vue b/src/components/Charts/Liquid.vue
new file mode 100644
index 0000000..4019fb1
--- /dev/null
+++ b/src/components/Charts/Liquid.vue
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/Charts/MiniArea.vue b/src/components/Charts/MiniArea.vue
new file mode 100644
index 0000000..58fe92c
--- /dev/null
+++ b/src/components/Charts/MiniArea.vue
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
diff --git a/src/components/Charts/MiniBar.vue b/src/components/Charts/MiniBar.vue
new file mode 100644
index 0000000..beac404
--- /dev/null
+++ b/src/components/Charts/MiniBar.vue
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
diff --git a/src/components/Charts/MiniProgress.vue b/src/components/Charts/MiniProgress.vue
new file mode 100644
index 0000000..e691363
--- /dev/null
+++ b/src/components/Charts/MiniProgress.vue
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
diff --git a/src/components/Charts/MiniSmoothArea.vue b/src/components/Charts/MiniSmoothArea.vue
new file mode 100644
index 0000000..e5455c2
--- /dev/null
+++ b/src/components/Charts/MiniSmoothArea.vue
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
diff --git a/src/components/Charts/Radar.vue b/src/components/Charts/Radar.vue
new file mode 100644
index 0000000..5ee88ad
--- /dev/null
+++ b/src/components/Charts/Radar.vue
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/Charts/RankList.vue b/src/components/Charts/RankList.vue
new file mode 100644
index 0000000..afb56a1
--- /dev/null
+++ b/src/components/Charts/RankList.vue
@@ -0,0 +1,77 @@
+
+
+
{{ title }}
+
+ -
+ {{ index + 1 }}
+ {{ item.name }}
+ {{ item.total }}
+
+
+
+
+
+
+
+
diff --git a/src/components/Charts/TagCloud.vue b/src/components/Charts/TagCloud.vue
new file mode 100644
index 0000000..74d1b3f
--- /dev/null
+++ b/src/components/Charts/TagCloud.vue
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/components/Charts/TransferBar.vue b/src/components/Charts/TransferBar.vue
new file mode 100644
index 0000000..7f96f0b
--- /dev/null
+++ b/src/components/Charts/TransferBar.vue
@@ -0,0 +1,64 @@
+
+
+
{{ title }}
+
+
+
+
+
+
+
+
+
diff --git a/src/components/Charts/Trend.vue b/src/components/Charts/Trend.vue
new file mode 100644
index 0000000..2dce37e
--- /dev/null
+++ b/src/components/Charts/Trend.vue
@@ -0,0 +1,82 @@
+
+
+ {{ term }}
+
{{ rate }}%
+
+
+
+
+
+
+
diff --git a/src/components/Charts/chart.less b/src/components/Charts/chart.less
new file mode 100644
index 0000000..f79e17d
--- /dev/null
+++ b/src/components/Charts/chart.less
@@ -0,0 +1,13 @@
+.antv-chart-mini {
+ position: relative;
+ width: 100%;
+
+ .chart-wrapper {
+ position: absolute;
+ bottom: -28px;
+ width: 100%;
+
+ /* margin: 0 -5px;
+ overflow: hidden; */
+ }
+}
diff --git a/src/components/Charts/smooth.area.less b/src/components/Charts/smooth.area.less
new file mode 100644
index 0000000..d31ff2f
--- /dev/null
+++ b/src/components/Charts/smooth.area.less
@@ -0,0 +1,14 @@
+@import '../index';
+
+@smoothArea-prefix-cls: ~"@{ant-pro-prefix}-smooth-area";
+
+.@{smoothArea-prefix-cls} {
+ position: relative;
+ width: 100%;
+
+ .chart-wrapper {
+ position: absolute;
+ bottom: -28px;
+ width: 100%;
+ }
+}
diff --git a/src/components/CommonButton.vue b/src/components/CommonButton.vue
new file mode 100644
index 0000000..2c4383b
--- /dev/null
+++ b/src/components/CommonButton.vue
@@ -0,0 +1,94 @@
+
+
+
+
+
+
+
diff --git a/src/components/Dialog.js b/src/components/Dialog.js
new file mode 100644
index 0000000..78e95b2
--- /dev/null
+++ b/src/components/Dialog.js
@@ -0,0 +1,113 @@
+import Modal from 'ant-design-vue/es/modal'
+export default (Vue) => {
+ function dialog (component, componentProps, modalProps) {
+ const _vm = this
+ modalProps = modalProps || {}
+ if (!_vm || !_vm._isVue) {
+ return
+ }
+ let dialogDiv = document.querySelector('body>div[type=dialog]')
+ if (!dialogDiv) {
+ dialogDiv = document.createElement('div')
+ dialogDiv.setAttribute('type', 'dialog')
+ document.body.appendChild(dialogDiv)
+ }
+
+ const handle = function (checkFunction, afterHandel) {
+ if (checkFunction instanceof Function) {
+ const res = checkFunction()
+ if (res instanceof Promise) {
+ res.then(c => {
+ c && afterHandel()
+ })
+ } else {
+ res && afterHandel()
+ }
+ } else {
+ // checkFunction && afterHandel()
+ checkFunction || afterHandel()
+ }
+ }
+
+ const dialogInstance = new Vue({
+ data () {
+ return {
+ visible: true
+ }
+ },
+ router: _vm.$router,
+ store: _vm.$store,
+ mounted () {
+ this.$on('close', (v) => {
+ this.handleClose()
+ })
+ },
+ methods: {
+ handleClose () {
+ handle(this.$refs._component.onCancel, () => {
+ this.visible = false
+ this.$refs._component.$emit('close')
+ this.$refs._component.$emit('cancel')
+ dialogInstance.$destroy()
+ })
+ },
+ handleOk () {
+ handle(this.$refs._component.onOK || this.$refs._component.onOk, () => {
+ this.visible = false
+ this.$refs._component.$emit('close')
+ this.$refs._component.$emit('ok')
+ dialogInstance.$destroy()
+ })
+ }
+ },
+ render: function (h) {
+ const that = this
+ const modalModel = modalProps && modalProps.model
+ if (modalModel) {
+ delete modalProps.model
+ }
+ const ModalProps = Object.assign({}, modalModel && { model: modalModel } || {}, {
+ attrs: Object.assign({}, {
+ ...(modalProps.attrs || modalProps)
+ }, {
+ visible: this.visible
+ }),
+ on: Object.assign({}, {
+ ...(modalProps.on || modalProps)
+ }, {
+ ok: () => {
+ that.handleOk()
+ },
+ cancel: () => {
+ that.handleClose()
+ }
+ })
+ })
+
+ const componentModel = componentProps && componentProps.model
+ if (componentModel) {
+ delete componentProps.model
+ }
+ const ComponentProps = Object.assign({}, componentModel && { model: componentModel } || {}, {
+ ref: '_component',
+ attrs: Object.assign({}, {
+ ...((componentProps && componentProps.attrs) || componentProps)
+ }),
+ on: Object.assign({}, {
+ ...((componentProps && componentProps.on) || componentProps)
+ })
+ })
+
+ return h(Modal, ModalProps, [h(component, ComponentProps)])
+ }
+ }).$mount(dialogDiv)
+ }
+
+ Object.defineProperty(Vue.prototype, '$dialog', {
+ get: () => {
+ return function () {
+ dialog.apply(this, arguments)
+ }
+ }
+ })
+}
diff --git a/src/components/DirectoryTree.vue b/src/components/DirectoryTree.vue
new file mode 100644
index 0000000..dadbf79
--- /dev/null
+++ b/src/components/DirectoryTree.vue
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+ {{ title }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/Editor/QuillEditor.vue b/src/components/Editor/QuillEditor.vue
new file mode 100644
index 0000000..9a041e5
--- /dev/null
+++ b/src/components/Editor/QuillEditor.vue
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/Editor/WangEditor.vue b/src/components/Editor/WangEditor.vue
new file mode 100644
index 0000000..d9c71c7
--- /dev/null
+++ b/src/components/Editor/WangEditor.vue
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
diff --git a/src/components/Ellipsis/Ellipsis.vue b/src/components/Ellipsis/Ellipsis.vue
new file mode 100644
index 0000000..5d59200
--- /dev/null
+++ b/src/components/Ellipsis/Ellipsis.vue
@@ -0,0 +1,64 @@
+
diff --git a/src/components/Ellipsis/index.js b/src/components/Ellipsis/index.js
new file mode 100644
index 0000000..91e3ff4
--- /dev/null
+++ b/src/components/Ellipsis/index.js
@@ -0,0 +1,3 @@
+import Ellipsis from './Ellipsis'
+
+export default Ellipsis
diff --git a/src/components/Ellipsis/index.md b/src/components/Ellipsis/index.md
new file mode 100644
index 0000000..f528ac7
--- /dev/null
+++ b/src/components/Ellipsis/index.md
@@ -0,0 +1,38 @@
+# Ellipsis 文本自动省略号
+
+文本过长自动处理省略号,支持按照文本长度和最大行数两种方式截取。
+
+
+
+引用方式:
+
+```javascript
+import Ellipsis from '@/components/Ellipsis'
+
+export default {
+ components: {
+ Ellipsis
+ }
+}
+```
+
+
+
+## 代码演示 [demo](https://pro.loacg.com/test/home)
+
+```html
+
+ There were injuries alleged in three cases in 2015, and a
+ 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.
+
+```
+
+
+
+## API
+
+
+参数 | 说明 | 类型 | 默认值
+----|------|-----|------
+tooltip | 移动到文本展示完整内容的提示 | boolean | -
+length | 在按照长度截取下的文本最大字符数,超过则截取省略 | number | -
\ No newline at end of file
diff --git a/src/components/FooterToolbar/FooterToolBar.vue b/src/components/FooterToolbar/FooterToolBar.vue
new file mode 100644
index 0000000..ea07123
--- /dev/null
+++ b/src/components/FooterToolbar/FooterToolBar.vue
@@ -0,0 +1,47 @@
+
+
+
+ {{ extra }}
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/FooterToolbar/index.js b/src/components/FooterToolbar/index.js
new file mode 100644
index 0000000..a0bf145
--- /dev/null
+++ b/src/components/FooterToolbar/index.js
@@ -0,0 +1,4 @@
+import FooterToolBar from './FooterToolBar'
+import './index.less'
+
+export default FooterToolBar
diff --git a/src/components/FooterToolbar/index.less b/src/components/FooterToolbar/index.less
new file mode 100644
index 0000000..3f49436
--- /dev/null
+++ b/src/components/FooterToolbar/index.less
@@ -0,0 +1,23 @@
+@import '../index';
+
+@footer-toolbar-prefix-cls: ~"@{ant-pro-prefix}-footer-toolbar";
+
+.@{footer-toolbar-prefix-cls} {
+ position: fixed;
+ right: 0;
+ bottom: 0;
+ z-index: 9;
+ width: 100%;
+ height: 56px;
+ padding: 0 24px;
+ line-height: 56px;
+ background: #fff;
+ box-shadow: 0 -1px 2px rgb(0 0 0 / 3%);
+ border-top: 1px solid #e8e8e8;
+
+ &::after {
+ display: block;
+ clear: both;
+ content: '';
+ }
+}
diff --git a/src/components/FooterToolbar/index.md b/src/components/FooterToolbar/index.md
new file mode 100644
index 0000000..c1aec2c
--- /dev/null
+++ b/src/components/FooterToolbar/index.md
@@ -0,0 +1,48 @@
+# FooterToolbar 底部工具栏
+
+固定在底部的工具栏。
+
+
+
+## 何时使用
+
+固定在内容区域的底部,不随滚动条移动,常用于长页面的数据搜集和提交工作。
+
+
+
+引用方式:
+
+```javascript
+import FooterToolBar from '@/components/FooterToolbar'
+
+export default {
+ components: {
+ FooterToolBar
+ }
+}
+```
+
+
+
+## 代码演示
+
+```html
+
+ 提交
+
+```
+或
+```html
+
+ 提交
+
+```
+
+
+## API
+
+参数 | 说明 | 类型 | 默认值
+----|------|-----|------
+children (slot) | 工具栏内容,向右对齐 | - | -
+extra | 额外信息,向左对齐 | String, Object | -
+
diff --git a/src/components/GlobalFooter/index.vue b/src/components/GlobalFooter/index.vue
new file mode 100644
index 0000000..c81d0a9
--- /dev/null
+++ b/src/components/GlobalFooter/index.vue
@@ -0,0 +1,19 @@
+
+
+
+
+
diff --git a/src/components/GlobalHeader/AvatarDropdown.vue b/src/components/GlobalHeader/AvatarDropdown.vue
new file mode 100644
index 0000000..b89cd39
--- /dev/null
+++ b/src/components/GlobalHeader/AvatarDropdown.vue
@@ -0,0 +1,98 @@
+
+
+
+
+ {{ currentUser.nickName }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/GlobalHeader/RightContent.vue b/src/components/GlobalHeader/RightContent.vue
new file mode 100644
index 0000000..fe5e804
--- /dev/null
+++ b/src/components/GlobalHeader/RightContent.vue
@@ -0,0 +1,56 @@
+
+
+
+
+
diff --git a/src/components/IconSelector/IconSelector.vue b/src/components/IconSelector/IconSelector.vue
new file mode 100644
index 0000000..810d297
--- /dev/null
+++ b/src/components/IconSelector/IconSelector.vue
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
diff --git a/src/components/IconSelector/README.md b/src/components/IconSelector/README.md
new file mode 100644
index 0000000..503095d
--- /dev/null
+++ b/src/components/IconSelector/README.md
@@ -0,0 +1,48 @@
+IconSelector
+====
+
+> 图标选择组件,常用于为某一个数据设定一个图标时使用
+> eg: 设定菜单列表时,为每个菜单设定一个图标
+
+该组件由 [@Saraka](https://github.com/saraka-tsukai) 封装
+
+
+
+### 使用方式
+
+```vue
+
+
+
+
+
+
+
+```
+
+
+
+### 事件
+
+
+| 名称 | 说明 | 类型 | 默认值 |
+| ------ | -------------------------- | ------ | ------ |
+| change | 当改变了 `icon` 选中项触发 | String | - |
diff --git a/src/components/IconSelector/icons.js b/src/components/IconSelector/icons.js
new file mode 100644
index 0000000..920f464
--- /dev/null
+++ b/src/components/IconSelector/icons.js
@@ -0,0 +1,36 @@
+/**
+ * 增加新的图标时,请遵循以下数据结构
+ * Adding new icon please follow the data structure below
+ */
+export default [
+ {
+ key: 'directional',
+ title: '方向性图标',
+ 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']
+ },
+ {
+ key: 'suggested',
+ title: '提示建议性图标',
+ 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']
+ },
+ {
+ key: 'editor',
+ title: '编辑类图标',
+ 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']
+ },
+ {
+ key: 'data',
+ title: '数据类图标',
+ icons: ['area-chart', 'pie-chart', 'bar-chart', 'dot-chart', 'line-chart', 'radar-chart', 'heat-map', 'fall', 'rise', 'stock', 'box-plot', 'fund', 'sliders']
+ },
+ {
+ key: 'brand_logo',
+ title: '网站通用图标',
+ 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']
+ },
+ {
+ key: 'application',
+ title: '品牌和标识',
+ 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']
+ }
+]
diff --git a/src/components/IconSelector/index.js b/src/components/IconSelector/index.js
new file mode 100644
index 0000000..2d27d70
--- /dev/null
+++ b/src/components/IconSelector/index.js
@@ -0,0 +1,2 @@
+import IconSelector from './IconSelector'
+export default IconSelector
diff --git a/src/components/ImportModal.vue b/src/components/ImportModal.vue
new file mode 100644
index 0000000..122489a
--- /dev/null
+++ b/src/components/ImportModal.vue
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+ 下载模板
+
+
+
+
+
+
+ 导入成功:{{ resultData.success }} 条
+ 导入失败:{{ resultData.failure }} 条
+
+
+ 导入失败原因:
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/MultiTab/MultiTab.vue b/src/components/MultiTab/MultiTab.vue
new file mode 100644
index 0000000..bfb6e57
--- /dev/null
+++ b/src/components/MultiTab/MultiTab.vue
@@ -0,0 +1,162 @@
+
diff --git a/src/components/MultiTab/events.js b/src/components/MultiTab/events.js
new file mode 100644
index 0000000..b0230b5
--- /dev/null
+++ b/src/components/MultiTab/events.js
@@ -0,0 +1,2 @@
+import Vue from 'vue'
+export default new Vue()
diff --git a/src/components/MultiTab/index.js b/src/components/MultiTab/index.js
new file mode 100644
index 0000000..02a1c77
--- /dev/null
+++ b/src/components/MultiTab/index.js
@@ -0,0 +1,40 @@
+import events from './events'
+import MultiTab from './MultiTab'
+import './index.less'
+
+const api = {
+ /**
+ * open new tab on route fullPath
+ * @param config
+ */
+ open: function (config) {
+ events.$emit('open', config)
+ },
+ rename: function (key, name) {
+ events.$emit('rename', { key: key, name: name })
+ },
+ /**
+ * close current page
+ */
+ closeCurrentPage: function () {
+ this.close()
+ },
+ /**
+ * close route fullPath tab
+ * @param config
+ */
+ close: function (config) {
+ events.$emit('close', config)
+ }
+}
+
+MultiTab.install = function (Vue) {
+ if (Vue.prototype.$multiTab) {
+ return
+ }
+ api.instance = events
+ Vue.prototype.$multiTab = api
+ Vue.component('multi-tab', MultiTab)
+}
+
+export default MultiTab
diff --git a/src/components/MultiTab/index.less b/src/components/MultiTab/index.less
new file mode 100644
index 0000000..d9d9fa6
--- /dev/null
+++ b/src/components/MultiTab/index.less
@@ -0,0 +1,25 @@
+@import '../index';
+
+@multi-tab-prefix-cls: ~"@{ant-pro-prefix}-multi-tab";
+@multi-tab-wrapper-prefix-cls: ~"@{ant-pro-prefix}-multi-tab-wrapper";
+
+/*
+.topmenu .@{multi-tab-prefix-cls} {
+ max-width: 1200px;
+ margin: -23px auto 24px auto;
+}
+*/
+.@{multi-tab-prefix-cls} {
+ margin: -23px -24px 24px;
+ background: #fff;
+}
+
+.topmenu .@{multi-tab-wrapper-prefix-cls} {
+ max-width: 1200px;
+ margin: 0 auto;
+}
+
+.topmenu.content-width-Fluid .@{multi-tab-wrapper-prefix-cls} {
+ max-width: 100%;
+ margin: 0 auto;
+}
diff --git a/src/components/NProgress/nprogress.less b/src/components/NProgress/nprogress.less
new file mode 100644
index 0000000..6593834
--- /dev/null
+++ b/src/components/NProgress/nprogress.less
@@ -0,0 +1,70 @@
+@import url('../index.less');
+
+/* Make clicks pass-through */
+#nprogress {
+ pointer-events: none;
+}
+
+#nprogress .bar {
+ position: fixed;
+ top: 0;
+ left: 0;
+ z-index: 1031;
+ width: 100%;
+ height: 2px;
+ background: @primary-color;
+}
+
+/* Fancy blur effect */
+#nprogress .peg {
+ position: absolute;
+ right: 0;
+ display: block;
+ width: 100px;
+ height: 100%;
+ opacity: 1;
+ transform: rotate(3deg) translate(0, -4px);
+ transform: rotate(3deg) translate(0, -4px);
+ transform: rotate(3deg) translate(0, -4px);
+ box-shadow: 0 0 10px @primary-color, 0 0 5px @primary-color;
+}
+
+/* Remove these to get rid of the spinner */
+#nprogress .spinner {
+ position: fixed;
+ top: 15px;
+ right: 15px;
+ z-index: 1031;
+ display: block;
+}
+
+#nprogress .spinner-icon {
+ width: 18px;
+ height: 18px;
+ box-sizing: border-box;
+ border: solid 2px transparent;
+ border-top-color: @primary-color;
+ border-left-color: @primary-color;
+ border-radius: 50%;
+ animation: nprogress-spinner 400ms linear infinite;
+ animation: nprogress-spinner 400ms linear infinite;
+}
+
+.nprogress-custom-parent {
+ position: relative;
+ overflow: hidden;
+}
+
+.nprogress-custom-parent #nprogress .spinner,
+.nprogress-custom-parent #nprogress .bar {
+ position: absolute;
+}
+
+@keyframes nprogress-spinner {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+}
+@keyframes nprogress-spinner {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+}
diff --git a/src/components/NoticeIcon/NoticeIcon.vue b/src/components/NoticeIcon/NoticeIcon.vue
new file mode 100644
index 0000000..8ae1c80
--- /dev/null
+++ b/src/components/NoticeIcon/NoticeIcon.vue
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 123
+
+
+ 123
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/NoticeIcon/index.js b/src/components/NoticeIcon/index.js
new file mode 100644
index 0000000..659b9ec
--- /dev/null
+++ b/src/components/NoticeIcon/index.js
@@ -0,0 +1,2 @@
+import NoticeIcon from './NoticeIcon'
+export default NoticeIcon
diff --git a/src/components/NumberInfo/NumberInfo.vue b/src/components/NumberInfo/NumberInfo.vue
new file mode 100644
index 0000000..b33036a
--- /dev/null
+++ b/src/components/NumberInfo/NumberInfo.vue
@@ -0,0 +1,54 @@
+
+
+
+ {{ typeof subTitle === 'string' ? subTitle : subTitle() }}
+
+
+ {{ total }}
+
+ {{ subTotal }}
+
+
+
+
+
+
+
+
+
diff --git a/src/components/NumberInfo/index.js b/src/components/NumberInfo/index.js
new file mode 100644
index 0000000..659a2f3
--- /dev/null
+++ b/src/components/NumberInfo/index.js
@@ -0,0 +1,3 @@
+import NumberInfo from './NumberInfo'
+
+export default NumberInfo
diff --git a/src/components/NumberInfo/index.less b/src/components/NumberInfo/index.less
new file mode 100644
index 0000000..6e5b62f
--- /dev/null
+++ b/src/components/NumberInfo/index.less
@@ -0,0 +1,57 @@
+@import '../index';
+
+@numberInfo-prefix-cls: ~"@{ant-pro-prefix}-number-info";
+
+.@{numberInfo-prefix-cls} {
+ .ant-pro-number-info-subtitle {
+ height: 22px;
+ overflow: hidden;
+ font-size: @font-size-base;
+ line-height: 22px;
+ color: @text-color-secondary;
+ text-overflow: ellipsis;
+ word-break: break-all;
+ white-space: nowrap;
+ }
+
+ .number-info-value {
+ margin-top: 4px;
+ overflow: hidden;
+ font-size: 0;
+ text-overflow: ellipsis;
+ word-break: break-all;
+ white-space: nowrap;
+
+ & > span {
+ display: inline-block;
+ height: 32px;
+ margin-right: 32px;
+ font-size: 24px;
+ line-height: 32px;
+ color: @heading-color;
+ }
+
+ .sub-total {
+ margin-right: 0;
+ font-size: @font-size-lg;
+ color: @text-color-secondary;
+ vertical-align: top;
+
+ i {
+ margin-left: 4px;
+ font-size: 12px;
+ transform: scale(.82);
+ }
+
+ :global {
+ .anticon-caret-up {
+ color: @red-6;
+ }
+
+ .anticon-caret-down {
+ color: @green-6;
+ }
+ }
+ }
+ }
+}
diff --git a/src/components/NumberInfo/index.md b/src/components/NumberInfo/index.md
new file mode 100644
index 0000000..147adc4
--- /dev/null
+++ b/src/components/NumberInfo/index.md
@@ -0,0 +1,43 @@
+# NumberInfo 数据文本
+
+常用在数据卡片中,用于突出展示某个业务数据。
+
+
+
+引用方式:
+
+```javascript
+import NumberInfo from '@/components/NumberInfo'
+
+export default {
+ components: {
+ NumberInfo
+ }
+}
+```
+
+
+
+## 代码演示 [demo](https://pro.loacg.com/test/home)
+
+```html
+
+```
+
+
+
+## API
+
+参数 | 说明 | 类型 | 默认值
+----|------|-----|------
+title | 标题 | ReactNode\|string | -
+subTitle | 子标题 | ReactNode\|string | -
+total | 总量 | ReactNode\|string | -
+subTotal | 子总量 | ReactNode\|string | -
+status | 增加状态 | 'up \| down' | -
+theme | 状态样式 | string | 'light'
+gap | 设置数字和描述之间的间距(像素)| number | 8
diff --git a/src/components/Other/CarbonAds.vue b/src/components/Other/CarbonAds.vue
new file mode 100644
index 0000000..32099c6
--- /dev/null
+++ b/src/components/Other/CarbonAds.vue
@@ -0,0 +1,62 @@
+
+
+
diff --git a/src/components/PageContainer/Index.vue b/src/components/PageContainer/Index.vue
new file mode 100644
index 0000000..285c5a8
--- /dev/null
+++ b/src/components/PageContainer/Index.vue
@@ -0,0 +1,102 @@
+
+
+
+
+
+
+
diff --git a/src/components/PageLoading/index.jsx b/src/components/PageLoading/index.jsx
new file mode 100644
index 0000000..af6d6d6
--- /dev/null
+++ b/src/components/PageLoading/index.jsx
@@ -0,0 +1,106 @@
+import { Spin } from 'ant-design-vue'
+
+export const PageLoading = {
+ name: 'PageLoading',
+ props: {
+ tip: {
+ type: String,
+ default: 'Loading..'
+ },
+ size: {
+ type: String,
+ default: 'large'
+ }
+ },
+ render () {
+ const style = {
+ textAlign: 'center',
+ background: 'rgba(0,0,0,0.6)',
+ position: 'fixed',
+ top: 0,
+ bottom: 0,
+ left: 0,
+ right: 0,
+ zIndex: 1100
+ }
+ const spinStyle = {
+ position: 'absolute',
+ left: '50%',
+ top: '40%',
+ transform: 'translate(-50%, -50%)'
+ }
+ return (
+
+
)
+ }
+}
+
+const version = '0.0.1'
+const loading = {}
+
+loading.newInstance = (Vue, options) => {
+ let loadingElement = document.querySelector('body>div[type=loading]')
+ if (!loadingElement) {
+ loadingElement = document.createElement('div')
+ loadingElement.setAttribute('type', 'loading')
+ loadingElement.setAttribute('class', 'ant-loading-wrapper')
+ document.body.appendChild(loadingElement)
+ }
+
+ const cdProps = Object.assign({ visible: false, size: 'large', tip: 'Loading...' }, options)
+
+ const instance = new Vue({
+ data () {
+ return {
+ ...cdProps
+ }
+ },
+ render () {
+ const { tip } = this
+ const props = {}
+ this.tip && (props.tip = tip)
+ if (this.visible) {
+ return
+ }
+ return null
+ }
+ }).$mount(loadingElement)
+
+ function update (config) {
+ const { visible, size, tip } = { ...cdProps, ...config }
+ instance.$set(instance, 'visible', visible)
+ if (tip) {
+ instance.$set(instance, 'tip', tip)
+ }
+ if (size) {
+ instance.$set(instance, 'size', size)
+ }
+ }
+
+ return {
+ instance,
+ update
+ }
+}
+
+const api = {
+ show: function (options) {
+ this.instance.update({ ...options, visible: true })
+ },
+ hide: function () {
+ this.instance.update({ visible: false })
+ }
+}
+
+const install = function (Vue, options) {
+ if (Vue.prototype.$loading) {
+ return
+ }
+ api.instance = loading.newInstance(Vue, options)
+ Vue.prototype.$loading = api
+}
+
+export default {
+ version,
+ install
+}
diff --git a/src/components/RangePicker.vue b/src/components/RangePicker.vue
new file mode 100644
index 0000000..9dabdd5
--- /dev/null
+++ b/src/components/RangePicker.vue
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
diff --git a/src/components/Search/GlobalSearch.jsx b/src/components/Search/GlobalSearch.jsx
new file mode 100644
index 0000000..bd9e604
--- /dev/null
+++ b/src/components/Search/GlobalSearch.jsx
@@ -0,0 +1,63 @@
+import { Select } from 'ant-design-vue'
+import './index.less'
+
+const GlobalSearch = {
+ name: 'GlobalSearch',
+ data () {
+ return {
+ visible: false
+ }
+ },
+ mounted () {
+ const keyboardHandle = (e) => {
+ e.preventDefault()
+ e.stopPropagation()
+ const { ctrlKey, shiftKey, altKey, keyCode } = e
+ console.log('keyCode:', e.keyCode, e)
+ // key is `K` and hold ctrl
+ if (keyCode === 75 && ctrlKey && !shiftKey && !altKey) {
+ this.visible = !this.visible
+ }
+ }
+ document.addEventListener('keydown', keyboardHandle)
+ },
+ render () {
+ const { visible } = this
+ const handleSearch = (e) => {
+ this.$emit('search', e)
+ }
+
+ const handleChange = (e) => {
+ this.$emit('change', e)
+ }
+ if (!visible) {
+ return null
+ }
+ return (
+
+
+
+
Open with Ctrl/⌘ + K
+
+
+ )
+ }
+}
+
+GlobalSearch.install = function (Vue) {
+ Vue.component(GlobalSearch.name, GlobalSearch)
+}
+
+export default GlobalSearch
diff --git a/src/components/Search/index.less b/src/components/Search/index.less
new file mode 100644
index 0000000..f8b51b5
--- /dev/null
+++ b/src/components/Search/index.less
@@ -0,0 +1,25 @@
+@import '~ant-design-vue/es/style/themes/default';
+
+.global-search-wrapper {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: @zindex-modal-mask;
+ background: @modal-mask-bg;
+
+ .global-search-box {
+ position: absolute;
+ top: 20%;
+ left: 50%;
+ width: 450px;
+ transform: translate(-50%, -50%);
+
+ .global-search-tips {
+ font-size: @font-size-lg;
+ color: @white;
+ text-align: right;
+ }
+ }
+}
diff --git a/src/components/SelectLang/index.jsx b/src/components/SelectLang/index.jsx
new file mode 100644
index 0000000..6115d8d
--- /dev/null
+++ b/src/components/SelectLang/index.jsx
@@ -0,0 +1,54 @@
+import './index.less'
+
+import { Icon, Menu, Dropdown } from 'ant-design-vue'
+import { i18nRender } from '@/locales'
+import i18nMixin from '@/store/i18n-mixin'
+
+const locales = ['zh-CN', 'en-US']
+const languageLabels = {
+ 'zh-CN': '简体中文',
+ 'en-US': 'English'
+}
+// eslint-disable-next-line
+const languageIcons = {
+ 'zh-CN': '🇨🇳',
+ 'en-US': '🇺🇸'
+}
+
+const SelectLang = {
+ props: {
+ prefixCls: {
+ type: String,
+ default: 'ant-pro-drop-down'
+ }
+ },
+ name: 'SelectLang',
+ mixins: [i18nMixin],
+ render () {
+ const { prefixCls } = this
+ const changeLang = ({ key }) => {
+ this.setLang(key)
+ }
+ const langMenu = (
+
+ )
+ return (
+
+
+
+
+
+ )
+ }
+}
+
+export default SelectLang
diff --git a/src/components/SelectLang/index.less b/src/components/SelectLang/index.less
new file mode 100644
index 0000000..a71f69c
--- /dev/null
+++ b/src/components/SelectLang/index.less
@@ -0,0 +1,30 @@
+@import '~ant-design-vue/es/style/themes/default';
+
+@header-menu-prefix-cls: ~'@{ant-prefix}-pro-header-menu';
+@header-drop-down-prefix-cls: ~'@{ant-prefix}-pro-drop-down';
+
+.@{header-menu-prefix-cls} {
+ .anticon {
+ margin-right: 8px;
+ }
+
+ .ant-dropdown-menu-item {
+ min-width: 160px;
+ }
+}
+
+.@{header-drop-down-prefix-cls} {
+ line-height: @layout-header-height;
+ vertical-align: top;
+ cursor: pointer;
+
+ > i {
+ font-size: 16px !important;
+ transform: none !important;
+
+ svg {
+ position: relative;
+ top: -1px;
+ }
+ }
+}
diff --git a/src/components/SettingDrawer/SettingDrawer.vue b/src/components/SettingDrawer/SettingDrawer.vue
new file mode 100644
index 0000000..a21e96c
--- /dev/null
+++ b/src/components/SettingDrawer/SettingDrawer.vue
@@ -0,0 +1,343 @@
+
+
+
+
+
+
+
整体风格设置
+
+
+
+
+ 暗色菜单风格
+
+
+
+
+
+
+
+
+
+ 亮色菜单风格
+
+
+
+
+
+
+
+
+
+
+
主题色
+
+
+
+
+ {{ item.key }}
+
+
+
+
+
+
+
+
+
+
+
+
导航模式
+
+
+
+
+ 侧边栏导航
+
+
+
+
+
+
+
+
+
+ 顶部栏导航
+
+
+
+
+
+
+
+
+
+
+
+
+ 该设定仅 [顶部栏导航] 时有效
+
+
+ 固定
+ 流式
+
+
+
+ 内容区域宽度
+
+
+
+
+
+ 固定 Header
+
+
+
+
+
+
+ 固定 Header 时可配置
+ 下滑时隐藏 Header
+
+
+
+
+
+
+ 固定侧边菜单
+
+
+
+
+
+
+
+
+
其他设置
+
+
+
+
+
+ 色弱模式
+
+
+
+
+
+ 多页签模式
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/SettingDrawer/SettingItem.vue b/src/components/SettingDrawer/SettingItem.vue
new file mode 100644
index 0000000..2b3b553
--- /dev/null
+++ b/src/components/SettingDrawer/SettingItem.vue
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
diff --git a/src/components/SettingDrawer/index.js b/src/components/SettingDrawer/index.js
new file mode 100644
index 0000000..8260f2d
--- /dev/null
+++ b/src/components/SettingDrawer/index.js
@@ -0,0 +1,2 @@
+import SettingDrawer from './SettingDrawer'
+export default SettingDrawer
diff --git a/src/components/SettingDrawer/settingConfig.js b/src/components/SettingDrawer/settingConfig.js
new file mode 100644
index 0000000..2cfab79
--- /dev/null
+++ b/src/components/SettingDrawer/settingConfig.js
@@ -0,0 +1,48 @@
+import message from 'ant-design-vue/es/message'
+// import defaultSettings from '../defaultSettings';
+import themeColor from './themeColor.js'
+
+// let lessNodesAppended
+const colorList = [
+ {
+ key: '薄暮', color: '#F5222D'
+ },
+ {
+ key: '火山', color: '#FA541C'
+ },
+ {
+ key: '日暮', color: '#FAAD14'
+ },
+ {
+ key: '明青', color: '#13C2C2'
+ },
+ {
+ key: '极光绿', color: '#52C41A'
+ },
+ {
+ key: '拂晓蓝(默认)', color: '#1890FF'
+ },
+ {
+ key: '极客蓝', color: '#2F54EB'
+ },
+ {
+ key: '酱紫', color: '#722ED1'
+ }
+]
+
+const updateTheme = newPrimaryColor => {
+ const hideMessage = message.loading('正在切换主题!', 0)
+ themeColor.changeColor(newPrimaryColor).finally(() => {
+ setTimeout(() => {
+ hideMessage()
+ }, 10)
+ })
+}
+
+const updateColorWeak = colorWeak => {
+ // document.body.className = colorWeak ? 'colorWeak' : '';
+ const app = document.body.querySelector('#app')
+ colorWeak ? app.classList.add('colorWeak') : app.classList.remove('colorWeak')
+}
+
+export { updateTheme, colorList, updateColorWeak }
diff --git a/src/components/SettingDrawer/themeColor.js b/src/components/SettingDrawer/themeColor.js
new file mode 100644
index 0000000..10dfbd4
--- /dev/null
+++ b/src/components/SettingDrawer/themeColor.js
@@ -0,0 +1,24 @@
+import client from 'webpack-theme-color-replacer/client'
+import generate from '@ant-design/colors/lib/generate'
+
+export default {
+ getAntdSerials (color) {
+ // 淡化(即less的tint)
+ const lightens = new Array(9).fill().map((t, i) => {
+ return client.varyColor.lighten(color, i / 10)
+ })
+ // colorPalette变换得到颜色值
+ const colorPalettes = generate(color)
+ const rgb = client.varyColor.toNum3(color.replace('#', '')).join(',')
+ return lightens.concat(colorPalettes).concat(rgb)
+ },
+ changeColor (newColor) {
+ var options = {
+ newColors: this.getAntdSerials(newColor), // new colors array, one-to-one corresponde with `matchColors`
+ changeUrl (cssUrl) {
+ return `/${cssUrl}` // while router is not `hash` mode, it needs absolute path
+ }
+ }
+ return client.changer.changeColor(options, Promise)
+ }
+}
diff --git a/src/components/StandardFormRow/StandardFormRow.vue b/src/components/StandardFormRow/StandardFormRow.vue
new file mode 100644
index 0000000..a4e261b
--- /dev/null
+++ b/src/components/StandardFormRow/StandardFormRow.vue
@@ -0,0 +1,122 @@
+
+
+
+ {{ title }}
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/StandardFormRow/index.js b/src/components/StandardFormRow/index.js
new file mode 100644
index 0000000..8155cc7
--- /dev/null
+++ b/src/components/StandardFormRow/index.js
@@ -0,0 +1,3 @@
+import StandardFormRow from './StandardFormRow'
+
+export default StandardFormRow
diff --git a/src/components/Table/README.md b/src/components/Table/README.md
new file mode 100644
index 0000000..e675c53
--- /dev/null
+++ b/src/components/Table/README.md
@@ -0,0 +1,341 @@
+Table 重封装组件说明
+====
+
+
+封装说明
+----
+
+> 基础的使用方式与 API 与 [官方版(Table)](https://vuecomponent.github.io/ant-design-vue/components/table-cn/) 本一致,在其基础上,封装了加载数据的方法。
+>
+> 你无需在你是用表格的页面进行分页逻辑处理,仅需向 Table 组件传递绑定 `:data="Promise"` 对象即可
+
+该 `table` 由 [@Saraka](https://github.com/saraka-tsukai) 完成封装
+
+
+例子1
+----
+(基础使用)
+
+```vue
+
+
+
+
+
+
+
+
+```
+
+
+
+例子2
+----
+
+(简单的表格,最后一列是各种操作)
+
+```vue
+
+
+
+ 编辑
+
+
+
+ 更多
+
+
+
+ 1st menu item
+
+
+ 2nd menu item
+
+
+ 3rd menu item
+
+
+
+
+
+
+
+
+```
+
+
+
+内置方法
+----
+
+通过 `this.$refs.table` 调用
+
+`this.$refs.table.refresh(true)` 刷新列表 (用户新增/修改数据后,重载列表数据)
+
+> 注意:要调用 `refresh(bool)` 需要给表格组件设定 `ref` 值
+>
+> `refresh()` 方法可以传一个 `bool` 值,当有传值 或值为 `true` 时,则刷新时会强制刷新到第一页(常用户页面 搜索 按钮进行搜索时,结果从第一页开始分页)
+
+
+内置属性
+----
+> 除去 `a-table` 自带属性外,还而外提供了一些额外属性属性
+
+
+| 属性 | 说明 | 类型 | 默认值 |
+| -------------- | ----------------------------------------------- | ----------------- | ------ |
+| alert | 设置是否显示表格信息栏 | [object, boolean] | null |
+| showPagination | 显示分页选择器,可传 'auto' \| boolean | [string, boolean] | 'auto' |
+| data | 加载数据方法 必须为 `Promise` 对象 **必须绑定** | Promise | - |
+
+
+`alert` 属性对象:
+
+```javascript
+alert: {
+ show: Boolean,
+ clear: [Function, Boolean]
+}
+```
+
+注意事项
+----
+
+> 你可能需要为了与后端提供的接口返回结果一致而去修改以下代码:
+> (需要注意的是,这里的修改是全局性的,意味着整个项目所有使用该 table 组件都需要遵守这个返回结果定义的字段。)
+>
+> 文档中的结构有可能由于组件 bug 进行修正而改动。实际修改请以当时最新版本为准
+
+修改 `@/components/table/index.js` 第 156 行起
+
+
+
+```javascript
+result.then(r => {
+ this.localPagination = this.showPagination && Object.assign({}, this.localPagination, {
+ current: r.pageNo, // 返回结果中的当前分页数
+ total: r.totalCount, // 返回结果中的总记录数
+ showSizeChanger: this.showSizeChanger,
+ pageSize: (pagination && pagination.pageSize) ||
+ this.localPagination.pageSize
+ }) || false
+ // 为防止删除数据后导致页面当前页面数据长度为 0 ,自动翻页到上一页
+ if (r.data.length === 0 && this.showPagination && this.localPagination.current > 1) {
+ this.localPagination.current--
+ this.loadData()
+ return
+ }
+
+ // 这里用于判断接口是否有返回 r.totalCount 且 this.showPagination = true 且 pageNo 和 pageSize 存在 且 totalCount 小于等于 pageNo * pageSize 的大小
+ // 当情况满足时,表示数据不满足分页大小,关闭 table 分页功能
+ try {
+ if ((['auto', true].includes(this.showPagination) && r.totalCount <= (r.pageNo * this.localPagination.pageSize))) {
+ this.localPagination.hideOnSinglePage = true
+ }
+ } catch (e) {
+ this.localPagination = false
+ }
+ console.log('loadData -> this.localPagination', this.localPagination)
+ this.localDataSource = r.data // 返回结果中的数组数据
+ this.localLoading = false
+ })
+```
+返回 JSON 例子:
+```json
+{
+ "message": "",
+ "result": {
+ "data": [{
+ id: 1,
+ cover: 'https://gw.alipayobjects.com/zos/rmsportal/WdGqmHpayyMjiEhcKoVE.png',
+ title: 'Alipay',
+ description: '那是一种内在的东西, 他们到达不了,也无法触及的',
+ status: 1,
+ updatedAt: '2018-07-26 00:00:00'
+ },
+ {
+ id: 2,
+ cover: 'https://gw.alipayobjects.com/zos/rmsportal/zOsKZmFRdUtvpqCImOVY.png',
+ title: 'Angular',
+ description: '希望是一个好东西,也许是最好的,好东西是不会消亡的',
+ status: 1,
+ updatedAt: '2018-07-26 00:00:00'
+ },
+ {
+ id: 3,
+ cover: 'https://gw.alipayobjects.com/zos/rmsportal/dURIMkkrRFpPgTuzkwnB.png',
+ title: 'Ant Design',
+ description: '城镇中有那么多的酒馆,她却偏偏走进了我的酒馆',
+ status: 1,
+ updatedAt: '2018-07-26 00:00:00'
+ },
+ {
+ id: 4,
+ cover: 'https://gw.alipayobjects.com/zos/rmsportal/sfjbOqnsXXJgNCjCzDBL.png',
+ title: 'HaveKion Pro',
+ description: '那时候我只会想自己想要什么,从不想自己拥有什么',
+ status: 1,
+ updatedAt: '2018-07-26 00:00:00'
+ },
+ {
+ id: 5,
+ cover: 'https://gw.alipayobjects.com/zos/rmsportal/siCrBXXhmvTQGWPNLBow.png',
+ title: 'Bootstrap',
+ description: '凛冬将至',
+ status: 1,
+ updatedAt: '2018-07-26 00:00:00'
+ },
+ {
+ id: 6,
+ cover: 'https://gw.alipayobjects.com/zos/rmsportal/ComBAopevLwENQdKWiIn.png',
+ title: 'Vue',
+ description: '生命就像一盒巧克力,结果往往出人意料',
+ status: 1,
+ updatedAt: '2018-07-26 00:00:00'
+ }
+ ],
+ "pageSize": 10,
+ "pageNo": 0,
+ "totalPage": 6,
+ "totalCount": 57
+ },
+ "status": 200,
+ "timestamp": 1534955098193
+}
+```
+
+
+
+更新时间
+----
+
+该文档最后更新于: 2019-06-23 PM 17:19
\ No newline at end of file
diff --git a/src/components/Table/index.js b/src/components/Table/index.js
new file mode 100644
index 0000000..a407a41
--- /dev/null
+++ b/src/components/Table/index.js
@@ -0,0 +1,325 @@
+import T from 'ant-design-vue/es/table/Table'
+import get from 'lodash.get'
+
+export default {
+ data () {
+ return {
+ needTotalList: [],
+
+ selectedRows: [],
+ selectedRowKeys: [],
+
+ localLoading: false,
+ localDataSource: [],
+ localPagination: Object.assign({}, this.pagination),
+
+ // 存储表格onchange时的filters, sorter对象
+ filters: {},
+ sorter: {}
+ }
+ },
+ props: Object.assign({}, T.props, {
+ rowKey: {
+ type: [String, Function],
+ default: 'key'
+ },
+ data: {
+ type: Function,
+ required: true
+ },
+ pageNum: {
+ type: Number,
+ default: 1
+ },
+ pageSize: {
+ type: Number,
+ default: 10
+ },
+ showSizeChanger: {
+ type: Boolean,
+ default: true
+ },
+ size: {
+ type: String,
+ default: 'default'
+ },
+ /**
+ * alert: {
+ * show: true,
+ * clear: Function
+ * }
+ */
+ alert: {
+ type: [Object, Boolean],
+ default: null
+ },
+ rowSelection: {
+ type: Object,
+ default: null
+ },
+ /** @Deprecated */
+ showAlertInfo: {
+ type: Boolean,
+ default: false
+ },
+ showPagination: {
+ type: String | Boolean,
+ default: 'auto'
+ },
+ /**
+ * enable page URI mode
+ *
+ * e.g:
+ * /users/1
+ * /users/2
+ * /users/3?queryParam=test
+ * ...
+ */
+ pageURI: {
+ type: Boolean,
+ default: false
+ }
+ }),
+ watch: {
+ 'localPagination.current' (val) {
+ this.pageURI && this.$router.push({
+ ...this.$route,
+ name: this.$route.name,
+ params: Object.assign({}, this.$route.params, {
+ pageNo: val
+ })
+ })
+ // change pagination, reset total data
+ this.needTotalList = this.initTotalList(this.columns)
+ this.selectedRowKeys = []
+ this.selectedRows = []
+ },
+ pageNum (val) {
+ Object.assign(this.localPagination, {
+ current: val
+ })
+ },
+ pageSize (val) {
+ Object.assign(this.localPagination, {
+ pageSize: val
+ })
+ },
+ showSizeChanger (val) {
+ Object.assign(this.localPagination, {
+ showSizeChanger: val
+ })
+ }
+ },
+ created () {
+ const { pageNo } = this.$route.params
+ const localPageNum = this.pageURI && (pageNo && parseInt(pageNo)) || this.pageNum
+ this.localPagination = ['auto', true].includes(this.showPagination) && Object.assign({}, this.localPagination, {
+ current: localPageNum,
+ pageSize: this.pageSize,
+ showSizeChanger: this.showSizeChanger
+ }) || false
+ this.needTotalList = this.initTotalList(this.columns)
+ this.loadData()
+ },
+ methods: {
+ /**
+ * 表格重新加载方法
+ * 如果参数为 true, 则强制刷新到第一页
+ * @param Boolean bool
+ */
+ refresh (bool = false) {
+ bool && (this.localPagination = Object.assign({}, {
+ current: 1, pageSize: this.pageSize
+ }))
+ this.loadData()
+ },
+ /**
+ * 加载数据方法
+ * @param {Object} pagination 分页选项器
+ * @param {Object} filters 过滤条件
+ * @param {Object} sorter 排序条件
+ */
+ loadData (pagination, filters = this.filters, sorter = this.sorter) {
+ this.filters = filters
+ this.sorter = sorter
+
+ this.localLoading = true
+ const parameter = Object.assign({
+ pageNo: (pagination && pagination.current) ||
+ this.showPagination && this.localPagination.current || this.pageNum,
+ pageSize: (pagination && pagination.pageSize) ||
+ this.showPagination && this.localPagination.pageSize || this.pageSize
+ },
+ (sorter && sorter.field && {
+ sortField: sorter.field
+ }) || {},
+ (sorter && sorter.order && {
+ sortOrder: sorter.order
+ }) || {}, {
+ ...filters
+ }
+ )
+ const result = this.data(parameter)
+ // 对接自己的通用数据接口需要修改下方代码中的 r.pageNo, r.totalCount, r.data
+ // eslint-disable-next-line
+ if ((typeof result === 'object' || typeof result === 'function') && typeof result.then === 'function') {
+ result.then(r => {
+ this.localPagination = this.showPagination && Object.assign({}, this.localPagination, {
+ current: r.pageNo, // 返回结果中的当前分页数
+ total: r.totalCount, // 返回结果中的总记录数
+ showSizeChanger: this.showSizeChanger,
+ pageSize: (pagination && pagination.pageSize) ||
+ this.localPagination.pageSize
+ }) || false
+ // 为防止删除数据后导致页面当前页面数据长度为 0 ,自动翻页到上一页
+ if (r.data.length === 0 && this.showPagination && this.localPagination.current > 1) {
+ this.localPagination.current--
+ this.loadData()
+ return
+ }
+
+ // 这里用于判断接口是否有返回 r.totalCount 且 this.showPagination = true 且 pageNo 和 pageSize 存在 且 totalCount 小于等于 pageNo * pageSize 的大小
+ // 当情况满足时,表示数据不满足分页大小,关闭 table 分页功能
+ try {
+ if ((['auto', true].includes(this.showPagination) && r.totalCount <= (r.pageNo * this.localPagination.pageSize))) {
+ this.localPagination.hideOnSinglePage = true
+ }
+ } catch (e) {
+ this.localPagination = false
+ }
+ this.localDataSource = r.data // 返回结果中的数组数据
+ })
+ .finally(() => {
+ this.localLoading = false
+ })
+ }
+ },
+ initTotalList (columns) {
+ const totalList = []
+ columns && columns instanceof Array && columns.forEach(column => {
+ if (column.needTotal) {
+ totalList.push({
+ ...column,
+ total: 0
+ })
+ }
+ })
+ return totalList
+ },
+ /**
+ * 用于更新已选中的列表数据 total 统计
+ * @param selectedRowKeys
+ * @param selectedRows
+ */
+ updateSelect (selectedRowKeys, selectedRows) {
+ this.selectedRows = selectedRows
+ this.selectedRowKeys = selectedRowKeys
+ const list = this.needTotalList
+ this.needTotalList = list.map(item => {
+ return {
+ ...item,
+ total: selectedRows.reduce((sum, val) => {
+ const total = sum + parseInt(get(val, item.dataIndex))
+ return isNaN(total) ? 0 : total
+ }, 0)
+ }
+ })
+ },
+ /**
+ * 清空 table 已选中项
+ */
+ clearSelected () {
+ if (this.rowSelection) {
+ this.rowSelection.onChange([], [])
+ this.updateSelect([], [])
+ }
+ },
+ /**
+ * 处理交给 table 使用者去处理 clear 事件时,内部选中统计同时调用
+ * @param callback
+ * @returns {*}
+ */
+ renderClear (callback) {
+ if (this.selectedRowKeys.length <= 0) return null
+ return (
+ {
+ callback()
+ this.clearSelected()
+ }}>清空
+ )
+ },
+ renderAlert () {
+ // 绘制统计列数据
+ const needTotalItems = this.needTotalList.map((item) => {
+ return (
+ {item.title}总计 {!item.customRender ? item.total : item.customRender(item.total)}
+ )
+ })
+
+ // 绘制 清空 按钮
+ const clearItem = (typeof this.alert.clear === 'boolean' && this.alert.clear) ? (
+ this.renderClear(this.clearSelected)
+ ) : (this.alert !== null && typeof this.alert.clear === 'function') ? (
+ this.renderClear(this.alert.clear)
+ ) : null
+
+ // 绘制 alert 组件
+ return (
+
+
+ 已选择: {this.selectedRows.length}
+ {needTotalItems}
+ {clearItem}
+
+
+ )
+ }
+ },
+
+ render () {
+ const props = {}
+ const localKeys = Object.keys(this.$data)
+ const showAlert = (typeof this.alert === 'object' && this.alert !== null && this.alert.show) && typeof this.rowSelection.selectedRowKeys !== 'undefined' || this.alert
+
+ Object.keys(T.props).forEach(k => {
+ const localKey = `local${k.substring(0, 1).toUpperCase()}${k.substring(1)}`
+ if (localKeys.includes(localKey)) {
+ props[k] = this[localKey]
+ return props[k]
+ }
+ if (k === 'rowSelection') {
+ if (showAlert && this.rowSelection) {
+ // 如果需要使用alert,则重新绑定 rowSelection 事件
+ props[k] = {
+ ...this.rowSelection,
+ selectedRows: this.selectedRows,
+ selectedRowKeys: this.selectedRowKeys,
+ onChange: (selectedRowKeys, selectedRows) => {
+ this.updateSelect(selectedRowKeys, selectedRows)
+ typeof this[k].onChange !== 'undefined' && this[k].onChange(selectedRowKeys, selectedRows)
+ }
+ }
+ return props[k]
+ } else if (!this.rowSelection) {
+ // 如果没打算开启 rowSelection 则清空默认的选择项
+ props[k] = null
+ return props[k]
+ }
+ }
+ this[k] && (props[k] = this[k])
+ return props[k]
+ })
+ const table = (
+ { this.$emit('expand', expanded, record) } }>
+ { Object.keys(this.$slots).map(name => ({this.$slots[name]})) }
+
+ )
+
+ return (
+
+ { showAlert ? this.renderAlert() : null }
+ { table }
+
+ )
+ }
+}
diff --git a/src/components/TagSelect/TagSelectOption.jsx b/src/components/TagSelect/TagSelectOption.jsx
new file mode 100644
index 0000000..b5ae799
--- /dev/null
+++ b/src/components/TagSelect/TagSelectOption.jsx
@@ -0,0 +1,45 @@
+import { Tag } from 'ant-design-vue'
+const { CheckableTag } = Tag
+
+export default {
+ name: 'TagSelectOption',
+ props: {
+ prefixCls: {
+ type: String,
+ default: 'ant-pro-tag-select-option'
+ },
+ value: {
+ type: [String, Number, Object],
+ default: ''
+ },
+ checked: {
+ type: Boolean,
+ default: false
+ }
+ },
+ data () {
+ return {
+ localChecked: this.checked || false
+ }
+ },
+ watch: {
+ 'checked' (val) {
+ this.localChecked = val
+ },
+ '$parent.items': {
+ handler: function (val) {
+ this.value && val.hasOwnProperty(this.value) && (this.localChecked = val[this.value])
+ },
+ deep: true
+ }
+ },
+ render () {
+ const { $slots, value } = this
+ const onChange = (checked) => {
+ this.$emit('change', { value, checked })
+ }
+ return (
+ {$slots.default}
+ )
+ }
+}
diff --git a/src/components/TagSelect/index.jsx b/src/components/TagSelect/index.jsx
new file mode 100644
index 0000000..af98ad7
--- /dev/null
+++ b/src/components/TagSelect/index.jsx
@@ -0,0 +1,113 @@
+import PropTypes from 'ant-design-vue/es/_util/vue-types'
+import Option from './TagSelectOption.jsx'
+import { filterEmpty } from '@/components/_util/util'
+
+export default {
+ Option,
+ name: 'TagSelect',
+ model: {
+ prop: 'checked',
+ event: 'change'
+ },
+ props: {
+ prefixCls: {
+ type: String,
+ default: 'ant-pro-tag-select'
+ },
+ defaultValue: {
+ type: PropTypes.array,
+ default: null
+ },
+ value: {
+ type: PropTypes.array,
+ default: null
+ },
+ expandable: {
+ type: Boolean,
+ default: false
+ },
+ hideCheckAll: {
+ type: Boolean,
+ default: false
+ }
+ },
+ data () {
+ return {
+ expand: false,
+ localCheckAll: false,
+ items: this.getItemsKey(filterEmpty(this.$slots.default)),
+ val: this.value || this.defaultValue || []
+ }
+ },
+ methods: {
+ onChange (checked) {
+ const key = Object.keys(this.items).filter(key => key === checked.value)
+ this.items[key] = checked.checked
+ const bool = Object.values(this.items).lastIndexOf(false)
+ if (bool === -1) {
+ this.localCheckAll = true
+ } else {
+ this.localCheckAll = false
+ }
+ },
+ onCheckAll (checked) {
+ Object.keys(this.items).forEach(v => {
+ this.items[v] = checked.checked
+ })
+ this.localCheckAll = checked.checked
+ },
+ getItemsKey (items) {
+ const totalItem = {}
+ items.forEach(item => {
+ totalItem[item.componentOptions.propsData && item.componentOptions.propsData.value] = false
+ })
+ return totalItem
+ },
+ // CheckAll Button
+ renderCheckAll () {
+ const props = {
+ on: {
+ change: (checked) => {
+ this.onCheckAll(checked)
+ checked.value = 'total'
+ this.$emit('change', checked)
+ }
+ }
+ }
+ const checkAllElement =
+ return !this.hideCheckAll && checkAllElement || null
+ },
+ // expandable
+ renderExpandable () {
+
+ },
+ // render option
+ renderTags (items) {
+ const listeners = {
+ change: (checked) => {
+ this.onChange(checked)
+ this.$emit('change', checked)
+ }
+ }
+
+ return items.map(vnode => {
+ const options = vnode.componentOptions
+ options.listeners = listeners
+ return vnode
+ })
+ }
+ },
+ render () {
+ const { $props: { prefixCls } } = this
+ const classString = {
+ [`${prefixCls}`]: true
+ }
+ const tagItems = filterEmpty(this.$slots.default)
+ return (
+
+ {this.renderCheckAll()}
+ {this.renderTags(tagItems)}
+
+ )
+ }
+}
diff --git a/src/components/TextArea/index.jsx b/src/components/TextArea/index.jsx
new file mode 100644
index 0000000..00aeb2f
--- /dev/null
+++ b/src/components/TextArea/index.jsx
@@ -0,0 +1,69 @@
+import './style.less'
+import { getStrFullLength, cutStrByFullLength } from '../_util/util'
+import Input from 'ant-design-vue/es/input'
+const TextArea = Input.TextArea
+
+export default {
+ name: 'LimitTextArea',
+ model: {
+ prop: 'value',
+ event: 'change'
+ },
+ props: Object.assign({}, TextArea.props, {
+ prefixCls: {
+ type: String,
+ default: 'ant-textarea-limit'
+ },
+ // eslint-disable-next-line
+ value: {
+ type: String
+ },
+ limit: {
+ type: Number,
+ default: 200
+ }
+ }),
+ data () {
+ return {
+ currentLimit: 0
+ }
+ },
+ watch: {
+ value (val) {
+ this.calcLimitNum(val)
+ }
+ },
+ created () {
+ this.calcLimitNum(this.value)
+ },
+ methods: {
+ handleChange (e) {
+ const value = e.target.value
+ const len = getStrFullLength(value)
+ if (len <= this.limit) {
+ this.currentLimit = len
+ this.$emit('change', value)
+ return
+ } else {
+ const str = cutStrByFullLength(value, this.limit)
+ this.currentLimit = getStrFullLength(str)
+ this.$emit('change', str)
+ }
+ console.error('limit out! currentLimit:', this.currentLimit)
+ },
+ calcLimitNum (val) {
+ const len = getStrFullLength(val)
+ this.currentLimit = len
+ }
+ },
+ render () {
+ const { prefixCls, ...props } = this.$props
+ return (
+
+
+ {this.currentLimit}/{this.limit}
+
+ )
+ }
+}
diff --git a/src/components/TextArea/style.less b/src/components/TextArea/style.less
new file mode 100644
index 0000000..ba544bf
--- /dev/null
+++ b/src/components/TextArea/style.less
@@ -0,0 +1,12 @@
+.ant-textarea-limit {
+ position: relative;
+
+ .limit {
+ position: absolute;
+ right: 10px;
+ bottom: 5px;
+ font-size: 12px;
+ color: #909399;
+ background: #fff;
+ }
+}
diff --git a/src/components/Tree/Tree.jsx b/src/components/Tree/Tree.jsx
new file mode 100644
index 0000000..e5a2a11
--- /dev/null
+++ b/src/components/Tree/Tree.jsx
@@ -0,0 +1,124 @@
+import { Menu, Icon, Input } from 'ant-design-vue'
+
+const { Item, ItemGroup, SubMenu } = Menu
+const { Search } = Input
+
+export default {
+ name: 'Tree',
+ props: {
+ dataSource: {
+ type: Array,
+ required: true
+ },
+ openKeys: {
+ type: Array,
+ default: () => []
+ },
+ search: {
+ type: Boolean,
+ default: false
+ }
+ },
+ created () {
+ this.localOpenKeys = this.openKeys.slice(0)
+ },
+ data () {
+ return {
+ localOpenKeys: []
+ }
+ },
+ methods: {
+ handlePlus (item) {
+ this.$emit('add', item)
+ },
+ handleTitleClick (...args) {
+ this.$emit('titleClick', { args })
+ },
+
+ renderSearch () {
+ return (
+
+ )
+ },
+ renderIcon (icon) {
+ return icon && () || null
+ },
+ renderMenuItem (item) {
+ return (
+ -
+ { this.renderIcon(item.icon) }
+ { item.title }
+ this.handlePlus(item) } }}>
+
+ )
+ },
+ renderItem (item) {
+ return item.children ? this.renderSubItem(item, item.key) : this.renderMenuItem(item, item.key)
+ },
+ renderItemGroup (item) {
+ const childrenItems = item.children.map(o => {
+ return this.renderItem(o, o.key)
+ })
+
+ return (
+
+
+ { item.title }
+
+
+
+ 新增
+ 合并
+ 移除
+
+
+
+ { childrenItems }
+
+ )
+ },
+ renderSubItem (item, key) {
+ const childrenItems = item.children && item.children.map(o => {
+ return this.renderItem(o, o.key)
+ })
+
+ const title = (
+
+ { this.renderIcon(item.icon) }
+ { item.title }
+
+ )
+
+ if (item.group) {
+ return this.renderItemGroup(item)
+ }
+ // titleClick={this.handleTitleClick(item)}
+ return (
+
+ { title }
+ { childrenItems }
+
+ )
+ }
+ },
+ render () {
+ const { dataSource, search } = this.$props
+
+ // this.localOpenKeys = openKeys.slice(0)
+ const list = dataSource.map(item => {
+ return this.renderItem(item)
+ })
+
+ return (
+
+ { search ? this.renderSearch() : null }
+
+
+ )
+ }
+}
diff --git a/src/components/Trend/Trend.vue b/src/components/Trend/Trend.vue
new file mode 100644
index 0000000..526e1cc
--- /dev/null
+++ b/src/components/Trend/Trend.vue
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
diff --git a/src/components/Trend/index.js b/src/components/Trend/index.js
new file mode 100644
index 0000000..9f14228
--- /dev/null
+++ b/src/components/Trend/index.js
@@ -0,0 +1,3 @@
+import Trend from './Trend.vue'
+
+export default Trend
diff --git a/src/components/Trend/index.less b/src/components/Trend/index.less
new file mode 100644
index 0000000..d02ac16
--- /dev/null
+++ b/src/components/Trend/index.less
@@ -0,0 +1,44 @@
+@import '../index';
+
+@trend-prefix-cls: ~"@{ant-pro-prefix}-trend";
+
+.@{trend-prefix-cls} {
+ display: inline-block;
+ font-size: @font-size-base;
+ line-height: 22px;
+
+ .up,
+ .down {
+ position: relative;
+ top: 1px;
+ margin-left: 4px;
+
+ i {
+ font-size: 12px;
+ transform: scale(.83);
+ }
+ }
+
+ .item-text {
+ display: inline-block;
+ margin-left: 8px;
+ color: rgb(0 0 0 / 85%);
+ }
+
+ .up {
+ color: @red-6;
+ }
+
+ .down {
+ top: -1px;
+ color: @green-6;
+ }
+
+ &.reverse-color .up {
+ color: @green-6;
+ }
+
+ &.reverse-color .down {
+ color: @red-6;
+ }
+}
diff --git a/src/components/Trend/index.md b/src/components/Trend/index.md
new file mode 100644
index 0000000..8881f0e
--- /dev/null
+++ b/src/components/Trend/index.md
@@ -0,0 +1,45 @@
+# Trend 趋势标记
+
+趋势符号,标记上升和下降趋势。通常用绿色代表“好”,红色代表“不好”,股票涨跌场景除外。
+
+
+
+引用方式:
+
+```javascript
+import Trend from '@/components/Trend'
+
+export default {
+ components: {
+ Trend
+ }
+}
+```
+
+
+
+## 代码演示 [demo](https://pro.loacg.com/test/home)
+
+```html
+5%
+```
+或
+```html
+
+ 工资
+ 5%
+
+```
+或
+```html
+5%
+```
+
+
+## API
+
+| 参数 | 说明 | 类型 | 默认值 |
+|----------|------------------------------------------|-------------|-------|
+| flag | 上升下降标识:`up|down` | string | - |
+| reverseColor | 颜色反转 | Boolean | false |
+
diff --git a/src/components/YearPicker.vue b/src/components/YearPicker.vue
new file mode 100644
index 0000000..13f5a26
--- /dev/null
+++ b/src/components/YearPicker.vue
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
diff --git a/src/components/_util/util.js b/src/components/_util/util.js
new file mode 100644
index 0000000..dd33231
--- /dev/null
+++ b/src/components/_util/util.js
@@ -0,0 +1,46 @@
+/**
+ * components util
+ */
+
+/**
+ * 清理空值,对象
+ * @param children
+ * @returns {*[]}
+ */
+export function filterEmpty (children = []) {
+ return children.filter(c => c.tag || (c.text && c.text.trim() !== ''))
+}
+
+/**
+ * 获取字符串长度,英文字符 长度1,中文字符长度2
+ * @param {*} str
+ */
+export const getStrFullLength = (str = '') =>
+ str.split('').reduce((pre, cur) => {
+ const charCode = cur.charCodeAt(0)
+ if (charCode >= 0 && charCode <= 128) {
+ return pre + 1
+ }
+ return pre + 2
+ }, 0)
+
+/**
+ * 截取字符串,根据 maxLength 截取后返回
+ * @param {*} str
+ * @param {*} maxLength
+ */
+export const cutStrByFullLength = (str = '', maxLength) => {
+ let showLength = 0
+ return str.split('').reduce((pre, cur) => {
+ const charCode = cur.charCodeAt(0)
+ if (charCode >= 0 && charCode <= 128) {
+ showLength += 1
+ } else {
+ showLength += 2
+ }
+ if (showLength <= maxLength) {
+ return pre + cur
+ }
+ return pre
+ }, '')
+}
diff --git a/src/components/form/DictSelect.vue b/src/components/form/DictSelect.vue
new file mode 100644
index 0000000..e8a27b1
--- /dev/null
+++ b/src/components/form/DictSelect.vue
@@ -0,0 +1,43 @@
+
+
+ {{ item.title }}
+
+
+
+
+
+
diff --git a/src/components/form/DirectoryTree.vue b/src/components/form/DirectoryTree.vue
new file mode 100644
index 0000000..9f57017
--- /dev/null
+++ b/src/components/form/DirectoryTree.vue
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
diff --git a/src/components/hivekion/DictSelect.vue b/src/components/hivekion/DictSelect.vue
new file mode 100644
index 0000000..e8a27b1
--- /dev/null
+++ b/src/components/hivekion/DictSelect.vue
@@ -0,0 +1,43 @@
+
+
+ {{ item.title }}
+
+
+
+
+
+
diff --git a/src/components/hivekion/HModal.vue b/src/components/hivekion/HModal.vue
new file mode 100644
index 0000000..f5097e5
--- /dev/null
+++ b/src/components/hivekion/HModal.vue
@@ -0,0 +1,221 @@
+
+
+
+
+
+
+
+ {{ title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/hivekion/index.js b/src/components/hivekion/index.js
new file mode 100644
index 0000000..1048cc3
--- /dev/null
+++ b/src/components/hivekion/index.js
@@ -0,0 +1,20 @@
+import HModal from './HModal'
+
+// import HChoseUser from './HChoseUser' // 人员选择
+// import HChoseUsers from './HChoseUsers' // 人员选择-文本域
+// import HDragModal from './DrapModal/index' // 弹窗拖拽
+// import HCropper from './HCropper' // 图片裁剪
+// import JFormContainer from './JFormContainer.vue'
+// import JPopup from './JPopup.vue'
+
+export default {
+ install (Vue) {
+ // Vue.component('JFormContainer', JFormContainer)
+ // Vue.component('JPopup', JPopup)
+ Vue.component('HModal', HModal)
+ // Vue.component('HDragModal', HDragModal)
+ // Vue.component('HChoseUser', HChoseUser)
+ // Vue.component('HChoseUsers', HChoseUsers)
+ // Vue.component('HCropper', HCropper)
+ }
+}
diff --git a/src/components/hivekion/utils/props-util.js b/src/components/hivekion/utils/props-util.js
new file mode 100644
index 0000000..91983cf
--- /dev/null
+++ b/src/components/hivekion/utils/props-util.js
@@ -0,0 +1,109 @@
+/**
+ * 该文件截取自 "ant-design-vue/es/_util/props-util.js" 文件,并对其做出特殊修改
+ */
+function classNames () {
+ const classes = []
+
+ for (let i = 0; i < arguments.length; i++) {
+ const arg = arguments[i]
+ if (!arg) continue
+ const argType = typeof arg
+ if (argType === 'string' || argType === 'number') {
+ classes.push(arg)
+ } else if (Array.isArray(arg) && arg.length) {
+ const inner = classNames.apply(null, arg)
+ if (inner) {
+ classes.push(inner)
+ }
+ } else if (argType === 'object') {
+ for (const key in arg) {
+ if (arg.hasOwnProperty(key) && arg[key]) {
+ classes.push(key)
+ }
+ }
+ }
+ }
+ return classes.join(' ')
+}
+const camelizeRE = /-(\w)/g
+
+function camelize (str) {
+ return str.replace(camelizeRE, (_, c) => (c ? c.toUpperCase() : ''))
+}
+
+function objectCamelize (obj) {
+ const res = {}
+ Object.keys(obj).forEach(k => (res[camelize(k)] = obj[k]))
+ return res
+}
+
+function parseStyleText (cssText = '', camel) {
+ const res = {}
+ const listDelimiter = /;(?![^(]*\))/g
+ const propertyDelimiter = /:(.+)/
+ cssText.split(listDelimiter).forEach(function (item) {
+ if (item) {
+ const tmp = item.split(propertyDelimiter)
+ if (tmp.length > 1) {
+ const k = camel ? camelize(tmp[0].trim()) : tmp[0].trim()
+ res[k] = tmp[1].trim()
+ }
+ }
+ })
+ return res
+}
+
+export function getClass (ele) {
+ let data = {}
+ if (ele.data) {
+ data = ele.data
+ } else if (ele.$vnode && ele.$vnode.data) {
+ data = ele.$vnode.data
+ }
+ const tempCls = data.class || {}
+ const staticClass = data.staticClass
+ let cls = {}
+ staticClass &&
+ staticClass.split(' ').forEach(c => {
+ cls[c.trim()] = true
+ })
+ if (typeof tempCls === 'string') {
+ tempCls.split(' ').forEach(c => {
+ cls[c.trim()] = true
+ })
+ } else if (Array.isArray(tempCls)) {
+ classNames(tempCls)
+ .split(' ')
+ .forEach(c => {
+ cls[c.trim()] = true
+ })
+ } else {
+ cls = { ...cls, ...tempCls }
+ }
+ return cls
+}
+
+export function getStyle (ele, camel) {
+ getClass(ele)
+
+ let data = {}
+ if (ele.data) {
+ data = ele.data
+ } else if (ele.$vnode && ele.$vnode.data) {
+ data = ele.$vnode.data
+ }
+
+ // update-begin-author:sunjianlei date:20200303 for: style 和 staticStyle 可以共存
+ let style = data.style || {}
+ let staticStyle = data.staticStyle
+ staticStyle = staticStyle ? objectCamelize(data.staticStyle) : {}
+ // update-end-author:sunjianlei date:20200303 for: style 和 staticStyle 可以共存
+
+ if (typeof style === 'string') {
+ style = parseStyleText(style, camel)
+ } else if (camel && style) {
+ // 驼峰化
+ style = objectCamelize(style)
+ }
+ return { ...staticStyle, ...style }
+}
diff --git a/src/components/index.js b/src/components/index.js
new file mode 100644
index 0000000..401ae0d
--- /dev/null
+++ b/src/components/index.js
@@ -0,0 +1,56 @@
+// chart
+import Bar from '@/components/Charts/Bar'
+import ChartCard from '@/components/Charts/ChartCard'
+import Liquid from '@/components/Charts/Liquid'
+import MiniArea from '@/components/Charts/MiniArea'
+import MiniSmoothArea from '@/components/Charts/MiniSmoothArea'
+import MiniBar from '@/components/Charts/MiniBar'
+import MiniProgress from '@/components/Charts/MiniProgress'
+import Radar from '@/components/Charts/Radar'
+import RankList from '@/components/Charts/RankList'
+import TransferBar from '@/components/Charts/TransferBar'
+import TagCloud from '@/components/Charts/TagCloud'
+
+// pro components
+import AvatarList from '@/components/AvatarList'
+import Ellipsis from '@/components/Ellipsis'
+import FooterToolbar from '@/components/FooterToolbar'
+import NumberInfo from '@/components/NumberInfo'
+import Tree from '@/components/Tree/Tree'
+import Trend from '@/components/Trend'
+import STable from '@/components/Table'
+import MultiTab from '@/components/MultiTab'
+import IconSelector from '@/components/IconSelector'
+import TagSelect from '@/components/TagSelect'
+import StandardFormRow from '@/components/StandardFormRow'
+import ArticleListContent from '@/components/ArticleListContent'
+
+import Dialog from '@/components/Dialog'
+
+export {
+ AvatarList,
+ Bar,
+ ChartCard,
+ Liquid,
+ MiniArea,
+ MiniSmoothArea,
+ MiniBar,
+ MiniProgress,
+ Radar,
+ TagCloud,
+ RankList,
+ TransferBar,
+ Trend,
+ Ellipsis,
+ FooterToolbar,
+ NumberInfo,
+ Tree,
+ STable,
+ MultiTab,
+ IconSelector,
+ TagSelect,
+ StandardFormRow,
+ ArticleListContent,
+
+ Dialog
+}
diff --git a/src/components/index.less b/src/components/index.less
new file mode 100644
index 0000000..01ef050
--- /dev/null
+++ b/src/components/index.less
@@ -0,0 +1,6 @@
+@import '~ant-design-vue/lib/style/index';
+
+// The prefix to use on all css classes from ant-pro.
+@ant-pro-prefix : ant-pro;
+@ant-global-sider-zindex : 106;
+@ant-global-header-zindex : 105;
diff --git a/src/components/tools/TwoStepCaptcha.vue b/src/components/tools/TwoStepCaptcha.vue
new file mode 100644
index 0000000..01302b4
--- /dev/null
+++ b/src/components/tools/TwoStepCaptcha.vue
@@ -0,0 +1,89 @@
+
+
+
+ 两步验证
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/config/defaultSettings.js b/src/config/defaultSettings.js
new file mode 100644
index 0000000..0c11f40
--- /dev/null
+++ b/src/config/defaultSettings.js
@@ -0,0 +1,30 @@
+/**
+ * 项目默认配置项
+ * primaryColor - 默认主题色, 如果修改颜色不生效,请清理 localStorage
+ * navTheme - sidebar theme ['dark', 'light'] 两种主题
+ * colorWeak - 色盲模式
+ * layout - 整体布局方式 ['sidemenu', 'topmenu'] 两种布局
+ * fixedHeader - 固定 Header : boolean
+ * fixSiderbar - 固定左侧菜单栏 : boolean
+ * contentWidth - 内容区布局: 流式 | 固定
+ *
+ * storageOptions: {} - Vue-ls 插件配置项 (localStorage/sessionStorage)
+ *
+ */
+
+export default {
+ navTheme: 'light', // theme for nav menu
+ primaryColor: '#0f81f4', // '#F5222D', // primary color of ant design
+ layout: 'topmenu', // nav menu position: `sidemenu` or `topmenu`
+ contentWidth: 'Fluid', // layout of content: `Fluid` or `Fixed`, only works when layout is topmenu
+ fixedHeader: false, // sticky header
+ fixSiderbar: false, // sticky siderbar
+ colorWeak: false,
+ menu: {
+ locale: true
+ },
+ title: '智能图文查重比对数据系统',
+ pwa: false,
+ iconfontUrl: '',
+ production: process.env.NODE_ENV === 'production' && process.env.VUE_APP_PREVIEW !== 'true'
+}
diff --git a/src/config/router.config.js b/src/config/router.config.js
new file mode 100644
index 0000000..4ea1fc9
--- /dev/null
+++ b/src/config/router.config.js
@@ -0,0 +1,396 @@
+// eslint-disable-next-line
+import { UserLayout, BasicLayout, BlankLayout } from '@/layouts'
+import { bxAnaalyse } from '@/core/icons'
+
+const RouteView = {
+ name: 'RouteView',
+ render: h => h('router-view')
+}
+
+export const asyncRouterMap = [
+ {
+ path: '/',
+ name: 'index',
+ component: BasicLayout,
+ meta: { title: 'menu.home' },
+ redirect: '/dashboard/workplace',
+ children: [
+ // dashboard
+ {
+ path: '/dashboard',
+ name: 'dashboard',
+ redirect: '/dashboard/workplace',
+ component: RouteView,
+ meta: { title: 'menu.dashboard', keepAlive: true, icon: bxAnaalyse, permission: ['dashboard'] },
+ children: [
+ {
+ path: '/dashboard/analysis/:pageNo([1-9]\\d*)?',
+ name: 'Analysis',
+ component: () => import('@/views/dashboard/Analysis'),
+ meta: { title: 'menu.dashboard.analysis', keepAlive: false, permission: ['dashboard'] }
+ },
+ // 外部链接
+ {
+ path: 'https://www.baidu.com/',
+ name: 'Monitor',
+ meta: { title: 'menu.dashboard.monitor', target: '_blank' }
+ },
+ {
+ path: '/dashboard/workplace',
+ name: 'Workplace',
+ component: () => import('@/views/dashboard/Workplace'),
+ meta: { title: 'menu.dashboard.workplace', keepAlive: true, permission: ['dashboard'] }
+ }
+ ]
+ },
+ // forms
+ {
+ path: '/form',
+ redirect: '/form/base-form',
+ component: RouteView,
+ meta: { title: 'menu.form', icon: 'form', permission: ['form'] },
+ children: [
+ {
+ path: '/form/base-form',
+ name: 'BaseForm',
+ component: () => import('@/views/form/basicForm'),
+ meta: { title: 'menu.form.basic-form', keepAlive: true, permission: ['form'] }
+ },
+ {
+ path: '/form/step-form',
+ name: 'StepForm',
+ component: () => import('@/views/form/stepForm/StepForm'),
+ meta: { title: 'menu.form.step-form', keepAlive: true, permission: ['form'] }
+ },
+ {
+ path: '/form/advanced-form',
+ name: 'AdvanceForm',
+ component: () => import('@/views/form/advancedForm/AdvancedForm'),
+ meta: { title: 'menu.form.advanced-form', keepAlive: true, permission: ['form'] }
+ }
+ ]
+ },
+ // list
+ {
+ path: '/list',
+ name: 'list',
+ component: RouteView,
+ redirect: '/list/table-list',
+ meta: { title: 'menu.list', icon: 'table', permission: ['table'] },
+ children: [
+ {
+ path: '/list/table-list/:pageNo([1-9]\\d*)?',
+ name: 'TableListWrapper',
+ hideChildrenInMenu: true, // 强制显示 MenuItem 而不是 SubMenu
+ component: () => import('@/views/list/TableList'),
+ meta: { title: 'menu.list.table-list', keepAlive: true, permission: ['table'] }
+ },
+ {
+ path: '/list/basic-list',
+ name: 'BasicList',
+ component: () => import('@/views/list/BasicList'),
+ meta: { title: 'menu.list.basic-list', keepAlive: true, permission: ['table'] }
+ },
+ {
+ path: '/list/card',
+ name: 'CardList',
+ component: () => import('@/views/list/CardList'),
+ meta: { title: 'menu.list.card-list', keepAlive: true, permission: ['table'] }
+ },
+ {
+ path: '/list/search',
+ name: 'SearchList',
+ component: () => import('@/views/list/search/SearchLayout'),
+ redirect: '/list/search/article',
+ meta: { title: 'menu.list.search-list', keepAlive: true, permission: ['table'] },
+ children: [
+ {
+ path: '/list/search/article',
+ name: 'SearchArticles',
+ component: () => import('../views/list/search/Article'),
+ meta: { title: 'menu.list.search-list.articles', permission: ['table'] }
+ },
+ {
+ path: '/list/search/project',
+ name: 'SearchProjects',
+ component: () => import('../views/list/search/Projects'),
+ meta: { title: 'menu.list.search-list.projects', permission: ['table'] }
+ },
+ {
+ path: '/list/search/application',
+ name: 'SearchApplications',
+ component: () => import('../views/list/search/Applications'),
+ meta: { title: 'menu.list.search-list.applications', permission: ['table'] }
+ }
+ ]
+ }
+ ]
+ },
+
+ // profile
+ {
+ path: '/profile',
+ name: 'profile',
+ component: RouteView,
+ redirect: '/profile/basic',
+ meta: { title: 'menu.profile', icon: 'profile', permission: ['profile'] },
+ children: [
+ {
+ path: '/profile/basic',
+ name: 'ProfileBasic',
+ component: () => import('@/views/profile/basic'),
+ meta: { title: 'menu.profile.basic', permission: ['profile'] }
+ },
+ {
+ path: '/profile/advanced',
+ name: 'ProfileAdvanced',
+ component: () => import('@/views/profile/advanced/Advanced'),
+ meta: { title: 'menu.profile.advanced', permission: ['profile'] }
+ }
+ ]
+ },
+
+ // result
+ {
+ path: '/result',
+ name: 'result',
+ component: RouteView,
+ redirect: '/result/success',
+ meta: { title: 'menu.result', icon: 'check-circle-o', permission: ['result'] },
+ children: [
+ {
+ path: '/result/success',
+ name: 'ResultSuccess',
+ component: () => import(/* webpackChunkName: "result" */ '@/views/result/Success'),
+ meta: { title: 'menu.result.success', keepAlive: false, hiddenHeaderContent: true, permission: ['result'] }
+ },
+ {
+ path: '/result/fail',
+ name: 'ResultFail',
+ component: () => import(/* webpackChunkName: "result" */ '@/views/result/Error'),
+ meta: { title: 'menu.result.fail', keepAlive: false, hiddenHeaderContent: true, permission: ['result'] }
+ }
+ ]
+ },
+
+ // Exception
+ {
+ path: '/exception',
+ name: 'exception',
+ component: RouteView,
+ redirect: '/exception/403',
+ meta: { title: 'menu.exception', icon: 'warning', permission: ['exception'] },
+ children: [
+ {
+ path: '/exception/403',
+ name: 'Exception403',
+ component: () => import(/* webpackChunkName: "fail" */ '@/views/exception/403'),
+ meta: { title: 'menu.exception.not-permission', permission: ['exception'] }
+ },
+ {
+ path: '/exception/404',
+ name: 'Exception404',
+ component: () => import(/* webpackChunkName: "fail" */ '@/views/exception/404'),
+ meta: { title: 'menu.exception.not-find', permission: ['exception'] }
+ },
+ {
+ path: '/exception/500',
+ name: 'Exception500',
+ component: () => import(/* webpackChunkName: "fail" */ '@/views/exception/500'),
+ meta: { title: 'menu.exception.server-error', permission: ['exception'] }
+ }
+ ]
+ },
+
+ // account
+ {
+ path: '/account',
+ component: RouteView,
+ redirect: '/account/center',
+ name: 'account',
+ meta: { title: 'menu.account', icon: 'user', keepAlive: true, permission: ['user'] },
+ children: [
+ {
+ path: '/account/center',
+ name: 'center',
+ component: () => import('@/views/account/center'),
+ meta: { title: 'menu.account.center', keepAlive: true, permission: ['user'] }
+ },
+ {
+ path: '/account/settings',
+ name: 'settings',
+ component: () => import('@/views/account/settings/Index'),
+ meta: { title: 'menu.account.settings', hideHeader: true, permission: ['user'] },
+ redirect: '/account/settings/basic',
+ hideChildrenInMenu: true,
+ children: [
+ {
+ path: '/account/settings/basic',
+ name: 'BasicSettings',
+ component: () => import('@/views/account/settings/BasicSetting'),
+ meta: { title: 'account.settings.menuMap.basic', hidden: true, permission: ['user'] }
+ },
+ {
+ path: '/account/settings/security',
+ name: 'SecuritySettings',
+ component: () => import('@/views/account/settings/Security'),
+ meta: {
+ title: 'account.settings.menuMap.security',
+ hidden: true,
+ keepAlive: true,
+ permission: ['user']
+ }
+ },
+ {
+ path: '/account/settings/custom',
+ name: 'CustomSettings',
+ component: () => import('@/views/account/settings/Custom'),
+ meta: { title: 'account.settings.menuMap.custom', hidden: true, keepAlive: true, permission: ['user'] }
+ },
+ {
+ path: '/account/settings/binding',
+ name: 'BindingSettings',
+ component: () => import('@/views/account/settings/Binding'),
+ meta: { title: 'account.settings.menuMap.binding', hidden: true, keepAlive: true, permission: ['user'] }
+ },
+ {
+ path: '/account/settings/notification',
+ name: 'NotificationSettings',
+ component: () => import('@/views/account/settings/Notification'),
+ meta: {
+ title: 'account.settings.menuMap.notification',
+ hidden: true,
+ keepAlive: true,
+ permission: ['user']
+ }
+ }
+ ]
+ }
+ ]
+ }
+
+ // other
+ /*
+ {
+ path: '/other',
+ name: 'otherPage',
+ component: PageView,
+ meta: { title: '其他组件', icon: 'slack', permission: [ 'dashboard' ] },
+ redirect: '/other/icon-selector',
+ children: [
+ {
+ path: '/other/icon-selector',
+ name: 'TestIconSelect',
+ component: () => import('@/views/other/IconSelectorView'),
+ meta: { title: 'IconSelector', icon: 'tool', keepAlive: true, permission: [ 'dashboard' ] }
+ },
+ {
+ path: '/other/list',
+ component: RouteView,
+ meta: { title: '业务布局', icon: 'layout', permission: [ 'support' ] },
+ redirect: '/other/list/tree-list',
+ children: [
+ {
+ path: '/other/list/tree-list',
+ name: 'TreeList',
+ component: () => import('@/views/other/TreeList'),
+ meta: { title: '树目录表格', keepAlive: true }
+ },
+ {
+ path: '/other/list/edit-table',
+ name: 'EditList',
+ component: () => import('@/views/other/TableInnerEditList'),
+ meta: { title: '内联编辑表格', keepAlive: true }
+ },
+ {
+ path: '/other/list/user-list',
+ name: 'UserList',
+ component: () => import('@/views/other/UserList'),
+ meta: { title: '用户列表', keepAlive: true }
+ },
+ {
+ path: '/other/list/role-list',
+ name: 'RoleList',
+ component: () => import('@/views/other/RoleList'),
+ meta: { title: '角色列表', keepAlive: true }
+ },
+ {
+ path: '/other/list/system-role',
+ name: 'SystemRole',
+ component: () => import('@/views/role/RoleList'),
+ meta: { title: '角色列表2', keepAlive: true }
+ },
+ {
+ path: '/other/list/permission-list',
+ name: 'PermissionList',
+ component: () => import('@/views/other/PermissionList'),
+ meta: { title: '权限列表', keepAlive: true }
+ }
+ ]
+ }
+ ]
+ }
+ */
+ ]
+ },
+ {
+ path: '*',
+ redirect: '/404',
+ hidden: true
+ }
+]
+
+/**
+ * 基础路由
+ * @type { *[] }
+ */
+export const constantRouterMap = [
+ {
+ path: '/user',
+ component: UserLayout,
+ redirect: '/user/login',
+ hidden: true,
+ children: [
+ {
+ path: 'login',
+ name: 'login',
+ component: () => import(/* webpackChunkName: "user" */ '@/views/user/Login')
+ },
+ {
+ path: 'register',
+ name: 'register',
+ component: () => import(/* webpackChunkName: "user" */ '@/views/user/Register')
+ },
+ {
+ path: 'register-result',
+ name: 'registerResult',
+ component: () => import(/* webpackChunkName: "user" */ '@/views/user/RegisterResult')
+ },
+ {
+ path: 'recover',
+ name: 'recover',
+ component: undefined
+ }
+ ]
+ },
+
+ {
+ path: '/other',
+ component: BasicLayout,
+ hidden: true,
+ children: [
+ {
+ path: 'resetPwd',
+ name: '重置密码',
+ meta: {
+ title: '重置密码'
+ },
+ component: () => import('@/views/user/ResetPwd.vue')
+ }
+ ]
+ },
+ {
+ path: '/404',
+ component: () => import(/* webpackChunkName: "fail" */ '@/views/exception/404')
+ }
+]
diff --git a/src/core/bootstrap.js b/src/core/bootstrap.js
new file mode 100644
index 0000000..7534bdb
--- /dev/null
+++ b/src/core/bootstrap.js
@@ -0,0 +1,30 @@
+import defaultSettings from '@/config/defaultSettings'
+import store from '@/store'
+import {
+ ACCESS_TOKEN,
+ APP_LANGUAGE, TOGGLE_COLOR, TOGGLE_CONTENT_WIDTH,
+ TOGGLE_FIXED_HEADER,
+ TOGGLE_FIXED_SIDEBAR, TOGGLE_HIDE_HEADER,
+ TOGGLE_LAYOUT, TOGGLE_MULTI_TAB, TOGGLE_NAV_THEME, TOGGLE_WEAK
+} from '@/store/mutation-types'
+import { printANSI } from '@/utils/screenLog'
+import storage from 'store'
+
+export default function Initializer () {
+ printANSI() // 请自行移除该行. please remove this line
+
+ store.commit(TOGGLE_LAYOUT, storage.get(TOGGLE_LAYOUT, defaultSettings.layout))
+ store.commit(TOGGLE_FIXED_HEADER, storage.get(TOGGLE_FIXED_HEADER, defaultSettings.fixedHeader))
+ store.commit(TOGGLE_FIXED_SIDEBAR, storage.get(TOGGLE_FIXED_SIDEBAR, defaultSettings.fixSiderbar))
+ store.commit(TOGGLE_CONTENT_WIDTH, storage.get(TOGGLE_CONTENT_WIDTH, defaultSettings.contentWidth))
+ store.commit(TOGGLE_HIDE_HEADER, storage.get(TOGGLE_HIDE_HEADER, defaultSettings.autoHideHeader))
+ store.commit(TOGGLE_NAV_THEME, storage.get(TOGGLE_NAV_THEME, defaultSettings.navTheme))
+ store.commit(TOGGLE_WEAK, storage.get(TOGGLE_WEAK, defaultSettings.colorWeak))
+ store.commit(TOGGLE_COLOR, storage.get(TOGGLE_COLOR, defaultSettings.primaryColor))
+ store.commit(TOGGLE_MULTI_TAB, storage.get(TOGGLE_MULTI_TAB, defaultSettings.multiTab))
+ store.commit('SET_TOKEN', storage.get(ACCESS_TOKEN))
+
+ // store.dispatch('setLang', storage.get(APP_LANGUAGE, 'en-US'))
+ store.dispatch('setLang', storage.get(APP_LANGUAGE, 'zh-CN'))
+ // last step
+}
diff --git a/src/core/directives/action.js b/src/core/directives/action.js
new file mode 100644
index 0000000..18b7584
--- /dev/null
+++ b/src/core/directives/action.js
@@ -0,0 +1,34 @@
+import Vue from 'vue'
+import store from '@/store'
+
+/**
+ * Action 权限指令
+ * 指令用法:
+ * - 在需要控制 action 级别权限的组件上使用 v-action:[method] , 如下:
+ * 添加用户
+ * 删除用户
+ * 修改
+ *
+ * - 当前用户没有权限时,组件上使用了该指令则会被隐藏
+ * - 当后台权限跟 pro 提供的模式不同时,只需要针对这里的权限过滤进行修改即可
+ *
+ * @see https://github.com/vueComponent/ant-design-vue-pro/pull/53
+ */
+const action = Vue.directive('action', {
+ inserted: function (el, binding, vnode) {
+ const actionName = binding.arg
+ const roles = store.getters.roles
+ const elVal = vnode.context.$route.meta.permission
+ const permissionId = elVal instanceof String && [elVal] || elVal
+ roles.permissions.forEach(p => {
+ if (!permissionId.includes(p.permissionId)) {
+ return
+ }
+ if (p.actionList && !p.actionList.includes(actionName)) {
+ el.parentNode && el.parentNode.removeChild(el) || (el.style.display = 'none')
+ }
+ })
+ }
+})
+
+export default action
diff --git a/src/core/icons.js b/src/core/icons.js
new file mode 100644
index 0000000..46b7261
--- /dev/null
+++ b/src/core/icons.js
@@ -0,0 +1,11 @@
+/**
+ * Custom icon list
+ * All icons are loaded here for easy management
+ * @see https://vue.ant.design/components/icon/#Custom-Font-Icon
+ *
+ * 自定义图标加载表
+ * 所有图标均从这里加载,方便管理
+ */
+import bxAnaalyse from '@/assets/icons/bx-analyse.svg?inline' // path to your '*.svg?inline' file.
+
+export { bxAnaalyse }
diff --git a/src/core/lazy_use.js b/src/core/lazy_use.js
new file mode 100644
index 0000000..ccbf73c
--- /dev/null
+++ b/src/core/lazy_use.js
@@ -0,0 +1,118 @@
+import Vue from 'vue'
+
+// base library
+import {
+ ConfigProvider,
+ Layout,
+ Input,
+ InputNumber,
+ Button,
+ Switch,
+ Radio,
+ Checkbox,
+ Select,
+ Card,
+ Form,
+ Row,
+ Col,
+ Modal,
+ Table,
+ Tabs,
+ Icon,
+ Badge,
+ Popover,
+ Dropdown,
+ List,
+ Avatar,
+ Breadcrumb,
+ Steps,
+ Spin,
+ Menu,
+ Drawer,
+ Tooltip,
+ Alert,
+ Tag,
+ Divider,
+ DatePicker,
+ TimePicker,
+ Upload,
+ Progress,
+ Skeleton,
+ Popconfirm,
+ PageHeader,
+ Result,
+ Statistic,
+ Descriptions,
+ Space,
+ message,
+ notification
+} from 'ant-design-vue'
+import Viser from 'viser-vue'
+
+// ext library
+import VueCropper from 'vue-cropper'
+import Dialog from '@/components/Dialog'
+import MultiTab from '@/components/MultiTab'
+import PageLoading from '@/components/PageLoading'
+import PermissionHelper from '@/core/permission/permission'
+import './directives/action'
+
+Vue.use(ConfigProvider)
+Vue.use(Layout)
+Vue.use(Input)
+Vue.use(InputNumber)
+Vue.use(Button)
+Vue.use(Switch)
+Vue.use(Radio)
+Vue.use(Checkbox)
+Vue.use(Select)
+Vue.use(Card)
+Vue.use(Form)
+Vue.use(Row)
+Vue.use(Col)
+Vue.use(Modal)
+Vue.use(Table)
+Vue.use(Tabs)
+Vue.use(Icon)
+Vue.use(Badge)
+Vue.use(Popover)
+Vue.use(Dropdown)
+Vue.use(List)
+Vue.use(Avatar)
+Vue.use(Breadcrumb)
+Vue.use(Steps)
+Vue.use(Spin)
+Vue.use(Menu)
+Vue.use(Drawer)
+Vue.use(Tooltip)
+Vue.use(Alert)
+Vue.use(Tag)
+Vue.use(Divider)
+Vue.use(DatePicker)
+Vue.use(TimePicker)
+Vue.use(Upload)
+Vue.use(Progress)
+Vue.use(Skeleton)
+Vue.use(Popconfirm)
+Vue.use(PageHeader)
+Vue.use(Result)
+Vue.use(Statistic)
+Vue.use(Descriptions)
+Vue.use(Space)
+
+Vue.prototype.$confirm = Modal.confirm
+Vue.prototype.$message = message
+Vue.prototype.$notification = notification
+Vue.prototype.$info = Modal.info
+Vue.prototype.$success = Modal.success
+Vue.prototype.$error = Modal.error
+Vue.prototype.$warning = Modal.warning
+
+Vue.use(Viser)
+Vue.use(Dialog) // this.$dialog func
+Vue.use(MultiTab)
+Vue.use(PageLoading)
+Vue.use(PermissionHelper)
+Vue.use(VueCropper)
+
+process.env.NODE_ENV !== 'production' && console.warn('[antd-pro] NOTICE: Antd use lazy-load.')
diff --git a/src/core/permission/permission.js b/src/core/permission/permission.js
new file mode 100644
index 0000000..9ab9738
--- /dev/null
+++ b/src/core/permission/permission.js
@@ -0,0 +1,50 @@
+export const PERMISSION_ENUM = {
+ 'add': { key: 'add', label: '新增' },
+ 'delete': { key: 'delete', label: '删除' },
+ 'edit': { key: 'edit', label: '修改' },
+ 'query': { key: 'query', label: '查询' },
+ 'get': { key: 'get', label: '详情' },
+ 'enable': { key: 'enable', label: '启用' },
+ 'disable': { key: 'disable', label: '禁用' },
+ 'import': { key: 'import', label: '导入' },
+ 'export': { key: 'export', label: '导出' }
+}
+
+/**
+ * Button
+ * @param Vue
+ */
+function plugin (Vue) {
+ if (plugin.installed) {
+ return
+ }
+
+ !Vue.prototype.$auth && Object.defineProperties(Vue.prototype, {
+ $auth: {
+ get () {
+ const _this = this
+ return (permissions) => {
+ const permissionList = _this.$store.getters.userInfo.permissions || []
+ return permissionList.includes(permissions)
+ }
+ }
+ }
+ })
+
+ !Vue.prototype.$enum && Object.defineProperties(Vue.prototype, {
+ $enum: {
+ get () {
+ // const _this = this;
+ return (val) => {
+ let result = PERMISSION_ENUM
+ val && val.split('.').forEach(v => {
+ result = result && result[v] || null
+ })
+ return result
+ }
+ }
+ }
+ })
+}
+
+export default plugin
diff --git a/src/core/use.js b/src/core/use.js
new file mode 100644
index 0000000..d98cd16
--- /dev/null
+++ b/src/core/use.js
@@ -0,0 +1,27 @@
+import Vue from 'vue'
+
+// base library
+import Antd from 'ant-design-vue'
+import Viser from 'viser-vue'
+import VueCropper from 'vue-cropper'
+import 'ant-design-vue/dist/antd.less'
+
+// ext library
+import VueClipboard from 'vue-clipboard2'
+import MultiTab from '@/components/MultiTab'
+import PageLoading from '@/components/PageLoading'
+import PermissionHelper from '@/core/permission/permission'
+// import '@/components/use'
+import './directives/action'
+
+VueClipboard.config.autoSetContainer = true
+
+Vue.use(Antd)
+Vue.use(Viser)
+Vue.use(MultiTab)
+Vue.use(PageLoading)
+Vue.use(VueClipboard)
+Vue.use(PermissionHelper)
+Vue.use(VueCropper)
+
+process.env.NODE_ENV !== 'production' && console.warn('[antd-pro] WARNING: Antd now use fulled imported.')
diff --git a/src/custom.less b/src/custom.less
new file mode 100644
index 0000000..b8c3e7b
--- /dev/null
+++ b/src/custom.less
@@ -0,0 +1,8 @@
+@primary-color: #dcdcdc;
+// Menu
+// ---
+// dark theme
+@menu-dark-color: #fff;
+@menu-highlight-color: #fff;
+@menu-dark-bg: #135da8;
+@menu-dark-item-hover-bg: @primary-color;
diff --git a/src/global.less b/src/global.less
new file mode 100644
index 0000000..5bdfd3a
--- /dev/null
+++ b/src/global.less
@@ -0,0 +1,219 @@
+@import '~ant-design-vue/dist/antd.less';
+@import '~ant-design-vue/es/style/themes/default.less';
+@import './custom';
+
+.ant-pro-basicLayout-content {
+ margin: 10px;
+}
+
+.ant-pro-top-nav-header.dark {
+ background: #135da8;
+
+ // .ant-menu-dark,
+ // .ant-menu-dark .ant-menu-sub {
+ // background: #135da8;
+ // }
+}
+
+html,
+body,
+#app,
+#root {
+ height: 100%;
+ background-color: #f5f6f8;
+}
+
+.colorWeak {
+ filter: invert(80%);
+}
+
+.ant-layout.layout-basic {
+ height: 100vh;
+ min-height: 100vh;
+}
+
+canvas {
+ display: block;
+}
+
+body {
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ text-rendering: optimizelegibility;
+}
+
+ul,
+ol {
+ list-style: none;
+}
+
+// 数据列表 样式
+.table-alert {
+ margin-bottom: 16px;
+}
+// 数据列表 操作
+.table-operator {
+ margin-bottom: 18px;
+
+ button {
+ margin-right: 8px;
+ }
+}
+// 数据列表 搜索条件
+.table-page-search-wrapper {
+ .ant-form-inline {
+ .ant-row {
+ margin-left: 0 !important;
+ margin-right: 0 !important;
+ }
+ .ant-form-item {
+ display: flex;
+ margin-right: 0;
+ margin-bottom: 24px;
+
+ .ant-form-item-control-wrapper {
+ flex: 1 1;
+ display: inline-block;
+ vertical-align: middle;
+ }
+
+ > .ant-form-item-label {
+ width: auto;
+ padding-right: 8px;
+ line-height: 32px;
+ }
+
+ .ant-form-item-control {
+ height: 32px;
+ line-height: 32px;
+ }
+ }
+ }
+
+ .table-page-search-buttons {
+ margin-bottom: 24px;
+ }
+
+ .table-page-search-submitButtons {
+ display: block;
+ margin-bottom: 24px;
+ white-space: nowrap;
+ }
+}
+
+@media (max-width: @screen-xs) {
+ .ant-table {
+ width: 100%;
+ overflow-x: auto;
+
+ &-thead > tr,
+ &-tbody > tr {
+ > th,
+ > td {
+ white-space: pre;
+
+ > span {
+ display: block;
+ }
+ }
+ }
+ }
+}
+
+/* 滚动条整体 */
+::-webkit-scrollbar {
+ width: 7px;
+ height: 7px;
+}
+
+/* 两个滚动条交接处 -- x轴和y轴 */
+::-webkit-scrollbar-corner {
+ background-color: transparent;
+}
+
+/* 滚动条滑块 */
+::-webkit-scrollbar-thumb {
+ background: @primary-color;
+ background: #dcdcdc;
+ border-radius: 10px;
+ -webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
+}
+
+* {
+ scrollbar-color: @primary-color @component-background;
+}
+
+/* 滚动条轨道 */
+::-webkit-scrollbar-track {
+ -webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
+ background: @component-background;
+ border-radius: 10px;
+}
+
+/* 滚动条两端按钮 */
+::-webkit-scrollbar-button {
+}
+
+.card-box {
+ position: static;
+ height: calc(100vh - 220px);
+ overflow: auto;
+
+ &.has-border {
+ border: 1px solid #2d81b1;
+ }
+}
+
+.right-wrapper {
+ display: flex;
+ height: calc(100vh - 200px);
+ flex-direction: column;
+
+ .chart-item-wrapper {
+ & + .chart-item-wrapper {
+ margin-top: 10px;
+ }
+
+ display: flex;
+ flex: 1;
+ background: #074c72;
+ border: 1px solid #1b78a9;
+ }
+}
+
+.form-flex {
+ .ant-form-item {
+ display: flex;
+ }
+}
+
+.form-item-flex.ant-form-item {
+ display: flex;
+}
+
+.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 {
+ color: #0f81f4 !important;
+ border-bottom: 2px solid #0f81f4 !important;
+ i, span {
+ color: #0f81f4 !important;
+ }
+}
+
+.ant-menu-item>a:hover,
+.ant-menu-item-selected, .ant-menu-item-selected>a, .ant-menu-item-selected>a:hover,
+.ant-menu-horizontal>.ant-menu-item-selected>a ,
+.ant-menu-item-active, .ant-menu-item:hover, .ant-menu-submenu-active, .ant-menu-submenu-title:hover, .ant-menu:not(.ant-menu-inline) .ant-menu-submenu-open{
+ color: #0f81f4 !important;
+}
+
+.ant-modal-wrap {
+ &::-webkit-scrollbar {
+ width: 9px;
+ height: 9px;
+ }
+
+ /* 滚动条滑块 */
+ &::-webkit-scrollbar-thumb {
+ background: #bcbcbc;
+ }
+}
\ No newline at end of file
diff --git a/src/layouts/BasicLayout.less b/src/layouts/BasicLayout.less
new file mode 100644
index 0000000..761aee9
--- /dev/null
+++ b/src/layouts/BasicLayout.less
@@ -0,0 +1,43 @@
+@import '~ant-design-vue/es/style/themes/default.less';
+
+.ant-pro-global-header-index-right {
+ margin-right: 8px;
+
+ &.ant-pro-global-header-index-dark {
+ .ant-pro-global-header-index-action {
+ color: hsl(0deg 0% 100% / 85%);
+
+ &:hover {
+ background: #1890ff;
+ }
+ }
+ }
+
+ .ant-pro-account-avatar {
+ .antd-pro-global-header-index-avatar {
+ margin: ~'calc((@{layout-header-height} - 24px) / 2)' 0;
+ margin-right: 8px;
+ color: @primary-color;
+ vertical-align: top;
+ background: rgb(255 255 255 / 85%);
+ }
+ }
+
+ .menu {
+ .anticon {
+ margin-right: 8px;
+ }
+
+ .ant-dropdown-menu-item {
+ min-width: 100px;
+ }
+ }
+}
+
+.ant-layout-footer {
+ padding: 0 auto;
+
+ .ant-pro-global-footer {
+ margin: 0;
+ }
+}
diff --git a/src/layouts/BasicLayout.vue b/src/layouts/BasicLayout.vue
new file mode 100644
index 0000000..02a68b4
--- /dev/null
+++ b/src/layouts/BasicLayout.vue
@@ -0,0 +1,214 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ $message.info('只是一个DEMO')
+ }
+ "
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/layouts/BlankLayout.vue b/src/layouts/BlankLayout.vue
new file mode 100644
index 0000000..1bfbfbf
--- /dev/null
+++ b/src/layouts/BlankLayout.vue
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/layouts/PageView.vue b/src/layouts/PageView.vue
new file mode 100644
index 0000000..86df485
--- /dev/null
+++ b/src/layouts/PageView.vue
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
diff --git a/src/layouts/RouteView.vue b/src/layouts/RouteView.vue
new file mode 100644
index 0000000..edae19e
--- /dev/null
+++ b/src/layouts/RouteView.vue
@@ -0,0 +1,32 @@
+
diff --git a/src/layouts/UserLayout.vue b/src/layouts/UserLayout.vue
new file mode 100644
index 0000000..f53ce9a
--- /dev/null
+++ b/src/layouts/UserLayout.vue
@@ -0,0 +1,162 @@
+
+
+
+
+
+
+
+
diff --git a/src/layouts/components/MenuButton.vue b/src/layouts/components/MenuButton.vue
new file mode 100644
index 0000000..5d3471a
--- /dev/null
+++ b/src/layouts/components/MenuButton.vue
@@ -0,0 +1,179 @@
+
+
+
+
+
+
+
+
diff --git a/src/layouts/components/PageBody.vue b/src/layouts/components/PageBody.vue
new file mode 100644
index 0000000..37a9cb2
--- /dev/null
+++ b/src/layouts/components/PageBody.vue
@@ -0,0 +1,172 @@
+
+
+
+
+
+
+
diff --git a/src/layouts/components/PageHeader.vue b/src/layouts/components/PageHeader.vue
new file mode 100644
index 0000000..b94a94a
--- /dev/null
+++ b/src/layouts/components/PageHeader.vue
@@ -0,0 +1,115 @@
+
+
+
+
+
+
+
diff --git a/src/layouts/index.js b/src/layouts/index.js
new file mode 100644
index 0000000..1d62d6c
--- /dev/null
+++ b/src/layouts/index.js
@@ -0,0 +1,7 @@
+import UserLayout from './UserLayout'
+import BlankLayout from './BlankLayout'
+import BasicLayout from './BasicLayout'
+import RouteView from './RouteView'
+import PageView from './PageView'
+
+export { UserLayout, BasicLayout, BlankLayout, RouteView, PageView }
diff --git a/src/locales/index.js b/src/locales/index.js
new file mode 100644
index 0000000..cda6e48
--- /dev/null
+++ b/src/locales/index.js
@@ -0,0 +1,63 @@
+import moment from 'moment'
+import storage from 'store'
+import Vue from 'vue'
+import VueI18n from 'vue-i18n'
+
+// default lang
+// import enUS from './lang/en-US'
+import zhCN from './lang/zh-CN'
+
+Vue.use(VueI18n)
+
+// export const defaultLang = 'en-US'
+export const defaultLang = 'zh-CN'
+const messages = {
+ // 'en-US': {
+ // ...enUS
+ // }
+ 'zh-CN': {
+ ...zhCN
+ }
+}
+
+const i18n = new VueI18n({
+ silentTranslationWarn: true,
+ locale: defaultLang,
+ fallbackLocale: defaultLang,
+ messages
+})
+
+const loadedLanguages = [defaultLang]
+
+function setI18nLanguage (lang) {
+ i18n.locale = lang
+ // request.headers['Accept-Language'] = lang
+ document.querySelector('html').setAttribute('lang', lang)
+ return lang
+}
+
+export function loadLanguageAsync (lang = defaultLang) {
+ return new Promise(resolve => {
+ // 缓存语言设置
+ storage.set('lang', lang)
+ if (i18n.locale !== lang) {
+ if (!loadedLanguages.includes(lang)) {
+ return import(/* webpackChunkName: "lang-[request]" */ `./lang/${lang}`).then(msg => {
+ const locale = msg.default
+ i18n.setLocaleMessage(lang, locale)
+ loadedLanguages.push(lang)
+ moment.updateLocale(locale.momentName, locale.momentLocale)
+ return setI18nLanguage(lang)
+ })
+ }
+ return resolve(setI18nLanguage(lang))
+ }
+ return resolve(lang)
+ })
+}
+
+export function i18nRender (key) {
+ return i18n.t(`${key}`)
+}
+
+export default i18n
diff --git a/src/locales/lang/en-US.js b/src/locales/lang/en-US.js
new file mode 100644
index 0000000..8d856f9
--- /dev/null
+++ b/src/locales/lang/en-US.js
@@ -0,0 +1,35 @@
+import antdEnUS from 'ant-design-vue/es/locale-provider/en_US'
+import momentEU from 'moment/locale/eu'
+import global from './en-US/global'
+
+import menu from './en-US/menu'
+import setting from './en-US/setting'
+import user from './en-US/user'
+
+import dashboard from './en-US/dashboard'
+import form from './en-US/form'
+import result from './en-US/result'
+import account from './en-US/account'
+
+const components = {
+ antLocale: antdEnUS,
+ momentName: 'eu',
+ momentLocale: momentEU
+}
+
+export default {
+ message: '-',
+
+ 'layouts.usermenu.dialog.title': 'Message',
+ 'layouts.usermenu.dialog.content': 'Are you sure you would like to logout?',
+ 'layouts.userLayout.title': 'Ant Design is the most influential web design specification in Xihu district',
+ ...components,
+ ...global,
+ ...menu,
+ ...setting,
+ ...user,
+ ...dashboard,
+ ...form,
+ ...result,
+ ...account
+}
diff --git a/src/locales/lang/en-US/account.js b/src/locales/lang/en-US/account.js
new file mode 100644
index 0000000..65a4774
--- /dev/null
+++ b/src/locales/lang/en-US/account.js
@@ -0,0 +1,5 @@
+import settings from './account/settings'
+
+export default {
+ ...settings
+ }
diff --git a/src/locales/lang/en-US/account/settings.js b/src/locales/lang/en-US/account/settings.js
new file mode 100644
index 0000000..74ec430
--- /dev/null
+++ b/src/locales/lang/en-US/account/settings.js
@@ -0,0 +1,62 @@
+export default {
+ 'account.settings.menuMap.basic': 'Basic Settings',
+ 'account.settings.menuMap.security': 'Security Settings',
+ 'account.settings.menuMap.custom': 'Custom Settings',
+ 'account.settings.menuMap.binding': 'Account Binding',
+ 'account.settings.menuMap.notification': 'New Message Notification',
+ 'account.settings.basic.avatar': 'Avatar',
+ 'account.settings.basic.change-avatar': 'Change avatar',
+ 'account.settings.basic.email': 'Email',
+ 'account.settings.basic.email-message': 'Please input your email!',
+ 'account.settings.basic.nickname': 'Nickname',
+ 'account.settings.basic.nickname-message': 'Please input your Nickname!',
+ 'account.settings.basic.profile': 'Personal profile',
+ 'account.settings.basic.profile-message': 'Please input your personal profile!',
+ 'account.settings.basic.profile-placeholder': 'Brief introduction to yourself',
+ 'account.settings.basic.country': 'Country/Region',
+ 'account.settings.basic.country-message': 'Please input your country!',
+ 'account.settings.basic.geographic': 'Province or city',
+ 'account.settings.basic.geographic-message': 'Please input your geographic info!',
+ 'account.settings.basic.address': 'Street Address',
+ 'account.settings.basic.address-message': 'Please input your address!',
+ 'account.settings.basic.phone': 'Phone Number',
+ 'account.settings.basic.phone-message': 'Please input your phone!',
+ 'account.settings.basic.update': 'Update Information',
+ 'account.settings.basic.update.success': 'Update basic information successfully',
+ 'account.settings.security.strong': 'Strong',
+ 'account.settings.security.medium': 'Medium',
+ 'account.settings.security.weak': 'Weak',
+ 'account.settings.security.password': 'Account Password',
+ 'account.settings.security.password-description': 'Current password strength:',
+ 'account.settings.security.phone': 'Security Phone',
+ 'account.settings.security.phone-description': 'Bound phone:',
+ 'account.settings.security.question': 'Security Question',
+ 'account.settings.security.question-description':
+ 'The security question is not set, and the security policy can effectively protect the account security',
+ 'account.settings.security.email': 'Backup Email',
+ 'account.settings.security.email-description': 'Bound Email:',
+ 'account.settings.security.mfa': 'MFA Device',
+ 'account.settings.security.mfa-description':
+ 'Unbound MFA device, after binding, can be confirmed twice',
+ 'account.settings.security.modify': 'Modify',
+ 'account.settings.security.set': 'Set',
+ 'account.settings.security.bind': 'Bind',
+ 'account.settings.binding.taobao': 'Binding Taobao',
+ 'account.settings.binding.taobao-description': 'Currently unbound Taobao account',
+ 'account.settings.binding.alipay': 'Binding Alipay',
+ 'account.settings.binding.alipay-description': 'Currently unbound Alipay account',
+ 'account.settings.binding.dingding': 'Binding DingTalk',
+ 'account.settings.binding.dingding-description': 'Currently unbound DingTalk account',
+ 'account.settings.binding.bind': 'Bind',
+ 'account.settings.notification.password': 'Account Password',
+ 'account.settings.notification.password-description':
+ 'Messages from other users will be notified in the form of a station letter',
+ 'account.settings.notification.messages': 'System Messages',
+ 'account.settings.notification.messages-description':
+ 'System messages will be notified in the form of a station letter',
+ 'account.settings.notification.todo': 'To-do Notification',
+ 'account.settings.notification.todo-description':
+ 'The to-do list will be notified in the form of a letter from the station',
+ 'account.settings.settings.open': 'Open',
+ 'account.settings.settings.close': 'Close'
+}
diff --git a/src/locales/lang/en-US/dashboard.js b/src/locales/lang/en-US/dashboard.js
new file mode 100644
index 0000000..9d40892
--- /dev/null
+++ b/src/locales/lang/en-US/dashboard.js
@@ -0,0 +1,5 @@
+import analysis from './dashboard/analysis'
+
+export default {
+ ...analysis
+ }
diff --git a/src/locales/lang/en-US/dashboard/analysis.js b/src/locales/lang/en-US/dashboard/analysis.js
new file mode 100644
index 0000000..6738d12
--- /dev/null
+++ b/src/locales/lang/en-US/dashboard/analysis.js
@@ -0,0 +1,36 @@
+export default {
+ 'dashboard.analysis.test': 'Gongzhuan No.{no} shop',
+ 'dashboard.analysis.introduce': 'Introduce',
+ 'dashboard.analysis.total-sales': 'Total Sales',
+ 'dashboard.analysis.day-sales': 'Daily Sales',
+ 'dashboard.analysis.visits': 'Visits',
+ 'dashboard.analysis.visits-trend': 'Visits Trend',
+ 'dashboard.analysis.visits-ranking': 'Visits Ranking',
+ 'dashboard.analysis.day-visits': 'Daily Visits',
+ 'dashboard.analysis.week': 'WoW Change',
+ 'dashboard.analysis.day': 'DoD Change',
+ 'dashboard.analysis.payments': 'Payments',
+ 'dashboard.analysis.conversion-rate': 'Conversion Rate',
+ 'dashboard.analysis.operational-effect': 'Operational Effect',
+ 'dashboard.analysis.sales-trend': 'Stores Sales Trend',
+ 'dashboard.analysis.sales-ranking': 'Sales Ranking',
+ 'dashboard.analysis.all-year': 'All Year',
+ 'dashboard.analysis.all-month': 'All Month',
+ 'dashboard.analysis.all-week': 'All Week',
+ 'dashboard.analysis.all-day': 'All day',
+ 'dashboard.analysis.search-users': 'Search Users',
+ 'dashboard.analysis.per-capita-search': 'Per Capita Search',
+ 'dashboard.analysis.online-top-search': 'Online Top Search',
+ 'dashboard.analysis.the-proportion-of-sales': 'The Proportion Of Sales',
+ 'dashboard.analysis.dropdown-option-one': 'Operation one',
+ 'dashboard.analysis.dropdown-option-two': 'Operation two',
+ 'dashboard.analysis.channel.all': 'ALL',
+ 'dashboard.analysis.channel.online': 'Online',
+ 'dashboard.analysis.channel.stores': 'Stores',
+ 'dashboard.analysis.sales': 'Sales',
+ 'dashboard.analysis.traffic': 'Traffic',
+ 'dashboard.analysis.table.rank': 'Rank',
+ 'dashboard.analysis.table.search-keyword': 'Keyword',
+ 'dashboard.analysis.table.users': 'Users',
+ 'dashboard.analysis.table.weekly-range': 'Weekly Range'
+}
diff --git a/src/locales/lang/en-US/form.js b/src/locales/lang/en-US/form.js
new file mode 100644
index 0000000..d004e52
--- /dev/null
+++ b/src/locales/lang/en-US/form.js
@@ -0,0 +1,5 @@
+import basicForm from './form/basicForm'
+
+export default {
+ ...basicForm
+ }
diff --git a/src/locales/lang/en-US/form/basicForm.js b/src/locales/lang/en-US/form/basicForm.js
new file mode 100644
index 0000000..3ef4bc0
--- /dev/null
+++ b/src/locales/lang/en-US/form/basicForm.js
@@ -0,0 +1,61 @@
+export default {
+ 'form.basic-form.basic.title': 'Basic form',
+ 'form.basic-form.basic.description':
+ 'Form pages are used to collect or verify information to users, and basic forms are common in scenarios where there are fewer data items.',
+ 'form.basic-form.title.label': 'Title',
+ 'form.basic-form.title.placeholder': 'Give the target a name',
+ 'form.basic-form.title.required': 'Please enter a title',
+ 'form.basic-form.date.label': 'Start and end date',
+ 'form.basic-form.placeholder.start': 'Start date',
+ 'form.basic-form.placeholder.end': 'End date',
+ 'form.basic-form.date.required': 'Please select the start and end date',
+ 'form.basic-form.goal.label': 'Goal description',
+ 'form.basic-form.goal.placeholder': 'Please enter your work goals',
+ 'form.basic-form.goal.required': 'Please enter a description of the goal',
+ 'form.basic-form.standard.label': 'Metrics',
+ 'form.basic-form.standard.placeholder': 'Please enter a metric',
+ 'form.basic-form.standard.required': 'Please enter a metric',
+ 'form.basic-form.client.label': 'Client',
+ 'form.basic-form.label.tooltip': 'Target service object',
+ 'form.basic-form.client.placeholder':
+ 'Please describe your customer service, internal customers directly @ Name / job number',
+ 'form.basic-form.client.required': 'Please describe the customers you serve',
+ 'form.basic-form.invites.label': 'Inviting critics',
+ 'form.basic-form.invites.placeholder':
+ 'Please direct @ Name / job number, you can invite up to 5 people',
+ 'form.basic-form.weight.label': 'Weight',
+ 'form.basic-form.weight.placeholder': 'Please enter weight',
+ 'form.basic-form.public.label': 'Target disclosure',
+ 'form.basic-form.label.help': 'Customers and invitees are shared by default',
+ 'form.basic-form.radio.public': 'Public',
+ 'form.basic-form.radio.partially-public': 'Partially public',
+ 'form.basic-form.radio.private': 'Private',
+ 'form.basic-form.publicUsers.placeholder': 'Open to',
+ 'form.basic-form.option.A': 'Colleague A',
+ 'form.basic-form.option.B': 'Colleague B',
+ 'form.basic-form.option.C': 'Colleague C',
+ 'form.basic-form.email.required': 'Please enter your email!',
+ 'form.basic-form.email.wrong-format': 'The email address is in the wrong format!',
+ 'form.basic-form.userName.required': 'Please enter your userName!',
+ 'form.basic-form.password.required': 'Please enter your password!',
+ 'form.basic-form.password.twice': 'The passwords entered twice do not match!',
+ 'form.basic-form.strength.msg':
+ "Please enter at least 6 characters and don't use passwords that are easy to guess.",
+ 'form.basic-form.strength.strong': 'Strength: strong',
+ 'form.basic-form.strength.medium': 'Strength: medium',
+ 'form.basic-form.strength.short': 'Strength: too short',
+ 'form.basic-form.confirm-password.required': 'Please confirm your password!',
+ 'form.basic-form.phone-number.required': 'Please enter your phone number!',
+ 'form.basic-form.phone-number.wrong-format': 'Malformed phone number!',
+ 'form.basic-form.verification-code.required': 'Please enter the verification code!',
+ 'form.basic-form.form.get-captcha': 'Get Captcha',
+ 'form.basic-form.captcha.second': 'sec',
+ 'form.basic-form.form.optional': ' (optional) ',
+ 'form.basic-form.form.submit': 'Submit',
+ 'form.basic-form.form.save': 'Save',
+ 'form.basic-form.email.placeholder': 'Email',
+ 'form.basic-form.password.placeholder': 'Password',
+ 'form.basic-form.confirm-password.placeholder': 'Confirm password',
+ 'form.basic-form.phone-number.placeholder': 'Phone number',
+ 'form.basic-form.verification-code.placeholder': 'Verification code'
+}
diff --git a/src/locales/lang/en-US/global.js b/src/locales/lang/en-US/global.js
new file mode 100644
index 0000000..1b0a940
--- /dev/null
+++ b/src/locales/lang/en-US/global.js
@@ -0,0 +1,6 @@
+export default {
+ submit: 'Submit',
+ save: 'Save',
+ 'submit.ok': 'Submit successfully',
+ 'save.ok': 'Saved successfully'
+}
diff --git a/src/locales/lang/en-US/menu.js b/src/locales/lang/en-US/menu.js
new file mode 100644
index 0000000..b3d73ea
--- /dev/null
+++ b/src/locales/lang/en-US/menu.js
@@ -0,0 +1,39 @@
+export default {
+ 'menu.welcome': 'Welcome',
+ 'menu.home': 'Home',
+ 'menu.dashboard': 'Dashboard',
+ 'menu.dashboard.analysis': 'Analysis',
+ 'menu.dashboard.monitor': 'Monitor',
+ 'menu.dashboard.workplace': 'Workplace',
+ 'menu.form': 'Form',
+ 'menu.form.basic-form': 'Basic Form',
+ 'menu.form.step-form': 'Step Form',
+ 'menu.form.step-form.info': 'Step Form(write transfer information)',
+ 'menu.form.step-form.confirm': 'Step Form(confirm transfer information)',
+ 'menu.form.step-form.result': 'Step Form(finished)',
+ 'menu.form.advanced-form': 'Advanced Form',
+ 'menu.list': 'List',
+ 'menu.list.table-list': 'Search Table',
+ 'menu.list.basic-list': 'Basic List',
+ 'menu.list.card-list': 'Card List',
+ 'menu.list.search-list': 'Search List',
+ 'menu.list.search-list.articles': 'Search List(articles)',
+ 'menu.list.search-list.projects': 'Search List(projects)',
+ 'menu.list.search-list.applications': 'Search List(applications)',
+ 'menu.profile': 'Profile',
+ 'menu.profile.basic': 'Basic Profile',
+ 'menu.profile.advanced': 'Advanced Profile',
+ 'menu.result': 'Result',
+ 'menu.result.success': 'Success',
+ 'menu.result.fail': 'Fail',
+ 'menu.exception': 'Exception',
+ 'menu.exception.not-permission': '403',
+ 'menu.exception.not-find': '404',
+ 'menu.exception.server-error': '500',
+ 'menu.exception.trigger': 'Trigger',
+ 'menu.account': 'Account',
+ 'menu.account.center': 'Account Center',
+ 'menu.account.settings': 'Account Settings',
+ 'menu.account.trigger': 'Trigger Error',
+ 'menu.account.logout': 'Logout'
+}
diff --git a/src/locales/lang/en-US/result.js b/src/locales/lang/en-US/result.js
new file mode 100644
index 0000000..75d3a4d
--- /dev/null
+++ b/src/locales/lang/en-US/result.js
@@ -0,0 +1,7 @@
+import success from './result/success'
+import fail from './result/fail'
+
+export default {
+ ...success,
+ ...fail
+ }
diff --git a/src/locales/lang/en-US/result/fail.js b/src/locales/lang/en-US/result/fail.js
new file mode 100644
index 0000000..168909c
--- /dev/null
+++ b/src/locales/lang/en-US/result/fail.js
@@ -0,0 +1,11 @@
+export default {
+ 'result.fail.error.title': 'Submission Failed',
+ 'result.fail.error.description':
+ 'Please check and modify the following information before resubmitting.',
+ 'result.fail.error.hint-title': 'The content you submitted has the following error:',
+ 'result.fail.error.hint-text1': 'Your account has been frozen',
+ 'result.fail.error.hint-btn1': 'Thaw immediately',
+ 'result.fail.error.hint-text2': 'Your account is not yet eligible to apply',
+ 'result.fail.error.hint-btn2': 'Upgrade immediately',
+ 'result.fail.error.btn-text': 'Return to modify'
+}
diff --git a/src/locales/lang/en-US/result/success.js b/src/locales/lang/en-US/result/success.js
new file mode 100644
index 0000000..fad6c1d
--- /dev/null
+++ b/src/locales/lang/en-US/result/success.js
@@ -0,0 +1,19 @@
+export default {
+ 'result.success.title': 'Submission Success',
+ 'result.success.description':
+ '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.',
+ 'result.success.operate-title': 'Project Name',
+ 'result.success.operate-id': 'Project ID',
+ 'result.success.principal': 'Principal',
+ 'result.success.operate-time': 'Effective time',
+ 'result.success.step1-title': 'Create project',
+ 'result.success.step1-operator': 'Qu Lili',
+ 'result.success.step2-title': 'Departmental preliminary review',
+ 'result.success.step2-operator': 'Zhou Maomao',
+ 'result.success.step2-extra': 'Urge',
+ 'result.success.step3-title': 'Financial review',
+ 'result.success.step4-title': 'Finish',
+ 'result.success.btn-return': 'Back List',
+ 'result.success.btn-project': 'View Project',
+ 'result.success.btn-print': 'Print'
+}
diff --git a/src/locales/lang/en-US/setting.js b/src/locales/lang/en-US/setting.js
new file mode 100644
index 0000000..f42ce9f
--- /dev/null
+++ b/src/locales/lang/en-US/setting.js
@@ -0,0 +1,29 @@
+export default {
+ 'app.setting.pagestyle': 'Page style setting',
+ 'app.setting.pagestyle.light': 'Light style',
+ 'app.setting.pagestyle.dark': 'Dark style',
+ 'app.setting.pagestyle.realdark': 'RealDark style',
+ 'app.setting.themecolor': 'Theme Color',
+ 'app.setting.navigationmode': 'Navigation Mode',
+ 'app.setting.content-width': 'Content Width',
+ 'app.setting.fixedheader': 'Fixed Header',
+ 'app.setting.fixedsidebar': 'Fixed Sidebar',
+ 'app.setting.sidemenu': 'Side Menu Layout',
+ 'app.setting.topmenu': 'Top Menu Layout',
+ 'app.setting.content-width.fixed': 'Fixed',
+ 'app.setting.content-width.fluid': 'Fluid',
+ 'app.setting.othersettings': 'Other Settings',
+ 'app.setting.weakmode': 'Weak Mode',
+ 'app.setting.copy': 'Copy Setting',
+ 'app.setting.loading': 'Loading theme',
+ 'app.setting.copyinfo': 'copy success,please replace defaultSettings in src/config/defaultSettings.js',
+ 'app.setting.production.hint': 'Setting panel shows in development environment only, please manually modify',
+ 'app.setting.themecolor.daybreak': 'Daybreak Blue',
+ 'app.setting.themecolor.dust': 'Dust Red',
+ 'app.setting.themecolor.volcano': 'Volcano',
+ 'app.setting.themecolor.sunset': 'Sunset Orange',
+ 'app.setting.themecolor.cyan': 'Cyan',
+ 'app.setting.themecolor.green': 'Polar Green',
+ 'app.setting.themecolor.geekblue': 'Geek Blue',
+ 'app.setting.themecolor.purple': 'Golden Purple'
+}
diff --git a/src/locales/lang/en-US/user.js b/src/locales/lang/en-US/user.js
new file mode 100644
index 0000000..561210c
--- /dev/null
+++ b/src/locales/lang/en-US/user.js
@@ -0,0 +1,45 @@
+export default {
+ 'user.login.userName': 'userName',
+ 'user.login.password': 'password',
+ 'user.login.username.placeholder': 'Account: admin',
+ 'user.login.password.placeholder': 'password: admin or ant.design',
+ 'user.login.message-invalid-credentials':
+ 'Invalid username or password(admin/ant.design)',
+ 'user.login.message-invalid-verification-code': 'Invalid verification code',
+ 'user.login.tab-login-credentials': 'Credentials',
+ 'user.login.tab-login-mobile': 'Mobile number',
+ 'user.login.mobile.placeholder': 'Mobile number',
+ 'user.login.mobile.verification-code.placeholder': 'Verification code',
+ 'user.login.remember-me': 'Remember me',
+ 'user.login.forgot-password': 'Forgot your password?',
+ 'user.login.sign-in-with': 'Sign in with',
+ 'user.login.signup': 'Sign up',
+ 'user.login.login': 'Login',
+ 'user.register.register': 'Register',
+ 'user.register.email.placeholder': 'Email',
+ 'user.register.password.placeholder': 'Password ',
+ 'user.register.password.popover-message': 'Please enter at least 6 characters. Please do not use passwords that are easy to guess. ',
+ 'user.register.confirm-password.placeholder': 'Confirm password',
+ 'user.register.get-verification-code': 'Get code',
+ 'user.register.sign-in': 'Already have an account?',
+ 'user.register-result.msg': 'Account:registered at {email}',
+ 'user.register-result.activation-email':
+ '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.',
+ 'user.register-result.back-home': 'Back to home',
+ 'user.register-result.view-mailbox': 'View mailbox',
+ 'user.email.required': 'Please enter your email!',
+ 'user.email.wrong-format': 'The email address is in the wrong format!',
+ 'user.userName.required': 'Please enter account name or email address',
+ 'user.password.required': 'Please enter your password!',
+ 'user.password.twice.msg': 'The passwords entered twice do not match!',
+ 'user.password.strength.msg':
+ 'The password is not strong enough',
+ 'user.password.strength.strong': 'Strength: strong',
+ 'user.password.strength.medium': 'Strength: medium',
+ 'user.password.strength.low': 'Strength: low',
+ 'user.password.strength.short': 'Strength: too short',
+ 'user.confirm-password.required': 'Please confirm your password!',
+ 'user.phone-number.required': 'Please enter your phone number!',
+ 'user.phone-number.wrong-format': 'Please enter a valid phone number',
+ 'user.verification-code.required': 'Please enter the verification code!'
+}
diff --git a/src/locales/lang/zh-CN.js b/src/locales/lang/zh-CN.js
new file mode 100644
index 0000000..111eab4
--- /dev/null
+++ b/src/locales/lang/zh-CN.js
@@ -0,0 +1,34 @@
+import antd from 'ant-design-vue/es/locale-provider/zh_CN'
+import momentCN from 'moment/locale/zh-cn'
+import global from './zh-CN/global'
+
+import menu from './zh-CN/menu'
+import setting from './zh-CN/setting'
+import user from './zh-CN/user'
+import dashboard from './zh-CN/dashboard'
+import form from './zh-CN/form'
+import result from './zh-CN/result'
+import account from './zh-CN/account'
+
+const components = {
+ antLocale: antd,
+ momentName: 'zh-cn',
+ momentLocale: momentCN
+}
+
+export default {
+ message: '-',
+
+ 'layouts.usermenu.dialog.title': '信息',
+ 'layouts.usermenu.dialog.content': '您确定要注销吗?',
+ 'layouts.userLayout.title': 'Ant Design 是西湖区最具影响力的 Web 设计规范',
+ ...components,
+ ...global,
+ ...menu,
+ ...setting,
+ ...user,
+ ...dashboard,
+ ...form,
+ ...result,
+ ...account
+}
diff --git a/src/locales/lang/zh-CN/account.js b/src/locales/lang/zh-CN/account.js
new file mode 100644
index 0000000..65a4774
--- /dev/null
+++ b/src/locales/lang/zh-CN/account.js
@@ -0,0 +1,5 @@
+import settings from './account/settings'
+
+export default {
+ ...settings
+ }
diff --git a/src/locales/lang/zh-CN/account/settings.js b/src/locales/lang/zh-CN/account/settings.js
new file mode 100644
index 0000000..c6c2eac
--- /dev/null
+++ b/src/locales/lang/zh-CN/account/settings.js
@@ -0,0 +1,57 @@
+export default {
+ 'account.settings.menuMap.basic': '基本设置',
+ 'account.settings.menuMap.security': '安全设置',
+ 'account.settings.menuMap.custom': '个性化',
+ 'account.settings.menuMap.binding': '账号绑定',
+ 'account.settings.menuMap.notification': '新消息通知',
+ 'account.settings.basic.avatar': '头像',
+ 'account.settings.basic.change-avatar': '更换头像',
+ 'account.settings.basic.email': '邮箱',
+ 'account.settings.basic.email-message': '请输入您的邮箱!',
+ 'account.settings.basic.nickname': '昵称',
+ 'account.settings.basic.nickname-message': '请输入您的昵称!',
+ 'account.settings.basic.profile': '个人简介',
+ 'account.settings.basic.profile-message': '请输入个人简介!',
+ 'account.settings.basic.profile-placeholder': '个人简介',
+ 'account.settings.basic.country': '国家/地区',
+ 'account.settings.basic.country-message': '请输入您的国家或地区!',
+ 'account.settings.basic.geographic': '所在省市',
+ 'account.settings.basic.geographic-message': '请输入您的所在省市!',
+ 'account.settings.basic.address': '街道地址',
+ 'account.settings.basic.address-message': '请输入您的街道地址!',
+ 'account.settings.basic.phone': '联系电话',
+ 'account.settings.basic.phone-message': '请输入您的联系电话!',
+ 'account.settings.basic.update': '更新基本信息',
+ 'account.settings.basic.update.success': '更新基本信息成功',
+ 'account.settings.security.strong': '强',
+ 'account.settings.security.medium': '中',
+ 'account.settings.security.weak': '弱',
+ 'account.settings.security.password': '账户密码',
+ 'account.settings.security.password-description': '当前密码强度:',
+ 'account.settings.security.phone': '密保手机',
+ 'account.settings.security.phone-description': '已绑定手机:',
+ 'account.settings.security.question': '密保问题',
+ 'account.settings.security.question-description': '未设置密保问题,密保问题可有效保护账户安全',
+ 'account.settings.security.email': '备用邮箱',
+ 'account.settings.security.email-description': '已绑定邮箱:',
+ 'account.settings.security.mfa': 'MFA 设备',
+ 'account.settings.security.mfa-description': '未绑定 MFA 设备,绑定后,可以进行二次确认',
+ 'account.settings.security.modify': '修改',
+ 'account.settings.security.set': '设置',
+ 'account.settings.security.bind': '绑定',
+ 'account.settings.binding.taobao': '绑定淘宝',
+ 'account.settings.binding.taobao-description': '当前未绑定淘宝账号',
+ 'account.settings.binding.alipay': '绑定支付宝',
+ 'account.settings.binding.alipay-description': '当前未绑定支付宝账号',
+ 'account.settings.binding.dingding': '绑定钉钉',
+ 'account.settings.binding.dingding-description': '当前未绑定钉钉账号',
+ 'account.settings.binding.bind': '绑定',
+ 'account.settings.notification.password': '账户密码',
+ 'account.settings.notification.password-description': '其他用户的消息将以站内信的形式通知',
+ 'account.settings.notification.messages': '系统消息',
+ 'account.settings.notification.messages-description': '系统消息将以站内信的形式通知',
+ 'account.settings.notification.todo': '待办任务',
+ 'account.settings.notification.todo-description': '待办任务将以站内信的形式通知',
+ 'account.settings.settings.open': '开',
+ 'account.settings.settings.close': '关'
+}
diff --git a/src/locales/lang/zh-CN/dashboard.js b/src/locales/lang/zh-CN/dashboard.js
new file mode 100644
index 0000000..9d40892
--- /dev/null
+++ b/src/locales/lang/zh-CN/dashboard.js
@@ -0,0 +1,5 @@
+import analysis from './dashboard/analysis'
+
+export default {
+ ...analysis
+ }
diff --git a/src/locales/lang/zh-CN/dashboard/analysis.js b/src/locales/lang/zh-CN/dashboard/analysis.js
new file mode 100644
index 0000000..b34f6a6
--- /dev/null
+++ b/src/locales/lang/zh-CN/dashboard/analysis.js
@@ -0,0 +1,36 @@
+export default {
+ 'dashboard.analysis.test': '工专路 {no} 号店',
+ 'dashboard.analysis.introduce': '指标说明',
+ 'dashboard.analysis.total-sales': '总销售额',
+ 'dashboard.analysis.day-sales': '日均销售额¥',
+ 'dashboard.analysis.visits': '访问量',
+ 'dashboard.analysis.visits-trend': '访问量趋势',
+ 'dashboard.analysis.visits-ranking': '门店访问量排名',
+ 'dashboard.analysis.day-visits': '日访问量',
+ 'dashboard.analysis.week': '周同比',
+ 'dashboard.analysis.day': '日同比',
+ 'dashboard.analysis.payments': '支付笔数',
+ 'dashboard.analysis.conversion-rate': '转化率',
+ 'dashboard.analysis.operational-effect': '运营活动效果',
+ 'dashboard.analysis.sales-trend': '销售趋势',
+ 'dashboard.analysis.sales-ranking': '门店销售额排名',
+ 'dashboard.analysis.all-year': '全年',
+ 'dashboard.analysis.all-month': '本月',
+ 'dashboard.analysis.all-week': '本周',
+ 'dashboard.analysis.all-day': '今日',
+ 'dashboard.analysis.search-users': '搜索用户数',
+ 'dashboard.analysis.per-capita-search': '人均搜索次数',
+ 'dashboard.analysis.online-top-search': '线上热门搜索',
+ 'dashboard.analysis.the-proportion-of-sales': '销售额类别占比',
+ 'dashboard.analysis.dropdown-option-one': '操作一',
+ 'dashboard.analysis.dropdown-option-two': '操作二',
+ 'dashboard.analysis.channel.all': '全部渠道',
+ 'dashboard.analysis.channel.online': '线上',
+ 'dashboard.analysis.channel.stores': '门店',
+ 'dashboard.analysis.sales': '销售额',
+ 'dashboard.analysis.traffic': '客流量',
+ 'dashboard.analysis.table.rank': '排名',
+ 'dashboard.analysis.table.search-keyword': '搜索关键词',
+ 'dashboard.analysis.table.users': '用户数',
+ 'dashboard.analysis.table.weekly-range': '周涨幅'
+}
diff --git a/src/locales/lang/zh-CN/form.js b/src/locales/lang/zh-CN/form.js
new file mode 100644
index 0000000..d004e52
--- /dev/null
+++ b/src/locales/lang/zh-CN/form.js
@@ -0,0 +1,5 @@
+import basicForm from './form/basicForm'
+
+export default {
+ ...basicForm
+ }
diff --git a/src/locales/lang/zh-CN/form/basicForm.js b/src/locales/lang/zh-CN/form/basicForm.js
new file mode 100644
index 0000000..7941075
--- /dev/null
+++ b/src/locales/lang/zh-CN/form/basicForm.js
@@ -0,0 +1,58 @@
+export default {
+ 'form.basic-form.basic.title': '基础表单',
+ 'form.basic-form.basic.description':
+ '表单页用于向用户收集或验证信息,基础表单常见于数据项较少的表单场景。',
+ 'form.basic-form.title.label': '标题',
+ 'form.basic-form.title.placeholder': '给目标起个名字',
+ 'form.basic-form.title.required': '请输入标题',
+ 'form.basic-form.date.label': '起止日期',
+ 'form.basic-form.placeholder.start': '开始日期',
+ 'form.basic-form.placeholder.end': '结束日期',
+ 'form.basic-form.date.required': '请选择起止日期',
+ 'form.basic-form.goal.label': '目标描述',
+ 'form.basic-form.goal.placeholder': '请输入你的阶段性工作目标',
+ 'form.basic-form.goal.required': '请输入目标描述',
+ 'form.basic-form.standard.label': '衡量标准',
+ 'form.basic-form.standard.placeholder': '请输入衡量标准',
+ 'form.basic-form.standard.required': '请输入衡量标准',
+ 'form.basic-form.client.label': '客户',
+ 'form.basic-form.client.required': '请描述你服务的客户',
+ 'form.basic-form.label.tooltip': '目标的服务对象',
+ 'form.basic-form.client.placeholder': '请描述你服务的客户,内部客户直接 @姓名/工号',
+ 'form.basic-form.invites.label': '邀评人',
+ 'form.basic-form.invites.placeholder': '请直接 @姓名/工号,最多可邀请 5 人',
+ 'form.basic-form.weight.label': '权重',
+ 'form.basic-form.weight.placeholder': '请输入',
+ 'form.basic-form.public.label': '目标公开',
+ 'form.basic-form.label.help': '客户、邀评人默认被分享',
+ 'form.basic-form.radio.public': '公开',
+ 'form.basic-form.radio.partially-public': '部分公开',
+ 'form.basic-form.radio.private': '不公开',
+ 'form.basic-form.publicUsers.placeholder': '公开给',
+ 'form.basic-form.option.A': '同事一',
+ 'form.basic-form.option.B': '同事二',
+ 'form.basic-form.option.C': '同事三',
+ 'form.basic-form.email.required': '请输入邮箱地址!',
+ 'form.basic-form.email.wrong-format': '邮箱地址格式错误!',
+ 'form.basic-form.userName.required': '请输入用户名!',
+ 'form.basic-form.password.required': '请输入密码!',
+ 'form.basic-form.password.twice': '两次输入的密码不匹配!',
+ 'form.basic-form.strength.msg': '请至少输入 6 个字符。请不要使用容易被猜到的密码。',
+ 'form.basic-form.strength.strong': '强度:强',
+ 'form.basic-form.strength.medium': '强度:中',
+ 'form.basic-form.strength.short': '强度:太短',
+ 'form.basic-form.confirm-password.required': '请确认密码!',
+ 'form.basic-form.phone-number.required': '请输入手机号!',
+ 'form.basic-form.phone-number.wrong-format': '手机号格式错误!',
+ 'form.basic-form.verification-code.required': '请输入验证码!',
+ 'form.basic-form.form.get-captcha': '获取验证码',
+ 'form.basic-form.captcha.second': '秒',
+ 'form.basic-form.form.optional': '(选填)',
+ 'form.basic-form.form.submit': '提交',
+ 'form.basic-form.form.save': '保存',
+ 'form.basic-form.email.placeholder': '邮箱',
+ 'form.basic-form.password.placeholder': '至少6位密码,区分大小写',
+ 'form.basic-form.confirm-password.placeholder': '确认密码',
+ 'form.basic-form.phone-number.placeholder': '手机号',
+ 'form.basic-form.verification-code.placeholder': '验证码'
+}
diff --git a/src/locales/lang/zh-CN/global.js b/src/locales/lang/zh-CN/global.js
new file mode 100644
index 0000000..d4a32d6
--- /dev/null
+++ b/src/locales/lang/zh-CN/global.js
@@ -0,0 +1,6 @@
+export default {
+ submit: '提交',
+ save: '保存',
+ 'submit.ok': '提交成功',
+ 'save.ok': '保存成功'
+}
diff --git a/src/locales/lang/zh-CN/menu.js b/src/locales/lang/zh-CN/menu.js
new file mode 100644
index 0000000..8900c44
--- /dev/null
+++ b/src/locales/lang/zh-CN/menu.js
@@ -0,0 +1,39 @@
+export default {
+ 'menu.welcome': '欢迎',
+ 'menu.home': '主页',
+ 'menu.dashboard': '仪表盘',
+ 'menu.dashboard.analysis': '分析页',
+ 'menu.dashboard.monitor': '监控页',
+ 'menu.dashboard.workplace': '工作台',
+ 'menu.form': '表单页',
+ 'menu.form.basic-form': '基础表单',
+ 'menu.form.step-form': '分步表单',
+ 'menu.form.step-form.info': '分步表单(填写转账信息)',
+ 'menu.form.step-form.confirm': '分步表单(确认转账信息)',
+ 'menu.form.step-form.result': '分步表单(完成)',
+ 'menu.form.advanced-form': '高级表单',
+ 'menu.list': '列表页',
+ 'menu.list.table-list': '查询表格',
+ 'menu.list.basic-list': '标准列表',
+ 'menu.list.card-list': '卡片列表',
+ 'menu.list.search-list': '搜索列表',
+ 'menu.list.search-list.articles': '搜索列表(文章)',
+ 'menu.list.search-list.projects': '搜索列表(项目)',
+ 'menu.list.search-list.applications': '搜索列表(应用)',
+ 'menu.profile': '详情页',
+ 'menu.profile.basic': '基础详情页',
+ 'menu.profile.advanced': '高级详情页',
+ 'menu.result': '结果页',
+ 'menu.result.success': '成功页',
+ 'menu.result.fail': '失败页',
+ 'menu.exception': '异常页',
+ 'menu.exception.not-permission': '403',
+ 'menu.exception.not-find': '404',
+ 'menu.exception.server-error': '500',
+ 'menu.exception.trigger': '触发错误',
+ 'menu.account': '个人页',
+ 'menu.account.center': '个人中心',
+ 'menu.account.settings': '个人设置',
+ 'menu.account.trigger': '触发报错',
+ 'menu.account.logout': '退出登录'
+}
diff --git a/src/locales/lang/zh-CN/result.js b/src/locales/lang/zh-CN/result.js
new file mode 100644
index 0000000..75d3a4d
--- /dev/null
+++ b/src/locales/lang/zh-CN/result.js
@@ -0,0 +1,7 @@
+import success from './result/success'
+import fail from './result/fail'
+
+export default {
+ ...success,
+ ...fail
+ }
diff --git a/src/locales/lang/zh-CN/result/fail.js b/src/locales/lang/zh-CN/result/fail.js
new file mode 100644
index 0000000..a9279e1
--- /dev/null
+++ b/src/locales/lang/zh-CN/result/fail.js
@@ -0,0 +1,10 @@
+export default {
+ 'result.fail.error.title': '提交失败',
+ 'result.fail.error.description': '请核对并修改以下信息后,再重新提交。',
+ 'result.fail.error.hint-title': '您提交的内容有如下错误:',
+ 'result.fail.error.hint-text1': '您的账户已被冻结',
+ 'result.fail.error.hint-btn1': '立即解冻',
+ 'result.fail.error.hint-text2': '您的账户还不具备申请资格',
+ 'result.fail.error.hint-btn2': '立即升级',
+ 'result.fail.error.btn-text': '返回修改'
+}
diff --git a/src/locales/lang/zh-CN/result/success.js b/src/locales/lang/zh-CN/result/success.js
new file mode 100644
index 0000000..bd18f9f
--- /dev/null
+++ b/src/locales/lang/zh-CN/result/success.js
@@ -0,0 +1,19 @@
+export default {
+ 'result.success.title': '提交成功',
+ 'result.success.description':
+ '提交结果页用于反馈一系列操作任务的处理结果, 如果仅是简单操作,使用 Message 全局提示反馈即可。 本文字区域可以展示简单的补充说明,如果有类似展示 “单据”的需求,下面这个灰色区域可以呈现比较复杂的内容。',
+ 'result.success.operate-title': '项目名称',
+ 'result.success.operate-id': '项目 ID',
+ 'result.success.principal': '负责人',
+ 'result.success.operate-time': '生效时间',
+ 'result.success.step1-title': '创建项目',
+ 'result.success.step1-operator': '曲丽丽',
+ 'result.success.step2-title': '部门初审',
+ 'result.success.step2-operator': '周毛毛',
+ 'result.success.step2-extra': '催一下',
+ 'result.success.step3-title': '财务复核',
+ 'result.success.step4-title': '完成',
+ 'result.success.btn-return': '返回列表',
+ 'result.success.btn-project': '查看项目',
+ 'result.success.btn-print': '打印'
+}
diff --git a/src/locales/lang/zh-CN/setting.js b/src/locales/lang/zh-CN/setting.js
new file mode 100644
index 0000000..0166d0b
--- /dev/null
+++ b/src/locales/lang/zh-CN/setting.js
@@ -0,0 +1,29 @@
+export default {
+ 'app.setting.pagestyle': '整体风格设置',
+ 'app.setting.pagestyle.light': '亮色菜单风格',
+ 'app.setting.pagestyle.dark': '暗色菜单风格',
+ 'app.setting.pagestyle.realdark': '暗黑模式',
+ 'app.setting.themecolor': '主题色',
+ 'app.setting.navigationmode': '导航模式',
+ 'app.setting.content-width': '内容区域宽度',
+ 'app.setting.fixedheader': '固定 Header',
+ 'app.setting.fixedsidebar': '固定侧边栏',
+ 'app.setting.sidemenu': '侧边菜单布局',
+ 'app.setting.topmenu': '顶部菜单布局',
+ 'app.setting.content-width.fixed': 'Fixed',
+ 'app.setting.content-width.fluid': 'Fluid',
+ 'app.setting.othersettings': '其他设置',
+ 'app.setting.weakmode': '色弱模式',
+ 'app.setting.copy': '拷贝设置',
+ 'app.setting.loading': '加载主题中',
+ 'app.setting.copyinfo': '拷贝设置成功 src/config/defaultSettings.js',
+ 'app.setting.production.hint': '配置栏只在开发环境用于预览,生产环境不会展现,请拷贝后手动修改配置文件',
+ 'app.setting.themecolor.daybreak': '拂晓蓝',
+ 'app.setting.themecolor.dust': '薄暮',
+ 'app.setting.themecolor.volcano': '火山',
+ 'app.setting.themecolor.sunset': '日暮',
+ 'app.setting.themecolor.cyan': '明青',
+ 'app.setting.themecolor.green': '极光绿',
+ 'app.setting.themecolor.geekblue': '极客蓝',
+ 'app.setting.themecolor.purple': '酱紫'
+}
diff --git a/src/locales/lang/zh-CN/user.js b/src/locales/lang/zh-CN/user.js
new file mode 100644
index 0000000..37731d9
--- /dev/null
+++ b/src/locales/lang/zh-CN/user.js
@@ -0,0 +1,43 @@
+export default {
+ 'user.login.userName': '用户名',
+ 'user.login.password': '密码',
+ 'user.login.username.placeholder': '账户: admin',
+ 'user.login.password.placeholder': '密码: admin or ant.design',
+ 'user.login.message-invalid-credentials': '账户或密码错误(admin/ant.design)',
+ 'user.login.message-invalid-verification-code': '验证码错误',
+ 'user.login.tab-login-credentials': '账户密码登录',
+ 'user.login.tab-login-mobile': '手机号登录',
+ 'user.login.mobile.placeholder': '手机号',
+ 'user.login.mobile.verification-code.placeholder': '验证码',
+ 'user.login.remember-me': '自动登录',
+ 'user.login.forgot-password': '忘记密码',
+ 'user.login.sign-in-with': '其他登录方式',
+ 'user.login.signup': '注册账户',
+ 'user.login.login': '登录',
+ 'user.register.register': '注册',
+ 'user.register.email.placeholder': '邮箱',
+ 'user.register.password.placeholder': '请至少输入 6 个字符。请不要使用容易被猜到的密码。',
+ 'user.register.password.popover-message': '请至少输入 6 个字符。请不要使用容易被猜到的密码。',
+ 'user.register.confirm-password.placeholder': '确认密码',
+ 'user.register.get-verification-code': '获取验证码',
+ 'user.register.sign-in': '使用已有账户登录',
+ 'user.register-result.msg': '你的账户:{email} 注册成功',
+ 'user.register-result.activation-email':
+ '激活邮件已发送到你的邮箱中,邮件有效期为24小时。请及时登录邮箱,点击邮件中的链接激活帐户。',
+ 'user.register-result.back-home': '返回首页',
+ 'user.register-result.view-mailbox': '查看邮箱',
+ 'user.email.required': '请输入邮箱地址!',
+ 'user.email.wrong-format': '邮箱地址格式错误!',
+ 'user.userName.required': '请输入帐户名或邮箱地址',
+ 'user.password.required': '请输入密码!',
+ 'user.password.twice.msg': '两次输入的密码不匹配!',
+ 'user.password.strength.msg': '密码强度不够 ',
+ 'user.password.strength.strong': '强度:强',
+ 'user.password.strength.medium': '强度:中',
+ 'user.password.strength.low': '强度:低',
+ 'user.password.strength.short': '强度:太短',
+ 'user.confirm-password.required': '请确认密码!',
+ 'user.phone-number.required': '请输入正确的手机号',
+ 'user.phone-number.wrong-format': '手机号格式错误!',
+ 'user.verification-code.required': '请输入验证码!'
+}
diff --git a/src/main.js b/src/main.js
new file mode 100644
index 0000000..f0621d4
--- /dev/null
+++ b/src/main.js
@@ -0,0 +1,69 @@
+// with polyfills
+import 'core-js/stable'
+import 'regenerator-runtime/runtime'
+
+import ProLayout from '@ant-design-vue/pro-layout'
+import PageHeaderWrapper from '@/components/PageContainer/Index'
+import CommonButton from '@/components/CommonButton'
+import { Affix, Anchor, collapse, FormModel, rate, Tree, TreeSelect, Timeline, Empty } from 'ant-design-vue'
+import Vue from 'vue'
+import RangePicker from '@/components/RangePicker'
+import themePluginConfig from '../config/themePluginConfig'
+import App from './App.vue'
+import i18n from './locales'
+import router from './router'
+import store from './store/'
+import { VueAxios } from './utils/request'
+import useEchart from './utils/useEchart'
+
+// mock
+// WARNING: `mockjs` NOT SUPPORT `IE` PLEASE DO NOT USE IN `production` ENV.
+
+import hivekionComponents from '@/components/hivekion/index'
+import YearPicker from './components/YearPicker.vue'
+import bootstrap from './core/bootstrap'
+import './core/lazy_use' // use lazy load components
+import './global.less' // global style
+import './permission' // permission control
+import './utils/filter' // global filter
+
+import JsonViewer from 'vue-json-viewer'
+
+import contentmenu from 'v-contextmenu'
+import 'v-contextmenu/dist/index.css'
+import htmlToPdf from '@/utils/htmlToPdf'
+Vue.config.productionTip = false
+useEchart(Vue)
+Vue.use(JsonViewer) // json可视化
+Vue.use(htmlToPdf)
+// mount axios to `Vue.$http` and `this.$http`
+Vue.use(VueAxios)
+Vue.use(TreeSelect)
+Vue.use(contentmenu)
+Vue.use(Tree)
+Vue.use(collapse)
+Vue.use(Affix)
+Vue.use(Anchor)
+Vue.use(rate)
+Vue.use(FormModel)
+Vue.use(Timeline)
+Vue.use(Empty)
+Vue.use(hivekionComponents)
+// use pro-layout components
+Vue.component('pro-layout', ProLayout)
+Vue.component('page-container', PageHeaderWrapper)
+Vue.component('page-header-wrapper', PageHeaderWrapper)
+Vue.component('range-picker', RangePicker)
+Vue.component('c-button', CommonButton)
+Vue.component('year-picker', YearPicker)
+
+window.umi_plugin_ant_themeVar = themePluginConfig.theme
+
+new Vue({
+ router,
+ store,
+ i18n,
+ // init localstorage, vuex, Logo message
+ created: bootstrap,
+ render: (h) => h(App)
+}).$mount('#app')
diff --git a/src/mixins/FormModalProps.js b/src/mixins/FormModalProps.js
new file mode 100644
index 0000000..4177919
--- /dev/null
+++ b/src/mixins/FormModalProps.js
@@ -0,0 +1,50 @@
+export default {
+ props: {
+ visible: Boolean,
+ id: String,
+ initData: { type: Object, default: () => ({}) }
+ },
+ data () {
+ return {
+ labelCol: { xs: { span: 24 }, sm: { span: 6 } },
+ wrapperCol: { xs: { span: 24 }, sm: { span: 15 } },
+ model: {},
+ defaultData: {}
+ }
+ },
+ watch: {
+ visible (val) {
+ if (val) {
+ if (this.$refs.form) {
+ this.$refs.form.clearValidate()
+ }
+ this.model = {}
+ this.handleInitData()
+ } else {
+ this.$emit('close')
+ }
+ }
+ },
+ methods: {
+ handleInitData () {
+ const hasInitData = Object.keys(this.initData).length
+ this.model = hasInitData ? this.initData : { ...this.defaultData }
+ },
+ handleClose () {
+ this.$emit('update:visible', false)
+ },
+ clickOk () {
+ this.$refs.form.validate(valid => {
+ if (valid) {
+ let target = this.model
+ if (this.id) {
+ target = { ...this.model, id: this.id }
+ }
+ this.$emit('submit', target)
+ } else {
+ return false
+ }
+ })
+ }
+ }
+}
diff --git a/src/mixins/PageProps.js b/src/mixins/PageProps.js
new file mode 100644
index 0000000..b308fdc
--- /dev/null
+++ b/src/mixins/PageProps.js
@@ -0,0 +1,78 @@
+const defaultPageSize = 10
+
+export default {
+ data () {
+ return {
+ advanced: false,
+ queryParam: {}, // 查询参数
+ SortName: '',
+ paginationProps: {
+ pageSize: defaultPageSize,
+ showSizeChanger: true,
+ showQuickJumper: true,
+ current: 1,
+ pageSizeOptions: ['10', '20', '50', '100', '200'],
+ showTotal: (total) => {
+ return `共 ${total} 条`
+ }
+ },
+ visible: false, // 新增表单弹框
+ currentId: null,
+ formData: { }, // 表单编辑时的默认数据
+ loadingTable: false, // table加载
+ loadData: [] // 加载数据方法 必须为 Promise 对象
+ }
+ },
+ computed: {
+ tableQueryParam () {
+ const { current, pageSize } = this.paginationProps
+ return { ...this.queryParam, pageNum: current, pageSize, SortName: this.SortName || undefined }
+ }
+ },
+ methods: {
+ toggleAdvanced () {
+ this.advanced = !this.advanced
+ },
+ handleRangePickerChange (val) {
+ this.queryParam = { ...this.queryParam, ...val }
+ },
+ getTableIndex (idx) {
+ const { current, pageSize } = this.paginationProps
+ return ((current - 1) * pageSize) + idx + 1
+ },
+ resetQuery () {
+ this.queryParam = {}
+ this.paginationProps.current = 1
+ this.queryTable()
+ },
+ updatePagination (data) {
+ this.paginationProps = { ...this.paginationProps, ...data }
+ },
+ handleTableChange (pagination, filters, sorter) {
+ if (sorter) {
+ if (sorter.order === 'ascend') {
+ this.SortName = sorter.field + ' asc'
+ }
+ if (sorter.order === 'descend') {
+ this.SortName = sorter.field + ' desc'
+ }
+ }
+ Object.assign(this.paginationProps, pagination)
+ this.queryTable()
+ },
+ handleAdd () {
+ this.visible = true
+ },
+ handleClose () {
+ this.visible = false
+ this.currentId = null
+ this.formData = {}
+ },
+
+ // 查询按钮
+ handleSearch () {
+ this.paginationProps.current = 1
+ this.queryTable()
+ }
+ }
+}
diff --git a/src/permission.js b/src/permission.js
new file mode 100644
index 0000000..320cc06
--- /dev/null
+++ b/src/permission.js
@@ -0,0 +1,84 @@
+import '@/components/NProgress/nprogress.less' // progress bar custom style
+import { i18nRender } from '@/locales'
+import { ACCESS_TOKEN } from '@/store/mutation-types'
+import { domTitle, setDocumentTitle } from '@/utils/domUtil'
+import notification from 'ant-design-vue/es/notification'
+import NProgress from 'nprogress' // progress bar
+import storage from 'store'
+import router from './router'
+import store from './store'
+
+NProgress.configure({ showSpinner: false }) // NProgress Configuration
+
+const allowList = ['login', 'register', 'registerResult'] // no redirect allowList
+const loginRoutePath = '/user/login'
+const defaultRoutePath = '/dashboard/workplace'
+
+router.beforeEach((to, from, next) => {
+ NProgress.start() // start progress bar
+ to.meta && typeof to.meta.title !== 'undefined' && setDocumentTitle(`${i18nRender(to.meta.title)} - ${domTitle}`)
+ /* has token */
+ if (storage.get(ACCESS_TOKEN)) {
+ if (to.path === loginRoutePath) {
+ next({ path: defaultRoutePath })
+ NProgress.done()
+ } else {
+ // check login user.roles is null
+ if (store.getters.roles.length === 0) {
+ // request login userInfo
+ store
+ .dispatch('GetInfo')
+ .then(res => {
+ // generate dynamic router
+ store.dispatch('GenerateRoutes').then(() => {
+ // 根据roles权限生成可访问的路由表
+ // 动态添加可访问路由表
+ // VueRouter@3.5.0+ New API
+
+ store.getters.addRouters.forEach(r => {
+ router.addRoute(r)
+ })
+ // 请求带有 redirect 重定向时,登录自动重定向到该地址
+ let redirect = decodeURIComponent(from.query.redirect || to.path)
+ if (window.redirect) {
+ redirect = window.redirect
+ window.redirect = undefined
+ }
+ if (to.path === redirect) {
+ // set the replace: true so the navigation will not leave a history record
+ next({ ...to, replace: true })
+ } else {
+ // 跳转到目的路由
+ next({ path: redirect })
+ }
+ })
+ })
+ .catch((e) => {
+ console.log(e, 'xxxxddddd')
+ notification.error({
+ message: '错误',
+ description: '请求用户信息失败,请重试'
+ })
+ // 失败时,获取用户信息失败时,调用登出,来清空历史保留信息
+ store.dispatch('Logout').then(() => {
+ next({ path: loginRoutePath, query: { redirect: to.fullPath } })
+ })
+ })
+ } else {
+ next()
+ }
+ }
+ } else {
+ if (allowList.includes(to.name)) {
+ // 在免登录名单,直接进入
+ next()
+ } else {
+ next({ path: loginRoutePath, query: { redirect: to.fullPath } })
+ NProgress.done() // if current page is login will not trigger afterEach hook, so manually handle it
+ }
+ }
+})
+
+router.afterEach(() => {
+ NProgress.done() // finish progress bar
+})
diff --git a/src/router/README.md b/src/router/README.md
new file mode 100644
index 0000000..48b7520
--- /dev/null
+++ b/src/router/README.md
@@ -0,0 +1,134 @@
+路由/菜单说明
+====
+
+
+格式和说明
+----
+
+```ecmascript 6
+const routerObject = {
+ redirect: noredirect,
+ name: 'router-name',
+ hidden: true,
+ meta: {
+ title: 'title',
+ icon: 'a-icon',
+ target: '_blank|_self|_top|_parent',
+ keepAlive: true,
+ hiddenHeaderContent: true,
+ }
+}
+```
+
+
+
+`{ Route }` 对象
+
+| 参数 | 说明 | 类型 | 默认值 |
+| -------- | ----------------------------------------- | ------- | ------ |
+| hidden | 控制路由是否显示在 sidebar | boolean | false |
+| redirect | 重定向地址, 访问这个路由时,自定进行重定向 | string | - |
+| name | 路由名称, 必须设置,且不能重名 | string | - |
+| meta | 路由元信息(路由附带扩展信息) | object | {} |
+| hideChildrenInMenu | 强制菜单显示为Item而不是SubItem(配合 meta.hidden) | boolean | - |
+
+
+`{ Meta }` 路由元信息对象
+
+| 参数 | 说明 | 类型 | 默认值 |
+| ------------------- | ------------------------------------------------------------ | ------- | ------ |
+| title | 路由标题, 用于显示面包屑, 页面标题 *推荐设置 | string | - |
+| icon | 路由在 menu 上显示的图标 | [string,svg] | - |
+| keepAlive | 缓存该路由 | boolean | false |
+| target | 菜单链接跳转目标(参考 html a 标记) | string | - |
+| hidden | 配合`hideChildrenInMenu`使用,用于隐藏菜单时,提供递归到父菜单显示 选中菜单项_(可参考 个人页 配置方式)_ | boolean | false |
+| hiddenHeaderContent | *特殊 隐藏 [PageHeader](https://github.com/vueComponent/ant-design-vue-pro/blob/master/src/components/PageHeader/PageHeader.vue#L6) 组件中的页面带的 面包屑和页面标题栏 | boolean | false |
+| permission | 与项目提供的权限拦截匹配的权限,如果不匹配,则会被禁止访问该路由页面 | array | [] |
+
+> 路由自定义 `Icon` 请引入自定义 `svg` Icon 文件,然后传递给路由的 `meta.icon` 参数即可
+
+路由构建例子方案1
+
+路由例子
+----
+
+```ecmascript 6
+const asyncRouterMap = [
+ {
+ path: '/',
+ name: 'index',
+ component: BasicLayout,
+ meta: { title: '首页' },
+ redirect: '/dashboard/analysis',
+ children: [
+ {
+ path: '/dashboard',
+ component: RouteView,
+ name: 'dashboard',
+ redirect: '/dashboard/workplace',
+ meta: {title: '仪表盘', icon: 'dashboard', permission: ['dashboard']},
+ children: [
+ {
+ path: '/dashboard/analysis',
+ name: 'Analysis',
+ component: () => import('@/views/dashboard/Analysis'),
+ meta: {title: '分析页', permission: ['dashboard']}
+ },
+ {
+ path: '/dashboard/monitor',
+ name: 'Monitor',
+ hidden: true,
+ component: () => import('@/views/dashboard/Monitor'),
+ meta: {title: '监控页', permission: ['dashboard']}
+ },
+ {
+ path: '/dashboard/workplace',
+ name: 'Workplace',
+ component: () => import('@/views/dashboard/Workplace'),
+ meta: {title: '工作台', permission: ['dashboard']}
+ }
+ ]
+ },
+
+ // result
+ {
+ path: '/result',
+ name: 'result',
+ component: PageView,
+ redirect: '/result/success',
+ meta: { title: '结果页', icon: 'check-circle-o', permission: [ 'result' ] },
+ children: [
+ {
+ path: '/result/success',
+ name: 'ResultSuccess',
+ component: () => import(/* webpackChunkName: "result" */ '@/views/result/Success'),
+ // 该页面隐藏面包屑和页面标题栏
+ meta: { title: '成功', hiddenHeaderContent: true, permission: [ 'result' ] }
+ },
+ {
+ path: '/result/fail',
+ name: 'ResultFail',
+ component: () => import(/* webpackChunkName: "result" */ '@/views/result/Error'),
+ // 该页面隐藏面包屑和页面标题栏
+ meta: { title: '失败', hiddenHeaderContent: true, permission: [ 'result' ] }
+ }
+ ]
+ },
+ ...
+ ]
+ },
+]
+```
+
+> 1. 请注意 `component: () => import('..') ` 方式引入路由的页面组件为 懒加载模式。具体可以看 [Vue 官方文档](https://router.vuejs.org/zh/guide/advanced/lazy-loading.html)
+> 2. 增加新的路由应该增加在 '/' (index) 路由的 `children` 内
+> 3. 子路由的父级路由必须有 `router-view` 才能让子路由渲染出来,请仔细查阅 vue-router 文档
+> 4. `permission` 可以进行自定义修改,只需要对这个模块进行自定义修改即可 [src/store/modules/permission.js#L10](https://github.com/vueComponent/ant-design-vue-pro/blob/master/src/store/modules/permission.js#L10)
+
+
+附权限路由结构:
+
+![权限结构](https://static-2.loacg.com/open/static/github/permissions.png)
+
+
+第二种前端路由由后端动态生成的设计,可以前往官网文档 https://pro.antdv.com/docs/authority-management 参考
diff --git a/src/router/generator-routers.js b/src/router/generator-routers.js
new file mode 100644
index 0000000..2e4d919
--- /dev/null
+++ b/src/router/generator-routers.js
@@ -0,0 +1,236 @@
+// eslint-disable-next-line
+import * as loginService from '@/api/login'
+// eslint-disable-next-line
+import { BasicLayout, BlankLayout, PageView, RouteView } from '@/layouts'
+import { baseAdminNav } from './routeData'
+import Store from '@/store'
+
+// 前端路由表
+const constantRouterComponents = {
+ // 基础页面 layout 必须引入
+ BasicLayout: BasicLayout,
+ BlankLayout: BlankLayout,
+ RouteView: RouteView,
+ PageView: PageView,
+ 403: () => import(/* webpackChunkName: "error" */ '@/views/exception/403'),
+ 404: () => import(/* webpackChunkName: "error" */ '@/views/exception/404'),
+ 500: () => import(/* webpackChunkName: "error" */ '@/views/exception/500'),
+
+ // 你需要动态引入的页面组件
+ Workplace: () => import('@/views/dashboard/Workplace'),
+ Analysis: () => import('@/views/dashboard/Analysis'),
+
+ // form
+ BasicForm: () => import('@/views/form/basicForm'),
+ StepForm: () => import('@/views/form/stepForm/StepForm'),
+ AdvanceForm: () => import('@/views/form/advancedForm/AdvancedForm'),
+
+ // list
+ TableList: () => import('@/views/list/TableList'),
+ StandardList: () => import('@/views/list/BasicList'),
+ CardList: () => import('@/views/list/CardList'),
+ SearchLayout: () => import('@/views/list/search/SearchLayout'),
+ SearchArticles: () => import('@/views/list/search/Article'),
+ SearchProjects: () => import('@/views/list/search/Projects'),
+ SearchApplications: () => import('@/views/list/search/Applications'),
+ ProfileBasic: () => import('@/views/profile/basic'),
+ ProfileAdvanced: () => import('@/views/profile/advanced/Advanced'),
+
+ // result
+ ResultSuccess: () => import(/* webpackChunkName: "result" */ '@/views/result/Success'),
+ ResultFail: () => import(/* webpackChunkName: "result" */ '@/views/result/Error'),
+
+ // exception
+ Exception403: () => import(/* webpackChunkName: "fail" */ '@/views/exception/403'),
+ Exception404: () => import(/* webpackChunkName: "fail" */ '@/views/exception/404'),
+ Exception500: () => import(/* webpackChunkName: "fail" */ '@/views/exception/500'),
+
+ // account
+ AccountCenter: () => import('@/views/account/center'),
+ AccountSettings: () => import('@/views/account/settings/Index'),
+ BasicSetting: () => import('@/views/account/settings/BasicSetting'),
+ SecuritySettings: () => import('@/views/account/settings/Security'),
+ CustomSettings: () => import('@/views/account/settings/Custom'),
+ BindingSettings: () => import('@/views/account/settings/Binding'),
+ NotificationSettings: () => import('@/views/account/settings/Notification'),
+
+ // 'TestWork': () => import(/* webpackChunkName: "TestWork" */ '@/views/dashboard/TestWork')
+ Recheck: () => import('@/views/recheck/Index'),
+ TaskProgress: () => import('@/views/recheck/taskProgress/Index'),
+
+ // 全文检索
+ DocList: () => import('@/views/docList/Index'),
+
+ // 项目管理
+ BiddingProject: () => import ('@/views/project/biddingproject/Index'),
+ TenderProject: () => import('@/views/project/tenderproject/Index'),
+ TenderBook: () => import('@/views/project/tenderBook/Index'),
+ Backup: () => import('@/views/system/backup/Index'),
+ Conclusion: () => import('@/views/system/conclusion/Index'),
+ CheckFilter: () => import('@/views/system/checkFilter/Index'),
+ FilterWord: () => import('@/views/system/filterWord/Index'),
+
+ RecheckOtherSetting: () => import('@/views/recheckSetting/OtherSetting.vue'),
+
+ AnalysisTender: () => import('@/views/analysis/Tender.vue'),
+ AnalysisBidding: () => import('@/views/analysis/Bidding.vue'),
+ AnalysisTotal: () => import('@/views/analysis/total/Index.vue'),
+
+ // PDF解析结果
+ ParseingPdf: () => import('@/views/parseingPdf/Index.vue')
+}
+
+// 前端未找到页面路由(固定不用改)
+const notFoundRouter = {
+ path: '*',
+ redirect: '/404',
+ hidden: true
+}
+
+const addRouter = [
+ {
+ path: '/Recheck/Compare/:totalTaskId',
+ component: () => import('@/views/recheck/Compare'),
+ meta: {
+ title: '查重结果对比'
+ },
+ name: '查重结果对比',
+ hidden: true
+ }
+]
+
+// 根级菜单
+const rootRouter = {
+ key: '',
+ name: 'index',
+ path: '',
+ component: 'BasicLayout',
+ redirect: '/BiddingProject',
+ meta: {
+ title: '首页'
+ },
+ children: []
+}
+
+/**
+ * 动态生成菜单
+ * @param token
+ * @returns {Promise}
+ */
+export const generatorDynamicRouter = (token) => {
+ console.log('generatorDynamicRoute111111r')
+ return new Promise((resolve, reject) => {
+ loginService
+ .getCurrentUserNav()
+ .then((res) => {
+ console.log('generatorDynamicRouter response:', res)
+ let data = res
+ data = data.filter(item => item.status !== 2)
+ const menuNav = []
+ const childrenNav = []
+ // 后端数据, 根级树数组, 根级 PID
+ const targetList = data.filter(item => item.visible !== 0)
+ listToTree(targetList, childrenNav, '')
+ if (childrenNav.length === 0) {
+ const userInfo = Store.getters.userInfo
+ if (userInfo && userInfo.userName === 'admin') {
+ listToTree(baseAdminNav, childrenNav, '')
+ window.redirect = '/System/MenuList'
+ }
+ }
+ console.log('childrenNav', childrenNav)
+ rootRouter.children = childrenNav
+ menuNav.push(rootRouter)
+ console.log('menuNav', menuNav)
+ const routers = generator(menuNav)
+ routers.push(notFoundRouter)
+ routers[0].children = routers[0].children.concat(addRouter)
+ console.log('routers', routers)
+ resolve(routers)
+ })
+ .catch((err) => {
+ reject(err)
+ })
+ })
+}
+
+/**
+ * 格式化树形结构数据 生成 vue-router 层级路由表
+ *
+ * @param routerMap
+ * @param parent
+ * @returns {*}
+ */
+export const generator = (routerMap, parent) => {
+ return routerMap.map((item) => {
+ const { title, show, hideChildren, hiddenHeaderContent, target, icon } = item || item.meta || {}
+ console.log('xxxxxxxddddd', `${(parent && parent.path) || ''}/${item.key}`)
+ const currentRouter = {
+ // 如果路由设置了 path,则作为默认 path,否则 路由地址 动态拼接生成如 /dashboard/workplace
+ path: item.path || `${(parent && parent.path) || ''}/${item.key}`,
+ // 路由名称,建议唯一
+ name: item.name || item.key || '',
+ // 该路由对应页面的 组件 :方案1
+ // component: constantRouterComponents[item.component || item.key],
+ // 该路由对应页面的 组件 :方案2 (动态加载)
+ component: constantRouterComponents[item.component || item.key] || (() => import(`@/views/${item.component}`)),
+ hidden: item.visible === 2,
+
+ // meta: 页面标题, 菜单图标, 页面权限(供指令权限用,可去掉)
+ meta: {
+ title: title,
+ icon: icon || undefined,
+ hiddenHeaderContent: hiddenHeaderContent,
+ target: target
+ // permission: item.name
+ }
+ }
+ // 是否设置了隐藏菜单
+ if (show === false) {
+ currentRouter.hidden = true
+ }
+ // 是否设置了隐藏子菜单
+ if (hideChildren) {
+ currentRouter.hideChildrenInMenu = true
+ }
+ // 为了防止出现后端返回结果不规范,处理有可能出现拼接出两个 反斜杠
+ if (!currentRouter.path.startsWith('http')) {
+ currentRouter.path = currentRouter.path.replace('//', '/')
+ }
+ // 重定向
+ item.redirect && (currentRouter.redirect = item.redirect)
+ // 是否有子菜单,并递归处理
+ if (item.children && item.children.length > 0) {
+ // Recursion
+ currentRouter.children = generator(item.children, currentRouter)
+ }
+ return currentRouter
+ })
+}
+
+/**
+ * 数组转树形结构
+ * @param list 源数组
+ * @param tree 树
+ * @param parentId 父ID
+ */
+const listToTree = (list, tree, parentId) => {
+ list.forEach((item) => {
+ // 判断是否为父级菜单
+ if (item.parentId === parentId) {
+ const child = {
+ ...item,
+ key: item.key || item.name,
+ children: []
+ }
+ // 迭代 list, 找到当前菜单相符合的所有子菜单
+ listToTree(list, child.children, item.id)
+ // 删掉不存在 children 值的属性
+ if (child.children.length <= 0) {
+ delete child.children
+ }
+ // 加入到树中
+ tree.push(child)
+ }
+ })
+}
diff --git a/src/router/index.js b/src/router/index.js
new file mode 100644
index 0000000..afda622
--- /dev/null
+++ b/src/router/index.js
@@ -0,0 +1,17 @@
+import Vue from 'vue'
+import Router from 'vue-router'
+import { constantRouterMap } from '@/config/router.config'
+
+// hack router push callback
+const originalPush = Router.prototype.push
+Router.prototype.push = function push (location, onResolve, onReject) {
+ if (onResolve || onReject) return originalPush.call(this, location, onResolve, onReject)
+ return originalPush.call(this, location).catch(err => err)
+}
+
+Vue.use(Router)
+
+export default new Router({
+ mode: 'history',
+ routes: constantRouterMap
+})
diff --git a/src/router/routeData.js b/src/router/routeData.js
new file mode 100644
index 0000000..23d6237
--- /dev/null
+++ b/src/router/routeData.js
@@ -0,0 +1,62 @@
+export const baseAdminNav = [
+ {
+ id: '67ed94a37b03415c8ee77a8991e79745',
+ title: '系统管理',
+ key: 'System',
+ name: '系统管理',
+ component: 'RouteView',
+ redirect: '/system/userlist',
+ parentId: '',
+ icon: 'setting'
+ },
+ {
+ id: '14623b5c94824b75affe75f438ef9802',
+ title: '组织机构',
+ key: 'System',
+ name: '组织机构',
+ component: 'system/dept/deptlist',
+ redirect: null,
+ parentId: '67ed94a37b03415c8ee77a8991e79745',
+ icon: 'apartment'
+ },
+ {
+ id: '230a5ebe7cdc41acb997122d6de2d86f',
+ title: '角色管理',
+ key: 'RoleList',
+ name: '角色管理',
+ component: 'system/role/rolelist',
+ redirect: null,
+ parentId: '67ed94a37b03415c8ee77a8991e79745',
+ icon: 'audit'
+ },
+ {
+ id: '5114bf6a963f41149ab2435c86551927',
+ title: '用户管理',
+ key: 'UserList',
+ name: '用户管理',
+ component: 'system/user/list',
+ redirect: null,
+ parentId: '67ed94a37b03415c8ee77a8991e79745',
+ icon: 'user'
+ },
+ {
+ id: '1',
+ title: '菜单管理',
+ key: 'MenuList',
+ name: '菜单管理',
+ component: 'system/menu/menulist',
+ redirect: null,
+ parentId: '67ed94a37b03415c8ee77a8991e79745',
+ icon: 'windows'
+ },
+ {
+ id: '85924f8619f1451e847c9f69705f360f',
+ title: '系统日志',
+ key: 'LogList',
+ name: '系统日志',
+ component: 'system/log/loglist',
+ redirect: null,
+ parentId: '67ed94a37b03415c8ee77a8991e79745',
+ icon: 'history'
+ }
+]
diff --git a/src/store/app-mixin.js b/src/store/app-mixin.js
new file mode 100644
index 0000000..c910ae9
--- /dev/null
+++ b/src/store/app-mixin.js
@@ -0,0 +1,32 @@
+import { mapState } from 'vuex'
+
+const baseMixin = {
+ computed: {
+ ...mapState({
+ layout: state => state.app.layout,
+ navTheme: state => state.app.theme,
+ primaryColor: state => state.app.color,
+ colorWeak: state => state.app.weak,
+ fixedHeader: state => state.app.fixedHeader,
+ fixedSidebar: state => state.app.fixedSidebar,
+ contentWidth: state => state.app.contentWidth,
+ autoHideHeader: state => state.app.autoHideHeader,
+
+ isMobile: state => state.app.isMobile,
+ sideCollapsed: state => state.app.sideCollapsed,
+ multiTab: state => state.app.multiTab
+ }),
+ isTopMenu () {
+ return this.layout === 'topmenu'
+ }
+ },
+ methods: {
+ isSideMenu () {
+ return !this.isTopMenu
+ }
+ }
+}
+
+export {
+ baseMixin
+}
diff --git a/src/store/device-mixin.js b/src/store/device-mixin.js
new file mode 100644
index 0000000..2510707
--- /dev/null
+++ b/src/store/device-mixin.js
@@ -0,0 +1,11 @@
+import { mapState } from 'vuex'
+
+const deviceMixin = {
+ computed: {
+ ...mapState({
+ isMobile: state => state.app.isMobile
+ })
+ }
+}
+
+export { deviceMixin }
diff --git a/src/store/getters.js b/src/store/getters.js
new file mode 100644
index 0000000..5a5ad70
--- /dev/null
+++ b/src/store/getters.js
@@ -0,0 +1,16 @@
+const getters = {
+ isMobile: state => state.app.isMobile,
+ lang: state => state.app.lang,
+ theme: state => state.app.theme,
+ color: state => state.app.color,
+ token: state => state.user.token,
+ avatar: state => state.user.avatar,
+ nickname: state => state.user.name,
+ welcome: state => state.user.welcome,
+ roles: state => state.user.roles,
+ userInfo: state => state.user.info,
+ addRouters: state => state.permission.addRouters,
+ multiTab: state => state.app.multiTab
+}
+
+export default getters
diff --git a/src/store/i18n-mixin.js b/src/store/i18n-mixin.js
new file mode 100644
index 0000000..715b0c8
--- /dev/null
+++ b/src/store/i18n-mixin.js
@@ -0,0 +1,16 @@
+import { mapState } from 'vuex'
+
+const i18nMixin = {
+ computed: {
+ ...mapState({
+ currentLang: state => state.app.lang
+ })
+ },
+ methods: {
+ setLang (lang) {
+ this.$store.dispatch('setLang', lang)
+ }
+ }
+}
+
+export default i18nMixin
diff --git a/src/store/index.js b/src/store/index.js
new file mode 100644
index 0000000..45fd660
--- /dev/null
+++ b/src/store/index.js
@@ -0,0 +1,26 @@
+import Vue from 'vue'
+import Vuex from 'vuex'
+
+import app from './modules/app'
+import user from './modules/user'
+
+// default router permission control
+// import permission from './modules/permission'
+
+// dynamic router permission control (Experimental)
+import permission from './modules/async-router'
+import getters from './getters'
+
+Vue.use(Vuex)
+
+export default new Vuex.Store({
+ modules: {
+ app,
+ user,
+ permission
+ },
+ state: {},
+ mutations: {},
+ actions: {},
+ getters
+})
diff --git a/src/store/modules/app.js b/src/store/modules/app.js
new file mode 100644
index 0000000..11c99e2
--- /dev/null
+++ b/src/store/modules/app.js
@@ -0,0 +1,90 @@
+import { loadLanguageAsync } from '@/locales'
+import {
+ // i18n
+ APP_LANGUAGE, SIDEBAR_TYPE, TOGGLE_COLOR, TOGGLE_CONTENT_WIDTH, TOGGLE_FIXED_HEADER,
+ TOGGLE_FIXED_SIDEBAR, TOGGLE_HIDE_HEADER, TOGGLE_LAYOUT, TOGGLE_MOBILE_TYPE, TOGGLE_MULTI_TAB, TOGGLE_NAV_THEME, TOGGLE_WEAK
+} from '@/store/mutation-types'
+import storage from 'store'
+
+const app = {
+ state: {
+ sideCollapsed: false,
+ isMobile: false,
+ theme: 'dark',
+ layout: '',
+ contentWidth: '',
+ fixedHeader: false,
+ fixedSidebar: false,
+ autoHideHeader: false,
+ color: '',
+ weak: false,
+ multiTab: true,
+ // lang: 'en-US',
+ lang: 'zh-CN',
+ _antLocale: {}
+ },
+ mutations: {
+ [SIDEBAR_TYPE]: (state, type) => {
+ state.sideCollapsed = type
+ storage.set(SIDEBAR_TYPE, type)
+ },
+ [TOGGLE_MOBILE_TYPE]: (state, isMobile) => {
+ state.isMobile = isMobile
+ },
+ [TOGGLE_NAV_THEME]: (state, theme) => {
+ state.theme = theme
+ storage.set(TOGGLE_NAV_THEME, theme)
+ },
+ [TOGGLE_LAYOUT]: (state, mode) => {
+ state.layout = mode
+ storage.set(TOGGLE_LAYOUT, mode)
+ },
+ [TOGGLE_FIXED_HEADER]: (state, mode) => {
+ state.fixedHeader = mode
+ storage.set(TOGGLE_FIXED_HEADER, mode)
+ },
+ [TOGGLE_FIXED_SIDEBAR]: (state, mode) => {
+ state.fixedSidebar = mode
+ storage.set(TOGGLE_FIXED_SIDEBAR, mode)
+ },
+ [TOGGLE_CONTENT_WIDTH]: (state, type) => {
+ state.contentWidth = type
+ storage.set(TOGGLE_CONTENT_WIDTH, type)
+ },
+ [TOGGLE_HIDE_HEADER]: (state, type) => {
+ state.autoHideHeader = type
+ storage.set(TOGGLE_HIDE_HEADER, type)
+ },
+ [TOGGLE_COLOR]: (state, color) => {
+ state.color = color
+ storage.set(TOGGLE_COLOR, color)
+ },
+ [TOGGLE_WEAK]: (state, mode) => {
+ state.weak = mode
+ storage.set(TOGGLE_WEAK, mode)
+ },
+ [APP_LANGUAGE]: (state, lang, antd = {}) => {
+ state.lang = lang
+ state._antLocale = antd
+ storage.set(APP_LANGUAGE, lang)
+ },
+ [TOGGLE_MULTI_TAB]: (state, bool) => {
+ storage.set(TOGGLE_MULTI_TAB, bool)
+ state.multiTab = bool
+ }
+ },
+ actions: {
+ setLang ({ commit }, lang) {
+ return new Promise((resolve, reject) => {
+ commit(APP_LANGUAGE, lang)
+ loadLanguageAsync(lang).then(() => {
+ resolve()
+ }).catch((e) => {
+ reject(e)
+ })
+ })
+ }
+ }
+}
+
+export default app
diff --git a/src/store/modules/async-router.js b/src/store/modules/async-router.js
new file mode 100644
index 0000000..f80c306
--- /dev/null
+++ b/src/store/modules/async-router.js
@@ -0,0 +1,31 @@
+/**
+ * 向后端请求用户的菜单,动态生成路由
+ */
+import { constantRouterMap } from '@/config/router.config'
+import { generatorDynamicRouter } from '@/router/generator-routers'
+
+const permission = {
+ state: {
+ routers: constantRouterMap,
+ addRouters: []
+ },
+ mutations: {
+ SET_ROUTERS: (state, routers) => {
+ state.addRouters = routers
+ state.routers = constantRouterMap.concat(routers)
+ }
+ },
+ actions: {
+ GenerateRoutes ({ commit }) {
+ return new Promise(resolve => {
+ generatorDynamicRouter().then(routers => {
+ console.log('cccccccccccc', routers)
+ commit('SET_ROUTERS', routers)
+ resolve()
+ })
+ })
+ }
+ }
+}
+
+export default permission
diff --git a/src/store/modules/permission.js b/src/store/modules/permission.js
new file mode 100644
index 0000000..4e35d87
--- /dev/null
+++ b/src/store/modules/permission.js
@@ -0,0 +1,79 @@
+import { asyncRouterMap, constantRouterMap } from '@/config/router.config'
+import cloneDeep from 'lodash.clonedeep'
+
+/**
+ * 过滤账户是否拥有某一个权限,并将菜单从加载列表移除
+ *
+ * @param permission
+ * @param route
+ * @returns {boolean}
+ */
+function hasPermission (permission, route) {
+ if (route.meta && route.meta.permission) {
+ let flag = false
+ for (let i = 0, len = permission.length; i < len; i++) {
+ flag = route.meta.permission.includes(permission[i])
+ if (flag) {
+ return true
+ }
+ }
+ return false
+ }
+ return true
+}
+
+/**
+ * 单账户多角色时,使用该方法可过滤角色不存在的菜单
+ *
+ * @param roles
+ * @param route
+ * @returns {*}
+ */
+// eslint-disable-next-line
+function hasRole (roles, route) {
+ if (route.meta && route.meta.roles) {
+ return route.meta.roles.includes(roles.id)
+ } else {
+ return true
+ }
+}
+
+function filterAsyncRouter (routerMap, roles) {
+ const accessedRouters = routerMap.filter(route => {
+ if (hasPermission(roles.permissionList, route)) {
+ if (route.children && route.children.length) {
+ route.children = filterAsyncRouter(route.children, roles)
+ }
+ return true
+ }
+ return false
+ })
+ return accessedRouters
+}
+
+const permission = {
+ state: {
+ routers: constantRouterMap,
+ addRouters: []
+ },
+ mutations: {
+ SET_ROUTERS: (state, routers) => {
+ state.addRouters = routers
+ state.routers = constantRouterMap.concat(routers)
+ }
+ },
+ actions: {
+ GenerateRoutes ({ commit }, data) {
+ console.log('adfafadfasddf')
+ return new Promise(resolve => {
+ const { roles } = data
+ const routerMap = cloneDeep(asyncRouterMap)
+ const accessedRouters = filterAsyncRouter(routerMap, roles)
+ commit('SET_ROUTERS', accessedRouters)
+ resolve()
+ })
+ }
+ }
+}
+
+export default permission
diff --git a/src/store/modules/user.js b/src/store/modules/user.js
new file mode 100644
index 0000000..66e4497
--- /dev/null
+++ b/src/store/modules/user.js
@@ -0,0 +1,103 @@
+import { getInfo, login, logout } from '@/api/login'
+import { ACCESS_TOKEN } from '@/store/mutation-types'
+import { welcome } from '@/utils/util'
+import storage from 'store'
+
+const user = {
+ state: {
+ token: '',
+ name: '',
+ welcome: '',
+ avatar: '',
+ roles: [],
+ info: {}
+ },
+
+ mutations: {
+ SET_TOKEN: (state, token) => {
+ state.token = token
+ },
+ SET_NAME: (state, { name, welcome }) => {
+ state.name = name
+ state.welcome = welcome
+ },
+ SET_AVATAR: (state, avatar) => {
+ state.avatar = avatar
+ },
+ SET_ROLES: (state, roles) => {
+ state.roles = roles
+ },
+ SET_INFO: (state, info) => {
+ state.info = info
+ }
+ },
+
+ actions: {
+ // 登录
+ Login ({ commit }, userInfo) {
+ return new Promise((resolve, reject) => {
+ login(userInfo).then(response => {
+ console.log(response)
+ const result = response
+ storage.set(ACCESS_TOKEN, result.token, 7 * 24 * 60 * 60 * 1000)
+ commit('SET_TOKEN', result.token)
+ resolve()
+ }).catch(error => {
+ reject(error)
+ })
+ })
+ },
+
+ // 获取用户信息
+ GetInfo ({ commit }) {
+ return new Promise((resolve, reject) => {
+ getInfo().then(response => {
+ const result = response
+ console.log('result', result)
+ if (result.roles && Array.isArray(result.permissions)) {
+ const role = result.roles
+ role.permissions = result.permissions.filter(item => !!item)
+ role.permissions.map(per => {
+ if (per.actionEntitySet != null && per.actionEntitySet.length > 0) {
+ const action = per.actionEntitySet.map(action => { return action.action })
+ per.actionList = action
+ }
+ })
+ console.log('xxxxxxxxxxxxxxxx')
+ // role.permissionList = role.permissions.map(permission => { return permission })
+ console.log('xxxxxxxxxxxxxxxx')
+ commit('SET_ROLES', result.roles)
+ commit('SET_INFO', result)
+ console.log('xxxxxxxxxxxxxxxx')
+ } else {
+ reject(new Error('getInfo: roles must be a non-null array !'))
+ }
+ commit('SET_NAME', { name: result.name, welcome: welcome() })
+ commit('SET_AVATAR', result.avatar)
+ resolve(response)
+ }).catch(error => {
+ reject(error)
+ })
+ })
+ },
+
+ // 登出
+ Logout ({ commit, state }) {
+ return new Promise((resolve) => {
+ logout(state.token).then(() => {
+ commit('SET_TOKEN', '')
+ commit('SET_ROLES', [])
+ storage.remove(ACCESS_TOKEN)
+ resolve()
+ }).catch((err) => {
+ console.log('logout fail:', err)
+ // resolve()
+ }).finally(() => {
+ })
+ })
+ }
+
+ }
+}
+
+export default user
diff --git a/src/store/mutation-types.js b/src/store/mutation-types.js
new file mode 100644
index 0000000..9bcaa35
--- /dev/null
+++ b/src/store/mutation-types.js
@@ -0,0 +1,24 @@
+export const ACCESS_TOKEN = 'Authorization'
+
+export const SIDEBAR_TYPE = 'sidebar_type'
+export const TOGGLE_MOBILE_TYPE = 'is_mobile'
+export const TOGGLE_NAV_THEME = 'nav_theme'
+export const TOGGLE_LAYOUT = 'layout'
+export const TOGGLE_FIXED_HEADER = 'fixed_header'
+export const TOGGLE_FIXED_SIDEBAR = 'fixed_sidebar'
+export const TOGGLE_CONTENT_WIDTH = 'content_width'
+export const TOGGLE_HIDE_HEADER = 'auto_hide_header'
+export const TOGGLE_COLOR = 'color'
+export const TOGGLE_WEAK = 'weak'
+export const TOGGLE_MULTI_TAB = 'multi_tab'
+export const APP_LANGUAGE = 'app_language'
+
+export const CONTENT_WIDTH_TYPE = {
+ Fluid: 'Fluid',
+ Fixed: 'Fixed'
+}
+
+export const NAV_THEME = {
+ LIGHT: 'light',
+ DARK: 'dark'
+}
diff --git a/src/utils/axios.js b/src/utils/axios.js
new file mode 100644
index 0000000..3b91f6b
--- /dev/null
+++ b/src/utils/axios.js
@@ -0,0 +1,35 @@
+const VueAxios = {
+ vm: {},
+ // eslint-disable-next-line no-unused-vars
+ install (Vue, instance) {
+ if (this.installed) {
+ return
+ }
+ this.installed = true
+
+ if (!instance) {
+ // eslint-disable-next-line no-console
+ console.error('You have to install axios')
+ return
+ }
+
+ Vue.axios = instance
+
+ Object.defineProperties(Vue.prototype, {
+ axios: {
+ get: function get () {
+ return instance
+ }
+ },
+ $http: {
+ get: function get () {
+ return instance
+ }
+ }
+ })
+ }
+}
+
+export {
+ VueAxios
+}
diff --git a/src/utils/domUtil.js b/src/utils/domUtil.js
new file mode 100644
index 0000000..be93027
--- /dev/null
+++ b/src/utils/domUtil.js
@@ -0,0 +1,21 @@
+import config from '@/config/defaultSettings'
+
+export const setDocumentTitle = function (title) {
+ document.title = title
+ const ua = navigator.userAgent
+ // eslint-disable-next-line
+ const regex = /\bMicroMessenger\/([\d\.]+)/
+ if (regex.test(ua) && /ip(hone|od|ad)/i.test(ua)) {
+ const i = document.createElement('iframe')
+ i.src = '/favicon.ico'
+ i.style.display = 'none'
+ i.onload = function () {
+ setTimeout(function () {
+ i.remove()
+ }, 9)
+ }
+ document.body.appendChild(i)
+ }
+}
+
+export const domTitle = config.title
diff --git a/src/utils/fileHelper.js b/src/utils/fileHelper.js
new file mode 100644
index 0000000..c7c99f3
--- /dev/null
+++ b/src/utils/fileHelper.js
@@ -0,0 +1,100 @@
+import request from '@/utils/request'
+
+export function slicingDownload (param, callback, sizeUrl = '/file/filesize', downloadUrl = '/file/download') {
+ callback && callback({ isLoading: true, progress: 0 })
+ getFileSize(param, sizeUrl).then(async (fileSize) => {
+ console.log('文件大小', fileSize)
+ if (fileSize === 0) {
+ this.$notification.open({
+ message: '操作提示',
+ description: '该文件不存在.',
+ icon:
+ })
+ callback && callback({ isLoading: false })
+ return
+ }
+ let slicingSize = null
+ if (fileSize <= 20971520) {
+ // 20M以内,单个切片大小设置为2MB
+ slicingSize = 2 * 1024 * 1024 // 切片大小 单位MB
+ } else if (fileSize <= 524288000) {
+ // 500M以内,单个切片大小设置为5MB
+ slicingSize = 5 * 1024 * 1024 // 切片大小 单位MB
+ } else {
+ // 500M以外,单个切片大小设置为10MB
+ slicingSize = 10 * 1024 * 1024 // 切片大小 单位MB
+ }
+ const sumSlicingCount = Math.ceil(fileSize / slicingSize) // 总片数
+ console.log('单个切片文件大小', slicingSize, '总片数', sumSlicingCount)
+ const blobArr = []
+
+ let fileName = '下载文件'
+
+ for (let i = 0; i < sumSlicingCount; i++) {
+ const start = i * slicingSize
+ const end = (i + 1) * slicingSize
+ const contentRage = 'bytes=' + start + '-' + (end || '')
+ const res = await request({
+ url: downloadUrl,
+ method: 'get',
+ params: param,
+ headers: { Range: contentRage },
+ responseType: 'arraybuffer',
+ withConfig: true
+ })
+
+ callback && callback({ isLoading: true, progress: parseInt((i / sumSlicingCount) * 100) })
+
+ if (i === 0) {
+ const contentDisposition = res.headers['content-disposition']
+ if (contentDisposition) {
+ fileName = decodeURIComponent(contentDisposition.split('=')[1], 'UTF-8')
+ }
+ }
+ blobArr.push({
+ index: i,
+ data: res.data
+ })
+ }
+
+ blobArr.sort((a, b) => a.index - b.index)
+ const targetBlobArr = blobArr.map((r) => r.data)
+ // 多个blob排序完合并为一个blob
+ const buffers = new Blob(targetBlobArr)
+ saveAs(fileName, buffers, () => {
+ callback && callback({ isLoading: false })
+ })
+ }).finally(() => {
+ callback && callback({ isLoading: false })
+ })
+}
+
+// 获取文件大小
+function getFileSize (param, sizeUrl) {
+ return new Promise((resolve, reject) => {
+ request({
+ url: sizeUrl,
+ method: 'get',
+ params: param
+ }).then((size) => {
+ if (size) {
+ resolve(size)
+ } else {
+ reject(size)
+ }
+ })
+ .catch((e) => {
+ reject(e)
+ })
+ })
+}
+
+function saveAs (name, buffers, callback) {
+ const blobUrl = URL.createObjectURL(buffers)
+ const a = document.createElement('a')
+ a.download = name
+ a.href = blobUrl
+ a.click()
+ callback && callback()
+ // URL.revokeObjectURL(blob)
+}
diff --git a/src/utils/filter.js b/src/utils/filter.js
new file mode 100644
index 0000000..04ec979
--- /dev/null
+++ b/src/utils/filter.js
@@ -0,0 +1,56 @@
+import Vue from 'vue'
+import moment from 'moment'
+import 'moment/locale/zh-cn'
+moment.locale('zh-cn')
+
+Vue.filter('NumberFormat', function (value) {
+ if (!value) {
+ return '0'
+ }
+ const intPartFormat = value.toString().replace(/(\d)(?=(?:\d{3})+$)/g, '$1,') // 将整数部分逢三一断
+ return intPartFormat
+})
+
+Vue.filter('amountFormat', function (value) {
+ let target
+ if (!value) {
+ target = 0
+ } else {
+ target = Number(value / 10000).toFixed(4)
+ target = parseFloat(target)
+ }
+ return target + '万元'
+})
+
+Vue.filter('dayjs', function (dataStr, pattern = 'YYYY-MM-DD HH:mm:ss') {
+ return dataStr ? moment(dataStr).format(pattern) : ''
+})
+
+Vue.filter('moment', function (dataStr, pattern = 'YYYY-MM-DD HH:mm:ss') {
+ return moment(dataStr).format(pattern)
+})
+
+Vue.filter('byteConvert', function (bytes) {
+ if (isNaN(bytes)) {
+ return ''
+ }
+ const symbols = ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
+ let exp = Math.floor(Math.log(bytes) / Math.log(2))
+ if (exp < 1) {
+ exp = 0
+ }
+ const i = Math.floor(exp / 10)
+ bytes = bytes / Math.pow(2, 10 * i)
+
+ if (bytes.toString().length > bytes.toFixed(2).toString().length) {
+ bytes = bytes.toFixed(2)
+ }
+ return bytes + ' ' + symbols[i]
+})
+
+Vue.filter('percentage', function (val, precision = 0) {
+ if (isNaN(val)) {
+ return ''
+ }
+ return (Number(val) * 100).toFixed(precision) + '%'
+})
diff --git a/src/utils/html2pdf.js b/src/utils/html2pdf.js
new file mode 100644
index 0000000..77a199d
--- /dev/null
+++ b/src/utils/html2pdf.js
@@ -0,0 +1,36 @@
+// 导出页面为PDF格式
+import html2canvas from 'html2canvas'
+import JSPDF from 'jspdf'
+/***
+ * elementName: 需要输出PDF的页面id
+ * htmlTitle: 页面标题
+ * currentTime:创建时间
+ */
+export default function (elementName, htmlTitle, currentTime) {
+ var element = document.getElementById(elementName)
+ html2canvas(element, {
+ logging: false
+ }).then(function (canvas) {
+ var pdf = new JSPDF('p', 'mm', 'a4') // A4纸,纵向
+ var ctx = canvas.getContext('2d')
+ var a4w = 190
+ var a4h = 257 // A4大小,210mm x 297mm,四边各保留20mm的边距
+ var imgHeight = Math.floor(a4h * canvas.width / a4w) // 按A4显示比例换算一页图像的像素高度
+ var renderedHeight = 0
+
+ while (renderedHeight < canvas.height) {
+ var page = document.createElement('canvas')
+ page.width = canvas.width
+ page.height = Math.min(imgHeight, canvas.height - renderedHeight) // 可能内容不足一页
+
+ // 用getImageData剪裁指定区域,并画到前面创建的canvas对象中
+ page.getContext('2d').putImageData(ctx.getImageData(0, renderedHeight, canvas.width, Math.min(imgHeight, canvas.height - renderedHeight)), 0, 0)
+ pdf.addImage(page.toDataURL('image/jpeg', 1.0), 'JPEG', 10, 10, a4w, Math.min(a4h, a4w * page.height / page.width)) // 添加图像到页面,保留10mm边距
+
+ renderedHeight += imgHeight
+ if (renderedHeight < canvas.height) { pdf.addPage() } // 如果后面还有内容,添加一个空页
+ // delete page;
+ }
+ pdf.save(htmlTitle + currentTime)
+ })
+}
diff --git a/src/utils/htmlToPdf.js b/src/utils/htmlToPdf.js
new file mode 100644
index 0000000..4ed6b30
--- /dev/null
+++ b/src/utils/htmlToPdf.js
@@ -0,0 +1,56 @@
+// 导出页面为PDF格式
+import html2Canvas from 'html2canvas'
+import JsPDF from 'jspdf'
+export default {
+ install (Vue, options) {
+ // 移除水印方法
+ Vue.prototype.getPdf = function (id, fileName, callback) {
+ var title = fileName
+ html2Canvas(document.querySelector(id), {
+ allowTaint: true
+ }).then(function (canvas) {
+ const contentWidth = canvas.width
+ const contentHeight = canvas.height
+
+ // 一页pdf显示html页面生成的canvas高度;
+ const pageHeight = contentWidth / 595.28 * 841.89
+ // 未生成pdf的html页面高度
+ let leftHeight = contentHeight
+ // pdf页面偏移
+ let position = 0
+ // a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
+ const imgWidth = 555.28
+ const imgHeight = 555.28 / contentWidth * contentHeight
+ const pageData = canvas.toDataURL('image/jpeg', 1.0)
+ const PDF = new JsPDF('', 'pt', 'a4')
+ if (leftHeight < pageHeight) {
+ PDF.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight)
+ } else {
+ while (leftHeight > 0) {
+ PDF.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
+ leftHeight -= pageHeight
+ position -= 841.89
+ if (leftHeight > 0) {
+ PDF.addPage()
+ }
+ }
+ }
+ // TpWatermark('wmName','500','700','-30','grey','50','0.1');
+ PDF.save(title + '.pdf')
+ setTimeout(() => {
+ clearTimeout()
+ callback && callback()
+ }, 300)
+ }
+ )
+ }
+
+ Vue.prototype.RemoveTpWatermark = function () {
+ // 判断水印是否存在,如果存在,那么执行
+ if (document.getElementById('tp-watermark') == null) {
+ return
+ }
+ document.getElementById('pdfDom').removeChild(document.getElementById('tp-watermark'))
+ }
+ }
+}
diff --git a/src/utils/request.js b/src/utils/request.js
new file mode 100644
index 0000000..a741b8f
--- /dev/null
+++ b/src/utils/request.js
@@ -0,0 +1,129 @@
+import store from '@/store'
+import { ACCESS_TOKEN } from '@/store/mutation-types'
+import notification from 'ant-design-vue/es/notification'
+import axios from 'axios'
+import storage from 'store'
+import { VueAxios } from './axios'
+
+// 创建 axios 实例
+const request = axios.create({
+ // API 请求的默认前缀
+ baseURL: process.env.VUE_APP_API_BASE_URL,
+ timeout: 0 // 请求超时时间
+})
+
+// 异常拦截处理器
+const errorHandler = (error) => {
+ if (error.response) {
+ const data = error.response.data
+ // 从 localstorage 获取 token
+ const token = storage.get(ACCESS_TOKEN)
+ if (error.response.status === 403) {
+ notification.error({
+ message: '权限不足',
+ description: data.message || '您的账号无此权限'
+ })
+ }
+ console.log('token', token)
+ if (error.response.status === 401 && !(data.result && data.result.isLogin)) {
+ notification.error({
+ message: '无权限',
+ description: '请登录您的账号'
+ })
+ if (token) {
+ store.dispatch('Logout').then(() => {
+ setTimeout(() => {
+ window.location.reload()
+ }, 1500)
+ })
+ }
+ }
+ }
+ return Promise.reject(error)
+}
+
+// request interceptor
+request.interceptors.request.use(config => {
+ const token = storage.get(ACCESS_TOKEN)
+ // 如果 token 存在
+ // 让每个请求携带自定义 token 请根据实际情况自行修改
+ if (token) {
+ config.headers[ACCESS_TOKEN] = token
+ }
+ if (config.isDownload) {
+ config.responseType = 'blob'
+ }
+ return config
+}, errorHandler)
+
+// response interceptor
+request.interceptors.response.use((response) => {
+ if (response.config.isDownload) {
+ downloadFile(response)
+ return
+ }
+ if (response.config.isRawData) {
+ return response.data
+ }
+ if (response.config.withConfig) {
+ return response
+ }
+ if (response.data && response.data.code === 200) {
+ return response.data.data
+ } else {
+ // if (response.data.code === 500) {
+ // notification.error({
+ // message: response.data.message || '操作失败'
+ // })
+ // }
+ if (!response.headers['content-range']) {
+ notification.error({
+ message: response.data.message || '操作失败'
+ })
+ }
+ }
+}, errorHandler)
+
+function downloadFile (response) {
+ let fileName = null
+ const contentDisposition = response.headers['content-disposition']
+ if (contentDisposition) {
+ fileName = decodeURIComponent(contentDisposition.split('=')[1], 'UTF-8')
+ }
+ const objectUrl = URL.createObjectURL(response.data)
+ const reader = new FileReader()
+ reader.readAsText(response.data)
+ reader.onload = function (e) {
+ const receiveData = e.target.result// 这个就是解析出来的数据
+ try {
+ const resData = JSON.parse(receiveData)
+ notification.error({
+ message: resData.data.message || '下载失败'
+ })
+ } catch (error) {
+ const link = document.createElement('a')
+ link.href = objectUrl
+ if (fileName) {
+ link.setAttribute('download', fileName)
+ link.setAttribute('target', '_blank')
+ }
+ document.body.appendChild(link)
+ link.click()
+ window.URL.revokeObjectURL(link.href)
+ }
+ }
+}
+
+const installer = {
+ vm: {},
+ install (Vue) {
+ Vue.use(VueAxios, request)
+ }
+}
+
+export default request
+
+export {
+ installer as VueAxios,
+ request as axios
+}
diff --git a/src/utils/routeConvert.js b/src/utils/routeConvert.js
new file mode 100644
index 0000000..e88b0d6
--- /dev/null
+++ b/src/utils/routeConvert.js
@@ -0,0 +1,30 @@
+import cloneDeep from 'lodash.clonedeep'
+
+export function convertRoutes (nodes) {
+ if (!nodes) return null
+
+ nodes = cloneDeep(nodes)
+
+ let queue = Array.isArray(nodes) ? nodes.concat() : [nodes]
+
+ while (queue.length) {
+ const levelSize = queue.length
+
+ for (let i = 0; i < levelSize; i++) {
+ const node = queue.shift()
+
+ if (!node.children || !node.children.length) continue
+
+ node.children.forEach(child => {
+ // 转化相对路径
+ if (child.path[0] !== '/' && !child.path.startsWith('http')) {
+ child.path = node.path.replace(/(\w*)[/]*$/, `$1/${child.path}`)
+ }
+ })
+
+ queue = queue.concat(node.children)
+ }
+ }
+
+ return nodes
+}
diff --git a/src/utils/screenLog.js b/src/utils/screenLog.js
new file mode 100644
index 0000000..0d89b94
--- /dev/null
+++ b/src/utils/screenLog.js
@@ -0,0 +1,12 @@
+/* eslint-disable */
+export const printANSI = () => {
+ // console.clear()
+ console.log('[antd pro] created()')
+ // ASCII - ANSI Shadow
+ let text = `
+\t\t\t\t\tPublished ${APP_VERSION}-${GIT_HASH} @ antdv.com
+\t\t\t\t\tBuild date: ${BUILD_DATE}`
+ console.log(`%c${text}`, 'color: #fc4d50')
+ 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;')
+ 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;')
+}
diff --git a/src/utils/useEchart.js b/src/utils/useEchart.js
new file mode 100644
index 0000000..11f23a8
--- /dev/null
+++ b/src/utils/useEchart.js
@@ -0,0 +1,34 @@
+import ECharts from 'vue-echarts'
+import { use } from 'echarts/core'
+import {
+ CanvasRenderer
+} from 'echarts/renderers'
+import {
+ BarChart,
+ PieChart,
+ LineChart,
+ ScatterChart
+} from 'echarts/charts'
+import {
+ GridComponent,
+ TooltipComponent,
+ LegendComponent,
+ ToolboxComponent,
+ TitleComponent
+} from 'echarts/components'
+
+export default function (Vue) {
+ use([
+ CanvasRenderer,
+ PieChart,
+ BarChart,
+ LineChart,
+ ScatterChart,
+ GridComponent,
+ TooltipComponent,
+ LegendComponent,
+ ToolboxComponent,
+ TitleComponent
+ ])
+ Vue.component('v-chart', ECharts)
+}
diff --git a/src/utils/util.js b/src/utils/util.js
new file mode 100644
index 0000000..2e6866e
--- /dev/null
+++ b/src/utils/util.js
@@ -0,0 +1,95 @@
+export function timeFix () {
+ const time = new Date()
+ const hour = time.getHours()
+ return hour < 9 ? '早上好' : hour <= 11 ? '上午好' : hour <= 13 ? '中午好' : hour < 20 ? '下午好' : '晚上好'
+}
+
+export function welcome () {
+ const arr = ['休息一会儿吧', '准备吃什么呢?', '要不要打一把 DOTA', '我猜你可能累了']
+ const index = Math.floor(Math.random() * arr.length)
+ return arr[index]
+}
+
+/**
+ * 触发 window.resize
+ */
+export function triggerWindowResizeEvent () {
+ const event = document.createEvent('HTMLEvents')
+ event.initEvent('resize', true, true)
+ event.eventType = 'message'
+ window.dispatchEvent(event)
+}
+
+export function handleScrollHeader (callback) {
+ let timer = 0
+
+ let beforeScrollTop = window.pageYOffset
+ callback = callback || function () {}
+ window.addEventListener(
+ 'scroll',
+ event => {
+ clearTimeout(timer)
+ timer = setTimeout(() => {
+ let direction = 'up'
+ const afterScrollTop = window.pageYOffset
+ const delta = afterScrollTop - beforeScrollTop
+ if (delta === 0) {
+ return false
+ }
+ direction = delta > 0 ? 'down' : 'up'
+ callback(direction)
+ beforeScrollTop = afterScrollTop
+ }, 50)
+ },
+ false
+ )
+}
+
+export function isIE () {
+ const bw = window.navigator.userAgent
+ const compare = (s) => bw.indexOf(s) >= 0
+ const ie11 = (() => 'ActiveXObject' in window)()
+ return compare('MSIE') || ie11
+}
+
+/**
+ * Remove loading animate
+ * @param id parent element id or class
+ * @param timeout
+ */
+export function removeLoadingAnimate (id = '', timeout = 1500) {
+ if (id === '') {
+ return
+ }
+ setTimeout(() => {
+ document.body.removeChild(document.getElementById(id))
+ }, timeout)
+}
+export function scorePassword (pass) {
+ let score = 0
+ if (!pass) {
+ return score
+ }
+ // award every unique letter until 5 repetitions
+ const letters = {}
+ for (let i = 0; i < pass.length; i++) {
+ letters[pass[i]] = (letters[pass[i]] || 0) + 1
+ score += 5.0 / letters[pass[i]]
+ }
+
+ // bonus points for mixing it up
+ const variations = {
+ digits: /\d/.test(pass),
+ lower: /[a-z]/.test(pass),
+ upper: /[A-Z]/.test(pass),
+ nonWords: /\W/.test(pass)
+ }
+
+ let variationCount = 0
+ for (var check in variations) {
+ variationCount += (variations[check] === true) ? 1 : 0
+ }
+ score += (variationCount - 1) * 10
+
+ return parseInt(score)
+}
diff --git a/src/utils/utils.less b/src/utils/utils.less
new file mode 100644
index 0000000..23bc405
--- /dev/null
+++ b/src/utils/utils.less
@@ -0,0 +1,54 @@
+.textOverflow() {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ word-break: break-all;
+ white-space: nowrap;
+}
+
+.textOverflowMulti(@line: 3, @bg: #fff) {
+ position: relative;
+ max-height: @line * 1.5em;
+ padding-right: 1em;
+ margin-right: -1em;
+ overflow: hidden;
+ line-height: 1.5em;
+ text-align: justify;
+
+ &::before {
+ position: absolute;
+ right: 14px;
+ bottom: 0;
+ padding: 0 1px;
+ background: @bg;
+ content: '...';
+ }
+
+ &::after {
+ position: absolute;
+ right: 14px;
+ width: 1em;
+ height: 1em;
+ margin-top: .2em;
+ background: white;
+ content: '';
+ }
+}
+
+// mixins for clearfix
+// ------------------------
+.clearfix() {
+ zoom: 1;
+
+ &::before,
+ &::after {
+ display: table;
+ content: ' ';
+ }
+
+ &::after {
+ height: 0;
+ clear: both;
+ font-size: 0;
+ visibility: hidden;
+ }
+}
diff --git a/src/views/404.vue b/src/views/404.vue
new file mode 100644
index 0000000..8c1d8a1
--- /dev/null
+++ b/src/views/404.vue
@@ -0,0 +1,15 @@
+
+
+ 404 page
+
+
+
+
+
+
diff --git a/src/views/account/center/index.vue b/src/views/account/center/index.vue
new file mode 100644
index 0000000..c3264ca
--- /dev/null
+++ b/src/views/account/center/index.vue
@@ -0,0 +1,289 @@
+
+
+
+
+
+
+
+
+
+
{{ nickname }}
+
海纳百川,有容乃大
+
+
+
+ 交互专家
+
+
+ 蚂蚁金服-某某某事业群-某某平台部-某某技术部-UED
+
+
+
+ 浙江省
+ 杭州市
+
+
+
+
+
+
+
+
+
+
+
+ handleTabChange(key, 'noTitleKey')"
+ >
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/account/center/page/App.vue b/src/views/account/center/page/App.vue
new file mode 100644
index 0000000..43e84a1
--- /dev/null
+++ b/src/views/account/center/page/App.vue
@@ -0,0 +1,106 @@
+
+
+
+
+
+
+
diff --git a/src/views/account/center/page/Article.vue b/src/views/account/center/page/Article.vue
new file mode 100644
index 0000000..4f36d63
--- /dev/null
+++ b/src/views/account/center/page/Article.vue
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
+
+
+ {{ item.title }}
+
+
+ Ant Design
+ 设计语言
+ 蚂蚁金服
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/account/center/page/Project.vue b/src/views/account/center/page/Project.vue
new file mode 100644
index 0000000..6e9cb60
--- /dev/null
+++ b/src/views/account/center/page/Project.vue
@@ -0,0 +1,109 @@
+
+
+
+
+
+
+
+
+ {{ item.description }}
+
+
+
+
{{ item.updatedAt | fromNow }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/account/center/page/index.js b/src/views/account/center/page/index.js
new file mode 100644
index 0000000..b579b6a
--- /dev/null
+++ b/src/views/account/center/page/index.js
@@ -0,0 +1,5 @@
+import AppPage from './App'
+import ArticlePage from './Article'
+import ProjectPage from './Project'
+
+export { AppPage, ArticlePage, ProjectPage }
diff --git a/src/views/account/settings/AvatarModal.vue b/src/views/account/settings/AvatarModal.vue
new file mode 100644
index 0000000..98f4325
--- /dev/null
+++ b/src/views/account/settings/AvatarModal.vue
@@ -0,0 +1,184 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 选择图片
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 保存
+
+
+
+
+
+
+
+
diff --git a/src/views/account/settings/BasicSetting.vue b/src/views/account/settings/BasicSetting.vue
new file mode 100644
index 0000000..1ef4cd0
--- /dev/null
+++ b/src/views/account/settings/BasicSetting.vue
@@ -0,0 +1,141 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('account.settings.basic.update') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/account/settings/Binding.vue b/src/views/account/settings/Binding.vue
new file mode 100644
index 0000000..cbea7fc
--- /dev/null
+++ b/src/views/account/settings/Binding.vue
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/views/account/settings/Custom.vue b/src/views/account/settings/Custom.vue
new file mode 100644
index 0000000..c01d921
--- /dev/null
+++ b/src/views/account/settings/Custom.vue
@@ -0,0 +1,68 @@
+
+
+
+
+
+ 风格配色
+
+
+
+ 整体风格配色设置
+
+
+
+
+
+
+
+
+
+
+ 主题色
+
+
+
+ 页面风格配色: {{ colorFilter(primaryColor) }}
+
+
+
+
+
+
+
diff --git a/src/views/account/settings/Index.vue b/src/views/account/settings/Index.vue
new file mode 100644
index 0000000..e7a7920
--- /dev/null
+++ b/src/views/account/settings/Index.vue
@@ -0,0 +1,154 @@
+
+
+
+
+
+
+
diff --git a/src/views/account/settings/Notification.vue b/src/views/account/settings/Notification.vue
new file mode 100644
index 0000000..cbea7fc
--- /dev/null
+++ b/src/views/account/settings/Notification.vue
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/views/account/settings/Security.vue b/src/views/account/settings/Security.vue
new file mode 100644
index 0000000..893967a
--- /dev/null
+++ b/src/views/account/settings/Security.vue
@@ -0,0 +1,41 @@
+
+
+
+
+ {{ item.title }}
+
+ {{ item.description }}
+ :
+ {{ item.value }}
+
+
+
+ {{ item.actions.title }}
+
+
+
+
+
+
+
+
+
diff --git a/src/views/analysis/Bidding.vue b/src/views/analysis/Bidding.vue
new file mode 100644
index 0000000..243205c
--- /dev/null
+++ b/src/views/analysis/Bidding.vue
@@ -0,0 +1,637 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/analysis/Tender.vue b/src/views/analysis/Tender.vue
new file mode 100644
index 0000000..ec28b26
--- /dev/null
+++ b/src/views/analysis/Tender.vue
@@ -0,0 +1,680 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ~
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ index + 1 }}
+
+
+
+
+ 中标
+
+ 金额(万元)
+
+
+
+ {{ text | dayjs('YYYY-MM-DD') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/analysis/YearPicker.vue b/src/views/analysis/YearPicker.vue
new file mode 100644
index 0000000..3425be2
--- /dev/null
+++ b/src/views/analysis/YearPicker.vue
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
diff --git a/src/views/analysis/total/BidWinner.vue b/src/views/analysis/total/BidWinner.vue
new file mode 100644
index 0000000..4f52eba
--- /dev/null
+++ b/src/views/analysis/total/BidWinner.vue
@@ -0,0 +1,56 @@
+
+
+
+
+
+ {{ getTableIndex(index) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/analysis/total/BidWinningDepartment.vue b/src/views/analysis/total/BidWinningDepartment.vue
new file mode 100644
index 0000000..9b68b32
--- /dev/null
+++ b/src/views/analysis/total/BidWinningDepartment.vue
@@ -0,0 +1,39 @@
+
+
+
+
+
+ {{ getTableIndex(index) }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/analysis/total/BidWinningProjects.vue b/src/views/analysis/total/BidWinningProjects.vue
new file mode 100644
index 0000000..5235de7
--- /dev/null
+++ b/src/views/analysis/total/BidWinningProjects.vue
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/analysis/total/BiddingProject.vue b/src/views/analysis/total/BiddingProject.vue
new file mode 100644
index 0000000..de419c2
--- /dev/null
+++ b/src/views/analysis/total/BiddingProject.vue
@@ -0,0 +1,162 @@
+
+
+
+
+ {{ item.unitName }}
+
+
+
+
+
+
+ {{ getTableIndex(index) }}
+
+
+
+
+
+
+
+
+ {{ text || 0 }}
+
+
+
+
+
+
+ {{ text.join('、') }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/analysis/total/Index.vue b/src/views/analysis/total/Index.vue
new file mode 100644
index 0000000..b0da921
--- /dev/null
+++ b/src/views/analysis/total/Index.vue
@@ -0,0 +1,101 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/analysis/total/mixins/total.js b/src/views/analysis/total/mixins/total.js
new file mode 100644
index 0000000..63953f8
--- /dev/null
+++ b/src/views/analysis/total/mixins/total.js
@@ -0,0 +1,24 @@
+export default {
+ props: {
+ year: {
+ type: String,
+ default: ''
+ },
+ month: {
+ type: String,
+ default: ''
+ },
+ height: {
+ type: Number,
+ default: 1
+ }
+ },
+ watch: {
+ year () {
+ this.queryData()
+ },
+ month () {
+ this.queryData()
+ }
+ }
+}
diff --git a/src/views/codebuild/codeBuildIndex.vue b/src/views/codebuild/codeBuildIndex.vue
new file mode 100644
index 0000000..7eae137
--- /dev/null
+++ b/src/views/codebuild/codeBuildIndex.vue
@@ -0,0 +1,369 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ index + 1 }}
+
+
+
+
+
+
+ {{ index + 1 }}
+
+
+
+
+
+
+ {{ index + 1 }}
+
+
+
+
+
+
+ {{ index + 1 }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/dashboard/Analysis.vue b/src/views/dashboard/Analysis.vue
new file mode 100644
index 0000000..81156d4
--- /dev/null
+++ b/src/views/dashboard/Analysis.vue
@@ -0,0 +1,420 @@
+
+
+
+
+
+
+
+
+
+
+ {{ $t('dashboard.analysis.week') }}
+ 12%
+
+
+ {{ $t('dashboard.analysis.day') }}
+ 11%
+
+
+ {{ $t('dashboard.analysis.day-sales') }}¥ 234.56
+
+
+
+
+
+
+
+
+
+
+ {{ $t('dashboard.analysis.day-visits') }} {{ '1234' | NumberFormat }}
+
+
+
+
+
+
+
+
+
+
+ {{ $t('dashboard.analysis.conversion-rate') }} 60%
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('dashboard.analysis.week') }}
+ 12%
+
+
+ {{ $t('dashboard.analysis.day') }}
+ 80%
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('dashboard.analysis.dropdown-option-one') }}
+
+
+ {{ $t('dashboard.analysis.dropdown-option-two') }}
+
+
+
+
+
+
+
+ {{ $t('dashboard.analysis.search-users') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('dashboard.analysis.per-capita-search') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ text }}%
+
+
+
+
+
+
+
+
+
+ {{ $t('dashboard.analysis.sales') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/dashboard/Monitor.vue b/src/views/dashboard/Monitor.vue
new file mode 100644
index 0000000..2b9c6c1
--- /dev/null
+++ b/src/views/dashboard/Monitor.vue
@@ -0,0 +1,15 @@
+
+
+ Monitor
+
+
+
+
+
+
diff --git a/src/views/dashboard/TestWork.vue b/src/views/dashboard/TestWork.vue
new file mode 100644
index 0000000..ae80f93
--- /dev/null
+++ b/src/views/dashboard/TestWork.vue
@@ -0,0 +1,117 @@
+
+
+
本页面内容均为测试功能,暂不提供稳定性保证
+
+
+
多标签组件测试功能
+
关闭当前页
+
打开 任务列表
+
+
+
+
+ visible = !visible" style="margin-right: 16px;">修改当前 Tab 名称
+
+
+
visible2 = false" okText="确定" cancelText="取消">
+
+
+
页面 KEY 是由页面的路由 path
决定的
+
如果要修改某一个页面标题,该页面必须已经被打开在 Tab 栏
+
后期可以考虑优化到编程式 Tab 栏,就可以没有这种限制
+
+
+
+
+
+
+
+
+
+
+ visible2 = !visible2">修改某一个 Tab 名称
+
+
+
+
+
全局遮罩测试
+
打开遮罩(5s 自动关闭)
+
打开遮罩(自定义提示语)
+
+
+
+
+
+
+
diff --git a/src/views/dashboard/Workplace.less b/src/views/dashboard/Workplace.less
new file mode 100644
index 0000000..a709f54
--- /dev/null
+++ b/src/views/dashboard/Workplace.less
@@ -0,0 +1,109 @@
+@import '~ant-design-vue/es/style/themes/default.less';
+
+.text-overflow() {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ word-break: break-all;
+ white-space: nowrap;
+}
+
+// mixins for clearfix
+// ------------------------
+.clearfix() {
+ zoom: 1;
+
+ &::before,
+ &::after {
+ display: table;
+ content: ' ';
+ }
+
+ &::after {
+ height: 0;
+ clear: both;
+ font-size: 0;
+ visibility: hidden;
+ }
+}
+
+.page-header-content {
+ display: flex;
+
+ .avatar {
+ flex: 0 1 72px;
+
+ & > span {
+ display: block;
+ width: 72px;
+ height: 72px;
+ border-radius: 72px;
+ }
+ }
+
+ .content {
+ position: relative;
+ top: 4px;
+ margin-left: 24px;
+ line-height: 22px;
+ color: @text-color-secondary;
+ flex: 1 1 auto;
+
+ .content-title {
+ margin-bottom: 12px;
+ font-size: 20px;
+ font-weight: 500;
+ line-height: 28px;
+ color: @heading-color;
+ }
+ }
+}
+
+.extra-content {
+ .clearfix();
+
+ float: right;
+ white-space: nowrap;
+
+ .stat-item {
+ position: relative;
+ display: inline-block;
+ padding: 0 32px;
+
+ > p:first-child {
+ margin-bottom: 4px;
+ font-size: @font-size-base;
+ line-height: 22px;
+ color: @text-color-secondary;
+ }
+
+ > p {
+ margin: 0;
+ font-size: 30px;
+ line-height: 38px;
+ color: @heading-color;
+
+ > span {
+ font-size: 20px;
+ color: @text-color-secondary;
+ }
+ }
+
+ &::after {
+ position: absolute;
+ top: 8px;
+ right: 0;
+ width: 1px;
+ height: 40px;
+ background-color: @border-color-split;
+ content: '';
+ }
+
+ &:last-child {
+ padding-right: 0;
+
+ &::after {
+ display: none;
+ }
+ }
+ }
+}
diff --git a/src/views/dashboard/Workplace.vue b/src/views/dashboard/Workplace.vue
new file mode 100644
index 0000000..47d7cad
--- /dev/null
+++ b/src/views/dashboard/Workplace.vue
@@ -0,0 +1,391 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 全部项目
+
+
+
+
+
+
+ {{ item.description }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.time }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/db/tablecolumndetail.vue b/src/views/db/tablecolumndetail.vue
new file mode 100644
index 0000000..b0213a6
--- /dev/null
+++ b/src/views/db/tablecolumndetail.vue
@@ -0,0 +1,178 @@
+
+
+
+
+
+ {{ index + 1 }}
+
+
+
+ 编辑
+
+ 删除
+
+
+
+
+
+
+
+
diff --git a/src/views/db/tablelist.vue b/src/views/db/tablelist.vue
new file mode 100644
index 0000000..943ad3d
--- /dev/null
+++ b/src/views/db/tablelist.vue
@@ -0,0 +1,344 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 查询
+ 重置
+
+
+
+
+
+
+
+
+
+ {{ index + 1 }}
+
+
+
+ 字段
+
+ 代码生成
+
+ 备份
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/docList/ComparePreview.vue b/src/views/docList/ComparePreview.vue
new file mode 100644
index 0000000..2cef121
--- /dev/null
+++ b/src/views/docList/ComparePreview.vue
@@ -0,0 +1,45 @@
+
+
+
+ 原始文件
+
+
+ 转换后文件
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/docList/Index.vue b/src/views/docList/Index.vue
new file mode 100644
index 0000000..d58439a
--- /dev/null
+++ b/src/views/docList/Index.vue
@@ -0,0 +1,252 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 查询
+ 重置
+
+
+
+
+
+
+
+
+
+
类型:{{ item.fileType }}
+
大小:{{ item.fileSize | byteConvert }}
+
日期:{{ item.createTime }}
+
+ {{ item.fileName }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/docList/ViewDoc.vue b/src/views/docList/ViewDoc.vue
new file mode 100644
index 0000000..136b532
--- /dev/null
+++ b/src/views/docList/ViewDoc.vue
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
diff --git a/src/views/docList/components/DocPreview.vue b/src/views/docList/components/DocPreview.vue
new file mode 100644
index 0000000..cb072f3
--- /dev/null
+++ b/src/views/docList/components/DocPreview.vue
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
diff --git a/src/views/docList/components/Document.vue b/src/views/docList/components/Document.vue
new file mode 100644
index 0000000..dda8202
--- /dev/null
+++ b/src/views/docList/components/Document.vue
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
diff --git a/src/views/docList/components/ImagePreview.vue b/src/views/docList/components/ImagePreview.vue
new file mode 100644
index 0000000..4b695c3
--- /dev/null
+++ b/src/views/docList/components/ImagePreview.vue
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/docList/components/PdfPreview.vue b/src/views/docList/components/PdfPreview.vue
new file mode 100644
index 0000000..0d4c82f
--- /dev/null
+++ b/src/views/docList/components/PdfPreview.vue
@@ -0,0 +1,85 @@
+
+
+
+
+
+
+
diff --git a/src/views/docList/components/PdfPreview_old.vue b/src/views/docList/components/PdfPreview_old.vue
new file mode 100644
index 0000000..4666df7
--- /dev/null
+++ b/src/views/docList/components/PdfPreview_old.vue
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
diff --git a/src/views/docList/components/TxtPreview.vue b/src/views/docList/components/TxtPreview.vue
new file mode 100644
index 0000000..b663b6a
--- /dev/null
+++ b/src/views/docList/components/TxtPreview.vue
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
diff --git a/src/views/exception/403.vue b/src/views/exception/403.vue
new file mode 100644
index 0000000..fb1bf36
--- /dev/null
+++ b/src/views/exception/403.vue
@@ -0,0 +1,20 @@
+
+
+
+
+ Back Home
+
+
+
+
+
+
diff --git a/src/views/exception/404.vue b/src/views/exception/404.vue
new file mode 100644
index 0000000..3142e7b
--- /dev/null
+++ b/src/views/exception/404.vue
@@ -0,0 +1,20 @@
+
+
+
+
+ Back Home
+
+
+
+
+
+
diff --git a/src/views/exception/500.vue b/src/views/exception/500.vue
new file mode 100644
index 0000000..2770b77
--- /dev/null
+++ b/src/views/exception/500.vue
@@ -0,0 +1,20 @@
+
+
+
+
+ Back Home
+
+
+
+
+
+
diff --git a/src/views/folder/folderList.vue b/src/views/folder/folderList.vue
new file mode 100644
index 0000000..d3b24ca
--- /dev/null
+++ b/src/views/folder/folderList.vue
@@ -0,0 +1,320 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ item.fileName }}
+
{{ item.createTime }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/form/advancedForm/AdvancedForm.vue b/src/views/form/advancedForm/AdvancedForm.vue
new file mode 100644
index 0000000..7a1a7ba
--- /dev/null
+++ b/src/views/form/advancedForm/AdvancedForm.vue
@@ -0,0 +1,330 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ handleChange(e.target.value, record.key, col)"
+ />
+ {{ text }}
+
+
+
+
+ 添加
+
+
+ 删除
+
+
+
+ 保存
+
+ 取消
+
+
+
+ 编辑
+
+
+ 删除
+
+
+
+
+ 新增成员
+
+
+
+
+
+
+
+
+
+ {{ item.message }}
+ {{ item.fieldLabel }}
+
+
+
+ {{ errors.length }}
+
+
+
+ 提交
+
+
+
+
+
+
+
diff --git a/src/views/form/advancedForm/RepositoryForm.vue b/src/views/form/advancedForm/RepositoryForm.vue
new file mode 100644
index 0000000..6b326aa
--- /dev/null
+++ b/src/views/form/advancedForm/RepositoryForm.vue
@@ -0,0 +1,119 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 王同学
+ 李同学
+ 黄同学
+
+
+
+
+
+
+
+
+ 王晓丽
+ 李军
+
+
+
+
+
+
+
+
+
+
+
+ 公开
+ 私密
+
+
+
+
+
+ Submit
+
+
+
+
+
+
+
diff --git a/src/views/form/advancedForm/TaskForm.vue b/src/views/form/advancedForm/TaskForm.vue
new file mode 100644
index 0000000..eceaa9b
--- /dev/null
+++ b/src/views/form/advancedForm/TaskForm.vue
@@ -0,0 +1,107 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 黄丽丽
+ 李大刀
+
+
+
+
+
+
+
+
+ 王伟
+ 李红军
+
+
+
+
+
+
+
+
+
+
+
+ 定时执行
+ 周期执行
+
+
+
+
+
+ Submit
+
+
+
+
+
+
+
diff --git a/src/views/form/basicForm/index.vue b/src/views/form/basicForm/index.vue
new file mode 100644
index 0000000..488989c
--- /dev/null
+++ b/src/views/form/basicForm/index.vue
@@ -0,0 +1,134 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ %
+
+
+
+ {{ $t('form.basic-form.radio.public') }}
+ {{ $t('form.basic-form.radio.partially-public') }}
+ {{ $t('form.basic-form.radio.private') }}
+
+
+
+ {{ $t('form.basic-form.option.A') }}
+ {{ $t('form.basic-form.option.B') }}
+ {{ $t('form.basic-form.option.C') }}
+
+
+
+
+ {{ $t('form.basic-form.form.submit') }}
+ {{ $t('form.basic-form.form.save') }}
+
+
+
+
+
+
+
diff --git a/src/views/form/stepForm/Step1.vue b/src/views/form/stepForm/Step1.vue
new file mode 100644
index 0000000..ff10600
--- /dev/null
+++ b/src/views/form/stepForm/Step1.vue
@@ -0,0 +1,112 @@
+
+
+
+
+
+ ant-design@alipay.com
+
+
+
+
+
+ 支付宝
+ 微信
+
+
+
+
+
+
+
+
+
+
+
+ 下一步
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/form/stepForm/Step2.vue b/src/views/form/stepForm/Step2.vue
new file mode 100644
index 0000000..dc50a7f
--- /dev/null
+++ b/src/views/form/stepForm/Step2.vue
@@ -0,0 +1,110 @@
+
+
+
+
+
+ ant-design@alipay.com
+
+
+ test@example.com
+
+
+ Alex
+
+
+ ¥ 5,000.00
+
+
+
+
+
+
+ 提交
+ 上一步
+
+
+
+
+
+
+
+
diff --git a/src/views/form/stepForm/Step3.vue b/src/views/form/stepForm/Step3.vue
new file mode 100644
index 0000000..94676c7
--- /dev/null
+++ b/src/views/form/stepForm/Step3.vue
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+ 再转一笔
+ 查看账单
+
+
+
+
+
+
+
+
diff --git a/src/views/form/stepForm/StepForm.vue b/src/views/form/stepForm/StepForm.vue
new file mode 100644
index 0000000..eb2da7b
--- /dev/null
+++ b/src/views/form/stepForm/StepForm.vue
@@ -0,0 +1,66 @@
+
+
+
+
+ 将一个冗长或用户不熟悉的表单任务分成多个步骤,指导用户完成。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/list/BasicList.vue b/src/views/list/BasicList.vue
new file mode 100644
index 0000000..de93f3f
--- /dev/null
+++ b/src/views/list/BasicList.vue
@@ -0,0 +1,220 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.title }}
+
+
+
+
+
+
Owner
+
{{ item.owner }}
+
+
+
开始时间
+
{{ item.startAt }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/list/CardList.vue b/src/views/list/CardList.vue
new file mode 100644
index 0000000..bdc8d01
--- /dev/null
+++ b/src/views/list/CardList.vue
@@ -0,0 +1,148 @@
+
+
+
+
+
+
+
+
+
+
+ 新增产品
+
+
+
+
+
+ {{ item.title }}
+
+ {{ item.content }}
+
+
+ 操作一
+ 操作二
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/list/QueryList.vue b/src/views/list/QueryList.vue
new file mode 100644
index 0000000..b3a2ca5
--- /dev/null
+++ b/src/views/list/QueryList.vue
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
diff --git a/src/views/list/TableList.vue b/src/views/list/TableList.vue
new file mode 100644
index 0000000..986eb2b
--- /dev/null
+++ b/src/views/list/TableList.vue
@@ -0,0 +1,318 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 全部
+ 关闭
+ 运行中
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 全部
+ 关闭
+ 运行中
+
+
+
+
+
+
+ 全部
+ 关闭
+ 运行中
+
+
+
+
+
+
+ 查询
+ this.queryParam = {}">重置
+
+ {{ advanced ? '收起' : '展开' }}
+
+
+
+
+
+
+
+
+
+
新建
+
+
+ 删除
+
+ 锁定
+
+
+ 批量操作
+
+
+
+
+
+
+ {{ index + 1 }}
+
+
+
+
+
+ {{ text }}
+
+
+
+
+ 配置
+
+ 订阅报警
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/list/components/Info.vue b/src/views/list/components/Info.vue
new file mode 100644
index 0000000..2bb1eb9
--- /dev/null
+++ b/src/views/list/components/Info.vue
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
diff --git a/src/views/list/modules/CreateForm.vue b/src/views/list/modules/CreateForm.vue
new file mode 100644
index 0000000..45f3e55
--- /dev/null
+++ b/src/views/list/modules/CreateForm.vue
@@ -0,0 +1,72 @@
+
+ { $emit('ok') }"
+ @cancel="() => { $emit('cancel') }"
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/list/modules/StepByStepModal.vue b/src/views/list/modules/StepByStepModal.vue
new file mode 100644
index 0000000..9200a94
--- /dev/null
+++ b/src/views/list/modules/StepByStepModal.vue
@@ -0,0 +1,172 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 表一
+ 表二
+
+
+
+
+
+ 规则模板一
+ 规则模板二
+
+
+
+
+
+ 强
+ 弱
+
+
+
+
+
+
+
+
+
+ 上一步
+ 取消
+ {{ currentStep === 2 && '完成' || '下一步' }}
+
+
+
+
+
diff --git a/src/views/list/modules/TaskForm.vue b/src/views/list/modules/TaskForm.vue
new file mode 100644
index 0000000..493ef0a
--- /dev/null
+++ b/src/views/list/modules/TaskForm.vue
@@ -0,0 +1,94 @@
+
+
+
+
+
+
+
+
+
+
+ 付晓晓
+ 周毛毛
+
+
+
+
+
+
+
+
+
diff --git a/src/views/list/search/Applications.vue b/src/views/list/search/Applications.vue
new file mode 100644
index 0000000..bd4d44a
--- /dev/null
+++ b/src/views/list/search/Applications.vue
@@ -0,0 +1,187 @@
+
+
+
+
+
+
+
+ 类目一
+ 类目二
+ 类目三
+ 类目四
+ 类目五
+ 类目六
+ 类目七
+ 类目八
+ 类目九
+ 类目十
+
+
+
+
+
+
+
+
+
+ 王昭君
+
+
+
+
+
+
+ 优秀
+ 普通
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1st menu item
+
+
+ 2nd menu item
+
+
+ 3rd menu item
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/list/search/Article.vue b/src/views/list/search/Article.vue
new file mode 100644
index 0000000..531c9a6
--- /dev/null
+++ b/src/views/list/search/Article.vue
@@ -0,0 +1,185 @@
+
+
+
+
+
+
+
+ 类目一
+ 类目二
+ 类目三
+ 类目四
+ 类目五
+ 类目六
+ 类目七
+ 类目八
+ 类目九
+ 类目十
+
+
+
+
+
+
+
+
+
+ {{ item.name }}
+
+ 只看自己的
+
+
+
+
+
+
+
+
+
+
+ 李三
+
+
+
+
+
+
+ 优秀
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.title }}
+
+
+ Ant Design
+ 设计语言
+ 蚂蚁金服
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/list/search/Projects.vue b/src/views/list/search/Projects.vue
new file mode 100644
index 0000000..e2d54df
--- /dev/null
+++ b/src/views/list/search/Projects.vue
@@ -0,0 +1,168 @@
+
+
+
+
+
+
+
+ 类目一
+ 类目二
+ 类目三
+ 类目四
+ 类目五
+ 类目六
+ 类目七
+ 类目八
+ 类目九
+ 类目十
+
+
+
+
+
+
+
+
+
+ 王昭君
+
+
+
+
+
+
+ 优秀
+ 普通
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.description }}
+
+
+
+
{{ item.updatedAt | fromNow }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/list/search/SearchLayout.vue b/src/views/list/search/SearchLayout.vue
new file mode 100644
index 0000000..cee6a35
--- /dev/null
+++ b/src/views/list/search/SearchLayout.vue
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/list/search/components/CardInfo.vue b/src/views/list/search/components/CardInfo.vue
new file mode 100644
index 0000000..1c54c99
--- /dev/null
+++ b/src/views/list/search/components/CardInfo.vue
@@ -0,0 +1,58 @@
+
+
+
+
活跃用户
+
{{ activeUser }}
+
+
+
+
+
+
+
+
diff --git a/src/views/list/search/components/IconText.vue b/src/views/list/search/components/IconText.vue
new file mode 100644
index 0000000..c7dd9e0
--- /dev/null
+++ b/src/views/list/search/components/IconText.vue
@@ -0,0 +1,22 @@
+
+
+
+ {{ text }}
+
+
+
+
diff --git a/src/views/list/table/Edit.vue b/src/views/list/table/Edit.vue
new file mode 100644
index 0000000..74b1695
--- /dev/null
+++ b/src/views/list/table/Edit.vue
@@ -0,0 +1,160 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Option 1
+ Option 2
+ Option 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 提交
+
+
+ 返回
+
+
+
+
+
+
+
+
+
diff --git a/src/views/list/table/List.vue b/src/views/list/table/List.vue
new file mode 100644
index 0000000..8e5da0b
--- /dev/null
+++ b/src/views/list/table/List.vue
@@ -0,0 +1,240 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 全部
+ 关闭
+ 运行中
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 全部
+ 关闭
+ 运行中
+
+
+
+
+
+
+ 全部
+ 关闭
+ 运行中
+
+
+
+
+
+
+ 查询
+ queryParam = {}">重置
+
+ {{ advanced ? '收起' : '展开' }}
+
+
+
+
+
+
+
+
+
+
新建
+
{{ optionAlertShow && '关闭' || '开启' }} alert
+
+
+ 删除
+
+ 锁定
+
+
+ 批量操作
+
+
+
+
+
+
+ {{ index + 1 }}
+
+
+
+ 编辑
+
+
+
+
+ 更多
+
+
+
+ 详情
+
+
+ 禁用
+
+
+ 删除
+
+
+
+
+
+
+
+
+
diff --git a/src/views/other/BigForm.vue b/src/views/other/BigForm.vue
new file mode 100644
index 0000000..5ec9622
--- /dev/null
+++ b/src/views/other/BigForm.vue
@@ -0,0 +1,554 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 王同学
+ 李同学
+ 黄同学
+
+
+
+
+
+
+
+
+ 王晓丽
+ 李军
+
+
+
+
+
+
+
+
+
+
+
+ 公开
+ 私密
+
+
+
+
+
+ Submit
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 王同学
+ 李同学
+ 黄同学
+
+
+
+
+
+
+
+
+ 王晓丽
+ 李军
+
+
+
+
+
+
+
+
+
+
+
+ 公开
+ 私密
+
+
+
+
+
+ Submit
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 王同学
+ 李同学
+ 黄同学
+
+
+
+
+
+
+
+
+ 王晓丽
+ 李军
+
+
+
+
+
+
+
+
+
+
+
+ 公开
+ 私密
+
+
+
+
+
+ Submit
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 王同学
+ 李同学
+ 黄同学
+
+
+
+
+
+
+
+
+ 王晓丽
+ 李军
+
+
+
+
+
+
+
+
+
+
+
+ 公开
+ 私密
+
+
+
+
+
+ Submit
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 王同学
+ 李同学
+ 黄同学
+
+
+
+
+
+
+
+
+ 王晓丽
+ 李军
+
+
+
+
+
+
+
+
+
+
+
+ 公开
+ 私密
+
+
+
+
+
+ Submit
+
+
+
+
+
+
+
+ handleChange(e.target.value, record.key, col)"
+ />
+ {{ text }}
+
+
+
+
+ 添加
+
+
+ 删除
+
+
+
+ 保存
+
+ 取消
+
+
+
+ 编辑
+
+
+ 删除
+
+
+
+
+ 新增成员
+
+
+
+
+
+
+
diff --git a/src/views/other/IconSelectorView.vue b/src/views/other/IconSelectorView.vue
new file mode 100644
index 0000000..1ea1da6
--- /dev/null
+++ b/src/views/other/IconSelectorView.vue
@@ -0,0 +1,36 @@
+
+
+
+
+
+ 测试 IconSelector 组件 v-model 功能
+ 改变 Icon-down
+
+ 改变 Icon-cloud-download
+
+
+
+
diff --git a/src/views/other/PermissionList.vue b/src/views/other/PermissionList.vue
new file mode 100644
index 0000000..2c09043
--- /dev/null
+++ b/src/views/other/PermissionList.vue
@@ -0,0 +1,272 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 全部
+ 关闭
+ 运行中
+
+
+
+
+
+ 查询
+ 重置
+
+
+
+
+
+
+
+
+
+ {{ action.describe }}
+
+
+
+ {{ text | statusFilter }}
+
+
+
+ 编辑
+
+
+
+ 更多
+
+
+
+ 详情
+
+
+ 禁用
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 正常
+ 禁用
+
+
+
+
+
+
+
+
+
+
+
+ {{ action.label }}
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/other/RoleList.vue b/src/views/other/RoleList.vue
new file mode 100644
index 0000000..0eb0915
--- /dev/null
+++ b/src/views/other/RoleList.vue
@@ -0,0 +1,182 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 全部
+ 正常
+ 禁用
+
+
+
+
+
+ 查询
+ 重置
+
+
+
+
+
+
+
+
+
+
+
+ {{ role.permissionName }}:
+
+
+ {{ action.describe }}
+
+ -
+
+
+
+
+ 编辑
+
+
+
+ 更多
+
+
+
+ 详情
+
+
+ 禁用
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/other/TableInnerEditList.vue b/src/views/other/TableInnerEditList.vue
new file mode 100644
index 0000000..493a2e9
--- /dev/null
+++ b/src/views/other/TableInnerEditList.vue
@@ -0,0 +1,268 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 全部
+ 关闭
+ 运行中
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 全部
+ 关闭
+ 运行中
+
+
+
+
+
+
+ 全部
+ 关闭
+ 运行中
+
+
+
+
+
+
+ 查询
+ 重置
+
+ {{ advanced ? '收起' : '展开' }}
+
+
+
+
+
+
+
+
+
+
新建
+
+
+ 删除
+
+ 锁定
+
+
+ 批量操作
+
+
+
+
+
+
+
+
handleChange(e.target.value, record.key, col, record)"
+ />
+ {{ text }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/other/TreeList.vue b/src/views/other/TreeList.vue
new file mode 100644
index 0000000..3936cf7
--- /dev/null
+++ b/src/views/other/TreeList.vue
@@ -0,0 +1,192 @@
+
+
+
+
+
+
+
+
+
+
+ 编辑
+
+
+
+
+ 更多
+
+
+
+ 详情
+
+
+ 禁用
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/other/UserList.vue b/src/views/other/UserList.vue
new file mode 100644
index 0000000..c41f3d3
--- /dev/null
+++ b/src/views/other/UserList.vue
@@ -0,0 +1,340 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 全部
+ 关闭
+ 运行中
+
+
+
+
+
+ 查询
+ 重置
+
+
+
+
+
+
+
+
+
+
+
+ {{ role.permissionName }}:
+
+
+ {{ action | permissionFilter }}
+
+ -
+
+
+
+ {{ text | statusFilter }}
+ {{ text | moment }}
+
+ 编辑
+
+
+
+ 更多
+
+
+
+ 详情
+
+
+ 禁用
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 正常
+ 禁用
+
+
+
+
+
+
+
+ 拥有权限
+
+
+ 全选
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/other/modules/OrgModal.vue b/src/views/other/modules/OrgModal.vue
new file mode 100644
index 0000000..d83955c
--- /dev/null
+++ b/src/views/other/modules/OrgModal.vue
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/other/modules/RoleModal.vue b/src/views/other/modules/RoleModal.vue
new file mode 100644
index 0000000..1998d77
--- /dev/null
+++ b/src/views/other/modules/RoleModal.vue
@@ -0,0 +1,146 @@
+
+
+
+
+
+
+ Finished
+
+ This is a description.
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/parseingPdf/Index.vue b/src/views/parseingPdf/Index.vue
new file mode 100644
index 0000000..bdf504a
--- /dev/null
+++ b/src/views/parseingPdf/Index.vue
@@ -0,0 +1,172 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 查询
+ 重置
+ 上传PDF
+
+ {{ advanced ? '收起' : '展开' }}
+
+
+
+
+
+
+
+
+
+
+
+
上传日期:{{ item.createTime | dayjs }}
+
+
+
上传人:{{ item.createUserName || '-' }}
+
+ {{ item.fileName }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/parseingPdf/UploadModal.vue b/src/views/parseingPdf/UploadModal.vue
new file mode 100644
index 0000000..5b037c8
--- /dev/null
+++ b/src/views/parseingPdf/UploadModal.vue
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/profile/advanced/Advanced.vue b/src/views/profile/advanced/Advanced.vue
new file mode 100644
index 0000000..1ea29a9
--- /dev/null
+++ b/src/views/profile/advanced/Advanced.vue
@@ -0,0 +1,373 @@
+
+
+
+
+ 曲丽丽
+ XX 服务
+ 2017-07-07
+
+ 12421
+
+ 2017-07-07 ~ 2017-08-08
+ 请于两个工作日内确认
+
+
+
+
+
+
+ 操作
+ 操作
+
+
+ 主操作
+
+
+
+
+
+ 状态
+ 待审批
+
+
+ 订单金额
+ ¥ 568.08
+
+
+
+
+
+
+
+
+ 创建项目
+
+
+
+ 曲丽丽
+
2016-12-12 12:32
+
+
+
+
+
+ 部门初审
+
+
+
+
+
+
+
+
+
+
+
+
+ 付晓晓
+ 32943898021309809423
+ 3321944288191034921
+ 18112345678
+ 浙江省杭州市西湖区黄姑山路工专路交叉路口
+
+
+ 725
+ 2018-08-08
+
+ 725
+ 2018-08-08
+
+
+
+
+ 林东东
+ 1234567
+ XX公司-YY部
+ 2018-08-08
+ 这段描述很长很长很长很长很长很长很长很长很长很长很长很长很长很长...
+
+
+
+ Citrullus lanatus (Thunb.) Matsum. et Nakai一年生蔓生藤本;茎、枝粗壮,具明显的棱。卷须较粗..
+
+
+
+ 付小小
+ 1234567
+
+
+
+
+
+
+
+
+
+
+ {this.operationActiveTabKey = key}"
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/profile/basic/index.vue b/src/views/profile/basic/index.vue
new file mode 100644
index 0000000..efaf623
--- /dev/null
+++ b/src/views/profile/basic/index.vue
@@ -0,0 +1,249 @@
+
+
+
+
+ 1000000000
+ 已取货
+ 1234123421
+ 3214321432
+
+
+
+ 付小小
+ 18100000000
+ 菜鸟仓储
+ 浙江省杭州市西湖区万塘路18号
+ 无
+
+
+
+ 退货商品
+
+
+
+
+ 退货进度
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/project/biddingproject/Form.vue b/src/views/project/biddingproject/Form.vue
new file mode 100644
index 0000000..6fecacf
--- /dev/null
+++ b/src/views/project/biddingproject/Form.vue
@@ -0,0 +1,281 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 万元
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ participateUnitTips }}
+
+
+
+
+
+
+
+
+
+
+ {{ item }}
+
+
+
+
+
+
+
+ 万元
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/project/biddingproject/Index.vue b/src/views/project/biddingproject/Index.vue
new file mode 100644
index 0000000..f6fa322
--- /dev/null
+++ b/src/views/project/biddingproject/Index.vue
@@ -0,0 +1,1220 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
+ {{ item.title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.unitName }}
+
+
+
+
+
+
+
+ {{ item.unitName }}
+
+
+
+
+
+
+
+
+
+
+
+
+ 查询
+ 重置
+
+ {{ advanced ? '收起' : '展开' }}
+
+
+
+
+
+
+
+
+
+
+ {{ text | dayjs }}
+ {{ text | byteConvert }}
+ {{ text }}
+
+ {{ { 0: '未审核', 1: '已审核', 2: '违规' }[text] }}
+
+
+
+ {{ { 0: '未开始', 1: '解析中', 2: '待提交', 3: '待审核', 4: '已完成', 5: '违规', 6: '等待中', '-1': '失败' }[text] }}
+
+
+ ,当前任务排名:{{ record.checkOrder }}
+
+
+
+
+
+
+
+
+ 审查表
+
+
+
+
+ 查重
+
+
+
+ 停止
+
+
+
+
+
+ 置顶
+
+
+
+
+
+ 编辑
+
+
+
+
+ 删除
+
+
+
+
+ 提交
+
+
+
+
+ 总报告
+
+
+
+
+
+ 审批
+
+
+
+
+ 通过审核
+ 退回
+ 违规
+
+
+
+
+
+
+ 日志
+
+
+
+ {{ text | byteConvert }}
+
+ {{ text }}
+
+
+ 下载源文件|
+ 下载解析文件|
+ 在线预览
+
+
+ 查看报告
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 打印
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/project/biddingproject/ReturnBackModal.vue b/src/views/project/biddingproject/ReturnBackModal.vue
new file mode 100644
index 0000000..889716f
--- /dev/null
+++ b/src/views/project/biddingproject/ReturnBackModal.vue
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/project/biddingproject/ViewDoc.vue b/src/views/project/biddingproject/ViewDoc.vue
new file mode 100644
index 0000000..5edeb91
--- /dev/null
+++ b/src/views/project/biddingproject/ViewDoc.vue
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
diff --git a/src/views/project/biddingproject/components/CheckResultPreview.vue b/src/views/project/biddingproject/components/CheckResultPreview.vue
new file mode 100644
index 0000000..5d16b3f
--- /dev/null
+++ b/src/views/project/biddingproject/components/CheckResultPreview.vue
@@ -0,0 +1,146 @@
+
+
+
+
+
+ 采购内容
+ {{ data.procurementContent }}
+ 月计划号
+ {{ data.projectNumber }}
+
+
+ 重复分析
+
+ {{ data.analysis }}
+
+
+
+ 审查意见
+
+ {{ data.description }}
+
+
+
审查人:{{ data.userName }}
+
时 间:{{ data.createTime }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/project/biddingproject/components/DocPreview.vue b/src/views/project/biddingproject/components/DocPreview.vue
new file mode 100644
index 0000000..138964a
--- /dev/null
+++ b/src/views/project/biddingproject/components/DocPreview.vue
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
diff --git a/src/views/project/biddingproject/components/ImagePreview.vue b/src/views/project/biddingproject/components/ImagePreview.vue
new file mode 100644
index 0000000..a0354a7
--- /dev/null
+++ b/src/views/project/biddingproject/components/ImagePreview.vue
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/project/biddingproject/components/PdfPreview.vue b/src/views/project/biddingproject/components/PdfPreview.vue
new file mode 100644
index 0000000..c60200f
--- /dev/null
+++ b/src/views/project/biddingproject/components/PdfPreview.vue
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
diff --git a/src/views/project/biddingproject/components/TxtPreview.vue b/src/views/project/biddingproject/components/TxtPreview.vue
new file mode 100644
index 0000000..01db547
--- /dev/null
+++ b/src/views/project/biddingproject/components/TxtPreview.vue
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
diff --git a/src/views/project/biddingproject/components/logPreview.vue b/src/views/project/biddingproject/components/logPreview.vue
new file mode 100644
index 0000000..e471f4a
--- /dev/null
+++ b/src/views/project/biddingproject/components/logPreview.vue
@@ -0,0 +1,82 @@
+
+
+
+
+ {{ { 0: '退回', 1: '提交', 2: '审核通过', 3: '违规'}[text] }}
+
+
+
+
+
+
+
+
diff --git a/src/views/project/tenderBook/Form.vue b/src/views/project/tenderBook/Form.vue
new file mode 100644
index 0000000..45c3e4e
--- /dev/null
+++ b/src/views/project/tenderBook/Form.vue
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+ {{ item.projectName }}
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/project/tenderBook/Index.vue b/src/views/project/tenderBook/Index.vue
new file mode 100644
index 0000000..1ed4abd
--- /dev/null
+++ b/src/views/project/tenderBook/Index.vue
@@ -0,0 +1,214 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 查询
+ 重置
+
+ {{ advanced ? '收起' : '展开' }}
+
+
+
+
+
+
+
+
+ {{ text | dayjs }}
+
+ 编辑
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/project/tenderproject/Form.vue b/src/views/project/tenderproject/Form.vue
new file mode 100644
index 0000000..bd18e95
--- /dev/null
+++ b/src/views/project/tenderproject/Form.vue
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/project/tenderproject/Index.vue b/src/views/project/tenderproject/Index.vue
new file mode 100644
index 0000000..5856e03
--- /dev/null
+++ b/src/views/project/tenderproject/Index.vue
@@ -0,0 +1,252 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 查询
+ 重置
+
+ {{ advanced ? '收起' : '展开' }}
+
+
+
+
+
+
+
+
+ {{ text | dayjs }}
+ {{ text | byteConvert }}
+
+ {{ text | dayjs }}
+
+
+ 编辑
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/recheck/Compare.vue b/src/views/recheck/Compare.vue
new file mode 100644
index 0000000..e9d0c3e
--- /dev/null
+++ b/src/views/recheck/Compare.vue
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+ 文档查重
+ 全文检索
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/recheck/Form.vue b/src/views/recheck/Form.vue
new file mode 100644
index 0000000..f3a741e
--- /dev/null
+++ b/src/views/recheck/Form.vue
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/recheck/Index.vue b/src/views/recheck/Index.vue
new file mode 100644
index 0000000..65e742a
--- /dev/null
+++ b/src/views/recheck/Index.vue
@@ -0,0 +1,508 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 查询
+ 重置
+
+ {{ advanced ? '收起' : '展开' }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ { 0: '未开始', 1: '解析中', 2: '已完成', '-1': '失败' }[text] }}
+
+ {{ text | dayjs }}
+ {{ text | dayjs }}
+
+
+ {{ text / 100 | percentage }}
+
+
+
+
+
+
+ {{ text | byteConvert }}
+
+
+
+ 删除
+
+
+ e.preventDefault()">更多
+
+
+
+ 提交
+
+
+ 重新上传文档
+
+
+ 查看总报告
+
+
+
+
+
+
+
+
+
+
+
+ 删除
+
+
+
+
+
+
+
+ {{ text | byteConvert }}
+
+ {{ text }}
+
+
+
+
+
+ 下载|
+ 在线预览
+
+
+ 查看报告
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/recheck/UploadModel.vue b/src/views/recheck/UploadModel.vue
new file mode 100644
index 0000000..8e6b437
--- /dev/null
+++ b/src/views/recheck/UploadModel.vue
@@ -0,0 +1,322 @@
+
+
+
+
+
+
+ 批量导入文档查重
+
+
+ 指定文档与历史库所有文档查重
+
+
+
+
+
+
+
+
+
+
+
+ handleSelectParticipateUnit(val, idx)"
+ >
+ {{ item }}
+
+
+
+
+
+
+
+
+ 无过滤
+ 文本过滤
+ 文档过滤
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/recheck/ViewDoc.vue b/src/views/recheck/ViewDoc.vue
new file mode 100644
index 0000000..ba153c1
--- /dev/null
+++ b/src/views/recheck/ViewDoc.vue
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
diff --git a/src/views/recheck/components/Contrast.vue b/src/views/recheck/components/Contrast.vue
new file mode 100644
index 0000000..766eb77
--- /dev/null
+++ b/src/views/recheck/components/Contrast.vue
@@ -0,0 +1,617 @@
+
+
+
+
+
+
+
+
+ 请选择主文档
+
+
+ {{ item.fileName }}
+
+
+
+ 文章总字数:{{ compareDetail.textNumber }}
+ 文章相似度:
+
+ {{ ((Number(compareDetail.similarity* 100)).toFixed(0)) + '%' }}
+
+ 0%
+
+ 相似段落数:{{ compareDetail.similarityStructNumber }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 请选择对比文档
+
+
+ {{ item.fileName }}
+
+
+
+ 文章总字数:{{ compareDetail.reTextNumber }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ propertiesList[index].title }}
+
+
+
+
+
+
+ {{ leftProperties[propertiesList[index].key]| dayjs('YYYY-MM-DD HH:mm') }}
+
+
+ {{ Number(leftProperties[propertiesList[index].key]) | duration }}
+
+
+ {{ leftProperties[propertiesList[index].key] }}
+
+
+
+
+
+
+
+
+ {{ rightProperties[propertiesList[index].key]| dayjs('YYYY-MM-DD HH:mm') }}
+
+
+ {{ Number(rightProperties[propertiesList[index].key]) | duration }}
+
+
+ {{ rightProperties[propertiesList[index].key] }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/recheck/components/DocPreview.vue b/src/views/recheck/components/DocPreview.vue
new file mode 100644
index 0000000..cb072f3
--- /dev/null
+++ b/src/views/recheck/components/DocPreview.vue
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
diff --git a/src/views/recheck/components/Document.vue b/src/views/recheck/components/Document.vue
new file mode 100644
index 0000000..dda8202
--- /dev/null
+++ b/src/views/recheck/components/Document.vue
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
diff --git a/src/views/recheck/components/ImagePreview.vue b/src/views/recheck/components/ImagePreview.vue
new file mode 100644
index 0000000..2775ea5
--- /dev/null
+++ b/src/views/recheck/components/ImagePreview.vue
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/recheck/components/PdfPreview.vue b/src/views/recheck/components/PdfPreview.vue
new file mode 100644
index 0000000..d9d23aa
--- /dev/null
+++ b/src/views/recheck/components/PdfPreview.vue
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
diff --git a/src/views/recheck/components/Pie.vue b/src/views/recheck/components/Pie.vue
new file mode 100644
index 0000000..081bf47
--- /dev/null
+++ b/src/views/recheck/components/Pie.vue
@@ -0,0 +1,117 @@
+
+
+
+
+
diff --git a/src/views/recheck/components/PropertyCompareModal.vue b/src/views/recheck/components/PropertyCompareModal.vue
new file mode 100644
index 0000000..4132d61
--- /dev/null
+++ b/src/views/recheck/components/PropertyCompareModal.vue
@@ -0,0 +1,209 @@
+
+
+
+
+
+ {{ propertiesList[index].title }}
+
+
+
+
+
+
+ {{ leftProperties[propertiesList[index].key] | dayjs('YYYY-MM-DD HH:mm') }}
+
+
+ {{ Number(leftProperties[propertiesList[index].key]) | duration }}
+
+
+ {{ leftProperties[propertiesList[index].key] }}
+
+
+
+
+
+
+
+
+ {{ rightProperties[propertiesList[index].key] | dayjs('YYYY-MM-DD HH:mm') }}
+
+
+ {{ Number(rightProperties[propertiesList[index].key]) | duration }}
+
+
+ {{ rightProperties[propertiesList[index].key] }}
+
+
+
+
+
+
+
+
+
diff --git a/src/views/recheck/components/Report.vue b/src/views/recheck/components/Report.vue
new file mode 100644
index 0000000..d533df4
--- /dev/null
+++ b/src/views/recheck/components/Report.vue
@@ -0,0 +1,660 @@
+
+
+
+
+ 导出PDF
+
+
+
+
+
{{detail.procurementContent}}项目技术文档查重检测报告
+
+
+
+
+ 编号:
+
+ {{ detail.id }}
+
+
+
+
+
+ 送检文献:
+
+ {{ detail.checkFile.fileName }}
+
+
+
+
+
+
+
+ 检测时间:
+
+ {{ detail.checkTime }}
+
+
+
+
+
+ 检验人:
+
+ {{ detail.checkUser }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ fullBtnName }}
+ 返回
顶部
+
+
+
+
+
diff --git a/src/views/recheck/components/SliceUpload.vue b/src/views/recheck/components/SliceUpload.vue
new file mode 100644
index 0000000..9d091af
--- /dev/null
+++ b/src/views/recheck/components/SliceUpload.vue
@@ -0,0 +1,431 @@
+
+
+
+
+
+
+
+ 文档上传
+
+
+
+
+
+ 文档上传
+
+
+
+
+
+
+
+
{{ file.fileName }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/recheck/components/TextPer.vue b/src/views/recheck/components/TextPer.vue
new file mode 100644
index 0000000..e493c37
--- /dev/null
+++ b/src/views/recheck/components/TextPer.vue
@@ -0,0 +1,123 @@
+
+
+
+
+
+ 头部
+ 中前部
+ 中部
+ 中后部
+ 尾部
+
+
+ 注释:
+ 无问题部分
+ 文字复制比部分
+
+
+
+
+
+
diff --git a/src/views/recheck/components/TotalRecord.vue b/src/views/recheck/components/TotalRecord.vue
new file mode 100644
index 0000000..51954a6
--- /dev/null
+++ b/src/views/recheck/components/TotalRecord.vue
@@ -0,0 +1,287 @@
+
+
+
+
+
{{ procurementContent }}项目技术文档查重检测报告
+
+
+
+
+
+
+
+
+
diff --git a/src/views/recheck/taskProgress/Index.vue b/src/views/recheck/taskProgress/Index.vue
new file mode 100644
index 0000000..a3f49bd
--- /dev/null
+++ b/src/views/recheck/taskProgress/Index.vue
@@ -0,0 +1,294 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 未开始
+ 解析中
+ 已完成
+ 失败
+
+
+
+
+
+
+
+
+
+
+
+ 查询
+ 重置
+
+ {{ advanced ? '收起' : '展开' }}
+
+
+
+
+
+
+
+
+
+
+ {{ text | byteConvert }}
+
+
+
+
+
+
+ {{ text | dayjs }}
+
+
+
+ {{ { 0: '未开始', 1: '解析中', 2: '已完成', '-1': '失败' }[text] }}
+
+
+
+ 重新解析
+
+
+
+ 删除
+
+
+
+
+
+
+
+
+
diff --git a/src/views/recheckSetting/OtherSetting.vue b/src/views/recheckSetting/OtherSetting.vue
new file mode 100644
index 0000000..c5795a6
--- /dev/null
+++ b/src/views/recheckSetting/OtherSetting.vue
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+ 保存
+
+
+
+
+
+
+
+
diff --git a/src/views/result/Error.vue b/src/views/result/Error.vue
new file mode 100644
index 0000000..c875939
--- /dev/null
+++ b/src/views/result/Error.vue
@@ -0,0 +1,39 @@
+
+
+
+
+ {{ $t('result.fail.error.btn-text') }}
+
+
+
+ {{ $t('result.fail.error.hint-title') }}
+
+
+
+
+
+
+
+
+
diff --git a/src/views/result/Success.vue b/src/views/result/Success.vue
new file mode 100644
index 0000000..bc54199
--- /dev/null
+++ b/src/views/result/Success.vue
@@ -0,0 +1,89 @@
+
+
+
+
+ {{ $t('result.success.btn-return') }}
+ {{ $t('result.success.btn-project') }}
+ {{ $t('result.success.btn-print') }}
+
+
+
{{ $t('result.success.operate-title') }}
+
+
+ {{ $t('result.success.operate-id') }}:
+ 20180724089
+
+
+ {{ $t('result.success.principal') }}:
+ 曲丽丽是谁?
+
+
+ {{ $t('result.success.operate-time') }}:
+ 2016-12-12 ~ 2017-12-12
+
+
+
+
+ {{ $t('result.success.step1-title') }}
+
+
+
+
+
+ {{ $t('result.success.step2-title') }}
+
+
+
+
+
+ {{ $t('result.success.step3-title') }}
+
+
+ {{ $t('result.success.step4-title') }}
+
+
+
+
+
+
+
+
diff --git a/src/views/system/area/list.vue b/src/views/system/area/list.vue
new file mode 100644
index 0000000..ab6439c
--- /dev/null
+++ b/src/views/system/area/list.vue
@@ -0,0 +1,118 @@
+
+
+
+
+
+
+ {{ index + 1 }}
+
+
+ {{ record }}
+
+
+
+
+
+
+
+
+
diff --git a/src/views/system/backup/Form.vue b/src/views/system/backup/Form.vue
new file mode 100644
index 0000000..f105b60
--- /dev/null
+++ b/src/views/system/backup/Form.vue
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item }}
+
+
+
+
+ 启用
+ 停用
+
+
+
+
+
+
+
+
+
diff --git a/src/views/system/backup/Index.vue b/src/views/system/backup/Index.vue
new file mode 100644
index 0000000..6354131
--- /dev/null
+++ b/src/views/system/backup/Index.vue
@@ -0,0 +1,160 @@
+
+
+
+
+ 备份
+ 更新配置
+
+
+ {{ text | dayjs }}
+ {{ text | byteConvert }}
+
+
+ 下载
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/system/checkFilter/Index.vue b/src/views/system/checkFilter/Index.vue
new file mode 100644
index 0000000..eebff8d
--- /dev/null
+++ b/src/views/system/checkFilter/Index.vue
@@ -0,0 +1,81 @@
+
+
+
+
+
+ {{ value }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 保存
+
+
+
+
+
+
+
+
diff --git a/src/views/system/conclusion/Form.vue b/src/views/system/conclusion/Form.vue
new file mode 100644
index 0000000..b378c67
--- /dev/null
+++ b/src/views/system/conclusion/Form.vue
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/system/conclusion/Index.vue b/src/views/system/conclusion/Index.vue
new file mode 100644
index 0000000..98a6f48
--- /dev/null
+++ b/src/views/system/conclusion/Index.vue
@@ -0,0 +1,131 @@
+
+
+
+ 新增
+
+
+
+
+
+ {{ getTableIndex(index) }}
+
+
+
+
+ {{ text }}
+
+
+
+
+ {{ record.lowerLimit + '%' }} - {{ record.upperLimit + '%' }}
+
+
+
+
+
+ {{ record.createTime | moment('YYYY-MM-DD HH:mm') }}
+
+
+
+
+
+ {{ record.updateTime | moment('YYYY-MM-DD HH:mm') }}
+
+
+
+
+ 编辑
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/system/dept/DeptForm.vue b/src/views/system/dept/DeptForm.vue
new file mode 100644
index 0000000..7c430e6
--- /dev/null
+++ b/src/views/system/dept/DeptForm.vue
@@ -0,0 +1,162 @@
+
+ this.handleCancel()"
+ @ok="() => this.handleOk()"
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/system/dept/deptlist.vue b/src/views/system/dept/deptlist.vue
new file mode 100644
index 0000000..8e0a1e9
--- /dev/null
+++ b/src/views/system/dept/deptlist.vue
@@ -0,0 +1,198 @@
+
+
+
+
+
+
+
+ {{ text | statusFilter }}
+ {{ text | statusFilter }}
+
+
+ {{ text | moment }}
+
+ 编辑
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/system/dict/DictDataForm.vue b/src/views/system/dict/DictDataForm.vue
new file mode 100644
index 0000000..5ed10f4
--- /dev/null
+++ b/src/views/system/dict/DictDataForm.vue
@@ -0,0 +1,174 @@
+
+ this.handleCancel()"
+ @ok="() => this.handleOk()"
+ switch-fullscreen
+ :fullscreen.sync="fullscreen"
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/system/dict/DictTypeForm.vue b/src/views/system/dict/DictTypeForm.vue
new file mode 100644
index 0000000..2b85bee
--- /dev/null
+++ b/src/views/system/dict/DictTypeForm.vue
@@ -0,0 +1,152 @@
+
+ this.handleCancel()"
+ @ok="() => this.handleOk()"
+ switch-fullscreen
+ :fullscreen.sync="fullscreen"
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 正常
+ 停用
+
+
+
+
+
+
+
+
diff --git a/src/views/system/dict/dictlist.vue b/src/views/system/dict/dictlist.vue
new file mode 100644
index 0000000..61e8bd7
--- /dev/null
+++ b/src/views/system/dict/dictlist.vue
@@ -0,0 +1,310 @@
+
+
+
+
+
+
+
+
+ 编辑节点
+ 删除节点
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 查询
+ 重置
+
+
+
+
+
+
+
新建
+
+
+ 删除
+ 锁定
+
+ 批量操作
+
+
+
+
+ {{ index + 1 }}
+
+ 编辑
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/system/filterWord/Form.vue b/src/views/system/filterWord/Form.vue
new file mode 100644
index 0000000..9f1f61e
--- /dev/null
+++ b/src/views/system/filterWord/Form.vue
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/system/filterWord/Index.vue b/src/views/system/filterWord/Index.vue
new file mode 100644
index 0000000..25ed077
--- /dev/null
+++ b/src/views/system/filterWord/Index.vue
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+ {{ getTableIndex(index) }}
+
+
+
+
+ {{ text }}
+
+
+
+
+
+ {{ record.createTime | moment('YYYY-MM-DD HH:mm') }}
+
+
+
+
+
+ {{ record.updateTime | moment('YYYY-MM-DD HH:mm') }}
+
+
+
+
+ 编辑
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/system/log/SystemLogDetailForm.vue b/src/views/system/log/SystemLogDetailForm.vue
new file mode 100644
index 0000000..3a25435
--- /dev/null
+++ b/src/views/system/log/SystemLogDetailForm.vue
@@ -0,0 +1,164 @@
+
+ this.handleCancel()"
+ >
+
+
+ {{ detailData.status === 1 ? '失败' : '成功' }}
+
+
+
+
+ 操作人
+
+
+ {{ detailData.createUserName }}
+
+
+
+
+ 操作时间
+
+
+ {{ moment(detailData.createTime).format('YYYY-MM-DD HH:mm:ss') }}
+
+
+
+
+ 操作类型
+
+
+ {{ detailData.operationType }}
+
+
+
+
+ 请求IP
+
+
+ {{ detailData.ip }}
+
+
+
+
+ 请求方法
+
+
+ {{ detailData.method }}
+
+
+
+
+
+ 请求参数
+
+
+
+
+
+
+
+ 请求结果
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/system/log/loglist.vue b/src/views/system/log/loglist.vue
new file mode 100644
index 0000000..8846225
--- /dev/null
+++ b/src/views/system/log/loglist.vue
@@ -0,0 +1,241 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 成功
+ 失败
+
+
+
+
+
+ 查询
+ 重置
+ 下载日志
+
+
+
+
+
+
+ {{ index + 1 }}
+
+ {{ text }}
+
+ {{ text | statusFilter }}
+
+ {{ text | dayjs }}
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/system/menu/ImportSql.vue b/src/views/system/menu/ImportSql.vue
new file mode 100644
index 0000000..8176f4b
--- /dev/null
+++ b/src/views/system/menu/ImportSql.vue
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/system/menu/MenuForm.vue b/src/views/system/menu/MenuForm.vue
new file mode 100644
index 0000000..a3387c9
--- /dev/null
+++ b/src/views/system/menu/MenuForm.vue
@@ -0,0 +1,178 @@
+
+ this.handleCancel()"
+ @ok="() => this.handleOk()"
+ >
+
+
+
+
+
+
+
+ 目录
+ 菜单
+ 按钮
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 显示
+ 隐藏
+
+
+
+
+ 正常
+ 停用
+
+
+
+
+
+
+
diff --git a/src/views/system/menu/menulist.vue b/src/views/system/menu/menulist.vue
new file mode 100644
index 0000000..ebdcf99
--- /dev/null
+++ b/src/views/system/menu/menulist.vue
@@ -0,0 +1,272 @@
+
+
+
+
+
+
+
+ {{ text | statusFilter }}
+ {{ text | statusFilter }}
+
+
+
+
+ {{ '/'+record.fullPath }}
+ {{ '/'+record.fullPath }}
+
+
+ {{ ['','目录','菜单','按钮'][text] }}
+
+
+ {{ ['','显示','隐藏'][text] }}
+
+
+ {{ ['','正常','停用'][text] }}
+
+
+ {{ record.createUserName }}
+ {{ record.createTime | moment('YYYY-MM-DD HH:mm') }}
+
+
+ {{ record.updateUserName }}
+ {{ record.updateTime | moment('YYYY-MM-DD HH:mm') }}
+
+
+ 编辑
+
+
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/system/role/RoleForm.vue b/src/views/system/role/RoleForm.vue
new file mode 100644
index 0000000..f059d24
--- /dev/null
+++ b/src/views/system/role/RoleForm.vue
@@ -0,0 +1,147 @@
+
+ this.handleCancel()"
+ @ok="() => this.handleOk()"
+ switch-fullscreen
+ :mask-closable="false"
+ :fullscreen.sync="fullscreen"
+ >
+
+
+
+
+
+
+
+
+
+
+ 正常
+ 停用
+
+
+
+
+
+
+
+
diff --git a/src/views/system/role/RolePermissionSetting.vue b/src/views/system/role/RolePermissionSetting.vue
new file mode 100644
index 0000000..bfd665c
--- /dev/null
+++ b/src/views/system/role/RolePermissionSetting.vue
@@ -0,0 +1,176 @@
+
+ this.handleCancel()"
+ @ok="() => this.handleOk()"
+ :mask-closable="false"
+ switch-fullscreen
+ :fullscreen.sync="fullscreen"
+ >
+
+
+
+
+ {{ text | statusFilter }}
+ {{ text | statusFilter }}
+
+ {{ text | moment }}
+
+
+ {{ item.menuName }}
+
+
+
+
+
+
+
+
+
diff --git a/src/views/system/role/rolelist.vue b/src/views/system/role/rolelist.vue
new file mode 100644
index 0000000..d1c73bd
--- /dev/null
+++ b/src/views/system/role/rolelist.vue
@@ -0,0 +1,261 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 查询
+ 重置
+
+
+
+ 新建
+
+
+
+
+
+
+ {{ text | statusFilter }}
+
+ {{ moment(text).format('YYYY-MM-DD') }}
+
+ 编辑
+
+
+
+ 删除
+
+
+ 授权
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/system/user/CreateForm.vue b/src/views/system/user/CreateForm.vue
new file mode 100644
index 0000000..9673dfc
--- /dev/null
+++ b/src/views/system/user/CreateForm.vue
@@ -0,0 +1,221 @@
+
+ this.handleCancel()"
+ @ok="() => this.handleOk()"
+ switch-fullscreen
+ :fullscreen.sync="fullscreen"
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 男
+ 女
+
+
+
+
+
+
+
+
+
+
+ 正常
+ 停用
+
+
+
+
+ {{ item.title }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/system/user/PasswordForm.vue b/src/views/system/user/PasswordForm.vue
new file mode 100644
index 0000000..251eb3d
--- /dev/null
+++ b/src/views/system/user/PasswordForm.vue
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/system/user/list.vue b/src/views/system/user/list.vue
new file mode 100644
index 0000000..7100b73
--- /dev/null
+++ b/src/views/system/user/list.vue
@@ -0,0 +1,408 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 正常
+ 停用
+
+
+
+
+
+ 查询
+ 重置
+
+
+
+
+
+
+
+
新建
+
导入
+
+
+
+ 删除
+
+
+
+ 锁定
+
+
+ 批量操作
+
+
+
+
+
+
+
+ {{ index + 1 }}
+
+
+ handleChangeStatus(record, val)" />
+
+
+ {{ text }}
+
+
+ {{ text ? moment(text).format('YYYY-MM-DD HH:mm') : '' }}
+
+
+
+ 编辑
+
+ 删除
+
+ 初始化密码
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/user/Login.vue b/src/views/user/Login.vue
new file mode 100644
index 0000000..516bb94
--- /dev/null
+++ b/src/views/user/Login.vue
@@ -0,0 +1,385 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/user/Register.vue b/src/views/user/Register.vue
new file mode 100644
index 0000000..8d5e59d
--- /dev/null
+++ b/src/views/user/Register.vue
@@ -0,0 +1,316 @@
+
+
+
{{ $t('user.register.register') }}
+
+
+
+
+
+
+
+
+
{{ $t(passwordLevelName) }}
+
+
+ {{ $t('user.register.password.popover-message') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +86
+ +87
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('user.register.register') }}
+
+ {{ $t('user.register.sign-in') }}
+
+
+
+
+
+
+
+
+
diff --git a/src/views/user/RegisterResult.vue b/src/views/user/RegisterResult.vue
new file mode 100644
index 0000000..e76511f
--- /dev/null
+++ b/src/views/user/RegisterResult.vue
@@ -0,0 +1,44 @@
+
+
+
+
+ 查看邮箱
+ 返回首页
+
+
+
+
+
+
+
+
diff --git a/src/views/user/ResetPwd.vue b/src/views/user/ResetPwd.vue
new file mode 100644
index 0000000..d9cad2c
--- /dev/null
+++ b/src/views/user/ResetPwd.vue
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 确认修改
+
+
+
+
+
+
+
+
+
diff --git a/tests/unit/.eslintrc.js b/tests/unit/.eslintrc.js
new file mode 100644
index 0000000..958d51b
--- /dev/null
+++ b/tests/unit/.eslintrc.js
@@ -0,0 +1,5 @@
+module.exports = {
+ env: {
+ jest: true
+ }
+}
diff --git a/vue.config.js b/vue.config.js
new file mode 100644
index 0000000..ddc7378
--- /dev/null
+++ b/vue.config.js
@@ -0,0 +1,135 @@
+const path = require('path')
+const webpack = require('webpack')
+const GitRevisionPlugin = require('git-revision-webpack-plugin')
+const GitRevision = new GitRevisionPlugin()
+const buildDate = JSON.stringify(new Date().toLocaleString())
+const createThemeColorReplacerPlugin = require('./config/plugin.config')
+
+function resolve (dir) {
+ return path.join(__dirname, dir)
+}
+
+// check Git
+function getGitHash () {
+ try {
+ return GitRevision.version()
+ } catch (e) { }
+ return 'unknown'
+}
+// eslint-disable-next-line no-unused-vars
+const isProd = process.env.NODE_ENV === 'production'
+// eslint-disable-next-line no-unused-vars
+const assetsCDN = {
+ // webpack build externals
+ externals: {
+ vue: 'Vue',
+ 'vue-router': 'VueRouter',
+ vuex: 'Vuex',
+ axios: 'axios'
+ },
+ css: [],
+ // https://unpkg.com/browse/vue@2.6.10/
+ js: [
+ '//cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js',
+ '//cdn.jsdelivr.net/npm/vue-router@3.5.1/dist/vue-router.min.js',
+ '//cdn.jsdelivr.net/npm/vuex@3.1.1/dist/vuex.min.js',
+ '//cdn.jsdelivr.net/npm/axios@0.21.1/dist/axios.min.js'
+ ]
+}
+
+// vue.config.js
+const vueConfig = {
+ configureWebpack: {
+ // webpack plugins
+ plugins: [
+ // Ignore all locale files of moment.js
+ new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
+ new webpack.DefinePlugin({
+ APP_VERSION: `"${require('./package.json').version}"`,
+ GIT_HASH: JSON.stringify(getGitHash()),
+ BUILD_DATE: buildDate
+ })
+ ]
+ // en_US: `if prod, add externals`
+ // zh_CN: `这里是用来控制编译忽略外部依赖的,与 config.plugin('html') 配合可以编译时引入外部CDN文件依赖`
+ // externals: isProd ? assetsCDN.externals : {}
+ },
+
+ chainWebpack: (config) => {
+ config.resolve.alias.set('@$', resolve('src'))
+
+ const svgRule = config.module.rule('svg')
+ svgRule.uses.clear()
+ svgRule
+ .oneOf('inline')
+ .resourceQuery(/inline/)
+ .use('vue-svg-icon-loader')
+ .loader('vue-svg-icon-loader')
+ .end()
+ .end()
+ .oneOf('external')
+ .use('file-loader')
+ .loader('file-loader')
+ .options({
+ name: 'assets/[name].[hash:8].[ext]',
+ esModule: false
+ })
+
+ // en_US: If prod is on assets require on cdn
+ // zh_CN: 如果是 prod 模式,则引入 CDN 依赖文件,有需要减少包大小请自行解除依赖
+ //
+ // if (isProd) {
+ // config.plugin('html').tap(args => {
+ // args[0].cdn = assetsCDN
+ // return args
+ // })
+ // }
+ },
+
+ css: {
+ loaderOptions: {
+ less: {
+ modifyVars: {
+ // less vars,customize ant design theme
+
+ 'primary-color': '#0f81f4',
+ // 'link-color': '#F5222D',
+ 'border-radius-base': '2px'
+ },
+ // DO NOT REMOVE THIS LINE
+ javascriptEnabled: true
+ }
+ }
+ },
+
+ devServer: {
+ // development server port 8000
+ port: 8001,
+ // If you want to turn on the proxy, please remove the mockjs /src/main.jsL11
+ proxy: {
+ '/api': {
+ target: 'http://127.0.0.1:8888',
+ // target: 'http://106.14.238.204:9079/',
+ ws: false,
+ changeOrigin: true,
+ pathRewrite: {
+ '^/api': ''
+ }
+ }
+ }
+ },
+
+ // disable source map in production
+ productionSourceMap: false,
+ lintOnSave: undefined,
+ // babel-loader no-ignore node_modules/*
+ transpileDependencies: []
+}
+
+// preview.pro.loacg.com only do not use in your production;
+if (process.env.VUE_APP_PREVIEW === 'true') {
+ // add `ThemeColorReplacer` plugin to webpack plugins
+ vueConfig.configureWebpack.plugins.push(createThemeColorReplacerPlugin())
+}
+
+module.exports = vueConfig