├── .babelrc
├── .circleci
└── config.yml
├── .eslintignore
├── .eslintrc.json
├── .gitattributes
├── .gitignore
├── .lintstagedrc
├── .travis.yml
├── LICENSE
├── _config.yml
├── app
├── apis
│ ├── __mocks__
│ │ └── manage.js
│ ├── common.js
│ └── manage.js
├── client.js
├── components
│ ├── draw
│ │ ├── README.md
│ │ ├── __mocks__
│ │ │ └── draw.js
│ │ ├── draw.js
│ │ ├── draw.less
│ │ └── draw2.0.js
│ ├── logo
│ │ ├── logo.css
│ │ └── logo.js
│ └── tableList
│ │ └── tableList.js
├── configs
│ ├── __mocks__
│ │ └── ajax.js
│ ├── ajax.js
│ ├── common.js
│ ├── config.js
│ ├── regular.config.js
│ ├── router.config.js
│ └── socket.js
├── images
│ ├── default.png
│ ├── icon
│ │ └── menu
│ │ │ ├── default.png
│ │ │ ├── icon_duty.png
│ │ │ ├── icon_pgmb.png
│ │ │ ├── icon_pgmx.png
│ │ │ ├── icon_statistics.png
│ │ │ ├── icon_xtxg.png
│ │ │ ├── moduleManage.png
│ │ │ ├── roleManage.png
│ │ │ └── userManage.png
│ ├── login.png
│ ├── logo.png
│ ├── navcontrol.png
│ ├── photo_default.jpg
│ ├── user.jpg
│ └── user.png
├── index.html
├── middleware
│ ├── configureStore.js
│ ├── history.js
│ ├── index.js
│ ├── logger.js
│ └── router.js
├── mocks
│ ├── apis
│ │ ├── base
│ │ │ ├── index.js
│ │ │ ├── login.js
│ │ │ ├── logout.js
│ │ │ ├── menu.js
│ │ │ └── staff.js
│ │ ├── fail.js
│ │ ├── success.js
│ │ ├── sys
│ │ │ ├── moduleManage
│ │ │ │ ├── fetchModuleDetail.js
│ │ │ │ ├── fetchModuleList.js
│ │ │ │ └── index.js
│ │ │ ├── roleManage
│ │ │ │ ├── fetchButtonList.js
│ │ │ │ ├── fetchModuleListInRole.js
│ │ │ │ ├── fetchRoleDetail.js
│ │ │ │ ├── fetchTreeList.js
│ │ │ │ └── index.js
│ │ │ └── userManage
│ │ │ │ ├── fetchRoleList.js
│ │ │ │ ├── fetchUserDepttList.js
│ │ │ │ ├── fetchUserDetail.js
│ │ │ │ ├── fetchUserList.js
│ │ │ │ └── index.js
│ │ └── tableList.js
│ ├── http.js
│ ├── interfaceFilter.js
│ └── interfaceMap.js
├── pages
│ ├── base
│ │ ├── app.js
│ │ ├── app
│ │ │ ├── header.js
│ │ │ ├── leftNav.js
│ │ │ ├── modal
│ │ │ │ ├── editPassword.js
│ │ │ │ └── userInfo.js
│ │ │ └── tabList.js
│ │ ├── developing.js
│ │ ├── example.js
│ │ ├── index.js
│ │ ├── login.js
│ │ ├── notfound.js
│ │ ├── socket.js
│ │ └── socketReceive.js
│ ├── example.js
│ ├── menu
│ │ ├── echarts.js
│ │ ├── editor.js
│ │ └── index.js
│ └── set
│ │ ├── index.js
│ │ ├── moduleManage
│ │ ├── index.js
│ │ ├── modal
│ │ │ ├── addButtonModal.js
│ │ │ ├── buttonModal.js
│ │ │ └── moduleAdd.js
│ │ └── moduleList.js
│ │ ├── roleManage
│ │ ├── index.js
│ │ ├── modal
│ │ │ ├── buttonModal.js
│ │ │ └── roleAdd.js
│ │ ├── peopleTreeList.js
│ │ ├── roleCheckbox.js
│ │ ├── roleList.js
│ │ └── roleModuleList.js
│ │ └── userManage
│ │ ├── index.js
│ │ ├── modal
│ │ ├── addPolice.js
│ │ └── selectRole.js
│ │ └── treeList.js
├── redux
│ ├── actions
│ │ ├── common.js
│ │ └── tabList.js
│ └── reducers
│ │ ├── common.js
│ │ ├── index.js
│ │ └── tabList.js
├── resource
│ └── iconfont
│ │ ├── iconfont.eot
│ │ ├── iconfont.svg
│ │ ├── iconfont.ttf
│ │ └── iconfont.woff
└── styles
│ ├── RichEditor.less
│ ├── base.less
│ ├── login.less
│ ├── personalCenter.less
│ ├── set.less
│ └── theme.less
├── package-lock.json
├── package.json
├── postcss.config.js
├── readme.md
├── scripts
├── webpack.base.config.js
├── webpack.dev.config.js
├── webpack.dll.config.js
├── webpack.prod.config.js
└── webpack.testing.config.js
└── test
├── Enzyme.js
└── setCenter
└── sys
├── moduleManage
├── index.spec.js
├── module
│ ├── addButtonModal.spec.js
│ ├── addmodal.spec.js
│ └── buttonModal.spec.js
└── moduleList.spec.js
├── roleManage
├── index.spec.js
├── modal
│ ├── buttonModal.spec.js
│ └── roleAdd.spec.js
├── roleCheckbox.spec.js
└── roleModuleList.spec.js
└── userManage
├── index.spec.js
└── modal
└── addPolice.spec.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["@babel/preset-env",{
4 | "useBuiltIns": "usage",
5 | "targets": {
6 | "chrome": "49",
7 | "ie": "11"
8 | },
9 | "corejs": 2
10 | }],
11 | "@babel/preset-react"
12 | ],
13 | "plugins": [
14 | ["@babel/plugin-transform-runtime",{
15 | "absoluteRuntime": false,
16 | "corejs": 2,
17 | "helpers": true,
18 | "regenerator": true,
19 | "useESModules": false
20 | }],
21 | [
22 | "@babel/plugin-proposal-decorators",
23 | {
24 | "legacy": true
25 | }
26 | ],
27 | "@babel/plugin-proposal-class-properties",
28 | // "transform-decorators-legacy",
29 | // "@babel/plugin-syntax-dynamic-import",
30 | ["import", {
31 | "libraryName": "antd",
32 | "libraryDirectory": "es",
33 | "style": true // `style: true` 会加载 less 文件
34 | }]
35 | ]
36 | }
--------------------------------------------------------------------------------
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 |
3 | references:
4 | container_config: &container_config
5 | docker:
6 | - image: circleci/node:8
7 | working_directory: ~/react
8 |
9 | attach_workspace: &attach_workspace
10 | attach_workspace:
11 | at: ~/react
12 |
13 | react_16: &react_16
14 | environment:
15 | REACT: 16
16 |
17 | workflow: &workflow
18 | jobs:
19 | - setup:
20 | filters:
21 | branches:
22 | ignore: gh-pages
23 | # - testing:
24 | # requires:
25 | # - setup
26 | - lint:
27 | requires:
28 | - setup
29 |
30 |
31 | jobs:
32 | setup:
33 | <<: *container_config
34 | steps:
35 | - checkout
36 | - run: node -v
37 | - run: npm -v
38 | - run: npm install
39 | - run: npm run dll
40 | - run:
41 | command: |
42 | set +eo
43 | npm ls
44 | true
45 | - persist_to_workspace:
46 | root: ~/react
47 | paths:
48 | - node_modules
49 |
50 | # testing:
51 | # <<: *container_config
52 | # steps:
53 | # - checkout
54 | # - *attach_workspace
55 | # - run: npm run testing
56 | # - run: node ./scripts/webpack.testing.config.js
57 | # - persist_to_workspace:
58 | # root: ~/react
59 | # paths:
60 | # - dist
61 |
62 |
63 | lint:
64 | <<: *container_config
65 | steps:
66 | - checkout
67 | - *attach_workspace
68 | - run: npm run lint
69 |
70 | workflows:
71 | version: 2
72 | build_test:
73 | <<: *workflow
74 | nightly:
75 | <<: *workflow
76 | triggers:
77 | - schedule:
78 | cron: "0 0 * * *"
79 | filters:
80 | branches:
81 | only:
82 | - master
83 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | # /node_modules/* and /bower_components/* ignored by default
2 |
3 | /*
4 | !app
5 |
6 | /test
7 |
8 | /app/components/draw/__mocks__/draw.js
9 |
10 | /app/configs/__mocks__/ajax.js
11 | /app/resource
12 |
13 | # app/configs
14 | # app/components
15 | # app/pages
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "airbnb",
3 | "env": {
4 | "browser": true,
5 | "node": true,
6 | "es6": true
7 | },
8 | "settings": {
9 | "import/core-modules": [
10 | "components",
11 | "actions",
12 | "api",
13 | "reducers",
14 | "utils",
15 | "constants"
16 | ]
17 | },
18 | "parser": "babel-eslint",
19 | "parserOptions": {
20 | "ecmaFeatures": {
21 | "jsx": true,
22 | "experimentalObjectRestSpread": true
23 | }
24 | },
25 | "rules": {
26 | "linebreak-style": "off",
27 | "func-names": 0,
28 | "max-len": [
29 | "warn",
30 | 200,
31 | 4,
32 | {
33 | "comments": 150
34 | }
35 | ],
36 | "indent": [
37 | "error",
38 | 2,
39 | {
40 | "SwitchCase": 1
41 | }
42 | ],
43 | "react/jsx-indent": [
44 | 2,
45 | 2
46 | ],
47 | "semi": 0,
48 | "react/sort-comp": 0,
49 | "react/prop-types": 0,
50 | "react/prefer-es6-class": 0,
51 | "react/prefer-stateless-function": 0,
52 | "react/jsx-first-prop-new-line": 0,
53 | "react/jsx-filename-extension": 0,
54 | "no-return-assign": 0,
55 | "react/no-multi-comp": 0,
56 | "array-callback-return": 0,
57 | "no-underscore-dangle": 0,
58 | "no-bitwise": [
59 | "error",
60 | {
61 | "allow": [
62 | "~"
63 | ]
64 | }
65 | ],
66 | "no-plusplus": 1,
67 | "no-unused-expressions": [
68 | "warn",
69 | {
70 | "allowShortCircuit": true,
71 | "allowTernary": true
72 | }
73 | ],
74 | "import/no-unresolved": 0,
75 | "import/no-extraneous-dependencies": 0,
76 | "jsx-a11y/no-static-element-interactions": 0,
77 | "jsx-a11y/img-has-alt": 0,
78 | "no-unused-vars": [
79 | "warn",
80 | {
81 | "vars": "all",
82 | "args": "none"
83 | }
84 | ],
85 | "react/no-unused-state": [
86 | "warn"
87 | ],
88 | "no-param-reassign": [
89 | "error",
90 | {
91 | "props": false
92 | }
93 | ],
94 | "object-shorthand": 0,
95 | "jsx-a11y/anchor-is-valid": 0,
96 | "react/no-array-index-key": 0,
97 | "jsx-a11y/click-events-have-key-events": 0,
98 | "import/extensions": 0,
99 | "no-debugger": "off",
100 | "react/jsx-closing-tag-location": 0,
101 | "import/prefer-default-export": 0,
102 | "react/forbid-prop-types": 1,
103 | "class-methods-use-this": 0,
104 | "consistent-return": 1,
105 | "import/first": 1,
106 | "no-console":"off",
107 | "prefer-destructuring": [
108 | "warn"
109 | ],
110 | "object-curly-newline": [
111 | "error",
112 | {
113 | "minProperties": 5,
114 | "consistent": true,
115 | "multiline":true
116 | }
117 | ]
118 | },
119 | "plugins": [
120 | "jsx-a11y"
121 | ]
122 | }
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.js eol=lf
2 | *.json eol=lf
3 | *.jsx eol=lf
4 | *.ts eol=lf
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 |
6 | # vscode
7 | jsconfig.json
8 | dist
9 |
10 | # Runtime data
11 | pids
12 | *.pid
13 | *.seed
14 | *.pid.lock
15 |
16 | # Directory for instrumented libs generated by jscoverage/JSCover
17 | lib-cov
18 |
19 | # Coverage directory used by tools like istanbul
20 | coverage
21 |
22 | # nyc test coverage
23 | .nyc_output
24 |
25 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
26 | .grunt
27 |
28 | # node-waf configuration
29 | .lock-wscript
30 |
31 | # Compiled binary addons (http://nodejs.org/api/addons.html)
32 | build/Release
33 |
34 | # Dependency directories
35 | node_modules
36 | jspm_packages
37 |
38 | # Optional npm cache directory
39 | .npm
40 |
41 | # Optional REPL history
42 | .node_repl_history
43 |
44 | #mac
45 | .DS_Store
46 |
47 | #vscode
48 | .vscode
49 | /.idea/
50 |
51 | #eslint
52 | .eslintcache
53 |
54 | #cashe
55 | .cache
56 |
57 | #app/components/condition1.0
58 |
59 | #don't upload node_modules.rar
60 | node_modules.rar
61 |
62 | #don't upload react.rar
63 | react.rar
64 |
--------------------------------------------------------------------------------
/.lintstagedrc:
--------------------------------------------------------------------------------
1 | {
2 | "linters": {
3 | "app/**/*.js": [
4 | "npm run lint",
5 | "git add"
6 | ]
7 | }
8 | }
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - '9'
4 | cache:
5 | directories:
6 | - node_modules
7 |
8 | install:
9 | - npm install
10 |
11 | script: 'true'
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017-present, dupi, Inc.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-cayman
--------------------------------------------------------------------------------
/app/apis/__mocks__/manage.js:
--------------------------------------------------------------------------------
1 |
2 | import { createApi } from '@ajax'
3 | import { mockURL, path } from '@configs/config'
4 |
5 | const prefix = 'usercenter'
6 | const option = { baseURL: mockURL }
7 | // 模块管理
8 | export const fetchModuleList = createApi(`${path}/${prefix}/resource/list`, option) // 获取模块列表
9 | export const fetchModuleDelete = createApi(`${path}/${prefix}/resource/delete`, option) // 删除模块
10 | export const fetchModuleDetail = createApi(`${path}/${prefix}/resource/detail`, option) // 获取模块详情
11 | export const fetchChangeModuleStatus = createApi(`${path}/${prefix}/resource/updateStatus`, option) // 修改模块显隐状态
12 | export const fetchModuleUpdateDetail = createApi(`${path}/${prefix}/resource/update`, option) // 修改模块详情
13 | export const fetchModuleAdd = createApi(`${path}/${prefix}/resource/save`, option) // 新增模块
14 | export const fetchButtonList = createApi(`${path}/${prefix}/resource/button/list`, 'fetchButtonList') // 按钮权限列表
15 |
16 | // 角色管理
17 | export const fetchRoleList = createApi(`${path}/${prefix}/role/list`, 'fetchRoleList') // 角色列表
18 | export const fetchRoleAdd = createApi(`${path}/${prefix}/role/save`, option) // 保存角色
19 | export const fetchRoleUpdate = createApi(`${path}/${prefix}/role/update`, option) // 角色编辑
20 | export const fetchRoleDetail = createApi(`${path}/${prefix}/role/detail`, option) // 已选择的菜单以及按钮
21 | export const fetchRoleDelete = createApi(`${path}/${prefix}/role/delete`, option) // 删除角色
22 | export const fetchModuleListInRole = createApi(`${path}/${prefix}/role/resList`, 'fetchModuleListInRole') // 已选择的模块
23 | export const fetchUpdateRoleRes = createApi(`${path}/${prefix}/role/updateRes`, option) // 更新已选择的模块
24 |
25 | export const fetchRoleDeletePeople = createApi(`${path}/${prefix}/user/removeRole`, option)
26 | export const fetchUpdateButton = createApi(`${path}/${prefix}/role/updateButton`, option)
27 | export const fetchTreeList = createApi(`${path}/${prefix}/role/resTree`, 'fetchTreeList')
28 | // 用户管理
29 | export const fetchUserDepttList = createApi(`${path}/${prefix}/dept/list`, 'fetchUserDepttList') // 获取用户管理左侧分类列表
30 | export const fetchUserList = createApi(`${path}/${prefix}/user/list`, 'fetchUserList') // 获取用户列表
31 | export const fetchUserDetail = createApi(`${path}/${prefix}/user/detail`, option) // 获取用户详情
32 | export const fetchUserDetailUpdate = createApi(`${path}/${prefix}/user/update`, option) // 修改用户详情
33 | export const fetchUserAdd = createApi(`${path}/${prefix}/user/save`, option) // 新增用户
34 | export const synUser = createApi(`${path}/${prefix}/user/synUser`, option) // 同步用户
35 | export const fetchUserSetRole = createApi(`${path}/${prefix}/user/updateRole`, option) // 修改用户角色
36 | export const fetchUserDelete = createApi(`${path}/${prefix}/user/delete`, option) // 删除用户
37 | export const fetchChangeUserStatus = createApi(`${path}/${prefix}/user/updateStatus`, option) // 设置用户是否冻结状态
38 |
--------------------------------------------------------------------------------
/app/apis/common.js:
--------------------------------------------------------------------------------
1 |
2 | import { createApi } from '@ajax'
3 | import { mockURL, /* baseURL, */ path } from '@config'
4 |
5 | const prefix = 'usercenter'
6 | const option = { baseURL: mockURL }
7 |
8 | export const login = createApi(`${path}/${prefix}/login`, option) // 登陆
9 | export const logout = createApi(`${path}/${prefix}/logout`, option) // 登出
10 | export const loginByTicket = createApi(`${path}/${prefix}/loginByTicket`, option) // 通过ticket登陆
11 | export const loginByKey = createApi(`${path}/service/pagerservice/checkKey`, option) // 通过key进入项目
12 | export const staff = createApi(`${path}/${prefix}/user/userInfo`, option) // 用户信息
13 | export const synUser = createApi(`${path}/${prefix}/user/synUser`, option)// 同步用户
14 | export const menu = createApi(`${path}/${prefix}/user/userMenu`, option) // 获取菜单
15 | export const getLevel = createApi(`${path}/${prefix}/user/getLevel`, option) // 当前用户的等级
16 | export const getBtns = createApi(`${path}/${prefix}/resource/listByPid`, option) // 获取菜单id
17 | export const getAllRetrieval = createApi(`${path}/data/sys/retrieval/queryAllRetrievald`) // 获取gForm2.0头部搜索
18 |
--------------------------------------------------------------------------------
/app/apis/manage.js:
--------------------------------------------------------------------------------
1 |
2 | import { createApi } from '@ajax'
3 | import { mockURL, /* baseURL, */ path } from '@config'
4 |
5 | const prefix = 'usercenter'
6 | const option = { baseURL: mockURL }
7 |
8 | // 模块管理
9 | export const fetchModuleList = createApi(`${path}/${prefix}/resource/list`, option) // 获取模块列表
10 | export const fetchModuleDelete = createApi(`${path}/${prefix}/resource/delete`, option) // 删除模块
11 | export const fetchModuleDetail = createApi(`${path}/${prefix}/resource/detail`, option) // 获取模块详情
12 | export const fetchChangeModuleStatus = createApi(`${path}/${prefix}/resource/updateStatus`, option) // 修改模块显隐状态
13 | export const fetchModuleUpdateDetail = createApi(`${path}/${prefix}/resource/update`, option) // 修改模块详情
14 | export const fetchModuleAdd = createApi(`${path}/${prefix}/resource/save`, option) // 新增模块
15 | export const fetchButtonList = createApi(`${path}/${prefix}/resource/button/list`, option) // 按钮权限列表
16 |
17 | // 角色管理
18 | export const fetchRoleList = createApi(`${path}/${prefix}/role/list`, option) // 角色列表
19 | export const fetchRoleAdd = createApi(`${path}/${prefix}/role/save`, option) // 保存角色
20 | export const fetchRoleUpdate = createApi(`${path}/${prefix}/role/update`, option) // 角色编辑
21 | export const fetchRoleDetail = createApi(`${path}/${prefix}/role/detail`, option) // 已选择的菜单以及按钮
22 | export const fetchRoleDelete = createApi(`${path}/${prefix}/role/delete`, option) // 删除角色
23 | export const fetchModuleListInRole = createApi(`${path}/${prefix}/role/resList`, option) // 已选择的模块
24 | export const fetchUpdateRoleRes = createApi(`${path}/${prefix}/role/updateRes`, option) // 更新已选择的模块
25 |
26 | export const fetchRoleDeletePeople = createApi(`${path}/${prefix}/user/removeRole`, option)
27 | export const fetchUpdateButton = createApi(`${path}/${prefix}/role/updateButton`, option)
28 | export const fetchTreeList = createApi(`${path}/${prefix}/role/resTree`, option)
29 | // 用户管理
30 | export const fetchUserDepttList = createApi(`${path}/${prefix}/dept/list`, option) // 获取用户管理左侧分类列表
31 | export const fetchUserList = createApi(`${path}/${prefix}/user/list`, option) // 获取用户列表
32 | export const fetchUserDetail = createApi(`${path}/${prefix}/user/detail`, option) // 获取用户详情
33 | export const fetchUserDetailUpdate = createApi(`${path}/${prefix}/user/update`, option) // 修改用户详情
34 | export const fetchUserAdd = createApi(`${path}/${prefix}/user/save`, option) // 新增用户
35 | export const synUser = createApi(`${path}/${prefix}/user/synUser`, option) // 同步用户
36 | export const fetchUserSetRole = createApi(`${path}/${prefix}/user/updateRole`, option) // 修改用户角色
37 | export const fetchUserDelete = createApi(`${path}/${prefix}/user/delete`, option) // 删除用户
38 | export const fetchChangeUserStatus = createApi(`${path}/${prefix}/user/updateStatus`, option) // 设置用户是否冻结状态
39 |
--------------------------------------------------------------------------------
/app/client.js:
--------------------------------------------------------------------------------
1 | // import '@babel/polyfill'
2 | import React from 'react'
3 | import ReactDOM from 'react-dom'
4 | import { Provider } from 'react-redux'
5 | import { hot } from 'react-hot-loader/root'
6 | import '@config'
7 | import Routes from '@configs/router.config'
8 | import configure from '@middleware/configureStore'
9 |
10 | const HotRoutes = hot(Routes)
11 | const store = configure({ })
12 | ReactDOM.render(
13 |
14 |
15 | ,
16 | document.getElementById('root'),
17 | )
18 |
--------------------------------------------------------------------------------
/app/components/draw/README.md:
--------------------------------------------------------------------------------
1 | ## drawde(抽屉组件)
2 | #### props
3 | | 属性名 | 类型 | 默认值 | 是否必填 | 描述 |
4 | | -------- | ----------------- | ------ | ---- | ------------------------------- |
5 | | visible | String | 无 | 是 | 组件是否显示 |
6 | | title | String | '标题' | 否 | 抽屉标题 |
7 | | footer | String\|ReactNode | 无 | 否 | 组件底部内容 |
8 | | onCancel | Function | 无 | 是 | 关闭组件的回调方法,将组件设置的visible设置为false |
9 | | size | String | 'base' | 否 | 组件的大小,有sm,base,lg共3个值 |
10 |
11 | #### 调用示例
12 |
13 | ```javascript
14 | {
15 | this.state.drawVisible ?
16 | this.setState({ drawVisible: false })}
21 | size="lg"
22 | >
23 | 111
24 |
25 | : null
26 | }
27 | ```
28 |
--------------------------------------------------------------------------------
/app/components/draw/draw2.0.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: 韩卿
3 | * @Date: 2017-08-20 16:07:21
4 | * @Last Modified by: dupi
5 | * @Last Modified time: 2018-10-22 17:10:34
6 | */
7 |
8 |
9 | import React, { Component } from 'react'
10 | import ReactDOM from 'react-dom'
11 | import PropTypes from 'prop-types';
12 | // import configure from '../../store/configureStore'
13 |
14 | import './draw.less'
15 |
16 | // const store = configure({ config: global.$GLOBALCONFIG })
17 |
18 | // 声明组件 并对外输出
19 | export default class Drawer extends Component {
20 | // 初始化页面常量 绑定事件方法
21 | constructor(props, context) {
22 | super(props, context)
23 | this.state = {
24 | // activeTab: 'pop' ,
25 | drawTrasformClass: '',
26 | maskTrasformClass: '',
27 | drawerSizeClass: 'modal-base',
28 | // drawerSizeClassList: ['modal-base', 'modal-sm', 'modal-lg'],
29 | }
30 | }
31 |
32 | componentWillMount() {
33 | const {
34 | size = 'default',
35 | } = this.props
36 | this.getDrawerSize(size)
37 | this.setTrasformClass()
38 | }
39 |
40 |
41 | // 组件已经加载到dom中
42 | componentDidMount() {
43 | const {
44 | visible = true,
45 | } = this.props
46 | if (visible) {
47 | this.initDrawer()
48 | }
49 | }
50 |
51 | // 监测visible属性,
52 | componentWillReceiveProps(nextProps) {
53 | /* const {
54 | visible = true,
55 | } = this.props
56 | console.log(visible)
57 | console.log(nextProps)
58 | if (visible || nextProps.visible) {
59 | this.initDrawer()
60 | } else {
61 | this.removeDrawer()
62 | } */
63 | }
64 |
65 | componentDidUpdate() {
66 | this.renderDrawer()
67 | }
68 |
69 | componentWillUnmount() {
70 | // ut(() => {
71 | ReactDOM.unmountComponentAtNode(this.popup)
72 | // }, 300)
73 | }
74 |
75 | // 初始化抽屉
76 | initDrawer = () => {
77 | this.popup = document.createElement('div')
78 | this.popup.setAttribute('class', 'drawers')
79 | this.renderDrawer()
80 | document.body.appendChild(this.popup)
81 | this.setTrasformClass()
82 | }
83 |
84 | // 抽屉添加动画效果class的设置
85 | setTrasformClass = () => {
86 | const {
87 | visible = true,
88 | } = this.props
89 | if (visible) {
90 | this.setState({
91 | drawTrasformClass: 'draw-enter',
92 | maskTrasformClass: 'mask-enter',
93 | }, () =>
94 | setTimeout(() => {
95 | this.setState({
96 | drawTrasformClass: '',
97 | maskTrasformClass: '',
98 | })
99 | }, 300))
100 | }
101 | }
102 |
103 | // 移除弹窗
104 | removeDrawer = () => {
105 | this.setState({
106 | drawTrasformClass: 'draw-leave',
107 | maskTrasformClass: 'mask-leave',
108 | }, () =>
109 | setTimeout(() => {
110 | this.setState({
111 | drawTrasformClass: '',
112 | maskTrasformClass: '',
113 | })
114 | document.body.removeChild(this.popup)
115 | ReactDOM.unmountComponentAtNode(this.popup)
116 |
117 | this.props.onCancel()
118 | }, 200))
119 | }
120 |
121 | // 判断抽屉的尺寸class
122 | getDrawerSize = (size) => {
123 | switch (size) {
124 | case 'sm':
125 | this.setState({
126 | drawerSizeClass: 'drawer-sm',
127 | })
128 | break
129 | case 'lg':
130 | this.setState({
131 | drawerSizeClass: 'drawer-lg',
132 | })
133 | break
134 | default:
135 | this.setState({
136 | drawerSizeClass: 'drawer-base',
137 | })
138 | break
139 | }
140 | }
141 |
142 | // 将弹窗内容插入到指定dom中
143 | renderDrawer() {
144 | const {
145 | title = '标题',
146 | footer = null,
147 | } = this.props
148 | const {
149 | drawTrasformClass,
150 | maskTrasformClass,
151 | drawerSizeClass,
152 | } = this.state
153 |
154 | ReactDOM.render(
155 |
156 |
this.removeDrawer()} />
157 |
158 |
159 |
160 |
163 |
166 |
167 | {this.props.children}
168 |
169 |
170 | {footer}
171 |
172 |
173 |
174 |
175 |
,
176 | this.popup,
177 | )
178 | }
179 |
180 | render() {
181 | return null
182 | }
183 | }
184 |
185 | Drawer.contextTypes = {
186 | form: PropTypes.object,
187 | vertical: PropTypes.bool,
188 | store: PropTypes.object,
189 | };
190 |
191 | class AntModalBody extends Component {
192 | getChildContext() {
193 | return { form: this.props.context.form, vertical: this.props.context.vertical, store: this.props.context.store }
194 | }
195 | render() {
196 | return (
197 |
198 | {this.props.children}
199 |
200 | )
201 | }
202 | }
203 |
204 | AntModalBody.childContextTypes = {
205 | form: PropTypes.object,
206 | vertical: PropTypes.string,
207 | store: PropTypes.object,
208 | }
209 |
--------------------------------------------------------------------------------
/app/components/logo/logo.css:
--------------------------------------------------------------------------------
1 | .logo-gather-demo-edit-wrapper {
2 | position: absolute;
3 | bottom: 0;
4 | width: 100%;
5 | background: #f1f1f1;
6 | padding: 0 5%;
7 | line-height: 45px;
8 | }
9 |
10 | .logo-gather-demo-edit-wrapper ul {
11 | display: block;
12 | width: 100%;
13 | overflow: hidden;
14 | }
15 |
16 | .logo-gather-demo-edit-wrapper ul li:first-child {
17 | margin-left: 0;
18 | }
19 |
20 | .logo-gather-demo-edit-wrapper ul li {
21 | float: left;
22 | vertical-align: middle;
23 | margin: 0 5px;
24 | }
25 |
26 | .logo-gather-demo-wrapper {
27 | position: absolute;
28 | z-index: 10;
29 | top: 0;
30 | /*margin:0 auto;*/
31 | left: 0;
32 | background: transparent;
33 | overflow: hidden;
34 | height: 100%;
35 | width: 100%;
36 | }
37 |
38 | .logo-gather-demo-wrapper .point-wrapper {
39 | position: absolute;
40 | }
41 |
42 | .logo-gather-demo-wrapper .point {
43 | border-radius: 100%;
44 | }
45 |
46 | .logo-gather-demo-wrapper .right-side {
47 | width: 1038px;
48 | height: 280px;
49 | position: absolute;
50 | right: 0;
51 | top: -60px;
52 | bottom: 0;
53 | left: 0;
54 | margin: auto;
55 | }
56 |
57 | .logo-gather-demo-wrapper .right-side * {
58 | pointer-events: none;
59 | }
60 |
61 | @media screen and (max-width: 414px) {
62 | .exhibition-details-demo {
63 | overflow: hidden;
64 | }
65 |
66 | .logo-gather-demo-edit-wrapper {
67 | transform: translateY(100%);
68 | transition: transform .45s ease-in-out;
69 | }
70 |
71 | .logo-gather-demo-edit-wrapper.open{
72 | transform: translateY(0);
73 | }
74 |
75 | .logo-gather-demo-edit-wrapper .anticon-down{
76 | transition: transform .45s ease-in-out;
77 | }
78 |
79 | .logo-gather-demo-edit-wrapper.open .anticon-down{
80 | transform: rotate(180deg);
81 | }
82 |
83 | .logo-gather-demo-edit-wrapper > div {
84 | width: 90%;
85 | line-height: 24px !important;
86 | margin-bottom: 5px;
87 | }
88 |
89 | .exhibition-details-demo .edit-button{
90 | position: absolute;
91 | top: -20px;
92 | width: 30px;
93 | height: 20px;
94 | border-radius: 30px 30px 0 0;
95 | background: #f1f1f1;
96 | text-align: center;
97 | left: 0;
98 | right: 0;
99 | margin: auto;
100 | box-shadow: 0 -5px 5px rgba(0, 0, 0, 0.15);
101 | }
102 |
103 | .logo-gather-demo-edit-wrapper ul {
104 | margin: 5px auto;
105 | }
106 |
107 | .phone-float-none {
108 | clear: both;
109 | margin-left: 0 !important;
110 | }
111 |
112 | .none {
113 | display: none;
114 | }
115 |
116 | }
--------------------------------------------------------------------------------
/app/components/logo/logo.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | // import ReactDOM from 'react-dom'
3 | import { connect } from 'react-redux'
4 | import TweenOne from 'rc-tween-one'
5 | import ticker from 'rc-tween-one/lib/ticker'
6 | import PropTypes from 'prop-types'
7 | import logo from '@images/login.png'
8 | import './logo.css'
9 |
10 | @connect((state, props) => ({
11 | config: state.config,
12 | }))
13 |
14 | export default class app extends Component {
15 | static propTypes = {
16 | image: PropTypes.string,
17 | w: PropTypes.number,
18 | h: PropTypes.number,
19 | pixSize: PropTypes.number,
20 | pointSizeMin: PropTypes.number,
21 | };
22 |
23 | static defaultProps = {
24 | image: logo,
25 | // className: 'logo-gather-demo',
26 | w: 1038,
27 | h: 280,
28 | pixSize: 20,
29 | pointSizeMin: 8,
30 | };
31 |
32 | constructor(props) {
33 | super(props);
34 | this.state = {};
35 | this.interval = null;
36 | this.gather = true;
37 | this.intervalTime = 9000;
38 | }
39 |
40 | componentDidMount() {
41 | // this.dom = ReactDOM.findDOMNode(this)
42 | this.dom = this.componentDom
43 | this.createPointData();
44 | }
45 |
46 | componentWillUnmount() {
47 | ticker.clear(this.interval)
48 | this.interval = null
49 | }
50 |
51 | onMouseEnter = () => {
52 | // !this.gather && this.updateTweenData();
53 | if (!this.gather) {
54 | this.updateTweenData();
55 | }
56 | this.componentWillUnmount();
57 | };
58 |
59 | onMouseLeave = () => {
60 | // this.gather && this.updateTweenData();
61 | if (this.gather) {
62 | this.updateTweenData();
63 | }
64 | this.interval = ticker.interval(this.updateTweenData, this.intervalTime);
65 | };
66 |
67 | setDataToDom(data, w, h) {
68 | this.pointArray = [];
69 | const number = this.props.pixSize;
70 | for (let i = 0; i < w; i += number) {
71 | for (let j = 0; j < h; j += number) {
72 | if (data[((i + (j * w)) * 4) + 3] > 150) {
73 | this.pointArray.push({ x: i, y: j });
74 | }
75 | }
76 | }
77 | const children = [];
78 | this.pointArray.forEach((item, i) => {
79 | const r = (Math.random() * this.props.pointSizeMin) + this.props.pointSizeMin;
80 | const b = (Math.random() * 0.4) + 0.1;
81 | children.push(
82 |
100 | );
101 | });
102 | this.setState({
103 | children,
104 | boxAnim: { opacity: 0, type: 'from', duration: 800 },
105 | }, () => {
106 | this.interval = ticker.interval(this.updateTweenData, this.intervalTime);
107 | });
108 | }
109 |
110 | createPointData = () => {
111 | const { w, h } = this.props;
112 | const canvas = document.getElementById('canvas');
113 | const ctx = canvas.getContext('2d');
114 | ctx.clearRect(0, 0, w, h);
115 | canvas.width = this.props.w;
116 | canvas.height = h;
117 | const img = new Image();
118 | img.onload = () => {
119 | ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, w, h);
120 | const { data } = ctx.getImageData(0, 0, w, h);
121 | this.setDataToDom(data, w, h);
122 | this.dom.removeChild(canvas);
123 | };
124 | img.crossOrigin = 'anonymous';
125 | img.src = this.props.image;
126 | };
127 |
128 | gatherData = () => {
129 | const children = this.state.children && this.state.children.map(item =>
130 | React.cloneElement(item, {
131 | animation: {
132 | x: 0,
133 | y: 0,
134 | opacity: 1,
135 | scale: 1,
136 | delay: Math.random() * 500,
137 | duration: 800,
138 | ease: 'easeInOutQuint',
139 | },
140 | }));
141 | this.setState({ children });
142 | };
143 |
144 | disperseData = () => {
145 | const rect = this.dom.getBoundingClientRect();
146 | const sideRect = this.sideBox.getBoundingClientRect();
147 | const sideTop = sideRect.top - rect.top;
148 | const sideLeft = sideRect.left - rect.left;
149 | const children = this.state.children.map(item =>
150 | React.cloneElement(item, {
151 | animation: {
152 | x: (Math.random() * rect.width) - sideLeft - item.props.style.left,
153 | y: (Math.random() * rect.height) - sideTop - item.props.style.top,
154 | opacity: (Math.random() * 0.4) + 0.1,
155 | scale: (Math.random() * 2.4) + 0.1,
156 | duration: (Math.random() * 500) + 500,
157 | ease: 'easeInOutQuint',
158 | },
159 | }));
160 |
161 | this.setState({
162 | children,
163 | });
164 | };
165 |
166 | updateTweenData = () => {
167 | // this.dom = ReactDOM.findDOMNode(this);
168 | this.dom = this.componentDom
169 | // this.sideBox = ReactDOM.findDOMNode(this.sideBoxComp);
170 | this.sideBox = document.querySelector('.right-side');
171 | ((this.gather && this.disperseData) || this.gatherData)();
172 | this.gather = !this.gather;
173 | };
174 |
175 | render() {
176 | return (
this.componentDom = c}>
177 |
178 | {
184 | this.sideBoxComp = c;
185 | }}
186 | >
187 | {this.state.children}
188 |
189 |
);
190 | }
191 | }
192 |
--------------------------------------------------------------------------------
/app/components/tableList/tableList.js:
--------------------------------------------------------------------------------
1 | /*
2 | 如果要使用不回行的table,那么就要设置table的className为nowrap,并且不能对td设置特定的宽度,且scroll={{ y: true, x: true }}的X值必须为true
3 | */
4 |
5 | import React, { Component } from 'react'
6 | import { Table, Pagination } from 'antd'
7 |
8 | export default class TableList extends Component {
9 | componentDidMount() {
10 | this.tableWidthAdaptive()
11 | }
12 |
13 | componentWillUnmount() {
14 | clearInterval(this.t)
15 | }
16 |
17 | // 动态计算td的宽度
18 | tableWidthAdaptive = () => {
19 | if (this.props.className && this.props.className.indexOf('nowrap') > -1) {
20 | this.t = setInterval(() => { // 通过定时器循环的方式,看看真实节点是否加载到dom中了
21 | const tds = document.querySelector('.ant-table-row') && document.querySelector('.ant-table-row').querySelectorAll('td')
22 | const ths = document.querySelectorAll('.ant-table-header th')
23 | if (tds && tds.length) {
24 | clearInterval(this.t)
25 | for (let i = 0; i < tds.length; i += 1) {
26 | const tdw = tds[i].offsetWidth
27 | const thw = ths[i].offsetWidth
28 | const w = (tdw > thw) ? tdw : thw
29 | tds[i].style.minWidth = `${w}px`
30 | ths[i].style.minWidth = `${w}px`
31 | }
32 | }
33 | }, 100)
34 | }
35 | }
36 |
37 | render() {
38 | const {
39 | currentPage,
40 | pageSize,
41 | totalCount,
42 | onShowSizeChange,
43 | onChange,
44 | columns,
45 | } = this.props
46 | const hasMultiHead = columns.filter(one => !!one.children).length > 0
47 | return (
48 |
49 |
56 | { currentPage ?
57 |
`共 ${_totalCount} 条`}
64 | current={currentPage || 1}
65 | pageSize={pageSize || 10}
66 | {...this.props}
67 | /> : null
68 | }
69 |
70 | )
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/app/configs/__mocks__/ajax.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 | import fetchUserList from '../../mocks/apis/sys/userManage/fetchUserList';
3 | import fetchUserDepttList from '../../mocks/apis/sys/userManage/fetchUserDepttList';
4 | import fetchButtonList from '../../mocks/apis/sys/roleManage/fetchButtonList';
5 | import fetchRoleList from '../../mocks/apis/sys/userManage/fetchRoleList';
6 | import fetchTreeList from '../../mocks/apis/sys/roleManage/fetchTreeList';
7 | import fetchModuleListInRole from '../../mocks/apis/sys/roleManage/fetchModuleListInRole';
8 |
9 | // 创建发起api的启动器
10 | export const createApi = function (api, type) {
11 | fetchUserList.data.totalCount = null;
12 | if (type == 'fetchUserList') {
13 | return backState(fetchUserList);
14 | }
15 | if (type == 'fetchUserDepttList') {
16 | return backState(fetchUserDepttList);
17 | }
18 | if (type == 'fetchButtonList') {
19 | return backState(fetchButtonList);
20 | }
21 | if (type == 'fetchRoleList') {
22 | return backState(fetchRoleList);
23 | }
24 | if (type == 'fetchTreeList') {
25 | return backState(fetchTreeList);
26 | }
27 | fetchModuleListInRole.data.list[0].status = true;
28 | if (type == 'fetchModuleListInRole') {
29 | return backState(fetchModuleListInRole);
30 | }
31 | const param = {
32 | data: {
33 | list: [],
34 | },
35 | msg: '操作成功',
36 | status: 1,
37 | };
38 | return backState(param);
39 | };
40 | function backState(param) {
41 | return (data, callback, callback2) => {
42 | callback(param);
43 | if (callback2) {
44 | callback2(param);
45 | }
46 | };
47 | }
48 |
--------------------------------------------------------------------------------
/app/configs/common.js:
--------------------------------------------------------------------------------
1 |
2 | import { hashHistory } from 'react-router'
3 | import { message } from 'antd'
4 | import { loginByTicket, staff, login as loginApi, getBtns } from '@apis/common'
5 |
6 | export function parseQueryString(url) {
7 | const obj = {}
8 | if (url.indexOf('?') !== -1) {
9 | const str = url.split('?')[1]
10 | const strs = str.split('&')
11 | strs.map((item, i) => {
12 | const arr = strs[i].split('=')
13 | /* eslint-disable */
14 | obj[arr[0]] = arr[1]
15 | })
16 | }
17 | return obj
18 | }
19 |
20 | /* --------------验证ticket并获取用户信息和菜单信息 --------------*/
21 | const _fetchLoginByTicket = async ticket => new Promise((resolve) => {
22 | loginByTicket({ ticket }, (response) => {
23 | resolve(response.data)
24 | }, (response) => {
25 | const obj = parseQueryString(window.location.href)
26 | console.log(obj)
27 | if (obj.ticket || obj.mode) {
28 | message.info('登录过期或服务不可用')
29 | } else {
30 | hashHistory.replace('/login')
31 | }
32 | })
33 | })
34 |
35 | const _fetchStaff = () => new Promise((resolve) => {
36 | staff({}, (res) => {
37 | const { data } = res
38 | sessionStorage.setItem('userinfo', JSON.stringify(data))
39 | resolve()
40 | })
41 | })
42 |
43 | /* eslint-disable no-use-before-define */
44 | export const isHasCurrentMenu = (allMenu, pathname) => compare(allMenu, pathname)
45 | /* eslint-enable no-use-before-define */
46 |
47 |
48 | const _fetchNav = pathname => new Promise((resolve) => {
49 | // try {
50 | // if (JSON.parse(sessionStorage.getItem('menu')).length > 0) {
51 | // resolve()
52 | // return
53 | // }
54 | // } catch (e) { e }
55 | nav({}, (response) => {
56 | const { list } = response.data
57 | if (list.length === 0) {
58 | message.info('该账户没有任何菜单权限,请联系管理员')
59 | hashHistory.replace('/login')
60 | // this.setState({ loading: false })
61 | return
62 | }
63 | sessionStorage.setItem('menu', JSON.stringify(list))
64 | // TODO:添加完菜单权限后,需要增加以下代码
65 | // if (pathname !== '/' && !isHasCurrentMenu(list, pathname)) {
66 | // if (process.env.NODE_ENV === 'production') {
67 | // hashHistory.replace('/')
68 | // }
69 | // }
70 | resolve()
71 | })
72 | })
73 |
74 | /* 不管是否含有ticket参数都会在顶层组件中调用 */
75 | export const validateTickit = async function validateTickit({ query, pathname }, callback) {
76 | const { ticket } = query
77 | if (ticket) {
78 | const loginInfo = await _fetchLoginByTicket(ticket)
79 | sessionStorage.setItem('token', loginInfo.token)
80 | // sessionStorage.setItem('isLeftNavMini', false)
81 | } else {
82 | /**
83 | * 仅存在于以下两种情况:
84 | * 1. 未登录,退出到登录页面进行登录操作,在登录时获取菜单并存到sessionStorage中,再进行页面跳转,执行此代码时只需要请求staff信息
85 | * 2. 登录过,刷新页面后执行此代码,认为上次登录时已经获取过菜单并已存到sessionStorage中,所以只需要请求staff信息
86 | * (FIXME:网速缓慢的情况下,可能存在登录token拿到后,菜单数据返回前,直接输入url访问页面的情况,所以会导致获取不到菜单)
87 | */
88 | // await _fetchStaff()
89 | // if (typeof callback === 'function')callback()
90 | /*
91 | _fetchStaff()
92 | _fetchNav(callback)
93 | */
94 | }
95 |
96 | const _a = _fetchStaff()
97 | const _b = _fetchNav(pathname)
98 | await _a
99 | await _b
100 | if (typeof callback === 'function') callback()
101 | }
102 | /* -----------------------------------------------------------------------------*/
103 |
104 | /* -------------- 存储当前页面的菜单id到sessionStorage的menuId属性上 --------------*/
105 | // 比较方法
106 | function compare(children, pathname) {
107 | for (let i = 0; i < children.length; i += 1) {
108 | const item = children[i]
109 | /* eslint-disable no-useless-escape */
110 | const _resKey = `${item.resKey.replace(/[\$\.\?\+\^\[\]\(\)\{\}\|\\\/]/g, '\\$&').replace(/\*\*/g, '[\\w|\\W]+').replace(/\*/g, '[^\\/]+')}$`
111 | /* eslint-enable no-useless-escape */
112 | if (new RegExp(_resKey).test(pathname)) {
113 | sessionStorage.setItem('menuId', item.id)
114 | return true
115 | } else if (item.children) {
116 | if (compare(item.children, pathname)) return true
117 | }
118 | }
119 | return false
120 | }
121 |
122 | // 获取菜单id
123 | export const getMenuId = (navs, pathname) => {
124 | if (navs && navs.length > 0) {
125 | compare(navs, pathname)
126 | }
127 | }
128 | /* -----------------------------------------------------------------------------*/
129 |
130 | /* ------------------------- 登陆 -------------------------*/
131 | export const login = (params, success, failure) => {
132 | loginApi(params, (response) => {
133 | sessionStorage.setItem('token', response.data.token)
134 | localStorage.setItem('sessionStorage', JSON.stringify(sessionStorage))
135 | // _fetchNav().then(() => { success() })
136 | if (typeof success === 'function') success(response)
137 | }, (response) => {
138 | if (typeof failure === 'function') failure(response)
139 | })
140 | }
141 | /* -------------------------------------------------------*/
142 |
143 | // 获取按钮
144 | export const fetchBtns = (component, cb) => {
145 | getBtns({ id: sessionStorage.getItem('menuId') }, (res) => {
146 | const result = {}
147 | res.data.list.map((item) => {
148 | result[item.resKey] = true
149 | })
150 | typeof (cb) === 'function' ? cb(result) : ''
151 | })
152 | }
153 |
154 | // 进入路由的判断
155 | export const isLogin = (nextState, replaceState) => {
156 | if (nextState.location.query && nextState.location.query.ticket) { // 如果url自带ticket
157 | sessionStorage.setItem('token', 'ticket')
158 | }
159 | if (nextState.location.query && nextState.location.query.key) { // 如果url自带key
160 | sessionStorage.setItem('token', 'key')
161 | }
162 | const token = sessionStorage.getItem('token')
163 | if (!token) { // 没有token,那就返回首页
164 | replaceState('/login')
165 | }
166 | }
167 |
168 |
169 | // 异步请求需要走redux的方式
170 | export const createAjaxAction = (createdApi, startAction, endAction) => (request = {}, resolve, reject, config) => (dispatch) => {
171 | if (startAction) dispatch(startAction({ req: request, res: {} }))
172 | const _resolve = (response) => {
173 | if (endAction) dispatch(endAction({ req: request, res: response }))
174 | if (resolve) resolve(response)
175 | }
176 | return createdApi(request, _resolve, reject, config)
177 | }
178 |
--------------------------------------------------------------------------------
/app/configs/config.js:
--------------------------------------------------------------------------------
1 |
2 | export const set = 'set$'
3 | export const brandName = 'React' // slogan
4 |
5 | // 开发环境默认配置
6 | let _serverIp = 'http://192.168.1.222'
7 | let _port = '1111'
8 | let _baseURL = `${_serverIp}:${_port}`
9 | let _mockURL = 'http://localhost:1111/'
10 |
11 | if (process.env.NODE_ENV === 'testing') { // 测试环境
12 | _mockURL = 'http://localhost:1111/'
13 | _port = '1111'
14 | _baseURL = `${_serverIp}:${_port}`
15 | }
16 | if (process.env.NODE_ENV === 'production') { // 发布环境
17 | _port = '1111'
18 | _serverIp = 'http://192.168.1.123'
19 | _baseURL = `${_serverIp}:${_port}`
20 | }
21 |
22 | export const serverIp = _serverIp
23 | export const path = '/mock'
24 | export const timeout = '15000' // 接口超时限制(ms)
25 | export const baseURL = _baseURL
26 | export const mockURL = _mockURL
27 |
--------------------------------------------------------------------------------
/app/configs/regular.config.js:
--------------------------------------------------------------------------------
1 | // 常用的正则规则
2 | // eslint-disable-next-line
3 | export const regExpConfig = {
4 | IDcard: /^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$|^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/, // 身份证
5 | mobile: /^1([3|4|5|7|8|])\d{9}$/, // 手机号码
6 | telephone: /^(\(\d{3,4}\)|\d{3,4}-|\s)?\d{7,14}$/, // 固定电话
7 | num: /^[0-9]*$/, // 数字
8 | phoneNo: /(^1([3|4|5|7|8|])\d{9}$)|(^(\(\d{3,4}\)|\d{3,4}-|\s)?\d{7,14}$)/, // 电话或者手机
9 | policeNo: /^[0-9A-Za-z]{4,10}$/, // 账号4-10位数字或字母组成
10 | pwd: /^[0-9A-Za-z]{6,16}$/, // 密码由6-16位数字或者字母组成
11 | isNumAlpha: /^[0-9A-Za-z]*$/, // 字母或数字
12 | isAlpha: /^[a-zA-Z]*$/, // 是否字母
13 | isNumAlphaCn: /^[0-9a-zA-Z\u4E00-\uFA29]*$/, // 是否数字或字母或汉字
14 | isPostCode: /^[\d-]*$/i, // 是否邮编
15 | isNumAlphaUline: /^[0-9a-zA-Z_]*$/, // 是否数字、字母或下划线
16 | isNumAndThanZero: /^([1-9]\d*(\.\d+)?|0)$/, // 是否为整数且大于0/^[1-9]\d*(\.\d+)?$/
17 | isNormalEncode: /^(\w||[\u4e00-\u9fa5]){0,}$/, // 是否为非特殊字符(包括数字字母下划线中文)
18 | isTableName: /^[a-zA-Z][A-Za-z0-9#$_-]{0,29}$/, // 表名
19 | isInt: /^-?\d+$/, // 整数
20 | isTableOtherName: /^[\u4e00-\u9fa5]{0,20}$/, // 别名
21 | // isText_30: /^(\W|\w{1,2}){0,15}$/, // 正则
22 | // isText_20: /^(\W|\w{1,2}){0,10}$/, // 正则
23 | isText_30: /^(\W|\w{1}){0,30}$/, // 匹配30个字符,字符可以使字母、数字、下划线、非字母,一个汉字算1个字符
24 | isText_50: /^(\W|\w{1}){0,50}$/, // 匹配50个字符,字符可以使字母、数字、下划线、非字母,一个汉字算1个字符
25 | isText_20: /^(\W|\w{1}){0,20}$/, // 匹配20个字符,字符可以使字母、数字、下划线、非字母,一个汉字算1个字符
26 | isText_100: /^(\W|\w{1}){0,100}$/, // 匹配100个字符,字符可以使字母、数字、下划线、非字母,一个汉字算1个字符
27 | isText_250: /^(\W|\w{1}){0,250}$/, // 匹配250个字符,字符可以使字母、数字、下划线、非字母,一个汉字算1个字符
28 | isNotChina: /^[^\u4e00-\u9fa5]{0,}$/, // 不为中文 IDcard: /^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$|^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/, // 身份证
29 | IDcardAndAdmin: /^(([1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$|^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X))|(admin))$/, // 身份证或者是admin账号
30 | IDcardTrim: /^\s*(([1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3})|([1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X))|(admin))\s*$/, // 身份证
31 | num1: /^[1-9]*$/, // 数字
32 | companyNO: /^qqb_[0-9a-zA-Z_]{1,}$/, // 公司人员账号
33 | imgType: /image\/(png|jpg|jpeg|gif)$/, // 上传图片类型
34 | isChina: /^[\u4e00-\u9fa5]{2,8}$/,
35 | isNozeroNumber: /^\+?[1-9]\d*$/, // 大于零的正整数
36 | float: /^\d+(\.?|(\.\d+)?)$/, // 匹配正整数或者小数 或者0.这个特殊值
37 | }
38 |
39 |
--------------------------------------------------------------------------------
/app/configs/router.config.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Router, Route, IndexRoute, hashHistory/* , Redirect */ } from 'react-router'
3 | import { isLogin } from '@configs/common'
4 | import { set } from '@config'
5 |
6 | import * as base from '@pages/base' // 基础
7 | import * as sysSet from '@pages/set' // 设置中心-系统设置
8 | import * as menu from '@pages/menu' // 菜单
9 |
10 | export default () => (
11 |
12 |
13 |
14 |
15 | {/* */}
16 | {/** *菜单 开始 */}
17 |
18 |
19 | {/** *菜单 结束 */}
20 | {/** *系统设置 开始 */}
21 |
22 |
23 |
24 | {/** *系统设置 结束 */}
25 |
26 |
27 |
28 |
29 | )
30 |
--------------------------------------------------------------------------------
/app/configs/socket.js:
--------------------------------------------------------------------------------
1 | import io from 'socket.io-client';
2 | // import queryString from 'query-string';
3 |
4 | // const parsed = queryString.parse(window.location.search);
5 |
6 | class Socket {
7 | constructor(ua = 'control', disable = false) {
8 | this.uid = this.random();
9 | // this.group = parsed.group || 'prod';
10 | this.disable = disable;
11 | this.socket = io('http://47.102.198.102:8080/', {
12 | transports: ['websocket'],
13 | query: {
14 | ua,
15 | group: 'prod',
16 | },
17 | });
18 | this.isSpeaker = false;
19 | this.speakerHandlers = [];
20 |
21 | this.socket.on('room', ({ speaker }) => {
22 | this.isSpeaker = speaker === this.socket.id;
23 | this.speakerHandlers.forEach((cb) => {
24 | if (typeof cb === 'function') {
25 | cb(this.isSpeaker);
26 | }
27 | });
28 | });
29 | }
30 |
31 | random = () => Date.now() + Math.random();
32 |
33 | registerSpeakerHandler = (callback) => {
34 | this.unregisterSpeakerHandler(callback);
35 | this.speakerHandlers.push(callback);
36 | };
37 |
38 | unregisterSpeakerHandler = (callback) => {
39 | let i = -1;
40 | this.speakerHandlers.some((cb, index) => {
41 | if (cb === callback) {
42 | i = index;
43 | return true;
44 | }
45 | return false;
46 | });
47 | if (i >= 0) {
48 | this.speakerHandlers.splice(i, 1);
49 | }
50 | };
51 |
52 | dispatch = (data) => {
53 | // if (!this.isSpeaker && !data.speaker) {
54 | // return Promise.resolve();
55 | // }
56 |
57 | data.uid = this.uid;
58 | data.timestamp = this.random();
59 | this.socket.emit('dispatch', data);
60 | if (data.speaker) {
61 | return new Promise((resolve, reject) => {
62 | this.registerSpeakerHandler((r) => {
63 | if (r) {
64 | resolve();
65 | } else {
66 | reject();
67 | }
68 | });
69 | });
70 | }
71 | return new Promise((resolve) => {
72 | const callback = (res) => {
73 | if (this.uid === res.uid && res.timestamp === data.timestamp) {
74 | this.socket.off('dispatch', callback);
75 | resolve();
76 | }
77 | };
78 | this.socket.on('dispatch', callback);
79 | });
80 | };
81 |
82 | sent = (data, force) => {
83 | if (!this.isSpeaker && !force) {
84 | return;
85 | }
86 | data.uid = this.uid;
87 | data.group = this.group;
88 | this.socket.emit('msg', data);
89 | };
90 |
91 | on = (name, call) => {
92 | if (!this.disable) {
93 | this.socket.on(name, call);
94 | }
95 | };
96 |
97 | close = () => {
98 | this.socket.close();
99 | };
100 |
101 | send = (data) => {
102 | this.dispatch({
103 | source: 'control',
104 | targets: ['control'],
105 | type: 'dispatch',
106 | payload: data,
107 | })
108 | }
109 | }
110 |
111 | const socket = new Socket('control', window.location.pathname === '/console');
112 | export const MsgSocket = Socket;
113 |
114 | export default socket;
115 |
--------------------------------------------------------------------------------
/app/images/default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/react_duxian/ff78ec236fe39fb59835141477240842d04494dc/app/images/default.png
--------------------------------------------------------------------------------
/app/images/icon/menu/default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/react_duxian/ff78ec236fe39fb59835141477240842d04494dc/app/images/icon/menu/default.png
--------------------------------------------------------------------------------
/app/images/icon/menu/icon_duty.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/react_duxian/ff78ec236fe39fb59835141477240842d04494dc/app/images/icon/menu/icon_duty.png
--------------------------------------------------------------------------------
/app/images/icon/menu/icon_pgmb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/react_duxian/ff78ec236fe39fb59835141477240842d04494dc/app/images/icon/menu/icon_pgmb.png
--------------------------------------------------------------------------------
/app/images/icon/menu/icon_pgmx.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/react_duxian/ff78ec236fe39fb59835141477240842d04494dc/app/images/icon/menu/icon_pgmx.png
--------------------------------------------------------------------------------
/app/images/icon/menu/icon_statistics.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/react_duxian/ff78ec236fe39fb59835141477240842d04494dc/app/images/icon/menu/icon_statistics.png
--------------------------------------------------------------------------------
/app/images/icon/menu/icon_xtxg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/react_duxian/ff78ec236fe39fb59835141477240842d04494dc/app/images/icon/menu/icon_xtxg.png
--------------------------------------------------------------------------------
/app/images/icon/menu/moduleManage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/react_duxian/ff78ec236fe39fb59835141477240842d04494dc/app/images/icon/menu/moduleManage.png
--------------------------------------------------------------------------------
/app/images/icon/menu/roleManage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/react_duxian/ff78ec236fe39fb59835141477240842d04494dc/app/images/icon/menu/roleManage.png
--------------------------------------------------------------------------------
/app/images/icon/menu/userManage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/react_duxian/ff78ec236fe39fb59835141477240842d04494dc/app/images/icon/menu/userManage.png
--------------------------------------------------------------------------------
/app/images/login.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/react_duxian/ff78ec236fe39fb59835141477240842d04494dc/app/images/login.png
--------------------------------------------------------------------------------
/app/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/react_duxian/ff78ec236fe39fb59835141477240842d04494dc/app/images/logo.png
--------------------------------------------------------------------------------
/app/images/navcontrol.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/react_duxian/ff78ec236fe39fb59835141477240842d04494dc/app/images/navcontrol.png
--------------------------------------------------------------------------------
/app/images/photo_default.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/react_duxian/ff78ec236fe39fb59835141477240842d04494dc/app/images/photo_default.jpg
--------------------------------------------------------------------------------
/app/images/user.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/react_duxian/ff78ec236fe39fb59835141477240842d04494dc/app/images/user.jpg
--------------------------------------------------------------------------------
/app/images/user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/react_duxian/ff78ec236fe39fb59835141477240842d04494dc/app/images/user.png
--------------------------------------------------------------------------------
/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
React
6 |
7 |
8 |
9 | <% for(var i = 0; i < htmlWebpackPlugin.options.dlls.length;i++){%>
10 |
11 | <%}%>
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/middleware/configureStore.js:
--------------------------------------------------------------------------------
1 |
2 | import { createStore, applyMiddleware } from 'redux'
3 | import thunkMiddleware from 'redux-thunk'
4 | import rootReducer from '@reducers'
5 | import { logger, /* router, */ reduxRouterMiddleware } from './index'
6 |
7 | const nextReducer = require('@reducers')
8 |
9 | export default function configure(initialState) {
10 | // console.log('initialState', initialState)
11 | const create = window.devToolsExtension
12 | ? window.devToolsExtension()(createStore)
13 | : createStore
14 |
15 | const createStoreWithMiddleware = applyMiddleware(
16 | reduxRouterMiddleware,
17 | thunkMiddleware,
18 | logger,
19 | // router,
20 | )(create)
21 |
22 | const store = createStoreWithMiddleware(rootReducer, initialState)
23 |
24 | if (module.hot) {
25 | module.hot.accept('@reducers', () => {
26 | store.replaceReducer(nextReducer)
27 | })
28 | }
29 |
30 | return store
31 | }
32 |
--------------------------------------------------------------------------------
/app/middleware/history.js:
--------------------------------------------------------------------------------
1 | import { useRouterHistory } from 'react-router'
2 | import createHashHistory from 'history/lib/createHashHistory'
3 |
4 | // export default useRouterHistory(createHashHistory)()
5 | const history = useRouterHistory(createHashHistory)({})
6 | export default history
7 |
--------------------------------------------------------------------------------
/app/middleware/index.js:
--------------------------------------------------------------------------------
1 |
2 | import { routerMiddleware } from 'react-router-redux'
3 | import logger from './logger'
4 | import history from './history'
5 | // import router from './router'
6 |
7 | const reduxRouterMiddleware = routerMiddleware(history)
8 |
9 | export {
10 | reduxRouterMiddleware,
11 | logger,
12 | // router,
13 | }
14 |
--------------------------------------------------------------------------------
/app/middleware/logger.js:
--------------------------------------------------------------------------------
1 |
2 | /* eslint-disable */
3 | export default store => next => (action) => {
4 | // console.log(action)
5 | return next(action)
6 | }
7 |
--------------------------------------------------------------------------------
/app/middleware/router.js:
--------------------------------------------------------------------------------
1 | import { browserHistory } from 'react-router'
2 | import { routerMiddleware } from 'react-router-redux'
3 |
4 | export default routerMiddleware(browserHistory)
5 |
--------------------------------------------------------------------------------
/app/mocks/apis/base/index.js:
--------------------------------------------------------------------------------
1 | const login = require('./login')
2 | const logout = require('./logout')
3 | const staff = require('./staff')
4 | const menu = require('./menu')
5 |
6 | module.exports = { login, logout, staff, menu }
7 |
--------------------------------------------------------------------------------
/app/mocks/apis/base/login.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | data: {
3 | ticket: 'ticket',
4 | token: '1111',
5 | },
6 | msg: '操作成功',
7 | status: 1,
8 | }
9 |
--------------------------------------------------------------------------------
/app/mocks/apis/base/logout.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = {
3 | data: {
4 | },
5 | msg: '退出成功!',
6 | status: 1,
7 | }
8 |
--------------------------------------------------------------------------------
/app/mocks/apis/base/menu.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = {
3 | data: {
4 | list: [
5 |
6 | {
7 | id: 10063,
8 | resName: '概览',
9 | resKey: 'desk$/index',
10 | resIcon: 'pgmb',
11 | },
12 | // {
13 | // id: 10064,
14 | // resName: 'socket接收',
15 | // resKey: 'socketReceive',
16 | // resIcon: 'pgmb',
17 | // },
18 | {
19 | id: 600110233,
20 | resName: '图表',
21 | resKey: 'echarts',
22 | resIcon: 'statistics',
23 | },
24 | {
25 | id: 100631,
26 | resName: '编辑器',
27 | resKey: 'editor',
28 | resIcon: 'duty',
29 | },
30 |
31 | {
32 | id: 10062,
33 | resName: '设置中心',
34 | children: [
35 | {
36 | id: 10108,
37 | resName: '用户管理',
38 | resKey: 'set$/userManage',
39 | resIcon: 'userManage',
40 | },
41 | {
42 | id: 10109,
43 | resName: '角色管理',
44 | resKey: 'set$/roleManage',
45 | resIcon: 'roleManage',
46 | },
47 | {
48 | id: 10110,
49 | resName: '权限管理',
50 | resKey: 'set$/moduleManage',
51 | resIcon: 'moduleManage',
52 | },
53 | ],
54 | resKey: 'set$',
55 | resIcon: 'xtxg',
56 | },
57 | ],
58 | },
59 | msg: '操作成功',
60 | status: 1,
61 | }
62 |
--------------------------------------------------------------------------------
/app/mocks/apis/base/staff.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = {
3 | data: {
4 | id: 1,
5 | username: 'admin',
6 | password: '121212',
7 | chineseName: '管理员',
8 | idcardNo: '000000000000000000',
9 | policeCode: '000000',
10 | deptCode: '370200000000',
11 | gender: 1,
12 | email: 'abc@abc.com',
13 | phoneNo: '15100000005',
14 | duty: '超级管理员',
15 | address: 'address',
16 | remark: 'remarl',
17 | type: 0,
18 | status: 0,
19 | roles: [
20 | {
21 | id: 1,
22 | roleName: '超级管理员',
23 | resources: [],
24 | },
25 | ],
26 | deptName: '杭州市',
27 | ticket: '.2XxGlEuidOmAoYIdSo6pQIlGbQSh83U7p4eJsoTO-70',
28 | gxdwdm: '370200000000',
29 | deptLevel: '1',
30 | defaultDeptCode: '370200000000',
31 | defaultXzqhCode: '370200',
32 | },
33 | msg: '操作成功',
34 | status: 1,
35 | }
36 |
--------------------------------------------------------------------------------
/app/mocks/apis/fail.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = {
3 | data: {
4 |
5 | },
6 | msg: '操作失败',
7 | status: 0,
8 | }
9 |
--------------------------------------------------------------------------------
/app/mocks/apis/success.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = {
3 | data: {
4 |
5 | },
6 | msg: '操作成功',
7 | status: 1,
8 | }
9 |
--------------------------------------------------------------------------------
/app/mocks/apis/sys/moduleManage/fetchModuleDetail.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = {
3 | data: {
4 | id: 2,
5 | resName: '基础信息',
6 | resType: 1,
7 | resModule: 'inedx',
8 | resKey: 'menu2',
9 | resIcon: 'null',
10 | sort: 1,
11 | status: 0,
12 | },
13 | msg: '操作成功',
14 | status: 1,
15 | }
16 |
--------------------------------------------------------------------------------
/app/mocks/apis/sys/moduleManage/fetchModuleList.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = {
3 | data: {
4 | list: [
5 | {
6 | id: 10060,
7 | resName: '工作台',
8 | children: [
9 | {
10 | id: 10063,
11 | resName: '概览',
12 | resKey: 'desk$/index',
13 | resIcon: 'cleanAccess',
14 | },
15 | ],
16 | resKey: 'desk$',
17 | resIcon: 'home',
18 | },
19 | {
20 | id: 10062,
21 | resName: '设置中心',
22 | children: [
23 | {
24 | id: 10108,
25 | resName: '用户管理',
26 | resKey: 'set$/userManage',
27 | resIcon: 'userManage',
28 | },
29 | {
30 | id: 10109,
31 | resName: '角色管理',
32 | resKey: 'set$/roleManage',
33 | resIcon: 'roleManage',
34 | },
35 | {
36 | id: 10110,
37 | resName: '权限管理',
38 | resKey: 'set$/moduleManage',
39 | resIcon: 'unitCount',
40 | },
41 | ],
42 | resKey: 'set$',
43 | resIcon: 'set',
44 | },
45 | ],
46 | },
47 | msg: '操作成功',
48 | status: 1,
49 | }
50 |
--------------------------------------------------------------------------------
/app/mocks/apis/sys/moduleManage/index.js:
--------------------------------------------------------------------------------
1 | const fetchModuleList = require('./fetchModuleList')
2 | const fetchModuleDelete = require('../../success')
3 | const fetchModuleDetail = require('./fetchModuleDetail')
4 | const fetchChangeModuleStatus = require('../../success')
5 | const fetchModuleUpdateDetail = require('../../success')
6 | const fetchModuleAdd = require('../../success')
7 |
8 |
9 | module.exports = {
10 | fetchModuleList,
11 | fetchModuleDelete,
12 | fetchModuleDetail,
13 | fetchChangeModuleStatus,
14 | fetchModuleUpdateDetail,
15 | fetchModuleAdd,
16 | }
17 |
--------------------------------------------------------------------------------
/app/mocks/apis/sys/roleManage/fetchButtonList.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = {
3 | data: {
4 | list: [
5 | {
6 | id: 134,
7 | resName: '新增附属区苑',
8 | resType: 3,
9 | parentId: 4,
10 | roleEntities: [],
11 | resKey: 'gardenAdd',
12 | sort: 0,
13 | status: 0,
14 | },
15 | {
16 | id: 137,
17 | resName: '新增附属区苑1',
18 | resType: 3,
19 | parentId: 4,
20 | roleEntities: [],
21 | resKey: 'gardenAdd',
22 | sort: 0,
23 | status: 0,
24 | },
25 | ],
26 | },
27 | msg: '操作成功',
28 | status: 1,
29 | }
30 |
--------------------------------------------------------------------------------
/app/mocks/apis/sys/roleManage/fetchModuleListInRole.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | data: {
3 | list: [
4 | {
5 | id: 10060,
6 | resName: '工作台',
7 | children: [
8 | {
9 | id: 10063,
10 | resName: '概览',
11 | resKey: 'desk$/index',
12 | resIcon: 'cleanAccess',
13 | resType: 1,
14 | status: 0,
15 | parentId: 10060,
16 | },
17 | ],
18 | resKey: 'desk$',
19 | resIcon: 'home',
20 | resType: 1,
21 | status: 0,
22 | },
23 | {
24 | id: 10062,
25 | resName: '设置中心',
26 | children: [
27 | {
28 | id: 10108,
29 | resName: '用户管理',
30 | resKey: 'set$/userManage',
31 | resIcon: 'userManage',
32 | parentId: 10062,
33 | children: [
34 | {
35 | id: 11003,
36 | resName: '看看',
37 | resKey: 'desk$/index',
38 | resIcon: 'cleanAccess',
39 | parentId: 10108,
40 | children: [
41 | {
42 | id: 11004,
43 | resName: '测试',
44 | resKey: 'desk$/index',
45 | resIcon: 'cleanAccess',
46 | parentId: 11003,
47 | },
48 | ],
49 | },
50 | ],
51 | },
52 | {
53 | id: 10109,
54 | resName: '角色管理',
55 | resKey: 'set$/roleManage',
56 | resIcon: 'roleManage',
57 | parentId: 10062,
58 | },
59 | {
60 | id: 10110,
61 | resName: '权限管理',
62 | resKey: 'set$/moduleManage',
63 | resIcon: 'unitCount',
64 | parentId: 10062,
65 | },
66 | ],
67 | resKey: 'set$',
68 | resIcon: 'set',
69 | resType: 1,
70 | status: 0,
71 | },
72 | ],
73 | },
74 | msg: '',
75 | errorCode: '',
76 | status: 1,
77 | };
78 |
--------------------------------------------------------------------------------
/app/mocks/apis/sys/roleManage/fetchRoleDetail.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = {
3 | data: {
4 | id: 2,
5 | roleName: '超级管理员',
6 | sort: 0,
7 | type: 0,
8 | resourceIds: [
9 | 10060,
10 | 10063,
11 | 10062,
12 | 10108,
13 | 10109,
14 | 10110,
15 | ],
16 | },
17 | msg: '操作成功',
18 | errorCode: '',
19 | status: 1,
20 | }
21 |
--------------------------------------------------------------------------------
/app/mocks/apis/sys/roleManage/fetchTreeList.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | data: {
3 | list: [
4 | {
5 | id: 10060,
6 | resName: '工作台',
7 | children: [
8 | {
9 | id: 10063,
10 | resName: '概览',
11 | resKey: 'desk$/index',
12 | resIcon: 'cleanAccess',
13 | parentId: 10060,
14 | },
15 | ],
16 | resKey: 'desk$',
17 | resIcon: 'home',
18 | },
19 | {
20 | id: 10062,
21 | resName: '设置中心',
22 | children: [
23 | {
24 | id: 10108,
25 | resName: '用户管理',
26 | resKey: 'set$/userManage',
27 | resIcon: 'userManage',
28 | parentId: 10062,
29 | buttons: [
30 | {
31 | id: 432,
32 | resName: '上传照片',
33 | resType: 3,
34 | parentId: 427,
35 | resKey: 'upload',
36 | status: 0,
37 | },
38 | {
39 | id: 433,
40 | resName: '查看照片',
41 | resType: 3,
42 | parentId: 427,
43 | resKey: 'view',
44 | status: 0,
45 | },
46 | {
47 | id: 434,
48 | resName: '删除照片',
49 | resType: 3,
50 | parentId: 427,
51 | resKey: 'delete',
52 | status: 0,
53 | },
54 | ],
55 | },
56 | {
57 | id: 10109,
58 | resName: '角色管理',
59 | resKey: 'set$/roleManage',
60 | resIcon: 'roleManage',
61 | parentId: 10062,
62 | },
63 | {
64 | id: 10110,
65 | resName: '权限管理',
66 | resKey: 'set$/moduleManage',
67 | resIcon: 'unitCount',
68 | parentId: 10062,
69 | },
70 | ],
71 | resKey: 'set$',
72 | resIcon: 'set',
73 | },
74 | ],
75 | },
76 | msg: '',
77 | errorCode: '',
78 | status: 1,
79 | };
80 |
--------------------------------------------------------------------------------
/app/mocks/apis/sys/roleManage/index.js:
--------------------------------------------------------------------------------
1 | const fetchRoleAdd = require('../../success')
2 | const fetchRoleUpdate = require('../../success')
3 | const fetchRoleDelete = require('../../success')
4 | const fetchUpdateRoleRes = require('../../success')
5 | const fetchTreeList = require('./fetchTreeList')
6 | const fetchModuleListInRole = require('./fetchModuleListInRole')
7 | const fetchRoleDetail = require('./fetchRoleDetail')
8 | const fetchButtonList = require('./fetchButtonList')
9 | const fetchRoleDeletePeople = require('../../success')
10 | const fetchUpdateButton = require('../../success')
11 |
12 |
13 | module.exports = {
14 | fetchRoleAdd,
15 | fetchRoleUpdate,
16 | fetchRoleDelete,
17 | fetchUpdateRoleRes,
18 | fetchTreeList,
19 | fetchModuleListInRole,
20 | fetchRoleDetail,
21 | fetchButtonList,
22 | fetchRoleDeletePeople,
23 | fetchUpdateButton,
24 | }
25 |
--------------------------------------------------------------------------------
/app/mocks/apis/sys/userManage/fetchRoleList.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = {
3 | data: {
4 | list: [
5 | {
6 | id: 1,
7 | roleName: '超级管理员',
8 | sort: 0,
9 | type: 0,
10 | resources: [],
11 | },
12 | {
13 | id: 10080,
14 | roleName: '开发账号',
15 | sort: 2,
16 | resources: [],
17 | },
18 | {
19 | id: 10060,
20 | roleName: '测试',
21 | sort: 3,
22 | resources: [],
23 | },
24 | {
25 | id: 10100,
26 | roleName: '演示账号',
27 | sort: 3,
28 | resources: [],
29 | },
30 | ],
31 | },
32 | msg: '',
33 | errorCode: '',
34 | status: 1,
35 | }
36 |
--------------------------------------------------------------------------------
/app/mocks/apis/sys/userManage/fetchUserDepttList.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = {
3 | data: {
4 | list: [
5 | {
6 | id: '1',
7 | children: [
8 | {
9 | id: '10416',
10 | parentCode: '370200000000',
11 | children: [
12 | {
13 | id: '10541',
14 | parentCode: '370202000000',
15 | deptName: '文一路',
16 | deptCode: '370202140000',
17 | },
18 | {
19 | id: '10401',
20 | parentCode: '370202000000',
21 | deptName: '文二路',
22 | deptCode: '370202150000',
23 | },
24 | {
25 | id: '10398',
26 | parentCode: '370202000000',
27 | children: [
28 | {
29 | id: '10628',
30 | parentCode: '370202230000',
31 | deptName: '文三路',
32 | deptCode: '370202230001',
33 | },
34 | {
35 | id: '10629',
36 | parentCode: '370202230000',
37 | deptName: '文晖路',
38 | deptCode: '370202230002',
39 | },
40 | ],
41 | deptName: '古翠路',
42 | deptCode: '370202230000',
43 | },
44 | {
45 | id: '10537',
46 | parentCode: '370202000000',
47 | deptName: '丰潭路',
48 | deptCode: '370202240000',
49 | },
50 | ],
51 | deptName: '下城区',
52 | deptCode: '370202000000',
53 | },
54 | ],
55 | deptName: '杭州市',
56 | deptCode: '370200000000',
57 | },
58 | ],
59 | },
60 | msg: '',
61 | errorCode: '',
62 | status: 1,
63 | }
64 |
--------------------------------------------------------------------------------
/app/mocks/apis/sys/userManage/fetchUserDetail.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = {
3 | data: {
4 | id: 10240,
5 | username: 'tgramxs',
6 | password: '123456',
7 | chineseName: '销售部',
8 | idcardNo: '332527198010230505',
9 | deptCode: '370200000000',
10 | phoneNo: '18969784568',
11 | status: 0,
12 | roleIds: [
13 | 10100,
14 | ],
15 | gxdwdm: '370200000000',
16 | },
17 | msg: '',
18 | errorCode: '',
19 | status: 1,
20 | }
21 |
--------------------------------------------------------------------------------
/app/mocks/apis/sys/userManage/fetchUserList.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = {
3 | data: {
4 | pageSize: 10,
5 | pageNo: 1,
6 | totalCount: 10,
7 | list: [
8 | {
9 | id: 10240,
10 | username: 'tgramxs',
11 | password: '123456',
12 | chineseName: '销售部',
13 | idcardNo: '332527198010230505',
14 | deptCode: '370200000000',
15 | phoneNo: '18969784568',
16 | status: 0,
17 | roles: [
18 | {
19 | id: 10100,
20 | roleName: '演示账号',
21 | resources: [],
22 | },
23 | ],
24 | gxdwdm: '370200000000',
25 | },
26 | {
27 | id: 10198,
28 | username: 'qingdaosj',
29 | password: '888888',
30 | chineseName: '市局',
31 | idcardNo: '412722196302151222',
32 | deptCode: '370200000000',
33 | phoneNo: '15236985623',
34 | status: 1,
35 | roles: [
36 | {
37 | id: 1,
38 | roleName: '超级管理员',
39 | resources: [],
40 | },
41 | ],
42 | gxdwdm: '370200000000',
43 | },
44 | {
45 | id: 10184,
46 | username: 'sjsjsj',
47 | password: '888888',
48 | chineseName: '测试sj',
49 | idcardNo: '332623196801254521',
50 | deptCode: '370200000000',
51 | phoneNo: '15821456854',
52 | type: 0,
53 | status: 1,
54 | roles: [
55 | {
56 | id: 1,
57 | roleName: '超级管理员',
58 | resources: [],
59 | },
60 | ],
61 | gxdwdm: '370200000000',
62 | },
63 | {
64 | id: 10180,
65 | username: 'sj666',
66 | password: '888888',
67 | chineseName: 'sj-admin',
68 | idcardNo: '612527199310150000',
69 | deptCode: '370200000000',
70 | phoneNo: '15522223333',
71 | type: 0,
72 | status: 0,
73 | roles: [
74 | {
75 | id: 1,
76 | roleName: '超级管理员',
77 | resources: [],
78 | },
79 | ],
80 | gxdwdm: '370200000000',
81 | },
82 | {
83 | id: 10178,
84 | username: 'zhlsj1',
85 | password: '888888',
86 | chineseName: 'zhlsj1',
87 | idcardNo: '330881187609090044',
88 | deptCode: '370200000000',
89 | phoneNo: '13200000000',
90 | type: 0,
91 | status: 0,
92 | roles: [
93 | {
94 | id: 1,
95 | roleName: '超级管理员',
96 | resources: [],
97 | },
98 | ],
99 | gxdwdm: '370200000000',
100 | },
101 | {
102 | id: 10177,
103 | username: 'zhlsj',
104 | password: '888888',
105 | chineseName: 'zhlsj',
106 | idcardNo: '330881187609090033',
107 | deptCode: '370200000000',
108 | phoneNo: '15600000000',
109 | type: 0,
110 | status: 0,
111 | roles: [
112 | {
113 | id: 1,
114 | roleName: '超级管理员',
115 | resources: [],
116 | },
117 | ],
118 | gxdwdm: '370200000000',
119 | },
120 | {
121 | id: 2,
122 | username: '111111',
123 | password: '111111',
124 | chineseName: '管理员',
125 | idcardNo: '000000000000000001',
126 | policeCode: '000000',
127 | deptCode: '370200000000',
128 | gender: 1,
129 | email: 'abc@abc.com',
130 | phoneNo: '15100000000',
131 | type: 0,
132 | status: 0,
133 | gxdwdm: '370200000000',
134 | },
135 | ],
136 | totalPage: 1,
137 | },
138 | msg: '',
139 | errorCode: '',
140 | status: 1,
141 | }
142 |
--------------------------------------------------------------------------------
/app/mocks/apis/sys/userManage/index.js:
--------------------------------------------------------------------------------
1 | const fetchUserDepttList = require('./fetchUserDepttList')
2 | const fetchRoleList = require('./fetchRoleList')
3 | const fetchUserList = require('./fetchUserList')
4 | const fetchUserDetail = require('./fetchUserDetail')
5 | const fetchUserDetailUpdate = require('../../success')
6 | const fetchUserAdd = require('../../success')
7 | const fetchUserDelete = require('../../success')
8 | const fetchUserSetRole = require('../../success')
9 | const fetchChangeUserStatus = require('../../success')
10 | const synUser = require('../../success')
11 |
12 |
13 | module.exports = {
14 | fetchUserDepttList,
15 | fetchRoleList,
16 | fetchUserList,
17 | fetchUserDetail,
18 | fetchUserDetailUpdate,
19 | fetchUserAdd,
20 | fetchUserDelete,
21 | fetchUserSetRole,
22 | fetchChangeUserStatus,
23 | synUser,
24 | }
25 |
--------------------------------------------------------------------------------
/app/mocks/apis/tableList.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = {
3 | data: {
4 | totalCount: 100,
5 | currentPage: 1,
6 | pageSize: 10,
7 | 'list|10': [
8 | {
9 | 'id|+1': 1,
10 | 'status|1': [1, 2, 3],
11 | 'name|1': ['特朗普', '奥巴马', '老布什'],
12 | },
13 | ],
14 | },
15 | msg: '',
16 | errorCode: '',
17 | status: 1,
18 | }
19 |
--------------------------------------------------------------------------------
/app/mocks/http.js:
--------------------------------------------------------------------------------
1 | const http = require('http')
2 | const _map = require('./interfaceMap')
3 | const _filter = require('./interfaceFilter')
4 | const Mock = require('mockjs')
5 |
6 | http.createServer((req, res) => {
7 | res.writeHead(200, {
8 | 'Content-Type': 'application/json;charset=utf-8',
9 | 'Access-Control-Allow-Origin': req.headers.origin,
10 | 'Access-Control-Allow-Methods': '*',
11 | 'Access-Control-Allow-Headers': '*',
12 | 'Access-Control-Allow-Credentials': true,
13 | 'Cache-Control': 'no-cache,no-store', // clear cache
14 | })
15 | if (req.method === 'OPTIONS') {
16 | res.end(null)
17 | }
18 | if (req.method === 'POST') {
19 | let postData = ''
20 | req.addListener('data', dataBuffer => postData += dataBuffer)
21 | req.addListener('end', () => {
22 | console.log('url=>', req.url)
23 | postData = JSON.parse(postData)
24 | const originData = _map[req.url]
25 | ? Mock.mock(_map[req.url])
26 | : ''
27 | const data = typeof (_filter[req.url]) === 'function'
28 | ? _filter[req.url](originData, postData)
29 | : originData
30 | // const data = originData
31 | setTimeout(() => {
32 | res.end(JSON.stringify(data))
33 | }, parseInt(((Math.random() - 0.5) + 1) * 500, 10)) // 随机数
34 | })
35 | }
36 | }).listen(1111)
37 | console.log('listening port 1111')
38 |
--------------------------------------------------------------------------------
/app/mocks/interfaceFilter.js:
--------------------------------------------------------------------------------
1 | const suffix = '.json'
2 | const prefix = '/kjdsj'
3 |
4 | module.exports = {
5 | [`${prefix}/dataManage/buildingAddress/fetchHouseCheckList${suffix}`]: function (mockData, request) {
6 | let jd = 120.000000000001
7 | let wd = 36.26404109130858
8 | mockData.data.list = mockData.data.list.map((one) => {
9 | jd += 0.001
10 | wd += 0.0000000001
11 | return Object.assign({}, one, { jd: String(jd), wd: String(wd), jwd: `${jd},${wd}` })
12 | })
13 | return mockData
14 | },
15 | }
16 |
--------------------------------------------------------------------------------
/app/mocks/interfaceMap.js:
--------------------------------------------------------------------------------
1 |
2 | const path = '/mock'
3 |
4 | // #region
5 | const base = require('./apis/base') // 基础的接口
6 | const userManage = require('./apis/sys/userManage') // 用户管理
7 | const roleManage = require('./apis/sys/roleManage') // 角色管理
8 | const moduleManage = require('./apis/sys/moduleManage') // 模块管理
9 | // #endregion
10 |
11 | module.exports = {
12 | // #region 收起所有
13 |
14 | // #region 公用
15 | [`${path}/usercenter/login`]: base.login, // 登录
16 | [`${path}/usercenter/user/userMenu`]: base.menu, // 菜单
17 | [`${path}/usercenter/user/userInfo`]: base.staff, // 用户信息
18 | [`${path}/usercenter/logout`]: base.logout, // 退出
19 | // #endregion
20 |
21 | // #region 用户管理
22 | [`${path}/usercenter/role/list`]: userManage.fetchRoleList, // 角色列表
23 | [`${path}/usercenter/dept/list`]: userManage.fetchUserDepttList, // 部门列表
24 | [`${path}/usercenter/user/list`]: userManage.fetchUserList, // 用户列表
25 | [`${path}/usercenter/user/detail`]: userManage.fetchUserDetail, // 获取用户详情
26 | [`${path}/usercenter/user/update`]: userManage.fetchUserDetailUpdate, // 修改用户详情
27 | [`${path}/usercenter/user/save`]: userManage.fetchUserAdd, // 新增用户
28 | [`${path}/usercenter/user/synUser`]: userManage.synUser, // 新增用户
29 | [`${path}/usercenter/user/updateRole`]: userManage.fetchUserSetRole, // 修改用户角色
30 | [`${path}/usercenter/user/delete`]: userManage.fetchUserDelete, // 删除用户
31 | [`${path}/usercenter/user/updateStatus`]: userManage.fetchChangeUserStatus, // 设置用户是否冻结状态
32 | // #endregion
33 |
34 | // #region 角色管理
35 | [`${path}/usercenter/role/save`]: roleManage.fetchRoleAdd, // 保存角色
36 | [`${path}/usercenter/role/delete`]: roleManage.fetchRoleDelete, // 删除角色
37 | [`${path}/usercenter/role/update`]: roleManage.fetchRoleUpdate, // 角色编辑
38 | [`${path}/usercenter/role/resTree`]: roleManage.fetchTreeList, // 角色列表
39 | [`${path}/usercenter/role/resList`]: roleManage.fetchModuleListInRole, // 已选择的模块
40 | [`${path}/usercenter/role/detail`]: roleManage.fetchRoleDetail, // 已选择的菜单以及按钮
41 | [`${path}/usercenter/resource/button/list`]: roleManage.fetchButtonList, // 模块的按钮列表
42 | [`${path}/usercenter/user/removeRole`]: roleManage.fetchRoleDeletePeople, // 删除用户
43 | [`${path}/usercenter/role/updateButton`]: roleManage.fetchUpdateButton, // 更新按钮
44 | [`${path}/usercenter/role/updateRes`]: roleManage.fetchUpdateRoleRes, // 更新已选择模块
45 | // #endregion
46 |
47 | // #region 模块管理
48 | [`${path}/usercenter/resource/list`]: moduleManage.fetchModuleList, // 获取模块列表
49 | [`${path}/usercenter/resource/delete`]: moduleManage.fetchModuleDelete, // 删除模块
50 | [`${path}/usercenter/resource/detail`]: moduleManage.fetchModuleDetail, // 获取模块详情
51 | [`${path}/usercenter/resource/updateStatus`]: moduleManage.fetchChangeModuleStatus, // 修改模块显隐状态
52 | [`${path}/usercenter/resource/update`]: moduleManage.fetchModuleUpdateDetail, // 修改模块详情
53 | [`${path}/usercenter/resource/save`]: moduleManage.fetchModuleAdd, // 新增模块
54 | // #endregion
55 |
56 | // #endregion
57 | }
58 |
--------------------------------------------------------------------------------
/app/pages/base/app/leftNav.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { connect } from 'react-redux'
3 | import { hashHistory/* , Link */ } from 'react-router'
4 | // import { routerActions } from 'react-router-redux'
5 | import { Menu, Spin } from 'antd'
6 | // import { updateTabList } from '@actions/tabList'
7 | import { clearGformCache2 } from '@actions/common'
8 |
9 | const { SubMenu } = Menu
10 |
11 | @connect((state, props) => ({
12 | config: state.config,
13 | }))
14 | export default class LeftNav extends Component {
15 | constructor(props, context) {
16 | super(props, context)
17 |
18 | // const { pathname } = props.location
19 | this.state = {
20 | // current: pathname,
21 | openKeys: [],
22 | menuStyle: false,
23 | rootSubmenuKeys: [],
24 | menu: JSON.parse(sessionStorage.getItem('leftNav')) || [],
25 | }
26 | }
27 |
28 | componentDidMount() {
29 | this.init()
30 | }
31 |
32 | componentWillReceiveProps(nextProps) {
33 | if (this.props.location.pathname !== nextProps.location.pathname) {
34 | this.openKeys(nextProps.location.pathname)
35 | }
36 | }
37 |
38 | init = () => {
39 | this.openKeys(this.props.location.pathname)
40 | const { menu } = this.state
41 | const arr = []
42 | menu.map((item, index) => {
43 | arr.push(`sub${index + 1}`)
44 | })
45 | this.setState({ rootSubmenuKeys: arr })
46 | }
47 |
48 | // 确认当前要打开的菜单
49 | openKeys = (pathname) => {
50 | /*
51 | **计算要打开的以及菜单
52 | */
53 | const { menu } = this.state
54 | const curPath = `${pathname.split('$')[0]}`.replace('/', '')
55 | if (curPath === '') { // 如果是默认首页,那么就不用往下计算了
56 | this.setState({
57 | openKeys: ['sub1'],
58 | })
59 | return
60 | }
61 | let count = 0
62 |
63 | // 定义一个标签语句
64 | // eslint-disable-next-line
65 | jumpOut1:
66 | for (let i = 0; i < menu.length; i += 1) {
67 | const item = menu[i]
68 | count += 1
69 | if (item.resKey && curPath === item.resKey.split('$')[0].replace('/', '')) {
70 | // eslint-disable-next-line
71 | break jumpOut1
72 | } else if (item.children && item.children.length > 0) {
73 | // eslint-disable-next-line
74 | jumpOut2:
75 | for (let j = 0; j < item.children.length; j += 1) {
76 | const record = item.children[j]
77 | if (item.resKey && curPath === record.resKey.split('$')[0].replace('/', '')) {
78 | // eslint-disable-next-line
79 | break jumpOut1
80 | }
81 | }
82 | }
83 | }
84 | this.setState({
85 | openKeys: [`sub${count - 1}`],
86 | })
87 | }
88 |
89 | // 菜单点击事件
90 | _handleClick = (e) => {
91 | this.props.dispatch(clearGformCache2({}))
92 | hashHistory.push(`/${e.key}`)
93 | }
94 |
95 | onOpenChange = (openKeys) => {
96 | const latestOpenKey = openKeys.find(key => this.state.openKeys.indexOf(key) === -1);
97 | if (this.state.rootSubmenuKeys.indexOf(latestOpenKey) === -1) {
98 | this.setState({ openKeys });
99 | } else {
100 | this.setState({
101 | openKeys: latestOpenKey ? [latestOpenKey] : [],
102 | })
103 | }
104 | }
105 |
106 | // 左侧菜单切换显示模式
107 | navMini = () => {
108 | this.setState({
109 | menuStyle: !this.state.menuStyle,
110 | }, () => {
111 | this.props.leftNavMode(this.state.menuStyle)
112 | })
113 | }
114 |
115 | // 二级菜单的生成
116 | renderLeftNav = (options) => {
117 | const { menu } = this.state
118 | return menu.map((item, index) => {
119 | if (!item.children || item.children.length === 0) {
120 | return (
121 |
122 |
123 | {item.resName}
124 |
125 | )
126 | }
127 | const key = `sub${index}`
128 | return (
129 |
132 |
133 | {item.resName}
134 |
135 | }
136 | >
137 | {
138 | item.children.map((child, _index) =>
139 | (
140 |
141 |
142 | {child.resName}
143 |
144 | ))
145 | }
146 |
147 | )
148 | })
149 | }
150 |
151 | // 左侧菜单高亮的控制
152 | leftMenuHighLight = () => {
153 | const { pathname } = this.props.location
154 | // console.log(pathname)
155 | let selectedKeys = [pathname.replace('/', '')]
156 | if (pathname === '/' || pathname.indexOf('desk$/index') > -1) {
157 | selectedKeys = ['desk$/index']
158 | }
159 | return selectedKeys
160 | }
161 |
162 | render() {
163 | const { openKeys, menuStyle } = this.state
164 | return (
165 |
166 |
184 |
185 | )
186 | }
187 | }
188 |
--------------------------------------------------------------------------------
/app/pages/base/app/modal/editPassword.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { connect } from 'react-redux'
3 | import { Button, Form, Input, /* Select, */ Modal, Row, Col, message } from 'antd'
4 | import { regExpConfig } from '@reg'
5 | import md5 from 'md5'
6 | import {
7 | fetchPassword,
8 | } from '@actions/common'
9 |
10 | const FormItem = Form.Item
11 | // const Option = Select.Option
12 |
13 | // 连接公用常量、后端返回的数据方法 并放置在props里面调用
14 | @connect((state, props) => ({
15 | config: state.config,
16 | }))
17 |
18 | @Form.create({})
19 |
20 | export default class index extends Component {
21 | constructor(props) {
22 | super(props)
23 | this.state = {
24 | confirmDirty: false,
25 | }
26 | this.handleSubmit = this.handleSubmit.bind(this)
27 | this.checkConfirm = this.checkConfirm.bind(this)
28 | this.checkPassword = this.checkPassword.bind(this)
29 | }
30 |
31 |
32 | // 组件已经加载到dom中
33 | componentDidMount() {
34 |
35 | }
36 |
37 | // 提交表单数据
38 | handleSubmit(e) {
39 | e.preventDefault()
40 | this.props.form.validateFields((errors, fieldsValue) => {
41 | if (errors) {
42 | return
43 | }
44 |
45 | if (fieldsValue.password) {
46 | // if (process.env.NODE_ENV === 'production') {
47 | // fieldsValue.password = fieldsValue.password
48 | // } else {
49 | fieldsValue.password = md5(fieldsValue.password)
50 | // }
51 | }
52 | const values = {
53 | oldPwd: fieldsValue.oldPwd ? fieldsValue.oldPwd : '',
54 | password: fieldsValue.password ? fieldsValue.password : '',
55 | };
56 | this.submitLoading = true
57 | this.props.dispatch(fetchPassword({
58 | ...values,
59 | }, (res) => {
60 | message.success(res.msg)
61 | this.submitLoading = false
62 | this.setState({})
63 | this.props.onCancel()
64 | }, (res) => {
65 | message.warning(res.msg)
66 | this.props.form.setFields({ oldPwd: '', password: '', confirm: '' })
67 | this.submitLoading = false
68 | this.setState({})
69 | }))
70 |
71 | // this.props.form.resetFields()
72 | });
73 | }
74 |
75 | checkPassword = (rule, value, callback) => {
76 | const { form } = this.props
77 | if (value && value !== form.getFieldValue('password')) {
78 | callback('两次输入的密码不一致')
79 | } else {
80 | callback()
81 | }
82 | }
83 |
84 | checkConfirm = (rule, value, callback) => {
85 | const { form } = this.props
86 | if (value && this.state.confirmDirty) {
87 | form.validateFields(['confirm'], { force: true })
88 | }
89 | callback()
90 | }
91 |
92 | // 弹窗的footer
93 | renderFooter() {
94 | return (
95 |
96 |
97 |
98 |
99 | )
100 | }
101 |
102 | render() {
103 | // const { imageUrl } = this.state
104 | const { getFieldDecorator } = this.props.form
105 | const formItemLayout = {
106 | labelCol: { span: 6 },
107 | wrapperCol: { span: 12 },
108 | hasFeedback: true,
109 | }
110 | return (
111 |
118 |
119 |
163 |
164 |
165 | )
166 | }
167 | }
168 |
--------------------------------------------------------------------------------
/app/pages/base/app/tabList.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { bindActionCreators } from 'redux'
3 | import { connect } from 'react-redux'
4 | import { routerActions } from 'react-router-redux'
5 | import { is } from 'immutable'
6 | import { Tabs } from 'antd'
7 | import { updateTabChecked, deleteTabFromList } from '@actions/tabList'
8 |
9 | const { TabPane } = Tabs
10 |
11 | @connect(
12 | (state, props) => ({ tabList: state.tabListResult }),
13 | dispatch => ({
14 | actions: bindActionCreators(routerActions, dispatch),
15 | dispatch: dispatch,
16 | }),
17 | )
18 | export default class TabList extends Component {
19 | constructor(props) {
20 | super(props)
21 | this.onChange = this.onChange.bind(this);
22 | this.onEdit = this.onEdit.bind(this);
23 | }
24 | componentDidMount() {
25 | // console.log('this.props', this.props);
26 | }
27 | onChange(activeKey) {
28 | const { actions } = this.props;
29 | this.props.dispatch(updateTabChecked({ activeKey: activeKey }))
30 | actions.push(activeKey)
31 | }
32 | onEdit(targetKey, action) {
33 | this[action](targetKey);
34 | }
35 | remove(targetKey) {
36 | const { actions, tabList } = this.props;
37 | let delIndex
38 | let activeKey
39 |
40 | if (targetKey === tabList.activeKey) {
41 | tabList.list.map((tab, index) => {
42 | // eslint-disable-next-line
43 | tab.key === targetKey ? delIndex = index : null;
44 | });
45 | // eslint-disable-next-line no-nested-ternary
46 | activeKey = tabList.list[delIndex + 1] ?
47 | tabList.list[delIndex + 1].key : (tabList.list[delIndex - 1] ?
48 | tabList.list[delIndex - 1].key : '');
49 | actions.push(activeKey);
50 | }
51 | this.props.dispatch(deleteTabFromList({ targetKey: targetKey }));
52 | }
53 | shouldComponentUpdate(nextProps, nextState) {
54 | const thisProps = this.props || {};
55 |
56 | if (Object.keys(thisProps).length !== Object.keys(nextProps).length) {
57 | return true;
58 | }
59 | // eslint-disable-next-line no-restricted-syntax
60 | for (const key in nextProps) {
61 | if (thisProps[key] !== nextProps[key] || !is(thisProps[key], nextProps[key])) {
62 | return true;
63 | }
64 | }
65 | return false;
66 | }
67 | render() {
68 | const { tabList } = this.props
69 | return (
70 |
77 | {
78 | tabList.list.map(tab =>
79 | {tab.content})
80 | }
81 |
82 | )
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/app/pages/base/developing.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { Progress } from 'antd'
3 |
4 | // 声明组件 并对外输出
5 | export default class developing extends Component {
6 | // 初始化页面常量 绑定事件方法
7 | constructor(props) {
8 | super(props)
9 | this.state = {
10 | // activeTab: 'pop' ,
11 | }
12 | }
13 |
14 |
15 | // 组件已经加载到dom中
16 | componentDidMount() {
17 |
18 | }
19 |
20 |
21 | render() {
22 | return (
23 |
24 |
32 | )
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/app/pages/base/example.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | // import PropTypes from 'prop-types'
3 | import { Button } from 'antd'
4 | // import {connect} from 'react-redux'
5 | // import {} from '@actions/xxx'
6 | // import Socket from '@configs/socket'
7 |
8 | // @connect((storeState)=>({}))
9 |
10 | export default class app extends Component {
11 | static defaultProps = {
12 | }
13 |
14 | static propTypes = {
15 | }
16 |
17 | constructor(props) {
18 | super(props)
19 | this.state = {}
20 | }
21 |
22 | componentDidMount() { }
23 |
24 | // #region vscode 1.17的收缩代码块功能 业务代码
25 |
26 |
27 | // #endregion
28 |
29 | // 发送socket数据
30 | onClickSend = () => {
31 | // Socket.send({ type: 'receive/hello3', data: { name: 'dupi' } })
32 | }
33 |
34 | render() {
35 | return (
36 |
37 | 示范页面
38 |
39 |
40 |
41 |
42 | )
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/app/pages/base/index.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | import developing from './developing'
4 | import example from './example'
5 | import login from './login'
6 | import notfound from './notfound'
7 | import app from './app'
8 | // import socketReceive from './socketReceive'
9 |
10 | export { developing, example, /* socketReceive, */ login, notfound, app }
11 |
--------------------------------------------------------------------------------
/app/pages/base/notfound.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | import { Link, hashHistory } from 'react-router'
3 | import { Progress, Button } from 'antd'
4 |
5 | // 声明组件 并对外输出
6 | export default class notfound extends Component {
7 | // 初始化页面常量 绑定事件方法
8 | constructor(props) {
9 | super(props)
10 | this.state = {
11 | // activeTab: 'pop' ,
12 | }
13 | }
14 |
15 | render() {
16 | return (
17 |
18 |
32 | )
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/app/pages/base/socket.js:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: hy
3 | * @Date: 2019-05-24 14:46:23
4 | * @Last Modified by: dupi
5 | * @Last Modified time: 2019-09-19 14:19:56
6 | */
7 |
8 | // socket on
9 |
10 | import React, { Component } from 'react'
11 | import socket from '@configs/socket'
12 | import { socketReceive } from '@actions/common'
13 | import { connect } from 'react-redux'
14 |
15 | @connect(() => ({}))
16 | export default class SocketOn extends Component {
17 | componentDidMount() {
18 | console.log('socket didmount')
19 | this.init()
20 | }
21 |
22 | init = () => {
23 | const callback = (res) => {
24 | this.props.dispatch(socketReceive(res))
25 | };
26 | socket.on('dispatch', callback);
27 | }
28 |
29 | render() {
30 | return null
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/app/pages/base/socketReceive.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | // import PropTypes from 'prop-types'
3 | import { Button } from 'antd'
4 | import { connect } from 'react-redux'
5 | // import {} from '@actions/xxx'
6 | // import Socket from '@configs/socket'
7 |
8 | @connect(store => ({
9 | // socketCollection: store.socketCollection,
10 | }))
11 |
12 | export default class app extends Component {
13 | static defaultProps = {
14 | }
15 |
16 | static propTypes = {
17 | }
18 |
19 | constructor(props) {
20 | super(props)
21 | this.state = {}
22 | }
23 |
24 | componentDidMount() { }
25 |
26 | // #region vscode 1.17的收缩代码块功能 业务代码
27 |
28 |
29 | // #endregion
30 |
31 | // 发送socket数据
32 | onClickSend = () => {
33 | // Socket.dispatch({ type: 'receive/hello2' })
34 | }
35 |
36 | render() {
37 | // const { socketCollection = {} } = this.props
38 | return (
39 |
40 | socket receive 页面示例
41 |
42 |
收到数据:
43 |
44 |
45 | {
46 | // JSON.stringify(socketCollection, null, 2)
47 | }
48 |
49 |
50 |
51 |
52 | )
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/app/pages/example.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 | // import PropTypes from 'prop-types'
3 | import { } from 'antd'
4 | // import {connect} from 'react-redux'
5 | // import {} from '@actions/xxx'
6 |
7 | // @connect((storeState)=>({}))
8 |
9 | export default class app extends Component {
10 | static defaultProps={
11 | }
12 |
13 | static propTypes = {
14 | }
15 |
16 | constructor(props) {
17 | super(props)
18 | this.state = {}
19 | }
20 |
21 | componentDidMount() {}
22 |
23 | // #region vscode 1.17的收缩代码块功能 业务代码
24 |
25 |
26 | // #endregion
27 |
28 | render() {
29 | return (
30 |
31 | 示范页面excample
32 |
33 | )
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/app/pages/menu/editor.js:
--------------------------------------------------------------------------------
1 |
2 | import React, { Component } from 'react'
3 | import { connect } from 'react-redux'
4 | import { Editor, EditorState, RichUtils } from 'draft-js'
5 | import 'draft-js/dist/Draft.css'
6 | import '@styles/RichEditor.less'
7 |
8 | // Custom overrides for "code" style.
9 | const styleMap = {
10 | CODE: {
11 | backgroundColor: 'rgba(0, 0, 0, 0.05)',
12 | fontFamily: '"Inconsolata", "Menlo", "Consolas", monospace',
13 | fontSize: 16,
14 | padding: 2,
15 | },
16 | }
17 |
18 | function getBlockStyle(block) {
19 | switch (block.getType()) {
20 | case 'blockquote': return 'RichEditor-blockquote';
21 | default: return null;
22 | }
23 | }
24 |
25 | @connect((state, props) => ({
26 | config: state.config,
27 | }))
28 | export default class app extends Component {
29 | constructor(props) {
30 | super(props);
31 | this.state = { editorState: EditorState.createEmpty() };
32 |
33 | this.focus = () => this.editor.focus()
34 | this.onChange = editorState => this.setState({ editorState });
35 |
36 | this.handleKeyCommand = this._handleKeyCommand.bind(this);
37 | this.onTab = this._onTab.bind(this);
38 | this.toggleBlockType = this._toggleBlockType.bind(this);
39 | this.toggleInlineStyle = this._toggleInlineStyle.bind(this);
40 | }
41 |
42 | _handleKeyCommand(command, editorState) {
43 | const newState = RichUtils.handleKeyCommand(editorState, command);
44 | if (newState) {
45 | this.onChange(newState);
46 | return true;
47 | }
48 | return false;
49 | }
50 |
51 | _onTab(e) {
52 | const maxDepth = 4;
53 | this.onChange(RichUtils.onTab(e, this.state.editorState, maxDepth));
54 | }
55 |
56 | _toggleBlockType(blockType) {
57 | this.onChange(RichUtils.toggleBlockType(
58 | this.state.editorState,
59 | blockType,
60 | ));
61 | }
62 |
63 | _toggleInlineStyle(inlineStyle) {
64 | this.onChange(RichUtils.toggleInlineStyle(
65 | this.state.editorState,
66 | inlineStyle,
67 | ));
68 | }
69 |
70 | render() {
71 | const { editorState } = this.state;
72 |
73 | // If the user changes block type before entering any text, we can
74 | // either style the placeholder or hide it. Let's just hide it now.
75 | let className = 'RichEditor-editor';
76 | const contentState = editorState.getCurrentContent();
77 | if (!contentState.hasText()) {
78 | if (contentState.getBlockMap().first().getType() !== 'unstyled') {
79 | className += ' RichEditor-hidePlaceholder';
80 | }
81 | }
82 |
83 | return (
84 |
85 |
89 |
93 |
94 | { this.editor = c }}
104 | spellCheck
105 | />
106 |
107 |
108 | );
109 | }
110 | }
111 |
112 |
113 | class StyleButton extends React.Component {
114 | constructor() {
115 | super();
116 | this.onToggle = (e) => {
117 | e.preventDefault();
118 | this.props.onToggle(this.props.style);
119 | };
120 | }
121 |
122 | render() {
123 | let className = 'RichEditor-styleButton';
124 | if (this.props.active) {
125 | className += ' RichEditor-activeButton';
126 | }
127 |
128 | return (
129 |
130 | {this.props.label}
131 |
132 | );
133 | }
134 | }
135 |
136 | const BLOCK_TYPES = [
137 | { label: 'H1', style: 'header-one' },
138 | { label: 'H2', style: 'header-two' },
139 | { label: 'H3', style: 'header-three' },
140 | { label: 'H4', style: 'header-four' },
141 | { label: 'H5', style: 'header-five' },
142 | { label: 'H6', style: 'header-six' },
143 | { label: 'Blockquote', style: 'blockquote' },
144 | { label: 'UL', style: 'unordered-list-item' },
145 | { label: 'OL', style: 'ordered-list-item' },
146 | { label: 'Code Block', style: 'code-block' },
147 | ];
148 |
149 | const BlockStyleControls = (props) => {
150 | const { editorState } = props;
151 | const selection = editorState.getSelection();
152 | const blockType = editorState
153 | .getCurrentContent()
154 | .getBlockForKey(selection.getStartKey())
155 | .getType();
156 |
157 | return (
158 |
159 | {BLOCK_TYPES.map(type =>
160 | ())}
167 |
168 | );
169 | };
170 |
171 | const INLINE_STYLES = [
172 | { label: 'Bold', style: 'BOLD' },
173 | { label: 'Italic', style: 'ITALIC' },
174 | { label: 'Underline', style: 'UNDERLINE' },
175 | { label: 'Monospace', style: 'CODE' },
176 | ];
177 |
178 | const InlineStyleControls = (props) => {
179 | const currentStyle = props.editorState.getCurrentInlineStyle();
180 | return (
181 |
182 | {INLINE_STYLES.map(type =>
183 | ())}
190 |
191 | );
192 | };
193 |
--------------------------------------------------------------------------------
/app/pages/menu/index.js:
--------------------------------------------------------------------------------
1 |
2 | import echarts from './echarts'
3 | import editor from './editor'
4 |
5 | export {
6 | echarts, editor,
7 | }
8 |
--------------------------------------------------------------------------------
/app/pages/set/index.js:
--------------------------------------------------------------------------------
1 |
2 | import '@styles/set.less'
3 | import userManage from './userManage'
4 | import roleManage from './roleManage'
5 | import moduleManage from './moduleManage'
6 |
7 | export { userManage, roleManage, moduleManage }
8 |
--------------------------------------------------------------------------------
/app/pages/set/moduleManage/modal/addButtonModal.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Button, Form, Input } from 'antd';
3 | import { connect } from 'react-redux';
4 | import { regExpConfig } from '@reg';
5 | import Drawer from '@components/draw/draw';
6 |
7 | const FormItem = Form.Item;
8 |
9 |
10 | // @connect((state, props) => ({
11 | // config: state.config
12 | // }))
13 | @Form.create()
14 |
15 | // 声明组件 并对外输出
16 | export default class Pop extends Component {
17 | // 初始化页面常量 绑定事件方法
18 | constructor(props) {
19 | super(props);
20 | this.state = {};
21 | this.handleSubmit = this.handleSubmit.bind(this);
22 | }
23 |
24 | componentWillMount() {
25 | this.props.form.resetFields();
26 | }
27 |
28 | // 组件已经加载到dom中
29 | componentDidMount() {}
30 |
31 | handleSubmit(e) {
32 | e.preventDefault();
33 | this.props.form.validateFields((errors, values) => {
34 | if (errors) {
35 | return;
36 | }
37 | values.resType = 3;
38 | if (this.props.state === 'edit') {
39 | values.id = this.props.buttonEditData.id;
40 | }
41 | this.props.handleAdd(values);
42 | });
43 | }
44 |
45 | footer() {
46 | const { onCancel } = this.props;
47 | return (
48 |
49 |
52 |
53 |
54 | );
55 | }
56 |
57 | render() {
58 | const { visible, onCancel, title, buttonEditData } = this.props;
59 | const { getFieldDecorator } = this.props.form;
60 | const formItemLayout = {
61 | labelCol: { span: 5 },
62 | wrapperCol: { span: 17 },
63 | };
64 | return (
65 |
72 |
73 |
144 |
145 |
146 | );
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/app/pages/set/moduleManage/modal/buttonModal.js:
--------------------------------------------------------------------------------
1 |
2 | import React, { Component } from 'react'
3 | import { connect } from 'react-redux'
4 | import { Button, message, Badge, Popconfirm } from 'antd'
5 | import TableList from '@tableList'
6 | import Drawer from '@components/draw/draw'
7 | import {
8 | // fetchButtonList,
9 | fetchModuleDelete,
10 | fetchChangeModuleStatus,
11 | } from '@apis/manage'
12 |
13 | // 连接公用常量、后端返回的数据方法 并放置在props里面调用
14 | // @connect((state, props) => ({
15 | // config: state.config,
16 | // }))
17 |
18 | // 声明组件 并对外输出
19 | export default class pop extends Component {
20 | // 初始化页面常量 绑定事件方法
21 | constructor(props) {
22 | super(props)
23 | this.state = {
24 | // selectedRowKeys: [],
25 | // loading: false,
26 | // dataSource: [],
27 | }
28 | this.deleteButton = this.deleteButton.bind(this)
29 | }
30 |
31 | componentWillMount() {
32 | // this.getList()
33 | }
34 |
35 | // 组件已经加载到dom中
36 | componentDidMount() {}
37 |
38 | componentWillReceiveProps(nextProps) {
39 | // this.getList()
40 | }
41 |
42 | // 删除
43 | deleteButton = (id) => {
44 | fetchModuleDelete({ id: id }, (result) => {
45 | message.success(result.msg)
46 | this.props.updateList()
47 | })
48 | }
49 |
50 | // 上线下线
51 | showOrHide=(id, val) => {
52 | fetchChangeModuleStatus({ id: id, status: val }, (result) => {
53 | this.props.updateList()
54 | })
55 | }
56 |
57 | column() {
58 | const self = this
59 | const { editButton } = self.props
60 | const configArr = [
61 | {
62 | title: '按钮名称',
63 | dataIndex: 'resName',
64 | key: 'resName',
65 | width: '40%',
66 | },
67 | {
68 | title: '状态',
69 | dataIndex: 'status',
70 | key: 'status',
71 | width: '20%',
72 | render: (text, record, index) => {
73 | if (text === 1) {
74 | return
75 | }
76 | return
77 | },
78 | },
79 | {
80 | title: '操作',
81 | dataIndex: 'caozuo',
82 | key: 'caozuo',
83 | width: '40%',
84 | render: (text, record, index) => (
85 |
86 | self.showOrHide(record.id, `${record.status}`)}
89 | >
90 | {record.status !== 1 ? '下线' : '上线'}
91 |
92 |
93 | editButton(record)}>修改
94 |
95 | self.deleteButton(record.id)}>
96 | 删除
97 |
98 |
99 | ),
100 | },
101 | ]
102 | return configArr
103 | }
104 |
105 | footer() {
106 | const { addButton } = this.props
107 | return (
108 |
109 |
110 |
111 | )
112 | }
113 |
114 | render() {
115 | const {
116 | visible, cancelButton, listLoading, dataSource,
117 | } = this.props
118 | // const { dataSource } = this.state
119 | return (
120 |
128 |
136 |
137 | )
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/app/pages/set/moduleManage/modal/moduleAdd.js:
--------------------------------------------------------------------------------
1 |
2 | import React, { Component } from 'react'
3 | import { connect } from 'react-redux'
4 | import { Button, Form, Input, message } from 'antd'
5 | import { regExpConfig } from '@reg'
6 | import Drawer from '@components/draw/draw'
7 | import {
8 | fetchModuleUpdateDetail,
9 | fetchModuleAdd,
10 | } from '@apis/manage'
11 |
12 | const FormItem = Form.Item
13 |
14 | // 连接公用常量、后端返回的数据方法 并放置在props里面调用
15 | // @connect((state, props) => ({
16 | // config: state.config,
17 | // }))
18 |
19 | @Form.create({})
20 |
21 | export default class Index extends Component {
22 | constructor(props) {
23 | super(props)
24 | this.state = {
25 | loading: false,
26 | // isFirst: this.props.isFirst,
27 | }
28 | }
29 |
30 | // 组件已经加载到dom中
31 | componentDidMount() {
32 | this.props.form.resetFields()
33 | }
34 |
35 | upDateValue = () => {
36 | if (this.props.pid) {
37 | this.props.form.setFieldsValue({
38 | parentid: this.props.pid,
39 | })
40 | }
41 | }
42 |
43 | handleSubmit = (e) => {
44 | e.preventDefault();
45 | this.props.form.validateFields((errors, values) => {
46 | if (errors) {
47 | return;
48 | }
49 | values.resType = 1
50 | this.setState({ loading: true })
51 | if (this.props.type === 'modify') {
52 | fetchModuleUpdateDetail({ ...values, id: this.props.itemId }, (result) => {
53 | message.success(result.msg)
54 | this.setState({ loading: false }, () => {
55 | this.props.handleOk()
56 | })
57 | // this.props.form.resetFields()
58 | })
59 | } else {
60 | fetchModuleAdd(values, (result) => {
61 | message.success(result.msg)
62 | this.setState({ loading: false }, () => {
63 | this.props.handleOk()
64 | })
65 | // this.props.form.resetFields()
66 | })
67 | }
68 | });
69 | }
70 |
71 | footer() {
72 | const { loading } = this.state
73 | return (
74 |
75 |
76 |
77 |
78 | )
79 | }
80 |
81 | render() {
82 | const {
83 | visible, onCancel, title,
84 | } = this.props
85 | const { getFieldDecorator } = this.props.form;
86 | const formItemLayout = {
87 | labelCol: { span: 5 },
88 | wrapperCol: { span: 17 },
89 | }
90 | return (
91 |
98 |
99 |
164 |
165 |
166 | )
167 | }
168 | }
169 |
--------------------------------------------------------------------------------
/app/pages/set/moduleManage/moduleList.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | import React, { Component } from 'react'
4 | import { Table, Popconfirm } from 'antd'
5 |
6 | export default class ModuleList extends Component {
7 | constructor(props) {
8 | super(props)
9 | this.state = {}
10 | }
11 |
12 | renderColumn() {
13 | const {
14 | onDelete, onModify, onUpdataStatus, onAddNode, buttonList,
15 | } = this.props
16 | return [
17 | {
18 | title: '功能',
19 | dataIndex: 'resName',
20 | width: '40%',
21 | key: 'resName',
22 | render: function (text, record, index) {
23 | return (
24 |
{text}
25 | )
26 | },
27 | },
28 | {
29 | title: '操作',
30 | width: '40%',
31 | key: 'operation',
32 | render: (text, record, index) => (
33 |
34 | onAddNode(record.id)}>新增
35 |
36 | onModify(record.id, record.parentid)}>修改
37 | {
38 | text.children && text.children.length > 0 ?
39 | null :
40 |
41 |
42 | onDelete(record.id)}>
43 | 删除
44 |
45 |
46 | }
47 | {
48 | record.resName !== '模块管理' ? (
49 |
50 |
51 | onUpdataStatus(text.id, `${text.status ? 0 : 1}`)}>
52 | {text.status ? '显示模块' : '隐藏模块'}
53 |
54 | ) : null
55 | }
56 |
57 | buttonList(record.id, record.parentid)}>按钮权限
58 |
59 | ),
60 | },
61 | {
62 | title: '状态',
63 | width: '20%',
64 | render: function (text, record, index) {
65 | return (
66 | record.resName !== '模块管理' ? (
67 |
{record.status ? 未上线 : 已上线}
68 | ) :
已上线
69 | )
70 | },
71 | },
72 | ]
73 | }
74 |
75 | render() {
76 | const { dataSource, loading/* , scroll */ } = this.props
77 | return (
78 |
90 | )
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/app/pages/set/roleManage/modal/buttonModal.js:
--------------------------------------------------------------------------------
1 |
2 | import React, { Component } from 'react'
3 | import { Button, Spin, Row, Col } from 'antd'
4 | import Drawer from '@components/draw/draw'
5 | import {
6 | fetchButtonList,
7 | fetchChangeModuleStatus,
8 | } from '@apis/manage'
9 |
10 | // 声明组件 并对外输出
11 | export default class pop extends Component {
12 | // 初始化页面常量 绑定事件方法
13 | constructor(props) {
14 | super(props)
15 | this.state = {
16 | selectedRowKeys: [],
17 | loading: false,
18 | dataSource: [],
19 | }
20 | this.change = this.change.bind(this)
21 | this.saveChecked = this.saveChecked.bind(this)
22 | this.selectChecked = this.selectChecked.bind(this)
23 | }
24 |
25 | componentWillMount() {
26 | this.state.selectedRowKeys = this.props.checkedIdArr[this.props.itemId] || []
27 | this.getList()
28 | }
29 |
30 | getList() {
31 | this.setState({
32 | loading: true,
33 | }, () => {
34 | fetchButtonList({ id: this.props.itemId }, (result) => {
35 | const data = result.data.list
36 | const dataSource = []
37 | data.map((item) => {
38 | if (item.status === 0) {
39 | const { selectedRowKeys } = this.state
40 | selectedRowKeys.map((key) => {
41 | if (item.id === key) {
42 | item.checked = true
43 | }
44 | })
45 | dataSource.push(item)
46 | }
47 | })
48 | this.setState({
49 | loading: false,
50 | dataSource: dataSource,
51 | })
52 | })
53 | })
54 | }
55 |
56 | // componentWillReceiveProps(nextProps) {
57 | // this.getList()
58 | // }
59 |
60 | // 上线下线
61 | // showOrHide(id, val) {
62 | // fetchChangeModuleStatus({ id: id, status: val }, (result) => {
63 | // this.getList()
64 | // })
65 | // }
66 |
67 | selectChecked() {
68 | // const checkedArr = []
69 | this.state.dataSource.map((item) => {
70 | item.checked = true
71 | // checkedArr.push(item.id)
72 | })
73 | this.setState({})
74 | // this.props.saveChecked(checkedArr)
75 | }
76 |
77 | saveChecked() {
78 | // const { selectedRowKeys } = this.state
79 | // if (selectedRowKeys.length === 0) {
80 | // message.info('请选择可供用户使用的按钮权限')
81 | // return
82 | // }
83 | const checkedArr = []
84 | this.state.dataSource.map((item) => {
85 | if (item.checked) {
86 | checkedArr.push(item.id)
87 | }
88 | })
89 | this.props.saveChecked(checkedArr)
90 | }
91 |
92 | footer() {
93 | const { cancelButton } = this.props
94 | return (
95 |
96 |
97 |
98 |
99 |
100 | )
101 | }
102 |
103 | change(id, index) {
104 | const data = this.state.dataSource[index]
105 | data.checked = !data.checked
106 | this.setState({})
107 | }
108 |
109 | render() {
110 | const { visible, cancelButton, title } = this.props
111 | const { loading, dataSource } = this.state
112 | return (
113 |
120 |
121 |
122 |
123 | {dataSource.map((arr, i) =>
124 | (
125 |
132 | ))}
133 |
134 |
135 |
136 |
137 | )
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/app/pages/set/roleManage/modal/roleAdd.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | import React, { Component } from 'react'
4 | import { Button, Form, Input, /* Modal, */ Select, message } from 'antd'
5 | import { regExpConfig } from '@reg'
6 | import Drawer from '@components/draw/draw'
7 | import {
8 | fetchRoleAdd,
9 | fetchRoleUpdate,
10 | } from '@apis/manage'
11 |
12 | const FormItem = Form.Item
13 | const { Option } = Select
14 |
15 |
16 | @Form.create({})
17 |
18 | export default class Index extends Component {
19 | constructor(props) {
20 | super(props)
21 | this.state = {
22 | loading: false,
23 | }
24 | this.handleSubmit = this.handleSubmit.bind(this)
25 | }
26 |
27 | componentDidMount() {
28 | this.props.form.resetFields()
29 | this.props.form.setFieldsValue({
30 | roleName: this.props.value.roleName,
31 | sort: `${this.props.value.sort}`,
32 | tjFlag: this.props.value.tjFlag !== undefined ? String(this.props.value.tjFlag) : '1',
33 | })
34 | }
35 |
36 | handleSubmit(e) {
37 | e.preventDefault();
38 | this.props.form.validateFields((errors, values) => {
39 | if (errors) {
40 | return;
41 | }
42 | this.setState({ loading: true })
43 | if (this.props.type === 'modify') {
44 | fetchRoleUpdate({ ...values, id: this.props.modifyId }, (res) => {
45 | message.success(res.msg)
46 | this.props.handleOk(false)
47 | })
48 | } else {
49 | fetchRoleAdd(values, (res) => {
50 | message.success(res.msg)
51 | this.props.handleOk(false)
52 | })
53 | }
54 | this.setState({ loading: false })
55 | });
56 | }
57 |
58 | footer() {
59 | const { loading } = this.state
60 | return (
61 |
62 |
63 |
64 |
65 | )
66 | }
67 |
68 | render() {
69 | const {
70 | visible, onCancel, title,
71 | } = this.props
72 | const { getFieldDecorator } = this.props.form
73 | const formItemLayout = {
74 | labelCol: { span: 5 },
75 | wrapperCol: { span: 17 },
76 | }
77 | return (
78 |
85 |
86 |
116 |
117 |
118 | )
119 | }
120 | }
121 |
122 |
--------------------------------------------------------------------------------
/app/pages/set/roleManage/peopleTreeList.js:
--------------------------------------------------------------------------------
1 |
2 | import React, { Component } from 'react'
3 | import TableList from '@tableList'
4 |
5 | export default class app extends Component {
6 | constructor(props) {
7 | super(props);
8 | this.state = {}
9 | }
10 |
11 | componentWillMount() {}
12 |
13 | componentDidMount() {
14 | }
15 |
16 | // #region 收缩业务代码功能
17 |
18 | columns() {
19 | return (
20 | [{
21 | title: '功能',
22 | dataIndex: 'resName',
23 | key: 'resName',
24 | width: '30%',
25 | }, {
26 | title: '已选模块',
27 | dataIndex: 'checkedArr',
28 | key: 'checkedArr',
29 | width: '40%',
30 | }]
31 | )
32 | }
33 |
34 | // #endregion
35 |
36 | render() {
37 | const {
38 | dataSource,
39 | } = this.props
40 | return (
41 |
50 | )
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/app/pages/set/roleManage/roleCheckbox.js:
--------------------------------------------------------------------------------
1 | import { Checkbox } from 'antd';
2 | import React from 'react';
3 |
4 | class RoleCheckbox extends React.Component {
5 | constructor(props) {
6 | super(props);
7 | this.state = {
8 | isChecked: false,
9 | };
10 | this.onChange = this.onChange.bind(this);
11 | }
12 |
13 | componentWillMount() {
14 | this.setState({
15 | isChecked: this.props.defaultChecked,
16 | });
17 | }
18 |
19 | componentWillReceiveProps(nextProps) {
20 | if (this.props.defaultChecked !== nextProps.defaultChecked) {
21 | this.setState({
22 | isChecked: nextProps.defaultChecked,
23 | });
24 | }
25 | }
26 |
27 | // #region 收缩业务代码功能
28 |
29 | onChange(e) {
30 | const item = this.props.checkItem;
31 | this.setState({
32 | isChecked: e.target.checked,
33 | });
34 | this.props.onChecked(item, e.target.checked);
35 | }
36 |
37 | // #endregion
38 |
39 | render() {
40 | return (
41 |
46 | {this.state.isChecked ? '已开通' : '未开通'}
47 |
48 | );
49 | }
50 | }
51 | export default RoleCheckbox;
52 |
--------------------------------------------------------------------------------
/app/pages/set/roleManage/roleList.js:
--------------------------------------------------------------------------------
1 |
2 | import React, { Component } from 'react'
3 | import { Icon, Popconfirm } from 'antd'
4 |
5 | export default class app extends Component {
6 | constructor(props) {
7 | super(props)
8 | this.state = {
9 | currentId: '',
10 | }
11 | }
12 |
13 | componentWillMount() {
14 | if (this.props.roles.length > 0) {
15 | this.setState({
16 | currentId: this.props.roles[0].id || 0,
17 | })
18 | }
19 | }
20 |
21 | componentDidMount() {
22 |
23 | }
24 |
25 | componentWillReceiveProps(nextProps) {
26 | if (this.state.currentId === '' && nextProps.roles.length > 0) {
27 | this.setState({
28 | currentId: nextProps.roles[0].id || 0,
29 | })
30 | }
31 | }
32 |
33 | // #region 收缩业务代码功能
34 |
35 | // 角色名点击
36 | roleNameClick = (roleid, roleType) => {
37 | this.setState({ currentId: roleid })
38 | this.props.onCurrentIndex(roleid, roleType)
39 | }
40 |
41 | // 改变选中li的样式
42 | checkTitleId = id =>
43 | // console.log(id)
44 | (id === this.state.currentId ? 'active cell-layout' : 'cell-layout')
45 |
46 |
47 | // 角色修改
48 | roleModify = (info) => {
49 | this.props.onRoleModify(info)
50 | }
51 |
52 | // 角色删除
53 | onDelete = (info) => {
54 | this.state.currentId = ''
55 | this.props.handleRoleDelete(info)
56 | }
57 |
58 | // render roleNodes
59 | renderRoleNodes = () => {
60 | const { roles, btnRights } = this.props
61 | return roles.map((item, index) =>
62 | (
63 | this.roleNameClick(item.id, item.type)}>{item.roleName}
64 |
65 | {
66 | btnRights.edit ?
67 | this.roleModify(item.id)} /> : null
68 | }
69 | {
70 | btnRights.deleteRole ?
71 | this.onDelete(item.id)}>
72 |
73 |
74 | : null
75 | }
76 |
77 | ))
78 | }
79 |
80 | // #endregion
81 |
82 | render() {
83 | return (
84 |
85 | {this.renderRoleNodes()}
86 |
87 | )
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/app/pages/set/userManage/modal/selectRole.js:
--------------------------------------------------------------------------------
1 |
2 | import React, { Component } from 'react'
3 | import { Radio, Button, Modal, message } from 'antd'
4 | import { fetchUserSetRole } from '@apis/manage'
5 |
6 | const RadioGroup = Radio.Group;
7 | const RadioButton = Radio.Button;
8 |
9 | export default class roleSelect extends Component {
10 | constructor(props) {
11 | super(props)
12 | this.state = {
13 | loading: false,
14 | checkedValues: '',
15 | }
16 | this.handleSubmit = this.handleSubmit.bind(this)
17 | this.onChange = this.onChange.bind(this)
18 | }
19 |
20 | componentWillMount() {
21 | this.setState({ checkedValues: this.props.values.roleid })
22 | }
23 |
24 | componentDidMount() {
25 |
26 | }
27 |
28 | onChange(e) {
29 | this.setState({ checkedValues: e.target.value })
30 | }
31 |
32 | handleSubmit() {
33 | this.setState({ loading: true })
34 | this.props.dispatch(fetchUserSetRole({
35 | roleid: this.state.checkedValues,
36 | id: this.props.currPeopleId,
37 | }, (res) => {
38 | message.success(res.msg)
39 | this.setState({ loading: false })
40 | this.props.handleOkRole()
41 | }))
42 | }
43 |
44 | footer() {
45 | return (
46 |
47 |
48 |
49 |
50 | )
51 | }
52 |
53 | render() {
54 | const { select, values, visible, onCancel } = this.props
55 | const selectNodes = select.map((item, index) =>
56 |
{item.name} )
57 | return (
58 |
65 |
66 |
67 | {selectNodes}
68 |
69 |
70 |
71 | )
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/app/pages/set/userManage/treeList.js:
--------------------------------------------------------------------------------
1 |
2 | import React, { Component } from 'react'
3 | import { Tree } from 'antd'
4 |
5 | const { TreeNode } = Tree
6 |
7 | export default class TreeList extends Component {
8 | constructor(props) {
9 | super(props)
10 | this.state = {
11 | // expandedKeys: ['123'],
12 | defaultExpandedKeys: ['123'],
13 | deptCode: props.curDeptCode,
14 | }
15 | this.handleOnSelect = this.handleOnSelect.bind(this)
16 | }
17 |
18 | componentDidMount() {
19 |
20 | }
21 |
22 | componentWillReceiveProps(nextProps) {
23 | if (nextProps.curDeptCode !== this.props.curDeptCode) {
24 | this.setState({ deptCode: nextProps.curDeptCode })
25 | }
26 | }
27 |
28 |
29 | // 展开事件
30 | onExpand = (expandedKeys) => {
31 | this.setState({ expandedKeys })
32 | }
33 |
34 | // 选中事件
35 | handleOnSelect(info, Nodes) {
36 | if (Nodes && Nodes.selectedNodes[0] && Nodes.selectedNodes[0].props && Nodes.selectedNodes[0].props.title) {
37 | const { title } = Nodes.selectedNodes[0].props
38 | this.props.onSelect(info, title)
39 | } else {
40 | this.props.onSelect()
41 | }
42 | }
43 |
44 | render() {
45 | const { trees } = this.props
46 | const loop = (data = []) => data.map((item) => {
47 | if (item.children && item.children.length) {
48 | return
{loop(item.children)}
49 | }
50 | return
51 | })
52 | const treeNodes = loop(trees)
53 |
54 | return (
55 |
56 |
62 | {treeNodes}
63 |
64 |
65 | )
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/app/redux/actions/common.js:
--------------------------------------------------------------------------------
1 |
2 | import { createAction } from 'redux-actions'
3 | import * as common from '@apis/common'
4 | import { createAjaxAction } from '@configs/common'
5 |
6 |
7 | // login 登陆
8 | export const requestLogin = createAction('request login')
9 | export const recevieLogin = createAction('receive login')
10 | export const login = createAjaxAction(common.login, requestLogin, recevieLogin)
11 |
12 | // gFormCache gfor2.0m的缓存
13 | export const setGformCache2 = createAction('set gform cache2')
14 | export const clearGformCache2 = createAction('clear gform cache2')
15 |
16 | // socket receive
17 | // export const socketReceive = createAction('socketReceive')
18 |
--------------------------------------------------------------------------------
/app/redux/actions/tabList.js:
--------------------------------------------------------------------------------
1 | import { createAction } from 'redux-actions'
2 |
3 | export const requestTabList = createAction('request tab list')
4 | export const updateTabList = createAction('update tab list')
5 | export const updateTabChecked = createAction('update tab checked')
6 | export const deleteTabFromList = createAction('delete tab from list');
7 |
--------------------------------------------------------------------------------
/app/redux/reducers/common.js:
--------------------------------------------------------------------------------
1 | import { handleActions } from 'redux-actions'
2 |
3 | // 登陆返回结果
4 | const loginState = () => ({})
5 | export const loginResponse = handleActions({
6 | 'request login'(state, action) {
7 | return { ...state, loading: true }
8 | },
9 | 'receive login'(state, action) {
10 | // eslint-disable-next-line no-unused-vars
11 | const { req, res } = action.payload
12 | return { data: res, loading: false }
13 | },
14 | }, loginState())
15 |
16 |
17 | // gForm2.0缓存
18 | const cache2 = () => ({})
19 | export const gFormCache2 = handleActions({
20 | 'set gform cache2'(state, action) {
21 | const { cacheKey, cacheContent } = action.payload
22 | if (cacheKey === undefined) {
23 | throw new Error('cacheKey不能是undefined')
24 | }
25 | if (cacheContent === undefined) {
26 | throw new Error('cacheContent不能是undefined')
27 | }
28 | state[cacheKey] = { ...state[cacheKey], ...cacheContent }
29 | return { ...state }
30 | },
31 | 'clear gform cache2'(state, action) {
32 | return cache2()
33 | },
34 | }, cache2())
35 |
36 |
37 | // gForm2.0头部搜索类别
38 | const allRetrievalState = {
39 | list: [],
40 | }
41 | export const allRetrievalResult = handleActions({
42 | 'request all retrieval'(state, action) {
43 | return { ...state, loading: true }
44 | },
45 | 'receive all retrieval'(state, action) {
46 | // eslint-disable-next-line no-unused-vars
47 | const { req, res } = action.payload
48 | return { ...res.data, loading: false }
49 | },
50 | }, allRetrievalState)
51 |
52 |
53 | // socket相关操作
54 | /* export const socketCollection = handleActions({
55 | 'socketReceive'(state, action) {
56 | // eslint-disable-next-line no-unused-vars
57 | const data = action.payload
58 | return { data }
59 | },
60 | }, {}) */
61 |
--------------------------------------------------------------------------------
/app/redux/reducers/index.js:
--------------------------------------------------------------------------------
1 | import { routerReducer as routing } from 'react-router-redux'
2 | import { combineReducers } from 'redux'
3 |
4 | import * as tabList from './tabList'
5 | import * as common from './common'
6 |
7 | const rootReducer = combineReducers({
8 | routing,
9 | config: (state = {}) => state,
10 | ...tabList,
11 | ...common,
12 | })
13 |
14 | export default rootReducer
15 |
--------------------------------------------------------------------------------
/app/redux/reducers/tabList.js:
--------------------------------------------------------------------------------
1 | import { handleActions } from 'redux-actions'
2 |
3 | const tabList = JSON.parse(sessionStorage.getItem('tabList'))
4 |
5 | const initialState = {
6 | list: tabList ? tabList.list : [],
7 | activeKey: tabList ? tabList.activeKey : '',
8 | }
9 |
10 | const tabListResult = handleActions({
11 | 'request tab list'(state, action) {
12 | return { ...state, loading: false }
13 | },
14 | 'update tab list'(state, action) {
15 | const data = action.payload
16 | const findList = state.list.find(tab => tab.key === data.key)
17 | const list = findList === undefined ? [...state.list, data] : state.list
18 | sessionStorage.setItem('tabList', JSON.stringify({ list, activeKey: data.key, loading: false }))
19 | return { list, activeKey: data.key, loading: false }
20 | },
21 | 'update tab checked'(state, action) {
22 | const { activeKey } = action.payload;
23 | sessionStorage.setItem('tabList', JSON.stringify({ ...state, activeKey, loading: false }))
24 | return { ...state, activeKey, loading: false }
25 | },
26 | 'delete tab from list'(state, action) {
27 | const { targetKey } = action.payload
28 | const list = []
29 | let delIndex = 0
30 | let { activeKey } = state
31 | state.list.map((tab, index) => {
32 | tab.key === targetKey ? delIndex = index : list.push(tab)
33 | })
34 | if (state.activeKey === targetKey) {
35 | // eslint-disable-next-line no-nested-ternary
36 | activeKey = list[delIndex] ? list[delIndex].key :
37 | (list[delIndex - 1] ? list[delIndex - 1].key : '')
38 | }
39 | sessionStorage.setItem('tabList', JSON.stringify({ list, activeKey, loading: false }))
40 | return { list, activeKey, loading: false }
41 | },
42 | }, initialState)
43 |
44 | export { tabListResult as default }
45 |
--------------------------------------------------------------------------------
/app/resource/iconfont/iconfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/react_duxian/ff78ec236fe39fb59835141477240842d04494dc/app/resource/iconfont/iconfont.eot
--------------------------------------------------------------------------------
/app/resource/iconfont/iconfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/react_duxian/ff78ec236fe39fb59835141477240842d04494dc/app/resource/iconfont/iconfont.ttf
--------------------------------------------------------------------------------
/app/resource/iconfont/iconfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webtopcoder/react_duxian/ff78ec236fe39fb59835141477240842d04494dc/app/resource/iconfont/iconfont.woff
--------------------------------------------------------------------------------
/app/styles/RichEditor.less:
--------------------------------------------------------------------------------
1 | .flexcolumn{ flex:1; display: flex; flex-direction: column;}
2 |
3 | .RichEditor-root { .flexcolumn;
4 | background: #fff;
5 | border: 1px solid #ddd;
6 | font-family: 'Georgia', serif;
7 | font-size: 14px;
8 | padding: 16px;
9 | // overflow: auto;
10 | }
11 |
12 | .RichEditor-editor {.flexcolumn;
13 | border-top: 1px solid #ddd;
14 | cursor: text;
15 | font-size: 16px;
16 | margin-top: 10px;
17 | }
18 |
19 | .DraftEditor-root{.flexcolumn; overflow-y: auto; overflow-x: hidden;}
20 |
21 | .RichEditor-editor .public-DraftEditorPlaceholder-root,
22 | .RichEditor-editor .public-DraftEditor-content {
23 | margin: 0 -15px -15px;
24 | padding: 15px;
25 | }
26 |
27 | .RichEditor-editor .public-DraftEditor-content {
28 | min-height: 100px;
29 | }
30 |
31 | .RichEditor-hidePlaceholder .public-DraftEditorPlaceholder-root {
32 | display: none;
33 | }
34 |
35 | .RichEditor-editor .RichEditor-blockquote {
36 | border-left: 5px solid #eee;
37 | color: #666;
38 | font-family: 'Hoefler Text', 'Georgia', serif;
39 | font-style: italic;
40 | margin: 16px 0;
41 | padding: 10px 20px;
42 | }
43 |
44 | .RichEditor-editor .public-DraftStyleDefault-pre {
45 | background-color: rgba(0, 0, 0, 0.05);
46 | font-family: 'Inconsolata', 'Menlo', 'Consolas', monospace;
47 | font-size: 16px;
48 | padding: 20px;
49 | }
50 |
51 | .RichEditor-controls {
52 | font-family: 'Helvetica', sans-serif;
53 | font-size: 14px;
54 | margin-bottom: 5px;
55 | user-select: none;
56 | }
57 |
58 | .RichEditor-styleButton {
59 | color: #999;
60 | cursor: pointer;
61 | margin-right: 16px;
62 | padding: 2px 0;
63 | display: inline-block;
64 | }
65 |
66 | .RichEditor-activeButton {
67 | color: #5890ff;
68 | }
69 |
--------------------------------------------------------------------------------
/app/styles/login.less:
--------------------------------------------------------------------------------
1 |
2 |
3 | @import './theme.less';
4 |
5 | .flexcolumn{display: flex; flex:1; flex-direction: column;}
6 |
7 | .root{height: 100%;
8 | .login-container{.flexcolumn;height: 100%; /* background: url(../images/bg.jpg) no-repeat 0 0; */ background-size: cover;
9 | .extraLink{ position: absolute; z-index: 999; right: @space-big; top: @space-big; display: none;
10 | a{ color: #eee; margin-left: @space-big; font-size: 16px;
11 | &:hover{color: #fff;}
12 | }
13 | }
14 | .login-header{flex: 3;background: #2d333e;color: #fff;display: flex;align-items: center;justify-content: center;font-size: 36px;letter-spacing: 10px; position: relative;
15 | .slogan{ position: absolute; z-index: 1000; bottom: 40px; margin-top: -10px; width: 100%; left: 0;
16 | div{ width: 100%; text-align: center; }
17 | .title{ font-size: 50px;
18 | .en{ display: block; font-size: 20px;}
19 | }
20 | .logo{height: 54px;margin-right: 10px;vertical-align: middle;margin-bottom: 8px;}
21 | }
22 | }
23 | .login-main{flex:3;display: flex;flex-direction: column;justify-content: center;
24 |
25 | .ant-row{
26 | .ant-col-8{
27 | .ant-form-item{display: flex;flex-direction: column;align-items: center;
28 | .ant-form-item-control-wrapper{width: 60%;
29 | .ant-form-item-control {text-align: right;
30 | .ant-form-explain{text-align: left;}
31 | .ant-input-group-wrapper{width: 100%;
32 | .ant-input-group-addon{font-size: 16px;color:#000;}
33 | }
34 | .ant-btn{width: 100%;}
35 | >a{color:@text-color-bold;font-weight: bold;}
36 | }
37 | }
38 | }
39 | }
40 | }
41 | }
42 | .login-footer{flex: 1;display: flex;align-items: center;justify-content: center;color: @text-color-secondary;flex-direction:column;font-size: 14px; display: none;
43 | a{align-self: flex-end;margin-right: 5%;color:@text-color-bold;font-weight: bold;}
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/app/styles/personalCenter.less:
--------------------------------------------------------------------------------
1 | @import './theme.less';
2 | .changePswWrap{position: relative;
3 | .changePsw{margin: 0px auto;background: #42485B;border-radius: 2px;position: absolute;z-index: 2;width: 100%;left: 0;top: -57px;cursor: pointer;
4 | .changePsw_title{padding: 16px;font-size:16px;color: #c0c0c0;border-bottom: 1px solid #565861;
5 | }
6 | .changePsw_title+form{margin-top:26px;
7 | .ant-input{background-color: rgba(255,255,255,0.66);border-radius:2px;color: #4A4A4A;
8 | &:focus{box-shadow: none;}
9 | }
10 | }
11 | .changePsw_btngroup{text-align: right;padding-bottom: 16px;
12 | button{
13 | margin-right:26px;
14 | }
15 | }
16 | .changePsw_btn{background: #42485B!important;border:none!important;}
17 | }
18 | }
19 | .changePsw_in{
20 | background: #42485B;
21 | font-size: 16px;
22 | .enter{
23 | cursor: pointer;
24 | color: #008fe3;
25 | font-style: normal;
26 | }
27 | }
--------------------------------------------------------------------------------
/app/styles/set.less:
--------------------------------------------------------------------------------
1 | @import './theme.less';
2 | .flexcolumn{display: flex; flex:1; flex-direction: column;}
3 | .page-usermanage{
4 | .page-header{flex: initial;/* margin-top: @space-big */;/* margin-left:@space-big; */ }
5 | .page-content .ant-pagination { padding-bottom: @space-big * 2; right: @space-big * 2;}
6 | .page-content{flex: auto;
7 | .table-content{margin-top:0;}
8 | }
9 | .page-body{ border:@border-split; flex-direction: row;}
10 | .page-title{border-bottom: @border-split;}
11 | .page-body-main{.flexcolumn;}
12 | .ant-layout-sider-children{.flexcolumn; height: 100%;
13 | .ant-spin-nested-loading{.flexcolumn;
14 | .ant-spin-container{.flexcolumn;
15 | .page-title{border-right: @border-split;}
16 | .treeside{ .flexcolumn;margin-bottom: 0;background: @component-background; border-right: @border-split; padding:@space-big;overflow: auto;
17 | > div{.flexcolumn; }
18 | .ant-tree-switcher-noop{ display: none;}
19 | .ant-tree {max-width: 190px;
20 | li { margin: 0; position: relative; padding: 1px 0;
21 | .ant-tree-node-content-wrapper{ width: 100%; padding:7.5px 5px; margin-left: 2px; font-size: 13px; color: #4A4A4A;
22 | &:hover { background-color: rgba(90, 141, 239, 0.12);
23 | .right-icon { display: block; }
24 | }
25 | }
26 | .ant-tree-child-tree{ position: relative; }
27 | .ant-tree-child-tree li:after{
28 | content: ''; position: absolute; left: -13px; top: -18px; bottom: 17px; border-left: 1px solid @border-color-split;
29 | }
30 | .ant-tree-child-tree li:before{
31 | content: ''; position: absolute; left: -12px; top: 18px; width: 12px; border-top: 1px solid @border-color-split;
32 | }
33 | .ant-tree-switcher.ant-tree-switcher_close,
34 | .ant-tree-switcher.ant-tree-switcher_open {
35 | cursor: pointer; display: inline-block; width: 12px; height: 12px; text-align: center; background: #fff; z-index: 9; position: relative;
36 | }
37 | }
38 | .right-icon { float: right; margin-right: 20px; display: none;
39 | i { margin-left: @space-base; color: @blue;
40 | &:hover { color: @blue; }
41 | }
42 | }
43 | }
44 | }
45 | }
46 | }
47 | }
48 | .ant-layout-content{.flexcolumn;}
49 | }
50 |
51 | // 角色管理
52 | .page-rolemanage{
53 | .page-footer{margin: 0 -@space-big;}
54 | .roleModuleList{
55 | tr{
56 | td:first-child{ text-align: left; padding-left: @space-base;;
57 | span{ white-space: nowrap;}
58 | }
59 | }
60 | }
61 | .page-content{
62 | .ant-spin-nested-loading{.flexcolumn;
63 | .ant-spin-container{.flexcolumn;}
64 | }
65 | }
66 | .ant-layout-content{.flexcolumn;
67 | .color-red{color:@red;}
68 | .color-green{color:@green;}
69 | .table-checkbox{display: inline-block;}
70 | }
71 | .ant-layout-sider-children{.flexcolumn; padding:@space-big; border-right: @border-split;
72 | .ant-input-group-addon{ cursor: pointer;}
73 | .ant-spin-nested-loading{.flexcolumn;
74 | .ant-spin-container{.flexcolumn;
75 | .treeside{ .flexcolumn;margin-bottom: 0;background: @component-background; border-right: 0; padding:0;overflow: auto;
76 | .ant-tree li{border: 0;}
77 | .roleslist {overflow-y: auto; overflow-x: hidden;
78 | .title{ padding-bottom: @space-base; display: block; color: @text-color-bold; font-size: @font-size-lg; border-bottom: @border-base; margin:@space-base 0 0 @space-sm;}
79 | li{ padding:@space-sm 0 @space-sm @space-base; text-align: left; position: relative; line-height: @line-height-normal; display: flex;
80 | a{ color: @text-color-bold;}
81 | .name{ display: block; flex:1}
82 | &:hover{ background: @hover-background;
83 | .icons{
84 | display: inline-block;
85 | }
86 | }
87 | }
88 | .icons{display: none; top: @space-normal; right:@space-sm; white-space: nowrap;
89 | i{ padding: @space-sm; color: #fff; margin-right: @space-sm; color: @text-color;
90 | &:hover{color: @blue;}
91 | }
92 | }
93 | .active{background: @hover-background;}
94 | }
95 | }
96 | }
97 | }
98 | }
99 | }
100 |
101 | // 模块管理
102 | .page-modulemanage{
103 | .ant-table-body{
104 | .ant-table-tbody{
105 | tr{
106 | td:first-child{ text-align: left; padding-left: 12%;
107 | span{ white-space: nowrap;}
108 | }
109 | }
110 | }
111 | }
112 | }
--------------------------------------------------------------------------------
/app/styles/theme.less:
--------------------------------------------------------------------------------
1 | // reset antd
2 | @input-height-base : 28px;
3 | @input-height-lg : 28px;
4 | @btn-height-base : 28px;
5 | @pagination-item-size : 28px;
6 | @font-size-base : 12px;
7 | // 全局常用颜色的定义
8 | @icon-url : "../resource/iconfont/iconfont";
9 | @white : #fff; // 白色
10 | @green : #69b721;//绿色
11 | @red : #ff0000;//红色
12 | @blue : #5a8def;//蓝色
13 | @yellow : #eca42b;//黄色
14 | @gray : #b2b2b2;//灰色色
15 | @orange : #ee860b; // 橙色
16 |
17 | // 全局按钮的颜色 主要用来重置antd的主题
18 | @primary-color : #4da9ec;
19 | @info-color : @primary-color;
20 | @success-color : @green;
21 | @error-color : @red;
22 | @highlight-color : @red;
23 | @warning-color : @yellow;
24 |
25 | // 全局默认字体颜色、二级标题颜色、背景颜色、
26 | @body-background : #fff; // 默认背景白色 用来重置antd的默认样式
27 | @background-color-base : #f8f9fd; // 灰白背景的颜色 接近白色
28 | @background-color-content : #e7ebee; // 灰白背景的颜色 更加灰
29 | @background-color-hover : rgba(90,141,239,0.2); // 元素hover的背景颜色
30 | @background-color-active : rgba(90,141,239,0.2); // 元素active的背景颜色
31 | @component-background : #fff; // 常用组件背景颜色 主要是重置antd默认样式
32 | @title-background : #f6f8fc; // 常用标题的淡蓝色背景色
33 | @hover-background : rgba(90, 141, 239, 0.2); // 常用标题的淡蓝色背景色
34 | @navbar-background : #373D41; // 左侧导航背景颜色
35 | @nav-background : #42485B; // 左侧导航背景颜色
36 | @nav-item-background : #333745; // 左侧导航打开项背景色
37 |
38 | // 全局字体定义
39 | @font-family : 'Helvetica Neue For Number,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,PingFang SC,Hiragino Sans GB,Microsoft YaHei,Helvetica Neue,Helvetica,Arial,sans-serif';
40 | @code-family : Consolas, Menlo, Courier, monospace;
41 |
42 | // 全局文字颜色
43 | @text-color-bold : #333;
44 | @text-color : #666;
45 | @text-color-secondary : #999;
46 |
47 | // 全局字体大小
48 | @font-size-base : 12px;
49 | @font-size-lg : 14px;
50 | @font-size-hg : 18px;
51 |
52 | // 全局圆角的定义
53 | @border-radius-base : 2px;
54 | @border-radius-sm : 2px;
55 |
56 | // 边框颜色以及圆角
57 | @border-color-base : #dfe4ea; // 常见灰色边框颜色的定义
58 | @border-color-split : #dfe4ea; // 常见淡蓝色边框颜色的定义
59 | @border-color-dark : #777C8D; // 常见淡蓝色边框颜色的定义
60 | @border-lightBlack : 1px solid #565c6d; // 常见弹框里的边框颜色
61 | @border-base : 1px solid @border-color-base; // 常见灰色边框线的简写方式
62 | @border-split : 1px solid @border-color-split; // 常见淡蓝色边框线的简写方式
63 | @border-split-dashed : 1px dashed @border-color-split; // 常见淡蓝色边框线的简写方式
64 | @border-dark : 1px solid @border-color-dark; // 常见淡蓝色边框线的简写方式
65 |
66 |
67 | // 全局常用行高的定义
68 | @line-height-sm : 28px;
69 | @line-height-normal : 30px;
70 | @line-height-base : 1.5;
71 | @line-height-big : 30px;
72 | @line-height-lg : 36px;
73 | @line-height-hg : 40px;
74 |
75 | // 全局所有的padding或者margin的常用间隔
76 | @space-sm : 4px;
77 | @space-base : 8px;
78 | @space-middle : 12px;
79 | @space-normal : 14px;
80 | @space-big : 16px;
81 | @space-lg : 24px;
82 | @space-hg : 32px;
83 |
84 | @scroll-width : 14px; // 全局滚动条的宽度
85 |
86 | // 全局结构宽度高度的定义
87 | @g-left-width-base : 142px;
88 | @g-left-width-mini : 50px;
89 | @g-middle-width : 280px;
90 | @g-header-height : 64px;
91 | @g-nav-height : 44px;
92 |
93 | @g-header-bg-color : #233344;
94 | @g-title-bg-color : #ebf5fd;
95 | @form-header-color : #fafdff;
96 |
97 | // 网站自定义的icon前缀
98 | @qqbicon-prefix : qqbicon;
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-admin",
3 | "version": "0.1.0",
4 | "description": "a react develop stack for pc management system",
5 | "repository": {
6 | "type": "git",
7 | "url": "https://github.com/duxianwei520/react"
8 | },
9 | "private": true,
10 | "scripts": {
11 | "start": "concurrently \"npm run dev\" \"npm run mock\"",
12 | "dev": "webpack-dev-server --config ./scripts/webpack.dev.config.js",
13 | "testing": "webpack --config ./scripts/webpack.testing.config.js",
14 | "build": "cross-env NODE_ENV=production webpack --config ./scripts/webpack.prod.config.js",
15 | "lint": "eslint ./ --cache --fix --ignore-pattern .gitignore",
16 | "test": "jest --coverage",
17 | "mock": "nodemon --watch app/mocks/ app/mocks/http.js",
18 | "precommit": "lint-staged",
19 | "preCommitInit": "node ./node_modules/husky/lib/installer/bin.js install",
20 | "test:report": "jest --coverage --coverageReporters=text-lcov | coveralls",
21 | "dll": "webpack --config ./scripts/webpack.dll.config.js"
22 | },
23 | "husky": {
24 | "hooks": {
25 | "pre-commit": "lint-staged"
26 | }
27 | },
28 | "author": "duxianwei",
29 | "contributors": [
30 | {
31 | "name": "HanQ"
32 | },
33 | {
34 | "name": "Huxiaoyu"
35 | },
36 | {
37 | "name": "jinxedjkldsa"
38 | },
39 | {
40 | "name": "FengYangLiu"
41 | }
42 | ],
43 | "jest": {
44 | "moduleFileExtensions": [
45 | "js",
46 | "jsx"
47 | ],
48 | "testEnvironment": "jsdom",
49 | "moduleNameMapper": {
50 | "\\.(css|less)$": "identity-obj-proxy",
51 | "^@apis(.*)$": "
/app/apis$1",
52 | "^@configs(.*)$": "/app/configs$1",
53 | "^@ajax(.*)$": "/app/configs/ajax.js",
54 | "^@config(.*)$": "/app/configs/config.js",
55 | "^@reg(.*)$": "/app/configs/regular.config.js",
56 | "^@components(.*)$": "/app/components$1",
57 | "^@tableList(.*)$": "/app/components/tableList/tableList.js",
58 | "^@redux/actions(.*)$": "/app/redux/actions$1",
59 | "^@images(.*)$": "/app/images$1"
60 | },
61 | "transform": {
62 | "^.+\\.js$": "babel-jest"
63 | },
64 | "collectCoverageFrom": [
65 | "**/*.{js,jsx}",
66 | "!**/coverage/**",
67 | "!**/scripts/**",
68 | "!**/reducers/**",
69 | "!**/actions/**",
70 | "!**/base/**",
71 | "!**/apis/**",
72 | "!**/mocks/**",
73 | "!**/middleware/**",
74 | "!**/components/**",
75 | "!**/menu/**",
76 | "!**/configs/**",
77 | "!**/store.js",
78 | "!**/provider.jsx",
79 | "!**/example.js",
80 | "!**/client.js",
81 | "!**/webpack.config.js",
82 | "!**/selectRole.js",
83 | "!**/setCenter/index.js",
84 | "!**/dist/**"
85 | ],
86 | "coverageThreshold": {
87 | "global": {
88 | "branches": 50,
89 | "functions": 50,
90 | "lines": 50,
91 | "statements": 50
92 | }
93 | }
94 | },
95 | "devDependencies": {
96 | "@babel/plugin-proposal-class-properties": "^7.7.0",
97 | "@babel/plugin-proposal-decorators": "^7.7.0",
98 | "@babel/plugin-transform-runtime": "^7.6.2",
99 | "@babel/preset-env": "^7.7.1",
100 | "@babel/preset-react": "^7.7.0",
101 | "add-asset-html-webpack-plugin": "^3.1.3",
102 | "autoprefixer": "^9.7.2",
103 | "babel-eslint": "~8.2.1",
104 | "babel-jest": "^23.6.0",
105 | "babel-loader": "^8.0.6",
106 | "babel-plugin-import": "^1.12.2",
107 | "babel-plugin-transform-es2015-modules-commonjs": "^6.26.2",
108 | "babel-plugin-transform-runtime": "~6.23.0",
109 | "clean-webpack-plugin": "^3.0.0",
110 | "concurrently": "^4.0.1",
111 | "copy-webpack-plugin": "^4.2.3",
112 | "coveralls": "^3.0.0",
113 | "cross-env": "^5.1.4",
114 | "css-loader": "^3.2.0",
115 | "dll-link-webpack-plugin": "^3.2.1",
116 | "enzyme": "^3.7.0",
117 | "eslint": "~4.15.0",
118 | "eslint-config-airbnb": "~16.1.0",
119 | "eslint-plugin-babel": "~4.1.2",
120 | "eslint-plugin-import": "~2.8.0",
121 | "eslint-plugin-jsx-a11y": "~6.0.3",
122 | "eslint-plugin-react": "~7.5.1",
123 | "file-loader": "^4.2.0",
124 | "happypack": "^5.0.0",
125 | "html-webpack-plugin": "^3.2.0",
126 | "http-proxy": "~1.16.2",
127 | "jest": "^23.6.0",
128 | "jsdom": "^12.2.0",
129 | "less": "~2.7.1",
130 | "less-loader": "^4.0.6",
131 | "mini-css-extract-plugin": "^0.8.0",
132 | "mockjs": "^1.0.1-beta3",
133 | "nodemon": "^2.0.7",
134 | "optimize-css-assets-webpack-plugin": "^5.0.3",
135 | "postcss-loader": "^3.0.0",
136 | "react-addons-test-utils": "~15.6.2",
137 | "sinon": "~4.1.6",
138 | "socket.io": "2.0.4",
139 | "style-loader": "^0.19.1",
140 | "terser-webpack-plugin": "^2.2.1",
141 | "url-loader": "^2.2.0",
142 | "webpack": "^4.41.2",
143 | "webpack-bundle-analyzer": "^3.6.0",
144 | "webpack-cli": "^3.3.10",
145 | "webpack-dev-server": "^3.9.0",
146 | "webpack-merge": "^4.1.1",
147 | "webpack-parallel-uglify-plugin": "^1.1.2"
148 | },
149 | "dependencies": {
150 | "@babel/core": "^7.7.2",
151 | "@babel/plugin-syntax-dynamic-import": "^7.2.0",
152 | "@babel/polyfill": "^7.7.0",
153 | "@babel/runtime": "^7.7.2",
154 | "@babel/runtime-corejs2": "^7.7.2",
155 | "@hot-loader/react-dom": "^16.11.0",
156 | "antd": "^3.25.2",
157 | "axios": "^0.19.0",
158 | "benz-amr-recorder": "^1.0.9",
159 | "clipboard": "^2.0.4",
160 | "core-js": "^2.6.10",
161 | "crypto-js": "^3.1.9-1",
162 | "draft-js": "^0.10.3",
163 | "echarts": "^4.5.0",
164 | "enzyme-adapter-react-16": "^1.6",
165 | "esri-loader": "0.3.1",
166 | "husky": "^1.1.2",
167 | "identity-obj-proxy": "^3.0.0",
168 | "immutable": "~3.8.1",
169 | "lint-staged": "^7.3.0",
170 | "md5": "^2.2.1",
171 | "prop-types": "^15.7.2",
172 | "rc-queue-anim": "^1.4.1",
173 | "rc-tween-one": "~1.7.3",
174 | "react": "^16.12.0",
175 | "react-copy-to-clipboard": "~5.0.1",
176 | "react-dom": "^16.5.2",
177 | "react-hot-loader": "^4.12.18",
178 | "react-redux": "~5.0.6",
179 | "react-router": "3.2.0",
180 | "react-router-redux": "~4.0.5",
181 | "redux": "~3.7.2",
182 | "redux-actions": "~2.2.1",
183 | "redux-mock-store": "^1.5.3",
184 | "redux-thunk": "~2.2.0",
185 | "require": "^2.4.20",
186 | "socket.io-client": "^2.2.0"
187 | }
188 | }
189 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: [
3 | require('autoprefixer')
4 | ],
5 | }
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | [](https://circleci.com/gh/duxianwei520/react)
2 | [](https://github.com/duxianwei520/react/network)
3 | [](https://github.com/duxianwei520/react/stargazers)
4 | [](https://github.com/duxianwei520/react/issues)
5 | [](https://github.com/duxianwei520/react/blob/master/LICENSE)
6 | [](https://coveralls.io/github/duxianwei520/react)
7 |
8 | ## 项目技术栈
9 |
10 | node10.15.3 + react@16.12.0 + redux@3.7.2 + react-router@3.2.0 + webpack@4.41.2 + axios@0.19.0 + less@2.7.1 + antd@3.25.2
11 |
12 | ## 交流
13 | QQ群:159697743
14 |
15 | ## 项目运行
16 |
17 |
18 | ```
19 | git clone --depth 1 https://github.com/duxianwei520/react.git
20 |
21 | cd react (进入项目)
22 |
23 | npm install (安装依赖包)
24 |
25 | npm start (启动服务)
26 |
27 | ```
28 |
29 | ### 如果有小伙伴因为网络原因npm包下载不下来,那么可以最好挂在一个vpn之类的去下载,cnpm不靠谱,不推荐使用
30 |
31 |
32 | ## screenshots
33 |
34 |
35 | ### login
36 |
37 |
38 |
39 | ### echart
40 |
41 |
42 |
43 |
44 | ### set center
45 |
46 |
47 |
48 |
49 | ### webpack bundle analysis
50 |
51 |
52 |
53 | ### build dist folder
54 |
55 |
56 |
57 |
58 | 最后的构建命令
59 | ```
60 | npm run build (正式环境的打包部署)
61 | npm run testing (测试环境的打包部署命令,可以根据具体需求自行配置修改)
62 |
63 | ```
64 |
65 | 服务端返回的数据格式也是标准的json,如下所示
66 |
67 | ```
68 | {
69 | data: {
70 | totalCount: 100,
71 | currentPage: 1,
72 | pageSize: 10,
73 | 'list': [
74 | ],
75 | },
76 | msg: '',
77 | status: 1,
78 | }
79 |
80 | ```
81 | 所有异步请求返回都会经过configs里面的ajax.js做处理,如果请求没有任何问题,那status返回值是1;
82 | 如果请求错误,比如说参数错误或者其他报错之类的,那status返回值就是0;
83 | 如果status值是-1,表示登录超时,那么就会跳出登录。
84 | 这些参数都可以根据实际情况进行调整,报错或者成功的提示信息放在msg里面返回。
85 | 当前项目集成了完整的用户管理、角色管理、模块管理等基本的权限管理功能,小伙伴们一定要同时启动npm run mock才可以看到噢
86 |
87 | 这个react的项目我有在跟nodejs的express框架配合做接口的开发,可以不靠后端输出数据库真实的数据,仓库地址在
88 |
89 | ```
90 | https://github.com/duxianwei520/express
91 |
92 | ```
93 | 还有一个原生的nodejs版本的,仓库库地址是
94 |
95 | ```
96 | https://github.com/duxianwei520/node
97 |
98 | ```
99 | 基本功能差不多,目前实现了注册登录以及获取用户信息等3个接口的真实api
100 |
101 |
102 | ## 说明
103 |
104 | > 如有问题请直接在 Issues 中提,或者您发现问题并有非常好的解决方案,欢迎 PR 👍
105 |
106 | ### 大部分人项目启动不起来的原因,绝大部分的情况都是npm依赖包安装的时候有些依赖包没有下载完全,当前的demo肯定是可以跑起来的
107 |
108 | ### 取消http请求示例:
109 | ```
110 | import axios from 'axios'
111 | const axiosHandle = axios.CancelToken.source()
112 |
113 | login(){
114 | this.props.dispatch(fetchLogin(values, (res) => {},(error)=>{},axiosHandle)
115 | 取消请求的操作
116 | setTimeout(() => {
117 | axiosHandle.cancel('手动取消。')
118 | }, 3000)
119 | }
120 |
121 | ```
122 |
123 |
124 | ## 功能一览
125 | - [√] 登录,以及登录权限控制
126 | - [√] 项目公用npm模块dll化
127 | - [√] redux完整示范
128 | - [√] mockjs模拟后端返回接口
129 | - [√] axios异步请求跨域的设置
130 | - [√] 实时的webpack包大小预览,方便优化
131 | - [√] draftjs编辑器
132 |
133 |
134 |
135 | ## License
136 |
137 | [MIT](https://github.com/duxianwei520/react/blob/master/LICENSE)
138 |
139 |
140 | ## 交流
141 | 想跟其他的使用react的小伙伴们交流的话,可以加入我创建的reactQQ群:159697743
--------------------------------------------------------------------------------
/scripts/webpack.dev.config.js:
--------------------------------------------------------------------------------
1 |
2 | const path = require('path')
3 | const webpack = require('webpack')
4 | const merge = require('webpack-merge')
5 | const webpackConfigBase = require('./webpack.base.config')
6 | const HtmlWebpackPlugin = require('html-webpack-plugin')
7 | const { CleanWebpackPlugin } = require('clean-webpack-plugin')
8 | const os = require('os')
9 | let selfIp
10 | try {
11 | // selfIp = os.networkInterfaces()['WLAN'][1].address
12 | selfIp = getIpAddress()
13 | } catch (e) {
14 | selfIp = 'localhost'
15 | }
16 |
17 | const PORT = 8888
18 | // 精确的获取本机ip地址
19 | function getIpAddress () {
20 | const interfaces = require('os').networkInterfaces
21 | for (let devName in interfaces) {
22 | const iface = interfaces[devName]
23 | for (let i = 0; i < iface.length; i += 1) {
24 | let alias = iface[i]
25 | if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {
26 | return alias.address
27 | }
28 | }
29 | }
30 | }
31 |
32 | function resolve(relatedPath) {
33 | return path.join(__dirname, relatedPath)
34 | }
35 | const webpackConfigDev = {
36 | mode: 'development',
37 | plugins: [
38 | // 定义环境变量为开发环境
39 | new webpack.DefinePlugin({
40 | 'process.env.NODE_ENV': JSON.stringify('development'),
41 | IS_DEVELOPMETN: true,
42 | }),
43 | // 将打包后的资源注入到html文件内
44 | new HtmlWebpackPlugin({
45 | template: resolve('../app/index.html'),
46 | dlls: [],
47 | }),
48 | new CleanWebpackPlugin(),
49 | new webpack.HotModuleReplacementPlugin()
50 | ],
51 | devtool: 'cheap-module-eval-source-map',
52 | devServer: {
53 | contentBase: resolve('../app'),
54 | historyApiFallback: false,
55 | open: true,
56 | hot: true,
57 | host: selfIp,
58 | port: PORT,
59 | },
60 | }
61 |
62 | module.exports = merge(webpackConfigBase, webpackConfigDev)
63 |
--------------------------------------------------------------------------------
/scripts/webpack.dll.config.js:
--------------------------------------------------------------------------------
1 | const webpack = require('webpack')
2 | const path = require('path')
3 | const { CleanWebpackPlugin } = require('clean-webpack-plugin')
4 |
5 | module.exports = {
6 | mode:"production",
7 | entry: {
8 | vendor: [
9 | // '@babel/polyfill',
10 | 'react',
11 | 'react-dom',
12 | 'react-router',
13 | 'axios',
14 | 'lodash'
15 | ],
16 | redux: [
17 | 'redux',
18 | 'redux-thunk',
19 | 'react-redux',
20 | 'react-router-redux',
21 | ],
22 | },
23 | devtool: 'source-mapcheap-module-eval-souce-map',
24 | output: {
25 | filename: '[name].dll.js',
26 | path: path.join(__dirname, '../app/resource/dll'),
27 | library: '[name]_[hash]',
28 | },
29 | performance: false,
30 | plugins: [
31 | new CleanWebpackPlugin({
32 | cleanOnceBeforeBuildPatterns:[path.join(__dirname, '../app/resource/dll')],
33 | verbose:true,
34 | }),
35 | // 定义环境变量为开发环境
36 | new webpack.DefinePlugin({
37 | 'process.env.NODE_ENV': JSON.stringify('production'),
38 | IS_DEVELOPMETN: true,
39 | }),
40 |
41 | // 使用插件 DllPlugin
42 | new webpack.DllPlugin({
43 | path: path.join(__dirname, '../app/resource/dll', '[name].manifest.json'),
44 | // This must match the output.library option above
45 | name: '[name]_[hash]',
46 | context: __dirname
47 | }),
48 |
49 |
50 | ]
51 | };
--------------------------------------------------------------------------------
/scripts/webpack.prod.config.js:
--------------------------------------------------------------------------------
1 |
2 | const webpack = require('webpack')
3 | const path = require('path')
4 | const merge = require('webpack-merge')
5 | const webpackConfigBase = require('./webpack.base.config')
6 | const Copy = require('copy-webpack-plugin')
7 | const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
8 | const HtmlWebpackPlugin = require('html-webpack-plugin')
9 | const { CleanWebpackPlugin } = require('clean-webpack-plugin')
10 | const TerserJSPlugin = require("terser-webpack-plugin");
11 | const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
12 |
13 | function resolve(relatedPath) {
14 | return path.join(__dirname, relatedPath)
15 | }
16 |
17 | const webpackConfigProd = {
18 | mode: 'production',
19 | output: {
20 | publicPath: './',
21 | },
22 | devtool: 'cheap-module-source-map',
23 | optimization: {
24 | minimizer: [
25 | new TerserJSPlugin({ // 多进程压缩
26 | // 设置缓存目录
27 | cache: path.resolve('.cache'),
28 | parallel: 4,// 开启多进程压缩
29 | // sourceMap,
30 | terserOptions: {
31 | compress: {
32 | // 删除所有的 `console` 语句
33 | drop_console: true,
34 | },
35 | },
36 | }),
37 | ]
38 | },
39 | plugins: [
40 | // 定义环境变量为开发环境
41 | new webpack.DefinePlugin({
42 | 'process.env.NODE_ENV': JSON.stringify('production'),
43 | IS_DEVELOPMETN: false,
44 | }),
45 | // 将打包后的资源注入到html文件内
46 | new HtmlWebpackPlugin({
47 | // inject: true, // will inject the main bundle to index.html
48 | template: resolve('../app/index.html'),
49 | // mapConfig:'http://192.168.0.1/map_config.js',
50 | // 这里列出要加入html中的js文件 注释不用dll
51 | dlls: [
52 | // './resource/dll/vendor.dll.js',
53 | // './resource/dll/redux.dll.js',
54 | ],
55 | }),
56 | // 分析代码
57 | new BundleAnalyzerPlugin({ analyzerMode: 'static' }),
58 | new Copy([
59 | // { from: './app/resource/dll', to: '../dist/resource/dll' },
60 | ]),
61 | new OptimizeCSSAssetsPlugin(),
62 | new CleanWebpackPlugin(),
63 | ],
64 | }
65 |
66 | module.exports = merge(webpackConfigBase, webpackConfigProd)
67 |
--------------------------------------------------------------------------------
/scripts/webpack.testing.config.js:
--------------------------------------------------------------------------------
1 |
2 | const webpack = require('webpack')
3 | const path = require('path')
4 | const merge = require('webpack-merge')
5 | const webpackConfigBase = require('./webpack.base.config')
6 | const Copy = require('copy-webpack-plugin')
7 | const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
8 | const HtmlWebpackPlugin = require('html-webpack-plugin')
9 | const { CleanWebpackPlugin } = require('clean-webpack-plugin')
10 |
11 | function resolve(relatedPath) {
12 | return path.join(__dirname, relatedPath)
13 | }
14 |
15 | const webpackConfigProd = {
16 | mode: 'development',
17 | output: {
18 | publicPath: './',
19 | },
20 | plugins: [
21 | // 定义环境变量为开发环境
22 | new webpack.DefinePlugin({
23 | 'process.env.NODE_ENV': JSON.stringify('testing'),
24 | IS_DEVELOPMETN: false,
25 | }),
26 | // 将打包后的资源注入到html文件内
27 | new HtmlWebpackPlugin({
28 | // inject: true, // will inject the main bundle to index.html
29 | template: resolve('../app/index.html'),
30 | // mapConfig:'http://192.168.0.1/map_config.js', 注释不用dll
31 | // 这里列出要加入html中的js文件
32 | dlls: [
33 | // './resource/dll/vendor.dll.js',
34 | // './resource/dll/redux.dll.js',
35 | ],
36 | }),
37 |
38 | // 分析代码
39 | new BundleAnalyzerPlugin({ analyzerMode: 'static' }),
40 | new Copy([
41 | // { from: './app/resource/dll', to: '../dist/resource/dll' },
42 | ]),
43 | new CleanWebpackPlugin(),
44 | ],
45 | }
46 |
47 | module.exports = merge(webpackConfigBase, webpackConfigProd)
48 |
--------------------------------------------------------------------------------
/test/Enzyme.js:
--------------------------------------------------------------------------------
1 | import Enzyme from 'enzyme';
2 | import Adapter from 'enzyme-adapter-react-16';
3 |
4 | Enzyme.configure({
5 | adapter: new Adapter(),
6 | });
7 |
8 | export default Enzyme;
9 |
--------------------------------------------------------------------------------
/test/setCenter/sys/moduleManage/index.spec.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Enzyme from "../../../Enzyme.js";
3 | import RoleManage from "../../../../app/pages/set/roleManage/index";
4 | import ModuleManage from "../../../../app/pages/set/moduleManage/index";
5 | import AddModal from "../../../../app/pages/set/moduleManage/modal/moduleAdd";
6 | import fetchTreeList from "../../../../app/mocks/apis/sys/roleManage/fetchTreeList";
7 | import ButtonModal from "../../../../app/pages/set/moduleManage/modal/buttonModal";
8 | jest.mock("../../../../app/pages/set/moduleManage/modal/addButtonModal");
9 |
10 | let form;
11 | let moduleManage = Enzyme.mount();
12 | console.log(moduleManage)
13 | moduleManage.setState({ tableDataSource: fetchTreeList.data.list });
14 | jest.mock("../../../../app/configs/ajax");
15 | jest.mock("../../../../app/apis/manage.js");
16 | //页面树
17 | test("tree", () => {
18 | //进入页面渲染
19 | expect(moduleManage.find("tbody tr").length).toBe(
20 | fetchTreeList.data.list.length
21 | );
22 | //点击tree效果
23 | moduleManage
24 | .find("tbody tr")
25 | .at(0)
26 | .find("span")
27 | .at(1)
28 | .simulate("click");
29 | expect(moduleManage.find("tbody tr").length).toBe(
30 | fetchTreeList.data.list.length + fetchTreeList.data.list[0].children.length
31 | );
32 | //状态以上线的类名
33 | expect(
34 | moduleManage
35 | .find(".success")
36 | .at(0)
37 | .text()
38 | ).toBe("已上线");
39 | });
40 | test("cancelButton", () => {
41 | moduleManage.instance().cancelButton();
42 | moduleManage.instance().handleCancel();
43 | moduleManage.setState({ buttonEditState: "add" });
44 | moduleManage.instance().handleAdd({});
45 |
46 | });
47 | //新增模块
48 | test("addButton/editButton", () => {
49 | moduleManage.find("button").simulate("click");
50 | //新建按钮点击
51 | expect(moduleManage.state("Visible")).toBe(true);
52 | //新建子菜单按钮点击
53 | moduleManage
54 | .find("tbody tr")
55 | .at(0)
56 | .find("a")
57 | .at(0)
58 | .simulate("click");
59 | expect(moduleManage.state("title")).toBe("新增子菜单");
60 | //权限按钮点击
61 | moduleManage
62 | .find("tbody tr")
63 | .at(0)
64 | .find("a")
65 | .at(3)
66 | .simulate("click");
67 | expect(moduleManage.state("buttonVisible")).toBe(true);
68 | });
69 |
--------------------------------------------------------------------------------
/test/setCenter/sys/moduleManage/module/addButtonModal.spec.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { createStore } from "redux";
3 | import { Provider } from "react-redux";
4 | import Enzyme from "../../../../Enzyme.js";
5 | import RoleManage from "../../../../../app/pages/set/roleManage/index";
6 | import ModuleManage from "../../../../../app/pages/set/moduleManage/index";
7 | import AddButtonModal from "../../../../../app/pages/set/moduleManage/modal/addButtonModal";
8 | import fetchButtonList from "../../../../../app/mocks/apis/sys/roleManage/fetchButtonList";
9 | import rootReducer from "../../../../../app/redux/reducers";
10 |
11 | const moduleManage = Enzyme.mount();
12 | jest.mock("../../../../../app/configs/ajax");
13 | jest.mock("../../../../../app/apis/manage.js");
14 | jest.mock("../../../../../app/components/draw/draw");
15 | // jest.mock("../../../../../app/pages/set/moduleManage/modal/addButtonModal");
16 |
17 | let store;
18 | let wrapper;
19 | let form;
20 | //新增 参数
21 | const addParam = {
22 | buttonEditData: {},
23 | title: "新增按钮权限",
24 | onCancel: moduleManage.instance().handleCancel,
25 | handleAdd: moduleManage.instance().handleAdd,
26 | state: "add",
27 | visible: true
28 | };
29 | store = createStore(rootReducer);
30 | wrapper = Enzyme.mount(
31 |
32 | (form = node)} />
33 |
34 | );
35 | //当前页面的WrappedComponent
36 | const ButtonModal = wrapper.prop("children").type.WrappedComponent;
37 |
38 | test("add", () => {
39 | moduleManage.setState({ buttonEditState: "add" });
40 | const buttonModal = Enzyme.mount(
41 |
42 | );
43 | buttonModal
44 | .find(".ant-modal-footer button")
45 | .at(0)
46 | .simulate("click");
47 | });
48 | //编辑
49 | test("edit", () => {
50 | moduleManage.setState({ buttonEditState: "edit" });
51 | const editParam = {
52 | buttonEditData: fetchButtonList.data.list[0],
53 | handleOk: moduleManage.instance().handleOk,
54 | title: "修改按钮权限",
55 | onCancel: moduleManage.instance().handleCancel,
56 | handleAdd: moduleManage.instance().handleAdd,
57 | state: "edit"
58 | };
59 | const buttonModal = Enzyme.mount(
60 |
61 | );
62 | buttonModal
63 | .find(".ant-modal-footer button")
64 | .at(0)
65 | .simulate("click");
66 | buttonModal
67 | .find(".ant-modal-footer button")
68 | .at(0)
69 | .simulate("click");
70 | buttonModal
71 | .prop("form")
72 | .setFieldsValue({ resName: fetchButtonList.data.list[0].resName });
73 | buttonModal
74 | .prop("form")
75 | .setFieldsValue({ sort: fetchButtonList.data.list[0].sort });
76 | buttonModal
77 | .prop("form")
78 | .setFieldsValue({ resKey: fetchButtonList.data.list[0].resKey });
79 | buttonModal
80 | .find(".ant-modal-footer button")
81 | .at(0)
82 | .simulate("click");
83 | });
84 |
--------------------------------------------------------------------------------
/test/setCenter/sys/moduleManage/module/addmodal.spec.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Enzyme from "../../../../Enzyme.js";
3 | import RoleManage from "../../../../../app/pages/set/roleManage/index";
4 | import ModuleManage from "../../../../../app/pages/set/moduleManage/index";
5 | import AddModal from "../../../../../app/pages/set/moduleManage/modal/moduleAdd";
6 | import fetchModuleDetail from "../../../../../app/mocks/apis/sys/moduleManage/fetchModuleDetail";
7 |
8 | const moduleManage = Enzyme.mount();
9 | jest.mock("../../../../../app/configs/ajax");
10 | jest.mock("../../../../../app/apis/manage.js");
11 | jest.mock("../../../../../app/components/draw/draw");
12 | jest.mock("../../../../../app/pages/set/moduleManage/modal/addButtonModal");
13 |
14 | let form;
15 | const ModalParam = {
16 | handleOk: moduleManage.instance().handleOk,
17 | visible: true,
18 | title: moduleManage.state("title"),
19 | pid: "",
20 | itemId: "",
21 | values: [],
22 | type: "add",
23 | onCancel: moduleManage.instance().handleCancel
24 | };
25 |
26 | function modalParam(ModalParam) {
27 | Enzyme.mount(
28 | (form = node)} {...ModalParam} />
29 | );
30 | const addModal = Enzyme.mount(
31 |
32 | );
33 | return addModal;
34 | }
35 | test("add", () => {
36 | const add = {
37 | handleOk: moduleManage.instance().handleOk,
38 | title: "新增菜单",
39 | Visible: true,
40 | pid: "",
41 | itemId: 10063,
42 | type: "add",
43 | values: {}
44 | };
45 | const addModal = modalParam(add);
46 | addModal
47 | .find(".ant-modal-footer button")
48 | .at(0)
49 | .simulate("click");
50 | addModal
51 | .prop("form")
52 | .setFieldsValue({ parentId: fetchModuleDetail.data.deptCode });
53 | addModal
54 | .prop("form")
55 | .setFieldsValue({ resName: fetchModuleDetail.data.resName });
56 | addModal
57 | .prop("form")
58 | .setFieldsValue({ sort: fetchModuleDetail.data.sort });
59 | addModal
60 | .prop("form")
61 | .setFieldsValue({ resModule: fetchModuleDetail.data.resModule });
62 | addModal
63 | .prop("form")
64 | .setFieldsValue({ resKey: fetchModuleDetail.data.resKey });
65 | addModal
66 | .prop("form")
67 | .setFieldsValue({ resIcon: fetchModuleDetail.data.resIcon });
68 | addModal
69 | .find(".ant-modal-footer button")
70 | .at(0)
71 | .simulate("click");
72 | });
73 | test("edit", () => {
74 | //编辑参数
75 | const editParam = {
76 | handleOk: moduleManage.instance().handleOk,
77 | title: "修改菜单",
78 | Visible: true,
79 | pid: "",
80 | itemId: 10063,
81 | type: "modify",
82 | values: fetchModuleDetail.data
83 | };
84 | const editModal = modalParam(editParam);
85 | //表单验证
86 | editModal.prop("form").validateFields((err, values) => {
87 | expect(values.parentId).toBe(editModal.prop("pid"));
88 | expect(values.resName).toBe(fetchModuleDetail.data.resName);
89 | expect(values.sort).toBe(String(fetchModuleDetail.data.sort));
90 | expect(values.resModule).toBe(fetchModuleDetail.data.resModule);
91 | expect(values.resKey).toBe(fetchModuleDetail.data.resKey);
92 | expect(values.resIcon).toBe(fetchModuleDetail.data.resIcon);
93 | });
94 | //提交
95 | editModal
96 | .find(".ant-modal-footer button")
97 | .at(0)
98 | .simulate("click");
99 |
100 | });
101 |
--------------------------------------------------------------------------------
/test/setCenter/sys/moduleManage/module/buttonModal.spec.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Enzyme from "../../../../Enzyme.js";
3 | import RoleManage from "../../../../../app/pages/set/roleManage/index";
4 | import ModuleManage from "../../../../../app/pages/set/moduleManage/index";
5 | import ButtonModal from "../../../../../app/pages/set/moduleManage/modal/buttonModal";
6 | import fetchButtonList from "../../../../../app/mocks/apis/sys/roleManage/fetchButtonList";
7 |
8 | jest.mock("../../../../../app/configs/ajax");
9 | jest.mock("../../../../../app/apis/manage.js");
10 | jest.mock("../../../../../app/components/draw/draw");
11 | jest.mock("../../../../../app/pages/set/moduleManage/modal/addButtonModal");
12 |
13 | const moduleManage = Enzyme.mount();
14 | function modalParam(ModalParam) {
15 | return Enzyme.mount();
16 | }
17 | fetchButtonList.data.list[0].status = 1;
18 | //页面表格渲染
19 | const editParam = {
20 | Visible: true,
21 | pid: "",
22 | itemId: 10063,
23 | dataSource: fetchButtonList.data.list,
24 | listLoading: true,
25 | title: "模块按钮权限列表",
26 | addButton: moduleManage.instance().addButton,
27 | updateList: moduleManage.instance().getButtonList,
28 | editButton: moduleManage.instance().editButton
29 | };
30 | const BtnModal = modalParam(editParam);
31 |
32 | test("delete", () => {
33 | BtnModal.find("tbody tr")
34 | .at(0)
35 | .find("a")
36 | .at(2)
37 | .simulate("click");
38 | BtnModal.find("Popconfirm button")
39 | .at(1)
40 | .simulate("click");
41 | });
42 | test("edit", () => {
43 | BtnModal.find("tbody tr")
44 | .at(0)
45 | .find("a")
46 | .at(1)
47 | .simulate("click");
48 | });
49 | test("showOrHide", () => {
50 | BtnModal.find("tbody tr")
51 | .at(0)
52 | .find("a")
53 | .at(0)
54 | .simulate("click");
55 | BtnModal.find("Popconfirm button")
56 | .at(1)
57 | .simulate("click");
58 | });
59 | test("add", () => {
60 | BtnModal.find(".ant-modal-footer button")
61 | .at(0)
62 | .simulate("click");
63 | });
64 | //表格数据
65 | test("module list", () => {
66 | expect(BtnModal.find("tbody tr").length).toBe(
67 | fetchButtonList.data.list.length
68 | );
69 | });
70 |
--------------------------------------------------------------------------------
/test/setCenter/sys/moduleManage/moduleList.spec.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Enzyme from "../../../Enzyme.js";
3 | import RoleManage from "../../../../app/pages/set/roleManage/index";
4 | import ModuleManage from "../../../../app/pages/set/moduleManage/index";
5 | import AddModal from "../../../../app/pages/set/moduleManage/modal/moduleAdd";
6 | import fetchModuleList from "../../../../app/mocks/apis/sys/moduleManage/fetchModuleList";
7 | import ModuleList from "../../../../app/pages/set/moduleManage/moduleList";
8 | let form;
9 | let moduleManage = Enzyme.mount();
10 | moduleManage.setState({ tableDataSource: fetchModuleList.data.list });
11 | jest.mock("../../../../app/configs/ajax");
12 | jest.mock("../../../../app/apis/manage.js");
13 | fetchModuleList.data.list[0].status = true;
14 | fetchModuleList.data.list[1].resName = "模块管理";
15 | const param = {
16 | dataSource: fetchModuleList.data.list,
17 | loading: true,
18 | onDelete: moduleManage.instance().handleDelete,
19 | onModify: moduleManage.instance().handleModify,
20 | onUpdataStatus: moduleManage.instance().handleChangeStatus,
21 | onAddNode: moduleManage.instance().handleAddNode,
22 | buttonList: moduleManage.instance().buttonList
23 | };
24 | let moduleList = Enzyme.mount();
25 | console.log(moduleList)
26 | fetchModuleList.data.list[1].resName = "123";
27 | moduleList.setProps({ dataSource: fetchModuleList.data.list });
28 | test("addButton", () => {
29 | moduleList
30 | .find("tbody tr")
31 | .at(0)
32 | .find("a")
33 | .at(0)
34 | .simulate("click");
35 | expect(moduleManage.state("title")).toBe("新增子菜单");
36 | });
37 | test("editButton", () => {
38 | moduleList
39 | .find("tbody tr")
40 | .at(0)
41 | .find("a")
42 | .at(1)
43 | .simulate("click");
44 | expect(moduleManage.state("title")).toBe("修改菜单");
45 | });
46 | test("UpdataStatus", () => {
47 | moduleList
48 | .find("tbody tr")
49 | .at(1)
50 | .find("a")
51 | .at(2)
52 | .simulate("click");
53 | moduleList
54 | .find("Popconfirm button")
55 | .at(1)
56 | .simulate("click");
57 | });
58 | test("delete", () => {
59 | //点击tree效果
60 | moduleList
61 | .find("tbody tr")
62 | .at(0)
63 | .find("span")
64 | .at(1)
65 | .simulate("click");
66 | //点击子元素的删除按钮
67 | moduleList
68 | .find("tbody tr")
69 | .at(1)
70 | .find("a")
71 | .at(2)
72 | .simulate("click");
73 | moduleList
74 | .find("Popconfirm button")
75 | .at(1)
76 | .simulate("click");
77 | });
78 |
--------------------------------------------------------------------------------
/test/setCenter/sys/roleManage/index.spec.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Enzyme from "../../../Enzyme.js";
3 | import RoleManage from "../../../../app/pages/set/roleManage/index";
4 | import fetchRoleList from "../../../../app/mocks/apis/sys/userManage/fetchRoleList";
5 | import fetchModuleListInRole from "../../../../app/mocks/apis/sys/roleManage/fetchModuleListInRole";
6 | import RoleList from "../../../../app/pages/set/roleManage/roleList";
7 | import fetchUserList from "../../../../app/mocks/apis/sys/userManage/fetchUserList";
8 | jest.mock("../../../../app/configs/ajax");
9 | jest.mock("../../../../app/apis/manage.js");
10 | let form;
11 | fetchRoleList.data.list[0].id = null;
12 | const listParam = {
13 | roles: fetchRoleList.data.list,
14 | btnRights: {}
15 | };
16 | const roleList = Enzyme.mount();
17 |
18 | Enzyme.mount( (form = node)} />);
19 | let roleManage = Enzyme.mount(
20 |
21 | );
22 |
23 | describe("index", () => {
24 | const eve = {
25 | target: {
26 | value: "setpeoples"
27 | }
28 | };
29 | roleManage.instance().changeTab(eve);
30 | eve.target.value = "stepTree";
31 | roleManage.instance().changeTab(eve);
32 | eve.target.value = "setmodules";
33 | roleManage.instance().changeTab(eve);
34 | roleManage.setState({ activeTab: "setpeoples" });
35 | roleManage.instance().getData("init");
36 | roleManage.instance().returnContent("i");
37 |
38 | roleManage.setState({
39 | btnRights: {
40 | add: false,
41 | edit: true,
42 | deleteRole: true,
43 | deletePolice: false
44 | }
45 | });
46 | roleManage.instance().renderColumn();
47 | roleManage.setState({
48 | btnRights: {
49 | add: true,
50 | edit: true,
51 | deleteRole: true,
52 | deletePolice: true
53 | }
54 | });
55 | //搜索
56 | test("search", () => {
57 | roleManage.instance().handleRoleSearch("123");
58 | });
59 | //编辑保存
60 | test("editsave", () => {
61 | roleManage.setState({ activeTab: "setpeoples" });
62 | roleManage
63 | .find(".left button")
64 | .at(0)
65 | .simulate("click");
66 | });
67 | //删除
68 | test("delete", () => {
69 | roleManage.setState({ activeTab: "setpeoples" });
70 | roleManage
71 | .find("tbody tr")
72 | .at(0)
73 | .find("a")
74 | .simulate("click");
75 | roleManage
76 | .find("Popconfirm button")
77 | .at(1)
78 | .simulate("click");
79 | });
80 | //列表搜索
81 | test("listSearch", () => {
82 | const event = {
83 | stopPropagation: function() {}
84 | };
85 | roleManage.instance().handleSearch(event);
86 | });
87 | //提交
88 | test("测试提交", () => {
89 | roleManage.setState({ activeTab: "setpeoples" });
90 |
91 | roleManage.instance().handleOk();
92 | roleManage.setState({ activeTab: "setmodules" });
93 |
94 | roleManage.instance().handleOk();
95 | });
96 | //Modal关闭函数
97 | test("Modal取消", () => {
98 | roleManage.instance().handleCancel();
99 | });
100 | test("pagenext", () => {
101 | roleManage.instance().pageChange(2);
102 | expect(roleManage.state().peopleSearchKey.pageNo).toBe(2);
103 | roleManage.instance().pageSizeChange({}, 20);
104 | expect(roleManage.state().peopleSearchKey.pageSize).toBe(20);
105 | });
106 | });
107 | //roleList模块
108 | describe("roleList", () => {
109 | roleList.setProps({
110 | roles: fetchRoleList.data.list,
111 | handleRoleDelete: roleManage.instance().handleRoleDelete,
112 | onCurrentIndex: roleManage.instance().handleCurrentIndex,
113 | btnRights: roleManage.state().btnRights,
114 | onRoleModify: roleManage.instance().onRoleModify
115 | });
116 | roleManage.setState({
117 | roleListResult: false
118 | });
119 | //左侧角色列表查询
120 | test("fetchUserList", () => {
121 | expect(roleManage.find(".roleslist li").length).toBe(
122 | fetchRoleList.data.list.length
123 | );
124 | });
125 | //搜索
126 | test("onSearch", () => {
127 | roleManage.find('.ant-input-wrapper .ant-input-suffix').simulate('click')
128 | roleManage.find('.ant-input-wrapper .ant-input-suffix i').simulate('click')
129 | });
130 | //编辑
131 |
132 | test("edit", () => {
133 | roleList
134 | .find("li")
135 | .at(0)
136 | .simulate("mouseover");
137 | roleList
138 | .find(".icons")
139 | .at(0)
140 | .find("i")
141 | .at(0)
142 | .simulate("click");
143 | });
144 | //删除
145 | test("delete", () => {
146 | roleList
147 | .find("li")
148 | .at(0)
149 | .simulate("mouseover");
150 | roleList
151 | .find(".icons")
152 | .at(0)
153 | .find("i")
154 | .at(1)
155 | .simulate("click");
156 | roleList
157 | .find("Popconfirm button")
158 | .at(1)
159 | .simulate("click");
160 | });
161 | //左侧菜单栏点击事件
162 | test("nameClick", () => {
163 | roleManage.setState({ activeTab: "stepTree" });
164 | roleManage
165 | .find(".roleslist li")
166 | .at(0)
167 | .find(".name")
168 | .simulate("click");
169 | roleManage.setState({ activeTab: "setpeoples" });
170 | roleManage
171 | .find(".roleslist li")
172 | .at(0)
173 | .find(".name")
174 | .simulate("click");
175 | roleManage.setState({ activeTab: "setmodules" });
176 | roleManage
177 | .find(".roleslist li")
178 | .at(0)
179 | .find(".name")
180 | .simulate("click");
181 | expect(roleManage.state("currRoleId")).toBe(fetchRoleList.data.list[0].id);
182 | });
183 | //添加模板
184 | test("addModule", () => {
185 | roleManage.find(".ant-input-group-addon i").simulate("click");
186 | expect(roleManage.state("title")).toBe("新增角色");
187 | expect(roleManage.state("type")).toBe("add");
188 | });
189 | });
190 | //校色树tab
191 | test("UserTreeTab", () => {
192 | roleManage.setState({
193 | activeTab: "stepTree",
194 | treeData: fetchModuleListInRole.data.list
195 | });
196 | expect(roleManage.find("tbody tr").length).toBe(
197 | fetchModuleListInRole.data.list.length
198 | );
199 | roleManage
200 | .find("tbody tr")
201 | .at(0)
202 | .find("span")
203 | .at(1)
204 | .simulate("click");
205 | expect(roleManage.find("tbody tr").length).toBe(
206 | fetchModuleListInRole.data.list.length +
207 | fetchModuleListInRole.data.list[0].children.length
208 | );
209 | });
210 |
--------------------------------------------------------------------------------
/test/setCenter/sys/roleManage/modal/buttonModal.spec.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Enzyme from "../../../../Enzyme.js";
3 | import RoleManage from "../../../../../app/pages/set/roleManage/index";
4 | import ButtonModal from "../../../../../app/pages/set/roleManage/modal/buttonModal";
5 | jest.mock("../../../../../app/configs/ajax");
6 | jest.mock("../../../../../app/apis/manage.js");
7 | jest.mock("../../../../../app/components/draw/draw");
8 | let form1;
9 | Enzyme.mount( (form1 = node)} />);
10 | let roleManage = Enzyme.mount(
11 |
12 | );
13 | const callback = {};
14 | let form = {};
15 |
16 | const param = {
17 | title: "按钮权限列表",
18 | type: "add",
19 | pid: 10062,
20 | itemId: 1,
21 | cancelButton: roleManage.instance().cancelButton,
22 | saveChecked: roleManage.instance().saveChecked,
23 | checkedIdArr: []
24 | };
25 | let buttonModal = Enzyme.mount();
26 | test("全选按钮", () => {
27 | buttonModal
28 | .find(".ant-modal-footer button")
29 | .at(0)
30 | .simulate("click");
31 | });
32 | buttonModal.setState({
33 | selectedRowKeys: [134]
34 | });
35 | test("初始化", () => {
36 | buttonModal.instance().getList();
37 | });
38 | test("确定按钮", () => {
39 | buttonModal
40 | .find(".ant-modal-footer button")
41 | .at(1)
42 | .simulate("click");
43 | });
44 | test("页面按钮点击选中", () => {
45 | buttonModal
46 | .find(".ant-spin-container button")
47 | .at(0)
48 | .simulate("click");
49 | });
50 |
--------------------------------------------------------------------------------
/test/setCenter/sys/roleManage/modal/roleAdd.spec.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Enzyme from "../../../../Enzyme.js";
3 | import RoleManage from "../../../../../app/pages/set/roleManage/index";
4 | import RoleAdd from "../../../../../app/pages/set/roleManage/modal/roleAdd";
5 | import fetchRoleDetail from "../../../../../app/mocks/apis/sys/roleManage/fetchRoleDetail";
6 | jest.mock("../../../../../app/configs/ajax");
7 | jest.mock("../../../../../app/apis/manage.js");
8 | jest.mock("../../../../../app/components/draw/draw");
9 | let form1;
10 | Enzyme.mount( (form1 = node)} />);
11 | let roleManage = Enzyme.mount(
12 |
13 | );
14 | const callback = {};
15 | let form = {};
16 | fetchRoleDetail.data.tjFlag='123'
17 | const param = {
18 | visible: true,
19 | title: "修改角色",
20 | onCancel: roleManage.instance().handleCancel,
21 | handleOk: roleManage.instance().handleOk,
22 | value: fetchRoleDetail.data,
23 | type: "modify",
24 | modifyId: 1
25 | };
26 | let Form = Enzyme.mount(
27 | (form = node)} />
28 | );
29 |
30 | let roleAdd = Enzyme.mount(
31 |
32 | );
33 | test("编辑提交", () => {
34 | const event = {
35 | preventDefault: function() {}
36 | };
37 | roleAdd.instance().handleSubmit(event);
38 | expect(roleAdd.find(".ant-modal-title").text()).toBe("修改角色");
39 | });
40 | test("新增提交", () => {
41 | const event = {
42 | preventDefault: function() {}
43 | };
44 | roleAdd.setProps({
45 | visible: true,
46 | title: "新增角色",
47 | onCancel: roleManage.instance().handleCancel,
48 | handleOk: roleManage.instance().handleOk,
49 | value: { roleName: "", sort: "", tjFlag: "123" },
50 | type: "add"
51 | });
52 | roleAdd
53 | .find(".ant-modal-footer button")
54 | .at(0)
55 | .simulate("click");
56 | expect(roleAdd.find(".ant-modal-title").text()).toBe("新增角色");
57 | roleAdd.prop("form").setFieldsValue({ roleName: "" });
58 | roleAdd
59 | .find(".ant-modal-footer button")
60 | .at(0)
61 | .simulate("click");
62 | roleAdd
63 | .find(".ant-modal-footer button")
64 | .at(0)
65 | .simulate("click");
66 | });
67 |
68 |
--------------------------------------------------------------------------------
/test/setCenter/sys/roleManage/roleCheckbox.spec.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Enzyme from "../../../Enzyme.js";
3 | import RoleManage from "../../../../app/pages/set/roleManage/index";
4 | import fetchRoleList from "../../../../app/mocks/apis/sys/userManage/fetchRoleList";
5 | import UserList from "../../../../app/mocks/apis/sys/userManage/fetchUserList";
6 | import fetchTreeList from "../../../../app/mocks/apis/sys/roleManage/fetchTreeList";
7 | import RoleModuleList from "../../../../app/pages/set/roleManage/roleModuleList";
8 |
9 | let form;
10 | Enzyme.mount( (form = node)} />);
11 | let roleManage = Enzyme.mount(
12 |
13 | );
14 |
15 |
16 | test("roleCheckbox", () => {
17 | const listParam = {
18 | dataSource: [],
19 | checkedId: []
20 | };
21 | const roleModule = Enzyme.mount();
22 | roleModule.setProps({
23 | dataSource: fetchTreeList.data.list,
24 | checkedId: [10062, 10063, 10108, 10109, 10110]
25 | });
26 | roleModule
27 | .find("tbody tr")
28 | .at(1)
29 | .find("span")
30 | .at(1)
31 | .simulate("click");
32 | });
33 |
--------------------------------------------------------------------------------
/test/setCenter/sys/roleManage/roleModuleList.spec.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Enzyme from "../../../Enzyme.js";
3 | import RoleManage from "../../../../app/pages/set/roleManage/index";
4 | import fetchRoleList from "../../../../app/mocks/apis/sys/userManage/fetchRoleList";
5 | import UserList from "../../../../app/mocks/apis/sys/userManage/fetchUserList";
6 | import fetchTreeList from "../../../../app/mocks/apis/sys/roleManage/fetchTreeList";
7 | import fetchModuleListInRole from "../../../../app/mocks/apis/sys/roleManage/fetchModuleListInRole";
8 | import RoleModuleList from "../../../../app/pages/set/roleManage/roleModuleList";
9 | import RoleCheckbox from "../../../../app/pages/set/roleManage/roleCheckbox";
10 | jest.mock("../../../../app/configs/ajax");
11 | jest.mock("../../../../app/apis/manage.js");
12 | let form;
13 | Enzyme.mount( (form = node)} />);
14 | let roleManage = Enzyme.mount(
15 |
16 | );
17 |
18 | describe("roleModuleList", () => {
19 | const listParam = {
20 | dataSource: [],
21 | checkedId: [],
22 | onCheckModify: roleManage.instance().handleCheckModify,
23 | buttonList:roleManage.instance().buttonList
24 | };
25 | const roleModule = Enzyme.mount();
26 | roleModule.setProps({
27 | dataSource: fetchModuleListInRole.data.list,
28 | checkedId: [10062, 10063, 10108, 10109, 10110, 10118, 11003]
29 | });
30 | test("rolecheckbox", () => {
31 | const checkboxParam = {
32 | checkItem: fetchModuleListInRole.data.list[1].children[1],
33 | onChecked: roleModule.instance().onChecked,
34 | defaultChecked: false,
35 | nowRoleName: undefined
36 | };
37 | const roleCheckbox = Enzyme.mount();
38 | roleCheckbox.setProps({ defaultChecked: true });
39 | const event = {
40 | target: {
41 | checked: false
42 | }
43 | };
44 | roleCheckbox.instance().onChange(event);
45 | //未开通的点击成已开通
46 | event.target.checked = true;
47 | roleCheckbox.setProps({
48 | checkItem: fetchModuleListInRole.data.list[1]
49 | });
50 | roleCheckbox.instance().onChange(event);
51 |
52 | event.target.checked = false;
53 | //onInArray函数
54 | roleCheckbox.setProps({
55 | checkItem: fetchModuleListInRole.data.list[1].children[2]
56 | });
57 | roleModule.setState({ checkedIds: null });
58 | roleCheckbox.instance().onChange(event);
59 | roleModule.setState({
60 | checkedIds: [10062, 10108]
61 | });
62 | roleCheckbox.setProps({
63 | checkItem: fetchModuleListInRole.data.list[1].children[0]
64 | });
65 | roleCheckbox.instance().onChange(event);
66 |
67 | //fatherArr.length === 1判断
68 |
69 | fetchModuleListInRole.data.list[1].children.pop();
70 | fetchModuleListInRole.data.list[1].children.pop();
71 | roleCheckbox.setProps({
72 | checkItem: fetchModuleListInRole.data.list[1].children[0]
73 | });
74 | event.target.checked = false;
75 | roleCheckbox.instance().onChange(event);
76 | event.target.checked = true;
77 | roleCheckbox.instance().onChange(event);
78 | //拥有两个父级
79 | event.target.checked = false;
80 | roleCheckbox.setProps({
81 | checkItem: fetchModuleListInRole.data.list[1].children[0].children[0]
82 | });
83 | roleCheckbox.instance().onChange(event);
84 | });
85 | //按钮权限
86 | test('buttonList',()=>{
87 | roleModule.find('tbody tr').at(0).find('a').simulate('click')
88 | })
89 |
90 | });
91 |
--------------------------------------------------------------------------------
/test/setCenter/sys/userManage/index.spec.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Enzyme from "../../../Enzyme.js";
3 | import UserName from "../../../../app/pages/set/userManage/index";
4 | import TreeList from "../../../../app/pages/set/userManage/treeList";
5 | import UserList from "../../../../app/mocks/apis/sys/userManage/fetchUserList";
6 | import AddPolice from "../../../../app/pages/set/userManage/modal/addPolice";
7 | import userDeptResult from "../../../../app/mocks/apis/sys/userManage/fetchUserDepttList";
8 | import TableList from "../../../../app/components/tableList/tableList";
9 | jest.mock("../../../../app/configs/ajax");
10 | jest.mock("../../../../app/apis/manage");
11 |
12 | let form;
13 | Enzyme.mount( (form = node)} />);
14 | let UserManage = Enzyme.mount(
15 |
16 | );
17 | const param = {
18 | deptCode: "370200000000"
19 | };
20 | UserManage.setState({
21 | searchKey: param,
22 | userListResult: UserList.data,
23 | userDeptResult: userDeptResult.data,
24 | btnRights: {
25 | view: false,
26 | freeze: false,
27 | delete: false,
28 | edit: false,
29 | add: false
30 | } // 按钮权限的数组
31 | });
32 |
33 | UserManage.setState({
34 | btnRights: {
35 | view: true,
36 | freeze: true,
37 | delete: true,
38 | edit: true,
39 | add: true
40 | } // 按钮权限的数组
41 | });
42 | // 搜索按钮点击
43 | test("search", () => {
44 | const event = {
45 | preventDefault: function() {}
46 | };
47 | UserManage.instance().handleSearch(event);
48 | });
49 |
50 | // 新增
51 | test("handleChangeStatusAdd", () => {
52 | UserManage.setState({
53 | searchKey: {
54 | deptCode: null
55 | }
56 | });
57 | UserManage.find("Button")
58 | .at(1)
59 | .simulate("click");
60 |
61 | UserManage.setState({
62 | searchKey: {
63 | deptCode: "370200000000"
64 | }
65 | });
66 | UserManage.find("Button")
67 | .at(1)
68 | .simulate("click");
69 | expect(UserManage.state().moduletitle).toBe("新增");
70 | });
71 |
72 | //点击用户详情
73 | test("handleChangeStatusEdit", () => {
74 | UserManage.setState({
75 | searchKey: param,
76 | userListResult: UserList.data,
77 | userDeptResult: userDeptResult.data,
78 | PoliceAddVisible: false,
79 | moduletype: "edit",
80 | userRoleSetResult: {}
81 | });
82 | UserManage.find("tbody tr")
83 | .at(0)
84 | .find("a")
85 | .at(0)
86 | .simulate("click");
87 | expect(UserManage.state().PoliceAddVisible).toBe(true);
88 | UserManage.instance().handleCancel();
89 | });
90 |
91 | //冻结账户
92 | test("handleChangeStatus", () => {
93 | UserManage.find("tbody tr")
94 | .at(0)
95 | .find("a")
96 | .at(1)
97 | .simulate("click");
98 | UserManage.find("Popconfirm button")
99 | .at(1)
100 | .simulate("click");
101 | UserManage.find("tbody tr")
102 | .at(1)
103 | .find("a")
104 | .at(1)
105 | .simulate("click");
106 | UserManage.find("Popconfirm button")
107 | .at(1)
108 | .simulate("click");
109 | });
110 |
111 | // 同步人员
112 | test("synchronize", () => {
113 | UserManage.find(".page-footer Button")
114 | .at(1)
115 | .simulate("click");
116 | });
117 | //页码改变
118 | test("pagenext", () => {
119 | UserManage.instance().pageChange(2);
120 | expect(UserManage.state().searchKey.pageNo).toBe(2);
121 | UserManage.instance().pageSizeChange({}, 20);
122 | expect(UserManage.state().searchKey.pageSize).toBe(20);
123 | });
124 | // treelist模块
125 | describe("treeList", () => {
126 | const treeListParam = {
127 | curDeptCode: "370200000000",
128 | onSelect: UserManage.instance().onSelect
129 | };
130 | const treeList = Enzyme.mount();
131 | //树点击事件
132 | treeList.setProps({
133 | trees: userDeptResult.data.list
134 | });
135 | it("treeClick", () => {
136 | treeList
137 | .find("li")
138 | .at(0)
139 | .find("span")
140 | .at(0)
141 | .simulate("click");
142 | expect(treeList.state("expandedKeys")).toContain(
143 | userDeptResult.data.list[0].deptCode
144 | );
145 | });
146 | //树内容点击事件
147 | it("treeListClick", () => {
148 | treeList
149 | .find("li")
150 | .at(0)
151 | .find("span")
152 | .at(1)
153 | .simulate("click");
154 | treeList
155 | .find("li")
156 | .at(1)
157 | .find("span")
158 | .at(1)
159 | .simulate("click");
160 | });
161 | });
162 |
--------------------------------------------------------------------------------
/test/setCenter/sys/userManage/modal/addPolice.spec.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Enzyme from "../../../../Enzyme.js";
3 | import UserName from "../../../../../app/pages/set/userManage/index";
4 | import AddPolice from "../../../../../app/pages/set/userManage/modal/addPolice";
5 | import roleList from "../../../../../app/mocks/apis/sys/userManage/fetchRoleList";
6 | import fetchUserDetail from "../../../../../app/mocks/apis/sys/userManage/fetchUserDetail";
7 | import UserList from "../../../../../app/mocks/apis/sys/userManage/fetchUserList";
8 |
9 | import Draw from "../../../../../app/components/draw/draw";
10 | jest.mock("../../../../../app/configs/ajax");
11 |
12 |
13 |
14 | jest.mock("../../../../../app/components/draw/draw");
15 | let form1;
16 | Enzyme.mount( (form1 = node)} />);
17 | let UserManage = Enzyme.mount(
18 |
19 | );
20 | const callback = {};
21 |
22 | let form = {};
23 | const param = {
24 | deptId: "370200000000",
25 | handleOk: UserManage.instance().handleOk,
26 | title: "新增",
27 | type: "add",
28 | visible: true,
29 | roleList: roleList.data.list,
30 | values: {},
31 | onCancel: UserManage.instance().onCancel
32 | };
33 | UserList.data.totalCount = 10;
34 | UserManage.setState({
35 | userListResult: UserList.data
36 | });
37 | let Form = Enzyme.mount(
38 | (form = node)}
42 | />
43 | );
44 |
45 | let policeFrom = Enzyme.mount(
46 |
51 | );
52 | //新增弹出框基础信息验证
53 | test("addInit", () => {
54 | UserManage.setState({
55 | moduletype: "add",
56 | userListResult: UserList.data
57 | });
58 | policeFrom
59 | .find("button")
60 | .at(2)
61 | .simulate("click");
62 | policeFrom
63 | .prop("form")
64 | .setFieldsValue({ chineseName: fetchUserDetail.data.chineseName });
65 | policeFrom
66 | .prop("form")
67 | .setFieldsValue({ password: fetchUserDetail.data.password });
68 | policeFrom
69 | .prop("form")
70 | .setFieldsValue({ username: fetchUserDetail.data.username });
71 | policeFrom
72 | .prop("form")
73 | .setFieldsValue({ idcardNo: fetchUserDetail.data.idcardNo });
74 | policeFrom
75 | .prop("form")
76 | .setFieldsValue({ deptCode: fetchUserDetail.data.deptCode });
77 | policeFrom
78 | .prop("form")
79 | .setFieldsValue({ phoneNo: fetchUserDetail.data.phoneNo });
80 | policeFrom
81 | .prop("form")
82 | .setFieldsValue({ gxdwdm: fetchUserDetail.data.gxdwdm });
83 | policeFrom
84 | .prop("form")
85 | .setFieldsValue({ roleIds: fetchUserDetail.data.roleIds });
86 | expect(policeFrom.find("Drawer").props().title).toBe("新增");
87 | expect(policeFrom.find("Drawer").props().visible).toBe(param.visible);
88 | policeFrom
89 | .find("button")
90 | .at(2)
91 | .simulate("click");
92 | });
93 | //编辑框基础信息验证
94 | test("editInit", () => {
95 | UserManage.setState({
96 | moduletype: "edit",
97 | userListResult: UserList.data
98 | });
99 | const param = {
100 | deptId: "370200000000",
101 | handleOk: UserManage.instance().handleOk,
102 | title: "编辑",
103 | type: "edit",
104 | visible: true,
105 | roleList: roleList.data.list,
106 | values: fetchUserDetail.data
107 | };
108 | policeFrom.setProps(param);
109 | expect(policeFrom.find("Drawer").props().title).toBe("编辑");
110 | policeFrom
111 | .find("button")
112 | .at(2)
113 | .simulate("click");
114 | policeFrom
115 | .find("button")
116 | .at(3)
117 | .simulate("click");
118 | });
119 |
--------------------------------------------------------------------------------