commit
8bc20069d2
374 changed files with 25289 additions and 0 deletions
Unified View
Diff Options
-
16.editorconfig
-
8.eslintignore
-
8.eslintrc.js
-
40.gitignore
-
23.prettierignore
-
5.prettierrc.js
-
5.stylelintrc.js
-
57README.md
-
18config/config.dev.js
-
49config/config.js
-
16config/defaultSettings.js
-
36config/proxy.js
-
147config/routes.js
-
BINdistribute.tar
-
9jest.config.js
-
10jsconfig.json
-
178mock/listTableList.js
-
103mock/notices.js
-
92mock/problem.js
-
7mock/route.js
-
166mock/user.js
-
106package.json
-
1public/CNAME
-
7public/config.json
-
BINpublic/favicon.ico
-
BINpublic/home_bg.png
-
BINpublic/icons/icon-128x128.png
-
BINpublic/icons/icon-192x192.png
-
BINpublic/icons/icon-512x512.png
-
5public/pro_icon.svg
-
58public/routes.json
-
7public/servers.json
-
1src/assets/logo.svg
-
1src/components/AJCZ/README.md
-
320src/components/AJCZ/index.jsx
-
16src/components/AJCZ/index.less
-
21src/components/Authorized/Authorized.jsx
-
25src/components/Authorized/AuthorizedRoute.jsx
-
72src/components/Authorized/CheckPermissions.jsx
-
78src/components/Authorized/PromiseRender.jsx
-
61src/components/Authorized/Secured.jsx
-
9src/components/Authorized/index.jsx
-
31src/components/Authorized/renderAuthorize.js
-
152src/components/BJSP-Batch/Agree.jsx
-
64src/components/BJSP-Batch/Info.jsx
-
1src/components/BJSP-Batch/README.md
-
64src/components/BJSP-Batch/Reject.jsx
-
166src/components/BJSP-Batch/index.jsx
-
16src/components/BJSP-Batch/index.less
-
152src/components/BJSP/Agree.jsx
-
64src/components/BJSP/Info.jsx
-
1src/components/BJSP/README.md
-
64src/components/BJSP/Reject.jsx
-
166src/components/BJSP/index.jsx
-
16src/components/BJSP/index.less
-
1src/components/CC/README.md
-
109src/components/CC/index.jsx
-
1src/components/CCJG/README.md
-
73src/components/CCJG/index.jsx
-
1src/components/CXPF/REASME.md
-
437src/components/CXPF/index.jsx
-
0src/components/CXPF/index.less
-
73src/components/CZMX/FormModal/TableSelect.jsx
-
332src/components/CZMX/FormModal/index.jsx
-
1src/components/CZMX/README.md
-
226src/components/CZMX/index.jsx
-
16src/components/CZMX/index.less
-
109src/components/CardList/index.jsx
-
5src/components/CardList/index.less
-
146src/components/FormModal/index.jsx
-
1src/components/GXBG/README.md
-
86src/components/GXBG/index.jsx
-
1src/components/GXBG/index.less
-
80src/components/GlobalHeader/AvatarDropdown.jsx
-
156src/components/GlobalHeader/NoticeIconView.jsx
-
42src/components/GlobalHeader/RightContent.jsx
-
86src/components/GlobalHeader/index.less
-
1src/components/HCBG/README.md
-
151src/components/HCBG/index.jsx
-
1src/components/HCZJ/README.md
-
92src/components/HCZJ/index.jsx
-
10src/components/HeaderDropdown/index.jsx
-
16src/components/HeaderDropdown/index.less
-
1src/components/HeaderMsg/README.md
-
387src/components/HeaderMsg/index.jsx
-
38src/components/HeaderMsg/index.less
-
86src/components/HeaderSearch/index.jsx
-
30src/components/HeaderSearch/index.less
-
1src/components/HeaderToDo/README.md
-
216src/components/HeaderToDo/index.jsx
-
1src/components/JDGZ/README.md
-
347src/components/JDGZ/index.jsx
-
1src/components/MyIcons/README.md
-
32src/components/MyIcons/index.jsx
-
1src/components/NextOrg/README.md
-
207src/components/NextOrg/index.js
-
97src/components/NoticeIcon/NoticeList.jsx
-
103src/components/NoticeIcon/NoticeList.less
-
119src/components/NoticeIcon/index.jsx
-
35src/components/NoticeIcon/index.less
@ -0,0 +1,16 @@ |
|||||
|
# http://editorconfig.org |
||||
|
root = true |
||||
|
|
||||
|
[*] |
||||
|
indent_style = space |
||||
|
indent_size = 2 |
||||
|
end_of_line = lf |
||||
|
charset = utf-8 |
||||
|
trim_trailing_whitespace = true |
||||
|
insert_final_newline = true |
||||
|
|
||||
|
[*.md] |
||||
|
trim_trailing_whitespace = false |
||||
|
|
||||
|
[Makefile] |
||||
|
indent_style = tab |
||||
@ -0,0 +1,8 @@ |
|||||
|
/lambda/ |
||||
|
/scripts |
||||
|
/config |
||||
|
.history |
||||
|
public |
||||
|
dist |
||||
|
.umi |
||||
|
mock |
||||
@ -0,0 +1,8 @@ |
|||||
|
module.exports = { |
||||
|
extends: [require.resolve('@umijs/fabric/dist/eslint')], |
||||
|
globals: { |
||||
|
ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION: true, |
||||
|
page: true, |
||||
|
REACT_APP_ENV: true, |
||||
|
}, |
||||
|
}; |
||||
@ -0,0 +1,40 @@ |
|||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. |
||||
|
|
||||
|
# dependencies |
||||
|
**/node_modules |
||||
|
# roadhog-api-doc ignore |
||||
|
/src/utils/request-temp.js |
||||
|
_roadhog-api-doc |
||||
|
|
||||
|
# production |
||||
|
/dist |
||||
|
/.vscode |
||||
|
|
||||
|
# misc |
||||
|
.DS_Store |
||||
|
npm-debug.log* |
||||
|
yarn-error.log |
||||
|
|
||||
|
/coverage |
||||
|
.idea |
||||
|
yarn.lock |
||||
|
package-lock.json |
||||
|
*bak |
||||
|
.vscode |
||||
|
|
||||
|
# visual studio code |
||||
|
.history |
||||
|
*.log |
||||
|
functions/* |
||||
|
.temp/** |
||||
|
|
||||
|
# umi |
||||
|
.umi |
||||
|
.umi-production |
||||
|
|
||||
|
# screenshot |
||||
|
screenshot |
||||
|
.firebase |
||||
|
.eslintcache |
||||
|
|
||||
|
build |
||||
@ -0,0 +1,23 @@ |
|||||
|
**/*.svg |
||||
|
package.json |
||||
|
.umi |
||||
|
.umi-production |
||||
|
/dist |
||||
|
.dockerignore |
||||
|
.DS_Store |
||||
|
.eslintignore |
||||
|
*.png |
||||
|
*.toml |
||||
|
docker |
||||
|
.editorconfig |
||||
|
Dockerfile* |
||||
|
.gitignore |
||||
|
.prettierignore |
||||
|
LICENSE |
||||
|
.eslintcache |
||||
|
*.lock |
||||
|
yarn-error.log |
||||
|
.history |
||||
|
CNAME |
||||
|
/build |
||||
|
/public |
||||
@ -0,0 +1,5 @@ |
|||||
|
const fabric = require('@umijs/fabric'); |
||||
|
|
||||
|
module.exports = { |
||||
|
...fabric.prettier, |
||||
|
}; |
||||
@ -0,0 +1,5 @@ |
|||||
|
const fabric = require('@umijs/fabric'); |
||||
|
|
||||
|
module.exports = { |
||||
|
...fabric.stylelint, |
||||
|
}; |
||||
@ -0,0 +1,57 @@ |
|||||
|
# Ant Design Pro |
||||
|
|
||||
|
This project is initialized with [Ant Design Pro](https://pro.ant.design). Follow is the quick guide for how to use. |
||||
|
|
||||
|
## Environment Prepare |
||||
|
|
||||
|
Install `node_modules`: |
||||
|
|
||||
|
```bash |
||||
|
npm install |
||||
|
``` |
||||
|
|
||||
|
or |
||||
|
|
||||
|
```bash |
||||
|
yarn |
||||
|
``` |
||||
|
|
||||
|
## Provided Scripts |
||||
|
|
||||
|
Ant Design Pro provides some useful script to help you quick start and build with web project, code style check and test. |
||||
|
|
||||
|
Scripts provided in `package.json`. It's safe to modify or add additional script: |
||||
|
|
||||
|
### Start project |
||||
|
|
||||
|
```bash |
||||
|
npm start |
||||
|
``` |
||||
|
|
||||
|
### Build project |
||||
|
|
||||
|
```bash |
||||
|
npm run build |
||||
|
``` |
||||
|
|
||||
|
### Check code style |
||||
|
|
||||
|
```bash |
||||
|
npm run lint |
||||
|
``` |
||||
|
|
||||
|
You can also use script to auto fix some lint error: |
||||
|
|
||||
|
```bash |
||||
|
npm run lint:fix |
||||
|
``` |
||||
|
|
||||
|
### Test code |
||||
|
|
||||
|
```bash |
||||
|
npm test |
||||
|
``` |
||||
|
|
||||
|
## More |
||||
|
|
||||
|
You can view full document on our [official website](https://pro.ant.design). And welcome any feedback in our [github](https://github.com/ant-design/ant-design-pro). |
||||
@ -0,0 +1,18 @@ |
|||||
|
// https://umijs.org/config/
|
||||
|
import { defineConfig } from 'umi'; |
||||
|
|
||||
|
export default defineConfig({ |
||||
|
plugins: [ |
||||
|
// https://github.com/zthxxx/react-dev-inspector
|
||||
|
'react-dev-inspector/plugins/umi/react-inspector', |
||||
|
], |
||||
|
// https://github.com/zthxxx/react-dev-inspector#inspector-loader-props
|
||||
|
inspectorConfig: { |
||||
|
exclude: [], |
||||
|
babelPlugins: [], |
||||
|
babelOptions: {}, |
||||
|
}, |
||||
|
|
||||
|
|
||||
|
|
||||
|
}); |
||||
@ -0,0 +1,49 @@ |
|||||
|
// https://umijs.org/config/
|
||||
|
import { defineConfig } from 'umi'; |
||||
|
import defaultSettings from './defaultSettings'; |
||||
|
import proxy from './proxy'; |
||||
|
import routes from './routes'; |
||||
|
|
||||
|
const { REACT_APP_ENV } = process.env; |
||||
|
|
||||
|
export default defineConfig({ |
||||
|
hash: true, |
||||
|
antd: {}, |
||||
|
dva: { |
||||
|
hmr: true, |
||||
|
}, |
||||
|
history: { |
||||
|
type: 'browser', |
||||
|
}, |
||||
|
locale: { |
||||
|
// default zh-CN
|
||||
|
default: 'zh-CN', |
||||
|
antd: true, |
||||
|
// default true, when it is true, will use `navigator.language` overwrite default
|
||||
|
baseNavigator: true, |
||||
|
}, |
||||
|
dynamicImport: { |
||||
|
loading: '@/components/PageLoading/index', |
||||
|
}, |
||||
|
targets: { |
||||
|
ie: 11, |
||||
|
}, |
||||
|
// umi routes: https://umijs.org/docs/routing
|
||||
|
routes, |
||||
|
// Theme for antd: https://ant.design/docs/react/customize-theme-cn
|
||||
|
theme: { |
||||
|
'primary-color': defaultSettings.primaryColor, |
||||
|
}, |
||||
|
base: '/superintend/', |
||||
|
publicPath: '/superintend/', |
||||
|
title: false, |
||||
|
ignoreMomentLocale: true, |
||||
|
proxy: proxy[REACT_APP_ENV || 'dev'], |
||||
|
manifest: { |
||||
|
basePath: '/', |
||||
|
}, |
||||
|
esbuild: {}, |
||||
|
define: { |
||||
|
|
||||
|
} |
||||
|
}); |
||||
@ -0,0 +1,16 @@ |
|||||
|
const proSettings = { |
||||
|
"navTheme": "light", |
||||
|
"primaryColor": "#1890ff", |
||||
|
"layout": "side", |
||||
|
// "contentWidth": "Fluid",
|
||||
|
"fixedHeader": false, |
||||
|
"fixSiderbar": false, |
||||
|
"pwa": false, |
||||
|
"iconfontUrl": "", |
||||
|
"menu": { |
||||
|
"locale": false |
||||
|
}, |
||||
|
"footerRender": false, |
||||
|
"menuHeaderRender": false |
||||
|
}; |
||||
|
export default proSettings; |
||||
@ -0,0 +1,36 @@ |
|||||
|
/** |
||||
|
* 在生产环境 代理是无法生效的,所以这里没有生产环境的配置 |
||||
|
* The agent cannot take effect in the production environment |
||||
|
* so there is no configuration of the production environment |
||||
|
* For details, please see |
||||
|
* https://pro.ant.design/docs/deploy
|
||||
|
*/ |
||||
|
export default { |
||||
|
dev: { |
||||
|
'/api/': { |
||||
|
target: 'https://preview.pro.ant.design', |
||||
|
changeOrigin: true, |
||||
|
pathRewrite: { |
||||
|
'^': '', |
||||
|
}, |
||||
|
}, |
||||
|
}, |
||||
|
test: { |
||||
|
'/api/': { |
||||
|
target: 'https://preview.pro.ant.design', |
||||
|
changeOrigin: true, |
||||
|
pathRewrite: { |
||||
|
'^': '', |
||||
|
}, |
||||
|
}, |
||||
|
}, |
||||
|
pre: { |
||||
|
'/api/': { |
||||
|
target: 'your pre url', |
||||
|
changeOrigin: true, |
||||
|
pathRewrite: { |
||||
|
'^': '', |
||||
|
}, |
||||
|
}, |
||||
|
}, |
||||
|
}; |
||||
@ -0,0 +1,147 @@ |
|||||
|
// 注释:hideInMenu参数控制菜单隐藏
|
||||
|
export default [ |
||||
|
{ |
||||
|
path: '/', |
||||
|
component: '../layouts/BlankLayout', |
||||
|
routes: [ |
||||
|
// {
|
||||
|
// path: '/user',
|
||||
|
// component: '../layouts/UserLayout',
|
||||
|
// routes: [
|
||||
|
// {
|
||||
|
// name: 'login',
|
||||
|
// path: '/user/login',
|
||||
|
// component: './User/login',
|
||||
|
// },
|
||||
|
// ],
|
||||
|
// },
|
||||
|
{ |
||||
|
path: '/', |
||||
|
component: '../layouts/SecurityLayout', |
||||
|
routes: [ |
||||
|
{ |
||||
|
path: '/resultdata', |
||||
|
component: './ResultData', |
||||
|
}, |
||||
|
{ |
||||
|
path:"/GZT", |
||||
|
component:"./GZT" |
||||
|
}, |
||||
|
{ |
||||
|
path: '/', |
||||
|
component: '../layouts/BasicLayout', |
||||
|
// authority: ['admin', 'user'],
|
||||
|
routes: [ |
||||
|
{ |
||||
|
path: '/', |
||||
|
redirect: '/doingcases', |
||||
|
}, |
||||
|
{ |
||||
|
name: '在办事项', |
||||
|
path: '/doingcases', |
||||
|
icon: 'BarsOutlined', |
||||
|
component: './DoingCases', |
||||
|
}, |
||||
|
{ |
||||
|
name: '已办事项', |
||||
|
path: '/donecases', |
||||
|
icon: 'AuditOutlined', |
||||
|
component: './DoneCases', |
||||
|
}, |
||||
|
{ |
||||
|
name: '进度查询', |
||||
|
path: '/progresssearch', |
||||
|
icon: 'ProfileOutlined', |
||||
|
component: './ProgressSearch', |
||||
|
}, |
||||
|
{ |
||||
|
name: '问题处理单查询', |
||||
|
path: '/problemhandlingsearch', |
||||
|
icon: 'ScheduleOutlined', |
||||
|
hideInMenu: false, // 控制菜单隐藏
|
||||
|
component: './ProblemHandlingSearch', |
||||
|
}, |
||||
|
// {
|
||||
|
// name: '督察专项',
|
||||
|
// path: '/superviseitem',
|
||||
|
// icon: 'ProjectOutlined',
|
||||
|
// component: './SuperviseItem',
|
||||
|
// },
|
||||
|
{ |
||||
|
name: '督察专项', |
||||
|
path: '/superviseitem', |
||||
|
icon: 'ProjectOutlined', |
||||
|
routes: [ |
||||
|
{ |
||||
|
name: '专项审批', |
||||
|
path: '/superviseitem/approve', |
||||
|
icon: 'AuditOutlined', |
||||
|
authority: ['bu'], |
||||
|
component: './SuperviseItem/ApproveItem', |
||||
|
}, |
||||
|
{ |
||||
|
name: '专项签收', |
||||
|
path: '/superviseitem/check', |
||||
|
icon: 'AuditOutlined', |
||||
|
component: './SuperviseItem/CheckItem', |
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
|
{ |
||||
|
name: '模型审批', |
||||
|
path: '/modelapprove', |
||||
|
icon: 'SnippetsOutlined', |
||||
|
routes: [ |
||||
|
{ |
||||
|
name: '模型分享', |
||||
|
path: '/modelapprove/share', |
||||
|
icon: 'AuditOutlined', |
||||
|
component: './ModelApprove/Share', |
||||
|
}, |
||||
|
{ |
||||
|
name: '省级上报', |
||||
|
path: '/modelapprove/report', |
||||
|
icon: 'AuditOutlined', |
||||
|
component: './ModelApprove/Report', |
||||
|
authority: ['bu', 'sheng'], |
||||
|
}, |
||||
|
{ |
||||
|
name: '市级上报', |
||||
|
path: '/modelapprove/reportshi', |
||||
|
icon: 'AuditOutlined', |
||||
|
component: './ModelApprove/Report', |
||||
|
authority: ['sheng', 'shi'], |
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
|
{ |
||||
|
name: '系统配置', |
||||
|
path: '/systemmanage', |
||||
|
icon: 'SettingOutlined', |
||||
|
authority: ['gly'], |
||||
|
routes: [ |
||||
|
{ |
||||
|
name: '层级联动', |
||||
|
path: '/systemmanage/levelmanage', |
||||
|
icon: 'AuditOutlined', |
||||
|
component: './SystemManage/LevelManage', |
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
|
{ |
||||
|
component: './404', |
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
|
{ |
||||
|
component: './404', |
||||
|
}, |
||||
|
], |
||||
|
|
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
|
{ |
||||
|
component: './404', |
||||
|
}, |
||||
|
]; |
||||
@ -0,0 +1,9 @@ |
|||||
|
module.exports = { |
||||
|
testURL: 'http://localhost:8000', |
||||
|
testEnvironment: './tests/PuppeteerEnvironment', |
||||
|
verbose: false, |
||||
|
globals: { |
||||
|
ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION: false, |
||||
|
localStorage: null, |
||||
|
}, |
||||
|
}; |
||||
@ -0,0 +1,10 @@ |
|||||
|
{ |
||||
|
"compilerOptions": { |
||||
|
"emitDecoratorMetadata": true, |
||||
|
"experimentalDecorators": true, |
||||
|
"baseUrl": ".", |
||||
|
"paths": { |
||||
|
"@/*": ["./src/*"] |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,178 @@ |
|||||
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
|
import { parse } from 'url'; |
||||
|
|
||||
|
// mock tableListDataSource
|
||||
|
const genList = (current, pageSize) => { |
||||
|
const tableListDataSource = []; |
||||
|
|
||||
|
for (let i = 0; i < pageSize; i += 1) { |
||||
|
const index = (current - 1) * 10 + i; |
||||
|
tableListDataSource.push({ |
||||
|
key: index, |
||||
|
disabled: i % 6 === 0, |
||||
|
href: 'https://ant.design', |
||||
|
avatar: [ |
||||
|
'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', |
||||
|
'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', |
||||
|
][i % 2], |
||||
|
name: `TradeCode ${index}`, |
||||
|
owner: '曲丽丽', |
||||
|
desc: '这是一段描述', |
||||
|
callNo: Math.floor(Math.random() * 1000), |
||||
|
status: Math.floor(Math.random() * 10) % 4, |
||||
|
updatedAt: new Date(), |
||||
|
createdAt: new Date(), |
||||
|
progress: Math.ceil(Math.random() * 100), |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
tableListDataSource.reverse(); |
||||
|
return tableListDataSource; |
||||
|
}; |
||||
|
|
||||
|
let tableListDataSource = genList(1, 100); |
||||
|
|
||||
|
function getRule(req, res, u) { |
||||
|
let realUrl = u; |
||||
|
|
||||
|
if (!realUrl || Object.prototype.toString.call(realUrl) !== '[object String]') { |
||||
|
realUrl = req.url; |
||||
|
} |
||||
|
|
||||
|
const { current = 1, pageSize = 10 } = req.query; |
||||
|
const params = parse(realUrl, true).query; |
||||
|
let dataSource = [...tableListDataSource].slice((current - 1) * pageSize, current * pageSize); |
||||
|
const sorter = JSON.parse(params.sorter); |
||||
|
|
||||
|
if (sorter) { |
||||
|
dataSource = dataSource.sort((prev, next) => { |
||||
|
let sortNumber = 0; |
||||
|
Object.keys(sorter).forEach(key => { |
||||
|
if (sorter[key] === 'descend') { |
||||
|
if (prev[key] - next[key] > 0) { |
||||
|
sortNumber += -1; |
||||
|
} else { |
||||
|
sortNumber += 1; |
||||
|
} |
||||
|
|
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (prev[key] - next[key] > 0) { |
||||
|
sortNumber += 1; |
||||
|
} else { |
||||
|
sortNumber += -1; |
||||
|
} |
||||
|
}); |
||||
|
return sortNumber; |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
if (params.filter) { |
||||
|
const filter = JSON.parse(params.filter); |
||||
|
|
||||
|
if (Object.keys(filter).length > 0) { |
||||
|
dataSource = dataSource.filter(item => |
||||
|
Object.keys(filter).some(key => { |
||||
|
if (!filter[key]) { |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
if (filter[key].includes(`${item[key]}`)) { |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
return false; |
||||
|
}), |
||||
|
); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (params.name) { |
||||
|
dataSource = dataSource.filter(data => data.name.includes(params.name || '')); |
||||
|
} |
||||
|
|
||||
|
const result = { |
||||
|
data: dataSource, |
||||
|
total: tableListDataSource.length, |
||||
|
success: true, |
||||
|
pageSize, |
||||
|
current: parseInt(`${params.currentPage}`, 10) || 1, |
||||
|
}; |
||||
|
return res.json(result); |
||||
|
} |
||||
|
|
||||
|
function postRule(req, res, u, b) { |
||||
|
let realUrl = u; |
||||
|
|
||||
|
if (!realUrl || Object.prototype.toString.call(realUrl) !== '[object String]') { |
||||
|
realUrl = req.url; |
||||
|
} |
||||
|
|
||||
|
const body = (b && b.body) || req.body; |
||||
|
const { method, name, desc, key } = body; |
||||
|
|
||||
|
switch (method) { |
||||
|
/* eslint no-case-declarations:0 */ |
||||
|
case 'delete': |
||||
|
tableListDataSource = tableListDataSource.filter(item => key.indexOf(item.key) === -1); |
||||
|
break; |
||||
|
|
||||
|
case 'post': |
||||
|
(() => { |
||||
|
const i = Math.ceil(Math.random() * 10000); |
||||
|
const newRule = { |
||||
|
key: tableListDataSource.length, |
||||
|
href: 'https://ant.design', |
||||
|
avatar: [ |
||||
|
'https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', |
||||
|
'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png', |
||||
|
][i % 2], |
||||
|
name, |
||||
|
owner: '曲丽丽', |
||||
|
desc, |
||||
|
callNo: Math.floor(Math.random() * 1000), |
||||
|
status: Math.floor(Math.random() * 10) % 2, |
||||
|
updatedAt: new Date(), |
||||
|
createdAt: new Date(), |
||||
|
progress: Math.ceil(Math.random() * 100), |
||||
|
}; |
||||
|
tableListDataSource.unshift(newRule); |
||||
|
return res.json(newRule); |
||||
|
})(); |
||||
|
|
||||
|
return; |
||||
|
|
||||
|
case 'update': |
||||
|
(() => { |
||||
|
let newRule = {}; |
||||
|
tableListDataSource = tableListDataSource.map(item => { |
||||
|
if (item.key === key) { |
||||
|
newRule = { ...item, desc, name }; |
||||
|
return { ...item, desc, name }; |
||||
|
} |
||||
|
|
||||
|
return item; |
||||
|
}); |
||||
|
return res.json(newRule); |
||||
|
})(); |
||||
|
|
||||
|
return; |
||||
|
|
||||
|
default: |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
const result = { |
||||
|
list: tableListDataSource, |
||||
|
pagination: { |
||||
|
total: tableListDataSource.length, |
||||
|
}, |
||||
|
}; |
||||
|
res.json(result); |
||||
|
} |
||||
|
|
||||
|
export default { |
||||
|
'GET /api/rule': getRule, |
||||
|
'POST /api/rule': postRule, |
||||
|
}; |
||||
@ -0,0 +1,103 @@ |
|||||
|
const getNotices = (req, res) => { |
||||
|
res.json([ |
||||
|
{ |
||||
|
id: '000000001', |
||||
|
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png', |
||||
|
title: '你收到了 14 份新周报', |
||||
|
datetime: '2017-08-09', |
||||
|
type: 'notification', |
||||
|
}, |
||||
|
{ |
||||
|
id: '000000002', |
||||
|
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/OKJXDXrmkNshAMvwtvhu.png', |
||||
|
title: '你推荐的 曲妮妮 已通过第三轮面试', |
||||
|
datetime: '2017-08-08', |
||||
|
type: 'notification', |
||||
|
}, |
||||
|
{ |
||||
|
id: '000000003', |
||||
|
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/kISTdvpyTAhtGxpovNWd.png', |
||||
|
title: '这种模板可以区分多种通知类型', |
||||
|
datetime: '2017-08-07', |
||||
|
read: true, |
||||
|
type: 'notification', |
||||
|
}, |
||||
|
{ |
||||
|
id: '000000004', |
||||
|
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/GvqBnKhFgObvnSGkDsje.png', |
||||
|
title: '左侧图标用于区分不同的类型', |
||||
|
datetime: '2017-08-07', |
||||
|
type: 'notification', |
||||
|
}, |
||||
|
{ |
||||
|
id: '000000005', |
||||
|
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png', |
||||
|
title: '内容不要超过两行字,超出时自动截断', |
||||
|
datetime: '2017-08-07', |
||||
|
type: 'notification', |
||||
|
}, |
||||
|
{ |
||||
|
id: '000000006', |
||||
|
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/fcHMVNCjPOsbUGdEduuv.jpeg', |
||||
|
title: '曲丽丽 评论了你', |
||||
|
description: '描述信息描述信息描述信息', |
||||
|
datetime: '2017-08-07', |
||||
|
type: 'message', |
||||
|
clickClose: true, |
||||
|
}, |
||||
|
{ |
||||
|
id: '000000007', |
||||
|
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/fcHMVNCjPOsbUGdEduuv.jpeg', |
||||
|
title: '朱偏右 回复了你', |
||||
|
description: '这种模板用于提醒谁与你发生了互动,左侧放『谁』的头像', |
||||
|
datetime: '2017-08-07', |
||||
|
type: 'message', |
||||
|
clickClose: true, |
||||
|
}, |
||||
|
{ |
||||
|
id: '000000008', |
||||
|
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/fcHMVNCjPOsbUGdEduuv.jpeg', |
||||
|
title: '标题', |
||||
|
description: '这种模板用于提醒谁与你发生了互动,左侧放『谁』的头像', |
||||
|
datetime: '2017-08-07', |
||||
|
type: 'message', |
||||
|
clickClose: true, |
||||
|
}, |
||||
|
{ |
||||
|
id: '000000009', |
||||
|
title: '任务名称', |
||||
|
description: '任务需要在 2017-01-12 20:00 前启动', |
||||
|
extra: '未开始', |
||||
|
status: 'todo', |
||||
|
type: 'event', |
||||
|
}, |
||||
|
{ |
||||
|
id: '000000010', |
||||
|
title: '第三方紧急代码变更', |
||||
|
description: '冠霖提交于 2017-01-06,需在 2017-01-07 前完成代码变更任务', |
||||
|
extra: '马上到期', |
||||
|
status: 'urgent', |
||||
|
type: 'event', |
||||
|
}, |
||||
|
{ |
||||
|
id: '000000011', |
||||
|
title: '信息安全考试', |
||||
|
description: '指派竹尔于 2017-01-09 前完成更新并发布', |
||||
|
extra: '已耗时 8 天', |
||||
|
status: 'doing', |
||||
|
type: 'event', |
||||
|
}, |
||||
|
{ |
||||
|
id: '000000012', |
||||
|
title: 'ABCD 版本发布', |
||||
|
description: '冠霖提交于 2017-01-06,需在 2017-01-07 前完成代码变更任务', |
||||
|
extra: '进行中', |
||||
|
status: 'processing', |
||||
|
type: 'event', |
||||
|
}, |
||||
|
]); |
||||
|
}; |
||||
|
|
||||
|
export default { |
||||
|
'GET /api/notices': getNotices, |
||||
|
}; |
||||
@ -0,0 +1,92 @@ |
|||||
|
const getProblemList = (req, res) => { |
||||
|
res.json({ |
||||
|
total: 1, |
||||
|
resCode: 0, |
||||
|
data: [ |
||||
|
{ |
||||
|
DCWTLXDM: "01010100", |
||||
|
DCWTMC_BT: "督办单测试", |
||||
|
JWDCFSDM: "101", |
||||
|
OPEN_DATE: "2018/9/28 15:31:32", |
||||
|
OrgNo: "650000000000", |
||||
|
TIMEOUT_DATE: "2018/9/28 15:31:54", |
||||
|
WTSJASJ_ASJFSKSSJ: "2018-09-28 15:31:28", |
||||
|
WTSJDW_GAJGJGDM: "650000000000", |
||||
|
WTSJDW_GAJGMC: "新疆维吾尔自治区公安厅", |
||||
|
XXDJDW_GAJGJGDM: "650000000000", |
||||
|
XXDJDW_GAJGMC: "新疆维吾尔自治区公安厅", |
||||
|
XXDJRY_GMSFHM: "430124198602200038", |
||||
|
XXDJRY_XM: "管理", |
||||
|
ZYCD_PDBZ: 0, |
||||
|
JJCD_PDBZ_NAME: "否", |
||||
|
WTSJASJ_ASJFSKSSJ_VIEW: "2018-09-28 15:31:28", |
||||
|
ZYCD_PDBZ_NAME: "否", |
||||
|
ZJMC: "测试一下督察问题证据信息证据名称", |
||||
|
JYQK: "没有什么可以写的", |
||||
|
GMSFHM: "430124198602200038", |
||||
|
UName: "管理", |
||||
|
OrgNo: "650000000000", |
||||
|
GAJGMC: "新疆维吾尔自治区公安厅", |
||||
|
wtsjrItem: [{ |
||||
|
WTSJR_GMSFHM: " 4310************11", |
||||
|
WTSJR_XM: "张三", |
||||
|
WTSJR_XBDM: "1", |
||||
|
WTSJR_CSRQ: " 19870101", |
||||
|
WTSJR_JH: " 10019", |
||||
|
WTSJR_JXYWZJBDM: "", |
||||
|
WTSJR_ZZMMDM: "", |
||||
|
WTSJR_GBZWDM: " 430000000000", |
||||
|
WTSJR_GAJGJGDM: " 430000000000", |
||||
|
WTSJR_LXDH: "" |
||||
|
}, { |
||||
|
WTSJR_GMSFHM: " 4310************25", |
||||
|
WTSJR_XM: "张红强", |
||||
|
WTSJR_XBDM: "1", |
||||
|
WTSJR_CSRQ: " 19000101", |
||||
|
WTSJR_JH: " 10008", |
||||
|
WTSJR_JXYWZJBDM: "", |
||||
|
WTSJR_ZZMMDM: "", |
||||
|
WTSJR_GBZWDM: " 431000000000", |
||||
|
WTSJR_GAJGJGDM: " 431000000000", |
||||
|
WTSJR_LXDH: "" |
||||
|
}], |
||||
|
evidenceItem: { |
||||
|
head: [{ |
||||
|
fieldName: "KeyWord", |
||||
|
fieldAlias: "关键字" |
||||
|
}, { |
||||
|
fieldName: "StartTime", |
||||
|
fieldAlias: "开始时间" |
||||
|
}, { |
||||
|
fieldName: "EndTime", |
||||
|
fieldAlias: "结束时间" |
||||
|
}, { |
||||
|
fieldName: "FileName", |
||||
|
fieldAlias: "文件名称" |
||||
|
}, { |
||||
|
fieldName: "FilePosition", |
||||
|
fieldAlias: "文件路径" |
||||
|
} |
||||
|
], |
||||
|
data: [{ |
||||
|
KeyWord: "关键字1", |
||||
|
StartTime: "2018-10-2 17:28:36", |
||||
|
EndTime: "2018-10-2 17:28:42", |
||||
|
FileName: "文件名1", |
||||
|
FilePosition: "http://www.baidu.com" |
||||
|
}, { |
||||
|
KeyWord: "关键字2", |
||||
|
StartTime: "2018-10-2 17:28:46", |
||||
|
EndTime: "2018-10-2 17:28:50", |
||||
|
FileName: "文件名2", |
||||
|
FilePosition: "http://www.baidu.com" |
||||
|
}] |
||||
|
} |
||||
|
} |
||||
|
] |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
export default { |
||||
|
'POST /Api/Dispose/BTDisposeList': getProblemList, |
||||
|
}; |
||||
@ -0,0 +1,7 @@ |
|||||
|
export default { |
||||
|
'/api/auth_routes': { |
||||
|
'/form/advanced-form': { |
||||
|
authority: ['admin', 'user'], |
||||
|
}, |
||||
|
}, |
||||
|
}; |
||||
@ -0,0 +1,166 @@ |
|||||
|
const waitTime = (time = 100) => |
||||
|
new Promise(resolve => { |
||||
|
setTimeout(() => { |
||||
|
resolve(true); |
||||
|
}, time); |
||||
|
}); |
||||
|
|
||||
|
async function getFakeCaptcha(req, res) { |
||||
|
await waitTime(2000); |
||||
|
return res.json('captcha-xxx'); |
||||
|
} // 代码中会兼容本地 service mock 以及部署站点的静态数据
|
||||
|
|
||||
|
export default { |
||||
|
// 支持值为 Object 和 Array
|
||||
|
'GET /api/currentUser': { |
||||
|
name: 'Serati Ma', |
||||
|
avatar: 'https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png', |
||||
|
userid: '00000001', |
||||
|
email: 'antdesign@alipay.com', |
||||
|
signature: '海纳百川,有容乃大', |
||||
|
title: '交互专家', |
||||
|
group: '蚂蚁集团-某某某事业群-某某平台部-某某技术部-UED', |
||||
|
tags: [ |
||||
|
{ |
||||
|
key: '0', |
||||
|
label: '很有想法的', |
||||
|
}, |
||||
|
{ |
||||
|
key: '1', |
||||
|
label: '专注设计', |
||||
|
}, |
||||
|
{ |
||||
|
key: '2', |
||||
|
label: '辣~', |
||||
|
}, |
||||
|
{ |
||||
|
key: '3', |
||||
|
label: '大长腿', |
||||
|
}, |
||||
|
{ |
||||
|
key: '4', |
||||
|
label: '川妹子', |
||||
|
}, |
||||
|
{ |
||||
|
key: '5', |
||||
|
label: '海纳百川', |
||||
|
}, |
||||
|
], |
||||
|
notifyCount: 12, |
||||
|
unreadCount: 11, |
||||
|
country: 'China', |
||||
|
geographic: { |
||||
|
province: { |
||||
|
label: '浙江省', |
||||
|
key: '330000', |
||||
|
}, |
||||
|
city: { |
||||
|
label: '杭州市', |
||||
|
key: '330100', |
||||
|
}, |
||||
|
}, |
||||
|
address: '西湖区工专路 77 号', |
||||
|
phone: '0752-268888888', |
||||
|
}, |
||||
|
// GET POST 可省略
|
||||
|
'GET /api/users': [ |
||||
|
{ |
||||
|
key: '1', |
||||
|
name: 'John Brown', |
||||
|
age: 32, |
||||
|
address: 'New York No. 1 Lake Park', |
||||
|
}, |
||||
|
{ |
||||
|
key: '2', |
||||
|
name: 'Jim Green', |
||||
|
age: 42, |
||||
|
address: 'London No. 1 Lake Park', |
||||
|
}, |
||||
|
{ |
||||
|
key: '3', |
||||
|
name: 'Joe Black', |
||||
|
age: 32, |
||||
|
address: 'Sidney No. 1 Lake Park', |
||||
|
}, |
||||
|
], |
||||
|
'POST /api/login/account': async (req, res) => { |
||||
|
const { password, userName, type } = req.body; |
||||
|
await waitTime(2000); |
||||
|
|
||||
|
if (password === 'ant.design' && userName === 'admin') { |
||||
|
res.send({ |
||||
|
status: 'ok', |
||||
|
type, |
||||
|
currentAuthority: 'admin', |
||||
|
}); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (password === 'ant.design' && userName === 'user') { |
||||
|
res.send({ |
||||
|
status: 'ok', |
||||
|
type, |
||||
|
currentAuthority: 'user', |
||||
|
}); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (type === 'mobile') { |
||||
|
res.send({ |
||||
|
status: 'ok', |
||||
|
type, |
||||
|
currentAuthority: 'admin', |
||||
|
}); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
res.send({ |
||||
|
status: 'error', |
||||
|
type, |
||||
|
currentAuthority: 'guest', |
||||
|
}); |
||||
|
}, |
||||
|
'POST /api/register': (req, res) => { |
||||
|
res.send({ |
||||
|
status: 'ok', |
||||
|
currentAuthority: 'user', |
||||
|
}); |
||||
|
}, |
||||
|
'GET /api/500': (req, res) => { |
||||
|
res.status(500).send({ |
||||
|
timestamp: 1513932555104, |
||||
|
status: 500, |
||||
|
error: 'error', |
||||
|
message: 'error', |
||||
|
path: '/base/category/list', |
||||
|
}); |
||||
|
}, |
||||
|
'GET /api/404': (req, res) => { |
||||
|
res.status(404).send({ |
||||
|
timestamp: 1513932643431, |
||||
|
status: 404, |
||||
|
error: 'Not Found', |
||||
|
message: 'No message available', |
||||
|
path: '/base/category/list/2121212', |
||||
|
}); |
||||
|
}, |
||||
|
'GET /api/403': (req, res) => { |
||||
|
res.status(403).send({ |
||||
|
timestamp: 1513932555104, |
||||
|
status: 403, |
||||
|
error: 'Unauthorized', |
||||
|
message: 'Unauthorized', |
||||
|
path: '/base/category/list', |
||||
|
}); |
||||
|
}, |
||||
|
'GET /api/401': (req, res) => { |
||||
|
res.status(401).send({ |
||||
|
timestamp: 1513932555104, |
||||
|
status: 401, |
||||
|
error: 'Unauthorized', |
||||
|
message: 'Unauthorized', |
||||
|
path: '/base/category/list', |
||||
|
}); |
||||
|
}, |
||||
|
'GET /api/login/captcha': getFakeCaptcha, |
||||
|
}; |
||||
@ -0,0 +1,106 @@ |
|||||
|
{ |
||||
|
"name": "ant-design-pro", |
||||
|
"version": "4.5.0", |
||||
|
"private": true, |
||||
|
"description": "An out-of-box UI solution for enterprise applications", |
||||
|
"scripts": { |
||||
|
"analyze": "cross-env ANALYZE=1 umi build", |
||||
|
"build": "umi build", |
||||
|
"build:sheng": "cross-env PRO=sheng umi build", |
||||
|
"deploy": "npm run site && npm run gh-pages", |
||||
|
"dev": "npm run start:dev", |
||||
|
"fetch:blocks": "pro fetch-blocks && npm run prettier", |
||||
|
"gh-pages": "gh-pages -d dist", |
||||
|
"i18n-remove": "pro i18n-remove --locale=zh-CN --write", |
||||
|
"postinstall": "umi g tmp", |
||||
|
"lint": "umi g tmp && npm run lint:js && npm run lint:style && npm run lint:prettier", |
||||
|
"lint-staged:js": "eslint --ext .js,.jsx,.ts,.tsx ", |
||||
|
"lint:fix": "eslint --fix --cache --ext .js,.jsx,.ts,.tsx --format=pretty ./src && npm run lint:style", |
||||
|
"lint:js": "eslint --cache --ext .js,.jsx,.ts,.tsx --format=pretty ./src", |
||||
|
"lint:prettier": "prettier --check \"src/**/*\" --end-of-line auto", |
||||
|
"lint:style": "stylelint --fix \"src/**/*.less\" --syntax less", |
||||
|
"prettier": "prettier -c --write \"src/**/*\"", |
||||
|
"start": "cross-env UMI_ENV=dev a=1 umi dev", |
||||
|
"start:dev": "cross-env REACT_APP_ENV=dev MOCK=none UMI_ENV=dev umi dev", |
||||
|
"start:no-mock": "cross-env MOCK=none UMI_ENV=dev umi dev", |
||||
|
"start:no-ui": "cross-env UMI_UI=none UMI_ENV=dev umi dev", |
||||
|
"start:pre": "cross-env REACT_APP_ENV=pre UMI_ENV=dev umi dev", |
||||
|
"start:test": "cross-env REACT_APP_ENV=test MOCK=none UMI_ENV=dev umi dev", |
||||
|
"pretest": "node ./tests/beforeTest", |
||||
|
"test": "umi test", |
||||
|
"test:all": "node ./tests/run-tests.js", |
||||
|
"test:component": "umi test ./src/components", |
||||
|
"tsc": "tsc --noEmit" |
||||
|
}, |
||||
|
"browserslist": [ |
||||
|
"> 1%", |
||||
|
"last 2 versions", |
||||
|
"not ie <= 10" |
||||
|
], |
||||
|
"dependencies": { |
||||
|
"@ant-design/icons": "^4.0.0", |
||||
|
"@ant-design/pro-descriptions": "^1.2.0", |
||||
|
"@ant-design/pro-form": "^1.3.0", |
||||
|
"@ant-design/pro-layout": "^6.9.0", |
||||
|
"@ant-design/pro-table": "^2.17.0", |
||||
|
"@umijs/route-utils": "^1.0.33", |
||||
|
"antd": "^4.10.0", |
||||
|
"classnames": "^2.2.6", |
||||
|
"lodash": "^4.17.11", |
||||
|
"moment": "^2.25.3", |
||||
|
"omit.js": "^2.0.2", |
||||
|
"qs": "^6.9.0", |
||||
|
"react": "^17.0.0", |
||||
|
"react-dev-inspector": "^1.1.1", |
||||
|
"react-dom": "^17.0.0", |
||||
|
"react-helmet-async": "^1.0.4", |
||||
|
"umi": "^3.2.14", |
||||
|
"umi-request": "^1.0.8" |
||||
|
}, |
||||
|
"devDependencies": { |
||||
|
"@ant-design/pro-cli": "^1.0.28", |
||||
|
"@types/classnames": "^2.2.7", |
||||
|
"@types/express": "^4.17.0", |
||||
|
"@types/history": "^4.7.2", |
||||
|
"@types/jest": "^26.0.0", |
||||
|
"@types/lodash": "^4.14.144", |
||||
|
"@types/qs": "^6.5.3", |
||||
|
"@types/react": "^17.0.0", |
||||
|
"@types/react-dom": "^17.0.0", |
||||
|
"@types/react-helmet": "^6.1.0", |
||||
|
"@umijs/fabric": "^2.5.1", |
||||
|
"@umijs/plugin-blocks": "^2.0.5", |
||||
|
"@umijs/plugin-esbuild": "^1.0.1", |
||||
|
"@umijs/preset-ant-design-pro": "^1.2.0", |
||||
|
"@umijs/preset-react": "^1.4.8", |
||||
|
"@umijs/yorkie": "^2.0.3", |
||||
|
"carlo": "^0.9.46", |
||||
|
"chalk": "^4.0.0", |
||||
|
"cross-env": "^7.0.0", |
||||
|
"cross-port-killer": "^1.1.1", |
||||
|
"detect-installer": "^1.0.1", |
||||
|
"enzyme": "^3.11.0", |
||||
|
"eslint": "^7.1.0", |
||||
|
"express": "^4.17.1", |
||||
|
"gh-pages": "^3.0.0", |
||||
|
"jsdom-global": "^3.0.2", |
||||
|
"lint-staged": "^10.0.0", |
||||
|
"mockjs": "^1.0.1-beta3", |
||||
|
"prettier": "^2.0.1", |
||||
|
"puppeteer-core": "^5.0.0", |
||||
|
"stylelint": "^13.0.0", |
||||
|
"typescript": "^4.0.3", |
||||
|
"uuid": "^8.3.2", |
||||
|
"uuidv4": "^6.2.13" |
||||
|
}, |
||||
|
"engines": { |
||||
|
"node": ">=10.0.0" |
||||
|
}, |
||||
|
"checkFiles": [ |
||||
|
"src/**/*.js*", |
||||
|
"src/**/*.ts*", |
||||
|
"src/**/*.less", |
||||
|
"config/**/*.js*", |
||||
|
"scripts/**/*.js" |
||||
|
] |
||||
|
} |
||||
@ -0,0 +1 @@ |
|||||
|
preview.pro.ant.design |
||||
@ -0,0 +1,7 @@ |
|||||
|
{ |
||||
|
"resCode": 0, |
||||
|
"msg": "成功", |
||||
|
"data": { |
||||
|
"moduleResultCycleCount": 10 |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,5 @@ |
|||||
|
<svg width="42" height="42" xmlns="http://www.w3.org/2000/svg"> |
||||
|
<g> |
||||
|
<path fill="#070707" d="m6.717392,13.773912l5.6,0c2.8,0 4.7,1.9 4.7,4.7c0,2.8 -2,4.7 -4.9,4.7l-2.5,0l0,4.3l-2.9,0l0,-13.7zm2.9,2.2l0,4.9l1.9,0c1.6,0 2.6,-0.9 2.6,-2.4c0,-1.6 -0.9,-2.4 -2.6,-2.4l-1.9,0l0,-0.1zm8.9,11.5l2.7,0l0,-5.7c0,-1.4 0.8,-2.3 2.2,-2.3c0.4,0 0.8,0.1 1,0.2l0,-2.4c-0.2,-0.1 -0.5,-0.1 -0.8,-0.1c-1.2,0 -2.1,0.7 -2.4,2l-0.1,0l0,-1.9l-2.7,0l0,10.2l0.1,0zm11.7,0.1c-3.1,0 -5,-2 -5,-5.3c0,-3.3 2,-5.3 5,-5.3s5,2 5,5.3c0,3.4 -1.9,5.3 -5,5.3zm0,-2.1c1.4,0 2.2,-1.1 2.2,-3.2c0,-2 -0.8,-3.2 -2.2,-3.2c-1.4,0 -2.2,1.2 -2.2,3.2c0,2.1 0.8,3.2 2.2,3.2z" class="st0" id="Ant-Design-Pro"/> |
||||
|
</g> |
||||
|
</svg> |
||||
@ -0,0 +1,58 @@ |
|||||
|
{ |
||||
|
"resCode": 0, |
||||
|
"msg": "成功", |
||||
|
"data": { |
||||
|
"/doingcases": { |
||||
|
"name": "在办事项", |
||||
|
"show": true |
||||
|
}, |
||||
|
"/donecases": { |
||||
|
"name": "已办事项", |
||||
|
"show": true |
||||
|
}, |
||||
|
"/progresssearch": { |
||||
|
"name": "进度查询", |
||||
|
"show": true |
||||
|
}, |
||||
|
"/problemhandlingsearch": { |
||||
|
"name": "问题处理单查询", |
||||
|
"show": false |
||||
|
}, |
||||
|
"/superviseitem": { |
||||
|
"name": "督察专项", |
||||
|
"show": true |
||||
|
}, |
||||
|
"/superviseitem/approve": { |
||||
|
"name": "专项审批", |
||||
|
"show": true |
||||
|
}, |
||||
|
"/superviseitem/check": { |
||||
|
"name": "专项签收", |
||||
|
"show": true |
||||
|
}, |
||||
|
"/modelapprove": { |
||||
|
"name": "模型审批", |
||||
|
"show": true |
||||
|
}, |
||||
|
"/modelapprove/share": { |
||||
|
"name": "模型分享", |
||||
|
"show": true |
||||
|
}, |
||||
|
"/modelapprove/report": { |
||||
|
"name": "省级上报", |
||||
|
"show": true |
||||
|
}, |
||||
|
"/modelapprove/reportshi": { |
||||
|
"name": "市级上报", |
||||
|
"show": true |
||||
|
}, |
||||
|
"/systemmanage": { |
||||
|
"name": "系统配置", |
||||
|
"show": true |
||||
|
}, |
||||
|
"/systemmanage/levelmanage": { |
||||
|
"name": "层级联动", |
||||
|
"show": true |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
{ |
||||
|
"API_URL": "http://localhost:8080/api/v4", |
||||
|
"SYS_MAN_URL": "http://localhost:8080/api", |
||||
|
"LOGIN_URL": "http://localhost:8080", |
||||
|
"PARENT_URL": "http://localhost:8080", |
||||
|
"moduleFactory": "http://localhost:8080/api/v4/sys/self" |
||||
|
} |
||||
@ -0,0 +1 @@ |
|||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200" version="1.1" viewBox="0 0 200 200"><title>Group 28 Copy 5</title><desc>Created with Sketch.</desc><defs><linearGradient id="linearGradient-1" x1="62.102%" x2="108.197%" y1="0%" y2="37.864%"><stop offset="0%" stop-color="#4285EB"/><stop offset="100%" stop-color="#2EC7FF"/></linearGradient><linearGradient id="linearGradient-2" x1="69.644%" x2="54.043%" y1="0%" y2="108.457%"><stop offset="0%" stop-color="#29CDFF"/><stop offset="37.86%" stop-color="#148EFF"/><stop offset="100%" stop-color="#0A60FF"/></linearGradient><linearGradient id="linearGradient-3" x1="69.691%" x2="16.723%" y1="-12.974%" y2="117.391%"><stop offset="0%" stop-color="#FA816E"/><stop offset="41.473%" stop-color="#F74A5C"/><stop offset="100%" stop-color="#F51D2C"/></linearGradient><linearGradient id="linearGradient-4" x1="68.128%" x2="30.44%" y1="-35.691%" y2="114.943%"><stop offset="0%" stop-color="#FA8E7D"/><stop offset="51.264%" stop-color="#F74A5C"/><stop offset="100%" stop-color="#F51D2C"/></linearGradient></defs><g id="Page-1" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="logo" transform="translate(-20.000000, -20.000000)"><g id="Group-28-Copy-5" transform="translate(20.000000, 20.000000)"><g id="Group-27-Copy-3"><g id="Group-25" fill-rule="nonzero"><g id="2"><path id="Shape" fill="url(#linearGradient-1)" d="M91.5880863,4.17652823 L4.17996544,91.5127728 C-0.519240605,96.2081146 -0.519240605,103.791885 4.17996544,108.487227 L91.5880863,195.823472 C96.2872923,200.518814 103.877304,200.518814 108.57651,195.823472 L145.225487,159.204632 C149.433969,154.999611 149.433969,148.181924 145.225487,143.976903 C141.017005,139.771881 134.193707,139.771881 129.985225,143.976903 L102.20193,171.737352 C101.032305,172.906015 99.2571609,172.906015 98.0875359,171.737352 L28.285908,101.993122 C27.1162831,100.824459 27.1162831,99.050775 28.285908,97.8821118 L98.0875359,28.1378823 C99.2571609,26.9692191 101.032305,26.9692191 102.20193,28.1378823 L129.985225,55.8983314 C134.193707,60.1033528 141.017005,60.1033528 145.225487,55.8983314 C149.433969,51.69331 149.433969,44.8756232 145.225487,40.6706018 L108.58055,4.05574592 C103.862049,-0.537986846 96.2692618,-0.500797906 91.5880863,4.17652823 Z"/><path id="Shape" fill="url(#linearGradient-2)" d="M91.5880863,4.17652823 L4.17996544,91.5127728 C-0.519240605,96.2081146 -0.519240605,103.791885 4.17996544,108.487227 L91.5880863,195.823472 C96.2872923,200.518814 103.877304,200.518814 108.57651,195.823472 L145.225487,159.204632 C149.433969,154.999611 149.433969,148.181924 145.225487,143.976903 C141.017005,139.771881 134.193707,139.771881 129.985225,143.976903 L102.20193,171.737352 C101.032305,172.906015 99.2571609,172.906015 98.0875359,171.737352 L28.285908,101.993122 C27.1162831,100.824459 27.1162831,99.050775 28.285908,97.8821118 L98.0875359,28.1378823 C100.999864,25.6271836 105.751642,20.541824 112.729652,19.3524487 C117.915585,18.4685261 123.585219,20.4140239 129.738554,25.1889424 C125.624663,21.0784292 118.571995,14.0340304 108.58055,4.05574592 C103.862049,-0.537986846 96.2692618,-0.500797906 91.5880863,4.17652823 Z"/></g><path id="Shape" fill="url(#linearGradient-3)" d="M153.685633,135.854579 C157.894115,140.0596 164.717412,140.0596 168.925894,135.854579 L195.959977,108.842726 C200.659183,104.147384 200.659183,96.5636133 195.960527,91.8688194 L168.690777,64.7181159 C164.472332,60.5180858 157.646868,60.5241425 153.435895,64.7316526 C149.227413,68.936674 149.227413,75.7543607 153.435895,79.9593821 L171.854035,98.3623765 C173.02366,99.5310396 173.02366,101.304724 171.854035,102.473387 L153.685633,120.626849 C149.47715,124.83187 149.47715,131.649557 153.685633,135.854579 Z"/></g><ellipse id="Combined-Shape" cx="100.519" cy="100.437" fill="url(#linearGradient-4)" rx="23.6" ry="23.581"/></g></g></g></g></svg> |
||||
@ -0,0 +1 @@ |
|||||
|
案件处置 (办结申请) |
||||
@ -0,0 +1,320 @@ |
|||||
|
import React, { useEffect, useState } from 'react'; |
||||
|
import { Card, Input, Select, Form, Button, Radio, Spin, message } from 'antd'; |
||||
|
import { connect } from 'umi'; |
||||
|
|
||||
|
import UploadBtn from '../UploadBtn'; |
||||
|
import SPLS from '../SPLS'; |
||||
|
|
||||
|
import CZMX from '../CZMX'; |
||||
|
import { ALLSPFS, CSQK, UserLevel } from '@/utils/constants'; |
||||
|
import { getDicsName } from '@/utils/utils'; |
||||
|
import styles from './index.less'; |
||||
|
|
||||
|
/** |
||||
|
* 请求数据为空显示保存按钮,可输入 |
||||
|
* 请求数据不为空为编辑按钮,点击后可编辑,可发布 |
||||
|
* 少一个添加处置信息弹窗 |
||||
|
* |
||||
|
* |
||||
|
*/ |
||||
|
|
||||
|
const layout = { |
||||
|
labelCol: { span: 4 }, |
||||
|
wrapperCol: { span: 18 }, |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
const tailLayout = { |
||||
|
wrapperCol: { offset: 10, span: 10 }, |
||||
|
}; |
||||
|
const { Option } = Select; |
||||
|
const { TextArea } = Input; |
||||
|
|
||||
|
const AJBJ = (props) => { |
||||
|
const { id, sysToken, loading, hideModal, fetchDictCZLX, onlyRead, global, user } = props; |
||||
|
const [form] = Form.useForm(); |
||||
|
const [czInfo, setCzInfo] = useState(null); |
||||
|
const [CZLX, setCZLX] = useState([]); |
||||
|
|
||||
|
const [btns, setBtns] = useState(null); // 办结方式权限:上级领导审批,本级领导审批,直接办理 |
||||
|
const [sjldspr, setSjldspr] = useState([]); // 上级领导审批人 |
||||
|
|
||||
|
const getBjldSpr = () => { |
||||
|
props.fetchSprList(); |
||||
|
} |
||||
|
|
||||
|
const getSjldspr = () => { |
||||
|
// 省级服务:在办》部级下发tab下 办结 申请和审批 上级领导审批人列表接口 需要判断当前登陆人是否是省级 省级继续走gatway 市级、县级走不加gatway |
||||
|
if (sysToken === 'bu' ) { |
||||
|
// && (user.departmentOrgLevel === UserLevel.City.value || user.departmentOrgLevel === UserLevel.Town.value) |
||||
|
props.fetchUperSprList({ params: user?.departmentCode ?? '', sysToken: user.departmentOrgLevel === UserLevel.Province.value ? 'bu' :'sheng' }).then(data => { |
||||
|
setSjldspr(data); |
||||
|
}) |
||||
|
} else { |
||||
|
props.fetchUperSprList({ params: user?.departmentCode ?? '', sysToken }).then(data => { |
||||
|
setSjldspr(data); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
const getBtns = () => { |
||||
|
props.fetchBjBtns({ params: id, sysToken }).then(data => { |
||||
|
setBtns(data); |
||||
|
if (data?.bjldsp) getBjldSpr(); |
||||
|
if (data?.sjldsp) getSjldspr(); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
useEffect(() => { |
||||
|
getBtns(); |
||||
|
fetchDictCZLX(sysToken).then((res) => { |
||||
|
if (res && res.resCode === 0) { |
||||
|
setCZLX(res.data); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
if (onlyRead) props.fetchCzInfo({ params: id, sysToken }).then((data) => setCzInfo(data)); |
||||
|
|
||||
|
return () => { |
||||
|
// cleanup |
||||
|
}; |
||||
|
}, []); |
||||
|
|
||||
|
|
||||
|
const saveBj = (params) => { |
||||
|
props.fetchSaveBJSQ({ params, sysToken }).then(data => { |
||||
|
if (data.resCode === 0) { |
||||
|
message.success('操作成功'); |
||||
|
props.hideModal(true); |
||||
|
} else { |
||||
|
message.error(data.resMsg); |
||||
|
} |
||||
|
|
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
const onFinish = (values) => { // 原来的两个tab合成一个 原来是表单两个接口,现在调用两次 |
||||
|
const czParmas = { |
||||
|
pfId: id, |
||||
|
cljg: values.cljg, |
||||
|
ssqk: values.ssqk, |
||||
|
ssqkMc: values.ssqkMc, |
||||
|
}; |
||||
|
const bjParmas = { |
||||
|
pfId: id, |
||||
|
bjyj: values.bjyj, |
||||
|
wj: values.wj, |
||||
|
xjSpr: values.xjSpr, |
||||
|
xjSprMc: values.xjSprMc, |
||||
|
spFs: values.spFs, |
||||
|
}; |
||||
|
|
||||
|
if (values.spFs === ALLSPFS.sjldsp.value) { // 上级领导审批 多带两个参数 |
||||
|
bjParmas.sjDw = values.sjDw; |
||||
|
bjParmas.sjDwMc = values.sjDwMc; |
||||
|
} |
||||
|
|
||||
|
props.fetchSaveCz({ params: czParmas, sysToken }).then((data) => { |
||||
|
if (data.resCode === 0) { |
||||
|
saveBj(bjParmas); |
||||
|
} else { |
||||
|
message.error(data.resMsg); |
||||
|
} |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
const renderBtns = (ops) => { |
||||
|
return Object.keys(ALLSPFS).map(key => { |
||||
|
if (ops?.[key] === true) { |
||||
|
return <Radio key={key} value={ALLSPFS[key].value}>{ALLSPFS[key].name}</Radio> |
||||
|
} |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
return ( |
||||
|
<Card title=""> |
||||
|
<Spin spinning={loading}> |
||||
|
{ |
||||
|
onlyRead ? |
||||
|
<Card> |
||||
|
<Form.Item label="属实情况"> |
||||
|
{getDicsName(CSQK,czInfo?.ssqk)} |
||||
|
</Form.Item> |
||||
|
<Form.Item label="处理意见"> |
||||
|
{czInfo?.cljg} |
||||
|
</Form.Item> |
||||
|
</Card> |
||||
|
: |
||||
|
<Form |
||||
|
{...layout} |
||||
|
name="ajcz" |
||||
|
form={form} |
||||
|
// initialValues={initFormData} |
||||
|
onFinish={onFinish} |
||||
|
> |
||||
|
<Form.Item |
||||
|
label="属实情况" |
||||
|
name="ssqk" |
||||
|
rules={[{ required: true, message: '请选择属实情况!' }]} |
||||
|
> |
||||
|
<Select |
||||
|
// disabled={!editing} |
||||
|
onSelect={(value, item) => { |
||||
|
form.setFieldsValue({ ssqkMc: item.mc }); |
||||
|
}} |
||||
|
> |
||||
|
{Object.keys(CSQK).map((key) => { |
||||
|
return ( |
||||
|
<Option key={key} mc={CSQK[key].name} value={CSQK[key].value}> |
||||
|
{CSQK[key].name} |
||||
|
</Option> |
||||
|
); |
||||
|
})} |
||||
|
</Select> |
||||
|
</Form.Item> |
||||
|
<Form.Item hidden label="属实情况名称" name="ssqkMc"> |
||||
|
<Input /> |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
label="处理意见" |
||||
|
name="cljg" |
||||
|
rules={[{ required: true, message: '请填写处理意见!' }]} |
||||
|
> |
||||
|
<TextArea rows={3} /> |
||||
|
</Form.Item> |
||||
|
<Form.Item label="办结意见" name='bjyj' rules={[{ required: true, message: '请填写办结意见!' }]}> |
||||
|
<TextArea rows={3} /> |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
label="附件" |
||||
|
name="wj" |
||||
|
> |
||||
|
<UploadBtn sysToken={sysToken} onChange={newValues => { |
||||
|
form.setFieldsValue({ wj: newValues }) |
||||
|
}} /> |
||||
|
</Form.Item> |
||||
|
<Form.Item label="办结方式" onChange={() => form.setFieldsValue({ xjSpr: '', xjSprMc: '' })} name='spFs' rules={[{ required: true, message: '请选择办结方式!' }]}> |
||||
|
<Radio.Group> |
||||
|
{renderBtns(btns)} |
||||
|
</Radio.Group> |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
noStyle |
||||
|
shouldUpdate={(prevValues, currentValues) => prevValues.spFs !== currentValues.spFs} |
||||
|
> |
||||
|
{({ getFieldValue }) => { |
||||
|
return getFieldValue('spFs') === ALLSPFS.bjldsp.value ? ( |
||||
|
<> |
||||
|
<Form.Item |
||||
|
label="审批人" |
||||
|
name="xjSpr" |
||||
|
rules={[{ required: true, message: '请选择审批人!' }]} |
||||
|
> |
||||
|
<Select style={{ width: 150 }} onSelect={(value, item) => { form.setFieldsValue({ xjSprMc: item.children }) }}> |
||||
|
{ |
||||
|
global?.sprList.map(item => <Option key={item.id} value={item.logingId}>{`${item.surname}${item.commonName}`}</Option>) |
||||
|
} |
||||
|
</Select> |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
hidden |
||||
|
label="审批人名称" |
||||
|
name="xjSprMc" |
||||
|
> |
||||
|
<Input /> |
||||
|
</Form.Item> |
||||
|
</> |
||||
|
) : null; |
||||
|
}} |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
noStyle |
||||
|
shouldUpdate={(prevValues, currentValues) => prevValues.spFs !== currentValues.spFs} |
||||
|
> |
||||
|
{({ getFieldValue }) => { |
||||
|
return getFieldValue('spFs') === ALLSPFS.sjldsp.value ? ( // 上级领导审批 |
||||
|
<> |
||||
|
<Form.Item |
||||
|
label="审批人" |
||||
|
name="xjSpr" |
||||
|
rules={[{ required: true, message: '请选择审批人!' }]} |
||||
|
> |
||||
|
<Select style={{ width: 150 }} onSelect={(value, item) => { form.setFieldsValue({ ...item.others }) }}> |
||||
|
{ |
||||
|
sjldspr.map(item => <Option key={item.id} value={item.jsr} others={{ xjSprMc: item.jsrMc, sjDw: item.jsdw, sjDwMc: item.jsdwMc }} >{item.jsrMc}</Option>) |
||||
|
} |
||||
|
</Select> |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
hidden |
||||
|
label="审批人名称" |
||||
|
name="xjSprMc" |
||||
|
> |
||||
|
<Input /> |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
hidden |
||||
|
label="接受单位" |
||||
|
name="sjDw" |
||||
|
> |
||||
|
<Input /> |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
hidden |
||||
|
label="接受单位名称" |
||||
|
name="sjDwMc" |
||||
|
> |
||||
|
<Input /> |
||||
|
</Form.Item> |
||||
|
</> |
||||
|
) : null; |
||||
|
}} |
||||
|
</Form.Item> |
||||
|
<Form.Item {...tailLayout}> |
||||
|
<Button onClick={() => props.hideModal(false)} style={{ marginRight: 20 }}>取消</Button> |
||||
|
<Button type="primary" htmlType="submit">保存</Button> |
||||
|
</Form.Item> |
||||
|
</Form> |
||||
|
} |
||||
|
|
||||
|
<CZMX id={id} sysToken={sysToken} CZLX={CZLX} onlyRead={onlyRead} /> |
||||
|
{ onlyRead && <SPLS id={id} sysToken={sysToken} type='bjsp'/>} |
||||
|
</Spin> |
||||
|
</Card> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
const mapStateToProps = ({ user, doing, global, loading }) => ({ |
||||
|
user: user.currentUser, |
||||
|
doing, |
||||
|
global, |
||||
|
loading: |
||||
|
loading.effects['doing/fetchSaveBJSQ'] || |
||||
|
loading.effects['doing/fetchSaveCz'] || |
||||
|
false, |
||||
|
}); |
||||
|
const mapDispatchToProps = (dispatch) => ({ |
||||
|
fetchCzInfo(params) { |
||||
|
return dispatch({ type: 'doing/fetchCzInfo', payload: params }); |
||||
|
}, |
||||
|
fetchSaveCz(params) { |
||||
|
return dispatch({ type: 'doing/fetchSaveCz', payload: params }); |
||||
|
}, |
||||
|
fetchDictCZLX(params) { |
||||
|
return dispatch({ type: 'global/fetchDictCZLX', payload: params }); |
||||
|
}, |
||||
|
fetchBjBtns(params) { |
||||
|
return dispatch({ type: 'doing/fetchBjBtns', payload: params }); |
||||
|
}, |
||||
|
fetchSprList(params) { |
||||
|
return dispatch({ type: 'global/fetchSprList', payload: params }); |
||||
|
}, |
||||
|
fetchUperSprList(params) { |
||||
|
return dispatch({ type: 'doing/fetchUperSprList', payload: params }); |
||||
|
}, |
||||
|
fetchSaveBJSQ(params) { |
||||
|
return dispatch({ type: 'doing/fetchSaveBJSQ', payload: params }); |
||||
|
}, |
||||
|
}); |
||||
|
export default connect(mapStateToProps, mapDispatchToProps)(AJBJ); |
||||
@ -0,0 +1,16 @@ |
|||||
|
.titleAndButton { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
height: 50px; |
||||
|
line-height: 50px; |
||||
|
.title { |
||||
|
color: cornflowerblue; |
||||
|
font-weight: 600; |
||||
|
} |
||||
|
.button { |
||||
|
color: white; |
||||
|
} |
||||
|
} |
||||
|
.submit { |
||||
|
text-align: right; |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
import React from 'react'; |
||||
|
import { Result } from 'antd'; |
||||
|
import check from './CheckPermissions'; |
||||
|
|
||||
|
const Authorized = ({ |
||||
|
children, |
||||
|
authority, |
||||
|
noMatch = ( |
||||
|
<Result |
||||
|
status="403" |
||||
|
title="403" |
||||
|
subTitle="Sorry, you are not authorized to access this page." |
||||
|
/> |
||||
|
), |
||||
|
}) => { |
||||
|
const childrenRender = typeof children === 'undefined' ? null : children; |
||||
|
const dom = check(authority, childrenRender, noMatch); |
||||
|
return <>{dom}</>; |
||||
|
}; |
||||
|
|
||||
|
export default Authorized; |
||||
@ -0,0 +1,25 @@ |
|||||
|
import { Redirect, Route } from 'umi'; |
||||
|
import React from 'react'; |
||||
|
import Authorized from './Authorized'; |
||||
|
|
||||
|
const AuthorizedRoute = ({ component: Component, render, authority, redirectPath, ...rest }) => ( |
||||
|
<Authorized |
||||
|
authority={authority} |
||||
|
noMatch={ |
||||
|
<Route |
||||
|
{...rest} |
||||
|
render={() => ( |
||||
|
<Redirect |
||||
|
to={{ |
||||
|
pathname: redirectPath, |
||||
|
}} |
||||
|
/> |
||||
|
)} |
||||
|
/> |
||||
|
} |
||||
|
> |
||||
|
<Route {...rest} render={props => (Component ? <Component {...props} /> : render(props))} /> |
||||
|
</Authorized> |
||||
|
); |
||||
|
|
||||
|
export default AuthorizedRoute; |
||||
@ -0,0 +1,72 @@ |
|||||
|
import React from 'react'; |
||||
|
import { CURRENT } from './renderAuthorize'; // eslint-disable-next-line import/no-cycle |
||||
|
|
||||
|
import PromiseRender from './PromiseRender'; |
||||
|
|
||||
|
/** |
||||
|
* 通用权限检查方法 Common check permissions method |
||||
|
* |
||||
|
* @param { 权限判定 | Permission judgment } authority |
||||
|
* @param { 你的权限 | Your permission description } currentAuthority |
||||
|
* @param { 通过的组件 | Passing components } target |
||||
|
* @param { 未通过的组件 | no pass components } Exception |
||||
|
*/ |
||||
|
const checkPermissions = (authority, currentAuthority, target, Exception) => { |
||||
|
// 没有判定权限.默认查看所有 |
||||
|
// Retirement authority, return target; |
||||
|
if (!authority) { |
||||
|
return target; |
||||
|
} // 数组处理 |
||||
|
|
||||
|
if (Array.isArray(authority)) { |
||||
|
if (Array.isArray(currentAuthority)) { |
||||
|
if (currentAuthority.some(item => authority.includes(item))) { |
||||
|
return target; |
||||
|
} |
||||
|
} else if (authority.includes(currentAuthority)) { |
||||
|
return target; |
||||
|
} |
||||
|
|
||||
|
return Exception; |
||||
|
} // string 处理 |
||||
|
|
||||
|
if (typeof authority === 'string') { |
||||
|
if (Array.isArray(currentAuthority)) { |
||||
|
if (currentAuthority.some(item => authority === item)) { |
||||
|
return target; |
||||
|
} |
||||
|
} else if (authority === currentAuthority) { |
||||
|
return target; |
||||
|
} |
||||
|
|
||||
|
return Exception; |
||||
|
} // Promise 处理 |
||||
|
|
||||
|
if (authority instanceof Promise) { |
||||
|
return <PromiseRender ok={target} error={Exception} promise={authority} />; |
||||
|
} // Function 处理 |
||||
|
|
||||
|
if (typeof authority === 'function') { |
||||
|
const bool = authority(currentAuthority); // 函数执行后返回值是 Promise |
||||
|
|
||||
|
if (bool instanceof Promise) { |
||||
|
return <PromiseRender ok={target} error={Exception} promise={bool} />; |
||||
|
} |
||||
|
|
||||
|
if (bool) { |
||||
|
return target; |
||||
|
} |
||||
|
|
||||
|
return Exception; |
||||
|
} |
||||
|
|
||||
|
throw new Error('unsupported parameters'); |
||||
|
}; |
||||
|
|
||||
|
export { checkPermissions }; |
||||
|
|
||||
|
function check(authority, target, Exception) { |
||||
|
return checkPermissions(authority, CURRENT, target, Exception); |
||||
|
} |
||||
|
|
||||
|
export default check; |
||||
@ -0,0 +1,78 @@ |
|||||
|
import React from 'react'; |
||||
|
import { Spin } from 'antd'; |
||||
|
import isEqual from 'lodash/isEqual'; |
||||
|
import { isComponentClass } from './Secured'; // eslint-disable-next-line import/no-cycle |
||||
|
|
||||
|
export default class PromiseRender extends React.Component { |
||||
|
state = { |
||||
|
component: () => null, |
||||
|
}; |
||||
|
|
||||
|
componentDidMount() { |
||||
|
this.setRenderComponent(this.props); |
||||
|
} |
||||
|
|
||||
|
shouldComponentUpdate = (nextProps, nextState) => { |
||||
|
const { component } = this.state; |
||||
|
|
||||
|
if (!isEqual(nextProps, this.props)) { |
||||
|
this.setRenderComponent(nextProps); |
||||
|
} |
||||
|
|
||||
|
if (nextState.component !== component) return true; |
||||
|
return false; |
||||
|
}; // set render Component : ok or error |
||||
|
|
||||
|
setRenderComponent(props) { |
||||
|
const ok = this.checkIsInstantiation(props.ok); |
||||
|
const error = this.checkIsInstantiation(props.error); |
||||
|
props.promise |
||||
|
.then(() => { |
||||
|
this.setState({ |
||||
|
component: ok, |
||||
|
}); |
||||
|
return true; |
||||
|
}) |
||||
|
.catch(() => { |
||||
|
this.setState({ |
||||
|
component: error, |
||||
|
}); |
||||
|
}); |
||||
|
} // Determine whether the incoming component has been instantiated |
||||
|
// AuthorizedRoute is already instantiated |
||||
|
// Authorized render is already instantiated, children is no instantiated |
||||
|
// Secured is not instantiated |
||||
|
|
||||
|
checkIsInstantiation = target => { |
||||
|
if (isComponentClass(target)) { |
||||
|
const Target = target; |
||||
|
return props => <Target {...props} />; |
||||
|
} |
||||
|
|
||||
|
if (React.isValidElement(target)) { |
||||
|
return props => React.cloneElement(target, props); |
||||
|
} |
||||
|
|
||||
|
return () => target; |
||||
|
}; |
||||
|
|
||||
|
render() { |
||||
|
const { component: Component } = this.state; |
||||
|
const { ok, error, promise, ...rest } = this.props; |
||||
|
return Component ? ( |
||||
|
<Component {...rest} /> |
||||
|
) : ( |
||||
|
<div |
||||
|
style={{ |
||||
|
width: '100%', |
||||
|
height: '100%', |
||||
|
margin: 'auto', |
||||
|
paddingTop: 50, |
||||
|
textAlign: 'center', |
||||
|
}} |
||||
|
> |
||||
|
<Spin size="large" /> |
||||
|
</div> |
||||
|
); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,61 @@ |
|||||
|
import React from 'react'; |
||||
|
import CheckPermissions from './CheckPermissions'; |
||||
|
/** 默认不能访问任何页面 default is "NULL" */ |
||||
|
|
||||
|
const Exception403 = () => 403; |
||||
|
|
||||
|
export const isComponentClass = component => { |
||||
|
if (!component) return false; |
||||
|
const proto = Object.getPrototypeOf(component); |
||||
|
if (proto === React.Component || proto === Function.prototype) return true; |
||||
|
return isComponentClass(proto); |
||||
|
}; // Determine whether the incoming component has been instantiated |
||||
|
// AuthorizedRoute is already instantiated |
||||
|
// Authorized render is already instantiated, children is no instantiated |
||||
|
// Secured is not instantiated |
||||
|
|
||||
|
const checkIsInstantiation = target => { |
||||
|
if (isComponentClass(target)) { |
||||
|
const Target = target; |
||||
|
return props => <Target {...props} />; |
||||
|
} |
||||
|
|
||||
|
if (React.isValidElement(target)) { |
||||
|
return props => React.cloneElement(target, props); |
||||
|
} |
||||
|
|
||||
|
return () => target; |
||||
|
}; |
||||
|
/** |
||||
|
* 用于判断是否拥有权限访问此 view 权限 authority 支持传入 string, () => boolean | Promise e.g. 'user' 只有 user 用户能访问 |
||||
|
* e.g. 'user,admin' user 和 admin 都能访问 e.g. ()=>boolean 返回true能访问,返回false不能访问 e.g. Promise then 能访问 |
||||
|
* catch不能访问 e.g. authority support incoming string, () => boolean | Promise e.g. 'user' only user |
||||
|
* user can access e.g. 'user, admin' user and admin can access e.g. () => boolean true to be able |
||||
|
* to visit, return false can not be accessed e.g. Promise then can not access the visit to catch |
||||
|
* |
||||
|
* @param {string | function | Promise} authority |
||||
|
* @param {ReactNode} error 非必需参数 |
||||
|
*/ |
||||
|
|
||||
|
const authorize = (authority, error) => { |
||||
|
/** |
||||
|
* Conversion into a class 防止传入字符串时找不到staticContext造成报错 String parameters can cause staticContext |
||||
|
* not found error |
||||
|
*/ |
||||
|
let classError = false; |
||||
|
|
||||
|
if (error) { |
||||
|
classError = () => error; |
||||
|
} |
||||
|
|
||||
|
if (!authority) { |
||||
|
throw new Error('authority is required'); |
||||
|
} |
||||
|
|
||||
|
return function decideAuthority(target) { |
||||
|
const component = CheckPermissions(authority, target, classError || Exception403); |
||||
|
return checkIsInstantiation(component); |
||||
|
}; |
||||
|
}; |
||||
|
|
||||
|
export default authorize; |
||||
@ -0,0 +1,9 @@ |
|||||
|
import Authorized from './Authorized'; |
||||
|
import Secured from './Secured'; |
||||
|
import check from './CheckPermissions'; |
||||
|
import renderAuthorize from './renderAuthorize'; |
||||
|
|
||||
|
Authorized.Secured = Secured; |
||||
|
Authorized.check = check; |
||||
|
const RenderAuthorize = renderAuthorize(Authorized); |
||||
|
export default RenderAuthorize; |
||||
@ -0,0 +1,31 @@ |
|||||
|
/* eslint-disable eslint-comments/disable-enable-pair */ |
||||
|
|
||||
|
/* eslint-disable import/no-mutable-exports */ |
||||
|
let CURRENT = 'NULL'; |
||||
|
|
||||
|
/** |
||||
|
* Use authority or getAuthority |
||||
|
* |
||||
|
* @param {string|()=>String} currentAuthority |
||||
|
*/ |
||||
|
const renderAuthorize = Authorized => currentAuthority => { |
||||
|
if (currentAuthority) { |
||||
|
if (typeof currentAuthority === 'function') { |
||||
|
CURRENT = currentAuthority(); |
||||
|
} |
||||
|
|
||||
|
if ( |
||||
|
Object.prototype.toString.call(currentAuthority) === '[object String]' || |
||||
|
Array.isArray(currentAuthority) |
||||
|
) { |
||||
|
CURRENT = currentAuthority; |
||||
|
} |
||||
|
} else { |
||||
|
CURRENT = 'NULL'; |
||||
|
} |
||||
|
|
||||
|
return Authorized; |
||||
|
}; |
||||
|
|
||||
|
export { CURRENT }; |
||||
|
export default Authorized => renderAuthorize(Authorized); |
||||
@ -0,0 +1,152 @@ |
|||||
|
import React from 'react'; |
||||
|
import { Form, Input, Select, Button, Space, Radio } from 'antd'; |
||||
|
|
||||
|
import UploadBtn from '../UploadBtn'; |
||||
|
import { ALLSPFS } from '@/utils/constants'; |
||||
|
|
||||
|
const { Option } = Select; |
||||
|
|
||||
|
const layout = { |
||||
|
labelCol: { span: 4 }, |
||||
|
wrapperCol: { span: 18 }, |
||||
|
}; |
||||
|
|
||||
|
const tailLayout = { |
||||
|
wrapperCol: { offset: 10, span: 10 }, |
||||
|
}; |
||||
|
|
||||
|
const Agree = (props) => { |
||||
|
const [form] = Form.useForm(); |
||||
|
const { btns, sysToken, sprList, sjldspr } = props; |
||||
|
const onFinish = (values) => { |
||||
|
props.handleSp(values); |
||||
|
} |
||||
|
|
||||
|
const renderBtns = (ops) => { |
||||
|
const all = Object.keys(ALLSPFS).map(key => { |
||||
|
if (ops?.[key] === true) { |
||||
|
return <Radio key={key} value={ALLSPFS[key].value}>{ALLSPFS[key].name}</Radio> |
||||
|
} |
||||
|
}) |
||||
|
return all; |
||||
|
} |
||||
|
|
||||
|
return ( |
||||
|
<div> |
||||
|
<Form |
||||
|
{...layout} |
||||
|
name="bjsp" |
||||
|
form={form} |
||||
|
// initialValues={{ }} |
||||
|
onFinish={onFinish} |
||||
|
> |
||||
|
|
||||
|
<Form.Item |
||||
|
label="领导批示" |
||||
|
name="spyj" |
||||
|
rules={[{ max: 200, message: '最多能输入200字!' }]} |
||||
|
> |
||||
|
<Input.TextArea /> |
||||
|
</Form.Item> |
||||
|
<Form.Item label="办结方式" onChange={() => form.setFieldsValue({ xjSpr: '', xjSprMc: '' })} name='spFs' rules={[{ required: true, message: '请选择办结方式!' }]}> |
||||
|
<Radio.Group> |
||||
|
{renderBtns(btns)} |
||||
|
</Radio.Group> |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
noStyle |
||||
|
shouldUpdate={(prevValues, currentValues) => prevValues.spFs !== currentValues.spFs} |
||||
|
> |
||||
|
{({ getFieldValue }) => { |
||||
|
return getFieldValue('spFs') === ALLSPFS.bjldsp.value ? ( |
||||
|
<> |
||||
|
<Form.Item |
||||
|
label="审批人" |
||||
|
name="xjSpr" |
||||
|
rules={[{ required: true, message: '请选择审批人!' }]} |
||||
|
> |
||||
|
<Select style={{ width: 150 }} onSelect={(value, item) => { form.setFieldsValue({ xjSprMc: item.children }) }}> |
||||
|
{ |
||||
|
sprList.map(item => <Option key={item.id} value={item.logingId}>{`${item.surname}${item.commonName}`}</Option>) |
||||
|
} |
||||
|
</Select> |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
hidden |
||||
|
label="审批人名称" |
||||
|
name="xjSprMc" |
||||
|
> |
||||
|
<Input /> |
||||
|
</Form.Item> |
||||
|
</> |
||||
|
) : null; |
||||
|
}} |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
noStyle |
||||
|
shouldUpdate={(prevValues, currentValues) => prevValues.spFs !== currentValues.spFs} |
||||
|
> |
||||
|
{({ getFieldValue }) => { |
||||
|
return getFieldValue('spFs') === ALLSPFS.sjldsp.value ? ( |
||||
|
<> |
||||
|
<Form.Item |
||||
|
label="审批人" |
||||
|
name="xjSpr" |
||||
|
rules={[{ required: true, message: '请选择审批人!' }]} |
||||
|
> |
||||
|
<Select style={{ width: 150 }} onSelect={(value, item) => { form.setFieldsValue({ ...item.others }) }}> |
||||
|
{ |
||||
|
sjldspr.map(item => <Option key={item.id} value={item.jsr} others={{xjSprMc: item.jsrMc, sjDw: item.jsdw, sjDwMc: item.jsdwMc }} >{item.jsrMc}</Option>) |
||||
|
} |
||||
|
</Select> |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
hidden |
||||
|
label="审批人名称" |
||||
|
name="xjSprMc" |
||||
|
> |
||||
|
<Input /> |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
hidden |
||||
|
label="接受单位" |
||||
|
name="sjDw" |
||||
|
> |
||||
|
<Input /> |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
hidden |
||||
|
label="接受单位名称" |
||||
|
name="sjDwMc" |
||||
|
> |
||||
|
<Input /> |
||||
|
</Form.Item> |
||||
|
</> |
||||
|
) : null; |
||||
|
}} |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
label="办结报告" |
||||
|
name="wj" |
||||
|
> |
||||
|
<UploadBtn sysToken={sysToken} onChange={newValues => { |
||||
|
form.setFieldsValue({ wj: newValues }) |
||||
|
}} /> |
||||
|
</Form.Item> |
||||
|
|
||||
|
<Form.Item {...tailLayout}> |
||||
|
<Space> |
||||
|
<Button type="default" onClick={() => props.hideModal(false)}> |
||||
|
取消 |
||||
|
</Button> |
||||
|
<Button type="primary" htmlType="submit"> |
||||
|
确认 |
||||
|
</Button> |
||||
|
</Space> |
||||
|
</Form.Item> |
||||
|
</Form> |
||||
|
</div> |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
export default Agree; |
||||
@ -0,0 +1,64 @@ |
|||||
|
import React from 'react'; |
||||
|
import { Form, Card, Button } from 'antd'; |
||||
|
|
||||
|
import commonDownLoad from '@/utils/downloadFile'; |
||||
|
import { CSQK } from '@/utils/constants'; |
||||
|
import { getDicsName } from '@/utils/utils'; |
||||
|
|
||||
|
const layout = { |
||||
|
labelCol: { span: 3 }, |
||||
|
wrapperCol: { span: 18 }, |
||||
|
}; |
||||
|
|
||||
|
const { Item } = Form; |
||||
|
|
||||
|
const Info = (props) => { |
||||
|
const { czInfo, spInfo, sysToken } = props; |
||||
|
|
||||
|
if (!spInfo?.ywSj) return ''; |
||||
|
|
||||
|
const { ywSj } = spInfo; |
||||
|
const ywSjIson = JSON.parse(ywSj); |
||||
|
|
||||
|
return ( |
||||
|
<Card title=''> |
||||
|
<div className='itemInfo'> |
||||
|
<Form {...layout}> |
||||
|
<Item label="属实情况"> |
||||
|
{getDicsName(CSQK, czInfo?.ssqk)} |
||||
|
</Item> |
||||
|
<Item label="处理意见"> |
||||
|
{czInfo?.cljg} |
||||
|
</Item> |
||||
|
{ |
||||
|
spInfo?.sfSq === 1 ? // 是否申请 |
||||
|
<Item label="办结意见"> |
||||
|
{ywSjIson?.bjyj} |
||||
|
</Item> |
||||
|
: |
||||
|
<Item label="审批意见"> |
||||
|
{ywSjIson?.spyj} |
||||
|
</Item> |
||||
|
} |
||||
|
<Item label="附件"> |
||||
|
{ywSjIson?.wj?.map(item => { return (<Button key={item.id} onClick={() => commonDownLoad(item, sysToken)} type='link'>{item.wjMc}</Button>) })} |
||||
|
</Item> |
||||
|
<Item label="申请人"> |
||||
|
{spInfo?.clrMc} |
||||
|
</Item> |
||||
|
<Item label="申请时间"> |
||||
|
{spInfo?.clSj} |
||||
|
</Item> |
||||
|
<Item label="申请单位"> |
||||
|
{spInfo?.cldwMc} |
||||
|
</Item> |
||||
|
<Item label="审批人" style={{ borderTop: '1px solid #d9d9d9' }}> |
||||
|
{ywSjIson?.xjSprMc} |
||||
|
</Item> |
||||
|
</Form> |
||||
|
</div> |
||||
|
</Card> |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
export default Info; |
||||
@ -0,0 +1 @@ |
|||||
|
办结审批,添加领导办结审批 |
||||
@ -0,0 +1,64 @@ |
|||||
|
import React from 'react'; |
||||
|
import { Form, Input, Button, Space } from 'antd'; |
||||
|
|
||||
|
import UploadBtn from '../UploadBtn'; |
||||
|
|
||||
|
const layout = { |
||||
|
labelCol: { span: 4 }, |
||||
|
wrapperCol: { span: 18 }, |
||||
|
}; |
||||
|
|
||||
|
const tailLayout = { |
||||
|
wrapperCol: { offset: 10, span: 10 }, |
||||
|
}; |
||||
|
|
||||
|
const Reject = (props) => { |
||||
|
const [form] = Form.useForm(); |
||||
|
const { sysToken } = props; |
||||
|
|
||||
|
const onFinish = (values) => { |
||||
|
props.handleSp({ ...values, spFs: 3 }); |
||||
|
} |
||||
|
|
||||
|
return ( |
||||
|
<div> |
||||
|
<Form |
||||
|
{...layout} |
||||
|
name="bjbh" |
||||
|
form={form} |
||||
|
// initialValues={{ }} |
||||
|
onFinish={onFinish} |
||||
|
> |
||||
|
|
||||
|
<Form.Item |
||||
|
label="驳回原因" |
||||
|
name="slyj" |
||||
|
rules={[{ max: 200, message: '最多能输入200字!' }]} |
||||
|
> |
||||
|
<Input.TextArea /> |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
label="附件" |
||||
|
name="wj" |
||||
|
> |
||||
|
<UploadBtn sysToken={sysToken} onChange={newValues => { |
||||
|
form.setFieldsValue({ wj: newValues }) |
||||
|
}} /> |
||||
|
</Form.Item> |
||||
|
|
||||
|
<Form.Item {...tailLayout}> |
||||
|
<Space> |
||||
|
<Button type="default" onClick={() => props.hideModal(false)}> |
||||
|
取消 |
||||
|
</Button> |
||||
|
<Button type="primary" htmlType="submit"> |
||||
|
确认 |
||||
|
</Button> |
||||
|
</Space> |
||||
|
</Form.Item> |
||||
|
</Form> |
||||
|
</div> |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
export default Reject; |
||||
@ -0,0 +1,166 @@ |
|||||
|
import React, { useEffect, useState } from 'react'; |
||||
|
import { Card, Spin, Radio, Button } from 'antd'; |
||||
|
import { connect } from 'umi'; |
||||
|
|
||||
|
import Info from './Info'; |
||||
|
import CZMX from '../CZMX'; |
||||
|
import Agree from './Agree'; |
||||
|
import Reject from './Reject'; |
||||
|
import { UserLevel } from '@/utils/constants'; |
||||
|
|
||||
|
import styles from './index.less'; |
||||
|
|
||||
|
|
||||
|
const BJSP = (props) => { |
||||
|
const { id, sysToken, loading, global, user, track } = props; |
||||
|
const [agree, setAgree] = useState(true); |
||||
|
const [btns, setBtns] = useState(null); |
||||
|
const [sjldspr, setSjldspr] = useState([]); |
||||
|
const [czInfo, setCzInfo] = useState(null); |
||||
|
const [spInfo, setSpInfo] = useState(null); |
||||
|
const [showCHBtn, setShowCHBtn] = useState(false); |
||||
|
const [CZLX, setCZLX] = useState([]); |
||||
|
const [showSP, setShowSP] = useState(!track); |
||||
|
|
||||
|
const getBjldSpr = () => { // 本级领导审批人 |
||||
|
props.fetchSprList(); |
||||
|
} |
||||
|
|
||||
|
const getSjldspr = () => { // 上级领导审批人 |
||||
|
// 省级服务:在办》部级下发tab下 办结 申请和审批 上级领导审批人列表接口 需要判断当前登陆人是否是省级 省级继续走gatway 市级、县级走不加gatway |
||||
|
if (sysToken === 'bu' ) { |
||||
|
// && (user.departmentOrgLevel === UserLevel.City.value || user.departmentOrgLevel === UserLevel.Town.value) |
||||
|
props.fetchUperSprList({ params: user?.departmentCode ?? '', sysToken: user.departmentOrgLevel === UserLevel.Province.value ? 'bu' :'sheng' }).then(data => { |
||||
|
setSjldspr(data); |
||||
|
}) |
||||
|
} else { |
||||
|
props.fetchUperSprList({ params: user?.departmentCode ?? '', sysToken }).then(data => { |
||||
|
setSjldspr(data); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
const getBtns = () => { // 审批方式获取:本级领导审批 上级领导审批 直接办理 |
||||
|
props.fetchBjBtns({ params: id, sysToken }).then(data => { |
||||
|
setBtns(data); |
||||
|
if (data?.bjldsp) getBjldSpr(); |
||||
|
if (data?.sjldsp) getSjldspr(); |
||||
|
} |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
useEffect(() => { |
||||
|
getBtns(); |
||||
|
props.fetchCzInfo({ params: id, sysToken }).then(data => setCzInfo(data)); // 获取案件处置信息 |
||||
|
props.fetchBJSPInfo({ params: id, sysToken }).then(data => setSpInfo(data)); // 获取最新受理待审批信息, 为了里面的id 审批时当成pfId的参数 |
||||
|
props.fetchDictCZLX(sysToken).then((res) => { |
||||
|
if (res && res.resCode === 0) { |
||||
|
setCZLX(res.data); |
||||
|
} |
||||
|
}); |
||||
|
return () => { |
||||
|
// cleanup |
||||
|
} |
||||
|
}, []); |
||||
|
|
||||
|
useEffect(() => { |
||||
|
if (track && spInfo) { |
||||
|
props.fetchCheckCH({ params: { pfId: id, spId: spInfo.id }, sysToken }).then(res => { |
||||
|
if (res?.data) { |
||||
|
setShowCHBtn(true); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
}, [spInfo]); |
||||
|
|
||||
|
const handleSp = (values) => { // 审批 |
||||
|
const params = { |
||||
|
...values, |
||||
|
pfId: id, |
||||
|
spId: spInfo.id, |
||||
|
}; |
||||
|
props.fetchSaveBJSP({ params, sysToken }).then(data => { |
||||
|
props.hideModal(true); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
const onClickCH = () => { // 撤回 |
||||
|
props.fetchSaveBJCH({ params: { pfId: id, spId: spInfo.id }, sysToken }).then(data => { |
||||
|
props.hideModal(true); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
return ( |
||||
|
<div> |
||||
|
<Info sysToken={sysToken} czInfo={czInfo} spInfo={spInfo} /> |
||||
|
<Spin spinning={loading}> |
||||
|
{track && |
||||
|
<div className={styles.btnCon}> |
||||
|
{showCHBtn && <Button onClick={onClickCH} type='primary'>撤回</Button>} |
||||
|
{/* <Button type='primary'>添加领导意见</Button> */} |
||||
|
</div> |
||||
|
} |
||||
|
{showSP && |
||||
|
<Card title='领导审批'> |
||||
|
<div className={styles.agreeCon}> |
||||
|
<Radio.Group onChange={(e) => setAgree(e.target.value)} value={agree}> |
||||
|
<Radio value={true}>同意</Radio> |
||||
|
<Radio value={false}>驳回</Radio> |
||||
|
</Radio.Group> |
||||
|
</div> |
||||
|
{ |
||||
|
agree ? |
||||
|
<Agree handleSp={handleSp} hideModal={props.hideModal} sysToken={sysToken} btns={btns} sjldspr={sjldspr} sprList={global.sprList} /> |
||||
|
: |
||||
|
<Reject handleSp={handleSp} hideModal={props.hideModal} sysToken={sysToken} /> |
||||
|
} |
||||
|
</Card> |
||||
|
} |
||||
|
<CZMX id={id} sysToken={sysToken} CZLX={CZLX} onlyRead /> |
||||
|
</Spin> |
||||
|
</div> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
const mapStateToProps = ({ user, doing, global, loading }) => ({ |
||||
|
user: user.currentUser, |
||||
|
doing, |
||||
|
global, |
||||
|
loading: |
||||
|
loading.effects['doing/fetchBjBtns'] || |
||||
|
loading.effects['doing/fetchSaveBJSP'] || |
||||
|
loading.effects['doing/fetchSaveBJCH'] || |
||||
|
false, |
||||
|
}); |
||||
|
const mapDispatchToProps = dispatch => ({ |
||||
|
fetchCzInfo(params) { |
||||
|
return dispatch({ type: 'doing/fetchCzInfo', payload: params }); |
||||
|
}, |
||||
|
fetchBjBtns(params) { |
||||
|
return dispatch({ type: 'doing/fetchBjBtns', payload: params }); |
||||
|
}, |
||||
|
fetchSprList(params) { |
||||
|
return dispatch({ type: 'global/fetchSprList', payload: params }); |
||||
|
}, |
||||
|
fetchUperSprList(params) { |
||||
|
return dispatch({ type: 'doing/fetchUperSprList', payload: params }); |
||||
|
}, |
||||
|
fetchSaveBJSP(params) { |
||||
|
return dispatch({ type: 'doing/fetchSaveBJSP', payload: params }); |
||||
|
}, |
||||
|
fetchBJSPInfo(params) { |
||||
|
return dispatch({ type: 'doing/fetchBJSPInfo', payload: params }); |
||||
|
}, |
||||
|
fetchCheckCH(params) { |
||||
|
return dispatch({ type: 'doing/fetchCheckCH', payload: params }); |
||||
|
}, |
||||
|
fetchSaveBJCH(params) { |
||||
|
return dispatch({ type: 'doing/fetchSaveBJCH', payload: params }); |
||||
|
}, |
||||
|
fetchDictCZLX(params) { |
||||
|
return dispatch({ type: 'global/fetchDictCZLX', payload: params }); |
||||
|
}, |
||||
|
}); |
||||
|
export default connect(mapStateToProps, mapDispatchToProps)(BJSP); |
||||
@ -0,0 +1,16 @@ |
|||||
|
.titleAndButton { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
height: 50px; |
||||
|
line-height: 50px; |
||||
|
.title { |
||||
|
color: cornflowerblue; |
||||
|
font-weight: 600; |
||||
|
} |
||||
|
.button { |
||||
|
color: white; |
||||
|
} |
||||
|
} |
||||
|
.submit { |
||||
|
text-align: right; |
||||
|
} |
||||
@ -0,0 +1,152 @@ |
|||||
|
import React from 'react'; |
||||
|
import { Form, Input, Select, Button, Space, Radio } from 'antd'; |
||||
|
|
||||
|
import UploadBtn from '../UploadBtn'; |
||||
|
import { ALLSPFS } from '@/utils/constants'; |
||||
|
|
||||
|
const { Option } = Select; |
||||
|
|
||||
|
const layout = { |
||||
|
labelCol: { span: 4 }, |
||||
|
wrapperCol: { span: 18 }, |
||||
|
}; |
||||
|
|
||||
|
const tailLayout = { |
||||
|
wrapperCol: { offset: 10, span: 10 }, |
||||
|
}; |
||||
|
|
||||
|
const Agree = (props) => { |
||||
|
const [form] = Form.useForm(); |
||||
|
const { btns, sysToken, sprList, sjldspr } = props; |
||||
|
const onFinish = (values) => { |
||||
|
props.handleSp(values); |
||||
|
} |
||||
|
|
||||
|
const renderBtns = (ops) => { |
||||
|
const all = Object.keys(ALLSPFS).map(key => { |
||||
|
if (ops?.[key] === true) { |
||||
|
return <Radio key={key} value={ALLSPFS[key].value}>{ALLSPFS[key].name}</Radio> |
||||
|
} |
||||
|
}) |
||||
|
return all; |
||||
|
} |
||||
|
|
||||
|
return ( |
||||
|
<div> |
||||
|
<Form |
||||
|
{...layout} |
||||
|
name="bjsp" |
||||
|
form={form} |
||||
|
// initialValues={{ }} |
||||
|
onFinish={onFinish} |
||||
|
> |
||||
|
|
||||
|
<Form.Item |
||||
|
label="领导批示" |
||||
|
name="spyj" |
||||
|
rules={[{ max: 200, message: '最多能输入200字!' }]} |
||||
|
> |
||||
|
<Input.TextArea /> |
||||
|
</Form.Item> |
||||
|
<Form.Item label="办结方式" onChange={() => form.setFieldsValue({ xjSpr: '', xjSprMc: '' })} name='spFs' rules={[{ required: true, message: '请选择办结方式!' }]}> |
||||
|
<Radio.Group> |
||||
|
{renderBtns(btns)} |
||||
|
</Radio.Group> |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
noStyle |
||||
|
shouldUpdate={(prevValues, currentValues) => prevValues.spFs !== currentValues.spFs} |
||||
|
> |
||||
|
{({ getFieldValue }) => { |
||||
|
return getFieldValue('spFs') === ALLSPFS.bjldsp.value ? ( |
||||
|
<> |
||||
|
<Form.Item |
||||
|
label="审批人" |
||||
|
name="xjSpr" |
||||
|
rules={[{ required: true, message: '请选择审批人!' }]} |
||||
|
> |
||||
|
<Select style={{ width: 150 }} onSelect={(value, item) => { form.setFieldsValue({ xjSprMc: item.children }) }}> |
||||
|
{ |
||||
|
sprList.map(item => <Option key={item.id} value={item.logingId}>{`${item.surname}${item.commonName}`}</Option>) |
||||
|
} |
||||
|
</Select> |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
hidden |
||||
|
label="审批人名称" |
||||
|
name="xjSprMc" |
||||
|
> |
||||
|
<Input /> |
||||
|
</Form.Item> |
||||
|
</> |
||||
|
) : null; |
||||
|
}} |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
noStyle |
||||
|
shouldUpdate={(prevValues, currentValues) => prevValues.spFs !== currentValues.spFs} |
||||
|
> |
||||
|
{({ getFieldValue }) => { |
||||
|
return getFieldValue('spFs') === ALLSPFS.sjldsp.value ? ( |
||||
|
<> |
||||
|
<Form.Item |
||||
|
label="审批人" |
||||
|
name="xjSpr" |
||||
|
rules={[{ required: true, message: '请选择审批人!' }]} |
||||
|
> |
||||
|
<Select style={{ width: 150 }} onSelect={(value, item) => { form.setFieldsValue({ ...item.others }) }}> |
||||
|
{ |
||||
|
sjldspr.map(item => <Option key={item.id} value={item.jsr} others={{xjSprMc: item.jsrMc, sjDw: item.jsdw, sjDwMc: item.jsdwMc }} >{item.jsrMc}</Option>) |
||||
|
} |
||||
|
</Select> |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
hidden |
||||
|
label="审批人名称" |
||||
|
name="xjSprMc" |
||||
|
> |
||||
|
<Input /> |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
hidden |
||||
|
label="接受单位" |
||||
|
name="sjDw" |
||||
|
> |
||||
|
<Input /> |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
hidden |
||||
|
label="接受单位名称" |
||||
|
name="sjDwMc" |
||||
|
> |
||||
|
<Input /> |
||||
|
</Form.Item> |
||||
|
</> |
||||
|
) : null; |
||||
|
}} |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
label="办结报告" |
||||
|
name="wj" |
||||
|
> |
||||
|
<UploadBtn sysToken={sysToken} onChange={newValues => { |
||||
|
form.setFieldsValue({ wj: newValues }) |
||||
|
}} /> |
||||
|
</Form.Item> |
||||
|
|
||||
|
<Form.Item {...tailLayout}> |
||||
|
<Space> |
||||
|
<Button type="default" onClick={() => props.hideModal(false)}> |
||||
|
取消 |
||||
|
</Button> |
||||
|
<Button type="primary" htmlType="submit"> |
||||
|
确认 |
||||
|
</Button> |
||||
|
</Space> |
||||
|
</Form.Item> |
||||
|
</Form> |
||||
|
</div> |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
export default Agree; |
||||
@ -0,0 +1,64 @@ |
|||||
|
import React from 'react'; |
||||
|
import { Form, Card, Button } from 'antd'; |
||||
|
|
||||
|
import commonDownLoad from '@/utils/downloadFile'; |
||||
|
import { CSQK } from '@/utils/constants'; |
||||
|
import { getDicsName } from '@/utils/utils'; |
||||
|
|
||||
|
const layout = { |
||||
|
labelCol: { span: 3 }, |
||||
|
wrapperCol: { span: 18 }, |
||||
|
}; |
||||
|
|
||||
|
const { Item } = Form; |
||||
|
|
||||
|
const Info = (props) => { |
||||
|
const { czInfo, spInfo, sysToken } = props; |
||||
|
|
||||
|
if (!spInfo?.ywSj) return ''; |
||||
|
|
||||
|
const { ywSj } = spInfo; |
||||
|
const ywSjIson = JSON.parse(ywSj); |
||||
|
|
||||
|
return ( |
||||
|
<Card title=''> |
||||
|
<div className='itemInfo'> |
||||
|
<Form {...layout}> |
||||
|
<Item label="属实情况"> |
||||
|
{getDicsName(CSQK, czInfo?.ssqk)} |
||||
|
</Item> |
||||
|
<Item label="处理意见"> |
||||
|
{czInfo?.cljg} |
||||
|
</Item> |
||||
|
{ |
||||
|
spInfo?.sfSq === 1 ? // 是否申请 |
||||
|
<Item label="办结意见"> |
||||
|
{ywSjIson?.bjyj || czInfo?.bjyj} |
||||
|
</Item> |
||||
|
: |
||||
|
<Item label="审批意见"> |
||||
|
{ywSjIson?.spyj} |
||||
|
</Item> |
||||
|
} |
||||
|
<Item label="附件"> |
||||
|
{ywSjIson?.wj?.map(item => { return (<Button key={item.id} onClick={() => commonDownLoad(item, sysToken)} type='link'>{item.wjMc}</Button>) })} |
||||
|
</Item> |
||||
|
<Item label="申请人"> |
||||
|
{spInfo?.clrMc} |
||||
|
</Item> |
||||
|
<Item label="申请时间"> |
||||
|
{spInfo?.clSj} |
||||
|
</Item> |
||||
|
<Item label="申请单位"> |
||||
|
{spInfo?.cldwMc} |
||||
|
</Item> |
||||
|
<Item label="审批人" style={{ borderTop: '1px solid #d9d9d9' }}> |
||||
|
{ywSjIson?.xjSprMc} |
||||
|
</Item> |
||||
|
</Form> |
||||
|
</div> |
||||
|
</Card> |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
export default Info; |
||||
@ -0,0 +1 @@ |
|||||
|
办结审批,添加领导办结审批 |
||||
@ -0,0 +1,64 @@ |
|||||
|
import React from 'react'; |
||||
|
import { Form, Input, Button, Space } from 'antd'; |
||||
|
|
||||
|
import UploadBtn from '../UploadBtn'; |
||||
|
|
||||
|
const layout = { |
||||
|
labelCol: { span: 4 }, |
||||
|
wrapperCol: { span: 18 }, |
||||
|
}; |
||||
|
|
||||
|
const tailLayout = { |
||||
|
wrapperCol: { offset: 10, span: 10 }, |
||||
|
}; |
||||
|
|
||||
|
const Reject = (props) => { |
||||
|
const [form] = Form.useForm(); |
||||
|
const { sysToken } = props; |
||||
|
|
||||
|
const onFinish = (values) => { |
||||
|
props.handleSp({ ...values, spFs: 3 }); |
||||
|
} |
||||
|
|
||||
|
return ( |
||||
|
<div> |
||||
|
<Form |
||||
|
{...layout} |
||||
|
name="bjbh" |
||||
|
form={form} |
||||
|
// initialValues={{ }} |
||||
|
onFinish={onFinish} |
||||
|
> |
||||
|
|
||||
|
<Form.Item |
||||
|
label="驳回原因" |
||||
|
name="slyj" |
||||
|
rules={[{ max: 200, message: '最多能输入200字!' }]} |
||||
|
> |
||||
|
<Input.TextArea /> |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
label="附件" |
||||
|
name="wj" |
||||
|
> |
||||
|
<UploadBtn sysToken={sysToken} onChange={newValues => { |
||||
|
form.setFieldsValue({ wj: newValues }) |
||||
|
}} /> |
||||
|
</Form.Item> |
||||
|
|
||||
|
<Form.Item {...tailLayout}> |
||||
|
<Space> |
||||
|
<Button type="default" onClick={() => props.hideModal(false)}> |
||||
|
取消 |
||||
|
</Button> |
||||
|
<Button type="primary" htmlType="submit"> |
||||
|
确认 |
||||
|
</Button> |
||||
|
</Space> |
||||
|
</Form.Item> |
||||
|
</Form> |
||||
|
</div> |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
export default Reject; |
||||
@ -0,0 +1,166 @@ |
|||||
|
import React, { useEffect, useState } from 'react'; |
||||
|
import { Card, Spin, Radio, Button } from 'antd'; |
||||
|
import { connect } from 'umi'; |
||||
|
|
||||
|
import Info from './Info'; |
||||
|
import CZMX from '../CZMX'; |
||||
|
import Agree from './Agree'; |
||||
|
import Reject from './Reject'; |
||||
|
import { UserLevel } from '@/utils/constants'; |
||||
|
|
||||
|
import styles from './index.less'; |
||||
|
|
||||
|
|
||||
|
const BJSP = (props) => { |
||||
|
const { id, sysToken, loading, global, user, track } = props; |
||||
|
const [agree, setAgree] = useState(true); |
||||
|
const [btns, setBtns] = useState(null); |
||||
|
const [sjldspr, setSjldspr] = useState([]); |
||||
|
const [czInfo, setCzInfo] = useState(null); |
||||
|
const [spInfo, setSpInfo] = useState(null); |
||||
|
const [showCHBtn, setShowCHBtn] = useState(false); |
||||
|
const [CZLX, setCZLX] = useState([]); |
||||
|
const [showSP, setShowSP] = useState(!track); |
||||
|
|
||||
|
const getBjldSpr = () => { // 本级领导审批人 |
||||
|
props.fetchSprList(); |
||||
|
} |
||||
|
|
||||
|
const getSjldspr = () => { // 上级领导审批人 |
||||
|
// 省级服务:在办》部级下发tab下 办结 申请和审批 上级领导审批人列表接口 需要判断当前登陆人是否是省级 省级继续走gatway 市级、县级走不加gatway |
||||
|
if (sysToken === 'bu') { |
||||
|
// && (user.departmentOrgLevel === UserLevel.City.value || user.departmentOrgLevel === UserLevel.Town.value) |
||||
|
props.fetchUperSprList({ params: user?.departmentCode ?? '', sysToken: user.departmentOrgLevel === UserLevel.Province.value ? 'bu' :'sheng' }).then(data => { |
||||
|
setSjldspr(data); |
||||
|
}) |
||||
|
} else { |
||||
|
props.fetchUperSprList({ params: user?.departmentCode ?? '', sysToken }).then(data => { |
||||
|
setSjldspr(data); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
const getBtns = () => { // 审批方式获取:本级领导审批 上级领导审批 直接办理 |
||||
|
props.fetchBjBtns({ params: id, sysToken }).then(data => { |
||||
|
setBtns(data); |
||||
|
if (data?.bjldsp) getBjldSpr(); |
||||
|
if (data?.sjldsp) getSjldspr(); |
||||
|
} |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
useEffect(() => { |
||||
|
getBtns(); |
||||
|
props.fetchCzInfo({ params: id, sysToken }).then(data => setCzInfo(data)); // 获取案件处置信息 |
||||
|
props.fetchBJSPInfo({ params: id, sysToken }).then(data => setSpInfo(data)); // 获取最新受理待审批信息, 为了里面的id 审批时当成pfId的参数 |
||||
|
props.fetchDictCZLX(sysToken).then((res) => { |
||||
|
if (res && res.resCode === 0) { |
||||
|
setCZLX(res.data); |
||||
|
} |
||||
|
}); |
||||
|
return () => { |
||||
|
// cleanup |
||||
|
} |
||||
|
}, []); |
||||
|
|
||||
|
useEffect(() => { |
||||
|
if (track && spInfo) { |
||||
|
props.fetchCheckCH({ params: { pfId: id, spId: spInfo.id }, sysToken }).then(res => { |
||||
|
if (res?.data) { |
||||
|
setShowCHBtn(true); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
}, [spInfo]); |
||||
|
|
||||
|
const handleSp = (values) => { // 审批 |
||||
|
const params = { |
||||
|
...values, |
||||
|
pfId: id, |
||||
|
spId: spInfo.id, |
||||
|
}; |
||||
|
props.fetchSaveBJSP({ params, sysToken }).then(data => { |
||||
|
props.hideModal(true); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
const onClickCH = () => { // 撤回 |
||||
|
props.fetchSaveBJCH({ params: { pfId: id, spId: spInfo.id }, sysToken }).then(data => { |
||||
|
props.hideModal(true); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
return ( |
||||
|
<div> |
||||
|
<Info sysToken={sysToken} czInfo={czInfo} spInfo={spInfo} /> |
||||
|
<Spin spinning={loading}> |
||||
|
{track && |
||||
|
<div className={styles.btnCon}> |
||||
|
{showCHBtn && <Button onClick={onClickCH} type='primary'>撤回</Button>} |
||||
|
{/* <Button type='primary'>添加领导意见</Button> */} |
||||
|
</div> |
||||
|
} |
||||
|
{showSP && |
||||
|
<Card title='领导审批'> |
||||
|
<div className={styles.agreeCon}> |
||||
|
<Radio.Group onChange={(e) => setAgree(e.target.value)} value={agree}> |
||||
|
<Radio value={true}>同意</Radio> |
||||
|
<Radio value={false}>驳回</Radio> |
||||
|
</Radio.Group> |
||||
|
</div> |
||||
|
{ |
||||
|
agree ? |
||||
|
<Agree handleSp={handleSp} hideModal={props.hideModal} sysToken={sysToken} btns={btns} sjldspr={sjldspr} sprList={global.sprList} /> |
||||
|
: |
||||
|
<Reject handleSp={handleSp} hideModal={props.hideModal} sysToken={sysToken} /> |
||||
|
} |
||||
|
</Card> |
||||
|
} |
||||
|
<CZMX id={id} sysToken={sysToken} CZLX={CZLX} onlyRead /> |
||||
|
</Spin> |
||||
|
</div> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
const mapStateToProps = ({ user, doing, global, loading }) => ({ |
||||
|
user: user.currentUser, |
||||
|
doing, |
||||
|
global, |
||||
|
loading: |
||||
|
loading.effects['doing/fetchBjBtns'] || |
||||
|
loading.effects['doing/fetchSaveBJSP'] || |
||||
|
loading.effects['doing/fetchSaveBJCH'] || |
||||
|
false, |
||||
|
}); |
||||
|
const mapDispatchToProps = dispatch => ({ |
||||
|
fetchCzInfo(params) { |
||||
|
return dispatch({ type: 'doing/fetchCzInfo', payload: params }); |
||||
|
}, |
||||
|
fetchBjBtns(params) { |
||||
|
return dispatch({ type: 'doing/fetchBjBtns', payload: params }); |
||||
|
}, |
||||
|
fetchSprList(params) { |
||||
|
return dispatch({ type: 'global/fetchSprList', payload: params }); |
||||
|
}, |
||||
|
fetchUperSprList(params) { |
||||
|
return dispatch({ type: 'doing/fetchUperSprList', payload: params }); |
||||
|
}, |
||||
|
fetchSaveBJSP(params) { |
||||
|
return dispatch({ type: 'doing/fetchSaveBJSP', payload: params }); |
||||
|
}, |
||||
|
fetchBJSPInfo(params) { |
||||
|
return dispatch({ type: 'doing/fetchBJSPInfo', payload: params }); |
||||
|
}, |
||||
|
fetchCheckCH(params) { |
||||
|
return dispatch({ type: 'doing/fetchCheckCH', payload: params }); |
||||
|
}, |
||||
|
fetchSaveBJCH(params) { |
||||
|
return dispatch({ type: 'doing/fetchSaveBJCH', payload: params }); |
||||
|
}, |
||||
|
fetchDictCZLX(params) { |
||||
|
return dispatch({ type: 'global/fetchDictCZLX', payload: params }); |
||||
|
}, |
||||
|
}); |
||||
|
export default connect(mapStateToProps, mapDispatchToProps)(BJSP); |
||||
@ -0,0 +1,16 @@ |
|||||
|
.titleAndButton { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
height: 50px; |
||||
|
line-height: 50px; |
||||
|
.title { |
||||
|
color: cornflowerblue; |
||||
|
font-weight: 600; |
||||
|
} |
||||
|
.button { |
||||
|
color: white; |
||||
|
} |
||||
|
} |
||||
|
.submit { |
||||
|
text-align: right; |
||||
|
} |
||||
@ -0,0 +1 @@ |
|||||
|
抽查按钮 |
||||
@ -0,0 +1,109 @@ |
|||||
|
import React, { useEffect, useState } from 'react'; |
||||
|
import { Input, Radio, Form, Button, Spin, Modal, Space } from 'antd'; |
||||
|
import { connect } from 'umi'; |
||||
|
|
||||
|
import { CCQK } from '@/utils/constants'; |
||||
|
|
||||
|
/** |
||||
|
* |
||||
|
* |
||||
|
* |
||||
|
*/ |
||||
|
const { Item } = Form; |
||||
|
const { TextArea } = Input; |
||||
|
|
||||
|
const layout = { |
||||
|
labelCol: { span: 4 }, |
||||
|
wrapperCol: { span: 18 }, |
||||
|
}; |
||||
|
const tailLayout = { |
||||
|
wrapperCol: { offset: 10, span: 10 }, |
||||
|
}; |
||||
|
|
||||
|
const CC = (props) => { |
||||
|
const { id, sysToken, loading } = props; |
||||
|
const [form] = Form.useForm(); |
||||
|
const [visible, setVisible] = useState(false); |
||||
|
|
||||
|
|
||||
|
|
||||
|
useEffect(() => { |
||||
|
|
||||
|
return () => { |
||||
|
// cleanup |
||||
|
}; |
||||
|
}, []); |
||||
|
|
||||
|
const onClose = () => { |
||||
|
form.resetFields(); |
||||
|
setVisible(false); |
||||
|
} |
||||
|
|
||||
|
const onFinish = (values) => { |
||||
|
const params = { ...values, pfId: id }; |
||||
|
props.fetchSaveCC({ params, sysToken }).then((data) => { |
||||
|
if (data) { |
||||
|
onClose(); |
||||
|
props.hideModal(true); |
||||
|
} |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
|
||||
|
return ( |
||||
|
<div title=""> |
||||
|
<Spin spinning={loading}> |
||||
|
<div style={{textAlign: 'right', marginBottom: 20 }}><Button type='primary' onClick={() => setVisible(true)}>抽查</Button></div> |
||||
|
<Modal |
||||
|
title='抽查情况' |
||||
|
onCancel={onClose} |
||||
|
visible={visible} |
||||
|
footer={null} |
||||
|
width={640} |
||||
|
maskClosable={false} |
||||
|
> |
||||
|
<Form onFinish={onFinish} {...layout}> |
||||
|
{/* <Item label='抽查时间' name='ccSj' rules={[{ required: true, message: '请选择抽查时间!' }]}> |
||||
|
<DatePicker format='YYYY-MM-DD HH:mm:ss' /> |
||||
|
</Item> */} |
||||
|
<Item label='抽查结果' name='ccjg' rules={[{ required: true, message: '请选择抽查结果!' }]}> |
||||
|
<Radio.Group> |
||||
|
{Object.keys(CCQK).map(key => { |
||||
|
if (key !== 'WCC') { // 抽查不显示‘未抽查’选项 |
||||
|
return <Radio key={key} value={CCQK[key].value}>{CCQK[key].name}</Radio> |
||||
|
} |
||||
|
})} |
||||
|
</Radio.Group> |
||||
|
</Item> |
||||
|
<Item label='备注' name='bzxx' rules={[{ max: 200, message: '最多能输入200字!' }]}> |
||||
|
<TextArea /> |
||||
|
</Item> |
||||
|
<Form.Item {...tailLayout}> |
||||
|
<Space> |
||||
|
<Button type="default" onClick={onClose}> |
||||
|
取消 |
||||
|
</Button> |
||||
|
<Button type="primary" htmlType="submit"> |
||||
|
确认 |
||||
|
</Button> |
||||
|
</Space> |
||||
|
</Form.Item> |
||||
|
</Form> |
||||
|
</Modal> |
||||
|
</Spin> |
||||
|
</div> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
const mapStateToProps = ({ doing, global, loading }) => ({ |
||||
|
doing, |
||||
|
global, |
||||
|
loading: loading.effects['doing/fetchSaveCC'] || false, |
||||
|
}); |
||||
|
const mapDispatchToProps = (dispatch) => ({ |
||||
|
fetchSaveCC(params) { |
||||
|
return dispatch({ type: 'doing/fetchSaveCC', payload: params }); |
||||
|
}, |
||||
|
}); |
||||
|
export default connect(mapStateToProps, mapDispatchToProps)(CC); |
||||
@ -0,0 +1 @@ |
|||||
|
抽查结果 |
||||
@ -0,0 +1,73 @@ |
|||||
|
import React, { useEffect, useState } from 'react'; |
||||
|
import { Table, Card } from 'antd'; |
||||
|
import { connect } from 'umi'; |
||||
|
|
||||
|
import { CCQK } from '@/utils/constants'; |
||||
|
import { getDicsName } from '@/utils/utils'; |
||||
|
/** |
||||
|
* |
||||
|
* |
||||
|
* |
||||
|
*/ |
||||
|
|
||||
|
const columns = [ |
||||
|
{ |
||||
|
title: '抽查时间', |
||||
|
dataIndex: 'ccSj', |
||||
|
}, |
||||
|
{ |
||||
|
title: '抽查人', |
||||
|
dataIndex: 'ccrMc', |
||||
|
}, |
||||
|
{ |
||||
|
title: '抽查结果', |
||||
|
dataIndex: 'ccjg', |
||||
|
key: 'id', |
||||
|
render: (text) => getDicsName(CCQK, text), |
||||
|
}, |
||||
|
{ |
||||
|
title: '备注信息', |
||||
|
dataIndex: 'bzxx', |
||||
|
}, |
||||
|
] |
||||
|
|
||||
|
const CCJG = (props) => { |
||||
|
const { id, sysToken } = props; |
||||
|
const [ccjg, setCcjg] = useState(null); |
||||
|
|
||||
|
const getCcjg = () => { |
||||
|
props.fetchCcjg({ id, sysToken }).then((data) => { |
||||
|
if (data) { |
||||
|
setCcjg(data); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
useEffect(() => { |
||||
|
getCcjg(); |
||||
|
return () => { |
||||
|
// cleanup |
||||
|
}; |
||||
|
}, []); |
||||
|
|
||||
|
if (!ccjg) return ''; |
||||
|
|
||||
|
return ( |
||||
|
<Card title="抽查"> |
||||
|
<Table |
||||
|
columns={columns} |
||||
|
dataSource={ccjg} |
||||
|
/> |
||||
|
</Card> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
const mapStateToProps = ({ doing, }) => ({ |
||||
|
doing, |
||||
|
}); |
||||
|
const mapDispatchToProps = (dispatch) => ({ |
||||
|
fetchCcjg(params) { |
||||
|
return dispatch({ type: 'doing/fetchCcjg', payload: params }); |
||||
|
}, |
||||
|
}); |
||||
|
export default connect(mapStateToProps, mapDispatchToProps)(CCJG); |
||||
@ -0,0 +1 @@ |
|||||
|
被驳回重新派发 或者派发失败重新派发 或者是 受理派发 |
||||
@ -0,0 +1,437 @@ |
|||||
|
import React, { useEffect, useState } from 'react'; |
||||
|
import moment from 'moment'; |
||||
|
import { Form, Input, Button, Card, Select, Radio, DatePicker, Row, Col, Space, Spin, message } from 'antd'; |
||||
|
import { connect } from 'umi'; |
||||
|
|
||||
|
import UploadBtn from '../UploadBtn'; |
||||
|
import NextOrg from '../NextOrg'; |
||||
|
|
||||
|
import { YJLX, BLFS, SPFS, UserLevel } from '@/utils/constants'; |
||||
|
import { getDicsName } from '@/utils/utils'; |
||||
|
import { truncate } from 'lodash'; |
||||
|
|
||||
|
const { Option } = Select; |
||||
|
|
||||
|
const layout1 = { |
||||
|
labelCol: { span: 12 }, |
||||
|
wrapperCol: { span: 12 }, |
||||
|
}; |
||||
|
|
||||
|
const layout2 = { |
||||
|
labelCol: { span: 5 }, |
||||
|
wrapperCol: { span: 19 }, |
||||
|
}; |
||||
|
|
||||
|
const layout = { |
||||
|
labelCol: { span: 3 }, |
||||
|
wrapperCol: { span: 20 }, |
||||
|
}; |
||||
|
|
||||
|
const layoutSPFS = { // 审批方式layout |
||||
|
labelCol: { span: 6 }, |
||||
|
wrapperCol: { span: 17 }, |
||||
|
}; |
||||
|
|
||||
|
const tailLayout = { |
||||
|
wrapperCol: { offset: 10, span: 10 }, |
||||
|
}; |
||||
|
|
||||
|
const initFormData = { blfs: YJLX.XJBL.value, nbfs: BLFS.DB.value, spFs: SPFS.LDSP.value, wj: [] }; |
||||
|
|
||||
|
|
||||
|
// 如果是初次受理 给案件流向默认 下级级办理 - 默认的下级单位 转办 直接办理 |
||||
|
// 办理方式 如果有受理和身份可以直接办理 办理方式默认直接办理 如果只是受理人 默认领导审批 |
||||
|
// 如果上级是拟办方式是督办,下级也必需是督办 |
||||
|
// 当这个人只是受理人时受理方式必须是领导审批 |
||||
|
// 如果是个审批人 办理方式肯定是领导审批 必定会有领导审批展示 要给领导赋默认值 |
||||
|
// 如果当前投诉的是公安部 选择本级办理,办理级别bljb一定是本级办理 |
||||
|
// 如果当前人是区级人员, 没有下级办理,办理级别bljb一定是本级办理, |
||||
|
|
||||
|
const PF = (props) => { |
||||
|
const { global, id, sysToken, loading, user } = props; |
||||
|
const [form] = Form.useForm(); |
||||
|
const [newestInfo, setNewestInfo] = useState(null); |
||||
|
const [toDays, setToDays] = useState(''); |
||||
|
|
||||
|
const changeData = s => { |
||||
|
let days = ''; |
||||
|
if (s) { |
||||
|
days = moment(moment(s).format('YYYY-MM-DD')).diff(moment().format('YYYY-MM-DD'), 'day'); |
||||
|
} |
||||
|
setToDays(days); |
||||
|
} |
||||
|
|
||||
|
const setDefaultForm = (data) => { |
||||
|
// sjPfdwzxSl 上级受理信息 null 初次受理 |
||||
|
// sfSsf 是否双身法 1:双身份 受理人 审批人 |
||||
|
const defaultForm = { |
||||
|
blfs: data.blfs, |
||||
|
blfsMc: data.blfsMc, |
||||
|
nbfs: data.nbfs, |
||||
|
zcfkSj: moment(data.zcfkSj), |
||||
|
slyj: data.slyj, |
||||
|
wj: data.wj || [], |
||||
|
wtjs: data.wtjs, |
||||
|
} |
||||
|
changeData(data.zcfkSj) |
||||
|
// 如果当前人是区级人员, 没有下级办理,办理级别bljb一定是本级办理, |
||||
|
if (user.departmentOrgLevel === UserLevel.Town.value) { |
||||
|
defaultForm.blfs = YJLX.BJBL.value; |
||||
|
defaultForm.blfsMc = YJLX.BJBL.name; |
||||
|
defaultForm.slyj = YJLX.BJBL.name; |
||||
|
} |
||||
|
|
||||
|
// defaultForm.slyj = `${defaultForm.blfsMc}-${getDicsName(BLFS, defaultForm.nbfs)}`; |
||||
|
form.setFieldsValue({ ...defaultForm }); |
||||
|
} |
||||
|
|
||||
|
useEffect(() => { |
||||
|
props.fetchSprList && props.fetchSprList(); |
||||
|
props.fetchCbrList && props.fetchCbrList(); |
||||
|
props.fetchNewest({ params: id, sysToken }).then(data => { |
||||
|
if (data.sfSsf === 1) form.setFieldsValue({ spFs: SPFS.ZJBL.value }); |
||||
|
// debugger; |
||||
|
setNewestInfo(data); |
||||
|
if (data.sjPfdwzxSl) { |
||||
|
setDefaultForm(data.sjPfdwzxSl) |
||||
|
} else if (user.departmentOrgLevel === UserLevel.Town.value) { // 如果没有值还是区级 |
||||
|
const defaultForm = {}; |
||||
|
defaultForm.blfs = YJLX.BJBL.value; |
||||
|
defaultForm.blfsMc = YJLX.BJBL.name; |
||||
|
defaultForm.slyj = YJLX.BJBL.name; |
||||
|
form.setFieldsValue({ ...defaultForm }); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
); |
||||
|
|
||||
|
return () => { |
||||
|
// cleanup |
||||
|
} |
||||
|
}, []); |
||||
|
|
||||
|
const onFinish = (values) => { |
||||
|
const params = { |
||||
|
...values, |
||||
|
blfsMc: getDicsName(YJLX, values.blfs), |
||||
|
zcfkSj: `${moment(values.zcfkSj).format('YYYY-MM-DD')} 23:59:59`, |
||||
|
pfId: id, |
||||
|
}; |
||||
|
|
||||
|
props.fetchSavePF({ params, sysToken }).then((data) => { |
||||
|
if (data?.resCode === 0) { |
||||
|
message.success('操作成功'); |
||||
|
props.hideModal(true); |
||||
|
} |
||||
|
|
||||
|
}) |
||||
|
|
||||
|
|
||||
|
}; |
||||
|
|
||||
|
const onFinishFailed = (errorInfo) => { |
||||
|
console.log('Failed:', errorInfo); |
||||
|
}; |
||||
|
|
||||
|
const onChangeBLFS = (e) => { |
||||
|
const text = `${YJLX.XJBL.name}-${getDicsName(BLFS, e.target.value)}`; |
||||
|
form.setFieldsValue({ slyj: text }) |
||||
|
} |
||||
|
|
||||
|
const changeYJLX = (v, item) => { |
||||
|
const text = v === YJLX.BJBL.value ? item.children : `${YJLX.XJBL.name}-${getDicsName(BLFS, form.getFieldValue('nbfs'))}`; |
||||
|
form.setFieldsValue({ slyj: text }); |
||||
|
} |
||||
|
|
||||
|
const onChangeOrg = params => { |
||||
|
const { bm, mc } = params; |
||||
|
form.setFieldsValue({ xjdwBm: bm, xjdwMc: mc }); |
||||
|
} |
||||
|
|
||||
|
const renderDw = () => { |
||||
|
return ( |
||||
|
<Col span={9} key='dbcbr'> |
||||
|
<Form.Item label="接收单位" name='xjdwBm' rules={[{ required: true, message: '请选择下级单位!' }]} {...layout2}> |
||||
|
{/* 办理方式是督办 */} |
||||
|
<NextOrg noLoad onChange={onChangeOrg} /> |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
hidden |
||||
|
label="下级单位名称" |
||||
|
name="xjdwMc" |
||||
|
> |
||||
|
<Input /> |
||||
|
</Form.Item> |
||||
|
</Col> |
||||
|
); |
||||
|
// if (blfs === BLFS.DB.value) { |
||||
|
// return (<Col span={9} key='dbcbr'> |
||||
|
// <Form.Item label="接收单位" name='xjdwBm' rules={[{ required: true, message: '请选择下级单位!' }]} {...layout2}> |
||||
|
// {/* 办理方式是督办 */} |
||||
|
// <NextOrg noLoad onChange={onChangeOrg} /> |
||||
|
// </Form.Item> |
||||
|
// <Form.Item |
||||
|
// hidden |
||||
|
// label="下级单位名称" |
||||
|
// name="xjdwMc" |
||||
|
// > |
||||
|
// <Input /> |
||||
|
// </Form.Item> |
||||
|
// </Col>) |
||||
|
// } |
||||
|
// if (blfs === BLFS.ZB.value) { |
||||
|
// return ( |
||||
|
// <Col span={9} key='zbcbr'> |
||||
|
// <Form.Item label="接收单位" name='xjdwBm' rules={[{ required: true, message: '请选择下级单位!' }]} {...layout2}> |
||||
|
// {/* 办理方式是转办 */} |
||||
|
// <NextOrg onChange={onChangeOrg} /> |
||||
|
// </Form.Item> |
||||
|
// <Form.Item |
||||
|
// hidden |
||||
|
// label="下级单位名称" |
||||
|
// name="xjdwMc" |
||||
|
// > |
||||
|
// <Input /> |
||||
|
// </Form.Item> |
||||
|
// </Col> |
||||
|
// ) |
||||
|
// } |
||||
|
} |
||||
|
|
||||
|
const disabledDate = (current) => { |
||||
|
// console.log(newestInfo) |
||||
|
// console.log(current) |
||||
|
return current ? (current < moment(moment().add(-1, 'days')).endOf('days')) || current.isAfter(moment(Date.now()).add(29, 'days')) : false; |
||||
|
} |
||||
|
|
||||
|
return ( |
||||
|
<div> |
||||
|
<Spin spinning={loading}> |
||||
|
<Card title='派发'> |
||||
|
<Form |
||||
|
{...layout} |
||||
|
name="cxpf" |
||||
|
form={form} |
||||
|
initialValues={initFormData} |
||||
|
onFinish={onFinish} |
||||
|
onFinishFailed={onFinishFailed} |
||||
|
> |
||||
|
<Row> |
||||
|
<Col span={6}> |
||||
|
<Form.Item |
||||
|
label="预警流向" |
||||
|
{...layout1} |
||||
|
name="blfs" |
||||
|
rules={[{ required: true, message: '请选择预警流向!' }]} |
||||
|
> |
||||
|
<Select style={{ width: 120 }} onChange={changeYJLX} disabled={user.departmentOrgLevel === UserLevel.Town.value}> |
||||
|
{Object.keys(YJLX).map(key => { |
||||
|
return <Option key={key} value={YJLX[key].value}>{YJLX[key].name}</Option> |
||||
|
})} |
||||
|
</Select> |
||||
|
</Form.Item> |
||||
|
</Col> |
||||
|
|
||||
|
<Form.Item |
||||
|
noStyle |
||||
|
shouldUpdate={(prevValues, currentValues) => prevValues.blfs !== currentValues.blfs} |
||||
|
> |
||||
|
{({ getFieldValue }) => { |
||||
|
return getFieldValue('blfs') === YJLX.XJBL.value ? ( |
||||
|
<> |
||||
|
<Col span={8}> |
||||
|
<Form.Item |
||||
|
label="办理方式" |
||||
|
{...layout2} |
||||
|
name="nbfs" |
||||
|
> |
||||
|
<Radio.Group onChange={onChangeBLFS} disabled={newestInfo?.sjPfdwzxSl?.nbfs === BLFS.DB.value}> |
||||
|
{Object.keys(BLFS).map(key => { |
||||
|
return <Radio key={key} value={BLFS[key].value}>{BLFS[key].name}</Radio> |
||||
|
})} |
||||
|
</Radio.Group> |
||||
|
</Form.Item> |
||||
|
</Col> |
||||
|
|
||||
|
<Form.Item |
||||
|
noStyle |
||||
|
shouldUpdate={(prevValues, currentValues) => (prevValues.nbfs !== currentValues.nbfs) || (prevValues.blfs !== currentValues.blfs) || (prevValues.xjdwBm !== currentValues.xjdwBm)} |
||||
|
> |
||||
|
{() => { |
||||
|
// return renderDw(getFieldValue('nbfs')) |
||||
|
return renderDw(); |
||||
|
}} |
||||
|
</Form.Item> |
||||
|
</> |
||||
|
) : ''; |
||||
|
}} |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
noStyle |
||||
|
shouldUpdate={(prevValues, currentValues) => (prevValues.blfs !== currentValues.blfs) || (prevValues.spFs !== currentValues.spFs)} |
||||
|
> |
||||
|
{({ getFieldValue }) => { |
||||
|
return getFieldValue('blfs') === YJLX.BJBL.value && getFieldValue('spFs') === SPFS.ZJBL.value ? |
||||
|
<Col span={8}> |
||||
|
<Form.Item |
||||
|
{...layout2} |
||||
|
label="承办人" |
||||
|
name="cbr" |
||||
|
rules={[{ required: true, message: '请选择承办人' }]} |
||||
|
> |
||||
|
<Select onSelect={(value, item) => { form.setFieldsValue({ cbrMc: item.children }) }}> |
||||
|
{ |
||||
|
global?.cbrList.map(item => <Option key={item.id} value={item.logingId}>{`${item.surname}${item.commonName}`}</Option>) |
||||
|
} |
||||
|
</Select> |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
hidden |
||||
|
label="承办人名称" |
||||
|
name="cbrMc" |
||||
|
> |
||||
|
<Input /> |
||||
|
</Form.Item> |
||||
|
</Col> |
||||
|
: |
||||
|
'' |
||||
|
}} |
||||
|
</Form.Item> |
||||
|
</Row> |
||||
|
<Form.Item |
||||
|
label="受理意见" |
||||
|
name="slyj" |
||||
|
rules={[{ max: 200, message: '最多能输入200字!' }]} |
||||
|
> |
||||
|
<Input.TextArea /> |
||||
|
</Form.Item> |
||||
|
|
||||
|
<Row> |
||||
|
<Col span={6}> |
||||
|
<Form.Item |
||||
|
{...layout1} |
||||
|
label="反馈期限" |
||||
|
name="zcfkSj" |
||||
|
rules={[{ required: true, message: '请选择反馈期限!' }]} |
||||
|
> |
||||
|
<DatePicker disabledDate={disabledDate} onChange={(m, s) => changeData(s)} /> |
||||
|
</Form.Item> |
||||
|
</Col> |
||||
|
{toDays !== '' ? <span style={{ marginLeft: 20, marginTop: 4 }}>距今<span style={{ margin: 6 }}>{toDays}</span>天</span> : ''} |
||||
|
</Row> |
||||
|
|
||||
|
<Form.Item |
||||
|
label="附件" |
||||
|
name="wj" |
||||
|
> |
||||
|
<UploadBtn defList={newestInfo?.sjPfdwzxSl?.wj} sysToken={sysToken} onChange={newValues => { |
||||
|
form.setFieldsValue({ wj: newValues }) |
||||
|
}} /> |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
label="问题简述" |
||||
|
name="wtjs" |
||||
|
rules={[{ max: 200, message: '最多能输入200字!' }]} |
||||
|
> |
||||
|
<Input.TextArea /> |
||||
|
</Form.Item> |
||||
|
|
||||
|
<Row style={{ borderTop: '1px solid #d9d9d9', paddingTop: 6 }}> |
||||
|
{/* <Col span={2}> <span >下一步</span></Col> */} |
||||
|
<Col span={12}> |
||||
|
<Form.Item |
||||
|
{...layoutSPFS} |
||||
|
label='审批方式' |
||||
|
// colon={false} |
||||
|
name="spFs" |
||||
|
rules={[{ required: true, message: '请选择审批方式!' }]} |
||||
|
> |
||||
|
<Radio.Group disabled={newestInfo?.sfSsf === 0}> |
||||
|
{Object.keys(SPFS).map(key => { |
||||
|
return <Radio key={key} value={SPFS[key].value}>{SPFS[key].name}</Radio> |
||||
|
})} |
||||
|
</Radio.Group> |
||||
|
</Form.Item> |
||||
|
</Col> |
||||
|
<Col span={12}> |
||||
|
<Form.Item |
||||
|
noStyle |
||||
|
shouldUpdate={(prevValues, currentValues) => prevValues.spFs !== currentValues.spFs} |
||||
|
> |
||||
|
{({ getFieldValue }) => { |
||||
|
return getFieldValue('spFs') === SPFS.LDSP.value ? ( |
||||
|
<div> |
||||
|
<Form.Item |
||||
|
{...layoutSPFS} |
||||
|
label="审批人" |
||||
|
name="xjSpr" |
||||
|
rules={[{ required: true, message: '请选择审批人!' }]} |
||||
|
> |
||||
|
<Select onSelect={(value, item) => { form.setFieldsValue({ xjSprMc: item.children }) }}> |
||||
|
{ |
||||
|
global?.sprList.map(item => <Option key={item.id} value={item.logingId}>{`${item.surname}${item.commonName}`}</Option>) |
||||
|
} |
||||
|
</Select> |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
hidden |
||||
|
label="审批人名称" |
||||
|
name="xjSprMc" |
||||
|
> |
||||
|
<Input /> |
||||
|
</Form.Item> |
||||
|
</div> |
||||
|
) : null; |
||||
|
}} |
||||
|
</Form.Item> |
||||
|
</Col> |
||||
|
</Row> |
||||
|
|
||||
|
<Form.Item {...tailLayout}> |
||||
|
<Space> |
||||
|
<Button type="default" onClick={() => props.hideModal(null)}> |
||||
|
取消 |
||||
|
</Button> |
||||
|
<Button type="primary" htmlType="submit"> |
||||
|
确认 |
||||
|
</Button> |
||||
|
</Space> |
||||
|
</Form.Item> |
||||
|
</Form> |
||||
|
</Card> |
||||
|
</Spin> |
||||
|
</div> |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
const mapStateToProps = ({ user, doing, global, loading }) => ({ |
||||
|
user: user.currentUser, |
||||
|
doing, |
||||
|
global, |
||||
|
loading: |
||||
|
loading.effects['doing/fetchNewest'] || |
||||
|
loading.effects['doing/fetchSpInfo'] || |
||||
|
loading.effects['doing/fetchSavePF'] || |
||||
|
false, |
||||
|
}); |
||||
|
|
||||
|
const mapDispatchToProps = dispatch => ({ |
||||
|
// 查询审批人列表 |
||||
|
fetchSprList(params) { |
||||
|
return dispatch({ type: 'global/fetchSprList', payload: { ...params } }); |
||||
|
}, |
||||
|
fetchCbrList(params) { |
||||
|
return dispatch({ type: 'global/fetchCbrList', payload: { ...params } }); |
||||
|
}, |
||||
|
fetchSavePF(params) { |
||||
|
return dispatch({ type: 'doing/fetchSavePF', payload: { ...params } }); |
||||
|
}, |
||||
|
// 获取当前案件的最新受理信息 |
||||
|
fetchNewest(params) { |
||||
|
return dispatch({ type: 'doing/fetchNewest', payload: params }); |
||||
|
}, |
||||
|
fetchSpInfo(params) { |
||||
|
return dispatch({ type: 'doing/fetchSpInfo', payload: params }); |
||||
|
}, |
||||
|
}); |
||||
|
export default connect(mapStateToProps, mapDispatchToProps)(PF); |
||||
@ -0,0 +1,73 @@ |
|||||
|
import React, { useEffect, useState } from 'react'; |
||||
|
import { Modal, Table, Input, Button, Pagination } from 'antd'; |
||||
|
const { Search } = Input; |
||||
|
const TableSelect = (props) => { |
||||
|
const { getList, visible, handleClose, handleSetOrg } = props; |
||||
|
const [searchParams, setSearchParams] = useState({ page: 1, limit: 10, name: '' }); |
||||
|
const [tableData, setTableData] = useState(); |
||||
|
const columns = [ |
||||
|
{ |
||||
|
dataIndex: 'name', |
||||
|
key: 'name', |
||||
|
title: '单位名称', |
||||
|
width: '80%', |
||||
|
}, |
||||
|
{ |
||||
|
key: 'action', |
||||
|
title: '操作', |
||||
|
render: (text) => { |
||||
|
return ( |
||||
|
<Button type="link" onClick={() => handleSelect(text)}> |
||||
|
选择 |
||||
|
</Button> |
||||
|
); |
||||
|
}, |
||||
|
}, |
||||
|
]; |
||||
|
const handleGetList = (params) => { |
||||
|
getList(params).then((res) => { |
||||
|
setTableData(res); |
||||
|
}); |
||||
|
}; |
||||
|
const onSearch = (value) => { |
||||
|
setSearchParams({ page: 1, limit: 10, name: value }); |
||||
|
}; |
||||
|
const onChange = (page, limit) => { |
||||
|
setSearchParams({ ...searchParams, page, limit }); |
||||
|
}; |
||||
|
const handleSelect = (org) => { |
||||
|
handleSetOrg(org.name); |
||||
|
}; |
||||
|
useEffect(() => { |
||||
|
handleGetList(searchParams); |
||||
|
}, [searchParams]); |
||||
|
return ( |
||||
|
<Modal width={620} visible={visible} onCancel={handleClose} title="选择单位" footer={false}> |
||||
|
<Search |
||||
|
placeholder="请输入单位名称关键词" |
||||
|
allowClear |
||||
|
enterButton |
||||
|
onSearch={onSearch} |
||||
|
style={{ marginBottom: 10 }} |
||||
|
/> |
||||
|
<Table |
||||
|
columns={columns} |
||||
|
dataSource={tableData?.records || []} |
||||
|
rowKey={(record) => record.id} |
||||
|
size="small" |
||||
|
pagination={false} |
||||
|
/> |
||||
|
<Pagination |
||||
|
size="small" |
||||
|
current={tableData?.current || 1} |
||||
|
pageSize={tableData?.size || 0} |
||||
|
total={tableData?.total || 0} |
||||
|
showQuickJumper |
||||
|
showLessItems |
||||
|
onChange={onChange} |
||||
|
/> |
||||
|
</Modal> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
export default TableSelect; |
||||
@ -0,0 +1,332 @@ |
|||||
|
import React, { useEffect, useState } from 'react'; |
||||
|
import { Modal, Button, Input, Form, Select, message, Radio, TreeSelect } from 'antd'; |
||||
|
import UploadBtn from '@/components/UploadBtn'; |
||||
|
import { CzqkList, IdCardReg } from '@/utils/constants'; |
||||
|
import TableSelect from './TableSelect'; |
||||
|
|
||||
|
/** |
||||
|
* visible:弹窗状态 |
||||
|
* handleClose:弹窗开关 |
||||
|
*/ |
||||
|
|
||||
|
const layout = { |
||||
|
labelCol: { span: 5 }, |
||||
|
wrapperCol: { span: 17 }, |
||||
|
}; |
||||
|
|
||||
|
const { TextArea } = Input; |
||||
|
|
||||
|
const FormModal = (props) => { |
||||
|
const { |
||||
|
id, |
||||
|
sysToken, |
||||
|
visible, |
||||
|
handleClose, |
||||
|
getTable, |
||||
|
fetchAddAJCZ, |
||||
|
fetchOrgTreeData, |
||||
|
fetchOrgDataByName, |
||||
|
CZLXList, |
||||
|
loading, |
||||
|
} = props; |
||||
|
const [form] = Form.useForm(); |
||||
|
const [nowRadio, setNowRadio] = useState(); |
||||
|
const [treeData, setTreeData] = useState(); |
||||
|
const [value, setValue] = useState(undefined); |
||||
|
const [tableVisible, setTableVisible] = useState(false); |
||||
|
|
||||
|
// 关闭模态框,清空表单数据 |
||||
|
const handleCloseModal = () => { |
||||
|
handleClose(); |
||||
|
form.resetFields(); |
||||
|
}; |
||||
|
|
||||
|
// 提交 |
||||
|
const onFinish = (values) => { |
||||
|
const params = { |
||||
|
...values, |
||||
|
pfId: id, |
||||
|
}; |
||||
|
console.log('params', params); |
||||
|
fetchAddAJCZ({ params, sysToken }).then((res) => { |
||||
|
if (res && res.resCode === 0) { |
||||
|
// message.success(res.resMsg); |
||||
|
getTable(); |
||||
|
handleCloseModal(); |
||||
|
} else { |
||||
|
message.error(res.resMsg); |
||||
|
} |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
// 处理节点 |
||||
|
const handleMakePoint = (list) => { |
||||
|
const arr = list?.map((item) => { |
||||
|
return { |
||||
|
...item, |
||||
|
pId: item?.upGovId, |
||||
|
title: item.name, |
||||
|
key: item.name, |
||||
|
value: item.name, |
||||
|
isLeaf: false, |
||||
|
}; |
||||
|
}); |
||||
|
return arr; |
||||
|
}; |
||||
|
|
||||
|
// 修改为叶子节点 |
||||
|
const handleToIsLeaf = (id, tree) => { |
||||
|
if (id) { |
||||
|
return tree?.map((i) => { |
||||
|
const item = { |
||||
|
...i, |
||||
|
}; |
||||
|
if (i.id === id) { |
||||
|
item.isLeaf = true; |
||||
|
item.children = []; |
||||
|
} else if (i.children) { |
||||
|
item.children = handleMakeTree(id, i.children); |
||||
|
} |
||||
|
return item; |
||||
|
}); |
||||
|
} else { |
||||
|
return tree; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
// 获取树数据 |
||||
|
const handleGetTree = (id = undefined) => { |
||||
|
fetchOrgTreeData({ id }).then((res) => { |
||||
|
if (res) setTreeData(handleMakePoint(res)); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
// 处理树结构 |
||||
|
const handleMakeTree = (list, tree) => { |
||||
|
if (list && list.length) { |
||||
|
return tree?.map((i) => { |
||||
|
const item = { |
||||
|
...i, |
||||
|
}; |
||||
|
if (i.id === list[0].pId) { |
||||
|
item.children = list; |
||||
|
} else if (i.children) { |
||||
|
item.children = handleMakeTree(list, i.children); |
||||
|
} |
||||
|
return item; |
||||
|
}); |
||||
|
} else { |
||||
|
return tree; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
// 加载树节点 |
||||
|
const onLoadData = (treeNode) => { |
||||
|
return new Promise((resolve) => { |
||||
|
const { id } = treeNode.props; |
||||
|
fetchOrgTreeData({ id }).then((res) => { |
||||
|
if (res && res.length) { |
||||
|
// 插入到对应children |
||||
|
const newRes = handleMakePoint(res); |
||||
|
setTreeData(handleMakeTree(newRes, treeData)); |
||||
|
resolve(); |
||||
|
} else { |
||||
|
// 设置当前节点为叶子节点 |
||||
|
setTreeData(handleToIsLeaf(id, treeData)); |
||||
|
resolve(); |
||||
|
} |
||||
|
}); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
const onChange = (value) => { |
||||
|
setValue(value); |
||||
|
}; |
||||
|
|
||||
|
const handleSetOrg = (value) => { |
||||
|
form.setFieldsValue({ |
||||
|
czDw: value, |
||||
|
}); |
||||
|
setTableVisible(false); |
||||
|
}; |
||||
|
|
||||
|
const handleSearchOrgListByName = (params) => { |
||||
|
fetchOrgDataByName(params).then((res) => { |
||||
|
setNameList(handleMakePoint(res?.records)); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
// 初始化,radio赋值 |
||||
|
useEffect(() => { |
||||
|
form.setFieldsValue({ |
||||
|
czqk: '0', |
||||
|
}); |
||||
|
setNowRadio('0'); |
||||
|
handleGetTree(); |
||||
|
}, []); |
||||
|
|
||||
|
return ( |
||||
|
<div> |
||||
|
<Modal title="添加" visible={visible} width={600} closable={false} footer={false}> |
||||
|
<Form form={form} {...layout} name="form" onFinish={onFinish}> |
||||
|
<Form.Item |
||||
|
label="处置情况" |
||||
|
name="czqk" |
||||
|
rules={[{ required: true, message: '请选择处置情况' }]} |
||||
|
> |
||||
|
<Radio.Group |
||||
|
onChange={(e) => { |
||||
|
setNowRadio(e.target.value); |
||||
|
}} |
||||
|
> |
||||
|
{CzqkList.map((i) => ( |
||||
|
<Radio value={i.value} key={i.value}> |
||||
|
{i.text} |
||||
|
</Radio> |
||||
|
))} |
||||
|
</Radio.Group> |
||||
|
</Form.Item> |
||||
|
{nowRadio !== '0' ? ( |
||||
|
<Form.Item |
||||
|
label="情况说明" |
||||
|
name="qksm" |
||||
|
rules={[ |
||||
|
{ required: true, message: '请输入情况说明' }, |
||||
|
{ max: 1000, message: '请输入不超过1000个字符' }, |
||||
|
]} |
||||
|
> |
||||
|
<TextArea rows={4} /> |
||||
|
</Form.Item> |
||||
|
) : ( |
||||
|
'' |
||||
|
)} |
||||
|
{nowRadio === '0' ? ( |
||||
|
<Form.Item |
||||
|
label="处置类型" |
||||
|
name="czlx" |
||||
|
rules={[{ required: true, message: '请选择处置类型' }]} |
||||
|
> |
||||
|
<Select> |
||||
|
{CZLXList?.map((item) => { |
||||
|
return ( |
||||
|
<Select.Option value={item.id} key={item.id}> |
||||
|
{item.mc} |
||||
|
</Select.Option> |
||||
|
); |
||||
|
})} |
||||
|
</Select> |
||||
|
</Form.Item> |
||||
|
) : ( |
||||
|
'' |
||||
|
)} |
||||
|
{nowRadio === '0' ? ( |
||||
|
<Form.Item |
||||
|
label="姓名" |
||||
|
name="czMc" |
||||
|
rules={[ |
||||
|
{ required: true, message: '请输入姓名' }, |
||||
|
{ max: 128, message: '请输入不超过128个字符' }, |
||||
|
]} |
||||
|
> |
||||
|
<Input /> |
||||
|
</Form.Item> |
||||
|
) : ( |
||||
|
'' |
||||
|
)} |
||||
|
{nowRadio === '0' ? ( |
||||
|
<Form.Item |
||||
|
label="身份证号" |
||||
|
name="czSfz" |
||||
|
rules={[ |
||||
|
{ required: true, message: '请输入身份证号' }, |
||||
|
{ pattern: IdCardReg, message: '请输入身份证号'} |
||||
|
]} |
||||
|
> |
||||
|
<Input /> |
||||
|
</Form.Item> |
||||
|
) : ( |
||||
|
'' |
||||
|
)} |
||||
|
{nowRadio === '0' ? ( |
||||
|
<Form.Item |
||||
|
label="警号" |
||||
|
name="czJh" |
||||
|
rules={[ |
||||
|
{ required: true, message: '请输入警号' }, |
||||
|
{ max: 32, message: '请输入不超过32个字符' }, |
||||
|
]} |
||||
|
> |
||||
|
<Input /> |
||||
|
</Form.Item> |
||||
|
) : ( |
||||
|
'' |
||||
|
)} |
||||
|
{nowRadio === '0' ? ( |
||||
|
<div id="czdw"> |
||||
|
<Form.Item |
||||
|
label="单位" |
||||
|
name="czDw" |
||||
|
rules={[{ required: true, message: '请选择单位' }]} |
||||
|
extra={ |
||||
|
<a |
||||
|
onClick={() => { |
||||
|
setTableVisible(true); |
||||
|
console.log('aaa'); |
||||
|
}} |
||||
|
> |
||||
|
点击搜索单位 |
||||
|
</a> |
||||
|
} |
||||
|
> |
||||
|
<TreeSelect |
||||
|
getPopupContainer={() => document.getElementById('czdw')} |
||||
|
treeDataSimpleMode |
||||
|
style={{ width: '100%' }} |
||||
|
value={value} |
||||
|
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }} |
||||
|
onChange={(e) => onChange(e)} |
||||
|
loadData={onLoadData} |
||||
|
treeData={treeData} |
||||
|
/> |
||||
|
</Form.Item> |
||||
|
</div> |
||||
|
) : ( |
||||
|
'' |
||||
|
)} |
||||
|
|
||||
|
<Form.Item |
||||
|
label="附件" |
||||
|
name="files" |
||||
|
rules={[{ required: nowRadio === '0', message: '请选择附件' }]} |
||||
|
> |
||||
|
<UploadBtn |
||||
|
sysToken={sysToken} |
||||
|
onChange={(newValues) => { |
||||
|
form.setFieldsValue({ files: newValues }); |
||||
|
}} |
||||
|
/> |
||||
|
</Form.Item> |
||||
|
<Form.Item> |
||||
|
<div style={{ width: 520, textAlign: 'right', marginTop: 20 }}> |
||||
|
<Button type="primary" htmlType="submit" loading={loading}> |
||||
|
确认 |
||||
|
</Button> |
||||
|
|
||||
|
<Button onClick={handleCloseModal}>取消</Button> |
||||
|
</div> |
||||
|
</Form.Item> |
||||
|
</Form> |
||||
|
</Modal> |
||||
|
{tableVisible && ( |
||||
|
<TableSelect |
||||
|
visible={tableVisible} |
||||
|
getList={fetchOrgDataByName} |
||||
|
handleClose={() => setTableVisible(false)} |
||||
|
handleSetOrg={handleSetOrg} |
||||
|
/> |
||||
|
)} |
||||
|
</div> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
export default FormModal; |
||||
@ -0,0 +1 @@ |
|||||
|
案件处置--处置明细 |
||||
@ -0,0 +1,226 @@ |
|||||
|
import React, { useState, useEffect } from 'react'; |
||||
|
import { connect } from 'umi'; |
||||
|
import { Button, Table, Popconfirm, message } from 'antd'; |
||||
|
import { CzqkList } from '@/utils/constants'; |
||||
|
import FormModal from './FormModal'; |
||||
|
import styles from './index.less'; |
||||
|
|
||||
|
const CZBtn = (props) => { |
||||
|
const { |
||||
|
id, |
||||
|
sysToken, |
||||
|
fetchAJCZtable, |
||||
|
fetchAddAJCZ, |
||||
|
fetchDeleteAJCZ, |
||||
|
fetchDownloadFile, |
||||
|
fetchOrgTreeData, |
||||
|
fetchOrgDataByName, |
||||
|
CZLX, |
||||
|
onlyRead, |
||||
|
loading, |
||||
|
} = props; |
||||
|
const [visible, setVisible] = useState(false); |
||||
|
const [tableData, setTableData] = useState([]); |
||||
|
// const [CZLX, setCZLX] = useState([]); |
||||
|
const handleOpenModal = () => { |
||||
|
// fetchDictCZLX(sysToken).then((res) => { |
||||
|
// if (res && res.resCode === 0) { |
||||
|
// setCZLX(res.data); |
||||
|
// setVisible(true); |
||||
|
// } |
||||
|
// }); |
||||
|
setVisible(true); |
||||
|
}; |
||||
|
const handleCloseModal = () => { |
||||
|
setVisible(false); |
||||
|
}; |
||||
|
const handleGetTable = () => { |
||||
|
fetchAJCZtable({ id, sysToken }).then((res) => { |
||||
|
setTableData(res); |
||||
|
}); |
||||
|
}; |
||||
|
const handleDelete = (id) => { |
||||
|
fetchDeleteAJCZ({ id, sysToken }).then((res) => { |
||||
|
if (res && res.resCode === 0) { |
||||
|
message.success(res.resMsg); |
||||
|
handleGetTable(); |
||||
|
} else { |
||||
|
message.error(res.resMsg); |
||||
|
} |
||||
|
}); |
||||
|
}; |
||||
|
useEffect(() => { |
||||
|
handleGetTable(); |
||||
|
// fetchCzlx(); |
||||
|
}, []); |
||||
|
|
||||
|
// 下载文件 |
||||
|
const handleDownload = (file) => { |
||||
|
const params = { |
||||
|
mc: file.wjMc, |
||||
|
path: file.wjPath, |
||||
|
url: file.wjUrl, |
||||
|
}; |
||||
|
fetchDownloadFile({ params, sysToken }); |
||||
|
}; |
||||
|
|
||||
|
const getCZLXMc = (text) => { |
||||
|
const p = []; |
||||
|
CZLX?.forEach((item) => { |
||||
|
if (item.id === Number(text)) { |
||||
|
p.push(item.mc); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
return p[0]; |
||||
|
}; |
||||
|
const columns = [ |
||||
|
{ |
||||
|
title: '处置类型', |
||||
|
dataIndex: 'czlx', |
||||
|
key: '', |
||||
|
render: (text) => { |
||||
|
return <span>{getCZLXMc(text)}</span>; |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: '处置情况', |
||||
|
dataIndex: 'czqk', |
||||
|
width: '10%', |
||||
|
render: (text) => CzqkList.filter((i) => i.value === String(text))[0]?.text, |
||||
|
}, |
||||
|
{ |
||||
|
title: '情况说明', |
||||
|
dataIndex: 'qksm', |
||||
|
width: '15%', |
||||
|
}, |
||||
|
{ |
||||
|
title: '姓名', |
||||
|
dataIndex: 'czMc', |
||||
|
key: 'czMc', |
||||
|
}, |
||||
|
{ |
||||
|
title: '身份证号', |
||||
|
dataIndex: 'czSfz', |
||||
|
key: 'czSfz', |
||||
|
}, |
||||
|
{ |
||||
|
title: '警号', |
||||
|
dataIndex: 'czJh', |
||||
|
key: 'czJh', |
||||
|
}, |
||||
|
{ |
||||
|
title: '单位', |
||||
|
dataIndex: 'czDw', |
||||
|
key: 'czDw', |
||||
|
}, |
||||
|
{ |
||||
|
title: '法律文书', |
||||
|
dataIndex: 'flwsMc', |
||||
|
key: 'flwsMc', |
||||
|
render: (text, record) => { |
||||
|
return record?.wjList?.map((file, index) => { |
||||
|
return ( |
||||
|
<a key={file.id} onClick={() => handleDownload(file)}> |
||||
|
{file.wjMc} |
||||
|
{index === record?.wjList?.length - 1 ? '' : ';'} |
||||
|
</a> |
||||
|
); |
||||
|
}); |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: '操作', |
||||
|
key: 'action', |
||||
|
render: (text, record) => { |
||||
|
if (onlyRead) { |
||||
|
return ( |
||||
|
<a type="text" disabled={onlyRead}> |
||||
|
删除 |
||||
|
</a> |
||||
|
); |
||||
|
} else { |
||||
|
return ( |
||||
|
<Popconfirm |
||||
|
placement="left" |
||||
|
title="确定删除吗?" |
||||
|
onConfirm={() => handleDelete(record.id)} |
||||
|
okText="确定" |
||||
|
cancelText="取消" |
||||
|
> |
||||
|
<a type="text" disabled={onlyRead}> |
||||
|
删除 |
||||
|
</a> |
||||
|
</Popconfirm> |
||||
|
); |
||||
|
} |
||||
|
}, |
||||
|
}, |
||||
|
]; |
||||
|
return ( |
||||
|
<div> |
||||
|
<div className={styles.titleAndButton}> |
||||
|
<div className={styles.title}>处置明细</div> |
||||
|
{!onlyRead && ( |
||||
|
<div className={styles.button}> |
||||
|
<Button onClick={handleOpenModal} type="primary" disabled={onlyRead} loading={loading}> |
||||
|
添加处置信息 |
||||
|
</Button> |
||||
|
</div> |
||||
|
)} |
||||
|
</div> |
||||
|
<div> |
||||
|
<Table |
||||
|
rowKey="id" |
||||
|
columns={columns} |
||||
|
dataSource={tableData || []} |
||||
|
pagination={false} |
||||
|
scroll={{ x: 1400 }} |
||||
|
/> |
||||
|
</div> |
||||
|
{visible && ( |
||||
|
<FormModal |
||||
|
id={id} |
||||
|
sysToken={sysToken} |
||||
|
visible={visible} |
||||
|
CZLXList={CZLX} |
||||
|
handleClose={handleCloseModal} |
||||
|
getTable={handleGetTable} |
||||
|
fetchAddAJCZ={fetchAddAJCZ} |
||||
|
fetchOrgTreeData={fetchOrgTreeData} |
||||
|
fetchOrgDataByName={fetchOrgDataByName} |
||||
|
loading={loading} |
||||
|
/> |
||||
|
)} |
||||
|
</div> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
const mapStateToProps = ({ doing, global, loading }) => ({ |
||||
|
...doing, |
||||
|
...global, |
||||
|
loading: loading.effects['doing/fetchAddAJCZ'] || false, |
||||
|
}); |
||||
|
|
||||
|
const mapDispatchToProps = (dispatch) => ({ |
||||
|
fetchAJCZtable(params) { |
||||
|
return dispatch({ type: 'doing/fetchAJCZtable', payload: { ...params } }); |
||||
|
}, |
||||
|
fetchAddAJCZ(params) { |
||||
|
return dispatch({ type: 'doing/fetchAddAJCZ', payload: { ...params } }); |
||||
|
}, |
||||
|
fetchDeleteAJCZ(params) { |
||||
|
return dispatch({ type: 'doing/fetchDeleteAJCZ', payload: { ...params } }); |
||||
|
}, |
||||
|
fetchDownloadFile(params) { |
||||
|
return dispatch({ type: 'doing/fetchDownloadFile', payload: { ...params } }); |
||||
|
}, |
||||
|
fetchOrgTreeData(params) { |
||||
|
return dispatch({ type: 'global/fetchOrgTreeData', payload: { ...params } }); |
||||
|
}, |
||||
|
fetchOrgDataByName(params) { |
||||
|
return dispatch({ type: 'global/fetchOrgDataByName', payload: { ...params } }); |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
export default connect(mapStateToProps, mapDispatchToProps)(CZBtn); |
||||
@ -0,0 +1,16 @@ |
|||||
|
.titleAndButton { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
height: 50px; |
||||
|
line-height: 50px; |
||||
|
.title { |
||||
|
color: cornflowerblue; |
||||
|
font-weight: 600; |
||||
|
} |
||||
|
.button { |
||||
|
color: white; |
||||
|
} |
||||
|
} |
||||
|
.submit { |
||||
|
text-align: right; |
||||
|
} |
||||
@ -0,0 +1,109 @@ |
|||||
|
import React, { useState } from 'react'; |
||||
|
import moment from 'moment'; |
||||
|
import { connect } from 'umi'; |
||||
|
import { Row, Col, Button, message } from 'antd'; |
||||
|
import FormModal from '@/components/FormModal'; |
||||
|
import styles from './index.less'; |
||||
|
import commonDownLoad from '@/utils/downloadFile'; |
||||
|
|
||||
|
const CardList = (props) => { |
||||
|
const { |
||||
|
sysToken, |
||||
|
sourceType, |
||||
|
dataSource, |
||||
|
fetchDeleteHCZJ, |
||||
|
getTable, |
||||
|
fetchEditHCZJ, |
||||
|
onlyRead, |
||||
|
} = props; |
||||
|
const [visible, setVisible] = useState(false); |
||||
|
const [record, setRecord] = useState(); |
||||
|
const handleDelete = (id) => { |
||||
|
fetchDeleteHCZJ({ id, sysToken }).then((res) => { |
||||
|
if (res && res.resCode === 0) { |
||||
|
message.success(res.resMsg); |
||||
|
getTable(); |
||||
|
} else { |
||||
|
message.error(res.resMsg); |
||||
|
} |
||||
|
}); |
||||
|
}; |
||||
|
const handleOpenModal = (item) => { |
||||
|
setRecord(item); |
||||
|
setVisible(true); |
||||
|
}; |
||||
|
const handleCloseModal = () => { |
||||
|
setVisible(false); |
||||
|
setRecord(); |
||||
|
}; |
||||
|
const renderList = (arr) => { |
||||
|
return arr?.map((item) => { |
||||
|
return ( |
||||
|
<div className={styles.card} key={item.id}> |
||||
|
<Row gutter={[0, 16]}> |
||||
|
<Col span={3} align="right"> |
||||
|
{sourceType === 'bg' ? '报告信息:' : '证据信息:'} |
||||
|
</Col> |
||||
|
<Col span={21}>{sourceType === 'bg' ? item.bgXx : item.zjXx}</Col> |
||||
|
<Col span={3} align="right"> |
||||
|
文件: |
||||
|
</Col> |
||||
|
<Col span={21}> |
||||
|
{item?.wjList?.map((i, index) => { |
||||
|
return ( |
||||
|
<a key={index} onClick={() => commonDownLoad(i, sysToken)}> |
||||
|
{i.wjMc} |
||||
|
{index === item?.wjList?.length - 1 ? '' : ';'} |
||||
|
</a> |
||||
|
); |
||||
|
})} |
||||
|
</Col> |
||||
|
<Col span={3} align="right"> |
||||
|
补充时间: |
||||
|
</Col> |
||||
|
<Col span={5}> |
||||
|
<span>{moment(item.bcSj).format('YYYY-MM-DD HH:mm:ss')}</span> |
||||
|
</Col> |
||||
|
<Col span={3} align="right"> |
||||
|
补充人: |
||||
|
</Col> |
||||
|
<Col span={5}>{item.bcrMc}</Col> |
||||
|
<Col span={3} align="right"> |
||||
|
补充单位: |
||||
|
</Col> |
||||
|
<Col span={5}>{item.bcdwMc}</Col> |
||||
|
{ |
||||
|
!onlyRead && |
||||
|
<Col> |
||||
|
<Button size='small' type="primary" onClick={() => handleOpenModal(item)} disabled={onlyRead}> |
||||
|
编辑 |
||||
|
</Button> |
||||
|
|
||||
|
<Button size='small' onClick={() => handleDelete(item.id)} disabled={onlyRead}> |
||||
|
{sourceType === 'bg' ? '报告撤回' : '证据撤回'} |
||||
|
</Button> |
||||
|
</Col> |
||||
|
} |
||||
|
|
||||
|
</Row> |
||||
|
{visible && ( |
||||
|
<FormModal |
||||
|
record={record} |
||||
|
visible={visible} |
||||
|
setVisible={setVisible} |
||||
|
getTable={getTable} |
||||
|
fetchEditHCZJ={fetchEditHCZJ} |
||||
|
handleClose={handleCloseModal} |
||||
|
sourceType={'zj'} |
||||
|
actionType={'edit'} |
||||
|
sysToken={sysToken} |
||||
|
/> |
||||
|
)} |
||||
|
</div> |
||||
|
); |
||||
|
}); |
||||
|
}; |
||||
|
return <div>{renderList(dataSource)}</div>; |
||||
|
}; |
||||
|
|
||||
|
export default connect()(CardList); |
||||
@ -0,0 +1,5 @@ |
|||||
|
.card { |
||||
|
padding: 10px 5px 0; |
||||
|
border-top: 1px solid #f1f1f1; |
||||
|
border-bottom: 1px solid #f1f1f1; |
||||
|
} |
||||
@ -0,0 +1,146 @@ |
|||||
|
import React, { useState, useEffect } from 'react'; |
||||
|
import { Modal, Button, Input, Form, message } from 'antd'; |
||||
|
import UploadBtn from '@/components/UploadBtn'; |
||||
|
/** |
||||
|
* visible:弹窗状态 |
||||
|
* handleClose:弹窗开关 |
||||
|
* sourceType:来源 bg-核查报告 zj-核查证据 |
||||
|
*/ |
||||
|
|
||||
|
const layout = { |
||||
|
labelCol: { span: 3 }, |
||||
|
wrapperCol: { span: 19 }, |
||||
|
}; |
||||
|
|
||||
|
const FormModal = (props) => { |
||||
|
const { |
||||
|
id, |
||||
|
sysToken, |
||||
|
visible, |
||||
|
handleClose, |
||||
|
actionType, |
||||
|
sourceType, |
||||
|
fetchAddHCZJ, |
||||
|
fetchEditHCZJ, |
||||
|
fetchAddHCBG, |
||||
|
getTable, |
||||
|
record, |
||||
|
} = props; |
||||
|
const [file, setFile] = useState([]); |
||||
|
const { TextArea } = Input; |
||||
|
const [form] = Form.useForm(); |
||||
|
const handleCloseModal = () => { |
||||
|
handleClose(); |
||||
|
form.resetFields(); |
||||
|
}; |
||||
|
useEffect(() => { |
||||
|
if (record?.id) { |
||||
|
form.setFieldsValue({ |
||||
|
files: record.wjList, |
||||
|
zjXx: record.zjXx, |
||||
|
}); |
||||
|
setFile(record.wjList); |
||||
|
} |
||||
|
}, []); |
||||
|
const fileCheck = () => { |
||||
|
if (!file?.length) { |
||||
|
return Promise.reject(new Error('请选择文件')); |
||||
|
} |
||||
|
return Promise.resolve(); |
||||
|
}; |
||||
|
const onFinish = (values) => { |
||||
|
if (sourceType === 'zj' && actionType === 'add') { |
||||
|
const params = { |
||||
|
...values, |
||||
|
pfId: id, |
||||
|
}; |
||||
|
fetchAddHCZJ({ params, sysToken }).then((data) => { |
||||
|
if (data && data.resCode === 0) { |
||||
|
message.success(data.resMsg); |
||||
|
handleCloseModal(); |
||||
|
getTable(); |
||||
|
} else { |
||||
|
message.error(data.resMsg); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
if (sourceType === 'zj' && actionType === 'edit') { |
||||
|
const params = { |
||||
|
...values, |
||||
|
id: record.id, |
||||
|
}; |
||||
|
fetchEditHCZJ({ params, sysToken }).then((data) => { |
||||
|
if (data && data.resCode === 0) { |
||||
|
message.success(data.resMsg); |
||||
|
handleCloseModal(); |
||||
|
getTable(); |
||||
|
} else { |
||||
|
message.error(data.resMsg); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
if (sourceType === 'bg') { |
||||
|
const pf = [id]; |
||||
|
const params = { |
||||
|
...values, |
||||
|
pfIds: pf, |
||||
|
}; |
||||
|
fetchAddHCBG({ params, sysToken }).then((data) => { |
||||
|
if (data && data.resCode === 0) { |
||||
|
message.success(data.resMsg); |
||||
|
handleCloseModal(); |
||||
|
getTable(); |
||||
|
} else { |
||||
|
message.error(data.resMsg); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
}; |
||||
|
return ( |
||||
|
<Modal |
||||
|
title={actionType === 'add' ? '添加' : '编辑'} |
||||
|
visible={visible} |
||||
|
width={750} |
||||
|
closable={false} |
||||
|
footer={false} |
||||
|
> |
||||
|
<Form form={form} {...layout} name="form" onFinish={onFinish}> |
||||
|
{sourceType === 'zj' && ( |
||||
|
<Form.Item |
||||
|
label={sourceType === 'bg' ? '报告信息' : '证据信息'} |
||||
|
name="zjXx" |
||||
|
rules={[ |
||||
|
{ required: true, message: '请输入信息' }, |
||||
|
{ max: 512, message: '请输入不超过512个字符' }, |
||||
|
]} |
||||
|
> |
||||
|
<TextArea rows={5} /> |
||||
|
</Form.Item> |
||||
|
)} |
||||
|
<Form.Item label="附件" name="files" rules={[{ required: true }]}> |
||||
|
<UploadBtn |
||||
|
defList={record?.id ? record.wjList : null} |
||||
|
sysToken={sysToken} |
||||
|
config={{ multiple: true }} |
||||
|
disable={sourceType === 'bg' && file?.length > 1} |
||||
|
onChange={(newValues) => { |
||||
|
form.setFieldsValue({ files: newValues }); |
||||
|
setFile(newValues); |
||||
|
}} |
||||
|
/> |
||||
|
</Form.Item> |
||||
|
<Form.Item> |
||||
|
<div style={{ width: 600, textAlign: 'right', marginTop: 20 }}> |
||||
|
<Button type="primary" htmlType="submit"> |
||||
|
确认 |
||||
|
</Button> |
||||
|
|
||||
|
<Button onClick={handleCloseModal}>取消</Button> |
||||
|
</div> |
||||
|
</Form.Item> |
||||
|
</Form> |
||||
|
</Modal> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
export default FormModal; |
||||
@ -0,0 +1 @@ |
|||||
|
管辖变更 |
||||
@ -0,0 +1,86 @@ |
|||||
|
import React, { useState, useEffect } from 'react'; |
||||
|
import { connect } from 'umi'; |
||||
|
import { Form, Button, Modal, Spin, Select, Input } from 'antd'; |
||||
|
|
||||
|
|
||||
|
const { Option } = Select; |
||||
|
const { TextArea } = Input; |
||||
|
|
||||
|
// 管辖变更 |
||||
|
const HeaderToDo = (props) => { |
||||
|
const [form] = Form.useForm(); |
||||
|
const [visible, setVisible] = useState(false); |
||||
|
|
||||
|
|
||||
|
|
||||
|
useEffect(() => { |
||||
|
|
||||
|
}, []); |
||||
|
|
||||
|
|
||||
|
const onFinish = values => { |
||||
|
console.log('vla', values); |
||||
|
} |
||||
|
|
||||
|
return ( |
||||
|
<div> |
||||
|
<Spin spinning={false}> |
||||
|
<Button onClick={() => setVisible(true)}>管辖变更</Button> |
||||
|
<Modal |
||||
|
visible={visible} |
||||
|
> |
||||
|
<Form |
||||
|
name="gxbg" |
||||
|
form={form} |
||||
|
// initialValues={initFormData} |
||||
|
onFinish={onFinish} |
||||
|
> |
||||
|
<Form.Item |
||||
|
label="变更原因" |
||||
|
name="bgyy" |
||||
|
rules={[{ required: true, message: '请选择变更原因!' }]} |
||||
|
> |
||||
|
{/* <Select onSelect={(value, item) => { form.setFieldsValue({ ssqkMc: item.mc }) }}> |
||||
|
{Object.keys(CSQK).map((key) => { |
||||
|
return ( |
||||
|
<Option key={key} mc={CSQK[key].name} value={CSQK[key].value} > |
||||
|
{CSQK[key].name} |
||||
|
</Option> |
||||
|
); |
||||
|
})} |
||||
|
</Select> */} |
||||
|
</Form.Item> |
||||
|
|
||||
|
<Form.Item |
||||
|
label="描述" |
||||
|
name="ms" |
||||
|
rules={[{ required: true, message: '请填写处理意见!' }]} |
||||
|
> |
||||
|
<TextArea rows={3} /> |
||||
|
</Form.Item> |
||||
|
<Form.Item> |
||||
|
<Button > |
||||
|
保存 |
||||
|
</Button> |
||||
|
<Button type="primary" htmlType="submit"> |
||||
|
保存 |
||||
|
</Button> |
||||
|
</Form.Item> |
||||
|
|
||||
|
</Form> |
||||
|
</Modal> |
||||
|
</Spin> |
||||
|
|
||||
|
</div> |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
const mapStateToProps = ({ doing }) => ({ |
||||
|
...doing, |
||||
|
}); |
||||
|
const mapDispatchToProps = (dispatch) => ({ |
||||
|
fetchJDGZInfo(params) { |
||||
|
return dispatch({ type: 'doing/fetchJDGZInfo', payload: { ...params } }); |
||||
|
}, |
||||
|
}); |
||||
|
export default connect(mapStateToProps, mapDispatchToProps)(HeaderToDo); |
||||
@ -0,0 +1 @@ |
|||||
|
|
||||
@ -0,0 +1,80 @@ |
|||||
|
import { LogoutOutlined, SettingOutlined, UserOutlined } from '@ant-design/icons'; |
||||
|
import { Avatar, Menu, Spin } from 'antd'; |
||||
|
import React from 'react'; |
||||
|
import { history, connect } from 'umi'; |
||||
|
import HeaderDropdown from '../HeaderDropdown'; |
||||
|
import styles from './index.less'; |
||||
|
|
||||
|
class AvatarDropdown extends React.Component { |
||||
|
onMenuClick = event => { |
||||
|
const { key } = event; |
||||
|
|
||||
|
if (key === 'logout') { |
||||
|
const { dispatch } = this.props; |
||||
|
|
||||
|
if (dispatch) { |
||||
|
dispatch({ |
||||
|
type: 'user/getLogout', |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
history.push(`/account/${key}`); |
||||
|
}; |
||||
|
|
||||
|
render() { |
||||
|
const { |
||||
|
currentUser = { |
||||
|
avatar: '', |
||||
|
name: '', |
||||
|
}, |
||||
|
menu, |
||||
|
} = this.props; |
||||
|
const menuHeaderDropdown = ( |
||||
|
<Menu className={styles.menu} selectedKeys={[]} onClick={this.onMenuClick}> |
||||
|
{menu && ( |
||||
|
<Menu.Item key="center"> |
||||
|
<UserOutlined /> |
||||
|
个人中心 |
||||
|
</Menu.Item> |
||||
|
)} |
||||
|
{menu && ( |
||||
|
<Menu.Item key="settings"> |
||||
|
<SettingOutlined /> |
||||
|
个人设置 |
||||
|
</Menu.Item> |
||||
|
)} |
||||
|
{menu && <Menu.Divider />} |
||||
|
|
||||
|
<Menu.Item key="logout"> |
||||
|
<LogoutOutlined /> |
||||
|
退出登录 |
||||
|
</Menu.Item> |
||||
|
</Menu> |
||||
|
); |
||||
|
return currentUser && currentUser.name ? ( |
||||
|
<HeaderDropdown overlay={menuHeaderDropdown}> |
||||
|
<span className={`${styles.action} ${styles.account}`}> |
||||
|
<Avatar size="small" className={styles.avatar} src={currentUser.avatar} alt="avatar" /> |
||||
|
<span className={`${styles.name} anticon`}>{currentUser.name}</span> |
||||
|
</span> |
||||
|
</HeaderDropdown> |
||||
|
) : ( |
||||
|
<span className={`${styles.action} ${styles.account}`}> |
||||
|
<Spin |
||||
|
size="small" |
||||
|
style={{ |
||||
|
marginLeft: 8, |
||||
|
marginRight: 8, |
||||
|
}} |
||||
|
/> |
||||
|
</span> |
||||
|
); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default connect(({ user }) => ({ |
||||
|
currentUser: user.currentUser, |
||||
|
}))(AvatarDropdown); |
||||
@ -0,0 +1,156 @@ |
|||||
|
import React, { Component } from 'react'; |
||||
|
import { connect } from 'umi'; |
||||
|
import { Tag, message } from 'antd'; |
||||
|
import groupBy from 'lodash/groupBy'; |
||||
|
import moment from 'moment'; |
||||
|
import NoticeIcon from '../NoticeIcon'; |
||||
|
import styles from './index.less'; |
||||
|
|
||||
|
class GlobalHeaderRight extends Component { |
||||
|
componentDidMount() { |
||||
|
const { dispatch } = this.props; |
||||
|
|
||||
|
if (dispatch) { |
||||
|
dispatch({ |
||||
|
type: 'global/fetchNotices', |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
changeReadState = clickedItem => { |
||||
|
const { id } = clickedItem; |
||||
|
const { dispatch } = this.props; |
||||
|
|
||||
|
if (dispatch) { |
||||
|
dispatch({ |
||||
|
type: 'global/changeNoticeReadState', |
||||
|
payload: id, |
||||
|
}); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
handleNoticeClear = (title, key) => { |
||||
|
const { dispatch } = this.props; |
||||
|
message.success(`${'清空了'} ${title}`); |
||||
|
|
||||
|
if (dispatch) { |
||||
|
dispatch({ |
||||
|
type: 'global/clearNotices', |
||||
|
payload: key, |
||||
|
}); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
getNoticeData = () => { |
||||
|
const { notices = [] } = this.props; |
||||
|
|
||||
|
if (!notices || notices.length === 0 || !Array.isArray(notices)) { |
||||
|
return {}; |
||||
|
} |
||||
|
|
||||
|
const newNotices = notices.map(notice => { |
||||
|
const newNotice = { ...notice }; |
||||
|
|
||||
|
if (newNotice.datetime) { |
||||
|
newNotice.datetime = moment(notice.datetime).fromNow(); |
||||
|
} |
||||
|
|
||||
|
if (newNotice.id) { |
||||
|
newNotice.key = newNotice.id; |
||||
|
} |
||||
|
|
||||
|
if (newNotice.extra && newNotice.status) { |
||||
|
const color = { |
||||
|
todo: '', |
||||
|
processing: 'blue', |
||||
|
urgent: 'red', |
||||
|
doing: 'gold', |
||||
|
}[newNotice.status]; |
||||
|
newNotice.extra = ( |
||||
|
<Tag |
||||
|
color={color} |
||||
|
style={{ |
||||
|
marginRight: 0, |
||||
|
}} |
||||
|
> |
||||
|
{newNotice.extra} |
||||
|
</Tag> |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
return newNotice; |
||||
|
}); |
||||
|
return groupBy(newNotices, 'type'); |
||||
|
}; |
||||
|
|
||||
|
getUnreadData = noticeData => { |
||||
|
const unreadMsg = {}; |
||||
|
Object.keys(noticeData).forEach(key => { |
||||
|
const value = noticeData[key]; |
||||
|
|
||||
|
if (!unreadMsg[key]) { |
||||
|
unreadMsg[key] = 0; |
||||
|
} |
||||
|
|
||||
|
if (Array.isArray(value)) { |
||||
|
unreadMsg[key] = value.filter(item => !item.read).length; |
||||
|
} |
||||
|
}); |
||||
|
return unreadMsg; |
||||
|
}; |
||||
|
|
||||
|
render() { |
||||
|
const { currentUser, fetchingNotices, onNoticeVisibleChange } = this.props; |
||||
|
const noticeData = this.getNoticeData(); |
||||
|
const unreadMsg = this.getUnreadData(noticeData); |
||||
|
return ( |
||||
|
<NoticeIcon |
||||
|
className={styles.action} |
||||
|
count={currentUser && currentUser.unreadCount} |
||||
|
onItemClick={item => { |
||||
|
this.changeReadState(item); |
||||
|
}} |
||||
|
loading={fetchingNotices} |
||||
|
clearText="清空" |
||||
|
viewMoreText="查看更多" |
||||
|
onClear={this.handleNoticeClear} |
||||
|
onPopupVisibleChange={onNoticeVisibleChange} |
||||
|
onViewMore={() => message.info('Click on view more')} |
||||
|
clearClose |
||||
|
> |
||||
|
<NoticeIcon.Tab |
||||
|
tabKey="notification" |
||||
|
count={unreadMsg.notification} |
||||
|
list={noticeData.notification} |
||||
|
title="通知" |
||||
|
emptyText="你已查看所有通知" |
||||
|
showViewMore |
||||
|
/> |
||||
|
<NoticeIcon.Tab |
||||
|
tabKey="message" |
||||
|
count={unreadMsg.message} |
||||
|
list={noticeData.message} |
||||
|
title="消息" |
||||
|
emptyText="您已读完所有消息" |
||||
|
showViewMore |
||||
|
/> |
||||
|
<NoticeIcon.Tab |
||||
|
tabKey="event" |
||||
|
title="待办" |
||||
|
emptyText="你已完成所有待办" |
||||
|
count={unreadMsg.event} |
||||
|
list={noticeData.event} |
||||
|
showViewMore |
||||
|
/> |
||||
|
</NoticeIcon> |
||||
|
); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default connect(({ user, global, loading }) => ({ |
||||
|
currentUser: user.currentUser, |
||||
|
collapsed: global.collapsed, |
||||
|
fetchingMoreNotices: loading.effects['global/fetchMoreNotices'], |
||||
|
fetchingNotices: loading.effects['global/fetchNotices'], |
||||
|
notices: global.notices, |
||||
|
}))(GlobalHeaderRight); |
||||
@ -0,0 +1,42 @@ |
|||||
|
import { Tag } from 'antd'; |
||||
|
import React from 'react'; |
||||
|
import { connect } from 'umi'; |
||||
|
|
||||
|
import HeaderMsg from '../HeaderMsg'; |
||||
|
import HeaderToDo from '../HeaderToDo'; |
||||
|
|
||||
|
import Avatar from './AvatarDropdown'; |
||||
|
import styles from './index.less'; |
||||
|
|
||||
|
const ENVTagColor = { |
||||
|
dev: 'orange', |
||||
|
test: 'green', |
||||
|
pre: '#87d068', |
||||
|
}; |
||||
|
|
||||
|
const GlobalHeaderRight = props => { |
||||
|
const { theme, layout } = props; |
||||
|
let className = styles.right; |
||||
|
|
||||
|
if (theme === 'dark' && layout === 'top') { |
||||
|
className = `${styles.right} ${styles.dark}`; |
||||
|
} |
||||
|
|
||||
|
return ( |
||||
|
<div className={className}> |
||||
|
<HeaderMsg /> |
||||
|
<HeaderToDo /> |
||||
|
{/* <Avatar /> */} |
||||
|
{/* {REACT_APP_ENV && ( |
||||
|
<span> |
||||
|
<Tag color={ENVTagColor[REACT_APP_ENV]}>{REACT_APP_ENV}</Tag> |
||||
|
</span> |
||||
|
)} */} |
||||
|
</div> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
export default connect(({ settings }) => ({ |
||||
|
theme: settings.navTheme, |
||||
|
layout: settings.layout, |
||||
|
}))(GlobalHeaderRight); |
||||
@ -0,0 +1,86 @@ |
|||||
|
@import '~antd/es/style/themes/default.less'; |
||||
|
|
||||
|
@pro-header-hover-bg: rgba(0, 0, 0, 0.025); |
||||
|
|
||||
|
.menu { |
||||
|
:global(.anticon) { |
||||
|
margin-right: 8px; |
||||
|
} |
||||
|
:global(.ant-dropdown-menu-item) { |
||||
|
min-width: 160px; |
||||
|
} |
||||
|
:global(.ant-pro-global-header) { |
||||
|
background: red; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.right { |
||||
|
display: flex; |
||||
|
float: right; |
||||
|
height: 20px; |
||||
|
margin-top: 15px; |
||||
|
margin-left: auto; |
||||
|
// overflow: hidden; |
||||
|
.action { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
height: 100%; |
||||
|
padding: 0 12px; |
||||
|
cursor: pointer; |
||||
|
transition: all 0.3s; |
||||
|
> span { |
||||
|
vertical-align: middle; |
||||
|
} |
||||
|
&:hover { |
||||
|
background: @pro-header-hover-bg; |
||||
|
} |
||||
|
&:global(.opened) { |
||||
|
background: @pro-header-hover-bg; |
||||
|
} |
||||
|
} |
||||
|
.search { |
||||
|
padding: 0 12px; |
||||
|
&:hover { |
||||
|
background: transparent; |
||||
|
} |
||||
|
} |
||||
|
.account { |
||||
|
.avatar { |
||||
|
margin: ~'calc((@{layout-header-height} - 24px) / 2)' 0; |
||||
|
margin-right: 8px; |
||||
|
color: @primary-color; |
||||
|
vertical-align: top; |
||||
|
background: rgba(255, 255, 255, 0.85); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.dark { |
||||
|
.action { |
||||
|
color: rgba(255, 255, 255, 0.85); |
||||
|
> span { |
||||
|
color: rgba(255, 255, 255, 0.85); |
||||
|
} |
||||
|
&:hover, |
||||
|
&:global(.opened) { |
||||
|
background: @primary-color; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
:global(.ant-pro-global-header) { |
||||
|
.dark { |
||||
|
.action { |
||||
|
color: @text-color; |
||||
|
> span { |
||||
|
color: @text-color; |
||||
|
} |
||||
|
&:hover { |
||||
|
color: rgba(255, 255, 255, 0.85); |
||||
|
> span { |
||||
|
color: rgba(255, 255, 255, 0.85); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1 @@ |
|||||
|
核查报告 |
||||
@ -0,0 +1,151 @@ |
|||||
|
import React, { useState, useEffect } from 'react'; |
||||
|
import { connect } from 'umi'; |
||||
|
import moment from 'moment'; |
||||
|
import { Card, Button, Table, message } from 'antd'; |
||||
|
import FormModal from '@/components/FormModal'; |
||||
|
|
||||
|
const HCBG = (props) => { |
||||
|
const { |
||||
|
id, |
||||
|
sysToken, |
||||
|
fetchHCBGtable, |
||||
|
fetchDeleteHCBG, |
||||
|
fetchAddHCBG, |
||||
|
fetchDownloadFile, |
||||
|
onlyRead, |
||||
|
} = props; |
||||
|
const [visible, setVisible] = useState(false); |
||||
|
const [dataSource, setDataSource] = useState([]); |
||||
|
|
||||
|
const getTable = () => { |
||||
|
fetchHCBGtable({ pfId: id, sysToken }).then((res) => { |
||||
|
setDataSource(res); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
useEffect(() => { |
||||
|
getTable(); |
||||
|
}, []); |
||||
|
const handleOpenModal = () => { |
||||
|
setVisible(true); |
||||
|
}; |
||||
|
const handleCloseModal = () => { |
||||
|
setVisible(false); |
||||
|
}; |
||||
|
const handleDeleteBG = (id) => { |
||||
|
fetchDeleteHCBG({ id, sysToken }).then((res) => { |
||||
|
if (res && res.resCode === 0) { |
||||
|
message.success(res.resMsg); |
||||
|
getTable(); |
||||
|
} else { |
||||
|
message.error(res.resMsg); |
||||
|
} |
||||
|
}); |
||||
|
}; |
||||
|
const handleDownload = (file) => { |
||||
|
const params = { |
||||
|
mc: file.wjMc, |
||||
|
path: file.wjPath, |
||||
|
url: file.wjUrl, |
||||
|
}; |
||||
|
fetchDownloadFile({ params, sysToken }); |
||||
|
}; |
||||
|
const columns = [ |
||||
|
{ |
||||
|
key: 'id', |
||||
|
title: '序号', |
||||
|
dataIndex: 'id', |
||||
|
render: (t, r, i) => i + 1 |
||||
|
}, |
||||
|
{ |
||||
|
key: 'wjMc', |
||||
|
title: '文件名称', |
||||
|
dataIndex: 'wjMc', |
||||
|
render: (text, record) => { |
||||
|
return record?.wjList?.map((file, index) => { |
||||
|
return ( |
||||
|
<a key={file.id} onClick={() => handleDownload(file)}> |
||||
|
{file.wjMc} |
||||
|
{index === record?.wjList?.length - 1 ? '' : ';'} |
||||
|
</a> |
||||
|
); |
||||
|
}); |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
key: 'bcrMc', |
||||
|
title: '补充人', |
||||
|
dataIndex: 'bcrMc', |
||||
|
}, |
||||
|
{ |
||||
|
key: 'bcrDwMc', |
||||
|
title: '补充单位', |
||||
|
dataIndex: 'bcrDwMc', |
||||
|
}, |
||||
|
{ |
||||
|
key: 'bcSj', |
||||
|
title: '补充时间', |
||||
|
dataIndex: 'bcSj', |
||||
|
render: (text) => { |
||||
|
return <span>{moment(text).format('YYYY-MM-DD HH:mm:ss')}</span>; |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
key: 'action', |
||||
|
render: (text, record) => { |
||||
|
return ( |
||||
|
<a onClick={() => onlyRead ? null : handleDeleteBG(record.id)} disabled={onlyRead}> |
||||
|
删除 |
||||
|
</a> |
||||
|
); |
||||
|
}, |
||||
|
}, |
||||
|
]; |
||||
|
return ( |
||||
|
<Card title="核查报告"> |
||||
|
{!onlyRead && ( |
||||
|
<div className="rightButton"> |
||||
|
<Button type="primary" onClick={handleOpenModal}> |
||||
|
上传核查报告 |
||||
|
</Button> |
||||
|
</div> |
||||
|
)} |
||||
|
<div> |
||||
|
<Table rowKey={(record) => record?.id || null} columns={columns} dataSource={dataSource || []} pagination={false} /> |
||||
|
</div> |
||||
|
{visible && ( |
||||
|
<FormModal |
||||
|
id={id} |
||||
|
visible={visible} |
||||
|
handleClose={handleCloseModal} |
||||
|
sourceType={'bg'} |
||||
|
actionType={'add'} |
||||
|
fetchAddHCBG={fetchAddHCBG} |
||||
|
sysToken={sysToken} |
||||
|
getTable={getTable} |
||||
|
/> |
||||
|
)} |
||||
|
</Card> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
const mapStateToProps = ({ doing }) => ({ |
||||
|
...doing, |
||||
|
}); |
||||
|
|
||||
|
const mapDispatchToProps = (dispatch) => ({ |
||||
|
fetchHCBGtable(params) { |
||||
|
return dispatch({ type: 'doing/fetchHCBGtable', payload: { ...params } }); |
||||
|
}, |
||||
|
fetchAddHCBG(params) { |
||||
|
return dispatch({ type: 'doing/fetchAddHCBG', payload: { ...params } }); |
||||
|
}, |
||||
|
fetchDeleteHCBG(params) { |
||||
|
return dispatch({ type: 'doing/fetchDeleteHCBG', payload: { ...params } }); |
||||
|
}, |
||||
|
fetchDownloadFile(params) { |
||||
|
return dispatch({ type: 'doing/fetchDownloadFile', payload: { ...params } }); |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
export default connect(mapStateToProps, mapDispatchToProps)(HCBG); |
||||
@ -0,0 +1 @@ |
|||||
|
核查证据 |
||||
@ -0,0 +1,92 @@ |
|||||
|
import React, { useState, useEffect } from 'react'; |
||||
|
import { connect } from 'umi'; |
||||
|
import { Card, Button } from 'antd'; |
||||
|
import FormModal from '@/components/FormModal'; |
||||
|
import CardList from '@/components/CardList'; |
||||
|
|
||||
|
const HCZJ = (props) => { |
||||
|
const { |
||||
|
id, |
||||
|
sysToken, |
||||
|
fetchHCZJtable, |
||||
|
fetchAddHCZJ, |
||||
|
fetchEditHCZJ, |
||||
|
fetchDeleteHCZJ, |
||||
|
onlyRead, |
||||
|
} = props; |
||||
|
const [visible, setVisible] = useState(false); |
||||
|
const [dataList, setDataList] = useState([]); |
||||
|
|
||||
|
const getTable = () => { |
||||
|
fetchHCZJtable({ pfId: id, sysToken }).then((res) => { |
||||
|
if (res) { |
||||
|
setDataList(res); |
||||
|
} |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
useEffect(() => { |
||||
|
getTable(); |
||||
|
}, []); |
||||
|
|
||||
|
const handleOpenModal = () => { |
||||
|
setVisible(true); |
||||
|
}; |
||||
|
const handleCloseModal = () => { |
||||
|
setVisible(false); |
||||
|
}; |
||||
|
return ( |
||||
|
<Card title="核查证据"> |
||||
|
{ |
||||
|
!onlyRead && |
||||
|
<div className="rightButton"> |
||||
|
<Button type="primary" onClick={handleOpenModal} > |
||||
|
上传核查证据 |
||||
|
</Button> |
||||
|
</div> |
||||
|
} |
||||
|
<div> |
||||
|
<CardList |
||||
|
onlyRead={onlyRead} |
||||
|
sourceType={'zj'} |
||||
|
dataSource={dataList} |
||||
|
fetchDeleteHCZJ={fetchDeleteHCZJ} |
||||
|
fetchEditHCZJ={fetchEditHCZJ} |
||||
|
getTable={getTable} |
||||
|
sysToken={sysToken} |
||||
|
/> |
||||
|
</div> |
||||
|
{visible && ( |
||||
|
<FormModal |
||||
|
visible={visible} |
||||
|
id={id} |
||||
|
sysToken={sysToken} |
||||
|
handleClose={handleCloseModal} |
||||
|
sourceType={'zj'} |
||||
|
actionType={'add'} |
||||
|
fetchAddHCZJ={fetchAddHCZJ} |
||||
|
getTable={getTable} |
||||
|
/> |
||||
|
)} |
||||
|
</Card> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
const mapStateToProps = ({ doing }) => ({ |
||||
|
...doing, |
||||
|
}); |
||||
|
const mapDispatchToProps = (dispatch) => ({ |
||||
|
fetchHCZJtable(params) { |
||||
|
return dispatch({ type: 'doing/fetchHCZJtable', payload: { ...params } }); |
||||
|
}, |
||||
|
fetchAddHCZJ(params) { |
||||
|
return dispatch({ type: 'doing/fetchAddHCZJ', payload: { ...params } }); |
||||
|
}, |
||||
|
fetchEditHCZJ(params) { |
||||
|
return dispatch({ type: 'doing/fetchEditHCZJ', payload: { ...params } }); |
||||
|
}, |
||||
|
fetchDeleteHCZJ(params) { |
||||
|
return dispatch({ type: 'doing/fetchDeleteHCZJ', payload: { ...params } }); |
||||
|
}, |
||||
|
}); |
||||
|
export default connect(mapStateToProps, mapDispatchToProps)(HCZJ); |
||||
@ -0,0 +1,10 @@ |
|||||
|
import { Dropdown } from 'antd'; |
||||
|
import React from 'react'; |
||||
|
import classNames from 'classnames'; |
||||
|
import styles from './index.less'; |
||||
|
|
||||
|
const HeaderDropdown = ({ overlayClassName: cls, ...restProps }) => ( |
||||
|
<Dropdown overlayClassName={classNames(styles.container, cls)} {...restProps} /> |
||||
|
); |
||||
|
|
||||
|
export default HeaderDropdown; |
||||
@ -0,0 +1,16 @@ |
|||||
|
@import '~antd/es/style/themes/default.less'; |
||||
|
|
||||
|
.container > * { |
||||
|
background-color: @popover-bg; |
||||
|
border-radius: 4px; |
||||
|
box-shadow: @shadow-1-down; |
||||
|
} |
||||
|
|
||||
|
@media screen and (max-width: @screen-xs) { |
||||
|
.container { |
||||
|
width: 100% !important; |
||||
|
} |
||||
|
.container > * { |
||||
|
border-radius: 0 !important; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1 @@ |
|||||
|
头部-消息 |
||||
@ -0,0 +1,387 @@ |
|||||
|
import React, { useState, useEffect } from 'react'; |
||||
|
import { connect } from 'umi'; |
||||
|
import { Popover, Badge, Table, Button, message, Tooltip, Modal, Tabs } from 'antd'; |
||||
|
import { BellOutlined } from '@ant-design/icons'; |
||||
|
import CK from '../Tabs-CK'; |
||||
|
import styles from './index.less'; |
||||
|
import { platformLevel } from '@/utils/constants'; |
||||
|
|
||||
|
// 消息 |
||||
|
const HeaderToDo = (props) => { |
||||
|
const { isLocationInBu, fetchMsgList, fetchSetIsReaded, fetchReadOnce, fetchGetDqXx, locationType } = props; |
||||
|
// debugger; |
||||
|
console.log(platformLevel['BU']) |
||||
|
const sysToken = isLocationInBu ? '' : 'bu'; // 如果本地是部 不加sysToken,否则加 |
||||
|
const { TabPane } = Tabs; |
||||
|
const [count, setCount] = useState(0); |
||||
|
const [visible, setVisible] = useState(false); |
||||
|
const [tabVisible, setTabVisible] = useState(false); |
||||
|
const [nowTab, setNowTab] = useState(0); // 0-部 1-省 |
||||
|
const [buBtn, setBuBtn] = useState(0); // 1-已读 0-未读 |
||||
|
const [shBtn, setShBtn] = useState(0); // 1-已读 0-未读 |
||||
|
const [buSearchParams, setBuSearchParams] = useState({ page: 1, isRead: buBtn }); |
||||
|
const [shSearchParams, setShSearchParams] = useState({ page: 1, isRead: shBtn }); |
||||
|
const [shiSearchParams, setShiSearchParams] = useState({ page: 1, isRead: shBtn }); |
||||
|
const [buTableData, setBuTableData] = useState([]); |
||||
|
const [shTableData, setShTableData] = useState([]); |
||||
|
const [shiTableData, setShiTableData] = useState([]); |
||||
|
const [showId, setShowId] = useState(); // 模态框id |
||||
|
const [showInfo, setShowInfo] = useState([]); // 模态框info |
||||
|
|
||||
|
// 点击已读/未读 |
||||
|
const handleIsRead = (type) => { |
||||
|
if (type === 1) { |
||||
|
// 省级系统 本级不传sysToken |
||||
|
setShBtn(Number(!shBtn)); |
||||
|
setShSearchParams({ page: 1, isRead: Number(!shBtn) }); |
||||
|
} |
||||
|
if (type === 0) { |
||||
|
// 省级系统的部&部级传对应的sysToken |
||||
|
setBuBtn(Number(!buBtn)); |
||||
|
setBuSearchParams({ page: 1, isRead: Number(!buBtn) }); |
||||
|
} |
||||
|
}; |
||||
|
// 部翻页 |
||||
|
const changeBuPage = (pagination) => { |
||||
|
setBuSearchParams({ ...buSearchParams, page: pagination }); |
||||
|
}; |
||||
|
// 省翻页 |
||||
|
const changeShPage = (pagination) => { |
||||
|
setShSearchParams({ ...shSearchParams, page: pagination }); |
||||
|
}; |
||||
|
// 市翻页 |
||||
|
const changeShiPage = (pagination) => { |
||||
|
setShiSearchParams({ ...shiSearchParams, page: pagination }); |
||||
|
}; |
||||
|
// 开关设置 |
||||
|
const handleVisibleChange = () => { |
||||
|
setVisible(!visible); |
||||
|
}; |
||||
|
// 置为全部已读 |
||||
|
const handleAllRead = () => { |
||||
|
if (nowTab === 1) { |
||||
|
fetchSetIsReaded('').then((res) => { |
||||
|
if (res && res.resCode === 0) { |
||||
|
getTable({ page: 1, isRead: buBtn }, { page: 1, isRead: shBtn }); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
if (nowTab === 0) { |
||||
|
fetchSetIsReaded(sysToken).then((res) => { |
||||
|
if (res && res.resCode === 0) { |
||||
|
getTable({ page: 1, isRead: buBtn }, { page: 1, isRead: shBtn }); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
}; |
||||
|
// 根据pageInfo获取列表 |
||||
|
const getTable = (buSearch, shSearch, shiSearch) => { |
||||
|
if (sysToken === 'bu') { |
||||
|
// 本级平台 |
||||
|
let psh = new Promise(function (resolve, reject) { |
||||
|
const search = { |
||||
|
params: locationType === platformLevel['SHENG'] ? { ...shSearch } : {...shiSearch}, |
||||
|
sysToken: '', |
||||
|
}; |
||||
|
fetchMsgList(search).then((res) => { |
||||
|
if (res && res.resCode === 0) { |
||||
|
resolve(res.data); |
||||
|
} |
||||
|
}); |
||||
|
}); |
||||
|
let pbu = new Promise(function (resolve, reject) { |
||||
|
const search = { |
||||
|
params: { ...buSearch }, |
||||
|
sysToken, |
||||
|
}; |
||||
|
fetchMsgList(search).then((res) => { |
||||
|
if (res && res.resCode === 0) { |
||||
|
resolve(res.data); |
||||
|
} |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
let pshi = new Promise(function (resolve, reject) { |
||||
|
const search = { |
||||
|
params: { ...shSearch }, |
||||
|
sysToken: 'sheng', |
||||
|
}; |
||||
|
fetchMsgList(search).then((res) => { |
||||
|
if (res && res.resCode === 0) { |
||||
|
resolve(res.data); |
||||
|
} |
||||
|
}); |
||||
|
}); |
||||
|
if(locationType === platformLevel['SHENG']){ |
||||
|
// 省级 查部(传‘bu’)和省(传‘’)的消息 |
||||
|
Promise.all([psh, pbu]).then(function (results) { |
||||
|
const num = Number(results[0].unread) + Number(results[1].unread); |
||||
|
setCount(num); |
||||
|
setBuTableData(results[1].list); |
||||
|
setShTableData(results[0].list); |
||||
|
}); |
||||
|
} |
||||
|
if(locationType === platformLevel['SHI']){ |
||||
|
Promise.all([psh, pbu, pshi]).then(function (results) { |
||||
|
console.log("results",results); |
||||
|
const num = Number(results[0].unread) + Number(results[1].unread)+ Number(results[2].unread); |
||||
|
setCount(num); |
||||
|
setShiTableData(results[0].list); |
||||
|
setBuTableData(results[1].list); |
||||
|
setShTableData(results[2].list); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
if (sysToken === '') { |
||||
|
// 部级 只查部级用sysToken |
||||
|
const search = { |
||||
|
params: { ...buSearch }, |
||||
|
sysToken, |
||||
|
}; |
||||
|
fetchMsgList(search).then((res) => { |
||||
|
if (res && res.resCode === 0) { |
||||
|
setCount(res.data.unread); |
||||
|
setBuTableData(res.data.list); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
}; |
||||
|
// 点击查看 |
||||
|
const clickItem = (record) => { |
||||
|
const { pfId, id } = record; |
||||
|
setShowId(pfId); |
||||
|
if (nowTab === 1) { |
||||
|
// 省级 不穿sysToken |
||||
|
const p = { |
||||
|
id: pfId, |
||||
|
sysToken: '', |
||||
|
}; |
||||
|
fetchGetDqXx(p).then((res) => { |
||||
|
if (res && res.resCode === 0) { |
||||
|
setShowInfo(res.data); |
||||
|
setVisible(false); |
||||
|
setTabVisible(true); |
||||
|
fetchReadOnce({ id, sysToken: '' }).then((response) => { |
||||
|
if (response && response.resCode === 0) { |
||||
|
getTable({ page: 1, isRead: buBtn }, { page: 1, isRead: shBtn }); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
if (nowTab === 0) { |
||||
|
// 省级系统的部&部级传对应的sysToken |
||||
|
fetchGetDqXx({ id: pfId, sysToken }).then((res) => { |
||||
|
if (res && res.resCode === 0) { |
||||
|
setShowInfo(res.data); |
||||
|
setVisible(false); |
||||
|
setTabVisible(true); |
||||
|
fetchReadOnce({ id, sysToken }).then((response) => { |
||||
|
if (response && response.resCode === 0) { |
||||
|
getTable({ page: 1, isRead: buBtn }, { page: 1, isRead: shBtn }); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
// 列名 |
||||
|
const columns = [ |
||||
|
{ |
||||
|
title: '编号', |
||||
|
dataIndex: 'xxnr', |
||||
|
width: '40%', |
||||
|
render: (text, item) => { |
||||
|
return ( |
||||
|
<Tooltip placement="topLeft" title={text}> |
||||
|
<Button type="link" onClick={() => clickItem(item)}> |
||||
|
<div className={styles.xxnr}>{text}</div> |
||||
|
</Button> |
||||
|
</Tooltip> |
||||
|
); |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: '消息类型', |
||||
|
dataIndex: 'xxLxMc', |
||||
|
width: '20%', |
||||
|
render: (text, item) => { |
||||
|
return ( |
||||
|
<Tooltip placement="topLeft" title={text}> |
||||
|
{text} |
||||
|
</Tooltip> |
||||
|
); |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: '时间', |
||||
|
dataIndex: 'createTime', |
||||
|
width: '30%', |
||||
|
render: (text) => { |
||||
|
return ( |
||||
|
<Tooltip placement="topLeft" title={text}> |
||||
|
{text} |
||||
|
</Tooltip> |
||||
|
); |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: '状态', |
||||
|
dataIndex: 'sfyd', |
||||
|
width: '10%', |
||||
|
render: (text) => { |
||||
|
return text == 1 ? '已读' : '未读'; |
||||
|
}, |
||||
|
}, |
||||
|
]; |
||||
|
|
||||
|
// 显示内容 |
||||
|
const renderContent = () => { |
||||
|
console.log(sysToken === 'bu' && locationType === platformLevel['SHI']); |
||||
|
return ( |
||||
|
<div style={{ width: 700 }}> |
||||
|
<Tabs |
||||
|
tabBarExtraContent={ |
||||
|
nowTab === 0 ? ( |
||||
|
<div style={{ textAlign: 'right' }}> |
||||
|
<Button onClick={handleAllRead}>全部标为已读</Button> |
||||
|
<Button type={buBtn === 0 ? 'primary' : ''} onClick={() => handleIsRead(0)}> |
||||
|
所有未读 |
||||
|
</Button> |
||||
|
</div> |
||||
|
) : ( |
||||
|
<div style={{ textAlign: 'right' }}> |
||||
|
<Button onClick={handleAllRead}>全部标为已读</Button> |
||||
|
<Button type={shBtn === 0 ? 'primary' : ''} onClick={() => handleIsRead(1)}> |
||||
|
所有未读 |
||||
|
</Button> |
||||
|
</div> |
||||
|
) |
||||
|
} |
||||
|
onTabClick={(key) => { |
||||
|
setNowTab(Number(key)); |
||||
|
}} |
||||
|
> |
||||
|
<TabPane tab="部级平台" key={0}> |
||||
|
<Table |
||||
|
columns={columns} |
||||
|
dataSource={buTableData?.records} |
||||
|
rowKey={(record) => record.id} |
||||
|
showHeader={false} |
||||
|
bordered={false} |
||||
|
pagination={{ |
||||
|
current: buTableData?.current, |
||||
|
pageSize: buTableData?.size, |
||||
|
total: buTableData?.total, |
||||
|
onChange: (page) => changeBuPage(page), |
||||
|
}} |
||||
|
/> |
||||
|
</TabPane> |
||||
|
{ |
||||
|
sysToken === 'bu' && locationType === platformLevel['SHI'] ? |
||||
|
<TabPane tab="省级平台" key={1}> |
||||
|
<Table |
||||
|
columns={columns} |
||||
|
dataSource={shTableData?.records} |
||||
|
rowKey={(record) => record.id} |
||||
|
showHeader={false} |
||||
|
bordered={false} |
||||
|
pagination={{ |
||||
|
current: shTableData?.current, |
||||
|
pageSize: shTableData?.size, |
||||
|
total: shTableData?.total, |
||||
|
onChange: (page) => changeShPage(page), |
||||
|
}} |
||||
|
/> |
||||
|
</TabPane> |
||||
|
: '' |
||||
|
} |
||||
|
{sysToken === 'bu' && ( |
||||
|
<TabPane tab="本级平台" key={2}> |
||||
|
<Table |
||||
|
columns={columns} |
||||
|
dataSource={locationType === platformLevel['SHENG'] ? shTableData?.records : shiTableData?.records } |
||||
|
rowKey={(record) => record.id} |
||||
|
showHeader={false} |
||||
|
bordered={false} |
||||
|
pagination={{ |
||||
|
current: locationType === platformLevel['SHENG'] ? shTableData?.current : shiTableData?.current, |
||||
|
pageSize: locationType === platformLevel['SHENG'] ? shTableData?.size : shiTableData?.size, |
||||
|
total: locationType === platformLevel['SHENG'] ? shTableData?.total : shTableData?.total, |
||||
|
onChange: (page) => locationType === platformLevel['SHENG'] ? changeShPage(page) : changeShiPage(page), |
||||
|
}} |
||||
|
/> |
||||
|
</TabPane> |
||||
|
)} |
||||
|
</Tabs> |
||||
|
</div> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
useEffect(() => { |
||||
|
if (sysToken === 'bu') { |
||||
|
if(locationType === platformLevel['SHENG']) { |
||||
|
getTable(buSearchParams, shSearchParams); |
||||
|
} |
||||
|
if(locationType === platformLevel['SHI'] ){ |
||||
|
getTable(buSearchParams, shSearchParams, shiSearchParams); |
||||
|
} |
||||
|
// 获取两个 |
||||
|
} |
||||
|
if (sysToken !== 'bu') { |
||||
|
getTable(buSearchParams); |
||||
|
// 获取一个 |
||||
|
} |
||||
|
}, [buSearchParams, shSearchParams, shiSearchParams]); |
||||
|
|
||||
|
return ( |
||||
|
<> |
||||
|
<Popover |
||||
|
content={renderContent()} |
||||
|
title="" |
||||
|
trigger="click" |
||||
|
visible={visible} |
||||
|
onVisibleChange={handleVisibleChange} |
||||
|
placement="bottomRight" |
||||
|
> |
||||
|
<Badge count={count}> |
||||
|
<a href="#" style={{ marginLeft: 16, fontSize: 22 }}> |
||||
|
<BellOutlined /> |
||||
|
</a> |
||||
|
</Badge> |
||||
|
</Popover> |
||||
|
{tabVisible && ( |
||||
|
<Modal |
||||
|
width={1200} |
||||
|
visible={tabVisible} |
||||
|
footer={false} |
||||
|
onCancel={() => setTabVisible(false)} |
||||
|
> |
||||
|
<CK id={showId} sysToken={sysToken} info={showInfo} /> |
||||
|
</Modal> |
||||
|
)} |
||||
|
</> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
const mapStateToProps = ({ global, user }) => ({ |
||||
|
...global, |
||||
|
isLocationInBu: user.isLocationInBu, |
||||
|
locationType: user.locationType |
||||
|
}); |
||||
|
const mapDispatchToProps = (dispatch) => ({ |
||||
|
fetchMsgList(params) { |
||||
|
return dispatch({ type: 'global/fetchMsgList', payload: { ...params } }); |
||||
|
}, |
||||
|
fetchSetIsReaded(params) { |
||||
|
return dispatch({ type: 'global/fetchSetIsReaded', payload: params }); |
||||
|
}, |
||||
|
fetchReadOnce(params) { |
||||
|
return dispatch({ type: 'global/fetchReadOnce', payload: { ...params } }); |
||||
|
}, |
||||
|
fetchGetDqXx(params) { |
||||
|
return dispatch({ type: 'global/fetchGetDqXx', payload: { ...params } }); |
||||
|
}, |
||||
|
}); |
||||
|
export default connect(mapStateToProps, mapDispatchToProps)(HeaderToDo); |
||||
@ -0,0 +1,38 @@ |
|||||
|
.titles { |
||||
|
:global { |
||||
|
.ant-col-11 { |
||||
|
text-align: right; |
||||
|
a { |
||||
|
margin-left: 24px; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.xxnr { |
||||
|
width: 320px; |
||||
|
overflow: hidden; |
||||
|
white-space: nowrap; |
||||
|
text-align: left; |
||||
|
text-overflow: ellipsis; |
||||
|
} |
||||
|
|
||||
|
.contents { |
||||
|
width: 800px; |
||||
|
.pagination { |
||||
|
margin-top: 16px; |
||||
|
text-align: right; |
||||
|
[class~='ant-pagination'] { |
||||
|
float: right; |
||||
|
} |
||||
|
.total { |
||||
|
float: right; |
||||
|
margin-left: 16px; |
||||
|
line-height: 32px; |
||||
|
.prompt { |
||||
|
margin: 0 4px; |
||||
|
color: #3488e9; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,86 @@ |
|||||
|
import { SearchOutlined } from '@ant-design/icons'; |
||||
|
import { AutoComplete, Input } from 'antd'; |
||||
|
import useMergedState from 'rc-util/es/hooks/useMergedState'; |
||||
|
import React, { useRef } from 'react'; |
||||
|
import classNames from 'classnames'; |
||||
|
import styles from './index.less'; |
||||
|
|
||||
|
const HeaderSearch = props => { |
||||
|
const { |
||||
|
className, |
||||
|
defaultValue, |
||||
|
onVisibleChange, |
||||
|
placeholder, |
||||
|
open, |
||||
|
defaultOpen, |
||||
|
...restProps |
||||
|
} = props; |
||||
|
const inputRef = useRef(null); |
||||
|
const [value, setValue] = useMergedState(defaultValue, { |
||||
|
value: props.value, |
||||
|
onChange: props.onChange, |
||||
|
}); |
||||
|
const [searchMode, setSearchMode] = useMergedState(defaultOpen ?? false, { |
||||
|
value: props.open, |
||||
|
onChange: onVisibleChange, |
||||
|
}); |
||||
|
const inputClass = classNames(styles.input, { |
||||
|
[styles.show]: searchMode, |
||||
|
}); |
||||
|
return ( |
||||
|
<div |
||||
|
className={classNames(className, styles.headerSearch)} |
||||
|
onClick={() => { |
||||
|
setSearchMode(true); |
||||
|
|
||||
|
if (searchMode && inputRef.current) { |
||||
|
inputRef.current.focus(); |
||||
|
} |
||||
|
}} |
||||
|
onTransitionEnd={({ propertyName }) => { |
||||
|
if (propertyName === 'width' && !searchMode) { |
||||
|
if (onVisibleChange) { |
||||
|
onVisibleChange(searchMode); |
||||
|
} |
||||
|
} |
||||
|
}} |
||||
|
> |
||||
|
<SearchOutlined |
||||
|
key="Icon" |
||||
|
style={{ |
||||
|
cursor: 'pointer', |
||||
|
}} |
||||
|
/> |
||||
|
<AutoComplete |
||||
|
key="AutoComplete" |
||||
|
className={inputClass} |
||||
|
value={value} |
||||
|
style={{ |
||||
|
height: 28, |
||||
|
marginTop: -6, |
||||
|
}} |
||||
|
options={restProps.options} |
||||
|
onChange={setValue} |
||||
|
> |
||||
|
<Input |
||||
|
ref={inputRef} |
||||
|
defaultValue={defaultValue} |
||||
|
aria-label={placeholder} |
||||
|
placeholder={placeholder} |
||||
|
onKeyDown={e => { |
||||
|
if (e.key === 'Enter') { |
||||
|
if (restProps.onSearch) { |
||||
|
restProps.onSearch(value); |
||||
|
} |
||||
|
} |
||||
|
}} |
||||
|
onBlur={() => { |
||||
|
setSearchMode(false); |
||||
|
}} |
||||
|
/> |
||||
|
</AutoComplete> |
||||
|
</div> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
export default HeaderSearch; |
||||
@ -0,0 +1,30 @@ |
|||||
|
@import '~antd/es/style/themes/default.less'; |
||||
|
|
||||
|
.headerSearch { |
||||
|
.input { |
||||
|
width: 0; |
||||
|
min-width: 0; |
||||
|
overflow: hidden; |
||||
|
background: transparent; |
||||
|
border-radius: 0; |
||||
|
transition: width 0.3s, margin-left 0.3s; |
||||
|
:global(.ant-select-selection) { |
||||
|
background: transparent; |
||||
|
} |
||||
|
input { |
||||
|
padding-right: 0; |
||||
|
padding-left: 0; |
||||
|
border: 0; |
||||
|
box-shadow: none !important; |
||||
|
} |
||||
|
&, |
||||
|
&:hover, |
||||
|
&:focus { |
||||
|
border-bottom: 1px solid @border-color-base; |
||||
|
} |
||||
|
&.show { |
||||
|
width: 210px; |
||||
|
margin-left: 8px; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1 @@ |
|||||
|
头部-待办 |
||||
@ -0,0 +1,216 @@ |
|||||
|
import React, { useState, useEffect } from 'react'; |
||||
|
import { connect, history } from 'umi'; |
||||
|
import { Popover, Tabs, Badge } from 'antd'; |
||||
|
import { HourglassOutlined } from '@ant-design/icons'; |
||||
|
|
||||
|
import { AJZT, platformLevel } from '@/utils/constants'; |
||||
|
|
||||
|
// 待办 |
||||
|
const HeaderToDo = (props) => { |
||||
|
const { fetchZbYbList, isLocationInBu, refresh, currentUser, locationType} = props; |
||||
|
console.log(currentUser, 'currentUser') |
||||
|
// debugger; |
||||
|
const sysToken = isLocationInBu ? '' : 'bu'; |
||||
|
const { TabPane } = Tabs; |
||||
|
const [nowTab, setNowTab] = useState(0); |
||||
|
const [count, setCount] = useState(0); |
||||
|
|
||||
|
const [visible, setVisible] = useState(false); |
||||
|
const [buDataSource, setBuDataSource] = useState([]); |
||||
|
const [shDataSource, setShDataSource] = useState([]); |
||||
|
const [shiDataSource, setShiDataSource] = useState([]); |
||||
|
const [reload, setReload] = useState(0); |
||||
|
const clickItem = (item) => { |
||||
|
console.log(item) |
||||
|
const list = []; |
||||
|
list.push(item.ajzt); |
||||
|
// debugger; |
||||
|
const pathParams = { |
||||
|
type: Number(nowTab) === 0 ? 'department' : Number(nowTab) === 1 ? 'province' : 'city', |
||||
|
msg: { dqZt: list, page: 1, size: 10, isClr: [0] }, |
||||
|
reload, |
||||
|
}; |
||||
|
|
||||
|
// 未受理的消息要添加当前办理单位的参数 |
||||
|
if (item.ajzt === AJZT.WSL.value) pathParams.msg.dqbldwBm = [currentUser?.departmentCode ?? '']; |
||||
|
|
||||
|
history.push({ |
||||
|
pathname: '/doingcases', |
||||
|
params: pathParams, |
||||
|
}); |
||||
|
setReload(reload + 1); |
||||
|
setVisible(false); |
||||
|
}; |
||||
|
|
||||
|
const handleChangeTab = (e) => { |
||||
|
setNowTab(e); |
||||
|
}; |
||||
|
|
||||
|
const renderContent = () => { |
||||
|
console.log(shDataSource) |
||||
|
return ( |
||||
|
<Tabs |
||||
|
onTabClick={(e) => { |
||||
|
handleChangeTab(e); |
||||
|
}} |
||||
|
> |
||||
|
<TabPane tab="部级平台" key={0}> |
||||
|
<div style={{ width: 150 }}> |
||||
|
<div style={{ fontWeight: 600, fontSize: 16, marginBottom: 5 }}>工作中心</div> |
||||
|
{buDataSource?.map((item) => { |
||||
|
return ( |
||||
|
<div key={item} style={{ paddingLeft: 15 }} onClick={() => clickItem(item)}> |
||||
|
<a style={{ color: '#000' }}> |
||||
|
{item.ajztValue}({item.count}) |
||||
|
</a> |
||||
|
</div> |
||||
|
); |
||||
|
})} |
||||
|
</div> |
||||
|
</TabPane> |
||||
|
{ |
||||
|
sysToken === 'bu' && locationType === platformLevel['SHI'] ? |
||||
|
<TabPane tab="省级平台" key={1}> |
||||
|
<div style={{ width: 150 }}> |
||||
|
<div style={{ fontWeight: 600, fontSize: 16, marginBottom: 5 }}>工作中心</div> |
||||
|
|
||||
|
{shDataSource?.map((item) => { |
||||
|
return ( |
||||
|
<div key={item} style={{ paddingLeft: 15 }} onClick={() => clickItem(item)}> |
||||
|
<a style={{ color: '#000' }}> |
||||
|
{item.ajztValue}({item.count}) |
||||
|
</a> |
||||
|
</div> |
||||
|
); |
||||
|
})} |
||||
|
</div> |
||||
|
</TabPane> |
||||
|
: '' |
||||
|
} |
||||
|
{sysToken === 'bu' && ( |
||||
|
<TabPane tab="本级平台" key={locationType === platformLevel['SHI'] ? 2 : 1 }> |
||||
|
<div style={{ width: 150 }}> |
||||
|
<div style={{ fontWeight: 600, fontSize: 16, marginBottom: 5 }}>工作中心</div> |
||||
|
{ |
||||
|
(locationType === platformLevel['SHENG'] ? shDataSource:shiDataSource)?.map((item) => { |
||||
|
return ( |
||||
|
<div key={item} style={{ paddingLeft: 15 }} onClick={() => clickItem(item)}> |
||||
|
<a style={{ color: '#000' }}> |
||||
|
{item.ajztValue}({item.count}) |
||||
|
</a> |
||||
|
</div> |
||||
|
); |
||||
|
}) |
||||
|
} |
||||
|
</div> |
||||
|
</TabPane> |
||||
|
)} |
||||
|
</Tabs> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
const handleVisibleChange = () => { |
||||
|
setVisible(!visible); |
||||
|
}; |
||||
|
|
||||
|
const getCount = (list) => { |
||||
|
let num = 0; |
||||
|
list?.forEach((item) => { |
||||
|
num += Number(item.count); |
||||
|
}); |
||||
|
|
||||
|
return num; |
||||
|
}; |
||||
|
|
||||
|
const getData = () => { |
||||
|
if (sysToken === 'bu') { |
||||
|
// 本级平台 |
||||
|
const psh = new Promise(function (resolve, reject) { |
||||
|
fetchZbYbList('').then((res) => { |
||||
|
if (res && res.resCode === 0) { |
||||
|
resolve(res.data); |
||||
|
} |
||||
|
}); |
||||
|
}); |
||||
|
const pbu = new Promise(function (resolve, reject) { |
||||
|
fetchZbYbList(sysToken).then((res) => { |
||||
|
if (res && res.resCode === 0) { |
||||
|
resolve(res.data); |
||||
|
} |
||||
|
}); |
||||
|
}); |
||||
|
const pshi = new Promise(function (resolve, reject) { |
||||
|
fetchZbYbList('sheng').then((res) => { |
||||
|
if (res && res.resCode === 0) { |
||||
|
resolve(res.data); |
||||
|
} |
||||
|
}); |
||||
|
}); |
||||
|
if(locationType === platformLevel['SHENG']) { |
||||
|
// 省级 查部(传‘bu’)和省(传‘’)的消息 |
||||
|
Promise.all([psh, pbu]).then(function (results) { |
||||
|
console.log("results",results); |
||||
|
const num = getCount(results[0]) + getCount(results[1]); |
||||
|
setCount(num); |
||||
|
setBuDataSource(results[1]); |
||||
|
setShDataSource(results[0]); |
||||
|
}); |
||||
|
} |
||||
|
if(locationType === platformLevel['SHI'] ) { |
||||
|
Promise.all([psh, pbu, pshi]).then(function (results) { |
||||
|
console.log("results",results); |
||||
|
const num = getCount(results[0]) + getCount(results[1]) + getCount(results[2]); |
||||
|
setCount(num); |
||||
|
setShiDataSource(results[0]); |
||||
|
setBuDataSource(results[1]); |
||||
|
setShDataSource(results[2]); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
if (sysToken === '') { |
||||
|
fetchZbYbList(sysToken).then((res) => { |
||||
|
if (res && res.resCode === 0) { |
||||
|
setCount(getCount(res.data)); |
||||
|
setBuDataSource(res.data); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
useEffect(() => { |
||||
|
getData(); |
||||
|
}, [refresh]); |
||||
|
|
||||
|
return ( |
||||
|
<Popover |
||||
|
content={renderContent} |
||||
|
title="" |
||||
|
trigger="click" |
||||
|
visible={visible} |
||||
|
onVisibleChange={handleVisibleChange} |
||||
|
placement="bottomRight" |
||||
|
> |
||||
|
<Badge count={count}> |
||||
|
<a href="#" style={{ marginLeft: 16, fontSize: 22 }}> |
||||
|
<HourglassOutlined /> |
||||
|
</a> |
||||
|
</Badge> |
||||
|
</Popover> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
const mapStateToProps = ({ global, user, doing }) => ({ |
||||
|
...global, |
||||
|
...user, |
||||
|
isLocationInBu: user.isLocationInBu, |
||||
|
currentUser: user.currentUser, |
||||
|
refresh: doing.refresh, |
||||
|
locationType:user.locationType |
||||
|
}); |
||||
|
const mapDispatchToProps = (dispatch) => ({ |
||||
|
fetchZbYbList(params) { |
||||
|
return dispatch({ type: 'global/fetchZbYbList', payload: params }); |
||||
|
}, |
||||
|
}); |
||||
|
export default connect(mapStateToProps, mapDispatchToProps)(HeaderToDo); |
||||
@ -0,0 +1 @@ |
|||||
|
进度跟踪 |
||||
@ -0,0 +1,347 @@ |
|||||
|
import React, { useState, useEffect } from 'react'; |
||||
|
import { connect } from 'umi'; |
||||
|
import moment from 'moment'; |
||||
|
import { Card, Row, Col, Timeline, Table } from 'antd'; |
||||
|
import { JDLX, ALLSPFS, YJLX, BLFS } from '@/utils/constants'; |
||||
|
|
||||
|
const JDGZ = (props) => { |
||||
|
const { |
||||
|
id, |
||||
|
sysToken, |
||||
|
fetchJDGZInfo, |
||||
|
fetchJDGZtableSqSp, |
||||
|
fetchJDGZtableCh, |
||||
|
fetchDownloadFile, |
||||
|
fetchJDGZtableAjhcz, |
||||
|
} = props; |
||||
|
const [nowId, setNowId] = useState(); // 当前选择时间点ID |
||||
|
const [tWidth, setTWidth] = useState(); // 列表宽度 |
||||
|
const [tColumns, setTColumns] = useState([]); // 列明 |
||||
|
const [timeLine, setTimeLine] = useState(); // 时间线数据 |
||||
|
const [tableData, setTableData] = useState(); // 列表数据 |
||||
|
|
||||
|
// 获取类型对应信息 |
||||
|
const getJDLX = (item) => { |
||||
|
const jdlx = Object.values(JDLX).find((e) => e.value === item) || {}; |
||||
|
return jdlx; |
||||
|
}; |
||||
|
|
||||
|
// 获取审批方式对应信息 |
||||
|
const getSPFS = (item) => { |
||||
|
const spfs = Object.values(ALLSPFS).find((e) => Number(e.value) === Number(item)) || {}; |
||||
|
return spfs; |
||||
|
}; |
||||
|
|
||||
|
// 获取预警流向对应信息 |
||||
|
const getYJLX = (item) => { |
||||
|
const yjlx = Object.values(YJLX).find((e) => Number(e.value) === Number(item)) || {}; |
||||
|
return yjlx; |
||||
|
}; |
||||
|
|
||||
|
// 获取拟办方式对应信息 |
||||
|
const getNBFS = (item) => { |
||||
|
const nbfs = Object.values(BLFS).find((e) => Number(e.value) === Number(item)) || {}; |
||||
|
return nbfs; |
||||
|
}; |
||||
|
|
||||
|
// 下载文件 |
||||
|
const handleDownload = (file) => { |
||||
|
const params = { |
||||
|
mc: file.wjMc, |
||||
|
path: file.wjPath, |
||||
|
url: file.wjUrl, |
||||
|
}; |
||||
|
fetchDownloadFile({ params, sysToken }); |
||||
|
}; |
||||
|
|
||||
|
const getColumns = (lx) => { |
||||
|
const commonColumns = [ |
||||
|
{ |
||||
|
title: '处理时间', |
||||
|
dataIndex: 'clSj', |
||||
|
key: 'clSj', |
||||
|
}, |
||||
|
{ |
||||
|
title: '处理人', |
||||
|
dataIndex: 'clrMc', |
||||
|
key: 'clrMc', |
||||
|
}, |
||||
|
{ |
||||
|
title: '处理单位', |
||||
|
dataIndex: 'cldwMc', |
||||
|
key: 'cldwMc', |
||||
|
}, |
||||
|
{ |
||||
|
title: '审批方式', |
||||
|
dataIndex: 'sp', |
||||
|
key: 'sp', |
||||
|
render: (text, record) => { |
||||
|
return getSPFS(record?.spFs).name; |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: '下级审批人', |
||||
|
dataIndex: 'xjSprMc', |
||||
|
key: 'xjSprMc', |
||||
|
}, |
||||
|
]; |
||||
|
const SLSPColums = [ |
||||
|
{ |
||||
|
title: '预警流向', |
||||
|
dataIndex: 'yjlx', |
||||
|
key: 'yjlx', |
||||
|
render: (text, record) => { |
||||
|
return getYJLX(record?.blfs).name; |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: '拟办方式', // 拟办方式 |
||||
|
dataIndex: 'nbfs', |
||||
|
key: 'nbfs', |
||||
|
render: (text, record) => { |
||||
|
return getNBFS(record?.nbfs).name; |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: '接收单位', |
||||
|
dataIndex: 'xjdwMc', |
||||
|
key: 'xjdwMc', |
||||
|
}, |
||||
|
{ |
||||
|
title: '受理意见', |
||||
|
dataIndex: 'slyj', |
||||
|
key: 'slyj', |
||||
|
}, |
||||
|
|
||||
|
{ |
||||
|
title: '反馈期限', |
||||
|
dataIndex: 'fksj', |
||||
|
key: 'fksj', |
||||
|
render: (text, record) => { |
||||
|
return moment(record?.zcfkSj).format('YYYY-MM-DD HH:mm:ss'); |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: '附件', |
||||
|
dataIndex: 'fj', |
||||
|
key: 'fj', |
||||
|
render: (text, record) => { |
||||
|
return record?.wj?.map((file, index) => { |
||||
|
return ( |
||||
|
<a key={file.id} onClick={() => handleDownload(file)}> |
||||
|
{file.wjMc} |
||||
|
{index === record?.wj?.length - 1 ? '' : ';'} |
||||
|
</a> |
||||
|
); |
||||
|
}); |
||||
|
}, |
||||
|
}, |
||||
|
// { |
||||
|
// title: '问题简述', |
||||
|
// dataIndex: 'wtms', |
||||
|
// key: 'wtms', |
||||
|
// }, |
||||
|
]; |
||||
|
const BJSPColumns = [ |
||||
|
{ |
||||
|
title: '附件', |
||||
|
dataIndex: 'fj', |
||||
|
key: 'fj', |
||||
|
render: (text, record) => { |
||||
|
return record?.wj?.map((file, index) => { |
||||
|
return ( |
||||
|
<a key={file.id} onClick={() => handleDownload(file)}> |
||||
|
{file.wjMc} |
||||
|
{index === record?.wj?.length - 1 ? '' : ';'} |
||||
|
</a> |
||||
|
); |
||||
|
}); |
||||
|
}, |
||||
|
}, |
||||
|
|
||||
|
{ |
||||
|
title: '办结意见', |
||||
|
dataIndex: 'bjyj', |
||||
|
key: 'bjyj', |
||||
|
}, |
||||
|
{ |
||||
|
title: '审批意见', |
||||
|
dataIndex: 'spyj', |
||||
|
key: 'spyj', |
||||
|
render: (text, record) => { |
||||
|
return text || JSON.parse(record?.ywSj)?.wtjs || JSON.parse(record?.ywSj)?.slyj || ''; |
||||
|
}, |
||||
|
}, |
||||
|
]; |
||||
|
const ANHCZColumns = [ |
||||
|
{ |
||||
|
title: '承办时间', |
||||
|
dataIndex: 'createTime', |
||||
|
key: 'cbsj', |
||||
|
}, |
||||
|
{ |
||||
|
title: '承办人', |
||||
|
dataIndex: 'cbrMc', |
||||
|
key: 'cbr', |
||||
|
}, |
||||
|
]; |
||||
|
const CHColumns = [ |
||||
|
{ |
||||
|
title: '撤回单位', |
||||
|
dataIndex: 'chdwMc', |
||||
|
key: 'chdwMc', |
||||
|
}, |
||||
|
{ |
||||
|
title: '处理人', |
||||
|
dataIndex: 'chrMc', |
||||
|
key: 'chrMc', |
||||
|
}, |
||||
|
{ |
||||
|
title: '撤回原因', |
||||
|
dataIndex: 'chyy', |
||||
|
key: 'chyy', |
||||
|
}, |
||||
|
{ |
||||
|
title: '撤回文书', |
||||
|
dataIndex: 'chwj', |
||||
|
key: 'chwj', |
||||
|
render: (text, record) => { |
||||
|
return record?.wj?.map((file, index) => { |
||||
|
return ( |
||||
|
<a key={file.id} onClick={() => handleDownload(file)}> |
||||
|
{file.wjMc} |
||||
|
{index === record?.wj?.length - 1 ? '' : ';'} |
||||
|
</a> |
||||
|
); |
||||
|
}); |
||||
|
}, |
||||
|
}, |
||||
|
]; |
||||
|
const CCColumns = [ |
||||
|
{ |
||||
|
title: '抽查单位', |
||||
|
dataIndex: 'chdwMc', |
||||
|
key: 'chdwMc', |
||||
|
}, |
||||
|
{ |
||||
|
title: '处理人', |
||||
|
dataIndex: 'chrMc', |
||||
|
key: 'chrMc', |
||||
|
}, |
||||
|
{ |
||||
|
title: '备注', |
||||
|
dataIndex: 'chyy', |
||||
|
key: 'chyy', |
||||
|
}, |
||||
|
]; |
||||
|
// 受理审批 |
||||
|
if (lx === '1') return { tableWidth: 1800, tableColumns: [...commonColumns, ...SLSPColums] }; |
||||
|
// 办结审批 |
||||
|
if (lx === '4') return { tableWidth: 1400, tableColumns: [...commonColumns, ...BJSPColumns] }; |
||||
|
// 延期申请 变更申请 |
||||
|
if (lx === '2' || lx === '3') return { tableWidth: 900, tableColumns: [...commonColumns] }; |
||||
|
// 案件核查中 |
||||
|
if (lx === '6') return { tableWidth: 400, tableColumns: [...ANHCZColumns] }; |
||||
|
// 撤回 |
||||
|
if (lx === '5') return { tableWidth: 800, tableColumns: [...CHColumns] }; |
||||
|
if (lx === '7') return { tableWidth: 800, tableColumns: [...CCColumns] }; |
||||
|
}; |
||||
|
|
||||
|
// 点击时间线获取 列名、表宽度、表数据 |
||||
|
const handleClickTimeline = (record) => { |
||||
|
const { id, lx, ywId, open, pfId } = record; |
||||
|
if (open) { |
||||
|
const tableInfo = getColumns(lx); |
||||
|
const { tableWidth, tableColumns } = tableInfo; |
||||
|
setTableData([]); |
||||
|
setNowId(id); |
||||
|
setTWidth(tableWidth); |
||||
|
setTColumns(tableColumns); |
||||
|
if (lx === '5' || lx === '7') { |
||||
|
// 撤回列表 |
||||
|
fetchJDGZtableCh({ id: ywId, sysToken }).then((res) => { |
||||
|
if (res) setTableData([res]); |
||||
|
}); |
||||
|
} else if (lx === '6') { |
||||
|
// 案件核查中 |
||||
|
const params = { |
||||
|
id, |
||||
|
pfId, |
||||
|
}; |
||||
|
fetchJDGZtableAjhcz({ params, sysToken }).then((res) => { |
||||
|
if (res) setTableData([res]); |
||||
|
}); |
||||
|
} else { |
||||
|
fetchJDGZtableSqSp({ jdgzId: id, sysToken }).then((res) => { |
||||
|
const source = []; |
||||
|
res?.forEach((item) => { |
||||
|
source.push({ ...item, ...JSON.parse(item?.ywSj) }); |
||||
|
}); |
||||
|
if (res) setTableData(source); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
useEffect(() => { |
||||
|
fetchJDGZInfo({ pfId: id, sysToken }).then((res) => { |
||||
|
setTimeLine(res?.data); |
||||
|
handleClickTimeline(res?.data[0]); |
||||
|
}); |
||||
|
}, []); |
||||
|
|
||||
|
const renderTimeLineItem = (list) => { |
||||
|
return list?.map((item) => { |
||||
|
return ( |
||||
|
<Timeline.Item key={item.id} onClick={() => handleClickTimeline(item)}> |
||||
|
<Row> |
||||
|
<Col span={6}> |
||||
|
<div>{item?.sj}</div> |
||||
|
<div>{item?.dwMc}</div> |
||||
|
<div>{getJDLX(item?.lx)?.name}</div> |
||||
|
</Col> |
||||
|
<Col span={18}> |
||||
|
{item.id === nowId ? ( |
||||
|
<Table |
||||
|
scroll={{ x: tWidth }} |
||||
|
columns={tColumns} |
||||
|
rowKey={(record) => record.id} |
||||
|
dataSource={tableData} |
||||
|
pagination={false} |
||||
|
/> |
||||
|
) : null} |
||||
|
</Col> |
||||
|
</Row> |
||||
|
</Timeline.Item> |
||||
|
); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
return ( |
||||
|
<Card title="进度跟踪"> |
||||
|
<Timeline>{timeLine?.length && renderTimeLineItem(timeLine)}</Timeline> |
||||
|
</Card> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
const mapStateToProps = ({ doing }) => ({ |
||||
|
...doing, |
||||
|
}); |
||||
|
const mapDispatchToProps = (dispatch) => ({ |
||||
|
fetchJDGZInfo(params) { |
||||
|
return dispatch({ type: 'doing/fetchJDGZInfo', payload: { ...params } }); |
||||
|
}, |
||||
|
fetchJDGZtableSqSp(params) { |
||||
|
return dispatch({ type: 'doing/fetchJDGZtableSqSp', payload: { ...params } }); |
||||
|
}, |
||||
|
fetchJDGZtableCh(params) { |
||||
|
return dispatch({ type: 'doing/fetchJDGZtableCh', payload: { ...params } }); |
||||
|
}, |
||||
|
fetchJDGZtableAjhcz(params) { |
||||
|
return dispatch({ type: 'doing/fetchJDGZtableAjhcz', payload: { ...params } }); |
||||
|
}, |
||||
|
fetchDownloadFile(params) { |
||||
|
return dispatch({ type: 'doing/fetchDownloadFile', payload: { ...params } }); |
||||
|
}, |
||||
|
}); |
||||
|
export default connect(mapStateToProps, mapDispatchToProps)(JDGZ); |
||||
@ -0,0 +1 @@ |
|||||
|
|
||||
@ -0,0 +1,32 @@ |
|||||
|
import React from 'react'; |
||||
|
|
||||
|
import { FileDoneOutlined, FileExcelOutlined, BulbFilled } from '@ant-design/icons'; |
||||
|
import { YQQK } from '@/utils/constants'; |
||||
|
|
||||
|
export const HGIcon = <FileDoneOutlined style={{ marginRight: 10, color: '#1AB58F' }} />; |
||||
|
|
||||
|
export const BHGIcon = <FileExcelOutlined style={{ marginRight: 10, color: '#FF704F' }} /> |
||||
|
|
||||
|
export const ExampleBar = () => { |
||||
|
return <div style={{ marginRight: 20, marginTop: 3}}> |
||||
|
{HGIcon}<span style={{ marginRight: 15}}>抽查合格</span> |
||||
|
{BHGIcon}<span style={{ marginRight: 15}}>抽查不合格</span> |
||||
|
</div> |
||||
|
} |
||||
|
|
||||
|
export const getHGIcons = (type) => { |
||||
|
if (type === 1) return HGIcon; |
||||
|
if (type === 0) return BHGIcon; |
||||
|
return <span style={{display: 'inline-block', width: 24, height: 14 }}></span> |
||||
|
} |
||||
|
|
||||
|
export const getTimeLine = (type) => { |
||||
|
if (type === YQQK.CQ.value) { |
||||
|
return <BulbFilled style={{ color: YQQK.CQ.color}} /> |
||||
|
} if (type === YQQK.JCQ.value) { |
||||
|
return <BulbFilled style={{ color: YQQK.JCQ.color}} /> |
||||
|
} if (type === YQQK.ZC.value) { |
||||
|
return <BulbFilled style={{ color: YQQK.ZC.color}} /> |
||||
|
} |
||||
|
return '' |
||||
|
} |
||||
@ -0,0 +1 @@ |
|||||
|
自动派发 |
||||
@ -0,0 +1,207 @@ |
|||||
|
import React, { useEffect, useState } from 'react'; |
||||
|
import { TreeSelect, Form, } from 'antd'; |
||||
|
// import _ from 'lodash';
|
||||
|
import { connect } from 'umi'; |
||||
|
|
||||
|
const { TreeNode } = TreeSelect; |
||||
|
/* |
||||
|
*受理时的下级单位;列表上部搜索的涉案单位,当前办理单位 |
||||
|
*下级单位有可能需要回显,也有可能跨级回显 |
||||
|
*列表上部搜索中用到的需要用自己来当根节点,在办列表中’当前办理单位‘这个字段可能有回显来展示消息调整来的页面 |
||||
|
*selfRoot:布尔值 true 需要用自己的信息当作根节点,当用在列表上部搜索时有这个需求,否则就需要用当前登陆人code来查下级单位 |
||||
|
*noLoad: 布尔值 不允许下钻树节点 办理方式 督办不允许下钻,转办可以下钻 |
||||
|
*multiple 布尔值 可以多选 当用在列表上部搜索时有这个需求 |
||||
|
*/ |
||||
|
|
||||
|
const NextOrg = (props) => { |
||||
|
const { user, selfRoot, noLoad, defaultVal, multiple, fetchOrgList, fetchOrgBranch } = props; |
||||
|
|
||||
|
const selfTreeData = [ |
||||
|
{ |
||||
|
code: user?.departmentCode ?? '', |
||||
|
name: user?.departmentName ?? '', |
||||
|
orgLevel: user?.departmentOrgLevel ?? '', |
||||
|
isLeaf: user?.departmentOrgLevel ?? '' === 3, |
||||
|
}, |
||||
|
]; |
||||
|
|
||||
|
const [treeList, setTreeList] = useState(selfRoot ? selfTreeData : []); |
||||
|
const [form] = Form.useForm(); |
||||
|
const [loadMoreOrg, setLoadMoreOrg] = useState([]); |
||||
|
const [treeValue, setTreeValue] = useState(defaultVal); |
||||
|
const [hited, setHited] = useState(false); // 第一次查询默认值是否命中
|
||||
|
|
||||
|
|
||||
|
const loopChildren = (key, list, appendList) => { |
||||
|
return list.map(item => { |
||||
|
const obj = { ...item }; |
||||
|
if (item.code === key) { |
||||
|
if (appendList.length > 0) { |
||||
|
obj.children = appendList; |
||||
|
} else { |
||||
|
obj.isLeaf = true; |
||||
|
} |
||||
|
} else if (item.children) { |
||||
|
obj.children = loopChildren(key, item.children, appendList); |
||||
|
} |
||||
|
return obj; |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
const onLoadData = treeNode => { |
||||
|
/* eslint-disable */ |
||||
|
return new Promise(resolve => { |
||||
|
if (treeNode?.props?.children) { |
||||
|
resolve(); |
||||
|
return; |
||||
|
} |
||||
|
const { key } = treeNode; |
||||
|
|
||||
|
fetchOrgList(key).then(res => { |
||||
|
const newObj = treeList.map(item => { |
||||
|
const obj = { ...item }; |
||||
|
if (item.code === key) { |
||||
|
if (res.length > 0) { |
||||
|
obj.children = res; |
||||
|
} else { |
||||
|
obj.isLeaf = true; |
||||
|
} |
||||
|
} else if (item.children) { |
||||
|
obj.children = loopChildren(key, item.children, res); |
||||
|
} |
||||
|
return obj; |
||||
|
}); |
||||
|
setTreeList(newObj); |
||||
|
resolve(); |
||||
|
}) |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
const getHit = (data) => { |
||||
|
if (defaultVal) { // 如果有默认值 要回显
|
||||
|
if (!data.some((item) => item.code === defaultVal)) { // 回显的值和当前级别没有匹配的 需要向下查询 来正确回显
|
||||
|
fetchOrgBranch(defaultVal).then(res => { // 获取到需要回显的层级路径
|
||||
|
const nowIndex = res.findIndex((item) => item.code === user?.departmentCode ?? ''); |
||||
|
const paths = res.slice(nowIndex + 1); |
||||
|
setLoadMoreOrg(paths); |
||||
|
}); |
||||
|
} else { |
||||
|
setHited(true); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
const getOrgList = () => { |
||||
|
if (treeList.length === 0) { // 初始没有, 需要查询
|
||||
|
fetchOrgList(user?.departmentCode ?? '').then(data => { // 查询树的第一层
|
||||
|
setTreeList(data); |
||||
|
getHit(data); |
||||
|
}); |
||||
|
} else { // 已经查询过 但是defatVal当时没有更新
|
||||
|
getHit(treeList); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
useEffect(() => { |
||||
|
// 因为有时defaultVal 赋值迟缓导致实际有值却是传过来undefined,导致getOrgList方法运算中defaultVal 为undefined,这样就无法继续查询匹配
|
||||
|
if (treeValue === undefined && defaultVal && typeof defaultVal === 'string' && !hited) { |
||||
|
getOrgList(); |
||||
|
} |
||||
|
setTreeValue(defaultVal); |
||||
|
return () => { |
||||
|
// cleanup
|
||||
|
} |
||||
|
}, [defaultVal]); |
||||
|
|
||||
|
useEffect(() => { |
||||
|
if (!selfRoot) { // 自己不是根节点,需要查询第一层数据
|
||||
|
getOrgList(); |
||||
|
} |
||||
|
return () => { |
||||
|
// cleanup
|
||||
|
} |
||||
|
}, []); |
||||
|
|
||||
|
useEffect(() => { // 查询更深的回显路径
|
||||
|
if (loadMoreOrg.length > 0) { |
||||
|
onLoadData({ key: loadMoreOrg[0].code, orgLevel: loadMoreOrg[0].orgLevel }).then(() => { |
||||
|
const paths = loadMoreOrg.slice(1); |
||||
|
setLoadMoreOrg(paths); |
||||
|
}) |
||||
|
} |
||||
|
return () => { |
||||
|
// cleanup
|
||||
|
} |
||||
|
}, [loadMoreOrg]); |
||||
|
|
||||
|
const loop = data => { |
||||
|
if (!data) return; |
||||
|
const list = data.map(item => { |
||||
|
if (item.children) { |
||||
|
return ( |
||||
|
<TreeNode |
||||
|
key={item.code} |
||||
|
value={item.code} |
||||
|
title={item.name} |
||||
|
orgLevel={item.orgLevel} |
||||
|
isLeaf={item.isLeaf || noLoad || item.orgLevel === 3} |
||||
|
> |
||||
|
{loop(item.children)} |
||||
|
</TreeNode> |
||||
|
); |
||||
|
} |
||||
|
return ( |
||||
|
<TreeNode |
||||
|
key={item.code} |
||||
|
value={item.code} |
||||
|
orgLevel={item.orgLevel} |
||||
|
title={item.name} |
||||
|
isLeaf={item.isLeaf || noLoad || item.orgLevel === 3} |
||||
|
/> |
||||
|
); |
||||
|
}) |
||||
|
return list; |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
|
||||
|
const onChange = (value, lable) => { |
||||
|
setTreeValue(value); |
||||
|
if (multiple) { |
||||
|
props.onChange({ bm: value, mc: lable }); |
||||
|
} else { |
||||
|
props.onChange({ bm: value, mc: lable[0] }); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return ( |
||||
|
<TreeSelect |
||||
|
multiple={multiple} |
||||
|
style={{ width: '100%' }} |
||||
|
dropdownStyle={{ overflow: 'auto' }} |
||||
|
allowClear |
||||
|
onChange={onChange} |
||||
|
loadData={noLoad ? null : onLoadData} |
||||
|
value={treeValue} |
||||
|
> |
||||
|
{loop(treeList)} |
||||
|
</TreeSelect> |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
const mapStateToProps = ({ user, global }) => ({ |
||||
|
user: user.currentUser, |
||||
|
global, |
||||
|
}); |
||||
|
const mapDispatchToProps = dispatch => ({ |
||||
|
// 查询审批人列表
|
||||
|
fetchOrgList(params) { |
||||
|
return dispatch({ type: 'global/fetchOrgList', payload: params }); |
||||
|
}, |
||||
|
fetchOrgBranch(params) { |
||||
|
return dispatch({ type: 'global/fetchOrgBranch', payload: params }); |
||||
|
}, |
||||
|
}); |
||||
|
export default connect(mapStateToProps, mapDispatchToProps)(NextOrg); |
||||
@ -0,0 +1,97 @@ |
|||||
|
import { Avatar, List } from 'antd'; |
||||
|
import React from 'react'; |
||||
|
import classNames from 'classnames'; |
||||
|
import styles from './NoticeList.less'; |
||||
|
|
||||
|
const NoticeList = ({ |
||||
|
data = [], |
||||
|
onClick, |
||||
|
onClear, |
||||
|
title, |
||||
|
onViewMore, |
||||
|
emptyText, |
||||
|
showClear = true, |
||||
|
clearText, |
||||
|
viewMoreText, |
||||
|
showViewMore = false, |
||||
|
}) => { |
||||
|
if (!data || data.length === 0) { |
||||
|
return ( |
||||
|
<div className={styles.notFound}> |
||||
|
<img |
||||
|
src="https://gw.alipayobjects.com/zos/rmsportal/sAuJeJzSKbUmHfBQRzmZ.svg" |
||||
|
alt="not found" |
||||
|
/> |
||||
|
<div>{emptyText}</div> |
||||
|
</div> |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
return ( |
||||
|
<div> |
||||
|
<List |
||||
|
className={styles.list} |
||||
|
dataSource={data} |
||||
|
renderItem={(item, i) => { |
||||
|
const itemCls = classNames(styles.item, { |
||||
|
[styles.read]: item.read, |
||||
|
}); // eslint-disable-next-line no-nested-ternary |
||||
|
|
||||
|
const leftIcon = item.avatar ? ( |
||||
|
typeof item.avatar === 'string' ? ( |
||||
|
<Avatar className={styles.avatar} src={item.avatar} /> |
||||
|
) : ( |
||||
|
<span className={styles.iconElement}>{item.avatar}</span> |
||||
|
) |
||||
|
) : null; |
||||
|
return ( |
||||
|
<List.Item |
||||
|
className={itemCls} |
||||
|
key={item.key || i} |
||||
|
onClick={() => { |
||||
|
onClick?.(item); |
||||
|
}} |
||||
|
> |
||||
|
<List.Item.Meta |
||||
|
className={styles.meta} |
||||
|
avatar={leftIcon} |
||||
|
title={ |
||||
|
<div className={styles.title}> |
||||
|
{item.title} |
||||
|
<div className={styles.extra}>{item.extra}</div> |
||||
|
</div> |
||||
|
} |
||||
|
description={ |
||||
|
<div> |
||||
|
<div className={styles.description}>{item.description}</div> |
||||
|
<div className={styles.datetime}>{item.datetime}</div> |
||||
|
</div> |
||||
|
} |
||||
|
/> |
||||
|
</List.Item> |
||||
|
); |
||||
|
}} |
||||
|
/> |
||||
|
<div className={styles.bottomBar}> |
||||
|
{showClear ? ( |
||||
|
<div onClick={onClear}> |
||||
|
{clearText} {title} |
||||
|
</div> |
||||
|
) : null} |
||||
|
{showViewMore ? ( |
||||
|
<div |
||||
|
onClick={e => { |
||||
|
if (onViewMore) { |
||||
|
onViewMore(e); |
||||
|
} |
||||
|
}} |
||||
|
> |
||||
|
{viewMoreText} |
||||
|
</div> |
||||
|
) : null} |
||||
|
</div> |
||||
|
</div> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
export default NoticeList; |
||||
@ -0,0 +1,103 @@ |
|||||
|
@import '~antd/es/style/themes/default.less'; |
||||
|
|
||||
|
.list { |
||||
|
max-height: 400px; |
||||
|
overflow: auto; |
||||
|
&::-webkit-scrollbar { |
||||
|
display: none; |
||||
|
} |
||||
|
.item { |
||||
|
padding-right: 24px; |
||||
|
padding-left: 24px; |
||||
|
overflow: hidden; |
||||
|
cursor: pointer; |
||||
|
transition: all 0.3s; |
||||
|
|
||||
|
.meta { |
||||
|
width: 100%; |
||||
|
} |
||||
|
|
||||
|
.avatar { |
||||
|
margin-top: 4px; |
||||
|
background: @component-background; |
||||
|
} |
||||
|
.iconElement { |
||||
|
font-size: 32px; |
||||
|
} |
||||
|
|
||||
|
&.read { |
||||
|
opacity: 0.4; |
||||
|
} |
||||
|
&:last-child { |
||||
|
border-bottom: 0; |
||||
|
} |
||||
|
&:hover { |
||||
|
background: @primary-1; |
||||
|
} |
||||
|
.title { |
||||
|
margin-bottom: 8px; |
||||
|
font-weight: normal; |
||||
|
} |
||||
|
.description { |
||||
|
font-size: 12px; |
||||
|
line-height: @line-height-base; |
||||
|
} |
||||
|
.datetime { |
||||
|
margin-top: 4px; |
||||
|
font-size: 12px; |
||||
|
line-height: @line-height-base; |
||||
|
} |
||||
|
.extra { |
||||
|
float: right; |
||||
|
margin-top: -1.5px; |
||||
|
margin-right: 0; |
||||
|
color: @text-color-secondary; |
||||
|
font-weight: normal; |
||||
|
} |
||||
|
} |
||||
|
.loadMore { |
||||
|
padding: 8px 0; |
||||
|
color: @primary-6; |
||||
|
text-align: center; |
||||
|
cursor: pointer; |
||||
|
&.loadedAll { |
||||
|
color: rgba(0, 0, 0, 0.25); |
||||
|
cursor: unset; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.notFound { |
||||
|
padding: 73px 0 88px; |
||||
|
color: @text-color-secondary; |
||||
|
text-align: center; |
||||
|
img { |
||||
|
display: inline-block; |
||||
|
height: 76px; |
||||
|
margin-bottom: 16px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.bottomBar { |
||||
|
height: 46px; |
||||
|
color: @text-color; |
||||
|
line-height: 46px; |
||||
|
text-align: center; |
||||
|
border-top: 1px solid @border-color-split; |
||||
|
border-radius: 0 0 @border-radius-base @border-radius-base; |
||||
|
transition: all 0.3s; |
||||
|
div { |
||||
|
display: inline-block; |
||||
|
width: 50%; |
||||
|
cursor: pointer; |
||||
|
transition: all 0.3s; |
||||
|
user-select: none; |
||||
|
|
||||
|
&:only-child { |
||||
|
width: 100%; |
||||
|
} |
||||
|
&:not(:only-child):last-child { |
||||
|
border-left: 1px solid @border-color-split; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,119 @@ |
|||||
|
import { BellOutlined } from '@ant-design/icons'; |
||||
|
import { Badge, Spin, Tabs } from 'antd'; |
||||
|
import useMergedState from 'rc-util/es/hooks/useMergedState'; |
||||
|
import React from 'react'; |
||||
|
import classNames from 'classnames'; |
||||
|
import NoticeList from './NoticeList'; |
||||
|
import HeaderDropdown from '../HeaderDropdown'; |
||||
|
import styles from './index.less'; |
||||
|
|
||||
|
const { TabPane } = Tabs; |
||||
|
|
||||
|
const NoticeIcon = props => { |
||||
|
const getNotificationBox = () => { |
||||
|
const { |
||||
|
children, |
||||
|
loading, |
||||
|
onClear, |
||||
|
onTabChange, |
||||
|
onItemClick, |
||||
|
onViewMore, |
||||
|
clearText, |
||||
|
viewMoreText, |
||||
|
} = props; |
||||
|
|
||||
|
if (!children) { |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
const panes = []; |
||||
|
React.Children.forEach(children, child => { |
||||
|
if (!child) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
const { list, title, count, tabKey, showClear, showViewMore } = child.props; |
||||
|
const len = list && list.length ? list.length : 0; |
||||
|
const msgCount = count || count === 0 ? count : len; |
||||
|
const tabTitle = msgCount > 0 ? `${title} (${msgCount})` : title; |
||||
|
panes.push( |
||||
|
<TabPane tab={tabTitle} key={tabKey}> |
||||
|
<NoticeList |
||||
|
{...child.props} |
||||
|
clearText={clearText} |
||||
|
viewMoreText={viewMoreText} |
||||
|
data={list} |
||||
|
onClear={() => { |
||||
|
onClear?.(title, tabKey); |
||||
|
}} |
||||
|
onClick={item => { |
||||
|
onItemClick?.(item, child.props); |
||||
|
}} |
||||
|
onViewMore={event => { |
||||
|
onViewMore?.(child.props, event); |
||||
|
}} |
||||
|
showClear={showClear} |
||||
|
showViewMore={showViewMore} |
||||
|
title={title} |
||||
|
/> |
||||
|
</TabPane>, |
||||
|
); |
||||
|
}); |
||||
|
return ( |
||||
|
<Spin spinning={loading} delay={300}> |
||||
|
<Tabs className={styles.tabs} onChange={onTabChange}> |
||||
|
{panes} |
||||
|
</Tabs> |
||||
|
</Spin> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
const { className, count, bell } = props; |
||||
|
const [visible, setVisible] = useMergedState(false, { |
||||
|
value: props.popupVisible, |
||||
|
onChange: props.onPopupVisibleChange, |
||||
|
}); |
||||
|
const noticeButtonClass = classNames(className, styles.noticeButton); |
||||
|
const notificationBox = getNotificationBox(); |
||||
|
const NoticeBellIcon = bell || <BellOutlined className={styles.icon} />; |
||||
|
const trigger = ( |
||||
|
<span |
||||
|
className={classNames(noticeButtonClass, { |
||||
|
opened: visible, |
||||
|
})} |
||||
|
> |
||||
|
<Badge |
||||
|
count={count} |
||||
|
style={{ |
||||
|
boxShadow: 'none', |
||||
|
}} |
||||
|
className={styles.badge} |
||||
|
> |
||||
|
{NoticeBellIcon} |
||||
|
</Badge> |
||||
|
</span> |
||||
|
); |
||||
|
|
||||
|
if (!notificationBox) { |
||||
|
return trigger; |
||||
|
} |
||||
|
|
||||
|
return ( |
||||
|
<HeaderDropdown |
||||
|
placement="bottomRight" |
||||
|
overlay={notificationBox} |
||||
|
overlayClassName={styles.popover} |
||||
|
trigger={['click']} |
||||
|
visible={visible} |
||||
|
onVisibleChange={setVisible} |
||||
|
> |
||||
|
{trigger} |
||||
|
</HeaderDropdown> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
NoticeIcon.defaultProps = { |
||||
|
emptyImage: 'https://gw.alipayobjects.com/zos/rmsportal/wAhyIChODzsoKIOBHcBk.svg', |
||||
|
}; |
||||
|
NoticeIcon.Tab = NoticeList; |
||||
|
export default NoticeIcon; |
||||
@ -0,0 +1,35 @@ |
|||||
|
@import '~antd/es/style/themes/default.less'; |
||||
|
|
||||
|
.popover { |
||||
|
position: relative; |
||||
|
width: 336px; |
||||
|
} |
||||
|
|
||||
|
.noticeButton { |
||||
|
display: inline-block; |
||||
|
cursor: pointer; |
||||
|
transition: all 0.3s; |
||||
|
} |
||||
|
.icon { |
||||
|
padding: 4px; |
||||
|
vertical-align: middle; |
||||
|
} |
||||
|
|
||||
|
.badge { |
||||
|
font-size: 16px; |
||||
|
} |
||||
|
|
||||
|
.tabs { |
||||
|
:global { |
||||
|
.ant-tabs-nav-list { |
||||
|
margin: auto; |
||||
|
} |
||||
|
|
||||
|
.ant-tabs-nav-scroll { |
||||
|
text-align: center; |
||||
|
} |
||||
|
.ant-tabs-bar { |
||||
|
margin-bottom: 0; |
||||
|
} |
||||
|
} |
||||
|
} |
||||