feat: 项目初始化
0 parents
Showing
150 changed files
with
4676 additions
and
0 deletions
.editorconfig
0 → 100644
.eslintignore
0 → 100644
.eslintrc.js
0 → 100644
.gitignore
0 → 100644
| 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
| 2 | |||
| 3 | # dependencies | ||
| 4 | **/node_modules | ||
| 5 | # roadhog-api-doc ignore | ||
| 6 | /src/utils/request-temp.js | ||
| 7 | _roadhog-api-doc | ||
| 8 | |||
| 9 | /dist | ||
| 10 | |||
| 11 | # production | ||
| 12 | /.vscode | ||
| 13 | |||
| 14 | # misc | ||
| 15 | .DS_Store | ||
| 16 | npm-debug.log* | ||
| 17 | yarn-error.log | ||
| 18 | |||
| 19 | /coverage | ||
| 20 | .idea | ||
| 21 | yarn.lock | ||
| 22 | package-lock.json | ||
| 23 | *bak | ||
| 24 | .vscode | ||
| 25 | |||
| 26 | # visual studio code | ||
| 27 | .history | ||
| 28 | *.log | ||
| 29 | functions/* | ||
| 30 | .temp/** | ||
| 31 | |||
| 32 | # umi | ||
| 33 | .umi | ||
| 34 | .umi-production | ||
| 35 | |||
| 36 | # screenshot | ||
| 37 | screenshot | ||
| 38 | .firebase | ||
| 39 | .eslintcache | ||
| 40 | |||
| 41 | build |
.prettierignore
0 → 100644
| 1 | **/*.svg | ||
| 2 | package.json | ||
| 3 | .umi | ||
| 4 | .umi-production | ||
| 5 | /dist | ||
| 6 | .dockerignore | ||
| 7 | .DS_Store | ||
| 8 | .eslintignore | ||
| 9 | *.png | ||
| 10 | *.toml | ||
| 11 | docker | ||
| 12 | .editorconfig | ||
| 13 | Dockerfile* | ||
| 14 | .gitignore | ||
| 15 | .prettierignore | ||
| 16 | LICENSE | ||
| 17 | .eslintcache | ||
| 18 | *.lock | ||
| 19 | yarn-error.log | ||
| 20 | .history | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
.prettierrc.js
0 → 100644
.stylelintrc.js
0 → 100644
README.md
0 → 100644
| 1 | # 项目名称 | ||
| 2 | |||
| 3 | Follow is the quick guide for how to use. | ||
| 4 | |||
| 5 | ## Environment Prepare | ||
| 6 | |||
| 7 | Install `node_modules`: | ||
| 8 | |||
| 9 | ```bash | ||
| 10 | npm install | ||
| 11 | ``` | ||
| 12 | |||
| 13 | or | ||
| 14 | |||
| 15 | ```bash | ||
| 16 | yarn | ||
| 17 | ``` | ||
| 18 | |||
| 19 | ## Provided Scripts | ||
| 20 | |||
| 21 | Ant Design Pro provides some useful script to help you quick start and build with web project, code style check and test. | ||
| 22 | |||
| 23 | Scripts provided in `package.json`. It's safe to modify or add additional script: | ||
| 24 | |||
| 25 | ### Start project | ||
| 26 | |||
| 27 | ```bash | ||
| 28 | npm start | ||
| 29 | ``` | ||
| 30 | |||
| 31 | ### Build project | ||
| 32 | |||
| 33 | ```bash | ||
| 34 | npm run build | ||
| 35 | ``` | ||
| 36 | |||
| 37 | ### Check code style | ||
| 38 | |||
| 39 | ```bash | ||
| 40 | npm run lint | ||
| 41 | ``` | ||
| 42 | |||
| 43 | You can also use script to auto fix some lint error: | ||
| 44 | |||
| 45 | ```bash | ||
| 46 | npm run lint:fix | ||
| 47 | ``` | ||
| 48 | |||
| 49 | ### Test code | ||
| 50 | |||
| 51 | ```bash | ||
| 52 | npm test | ||
| 53 | ``` | ||
| 54 | |||
| 55 | ## More | ||
| 56 | |||
| 57 | You can view full document on our [official website](https://pro.ant.design). And welcome any feedback in our [github](https://github.com/ant-design/ant-design-pro). |
config/config.js
0 → 100644
| 1 | import defaultSettings from './defaultSettings'; // https://umijs.org/config/ | ||
| 2 | import slash from 'slash2'; | ||
| 3 | import routes from './routerConfig'; | ||
| 4 | import proxy from './proxy'; | ||
| 5 | const { pwa, primaryColor } = defaultSettings; // preview.pro.ant.design only do not use in your production ; | ||
| 6 | // preview.pro.ant.design 专用环境变量,请不要在你的项目中使用它。 | ||
| 7 | const { ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION, REACT_APP_ENV } = process.env; | ||
| 8 | import { defineConfig, utils } from 'umi'; | ||
| 9 | |||
| 10 | const { winPath } = utils; | ||
| 11 | export default defineConfig({ | ||
| 12 | antd: {}, | ||
| 13 | dva: { | ||
| 14 | hmr: true, | ||
| 15 | }, | ||
| 16 | locale: { | ||
| 17 | default: 'zh-CN', | ||
| 18 | baseNavigator: true, | ||
| 19 | }, | ||
| 20 | dynamicImport: { | ||
| 21 | // 无需 level, webpackChunkName 配置 | ||
| 22 | // loadingComponent: './components/PageLoading/index' | ||
| 23 | loading: '@/components/PageLoading/index', | ||
| 24 | }, | ||
| 25 | hash: true, | ||
| 26 | targets: { | ||
| 27 | ie: 11, | ||
| 28 | }, | ||
| 29 | title: false, | ||
| 30 | // umi routes: https://umijs.org/zh/guide/router.html | ||
| 31 | routes: routes, | ||
| 32 | // Theme for antd: https://ant.design/docs/react/customize-theme-cn | ||
| 33 | theme: { | ||
| 34 | // ...darkTheme, | ||
| 35 | 'primary-color': primaryColor, | ||
| 36 | }, | ||
| 37 | define: { | ||
| 38 | REACT_APP_ENV: REACT_APP_ENV || false, | ||
| 39 | ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION: | ||
| 40 | ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION || '', // preview.pro.ant.design only do not use in your production ; preview.pro.ant.design 专用环境变量,请不要在你的项目中使用它。 | ||
| 41 | }, | ||
| 42 | ignoreMomentLocale: true, | ||
| 43 | lessLoader: { | ||
| 44 | javascriptEnabled: true, | ||
| 45 | }, | ||
| 46 | cssLoader: { | ||
| 47 | modules: { | ||
| 48 | getLocalIdent: (context, _, localName) => { | ||
| 49 | if ( | ||
| 50 | context.resourcePath.includes('node_modules') || | ||
| 51 | context.resourcePath.includes('ant.design.pro.less') || | ||
| 52 | context.resourcePath.includes('global.less') | ||
| 53 | ) { | ||
| 54 | return localName; | ||
| 55 | } | ||
| 56 | |||
| 57 | const match = context.resourcePath.match(/src(.*)/); | ||
| 58 | |||
| 59 | if (match && match[1]) { | ||
| 60 | const antdProPath = match[1].replace('.less', ''); | ||
| 61 | const arr = slash(antdProPath) | ||
| 62 | .split('/') | ||
| 63 | .map(a => a.replace(/([A-Z])/g, '-$1')) | ||
| 64 | .map(a => a.toLowerCase()); | ||
| 65 | return `antd-pro${arr.join('-')}-${localName}`.replace(/--/g, '-'); | ||
| 66 | } | ||
| 67 | |||
| 68 | return localName; | ||
| 69 | }, | ||
| 70 | }, | ||
| 71 | }, | ||
| 72 | manifest: { | ||
| 73 | basePath: '/', | ||
| 74 | }, | ||
| 75 | proxy: proxy[REACT_APP_ENV || 'dev'], | ||
| 76 | externals: { | ||
| 77 | react: 'React', | ||
| 78 | 'react-dom': 'ReactDOM', | ||
| 79 | bizcharts: 'BizCharts', | ||
| 80 | mockjs: 'Mock', | ||
| 81 | '@antv/data-set': 'DataSet', | ||
| 82 | }, | ||
| 83 | }); |
config/defaultSettings.js
0 → 100644
| 1 | import { routeMaps } from './routerConfig'; | ||
| 2 | export default { | ||
| 3 | navTheme: 'dark', | ||
| 4 | primaryColor: '#185DA2', | ||
| 5 | layout: 'sidemenu', | ||
| 6 | contentWidth: 'Fluid', | ||
| 7 | fixedHeader: false, | ||
| 8 | autoHideHeader: false, | ||
| 9 | fixSiderbar: false, | ||
| 10 | colorWeak: false, | ||
| 11 | menu: { | ||
| 12 | locale: true, | ||
| 13 | }, | ||
| 14 | title: '一网打“净”数智在线', | ||
| 15 | pwa: false, | ||
| 16 | iconfontUrl: '', | ||
| 17 | //缓存token的key | ||
| 18 | tokenKey: 'yh_token', | ||
| 19 | //md5的key | ||
| 20 | md5Key: 'QHZT', | ||
| 21 | // 路由对象 | ||
| 22 | routeMaps, | ||
| 23 | }; |
config/plugin.config.js
0 → 100644
| 1 | import path from 'path'; | ||
| 2 | |||
| 3 | function getModulePackageName(module) { | ||
| 4 | if (!module.context) return null; | ||
| 5 | const nodeModulesPath = path.join(__dirname, '../node_modules/'); | ||
| 6 | |||
| 7 | if (module.context.substring(0, nodeModulesPath.length) !== nodeModulesPath) { | ||
| 8 | return null; | ||
| 9 | } | ||
| 10 | |||
| 11 | const moduleRelativePath = module.context.substring(nodeModulesPath.length); | ||
| 12 | const [moduleDirName] = moduleRelativePath.split(path.sep); | ||
| 13 | let packageName = moduleDirName; // handle tree shaking | ||
| 14 | |||
| 15 | if (packageName && packageName.match('^_')) { | ||
| 16 | // eslint-disable-next-line prefer-destructuring | ||
| 17 | packageName = packageName.match(/^_(@?[^@]+)/)[1]; | ||
| 18 | } | ||
| 19 | |||
| 20 | return packageName; | ||
| 21 | } | ||
| 22 | |||
| 23 | export const webpackPlugin = config => { | ||
| 24 | // optimize chunks | ||
| 25 | config.optimization // share the same chunks across different modules | ||
| 26 | .runtimeChunk(false) | ||
| 27 | .splitChunks({ | ||
| 28 | chunks: 'async', | ||
| 29 | name: 'vendors', | ||
| 30 | maxInitialRequests: Infinity, | ||
| 31 | minSize: 0, | ||
| 32 | cacheGroups: { | ||
| 33 | vendors: { | ||
| 34 | test: module => { | ||
| 35 | const packageName = getModulePackageName(module) || ''; | ||
| 36 | |||
| 37 | if (packageName) { | ||
| 38 | return [ | ||
| 39 | 'bizcharts', | ||
| 40 | 'gg-editor', | ||
| 41 | 'g6', | ||
| 42 | '@antv', | ||
| 43 | 'gg-editor-core', | ||
| 44 | 'bizcharts-plugin-slider', | ||
| 45 | ].includes(packageName); | ||
| 46 | } | ||
| 47 | |||
| 48 | return false; | ||
| 49 | }, | ||
| 50 | |||
| 51 | name(module) { | ||
| 52 | const packageName = getModulePackageName(module); | ||
| 53 | |||
| 54 | if (packageName) { | ||
| 55 | if (['bizcharts', '@antv_data-set'].indexOf(packageName) >= 0) { | ||
| 56 | return 'viz'; // visualization package | ||
| 57 | } | ||
| 58 | } | ||
| 59 | |||
| 60 | return 'misc'; | ||
| 61 | }, | ||
| 62 | }, | ||
| 63 | }, | ||
| 64 | }); | ||
| 65 | }; |
config/proxy.js
0 → 100644
| 1 | /** | ||
| 2 | * 在生产环境 代理是无法生效的,所以这里没有生产环境的配置 | ||
| 3 | * The agent cannot take effect in the production environment | ||
| 4 | * so there is no configuration of the production environment | ||
| 5 | * For details, please see | ||
| 6 | * https://pro.ant.design/docs/deploy | ||
| 7 | */ | ||
| 8 | export default { | ||
| 9 | dev: { | ||
| 10 | '/ql/api/': { | ||
| 11 | target: 'https://yh2.jimilicai.com', | ||
| 12 | changeOrigin: true, | ||
| 13 | pathRewrite: { | ||
| 14 | '^': '', | ||
| 15 | }, | ||
| 16 | }, | ||
| 17 | }, | ||
| 18 | }; |
config/routerConfig/app.js
0 → 100644
| 1 | export default { | ||
| 2 | path: '/', | ||
| 3 | name: 'appliction', | ||
| 4 | component: '../layouts/BasicLayout', | ||
| 5 | routes: [ | ||
| 6 | { path: '/', redirect: '/screen' }, | ||
| 7 | { | ||
| 8 | path: '/screen', | ||
| 9 | name: 'dataScreen', | ||
| 10 | component: './Screen', | ||
| 11 | icons: 'screen', | ||
| 12 | resourceCode: 'Home', | ||
| 13 | }, | ||
| 14 | { | ||
| 15 | path: '/risk', | ||
| 16 | name: 'risk', | ||
| 17 | component: './Risk', | ||
| 18 | icons: 'risk', | ||
| 19 | resourceCode: 'RiskManage', | ||
| 20 | }, | ||
| 21 | { | ||
| 22 | path: '/event', | ||
| 23 | name: 'event', | ||
| 24 | component: './Incident', | ||
| 25 | icons: 'event', | ||
| 26 | resourceCode: 'EventManage', | ||
| 27 | }, | ||
| 28 | { | ||
| 29 | path: '/data', | ||
| 30 | name: 'data', | ||
| 31 | component: './Data', | ||
| 32 | icons: 'data', | ||
| 33 | resourceCode: 'DataManage', | ||
| 34 | }, | ||
| 35 | { | ||
| 36 | path: '/system', | ||
| 37 | name: 'system', | ||
| 38 | icons: 'system', | ||
| 39 | |||
| 40 | resourceCode: 'SystemManage', | ||
| 41 | routes: [ | ||
| 42 | { | ||
| 43 | path: '/system/account', | ||
| 44 | name: 'account', | ||
| 45 | component: './System/Account', | ||
| 46 | icons: '', | ||
| 47 | resourceCode: 'AccountManage', | ||
| 48 | }, | ||
| 49 | { | ||
| 50 | path: '/system/role', | ||
| 51 | name: 'role', | ||
| 52 | component: './System/Role', | ||
| 53 | icons: '', | ||
| 54 | resourceCode: 'RoleManage', | ||
| 55 | }, | ||
| 56 | { | ||
| 57 | path: '/system/menu', | ||
| 58 | name: 'menu', | ||
| 59 | component: './System/Menu', | ||
| 60 | icons: '', | ||
| 61 | resourceCode: 'MenuManage', | ||
| 62 | }, | ||
| 63 | ], | ||
| 64 | }, | ||
| 65 | { | ||
| 66 | component: './404', | ||
| 67 | resourceCode: '404', | ||
| 68 | }, | ||
| 69 | ], | ||
| 70 | }; |
config/routerConfig/index.js
0 → 100644
| 1 | import user from './user'; | ||
| 2 | import app from './app'; | ||
| 3 | import { cloneDeep } from 'lodash'; | ||
| 4 | |||
| 5 | const getRoutes = (routes, maps = {}) => { | ||
| 6 | routes = routes.map(item => { | ||
| 7 | if (item.auths) { | ||
| 8 | maps[item.path] = item.auths; | ||
| 9 | } | ||
| 10 | if (item.routes) { | ||
| 11 | item.routes = getRoutes(item.routes, maps).routes; | ||
| 12 | } | ||
| 13 | return item; | ||
| 14 | }); | ||
| 15 | routes.push({ | ||
| 16 | component: '../pages/404', | ||
| 17 | }); | ||
| 18 | return { | ||
| 19 | routes, | ||
| 20 | maps, | ||
| 21 | }; | ||
| 22 | }; | ||
| 23 | |||
| 24 | const { routes, maps } = getRoutes([user, app]); | ||
| 25 | |||
| 26 | export const routeMaps = maps; | ||
| 27 | |||
| 28 | export const codeMappingForResource = (() => { | ||
| 29 | let menu = cloneDeep([app]); | ||
| 30 | let codeMapping = new Map(); | ||
| 31 | const getItem = arr => { | ||
| 32 | arr.forEach(item => { | ||
| 33 | codeMapping.set(item?.resourceCode, item); | ||
| 34 | if (item.routes) { | ||
| 35 | getItem(item.routes); | ||
| 36 | } | ||
| 37 | }); | ||
| 38 | }; | ||
| 39 | getItem(menu); | ||
| 40 | return codeMapping; | ||
| 41 | })(); | ||
| 42 | |||
| 43 | export default routes; |
config/routerConfig/user.js
0 → 100644
config/themePluginConfig.js
0 → 100644
| 1 | export default { | ||
| 2 | theme: [ | ||
| 3 | { | ||
| 4 | key: 'dark', | ||
| 5 | fileName: 'dark.css', | ||
| 6 | theme: 'dark', | ||
| 7 | }, | ||
| 8 | { | ||
| 9 | key: 'dust', | ||
| 10 | fileName: 'dust.css', | ||
| 11 | modifyVars: { | ||
| 12 | '@primary-color': '#F5222D', | ||
| 13 | }, | ||
| 14 | }, | ||
| 15 | { | ||
| 16 | key: 'volcano', | ||
| 17 | fileName: 'volcano.css', | ||
| 18 | modifyVars: { | ||
| 19 | '@primary-color': '#FA541C', | ||
| 20 | }, | ||
| 21 | }, | ||
| 22 | { | ||
| 23 | key: 'sunset', | ||
| 24 | fileName: 'sunset.css', | ||
| 25 | modifyVars: { | ||
| 26 | '@primary-color': '#FAAD14', | ||
| 27 | }, | ||
| 28 | }, | ||
| 29 | { | ||
| 30 | key: 'cyan', | ||
| 31 | fileName: 'cyan.css', | ||
| 32 | modifyVars: { | ||
| 33 | '@primary-color': '#13C2C2', | ||
| 34 | }, | ||
| 35 | }, | ||
| 36 | { | ||
| 37 | key: 'green', | ||
| 38 | fileName: 'green.css', | ||
| 39 | modifyVars: { | ||
| 40 | '@primary-color': '#52C41A', | ||
| 41 | }, | ||
| 42 | }, | ||
| 43 | { | ||
| 44 | key: 'geekblue', | ||
| 45 | fileName: 'geekblue.css', | ||
| 46 | modifyVars: { | ||
| 47 | '@primary-color': '#2F54EB', | ||
| 48 | }, | ||
| 49 | }, | ||
| 50 | { | ||
| 51 | key: 'purple', | ||
| 52 | fileName: 'purple.css', | ||
| 53 | modifyVars: { | ||
| 54 | '@primary-color': '#722ED1', | ||
| 55 | }, | ||
| 56 | }, | ||
| 57 | { | ||
| 58 | key: 'dust', | ||
| 59 | theme: 'dark', | ||
| 60 | fileName: 'dark-dust.css', | ||
| 61 | modifyVars: { | ||
| 62 | '@primary-color': '#F5222D', | ||
| 63 | }, | ||
| 64 | }, | ||
| 65 | { | ||
| 66 | key: 'volcano', | ||
| 67 | theme: 'dark', | ||
| 68 | fileName: 'dark-volcano.css', | ||
| 69 | modifyVars: { | ||
| 70 | '@primary-color': '#FA541C', | ||
| 71 | }, | ||
| 72 | }, | ||
| 73 | { | ||
| 74 | key: 'sunset', | ||
| 75 | theme: 'dark', | ||
| 76 | fileName: 'dark-sunset.css', | ||
| 77 | modifyVars: { | ||
| 78 | '@primary-color': '#FAAD14', | ||
| 79 | }, | ||
| 80 | }, | ||
| 81 | { | ||
| 82 | key: 'cyan', | ||
| 83 | theme: 'dark', | ||
| 84 | fileName: 'dark-cyan.css', | ||
| 85 | modifyVars: { | ||
| 86 | '@primary-color': '#13C2C2', | ||
| 87 | }, | ||
| 88 | }, | ||
| 89 | { | ||
| 90 | key: 'green', | ||
| 91 | theme: 'dark', | ||
| 92 | fileName: 'dark-green.css', | ||
| 93 | modifyVars: { | ||
| 94 | '@primary-color': '#52C41A', | ||
| 95 | }, | ||
| 96 | }, | ||
| 97 | { | ||
| 98 | key: 'geekblue', | ||
| 99 | theme: 'dark', | ||
| 100 | fileName: 'dark-geekblue.css', | ||
| 101 | modifyVars: { | ||
| 102 | '@primary-color': '#2F54EB', | ||
| 103 | }, | ||
| 104 | }, | ||
| 105 | { | ||
| 106 | key: 'purple', | ||
| 107 | theme: 'dark', | ||
| 108 | fileName: 'dark-purple.css', | ||
| 109 | modifyVars: { | ||
| 110 | '@primary-color': '#722ED1', | ||
| 111 | }, | ||
| 112 | }, | ||
| 113 | ], | ||
| 114 | }; |
jest-puppeteer.config.js
0 → 100644
jest.config.js
0 → 100644
jsconfig.json
0 → 100644
package.json
0 → 100644
| 1 | { | ||
| 2 | "name": "ant-design-pro", | ||
| 3 | "version": "1.0.0", | ||
| 4 | "private": true, | ||
| 5 | "description": "An out-of-box UI solution for enterprise applications", | ||
| 6 | "scripts": { | ||
| 7 | "analyze": "cross-env ANALYZE=1 umi build", | ||
| 8 | "build": "umi build", | ||
| 9 | "deploy": "npm run site && npm run gh-pages", | ||
| 10 | "dev": "npm run start:dev", | ||
| 11 | "fetch:blocks": "pro fetch-blocks --branch antd@4 && npm run prettier", | ||
| 12 | "format-imports": "cross-env import-sort --write '**/*.{js,jsx,ts,tsx}'", | ||
| 13 | "gh-pages": "cp CNAME ./dist/ && gh-pages -d dist", | ||
| 14 | "i18n-remove": "pro i18n-remove --locale=zh-CN --write", | ||
| 15 | "lint": "npm run lint:js && npm run lint:style && npm run lint:prettier", | ||
| 16 | "lint-staged": "lint-staged", | ||
| 17 | "lint-staged:js": "eslint --ext .js,.jsx,.ts,.tsx ", | ||
| 18 | "lint:fix": "eslint --fix --cache --ext .js,.jsx,.ts,.tsx --format=pretty ./src && npm run lint:style", | ||
| 19 | "lint:js": "eslint --cache --ext .js,.jsx,.ts,.tsx --format=pretty ./src", | ||
| 20 | "lint:prettier": "check-prettier lint", | ||
| 21 | "lint:style": "stylelint --fix \"src/**/*.less\" --syntax less", | ||
| 22 | "prettier": "prettier -c --write \"**/*\"", | ||
| 23 | "start": "umi dev", | ||
| 24 | "start:dev": "cross-env REACT_APP_ENV=dev MOCK=none umi dev", | ||
| 25 | "start:no-mock": "cross-env MOCK=none umi dev", | ||
| 26 | "start:no-ui": "cross-env UMI_UI=none umi dev", | ||
| 27 | "start:pre": "cross-env REACT_APP_ENV=pre umi dev", | ||
| 28 | "start:test": "cross-env REACT_APP_ENV=test MOCK=none umi dev", | ||
| 29 | "test": "umi test", | ||
| 30 | "test:all": "node ./tests/run-tests.js", | ||
| 31 | "test:component": "umi test ./src/components", | ||
| 32 | "tsc": "tsc", | ||
| 33 | "ui": "umi ui" | ||
| 34 | }, | ||
| 35 | "lint-staged": { | ||
| 36 | "**/*.less": "stylelint --syntax less", | ||
| 37 | "**/*.{js,jsx,ts,tsx}": "npm run lint-staged:js", | ||
| 38 | "**/*.{js,jsx,tsx,ts,less,md,json}": [ | ||
| 39 | "prettier --write" | ||
| 40 | ] | ||
| 41 | }, | ||
| 42 | "browserslist": [ | ||
| 43 | "> 1%", | ||
| 44 | "last 2 versions", | ||
| 45 | "not ie <= 10" | ||
| 46 | ], | ||
| 47 | "dependencies": { | ||
| 48 | "@ant-design/icons": "^4.0.0-rc.0", | ||
| 49 | "@ant-design/pro-layout": "^5.0.3", | ||
| 50 | "@antv/data-set": "^0.10.2", | ||
| 51 | "@umijs/preset-react": "^1.2.2", | ||
| 52 | "antd": "4.23.1", | ||
| 53 | "bizcharts": "^3.5.7", | ||
| 54 | "blueimp-md5": "^2.16.0", | ||
| 55 | "classnames": "^2.2.6", | ||
| 56 | "crypto-js": "^4.1.1", | ||
| 57 | "lodash": "^4.17.21", | ||
| 58 | "moment": "^2.24.0", | ||
| 59 | "omit.js": "^1.0.2", | ||
| 60 | "path-to-regexp": "2.4.0", | ||
| 61 | "qs": "^6.11.0", | ||
| 62 | "react": "^16.8.6", | ||
| 63 | "react-copy-to-clipboard": "^5.0.2", | ||
| 64 | "react-dom": "^16.8.6", | ||
| 65 | "react-helmet": "^5.2.1", | ||
| 66 | "react-redux": "^7.2.0", | ||
| 67 | "redux": "^4.0.1", | ||
| 68 | "styled-components": "^5.3.5", | ||
| 69 | "umi": "^3.0.0", | ||
| 70 | "umi-request": "^1.2.19", | ||
| 71 | "use-merge-value": "^1.0.1" | ||
| 72 | }, | ||
| 73 | "devDependencies": { | ||
| 74 | "@ant-design/pro-cli": "^1.0.18", | ||
| 75 | "@types/classnames": "^2.2.7", | ||
| 76 | "@types/express": "^4.17.0", | ||
| 77 | "@types/history": "^4.7.2", | ||
| 78 | "@types/jest": "^25.1.0", | ||
| 79 | "@types/lodash": "^4.14.144", | ||
| 80 | "@types/qs": "^6.5.3", | ||
| 81 | "@types/react": "^16.9.17", | ||
| 82 | "@types/react-dom": "^16.8.4", | ||
| 83 | "@types/react-helmet": "^5.0.13", | ||
| 84 | "@umijs/fabric": "^2.0.2", | ||
| 85 | "chalk": "^3.0.0", | ||
| 86 | "check-prettier": "^1.0.3", | ||
| 87 | "cross-env": "^7.0.0", | ||
| 88 | "cross-port-killer": "^1.1.1", | ||
| 89 | "enzyme": "^3.11.0", | ||
| 90 | "express": "^4.17.1", | ||
| 91 | "gh-pages": "^2.0.1", | ||
| 92 | "husky": "^4.0.7", | ||
| 93 | "import-sort-cli": "^6.0.0", | ||
| 94 | "import-sort-parser-babylon": "^6.0.0", | ||
| 95 | "import-sort-parser-typescript": "^6.0.0", | ||
| 96 | "import-sort-style-module": "^6.0.0", | ||
| 97 | "jest-puppeteer": "^4.4.0", | ||
| 98 | "jsdom-global": "^3.0.2", | ||
| 99 | "lint-staged": "^10.0.0", | ||
| 100 | "mockjs": "^1.0.1-beta3", | ||
| 101 | "node-fetch": "^2.6.0", | ||
| 102 | "prettier": "^1.19.1", | ||
| 103 | "pro-download": "1.0.1", | ||
| 104 | "stylelint": "^13.0.0" | ||
| 105 | }, | ||
| 106 | "optionalDependencies": { | ||
| 107 | "puppeteer": "^2.0.0" | ||
| 108 | }, | ||
| 109 | "engines": { | ||
| 110 | "node": ">=10.0.0" | ||
| 111 | }, | ||
| 112 | "checkFiles": [ | ||
| 113 | "src/**/*.js*", | ||
| 114 | "src/**/*.ts*", | ||
| 115 | "src/**/*.less", | ||
| 116 | "config/**/*.js*", | ||
| 117 | "scripts/**/*.js" | ||
| 118 | ] | ||
| 119 | } |
public/favicon.ico
0 → 100644
No preview for this file type
src/assets/yh-logo.png
0 → 100644
6.95 KB
src/common/index.js
0 → 100644
| 1 | import { createFromIconfontCN } from '@ant-design/icons'; | ||
| 2 | |||
| 3 | /* 接口域名 */ | ||
| 4 | const domain = window.location.hostname.toLowerCase(); | ||
| 5 | export const urlConfig = { | ||
| 6 | 'middletest.lipinclub.com': { | ||
| 7 | URL_API: 'http://middletest.lipinclub.com/api/', | ||
| 8 | }, | ||
| 9 | 'middle.lipinclub.com': { | ||
| 10 | URL_API: 'http://middle.lipinclub.com/api/', | ||
| 11 | }, | ||
| 12 | }[domain] || { | ||
| 13 | URL_API: '/ql/api', | ||
| 14 | }; | ||
| 15 | |||
| 16 | // 七牛云图片域名 | ||
| 17 | export const IMG_URL = 'http://qn.qinwell.com/'; | ||
| 18 | |||
| 19 | /* 自定义icon的地址 */ | ||
| 20 | export const IconFontConfig = createFromIconfontCN({ | ||
| 21 | scriptUrl: '//at.alicdn.com/t/font_1948876_xye4vujgq2j.js', | ||
| 22 | }); |
src/components/Auth/AuthBlock.js
0 → 100644
| 1 | /** | ||
| 2 | * Auther: APIS | ||
| 3 | */ | ||
| 4 | import React, { useEffect, useState } from 'react'; | ||
| 5 | import { connect } from 'umi'; | ||
| 6 | const AuthBlock = props => { | ||
| 7 | const { auth, userAuths, children } = props; | ||
| 8 | |||
| 9 | if (userAuths.includes(auth) || !auth) { | ||
| 10 | return <>{children}</>; | ||
| 11 | } else { | ||
| 12 | return null; | ||
| 13 | } | ||
| 14 | }; | ||
| 15 | export default connect(({ user }) => { | ||
| 16 | return { | ||
| 17 | userAuths: user.userAuths, | ||
| 18 | }; | ||
| 19 | })(AuthBlock); |
src/components/Auth/AuthRouter.js
0 → 100644
| 1 | /** | ||
| 2 | * Auther: APIS | ||
| 3 | */ | ||
| 4 | import React, { useEffect, useState } from 'react'; | ||
| 5 | import { connect } from 'umi'; | ||
| 6 | import NoFoundPage from '@/pages/404'; | ||
| 7 | |||
| 8 | /** | ||
| 9 | * 路由权限控制 | ||
| 10 | * 路由权限控制需要在路由配置里面对应的路由设置'auths'字段即可,支持字符串和数组,不需要加权限的路由不设置即可。 | ||
| 11 | * 原则上一个页面允许存在多个权限code,但是不允许一个code对应多个页面 | ||
| 12 | * @param {*} props | ||
| 13 | */ | ||
| 14 | const AuthRouter = props=> { | ||
| 15 | const { userAuths, routeMaps, path, children } = props; | ||
| 16 | |||
| 17 | const currentAuths = routeMaps[path]; | ||
| 18 | |||
| 19 | let hasAuth = true; | ||
| 20 | if (currentAuths) { | ||
| 21 | if (Array.isArray(currentAuths)) { | ||
| 22 | hasAuth = currentAuths.some(item=> userAuths.includes(item)); | ||
| 23 | } else { | ||
| 24 | hasAuth = userAuths.includes(currentAuths); | ||
| 25 | } | ||
| 26 | } | ||
| 27 | |||
| 28 | return <>{hasAuth ? children : <NoFoundPage />}</>; | ||
| 29 | }; | ||
| 30 | export default connect(({user, settings})=> { | ||
| 31 | return { | ||
| 32 | userAuths: user.userAuths, | ||
| 33 | routeMaps: settings.routeMaps | ||
| 34 | } | ||
| 35 | })(AuthRouter); | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
src/components/CopyToClipboard.js
0 → 100644
| 1 | /** | ||
| 2 | * Auther: APIS | ||
| 3 | */ | ||
| 4 | import React, { useEffect, useState } from 'react'; | ||
| 5 | import { message} from 'antd'; | ||
| 6 | import { CopyToClipboard } from 'react-copy-to-clipboard'; | ||
| 7 | |||
| 8 | const style = { | ||
| 9 | cursor: 'pointer' | ||
| 10 | }; | ||
| 11 | |||
| 12 | const Template = props=> { | ||
| 13 | const { text, children } = props; | ||
| 14 | |||
| 15 | useEffect(()=> { | ||
| 16 | }, [text]); | ||
| 17 | |||
| 18 | const onCopy = (test, result)=> { | ||
| 19 | if (result) { | ||
| 20 | message.success('已复制到剪切板~'); | ||
| 21 | } else { | ||
| 22 | message.error('复制失败,请手动进行复制~'); | ||
| 23 | } | ||
| 24 | } | ||
| 25 | |||
| 26 | return ( | ||
| 27 | <CopyToClipboard text={text} onCopy={onCopy} style={style} title='点击可复制'> | ||
| 28 | {children} | ||
| 29 | </CopyToClipboard> | ||
| 30 | ); | ||
| 31 | }; | ||
| 32 | export default Template; | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
src/components/FileExport.js
0 → 100644
| 1 | /** | ||
| 2 | * Auther: APIS | ||
| 3 | */ | ||
| 4 | import React, { useEffect, useState } from 'react'; | ||
| 5 | |||
| 6 | const FileExport = props=> { | ||
| 7 | const { url, dispatch } = props; | ||
| 8 | |||
| 9 | useEffect(()=> { | ||
| 10 | const linkExport = document.getElementById('J_HandleExport'); | ||
| 11 | if (url && linkExport) { | ||
| 12 | linkExport.click(); | ||
| 13 | setTimeout(()=> { | ||
| 14 | dispatch({type: 'global/changeState', payload: { urlFileExport: '' }}); | ||
| 15 | }, 100); | ||
| 16 | } | ||
| 17 | }, [url]); | ||
| 18 | |||
| 19 | return <a href={url} download id="J_HandleExport"></a> | ||
| 20 | }; | ||
| 21 | export default FileExport; | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | /** | ||
| 2 | * 省市区formItem组件 | ||
| 3 | * @param {*省市区的标签的文本} label | ||
| 4 | * @param {*省市区的标签的字段名} name | ||
| 5 | * @param {*详细地址的标签的文本} alabel | ||
| 6 | * @param {*详细地址的字段名} aname | ||
| 7 | */ | ||
| 8 | import React, { useState, useEffect, forwardRef } from 'react'; | ||
| 9 | import { connect } from 'dva'; | ||
| 10 | import { Card, Button, Row, Col, Input, Popover, Form, Cascader, Select } from 'antd'; | ||
| 11 | import InputFormItem from '@/components/FormItems/InputFormItem'; | ||
| 12 | const { TextArea } = Input; | ||
| 13 | const { Option } = Select; | ||
| 14 | const CitySelects = forwardRef((props, ref) => { | ||
| 15 | const { value = {}, onChange, options = [], disabled } = props; | ||
| 16 | const { province, city, district } = value; | ||
| 17 | const [provinceData, setprovinceData] = useState([]); | ||
| 18 | const [cityData, setcityData] = useState([]); | ||
| 19 | const [districtData, setdistrictData] = useState([]); | ||
| 20 | useEffect(() => { | ||
| 21 | if (options.length > 0) { | ||
| 22 | if (province) { | ||
| 23 | const plists = provinceData.filter(_ => _.label === province); | ||
| 24 | setcityData(plists[0].children); | ||
| 25 | } | ||
| 26 | } | ||
| 27 | }, [province]); | ||
| 28 | useEffect(() => { | ||
| 29 | if (city && cityData.length > 0) { | ||
| 30 | const cityLists = cityData.filter(_ => _.label === city); | ||
| 31 | setdistrictData(cityLists[0].children); | ||
| 32 | } | ||
| 33 | }, [city]); | ||
| 34 | |||
| 35 | useEffect(() => { | ||
| 36 | if (cityData.length > 0) { | ||
| 37 | const cityLists = cityData.filter(_ => _.label === city); | ||
| 38 | |||
| 39 | setdistrictData(cityLists.length > 0 ? cityLists[0].children : []); | ||
| 40 | } | ||
| 41 | }, [cityData]); | ||
| 42 | |||
| 43 | useEffect(() => { | ||
| 44 | setprovinceData(options); | ||
| 45 | }, [options]); | ||
| 46 | |||
| 47 | const handleProvinceChange = province => { | ||
| 48 | const provinceLists = provinceData.filter(_ => _.label === province); | ||
| 49 | setcityData(provinceLists[0].children); | ||
| 50 | onChange({ | ||
| 51 | ...value, | ||
| 52 | province, | ||
| 53 | city: '', | ||
| 54 | }); | ||
| 55 | }; | ||
| 56 | const onSecondCityChange = city => { | ||
| 57 | const cityLists = cityData.filter(_ => _.label === city); | ||
| 58 | setdistrictData(cityLists[0].children); | ||
| 59 | onChange({ | ||
| 60 | ...value, | ||
| 61 | city, | ||
| 62 | district: '', | ||
| 63 | }); | ||
| 64 | }; | ||
| 65 | const onDistrictChange = district => { | ||
| 66 | onChange({ | ||
| 67 | ...value, | ||
| 68 | district, | ||
| 69 | }); | ||
| 70 | }; | ||
| 71 | return ( | ||
| 72 | <> | ||
| 73 | <Select | ||
| 74 | className="mr-10" | ||
| 75 | value={province} | ||
| 76 | style={{ width: 150 }} | ||
| 77 | onChange={handleProvinceChange} | ||
| 78 | placeholder="请选择省份" | ||
| 79 | disabled={disabled} | ||
| 80 | > | ||
| 81 | {provinceData.map(province => ( | ||
| 82 | <Option key={province.label}>{province.label}</Option> | ||
| 83 | ))} | ||
| 84 | </Select> | ||
| 85 | <Select | ||
| 86 | className="mr-10" | ||
| 87 | value={city} | ||
| 88 | style={{ width: 150 }} | ||
| 89 | onChange={onSecondCityChange} | ||
| 90 | placeholder="请选择城市" | ||
| 91 | disabled={disabled} | ||
| 92 | > | ||
| 93 | {cityData.map(city => ( | ||
| 94 | <Option key={city.label}>{city.label}</Option> | ||
| 95 | ))} | ||
| 96 | </Select> | ||
| 97 | <Select | ||
| 98 | value={district} | ||
| 99 | style={{ width: 150 }} | ||
| 100 | onChange={onDistrictChange} | ||
| 101 | placeholder="请选择区县" | ||
| 102 | disabled={disabled} | ||
| 103 | > | ||
| 104 | {districtData.map(district => ( | ||
| 105 | <Option key={district.label}>{district.label}</Option> | ||
| 106 | ))} | ||
| 107 | </Select> | ||
| 108 | </> | ||
| 109 | ); | ||
| 110 | }); | ||
| 111 | |||
| 112 | const FormItem = props => { | ||
| 113 | const { | ||
| 114 | name, | ||
| 115 | label, | ||
| 116 | alabel, | ||
| 117 | aname, | ||
| 118 | wrapperCol = { span: 10 }, | ||
| 119 | BaseProvinceList, | ||
| 120 | dispatch, | ||
| 121 | form, | ||
| 122 | disabled, | ||
| 123 | } = props; | ||
| 124 | const validator = (rule, value = {}) => { | ||
| 125 | const { province, city, district } = value; | ||
| 126 | if (!province && !city && !district) { | ||
| 127 | return Promise.reject('请选择省市区!'); | ||
| 128 | } else if (!province) { | ||
| 129 | return Promise.reject('请选择省份!'); | ||
| 130 | } else if (!city) { | ||
| 131 | return Promise.reject('请选择城市!'); | ||
| 132 | } else if (!district) { | ||
| 133 | return Promise.reject('请选择区县!'); | ||
| 134 | } else { | ||
| 135 | return Promise.resolve(); | ||
| 136 | } | ||
| 137 | }; | ||
| 138 | return ( | ||
| 139 | <> | ||
| 140 | <Form.Item | ||
| 141 | label={label} | ||
| 142 | name={name} | ||
| 143 | required | ||
| 144 | rules={[ | ||
| 145 | { | ||
| 146 | validator, | ||
| 147 | }, | ||
| 148 | ]} | ||
| 149 | > | ||
| 150 | <CitySelects disabled={disabled} options={BaseProvinceList} /> | ||
| 151 | </Form.Item> | ||
| 152 | <InputFormItem disabled={disabled} label={alabel} name={aname} max={25} /> | ||
| 153 | </> | ||
| 154 | ); | ||
| 155 | }; | ||
| 156 | const mapStateToProps = ({ global }) => { | ||
| 157 | return { | ||
| 158 | BaseProvinceList: global.BaseProvinceList, | ||
| 159 | }; | ||
| 160 | }; | ||
| 161 | export default connect(mapStateToProps)(FormItem); |
| 1 | /** | ||
| 2 | * Author: wjw | ||
| 3 | * Date: | ||
| 4 | * Description: | ||
| 5 | */ | ||
| 6 | import React, { useState, useEffect, forwardRef } from 'react'; | ||
| 7 | import { connect } from 'dva'; | ||
| 8 | import { Card, Button, Row, Col, Input } from 'antd'; | ||
| 9 | import styles from './index.less'; | ||
| 10 | const { TextArea } = Input; | ||
| 11 | const InputCom = forwardRef((props, ref) => { | ||
| 12 | const { value, onChange, placeholder, max, type = 'input', style, disabled, defaultLen = 0 } = props; | ||
| 13 | const onIptChange = ({ target: { value } }) => { | ||
| 14 | if (onChange) { | ||
| 15 | onChange(value); | ||
| 16 | } | ||
| 17 | }; | ||
| 18 | const suffix = ( | ||
| 19 | <span style={{ lineHeight: '20px' }}> | ||
| 20 | {(value) ? (value.length + defaultLen) : ((!value && defaultLen) ? defaultLen : 0) }/{!defaultLen ? max : 500} | ||
| 21 | </span> | ||
| 22 | ); | ||
| 23 | const params = { | ||
| 24 | autoComplete: 'off', | ||
| 25 | maxLength: max, | ||
| 26 | placeholder, | ||
| 27 | value, | ||
| 28 | style, | ||
| 29 | onChange: onIptChange, | ||
| 30 | disabled, | ||
| 31 | }; | ||
| 32 | return ( | ||
| 33 | <div> | ||
| 34 | {type === 'input' && <Input {...params} suffix={suffix} />} | ||
| 35 | {type === 'textArea' && ( | ||
| 36 | <div style={{ position: 'relative' }}> | ||
| 37 | <TextArea {...params} rows={4} /> | ||
| 38 | <div className={styles.suffixttextarea}>{suffix}</div> | ||
| 39 | </div> | ||
| 40 | )} | ||
| 41 | </div> | ||
| 42 | ); | ||
| 43 | }); | ||
| 44 | |||
| 45 | export default InputCom; |
| 1 | /** | ||
| 2 | * 带有长度统计formItem组件 | ||
| 3 | * @param {*标签的文本} label | ||
| 4 | * @param {*字段名} name | ||
| 5 | * @param {*占位符} placeholder | ||
| 6 | * @param {*最小长度} min | ||
| 7 | * @param {*最大长度} max | ||
| 8 | * @param {*input框类型input、textArea} type | ||
| 9 | * @param {*规则} rules | ||
| 10 | * @param {*是否必填} required | ||
| 11 | * @param {*必填提示} message | ||
| 12 | */ | ||
| 13 | import React, { useState, useEffect, forwardRef } from 'react'; | ||
| 14 | import { connect } from 'dva'; | ||
| 15 | import { Card, Button, Row, Col, Input, Popover, Form, Cascader, Upload } from 'antd'; | ||
| 16 | import InputCom from './InputCom'; | ||
| 17 | const FormItem = props => { | ||
| 18 | const { label, name, placeholder, max, type, rules, required = true, min = 0, message, extra } = props; | ||
| 19 | const placeholderText = placeholder ? placeholder : `请输入${label}`; | ||
| 20 | const rlueMessage = message ? message : placeholderText; | ||
| 21 | return ( | ||
| 22 | <Form.Item | ||
| 23 | label={label} | ||
| 24 | name={name} | ||
| 25 | extra={extra} | ||
| 26 | rules={rules ? rules : [{ required: required, message: rlueMessage, min }]} | ||
| 27 | > | ||
| 28 | <InputCom {...props} placeholder={placeholderText} /> | ||
| 29 | </Form.Item> | ||
| 30 | ); | ||
| 31 | }; | ||
| 32 | export default FormItem; |
| 1 | /** | ||
| 2 | * Author: wjw | ||
| 3 | * Date: | ||
| 4 | * Description: | ||
| 5 | */ | ||
| 6 | import React, { useState, useEffect, forwardRef } from 'react'; | ||
| 7 | import { connect } from 'umi'; | ||
| 8 | import { Card, Button, Row, Col, Input, Popover, Form } from 'antd'; | ||
| 9 | import { CheckCircleOutlined } from '@ant-design/icons'; | ||
| 10 | const hasLength = value => { | ||
| 11 | return value.length >= 6 && value.length <= 16; | ||
| 12 | }; | ||
| 13 | const hasletter = value => { | ||
| 14 | for (var i in value) { | ||
| 15 | var asc = value.charCodeAt(i); | ||
| 16 | if ((asc >= 65 && asc <= 90) || (asc >= 97 && asc <= 122)) { | ||
| 17 | return true; | ||
| 18 | } | ||
| 19 | } | ||
| 20 | return false; | ||
| 21 | }; | ||
| 22 | const hasnum = value => { | ||
| 23 | var str = value; | ||
| 24 | var reg = new RegExp(/\d+/gi); | ||
| 25 | if (reg.test(str)) { | ||
| 26 | return true; | ||
| 27 | } else { | ||
| 28 | return false; | ||
| 29 | } | ||
| 30 | }; | ||
| 31 | const PasswordFormItem = forwardRef((props, ref) => { | ||
| 32 | const { | ||
| 33 | value = '', | ||
| 34 | onChange, | ||
| 35 | placeholder = '6 - 16位密码,包含字母和数字', | ||
| 36 | form, | ||
| 37 | visible, | ||
| 38 | prefix, | ||
| 39 | } = props; | ||
| 40 | |||
| 41 | const onIptChange = ({ target: { value } }) => { | ||
| 42 | onChange(value); | ||
| 43 | }; | ||
| 44 | const [isObj, setIsObj] = useState({ | ||
| 45 | count: false, | ||
| 46 | letter: false, | ||
| 47 | num: false, | ||
| 48 | }); | ||
| 49 | |||
| 50 | useEffect(() => { | ||
| 51 | const nobj = { | ||
| 52 | count: hasLength(value), | ||
| 53 | letter: hasletter(value), | ||
| 54 | num: hasnum(value), | ||
| 55 | }; | ||
| 56 | setIsObj(nobj); | ||
| 57 | }, [value]); | ||
| 58 | const isTure = bool => { | ||
| 59 | return ( | ||
| 60 | <div className="mr-5"> | ||
| 61 | {bool ? ( | ||
| 62 | <CheckCircleOutlined style={{ color: '#52c41a' }} /> | ||
| 63 | ) : ( | ||
| 64 | <div | ||
| 65 | style={{ | ||
| 66 | width: '14px', | ||
| 67 | height: '14px', | ||
| 68 | border: '1px solid #ccc', | ||
| 69 | borderRadius: '100%', | ||
| 70 | }} | ||
| 71 | ></div> | ||
| 72 | )} | ||
| 73 | </div> | ||
| 74 | ); | ||
| 75 | }; | ||
| 76 | const styles = { | ||
| 77 | display: 'flex', | ||
| 78 | flexDirection: 'row', | ||
| 79 | justifyContent: 'flex-start', | ||
| 80 | alignItems: 'center', | ||
| 81 | }; | ||
| 82 | const Content = props => { | ||
| 83 | return ( | ||
| 84 | <div> | ||
| 85 | <div style={styles}> | ||
| 86 | {isTure(isObj.count)}输入6 - 16 位字符,特殊字符包括下划线,@,#等等 | ||
| 87 | </div> | ||
| 88 | <div style={styles}>{isTure(isObj.letter)}包含字母</div> | ||
| 89 | <div style={styles}>{isTure(isObj.num)}包含数字</div> | ||
| 90 | </div> | ||
| 91 | ); | ||
| 92 | }; | ||
| 93 | return ( | ||
| 94 | <Popover placement="right" content={<Content />} visible={visible}> | ||
| 95 | <Input.Password | ||
| 96 | prefix={prefix} | ||
| 97 | autoComplete="new-password" | ||
| 98 | placeholder={placeholder} | ||
| 99 | value={value} | ||
| 100 | onChange={onIptChange} | ||
| 101 | visibilityToggle={false} | ||
| 102 | /> | ||
| 103 | </Popover> | ||
| 104 | ); | ||
| 105 | }); | ||
| 106 | const FormItem = props => { | ||
| 107 | const { prefix, label } = props; | ||
| 108 | const [visible, setvisible] = useState(false); | ||
| 109 | const checkpassword = (rule, value) => { | ||
| 110 | if (!value || !(hasLength(value) && hasletter(value) && hasnum(value))) { | ||
| 111 | setvisible(true); | ||
| 112 | return Promise.reject(''); | ||
| 113 | } else { | ||
| 114 | setvisible(false); | ||
| 115 | return Promise.resolve(); | ||
| 116 | } | ||
| 117 | }; | ||
| 118 | return ( | ||
| 119 | <Form.Item required label={label} name="password" rules={[{ validator: checkpassword }]}> | ||
| 120 | <PasswordFormItem prefix={prefix} visible={visible} /> | ||
| 121 | </Form.Item> | ||
| 122 | ); | ||
| 123 | }; | ||
| 124 | export default FormItem; |
| 1 | /** | ||
| 2 | * Author: wjw | ||
| 3 | * Date: | ||
| 4 | * Description: | ||
| 5 | */ | ||
| 6 | import React, { useState, useEffect, forwardRef } from 'react'; | ||
| 7 | import { connect } from 'umi'; | ||
| 8 | import { Card, Button, Icon, Row, Col, Input, Popover, Form, Select } from 'antd'; | ||
| 9 | import { isPhone } from '@/utils/utils'; | ||
| 10 | const { Option } = Select; | ||
| 11 | const FormItem = props => { | ||
| 12 | const { label = null, name, isPrefixSelector = false, cd, hasFeedback = true } = props; | ||
| 13 | |||
| 14 | const prefixSelector = ( | ||
| 15 | <Form.Item name="prefix" noStyle> | ||
| 16 | <Select style={{ width: 70 }}> | ||
| 17 | <Option value="86">+86</Option> | ||
| 18 | </Select> | ||
| 19 | </Form.Item> | ||
| 20 | ); | ||
| 21 | const validateTocheckMobile = (rule, value) => { | ||
| 22 | if (value) { | ||
| 23 | if (!isPhone(value)) { | ||
| 24 | return Promise.reject('请输入正确手机格式'); | ||
| 25 | return; | ||
| 26 | } else { | ||
| 27 | if (cd) { | ||
| 28 | cd(); | ||
| 29 | } else { | ||
| 30 | return Promise.resolve(); | ||
| 31 | } | ||
| 32 | } | ||
| 33 | } else { | ||
| 34 | return Promise.resolve(); | ||
| 35 | } | ||
| 36 | }; | ||
| 37 | |||
| 38 | return ( | ||
| 39 | <Form.Item | ||
| 40 | label={label} | ||
| 41 | hasFeedback={hasFeedback} | ||
| 42 | name={name} | ||
| 43 | rules={[ | ||
| 44 | { | ||
| 45 | required: true, | ||
| 46 | message: '输入手机号', | ||
| 47 | }, | ||
| 48 | { | ||
| 49 | validator: validateTocheckMobile, | ||
| 50 | }, | ||
| 51 | ]} | ||
| 52 | validateTrigger="onBlur" | ||
| 53 | > | ||
| 54 | <Input | ||
| 55 | addonBefore={isPrefixSelector ? prefixSelector : null} | ||
| 56 | style={{ width: '100%' }} | ||
| 57 | placeholder="11位手机号" | ||
| 58 | /> | ||
| 59 | </Form.Item> | ||
| 60 | ); | ||
| 61 | }; | ||
| 62 | export default FormItem; |
| 1 | /** | ||
| 2 | * Author: wjw | ||
| 3 | * Date: | ||
| 4 | * Description: | ||
| 5 | */ | ||
| 6 | import React, { useState, useEffect, forwardRef } from 'react'; | ||
| 7 | import { connect } from 'dva'; | ||
| 8 | import { Card, Button, Form, Radio } from 'antd'; | ||
| 9 | |||
| 10 | const RadioFormItem = props => { | ||
| 11 | const { name, label, list = [], disabled } = props; | ||
| 12 | |||
| 13 | return ( | ||
| 14 | <div> | ||
| 15 | <Form.Item label={label} name={name} rules={[{ required: true, message: '请选择' }]}> | ||
| 16 | <Radio.Group disabled={disabled}> | ||
| 17 | {list.map((item, index) => { | ||
| 18 | return ( | ||
| 19 | <Radio key={index} value={item.value}> | ||
| 20 | {item.name} | ||
| 21 | </Radio> | ||
| 22 | ); | ||
| 23 | })} | ||
| 24 | </Radio.Group> | ||
| 25 | </Form.Item> | ||
| 26 | </div> | ||
| 27 | ); | ||
| 28 | }; | ||
| 29 | export default RadioFormItem; |
| 1 | import React, { useState, useEffect, forwardRef } from 'react'; | ||
| 2 | import { connect } from 'dva'; | ||
| 3 | import { Card, Button, Upload, message } from 'antd'; | ||
| 4 | import { urlConfig } from '@/common'; | ||
| 5 | import styles from '../index.less'; | ||
| 6 | import { getFileName, getFileType } from '@/utils/utils'; | ||
| 7 | import { PlusOutlined, DownloadOutlined } from '@ant-design/icons'; | ||
| 8 | // 上传图片的配置 | ||
| 9 | const token = window.localStorage.getItem('qintaoyouxuan_token') || ''; | ||
| 10 | |||
| 11 | const settings = { | ||
| 12 | name: 'file', | ||
| 13 | withCredentials: true, | ||
| 14 | headers: { | ||
| 15 | token, | ||
| 16 | }, | ||
| 17 | }; | ||
| 18 | const IMGUploadButton = ({ text }) => { | ||
| 19 | return ( | ||
| 20 | <div> | ||
| 21 | <PlusOutlined /> | ||
| 22 | <div className="ant-upload-text">{text}</div> | ||
| 23 | </div> | ||
| 24 | ); | ||
| 25 | }; | ||
| 26 | |||
| 27 | const UploadButton = ({ text }) => { | ||
| 28 | return ( | ||
| 29 | <Button className={styles.textbtn}> | ||
| 30 | <DownloadOutlined /> | ||
| 31 | {text} | ||
| 32 | </Button> | ||
| 33 | ); | ||
| 34 | }; | ||
| 35 | |||
| 36 | const UploadItem = forwardRef((props, ref) => { | ||
| 37 | const { | ||
| 38 | value, | ||
| 39 | onChange, | ||
| 40 | listType = 'text', | ||
| 41 | length = 1, | ||
| 42 | defaultFileList = [], | ||
| 43 | accept = 'image/jpg,image/jpeg,image/png', | ||
| 44 | maxSize = 2, | ||
| 45 | filemaxSize = 25, | ||
| 46 | dispatch, | ||
| 47 | style, | ||
| 48 | className, | ||
| 49 | text = '上传文件', | ||
| 50 | disabled, | ||
| 51 | children, | ||
| 52 | isError = false, | ||
| 53 | action = 'imgs/uploadImg', | ||
| 54 | } = props; | ||
| 55 | |||
| 56 | const serverURL = `${urlConfig.URL_API}${action}`; | ||
| 57 | const [fileList, setfileList] = useState(defaultFileList); | ||
| 58 | const [len, setlen] = useState(-1); | ||
| 59 | const [isupload, setIsupload] = useState(false); | ||
| 60 | |||
| 61 | useEffect(() => { | ||
| 62 | if (Array.isArray(value) && !isupload) { | ||
| 63 | let files = value.map((item, index) => { | ||
| 64 | let name = getFileName(item); | ||
| 65 | return { | ||
| 66 | uid: index, | ||
| 67 | name, | ||
| 68 | url: item, | ||
| 69 | thumbUrl: item, | ||
| 70 | status: 'done', | ||
| 71 | response: { status: 1, data: item }, | ||
| 72 | percent: 100, | ||
| 73 | size: 0, | ||
| 74 | }; | ||
| 75 | }); | ||
| 76 | setfileList(files); | ||
| 77 | } | ||
| 78 | }, [value]); | ||
| 79 | |||
| 80 | useEffect(() => { | ||
| 81 | if (fileList.length >= len && len !== -1) { | ||
| 82 | let values = fileList.filter(item => item.url).map(i => i.url); | ||
| 83 | if (isError) { | ||
| 84 | values = fileList.map(i => { | ||
| 85 | const { status, response, url } = i; | ||
| 86 | return { | ||
| 87 | status, | ||
| 88 | url, | ||
| 89 | response, | ||
| 90 | }; | ||
| 91 | }); | ||
| 92 | } | ||
| 93 | |||
| 94 | if (onChange) { | ||
| 95 | onChange(values); | ||
| 96 | } | ||
| 97 | } | ||
| 98 | }, [fileList]); | ||
| 99 | const getisLtM = file => { | ||
| 100 | const { name, size } = file; | ||
| 101 | const type = getFileType(name); | ||
| 102 | const is = !!(type === '.pdf' || type === '.rar'); | ||
| 103 | const MAX_SIZE = is ? filemaxSize : maxSize; | ||
| 104 | return { | ||
| 105 | MAX_SIZE, | ||
| 106 | isLtM: size / 1024 / 1024 < MAX_SIZE, | ||
| 107 | }; | ||
| 108 | }; | ||
| 109 | const getStatus = item => { | ||
| 110 | const { name, size, status, response, type } = item; | ||
| 111 | const MAX_SIZE = getisLtM(item).MAX_SIZE; | ||
| 112 | const isLtM = getisLtM(item).isLtM; | ||
| 113 | |||
| 114 | if (!isLtM) { | ||
| 115 | return { | ||
| 116 | ...item, | ||
| 117 | status: status === 'removed' ? 'removed' : 'error', | ||
| 118 | response: `上传的文件大小不能超过${MAX_SIZE}M`, | ||
| 119 | url: item.url, | ||
| 120 | }; | ||
| 121 | } | ||
| 122 | if (status === 'done') { | ||
| 123 | if (response && response.status !== 1) { | ||
| 124 | return { | ||
| 125 | ...item, | ||
| 126 | status: 'error', | ||
| 127 | response: response.msg ? response.msg : response.data, | ||
| 128 | url: item.url, | ||
| 129 | }; | ||
| 130 | } | ||
| 131 | } | ||
| 132 | return { | ||
| 133 | ...item, | ||
| 134 | status: status, | ||
| 135 | response: response, | ||
| 136 | url: | ||
| 137 | item.status === 'done' | ||
| 138 | ? item.response.data | ||
| 139 | : item.status === 'uploading' | ||
| 140 | ? 'uploading' | ||
| 141 | : item.url, | ||
| 142 | }; | ||
| 143 | }; | ||
| 144 | |||
| 145 | const onFilechange = info => { | ||
| 146 | setIsupload(true); | ||
| 147 | let fileone = info.file; | ||
| 148 | let fileList = info.fileList; | ||
| 149 | fileone = getStatus(fileone); | ||
| 150 | if (fileone.status === 'done' && fileone.response) { | ||
| 151 | message.success('上传成功'); | ||
| 152 | // onChange(); | ||
| 153 | } else if (fileone.status === 'error' && fileone.response) { | ||
| 154 | message.error(`${fileone.response}`); | ||
| 155 | //不符合的文件删除 | ||
| 156 | fileList = fileList.filter(_ => _.uid !== fileone.uid); | ||
| 157 | } | ||
| 158 | //长度限制 | ||
| 159 | fileList = fileList | ||
| 160 | .filter((i, idx) => idx < length) | ||
| 161 | .map(item => { | ||
| 162 | return getStatus(item); | ||
| 163 | }); | ||
| 164 | |||
| 165 | setfileList(fileList); | ||
| 166 | setlen(fileList.length); | ||
| 167 | }; | ||
| 168 | |||
| 169 | const onRemove = file => { | ||
| 170 | setlen(fileList.length - 1); | ||
| 171 | }; | ||
| 172 | const onPreview = file => { | ||
| 173 | const img = file.url; | ||
| 174 | if (img) { | ||
| 175 | handleAdd('PREVIEWIMG', { imgUrl: img }); | ||
| 176 | } | ||
| 177 | }; | ||
| 178 | const handleAdd = (modalType, r) => { | ||
| 179 | const payload = { | ||
| 180 | preImgDataModal: { | ||
| 181 | modalType, | ||
| 182 | modalShow: true, | ||
| 183 | modalData: r ? r : {}, | ||
| 184 | }, | ||
| 185 | }; | ||
| 186 | dispatch({ type: 'global/changeState', payload }); | ||
| 187 | }; | ||
| 188 | |||
| 189 | //上传前判断文件大小是否符合 | ||
| 190 | const imgupload = (file, fileList) => { | ||
| 191 | const isLtM = getisLtM(file).isLtM; | ||
| 192 | if (!isLtM) { | ||
| 193 | return false; | ||
| 194 | } | ||
| 195 | return isLtM; | ||
| 196 | }; | ||
| 197 | return ( | ||
| 198 | <Upload | ||
| 199 | action={serverURL} | ||
| 200 | // accept={accept} | ||
| 201 | multiple={!!(length > 1)} | ||
| 202 | onChange={onFilechange} | ||
| 203 | fileList={fileList} | ||
| 204 | {...settings} | ||
| 205 | beforeUpload={imgupload} | ||
| 206 | listType={listType} | ||
| 207 | onRemove={onRemove} | ||
| 208 | onPreview={listType === 'picture-card' ? onPreview : null} | ||
| 209 | style={style} | ||
| 210 | className={className} | ||
| 211 | disabled={disabled} | ||
| 212 | > | ||
| 213 | {!disabled && fileList.length < length && ( | ||
| 214 | <div> | ||
| 215 | {listType === 'picture-card' ? ( | ||
| 216 | <IMGUploadButton text={text} /> | ||
| 217 | ) : children ? ( | ||
| 218 | children | ||
| 219 | ) : ( | ||
| 220 | <UploadButton text={text} /> | ||
| 221 | )} | ||
| 222 | </div> | ||
| 223 | )} | ||
| 224 | </Upload> | ||
| 225 | ); | ||
| 226 | }); | ||
| 227 | const mapStateToProps = ({ global }) => { | ||
| 228 | return { | ||
| 229 | preImgDataModal: global.preImgDataModal, | ||
| 230 | }; | ||
| 231 | }; | ||
| 232 | export default connect(mapStateToProps)(UploadItem); |
| 1 | /** | ||
| 2 | * 上传图片组件 | ||
| 3 | * @param {*标签的文本} label | ||
| 4 | * @param {*标签的字段名} name | ||
| 5 | * @param {*额外的提示信息} extra | ||
| 6 | * @param {*插槽} children | ||
| 7 | * @param {*value是否含有上传文件的当前状态{status:'done',url:'',response:''}} isError | ||
| 8 | */ | ||
| 9 | import React, { useState, useEffect, forwardRef } from 'react'; | ||
| 10 | import { connect } from 'dva'; | ||
| 11 | import { Card, Button, Icon, Row, Col, Input, Popover, Form, Cascader, Upload } from 'antd'; | ||
| 12 | import UploadItem from './UploadItem'; | ||
| 13 | const FormItem = props => { | ||
| 14 | const { name, label, extra, children, isError } = props; | ||
| 15 | const validator = (rule, value) => { | ||
| 16 | if (value && value.some(i => i.status === 'error')) { | ||
| 17 | return Promise.reject('您有文件不符合要求,请删除!'); | ||
| 18 | } else if (value && value.some(i => i.status === 'uploading' || i === 'uploading')) { | ||
| 19 | return Promise.reject('您有文件正在上传!'); | ||
| 20 | } else { | ||
| 21 | return Promise.resolve(); | ||
| 22 | } | ||
| 23 | }; | ||
| 24 | |||
| 25 | let rules = [ | ||
| 26 | { required: true, message: '请上传文件' }, | ||
| 27 | { | ||
| 28 | validator: validator, | ||
| 29 | }, | ||
| 30 | ]; | ||
| 31 | |||
| 32 | return ( | ||
| 33 | <Form.Item label={label} extra={extra} name={name} rules={rules}> | ||
| 34 | <UploadItem {...props}>{children}</UploadItem> | ||
| 35 | </Form.Item> | ||
| 36 | ); | ||
| 37 | }; | ||
| 38 | export default FormItem; |
| 1 | .upfilebtn { | ||
| 2 | width: 70px; | ||
| 3 | height: 70px; | ||
| 4 | background: rgba(251, 251, 251, 1); | ||
| 5 | border: 1px dashed rgba(218, 218, 218, 1); | ||
| 6 | display: flex; | ||
| 7 | flex-direction: column; | ||
| 8 | justify-content: center; | ||
| 9 | align-items: center; | ||
| 10 | p { | ||
| 11 | font-size: 14px; | ||
| 12 | font-family: Source Han Sans CN; | ||
| 13 | font-weight: 400; | ||
| 14 | color: rgba(153, 153, 153, 1); | ||
| 15 | margin-top: 11px; | ||
| 16 | } | ||
| 17 | } | ||
| 18 | .textbtn:hover, | ||
| 19 | .textbtn:focus { | ||
| 20 | border: 1px solid #1890ff !important; | ||
| 21 | color: #1890ff !important; | ||
| 22 | } |
| 1 | import React from 'react'; | ||
| 2 | import { connect } from 'umi'; | ||
| 3 | import { LogoutOutlined, InfoCircleOutlined } from '@ant-design/icons'; | ||
| 4 | import { Avatar, Menu, Spin } from 'antd'; | ||
| 5 | import { IconFontConfig } from '@/common'; | ||
| 6 | import HeaderDropdown from '../HeaderDropdown'; | ||
| 7 | import styles from './index.less'; | ||
| 8 | import ModalUpdatePassword from '../ModalUpdatePassword'; | ||
| 9 | |||
| 10 | class AvatarDropdown extends React.Component { | ||
| 11 | onMenuClick = event => { | ||
| 12 | const { key } = event; | ||
| 13 | |||
| 14 | if (key === 'logout') { | ||
| 15 | const { dispatch } = this.props; | ||
| 16 | if (dispatch) { | ||
| 17 | dispatch({ | ||
| 18 | type: 'login/logout', | ||
| 19 | }); | ||
| 20 | } | ||
| 21 | return; | ||
| 22 | } else if (key === 'password') { | ||
| 23 | const { dispatch } = this.props; | ||
| 24 | dispatch({ | ||
| 25 | type: 'user/changeState', | ||
| 26 | payload: { | ||
| 27 | dataModal: { | ||
| 28 | modalType: 'PASSWORD_UPDATE_MODAL', | ||
| 29 | modalShow: true, | ||
| 30 | modalData: {}, | ||
| 31 | }, | ||
| 32 | }, | ||
| 33 | }); | ||
| 34 | } | ||
| 35 | }; | ||
| 36 | |||
| 37 | render() { | ||
| 38 | const { | ||
| 39 | currentUser = { | ||
| 40 | avatar: '', | ||
| 41 | name: '', | ||
| 42 | }, | ||
| 43 | menu, | ||
| 44 | } = this.props; | ||
| 45 | const menuHeaderDropdown = ( | ||
| 46 | <Menu className={styles.menu} selectedKeys={[]} onClick={this.onMenuClick}> | ||
| 47 | <Menu.Item key="password"> | ||
| 48 | <InfoCircleOutlined /> | ||
| 49 | 修改密码 | ||
| 50 | </Menu.Item> | ||
| 51 | <Menu.Item key="logout"> | ||
| 52 | <LogoutOutlined /> | ||
| 53 | 退出登录 | ||
| 54 | </Menu.Item> | ||
| 55 | </Menu> | ||
| 56 | ); | ||
| 57 | return currentUser && currentUser.name ? ( | ||
| 58 | <> | ||
| 59 | <HeaderDropdown overlay={menuHeaderDropdown}> | ||
| 60 | <span className={`${styles.action} ${styles.account}`}> | ||
| 61 | <IconFontConfig type="icon-header" style={{ fontSize: '28px' }} className="mr-10" /> | ||
| 62 | <span className={styles.name}>{currentUser.name}</span> | ||
| 63 | </span> | ||
| 64 | </HeaderDropdown> | ||
| 65 | <ModalUpdatePassword /> | ||
| 66 | </> | ||
| 67 | ) : ( | ||
| 68 | <Spin | ||
| 69 | size="small" | ||
| 70 | style={{ | ||
| 71 | marginLeft: 8, | ||
| 72 | marginRight: 8, | ||
| 73 | lineHeight: '64px', | ||
| 74 | }} | ||
| 75 | /> | ||
| 76 | ); | ||
| 77 | } | ||
| 78 | } | ||
| 79 | |||
| 80 | export default connect(({ user }) => ({ | ||
| 81 | currentUser: user.currentUser, | ||
| 82 | }))(AvatarDropdown); |
src/components/GlobalHeader/RightContent.jsx
0 → 100644
| 1 | import { Tooltip, Tag } from 'antd'; | ||
| 2 | import { QuestionCircleOutlined } from '@ant-design/icons'; | ||
| 3 | import React from 'react'; | ||
| 4 | import { connect } from 'umi'; | ||
| 5 | import Avatar from './AvatarDropdown'; | ||
| 6 | import styles from './index.less'; | ||
| 7 | const ENVTagColor = { | ||
| 8 | dev: 'orange', | ||
| 9 | test: 'green', | ||
| 10 | pre: '#87d068', | ||
| 11 | }; | ||
| 12 | |||
| 13 | const GlobalHeaderRight = props => { | ||
| 14 | const { theme, layout } = props; | ||
| 15 | let className = styles.right; | ||
| 16 | |||
| 17 | if (theme === 'dark' && layout === 'topmenu') { | ||
| 18 | className = `${styles.right} ${styles.dark}`; | ||
| 19 | } | ||
| 20 | |||
| 21 | return ( | ||
| 22 | <div className={className}> | ||
| 23 | |||
| 24 | {/* <Tooltip title="使用文档"> | ||
| 25 | <a | ||
| 26 | target="_blank" | ||
| 27 | href="https://pro.ant.design/docs/getting-started" | ||
| 28 | rel="noopener noreferrer" | ||
| 29 | className={styles.action} | ||
| 30 | > | ||
| 31 | <QuestionCircleOutlined /> | ||
| 32 | </a> | ||
| 33 | </Tooltip> */} | ||
| 34 | <Avatar /> | ||
| 35 | {REACT_APP_ENV && ( | ||
| 36 | <span> | ||
| 37 | <Tag color={ENVTagColor[REACT_APP_ENV]}>{REACT_APP_ENV}</Tag> | ||
| 38 | </span> | ||
| 39 | )} | ||
| 40 | </div> | ||
| 41 | ); | ||
| 42 | }; | ||
| 43 | |||
| 44 | export default connect(({ settings }) => ({ | ||
| 45 | theme: settings.navTheme, | ||
| 46 | layout: settings.layout, | ||
| 47 | }))(GlobalHeaderRight); |
src/components/GlobalHeader/index.less
0 → 100644
| 1 | @import '~antd/es/style/themes/default.less'; | ||
| 2 | |||
| 3 | @pro-header-hover-bg: rgba(0, 0, 0, 0.025); | ||
| 4 | |||
| 5 | .menu { | ||
| 6 | :global(.anticon) { | ||
| 7 | margin-right: 8px; | ||
| 8 | } | ||
| 9 | :global(.ant-dropdown-menu-item) { | ||
| 10 | min-width: 160px; | ||
| 11 | } | ||
| 12 | } | ||
| 13 | |||
| 14 | .right { | ||
| 15 | display: flex; | ||
| 16 | float: right; | ||
| 17 | height: @layout-header-height; | ||
| 18 | margin-left: auto; | ||
| 19 | overflow: hidden; | ||
| 20 | .action { | ||
| 21 | display: flex; | ||
| 22 | align-items: center; | ||
| 23 | height: 100%; | ||
| 24 | padding: 0 12px; | ||
| 25 | cursor: pointer; | ||
| 26 | transition: all 0.3s; | ||
| 27 | > span { | ||
| 28 | color: @text-color; | ||
| 29 | vertical-align: middle; | ||
| 30 | } | ||
| 31 | // &:hover { | ||
| 32 | // background: @pro-header-hover-bg; | ||
| 33 | // } | ||
| 34 | // &:global(.opened) { | ||
| 35 | // background: @pro-header-hover-bg; | ||
| 36 | // } | ||
| 37 | } | ||
| 38 | .search { | ||
| 39 | padding: 0 12px; | ||
| 40 | &:hover { | ||
| 41 | background: transparent; | ||
| 42 | } | ||
| 43 | } | ||
| 44 | .account { | ||
| 45 | .avatar { | ||
| 46 | margin: ~'calc((@{layout-header-height} - 24px) / 2)' 0; | ||
| 47 | margin-right: 8px; | ||
| 48 | color: @primary-color; | ||
| 49 | vertical-align: top; | ||
| 50 | background: rgba(255, 255, 255, 0.85); | ||
| 51 | } | ||
| 52 | } | ||
| 53 | } | ||
| 54 | |||
| 55 | .dark { | ||
| 56 | .action { | ||
| 57 | color: rgba(255, 255, 255, 0.85); | ||
| 58 | > span { | ||
| 59 | color: rgba(255, 255, 255, 0.85); | ||
| 60 | } | ||
| 61 | // &:hover, | ||
| 62 | // &:global(.opened) { | ||
| 63 | // background: @primary-color; | ||
| 64 | // } | ||
| 65 | } | ||
| 66 | } | ||
| 67 | |||
| 68 | :global(.ant-pro-global-header) { | ||
| 69 | img { | ||
| 70 | height: 50px; | ||
| 71 | } | ||
| 72 | .dark { | ||
| 73 | .action { | ||
| 74 | color: @text-color; | ||
| 75 | > span { | ||
| 76 | color: @text-color; | ||
| 77 | } | ||
| 78 | &:hover { | ||
| 79 | color: rgba(255, 255, 255, 0.85); | ||
| 80 | > span { | ||
| 81 | color: rgba(255, 255, 255, 0.85); | ||
| 82 | } | ||
| 83 | } | ||
| 84 | } | ||
| 85 | } | ||
| 86 | } | ||
| 87 | |||
| 88 | @media only screen and (max-width: @screen-md) { | ||
| 89 | :global(.ant-divider-vertical) { | ||
| 90 | vertical-align: unset; | ||
| 91 | } | ||
| 92 | .name { | ||
| 93 | display: none; | ||
| 94 | } | ||
| 95 | .right { | ||
| 96 | position: absolute; | ||
| 97 | top: 0; | ||
| 98 | right: 12px; | ||
| 99 | .account { | ||
| 100 | .avatar { | ||
| 101 | margin-right: 0; | ||
| 102 | } | ||
| 103 | } | ||
| 104 | } | ||
| 105 | } |
src/components/HeaderDropdown/index.jsx
0 → 100644
| 1 | import { Dropdown } from 'antd'; | ||
| 2 | import React from 'react'; | ||
| 3 | import classNames from 'classnames'; | ||
| 4 | import styles from './index.less'; | ||
| 5 | |||
| 6 | const HeaderDropdown = ({ overlayClassName: cls, ...restProps }) => ( | ||
| 7 | <Dropdown overlayClassName={classNames(styles.container, cls)} {...restProps} /> | ||
| 8 | ); | ||
| 9 | |||
| 10 | export default HeaderDropdown; |
src/components/HeaderDropdown/index.less
0 → 100644
| 1 | @import '~antd/es/style/themes/default.less'; | ||
| 2 | |||
| 3 | .container > * { | ||
| 4 | background-color: @popover-bg; | ||
| 5 | border-radius: 4px; | ||
| 6 | box-shadow: @shadow-1-down; | ||
| 7 | } | ||
| 8 | |||
| 9 | @media screen and (max-width: @screen-xs) { | ||
| 10 | .container { | ||
| 11 | width: 100% !important; | ||
| 12 | } | ||
| 13 | .container > * { | ||
| 14 | border-radius: 0 !important; | ||
| 15 | } | ||
| 16 | } |
src/components/Loading/index.js
0 → 100644
| 1 | /** | ||
| 2 | * Auther: APIS | ||
| 3 | */ | ||
| 4 | import React, { useEffect, useState } from 'react'; | ||
| 5 | import { Spin } from 'antd'; | ||
| 6 | import styles from './index.less'; | ||
| 7 | export const customLoadingParams = { | ||
| 8 | indicator: ( | ||
| 9 | <img | ||
| 10 | className="loading-img" | ||
| 11 | src="https://youxuan-prod.oss-cn-zhangjiakou.aliyuncs.com/qintaoyouxuan/loading.gif" | ||
| 12 | /> | ||
| 13 | ), | ||
| 14 | delay: 50, | ||
| 15 | }; | ||
| 16 | const Loading = props => { | ||
| 17 | const { loading } = props; | ||
| 18 | |||
| 19 | return <Spin spinning={loading} {...customLoadingParams} className="wrap-loading"></Spin>; | ||
| 20 | }; | ||
| 21 | export default Loading; |
src/components/Loading/index.less
0 → 100644
| 1 | :global { | ||
| 2 | .ant-pro-basicLayout .ant-pro-basicLayout-is-children.ant-pro-basicLayout-fix-siderbar{ | ||
| 3 | .wrap-loading{ | ||
| 4 | left: -100px !important; | ||
| 5 | } | ||
| 6 | } | ||
| 7 | .wrap-loading{ | ||
| 8 | position: fixed !important; | ||
| 9 | top: 0 !important; | ||
| 10 | left: 0px !important; | ||
| 11 | right: 0 !important; | ||
| 12 | bottom: 0 !important; | ||
| 13 | z-index: 999 !important; | ||
| 14 | &:before{ | ||
| 15 | content: ''; | ||
| 16 | display: block; | ||
| 17 | width: 100%; | ||
| 18 | height: 100%; | ||
| 19 | background: #FFF; | ||
| 20 | opacity: .6; | ||
| 21 | } | ||
| 22 | .ant-spin-dot.ant-spin-dot-spin{ | ||
| 23 | position: absolute; | ||
| 24 | top: 40%; | ||
| 25 | left: 50%; | ||
| 26 | } | ||
| 27 | .loading-img{ | ||
| 28 | position: absolute; | ||
| 29 | top: 40%; | ||
| 30 | left: 50%; | ||
| 31 | width: 30px; | ||
| 32 | height: auto; | ||
| 33 | opacity: .6; | ||
| 34 | } | ||
| 35 | } | ||
| 36 | } | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
src/components/ModalUpdatePassword/index.jsx
0 → 100644
| 1 | /** | ||
| 2 | * Author: Charles | ||
| 3 | * Date: 2022.9.13 | ||
| 4 | * Description: [修改密码] | ||
| 5 | */ | ||
| 6 | import React, { useEffect } from 'react'; | ||
| 7 | import { connect } from 'umi'; | ||
| 8 | import { Modal, Form, Input, Button } from 'antd'; | ||
| 9 | |||
| 10 | const formItemLayout = { labelCol: { span: 4 }, wrapperCol: { span: 20 } }; | ||
| 11 | |||
| 12 | const ModalUpdatePassword = props => { | ||
| 13 | const [form] = Form.useForm(); | ||
| 14 | const { | ||
| 15 | dispatch, | ||
| 16 | dataModal: { modalType, modalShow }, | ||
| 17 | } = props; | ||
| 18 | |||
| 19 | useEffect(() => { | ||
| 20 | if (modalType === 'PASSWORD_UPDATE_MODAL' && modalShow) { | ||
| 21 | form.resetFields(); | ||
| 22 | } | ||
| 23 | }, [modalType, modalShow]); | ||
| 24 | |||
| 25 | /* 点击保存 */ | ||
| 26 | const handleSave = () => { | ||
| 27 | form.validateFields().then(values => { | ||
| 28 | dispatch({ type: 'user/updatePassword', payload: values }); | ||
| 29 | }); | ||
| 30 | }; | ||
| 31 | |||
| 32 | return ( | ||
| 33 | <Modal | ||
| 34 | title="修改密码" | ||
| 35 | placement="right" | ||
| 36 | width={700} | ||
| 37 | maskClosable={false} | ||
| 38 | onCancel={() => { | ||
| 39 | dispatch({ type: 'user/cancelModal' }); | ||
| 40 | }} | ||
| 41 | visible={modalType === 'PASSWORD_UPDATE_MODAL' && modalShow} | ||
| 42 | footer={ | ||
| 43 | <div | ||
| 44 | style={{ | ||
| 45 | textAlign: 'right', | ||
| 46 | }} | ||
| 47 | > | ||
| 48 | <Button | ||
| 49 | onClick={() => { | ||
| 50 | dispatch({ type: 'user/cancelModal' }); | ||
| 51 | }} | ||
| 52 | className="mr-10" | ||
| 53 | > | ||
| 54 | 取消 | ||
| 55 | </Button> | ||
| 56 | <Button onClick={handleSave} type="primary"> | ||
| 57 | 保存 | ||
| 58 | </Button> | ||
| 59 | </div> | ||
| 60 | } | ||
| 61 | > | ||
| 62 | <Form form={form} {...formItemLayout} name="password_set_modal"> | ||
| 63 | <Form.Item | ||
| 64 | name="oldPassword" | ||
| 65 | label="原密码" | ||
| 66 | rules={[{ required: true, message: '请输入原密码' }]} | ||
| 67 | > | ||
| 68 | <Input.Password placeholder="请输入原密码" /> | ||
| 69 | </Form.Item> | ||
| 70 | <Form.Item | ||
| 71 | name="newPassword" | ||
| 72 | label="新密码" | ||
| 73 | rules={[ | ||
| 74 | { required: true, message: '请输入新密码' }, | ||
| 75 | { | ||
| 76 | pattern: /^(?![\d]+$)(?![a-zA-Z]+$)(?![!#$%^&*]+$)[\da-zA-Z!#$%^&@*]{6,16}$/, | ||
| 77 | message: '密码至少包含字母、数字、特殊符号的两种组合,限制6~16个字符~', | ||
| 78 | }, | ||
| 79 | ]} | ||
| 80 | > | ||
| 81 | <Input.Password placeholder="请输入新密码" /> | ||
| 82 | </Form.Item> | ||
| 83 | <Form.Item | ||
| 84 | name="checkPassword" | ||
| 85 | label="确认新密码" | ||
| 86 | rules={[ | ||
| 87 | { required: true, message: '请输入确认新密码' }, | ||
| 88 | ({ getFieldValue }) => ({ | ||
| 89 | validator(_, value) { | ||
| 90 | if (!value || getFieldValue('newPassword') === value) { | ||
| 91 | return Promise.resolve(); | ||
| 92 | } | ||
| 93 | return Promise.reject(new Error('两次密码不一致,请重新输入')); | ||
| 94 | }, | ||
| 95 | }), | ||
| 96 | ]} | ||
| 97 | > | ||
| 98 | <Input.Password placeholder="请输入确认新密码" /> | ||
| 99 | </Form.Item> | ||
| 100 | </Form> | ||
| 101 | </Modal> | ||
| 102 | ); | ||
| 103 | }; | ||
| 104 | |||
| 105 | export default connect(({ user }) => ({ | ||
| 106 | ...user, | ||
| 107 | }))(ModalUpdatePassword); |
src/components/PageCommons.js
0 → 100644
| 1 | /** | ||
| 2 | * Auther: APIS | ||
| 3 | */ | ||
| 4 | import ModalPreImg from '@/pages/Modals/ModalPreImg'; | ||
| 5 | import FileExport from '@/components/FileExport'; | ||
| 6 | import Loading from '@/components/Loading'; | ||
| 7 | |||
| 8 | |||
| 9 | const PageCommons = props=> { | ||
| 10 | const { urlFileExport, loading, dispatch } = props; | ||
| 11 | return ( | ||
| 12 | <> | ||
| 13 | {/* 图片预览 */} | ||
| 14 | <ModalPreImg /> | ||
| 15 | {/* 文件下载 */} | ||
| 16 | <FileExport url={urlFileExport} dispatch={dispatch} /> | ||
| 17 | {/* 全局loading */} | ||
| 18 | <Loading loading={loading} /> | ||
| 19 | </> | ||
| 20 | ) | ||
| 21 | }; | ||
| 22 | export default PageCommons; | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
src/components/PageLoading/index.jsx
0 → 100644
src/components/QCard/index.js
0 → 100644
| 1 | import React, { useEffect } from 'react'; | ||
| 2 | import { Row, Col, Card, Typography, Tooltip, Spin } from 'antd'; | ||
| 3 | import styles from './index.less'; | ||
| 4 | import { ExclamationCircleOutlined } from '@ant-design/icons'; | ||
| 5 | import Loading from '@/components/Loading'; | ||
| 6 | const { Title } = Typography; | ||
| 7 | |||
| 8 | const QCard = props => { | ||
| 9 | const { title, des, children, extra, loading = false, ...otherProps } = props; | ||
| 10 | return ( | ||
| 11 | <Card {...otherProps}> | ||
| 12 | <Loading loading={loading} /> | ||
| 13 | <Row className={styles.main} type="flex" justify="space-between" align="middle"> | ||
| 14 | <Col> | ||
| 15 | <Row type="flex" align="middle"> | ||
| 16 | <Col> | ||
| 17 | <div className={styles.fk} /> | ||
| 18 | </Col> | ||
| 19 | {title && ( | ||
| 20 | <Col> | ||
| 21 | <div className={styles.title}>{title}</div> | ||
| 22 | </Col> | ||
| 23 | )} | ||
| 24 | {des && ( | ||
| 25 | <Col> | ||
| 26 | <Tooltip title={des}> | ||
| 27 | <ExclamationCircleOutlined /> | ||
| 28 | </Tooltip> | ||
| 29 | </Col> | ||
| 30 | )} | ||
| 31 | </Row> | ||
| 32 | </Col> | ||
| 33 | {extra && <Col>{extra}</Col>} | ||
| 34 | </Row> | ||
| 35 | |||
| 36 | {children} | ||
| 37 | </Card> | ||
| 38 | ); | ||
| 39 | }; | ||
| 40 | |||
| 41 | export default QCard; |
src/components/QCard/index.less
0 → 100644
src/components/style/index.tsx
0 → 100644
| 1 | import styled, { css } from 'styled-components'; | ||
| 2 | |||
| 3 | export const StyledPageContainer = styled.div` | ||
| 4 | width: 100%; | ||
| 5 | height: 100%; | ||
| 6 | `; | ||
| 7 | |||
| 8 | export const StyledPageHeader = styled.div<{ border: Boolean }>` | ||
| 9 | display: flex; | ||
| 10 | align-items: center; | ||
| 11 | justify-content: flex-end; | ||
| 12 | background-color: #fff; | ||
| 13 | padding: 8px 16px; | ||
| 14 | border-radius: 2px; | ||
| 15 | border-top: ${props => (props.border ? '1px solid rgba(0, 0, 0, 0.06)' : 'none')}; | ||
| 16 | .ant-btn { | ||
| 17 | margin-left: 10px; | ||
| 18 | } | ||
| 19 | .ant-upload-list { | ||
| 20 | display: none; | ||
| 21 | } | ||
| 22 | `; | ||
| 23 | |||
| 24 | export const StyledPageContent = styled.div` | ||
| 25 | margin: 16px 16px 0; | ||
| 26 | .ant-form { | ||
| 27 | .ant-form-item { | ||
| 28 | margin-bottom: 16px; | ||
| 29 | } | ||
| 30 | } | ||
| 31 | `; | ||
| 32 | |||
| 33 | export const StyledEllipsisWrap = styled.div<{ maxLine: number }>` | ||
| 34 | overflow: hidden; | ||
| 35 | text-overflow: ellipsis; | ||
| 36 | ${p => | ||
| 37 | p.maxLine === 1 | ||
| 38 | ? css` | ||
| 39 | white-space: nowrap; | ||
| 40 | ` | ||
| 41 | : css` | ||
| 42 | display: -webkit-box; | ||
| 43 | white-space: normal; | ||
| 44 | -webkit-line-clamp: ${p.maxLine}; | ||
| 45 | -webkit-box-orient: vertical; | ||
| 46 | word-break: break-all; | ||
| 47 | `} | ||
| 48 | `; | ||
| 49 | |||
| 50 | export const StyledWapperTab = styled.div` | ||
| 51 | .ant-tabs { | ||
| 52 | background-color: #fff; | ||
| 53 | padding: 0px 16px; | ||
| 54 | } | ||
| 55 | .ant-tabs-nav { | ||
| 56 | margin: 0; | ||
| 57 | } | ||
| 58 | .ant-tabs-top > .ant-tabs-nav::before, | ||
| 59 | .ant-tabs-bottom > .ant-tabs-nav::before, | ||
| 60 | .ant-tabs-top > div > .ant-tabs-nav::before, | ||
| 61 | .ant-tabs-bottom > div > .ant-tabs-nav::before { | ||
| 62 | border-bottom: none; | ||
| 63 | } | ||
| 64 | `; | ||
| 65 | |||
| 66 | export const StyledPageFlex = styled.div` | ||
| 67 | display: flex; | ||
| 68 | `; | ||
| 69 | |||
| 70 | export const StyledPageLeft = styled.div` | ||
| 71 | width: 300px; | ||
| 72 | margin-right: 16px; | ||
| 73 | border-radius: 2px; | ||
| 74 | padding: 22px 16px; | ||
| 75 | background-color: #fff; | ||
| 76 | min-height: calc(100vh - 144px); | ||
| 77 | max-height: calc(100vh - 144px); | ||
| 78 | overflow-y: scroll; | ||
| 79 | .ant-tree .ant-tree-node-content-wrapper { | ||
| 80 | padding: 0 6px; | ||
| 81 | .ant-tree-title { | ||
| 82 | font-size: 15px; | ||
| 83 | } | ||
| 84 | } | ||
| 85 | `; | ||
| 86 | |||
| 87 | export const StyledPageRight = styled.div` | ||
| 88 | flex: 1; | ||
| 89 | border-radius: 2px; | ||
| 90 | `; | ||
| 91 | |||
| 92 | export const StyledWapperIframe = styled.div` | ||
| 93 | height: calc(100vh - 62px); | ||
| 94 | width: 100%; | ||
| 95 | background-color: #fff; | ||
| 96 | `; | ||
| 97 | |||
| 98 | export const StyledTitle = styled.div` | ||
| 99 | h1 { | ||
| 100 | font-size: 16px; | ||
| 101 | } | ||
| 102 | `; | ||
| 103 | |||
| 104 | export const StyledText = styled.div` | ||
| 105 | display: flex; | ||
| 106 | flex-wrap: wrap; | ||
| 107 | .item-text { | ||
| 108 | width: calc(50% - 10px); | ||
| 109 | margin-bottom: 10px; | ||
| 110 | margin-right: 10px; | ||
| 111 | .title { | ||
| 112 | color: #797e8f; | ||
| 113 | font-size: 14px; | ||
| 114 | margin-bottom: 4px; | ||
| 115 | } | ||
| 116 | .desc { | ||
| 117 | color: #000; | ||
| 118 | font-size: 14px; | ||
| 119 | } | ||
| 120 | } | ||
| 121 | `; |
src/constants/index.js
0 → 100644
| 1 | import moment from 'moment'; | ||
| 2 | // paginationDefault | ||
| 3 | export const paginations = { | ||
| 4 | position: ['bottomCenter'], | ||
| 5 | defaultCurrent: 1, | ||
| 6 | showSizeChanger: true, | ||
| 7 | showQuickJumper: true, | ||
| 8 | pageSizeOptions: ['5', '10', '20', '50'], | ||
| 9 | }; | ||
| 10 | // staticModal | ||
| 11 | export const staticModal = { | ||
| 12 | modalType: '', | ||
| 13 | modalShow: false, | ||
| 14 | modalData: {}, | ||
| 15 | }; | ||
| 16 | |||
| 17 | // 处理状态 | ||
| 18 | export const mapStatus = { | ||
| 19 | 1: { | ||
| 20 | label: '待办理', | ||
| 21 | value: '1', | ||
| 22 | }, | ||
| 23 | 2: { | ||
| 24 | label: '待整改', | ||
| 25 | value: '2', | ||
| 26 | }, | ||
| 27 | 3: { | ||
| 28 | label: '已办结', | ||
| 29 | value: '3', | ||
| 30 | }, | ||
| 31 | 4: { | ||
| 32 | label: '已整改', | ||
| 33 | value: '4', | ||
| 34 | }, | ||
| 35 | }; | ||
| 36 | |||
| 37 | // 风险类型 | ||
| 38 | export const mapRiskType = { | ||
| 39 | 1: { | ||
| 40 | label: '涉黄', | ||
| 41 | value: '1', | ||
| 42 | }, | ||
| 43 | 2: { | ||
| 44 | label: '涉非', | ||
| 45 | value: '2', | ||
| 46 | }, | ||
| 47 | 3: { | ||
| 48 | label: '涉政', | ||
| 49 | value: '3', | ||
| 50 | }, | ||
| 51 | }; | ||
| 52 | |||
| 53 | // 风险源类型 | ||
| 54 | export const mapRiskSourceType = { | ||
| 55 | 1: { | ||
| 56 | label: '文本', | ||
| 57 | value: '1', | ||
| 58 | }, | ||
| 59 | 2: { | ||
| 60 | label: '图片', | ||
| 61 | value: '2', | ||
| 62 | }, | ||
| 63 | 3: { | ||
| 64 | label: '音频', | ||
| 65 | value: '3', | ||
| 66 | }, | ||
| 67 | 4: { | ||
| 68 | label: '视频', | ||
| 69 | value: '4', | ||
| 70 | }, | ||
| 71 | }; | ||
| 72 | |||
| 73 | // 事件类型 | ||
| 74 | export const mapEventType = { | ||
| 75 | 1: { | ||
| 76 | label: '网吧', | ||
| 77 | value: '1', | ||
| 78 | }, | ||
| 79 | 2: { | ||
| 80 | label: '出版物', | ||
| 81 | value: '2', | ||
| 82 | }, | ||
| 83 | 3: { | ||
| 84 | label: '网络文化', | ||
| 85 | value: '3', | ||
| 86 | }, | ||
| 87 | 4: { | ||
| 88 | label: '印刷', | ||
| 89 | value: '4', | ||
| 90 | }, | ||
| 91 | 5: { | ||
| 92 | label: '电影', | ||
| 93 | value: '5', | ||
| 94 | }, | ||
| 95 | 6: { | ||
| 96 | label: '广电', | ||
| 97 | value: '6', | ||
| 98 | }, | ||
| 99 | 7: { | ||
| 100 | label: '互联网视听', | ||
| 101 | value: '7', | ||
| 102 | }, | ||
| 103 | }; | ||
| 104 | |||
| 105 | // 事件等级 | ||
| 106 | export const mapEventLevel = { | ||
| 107 | 1: { | ||
| 108 | label: '轻微', | ||
| 109 | value: '1', | ||
| 110 | }, | ||
| 111 | 2: { | ||
| 112 | label: '一般', | ||
| 113 | value: '2', | ||
| 114 | }, | ||
| 115 | 3: { | ||
| 116 | label: '严重', | ||
| 117 | value: '3', | ||
| 118 | }, | ||
| 119 | }; | ||
| 120 | |||
| 121 | // 风险标签 | ||
| 122 | export const enumRiskLabel = [ | ||
| 123 | { | ||
| 124 | label: '涉黄', | ||
| 125 | value: '1', | ||
| 126 | }, | ||
| 127 | { | ||
| 128 | label: '涉非', | ||
| 129 | value: '2', | ||
| 130 | }, | ||
| 131 | { | ||
| 132 | label: '涉政', | ||
| 133 | value: '3', | ||
| 134 | }, | ||
| 135 | ]; | ||
| 136 | |||
| 137 | // 事件状态 | ||
| 138 | export const mapEventStatus = { | ||
| 139 | 1: { | ||
| 140 | label: '发起中', | ||
| 141 | value: '1', | ||
| 142 | }, | ||
| 143 | 2: { | ||
| 144 | label: '处理中', | ||
| 145 | value: '2', | ||
| 146 | }, | ||
| 147 | 3: { | ||
| 148 | label: '协同中', | ||
| 149 | value: '3', | ||
| 150 | }, | ||
| 151 | 4: { | ||
| 152 | label: '已办结', | ||
| 153 | value: '4', | ||
| 154 | }, | ||
| 155 | 5: { | ||
| 156 | label: '已关闭', | ||
| 157 | value: '5', | ||
| 158 | }, | ||
| 159 | }; | ||
| 160 | |||
| 161 | // 区域 | ||
| 162 | export const enumArea = [ | ||
| 163 | '百丈镇', | ||
| 164 | '黄湖镇', | ||
| 165 | '鸬鸟镇', | ||
| 166 | '径山镇', | ||
| 167 | '瓶窑镇', | ||
| 168 | '良渚街道', | ||
| 169 | '仁和街道', | ||
| 170 | '仓前街道', | ||
| 171 | '余杭街道', | ||
| 172 | '中泰街道', | ||
| 173 | '闲林街道', | ||
| 174 | '五常街道', | ||
| 175 | ]; | ||
| 176 | |||
| 177 | // 案件原由 | ||
| 178 | export const mapCause = { | ||
| 179 | 1: { | ||
| 180 | label: '行政案件办理', | ||
| 181 | value: '1', | ||
| 182 | }, | ||
| 183 | 2: { | ||
| 184 | label: '网络行政案件', | ||
| 185 | value: '2', | ||
| 186 | }, | ||
| 187 | 3: { | ||
| 188 | label: '刑事案件', | ||
| 189 | value: '3', | ||
| 190 | }, | ||
| 191 | 4: { | ||
| 192 | label: '保护未成年人重要案件', | ||
| 193 | value: '4', | ||
| 194 | }, | ||
| 195 | 0: { | ||
| 196 | label: '其他', | ||
| 197 | value: '0', | ||
| 198 | }, | ||
| 199 | }; | ||
| 200 | |||
| 201 | export const enumYear = (startYear = 1950, endYear = +moment().format('YYYY')) => { | ||
| 202 | let year = []; | ||
| 203 | for (let i = startYear; i <= endYear; i++) { | ||
| 204 | year.push({ | ||
| 205 | label: `${i} 年`, | ||
| 206 | value: i + '', | ||
| 207 | }); | ||
| 208 | } | ||
| 209 | return year; | ||
| 210 | }; |
src/constants/reg.js
0 → 100644
src/e2e/__mocks__/antd-pro-merge-less.js
0 → 100644
| 1 | export default undefined; |
src/e2e/baseLayout.e2e.js
0 → 100644
| 1 | const { uniq } = require('lodash'); | ||
| 2 | const RouterConfig = require('../../config/config').default.routes; | ||
| 3 | |||
| 4 | const BASE_URL = `http://localhost:${process.env.PORT || 8000}`; | ||
| 5 | |||
| 6 | function formatter(routes, parentPath = '') { | ||
| 7 | const fixedParentPath = parentPath.replace(/\/{1,}/g, '/'); | ||
| 8 | let result = []; | ||
| 9 | routes.forEach(item => { | ||
| 10 | if (item.path) { | ||
| 11 | result.push(`${fixedParentPath}/${item.path}`.replace(/\/{1,}/g, '/')); | ||
| 12 | } | ||
| 13 | if (item.routes) { | ||
| 14 | result = result.concat( | ||
| 15 | formatter(item.routes, item.path ? `${fixedParentPath}/${item.path}` : parentPath), | ||
| 16 | ); | ||
| 17 | } | ||
| 18 | }); | ||
| 19 | return uniq(result.filter(item => !!item)); | ||
| 20 | } | ||
| 21 | |||
| 22 | beforeAll(async () => { | ||
| 23 | await page.goto(`${BASE_URL}`); | ||
| 24 | await page.evaluate(() => { | ||
| 25 | localStorage.setItem('antd-pro-authority', '["admin"]'); | ||
| 26 | }); | ||
| 27 | }); | ||
| 28 | |||
| 29 | describe('Ant Design Pro E2E test', () => { | ||
| 30 | const testPage = path => async () => { | ||
| 31 | await page.goto(`${BASE_URL}${path}`); | ||
| 32 | await page.waitForSelector('footer', { | ||
| 33 | timeout: 2000, | ||
| 34 | }); | ||
| 35 | const haveFooter = await page.evaluate( | ||
| 36 | () => document.getElementsByTagName('footer').length > 0, | ||
| 37 | ); | ||
| 38 | expect(haveFooter).toBeTruthy(); | ||
| 39 | }; | ||
| 40 | |||
| 41 | const routers = formatter(RouterConfig); | ||
| 42 | routers.forEach(route => { | ||
| 43 | it(`test pages ${route}`, testPage(route)); | ||
| 44 | }); | ||
| 45 | }); |
src/e2e/topMenu.e2e.js
0 → 100644
| 1 | const BASE_URL = `http://localhost:${process.env.PORT || 8000}`; | ||
| 2 | |||
| 3 | describe('Homepage', () => { | ||
| 4 | it('topmenu should have footer', async () => { | ||
| 5 | const params = '?navTheme=light&layout=topmenu'; | ||
| 6 | await page.goto(`${BASE_URL}${params}`); | ||
| 7 | await page.waitForSelector('footer', { | ||
| 8 | timeout: 2000, | ||
| 9 | }); | ||
| 10 | const haveFooter = await page.evaluate( | ||
| 11 | () => document.getElementsByTagName('footer').length > 0, | ||
| 12 | ); | ||
| 13 | expect(haveFooter).toBeTruthy(); | ||
| 14 | }); | ||
| 15 | }); |
src/global.jsx
0 → 100644
| 1 | import { Button, message, notification } from 'antd'; | ||
| 2 | import React from 'react'; | ||
| 3 | import { formatMessage } from 'umi'; | ||
| 4 | import defaultSettings from '../config/defaultSettings'; | ||
| 5 | const { pwa } = defaultSettings; // if pwa is true | ||
| 6 | |||
| 7 | if (pwa) { | ||
| 8 | // Notify user if offline now | ||
| 9 | window.addEventListener('sw.offline', () => { | ||
| 10 | message.warning( | ||
| 11 | formatMessage({ | ||
| 12 | id: 'app.pwa.offline', | ||
| 13 | }), | ||
| 14 | ); | ||
| 15 | }); // Pop up a prompt on the page asking the user if they want to use the latest version | ||
| 16 | |||
| 17 | window.addEventListener('sw.updated', event => { | ||
| 18 | const e = event; | ||
| 19 | |||
| 20 | const reloadSW = async () => { | ||
| 21 | // Check if there is sw whose state is waiting in ServiceWorkerRegistration | ||
| 22 | // https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration | ||
| 23 | const worker = e.detail && e.detail.waiting; | ||
| 24 | |||
| 25 | if (!worker) { | ||
| 26 | return true; | ||
| 27 | } // Send skip-waiting event to waiting SW with MessageChannel | ||
| 28 | |||
| 29 | await new Promise((resolve, reject) => { | ||
| 30 | const channel = new MessageChannel(); | ||
| 31 | |||
| 32 | channel.port1.onmessage = msgEvent => { | ||
| 33 | if (msgEvent.data.error) { | ||
| 34 | reject(msgEvent.data.error); | ||
| 35 | } else { | ||
| 36 | resolve(msgEvent.data); | ||
| 37 | } | ||
| 38 | }; | ||
| 39 | |||
| 40 | worker.postMessage( | ||
| 41 | { | ||
| 42 | type: 'skip-waiting', | ||
| 43 | }, | ||
| 44 | [channel.port2], | ||
| 45 | ); | ||
| 46 | }); // Refresh current page to use the updated HTML and other assets after SW has skiped waiting | ||
| 47 | |||
| 48 | window.location.reload(true); | ||
| 49 | return true; | ||
| 50 | }; | ||
| 51 | |||
| 52 | const key = `open${Date.now()}`; | ||
| 53 | const btn = ( | ||
| 54 | <Button | ||
| 55 | type="primary" | ||
| 56 | onClick={() => { | ||
| 57 | notification.close(key); | ||
| 58 | reloadSW(); | ||
| 59 | }} | ||
| 60 | > | ||
| 61 | {formatMessage({ | ||
| 62 | id: 'app.pwa.serviceworker.updated.ok', | ||
| 63 | })} | ||
| 64 | </Button> | ||
| 65 | ); | ||
| 66 | notification.open({ | ||
| 67 | message: formatMessage({ | ||
| 68 | id: 'app.pwa.serviceworker.updated', | ||
| 69 | }), | ||
| 70 | description: formatMessage({ | ||
| 71 | id: 'app.pwa.serviceworker.updated.hint', | ||
| 72 | }), | ||
| 73 | btn, | ||
| 74 | key, | ||
| 75 | onClose: async () => {}, | ||
| 76 | }); | ||
| 77 | }); | ||
| 78 | } else if ('serviceWorker' in navigator) { | ||
| 79 | // unregister service worker | ||
| 80 | const { serviceWorker } = navigator; | ||
| 81 | |||
| 82 | if (serviceWorker.getRegistrations) { | ||
| 83 | serviceWorker.getRegistrations().then(sws => { | ||
| 84 | sws.forEach(sw => { | ||
| 85 | sw.unregister(); | ||
| 86 | }); | ||
| 87 | }); | ||
| 88 | } | ||
| 89 | |||
| 90 | serviceWorker.getRegistration().then(sw => { | ||
| 91 | if (sw) sw.unregister(); | ||
| 92 | }); // remove all caches | ||
| 93 | |||
| 94 | if (window.caches && window.caches.keys) { | ||
| 95 | caches.keys().then(keys => { | ||
| 96 | keys.forEach(key => { | ||
| 97 | caches.delete(key); | ||
| 98 | }); | ||
| 99 | }); | ||
| 100 | } | ||
| 101 | } |
src/global.less
0 → 100644
| 1 | @import '~antd/es/style/themes/default.less'; | ||
| 2 | |||
| 3 | html, | ||
| 4 | body, | ||
| 5 | #root { | ||
| 6 | height: 100%; | ||
| 7 | overflow: hidden; | ||
| 8 | } | ||
| 9 | |||
| 10 | .colorWeak { | ||
| 11 | filter: invert(80%); | ||
| 12 | } | ||
| 13 | |||
| 14 | .ant-layout { | ||
| 15 | min-height: 100vh; | ||
| 16 | } | ||
| 17 | |||
| 18 | canvas { | ||
| 19 | display: block; | ||
| 20 | } | ||
| 21 | |||
| 22 | body { | ||
| 23 | text-rendering: optimizeLegibility; | ||
| 24 | -webkit-font-smoothing: antialiased; | ||
| 25 | -moz-osx-font-smoothing: grayscale; | ||
| 26 | } | ||
| 27 | |||
| 28 | /* 浏览器滚动条相关 */ | ||
| 29 | ::-webkit-scrollbar-thumb { | ||
| 30 | height: 50px; | ||
| 31 | background: rgba(160, 160, 160, 0.8); | ||
| 32 | border-radius: 3px; | ||
| 33 | transition: background 1s; | ||
| 34 | &:hover { | ||
| 35 | background: rgba(160, 160, 160, 1); | ||
| 36 | } | ||
| 37 | } | ||
| 38 | ::-webkit-scrollbar { | ||
| 39 | width: 4px; | ||
| 40 | height: 4px; | ||
| 41 | } | ||
| 42 | |||
| 43 | ul, | ||
| 44 | ol { | ||
| 45 | list-style: none; | ||
| 46 | } | ||
| 47 | |||
| 48 | @media (max-width: @screen-xs) { | ||
| 49 | .ant-table { | ||
| 50 | width: 100%; | ||
| 51 | overflow-x: auto; | ||
| 52 | &-thead > tr, | ||
| 53 | &-tbody > tr { | ||
| 54 | > th, | ||
| 55 | > td { | ||
| 56 | white-space: pre; | ||
| 57 | > span { | ||
| 58 | display: block; | ||
| 59 | } | ||
| 60 | } | ||
| 61 | } | ||
| 62 | } | ||
| 63 | } | ||
| 64 | |||
| 65 | // 兼容IE11 | ||
| 66 | @media screen and(-ms-high-contrast: active), (-ms-high-contrast: none) { | ||
| 67 | body .ant-design-pro > .ant-layout { | ||
| 68 | min-height: 100vh; | ||
| 69 | } | ||
| 70 | } | ||
| 71 | .mt-5 { | ||
| 72 | margin-top: 5px !important; | ||
| 73 | } | ||
| 74 | .mt-10 { | ||
| 75 | margin-top: 10px !important; | ||
| 76 | } | ||
| 77 | .mt-15 { | ||
| 78 | margin-top: 15px !important; | ||
| 79 | } | ||
| 80 | .mt-20 { | ||
| 81 | margin-top: 20px !important; | ||
| 82 | } | ||
| 83 | .mt-24 { | ||
| 84 | margin-top: 24px !important; | ||
| 85 | } | ||
| 86 | |||
| 87 | .ml-5 { | ||
| 88 | margin-left: 5px !important; | ||
| 89 | } | ||
| 90 | .ml-10 { | ||
| 91 | margin-left: 10px !important; | ||
| 92 | } | ||
| 93 | .ml-15 { | ||
| 94 | margin-left: 15px !important; | ||
| 95 | } | ||
| 96 | .ml-20 { | ||
| 97 | margin-left: 20px !important; | ||
| 98 | } | ||
| 99 | |||
| 100 | .mr-5 { | ||
| 101 | margin-right: 5px !important; | ||
| 102 | } | ||
| 103 | .mr-10 { | ||
| 104 | margin-right: 10px !important; | ||
| 105 | } | ||
| 106 | .mr-15 { | ||
| 107 | margin-right: 15px !important; | ||
| 108 | } | ||
| 109 | .mr-20 { | ||
| 110 | margin-right: 20px !important; | ||
| 111 | } | ||
| 112 | .mr-30 { | ||
| 113 | margin-right: 30px !important; | ||
| 114 | } | ||
| 115 | |||
| 116 | .mb-5 { | ||
| 117 | margin-bottom: 5px !important; | ||
| 118 | } | ||
| 119 | .mb-10 { | ||
| 120 | margin-bottom: 10px !important; | ||
| 121 | } | ||
| 122 | .mb-15 { | ||
| 123 | margin-bottom: 15px !important; | ||
| 124 | } | ||
| 125 | .mb-20 { | ||
| 126 | margin-bottom: 20px !important; | ||
| 127 | } | ||
| 128 | |||
| 129 | .tn-l { | ||
| 130 | text-align: left; | ||
| 131 | } | ||
| 132 | .tn-c { | ||
| 133 | text-align: center; | ||
| 134 | } | ||
| 135 | .tn-r { | ||
| 136 | text-align: right; | ||
| 137 | } | ||
| 138 | .ft-24 { | ||
| 139 | font-size: 24px; | ||
| 140 | } | ||
| 141 | .color-gray { | ||
| 142 | color: rgba(0, 0, 0, 0.35); | ||
| 143 | } | ||
| 144 | .color-primary { | ||
| 145 | color: @primary-color !important; | ||
| 146 | } | ||
| 147 | |||
| 148 | // 清除上下浮动 | ||
| 149 | .clearfix { | ||
| 150 | &::before, | ||
| 151 | &::after { | ||
| 152 | content: ' '; | ||
| 153 | display: table; | ||
| 154 | } | ||
| 155 | &::after { | ||
| 156 | clear: both; | ||
| 157 | } | ||
| 158 | } | ||
| 159 | .left { | ||
| 160 | float: left; | ||
| 161 | } | ||
| 162 | .right { | ||
| 163 | float: right; | ||
| 164 | } | ||
| 165 | .fn-hide { | ||
| 166 | display: none !important; | ||
| 167 | } | ||
| 168 | // 单行字体溢出时显示省略号 | ||
| 169 | .ellipsis { | ||
| 170 | white-space: nowrap; | ||
| 171 | overflow: hidden; | ||
| 172 | text-overflow: ellipsis; | ||
| 173 | } | ||
| 174 | |||
| 175 | .pointer { | ||
| 176 | cursor: pointer; | ||
| 177 | &:hover { | ||
| 178 | color: #40a9ff; | ||
| 179 | } | ||
| 180 | } | ||
| 181 | .wflex_r_s { | ||
| 182 | display: flex; | ||
| 183 | flex-direction: row; | ||
| 184 | justify-content: space-between; | ||
| 185 | align-items: center; | ||
| 186 | } | ||
| 187 | |||
| 188 | .c9 { | ||
| 189 | color: #999 !important; | ||
| 190 | } | ||
| 191 | |||
| 192 | :global { | ||
| 193 | .ant-table-wrapper { | ||
| 194 | .ant-table-pagination.ant-pagination { | ||
| 195 | margin-top: 24px; | ||
| 196 | margin-bottom: 0px; | ||
| 197 | justify-content: flex-end; | ||
| 198 | } | ||
| 199 | } | ||
| 200 | .ant-pro-basicLayout-content { | ||
| 201 | margin: 0px; | ||
| 202 | } | ||
| 203 | .ant-tooltip-inner { | ||
| 204 | .anticon { | ||
| 205 | margin-right: 6px; | ||
| 206 | } | ||
| 207 | } | ||
| 208 | } | ||
| 209 | |||
| 210 | /* 权限相关样式 */ | ||
| 211 | .view-tree-auth { | ||
| 212 | :global { | ||
| 213 | .ant-tree { | ||
| 214 | position: relative; | ||
| 215 | top: 3px; | ||
| 216 | } | ||
| 217 | .info-tree { | ||
| 218 | .ant-tree-list { | ||
| 219 | .ant-tree-treenode { | ||
| 220 | .ant-tree-node-content-wrapper { | ||
| 221 | .ant-tree-title { | ||
| 222 | span { | ||
| 223 | display: none; | ||
| 224 | &:hover { | ||
| 225 | opacity: 0.8; | ||
| 226 | } | ||
| 227 | &:first-child { | ||
| 228 | color: #185da2; | ||
| 229 | } | ||
| 230 | &:last-child { | ||
| 231 | color: #666; | ||
| 232 | } | ||
| 233 | } | ||
| 234 | &:hover { | ||
| 235 | span { | ||
| 236 | display: inline-block; | ||
| 237 | } | ||
| 238 | } | ||
| 239 | } | ||
| 240 | } | ||
| 241 | } | ||
| 242 | } | ||
| 243 | } | ||
| 244 | } | ||
| 245 | } | ||
| 246 | |||
| 247 | .box-info { | ||
| 248 | min-height: calc(~'100vh - 112px'); | ||
| 249 | :global { | ||
| 250 | .ant-card { | ||
| 251 | min-height: calc(~'100vh - 195px'); | ||
| 252 | margin-bottom: 70px; | ||
| 253 | .footer-btn { | ||
| 254 | position: fixed; | ||
| 255 | bottom: 0; | ||
| 256 | left: 0; | ||
| 257 | z-index: 10; | ||
| 258 | width: 100%; | ||
| 259 | height: 56px; | ||
| 260 | line-height: 56px; | ||
| 261 | margin-bottom: 0; | ||
| 262 | text-align: center; | ||
| 263 | background-color: #fff; | ||
| 264 | box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.03); | ||
| 265 | } | ||
| 266 | } | ||
| 267 | } | ||
| 268 | } |
src/layouts/BasicLayout.jsx
0 → 100644
| 1 | /** | ||
| 2 | * Ant Design Pro v4 use `@ant-design/pro-layout` to handle Layout. | ||
| 3 | * You can view component api by: | ||
| 4 | * https://github.com/ant-design/ant-design-pro-layout | ||
| 5 | */ | ||
| 6 | import ProLayout from '@ant-design/pro-layout'; | ||
| 7 | import { Link, connect, useIntl, history } from 'umi'; | ||
| 8 | import React from 'react'; | ||
| 9 | import RightContent from '@/components/GlobalHeader/RightContent'; | ||
| 10 | import AuthRouter from '@/components/Auth/AuthRouter'; | ||
| 11 | import PageCommons from '@/components/PageCommons'; | ||
| 12 | import YH from '@/assets/yh-logo.png'; | ||
| 13 | import { | ||
| 14 | DesktopOutlined, | ||
| 15 | WarningOutlined, | ||
| 16 | SelectOutlined, | ||
| 17 | BarsOutlined, | ||
| 18 | SettingOutlined, | ||
| 19 | } from '@ant-design/icons'; | ||
| 20 | import { StyledTitle } from '@/components/style'; | ||
| 21 | import { codeMappingForResource } from '../../config/routerConfig'; | ||
| 22 | |||
| 23 | const IconMap = { | ||
| 24 | screen: <DesktopOutlined />, | ||
| 25 | risk: <WarningOutlined />, | ||
| 26 | event: <SelectOutlined />, | ||
| 27 | data: <BarsOutlined />, | ||
| 28 | system: <SettingOutlined />, | ||
| 29 | }; | ||
| 30 | |||
| 31 | const BasicLayout = props => { | ||
| 32 | const intl = useIntl(); | ||
| 33 | const { formatMessage } = intl; | ||
| 34 | const { | ||
| 35 | dispatch, | ||
| 36 | children, | ||
| 37 | settings, | ||
| 38 | location: { pathname }, | ||
| 39 | loading, | ||
| 40 | urlFileExport, | ||
| 41 | currentUser: { menus }, | ||
| 42 | } = props; | ||
| 43 | const handleMenuCollapse = payload => { | ||
| 44 | if (dispatch) { | ||
| 45 | dispatch({ | ||
| 46 | type: 'global/changeLayoutCollapsed', | ||
| 47 | payload, | ||
| 48 | }); | ||
| 49 | } | ||
| 50 | }; | ||
| 51 | // 重定向处理 | ||
| 52 | // const isRedirect = pathname === '/'; | ||
| 53 | // if (isRedirect && dataMenus.length) { | ||
| 54 | // history.replace({ pathname: dataMenus[0].path }); | ||
| 55 | // }; | ||
| 56 | // 菜单 loop | ||
| 57 | const loopMenuItem = menus => { | ||
| 58 | // console.log(menus, 'menus', codeMappingForResource); | ||
| 59 | return menus?.map(({ icon, children, ...item }) => ({ | ||
| 60 | ...(codeMappingForResource.get(item.resourceCode) || {}), | ||
| 61 | icon: icon && IconMap[icon], | ||
| 62 | routes: children && loopMenuItem(children), | ||
| 63 | })); | ||
| 64 | }; | ||
| 65 | |||
| 66 | return ( | ||
| 67 | <ProLayout | ||
| 68 | formatMessage={formatMessage} | ||
| 69 | menuHeaderRender={(logoDom, titleDom) => ( | ||
| 70 | <Link to="/"> | ||
| 71 | <img src={YH} /> | ||
| 72 | <StyledTitle>{titleDom}</StyledTitle> | ||
| 73 | </Link> | ||
| 74 | )} | ||
| 75 | onCollapse={handleMenuCollapse} | ||
| 76 | menuItemRender={(menuItemProps, defaultDom) => { | ||
| 77 | if (menuItemProps.isUrl || menuItemProps.children || !menuItemProps.path) { | ||
| 78 | return defaultDom; | ||
| 79 | } | ||
| 80 | return ( | ||
| 81 | <Link to={menuItemProps.path}> | ||
| 82 | {IconMap[menuItemProps.icons]} | ||
| 83 | {defaultDom} | ||
| 84 | </Link> | ||
| 85 | ); | ||
| 86 | }} | ||
| 87 | subMenuItemRender={subProps => { | ||
| 88 | return ( | ||
| 89 | <span className="ant-pro-menu-item"> | ||
| 90 | {IconMap[subProps.icons]} | ||
| 91 | <span>{subProps.name}</span> | ||
| 92 | </span> | ||
| 93 | ); | ||
| 94 | }} | ||
| 95 | menuDataRender={() => loopMenuItem(menus)} | ||
| 96 | rightContentRender={() => <RightContent />} | ||
| 97 | {...props} | ||
| 98 | {...settings} | ||
| 99 | > | ||
| 100 | {/* 路由权限 */} | ||
| 101 | <AuthRouter path={pathname}>{children}</AuthRouter> | ||
| 102 | <PageCommons loading={loading} urlFileExport={urlFileExport} dispatch={dispatch} /> | ||
| 103 | </ProLayout> | ||
| 104 | ); | ||
| 105 | }; | ||
| 106 | |||
| 107 | export default connect(({ global, settings, user }) => ({ | ||
| 108 | settings, | ||
| 109 | loading: global.loading, | ||
| 110 | collapsed: global.collapsed, | ||
| 111 | urlFileExport: global.urlFileExport, | ||
| 112 | currentUser: user.currentUser, | ||
| 113 | }))(BasicLayout); |
src/layouts/BlankLayout.jsx
0 → 100644
src/layouts/UserLayout.jsx
0 → 100644
| 1 | import { connect } from 'umi'; | ||
| 2 | import React from 'react'; | ||
| 3 | import styles from './UserLayout.less'; | ||
| 4 | |||
| 5 | const UserLayout = props => { | ||
| 6 | const { children } = props; | ||
| 7 | return ( | ||
| 8 | <> | ||
| 9 | <div className={styles.container}> | ||
| 10 | <div className={styles.bgTop}> | ||
| 11 | <div>一网打“净”数智在线</div> | ||
| 12 | </div> | ||
| 13 | <div className={styles.content}> | ||
| 14 | <div className={styles.login}>{children}</div> | ||
| 15 | </div> | ||
| 16 | </div> | ||
| 17 | </> | ||
| 18 | ); | ||
| 19 | }; | ||
| 20 | |||
| 21 | export default connect(({ settings, user }) => ({ | ||
| 22 | ...settings, | ||
| 23 | currentUser: user.currentUser, | ||
| 24 | }))(UserLayout); |
src/layouts/UserLayout.less
0 → 100644
| 1 | @import '~antd/es/style/themes/default.less'; | ||
| 2 | |||
| 3 | .container { | ||
| 4 | width: 100%; | ||
| 5 | display: flex; | ||
| 6 | flex-direction: column; | ||
| 7 | height: 100vh; | ||
| 8 | overflow: auto; | ||
| 9 | position: relative; | ||
| 10 | background-color: #F5F5F5; | ||
| 11 | .bgTop { | ||
| 12 | background-color: @primary-color; | ||
| 13 | height: 400px; | ||
| 14 | div { | ||
| 15 | color: #fff; | ||
| 16 | text-align: center; | ||
| 17 | font-size: 22px; | ||
| 18 | position: absolute; | ||
| 19 | top: 170px; | ||
| 20 | left: 50%; | ||
| 21 | letter-spacing: 2px; | ||
| 22 | transform: translateX(-50%); | ||
| 23 | } | ||
| 24 | } | ||
| 25 | .content { | ||
| 26 | position: absolute; | ||
| 27 | background-color: #fff; | ||
| 28 | border-radius: 2px; | ||
| 29 | top: 220px; | ||
| 30 | left: 50%; | ||
| 31 | z-index: 2; | ||
| 32 | transform: translateX(-50%); | ||
| 33 | .login { | ||
| 34 | width: 400px; | ||
| 35 | box-shadow: 0 4px 50px 0 rgba(121,173,201,.17); | ||
| 36 | } | ||
| 37 | } | ||
| 38 | } |
src/locales/en-US.js
0 → 100644
| 1 | import component from './en-US/component'; | ||
| 2 | import globalHeader from './en-US/globalHeader'; | ||
| 3 | import menu from './en-US/menu'; | ||
| 4 | import pwa from './en-US/pwa'; | ||
| 5 | import settingDrawer from './en-US/settingDrawer'; | ||
| 6 | import settings from './en-US/settings'; | ||
| 7 | export default { | ||
| 8 | 'navBar.lang': 'Languages', | ||
| 9 | 'layout.user.link.help': 'Help', | ||
| 10 | 'layout.user.link.privacy': 'Privacy', | ||
| 11 | 'layout.user.link.terms': 'Terms', | ||
| 12 | 'app.preview.down.block': 'Download this page to your local project', | ||
| 13 | 'app.welcome.link.fetch-blocks': 'Get all block', | ||
| 14 | 'app.welcome.link.block-list': 'Quickly build standard, pages based on `block` development', | ||
| 15 | ...globalHeader, | ||
| 16 | ...menu, | ||
| 17 | ...settingDrawer, | ||
| 18 | ...settings, | ||
| 19 | ...pwa, | ||
| 20 | ...component, | ||
| 21 | }; |
src/locales/en-US/component.js
0 → 100644
src/locales/en-US/globalHeader.js
0 → 100644
| 1 | export default { | ||
| 2 | 'component.globalHeader.search': 'Search', | ||
| 3 | 'component.globalHeader.search.example1': 'Search example 1', | ||
| 4 | 'component.globalHeader.search.example2': 'Search example 2', | ||
| 5 | 'component.globalHeader.search.example3': 'Search example 3', | ||
| 6 | 'component.globalHeader.help': 'Help', | ||
| 7 | 'component.globalHeader.notification': 'Notification', | ||
| 8 | 'component.globalHeader.notification.empty': 'You have viewed all notifications.', | ||
| 9 | 'component.globalHeader.message': 'Message', | ||
| 10 | 'component.globalHeader.message.empty': 'You have viewed all messsages.', | ||
| 11 | 'component.globalHeader.event': 'Event', | ||
| 12 | 'component.globalHeader.event.empty': 'You have viewed all events.', | ||
| 13 | 'component.noticeIcon.clear': 'Clear', | ||
| 14 | 'component.noticeIcon.cleared': 'Cleared', | ||
| 15 | 'component.noticeIcon.empty': 'No notifications', | ||
| 16 | 'component.noticeIcon.view-more': 'View more', | ||
| 17 | }; |
src/locales/en-US/menu.js
0 → 100644
| 1 | export default { | ||
| 2 | 'menu.welcome': 'Welcome', | ||
| 3 | 'menu.more-blocks': 'More Blocks', | ||
| 4 | 'menu.home': 'Home', | ||
| 5 | 'menu.admin': 'Admin', | ||
| 6 | 'menu.admin.sub-page': 'Sub-Page', | ||
| 7 | 'menu.login': 'Login', | ||
| 8 | 'menu.register': 'Register', | ||
| 9 | 'menu.register.result': 'Register Result', | ||
| 10 | 'menu.dashboard': 'Dashboard', | ||
| 11 | 'menu.dashboard.analysis': 'Analysis', | ||
| 12 | 'menu.dashboard.monitor': 'Monitor', | ||
| 13 | 'menu.dashboard.workplace': 'Workplace', | ||
| 14 | 'menu.exception.403': '403', | ||
| 15 | 'menu.exception.404': '404', | ||
| 16 | 'menu.exception.500': '500', | ||
| 17 | 'menu.form': 'Form', | ||
| 18 | 'menu.form.basic-form': 'Basic Form', | ||
| 19 | 'menu.form.step-form': 'Step Form', | ||
| 20 | 'menu.form.step-form.info': 'Step Form(write transfer information)', | ||
| 21 | 'menu.form.step-form.confirm': 'Step Form(confirm transfer information)', | ||
| 22 | 'menu.form.step-form.result': 'Step Form(finished)', | ||
| 23 | 'menu.form.advanced-form': 'Advanced Form', | ||
| 24 | 'menu.list': 'List', | ||
| 25 | 'menu.list.table-list': 'Search Table', | ||
| 26 | 'menu.list.basic-list': 'Basic List', | ||
| 27 | 'menu.list.card-list': 'Card List', | ||
| 28 | 'menu.list.search-list': 'Search List', | ||
| 29 | 'menu.list.search-list.articles': 'Search List(articles)', | ||
| 30 | 'menu.list.search-list.projects': 'Search List(projects)', | ||
| 31 | 'menu.list.search-list.applications': 'Search List(applications)', | ||
| 32 | 'menu.profile': 'Profile', | ||
| 33 | 'menu.profile.basic': 'Basic Profile', | ||
| 34 | 'menu.profile.advanced': 'Advanced Profile', | ||
| 35 | 'menu.result': 'Result', | ||
| 36 | 'menu.result.success': 'Success', | ||
| 37 | 'menu.result.fail': 'Fail', | ||
| 38 | 'menu.exception': 'Exception', | ||
| 39 | 'menu.exception.not-permission': '403', | ||
| 40 | 'menu.exception.not-find': '404', | ||
| 41 | 'menu.exception.server-error': '500', | ||
| 42 | 'menu.exception.trigger': 'Trigger', | ||
| 43 | 'menu.account': 'Account', | ||
| 44 | 'menu.account.center': 'Account Center', | ||
| 45 | 'menu.account.settings': 'Account Settings', | ||
| 46 | 'menu.account.trigger': 'Trigger Error', | ||
| 47 | 'menu.account.logout': 'Logout', | ||
| 48 | 'menu.editor': 'Graphic Editor', | ||
| 49 | 'menu.editor.flow': 'Flow Editor', | ||
| 50 | 'menu.editor.mind': 'Mind Editor', | ||
| 51 | 'menu.editor.koni': 'Koni Editor', | ||
| 52 | }; |
src/locales/en-US/pwa.js
0 → 100644
src/locales/en-US/settingDrawer.js
0 → 100644
| 1 | export default { | ||
| 2 | 'app.setting.pagestyle': 'Page style setting', | ||
| 3 | 'app.setting.pagestyle.dark': 'Dark style', | ||
| 4 | 'app.setting.pagestyle.light': 'Light style', | ||
| 5 | 'app.setting.content-width': 'Content Width', | ||
| 6 | 'app.setting.content-width.fixed': 'Fixed', | ||
| 7 | 'app.setting.content-width.fluid': 'Fluid', | ||
| 8 | 'app.setting.themecolor': 'Theme Color', | ||
| 9 | 'app.setting.themecolor.dust': 'Dust Red', | ||
| 10 | 'app.setting.themecolor.volcano': 'Volcano', | ||
| 11 | 'app.setting.themecolor.sunset': 'Sunset Orange', | ||
| 12 | 'app.setting.themecolor.cyan': 'Cyan', | ||
| 13 | 'app.setting.themecolor.green': 'Polar Green', | ||
| 14 | 'app.setting.themecolor.daybreak': 'Daybreak Blue (default)', | ||
| 15 | 'app.setting.themecolor.geekblue': 'Geek Glue', | ||
| 16 | 'app.setting.themecolor.purple': 'Golden Purple', | ||
| 17 | 'app.setting.navigationmode': 'Navigation Mode', | ||
| 18 | 'app.setting.sidemenu': 'Side Menu Layout', | ||
| 19 | 'app.setting.topmenu': 'Top Menu Layout', | ||
| 20 | 'app.setting.fixedheader': 'Fixed Header', | ||
| 21 | 'app.setting.fixedsidebar': 'Fixed Sidebar', | ||
| 22 | 'app.setting.fixedsidebar.hint': 'Works on Side Menu Layout', | ||
| 23 | 'app.setting.hideheader': 'Hidden Header when scrolling', | ||
| 24 | 'app.setting.hideheader.hint': 'Works when Hidden Header is enabled', | ||
| 25 | 'app.setting.othersettings': 'Other Settings', | ||
| 26 | 'app.setting.weakmode': 'Weak Mode', | ||
| 27 | 'app.setting.copy': 'Copy Setting', | ||
| 28 | 'app.setting.copyinfo': 'copy success,please replace defaultSettings in src/models/setting.js', | ||
| 29 | 'app.setting.production.hint': | ||
| 30 | 'Setting panel shows in development environment only, please manually modify', | ||
| 31 | }; |
src/locales/en-US/settings.js
0 → 100644
| 1 | export default { | ||
| 2 | 'app.settings.menuMap.basic': 'Basic Settings', | ||
| 3 | 'app.settings.menuMap.security': 'Security Settings', | ||
| 4 | 'app.settings.menuMap.binding': 'Account Binding', | ||
| 5 | 'app.settings.menuMap.notification': 'New Message Notification', | ||
| 6 | 'app.settings.basic.avatar': 'Avatar', | ||
| 7 | 'app.settings.basic.change-avatar': 'Change avatar', | ||
| 8 | 'app.settings.basic.email': 'Email', | ||
| 9 | 'app.settings.basic.email-message': 'Please input your email!', | ||
| 10 | 'app.settings.basic.nickname': 'Nickname', | ||
| 11 | 'app.settings.basic.nickname-message': 'Please input your Nickname!', | ||
| 12 | 'app.settings.basic.profile': 'Personal profile', | ||
| 13 | 'app.settings.basic.profile-message': 'Please input your personal profile!', | ||
| 14 | 'app.settings.basic.profile-placeholder': 'Brief introduction to yourself', | ||
| 15 | 'app.settings.basic.country': 'Country/Region', | ||
| 16 | 'app.settings.basic.country-message': 'Please input your country!', | ||
| 17 | 'app.settings.basic.geographic': 'Province or city', | ||
| 18 | 'app.settings.basic.geographic-message': 'Please input your geographic info!', | ||
| 19 | 'app.settings.basic.address': 'Street Address', | ||
| 20 | 'app.settings.basic.address-message': 'Please input your address!', | ||
| 21 | 'app.settings.basic.phone': 'Phone Number', | ||
| 22 | 'app.settings.basic.phone-message': 'Please input your phone!', | ||
| 23 | 'app.settings.basic.update': 'Update Information', | ||
| 24 | 'app.settings.security.strong': 'Strong', | ||
| 25 | 'app.settings.security.medium': 'Medium', | ||
| 26 | 'app.settings.security.weak': 'Weak', | ||
| 27 | 'app.settings.security.password': 'Account Password', | ||
| 28 | 'app.settings.security.password-description': 'Current password strength', | ||
| 29 | 'app.settings.security.phone': 'Security Phone', | ||
| 30 | 'app.settings.security.phone-description': 'Bound phone', | ||
| 31 | 'app.settings.security.question': 'Security Question', | ||
| 32 | 'app.settings.security.question-description': | ||
| 33 | 'The security question is not set, and the security policy can effectively protect the account security', | ||
| 34 | 'app.settings.security.email': 'Backup Email', | ||
| 35 | 'app.settings.security.email-description': 'Bound Email', | ||
| 36 | 'app.settings.security.mfa': 'MFA Device', | ||
| 37 | 'app.settings.security.mfa-description': | ||
| 38 | 'Unbound MFA device, after binding, can be confirmed twice', | ||
| 39 | 'app.settings.security.modify': 'Modify', | ||
| 40 | 'app.settings.security.set': 'Set', | ||
| 41 | 'app.settings.security.bind': 'Bind', | ||
| 42 | 'app.settings.binding.taobao': 'Binding Taobao', | ||
| 43 | 'app.settings.binding.taobao-description': 'Currently unbound Taobao account', | ||
| 44 | 'app.settings.binding.alipay': 'Binding Alipay', | ||
| 45 | 'app.settings.binding.alipay-description': 'Currently unbound Alipay account', | ||
| 46 | 'app.settings.binding.dingding': 'Binding DingTalk', | ||
| 47 | 'app.settings.binding.dingding-description': 'Currently unbound DingTalk account', | ||
| 48 | 'app.settings.binding.bind': 'Bind', | ||
| 49 | 'app.settings.notification.password': 'Account Password', | ||
| 50 | 'app.settings.notification.password-description': | ||
| 51 | 'Messages from other users will be notified in the form of a station letter', | ||
| 52 | 'app.settings.notification.messages': 'System Messages', | ||
| 53 | 'app.settings.notification.messages-description': | ||
| 54 | 'System messages will be notified in the form of a station letter', | ||
| 55 | 'app.settings.notification.todo': 'To-do Notification', | ||
| 56 | 'app.settings.notification.todo-description': | ||
| 57 | 'The to-do list will be notified in the form of a letter from the station', | ||
| 58 | 'app.settings.open': 'Open', | ||
| 59 | 'app.settings.close': 'Close', | ||
| 60 | }; |
src/locales/pt-BR.js
0 → 100644
| 1 | import component from './pt-BR/component'; | ||
| 2 | import globalHeader from './pt-BR/globalHeader'; | ||
| 3 | import menu from './pt-BR/menu'; | ||
| 4 | import pwa from './pt-BR/pwa'; | ||
| 5 | import settingDrawer from './pt-BR/settingDrawer'; | ||
| 6 | import settings from './pt-BR/settings'; | ||
| 7 | export default { | ||
| 8 | 'navBar.lang': 'Idiomas', | ||
| 9 | 'layout.user.link.help': 'ajuda', | ||
| 10 | 'layout.user.link.privacy': 'política de privacidade', | ||
| 11 | 'layout.user.link.terms': 'termos de serviços', | ||
| 12 | 'app.preview.down.block': 'Download this page to your local project', | ||
| 13 | ...globalHeader, | ||
| 14 | ...menu, | ||
| 15 | ...settingDrawer, | ||
| 16 | ...settings, | ||
| 17 | ...pwa, | ||
| 18 | ...component, | ||
| 19 | }; |
src/locales/pt-BR/component.js
0 → 100644
src/locales/pt-BR/globalHeader.js
0 → 100644
| 1 | export default { | ||
| 2 | 'component.globalHeader.search': 'Busca', | ||
| 3 | 'component.globalHeader.search.example1': 'Exemplo de busca 1', | ||
| 4 | 'component.globalHeader.search.example2': 'Exemplo de busca 2', | ||
| 5 | 'component.globalHeader.search.example3': 'Exemplo de busca 3', | ||
| 6 | 'component.globalHeader.help': 'Ajuda', | ||
| 7 | 'component.globalHeader.notification': 'Notificação', | ||
| 8 | 'component.globalHeader.notification.empty': 'Você visualizou todas as notificações.', | ||
| 9 | 'component.globalHeader.message': 'Mensagem', | ||
| 10 | 'component.globalHeader.message.empty': 'Você visualizou todas as mensagens.', | ||
| 11 | 'component.globalHeader.event': 'Evento', | ||
| 12 | 'component.globalHeader.event.empty': 'Você visualizou todos os eventos.', | ||
| 13 | 'component.noticeIcon.clear': 'Limpar', | ||
| 14 | 'component.noticeIcon.cleared': 'Limpo', | ||
| 15 | 'component.noticeIcon.empty': 'Sem notificações', | ||
| 16 | 'component.noticeIcon.loaded': 'Carregado', | ||
| 17 | 'component.noticeIcon.view-more': 'Veja mais', | ||
| 18 | }; |
src/locales/pt-BR/menu.js
0 → 100644
| 1 | export default { | ||
| 2 | 'menu.welcome': 'Welcome', | ||
| 3 | 'menu.more-blocks': 'More Blocks', | ||
| 4 | 'menu.home': 'Início', | ||
| 5 | 'menu.login': 'Login', | ||
| 6 | 'menu.admin': 'Admin', | ||
| 7 | 'menu.admin.sub-page': 'Sub-Page', | ||
| 8 | 'menu.register': 'Registro', | ||
| 9 | 'menu.register.result': 'Resultado de registro', | ||
| 10 | 'menu.dashboard': 'Dashboard', | ||
| 11 | 'menu.dashboard.analysis': 'Análise', | ||
| 12 | 'menu.dashboard.monitor': 'Monitor', | ||
| 13 | 'menu.dashboard.workplace': 'Ambiente de Trabalho', | ||
| 14 | 'menu.exception.403': '403', | ||
| 15 | 'menu.exception.404': '404', | ||
| 16 | 'menu.exception.500': '500', | ||
| 17 | 'menu.form': 'Formulário', | ||
| 18 | 'menu.form.basic-form': 'Formulário Básico', | ||
| 19 | 'menu.form.step-form': 'Formulário Assistido', | ||
| 20 | 'menu.form.step-form.info': 'Formulário Assistido(gravar informações de transferência)', | ||
| 21 | 'menu.form.step-form.confirm': 'Formulário Assistido(confirmar informações de transferência)', | ||
| 22 | 'menu.form.step-form.result': 'Formulário Assistido(finalizado)', | ||
| 23 | 'menu.form.advanced-form': 'Formulário Avançado', | ||
| 24 | 'menu.list': 'Lista', | ||
| 25 | 'menu.list.table-list': 'Tabela de Busca', | ||
| 26 | 'menu.list.basic-list': 'Lista Básica', | ||
| 27 | 'menu.list.card-list': 'Lista de Card', | ||
| 28 | 'menu.list.search-list': 'Lista de Busca', | ||
| 29 | 'menu.list.search-list.articles': 'Lista de Busca(artigos)', | ||
| 30 | 'menu.list.search-list.projects': 'Lista de Busca(projetos)', | ||
| 31 | 'menu.list.search-list.applications': 'Lista de Busca(aplicações)', | ||
| 32 | 'menu.profile': 'Perfil', | ||
| 33 | 'menu.profile.basic': 'Perfil Básico', | ||
| 34 | 'menu.profile.advanced': 'Perfil Avançado', | ||
| 35 | 'menu.result': 'Resultado', | ||
| 36 | 'menu.result.success': 'Sucesso', | ||
| 37 | 'menu.result.fail': 'Falha', | ||
| 38 | 'menu.exception': 'Exceção', | ||
| 39 | 'menu.exception.not-permission': '403', | ||
| 40 | 'menu.exception.not-find': '404', | ||
| 41 | 'menu.exception.server-error': '500', | ||
| 42 | 'menu.exception.trigger': 'Disparar', | ||
| 43 | 'menu.account': 'Conta', | ||
| 44 | 'menu.account.center': 'Central da Conta', | ||
| 45 | 'menu.account.settings': 'Configurar Conta', | ||
| 46 | 'menu.account.trigger': 'Disparar Erro', | ||
| 47 | 'menu.account.logout': 'Sair', | ||
| 48 | 'menu.editor': 'Graphic Editor', | ||
| 49 | 'menu.editor.flow': 'Flow Editor', | ||
| 50 | 'menu.editor.mind': 'Mind Editor', | ||
| 51 | 'menu.editor.koni': 'Koni Editor', | ||
| 52 | }; |
src/locales/pt-BR/pwa.js
0 → 100644
| 1 | export default { | ||
| 2 | 'app.pwa.offline': 'Você está offline agora', | ||
| 3 | 'app.pwa.serviceworker.updated': 'Novo conteúdo está disponível', | ||
| 4 | 'app.pwa.serviceworker.updated.hint': | ||
| 5 | 'Por favor, pressione o botão "Atualizar" para recarregar a página atual', | ||
| 6 | 'app.pwa.serviceworker.updated.ok': 'Atualizar', | ||
| 7 | }; |
src/locales/pt-BR/settingDrawer.js
0 → 100644
| 1 | export default { | ||
| 2 | 'app.setting.pagestyle': 'Configuração de estilo da página', | ||
| 3 | 'app.setting.pagestyle.dark': 'Dark style', | ||
| 4 | 'app.setting.pagestyle.light': 'Light style', | ||
| 5 | 'app.setting.content-width': 'Largura do conteúdo', | ||
| 6 | 'app.setting.content-width.fixed': 'Fixo', | ||
| 7 | 'app.setting.content-width.fluid': 'Fluido', | ||
| 8 | 'app.setting.themecolor': 'Cor do Tema', | ||
| 9 | 'app.setting.themecolor.dust': 'Dust Red', | ||
| 10 | 'app.setting.themecolor.volcano': 'Volcano', | ||
| 11 | 'app.setting.themecolor.sunset': 'Sunset Orange', | ||
| 12 | 'app.setting.themecolor.cyan': 'Cyan', | ||
| 13 | 'app.setting.themecolor.green': 'Polar Green', | ||
| 14 | 'app.setting.themecolor.daybreak': 'Daybreak Blue (default)', | ||
| 15 | 'app.setting.themecolor.geekblue': 'Geek Glue', | ||
| 16 | 'app.setting.themecolor.purple': 'Golden Purple', | ||
| 17 | 'app.setting.navigationmode': 'Modo de Navegação', | ||
| 18 | 'app.setting.sidemenu': 'Layout do Menu Lateral', | ||
| 19 | 'app.setting.topmenu': 'Layout do Menu Superior', | ||
| 20 | 'app.setting.fixedheader': 'Cabeçalho fixo', | ||
| 21 | 'app.setting.fixedsidebar': 'Barra lateral fixa', | ||
| 22 | 'app.setting.fixedsidebar.hint': 'Funciona no layout do menu lateral', | ||
| 23 | 'app.setting.hideheader': 'Esconder o cabeçalho quando rolar', | ||
| 24 | 'app.setting.hideheader.hint': 'Funciona quando o esconder cabeçalho está abilitado', | ||
| 25 | 'app.setting.othersettings': 'Outras configurações', | ||
| 26 | 'app.setting.weakmode': 'Weak Mode', | ||
| 27 | 'app.setting.copy': 'Copiar Configuração', | ||
| 28 | 'app.setting.copyinfo': | ||
| 29 | 'copiado com sucesso,por favor trocar o defaultSettings em src/models/setting.js', | ||
| 30 | 'app.setting.production.hint': | ||
| 31 | 'O painel de configuração apenas é exibido no ambiente de desenvolvimento, por favor modifique manualmente o', | ||
| 32 | }; |
src/locales/pt-BR/settings.js
0 → 100644
| 1 | export default { | ||
| 2 | 'app.settings.menuMap.basic': 'Configurações Básicas', | ||
| 3 | 'app.settings.menuMap.security': 'Configurações de Segurança', | ||
| 4 | 'app.settings.menuMap.binding': 'Vinculação de Conta', | ||
| 5 | 'app.settings.menuMap.notification': 'Mensagens de Notificação', | ||
| 6 | 'app.settings.basic.avatar': 'Avatar', | ||
| 7 | 'app.settings.basic.change-avatar': 'Alterar avatar', | ||
| 8 | 'app.settings.basic.email': 'Email', | ||
| 9 | 'app.settings.basic.email-message': 'Por favor insira seu email!', | ||
| 10 | 'app.settings.basic.nickname': 'Nome de usuário', | ||
| 11 | 'app.settings.basic.nickname-message': 'Por favor insira seu nome de usuário!', | ||
| 12 | 'app.settings.basic.profile': 'Perfil pessoal', | ||
| 13 | 'app.settings.basic.profile-message': 'Por favor insira seu perfil pessoal!', | ||
| 14 | 'app.settings.basic.profile-placeholder': 'Breve introdução sua', | ||
| 15 | 'app.settings.basic.country': 'País/Região', | ||
| 16 | 'app.settings.basic.country-message': 'Por favor insira país!', | ||
| 17 | 'app.settings.basic.geographic': 'Província, estado ou cidade', | ||
| 18 | 'app.settings.basic.geographic-message': 'Por favor insira suas informações geográficas!', | ||
| 19 | 'app.settings.basic.address': 'Endereço', | ||
| 20 | 'app.settings.basic.address-message': 'Por favor insira seu endereço!', | ||
| 21 | 'app.settings.basic.phone': 'Número de telefone', | ||
| 22 | 'app.settings.basic.phone-message': 'Por favor insira seu número de telefone!', | ||
| 23 | 'app.settings.basic.update': 'Atualizar Informações', | ||
| 24 | 'app.settings.security.strong': 'Forte', | ||
| 25 | 'app.settings.security.medium': 'Média', | ||
| 26 | 'app.settings.security.weak': 'Fraca', | ||
| 27 | 'app.settings.security.password': 'Senha da Conta', | ||
| 28 | 'app.settings.security.password-description': 'Força da senha', | ||
| 29 | 'app.settings.security.phone': 'Telefone de Seguraça', | ||
| 30 | 'app.settings.security.phone-description': 'Telefone vinculado', | ||
| 31 | 'app.settings.security.question': 'Pergunta de Segurança', | ||
| 32 | 'app.settings.security.question-description': | ||
| 33 | 'A pergunta de segurança não está definida e a política de segurança pode proteger efetivamente a segurança da conta', | ||
| 34 | 'app.settings.security.email': 'Email de Backup', | ||
| 35 | 'app.settings.security.email-description': 'Email vinculado', | ||
| 36 | 'app.settings.security.mfa': 'Dispositivo MFA', | ||
| 37 | 'app.settings.security.mfa-description': | ||
| 38 | 'O dispositivo MFA não vinculado, após a vinculação, pode ser confirmado duas vezes', | ||
| 39 | 'app.settings.security.modify': 'Modificar', | ||
| 40 | 'app.settings.security.set': 'Atribuir', | ||
| 41 | 'app.settings.security.bind': 'Vincular', | ||
| 42 | 'app.settings.binding.taobao': 'Vincular Taobao', | ||
| 43 | 'app.settings.binding.taobao-description': 'Atualmente não vinculado à conta Taobao', | ||
| 44 | 'app.settings.binding.alipay': 'Vincular Alipay', | ||
| 45 | 'app.settings.binding.alipay-description': 'Atualmente não vinculado à conta Alipay', | ||
| 46 | 'app.settings.binding.dingding': 'Vincular DingTalk', | ||
| 47 | 'app.settings.binding.dingding-description': 'Atualmente não vinculado à conta DingTalk', | ||
| 48 | 'app.settings.binding.bind': 'Vincular', | ||
| 49 | 'app.settings.notification.password': 'Senha da Conta', | ||
| 50 | 'app.settings.notification.password-description': | ||
| 51 | 'Mensagens de outros usuários serão notificadas na forma de uma estação de letra', | ||
| 52 | 'app.settings.notification.messages': 'Mensagens de Sistema', | ||
| 53 | 'app.settings.notification.messages-description': | ||
| 54 | 'Mensagens de sistema serão notificadas na forma de uma estação de letra', | ||
| 55 | 'app.settings.notification.todo': 'Notificação de To-do', | ||
| 56 | 'app.settings.notification.todo-description': | ||
| 57 | 'A lista de to-do será notificada na forma de uma estação de letra', | ||
| 58 | 'app.settings.open': 'Aberto', | ||
| 59 | 'app.settings.close': 'Fechado', | ||
| 60 | }; |
src/locales/zh-CN.js
0 → 100644
| 1 | import component from './zh-CN/component'; | ||
| 2 | import globalHeader from './zh-CN/globalHeader'; | ||
| 3 | import menu from './zh-CN/menu'; | ||
| 4 | import pwa from './zh-CN/pwa'; | ||
| 5 | import settingDrawer from './zh-CN/settingDrawer'; | ||
| 6 | import settings from './zh-CN/settings'; | ||
| 7 | export default { | ||
| 8 | 'navBar.lang': '语言', | ||
| 9 | 'layout.user.link.help': '帮助', | ||
| 10 | 'layout.user.link.privacy': '隐私', | ||
| 11 | 'layout.user.link.terms': '条款', | ||
| 12 | 'app.preview.down.block': '下载此页面到本地项目', | ||
| 13 | 'app.welcome.link.fetch-blocks': '获取全部区块', | ||
| 14 | 'app.welcome.link.block-list': '基于 block 开发,快速构建标准页面', | ||
| 15 | ...globalHeader, | ||
| 16 | ...menu, | ||
| 17 | ...settingDrawer, | ||
| 18 | ...settings, | ||
| 19 | ...pwa, | ||
| 20 | ...component, | ||
| 21 | }; |
src/locales/zh-CN/component.js
0 → 100644
src/locales/zh-CN/globalHeader.js
0 → 100644
| 1 | export default { | ||
| 2 | 'component.globalHeader.search': '站内搜索', | ||
| 3 | 'component.globalHeader.search.example1': '搜索提示一', | ||
| 4 | 'component.globalHeader.search.example2': '搜索提示二', | ||
| 5 | 'component.globalHeader.search.example3': '搜索提示三', | ||
| 6 | 'component.globalHeader.help': '使用文档', | ||
| 7 | 'component.globalHeader.notification': '通知', | ||
| 8 | 'component.globalHeader.notification.empty': '你已查看所有通知', | ||
| 9 | 'component.globalHeader.message': '消息', | ||
| 10 | 'component.globalHeader.message.empty': '您已读完所有消息', | ||
| 11 | 'component.globalHeader.event': '待办', | ||
| 12 | 'component.globalHeader.event.empty': '你已完成所有待办', | ||
| 13 | 'component.noticeIcon.clear': '清空', | ||
| 14 | 'component.noticeIcon.cleared': '清空了', | ||
| 15 | 'component.noticeIcon.empty': '暂无数据', | ||
| 16 | 'component.noticeIcon.view-more': '查看更多', | ||
| 17 | }; |
src/locales/zh-CN/menu.js
0 → 100644
| 1 | export default { | ||
| 2 | 'menu.appliction': '应用列表', | ||
| 3 | 'menu.info': '应用详情', | ||
| 4 | 'menu.login': '登录', | ||
| 5 | 'menu.risk': '风险管理', | ||
| 6 | 'menu.event': '事件管理', | ||
| 7 | 'menu.data': '数据管理', | ||
| 8 | 'menu.system': '系统管理', | ||
| 9 | 'menu.system.account': '账号管理', | ||
| 10 | 'menu.system.role': '角色管理', | ||
| 11 | 'menu.system.menu': '菜单管理', | ||
| 12 | 'menu.dataScreen': '数智大屏', | ||
| 13 | }; |
src/locales/zh-CN/pwa.js
0 → 100644
src/locales/zh-CN/settingDrawer.js
0 → 100644
| 1 | export default { | ||
| 2 | 'app.setting.pagestyle': '整体风格设置', | ||
| 3 | 'app.setting.pagestyle.dark': '暗色菜单风格', | ||
| 4 | 'app.setting.pagestyle.light': '亮色菜单风格', | ||
| 5 | 'app.setting.content-width': '内容区域宽度', | ||
| 6 | 'app.setting.content-width.fixed': '定宽', | ||
| 7 | 'app.setting.content-width.fluid': '流式', | ||
| 8 | 'app.setting.themecolor': '主题色', | ||
| 9 | 'app.setting.themecolor.dust': '薄暮', | ||
| 10 | 'app.setting.themecolor.volcano': '火山', | ||
| 11 | 'app.setting.themecolor.sunset': '日暮', | ||
| 12 | 'app.setting.themecolor.cyan': '明青', | ||
| 13 | 'app.setting.themecolor.green': '极光绿', | ||
| 14 | 'app.setting.themecolor.daybreak': '拂晓蓝(默认)', | ||
| 15 | 'app.setting.themecolor.geekblue': '极客蓝', | ||
| 16 | 'app.setting.themecolor.purple': '酱紫', | ||
| 17 | 'app.setting.navigationmode': '导航模式', | ||
| 18 | 'app.setting.sidemenu': '侧边菜单布局', | ||
| 19 | 'app.setting.topmenu': '顶部菜单布局', | ||
| 20 | 'app.setting.fixedheader': '固定 Header', | ||
| 21 | 'app.setting.fixedsidebar': '固定侧边菜单', | ||
| 22 | 'app.setting.fixedsidebar.hint': '侧边菜单布局时可配置', | ||
| 23 | 'app.setting.hideheader': '下滑时隐藏 Header', | ||
| 24 | 'app.setting.hideheader.hint': '固定 Header 时可配置', | ||
| 25 | 'app.setting.othersettings': '其他设置', | ||
| 26 | 'app.setting.weakmode': '色弱模式', | ||
| 27 | 'app.setting.copy': '拷贝设置', | ||
| 28 | 'app.setting.copyinfo': '拷贝成功,请到 src/defaultSettings.js 中替换默认配置', | ||
| 29 | 'app.setting.production.hint': | ||
| 30 | '配置栏只在开发环境用于预览,生产环境不会展现,请拷贝后手动修改配置文件', | ||
| 31 | }; |
src/locales/zh-CN/settings.js
0 → 100644
| 1 | export default { | ||
| 2 | 'app.settings.menuMap.basic': '基本设置', | ||
| 3 | 'app.settings.menuMap.security': '安全设置', | ||
| 4 | 'app.settings.menuMap.binding': '账号绑定', | ||
| 5 | 'app.settings.menuMap.notification': '新消息通知', | ||
| 6 | 'app.settings.basic.avatar': '头像', | ||
| 7 | 'app.settings.basic.change-avatar': '更换头像', | ||
| 8 | 'app.settings.basic.email': '邮箱', | ||
| 9 | 'app.settings.basic.email-message': '请输入您的邮箱!', | ||
| 10 | 'app.settings.basic.nickname': '昵称', | ||
| 11 | 'app.settings.basic.nickname-message': '请输入您的昵称!', | ||
| 12 | 'app.settings.basic.profile': '个人简介', | ||
| 13 | 'app.settings.basic.profile-message': '请输入个人简介!', | ||
| 14 | 'app.settings.basic.profile-placeholder': '个人简介', | ||
| 15 | 'app.settings.basic.country': '国家/地区', | ||
| 16 | 'app.settings.basic.country-message': '请输入您的国家或地区!', | ||
| 17 | 'app.settings.basic.geographic': '所在省市', | ||
| 18 | 'app.settings.basic.geographic-message': '请输入您的所在省市!', | ||
| 19 | 'app.settings.basic.address': '街道地址', | ||
| 20 | 'app.settings.basic.address-message': '请输入您的街道地址!', | ||
| 21 | 'app.settings.basic.phone': '联系电话', | ||
| 22 | 'app.settings.basic.phone-message': '请输入您的联系电话!', | ||
| 23 | 'app.settings.basic.update': '更新基本信息', | ||
| 24 | 'app.settings.security.strong': '强', | ||
| 25 | 'app.settings.security.medium': '中', | ||
| 26 | 'app.settings.security.weak': '弱', | ||
| 27 | 'app.settings.security.password': '账户密码', | ||
| 28 | 'app.settings.security.password-description': '当前密码强度', | ||
| 29 | 'app.settings.security.phone': '密保手机', | ||
| 30 | 'app.settings.security.phone-description': '已绑定手机', | ||
| 31 | 'app.settings.security.question': '密保问题', | ||
| 32 | 'app.settings.security.question-description': '未设置密保问题,密保问题可有效保护账户安全', | ||
| 33 | 'app.settings.security.email': '备用邮箱', | ||
| 34 | 'app.settings.security.email-description': '已绑定邮箱', | ||
| 35 | 'app.settings.security.mfa': 'MFA 设备', | ||
| 36 | 'app.settings.security.mfa-description': '未绑定 MFA 设备,绑定后,可以进行二次确认', | ||
| 37 | 'app.settings.security.modify': '修改', | ||
| 38 | 'app.settings.security.set': '设置', | ||
| 39 | 'app.settings.security.bind': '绑定', | ||
| 40 | 'app.settings.binding.taobao': '绑定淘宝', | ||
| 41 | 'app.settings.binding.taobao-description': '当前未绑定淘宝账号', | ||
| 42 | 'app.settings.binding.alipay': '绑定支付宝', | ||
| 43 | 'app.settings.binding.alipay-description': '当前未绑定支付宝账号', | ||
| 44 | 'app.settings.binding.dingding': '绑定钉钉', | ||
| 45 | 'app.settings.binding.dingding-description': '当前未绑定钉钉账号', | ||
| 46 | 'app.settings.binding.bind': '绑定', | ||
| 47 | 'app.settings.notification.password': '账户密码', | ||
| 48 | 'app.settings.notification.password-description': '其他用户的消息将以站内信的形式通知', | ||
| 49 | 'app.settings.notification.messages': '系统消息', | ||
| 50 | 'app.settings.notification.messages-description': '系统消息将以站内信的形式通知', | ||
| 51 | 'app.settings.notification.todo': '待办任务', | ||
| 52 | 'app.settings.notification.todo-description': '待办任务将以站内信的形式通知', | ||
| 53 | 'app.settings.open': '开', | ||
| 54 | 'app.settings.close': '关', | ||
| 55 | }; |
src/locales/zh-TW.js
0 → 100644
| 1 | import component from './zh-TW/component'; | ||
| 2 | import globalHeader from './zh-TW/globalHeader'; | ||
| 3 | import menu from './zh-TW/menu'; | ||
| 4 | import pwa from './zh-TW/pwa'; | ||
| 5 | import settingDrawer from './zh-TW/settingDrawer'; | ||
| 6 | import settings from './zh-TW/settings'; | ||
| 7 | export default { | ||
| 8 | 'navBar.lang': '語言', | ||
| 9 | 'layout.user.link.help': '幫助', | ||
| 10 | 'layout.user.link.privacy': '隱私', | ||
| 11 | 'layout.user.link.terms': '條款', | ||
| 12 | 'app.preview.down.block': '下載此頁面到本地項目', | ||
| 13 | ...globalHeader, | ||
| 14 | ...menu, | ||
| 15 | ...settingDrawer, | ||
| 16 | ...settings, | ||
| 17 | ...pwa, | ||
| 18 | ...component, | ||
| 19 | }; |
src/locales/zh-TW/component.js
0 → 100644
src/locales/zh-TW/globalHeader.js
0 → 100644
| 1 | export default { | ||
| 2 | 'component.globalHeader.search': '站內搜索', | ||
| 3 | 'component.globalHeader.search.example1': '搜索提示壹', | ||
| 4 | 'component.globalHeader.search.example2': '搜索提示二', | ||
| 5 | 'component.globalHeader.search.example3': '搜索提示三', | ||
| 6 | 'component.globalHeader.help': '使用手冊', | ||
| 7 | 'component.globalHeader.notification': '通知', | ||
| 8 | 'component.globalHeader.notification.empty': '妳已查看所有通知', | ||
| 9 | 'component.globalHeader.message': '消息', | ||
| 10 | 'component.globalHeader.message.empty': '您已讀完所有消息', | ||
| 11 | 'component.globalHeader.event': '待辦', | ||
| 12 | 'component.globalHeader.event.empty': '妳已完成所有待辦', | ||
| 13 | 'component.noticeIcon.clear': '清空', | ||
| 14 | 'component.noticeIcon.cleared': '清空了', | ||
| 15 | 'component.noticeIcon.empty': '暫無資料', | ||
| 16 | 'component.noticeIcon.view-more': '查看更多', | ||
| 17 | }; |
src/locales/zh-TW/menu.js
0 → 100644
| 1 | export default { | ||
| 2 | 'menu.welcome': '歡迎', | ||
| 3 | 'menu.more-blocks': '更多區塊', | ||
| 4 | 'menu.home': '首頁', | ||
| 5 | 'menu.login': '登錄', | ||
| 6 | 'menu.admin': '权限', | ||
| 7 | 'menu.admin.sub-page': '二级管理页', | ||
| 8 | 'menu.exception.403': '403', | ||
| 9 | 'menu.exception.404': '404', | ||
| 10 | 'menu.exception.500': '500', | ||
| 11 | 'menu.register': '註冊', | ||
| 12 | 'menu.register.result': '註冊結果', | ||
| 13 | 'menu.dashboard': 'Dashboard', | ||
| 14 | 'menu.dashboard.analysis': '分析頁', | ||
| 15 | 'menu.dashboard.monitor': '監控頁', | ||
| 16 | 'menu.dashboard.workplace': '工作臺', | ||
| 17 | 'menu.form': '表單頁', | ||
| 18 | 'menu.form.basic-form': '基礎表單', | ||
| 19 | 'menu.form.step-form': '分步表單', | ||
| 20 | 'menu.form.step-form.info': '分步表單(填寫轉賬信息)', | ||
| 21 | 'menu.form.step-form.confirm': '分步表單(確認轉賬信息)', | ||
| 22 | 'menu.form.step-form.result': '分步表單(完成)', | ||
| 23 | 'menu.form.advanced-form': '高級表單', | ||
| 24 | 'menu.list': '列表頁', | ||
| 25 | 'menu.list.table-list': '查詢表格', | ||
| 26 | 'menu.list.basic-list': '標淮列表', | ||
| 27 | 'menu.list.card-list': '卡片列表', | ||
| 28 | 'menu.list.search-list': '搜索列表', | ||
| 29 | 'menu.list.search-list.articles': '搜索列表(文章)', | ||
| 30 | 'menu.list.search-list.projects': '搜索列表(項目)', | ||
| 31 | 'menu.list.search-list.applications': '搜索列表(應用)', | ||
| 32 | 'menu.profile': '詳情頁', | ||
| 33 | 'menu.profile.basic': '基礎詳情頁', | ||
| 34 | 'menu.profile.advanced': '高級詳情頁', | ||
| 35 | 'menu.result': '結果頁', | ||
| 36 | 'menu.result.success': '成功頁', | ||
| 37 | 'menu.result.fail': '失敗頁', | ||
| 38 | 'menu.account': '個人頁', | ||
| 39 | 'menu.account.center': '個人中心', | ||
| 40 | 'menu.account.settings': '個人設置', | ||
| 41 | 'menu.account.trigger': '觸發報錯', | ||
| 42 | 'menu.account.logout': '退出登錄', | ||
| 43 | 'menu.exception': '异常页', | ||
| 44 | 'menu.exception.not-permission': '403', | ||
| 45 | 'menu.exception.not-find': '404', | ||
| 46 | 'menu.exception.server-error': '500', | ||
| 47 | 'menu.exception.trigger': '触发错误', | ||
| 48 | 'menu.editor': '圖形編輯器', | ||
| 49 | 'menu.editor.flow': '流程編輯器', | ||
| 50 | 'menu.editor.mind': '腦圖編輯器', | ||
| 51 | 'menu.editor.koni': '拓撲編輯器', | ||
| 52 | }; |
src/locales/zh-TW/pwa.js
0 → 100644
src/locales/zh-TW/settingDrawer.js
0 → 100644
| 1 | export default { | ||
| 2 | 'app.setting.pagestyle': '整體風格設置', | ||
| 3 | 'app.setting.pagestyle.dark': '暗色菜單風格', | ||
| 4 | 'app.setting.pagestyle.light': '亮色菜單風格', | ||
| 5 | 'app.setting.content-width': '內容區域寬度', | ||
| 6 | 'app.setting.content-width.fixed': '定寬', | ||
| 7 | 'app.setting.content-width.fluid': '流式', | ||
| 8 | 'app.setting.themecolor': '主題色', | ||
| 9 | 'app.setting.themecolor.dust': '薄暮', | ||
| 10 | 'app.setting.themecolor.volcano': '火山', | ||
| 11 | 'app.setting.themecolor.sunset': '日暮', | ||
| 12 | 'app.setting.themecolor.cyan': '明青', | ||
| 13 | 'app.setting.themecolor.green': '極光綠', | ||
| 14 | 'app.setting.themecolor.daybreak': '拂曉藍(默認)', | ||
| 15 | 'app.setting.themecolor.geekblue': '極客藍', | ||
| 16 | 'app.setting.themecolor.purple': '醬紫', | ||
| 17 | 'app.setting.navigationmode': '導航模式', | ||
| 18 | 'app.setting.sidemenu': '側邊菜單布局', | ||
| 19 | 'app.setting.topmenu': '頂部菜單布局', | ||
| 20 | 'app.setting.fixedheader': '固定 Header', | ||
| 21 | 'app.setting.fixedsidebar': '固定側邊菜單', | ||
| 22 | 'app.setting.fixedsidebar.hint': '側邊菜單布局時可配置', | ||
| 23 | 'app.setting.hideheader': '下滑時隱藏 Header', | ||
| 24 | 'app.setting.hideheader.hint': '固定 Header 時可配置', | ||
| 25 | 'app.setting.othersettings': '其他設置', | ||
| 26 | 'app.setting.weakmode': '色弱模式', | ||
| 27 | 'app.setting.copy': '拷貝設置', | ||
| 28 | 'app.setting.copyinfo': '拷貝成功,請到 src/defaultSettings.js 中替換默認配置', | ||
| 29 | 'app.setting.production.hint': | ||
| 30 | '配置欄只在開發環境用於預覽,生產環境不會展現,請拷貝後手動修改配置文件', | ||
| 31 | }; |
src/locales/zh-TW/settings.js
0 → 100644
| 1 | export default { | ||
| 2 | 'app.settings.menuMap.basic': '基本設置', | ||
| 3 | 'app.settings.menuMap.security': '安全設置', | ||
| 4 | 'app.settings.menuMap.binding': '賬號綁定', | ||
| 5 | 'app.settings.menuMap.notification': '新消息通知', | ||
| 6 | 'app.settings.basic.avatar': '頭像', | ||
| 7 | 'app.settings.basic.change-avatar': '更換頭像', | ||
| 8 | 'app.settings.basic.email': '郵箱', | ||
| 9 | 'app.settings.basic.email-message': '請輸入您的郵箱!', | ||
| 10 | 'app.settings.basic.nickname': '昵稱', | ||
| 11 | 'app.settings.basic.nickname-message': '請輸入您的昵稱!', | ||
| 12 | 'app.settings.basic.profile': '個人簡介', | ||
| 13 | 'app.settings.basic.profile-message': '請輸入個人簡介!', | ||
| 14 | 'app.settings.basic.profile-placeholder': '個人簡介', | ||
| 15 | 'app.settings.basic.country': '國家/地區', | ||
| 16 | 'app.settings.basic.country-message': '請輸入您的國家或地區!', | ||
| 17 | 'app.settings.basic.geographic': '所在省市', | ||
| 18 | 'app.settings.basic.geographic-message': '請輸入您的所在省市!', | ||
| 19 | 'app.settings.basic.address': '街道地址', | ||
| 20 | 'app.settings.basic.address-message': '請輸入您的街道地址!', | ||
| 21 | 'app.settings.basic.phone': '聯系電話', | ||
| 22 | 'app.settings.basic.phone-message': '請輸入您的聯系電話!', | ||
| 23 | 'app.settings.basic.update': '更新基本信息', | ||
| 24 | 'app.settings.security.strong': '強', | ||
| 25 | 'app.settings.security.medium': '中', | ||
| 26 | 'app.settings.security.weak': '弱', | ||
| 27 | 'app.settings.security.password': '賬戶密碼', | ||
| 28 | 'app.settings.security.password-description': '當前密碼強度', | ||
| 29 | 'app.settings.security.phone': '密保手機', | ||
| 30 | 'app.settings.security.phone-description': '已綁定手機', | ||
| 31 | 'app.settings.security.question': '密保問題', | ||
| 32 | 'app.settings.security.question-description': '未設置密保問題,密保問題可有效保護賬戶安全', | ||
| 33 | 'app.settings.security.email': '備用郵箱', | ||
| 34 | 'app.settings.security.email-description': '已綁定郵箱', | ||
| 35 | 'app.settings.security.mfa': 'MFA 設備', | ||
| 36 | 'app.settings.security.mfa-description': '未綁定 MFA 設備,綁定後,可以進行二次確認', | ||
| 37 | 'app.settings.security.modify': '修改', | ||
| 38 | 'app.settings.security.set': '設置', | ||
| 39 | 'app.settings.security.bind': '綁定', | ||
| 40 | 'app.settings.binding.taobao': '綁定淘寶', | ||
| 41 | 'app.settings.binding.taobao-description': '當前未綁定淘寶賬號', | ||
| 42 | 'app.settings.binding.alipay': '綁定支付寶', | ||
| 43 | 'app.settings.binding.alipay-description': '當前未綁定支付寶賬號', | ||
| 44 | 'app.settings.binding.dingding': '綁定釘釘', | ||
| 45 | 'app.settings.binding.dingding-description': '當前未綁定釘釘賬號', | ||
| 46 | 'app.settings.binding.bind': '綁定', | ||
| 47 | 'app.settings.notification.password': '賬戶密碼', | ||
| 48 | 'app.settings.notification.password-description': '其他用戶的消息將以站內信的形式通知', | ||
| 49 | 'app.settings.notification.messages': '系統消息', | ||
| 50 | 'app.settings.notification.messages-description': '系統消息將以站內信的形式通知', | ||
| 51 | 'app.settings.notification.todo': '待辦任務', | ||
| 52 | 'app.settings.notification.todo-description': '待辦任務將以站內信的形式通知', | ||
| 53 | 'app.settings.open': '開', | ||
| 54 | 'app.settings.close': '關', | ||
| 55 | }; |
src/manifest.json
0 → 100644
| 1 | { | ||
| 2 | "name": "Ant Design Pro", | ||
| 3 | "short_name": "Ant Design Pro", | ||
| 4 | "display": "standalone", | ||
| 5 | "start_url": "./?utm_source=homescreen", | ||
| 6 | "theme_color": "#002140", | ||
| 7 | "background_color": "#001529", | ||
| 8 | "icons": [ | ||
| 9 | { | ||
| 10 | "src": "icons/icon-192x192.png", | ||
| 11 | "sizes": "192x192" | ||
| 12 | }, | ||
| 13 | { | ||
| 14 | "src": "icons/icon-128x128.png", | ||
| 15 | "sizes": "128x128" | ||
| 16 | }, | ||
| 17 | { | ||
| 18 | "src": "icons/icon-512x512.png", | ||
| 19 | "sizes": "512x512" | ||
| 20 | } | ||
| 21 | ] | ||
| 22 | } |
src/models/global.js
0 → 100644
| 1 | import { queryNotices } from '@/services/user'; | ||
| 2 | const GlobalModel = { | ||
| 3 | namespace: 'global', | ||
| 4 | state: { | ||
| 5 | collapsed: false, | ||
| 6 | loading: false, | ||
| 7 | urlFileExport: '', | ||
| 8 | dataModal: { | ||
| 9 | modalType: '', | ||
| 10 | modalShow: false, | ||
| 11 | modalData: {}, | ||
| 12 | }, | ||
| 13 | preImgDataModal: { | ||
| 14 | modalType: '', | ||
| 15 | modalShow: false, | ||
| 16 | modalData: {}, | ||
| 17 | }, | ||
| 18 | }, | ||
| 19 | effects: {}, | ||
| 20 | reducers: { | ||
| 21 | changeLayoutCollapsed( | ||
| 22 | state = { | ||
| 23 | notices: [], | ||
| 24 | collapsed: true, | ||
| 25 | }, | ||
| 26 | { payload }, | ||
| 27 | ) { | ||
| 28 | return { ...state, collapsed: payload }; | ||
| 29 | }, | ||
| 30 | }, | ||
| 31 | subscriptions: { | ||
| 32 | setup({ history, dispatch }) { | ||
| 33 | // Subscribe history(url) change, trigger `load` action if pathname is `/` | ||
| 34 | history.listen(({ pathname, search }) => { | ||
| 35 | // 路由发生变化的时候切换菜单 | ||
| 36 | const whiteList = ['/user/login']; | ||
| 37 | |||
| 38 | if (!whiteList.includes(pathname)) { | ||
| 39 | // 获取用户信息 | ||
| 40 | dispatch({ type: 'user/fetchCurrent' }); | ||
| 41 | } | ||
| 42 | }); | ||
| 43 | }, | ||
| 44 | }, | ||
| 45 | }; | ||
| 46 | export default GlobalModel; |
src/models/login.js
0 → 100644
| 1 | import { queryLogin, loginOut } from '@/services/login'; | ||
| 2 | import { getUserInfo, getBosUserList } from '@/services/user'; | ||
| 3 | import { message } from 'antd'; | ||
| 4 | import { history } from 'umi'; | ||
| 5 | import md5 from 'blueimp-md5'; | ||
| 6 | import defaultSettings from '../../config/defaultSettings'; | ||
| 7 | import { getDataMenus } from '@/utils/menu'; | ||
| 8 | const { tokenKey, md5Key } = defaultSettings; | ||
| 9 | const Model = { | ||
| 10 | namespace: 'login', | ||
| 11 | state: { | ||
| 12 | status: undefined, | ||
| 13 | }, | ||
| 14 | effects: { | ||
| 15 | //退出登录 | ||
| 16 | *logout({ payload }, { call, put, select }) { | ||
| 17 | try { | ||
| 18 | const res = yield call(loginOut); | ||
| 19 | if (res.code === 0 && res.data) { | ||
| 20 | if (!payload) { | ||
| 21 | message.success('退出成功'); | ||
| 22 | } | ||
| 23 | localStorage.removeItem(tokenKey); | ||
| 24 | setTimeout(() => { | ||
| 25 | window.location.href = '/user/login'; | ||
| 26 | }, 500); | ||
| 27 | } | ||
| 28 | } catch (err) { | ||
| 29 | console.error(err); | ||
| 30 | } | ||
| 31 | }, | ||
| 32 | //登录 | ||
| 33 | *login({ payload }, { call, put }) { | ||
| 34 | try { | ||
| 35 | const res = yield call(queryLogin, payload); | ||
| 36 | if (res.code === 0) { | ||
| 37 | localStorage.setItem(tokenKey, res.data); | ||
| 38 | // const userinfo = yield call(getUserInfo); | ||
| 39 | // const { permissionVos = [] } = userinfo.data; | ||
| 40 | // const dataMenus = getDataMenus(permissionVos); | ||
| 41 | // console.log(dataMenus); | ||
| 42 | // if (dataMenus.length) { | ||
| 43 | // history.replace(dataMenus[0].path); | ||
| 44 | // } else { | ||
| 45 | // history.replace('/'); | ||
| 46 | // } | ||
| 47 | history.replace('/'); | ||
| 48 | message.success('登录成功'); | ||
| 49 | } | ||
| 50 | } catch (err) { | ||
| 51 | console.error(err); | ||
| 52 | } | ||
| 53 | }, | ||
| 54 | }, | ||
| 55 | reducers: { | ||
| 56 | changeLoginStatus(state, { payload }) { | ||
| 57 | return { ...state, status: payload.status, type: payload.type }; | ||
| 58 | }, | ||
| 59 | }, | ||
| 60 | }; | ||
| 61 | export default Model; |
src/models/setting.js
0 → 100644
| 1 | import defaultSettings from '../../config/defaultSettings'; | ||
| 2 | |||
| 3 | const updateColorWeak = colorWeak => { | ||
| 4 | const root = document.getElementById('root'); | ||
| 5 | |||
| 6 | if (root) { | ||
| 7 | root.className = colorWeak ? 'colorWeak' : ''; | ||
| 8 | } | ||
| 9 | }; | ||
| 10 | |||
| 11 | const SettingModel = { | ||
| 12 | namespace: 'settings', | ||
| 13 | state: defaultSettings, | ||
| 14 | reducers: { | ||
| 15 | changeSetting(state = defaultSettings, { payload }) { | ||
| 16 | const { colorWeak, contentWidth } = payload; | ||
| 17 | |||
| 18 | if (state.contentWidth !== contentWidth && window.dispatchEvent) { | ||
| 19 | window.dispatchEvent(new Event('resize')); | ||
| 20 | } | ||
| 21 | |||
| 22 | updateColorWeak(!!colorWeak); | ||
| 23 | return { ...state, ...payload }; | ||
| 24 | }, | ||
| 25 | }, | ||
| 26 | }; | ||
| 27 | export default SettingModel; |
src/models/user.js
0 → 100644
| 1 | import { getUserInfo, updatePassword } from '@/services/user'; | ||
| 2 | import { getDataMenus } from '@/utils/menu'; | ||
| 3 | import { message } from 'antd'; | ||
| 4 | const UserModel = { | ||
| 5 | namespace: 'user', | ||
| 6 | state: { | ||
| 7 | currentUser: { | ||
| 8 | admin: {}, | ||
| 9 | dataMenus: [], | ||
| 10 | username: '', | ||
| 11 | }, | ||
| 12 | userAuths: [], // 权限 | ||
| 13 | dataModal: { | ||
| 14 | modalType: '', | ||
| 15 | modalShow: false, | ||
| 16 | modalData: {}, | ||
| 17 | }, | ||
| 18 | }, | ||
| 19 | effects: { | ||
| 20 | *fetchCurrent(_, { call, put, select }) { | ||
| 21 | const { | ||
| 22 | currentUser, | ||
| 23 | currentUser: { username }, | ||
| 24 | } = yield select(state => state.user); | ||
| 25 | if (!currentUser || !username) { | ||
| 26 | try { | ||
| 27 | const res = yield call(getUserInfo); | ||
| 28 | // data.dataMenus = getDataMenus(data.permissionVos); | ||
| 29 | if (res.code === 0) { | ||
| 30 | res.data.menus = [ | ||
| 31 | { | ||
| 32 | children: [], | ||
| 33 | id: 999999, | ||
| 34 | parentId: 0, | ||
| 35 | resourceCode: 'Home', | ||
| 36 | resourceNodeType: '1', | ||
| 37 | title: '数智大屏', | ||
| 38 | }, | ||
| 39 | ...(res.data.menus || []), | ||
| 40 | { | ||
| 41 | resourceCode: '404', | ||
| 42 | }, | ||
| 43 | ]; | ||
| 44 | yield put({ type: 'saveCurrentUser', payload: res.data }); | ||
| 45 | } | ||
| 46 | } catch (err) { | ||
| 47 | console.error(err, 'err'); | ||
| 48 | } | ||
| 49 | } | ||
| 50 | }, | ||
| 51 | /* 修改密码 */ | ||
| 52 | *updatePassword({ payload }, { call, put, select }) { | ||
| 53 | try { | ||
| 54 | const res = yield call(updatePassword, payload); | ||
| 55 | if (res.code === 0) { | ||
| 56 | message.success('修改成功'); | ||
| 57 | yield put({ type: 'cancelModal' }); | ||
| 58 | yield put({ type: 'login/logout', payload: { message: 1 } }); | ||
| 59 | } | ||
| 60 | } catch (err) { | ||
| 61 | console.error(err); | ||
| 62 | } | ||
| 63 | }, | ||
| 64 | }, | ||
| 65 | reducers: { | ||
| 66 | changeState(state, { payload }) { | ||
| 67 | return { | ||
| 68 | ...state, | ||
| 69 | ...payload, | ||
| 70 | }; | ||
| 71 | }, | ||
| 72 | cancelModal(state, { payload }) { | ||
| 73 | return { | ||
| 74 | ...state, | ||
| 75 | dataModal: { | ||
| 76 | modalType: '', | ||
| 77 | modalShow: false, | ||
| 78 | modalData: {}, | ||
| 79 | }, | ||
| 80 | }; | ||
| 81 | }, | ||
| 82 | saveCurrentUser(state, { payload }) { | ||
| 83 | return { | ||
| 84 | ...state, | ||
| 85 | currentUser: payload || {}, | ||
| 86 | // userAuths: payload.authorities.map(_ => _.code), | ||
| 87 | }; | ||
| 88 | }, | ||
| 89 | }, | ||
| 90 | }; | ||
| 91 | export default UserModel; |
src/pages/404.jsx
0 → 100644
| 1 | import { Button, Result } from 'antd'; | ||
| 2 | import React from 'react'; | ||
| 3 | import { history } from 'umi'; | ||
| 4 | |||
| 5 | const NoFoundPage = () => ( | ||
| 6 | <Result | ||
| 7 | status="404" | ||
| 8 | title="404" | ||
| 9 | subTitle="Sorry, the page you visited does not exist." | ||
| 10 | extra={ | ||
| 11 | <Button type="primary" onClick={() => history.push('/')}> | ||
| 12 | Back Home | ||
| 13 | </Button> | ||
| 14 | } | ||
| 15 | /> | ||
| 16 | ); | ||
| 17 | |||
| 18 | export default NoFoundPage; |
src/pages/Application/Info.js
0 → 100644
This diff is collapsed.
Click to expand it.
src/pages/Application/ModalSetAuth.js
0 → 100644
| 1 | /** | ||
| 2 | * Author: llw | ||
| 3 | * Date: 2020.7.20 | ||
| 4 | * Description: [设置权限弹框] | ||
| 5 | */ | ||
| 6 | import React, { useEffect, useState } from 'react'; | ||
| 7 | import { Drawer, Radio, Form, Select, Input, Button } from 'antd'; | ||
| 8 | |||
| 9 | const { Option } = Select; | ||
| 10 | const formItemLayout = {labelCol: { span: 4 }, wrapperCol: { span: 20 }}; | ||
| 11 | |||
| 12 | const ModalSetAuth = props => { | ||
| 13 | const [menuType, setType] = useState(1); | ||
| 14 | const [form] = Form.useForm(); | ||
| 15 | let { | ||
| 16 | handleCancelModal, | ||
| 17 | handleAuthSetOk, | ||
| 18 | dataMenuList = [], | ||
| 19 | dataModal: { | ||
| 20 | modalType, | ||
| 21 | modalShow, | ||
| 22 | modalData, | ||
| 23 | modalData: { name, code, type, url, icon, parentCode, isEdit } | ||
| 24 | } | ||
| 25 | } = props; | ||
| 26 | |||
| 27 | dataMenuList = code ? dataMenuList.filter(item => code !== item.code) : dataMenuList; | ||
| 28 | |||
| 29 | /* 重置type */ | ||
| 30 | useEffect(() => { | ||
| 31 | if (modalType === "AUTH_SET_MODAL" && modalShow) { | ||
| 32 | setType(type || 1); | ||
| 33 | setTimeout(() => { | ||
| 34 | form.resetFields(); | ||
| 35 | form.setFieldsValue({ | ||
| 36 | name, | ||
| 37 | code, | ||
| 38 | url, | ||
| 39 | icon, | ||
| 40 | parentCode, | ||
| 41 | type: type || 1, | ||
| 42 | }); | ||
| 43 | }, 100) | ||
| 44 | } | ||
| 45 | }, [modalType, modalShow]) | ||
| 46 | |||
| 47 | /* 点击保存 */ | ||
| 48 | const handleSave = () => { | ||
| 49 | form.validateFields().then(values => { | ||
| 50 | handleAuthSetOk({ | ||
| 51 | ...modalData, | ||
| 52 | ...values, | ||
| 53 | isEdit | ||
| 54 | }); | ||
| 55 | }) | ||
| 56 | }; | ||
| 57 | |||
| 58 | /* 选择菜单类型 */ | ||
| 59 | const handleChangeRadio = (value) => { | ||
| 60 | form.resetFields(); | ||
| 61 | setType(value); | ||
| 62 | form.setFieldsValue({type: value}); | ||
| 63 | }; | ||
| 64 | |||
| 65 | return ( | ||
| 66 | <Drawer | ||
| 67 | title="权限设置" | ||
| 68 | placement="right" | ||
| 69 | width={600} | ||
| 70 | maskClosable={false} | ||
| 71 | onClose={handleCancelModal} | ||
| 72 | visible={modalType === 'AUTH_SET_MODAL' && modalShow} | ||
| 73 | footer={ | ||
| 74 | <div | ||
| 75 | style={{ | ||
| 76 | textAlign: 'right', | ||
| 77 | }} | ||
| 78 | > | ||
| 79 | <Button onClick={handleCancelModal} className="mr-10">取消</Button> | ||
| 80 | <Button onClick={handleSave} type="primary">保存</Button> | ||
| 81 | </div> | ||
| 82 | } | ||
| 83 | > | ||
| 84 | <Form | ||
| 85 | form={form} | ||
| 86 | {...formItemLayout} | ||
| 87 | name="auth_set_modal" | ||
| 88 | initialValues={{ type: 1 }} | ||
| 89 | > | ||
| 90 | <Form.Item | ||
| 91 | name="type" | ||
| 92 | label="菜单类型" | ||
| 93 | > | ||
| 94 | <Radio.Group buttonStyle="solid" onChange={(e) => handleChangeRadio(e.target.value)}> | ||
| 95 | <Radio.Button disabled={(isEdit && type !== 1) ? true : false} value={1}>一级菜单</Radio.Button> | ||
| 96 | <Radio.Button disabled={(isEdit && type !== 2) ? true : false} value={2}>子菜单</Radio.Button> | ||
| 97 | <Radio.Button disabled={(isEdit && type !== 3) ? true : false} value={3}>按钮</Radio.Button> | ||
| 98 | </Radio.Group> | ||
| 99 | </Form.Item> | ||
| 100 | { | ||
| 101 | menuType !== 1 && <Form.Item | ||
| 102 | name="parentCode" | ||
| 103 | label={menuType === 2 ? "上级菜单" : "包含菜单"} | ||
| 104 | rules={ | ||
| 105 | [{required: true, message: menuType === 2 ? "请选择上级菜单" : "请选择包含该按钮的菜单"}] | ||
| 106 | } | ||
| 107 | > | ||
| 108 | <Select | ||
| 109 | showSearch | ||
| 110 | placeholder={menuType === 2 ? '请选择上级菜单' : '请选择包含该按钮的菜单'} | ||
| 111 | optionFilterProp="children" | ||
| 112 | filterOption={(input, option) => | ||
| 113 | option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0 | ||
| 114 | } | ||
| 115 | > | ||
| 116 | { | ||
| 117 | dataMenuList.map(item => { | ||
| 118 | return ( | ||
| 119 | <Option key={item.code} value={item.code}>{item.name}</Option> | ||
| 120 | ) | ||
| 121 | }) | ||
| 122 | } | ||
| 123 | </Select> | ||
| 124 | </Form.Item> | ||
| 125 | } | ||
| 126 | <Form.Item | ||
| 127 | name="name" | ||
| 128 | label={menuType === 3 ? "按钮名称" : "菜单名称"} | ||
| 129 | rules={ | ||
| 130 | [ | ||
| 131 | {required: true, message: menuType === 3 ? '请输入按钮名称' : '请输入菜单名称'}, | ||
| 132 | {min: 2, max: 15, message: '名称长度2~15个字符'} | ||
| 133 | ] | ||
| 134 | } | ||
| 135 | > | ||
| 136 | <Input maxLength={15} placeholder={menuType === 3 ? "请输入按钮名称" : "请输入菜单名称"} /> | ||
| 137 | </Form.Item> | ||
| 138 | <Form.Item | ||
| 139 | name="code" | ||
| 140 | label={menuType === 3 ? "按钮code" : "菜单code"} | ||
| 141 | rules={ | ||
| 142 | [{required: true, message: menuType === 3 ? '请输入按钮code' : '请输入菜单code'}] | ||
| 143 | } | ||
| 144 | > | ||
| 145 | <Input maxLength={20} placeholder={menuType === 3 ? "请输入按钮code" : "请输入菜单code"} /> | ||
| 146 | </Form.Item> | ||
| 147 | { | ||
| 148 | menuType !== 3 && <> | ||
| 149 | <Form.Item | ||
| 150 | name="url" | ||
| 151 | label="菜单URL" | ||
| 152 | rules={ | ||
| 153 | [{required: true, message: '请输入菜单URL'}] | ||
| 154 | } | ||
| 155 | > | ||
| 156 | <Input placeholder="请输入菜单URL" /> | ||
| 157 | </Form.Item> | ||
| 158 | <Form.Item | ||
| 159 | name="icon" | ||
| 160 | label="菜单Icon" | ||
| 161 | > | ||
| 162 | <Input placeholder="请输入菜单Icon" /> | ||
| 163 | </Form.Item> | ||
| 164 | </> | ||
| 165 | } | ||
| 166 | </Form> | ||
| 167 | </Drawer> | ||
| 168 | ) | ||
| 169 | }; | ||
| 170 | |||
| 171 | export default ModalSetAuth; | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
src/pages/Application/index.js
0 → 100644
| 1 | /** | ||
| 2 | * Author: llw | ||
| 3 | * Date: 2020.7.16 | ||
| 4 | * Description: [应用列表] | ||
| 5 | */ | ||
| 6 | import React, { useEffect } from 'react'; | ||
| 7 | import { connect, Link } from 'umi'; | ||
| 8 | import { Card, Form, DatePicker, Input, Button, Table, Divider, Modal } from 'antd'; | ||
| 9 | import { ExclamationCircleOutlined } from '@ant-design/icons'; | ||
| 10 | import { paginations } from '@/constants'; | ||
| 11 | import moment from 'moment'; | ||
| 12 | |||
| 13 | const { RangePicker } = DatePicker; | ||
| 14 | const FormItem = Form.Item; | ||
| 15 | |||
| 16 | /* SearchForm */ | ||
| 17 | const SearchForm = props => { | ||
| 18 | const [form] = Form.useForm(); | ||
| 19 | const { | ||
| 20 | dataSearch, | ||
| 21 | handleReset, | ||
| 22 | handleFinish, | ||
| 23 | dataSearch: { createTimeBegin, createTimeEnd } | ||
| 24 | } = props; | ||
| 25 | |||
| 26 | useEffect(() => { | ||
| 27 | form.setFieldsValue({ | ||
| 28 | ...dataSearch, | ||
| 29 | createTime: [createTimeBegin ? moment(createTimeBegin) : undefined, createTimeEnd ? moment(createTimeEnd) : undefined] | ||
| 30 | }); | ||
| 31 | }, [dataSearch]); | ||
| 32 | |||
| 33 | /* 点击搜索 */ | ||
| 34 | const onFinish = (values) => { | ||
| 35 | handleFinish(values); | ||
| 36 | }; | ||
| 37 | |||
| 38 | /* 点击重置 */ | ||
| 39 | const onReset = () => { | ||
| 40 | handleReset(); | ||
| 41 | }; | ||
| 42 | |||
| 43 | return ( | ||
| 44 | <Form | ||
| 45 | name="Form_Application" | ||
| 46 | layout="inline" | ||
| 47 | form={form} | ||
| 48 | onFinish={onFinish} | ||
| 49 | > | ||
| 50 | <FormItem label="应用名称" name="name"> | ||
| 51 | <Input placeholder="请输入应用名称" style={{width: "220px"}} /> | ||
| 52 | </FormItem> | ||
| 53 | <FormItem label="创建时间" name="createTime"> | ||
| 54 | <RangePicker allowClear={false} /> | ||
| 55 | </FormItem> | ||
| 56 | <FormItem> | ||
| 57 | <Button type="primary" htmlType="submit" className="mr-15">搜索</Button> | ||
| 58 | <Button className="mr-15" htmlType="button" onClick={onReset}>重置</Button> | ||
| 59 | <Link to="/appliction/info"><Button>创建应用</Button></Link> | ||
| 60 | </FormItem> | ||
| 61 | </Form> | ||
| 62 | ) | ||
| 63 | }; | ||
| 64 | |||
| 65 | /* DataTable */ | ||
| 66 | const DataTable = props => { | ||
| 67 | const { | ||
| 68 | loading, | ||
| 69 | handleDel, | ||
| 70 | handleGetList, | ||
| 71 | dataApplication: { data = [], page, size, totalItem } | ||
| 72 | } = props; | ||
| 73 | |||
| 74 | /* 点击分页 */ | ||
| 75 | const handlePageChange = (page, size) => { | ||
| 76 | handleGetList(page, size); | ||
| 77 | }; | ||
| 78 | |||
| 79 | const columns = [ | ||
| 80 | { | ||
| 81 | title: '应用名称', | ||
| 82 | dataIndex: 'name', | ||
| 83 | align: 'center' | ||
| 84 | }, | ||
| 85 | { | ||
| 86 | title: '应用标识码', | ||
| 87 | dataIndex: 'code', | ||
| 88 | align: 'center', | ||
| 89 | render(t, r) { | ||
| 90 | return t || '--' | ||
| 91 | } | ||
| 92 | }, | ||
| 93 | { | ||
| 94 | title: '应用链接地址', | ||
| 95 | dataIndex: 'url', | ||
| 96 | align: 'center', | ||
| 97 | render(t, r) { | ||
| 98 | return t || '--' | ||
| 99 | } | ||
| 100 | }, | ||
| 101 | { | ||
| 102 | title: '创建时间', | ||
| 103 | dataIndex: 'createTime', | ||
| 104 | align: 'center', | ||
| 105 | render(t, r) { | ||
| 106 | return t ? moment(t).format("YYYY-MM-DD HH:mm:ss") : '--' | ||
| 107 | } | ||
| 108 | }, | ||
| 109 | { | ||
| 110 | title: '操作', | ||
| 111 | align: 'center', | ||
| 112 | render(t, r) { | ||
| 113 | return ( | ||
| 114 | <> | ||
| 115 | <Link to={`/appliction/info?id=${r.id}`}>编辑</Link> | ||
| 116 | <Divider type="vertical" /> | ||
| 117 | <a onClick={() => handleDel(r)}>删除</a> | ||
| 118 | </> | ||
| 119 | ) | ||
| 120 | } | ||
| 121 | } | ||
| 122 | ]; | ||
| 123 | const pagination = { | ||
| 124 | ...paginations, | ||
| 125 | total: totalItem, | ||
| 126 | pageSize: size, | ||
| 127 | current: page, | ||
| 128 | showSizeChanger: totalItem > 20, | ||
| 129 | onChange: (page, pageSize) => { | ||
| 130 | handlePageChange(page, pageSize); | ||
| 131 | }, | ||
| 132 | onShowSizeChange: (page, pageSize) => { | ||
| 133 | handlePageChange(1, pageSize); | ||
| 134 | }, | ||
| 135 | showTotal(total) { | ||
| 136 | return `总共 ${total} 条数据`; | ||
| 137 | }, | ||
| 138 | }; | ||
| 139 | return ( | ||
| 140 | <Table | ||
| 141 | rowKey="id" | ||
| 142 | loading={loading} | ||
| 143 | dataSource={data} | ||
| 144 | columns={columns} | ||
| 145 | pagination={pagination} | ||
| 146 | /> | ||
| 147 | ) | ||
| 148 | }; | ||
| 149 | |||
| 150 | /* Main */ | ||
| 151 | const Application = props => { | ||
| 152 | const { dispatch, loading, dataSearch, dataApplication, dataApplication: { size } } = props; | ||
| 153 | |||
| 154 | useEffect(() => { | ||
| 155 | handleGetList(1, 10); | ||
| 156 | }, []) | ||
| 157 | |||
| 158 | /* 应用列表 */ | ||
| 159 | const handleGetList = (page, size) => { | ||
| 160 | dispatch({type: 'Application/getApplicationList', payload: { | ||
| 161 | page: page || 1, | ||
| 162 | size: size || 10 | ||
| 163 | }}); | ||
| 164 | }; | ||
| 165 | |||
| 166 | /* 点击搜索 */ | ||
| 167 | const handleFinish = (values) => { | ||
| 168 | const { createTime, name } = values; | ||
| 169 | dispatch({type: 'Application/changeState', payload: { | ||
| 170 | dataSearch: { | ||
| 171 | name, | ||
| 172 | createTimeBegin: createTime[0] ? createTime[0].startOf('day').valueOf() : undefined, | ||
| 173 | createTimeEnd: createTime[1] ? createTime[1].endOf('day').valueOf() : undefined, | ||
| 174 | } | ||
| 175 | }}); | ||
| 176 | handleGetList(0, size); | ||
| 177 | }; | ||
| 178 | |||
| 179 | /* 点击重置 */ | ||
| 180 | const handleReset = () => { | ||
| 181 | dispatch({type: 'Application/resetSearch'}); | ||
| 182 | handleGetList(0, 10); | ||
| 183 | }; | ||
| 184 | |||
| 185 | /* 点击删除 */ | ||
| 186 | const handleDel = ({ id }) => { | ||
| 187 | Modal.confirm({ | ||
| 188 | title: '确定删除该应用吗?', | ||
| 189 | icon: <ExclamationCircleOutlined />, | ||
| 190 | okText: '确定', | ||
| 191 | cancelText: '取消', | ||
| 192 | onOk() { | ||
| 193 | dispatch({type: 'Application/delApplication', payload: {id}}); | ||
| 194 | }, | ||
| 195 | }); | ||
| 196 | }; | ||
| 197 | |||
| 198 | return ( | ||
| 199 | <Card bordered={false}> | ||
| 200 | <SearchForm | ||
| 201 | dataSearch={dataSearch} | ||
| 202 | handleReset={handleReset} | ||
| 203 | handleFinish={handleFinish} | ||
| 204 | /> | ||
| 205 | <div className="mt-24"> | ||
| 206 | <DataTable | ||
| 207 | loading={loading} | ||
| 208 | handleDel={handleDel} | ||
| 209 | handleGetList={handleGetList} | ||
| 210 | dataApplication={dataApplication} | ||
| 211 | /> | ||
| 212 | </div> | ||
| 213 | </Card> | ||
| 214 | ) | ||
| 215 | }; | ||
| 216 | |||
| 217 | export default connect(({ Application, loading }) => ({ | ||
| 218 | ...Application, | ||
| 219 | loading: loading.effects["Application/getApplicationList"] | ||
| 220 | }))(Application) | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
src/pages/Application/models/application.js
0 → 100644
| 1 | import { routerRedux } from 'dva'; | ||
| 2 | import { message } from 'antd'; | ||
| 3 | import { getPermissionList } from '@/utils/utils'; | ||
| 4 | import * as services from '@/services/application'; | ||
| 5 | |||
| 6 | /* SerachParams */ | ||
| 7 | const staticSearch = { | ||
| 8 | name: undefined, | ||
| 9 | createTimeBegin: undefined, | ||
| 10 | createTimeEnd: undefined | ||
| 11 | }; | ||
| 12 | |||
| 13 | export default { | ||
| 14 | namespace: 'Application', | ||
| 15 | state: { | ||
| 16 | dataSearch: { | ||
| 17 | ...staticSearch | ||
| 18 | }, | ||
| 19 | dataApplication: { | ||
| 20 | data: [], | ||
| 21 | page: 1, | ||
| 22 | size: 10, | ||
| 23 | totalItem: 0, | ||
| 24 | totalPage: 0, | ||
| 25 | }, | ||
| 26 | dataModal: { | ||
| 27 | modalType: '', | ||
| 28 | modalShow: false, | ||
| 29 | modalData: {} | ||
| 30 | }, | ||
| 31 | dataMenuList: [], // 获取所有的菜单 | ||
| 32 | dataAuth: [], // 权限模块提交给后端的数据 | ||
| 33 | dataExpandedKeys: [], // tree展开的数据 | ||
| 34 | dataApplicationInfo: {}, // 应用相关信息 | ||
| 35 | oldInfo: {}, // 上一次权限信息 | ||
| 36 | }, | ||
| 37 | effects: { | ||
| 38 | /* 获取应用列表 */ | ||
| 39 | *getApplicationList({ payload }, { call, put, select }) { | ||
| 40 | const { dataSearch } = yield select(state => state.Application); | ||
| 41 | try { | ||
| 42 | const res = yield call(services.getApplicationList, { | ||
| 43 | page: 1, | ||
| 44 | size: 10, | ||
| 45 | ...dataSearch, | ||
| 46 | ...payload | ||
| 47 | }); | ||
| 48 | if (res.status === 1) { | ||
| 49 | res.data.data = res.data.data || []; | ||
| 50 | yield put({type: 'changeState', payload: { | ||
| 51 | dataApplication: res.data | ||
| 52 | }}) | ||
| 53 | } | ||
| 54 | } catch (err) { | ||
| 55 | console.error(err) | ||
| 56 | } | ||
| 57 | }, | ||
| 58 | /* 删除应用 */ | ||
| 59 | *delApplication({ payload }, { call, put, select }) { | ||
| 60 | const { dataApplication: { data = [], page, size } } = yield select(state => state.Application); | ||
| 61 | try { | ||
| 62 | const res = yield call(services.delApplication, payload); | ||
| 63 | if (res.status === 1) { | ||
| 64 | message.success("删除成功~"); | ||
| 65 | yield put({type: 'getApplicationList', payload: { | ||
| 66 | size, | ||
| 67 | page: (data.length === 1 ? (page === 1 ? 1 : page - 1) : page) | ||
| 68 | }}) | ||
| 69 | } | ||
| 70 | } catch (err) { | ||
| 71 | console.error(err) | ||
| 72 | } | ||
| 73 | }, | ||
| 74 | /* 新增、修改应用 */ | ||
| 75 | *updateApplication({ payload }, { call, put, select }) { | ||
| 76 | const { id } = payload; | ||
| 77 | try { | ||
| 78 | const res = yield call(services[!id ? "addApplication" : "updateApplication"], payload); | ||
| 79 | if (res.status === 1) { | ||
| 80 | message.success(!id ? "新增成功~" : "修改成功~"); | ||
| 81 | yield put(routerRedux.push('/appliction')); | ||
| 82 | } | ||
| 83 | } catch (err) { | ||
| 84 | console.error(err) | ||
| 85 | } | ||
| 86 | }, | ||
| 87 | /* 获取应用详情 */ | ||
| 88 | *getApplicationInfo({ payload }, { call, put, select }) { | ||
| 89 | try { | ||
| 90 | const res = yield call(services.getApplicationInfo, payload); | ||
| 91 | if (res.status === 1) { | ||
| 92 | const { data, dataMenu, dataExpandedKeys } = getPermissionList(res.data.permissionList, true); | ||
| 93 | yield put({type: 'changeState', payload: { | ||
| 94 | dataApplicationInfo: res.data || {}, | ||
| 95 | dataAuth: data, | ||
| 96 | dataMenuList: dataMenu, | ||
| 97 | dataExpandedKeys | ||
| 98 | }}) | ||
| 99 | }; | ||
| 100 | return res; | ||
| 101 | } catch (err) { | ||
| 102 | console.error(err) | ||
| 103 | } | ||
| 104 | } | ||
| 105 | }, | ||
| 106 | reducers: { | ||
| 107 | changeState(state, { payload }) { | ||
| 108 | return { | ||
| 109 | ...state, | ||
| 110 | ...payload | ||
| 111 | } | ||
| 112 | }, | ||
| 113 | cancelModal(state, { payload }) { | ||
| 114 | return { | ||
| 115 | ...state, | ||
| 116 | dataModal: { | ||
| 117 | modalType: '', | ||
| 118 | modalShow: false, | ||
| 119 | modalData: {} | ||
| 120 | } | ||
| 121 | } | ||
| 122 | }, | ||
| 123 | resetSearch(state, { payload }) { | ||
| 124 | return { | ||
| 125 | ...state, | ||
| 126 | dataSearch: { | ||
| 127 | ...staticSearch | ||
| 128 | } | ||
| 129 | } | ||
| 130 | } | ||
| 131 | } | ||
| 132 | }; |
src/pages/Data/Modal/ModalEnforcement.jsx
0 → 100644
| 1 | /** | ||
| 2 | * Author: llw | ||
| 3 | * Date: 2022.9.14 | ||
| 4 | * Description: [行政执法案件详情] | ||
| 5 | */ | ||
| 6 | import React, { useEffect } from 'react'; | ||
| 7 | import { connect } from 'umi'; | ||
| 8 | import { Drawer } from 'antd'; | ||
| 9 | import { StyledText } from '@/components/style'; | ||
| 10 | import { mapCause } from '@/constants'; | ||
| 11 | |||
| 12 | const ModalEnforceMent = props => { | ||
| 13 | let { | ||
| 14 | dispatch, | ||
| 15 | dataModal: { | ||
| 16 | modalType, | ||
| 17 | modalShow, | ||
| 18 | modalData: { id }, | ||
| 19 | }, | ||
| 20 | enforcementInfo, | ||
| 21 | } = props; | ||
| 22 | |||
| 23 | useEffect(() => { | ||
| 24 | if (modalType === 'Enforce_Ment_Modal' && modalShow) { | ||
| 25 | dispatch({ type: 'Enforcement/getEventIllegalDetail', payload: { id } }); | ||
| 26 | } | ||
| 27 | }, [modalType, modalShow]); | ||
| 28 | |||
| 29 | return ( | ||
| 30 | <Drawer | ||
| 31 | title="详情" | ||
| 32 | placement="right" | ||
| 33 | width={900} | ||
| 34 | maskClosable={false} | ||
| 35 | onClose={() => { | ||
| 36 | dispatch({ type: 'Enforcement/cancelModal' }); | ||
| 37 | }} | ||
| 38 | visible={modalType === 'Enforce_Ment_Modal' && modalShow} | ||
| 39 | footer={null} | ||
| 40 | > | ||
| 41 | <StyledText> | ||
| 42 | <div className="item-text"> | ||
| 43 | <div className="title">立案单位</div> | ||
| 44 | <div className="desc">{enforcementInfo.company || '-'}</div> | ||
| 45 | </div> | ||
| 46 | <div className="item-text"> | ||
| 47 | <div className="title">类型</div> | ||
| 48 | <div className="desc"> | ||
| 49 | {(mapCause[enforcementInfo.type] && mapCause[enforcementInfo.type].label) || '-'} | ||
| 50 | </div> | ||
| 51 | </div> | ||
| 52 | <div className="item-text"> | ||
| 53 | <div className="title">案件编号</div> | ||
| 54 | <div className="desc">{enforcementInfo.num || '-'}</div> | ||
| 55 | </div> | ||
| 56 | <div className="item-text"> | ||
| 57 | <div className="title">呈批时间</div> | ||
| 58 | <div className="desc">{enforcementInfo.submitDate || '-'}</div> | ||
| 59 | </div> | ||
| 60 | <div className="item-text"> | ||
| 61 | <div className="title">法定代表人及负责人</div> | ||
| 62 | <div className="desc">{enforcementInfo.placeUserName || '-'}</div> | ||
| 63 | </div> | ||
| 64 | <div className="item-text"> | ||
| 65 | <div className="title">电话</div> | ||
| 66 | <div className="desc">{enforcementInfo.placeUserTel || '-'}</div> | ||
| 67 | </div> | ||
| 68 | <div className="item-text"> | ||
| 69 | <div className="title">案件来源</div> | ||
| 70 | <div className="desc">{enforcementInfo.source || '-'}</div> | ||
| 71 | </div> | ||
| 72 | <div className="item-text"> | ||
| 73 | <div className="title">执法人员及执法编号</div> | ||
| 74 | <div className="desc">{enforcementInfo.nameCode || '-'}</div> | ||
| 75 | </div> | ||
| 76 | <div className="item-text"> | ||
| 77 | <div className="title">案由</div> | ||
| 78 | <div className="desc">{enforcementInfo.cause || '-'}</div> | ||
| 79 | </div> | ||
| 80 | <div className="item-text"> | ||
| 81 | <div className="title">案发区域</div> | ||
| 82 | <div className="desc">{enforcementInfo.area || '-'}</div> | ||
| 83 | </div> | ||
| 84 | <div className="item-text" style={{ width: '100%' }}> | ||
| 85 | <div className="title">违法依据</div> | ||
| 86 | <div className="desc">{enforcementInfo.illegalBasis || '-'}</div> | ||
| 87 | </div> | ||
| 88 | <div className="item-text" style={{ width: '100%' }}> | ||
| 89 | <div className="title">处罚依据</div> | ||
| 90 | <div className="desc">{enforcementInfo.punishBasis || '-'}</div> | ||
| 91 | </div> | ||
| 92 | <div className="item-text" style={{ width: '100%' }}> | ||
| 93 | <div className="title">地址</div> | ||
| 94 | <div className="desc">{enforcementInfo.placeName || '-'}</div> | ||
| 95 | </div> | ||
| 96 | <div className="item-text" style={{ width: '100%' }}> | ||
| 97 | <div className="title">处罚内容</div> | ||
| 98 | <div className="desc">{enforcementInfo.contents || '-'}</div> | ||
| 99 | </div> | ||
| 100 | <div className="item-text" style={{ width: '100%' }}> | ||
| 101 | <div className="title">案卷相关文书</div> | ||
| 102 | <div className="desc">{enforcementInfo.instruments || '-'}</div> | ||
| 103 | </div> | ||
| 104 | </StyledText> | ||
| 105 | </Drawer> | ||
| 106 | ); | ||
| 107 | }; | ||
| 108 | export default connect(({ Enforcement }) => ({ | ||
| 109 | ...Enforcement, | ||
| 110 | }))(ModalEnforceMent); |
src/pages/Data/Modal/ModalNetworkEvent.jsx
0 → 100644
This diff is collapsed.
Click to expand it.
src/pages/Data/complaint.jsx
0 → 100644
This diff is collapsed.
Click to expand it.
src/pages/Data/enforcement.jsx
0 → 100644
This diff is collapsed.
Click to expand it.
src/pages/Data/index.jsx
0 → 100644
This diff is collapsed.
Click to expand it.
src/pages/Data/models/complaint.js
0 → 100644
This diff is collapsed.
Click to expand it.
src/pages/Data/models/enforcement.js
0 → 100644
This diff is collapsed.
Click to expand it.
src/pages/Data/models/networkEvent.js
0 → 100644
This diff is collapsed.
Click to expand it.
src/pages/Data/models/place.js
0 → 100644
This diff is collapsed.
Click to expand it.
src/pages/Data/networkEvent.jsx
0 → 100644
This diff is collapsed.
Click to expand it.
src/pages/Data/place.jsx
0 → 100644
This diff is collapsed.
Click to expand it.
src/pages/Incident/ModalEventInfo.jsx
0 → 100644
This diff is collapsed.
Click to expand it.
src/pages/Incident/ModalEventLog.jsx
0 → 100644
This diff is collapsed.
Click to expand it.
src/pages/Incident/index.jsx
0 → 100644
This diff is collapsed.
Click to expand it.
src/pages/Incident/models/incident.js
0 → 100644
This diff is collapsed.
Click to expand it.
src/pages/Modals/ModalPreImg.js
0 → 100644
This diff is collapsed.
Click to expand it.
src/pages/Risk/index.jsx
0 → 100644
This diff is collapsed.
Click to expand it.
src/pages/Risk/models/risk.js
0 → 100644
This diff is collapsed.
Click to expand it.
src/pages/Screen/index.jsx
0 → 100644
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
src/pages/System/Account/index.jsx
0 → 100644
This diff is collapsed.
Click to expand it.
src/pages/System/Account/models/account.js
0 → 100644
This diff is collapsed.
Click to expand it.
src/pages/System/Menu/MenuTree.jsx
0 → 100644
This diff is collapsed.
Click to expand it.
src/pages/System/Menu/ModalSetMenu.jsx
0 → 100644
This diff is collapsed.
Click to expand it.
src/pages/System/Menu/index.jsx
0 → 100644
This diff is collapsed.
Click to expand it.
src/pages/System/Menu/models/index.js
0 → 100644
This diff is collapsed.
Click to expand it.
src/pages/System/Role/ModalUpdateRole.jsx
0 → 100644
This diff is collapsed.
Click to expand it.
src/pages/System/Role/index.jsx
0 → 100644
This diff is collapsed.
Click to expand it.
src/pages/System/Role/models/role.js
0 → 100644
This diff is collapsed.
Click to expand it.
src/pages/User/Login/index.js
0 → 100644
This diff is collapsed.
Click to expand it.
src/pages/User/Login/index.less
0 → 100644
This diff is collapsed.
Click to expand it.
src/pages/User/Risk/index.jsx
0 → 100644
This diff is collapsed.
Click to expand it.
src/pages/User/Risk/models/risk.js
0 → 100644
This diff is collapsed.
Click to expand it.
src/pages/document.ejs
0 → 100644
This diff is collapsed.
Click to expand it.
src/service-worker.js
0 → 100644
This diff is collapsed.
Click to expand it.
src/services/account.js
0 → 100644
This diff is collapsed.
Click to expand it.
src/services/application.js
0 → 100644
This diff is collapsed.
Click to expand it.
src/services/data.js
0 → 100644
This diff is collapsed.
Click to expand it.
src/services/incident.js
0 → 100644
This diff is collapsed.
Click to expand it.
src/services/login.js
0 → 100644
This diff is collapsed.
Click to expand it.
src/services/menu.js
0 → 100644
This diff is collapsed.
Click to expand it.
src/services/risk.js
0 → 100644
This diff is collapsed.
Click to expand it.
src/services/role.js
0 → 100644
This diff is collapsed.
Click to expand it.
src/services/user.js
0 → 100644
This diff is collapsed.
Click to expand it.
src/utils/encrypt.js
0 → 100644
This diff is collapsed.
Click to expand it.
src/utils/menu.js
0 → 100644
This diff is collapsed.
Click to expand it.
src/utils/request.js
0 → 100644
This diff is collapsed.
Click to expand it.
src/utils/utils.js
0 → 100644
This diff is collapsed.
Click to expand it.
tests/run-tests.js
0 → 100644
This diff is collapsed.
Click to expand it.
tests/setupTests.js
0 → 100644
This diff is collapsed.
Click to expand it.
-
Please register or sign in to post a comment