├── .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
├── cypress.config.js
├── cypress
├── e2e
│ ├── 1-getting-started
│ │ └── todo.cy.js
│ └── 2-advanced-examples
│ │ ├── actions.cy.js
│ │ ├── aliasing.cy.js
│ │ ├── assertions.cy.js
│ │ ├── connectors.cy.js
│ │ ├── cookies.cy.js
│ │ ├── cypress_api.cy.js
│ │ ├── files.cy.js
│ │ ├── location.cy.js
│ │ ├── misc.cy.js
│ │ ├── navigation.cy.js
│ │ ├── network_requests.cy.js
│ │ ├── querying.cy.js
│ │ ├── spies_stubs_clocks.cy.js
│ │ ├── storage.cy.js
│ │ ├── traversal.cy.js
│ │ ├── utilities.cy.js
│ │ ├── viewport.cy.js
│ │ ├── waiting.cy.js
│ │ └── window.cy.js
├── fixtures
│ └── example.json
└── support
│ ├── commands.js
│ └── e2e.js
├── 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 |
84 |
--------------------------------------------------------------------------------
/.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 | app/images
13 |
14 | # app/configs
15 | # app/components
16 | # 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
5 |
--------------------------------------------------------------------------------
/.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 | #don't upload node_modules.rar
58 | node_modules.rar
59 |
60 | #don't upload react.rar
61 | react.rar
62 |
--------------------------------------------------------------------------------
/.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, doupi, 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/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/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/duxianwei520/react/314b0d6db29f6c6201a11f4851bc0a82c7b48fd6/app/images/default.png
--------------------------------------------------------------------------------
/app/images/icon/menu/default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duxianwei520/react/314b0d6db29f6c6201a11f4851bc0a82c7b48fd6/app/images/icon/menu/default.png
--------------------------------------------------------------------------------
/app/images/icon/menu/icon_duty.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duxianwei520/react/314b0d6db29f6c6201a11f4851bc0a82c7b48fd6/app/images/icon/menu/icon_duty.png
--------------------------------------------------------------------------------
/app/images/icon/menu/icon_pgmb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duxianwei520/react/314b0d6db29f6c6201a11f4851bc0a82c7b48fd6/app/images/icon/menu/icon_pgmb.png
--------------------------------------------------------------------------------
/app/images/icon/menu/icon_pgmx.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duxianwei520/react/314b0d6db29f6c6201a11f4851bc0a82c7b48fd6/app/images/icon/menu/icon_pgmx.png
--------------------------------------------------------------------------------
/app/images/icon/menu/icon_statistics.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duxianwei520/react/314b0d6db29f6c6201a11f4851bc0a82c7b48fd6/app/images/icon/menu/icon_statistics.png
--------------------------------------------------------------------------------
/app/images/icon/menu/icon_xtxg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duxianwei520/react/314b0d6db29f6c6201a11f4851bc0a82c7b48fd6/app/images/icon/menu/icon_xtxg.png
--------------------------------------------------------------------------------
/app/images/icon/menu/moduleManage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duxianwei520/react/314b0d6db29f6c6201a11f4851bc0a82c7b48fd6/app/images/icon/menu/moduleManage.png
--------------------------------------------------------------------------------
/app/images/icon/menu/roleManage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duxianwei520/react/314b0d6db29f6c6201a11f4851bc0a82c7b48fd6/app/images/icon/menu/roleManage.png
--------------------------------------------------------------------------------
/app/images/icon/menu/userManage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duxianwei520/react/314b0d6db29f6c6201a11f4851bc0a82c7b48fd6/app/images/icon/menu/userManage.png
--------------------------------------------------------------------------------
/app/images/login.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duxianwei520/react/314b0d6db29f6c6201a11f4851bc0a82c7b48fd6/app/images/login.png
--------------------------------------------------------------------------------
/app/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duxianwei520/react/314b0d6db29f6c6201a11f4851bc0a82c7b48fd6/app/images/logo.png
--------------------------------------------------------------------------------
/app/images/navcontrol.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duxianwei520/react/314b0d6db29f6c6201a11f4851bc0a82c7b48fd6/app/images/navcontrol.png
--------------------------------------------------------------------------------
/app/images/photo_default.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duxianwei520/react/314b0d6db29f6c6201a11f4851bc0a82c7b48fd6/app/images/photo_default.jpg
--------------------------------------------------------------------------------
/app/images/user.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duxianwei520/react/314b0d6db29f6c6201a11f4851bc0a82c7b48fd6/app/images/user.jpg
--------------------------------------------------------------------------------
/app/images/user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duxianwei520/react/314b0d6db29f6c6201a11f4851bc0a82c7b48fd6/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/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/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/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/duxianwei520/react/314b0d6db29f6c6201a11f4851bc0a82c7b48fd6/app/resource/iconfont/iconfont.eot
--------------------------------------------------------------------------------
/app/resource/iconfont/iconfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duxianwei520/react/314b0d6db29f6c6201a11f4851bc0a82c7b48fd6/app/resource/iconfont/iconfont.ttf
--------------------------------------------------------------------------------
/app/resource/iconfont/iconfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/duxianwei520/react/314b0d6db29f6c6201a11f4851bc0a82c7b48fd6/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;
--------------------------------------------------------------------------------
/cypress.config.js:
--------------------------------------------------------------------------------
1 | const { defineConfig } = require("cypress");
2 |
3 | module.exports = defineConfig({
4 | e2e: {
5 | setupNodeEvents(on, config) {
6 | // implement node event listeners here
7 | },
8 | },
9 | });
10 |
--------------------------------------------------------------------------------
/cypress/e2e/2-advanced-examples/aliasing.cy.js:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | context('Aliasing', () => {
4 | beforeEach(() => {
5 | cy.visit('https://example.cypress.io/commands/aliasing')
6 | })
7 |
8 | it('.as() - alias a DOM element for later use', () => {
9 | // https://on.cypress.io/as
10 |
11 | // Alias a DOM element for use later
12 | // We don't have to traverse to the element
13 | // later in our code, we reference it with @
14 |
15 | cy.get('.as-table').find('tbody>tr')
16 | .first().find('td').first()
17 | .find('button').as('firstBtn')
18 |
19 | // when we reference the alias, we place an
20 | // @ in front of its name
21 | cy.get('@firstBtn').click()
22 |
23 | cy.get('@firstBtn')
24 | .should('have.class', 'btn-success')
25 | .and('contain', 'Changed')
26 | })
27 |
28 | it('.as() - alias a route for later use', () => {
29 | // Alias the route to wait for its response
30 | cy.intercept('GET', '**/comments/*').as('getComment')
31 |
32 | // we have code that gets a comment when
33 | // the button is clicked in scripts.js
34 | cy.get('.network-btn').click()
35 |
36 | // https://on.cypress.io/wait
37 | cy.wait('@getComment').its('response.statusCode').should('eq', 200)
38 | })
39 | })
40 |
--------------------------------------------------------------------------------
/cypress/e2e/2-advanced-examples/connectors.cy.js:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | context('Connectors', () => {
4 | beforeEach(() => {
5 | cy.visit('https://example.cypress.io/commands/connectors')
6 | })
7 |
8 | it('.each() - iterate over an array of elements', () => {
9 | // https://on.cypress.io/each
10 | cy.get('.connectors-each-ul>li')
11 | .each(($el, index, $list) => {
12 | console.log($el, index, $list)
13 | })
14 | })
15 |
16 | it('.its() - get properties on the current subject', () => {
17 | // https://on.cypress.io/its
18 | cy.get('.connectors-its-ul>li')
19 | // calls the 'length' property yielding that value
20 | .its('length')
21 | .should('be.gt', 2)
22 | })
23 |
24 | it('.invoke() - invoke a function on the current subject', () => {
25 | // our div is hidden in our script.js
26 | // $('.connectors-div').hide()
27 | cy.get('.connectors-div').should('be.hidden')
28 |
29 | // https://on.cypress.io/invoke
30 | // call the jquery method 'show' on the 'div.container'
31 | cy.get('.connectors-div').invoke('show')
32 |
33 | cy.get('.connectors-div').should('be.visible')
34 | })
35 |
36 | it('.spread() - spread an array as individual args to callback function', () => {
37 | // https://on.cypress.io/spread
38 | const arr = ['foo', 'bar', 'baz']
39 |
40 | cy.wrap(arr).spread((foo, bar, baz) => {
41 | expect(foo).to.eq('foo')
42 | expect(bar).to.eq('bar')
43 | expect(baz).to.eq('baz')
44 | })
45 | })
46 |
47 | describe('.then()', () => {
48 | it('invokes a callback function with the current subject', () => {
49 | // https://on.cypress.io/then
50 | cy.get('.connectors-list > li')
51 | .then(($lis) => {
52 | expect($lis, '3 items').to.have.length(3)
53 | expect($lis.eq(0), 'first item').to.contain('Walk the dog')
54 | expect($lis.eq(1), 'second item').to.contain('Feed the cat')
55 | expect($lis.eq(2), 'third item').to.contain('Write JavaScript')
56 | })
57 | })
58 |
59 | it('yields the returned value to the next command', () => {
60 | cy.wrap(1)
61 | .then((num) => {
62 | expect(num).to.equal(1)
63 |
64 | return 2
65 | })
66 | .then((num) => {
67 | expect(num).to.equal(2)
68 | })
69 | })
70 |
71 | it('yields the original subject without return', () => {
72 | cy.wrap(1)
73 | .then((num) => {
74 | expect(num).to.equal(1)
75 | // note that nothing is returned from this callback
76 | })
77 | .then((num) => {
78 | // this callback receives the original unchanged value 1
79 | expect(num).to.equal(1)
80 | })
81 | })
82 |
83 | it('yields the value yielded by the last Cypress command inside', () => {
84 | cy.wrap(1)
85 | .then((num) => {
86 | expect(num).to.equal(1)
87 | // note how we run a Cypress command
88 | // the result yielded by this Cypress command
89 | // will be passed to the second ".then"
90 | cy.wrap(2)
91 | })
92 | .then((num) => {
93 | // this callback receives the value yielded by "cy.wrap(2)"
94 | expect(num).to.equal(2)
95 | })
96 | })
97 | })
98 | })
99 |
--------------------------------------------------------------------------------
/cypress/e2e/2-advanced-examples/cookies.cy.js:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | context('Cookies', () => {
4 | beforeEach(() => {
5 | Cypress.Cookies.debug(true)
6 |
7 | cy.visit('https://example.cypress.io/commands/cookies')
8 |
9 | // clear cookies again after visiting to remove
10 | // any 3rd party cookies picked up such as cloudflare
11 | cy.clearCookies()
12 | })
13 |
14 | it('cy.getCookie() - get a browser cookie', () => {
15 | // https://on.cypress.io/getcookie
16 | cy.get('#getCookie .set-a-cookie').click()
17 |
18 | // cy.getCookie() yields a cookie object
19 | cy.getCookie('token').should('have.property', 'value', '123ABC')
20 | })
21 |
22 | it('cy.getCookies() - get browser cookies for the current domain', () => {
23 | // https://on.cypress.io/getcookies
24 | cy.getCookies().should('be.empty')
25 |
26 | cy.get('#getCookies .set-a-cookie').click()
27 |
28 | // cy.getCookies() yields an array of cookies
29 | cy.getCookies().should('have.length', 1).should((cookies) => {
30 | // each cookie has these properties
31 | expect(cookies[0]).to.have.property('name', 'token')
32 | expect(cookies[0]).to.have.property('value', '123ABC')
33 | expect(cookies[0]).to.have.property('httpOnly', false)
34 | expect(cookies[0]).to.have.property('secure', false)
35 | expect(cookies[0]).to.have.property('domain')
36 | expect(cookies[0]).to.have.property('path')
37 | })
38 | })
39 |
40 | it('cy.getAllCookies() - get all browser cookies', () => {
41 | // https://on.cypress.io/getallcookies
42 | cy.getAllCookies().should('be.empty')
43 |
44 | cy.setCookie('key', 'value')
45 | cy.setCookie('key', 'value', { domain: '.example.com' })
46 |
47 | // cy.getAllCookies() yields an array of cookies
48 | cy.getAllCookies().should('have.length', 2).should((cookies) => {
49 | // each cookie has these properties
50 | expect(cookies[0]).to.have.property('name', 'key')
51 | expect(cookies[0]).to.have.property('value', 'value')
52 | expect(cookies[0]).to.have.property('httpOnly', false)
53 | expect(cookies[0]).to.have.property('secure', false)
54 | expect(cookies[0]).to.have.property('domain')
55 | expect(cookies[0]).to.have.property('path')
56 |
57 | expect(cookies[1]).to.have.property('name', 'key')
58 | expect(cookies[1]).to.have.property('value', 'value')
59 | expect(cookies[1]).to.have.property('httpOnly', false)
60 | expect(cookies[1]).to.have.property('secure', false)
61 | expect(cookies[1]).to.have.property('domain', '.example.com')
62 | expect(cookies[1]).to.have.property('path')
63 | })
64 | })
65 |
66 | it('cy.setCookie() - set a browser cookie', () => {
67 | // https://on.cypress.io/setcookie
68 | cy.getCookies().should('be.empty')
69 |
70 | cy.setCookie('foo', 'bar')
71 |
72 | // cy.getCookie() yields a cookie object
73 | cy.getCookie('foo').should('have.property', 'value', 'bar')
74 | })
75 |
76 | it('cy.clearCookie() - clear a browser cookie', () => {
77 | // https://on.cypress.io/clearcookie
78 | cy.getCookie('token').should('be.null')
79 |
80 | cy.get('#clearCookie .set-a-cookie').click()
81 |
82 | cy.getCookie('token').should('have.property', 'value', '123ABC')
83 |
84 | // cy.clearCookies() yields null
85 | cy.clearCookie('token').should('be.null')
86 |
87 | cy.getCookie('token').should('be.null')
88 | })
89 |
90 | it('cy.clearCookies() - clear browser cookies for the current domain', () => {
91 | // https://on.cypress.io/clearcookies
92 | cy.getCookies().should('be.empty')
93 |
94 | cy.get('#clearCookies .set-a-cookie').click()
95 |
96 | cy.getCookies().should('have.length', 1)
97 |
98 | // cy.clearCookies() yields null
99 | cy.clearCookies()
100 |
101 | cy.getCookies().should('be.empty')
102 | })
103 |
104 | it('cy.clearAllCookies() - clear all browser cookies', () => {
105 | // https://on.cypress.io/clearallcookies
106 | cy.getAllCookies().should('be.empty')
107 |
108 | cy.setCookie('key', 'value')
109 | cy.setCookie('key', 'value', { domain: '.example.com' })
110 |
111 | cy.getAllCookies().should('have.length', 2)
112 |
113 | // cy.clearAllCookies() yields null
114 | cy.clearAllCookies()
115 |
116 | cy.getAllCookies().should('be.empty')
117 | })
118 | })
119 |
--------------------------------------------------------------------------------
/cypress/e2e/2-advanced-examples/files.cy.js:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | /// JSON fixture file can be loaded directly using
4 | // the built-in JavaScript bundler
5 | const requiredExample = require('../../fixtures/example')
6 |
7 | context('Files', () => {
8 | beforeEach(() => {
9 | cy.visit('https://example.cypress.io/commands/files')
10 |
11 | // load example.json fixture file and store
12 | // in the test context object
13 | cy.fixture('example.json').as('example')
14 | })
15 |
16 | it('cy.fixture() - load a fixture', () => {
17 | // https://on.cypress.io/fixture
18 |
19 | // Instead of writing a response inline you can
20 | // use a fixture file's content.
21 |
22 | // when application makes an Ajax request matching "GET **/comments/*"
23 | // Cypress will intercept it and reply with the object in `example.json` fixture
24 | cy.intercept('GET', '**/comments/*', { fixture: 'example.json' }).as('getComment')
25 |
26 | // we have code that gets a comment when
27 | // the button is clicked in scripts.js
28 | cy.get('.fixture-btn').click()
29 |
30 | cy.wait('@getComment').its('response.body')
31 | .should('have.property', 'name')
32 | .and('include', 'Using fixtures to represent data')
33 | })
34 |
35 | it('cy.fixture() or require - load a fixture', function () {
36 | // we are inside the "function () { ... }"
37 | // callback and can use test context object "this"
38 | // "this.example" was loaded in "beforeEach" function callback
39 | expect(this.example, 'fixture in the test context')
40 | .to.deep.equal(requiredExample)
41 |
42 | // or use "cy.wrap" and "should('deep.equal', ...)" assertion
43 | cy.wrap(this.example)
44 | .should('deep.equal', requiredExample)
45 | })
46 |
47 | it('cy.readFile() - read file contents', () => {
48 | // https://on.cypress.io/readfile
49 |
50 | // You can read a file and yield its contents
51 | // The filePath is relative to your project's root.
52 | cy.readFile(Cypress.config('configFile')).then((config) => {
53 | expect(config).to.be.an('string')
54 | })
55 | })
56 |
57 | it('cy.writeFile() - write to a file', () => {
58 | // https://on.cypress.io/writefile
59 |
60 | // You can write to a file
61 |
62 | // Use a response from a request to automatically
63 | // generate a fixture file for use later
64 | cy.request('https://jsonplaceholder.cypress.io/users')
65 | .then((response) => {
66 | cy.writeFile('cypress/fixtures/users.json', response.body)
67 | })
68 |
69 | cy.fixture('users').should((users) => {
70 | expect(users[0].name).to.exist
71 | })
72 |
73 | // JavaScript arrays and objects are stringified
74 | // and formatted into text.
75 | cy.writeFile('cypress/fixtures/profile.json', {
76 | id: 8739,
77 | name: 'Jane',
78 | email: 'jane@example.com',
79 | })
80 |
81 | cy.fixture('profile').should((profile) => {
82 | expect(profile.name).to.eq('Jane')
83 | })
84 | })
85 | })
86 |
--------------------------------------------------------------------------------
/cypress/e2e/2-advanced-examples/location.cy.js:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | context('Location', () => {
4 | beforeEach(() => {
5 | cy.visit('https://example.cypress.io/commands/location')
6 | })
7 |
8 | it('cy.hash() - get the current URL hash', () => {
9 | // https://on.cypress.io/hash
10 | cy.hash().should('be.empty')
11 | })
12 |
13 | it('cy.location() - get window.location', () => {
14 | // https://on.cypress.io/location
15 | cy.location().should((location) => {
16 | expect(location.hash).to.be.empty
17 | expect(location.href).to.eq('https://example.cypress.io/commands/location')
18 | expect(location.host).to.eq('example.cypress.io')
19 | expect(location.hostname).to.eq('example.cypress.io')
20 | expect(location.origin).to.eq('https://example.cypress.io')
21 | expect(location.pathname).to.eq('/commands/location')
22 | expect(location.port).to.eq('')
23 | expect(location.protocol).to.eq('https:')
24 | expect(location.search).to.be.empty
25 | })
26 | })
27 |
28 | it('cy.url() - get the current URL', () => {
29 | // https://on.cypress.io/url
30 | cy.url().should('eq', 'https://example.cypress.io/commands/location')
31 | })
32 | })
33 |
--------------------------------------------------------------------------------
/cypress/e2e/2-advanced-examples/misc.cy.js:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | context('Misc', () => {
4 | beforeEach(() => {
5 | cy.visit('https://example.cypress.io/commands/misc')
6 | })
7 |
8 | it('.end() - end the command chain', () => {
9 | // https://on.cypress.io/end
10 |
11 | // cy.end is useful when you want to end a chain of commands
12 | // and force Cypress to re-query from the root element
13 | cy.get('.misc-table').within(() => {
14 | // ends the current chain and yields null
15 | cy.contains('Cheryl').click().end()
16 |
17 | // queries the entire table again
18 | cy.contains('Charles').click()
19 | })
20 | })
21 |
22 | it('cy.exec() - execute a system command', () => {
23 | // execute a system command.
24 | // so you can take actions necessary for
25 | // your test outside the scope of Cypress.
26 | // https://on.cypress.io/exec
27 |
28 | // we can use Cypress.platform string to
29 | // select appropriate command
30 | // https://on.cypress/io/platform
31 | cy.log(`Platform ${Cypress.platform} architecture ${Cypress.arch}`)
32 |
33 | // on CircleCI Windows build machines we have a failure to run bash shell
34 | // https://github.com/cypress-io/cypress/issues/5169
35 | // so skip some of the tests by passing flag "--env circle=true"
36 | const isCircleOnWindows = Cypress.platform === 'win32' && Cypress.env('circle')
37 |
38 | if (isCircleOnWindows) {
39 | cy.log('Skipping test on CircleCI')
40 |
41 | return
42 | }
43 |
44 | // cy.exec problem on Shippable CI
45 | // https://github.com/cypress-io/cypress/issues/6718
46 | const isShippable = Cypress.platform === 'linux' && Cypress.env('shippable')
47 |
48 | if (isShippable) {
49 | cy.log('Skipping test on ShippableCI')
50 |
51 | return
52 | }
53 |
54 | cy.exec('echo Jane Lane')
55 | .its('stdout').should('contain', 'Jane Lane')
56 |
57 | if (Cypress.platform === 'win32') {
58 | cy.exec(`print ${Cypress.config('configFile')}`)
59 | .its('stderr').should('be.empty')
60 | } else {
61 | cy.exec(`cat ${Cypress.config('configFile')}`)
62 | .its('stderr').should('be.empty')
63 |
64 | cy.exec('pwd')
65 | .its('code').should('eq', 0)
66 | }
67 | })
68 |
69 | it('cy.focused() - get the DOM element that has focus', () => {
70 | // https://on.cypress.io/focused
71 | cy.get('.misc-form').find('#name').click()
72 | cy.focused().should('have.id', 'name')
73 |
74 | cy.get('.misc-form').find('#description').click()
75 | cy.focused().should('have.id', 'description')
76 | })
77 |
78 | context('Cypress.Screenshot', function () {
79 | it('cy.screenshot() - take a screenshot', () => {
80 | // https://on.cypress.io/screenshot
81 | cy.screenshot('my-image')
82 | })
83 |
84 | it('Cypress.Screenshot.defaults() - change default config of screenshots', function () {
85 | Cypress.Screenshot.defaults({
86 | blackout: ['.foo'],
87 | capture: 'viewport',
88 | clip: { x: 0, y: 0, width: 200, height: 200 },
89 | scale: false,
90 | disableTimersAndAnimations: true,
91 | screenshotOnRunFailure: true,
92 | onBeforeScreenshot () { },
93 | onAfterScreenshot () { },
94 | })
95 | })
96 | })
97 |
98 | it('cy.wrap() - wrap an object', () => {
99 | // https://on.cypress.io/wrap
100 | cy.wrap({ foo: 'bar' })
101 | .should('have.property', 'foo')
102 | .and('include', 'bar')
103 | })
104 | })
105 |
--------------------------------------------------------------------------------
/cypress/e2e/2-advanced-examples/navigation.cy.js:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | context('Navigation', () => {
4 | beforeEach(() => {
5 | cy.visit('https://example.cypress.io')
6 | cy.get('.navbar-nav').contains('Commands').click()
7 | cy.get('.dropdown-menu').contains('Navigation').click()
8 | })
9 |
10 | it('cy.go() - go back or forward in the browser\'s history', () => {
11 | // https://on.cypress.io/go
12 |
13 | cy.location('pathname').should('include', 'navigation')
14 |
15 | cy.go('back')
16 | cy.location('pathname').should('not.include', 'navigation')
17 |
18 | cy.go('forward')
19 | cy.location('pathname').should('include', 'navigation')
20 |
21 | // clicking back
22 | cy.go(-1)
23 | cy.location('pathname').should('not.include', 'navigation')
24 |
25 | // clicking forward
26 | cy.go(1)
27 | cy.location('pathname').should('include', 'navigation')
28 | })
29 |
30 | it('cy.reload() - reload the page', () => {
31 | // https://on.cypress.io/reload
32 | cy.reload()
33 |
34 | // reload the page without using the cache
35 | cy.reload(true)
36 | })
37 |
38 | it('cy.visit() - visit a remote url', () => {
39 | // https://on.cypress.io/visit
40 |
41 | // Visit any sub-domain of your current domain
42 |
43 | // Pass options to the visit
44 | cy.visit('https://example.cypress.io/commands/navigation', {
45 | timeout: 50000, // increase total time for the visit to resolve
46 | onBeforeLoad (contentWindow) {
47 | // contentWindow is the remote page's window object
48 | expect(typeof contentWindow === 'object').to.be.true
49 | },
50 | onLoad (contentWindow) {
51 | // contentWindow is the remote page's window object
52 | expect(typeof contentWindow === 'object').to.be.true
53 | },
54 | })
55 | })
56 | })
57 |
--------------------------------------------------------------------------------
/cypress/e2e/2-advanced-examples/querying.cy.js:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | context('Querying', () => {
4 | beforeEach(() => {
5 | cy.visit('https://example.cypress.io/commands/querying')
6 | })
7 |
8 | // The most commonly used query is 'cy.get()', you can
9 | // think of this like the '$' in jQuery
10 |
11 | it('cy.get() - query DOM elements', () => {
12 | // https://on.cypress.io/get
13 |
14 | cy.get('#query-btn').should('contain', 'Button')
15 |
16 | cy.get('.query-btn').should('contain', 'Button')
17 |
18 | cy.get('#querying .well>button:first').should('contain', 'Button')
19 | // ↲
20 | // Use CSS selectors just like jQuery
21 |
22 | cy.get('[data-test-id="test-example"]').should('have.class', 'example')
23 |
24 | // 'cy.get()' yields jQuery object, you can get its attribute
25 | // by invoking `.attr()` method
26 | cy.get('[data-test-id="test-example"]')
27 | .invoke('attr', 'data-test-id')
28 | .should('equal', 'test-example')
29 |
30 | // or you can get element's CSS property
31 | cy.get('[data-test-id="test-example"]')
32 | .invoke('css', 'position')
33 | .should('equal', 'static')
34 |
35 | // or use assertions directly during 'cy.get()'
36 | // https://on.cypress.io/assertions
37 | cy.get('[data-test-id="test-example"]')
38 | .should('have.attr', 'data-test-id', 'test-example')
39 | .and('have.css', 'position', 'static')
40 | })
41 |
42 | it('cy.contains() - query DOM elements with matching content', () => {
43 | // https://on.cypress.io/contains
44 | cy.get('.query-list')
45 | .contains('bananas')
46 | .should('have.class', 'third')
47 |
48 | // we can pass a regexp to `.contains()`
49 | cy.get('.query-list')
50 | .contains(/^b\w+/)
51 | .should('have.class', 'third')
52 |
53 | cy.get('.query-list')
54 | .contains('apples')
55 | .should('have.class', 'first')
56 |
57 | // passing a selector to contains will
58 | // yield the selector containing the text
59 | cy.get('#querying')
60 | .contains('ul', 'oranges')
61 | .should('have.class', 'query-list')
62 |
63 | cy.get('.query-button')
64 | .contains('Save Form')
65 | .should('have.class', 'btn')
66 | })
67 |
68 | it('.within() - query DOM elements within a specific element', () => {
69 | // https://on.cypress.io/within
70 | cy.get('.query-form').within(() => {
71 | cy.get('input:first').should('have.attr', 'placeholder', 'Email')
72 | cy.get('input:last').should('have.attr', 'placeholder', 'Password')
73 | })
74 | })
75 |
76 | it('cy.root() - query the root DOM element', () => {
77 | // https://on.cypress.io/root
78 |
79 | // By default, root is the document
80 | cy.root().should('match', 'html')
81 |
82 | cy.get('.query-ul').within(() => {
83 | // In this within, the root is now the ul DOM element
84 | cy.root().should('have.class', 'query-ul')
85 | })
86 | })
87 |
88 | it('best practices - selecting elements', () => {
89 | // https://on.cypress.io/best-practices#Selecting-Elements
90 | cy.get('[data-cy=best-practices-selecting-elements]').within(() => {
91 | // Worst - too generic, no context
92 | cy.get('button').click()
93 |
94 | // Bad. Coupled to styling. Highly subject to change.
95 | cy.get('.btn.btn-large').click()
96 |
97 | // Average. Coupled to the `name` attribute which has HTML semantics.
98 | cy.get('[name=submission]').click()
99 |
100 | // Better. But still coupled to styling or JS event listeners.
101 | cy.get('#main').click()
102 |
103 | // Slightly better. Uses an ID but also ensures the element
104 | // has an ARIA role attribute
105 | cy.get('#main[role=button]').click()
106 |
107 | // Much better. But still coupled to text content that may change.
108 | cy.contains('Submit').click()
109 |
110 | // Best. Insulated from all changes.
111 | cy.get('[data-cy=submit]').click()
112 | })
113 | })
114 | })
115 |
--------------------------------------------------------------------------------
/cypress/e2e/2-advanced-examples/storage.cy.js:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | context('Local Storage / Session Storage', () => {
4 | beforeEach(() => {
5 | cy.visit('https://example.cypress.io/commands/storage')
6 | })
7 | // Although localStorage is automatically cleared
8 | // in between tests to maintain a clean state
9 | // sometimes we need to clear localStorage manually
10 |
11 | it('cy.clearLocalStorage() - clear all data in localStorage for the current origin', () => {
12 | // https://on.cypress.io/clearlocalstorage
13 | cy.get('.ls-btn').click().should(() => {
14 | expect(localStorage.getItem('prop1')).to.eq('red')
15 | expect(localStorage.getItem('prop2')).to.eq('blue')
16 | expect(localStorage.getItem('prop3')).to.eq('magenta')
17 | })
18 |
19 | // clearLocalStorage() yields the localStorage object
20 | cy.clearLocalStorage().should((ls) => {
21 | expect(ls.getItem('prop1')).to.be.null
22 | expect(ls.getItem('prop2')).to.be.null
23 | expect(ls.getItem('prop3')).to.be.null
24 | })
25 |
26 | cy.get('.ls-btn').click().should(() => {
27 | expect(localStorage.getItem('prop1')).to.eq('red')
28 | expect(localStorage.getItem('prop2')).to.eq('blue')
29 | expect(localStorage.getItem('prop3')).to.eq('magenta')
30 | })
31 |
32 | // Clear key matching string in localStorage
33 | cy.clearLocalStorage('prop1').should((ls) => {
34 | expect(ls.getItem('prop1')).to.be.null
35 | expect(ls.getItem('prop2')).to.eq('blue')
36 | expect(ls.getItem('prop3')).to.eq('magenta')
37 | })
38 |
39 | cy.get('.ls-btn').click().should(() => {
40 | expect(localStorage.getItem('prop1')).to.eq('red')
41 | expect(localStorage.getItem('prop2')).to.eq('blue')
42 | expect(localStorage.getItem('prop3')).to.eq('magenta')
43 | })
44 |
45 | // Clear keys matching regex in localStorage
46 | cy.clearLocalStorage(/prop1|2/).should((ls) => {
47 | expect(ls.getItem('prop1')).to.be.null
48 | expect(ls.getItem('prop2')).to.be.null
49 | expect(ls.getItem('prop3')).to.eq('magenta')
50 | })
51 | })
52 |
53 | it('cy.getAllLocalStorage() - get all data in localStorage for all origins', () => {
54 | // https://on.cypress.io/getalllocalstorage
55 | cy.get('.ls-btn').click()
56 |
57 | // getAllLocalStorage() yields a map of origins to localStorage values
58 | cy.getAllLocalStorage().should((storageMap) => {
59 | expect(storageMap).to.deep.equal({
60 | // other origins will also be present if localStorage is set on them
61 | 'https://example.cypress.io': {
62 | 'prop1': 'red',
63 | 'prop2': 'blue',
64 | 'prop3': 'magenta',
65 | },
66 | })
67 | })
68 | })
69 |
70 | it('cy.clearAllLocalStorage() - clear all data in localStorage for all origins', () => {
71 | // https://on.cypress.io/clearalllocalstorage
72 | cy.get('.ls-btn').click()
73 |
74 | // clearAllLocalStorage() yields null
75 | cy.clearAllLocalStorage().should(() => {
76 | expect(sessionStorage.getItem('prop1')).to.be.null
77 | expect(sessionStorage.getItem('prop2')).to.be.null
78 | expect(sessionStorage.getItem('prop3')).to.be.null
79 | })
80 | })
81 |
82 | it('cy.getAllSessionStorage() - get all data in sessionStorage for all origins', () => {
83 | // https://on.cypress.io/getallsessionstorage
84 | cy.get('.ls-btn').click()
85 |
86 | // getAllSessionStorage() yields a map of origins to sessionStorage values
87 | cy.getAllSessionStorage().should((storageMap) => {
88 | expect(storageMap).to.deep.equal({
89 | // other origins will also be present if sessionStorage is set on them
90 | 'https://example.cypress.io': {
91 | 'prop4': 'cyan',
92 | 'prop5': 'yellow',
93 | 'prop6': 'black',
94 | },
95 | })
96 | })
97 | })
98 |
99 | it('cy.clearAllSessionStorage() - clear all data in sessionStorage for all origins', () => {
100 | // https://on.cypress.io/clearallsessionstorage
101 | cy.get('.ls-btn').click()
102 |
103 | // clearAllSessionStorage() yields null
104 | cy.clearAllSessionStorage().should(() => {
105 | expect(sessionStorage.getItem('prop4')).to.be.null
106 | expect(sessionStorage.getItem('prop5')).to.be.null
107 | expect(sessionStorage.getItem('prop6')).to.be.null
108 | })
109 | })
110 | })
111 |
--------------------------------------------------------------------------------
/cypress/e2e/2-advanced-examples/traversal.cy.js:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | context('Traversal', () => {
4 | beforeEach(() => {
5 | cy.visit('https://example.cypress.io/commands/traversal')
6 | })
7 |
8 | it('.children() - get child DOM elements', () => {
9 | // https://on.cypress.io/children
10 | cy.get('.traversal-breadcrumb')
11 | .children('.active')
12 | .should('contain', 'Data')
13 | })
14 |
15 | it('.closest() - get closest ancestor DOM element', () => {
16 | // https://on.cypress.io/closest
17 | cy.get('.traversal-badge')
18 | .closest('ul')
19 | .should('have.class', 'list-group')
20 | })
21 |
22 | it('.eq() - get a DOM element at a specific index', () => {
23 | // https://on.cypress.io/eq
24 | cy.get('.traversal-list>li')
25 | .eq(1).should('contain', 'siamese')
26 | })
27 |
28 | it('.filter() - get DOM elements that match the selector', () => {
29 | // https://on.cypress.io/filter
30 | cy.get('.traversal-nav>li')
31 | .filter('.active').should('contain', 'About')
32 | })
33 |
34 | it('.find() - get descendant DOM elements of the selector', () => {
35 | // https://on.cypress.io/find
36 | cy.get('.traversal-pagination')
37 | .find('li').find('a')
38 | .should('have.length', 7)
39 | })
40 |
41 | it('.first() - get first DOM element', () => {
42 | // https://on.cypress.io/first
43 | cy.get('.traversal-table td')
44 | .first().should('contain', '1')
45 | })
46 |
47 | it('.last() - get last DOM element', () => {
48 | // https://on.cypress.io/last
49 | cy.get('.traversal-buttons .btn')
50 | .last().should('contain', 'Submit')
51 | })
52 |
53 | it('.next() - get next sibling DOM element', () => {
54 | // https://on.cypress.io/next
55 | cy.get('.traversal-ul')
56 | .contains('apples').next().should('contain', 'oranges')
57 | })
58 |
59 | it('.nextAll() - get all next sibling DOM elements', () => {
60 | // https://on.cypress.io/nextall
61 | cy.get('.traversal-next-all')
62 | .contains('oranges')
63 | .nextAll().should('have.length', 3)
64 | })
65 |
66 | it('.nextUntil() - get next sibling DOM elements until next el', () => {
67 | // https://on.cypress.io/nextuntil
68 | cy.get('#veggies')
69 | .nextUntil('#nuts').should('have.length', 3)
70 | })
71 |
72 | it('.not() - remove DOM elements from set of DOM elements', () => {
73 | // https://on.cypress.io/not
74 | cy.get('.traversal-disabled .btn')
75 | .not('[disabled]').should('not.contain', 'Disabled')
76 | })
77 |
78 | it('.parent() - get parent DOM element from DOM elements', () => {
79 | // https://on.cypress.io/parent
80 | cy.get('.traversal-mark')
81 | .parent().should('contain', 'Morbi leo risus')
82 | })
83 |
84 | it('.parents() - get parent DOM elements from DOM elements', () => {
85 | // https://on.cypress.io/parents
86 | cy.get('.traversal-cite')
87 | .parents().should('match', 'blockquote')
88 | })
89 |
90 | it('.parentsUntil() - get parent DOM elements from DOM elements until el', () => {
91 | // https://on.cypress.io/parentsuntil
92 | cy.get('.clothes-nav')
93 | .find('.active')
94 | .parentsUntil('.clothes-nav')
95 | .should('have.length', 2)
96 | })
97 |
98 | it('.prev() - get previous sibling DOM element', () => {
99 | // https://on.cypress.io/prev
100 | cy.get('.birds').find('.active')
101 | .prev().should('contain', 'Lorikeets')
102 | })
103 |
104 | it('.prevAll() - get all previous sibling DOM elements', () => {
105 | // https://on.cypress.io/prevall
106 | cy.get('.fruits-list').find('.third')
107 | .prevAll().should('have.length', 2)
108 | })
109 |
110 | it('.prevUntil() - get all previous sibling DOM elements until el', () => {
111 | // https://on.cypress.io/prevuntil
112 | cy.get('.foods-list').find('#nuts')
113 | .prevUntil('#veggies').should('have.length', 3)
114 | })
115 |
116 | it('.siblings() - get all sibling DOM elements', () => {
117 | // https://on.cypress.io/siblings
118 | cy.get('.traversal-pills .active')
119 | .siblings().should('have.length', 2)
120 | })
121 | })
122 |
--------------------------------------------------------------------------------
/cypress/e2e/2-advanced-examples/utilities.cy.js:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | context('Utilities', () => {
4 | beforeEach(() => {
5 | cy.visit('https://example.cypress.io/utilities')
6 | })
7 |
8 | it('Cypress._ - call a lodash method', () => {
9 | // https://on.cypress.io/_
10 | cy.request('https://jsonplaceholder.cypress.io/users')
11 | .then((response) => {
12 | let ids = Cypress._.chain(response.body).map('id').take(3).value()
13 |
14 | expect(ids).to.deep.eq([1, 2, 3])
15 | })
16 | })
17 |
18 | it('Cypress.$ - call a jQuery method', () => {
19 | // https://on.cypress.io/$
20 | let $li = Cypress.$('.utility-jquery li:first')
21 |
22 | cy.wrap($li)
23 | .should('not.have.class', 'active')
24 | .click()
25 | .should('have.class', 'active')
26 | })
27 |
28 | it('Cypress.Blob - blob utilities and base64 string conversion', () => {
29 | // https://on.cypress.io/blob
30 | cy.get('.utility-blob').then(($div) => {
31 | // https://github.com/nolanlawson/blob-util#imgSrcToDataURL
32 | // get the dataUrl string for the javascript-logo
33 | return Cypress.Blob.imgSrcToDataURL('https://example.cypress.io/assets/img/javascript-logo.png', undefined, 'anonymous')
34 | .then((dataUrl) => {
35 | // create an
![]()
element and set its src to the dataUrl
36 | let img = Cypress.$('
![]()
', { src: dataUrl })
37 |
38 | // need to explicitly return cy here since we are initially returning
39 | // the Cypress.Blob.imgSrcToDataURL promise to our test
40 | // append the image
41 | $div.append(img)
42 |
43 | cy.get('.utility-blob img').click()
44 | .should('have.attr', 'src', dataUrl)
45 | })
46 | })
47 | })
48 |
49 | it('Cypress.minimatch - test out glob patterns against strings', () => {
50 | // https://on.cypress.io/minimatch
51 | let matching = Cypress.minimatch('/users/1/comments', '/users/*/comments', {
52 | matchBase: true,
53 | })
54 |
55 | expect(matching, 'matching wildcard').to.be.true
56 |
57 | matching = Cypress.minimatch('/users/1/comments/2', '/users/*/comments', {
58 | matchBase: true,
59 | })
60 |
61 | expect(matching, 'comments').to.be.false
62 |
63 | // ** matches against all downstream path segments
64 | matching = Cypress.minimatch('/foo/bar/baz/123/quux?a=b&c=2', '/foo/**', {
65 | matchBase: true,
66 | })
67 |
68 | expect(matching, 'comments').to.be.true
69 |
70 | // whereas * matches only the next path segment
71 |
72 | matching = Cypress.minimatch('/foo/bar/baz/123/quux?a=b&c=2', '/foo/*', {
73 | matchBase: false,
74 | })
75 |
76 | expect(matching, 'comments').to.be.false
77 | })
78 |
79 | it('Cypress.Promise - instantiate a bluebird promise', () => {
80 | // https://on.cypress.io/promise
81 | let waited = false
82 |
83 | /**
84 | * @return Bluebird
85 | */
86 | function waitOneSecond () {
87 | // return a promise that resolves after 1 second
88 | return new Cypress.Promise((resolve, reject) => {
89 | setTimeout(() => {
90 | // set waited to true
91 | waited = true
92 |
93 | // resolve with 'foo' string
94 | resolve('foo')
95 | }, 1000)
96 | })
97 | }
98 |
99 | cy.then(() => {
100 | // return a promise to cy.then() that
101 | // is awaited until it resolves
102 | return waitOneSecond().then((str) => {
103 | expect(str).to.eq('foo')
104 | expect(waited).to.be.true
105 | })
106 | })
107 | })
108 | })
109 |
--------------------------------------------------------------------------------
/cypress/e2e/2-advanced-examples/viewport.cy.js:
--------------------------------------------------------------------------------
1 | ///
2 | context('Viewport', () => {
3 | beforeEach(() => {
4 | cy.visit('https://example.cypress.io/commands/viewport')
5 | })
6 |
7 | it('cy.viewport() - set the viewport size and dimension', () => {
8 | // https://on.cypress.io/viewport
9 |
10 | cy.get('#navbar').should('be.visible')
11 | cy.viewport(320, 480)
12 |
13 | // the navbar should have collapse since our screen is smaller
14 | cy.get('#navbar').should('not.be.visible')
15 | cy.get('.navbar-toggle').should('be.visible').click()
16 | cy.get('.nav').find('a').should('be.visible')
17 |
18 | // lets see what our app looks like on a super large screen
19 | cy.viewport(2999, 2999)
20 |
21 | // cy.viewport() accepts a set of preset sizes
22 | // to easily set the screen to a device's width and height
23 |
24 | // We added a cy.wait() between each viewport change so you can see
25 | // the change otherwise it is a little too fast to see :)
26 |
27 | cy.viewport('macbook-15')
28 | cy.wait(200)
29 | cy.viewport('macbook-13')
30 | cy.wait(200)
31 | cy.viewport('macbook-11')
32 | cy.wait(200)
33 | cy.viewport('ipad-2')
34 | cy.wait(200)
35 | cy.viewport('ipad-mini')
36 | cy.wait(200)
37 | cy.viewport('iphone-6+')
38 | cy.wait(200)
39 | cy.viewport('iphone-6')
40 | cy.wait(200)
41 | cy.viewport('iphone-5')
42 | cy.wait(200)
43 | cy.viewport('iphone-4')
44 | cy.wait(200)
45 | cy.viewport('iphone-3')
46 | cy.wait(200)
47 |
48 | // cy.viewport() accepts an orientation for all presets
49 | // the default orientation is 'portrait'
50 | cy.viewport('ipad-2', 'portrait')
51 | cy.wait(200)
52 | cy.viewport('iphone-4', 'landscape')
53 | cy.wait(200)
54 |
55 | // The viewport will be reset back to the default dimensions
56 | // in between tests (the default can be set in cypress.config.{js|ts})
57 | })
58 | })
59 |
--------------------------------------------------------------------------------
/cypress/e2e/2-advanced-examples/waiting.cy.js:
--------------------------------------------------------------------------------
1 | ///
2 | context('Waiting', () => {
3 | beforeEach(() => {
4 | cy.visit('https://example.cypress.io/commands/waiting')
5 | })
6 | // BE CAREFUL of adding unnecessary wait times.
7 | // https://on.cypress.io/best-practices#Unnecessary-Waiting
8 |
9 | // https://on.cypress.io/wait
10 | it('cy.wait() - wait for a specific amount of time', () => {
11 | cy.get('.wait-input1').type('Wait 1000ms after typing')
12 | cy.wait(1000)
13 | cy.get('.wait-input2').type('Wait 1000ms after typing')
14 | cy.wait(1000)
15 | cy.get('.wait-input3').type('Wait 1000ms after typing')
16 | cy.wait(1000)
17 | })
18 |
19 | it('cy.wait() - wait for a specific route', () => {
20 | // Listen to GET to comments/1
21 | cy.intercept('GET', '**/comments/*').as('getComment')
22 |
23 | // we have code that gets a comment when
24 | // the button is clicked in scripts.js
25 | cy.get('.network-btn').click()
26 |
27 | // wait for GET comments/1
28 | cy.wait('@getComment').its('response.statusCode').should('be.oneOf', [200, 304])
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/cypress/e2e/2-advanced-examples/window.cy.js:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | context('Window', () => {
4 | beforeEach(() => {
5 | cy.visit('https://example.cypress.io/commands/window')
6 | })
7 |
8 | it('cy.window() - get the global window object', () => {
9 | // https://on.cypress.io/window
10 | cy.window().should('have.property', 'top')
11 | })
12 |
13 | it('cy.document() - get the document object', () => {
14 | // https://on.cypress.io/document
15 | cy.document().should('have.property', 'charset').and('eq', 'UTF-8')
16 | })
17 |
18 | it('cy.title() - get the title', () => {
19 | // https://on.cypress.io/title
20 | cy.title().should('include', 'Kitchen Sink')
21 | })
22 | })
23 |
--------------------------------------------------------------------------------
/cypress/fixtures/example.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Using fixtures to represent data",
3 | "email": "hello@cypress.io",
4 | "body": "Fixtures are a great way to mock data for responses to routes"
5 | }
6 |
--------------------------------------------------------------------------------
/cypress/support/commands.js:
--------------------------------------------------------------------------------
1 | // ***********************************************
2 | // This example commands.js shows you how to
3 | // create various custom commands and overwrite
4 | // existing commands.
5 | //
6 | // For more comprehensive examples of custom
7 | // commands please read more here:
8 | // https://on.cypress.io/custom-commands
9 | // ***********************************************
10 | //
11 | //
12 | // -- This is a parent command --
13 | // Cypress.Commands.add('login', (email, password) => { ... })
14 | //
15 | //
16 | // -- This is a child command --
17 | // Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
18 | //
19 | //
20 | // -- This is a dual command --
21 | // Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
22 | //
23 | //
24 | // -- This will overwrite an existing command --
25 | // Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
--------------------------------------------------------------------------------
/cypress/support/e2e.js:
--------------------------------------------------------------------------------
1 | // ***********************************************************
2 | // This example support/e2e.js is processed and
3 | // loaded automatically before your test files.
4 | //
5 | // This is a great place to put global configuration and
6 | // behavior that modifies Cypress.
7 | //
8 | // You can change the location of this file or turn off
9 | // automatically serving support files with the
10 | // 'supportFile' configuration option.
11 | //
12 | // You can read more here:
13 | // https://on.cypress.io/configuration
14 | // ***********************************************************
15 |
16 | // Import commands.js using ES2015 syntax:
17 | import './commands'
18 |
19 | // Alternatively you can use CommonJS syntax:
20 | // require('./commands')
--------------------------------------------------------------------------------
/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 | - [√] cypress自动化测试
133 |
134 |
135 |
136 | ## License
137 |
138 | [MIT](https://github.com/duxianwei520/react/blob/master/LICENSE)
139 |
140 |
141 | ## 交流
142 | 想跟其他的使用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 |
10 |
11 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------