forked from Gitlink/forgeplus-react
Merge pull request '新版后台管理' (#390) from tongChong/forgeplus-react:dev_military_admin into pre_dev_military
This commit is contained in:
commit
fa57794270
|
|
@ -104,6 +104,7 @@ module.exports = {
|
|||
src: path.join(paths.appSrc), // 整个源代码目录
|
||||
forge: path.join(paths.appSrc, 'forge'),
|
||||
military: path.join(paths.appSrc, 'military'),
|
||||
components: path.join(paths.appSrc, 'components'),
|
||||
// Support React Native Web
|
||||
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
|
||||
"react-native": "react-native-web",
|
||||
|
|
|
|||
|
|
@ -19,7 +19,9 @@ const getClientEnvironment = require("./env");
|
|||
|
||||
let publicPath = "/react/build/";
|
||||
const publicUrl = publicPath.slice(0, -1);
|
||||
const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== "false";
|
||||
// const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== "false";
|
||||
const shouldUseSourceMap = process.env.NODE_ENV !== "production";
|
||||
|
||||
const env = getClientEnvironment(publicPath);
|
||||
|
||||
// This is the production configuration.
|
||||
|
|
@ -54,7 +56,8 @@ module.exports = {
|
|||
},
|
||||
bail: true,
|
||||
mode: "production",
|
||||
devtool: false, //测试版
|
||||
// devtool: false, //测试版
|
||||
devtool: shouldUseSourceMap?'source-map':false,
|
||||
entry: [require.resolve("./polyfills"), paths.appIndexJs],
|
||||
output: {
|
||||
path: paths.appBuild,
|
||||
|
|
@ -90,6 +93,7 @@ module.exports = {
|
|||
src: path.join(paths.appSrc),
|
||||
forge: path.join(paths.appSrc, 'forge'),
|
||||
military: path.join(paths.appSrc, 'military'),
|
||||
components: path.join(paths.appSrc, 'components'),
|
||||
// Support React Native Web
|
||||
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
|
||||
"react-native": "react-native-web",
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
"educoder": ["./src/common/educoder.js"],
|
||||
"forge":["./src/forge"],
|
||||
"military":["./src/military"],
|
||||
"components":["./src/components"],
|
||||
}
|
||||
},
|
||||
"exclude": [
|
||||
|
|
|
|||
|
|
@ -265,17 +265,17 @@
|
|||
}
|
||||
},
|
||||
"@babel/runtime-corejs3": {
|
||||
"version": "7.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.16.0.tgz",
|
||||
"integrity": "sha512-Oi2qwQ21X7/d9gn3WiwkDTJmq3TQtYNz89lRnoFy8VeZpWlsyXvzSwiRrRZ8cXluvSwqKxqHJ6dBd9Rv+p0ZGQ==",
|
||||
"version": "7.17.2",
|
||||
"resolved": "http://173.15.15.82:8081/repository/npm-all/@babel/runtime-corejs3/-/runtime-corejs3-7.17.2.tgz",
|
||||
"integrity": "sha512-NcKtr2epxfIrNM4VOmPKO46TvDMCBhgi2CrSHaEarrz+Plk2K5r9QemmOFTGpZaoKnWoGH5MO+CzeRsih/Fcgg==",
|
||||
"requires": {
|
||||
"core-js-pure": "^3.19.0",
|
||||
"core-js-pure": "^3.20.2",
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"regenerator-runtime": {
|
||||
"version": "0.13.9",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
|
||||
"resolved": "http://173.15.15.82:8081/repository/npm-all/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
|
||||
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
|
||||
}
|
||||
}
|
||||
|
|
@ -3969,9 +3969,9 @@
|
|||
"integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ=="
|
||||
},
|
||||
"core-js-pure": {
|
||||
"version": "3.19.1",
|
||||
"resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.19.1.tgz",
|
||||
"integrity": "sha512-Q0Knr8Es84vtv62ei6/6jXH/7izKmOrtrxH9WJTHLCMAVeU+8TF8z8Nr08CsH4Ot0oJKzBzJJL9SJBYIv7WlfQ=="
|
||||
"version": "3.21.1",
|
||||
"resolved": "http://173.15.15.82:8081/repository/npm-all/core-js-pure/-/core-js-pure-3.21.1.tgz",
|
||||
"integrity": "sha512-12VZfFIu+wyVbBebyHmRTuEE/tZrB4tJToWcwAMcsp3h4+sHR+fMJWbKpYiCRWlhFBq+KNyO8rIV9rTkeVmznQ=="
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
|
|
@ -19402,9 +19402,9 @@
|
|||
}
|
||||
},
|
||||
"wangeditor": {
|
||||
"version": "4.7.7",
|
||||
"resolved": "https://registry.npmjs.org/wangeditor/-/wangeditor-4.7.7.tgz",
|
||||
"integrity": "sha512-eUpgP7i4pCYIjxjGMMcSUtkHUCkdX7BBwLZE6umseoK9hs3qIMu1tQ95FG48NJwL71JyAjt5c1gB56PzducL3Q==",
|
||||
"version": "4.7.12",
|
||||
"resolved": "http://173.15.15.82:8081/repository/npm-all/wangeditor/-/wangeditor-4.7.12.tgz",
|
||||
"integrity": "sha512-5KOIpQ0+idKvDTkjZOp7RHYXA97FyJ9mjwy+zQUdMUCqZItlEXzvVOYtOlHkJr/HcbwgIz/7f/trGFggZK5X4g==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.11.2",
|
||||
"@babel/runtime-corejs3": "^7.11.2",
|
||||
|
|
@ -19412,38 +19412,26 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": {
|
||||
"version": "7.15.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.3.tgz",
|
||||
"integrity": "sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA==",
|
||||
"version": "7.17.2",
|
||||
"resolved": "http://173.15.15.82:8081/repository/npm-all/@babel/runtime/-/runtime-7.17.2.tgz",
|
||||
"integrity": "sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==",
|
||||
"requires": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
}
|
||||
},
|
||||
"regenerator-runtime": {
|
||||
"version": "0.13.9",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
|
||||
"resolved": "http://173.15.15.82:8081/repository/npm-all/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
|
||||
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"wangeditor-for-react": {
|
||||
"version": "1.5.3",
|
||||
"resolved": "https://registry.npmjs.org/wangeditor-for-react/-/wangeditor-for-react-1.5.3.tgz",
|
||||
"integrity": "sha512-nnfZW6leWrVP5UFLEl93UmquSxgfkMpRM45nRusuA/QA+OPIKh0+JW4ZSmSjpmolhT8//iyQOry1I5EuVFwgog==",
|
||||
"version": "1.5.6",
|
||||
"resolved": "http://173.15.15.82:8081/repository/npm-all/wangeditor-for-react/-/wangeditor-for-react-1.5.6.tgz",
|
||||
"integrity": "sha512-FLxU4K6PXc9AS3SFfU7vZhUR+EpUEWUVraFPRUiSH9VSzt9jLO9fp4IyReT7ebbp/YaMKXHhN5JLu2v2/zvNrA==",
|
||||
"requires": {
|
||||
"react": "^17.0.2",
|
||||
"wangeditor": "^4.7.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": {
|
||||
"version": "17.0.2",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz",
|
||||
"integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==",
|
||||
"requires": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1"
|
||||
}
|
||||
}
|
||||
"wangeditor": "^4.7.12"
|
||||
}
|
||||
},
|
||||
"warning": {
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@
|
|||
"styled-components": "^4.4.1",
|
||||
"sw-precache-webpack-plugin": "0.11.4",
|
||||
"url-loader": "0.6.2",
|
||||
"wangeditor-for-react": "^1.4.0",
|
||||
"wangeditor-for-react": "^1.5.6",
|
||||
"webpack-cli": "^3.3.11",
|
||||
"webpack-dev-server": "^3.10.3",
|
||||
"webpack-manifest-plugin": "^2.2.0",
|
||||
|
|
|
|||
|
|
@ -1,14 +1,9 @@
|
|||
@font-face {
|
||||
font-family: "iconfont"; /* Project id 2340181 */
|
||||
<<<<<<< HEAD
|
||||
src: url('iconfont.woff2?t=1644907653340') format('woff2'),
|
||||
url('iconfont.woff?t=1644907653340') format('woff'),
|
||||
url('iconfont.ttf?t=1644907653340') format('truetype');
|
||||
=======
|
||||
src: url('iconfont.woff2?t=1648801178933') format('woff2'),
|
||||
url('iconfont.woff?t=1648801178933') format('woff'),
|
||||
url('iconfont.ttf?t=1648801178933') format('truetype');
|
||||
>>>>>>> a58c7403 (修改样式)
|
||||
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
|
|
@ -19,8 +14,6 @@
|
|||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
.icon-kaiyuanxiangmu:before {
|
||||
content: "\e91d";
|
||||
}
|
||||
|
|
@ -93,7 +86,6 @@
|
|||
content: "\e915";
|
||||
}
|
||||
|
||||
>>>>>>> a58c7403 (修改样式)
|
||||
.icon-icon2:before {
|
||||
content: "\e912";
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -6,8 +6,6 @@
|
|||
"description": "",
|
||||
"glyphs": [
|
||||
{
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
"icon_id": "28163416",
|
||||
"name": "开源项目",
|
||||
"font_class": "kaiyuanxiangmu",
|
||||
|
|
@ -134,7 +132,7 @@
|
|||
"unicode_decimal": 59669
|
||||
},
|
||||
{
|
||||
>>>>>>> a58c7403 (修改样式)
|
||||
|
||||
"icon_id": "27299393",
|
||||
"name": "icon",
|
||||
"font_class": "icon2",
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
10
src/App.js
10
src/App.js
|
|
@ -137,7 +137,7 @@ const AboutUs = Loadable({
|
|||
|
||||
// 管理页面
|
||||
const Managements = Loadable({
|
||||
loader: () => import('./military/managements'),
|
||||
loader: () => import('./managements/index'),
|
||||
loading: Loading,
|
||||
})
|
||||
// const CreateMerge = Loadable({
|
||||
|
|
@ -146,7 +146,7 @@ const Managements = Loadable({
|
|||
// })
|
||||
|
||||
// 此处仅维护前端可能的一级路由,不用进行项目或者组织判断的字段。
|
||||
const keyWord = ["explore", "settings", "setting", "mulan", "wiki", "issues", "setting", "trending", "code", "projects", "pulls", "mine", "login", "register", "email", "export", "nopage", "404", "403", "500", "501", "search", "organize", "login", "register", "resetPassword", "aboutus","educoder","task","notice","managements","expert","competition"];
|
||||
const keyWord = ["explore", "settings", "setting", "mulan", "wiki", "issues", "setting", "trending", "code", "projects", "pulls", "mine", "login", "register", "email", "export", "nopage", "404", "403", "500", "501", "search", "organize", "login", "register", "resetPassword", "aboutus","educoder","task","notice","managements","expert","competition","administration"];
|
||||
|
||||
class App extends Component {
|
||||
constructor(props) {
|
||||
|
|
@ -405,8 +405,12 @@ class App extends Component {
|
|||
path="/register"
|
||||
render={(props) =><LoginRegisterPage {...this.props} {...props}/>}
|
||||
></Route>
|
||||
{/*管理页面*/}
|
||||
|
||||
{/*管理页面 三个路由,分别对应本环境管理、原测试ruby模板管理、原项目管理*/}
|
||||
<Route path="/managements" component={Managements} />
|
||||
<Route path="/admin" component={Managements} />
|
||||
<Route path="/administration" component={Managements} />
|
||||
|
||||
|
||||
{/*403*/}
|
||||
<Route path="/403" component={Shixunauthority} />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,125 @@
|
|||
/* eslint-disable react/jsx-no-duplicate-props */
|
||||
import React, { useState } from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
import { Modal, Button } from 'antd';
|
||||
import './index.scss';
|
||||
|
||||
// 函数式调用删除、通知等模态框
|
||||
|
||||
InitModal.defaultProps = {
|
||||
okText: '确认', //确定按钮的文字
|
||||
cancelText: '取消', //取消按钮的文字
|
||||
className: '', //传入的模态框类名
|
||||
inputId: 'copyText', //要复制的文本的ID
|
||||
onCancel:()=>{}, //取消的回调
|
||||
onOk:()=>{}, //确认的回调
|
||||
title:'提示', //模态框名字
|
||||
contentTitle:'', //内容标题
|
||||
content:'', //详细内容
|
||||
afterClose:()=>{}, //关闭模态框以后的回调
|
||||
};
|
||||
|
||||
// 使用函数调用删除组件
|
||||
export default function DelModal(props) {
|
||||
renderModal({ ...props, type: 'delete' })
|
||||
}
|
||||
|
||||
// 使用函数调用选择模态框组件
|
||||
export function Confirm(props) {
|
||||
renderModal({ ...props, type: 'confirm' })
|
||||
}
|
||||
|
||||
function renderModal(props) {
|
||||
const { type, afterClose } = props;
|
||||
const div = document.createElement('div');
|
||||
document.body.appendChild(div);
|
||||
|
||||
function destroy() {
|
||||
afterClose && afterClose();
|
||||
const unmountResult = ReactDOM.unmountComponentAtNode(div);
|
||||
if (unmountResult && div.parentNode) {
|
||||
div.parentNode.removeChild(div);
|
||||
}
|
||||
}
|
||||
|
||||
function modalType(type) {
|
||||
if (type === 'delete') {
|
||||
return <InitModal
|
||||
title="删除"
|
||||
contentTitle="确定要删除吗?"
|
||||
okText="确认删除"
|
||||
{...props}
|
||||
|
||||
afterClose={destroy}
|
||||
contentTitle={<React.Fragment>
|
||||
<i className="red-circle iconfont icon-shanchu_tc_icon mr3"></i>
|
||||
{props.contentTitle}
|
||||
</React.Fragment>}
|
||||
/>
|
||||
} else if (type === 'confirm') {
|
||||
return <InitModal title="选择" afterClose={destroy} {...props} />
|
||||
} else {
|
||||
return <InitModal title="选择" afterClose={destroy} {...props} />
|
||||
}
|
||||
}
|
||||
|
||||
function render() {
|
||||
setTimeout(() => {
|
||||
ReactDOM.render(
|
||||
modalType(type),
|
||||
div,
|
||||
);
|
||||
});
|
||||
}
|
||||
render();
|
||||
}
|
||||
|
||||
// 选择模态框组件
|
||||
function InitModal({
|
||||
onCancel,
|
||||
onOk,
|
||||
title,
|
||||
contentTitle,
|
||||
content,
|
||||
okText,
|
||||
cancelText,
|
||||
afterClose,
|
||||
className,
|
||||
}) {
|
||||
|
||||
const [visible, setVisible] = useState(true);
|
||||
|
||||
function onCancelModal() {
|
||||
setVisible(false);
|
||||
onCancel && onCancel()
|
||||
}
|
||||
|
||||
function onSuccess() {
|
||||
setVisible(false);
|
||||
onOk && onOk();
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal
|
||||
visible={visible}
|
||||
onCancel={onCancelModal}
|
||||
afterClose={afterClose}
|
||||
title={title}
|
||||
className={`myself-modal ${className}`}
|
||||
centered
|
||||
footer={[
|
||||
<Button type="default" key="back" onClick={onCancelModal}>
|
||||
{cancelText}
|
||||
</Button>,
|
||||
<Button className="foot-submit" key="submit" onClick={onSuccess}>
|
||||
{okText}
|
||||
</Button>,
|
||||
]}
|
||||
>
|
||||
<div>
|
||||
{contentTitle && <p className="content-title">{contentTitle}</p>}
|
||||
<p className="content-descibe">{content}</p>
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
.myself-modal {
|
||||
.ant-modal-header {
|
||||
padding: 9px 24px;
|
||||
background: #f8f8f8;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
.ant-modal-title {
|
||||
text-align: left;
|
||||
}
|
||||
.ant-modal-close {
|
||||
top: 0px !important;
|
||||
}
|
||||
.ant-modal-close-x {
|
||||
font-size: 24px;
|
||||
}
|
||||
.ant-modal-body {
|
||||
text-align: center;
|
||||
}
|
||||
.content-title {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 2rem 0 1rem !important;
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
letter-spacing: 0;
|
||||
line-height: 29px;
|
||||
font-weight: 400;
|
||||
}
|
||||
.red-circle {
|
||||
align-self: flex-start;
|
||||
color: #ca0002;
|
||||
font-size: 1.5rem !important;
|
||||
}
|
||||
.content-descibe {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
line-height: 33px;
|
||||
font-weight: 400;
|
||||
}
|
||||
.ant-modal-footer {
|
||||
padding: 2rem 0;
|
||||
text-align: center;
|
||||
border: 0;
|
||||
.ant-btn {
|
||||
width: 6rem;
|
||||
}
|
||||
}
|
||||
.foot-submit {
|
||||
margin-left: 3rem;
|
||||
color: #df0002;
|
||||
&:hover {
|
||||
border-color: #df0002;
|
||||
}
|
||||
}
|
||||
.ant-btn-default:hover,
|
||||
.ant-btn-default:active,
|
||||
.ant-btn-default:focus {
|
||||
background: #f3f4f6;
|
||||
color: #333;
|
||||
border-color: #d0d0d0;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
import React from 'react';
|
||||
import { Modal , Button } from 'antd';
|
||||
import './index.scss';
|
||||
|
||||
function Modals({visible,title,content,onOk,onCancel}){
|
||||
return(
|
||||
<Modal
|
||||
className="modalsStyle"
|
||||
visible={visible}
|
||||
title={title}
|
||||
onCancel={onCancel}
|
||||
closable={true}
|
||||
footer={
|
||||
<div>
|
||||
<Button onClick={onCancel}>取消</Button>
|
||||
<Button type={"primary"} style={{marginLeft:"20px"}} onClick={onOk}>确定</Button>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div>{content}</div>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
export default Modals;
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
import React, { Fragment } from 'react';
|
||||
import { Table, Pagination } from 'antd';
|
||||
import './index.scss';
|
||||
|
||||
export default (props) => {
|
||||
const {handleRow, total, setCurPage, current, onShowSizeChange, showSizeChanger, pagination} = props;
|
||||
|
||||
return (
|
||||
<div className='pagination-table'>
|
||||
<Table
|
||||
{...props}
|
||||
pagination={false}
|
||||
onRow={handleRow}
|
||||
/>
|
||||
{total > 10 && (!pagination) &&
|
||||
<Pagination
|
||||
showQuickJumper
|
||||
onShowSizeChange={onShowSizeChange}
|
||||
onChange={setCurPage}
|
||||
current={current}
|
||||
total={total}
|
||||
showSizeChanger={showSizeChanger}
|
||||
/>}
|
||||
</div>
|
||||
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
.pagination-table {
|
||||
margin-top: 1rem;
|
||||
padding: 1.5rem;
|
||||
background-color: #ffffff;
|
||||
box-shadow:0px 0px 10px rgba(88, 116, 255, 0.18);
|
||||
.ant-table {
|
||||
border-radius: 0 0 4px 4px;
|
||||
tr > td{
|
||||
border-bottom: none;
|
||||
border-top: 1px solid #e2e6f5;
|
||||
}
|
||||
tr:first-child > td{border-top: none;}
|
||||
tr:last-child > td{border-bottom: 1px solid #e2e6f5;}
|
||||
.ant-table-expanded-row td{border-top: none;}
|
||||
}
|
||||
.ant-table-thead tr th div {
|
||||
color: #181818;
|
||||
font-weight: 500;
|
||||
}
|
||||
.ant-table-wrapper {
|
||||
::-webkit-scrollbar {
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
}
|
||||
.ant-table-hide-scrollbar {
|
||||
margin-bottom: -5px;
|
||||
overflow-y: hidden !important;
|
||||
::-webkit-scrollbar {
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.ant-pagination {
|
||||
margin: 2rem 1.5rem;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ const { Search } = Input;
|
|||
const LIMIT = 15;
|
||||
function SpecialProject(props){
|
||||
const [ page , setPage] = useState(1);
|
||||
const [ searchValue , SetSearchValue ] = useState(undefined);
|
||||
const [ searchValue , setSearchValue ] = useState(undefined);
|
||||
const [ total , setTotal ] = useState(0);
|
||||
const [ list , setList ] = useState(undefined);
|
||||
const [ status , setStatus ] = useState(undefined);
|
||||
|
|
@ -22,7 +22,7 @@ function SpecialProject(props){
|
|||
setLoading(true);
|
||||
Init(searchValue, status);
|
||||
}
|
||||
},[page,project_id]);
|
||||
},[page, project_id, searchValue]);
|
||||
|
||||
function Init(search,status){
|
||||
const url = `/apply_signatures.json`;
|
||||
|
|
@ -125,9 +125,9 @@ function SpecialProject(props){
|
|||
}).catch(error=>{setLoading(false)})
|
||||
}
|
||||
|
||||
function searchList(){
|
||||
function searchList(value){
|
||||
setSearchValue(value);
|
||||
setLoading(true);
|
||||
Init(searchValue,status);
|
||||
}
|
||||
|
||||
const menu=(
|
||||
|
|
@ -155,9 +155,7 @@ function SpecialProject(props){
|
|||
enterButton="搜索"
|
||||
style={{width:400}}
|
||||
size="middle"
|
||||
value={searchValue}
|
||||
onChange={(e)=>SetSearchValue(e.target.value)}
|
||||
onSearch={searchList}
|
||||
onSearch={(value)=>searchList(value)}
|
||||
/>
|
||||
<Dropdown overlay={menu} placement="bottomRight">
|
||||
<span>
|
||||
|
|
|
|||
|
|
@ -106,52 +106,6 @@
|
|||
line-height: 1.6875em;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
// 首页特定头部样式起
|
||||
|
||||
&.newHeaders {
|
||||
// background-color: #1a2358;
|
||||
background-color: #0037af;
|
||||
z-index: 1000;
|
||||
}
|
||||
.newFooter{
|
||||
background: inherit;
|
||||
}
|
||||
.head-nav {
|
||||
min-width: auto;
|
||||
}
|
||||
.head-nav ul#header-nav li a {
|
||||
font-size: 1em;
|
||||
color: #fff;
|
||||
}
|
||||
.head-nav ul#header-nav li:hover a,
|
||||
.head-nav ul#header-nav li.active a {
|
||||
color: #ffa13a;
|
||||
}
|
||||
.head-nav ul#header-nav li.active a::after {
|
||||
background-color: #ffa13a;
|
||||
}
|
||||
|
||||
.logoDiv img {
|
||||
min-width: 2.8125em;
|
||||
height: 2.8125em;
|
||||
}
|
||||
|
||||
.color-home {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.color-home:hover {
|
||||
color: #4154f1;
|
||||
}
|
||||
|
||||
.register-button {
|
||||
height: 3em;
|
||||
margin-left: 1.25em;
|
||||
padding: 0 1.5625em;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
// 首页特定头部样式止
|
||||
}
|
||||
|
||||
// 波浪样式起
|
||||
|
|
|
|||
|
|
@ -0,0 +1,138 @@
|
|||
import fetch,{main_web_site_url} from './fetch';
|
||||
import { notification } from 'antd';
|
||||
|
||||
// 新增后台菜单
|
||||
export async function createMenu(data){
|
||||
let res = await fetch({
|
||||
url: '/api/menu/create',
|
||||
method: 'post',
|
||||
data,
|
||||
});
|
||||
return res;
|
||||
}
|
||||
//删除后台菜单
|
||||
export async function deleteMenu(menuId){
|
||||
let res = await fetch({
|
||||
url: `/api/menu/delete/${menuId}`,
|
||||
method: 'post',
|
||||
});
|
||||
return res;
|
||||
}
|
||||
//修改菜单状态
|
||||
export async function updateMenuStatus(menuId, hidden){
|
||||
let res = await fetch({
|
||||
url: `/api/menu/updateHidden/${menuId}?hidden=${hidden}`,
|
||||
method: 'post',
|
||||
});
|
||||
return res;
|
||||
}
|
||||
//修改菜单信息
|
||||
export async function updateMenu(menuId, data){
|
||||
let res = await fetch({
|
||||
url: `/api/menu/update/${menuId}`,
|
||||
method: 'post',
|
||||
data,
|
||||
});
|
||||
return res;
|
||||
}
|
||||
// 分页查询后台菜单
|
||||
export async function menuList(parentId,params) {
|
||||
let res = await fetch({
|
||||
url: `/api/menu/list/${parentId}`,
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
return res;
|
||||
}
|
||||
// 树形结构返回所有菜单列表
|
||||
export async function treeList() {
|
||||
let res = await fetch({
|
||||
url: `/api/menu/treeList`,
|
||||
method: 'get',
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
||||
//添加角色
|
||||
export async function createRole(data){
|
||||
let res = await fetch({
|
||||
url: '/api/role/create',
|
||||
method: 'post',
|
||||
data,
|
||||
});
|
||||
return res;
|
||||
}
|
||||
//获取所有角色
|
||||
export async function roleList() {
|
||||
let res = await fetch({
|
||||
url: `/api/role/listAll`,
|
||||
method: 'get',
|
||||
});
|
||||
return res;
|
||||
}
|
||||
//修改角色信息
|
||||
export async function updateRole(roleId, data){
|
||||
let res = await fetch({
|
||||
url: `/api/role/update/${roleId}`,
|
||||
method: 'post',
|
||||
data,
|
||||
});
|
||||
return res;
|
||||
}
|
||||
//修改角色状态
|
||||
export async function updateRoleStatus(roleId, status){
|
||||
let res = await fetch({
|
||||
url: `/api/role/updateStatus/${roleId}?status=${status}`,
|
||||
method: 'post',
|
||||
});
|
||||
return res;
|
||||
}
|
||||
//删除角色
|
||||
export async function deleteRole(roleId){
|
||||
let res = await fetch({
|
||||
url: `/api/role/delete?ids=${roleId}`,
|
||||
method: 'post',
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
||||
//为角色赋予菜单
|
||||
export async function allocMenu(roleId, menuIds){
|
||||
let res = await fetch({
|
||||
url: `/api/role/allocMenu?roleId=${roleId}&menuIds=${menuIds}`,
|
||||
method: 'post',
|
||||
});
|
||||
return res;
|
||||
}
|
||||
//通过角色id获取菜单列表
|
||||
export async function listMenu(roleId) {
|
||||
let res = await fetch({
|
||||
url: `/api/role/listMenu/${roleId}`,
|
||||
method: 'get',
|
||||
});
|
||||
return res;
|
||||
}
|
||||
//修改用户角色
|
||||
export async function updateUserRole(userId, ruleId){
|
||||
let res = await fetch({
|
||||
url: `/api/admin/role/update/?adminId=${userId}&roleIds=${ruleId}`,
|
||||
method: 'post',
|
||||
});
|
||||
return res;
|
||||
}
|
||||
//获取所有管理员用户
|
||||
export async function adminUserList() {
|
||||
let res = await fetch({
|
||||
url: `/api/admin/list`,
|
||||
method: 'get',
|
||||
});
|
||||
return res;
|
||||
}
|
||||
// 获取用户角色
|
||||
export async function getUserRole(adminId) {
|
||||
let res = await fetch({
|
||||
url: `/api/admin/role/${adminId}`,
|
||||
method: 'get',
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
// 公告开始
|
||||
export const noticeStatus = [
|
||||
{ code: 0, name: "关闭" },
|
||||
{ code: 1, name: "正常" },
|
||||
{ code: 2, name: "草稿" },
|
||||
];
|
||||
|
||||
export const noticeType = [
|
||||
{ code: 4, name: "招标" },
|
||||
{ code: 1, name: "更正" },
|
||||
{ code: 2, name: "中标" },
|
||||
{ code: 3, name: "废标" },
|
||||
{ code: 5, name: "技术资产" },
|
||||
{ code: 6, name: "成交" },
|
||||
];
|
||||
|
||||
export const noticeChecked = [
|
||||
{ code: 0, name: "未通过" },
|
||||
{ code: 1, name: "已发布" },
|
||||
{ code: 2, name: "待审核" },
|
||||
];
|
||||
//公告结束
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
/**
|
||||
* 生成唯一字符串
|
||||
*/
|
||||
export function uuid() {
|
||||
const s = [];
|
||||
const hexDigits = '0123456789abcdef';
|
||||
for (let i = 0; i < 36; i += 1) {
|
||||
s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
|
||||
}
|
||||
s[14] = '4';
|
||||
s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
|
||||
s[8] = '-';
|
||||
s[13] = '-';
|
||||
s[18] = '-';
|
||||
s[23] = '-';
|
||||
s[0] = 'abcdefghigklmnopqrst'.substr(Math.floor(Math.random() * 0x10), 1);
|
||||
return s.join('');
|
||||
}
|
||||
|
||||
// 获取当前日期前N天数组
|
||||
// format='MM-dd'
|
||||
export function beforeDayArr(length = 31, myDate = new Date(), flag = 1) {
|
||||
myDate.setDate(myDate.getDate());
|
||||
let dateArray = [];
|
||||
let dateTemp;
|
||||
for (let i = length; i > 0; i--) {
|
||||
dateTemp = (myDate.getMonth() + 1) + "-" + myDate.getDate();
|
||||
dateArray.unshift(dateTemp);
|
||||
myDate.setDate(myDate.getDate() - flag);
|
||||
}
|
||||
return dateArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* param拼接到url地址上,get请求
|
||||
* @param {*} url
|
||||
* @param {*} params
|
||||
* @param {*} prefix
|
||||
*/
|
||||
export const paramToUrl = (url, params) => {
|
||||
if (url.indexOf('?') == -1) {
|
||||
// url += '?r=' + Math.random();
|
||||
url += '?';
|
||||
}
|
||||
let time = 0;
|
||||
for (let attr in params) {
|
||||
if (!time) {
|
||||
url += attr + '=' + params[attr] || '';
|
||||
time++;
|
||||
} else {
|
||||
url += '&' + attr + '=' + params[attr] || '';
|
||||
}
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
|
||||
const isDev = window.location.port == 8000;
|
||||
// const isdev2 = window.location.hostname === 'www.educoder.net'
|
||||
export const TEST_HOST = "https://testforgeplus.trustie.net/"
|
||||
export function getImageUrl(path) {
|
||||
const local = 'https://testforgeplus.trustie.net';
|
||||
if (isDev) {
|
||||
return `${local}/${path}`
|
||||
}
|
||||
return `https://forgeplus.trustie.net${path}`;
|
||||
}
|
||||
|
||||
|
||||
export const uploadNameSizeSeperator = ' '
|
||||
|
||||
export function appendFileSizeToUploadFileAll(fileList) {
|
||||
return fileList && fileList.map(item => {
|
||||
if (item.name&&item.name.indexOf(uploadNameSizeSeperator) == -1) {
|
||||
return Object.assign({}, item, { name: `${item.name}${uploadNameSizeSeperator}${bytesToSize(item.size)}` })
|
||||
}
|
||||
return item;
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export function bytesToSize(bytes) {
|
||||
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
|
||||
if (bytes == 0) return '0 Byte';
|
||||
if (!bytes) return '';
|
||||
var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
|
||||
return parseFloat(bytes / Math.pow(1024, i), 2).toFixed(1) + ' ' + sizes[i];
|
||||
}
|
||||
|
|
@ -21,6 +21,9 @@ export default Form.create()(({ form, match, history, current_user, showNotifica
|
|||
const [plainOptions, setPlainOptions] = useState([]);
|
||||
const [admin_data, setAdmin_data] = useState([]);
|
||||
|
||||
const [contentMd,setContentMd]=useState(false);
|
||||
const [guideMd,setGuideMd]=useState(false);
|
||||
|
||||
let tableRef = useRef();
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -49,27 +52,29 @@ export default Form.create()(({ form, match, history, current_user, showNotifica
|
|||
// manager_ids: details.manager_ids,
|
||||
};
|
||||
setFieldsValue(initValue);
|
||||
setContent(details.content);
|
||||
setGuide(details.guide);
|
||||
setAbout_us(details.about_us);
|
||||
setTimeout(() => {
|
||||
setContent(details.content);
|
||||
setContentMd(true);
|
||||
}, 200);
|
||||
setTimeout(() => {
|
||||
setGuide(details.guide);
|
||||
}, 800);
|
||||
setGuideMd(true);
|
||||
}, 300);
|
||||
setTimeout(() => {
|
||||
setAbout_us(details.about_us);
|
||||
document.querySelector('#title').focus();
|
||||
}, 1400);
|
||||
setLoading(false);
|
||||
}, 600);
|
||||
if (details.is_local) {
|
||||
zonesArr(details.zones_local);
|
||||
} else {
|
||||
zonesArr(details.zones);
|
||||
}
|
||||
setAdmin_data(Array.isArray(details.admin_data) ? details.admin_data : []);
|
||||
}else{
|
||||
setLoading(false);
|
||||
}
|
||||
setLoading(false);
|
||||
}).catch((error) => {
|
||||
}).finally(() => {
|
||||
setLoading(false);
|
||||
})
|
||||
}
|
||||
}, [id])
|
||||
|
|
@ -252,7 +257,6 @@ export default Form.create()(({ form, match, history, current_user, showNotifica
|
|||
</Form.Item>
|
||||
|
||||
|
||||
|
||||
{helper('赛项',
|
||||
'sub_competitions',
|
||||
[{ required: true, message: "请填写赛项" }],
|
||||
|
|
@ -315,26 +319,26 @@ export default Form.create()(({ form, match, history, current_user, showNotifica
|
|||
</Form.Item>
|
||||
|
||||
<Form.Item className="mb0 mdEditor" label={'大赛介绍'}>
|
||||
<MDEditor
|
||||
{contentMd&&<MDEditor
|
||||
placeholder={"请输入大赛介绍"}
|
||||
height={500}
|
||||
mdID={"competition-content"}
|
||||
initValue={content}
|
||||
onChange={(value) => { onContentChange(value, 'content') }}
|
||||
/>
|
||||
/>}
|
||||
{getFieldDecorator("content", {
|
||||
rules: [{ required: true, message: "请输入大赛介绍" }],
|
||||
})(<Input style={{ display: "none" }} />)}
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item className="mb0 mdEditor" label={'赛事指南'}>
|
||||
<MDEditor
|
||||
{guideMd&&<MDEditor
|
||||
placeholder={"请输入赛事指南"}
|
||||
height={500}
|
||||
mdID={"competition-guide"}
|
||||
initValue={guide}
|
||||
onChange={(value) => { onContentChange(value, 'guide') }}
|
||||
/>
|
||||
/>}
|
||||
{getFieldDecorator("guide", {
|
||||
rules: [{ required: true, message: "请输入赛事指南" }],
|
||||
})(<Input style={{ display: "none" }} />)}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
import { Modal } from 'antd';
|
||||
|
||||
export default (
|
||||
handleOk,
|
||||
title,
|
||||
content,
|
||||
handleCancel) => {
|
||||
return Modal.confirm({
|
||||
title: title || "警告",
|
||||
content: content || "确认删除?",
|
||||
okText: '确定',
|
||||
cancelText: '取消',
|
||||
onOk() {
|
||||
handleOk && handleOk();
|
||||
},
|
||||
onCancel() {
|
||||
handleCancel && handleCancel();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import * as echarts from 'echarts';
|
||||
|
||||
let fontSizeText = 16;
|
||||
let clientWidth = document.body.clientWidth;
|
||||
if (clientWidth < 1000) {
|
||||
fontSizeText = 16
|
||||
} else if (clientWidth >= 1000 && clientWidth <= 2000) {
|
||||
fontSizeText = 14 + (clientWidth - 1000) / 500;
|
||||
} else if (clientWidth > 2000) {
|
||||
fontSizeText = 16 + (clientWidth - 2000) / 500;
|
||||
} else if (clientWidth > 3000) {
|
||||
fontSizeText = 18 + (clientWidth - 3000) / 2000;
|
||||
}
|
||||
let fontSizeTitle = 1.25 * fontSizeText;
|
||||
|
||||
|
||||
export default ({ id,className, title, xData, yData }) => {
|
||||
|
||||
useEffect(() => {
|
||||
let newEchartBar = document.getElementById(id) && echarts.init(document.getElementById(id));
|
||||
let textColor = "#7988a5";
|
||||
let normalColor = "#e8e8ed";
|
||||
|
||||
let option = {
|
||||
grid: {
|
||||
left: "3%",
|
||||
top: "15%",
|
||||
right: "8%",
|
||||
bottom: 0,
|
||||
containLabel: true
|
||||
},
|
||||
title: {
|
||||
text: title,
|
||||
fontSize: fontSizeTitle,
|
||||
position: 'inside',
|
||||
textStyle: {
|
||||
color: textColor
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
axisPointer: {
|
||||
type: "shadow",
|
||||
textStyle: {
|
||||
color: "#fff"
|
||||
}
|
||||
},
|
||||
},
|
||||
xAxis: [{
|
||||
type: "category",
|
||||
data: xData,
|
||||
axisPointer: {
|
||||
type: "shadow"
|
||||
},
|
||||
axisLabel: {
|
||||
textStyle: {
|
||||
color: textColor,
|
||||
fontSize: .75 * fontSizeText
|
||||
},
|
||||
interval: 0,
|
||||
rotate: 40
|
||||
},
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: normalColor
|
||||
}
|
||||
},
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
splitLine: {
|
||||
show: false
|
||||
}
|
||||
}],
|
||||
yAxis: [{
|
||||
type: "value",
|
||||
minInterval: 1,
|
||||
nameTextStyle: {
|
||||
color: textColor,
|
||||
fontSize: fontSizeText
|
||||
},
|
||||
axisLabel: {
|
||||
formatter: "{value}",
|
||||
textStyle: {
|
||||
color: textColor,
|
||||
fontSize: fontSizeText
|
||||
}
|
||||
},
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: normalColor
|
||||
}
|
||||
},
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: normalColor
|
||||
}
|
||||
},
|
||||
}],
|
||||
series: [{
|
||||
type: "bar",
|
||||
data: yData,
|
||||
barWidth: "60%",
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: {
|
||||
type: "linear",
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 0,
|
||||
y2: 1,
|
||||
colorStops: [{
|
||||
offset: 0,
|
||||
color: "#deeefe"
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: "#2c8bff"
|
||||
}
|
||||
],
|
||||
globalCoord: false
|
||||
}
|
||||
}
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
// position: ['-20%', -1.2 * fontSizeText],
|
||||
position: "top",
|
||||
// color: "#2c8bff",
|
||||
color: '#555',
|
||||
fontSize: fontSizeText,
|
||||
formatter: function (params) {
|
||||
// var percent = 0;
|
||||
// percent = ((params.value / allStaff.num) * 100).toFixed(0);
|
||||
return params.value || ''
|
||||
// + '\n' + percent + '%';
|
||||
},
|
||||
}
|
||||
}]
|
||||
};
|
||||
newEchartBar && newEchartBar.setOption(option);
|
||||
}, [id, title, xData, yData])
|
||||
|
||||
return (
|
||||
<div id={id} key={id} className={className} style={{minHeight:"20vh"}}>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,198 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import * as echarts from 'echarts';
|
||||
|
||||
|
||||
let fontSizeText = 16;
|
||||
let clientWidth = document.body.clientWidth;
|
||||
if (clientWidth < 1000) {
|
||||
fontSizeText = 16
|
||||
} else if (clientWidth >= 1000 && clientWidth <= 2000) {
|
||||
fontSizeText = 14 + (clientWidth - 1000) / 500;
|
||||
} else if (clientWidth > 2000) {
|
||||
fontSizeText = 16 + (clientWidth - 2000) / 500;
|
||||
} else if (clientWidth > 3000) {
|
||||
fontSizeText = 18 + (clientWidth - 3000) / 2000;
|
||||
}
|
||||
|
||||
const colorList = ["#27e8b4", '#77b4fd', '#ffd55f', '#ac90ef', '#9E87FF'];
|
||||
|
||||
export default ({ id = "uid", className, title, xData, seriesArr }) => {
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
let newEchartBar = document.getElementById(id) && echarts.init(document.getElementById(id));
|
||||
let option = {
|
||||
backgroundColor: '#fff',
|
||||
legend: {
|
||||
icon: 'circle',
|
||||
top: '5%',
|
||||
itemWidth: 6,
|
||||
itemGap: 20,
|
||||
textStyle: {
|
||||
color: '#556677'
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
lineStyle: {
|
||||
color: "#DCE2E8"
|
||||
}
|
||||
},
|
||||
backgroundColor: '#fff',
|
||||
textStyle: {
|
||||
color: '#5c6c7c'
|
||||
},
|
||||
padding: [10, 10],
|
||||
extraCssText: 'box-shadow: 1px 0 2px 0 rgba(163,163,163,0.5)'
|
||||
},
|
||||
grid: {
|
||||
top: '15%'
|
||||
},
|
||||
xAxis: [{
|
||||
type: 'category',
|
||||
data: xData,
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: '#DCE2E8'
|
||||
}
|
||||
},
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
axisLabel: {
|
||||
// interval: 0,
|
||||
textStyle: {
|
||||
color: '#556677'
|
||||
},
|
||||
// 默认x轴字体大小
|
||||
fontSize: 0.75*fontSizeText,
|
||||
// margin:文字到x轴的距离
|
||||
margin: fontSizeText,
|
||||
rotate: 40
|
||||
},
|
||||
axisPointer: {
|
||||
label: {
|
||||
padding: [0, 0, 10, 0],
|
||||
/*
|
||||
除了padding[0]建议必须是0之外,其他三项可随意设置
|
||||
和CSSpadding相同,[上,右,下,左]
|
||||
如果需要下边线超出文字,设左右padding即可,注:左右padding最好相同
|
||||
padding[2]的10:
|
||||
10 = 文字距下边线的距离 + 下边线的宽度
|
||||
如:UI图中文字距下边线距离为7 下边线宽度为2
|
||||
则padding: [0, 0, 9, 0]
|
||||
*/
|
||||
// 这里的margin和axisLabel的margin要一致!
|
||||
margin: fontSizeText,
|
||||
// 移入时的字体大小
|
||||
fontSize: 0.75*fontSizeText,
|
||||
backgroundColor: {
|
||||
type: 'linear',
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 0,
|
||||
y2: 1,
|
||||
colorStops: [{
|
||||
offset: 0,
|
||||
color: '#fff' // 0% 处的颜色
|
||||
}, {
|
||||
// offset: 0.9,
|
||||
offset: 0.86,
|
||||
//0.86 = (文字 + 文字距下边线的距离)/(文字 + 文字距下边线的距离 + 下边线的宽度)
|
||||
color: '#fff' // 0% 处的颜色
|
||||
}, {
|
||||
offset: 0.86,
|
||||
color: '#33c0cd' // 0% 处的颜色
|
||||
}, {
|
||||
offset: 1,
|
||||
color: '#33c0cd' // 100% 处的颜色
|
||||
}],
|
||||
global: false // 缺省为 false
|
||||
}
|
||||
}
|
||||
},
|
||||
boundaryGap: false
|
||||
}],
|
||||
yAxis: [{
|
||||
name: "(个)",
|
||||
minInterval: 1,
|
||||
type: 'value',
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
axisLine: {
|
||||
show: false,
|
||||
lineStyle: {
|
||||
color: '#556677'
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
textStyle: {
|
||||
color: '#556677'
|
||||
}
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: '#e8e8ed'
|
||||
}
|
||||
}
|
||||
}],
|
||||
series: [],
|
||||
};
|
||||
|
||||
for (let i = 0; i < seriesArr.length; i++) {
|
||||
if (seriesArr[i].data) {
|
||||
option.series.push({
|
||||
name: seriesArr[i].name,
|
||||
type: 'line',
|
||||
data: seriesArr[i].data,
|
||||
symbolSize: 1,
|
||||
symbol: 'circle',
|
||||
smooth: true,
|
||||
yAxisIndex: 0,
|
||||
showSymbol: false,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: colorList[i],
|
||||
borderColor: colorList[i]
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if(seriesArr[i].name=='新增代码数'&&seriesArr[i].data){
|
||||
option.yAxis.push({
|
||||
name: "(行)",
|
||||
type: 'value',
|
||||
position: 'right',
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
axisLabel: {
|
||||
textStyle: {
|
||||
color: '#556677'
|
||||
},
|
||||
formatter: '{value}'
|
||||
},
|
||||
axisLine: {
|
||||
show: false,
|
||||
lineStyle: {
|
||||
color: '#556677'
|
||||
}
|
||||
},
|
||||
splitLine: {
|
||||
show: false
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
newEchartBar && newEchartBar.setOption(option);
|
||||
}, [xData,seriesArr])
|
||||
|
||||
return (
|
||||
<div id={id} key={id} className={className} style={{ minHeight: "400px" }}>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
import { notification } from 'antd';
|
||||
|
||||
export default (message)=>{
|
||||
notification.open({
|
||||
message: "提示",
|
||||
description: message,
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
import React, { useEffect, useState } from "react";
|
||||
import { Upload, Button } from 'antd';
|
||||
import { appendFileSizeToUploadFileAll } from '../common/utils';
|
||||
import ShowNotification from './ShowNotification';
|
||||
|
||||
|
||||
function Uploads({ className, size, actionUrl, fileList, load, number }) {
|
||||
const [files, setFiles] = useState(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
if (fileList) {
|
||||
init();
|
||||
}
|
||||
}, [fileList]);
|
||||
|
||||
function init() {
|
||||
let f = appendFileSizeToUploadFileAll(fileList);
|
||||
setFiles(f);
|
||||
}
|
||||
function onAttachmentRemove(file) {
|
||||
if (!file.percent || file.percent === 100) {
|
||||
deleteAttachment(file);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
function deleteAttachment(file) {
|
||||
let id = (file.response && file.response.data && file.response.data.id) || file.id;
|
||||
|
||||
// 暂时不直接删除上传的文件,只在最后保存的时候进行修改
|
||||
let nf = files.filter(item => {
|
||||
let itemId = (item.response && item.response.data && item.response.data.id) || item.id;
|
||||
return itemId !== id;
|
||||
});
|
||||
setFiles(nf);
|
||||
load && load(nf);
|
||||
}
|
||||
|
||||
|
||||
function handleChange(info) {
|
||||
if (info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') {
|
||||
let fileList = info.fileList;
|
||||
if (number) {
|
||||
fileList = fileList.slice(-number);
|
||||
}
|
||||
if (info.file.status === 'done' && info.file.response.code === "0") {
|
||||
fileList.pop();
|
||||
ShowNotification(info.file.response.message);
|
||||
}
|
||||
setFiles(appendFileSizeToUploadFileAll(fileList));
|
||||
if (info.file.status === 'done' || info.file.status === 'removed') load && load(fileList);
|
||||
}
|
||||
}
|
||||
|
||||
function beforeUpload(file) {
|
||||
const isLt100M = file.size / 1024 / 1024 < size;
|
||||
if (!isLt100M) {
|
||||
ShowNotification(`文件大小必须小于${size}MB!`);
|
||||
}
|
||||
return isLt100M;
|
||||
}
|
||||
|
||||
const upload = {
|
||||
name: 'file',
|
||||
fileList: files,
|
||||
action: actionUrl + `/busiAttachments/upload`,
|
||||
onChange: handleChange,
|
||||
onRemove: onAttachmentRemove,
|
||||
beforeUpload: beforeUpload,
|
||||
};
|
||||
return (
|
||||
<Upload {...upload} className={className}>
|
||||
<Button type="primary">点击上传</Button>
|
||||
<span className="ml10 color-grey-9">(你可以上传小于<span className="color-red">{size}MB</span>的文件)</span>
|
||||
</Upload>
|
||||
)
|
||||
}
|
||||
export default Uploads;
|
||||
|
|
@ -0,0 +1,464 @@
|
|||
/**
|
||||
* 路由配置表
|
||||
* key:必填,唯一标识
|
||||
* title:必填,菜单名称
|
||||
* location:路由地址
|
||||
* icon:左侧图标
|
||||
* target:打开方式,参考HTML标签的target属性
|
||||
* urltype:路由类别,用于拓展其它项目管理菜单,self为在当前项目下跳转路由,main_web_site_url或其它为匹配setting中对应路参数径
|
||||
* children:子元素数组
|
||||
*/
|
||||
|
||||
export default [
|
||||
{
|
||||
key: "statistics",
|
||||
title: "概览",
|
||||
location: "",
|
||||
icon: "icon-yonghuguanli",
|
||||
target: "_self",
|
||||
urltype: "self",
|
||||
children: [
|
||||
{
|
||||
key: "global",
|
||||
title: "全局统计",
|
||||
location: "/managements/statistics/global",
|
||||
menustatus: "Y",
|
||||
parentKey: "statistics",
|
||||
icon: "",
|
||||
target: "",
|
||||
urltype: "self",
|
||||
children: [],
|
||||
},
|
||||
// {
|
||||
// key: "member",
|
||||
// title: "成员工作统计",
|
||||
// location: "/managements/statistics/member",
|
||||
// menustatus: "Y",
|
||||
// parentKey: "statistics",
|
||||
// icon: "",
|
||||
// target: "",
|
||||
// urltype: "self",
|
||||
// children: [],
|
||||
// },
|
||||
// {
|
||||
// key: "activity",
|
||||
// title: "项目活跃度统计",
|
||||
// location: "/managements/statistics/activity",
|
||||
// menustatus: "Y",
|
||||
// parentKey: "statistics",
|
||||
// icon: "",
|
||||
// target: "",
|
||||
// urltype: "self",
|
||||
// children: [],
|
||||
// },
|
||||
],
|
||||
},
|
||||
{
|
||||
key: "task",
|
||||
title: "创客空间",
|
||||
location: "",
|
||||
icon: "icon-weixuanze-chuangkekongjian",
|
||||
target: "_self",
|
||||
urltype: "self",
|
||||
children: [
|
||||
{
|
||||
key: "taskAdmin",
|
||||
title: "创客任务列表",
|
||||
location: "/managements/task/taskAdmin",
|
||||
menustatus: "Y",
|
||||
parentKey: "task",
|
||||
icon: "",
|
||||
target: "",
|
||||
urltype: "self",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
key: "commission",
|
||||
title: "待办事项",
|
||||
location: "",
|
||||
menustatus: "Y",
|
||||
parentKey: "task",
|
||||
icon: "",
|
||||
target: "_self",
|
||||
urltype: "self",
|
||||
children: [
|
||||
{
|
||||
key: "delayManage",
|
||||
title: "延期任务处理",
|
||||
location: "/managements/task/delayManage",
|
||||
menustatus: "Y",
|
||||
parentKey: "commission",
|
||||
icon: "",
|
||||
target: "",
|
||||
urltype: "self",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
key: "payProof",
|
||||
title: "支付报酬凭证上传",
|
||||
location: "/managements/task/payProof",
|
||||
menustatus: "Y",
|
||||
parentKey: "commission",
|
||||
icon: "",
|
||||
target: "",
|
||||
urltype: "self",
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
key: "publish",
|
||||
title: "任务发布审批",
|
||||
location: "",
|
||||
menustatus: "Y",
|
||||
parentKey: "task",
|
||||
icon: "",
|
||||
target: "_self",
|
||||
urltype: "self",
|
||||
children: [
|
||||
{
|
||||
key: "overall",
|
||||
title: "统筹任务发布审批",
|
||||
location: "/managements/task/taskManage/1",
|
||||
menustatus: "Y",
|
||||
parentKey: "publish",
|
||||
icon: "",
|
||||
target: "",
|
||||
urltype: "self",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
key: "autonomous",
|
||||
title: "自主任务发布审批",
|
||||
location: "/managements/task/taskManage/0",
|
||||
menustatus: "Y",
|
||||
parentKey: "publish",
|
||||
icon: "",
|
||||
target: "",
|
||||
urltype: "self",
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
key: "outcomeReview",
|
||||
title: "成果评论审批",
|
||||
location: "/managements/task/paperManage",
|
||||
menustatus: "Y",
|
||||
parentKey: "task",
|
||||
icon: "",
|
||||
target: "",
|
||||
urltype: "self",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
key: "supportingMaterials",
|
||||
title: "佐证材料审批",
|
||||
location: "/managements/task/proofManage",
|
||||
menustatus: "Y",
|
||||
parentKey: "task",
|
||||
icon: "",
|
||||
target: "",
|
||||
urltype: "self",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
key: "agreement",
|
||||
title: "协议审批",
|
||||
location: "/managements/task/agreementManage",
|
||||
menustatus: "Y",
|
||||
parentKey: "task",
|
||||
icon: "",
|
||||
target: "",
|
||||
urltype: "self",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
key: "appeal",
|
||||
title: "申诉审批",
|
||||
location: "",
|
||||
menustatus: "Y",
|
||||
parentKey: "task",
|
||||
icon: "",
|
||||
target: "",
|
||||
urltype: "self",
|
||||
children: [
|
||||
{
|
||||
key: "resultsSubmission",
|
||||
title: "成果提交申诉审批",
|
||||
location: "/managements/task/paperComplain",
|
||||
menustatus: "Y",
|
||||
parentKey: "task",
|
||||
icon: "",
|
||||
target: "",
|
||||
urltype: "self",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
key: "publicityPeriod",
|
||||
title: "公示期成果申诉审批",
|
||||
location: "/managements/task/publicityComplain",
|
||||
menustatus: "Y",
|
||||
parentKey: "task",
|
||||
icon: "",
|
||||
target: "",
|
||||
urltype: "self",
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
// {
|
||||
// key: "basics",
|
||||
// title: "基础数据",
|
||||
// location: "",
|
||||
// menustatus: "Y",
|
||||
// parentKey: "task",
|
||||
// icon: "",
|
||||
// target: "_self",
|
||||
// urltype: "self",
|
||||
// children: [
|
||||
// {
|
||||
// key: "categories",
|
||||
// title: "任务领域",
|
||||
// location: "/admin/categories/list",
|
||||
// menustatus: "Y",
|
||||
// parentKey: "task",
|
||||
// icon: "",
|
||||
// target: "_self",
|
||||
// urltype: "main_web_site_url",
|
||||
// children: [],
|
||||
// },
|
||||
// {
|
||||
// key: "industries",
|
||||
// title: "行业信息",
|
||||
// location: "/managements/industries/list",
|
||||
// menustatus: "Y",
|
||||
// parentKey: "task",
|
||||
// icon: "",
|
||||
// target: "_self",
|
||||
// urltype: "main_web_site_url",
|
||||
// children: [],
|
||||
// },
|
||||
// {
|
||||
// key: "placements",
|
||||
// title: "职位信息",
|
||||
// location: "/managements/placements/list",
|
||||
// menustatus: "Y",
|
||||
// parentKey: "task",
|
||||
// icon: "",
|
||||
// target: "_self",
|
||||
// urltype: "main_web_site_url",
|
||||
// children: [],
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
],
|
||||
},
|
||||
{
|
||||
key: "competition",
|
||||
title: "竞赛活动",
|
||||
location: "",
|
||||
icon: "icon-jingsaihuodong",
|
||||
target: "_self",
|
||||
urltype: "self",
|
||||
children: [
|
||||
{
|
||||
key: "competitionList",
|
||||
title: "竞赛列表",
|
||||
location: "/admin/competitions/list",
|
||||
menustatus: "Y",
|
||||
parentKey: "task",
|
||||
icon: "",
|
||||
target: "",
|
||||
urltype: "main_web_site_url",
|
||||
params:'layout=none',
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
key: "competitionRegion",
|
||||
title: "赛区配置",
|
||||
location: "/admin/competitions/region_zone_edit",
|
||||
menustatus: "Y",
|
||||
parentKey: "task",
|
||||
icon: "",
|
||||
target: "_blank",
|
||||
urltype: "main_web_site_url",
|
||||
params:'layout=none',
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
key: "competitionExpert",
|
||||
title: "竞赛评审列表",
|
||||
location: "/managements/expert/competition",
|
||||
menustatus: "Y",
|
||||
parentKey: "competition",
|
||||
icon: "",
|
||||
target: "",
|
||||
urltype: "self",
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
key: "userManagement",
|
||||
title: "用户管理",
|
||||
location: "",
|
||||
icon: "icon-yonghuguanli",
|
||||
target: "_self",
|
||||
urltype: "self",
|
||||
children: [
|
||||
{
|
||||
key: "expertRegister",
|
||||
title: "专家注册列表",
|
||||
location: "/managements/expert/register",
|
||||
menustatus: "Y",
|
||||
parentKey: "userManagement",
|
||||
icon: "",
|
||||
target: "",
|
||||
urltype: "self",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
key: "expertList",
|
||||
title: "专家库列表",
|
||||
location: "/managements/expert/list",
|
||||
menustatus: "Y",
|
||||
parentKey: "userManagement",
|
||||
icon: "",
|
||||
target: "",
|
||||
urltype: "self",
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
key: "notice",
|
||||
title: "公告管理",
|
||||
location: "",
|
||||
icon: "icon-yonghuguanli",
|
||||
target: "_self",
|
||||
urltype: "self",
|
||||
children: [
|
||||
{
|
||||
key: "noticeList1",
|
||||
title: "已发布",
|
||||
location: "/managements/notice/list/1",
|
||||
menustatus: "Y",
|
||||
parentKey: "notice",
|
||||
icon: "",
|
||||
target: "",
|
||||
urltype: "self",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
key: "noticeList2",
|
||||
title: "待审核",
|
||||
location: "/managements/notice/list/2",
|
||||
menustatus: "Y",
|
||||
parentKey: "notice",
|
||||
icon: "",
|
||||
target: "",
|
||||
urltype: "self",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
key: "noticeList0",
|
||||
title: "未通过",
|
||||
location: "/managements/notice/list/0",
|
||||
menustatus: "Y",
|
||||
parentKey: "notice",
|
||||
icon: "",
|
||||
target: "",
|
||||
urltype: "self",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
key: "noticeDraft",
|
||||
title: "草稿箱",
|
||||
location: "/managements/notice/list/draft",
|
||||
menustatus: "Y",
|
||||
parentKey: "notice",
|
||||
icon: "",
|
||||
target: "",
|
||||
urltype: "self",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
key: "noticeEdit",
|
||||
title: "发布公告",
|
||||
location: "/managements/notice/edit",
|
||||
menustatus: "Y",
|
||||
parentKey: "notice",
|
||||
icon: "",
|
||||
target: "",
|
||||
urltype: "self",
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
key: "jurisdiction",
|
||||
title: "权限管理",
|
||||
location: "",
|
||||
icon: "icon-yonghuguanli",
|
||||
target: "_self",
|
||||
urltype: "self",
|
||||
children: [
|
||||
{
|
||||
key: "adminUserList",
|
||||
title: "管理员列表",
|
||||
location: "/managements/jurisdiction/users",
|
||||
menustatus: "Y",
|
||||
parentKey: "jurisdiction",
|
||||
icon: "",
|
||||
target: "",
|
||||
urltype: "self",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
key: "roleList",
|
||||
title: "角色列表",
|
||||
location: "/managements/jurisdiction/roles",
|
||||
menustatus: "Y",
|
||||
parentKey: "jurisdiction",
|
||||
icon: "",
|
||||
target: "",
|
||||
urltype: "self",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
key: "menuList",
|
||||
title: "菜单列表",
|
||||
location: "/managements/jurisdiction/menu",
|
||||
menustatus: "Y",
|
||||
parentKey: "jurisdiction",
|
||||
icon: "",
|
||||
target: "",
|
||||
urltype: "self",
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
key: "settings",
|
||||
title: "网站配置",
|
||||
location: "",
|
||||
icon: "icon-yonghuguanli",
|
||||
target: "",
|
||||
urltype: "current_main_site_url",
|
||||
children: [
|
||||
{
|
||||
key: "platform_communicates",
|
||||
title: "社区动态管理",
|
||||
location: "/managements/admins/platform_communicates",
|
||||
menustatus: "Y",
|
||||
parentKey: "settings",
|
||||
icon: "",
|
||||
target: "",
|
||||
urltype: "current_main_site_url",
|
||||
params:'layout=none',
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
|
@ -0,0 +1,197 @@
|
|||
import React, { useState, useEffect, Fragment } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Menu } from "antd";
|
||||
import { main_web_site_url } from '../../fetch';
|
||||
import "./index.scss";
|
||||
const { SubMenu } = Menu;
|
||||
|
||||
|
||||
export default (props) => {
|
||||
const { current_user, children, history, menuList, location: { pathname } } = props;
|
||||
const setting = (localStorage.chromesetting && JSON.parse(localStorage.chromesetting)) || {};
|
||||
const [openKeys, setOpenKeys] = useState([]);
|
||||
const [current, setCurrent] = useState();
|
||||
const [keyPath, setKeyPath] = useState();
|
||||
const [acitve, setActive] = useState({});
|
||||
|
||||
const titleObj = {};
|
||||
const locationObj = {};
|
||||
const parentKeyObj = {};
|
||||
const allRouter = [];
|
||||
const rootSubmenuKeys = [];
|
||||
|
||||
function titleFun(menus) {
|
||||
menus.forEach(i => {
|
||||
if (i.hidden === 1) {
|
||||
titleObj[i.key] = i.title;
|
||||
locationObj[i.location] = i;
|
||||
i.key = i.key + '';
|
||||
i.parentKey = i.parentKey + '';
|
||||
i.location && allRouter.push(i.location);
|
||||
i.parentKey == '0' && rootSubmenuKeys.push(i.key);
|
||||
if (i.hidden === 1 && Array.isArray(i.children) && i.children.length > 0) {
|
||||
titleFun(i.children);
|
||||
i.parentKey && (parentKeyObj[i.key] = i.parentKey + '');
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
menuList && menuList.length && titleFun(menuList);
|
||||
|
||||
useEffect(() => {
|
||||
sessionStorage.setItem("current_user", JSON.stringify(current_user));
|
||||
}, [current_user.login]);
|
||||
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (locationObj[pathname]) {
|
||||
setCurrent(locationObj[pathname] ? [locationObj[pathname].key] : []);
|
||||
setKeyPath(locationObj[pathname] ? [locationObj[pathname].parentKey, locationObj[pathname].key] : []);
|
||||
const defaultOpenKeys = [];
|
||||
const myKey = pathname && locationObj[pathname] && locationObj[pathname].parentKey;
|
||||
defaultOpenKeys.push(myKey ? myKey : "task");
|
||||
parentKeyObj[myKey] && defaultOpenKeys.push(parentKeyObj[myKey]);
|
||||
setActive(locationObj[pathname]);
|
||||
setOpenKeys(defaultOpenKeys);
|
||||
}
|
||||
}, [locationObj[pathname]])
|
||||
|
||||
|
||||
function handleClick(e) {
|
||||
setCurrent([e.key]);
|
||||
setKeyPath(e.keyPath.reverse());
|
||||
}
|
||||
|
||||
function itemClick(item) {
|
||||
let myIframe = document.getElementById("iframe");
|
||||
if (myIframe) {
|
||||
myIframe.height = 'auto';
|
||||
}
|
||||
setActive(item)
|
||||
}
|
||||
|
||||
function getMenuList(menus) {
|
||||
return menus.map(function (item) {
|
||||
if (item.hidden === 1) {
|
||||
let title = (
|
||||
<span>
|
||||
{item.icon && <i className={"left-icon iconfont " + item.icon}></i>}
|
||||
<span>{item.title}</span>
|
||||
</span>
|
||||
);
|
||||
if (Array.isArray(item.children) && item.children.length > 0) {
|
||||
return (
|
||||
<SubMenu key={item.key} children={item.children} title={title}>{getMenuList(item.children)}</SubMenu>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<Menu.Item title={title} key={item.key}>
|
||||
{item.location ? <Link to={item.location} onClick={() => { itemClick(item) }}>{title}</Link>
|
||||
: title}
|
||||
</Menu.Item>
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function head(keyPath) {
|
||||
return keyPath ? keyPath.map((i, index) => {
|
||||
return <span key={index}>{titleObj[i]}{index !== keyPath.length - 1 && ' / '}</span>
|
||||
}) : ''
|
||||
}
|
||||
|
||||
function iframeLoad() {
|
||||
try {
|
||||
let myIframe = document.getElementById("iframe");
|
||||
if (myIframe.contentDocument) {
|
||||
myIframe.height = myIframe.contentDocument.querySelector('.content').clientHeight + 260;
|
||||
myIframe.contentDocument.querySelector('.admin-body-container').style.overflow = 'hidden';
|
||||
// let MutationObserver =window.MutationObserver ;
|
||||
|
||||
// // let MutationObserver =myIframe.contentWindow.MutationObserver || myIframe.contentWindow.WebKitMutationObserver || myIframe.contentWindow.MozMutationObserver;
|
||||
// let observer = new MutationObserver(function (mutations) {
|
||||
// console.log("asdf", mutations);
|
||||
// });
|
||||
// observer.observe(myIframe.contentDocument.querySelector('.content'), {
|
||||
// attributes: true,
|
||||
// attributeFilter:['style'],
|
||||
// attributeOldValue:true
|
||||
// });
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
// useEffect(() => {
|
||||
// try {
|
||||
// document.getElementById("iframe").contentDocument.querySelector('.content').addEventListener("message", iframeHeight, false);
|
||||
// return () => {
|
||||
// document.getElementById("iframe").contentDocument.querySelector('.content').removeEventListener("message", iframeHeight, false);
|
||||
// }
|
||||
// } catch (err) {
|
||||
// console.error(err);
|
||||
// }
|
||||
// }, []);
|
||||
|
||||
function onOpenChange(newOpenKeys) {
|
||||
const latestOpenKey = newOpenKeys.find(key => openKeys.indexOf(key) === -1);
|
||||
if (rootSubmenuKeys.indexOf(latestOpenKey) === -1) {
|
||||
setOpenKeys(newOpenKeys);
|
||||
} else {
|
||||
setOpenKeys(latestOpenKey ? [latestOpenKey] : []);
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
// 添加路由监听函数
|
||||
history.listen(historyLocation => {
|
||||
// 每次路由变化都会执行这个方法
|
||||
if (allRouter.includes(historyLocation.pathname)) {
|
||||
setCurrent([locationObj[historyLocation.pathname].key]);
|
||||
setKeyPath([locationObj[pathname].parentKey, locationObj[pathname].key]);
|
||||
}
|
||||
})
|
||||
}, [history]);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener("message", iframeHeight, false);
|
||||
return () => {
|
||||
window.removeEventListener("message", iframeHeight, false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
function iframeHeight(e) {
|
||||
if (e.origin === main_web_site_url && e.data && !isNaN(e.data)) {
|
||||
document.getElementById("iframe").height=Number(e.data)+20;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<div className="layouts">
|
||||
<Menu
|
||||
mode="inline"
|
||||
selectedKeys={current}
|
||||
onClick={handleClick}
|
||||
onOpenChange={onOpenChange}
|
||||
openKeys={openKeys}
|
||||
>
|
||||
{menuList && menuList.length && getMenuList(menuList)}
|
||||
</Menu>
|
||||
</div>
|
||||
<div className="managements">
|
||||
<div className="head-title">{head(keyPath)}</div>
|
||||
{acitve && acitve.urlType && acitve.urlType !== 'self' ?
|
||||
<iframe id="iframe" className="iframe-item" src={`${setting[acitve.urlType]}${acitve.location && acitve.location.startsWith('/administration') ? acitve.location.replace(/\/administration/, "") : acitve.location}?${acitve.params || 'layout=none'}`} onLoad={iframeLoad}></iframe>
|
||||
: children
|
||||
}
|
||||
</div>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
.layouts {
|
||||
position: fixed;
|
||||
top: 70px;
|
||||
left: 0;
|
||||
width: 13.75rem;
|
||||
height: calc(100vh - 70px);
|
||||
overflow: hidden;
|
||||
overflow-y: scroll;
|
||||
background-color:#ffffff;
|
||||
border-radius:4px;
|
||||
box-shadow:0px 3px 10px rgba(88, 116, 255, 0.07);
|
||||
&::-webkit-scrollbar{
|
||||
width: 0;
|
||||
}
|
||||
.left-icon {
|
||||
font-size: 1.25rem;
|
||||
margin-right: 0.625rem;
|
||||
margin-left: -.3125rem;
|
||||
}
|
||||
.ant-menu-submenu:hover, .ant-menu-submenu-selected, .ant-menu:hover, .ant-menu-submenu-selected .ant-menu{
|
||||
background-color:#fbfbff;
|
||||
}
|
||||
|
||||
.ant-menu-submenu-selected{
|
||||
.ant-menu:not(.ant-menu-horizontal) .ant-menu-item-selected{
|
||||
background-image:linear-gradient(90deg,#e7efff 0%,#f0f5ff 65.69%,#ffffff 100%);
|
||||
&::after{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
content: '';
|
||||
border: none;
|
||||
border-left: 5px solid #2a3ee9;
|
||||
}
|
||||
}
|
||||
}
|
||||
li.ant-menu-item{
|
||||
border: none;
|
||||
&:hover{
|
||||
background-color:#e2e6f5;
|
||||
a{ color: rgba(0, 0, 0, 0.65) !important;}
|
||||
}
|
||||
}
|
||||
}
|
||||
.managements {
|
||||
.head-title {
|
||||
padding-top:1.25rem;
|
||||
span {
|
||||
color: #a6adc4;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.375rem;
|
||||
|
||||
&:last-child{
|
||||
color:#596078;
|
||||
}
|
||||
}
|
||||
}
|
||||
.iframe-item{
|
||||
width: 100%;
|
||||
min-height: calc(100vh - 225px);
|
||||
border: 0;
|
||||
}
|
||||
.ant-input, .ant-select-selection{
|
||||
border-color:#e2e6f5;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
import javaFetch from '../military/javaFetch';
|
||||
|
||||
|
||||
let settings = localStorage.chromesetting && JSON.parse(localStorage.chromesetting);
|
||||
let actionUrl = settings && settings.api_urls && settings.api_urls.task ? settings.api_urls.task : 'https://task.osredm.com';
|
||||
// let actionUrl = 'http://10.47.38.60:8088';
|
||||
const service = javaFetch(actionUrl);
|
||||
export const httpUrl = actionUrl;
|
||||
export const main_web_site_url = settings && settings.main_web_site_url;
|
||||
export default service;
|
||||
|
|
@ -0,0 +1,334 @@
|
|||
import React, { useEffect, useState } from "react";
|
||||
import { Route, Switch } from "react-router-dom";
|
||||
import { withRouter } from "react-router";
|
||||
import { SnackbarHOC } from "educoder";
|
||||
import { CNotificationHOC } from "../modules/courses/common/CNotificationHOC";
|
||||
import { TPMIndexHOC } from "../modules/tpm/TPMIndexHOC";
|
||||
import Loadable from "react-loadable";
|
||||
import Loading from "../Loading";
|
||||
import { ImageLayerOfCommentHOC } from "../modules/page/layers/ImageLayerOfCommentHOC";
|
||||
import Layouts from "./components/layouts";
|
||||
import './index.scss';
|
||||
|
||||
// 概览
|
||||
const Statistics = Loadable({
|
||||
loader: () => import("./statistics/"),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
{/* 任务管理审核 */ }
|
||||
const TaskManage = Loadable({
|
||||
loader: () => import("../military/task/taskManage"),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
{/* 成果管理审核 */ }
|
||||
const PaperManage = Loadable({
|
||||
loader: () => import("../military/task/paperManage"),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
{/* 成果申诉管理审核 */ }
|
||||
const PaperComplain = Loadable({
|
||||
loader: () => import("../military/task/paperComplain"),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
const ProofManage = Loadable({
|
||||
loader: () => import("../military/task/proofManage"),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
const PublicityComplain = Loadable({
|
||||
loader: () => import("../military/task/publicityComplain"),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
const AgreementManage = Loadable({
|
||||
loader: () => import("../military/task/agreementManage"),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
const PayProof = Loadable({
|
||||
loader: () => import("../military/task/payProof"),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
const TaskAdmin = Loadable({
|
||||
loader: () => import("../military/task/taskAdmin"),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
const DelayManage = Loadable({
|
||||
loader: () => import("../military/task/delayManage"),
|
||||
loading: Loading,
|
||||
});
|
||||
// 协议签订模板
|
||||
const AgreementContent = Loadable({
|
||||
loader: () => import("../military/task/agreementContent"),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
|
||||
|
||||
// 专家库
|
||||
const ExpertList = Loadable({
|
||||
loader: () => import("../military/expert/expertList"),
|
||||
loading: Loading,
|
||||
});
|
||||
// 专家审核
|
||||
const RegisterList = Loadable({
|
||||
loader: () => import("../military/expert/registerList"),
|
||||
loading: Loading,
|
||||
});
|
||||
//创客任务评审规则
|
||||
const ReviewRules = Loadable({
|
||||
loader: () => import("../military/expert/reviewRules"),
|
||||
loading: Loading,
|
||||
});
|
||||
//创客任务选择评审专家
|
||||
const SelectExpert = Loadable({
|
||||
loader: () => import("../military/expert/selectExpert"),
|
||||
loading: Loading,
|
||||
});
|
||||
//创客任务评审结果查看
|
||||
const ReviewResult = Loadable({
|
||||
loader: () => import("../military/expert/reviewResult"),
|
||||
loading: Loading,
|
||||
});
|
||||
//竞赛评审任务列表
|
||||
const CompetitionList = Loadable({
|
||||
loader: () => import("../military/expert/competionList"),
|
||||
loading: Loading,
|
||||
});
|
||||
// 定制化竞赛列表,如启智
|
||||
const CompetionCustomize =Loadable({
|
||||
loader: () => import("../managements/competition/competionCustomize"),
|
||||
loading: Loading,
|
||||
})
|
||||
const CompetionSetting=Loadable({
|
||||
loader: () => import("../managements/competition/setting"),
|
||||
loading: Loading,
|
||||
});
|
||||
// 公告管理
|
||||
const NoticeManage = Loadable({
|
||||
loader: () => import("./notice"),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
// 权限管理
|
||||
// 非普通用户(管理员)列表
|
||||
const AdminUserList = Loadable({
|
||||
loader: () => import("./jurisdiction/userList"),
|
||||
loading: Loading,
|
||||
})
|
||||
// 系统角色列表
|
||||
const RoleList = Loadable({
|
||||
loader: () => import("./jurisdiction/roles"),
|
||||
loading: Loading,
|
||||
})
|
||||
// 菜单列表
|
||||
const MenuList = Loadable({
|
||||
loader: () => import("./jurisdiction/menuList"),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
const Managements = (propsF) => {
|
||||
|
||||
return (
|
||||
<div className="newMain clearfix">
|
||||
<Layouts {...propsF} >
|
||||
<Switch {...propsF}>
|
||||
|
||||
{/* 概览 */}
|
||||
<Route
|
||||
path="/managements/statistics"
|
||||
render={(props) => (
|
||||
<Statistics {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
|
||||
{/* 任务管理审核 */}
|
||||
<Route
|
||||
path="/managements/task/taskManage/:publishMode"
|
||||
render={(props) => (
|
||||
<TaskManage {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
|
||||
{/* 成果管理审核 */}
|
||||
<Route
|
||||
path="/managements/task/paperManage"
|
||||
render={(props) => (
|
||||
<PaperManage {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
|
||||
{/* 成果申诉管理审核 */}
|
||||
<Route
|
||||
path="/managements/task/paperComplain"
|
||||
render={(props) => (
|
||||
<PaperComplain {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
|
||||
{/* 公示期成果申诉管理审核 */}
|
||||
<Route
|
||||
path="/managements/task/publicityComplain"
|
||||
render={(props) => (
|
||||
<PublicityComplain {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
|
||||
{/* 佐证管理审核 */}
|
||||
<Route
|
||||
path="/managements/task/proofManage"
|
||||
render={(props) => (
|
||||
<ProofManage {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
|
||||
{/* 管理员协议审核 */}
|
||||
<Route
|
||||
path="/managements/task/agreementManage"
|
||||
render={(props) => (
|
||||
<AgreementManage {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
|
||||
{/* 管理员上传支付凭证 */}
|
||||
<Route
|
||||
path="/managements/task/payProof"
|
||||
render={(props) => (
|
||||
<PayProof {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
|
||||
{/* 管理员任务列表 */}
|
||||
<Route
|
||||
path="/managements/task/taskAdmin"
|
||||
render={(props) => (
|
||||
<TaskAdmin {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
|
||||
{/* 延期管理 */}
|
||||
<Route
|
||||
path="/managements/task/delayManage"
|
||||
render={(props) => (
|
||||
<DelayManage {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
|
||||
{/* 协议内容 */}
|
||||
<Route
|
||||
path="/managements/task/agreement/content"
|
||||
render={(props) => (
|
||||
<AgreementContent {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
|
||||
{/* 专家审核 */}
|
||||
<Route
|
||||
path="/managements/expert/register"
|
||||
render={(props) => (
|
||||
<RegisterList {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
{/* 专家库列表 */}
|
||||
<Route
|
||||
path="/managements/expert/list"
|
||||
render={(props) => (
|
||||
<ExpertList {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
{/* 创客任务评审规则 */}
|
||||
<Route
|
||||
path="/managements/expert/task/review/rules/:containerType/:containerId"
|
||||
render={(props) => (
|
||||
<ReviewRules {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
{/* 创客任务选择评审专家 */}
|
||||
<Route
|
||||
path="/managements/expert/task/review/select/:containerType/:containerId"
|
||||
render={(props) => (
|
||||
<SelectExpert {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
{/* 创客任务评审结果查看 */}
|
||||
<Route
|
||||
path="/managements/expert/task/review/results/:containerType/:containerId"
|
||||
render={(props) => (
|
||||
<ReviewResult {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
{/* 竞赛评审任务列表 */}
|
||||
<Route
|
||||
path="/managements/expert/competition"
|
||||
render={(props) => (
|
||||
<CompetitionList {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
{/* 非普通用户(管理员)列表 */}
|
||||
<Route
|
||||
path="/managements/jurisdiction/users"
|
||||
render={(props) => (
|
||||
<AdminUserList {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
{/* 系统角色列表 */}
|
||||
<Route
|
||||
path="/managements/jurisdiction/roles"
|
||||
render={(props) => (
|
||||
<RoleList {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
{/* 菜单列表 */}
|
||||
<Route
|
||||
path="/managements/jurisdiction/menu"
|
||||
render={(props) => (
|
||||
<MenuList {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
|
||||
{/* 公告管理 */}
|
||||
<Route
|
||||
path="/managements/notice"
|
||||
render={(props) => (
|
||||
<NoticeManage {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
|
||||
{/* 定制竞赛配置详情 */}
|
||||
<Route
|
||||
path="/managements/competition/customize/edit/:id"
|
||||
render={(props) => (
|
||||
<CompetionSetting {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
<Route
|
||||
path="/managements/competition/customize/add"
|
||||
render={(props) => (
|
||||
<CompetionSetting {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
{/* 定制竞赛配置列表 */}
|
||||
<Route
|
||||
path="/managements/competition/customize"
|
||||
render={(props) => (
|
||||
<CompetionCustomize {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
</Switch>
|
||||
</Layouts>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default withRouter(
|
||||
ImageLayerOfCommentHOC({
|
||||
imgSelector: ".imageLayerParent img, .imageLayerParent .imageTarget",
|
||||
parentSelector: ".newMain",
|
||||
})(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(Managements))))
|
||||
);
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
.managements{
|
||||
margin-left: 13.75rem;
|
||||
padding:0 1.875rem 1.6rem;
|
||||
background: #f6f9fe;
|
||||
min-height: 80vh;
|
||||
.content{
|
||||
margin-top:1rem;
|
||||
}
|
||||
}
|
||||
.management-content-head{
|
||||
background-color: #fff;
|
||||
margin-top: 1.5rem;
|
||||
padding: 1.5rem;
|
||||
border-radius:4px;
|
||||
box-shadow:0px 0px 10px rgba(88, 116, 255, 0.18);
|
||||
>p{
|
||||
color:#18191e;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px solid #e2e6f5;
|
||||
}
|
||||
}
|
||||
.managements .ant-table-thead > tr > th,.managements .ant-table-tbody > tr > td {
|
||||
padding: 1rem 1rem;
|
||||
text-align: left;
|
||||
.ant-btn{
|
||||
padding: 0 9px;
|
||||
}
|
||||
.f20{
|
||||
border-color:#f20000;
|
||||
span{
|
||||
color:#f20000;
|
||||
}
|
||||
}
|
||||
.f89{
|
||||
border-color:#f89d00;
|
||||
span{
|
||||
color:#f89d00;
|
||||
}
|
||||
}
|
||||
.c2a3{
|
||||
border-color:#2a3ee9;
|
||||
&.bor{
|
||||
background-color: #fff;
|
||||
span{color:#2a3ee9;}
|
||||
}
|
||||
&.full{
|
||||
background-color:#2a3ee9;
|
||||
span{color: white;}
|
||||
}
|
||||
&.disabled{
|
||||
background-color:#f2f2f2;
|
||||
border: none;
|
||||
span{color:#a6adc4;}
|
||||
}
|
||||
}
|
||||
}
|
||||
.f20{
|
||||
border-color:#f20000;
|
||||
span{
|
||||
color:#f20000;
|
||||
}
|
||||
}
|
||||
.f89{
|
||||
border-color:#f89d00;
|
||||
span{
|
||||
color:#f89d00;
|
||||
}
|
||||
}
|
||||
.c2a3{
|
||||
border-color:#2a3ee9;
|
||||
&.bor{
|
||||
background-color: #fff;
|
||||
span{color:#2a3ee9;}
|
||||
}
|
||||
&.full{
|
||||
background-color:#2a3ee9;
|
||||
span{color: white;}
|
||||
}
|
||||
&.disabled{
|
||||
background-color:#f2f2f2;
|
||||
border: none;
|
||||
span{color:#a6adc4;}
|
||||
}
|
||||
}
|
||||
// 系统默认字体大小是16px,大屏的在此基础上增大字体
|
||||
@media screen and (min-width: 1921px) {
|
||||
html{
|
||||
font-size: calc(100% + 6 * (100vw - 1920px) / 1000 );
|
||||
font-size: calc(100% + 6 * (100vw - 1920px) / 1000 );
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
.search-list{
|
||||
margin-top: 1rem;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.menuDetail{
|
||||
>div{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.ant-form-item-label{
|
||||
width: 5rem;
|
||||
justify-content: flex-end;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
}
|
||||
.menuDetail{
|
||||
.has-error .ant-form-explain{
|
||||
position: absolute;
|
||||
}
|
||||
.ant-row{
|
||||
margin-top: 24px;
|
||||
}
|
||||
.ant-row:first-child{
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,285 @@
|
|||
import React, { useCallback, useEffect, useState, useMemo } from 'react';
|
||||
import { Input, Select, Button, Form, message, Switch, Radio, Popconfirm, TreeSelect } from 'antd';
|
||||
import {createMenu, deleteMenu, treeList, updateMenu, updateMenuStatus} from '../../api';
|
||||
import PaginationTable from '../../../components/pagination-table';
|
||||
import Modal from '../../../components/modal/index';
|
||||
|
||||
import './index.scss';
|
||||
import '../index.scss';
|
||||
const Option = Select.Option;
|
||||
|
||||
export default Form.create()(({ form}) => {
|
||||
const { getFieldDecorator, setFieldsValue, getFieldsValue, validateFields } = form;
|
||||
const [reload, setReload] = useState();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [curPage, setCurPage] = useState(1);
|
||||
const [total, setTotal] = useState(0);
|
||||
// 菜单列表
|
||||
const [dataList, setDataList] = useState([]);
|
||||
// 菜单列表(多一个无上级菜单)
|
||||
const [treeNode, setTreeNode] = useState([]);
|
||||
// 新增、编辑菜单详情信息
|
||||
const [menuDetailModal, setMenuDetailModal] = useState(false);
|
||||
const [editMenuModal, setEditMenuModal] = useState(false);
|
||||
const [editMenuId, setEditMenuId] = useState(undefined);
|
||||
const [treeSelectValue, setTreeSelectValue] = useState(undefined);
|
||||
const helper = useCallback(
|
||||
(label, name, rules, widget, initialValue) => (
|
||||
<Form.Item label={label}>
|
||||
{getFieldDecorator(name, { rules, initialValue, validateFirst: true, })(widget)}
|
||||
</Form.Item>
|
||||
), []);
|
||||
|
||||
const columns = useMemo(() => {
|
||||
return [
|
||||
{
|
||||
title: '菜单名称',
|
||||
dataIndex: 'title',
|
||||
render: (text, record) => (
|
||||
text || record.name
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '菜单级数',
|
||||
dataIndex: 'level',
|
||||
render: (text, record) => (text+1),
|
||||
},
|
||||
{
|
||||
title: '路由',
|
||||
dataIndex: 'location',
|
||||
width: "20%",
|
||||
render: (text, record) => (text || '--'),
|
||||
},
|
||||
{
|
||||
title: '前端图标',
|
||||
dataIndex: 'icon',
|
||||
width: "20%",
|
||||
render: (text, record) => {return text || '--'}
|
||||
},
|
||||
{
|
||||
title: '是否显示',
|
||||
dataIndex: 'hidden',
|
||||
render: (text, record) => {
|
||||
return <Switch checked={text==1} onChange={(checked)=>changeMenuStatus(checked, record.key)}/>
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
dataIndex: 'key',
|
||||
align: 'center',
|
||||
render: (text, record) => {
|
||||
return(
|
||||
<React.Fragment>
|
||||
<Button className="mr5 f89" onClick={()=>editMenuDetail(record)}>编辑</Button>
|
||||
<Popconfirm placement="bottom" title="你确认要删除此菜单吗?" onConfirm={()=>deleteMenuById(text)}>
|
||||
<Button className='mr5 f20'>删除</Button>
|
||||
</Popconfirm>
|
||||
</React.Fragment>
|
||||
)},
|
||||
},
|
||||
]
|
||||
}, [curPage, reload]);
|
||||
|
||||
const menuDetail =(
|
||||
<div className='menuDetail'>
|
||||
{helper(
|
||||
"菜单名称",
|
||||
"menuName",
|
||||
[{ max: 20, message: '长度不能超过20个字符' },{required: true, message: "菜单名称不能为空"}],
|
||||
<Input
|
||||
placeholder="请输入菜单名称"
|
||||
/>
|
||||
)}
|
||||
{helper(
|
||||
"上级菜单",
|
||||
"parentKey",
|
||||
[],
|
||||
<TreeSelect
|
||||
className="column-select"
|
||||
treeData={treeNode}
|
||||
placeholder="请选择上级菜单"
|
||||
style={{ width: '195px' }}
|
||||
allowClear
|
||||
value={treeSelectValue}
|
||||
onChange={(value)=>setTreeSelectValue(value)}
|
||||
/>,
|
||||
)}
|
||||
{helper(
|
||||
"路由",
|
||||
"location",
|
||||
[{ max: 100, message: '长度不能超过100个字符' }],
|
||||
<Input
|
||||
placeholder="请输入前端路由"
|
||||
/>
|
||||
)}
|
||||
{helper(
|
||||
"前端图标",
|
||||
"icon",
|
||||
[{ max: 100, message: '长度不能超过100个字符' }],
|
||||
<Input
|
||||
placeholder="请输入前端图标"
|
||||
/>
|
||||
)}
|
||||
{helper(
|
||||
"是否显示",
|
||||
"hidden",
|
||||
[],
|
||||
<Radio.Group>
|
||||
<Radio value={1}>是</Radio>
|
||||
<Radio value={0}>否</Radio>
|
||||
</Radio.Group>,
|
||||
)}
|
||||
{helper(
|
||||
"环境",
|
||||
"urlType",
|
||||
[],
|
||||
<Select
|
||||
className="column-select"
|
||||
>
|
||||
<Option key={'self'}>8000环境</Option>
|
||||
<Option key={'current_main_site_url'}>8000项目管理</Option>
|
||||
<Option key={'main_web_site_url'}>8001环境</Option>
|
||||
</Select>,
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
//菜单是否启用
|
||||
function changeMenuStatus(checked, MenuId){
|
||||
updateMenuStatus(MenuId, checked ? 1: 0).then(response=>{
|
||||
if(response && response.message=='success'){
|
||||
message.success("状态更新成功");
|
||||
setReload(Math.random());
|
||||
}else{
|
||||
message.error('状态更新失败');
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function addMenu(){
|
||||
validateFields((error, values) => {
|
||||
if(!error){
|
||||
// 获取用户输入的内容
|
||||
const params = {
|
||||
name: values.menuName,
|
||||
title: values.menuName,
|
||||
parentKey: parseInt(values.parentKey || 0),
|
||||
location: values.location,
|
||||
icon: values.icon,
|
||||
hidden: values.hidden,
|
||||
level: parseInt(values.parentKey)+1,
|
||||
urlType:values.urlType,
|
||||
}
|
||||
createMenu(params).then(response=>{
|
||||
if(response && response.message=='success'){
|
||||
message.success("菜单新建成功");
|
||||
setReload(Math.random());
|
||||
setMenuDetailModal(false);
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//删除菜单
|
||||
function deleteMenuById(menuId){
|
||||
// 获取用户输入的内容
|
||||
deleteMenu(menuId).then(response=>{
|
||||
if(response && response.message=='success'){
|
||||
message.success("菜单删除成功");
|
||||
setReload(Math.random());
|
||||
}else{
|
||||
message.error('菜单删除失败');
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//编辑菜单
|
||||
function editMenuDetail(roleDetail){
|
||||
setEditMenuId(roleDetail.key);
|
||||
setFieldsValue({
|
||||
menuName: roleDetail.name,
|
||||
parentKey: roleDetail.parentKey.toString(),
|
||||
location: roleDetail.location,
|
||||
icon: roleDetail.icon,
|
||||
hidden: roleDetail.hidden,
|
||||
urlType: roleDetail.urlType
|
||||
});
|
||||
setEditMenuModal(true);
|
||||
}
|
||||
|
||||
// 编辑菜单信息
|
||||
function editMenu(){
|
||||
validateFields((error, values) => {
|
||||
if(!error){
|
||||
// 获取用户输入的内容
|
||||
const params = {
|
||||
...values,
|
||||
title: values.menuName,
|
||||
name: values.menuName,
|
||||
}
|
||||
updateMenu(editMenuId, params).then(response=>{
|
||||
if(response && response.message=='success'){
|
||||
setReload(Math.random());
|
||||
setEditMenuModal(false);
|
||||
message.success("菜单更新成功");
|
||||
}else{
|
||||
message.error('菜单更新失败');
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 遍历数组,对象新增value属性,新增或者修改菜单 选择上级菜单需要使用
|
||||
function valueFun(menus) {
|
||||
const treeList = menus.slice(0, menus.length);
|
||||
treeList.map(item=>{
|
||||
item.value = item.key;
|
||||
if (Array.isArray(item.children) && item.children.length > 0) {
|
||||
valueFun(item.children);
|
||||
}
|
||||
})
|
||||
treeList.unshift({key:'0', value: '0', title: "无上级菜单"});
|
||||
setTreeNode(treeList);
|
||||
}
|
||||
|
||||
useEffect(()=>{
|
||||
setLoading(true);
|
||||
treeList().then(response=>{
|
||||
if(response && response.message=='success'){
|
||||
setDataList(response.data);
|
||||
valueFun(response.data);
|
||||
}
|
||||
}).finally(()=>{
|
||||
setLoading(false);
|
||||
})
|
||||
},[reload])
|
||||
|
||||
return (
|
||||
<div className="centerbox task-manage-all ">
|
||||
<div className='management-content-head'>
|
||||
<p className='font-18'>菜单列表</p>
|
||||
<div className="search-list" >
|
||||
<Button className='c2a3 full' onClick={()=>{setFieldsValue({hidden: 1,menuName: '',parentKey: undefined,location: '',icon: '', urlType: "self"}); setMenuDetailModal(true);}}>新增</Button>
|
||||
<Modal visible={menuDetailModal} title="新增菜单" content={menuDetail} onOk={addMenu} onCancel={()=>setMenuDetailModal(false)}/>
|
||||
<Modal visible={editMenuModal} title="编辑菜单" content={menuDetail} onOk={editMenu} onCancel={()=>setEditMenuModal(false)}/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="center-content">
|
||||
<PaginationTable
|
||||
loading={loading}
|
||||
rowKey={row=> row.key}
|
||||
dataSource={dataList}
|
||||
columns={columns}
|
||||
total={total}
|
||||
current={curPage}
|
||||
setCurPage={(page)=>{setCurPage(page)}}
|
||||
className="expertReviewTable"
|
||||
indentSize={30}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
// .ant-table-row-collapsed::after, .ant-table-row-expanded::after{
|
||||
// content: '查看下级';
|
||||
// color:#2a3ee9;
|
||||
// }
|
||||
// .ant-table-row-expand-icon, .ant-table-row-expand-icon{
|
||||
// width: auto;
|
||||
// height: 32px;
|
||||
// line-height: 32px;
|
||||
// padding: 0 9px;
|
||||
// border-color:#2a3ee9;
|
||||
// background-color: #fff;
|
||||
// :hover, :hover::after{
|
||||
// border-color:#2a3ee9;
|
||||
// opacity: 0.75;
|
||||
// }
|
||||
// }
|
||||
|
||||
.column-select .ant-select-selection{
|
||||
width: 193px;
|
||||
}
|
||||
|
|
@ -0,0 +1,286 @@
|
|||
import React, { useCallback, useEffect, useState, useMemo } from 'react';
|
||||
import { Input, Button, Form, message, Radio, Switch, Popconfirm, Tree } from 'antd';
|
||||
import Modal from '../../../components/modal/index';
|
||||
import PaginationTable from '../../../components/pagination-table';
|
||||
import './index.scss';
|
||||
import '../index.scss';
|
||||
import '../../index.scss';
|
||||
import { createRole, deleteRole, roleList, updateRoleStatus, updateRole, treeList, allocMenu, listMenu } from 'src/managements/api';
|
||||
const { TextArea } = Input;
|
||||
|
||||
export default Form.create()(({form}) => {
|
||||
const { getFieldDecorator, setFieldsValue, getFieldsValue, validateFields } = form;
|
||||
const [reload, setReload] = useState();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [curPage, setCurPage] = useState(1);
|
||||
const [total, setTotal] = useState(0);
|
||||
//角色列表
|
||||
const [dataList, setDataList] = useState([]);
|
||||
// 角色详情弹框
|
||||
const [roleDetailModal, setRoleDetailModal] = useState(false);
|
||||
// 更新角色信息弹框
|
||||
const [editRoleModal, setEditRoleModal] = useState(false);
|
||||
const [editRoleId, setEditRoleId] = useState(undefined);
|
||||
//分配菜单弹框
|
||||
const [menuModal, setMenuModal] = useState(false);
|
||||
const [menuTreeData, setMenuTreeData] = useState(false);
|
||||
const [roleId, setRoleId] = useState(undefined);
|
||||
//选中的菜单项
|
||||
const [selectedMenu, setSelectedMenu] = useState(undefined);
|
||||
// 选中的菜单项(子菜单项未选中,带父菜单项)
|
||||
const [selectedMenuFa, setSelectedMenuFa] = useState(undefined);
|
||||
// 一级菜单项
|
||||
let oneTree = [];
|
||||
|
||||
const helper = useCallback(
|
||||
(label, name, rules, widget, initialValue) => (
|
||||
<Form.Item label={label}>
|
||||
{getFieldDecorator(name, { rules, initialValue, validateFirst: true, })(widget)}
|
||||
</Form.Item>
|
||||
), []);
|
||||
|
||||
const columns = useMemo(() => {
|
||||
return [
|
||||
{
|
||||
title: '编号',
|
||||
dataIndex: 'number',
|
||||
render: (text, record, index) => (
|
||||
index+1
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '角色名称',
|
||||
dataIndex: 'name'
|
||||
},
|
||||
{
|
||||
title: '描述',
|
||||
dataIndex: 'description',
|
||||
width: "20%"
|
||||
},
|
||||
{
|
||||
title: '添加时间',
|
||||
dataIndex: 'createTime',
|
||||
render: (text, record) => {
|
||||
text = text && text.replaceAll('-','/').substring(0,16);
|
||||
return text || '--'
|
||||
}
|
||||
},
|
||||
// {
|
||||
// title: '是否启用',
|
||||
// dataIndex: 'status',
|
||||
// render: (text, record) => {
|
||||
// return <Switch defaultChecked={text == 1} onChange={(checked)=>changeRoleStatus(checked, record.id)}/>
|
||||
// }
|
||||
// },
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
dataIndex: 'id',
|
||||
align: 'center',
|
||||
render: (text, record) => {
|
||||
return(
|
||||
<React.Fragment>
|
||||
<Button className="mr5 c2a3 full" onClick={()=>menuListByRole(text)}>分配菜单</Button>
|
||||
<Button className="mr5 f89" onClick={()=>editRoleDetail(record)}>编辑</Button>
|
||||
<Popconfirm placement="bottom" title="你确认要删除此角色吗?" onConfirm={()=>deleteRoleById(text)}>
|
||||
<Button className='mr5 f20'>删除</Button>
|
||||
</Popconfirm>
|
||||
</React.Fragment>
|
||||
)},
|
||||
},
|
||||
]
|
||||
}, [curPage]);
|
||||
|
||||
const roleDetail =(
|
||||
<div className='menuDetail'>
|
||||
{helper(
|
||||
"角色名称",
|
||||
"name",
|
||||
[{ max: 20, message: '长度不能超过20个字符'},
|
||||
{ required: true, message: "角色名称不能为空"},
|
||||
{ validator: (rule, value, callback)=>{
|
||||
// 角色名称是否存在 要过滤掉编辑菜单项的初始值
|
||||
const filter = dataList.filter(item=>{ return item.id !== editRoleId && item.name === value});
|
||||
filter.length>0 ? callback('此角色名称已存在'):callback();
|
||||
}}],
|
||||
<Input
|
||||
placeholder="请输入角色名称"
|
||||
/>
|
||||
)}
|
||||
{helper(
|
||||
"描述",
|
||||
"description",
|
||||
[{ max: 500, message: '长度不能超过500个字符'}],
|
||||
<TextArea rows={4}/>,
|
||||
)}
|
||||
{false && helper(
|
||||
"是否启用",
|
||||
"status",
|
||||
[],
|
||||
<Radio.Group>
|
||||
<Radio value={1}>是</Radio>
|
||||
<Radio value={0}>否</Radio>
|
||||
</Radio.Group>,
|
||||
1
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
const menuTree = (
|
||||
<Tree
|
||||
checkable
|
||||
treeData={menuTreeData}
|
||||
onCheck={(checkedKeys, info)=>{const keys = [...checkedKeys, ...info.halfCheckedKeys]; setSelectedMenu(checkedKeys); setSelectedMenuFa(keys)}}
|
||||
checkedKeys={selectedMenu}
|
||||
/>
|
||||
)
|
||||
|
||||
function addRole(){
|
||||
validateFields((error, values) => {
|
||||
if(!error){
|
||||
// 获取用户输入的内容
|
||||
// let values = getFieldsValue(['name', 'description']);
|
||||
const params = {
|
||||
...values
|
||||
}
|
||||
createRole(params).then(response=>{
|
||||
if(response && response.message=='success'){
|
||||
message.success("角色新建成功");
|
||||
setReload(Math.random());
|
||||
setRoleDetailModal(false);
|
||||
}else{
|
||||
message.error('角色新建失败');
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
//删除角色
|
||||
function deleteRoleById(roleId){
|
||||
// 获取用户输入的内容
|
||||
deleteRole(roleId).then(response=>{
|
||||
if(response && response.message=='success'){
|
||||
message.success("角色删除成功");
|
||||
setReload(Math.random());
|
||||
}else{
|
||||
message.error('角色删除失败');
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//角色是否启用
|
||||
function changeRoleStatus(checked, roleId){
|
||||
updateRoleStatus(roleId, checked ? 1: 0).then(response=>{
|
||||
if(response && response.message=='success'){
|
||||
message.success("状态更新成功");
|
||||
}else{
|
||||
message.error('状态更新失败');
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function editRoleDetail(roleDetail){
|
||||
setEditRoleId(roleDetail.id);
|
||||
setFieldsValue({
|
||||
name: roleDetail.name,
|
||||
description: roleDetail.description,
|
||||
});
|
||||
setEditRoleModal(true);
|
||||
}
|
||||
|
||||
// 编辑角色信息
|
||||
function editRole(){
|
||||
validateFields((error, values) => {
|
||||
if(!error){
|
||||
// 获取用户输入的内容
|
||||
const params = {
|
||||
...values
|
||||
}
|
||||
updateRole(editRoleId, params).then(response=>{
|
||||
if(response && response.message=='success'){
|
||||
message.success("角色更新成功");
|
||||
setReload(Math.random());
|
||||
setEditRoleModal(false);
|
||||
}else{
|
||||
message.error('角色更新失败');
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 获取角色已分配的菜单项
|
||||
function menuListByRole(roleId){
|
||||
listMenu(roleId).then(response=>{
|
||||
if(response && response.message=='success'){
|
||||
// 过滤掉一级菜单项
|
||||
const keys = response.data.map(item=>{return oneTree.indexOf(item.key.toString()) === -1 ? item.key.toString() : null});
|
||||
setSelectedMenu(keys);
|
||||
setRoleId(roleId);
|
||||
setMenuModal(true);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 分配菜单
|
||||
function allotMenu(){
|
||||
allocMenu(roleId, selectedMenuFa).then(response=>{
|
||||
if(response && response.message=='success'){
|
||||
message.success("分配成功");
|
||||
setMenuModal(false);
|
||||
}else{
|
||||
message.error('分配失败');
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(()=>{
|
||||
treeList().then(response=>{
|
||||
if(response && response.message=='success'){
|
||||
oneTree = response.data.map(item=>{return item.key.toString()});
|
||||
setMenuTreeData(response.data);
|
||||
}
|
||||
}).finally(()=>{
|
||||
setLoading(false);
|
||||
})
|
||||
},[])
|
||||
|
||||
useEffect(()=>{
|
||||
setLoading(true);
|
||||
roleList().then(response=>{
|
||||
if(response && response.message=='success'){
|
||||
setDataList(response.data);
|
||||
}
|
||||
}).finally(()=>{
|
||||
setLoading(false);
|
||||
})
|
||||
},[reload])
|
||||
|
||||
return (
|
||||
<div className="centerbox task-manage-all ">
|
||||
<div className='management-content-head'>
|
||||
<p className='font-18'>角色列表</p>
|
||||
<div className="search-list">
|
||||
<Button className='c2a3 full' onClick={()=>{setRoleDetailModal(true); setEditRoleId(undefined); setFieldsValue({name: '',description: ''})}}>新增</Button>
|
||||
<Modal visible={roleDetailModal} title="添加角色" content={roleDetail} onOk={addRole} onCancel={()=>setRoleDetailModal(false)}/>
|
||||
<Modal visible={editRoleModal} title="编辑角色" content={roleDetail} onOk={editRole} onCancel={()=>setEditRoleModal(false)}/>
|
||||
<Modal visible={menuModal} title="分配菜单" content={menuTree} onOk={allotMenu} onCancel={()=>setMenuModal(false)}/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="center-content">
|
||||
<PaginationTable
|
||||
loading={loading}
|
||||
rowKey={(row) => row.id}
|
||||
dataSource={dataList}
|
||||
columns={columns}
|
||||
total={total}
|
||||
current={curPage}
|
||||
setCurPage={(page)=>{setCurPage(page)}}
|
||||
className="expertReviewTable"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
import React, { useCallback, useEffect, useState, useMemo } from 'react';
|
||||
import {Select, Form, message } from 'antd';
|
||||
import PaginationTable from '../../../components/pagination-table';
|
||||
import './index.scss';
|
||||
import '../index.scss';
|
||||
import { adminUserList, roleList, updateUserRole } from 'src/managements/api';
|
||||
const Option = Select.Option;
|
||||
|
||||
export default Form.create()(({form}) => {
|
||||
const { getFieldDecorator, setFieldsValue, getFieldsValue } = form;
|
||||
|
||||
const [reload, setReload] = useState();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [curPage, setCurPage] = useState(1);
|
||||
const [total, setTotal] = useState(0);
|
||||
const [dataList, setDataList] = useState([]);
|
||||
//角色列表
|
||||
const [rolesList, setRolesList] = useState([]);
|
||||
|
||||
const helper = useCallback(
|
||||
(label, name, rules, widget, initialValue) => (
|
||||
<Form.Item label={label}>
|
||||
{getFieldDecorator(name, { rules, initialValue, validateFirst: true, })(widget)}
|
||||
</Form.Item>
|
||||
), []);
|
||||
|
||||
const columns = useMemo(() => {
|
||||
return [
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'login'
|
||||
},
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
},
|
||||
{
|
||||
title: '邮箱',
|
||||
dataIndex: 'email',
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createdOn',
|
||||
render: (text, record) => {
|
||||
text = text && text.replaceAll('-','/').substring(0,16);
|
||||
return text || '--'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '最后登录时间',
|
||||
dataIndex: 'lastLoginOn',
|
||||
render: (text, record) => {
|
||||
text = text && text.replaceAll('-','/').substring(0,16);
|
||||
return text || '--'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '角色',
|
||||
key: 'action',
|
||||
dataIndex: 'roles',
|
||||
align: 'center',
|
||||
render: (text, record) => {
|
||||
return(
|
||||
<Select
|
||||
mode="multiple"
|
||||
className="column-select"
|
||||
defaultValue={(text && text.substring(1, text.length-1).replaceAll(' ','').split(',')) || []}
|
||||
onChange={(key) => { changeRole(key, record.id) }}
|
||||
style={{ minWidth: 200 }}
|
||||
placeholder="请选择角色"
|
||||
>
|
||||
{
|
||||
rolesList && rolesList.map(item => {
|
||||
return <Option key={parseInt(item.id)}>{item.name}</Option>
|
||||
})
|
||||
}
|
||||
</Select>
|
||||
)},
|
||||
},
|
||||
]
|
||||
}, [curPage, rolesList]);
|
||||
|
||||
function changeRole(value, userId){
|
||||
updateUserRole(userId, value).then(response=>{
|
||||
if(response && response.message!='success'){
|
||||
message.error('用户更新失败');
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(()=>{
|
||||
roleList().then(response=>{
|
||||
if(response && response.message=='success'){
|
||||
setRolesList(response.data);
|
||||
}
|
||||
})
|
||||
},[])
|
||||
|
||||
useEffect(()=>{
|
||||
setLoading(true);
|
||||
adminUserList().then(response=>{
|
||||
if(response && response.message=='success'){
|
||||
setDataList(response.data);
|
||||
}
|
||||
}).finally(()=>{
|
||||
setLoading(false);
|
||||
})
|
||||
},[reload])
|
||||
|
||||
return (
|
||||
<div className="centerbox task-manage-all ">
|
||||
<div className='management-content-head'>
|
||||
<p className='font-18'>管理员列表</p>
|
||||
<div className="search-list" ></div>
|
||||
</div>
|
||||
<div className="center-content">
|
||||
<PaginationTable
|
||||
loading={loading}
|
||||
rowKey={(row) => row.id}
|
||||
dataSource={dataList}
|
||||
columns={columns}
|
||||
total={total}
|
||||
current={curPage}
|
||||
setCurPage={(page)=>{setCurPage(page)}}
|
||||
className="expertReviewTable"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
import fetch from 'military/notice/fetch';
|
||||
import showNotification from '../components/ShowNotification';
|
||||
|
||||
|
||||
// 公告列表查询
|
||||
export async function getNoticeList(params) {
|
||||
let res = await fetch({
|
||||
url: '/api/announcements/',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
if (res.message === 'success') {
|
||||
return res.data;
|
||||
} else {
|
||||
showNotification(res.message || '请求错误');
|
||||
}
|
||||
}
|
||||
|
||||
//新增公告
|
||||
export function addNotice(data) {
|
||||
return fetch({
|
||||
url: '/api/announcements/add',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
//删除公告
|
||||
export function deleteNotice(id) {
|
||||
return fetch({
|
||||
url: '/api/announcements/' + id,
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
|
||||
//更新公告
|
||||
export function editNotice(data) {
|
||||
return fetch({
|
||||
url: '/api/announcements/update',
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
//审核公告
|
||||
export function checkNotice(data) {
|
||||
return fetch({
|
||||
url: '/api/announcements/check',
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
// 公告详情查询
|
||||
export async function getNoticeDetail(id) {
|
||||
let res = await fetch({
|
||||
url: '/api/announcements/' + id,
|
||||
method: 'get',
|
||||
});
|
||||
if (res.data) {
|
||||
return res.data;
|
||||
} else {
|
||||
showNotification(res.message || '请求错误');
|
||||
}
|
||||
}
|
||||
|
||||
// 公告密文查看人详情
|
||||
export async function getNoticeReader(params) {
|
||||
let res = await fetch({
|
||||
url: '/api/request_contact_reader_info/',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
if (res.data) {
|
||||
return res.data;
|
||||
} else {
|
||||
showNotification(res.message || '请求错误');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
.notice-content {
|
||||
min-height: 50vh;
|
||||
margin: 1em;
|
||||
background: #fff;
|
||||
border-radius: 1em;
|
||||
box-shadow: 0 1px 2px #d9d9d9;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.notice-title {
|
||||
padding: 0.75em;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
}
|
||||
|
||||
.notice-form .edit-input{
|
||||
max-width:450px;
|
||||
}
|
||||
|
||||
.my-search-button{
|
||||
margin-top:4px;
|
||||
}
|
||||
|
||||
.encrypt-item{
|
||||
margin-top: -24px;
|
||||
}
|
||||
|
||||
.encrypt-item .ant-form-item-label{
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.ant-radio-checked .ant-radio-inner{
|
||||
border-color: #4154f1;
|
||||
}
|
||||
.ant-radio-inner::after{
|
||||
background-color: #4154f1;
|
||||
}
|
||||
.ant-radio-wrapper:hover .ant-radio, .ant-radio:hover .ant-radio-inner, .ant-radio-input:focus + .ant-radio-inner{
|
||||
border-color: #4154f1;
|
||||
}
|
||||
.ant-radio-checked::after{
|
||||
border: 1px solid #4154f1;
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
import React from "react";
|
||||
import { Route, Switch } from "react-router-dom";
|
||||
import Loadable from "react-loadable";
|
||||
import Loading from "../../Loading";
|
||||
|
||||
// 公告管理
|
||||
const NoticeList = Loadable({
|
||||
loader: () => import("./noticeList"),
|
||||
loading: Loading,
|
||||
});
|
||||
// 公告管理详情
|
||||
const NoticeDetail = Loadable({
|
||||
loader: () => import("./noticeDetail"),
|
||||
loading: Loading,
|
||||
});
|
||||
// 公告管理编辑
|
||||
const NoticeEdit = Loadable({
|
||||
loader: () => import("./noticeEdit"),
|
||||
loading: Loading,
|
||||
});
|
||||
// 公告reader
|
||||
const NoticeReader = Loadable({
|
||||
loader: () => import("./noticeReader"),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
export default (propsF)=>{
|
||||
return (
|
||||
<Switch {...propsF}>
|
||||
{/* 公告列表 */}
|
||||
<Route
|
||||
path="/managements/notice/list/:isChecked"
|
||||
render={(props) => (
|
||||
<NoticeList {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
{/* 公告详情 */}
|
||||
<Route
|
||||
path="/managements/notice/detail/:noticeId"
|
||||
render={(props) => (
|
||||
<NoticeDetail {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
{/* 公告编辑 */}
|
||||
<Route
|
||||
path="/managements/notice/edit/:noticeId"
|
||||
render={(props) => (
|
||||
<NoticeEdit {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
{/* 公告新增 */}
|
||||
<Route
|
||||
path="/managements/notice/edit"
|
||||
render={(props) => (
|
||||
<NoticeEdit {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
{/* 公告预览 */}
|
||||
<Route
|
||||
path="/managements/notice/reader/:noticeId"
|
||||
render={(props) => (
|
||||
<NoticeReader {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
</Switch>
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { Button, Descriptions, Icon } from 'antd';
|
||||
import ShowNotification from '../../components/ShowNotification';
|
||||
import { noticeType, noticeChecked } from '../../common/static';
|
||||
import { getNoticeDetail, checkNotice } from '../api';
|
||||
import '../index.css';
|
||||
import './index.scss';
|
||||
|
||||
const noticeTypeArr = [];
|
||||
for (const item of noticeType) {
|
||||
noticeTypeArr[item.code] = (item.name);
|
||||
}
|
||||
const noticeCheckedArr = [];
|
||||
for (const item of noticeChecked) {
|
||||
noticeCheckedArr[item.code] = (item.name);
|
||||
}
|
||||
|
||||
const IndexPage = ({ match, history, current_user: { admin } }) => {
|
||||
const [noticeData, setNoticeData] = useState({});
|
||||
const id = match.params.noticeId;
|
||||
|
||||
useEffect(() => {
|
||||
id && getNoticeDetail(id).then(data => {
|
||||
setNoticeData(data || {});
|
||||
})
|
||||
}, [id]);
|
||||
|
||||
// 审核
|
||||
function checkItem(isChecked) {
|
||||
checkNotice({
|
||||
id: noticeData.id,
|
||||
isChecked,
|
||||
}).then(res => {
|
||||
if (res && res.code == '1') {
|
||||
ShowNotification("操作成功");
|
||||
history.go(-1);
|
||||
} else {
|
||||
ShowNotification(res.message || "操作失败");
|
||||
history.go(-1);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function download(url) {
|
||||
if (window.location.href.indexOf('localhost') > -1) {
|
||||
url = 'http://106.75.31.211:58088' + url;
|
||||
}
|
||||
window.open(url);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="notice-content">
|
||||
<h4 className="notice-title"><span className='backList' onClick={() => { history.go(-1) }}><Icon type="left" />返回</span>公告详情</h4>
|
||||
|
||||
<Descriptions className='itemContent' column={1}>
|
||||
<Descriptions.Item label="公告状态"><span className='statusColor'>{noticeData.status == 1 ? noticeCheckedArr[noticeData.isChecked] : '草稿'}</span></Descriptions.Item>
|
||||
<Descriptions.Item label="公告标题">{noticeData.title}</Descriptions.Item>
|
||||
<Descriptions.Item label="公告类型">{noticeTypeArr[noticeData.type]}</Descriptions.Item>
|
||||
<Descriptions.Item label="发布单位">{noticeData.publisher}</Descriptions.Item>
|
||||
<Descriptions.Item label="公告描述" className='alignTop'><div className="editor-w-text" dangerouslySetInnerHTML={{ __html: noticeData.text }}></div></Descriptions.Item>
|
||||
{[4, 5, 6].includes(noticeData.type) && <Descriptions.Item label="联系方式" className='alignTop'><div className="editor-w-text" dangerouslySetInnerHTML={{ __html: noticeData.contactInfo && noticeData.contactInfo.replace(/\n/g, '</br>') }}></div></Descriptions.Item>}
|
||||
<Descriptions.Item label="公告附件">
|
||||
<div style={{ color: '#1890ff' }} onClick={() => { download(noticeData.fileDownloadPath) }}>{noticeData.fileName}</div>
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="创建时间">{noticeData.createdAt}</Descriptions.Item>
|
||||
{noticeData.publishDate && <Descriptions.Item label="发布时间">{noticeData.publishDate}</Descriptions.Item>}
|
||||
<Descriptions.Item label="截止时间">{noticeData.closingDate}</Descriptions.Item>
|
||||
<Descriptions.Item label="">
|
||||
{admin && noticeData.status == 1 && noticeData.isChecked == 2 &&
|
||||
<React.Fragment>
|
||||
<Button className="mr20" type="primary" onClick={() => { checkItem(1) }}>通过</Button>
|
||||
<Button className="mr20" type="primary" onClick={() => { checkItem(0) }}>拒绝</Button>
|
||||
<Button className="mr20" onClick={() => { history.go(-1) }}>取消</Button>
|
||||
</React.Fragment>
|
||||
}
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
export default IndexPage;
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
.itemContent {
|
||||
padding: 10px 10px 0 30px;
|
||||
}
|
||||
.statusColor{
|
||||
color: #1890ff;
|
||||
}
|
||||
.alignTop{
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
}
|
||||
.backList{
|
||||
margin-right:1em;
|
||||
&:hover{
|
||||
color: #1890ff;
|
||||
}
|
||||
}
|
||||
|
||||
:global{
|
||||
.ant-descriptions-item-label{
|
||||
min-width: 5em;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,322 @@
|
|||
import React, { forwardRef, Fragment, useCallback, useEffect, useState } from 'react';
|
||||
import ReactWEditor from 'wangeditor-for-react';
|
||||
import { Form, Input, Button, Radio, Checkbox, DatePicker } from 'antd';
|
||||
import moment from 'moment';
|
||||
import { noticeType } from '../../common/static';
|
||||
import Upload from '../../components/Upload';
|
||||
import ShowNotification from '../../components/ShowNotification';
|
||||
import { getNoticeDetail, addNotice, editNotice } from '../api';
|
||||
import { httpUrl } from 'military/notice/fetch';
|
||||
|
||||
import '../index.css';
|
||||
const format = "YYYY-MM-DD HH:mm:ss";
|
||||
const { TextArea } = Input;
|
||||
|
||||
let actionUrl = httpUrl;
|
||||
// if (window.location.href.indexOf('localhost') > -1) {
|
||||
// actionUrl = httpUrl;
|
||||
// } else {
|
||||
// actionUrl = "https://info.osredm.com";
|
||||
// }
|
||||
|
||||
const NoticeEdit = Form.create()(forwardRef(({ form, match, history }, ref) => {
|
||||
|
||||
const [fileList, setFileList] = useState(null);
|
||||
const [noticeHtml, setNoticeHtml] = useState('');
|
||||
const id = match.params.noticeId;
|
||||
const { getFieldDecorator, validateFields, setFieldsValue } = form;
|
||||
const [typeValue, setTypeValue] = useState(4);
|
||||
const [isSecret, setIsSecret] = useState();
|
||||
|
||||
useEffect(() => {
|
||||
id && getNoticeDetail(id).then(data => {
|
||||
const formValue = {
|
||||
type: data.type,
|
||||
title: data.title,
|
||||
publisher: data.publisher,
|
||||
text: data.text,
|
||||
closingDate: data.closingDate && moment(data.closingDate),
|
||||
contactInfo: data.contactInfo,
|
||||
};
|
||||
setFieldsValue(formValue);
|
||||
setNoticeHtml(data.text || '');
|
||||
setIsSecret(Boolean(data.isSecret));
|
||||
if (data.fileName) {
|
||||
setFileList([{
|
||||
name: data.fileName,
|
||||
fileName: data.fileName,
|
||||
fileDownloadPath: data.fileDownloadPath,
|
||||
uid: "rc-upload" + data.id
|
||||
}])
|
||||
}
|
||||
})
|
||||
}, [id]);
|
||||
|
||||
// 上传附件后得到的文件数组
|
||||
function UploadFunc(fileList) {
|
||||
setFileList(fileList);
|
||||
}
|
||||
|
||||
const helper = useCallback(
|
||||
(label, name, rules, widget, initialValue) => (
|
||||
<Form.Item label={label}>
|
||||
{getFieldDecorator(name, { rules, initialValue, validateFirst: true })(widget)}
|
||||
</Form.Item>
|
||||
),
|
||||
[]
|
||||
);
|
||||
|
||||
const editor = useCallback(() => (
|
||||
<Form.Item label={"公告描述:"} required={true}>
|
||||
{(!id || (id && noticeHtml)) &&
|
||||
<ReactWEditor
|
||||
defaultValue={noticeHtml}
|
||||
config={
|
||||
{
|
||||
placeholder: "请输入公告描述",
|
||||
excludeMenus: [
|
||||
'list',
|
||||
'todo',
|
||||
'emoticon',
|
||||
'video'
|
||||
],
|
||||
uploadImgServer: actionUrl + '/busiAttachments/upload',
|
||||
uploadFileName: 'file',
|
||||
uploadImgHeaders: {
|
||||
'X-Requested-With': 'XMLHttpRequest'
|
||||
},
|
||||
uploadImgHooks: {
|
||||
// 图片上传并返回了结果,想要自己把图片插入到编辑器中
|
||||
customInsert: function (insertImgFn, result) {
|
||||
// result 即服务端返回的接口
|
||||
// insertImgFn 可把图片插入到编辑器,传入图片 src ,执行函数即可
|
||||
if (result && result.data && result.data.id) {
|
||||
insertImgFn(`${actionUrl}/busiAttachments/view/${result.data.id}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
onChange={(html) => {
|
||||
changeHtml(html);
|
||||
}}
|
||||
/>}
|
||||
|
||||
{getFieldDecorator('text', {
|
||||
rules: [{ required: true, message: "请输入公告描述" }],
|
||||
validateFirst: true
|
||||
})(<Input style={{ display: 'none' }} />)}
|
||||
</Form.Item>
|
||||
), [noticeHtml])
|
||||
|
||||
const formItemLayout = {
|
||||
labelCol: {
|
||||
xs: { span: 10 },
|
||||
sm: { span: 8 },
|
||||
lg: { span: 3 },
|
||||
},
|
||||
wrapperCol: {
|
||||
xs: { span: 14 },
|
||||
sm: { span: 16 },
|
||||
lg: { span: 16 },
|
||||
},
|
||||
};
|
||||
|
||||
const tailFormItemLayout = {
|
||||
wrapperCol: {
|
||||
xs: {
|
||||
span: 20,
|
||||
offset: 4,
|
||||
},
|
||||
sm: {
|
||||
span: 20,
|
||||
offset: 4,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// 修改
|
||||
function saveItem(status) {
|
||||
validateFields((error, values) => {
|
||||
if (!error) {
|
||||
let params = {
|
||||
...values,
|
||||
status,
|
||||
fileDownloadPath: '',
|
||||
fileName: '',
|
||||
|
||||
templateUrl: '',
|
||||
};
|
||||
params.closingDate = params.closingDate.format(format);
|
||||
params.isSecret = Number(params.isSecret);
|
||||
if (fileList && fileList.length) {
|
||||
params.fileName = fileList[0].fileName || fileList[0].response.data.fileName;
|
||||
params.fileDownloadPath = fileList[0].fileDownloadPath || `${actionUrl}/busiAttachments/download/${fileList[0].response.data.id}`;
|
||||
}
|
||||
if (id) {
|
||||
// 编辑
|
||||
params.id = id;
|
||||
editNotice(params).then(res => {
|
||||
if (res.message === 'success') {
|
||||
ShowNotification("操作成功!");
|
||||
if (status == 1) {
|
||||
history.push('/managements/notice/list/2');
|
||||
} else {
|
||||
history.push('/managements/notice/list/draft');
|
||||
}
|
||||
} else {
|
||||
ShowNotification(res.message);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 新增
|
||||
addNotice(params).then(res => {
|
||||
if (res.message === 'success') {
|
||||
ShowNotification("公告新增成功!");
|
||||
if (status == 1) {
|
||||
history.push('/managements/notice/list/2');
|
||||
} else {
|
||||
history.push('/managements/notice/list/draft');
|
||||
}
|
||||
} else {
|
||||
ShowNotification(res.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function changeClosingDate(val) {
|
||||
if (val) {
|
||||
let nextTime = moment(new Date().setDate(new Date().getDate() + val)).format('YYYY-MM-DD');
|
||||
nextTime += ' 23:59:59';
|
||||
setFieldsValue({
|
||||
closingDate: moment(nextTime)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function changeHtml(html) {
|
||||
setFieldsValue({
|
||||
text: html
|
||||
});
|
||||
// setNoticeHtml(html);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="notice-content">
|
||||
<h4 className="notice-title">{id ? '修改' : '发布'}公告</h4>
|
||||
<Form className="notice-form" {...formItemLayout}>
|
||||
|
||||
{helper(
|
||||
"公告类型:",
|
||||
"type",
|
||||
[{ required: true, message: "请选择公告类型" }],
|
||||
<Radio.Group
|
||||
onChange={(e) => { setTypeValue(e.target.value) }}
|
||||
>
|
||||
{
|
||||
noticeType.map(item => {
|
||||
return <Radio key={item.code} value={item.code}>{item.name}</Radio>
|
||||
})
|
||||
}
|
||||
</Radio.Group>,
|
||||
4
|
||||
)}
|
||||
|
||||
{helper(
|
||||
"公告标题:",
|
||||
"title",
|
||||
[{ required: true, message: "请输入公告标题" },
|
||||
{ max: 50, message: '长度不能超过50个字符' }],
|
||||
<Input
|
||||
className="edit-input"
|
||||
placeholder="请输入公告标题"
|
||||
/>
|
||||
)}
|
||||
|
||||
{helper(
|
||||
"发布单位:",
|
||||
"publisher",
|
||||
[{ required: true, message: "请输入发布单位" },
|
||||
{ max: 50, message: '长度不能超过50个字符' }],
|
||||
<Input
|
||||
className="edit-input"
|
||||
placeholder="请输入发布单位"
|
||||
/>
|
||||
)}
|
||||
|
||||
{editor()}
|
||||
|
||||
{[4, 5, 6].includes(typeValue) && <Fragment>
|
||||
{helper(
|
||||
"联系方式:",
|
||||
"contactInfo",
|
||||
[{ max: 5000, message: '长度不能超过5000个字符' }],
|
||||
<TextArea
|
||||
rows={4}
|
||||
// className="edit-input"
|
||||
placeholder="请输入联系方式"
|
||||
/>
|
||||
)}
|
||||
|
||||
<Form.Item className="encrypt-item" label="加密与否">
|
||||
{/* <Checkbox checked={isSecret} onChange={e => { setIsSecret(e.target.checked) }}>设置联系方式为加密内容</Checkbox> */}
|
||||
{getFieldDecorator('isSecret',
|
||||
{
|
||||
validateFirst: true
|
||||
})(<Checkbox checked={isSecret} onChange={e => { setIsSecret(e.target.checked) }}>设置联系方式为加密内容</Checkbox>)}
|
||||
</Form.Item>
|
||||
</Fragment>}
|
||||
|
||||
|
||||
<Form.Item label={"上传文件:"}>
|
||||
<Upload
|
||||
className="commentStyle"
|
||||
load={UploadFunc}
|
||||
size={100}
|
||||
ShowNotification={ShowNotification}
|
||||
actionUrl={actionUrl}
|
||||
fileList={fileList}
|
||||
number={1}
|
||||
/>
|
||||
{/* 用一个隐藏的input实现上传文件的必填校验 */}
|
||||
{/* {getFieldDecorator('file_name', {
|
||||
rules: [{ required: true, message: "请上传公告文件" }],
|
||||
validateFirst: true
|
||||
})(<Input style={{ display: 'none' }} />)} */}
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item label="截止时间:">
|
||||
<Radio.Group onChange={(e) => { changeClosingDate(e.target.value) }}>
|
||||
<Radio value={6}>一周内</Radio>
|
||||
<Radio value={29}>一个月内</Radio>
|
||||
<Radio value={90}>三个月内</Radio>
|
||||
<Radio value={182}>半年内</Radio>
|
||||
<Radio value={0}>自定义</Radio>
|
||||
</Radio.Group>
|
||||
{getFieldDecorator('closingDate',
|
||||
{
|
||||
rules: [{ required: true, message: "请选择截止时间" }],
|
||||
validateFirst: true
|
||||
})(<DatePicker
|
||||
showTime
|
||||
format={format}
|
||||
placeholder="请选择截止时间"
|
||||
/>)}
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item {...tailFormItemLayout}>
|
||||
<Button className="mr20" type={"primary"} onClick={() => { saveItem(1) }}>发布</Button>
|
||||
<Button className="mr20" type={"primary"} onClick={() => { saveItem(2) }}>保存</Button>
|
||||
<Button onClick={() => { history.go(-1) }}>取消</Button>
|
||||
</Form.Item>
|
||||
|
||||
</Form>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
)
|
||||
|
||||
export default NoticeEdit;
|
||||
|
|
@ -0,0 +1,302 @@
|
|||
import React, { forwardRef, useEffect, useState, useCallback } from 'react';
|
||||
import { Button, Form, Modal, Input, Select, Radio, } from 'antd';
|
||||
import PaginationTable from "../../../components/pagination-table";
|
||||
import { noticeType } from '../../common/static';
|
||||
import DelModal from '../../components/DelModal';
|
||||
import ShowNotification from '../../components/ShowNotification';
|
||||
|
||||
import { getNoticeList, checkNotice, deleteNotice } from '../api';
|
||||
import '../index.css';
|
||||
import './index.scss';
|
||||
const Option = Select.Option;
|
||||
|
||||
const noticeTypeArr = [];
|
||||
for (const item of noticeType) {
|
||||
noticeTypeArr[item.code] = (item.name);
|
||||
}
|
||||
|
||||
const NoticeList = Form.create()(forwardRef(({ form, match, history, current_user: { admin } }, ref) => {
|
||||
let status = 1;
|
||||
let isChecked = match.params.isChecked;
|
||||
if (history.location.pathname.indexOf('draft') > -1) {
|
||||
status = 2;
|
||||
isChecked ='';
|
||||
}
|
||||
|
||||
const { getFieldDecorator, validateFields, setFieldsValue, } = form;
|
||||
|
||||
const [type, setType] = useState(undefined);
|
||||
const [title, setTitle] = useState(undefined);
|
||||
const [pageSize, setPageSize] = useState(10);
|
||||
const [curPage, setCurPage] = useState(1);
|
||||
const [total, setTotal] = useState(0);
|
||||
const [orderBy, setOrderBy] = useState('');
|
||||
const [dataList, setDataList] = useState([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [currentId, setCurrentId] = useState('');
|
||||
const [currentIsChecked, setCurrentIsChecked] = useState(1);
|
||||
|
||||
const [reload, setReload] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
// 组件第一次渲染会执行这个方法
|
||||
console.log('useEffect --- ');
|
||||
// 添加路由监听函数
|
||||
history.listen(historyLocation => {
|
||||
// 每次路由变化都会执行这个方法
|
||||
// console.log('route history , ', history);
|
||||
// console.log('route history location , ', historyLocation);
|
||||
setCurPage(1);
|
||||
setType(undefined);
|
||||
setTitle(undefined);
|
||||
setFieldsValue({
|
||||
type: undefined,
|
||||
title: undefined,
|
||||
});
|
||||
})
|
||||
}, [history]);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true);
|
||||
getNoticeList({
|
||||
orderBy,
|
||||
curPage,
|
||||
isChecked,
|
||||
pageSize,
|
||||
status,
|
||||
type,
|
||||
title,
|
||||
flag: 2, //后台管理查询:2;前台展示:1
|
||||
}).then(data => {
|
||||
setLoading(false);
|
||||
if (data) {
|
||||
setDataList(data.rows);
|
||||
setTotal(data.total);
|
||||
} else {
|
||||
setTotal(0);
|
||||
setDataList([]);
|
||||
}
|
||||
});
|
||||
}, [curPage, type, title, isChecked, reload,pageSize]);
|
||||
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '公告标题',
|
||||
dataIndex: 'title',
|
||||
key: 'title',
|
||||
width: '30%'
|
||||
},
|
||||
{
|
||||
title: '公告类型',
|
||||
key: 'type',
|
||||
dataIndex: 'type',
|
||||
render: (text, record) => {
|
||||
return noticeTypeArr[text];
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
key: 'createdAt',
|
||||
dataIndex: 'createdAt',
|
||||
},
|
||||
{
|
||||
title: '截止时间',
|
||||
key: 'closingDate',
|
||||
dataIndex: 'closingDate',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
render: (text, record) => (
|
||||
<span>
|
||||
{record.status == 2 && <Button className="mr5 font-12" type="primary" size="small" onClick={() => { editItem(record.id) }}>修改</Button>}
|
||||
<Button className="mr5 font-12" type="info" size="small" onClick={() => { detailItem(record.id) }}>详情</Button>
|
||||
{admin && record.status == 1 && record.isChecked == 2 && <Button className="mr5 font-12" type="primary" size="small" onClick={() => { setCurrentId(record.id); setVisible(true); }}>审核</Button>}
|
||||
{(admin || (record.isChecked != 1)) && < Button className="mr5 font-12" type="danger" size="small" onClick={() => { deletItem(record.id) }}>删除</Button>}
|
||||
</span >
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
// 如果是已发布,那么增加一项
|
||||
if (isChecked == 1) {
|
||||
columns.splice(3, 0, {
|
||||
title: '发布时间',
|
||||
key: 'publishDate',
|
||||
dataIndex: 'publishDate',
|
||||
});
|
||||
columns.splice(4, 0, {
|
||||
title: '密文浏览数',
|
||||
key: 'requestViewCount',
|
||||
dataIndex: 'requestViewCount',
|
||||
render: (text, record) => {
|
||||
return <span className={`${text > 0 ? 'link' : ''}`} onClick={() => { text > 0 && history.push(`/managements/notice/reader/${record.id}`) }}>{text}</span>;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function detailItem(id) {
|
||||
history.push(`/managements/notice/detail/${id}`);
|
||||
}
|
||||
|
||||
// 审核
|
||||
function checkItem() {
|
||||
checkNotice({
|
||||
id: currentId,
|
||||
isChecked: currentIsChecked,
|
||||
}).then(res => {
|
||||
if (res && res.code == '1') {
|
||||
ShowNotification("操作成功");
|
||||
setVisible(false);
|
||||
setReload(reload + 1);
|
||||
} else {
|
||||
ShowNotification(res.message || "操作失败");
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function editItem(id) {
|
||||
history.push(`/managements/notice/edit/${id}`);
|
||||
}
|
||||
|
||||
function deletItem(id) {
|
||||
DelModal(() => {
|
||||
deleteNotice(id).then(res => {
|
||||
if (res.message === 'success') {
|
||||
ShowNotification("删除成功");
|
||||
if (dataList.length == 1 && curPage > 1) {
|
||||
setCurPage(curPage - 1);
|
||||
} else {
|
||||
setReload(reload + 1);
|
||||
}
|
||||
} else {
|
||||
ShowNotification("删除失败");
|
||||
}
|
||||
})
|
||||
}, '此操作将删除该记录, 是否继续?');
|
||||
}
|
||||
|
||||
function handleSearch() {
|
||||
validateFields((error, values) => {
|
||||
console.log(values);
|
||||
if (!error) {
|
||||
setType(values.type || "");
|
||||
setTitle(values.title);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const helper = useCallback(
|
||||
(label, name, rules, widget) => (
|
||||
<Form.Item label={label} className='searchForm'>
|
||||
{getFieldDecorator(name, { rules, validateFirst: true, })(widget)}
|
||||
</Form.Item>
|
||||
), []);
|
||||
|
||||
|
||||
const formItemLayout = {
|
||||
labelCol: {
|
||||
xs: { span: 12 },
|
||||
sm: { span: 6 },
|
||||
},
|
||||
wrapperCol: {
|
||||
xs: { span: 12 },
|
||||
sm: { span: 18 },
|
||||
},
|
||||
};
|
||||
|
||||
function onShowSizeChange(current, pageSize) {
|
||||
setCurPage(current);
|
||||
setPageSize(pageSize);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="content">
|
||||
<Form className="clearfix">
|
||||
{helper(
|
||||
"",
|
||||
"type",
|
||||
[],
|
||||
<Select
|
||||
placeholder="公告类型"
|
||||
allowClear
|
||||
showArrow
|
||||
>
|
||||
{
|
||||
noticeType.map(item => {
|
||||
return <Option key={item.code}>{item.name}</Option>
|
||||
})
|
||||
}
|
||||
</Select>
|
||||
)}
|
||||
|
||||
{helper(
|
||||
"",
|
||||
"title",
|
||||
[{ max: 20, message: '关键字长度不能超过20个字符' }],
|
||||
<Input
|
||||
placeholder="输入标题关键字进行搜索"
|
||||
/>
|
||||
)}
|
||||
|
||||
<Button className="my-search-button" type="primary" onClick={handleSearch}>查询</Button>
|
||||
</Form>
|
||||
|
||||
<div className="table-detail">
|
||||
<PaginationTable
|
||||
loading={loading}
|
||||
dataSource={dataList}
|
||||
columns={columns}
|
||||
total={total}
|
||||
setCurPage={setCurPage}
|
||||
current={curPage}
|
||||
onShowSizeChange={onShowSizeChange}
|
||||
showSizeChanger
|
||||
/>
|
||||
{/* <Table
|
||||
loading={loading}
|
||||
rowKey={(row) => row.id}
|
||||
dataSource={dataList}
|
||||
columns={columns}
|
||||
pagination={false}
|
||||
/>
|
||||
|
||||
{dataList.length > 0 &&
|
||||
<Pagination
|
||||
onChange={(page) => { setCurPage(page) }}
|
||||
current={curPage}
|
||||
total={total}
|
||||
/>} */}
|
||||
</div>
|
||||
|
||||
<Modal
|
||||
title="公告审核"
|
||||
visible={visible}
|
||||
onOk={checkItem}
|
||||
onCancel={() => { setVisible(false) }}
|
||||
className="form-edit-modal"
|
||||
>
|
||||
<Form {...formItemLayout}>
|
||||
<Form.Item label={"审核意见:"} >
|
||||
<Radio.Group defaultValue={currentIsChecked} onChange={(e) => { setCurrentIsChecked(e.target.value) }} >
|
||||
<Radio className="columsRadio" value={1}>
|
||||
通过
|
||||
</Radio>
|
||||
<Radio className="columsRadio" value={0}>
|
||||
拒绝
|
||||
</Radio>
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
})
|
||||
)
|
||||
|
||||
export default NoticeList;
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
.searchForm{
|
||||
float: left;
|
||||
min-width: 260px;
|
||||
margin-right:2em !important;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { Button, Descriptions, Pagination, Icon, Table } from 'antd';
|
||||
import PaginationTable from "../../../components/pagination-table";
|
||||
import { noticeType, noticeChecked } from '../../common/static';
|
||||
import { getNoticeDetail, getNoticeReader } from '../api';
|
||||
import '../index.css';
|
||||
import './index.scss';
|
||||
|
||||
const noticeTypeArr = [];
|
||||
for (const item of noticeType) {
|
||||
noticeTypeArr[item.code] = (item.name);
|
||||
}
|
||||
const noticeCheckedArr = [];
|
||||
for (const item of noticeChecked) {
|
||||
noticeCheckedArr[item.code] = (item.name);
|
||||
}
|
||||
|
||||
const NoticeReader = ({ match, history }) => {
|
||||
const id = match.params.noticeId;
|
||||
const [noticeData, setNoticeData] = useState({});
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [dataList, setDataList] = useState([]);
|
||||
const [pageSize, setPageSize] = useState(10);
|
||||
const [curPage, setCurPage] = useState(1);
|
||||
const [total, setTotal] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
id && getNoticeDetail(id).then(data => {
|
||||
setNoticeData(data || {});
|
||||
})
|
||||
}, [id]);
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true);
|
||||
id && getNoticeReader({
|
||||
currentPage: curPage,
|
||||
annId: id,
|
||||
pageSize,
|
||||
}).then(data => {
|
||||
setLoading(false);
|
||||
if (data) {
|
||||
setDataList(data.rows);
|
||||
setTotal(data.total);
|
||||
} else {
|
||||
setTotal(0);
|
||||
setDataList([]);
|
||||
}
|
||||
})
|
||||
}, [id, curPage, pageSize]);
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '用户姓名',
|
||||
key: 'readerName',
|
||||
dataIndex: 'readerName',
|
||||
width: '20%',
|
||||
},
|
||||
{
|
||||
title: '公司名称',
|
||||
key: 'companyName',
|
||||
dataIndex: 'companyName',
|
||||
width: '40%',
|
||||
},
|
||||
{
|
||||
title: '联系方式',
|
||||
key: 'contactInfo',
|
||||
dataIndex: 'contactInfo',
|
||||
width: '40%',
|
||||
},
|
||||
];
|
||||
|
||||
function onShowSizeChange(current, pageSize) {
|
||||
setCurPage(current);
|
||||
setPageSize(pageSize);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="notice-content">
|
||||
<h4 className="notice-title"><span className='backList' onClick={() => { history.go(-1) }}><Icon type="left" />返回</span>浏览过该公告加密内容的用户详情</h4>
|
||||
|
||||
<Descriptions className='itemContent' column={1}>
|
||||
<Descriptions.Item label="公告标题">{noticeData.title}</Descriptions.Item>
|
||||
<Descriptions.Item label="加密信息被浏览数">{total}</Descriptions.Item>
|
||||
<Descriptions.Item label="浏览过该公告加密内容的用户信息"></Descriptions.Item>
|
||||
</Descriptions>
|
||||
|
||||
<div className="table-detail">
|
||||
<PaginationTable
|
||||
loading={loading}
|
||||
dataSource={dataList}
|
||||
columns={columns}
|
||||
total={total}
|
||||
setCurPage={setCurPage}
|
||||
current={curPage}
|
||||
onShowSizeChange={onShowSizeChange}
|
||||
showSizeChanger
|
||||
/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
export default NoticeReader;
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
.itemContent {
|
||||
padding: 10px 10px 0 30px;
|
||||
}
|
||||
.statusColor{
|
||||
color: #1890ff;
|
||||
}
|
||||
.alignTop{
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
}
|
||||
.backList{
|
||||
margin-right:1em;
|
||||
&:hover{
|
||||
color: #1890ff;
|
||||
}
|
||||
}
|
||||
|
||||
:global{
|
||||
.ant-descriptions-item-label{
|
||||
min-width: 5em;
|
||||
}
|
||||
.ant-table-row-cell-break-word{
|
||||
word-break: break-all;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,175 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { Table, Pagination, notification, Input } from 'antd';
|
||||
import { paramToUrl } from '../../common/utils';
|
||||
import fetch from 'military/notice/fetch';
|
||||
|
||||
|
||||
const { Search } = Input;
|
||||
|
||||
export default function Activity(props) {
|
||||
|
||||
const [curPage, setCurPage] = useState(1);
|
||||
const [total, setTotal] = useState(0);
|
||||
const [orderBy, setOrderBy] = useState('');
|
||||
const [dataList, setDataList] = useState([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [projectName, setProjectName] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
// 获取table数据
|
||||
let params = {
|
||||
orderBy,
|
||||
curPage,
|
||||
projectName,
|
||||
pageSize: 10,
|
||||
};
|
||||
let url = encodeURI(paramToUrl('/api/ProjectActivityData/', params));
|
||||
setLoading(true);
|
||||
fetch({
|
||||
url,
|
||||
method: 'get',
|
||||
}).then(res => {
|
||||
if (res.code === '1') {
|
||||
setDataList(res.data.rows);
|
||||
setTotal(res.data.total);
|
||||
} else {
|
||||
setDataList([]);
|
||||
setTotal(0);
|
||||
notification.open({
|
||||
message: "错误",
|
||||
description: res.message,
|
||||
});
|
||||
}
|
||||
setLoading(false);
|
||||
});
|
||||
}, [curPage, orderBy, projectName]);
|
||||
|
||||
|
||||
|
||||
|
||||
function handleTableChange(pagination, filters, sorter) {
|
||||
if (sorter.order) {
|
||||
if (sorter.order === 'ascend') {
|
||||
setOrderBy(sorter.field + 'Asc');
|
||||
} else {
|
||||
setOrderBy(sorter.field + 'Desc');
|
||||
}
|
||||
} else {
|
||||
setOrderBy('');
|
||||
}
|
||||
}
|
||||
|
||||
function onCell(record) {
|
||||
return {
|
||||
onClick: event => { onCellClick(record) }, // 点击
|
||||
}
|
||||
}
|
||||
|
||||
function onCellClick(record) {
|
||||
|
||||
let url = encodeURI(paramToUrl('/api/ProjectActivityData/getUrl', { projectId: record.projectId }));
|
||||
fetch({
|
||||
url,
|
||||
method: 'get',
|
||||
}).then(res => {
|
||||
if (res.code === '1') {
|
||||
window.open(res.data);
|
||||
} else {
|
||||
notification.open({
|
||||
message: "错误",
|
||||
description: res.message,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '项目名',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
className: 'link',
|
||||
onCell,
|
||||
},
|
||||
{
|
||||
title: '活跃度',
|
||||
key: 'activityScore',
|
||||
dataIndex: 'activityScore',
|
||||
sorter: true,
|
||||
},
|
||||
{
|
||||
title: '浏览数',
|
||||
key: 'visits',
|
||||
dataIndex: 'visits',
|
||||
sorter: true,
|
||||
},
|
||||
{
|
||||
title: '点赞数',
|
||||
key: 'praisesCount',
|
||||
dataIndex: 'praisesCount',
|
||||
sorter: true,
|
||||
},
|
||||
{
|
||||
title: '关注数',
|
||||
key: 'watchersCount',
|
||||
dataIndex: 'watchersCount',
|
||||
sorter: true,
|
||||
},
|
||||
{
|
||||
title: '任务数',
|
||||
key: 'issuesCount',
|
||||
dataIndex: 'issuesCount',
|
||||
sorter: true,
|
||||
},
|
||||
{
|
||||
title: 'PR数',
|
||||
key: 'pullRequestsCount',
|
||||
dataIndex: 'pullRequestsCount',
|
||||
sorter: true,
|
||||
},
|
||||
{
|
||||
title: '版本数',
|
||||
key: 'versionsCount',
|
||||
dataIndex: 'versionsCount',
|
||||
sorter: true,
|
||||
},
|
||||
];
|
||||
|
||||
function searchFun(val) {
|
||||
setProjectName(val);
|
||||
setCurPage(1);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="content">
|
||||
<Search
|
||||
style={{ width: '300px', margin: '1em' }}
|
||||
placeholder="请输入项目关键字"
|
||||
enterButton="搜索"
|
||||
size="large"
|
||||
onSearch={searchFun}
|
||||
className="global-search"
|
||||
maxLength={20}
|
||||
/>
|
||||
|
||||
<div className="table-detail">
|
||||
<Table
|
||||
loading={loading}
|
||||
rowKey={(row) => row.id}
|
||||
dataSource={dataList}
|
||||
columns={columns}
|
||||
pagination={false}
|
||||
onChange={handleTableChange} //预留的排序
|
||||
/>
|
||||
|
||||
{dataList.length > 0 &&
|
||||
<Pagination
|
||||
onChange={(page) => { setCurPage(page) }}
|
||||
current={curPage}
|
||||
total={total}
|
||||
/>}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { Icon, Col, Row, Tabs, notification } from 'antd';
|
||||
import EchartBar from '../../components/EchartBar';
|
||||
import fetch from 'military/notice/fetch';
|
||||
import './index.scss';
|
||||
const { TabPane } = Tabs;
|
||||
|
||||
let length = 13;
|
||||
let nowMonth = new Date().getMonth() + 1;
|
||||
let year = new Date().getFullYear() - 1;
|
||||
let monthArr = [];
|
||||
if (nowMonth === 13) {
|
||||
nowMonth = 1
|
||||
}
|
||||
for (let i = 0; i < length; i++) {
|
||||
monthArr.push(year + '.' + nowMonth);
|
||||
nowMonth++;
|
||||
if (nowMonth === 13) {
|
||||
nowMonth = 1;
|
||||
year++;
|
||||
}
|
||||
}
|
||||
|
||||
export default function Global(props){
|
||||
const [type, setType] = useState(1);
|
||||
const [totalProjects, setTotalProjects] = useState(0);
|
||||
const [totalMembers, setTotalMembers] = useState(0);
|
||||
const [newAddedProjects, setNewAddedProjects] = useState([]);
|
||||
const [newAddedMembers, setNewAddedMembers] = useState([]);
|
||||
const [newCodeSubmissionTimes, setNewCodeSubmissionTimes] = useState([]);
|
||||
const [taskCompletion, setTaskCompletion] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
fetch({
|
||||
url: 'http://111.8.36.180:8092/api/GlobalResourcesData/',
|
||||
method: 'get',
|
||||
}).then(res => {
|
||||
if (res.data) {
|
||||
const data = res.data;
|
||||
setTotalProjects(data.totalProjects);
|
||||
setTotalMembers(data.totalMembers);
|
||||
setNewAddedProjects(data.newAddedProjects);
|
||||
setNewAddedMembers(data.newAddedMembers);
|
||||
setNewCodeSubmissionTimes(data.newCodeSubmissionTimes);
|
||||
setTaskCompletion(data.taskCompletion);
|
||||
} else {
|
||||
notification.open({
|
||||
message: "错误",
|
||||
description: res.message,
|
||||
});
|
||||
}
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
|
||||
<div className="content">
|
||||
<Row>
|
||||
<Col className="box-item" xs={12} lg={6}>
|
||||
<Icon type="folder" />
|
||||
<div>
|
||||
<p className="box-item-tit">项目总数</p>
|
||||
<p className="box-item-num">{totalProjects}</p>
|
||||
<p className="box-item-describe">当前项目总数</p>
|
||||
</div>
|
||||
</Col>
|
||||
<Col className="box-item" xs={12} lg={6}>
|
||||
<Icon type="user" />
|
||||
<div>
|
||||
<p className="box-item-tit">用户总数</p>
|
||||
<p className="box-item-num">{totalMembers}</p>
|
||||
<p className="box-item-describe">当前用户总数</p>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Tabs defaultActiveKey="1" onChange={(key) => { setType(key) }}>
|
||||
<TabPane tab="开源统计" key="1">
|
||||
<Row>
|
||||
<Col xs={24} lg={12}>
|
||||
<EchartBar
|
||||
id="newAddedProjects"
|
||||
className="echart-box"
|
||||
title="新项目统计"
|
||||
xData={monthArr}
|
||||
yData={newAddedProjects}
|
||||
/>
|
||||
</Col>
|
||||
|
||||
<Col xs={24} lg={12}>
|
||||
<EchartBar
|
||||
id="newAddedMembers"
|
||||
className="echart-box"
|
||||
title="新用户统计"
|
||||
xData={monthArr}
|
||||
yData={newAddedMembers}
|
||||
/>
|
||||
</Col>
|
||||
|
||||
<Col xs={24} lg={12}>
|
||||
<EchartBar
|
||||
id="newCodeSubmissionTimes"
|
||||
className="echart-box"
|
||||
title="issue创建数"
|
||||
xData={monthArr}
|
||||
yData={newCodeSubmissionTimes}
|
||||
/>
|
||||
</Col>
|
||||
|
||||
<Col xs={24} lg={12}>
|
||||
<EchartBar
|
||||
id="taskCompletion"
|
||||
className="echart-box"
|
||||
title="任务完成量"
|
||||
xData={monthArr}
|
||||
yData={taskCompletion}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</TabPane>
|
||||
|
||||
{/* <TabPane tab="众包统计任务" key="2">
|
||||
|
||||
</TabPane>
|
||||
|
||||
<TabPane tab="其他" key="4">
|
||||
|
||||
</TabPane> */}
|
||||
|
||||
</Tabs>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
.box-item{
|
||||
display: flex;
|
||||
max-width: 300px;
|
||||
justify-content: space-around;
|
||||
margin: .75em;
|
||||
padding: .5em;
|
||||
background: #fff;
|
||||
border-radius: .5em;
|
||||
box-shadow: 0 1px 1px #d9d9d9;
|
||||
|
||||
.anticon{
|
||||
font-size: 4em;
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.box-item-num{
|
||||
font-size: 2em;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.box-item-describe{
|
||||
font-size: .9em;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
.ant-tabs-bar{
|
||||
border: 0;
|
||||
}
|
||||
.ant-tabs-tabpane {
|
||||
min-height: 25vh;
|
||||
}
|
||||
.ant-tabs-tab-active {
|
||||
color: #000;
|
||||
font-weight: 600;
|
||||
}
|
||||
.ant-tabs-nav .ant-tabs-tab:hover {
|
||||
color: #000;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.echart-box{
|
||||
height: 300px;
|
||||
margin: .75em;
|
||||
padding: 1em;
|
||||
border-radius: .5em;
|
||||
background: #fff;
|
||||
border:1px solid #d9d9d9;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
import React from "react";
|
||||
import { Route, Switch } from "react-router-dom";
|
||||
import Loadable from "react-loadable";
|
||||
import Loading from "../../Loading";
|
||||
|
||||
// 全局统计
|
||||
const Global = Loadable({
|
||||
loader: () => import("./global"),
|
||||
loading: Loading,
|
||||
});
|
||||
// 成员工作统计
|
||||
const Member = Loadable({
|
||||
loader: () => import("./member"),
|
||||
loading: Loading,
|
||||
});
|
||||
// 项目活跃度统计
|
||||
const Activity = Loadable({
|
||||
loader: () => import("./activity"),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
|
||||
export default (propsF)=>{
|
||||
return (
|
||||
<Switch {...propsF}>
|
||||
{/* 全局统计 */}
|
||||
<Route
|
||||
path="/managements/statistics/global"
|
||||
render={(props) => (
|
||||
<Global {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
{/* 成员工作统计 */}
|
||||
<Route
|
||||
path="/managements/statistics/member"
|
||||
render={(props) => (
|
||||
<Member {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
{/* 活跃度统计 */}
|
||||
<Route
|
||||
path="/managements/statistics/activity"
|
||||
render={(props) => (
|
||||
<Activity {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
</Switch>
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,280 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { Col, Row, Select, Button, DatePicker, notification } from 'antd';
|
||||
import moment from 'moment';
|
||||
import EchartLine from '../../components/EchartLine';
|
||||
import { beforeDayArr, paramToUrl } from '../../common/utils';
|
||||
import TableDetail from './table-detail';
|
||||
import fetch from 'military/notice/fetch';
|
||||
import './index.scss';
|
||||
|
||||
const { Option } = Select;
|
||||
const ButtonGroup = Button.Group;
|
||||
const { RangePicker } = DatePicker;
|
||||
|
||||
const monthArr = beforeDayArr();
|
||||
const nowDate = moment(new Date()).format('YYYY-MM-DD');
|
||||
const weekAgo = moment(new Date().setDate(new Date().getDate() - 6)).format('YYYY-MM-DD');
|
||||
console.log(weekAgo);
|
||||
const monthAgo = moment(new Date().setDate(new Date().getDate() - 30)).format('YYYY-MM-DD');
|
||||
const threeMonthAgo = moment(new Date().setDate(new Date().getDate() - 90)).format('YYYY-MM-DD');
|
||||
|
||||
export default function Member(props) {
|
||||
|
||||
const [member, setMember] = useState(undefined);
|
||||
const [memberList, setMemberList] = useState([]);
|
||||
const [timeType, setTimeType] = useState(2);
|
||||
const [dayNum, setDayNum] = useState(30);
|
||||
const [timeArr, setTimeArr] = useState(monthArr);
|
||||
const [startTime, setStartTime] = useState(monthAgo); //初始化为当前时间
|
||||
const [endTime, setEndTime] = useState(nowDate);
|
||||
|
||||
const [newTask, setNewTask] = useState(null);
|
||||
const [completedTask, setCompletedTask] = useState(null);
|
||||
const [newPrNum, setNewPrNum] = useState(null);
|
||||
const [newCommitNum, setNewCommitNum] = useState(null);
|
||||
const [newCodeNum, setNewCodeNum] = useState(null);
|
||||
|
||||
|
||||
|
||||
// 获取总体折线图数据
|
||||
function getAllDataLine() {
|
||||
let params = {
|
||||
startTime,
|
||||
endTime,
|
||||
}
|
||||
let url = encodeURI(paramToUrl('/api/DeveloperData/total', params));
|
||||
fetch({
|
||||
url,
|
||||
method: 'get',
|
||||
}).then(res => {
|
||||
if (res.code === '1') {
|
||||
const data = res.data;
|
||||
setNewTask(data.newTask);
|
||||
setCompletedTask(data.completedTask);
|
||||
setNewPrNum(data.newPrNum);
|
||||
setNewCommitNum(data.newCommitNum);
|
||||
setNewCodeNum(data.newCodeNum);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 获取单个成员的数据
|
||||
function getPersonData() {
|
||||
let params = {
|
||||
startTime,
|
||||
endTime,
|
||||
curPage: 1,
|
||||
pageSize: 31,
|
||||
userId: member.key,
|
||||
userName:member.login,
|
||||
};
|
||||
if (timeType == 1) {
|
||||
params.pageSize = 7;
|
||||
} else if (timeType == 3) {
|
||||
params.pageSize = 91;
|
||||
} else if (timeType == 0) {
|
||||
params.pageSize = dayNum;
|
||||
}
|
||||
let url = encodeURI(paramToUrl('/api/DeveloperData/detail/search', params));
|
||||
fetch({
|
||||
url,
|
||||
method: 'get',
|
||||
}).then(res => {
|
||||
let newTask = [];
|
||||
let completedTask = [];
|
||||
let newPrNum = [];
|
||||
let newCommitNum = [];
|
||||
let newCodeNum = [];
|
||||
|
||||
if (res.code === '1' && res.data.rows) {
|
||||
if (res.data.rows.length) {
|
||||
for (const item of res.data.rows) {
|
||||
newTask.unshift(item.newTask);
|
||||
completedTask.unshift(item.completedTask);
|
||||
newPrNum.unshift(item.newPrNum);
|
||||
newCommitNum.unshift(item.newCommitNum);
|
||||
newCodeNum.unshift(item.newCodeNum);
|
||||
}
|
||||
} else {
|
||||
newCodeNum.fill(0, 0,);
|
||||
}
|
||||
} else {
|
||||
notification.open({
|
||||
message: "错误",
|
||||
description: res.message,
|
||||
});
|
||||
}
|
||||
setNewTask(newTask);
|
||||
setCompletedTask(completedTask);
|
||||
setNewPrNum(newPrNum);
|
||||
setNewCommitNum(newCommitNum);
|
||||
setNewCodeNum(newCodeNum);
|
||||
});
|
||||
}
|
||||
|
||||
function onSearch(value) {
|
||||
if (value) {
|
||||
getMemberList(value);
|
||||
}
|
||||
}
|
||||
|
||||
// 获取成员数据
|
||||
let timeout;
|
||||
function getMemberList(value) {
|
||||
if (timeout) {
|
||||
clearTimeout(timeout);
|
||||
timeout = null;
|
||||
}
|
||||
function fake() {
|
||||
fetch({
|
||||
url: '/api/DeveloperData/detail/searchInput?userName=' + value,
|
||||
method: 'get',
|
||||
}).then(res => {
|
||||
if (res.code === '1') {
|
||||
setMemberList(res.data);
|
||||
} else {
|
||||
notification.open({
|
||||
message: "错误",
|
||||
description: res.message,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
timeout = setTimeout(fake, 1000);
|
||||
}
|
||||
|
||||
|
||||
function searchInTime(timeType) {
|
||||
setTimeType(timeType);
|
||||
if (timeType === 1) {
|
||||
setTimeArr(beforeDayArr(7));
|
||||
setStartTime(weekAgo);
|
||||
setEndTime(nowDate);
|
||||
|
||||
} else if (timeType === 2) {
|
||||
setTimeArr(monthArr);
|
||||
setStartTime(monthAgo);
|
||||
setEndTime(nowDate);
|
||||
} else if (timeType === 3) {
|
||||
setTimeArr(beforeDayArr(91));
|
||||
setStartTime(threeMonthAgo);
|
||||
setEndTime(nowDate);
|
||||
}
|
||||
}
|
||||
|
||||
function changeDate(dates, dateStrings) {
|
||||
if (dateStrings && dateStrings[0]) {
|
||||
setStartTime(dateStrings[0]);
|
||||
setEndTime(dateStrings[1]);
|
||||
let dayNum = (dates[1] - dates[0]) / 86400000 + 1;
|
||||
setTimeArr(beforeDayArr(dayNum, new Date(dates[1])));
|
||||
setTimeType(0);
|
||||
setDayNum(dayNum);
|
||||
} else {
|
||||
setTimeType(2);
|
||||
setTimeArr(monthArr);
|
||||
setStartTime(monthAgo);
|
||||
setEndTime(nowDate);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (member) {
|
||||
getPersonData();
|
||||
} else {
|
||||
getAllDataLine();
|
||||
}
|
||||
}, [startTime, endTime, member]);
|
||||
|
||||
function changeMember(val){
|
||||
if(val){
|
||||
for(const item of memberList){
|
||||
if(val.key==item.id){
|
||||
val.login=item.login
|
||||
}
|
||||
}
|
||||
}
|
||||
setMember(val);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
<div className="content">
|
||||
<Row className="search-box">
|
||||
<Col xs={24} sm={12} lg={10} >
|
||||
<Select
|
||||
showSearch
|
||||
value={member}
|
||||
placeholder={'请选择成员或输入成员查询'}
|
||||
defaultActiveFirstOption={false}
|
||||
filterOption={false}
|
||||
onSearch={onSearch}
|
||||
onChange={(val) => { changeMember(val) }}
|
||||
notFoundContent={null}
|
||||
allowClear={true}
|
||||
labelInValue
|
||||
>
|
||||
{
|
||||
memberList.map(d => <Option key={d.id}>{d.nickname || d.login}</Option>)
|
||||
}
|
||||
</Select>
|
||||
</Col>
|
||||
|
||||
|
||||
<Col xs={24} sm={12} lg={14} className="choose-time">
|
||||
<ButtonGroup>
|
||||
<Button type={timeType === 1 ? "primary" : ""} onClick={() => { searchInTime(1) }}>
|
||||
近1周
|
||||
</Button>
|
||||
<Button type={timeType === 2 ? "primary" : ""} onClick={() => { searchInTime(2) }}>
|
||||
近1月
|
||||
</Button>
|
||||
<Button type={timeType === 3 ? "primary" : ""} onClick={() => { searchInTime(3) }}>
|
||||
近3月
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
|
||||
<div className="custom-time">
|
||||
<div className="time-label">自定义时间段</div>
|
||||
<RangePicker
|
||||
placeholder={['--/--', '--/--']}
|
||||
onChange={changeDate}
|
||||
/>
|
||||
</div>
|
||||
</Col>
|
||||
|
||||
</Row>
|
||||
|
||||
<EchartLine
|
||||
id="memberStatistics"
|
||||
xData={timeArr}
|
||||
seriesArr={
|
||||
[{
|
||||
name: '新增任务数',
|
||||
data: newTask
|
||||
}, {
|
||||
name: '完成任务数',
|
||||
data: completedTask
|
||||
}, {
|
||||
name: '新增PR数',
|
||||
data: newPrNum
|
||||
}, {
|
||||
name: '新增提交数',
|
||||
data: newCommitNum
|
||||
}, {
|
||||
name: '新增代码数',
|
||||
data: newCodeNum
|
||||
}]
|
||||
}
|
||||
/>
|
||||
|
||||
<h4 className="mt20">详情列表</h4>
|
||||
<TableDetail
|
||||
member={member}
|
||||
startTime={startTime}
|
||||
endTime={endTime}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
.search-box {
|
||||
margin-bottom: .75rem;
|
||||
.ant-select {
|
||||
min-width: 280px;
|
||||
}
|
||||
|
||||
.ant-btn:active, .ant-btn.active{
|
||||
color: #fff;
|
||||
background-color: #096dd9;
|
||||
border-color: #096dd9;
|
||||
}
|
||||
|
||||
.choose-time{
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.ant-btn-group{
|
||||
margin-right: 10px;
|
||||
}
|
||||
.custom-time{
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
}
|
||||
.ant-calendar-picker{
|
||||
max-width: 250px;
|
||||
}
|
||||
.time-label{
|
||||
background: #fafbfc;
|
||||
line-height: 30px;
|
||||
padding: 0 10px;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-right: 0;
|
||||
border-top-left-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
|
||||
}
|
||||
.ant-calendar-picker-input{
|
||||
text-align: left;
|
||||
border-top-left-radius: 0px;
|
||||
border-bottom-left-radius: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,175 @@
|
|||
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Table, Pagination, notification } from 'antd';
|
||||
import { paramToUrl } from '../../common/utils';
|
||||
import fetch from 'military/notice/fetch';
|
||||
|
||||
|
||||
export default ({ member, startTime, endTime }) => {
|
||||
|
||||
const [curPage, setCurPage] = useState(1);
|
||||
const [total, setTotal] = useState(0);
|
||||
const [orderBy, setOrderBy] = useState('');
|
||||
const [dataList, setDataList] = useState([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
getTableData();
|
||||
}, [member, startTime, endTime, orderBy, curPage]);
|
||||
|
||||
// 获取table数据
|
||||
function getTableData() {
|
||||
let params = {
|
||||
startTime,
|
||||
endTime,
|
||||
orderBy,
|
||||
curPage,
|
||||
pageSize: 10,
|
||||
};
|
||||
setLoading(true);
|
||||
let url;
|
||||
if (member) {
|
||||
// 获取单人数据
|
||||
params = {
|
||||
...params,
|
||||
userId: member.key,
|
||||
userName: member.login,
|
||||
};
|
||||
url = encodeURI(paramToUrl('/api/DeveloperData/detail/search', params));
|
||||
} else {
|
||||
// 获取总体数据
|
||||
url = encodeURI(paramToUrl('/api/DeveloperData/detail', params));
|
||||
}
|
||||
fetch({
|
||||
url,
|
||||
method: 'get',
|
||||
data: params
|
||||
}).then(res => {
|
||||
if (res.code === '1') {
|
||||
setDataList(res.data.rows);
|
||||
setTotal(res.data.total);
|
||||
} else {
|
||||
setDataList([]);
|
||||
setTotal(0);
|
||||
notification.open({
|
||||
message: "错误",
|
||||
description: res.message,
|
||||
});
|
||||
}
|
||||
setLoading(false);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function handleTableChange(pagination, filters, sorter) {
|
||||
if (sorter.order) {
|
||||
if (sorter.order === 'ascend') {
|
||||
setOrderBy(sorter.field + 'Asc');
|
||||
setCurPage(1);
|
||||
} else {
|
||||
setOrderBy(sorter.field + 'Desc');
|
||||
setCurPage(1);
|
||||
}
|
||||
} else {
|
||||
setOrderBy('');
|
||||
setCurPage(1);
|
||||
}
|
||||
}
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '成员姓名',
|
||||
dataIndex: 'nickName',
|
||||
key: 'nickName',
|
||||
width: '20%',
|
||||
className: 'link',
|
||||
onCell,
|
||||
render: (text, record) => {
|
||||
return (text || record.userName)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '新增任务数',
|
||||
key: 'newTask',
|
||||
dataIndex: 'newTask',
|
||||
sorter: true,
|
||||
},
|
||||
{
|
||||
title: '完成任务数',
|
||||
key: 'completedTask',
|
||||
dataIndex: 'completedTask',
|
||||
sorter: true,
|
||||
},
|
||||
{
|
||||
title: '新增PR数',
|
||||
key: 'newPrNum',
|
||||
dataIndex: 'newPrNum',
|
||||
sorter: true,
|
||||
},
|
||||
{
|
||||
title: '新增提交数',
|
||||
key: 'newCommitNum',
|
||||
dataIndex: 'newCommitNum',
|
||||
sorter: true,
|
||||
},
|
||||
// {
|
||||
// title: '新增代码',
|
||||
// key: 'newCodeNum',
|
||||
// dataIndex: 'newCodeNum',
|
||||
// },
|
||||
];
|
||||
|
||||
function onCell(record) {
|
||||
return {
|
||||
onClick: event => { onCellClick(record) }, // 点击
|
||||
}
|
||||
}
|
||||
|
||||
function onCellClick(record) {
|
||||
|
||||
let url = encodeURI(paramToUrl('/api/DeveloperData/getUrl', { login: record.userName }));
|
||||
fetch({
|
||||
url,
|
||||
method: 'get',
|
||||
}).then(res => {
|
||||
if (res.code === '1') {
|
||||
window.open(res.data);
|
||||
} else {
|
||||
notification.open({
|
||||
message: "错误",
|
||||
description: res.message,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (member) {
|
||||
columns.splice(0, 1, {
|
||||
title: '日期',
|
||||
dataIndex: 'date',
|
||||
key: 'date',
|
||||
width: '20%',
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="table-detail">
|
||||
<Table
|
||||
loading={loading}
|
||||
rowKey={(row, i) => row.id || i}
|
||||
dataSource={dataList}
|
||||
columns={columns}
|
||||
pagination={false}
|
||||
onChange={handleTableChange}
|
||||
/>
|
||||
|
||||
{dataList.length > 0 &&
|
||||
<Pagination
|
||||
onChange={(page) => { setCurPage(page) }}
|
||||
current={curPage}
|
||||
total={total}
|
||||
loading={loading}
|
||||
/>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -7,9 +7,10 @@ function Uploads({ className, size, actionUrl, fileList, showNotification, load
|
|||
const [files, setFiles] = useState(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
if (fileList) {
|
||||
init();
|
||||
}
|
||||
// if (fileList) {
|
||||
// init();
|
||||
// }
|
||||
init();
|
||||
}, [fileList]);
|
||||
|
||||
function init() {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { getCompetitionList, getRules, selectExpertList, updateCompetitionReview
|
|||
import { competitionStatus } from "../static";
|
||||
|
||||
import './index.scss';
|
||||
import '../../../managements/index.scss';
|
||||
const Option = Select.Option;
|
||||
|
||||
const statusArr = [];
|
||||
|
|
@ -260,7 +261,7 @@ function Competition(props){
|
|||
// 修改路由,跳转到第几页
|
||||
function updateUrl(page){
|
||||
setCurPage(page);
|
||||
window.location.href=`/managements/expert/competition/#page=${page}`;
|
||||
window.location.href=`/managements/expert/competition#page=${page}`;
|
||||
}
|
||||
|
||||
function hashDate(hash) {
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ a.primary-link{
|
|||
}
|
||||
|
||||
.competitionList{
|
||||
margin-top: 1rem;
|
||||
.ant-select-selection{
|
||||
width: 115px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import React, { useState, useMemo, useEffect } from "react";
|
|||
import { Input, Select, Button, Form, Table, Upload, Modal, Popconfirm, message } from 'antd';
|
||||
import cookie from 'react-cookies';
|
||||
import { exportExcel } from '../components/exportExcel.js';
|
||||
import Paginationtable from "../../components/paginationTable";
|
||||
import Paginationtable from "../../../components/pagination-table";
|
||||
import { Info } from '../../components/ModalFun';
|
||||
import { expertList, deleteExpert } from "../api";
|
||||
import { professionalType, reviewArea } from "../static";
|
||||
|
|
@ -221,6 +221,9 @@ function RegisterList({ showNotification }) {
|
|||
statusString: '1',
|
||||
};
|
||||
expertList(params).then(data => {
|
||||
if((data.rows && data.rows.length<=0) && curPage>1){
|
||||
setCurPage(curPage-1);
|
||||
}
|
||||
setDataList(data.rows || []);
|
||||
setLoading(false);
|
||||
setTotal(data && data.total);
|
||||
|
|
@ -315,15 +318,16 @@ function RegisterList({ showNotification }) {
|
|||
};
|
||||
|
||||
return (
|
||||
<div className="expert-list centerbox">
|
||||
<div className="expert-list">
|
||||
<div className="center-screen" >
|
||||
<div className="center-right-but">
|
||||
<div className="center-right-but btn-group">
|
||||
<Form.Item label={"姓名/手机"}>
|
||||
<Search
|
||||
maxLength={20}
|
||||
style={{ width: "300px" }}
|
||||
placeholder="请输入专家姓名或手机号"
|
||||
onSearch={(value) => { setSearchInput(value); setCurPage(1); }}
|
||||
allowClear
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
|
|
|
|||
|
|
@ -8,8 +8,10 @@
|
|||
}
|
||||
.center-right-but{
|
||||
flex:auto;
|
||||
justify-content: space-between;
|
||||
justify-content: flex-start;
|
||||
margin-right: 4em;
|
||||
.ant-row{margin-right: 5rem;}
|
||||
.ant-form-item{margin-bottom: 0;}
|
||||
}
|
||||
|
||||
.ant-form-item-control-wrapper{
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import javaFetch from '../javaFetch';
|
|||
|
||||
let settings = localStorage.chromesetting && JSON.parse(localStorage.chromesetting);
|
||||
let actionUrl = settings && settings.api_urls && settings.api_urls.task ? settings.api_urls.task : 'https://task.osredm.com';
|
||||
// let actionUrl = 'http://10.47.38.60:8088';
|
||||
const service = javaFetch(actionUrl);
|
||||
export const httpUrl = actionUrl;
|
||||
export const main_web_site_url = settings && settings.main_web_site_url;
|
||||
|
|
|
|||
|
|
@ -178,4 +178,10 @@
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
.expert-list .center-screen{
|
||||
padding: 1rem;
|
||||
background: #fff;
|
||||
border-radius: 4px;
|
||||
box-shadow:0px 0px 10px rgba(88, 116, 255, 0.18);
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useState, useCallback, useMemo, useEffect } from "react";
|
||||
import { Input, Select, Button, Form, Modal } from 'antd';
|
||||
import Paginationtable from "../../components/paginationTable";
|
||||
import Paginationtable from "../../../components/pagination-table";
|
||||
import { Confirm } from '../../components/ModalFun';
|
||||
import { expertList, registerCheck } from "../api";
|
||||
import { httpUrl } from '../fetch';
|
||||
|
|
@ -188,6 +188,9 @@ function RegisterList({ showNotification, form }) {
|
|||
};
|
||||
expertList(params).then(data => {
|
||||
if (data && Array.isArray(data.rows)) {
|
||||
if((data.rows && data.rows.length<=0) && curPage>1){
|
||||
setCurPage(curPage-1);
|
||||
}
|
||||
for (const item of data.rows) {
|
||||
item.detail = item.paperDetail && item.paperDetail.content;
|
||||
}
|
||||
|
|
@ -249,21 +252,17 @@ function RegisterList({ showNotification, form }) {
|
|||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<div className="expert-list centerbox">
|
||||
<div className="center-screen mb30" >
|
||||
<Search
|
||||
maxLength={20}
|
||||
style={{ width: "300px" }}
|
||||
placeholder="请输入专家姓名或手机号"
|
||||
onSearch={(value) => { setSearchInput(value); setCurPage(1); }}
|
||||
/>
|
||||
<div className="center-screen mb20" >
|
||||
<Search
|
||||
maxLength={20}
|
||||
style={{ width: "300px" }}
|
||||
placeholder="请输入专家姓名或手机号"
|
||||
onSearch={(value) => { setSearchInput(value); setCurPage(1); }}
|
||||
/>
|
||||
</div>
|
||||
<Paginationtable
|
||||
loading={loading}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,9 @@ export default Form.create()(({ form, showNotification, match, history }) => {
|
|||
setLoading(true);
|
||||
agreementList(params).then(data => {
|
||||
if (data) {
|
||||
if((data.rows && data.rows.length<=0) && curPage>1){
|
||||
setCurPage(curPage-1);
|
||||
}
|
||||
if (loadPaper === 0 && data.rows.length === 0) {
|
||||
setLoadPaper(1);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 20px;
|
||||
margin: 0 1.5rem;
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #dedede;
|
||||
a.edu-orangeline-btn {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 20px;
|
||||
margin: 0 1.5rem;
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #dedede;
|
||||
a.edu-orangeline-btn {
|
||||
|
|
|
|||
|
|
@ -62,6 +62,11 @@ export default Form.create()((props) => {
|
|||
}
|
||||
|
||||
function uploadAgree(item) {
|
||||
// 清空文件列表
|
||||
setFileList(null);
|
||||
setFieldsValue({
|
||||
files: ''
|
||||
});
|
||||
setVisibleAgree(true);
|
||||
setTaskId(item.id);
|
||||
setCheckItem(item);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 20px;
|
||||
margin: 0 1.5rem;
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #dedede;
|
||||
a.edu-orangeline-btn {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 20px;
|
||||
margin: 0 1.5rem;
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #dedede;
|
||||
a.edu-orangeline-btn {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,14 @@ export default Form.create()((props) => {
|
|||
|
||||
|
||||
function deal(item) {
|
||||
// 重置处理申诉弹框各项内容
|
||||
setIsAccepted('');
|
||||
setIsReconsidered('');
|
||||
setIsChanged('');
|
||||
setFieldsValue({
|
||||
isAccepted: '',
|
||||
reason: '',
|
||||
});
|
||||
setCheckedItem(item);
|
||||
setVisible(true);
|
||||
}
|
||||
|
|
@ -37,6 +45,9 @@ export default Form.create()((props) => {
|
|||
if (res && res.message === 'success') {
|
||||
showNotification('操作成功');
|
||||
reloadList();
|
||||
setIsAccepted('');
|
||||
setIsReconsidered('');
|
||||
setIsChanged('');
|
||||
setFieldsValue({
|
||||
isAccepted: '',
|
||||
reason: '',
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 20px;
|
||||
margin: 0 1.5rem;
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #dedede;
|
||||
a.edu-orangeline-btn {
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ export default (props) => {
|
|||
<span className="fl color-grey-9 mt3">{timeAgo(item.createdAt)}</span>
|
||||
<span className="fr">
|
||||
{item.status > 2 && item.status !== 9 && <span className="spanTitle color-grey-6 fl ml20">已同意</span>}
|
||||
{item.status === 9 && <span className="spanTitle color-yellow fl ml20">已处理</span>}
|
||||
{item.status === 9 && <span className="spanTitle color-yellow fl ml20">待修缮</span>}
|
||||
{item.status === 2 && <span className="spanTitle color-red fl ml20">已拒绝</span>}
|
||||
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 20px;
|
||||
margin: 0 1.5rem;
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #dedede;
|
||||
a.edu-orangeline-btn {
|
||||
|
|
|
|||
|
|
@ -37,6 +37,9 @@ export default ({ current_user, showNotification, history }) => {
|
|||
setLoading(true);
|
||||
delayList(params).then(data => {
|
||||
if (data) {
|
||||
if((data.rows && data.rows.length<=0) && curPage>1){
|
||||
setCurPage(curPage-1);
|
||||
}
|
||||
setTaskList(data.rows);
|
||||
setTotal(data.total);
|
||||
}
|
||||
|
|
@ -68,7 +71,7 @@ export default ({ current_user, showNotification, history }) => {
|
|||
}, [])
|
||||
|
||||
return (
|
||||
<div className="centerbox task-manage">
|
||||
<div className="task-manage">
|
||||
|
||||
<div className="center-screen" >
|
||||
<div className="center-left-but">
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import javaFetch from '../javaFetch';
|
|||
|
||||
let settings=localStorage.chromesetting&&JSON.parse(localStorage.chromesetting);
|
||||
let actionUrl = settings && settings.api_urls? settings.api_urls.task :'https://task.osredm.com';
|
||||
// let actionUrl = 'http://111.8.36.180:8094'
|
||||
// let actionUrl = 'http://10.47.38.60:8088'
|
||||
|
||||
const service = javaFetch(actionUrl);
|
||||
export const httpUrl = actionUrl;
|
||||
|
|
|
|||
|
|
@ -1,15 +1,12 @@
|
|||
// 本功能模块公告样式
|
||||
// 本功能模块公共样式
|
||||
.task-manage {
|
||||
margin-top: 1.25rem;
|
||||
.status-list {
|
||||
margin: 0 1.5rem;
|
||||
}
|
||||
|
||||
.center-screen {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin: 1.25rem 0;
|
||||
padding: 1rem 0;
|
||||
padding: 1rem 1.5rem;
|
||||
background-color: #fff;
|
||||
|
||||
.ant-form-item {
|
||||
|
|
@ -88,6 +85,8 @@ span.list-gray {
|
|||
}
|
||||
|
||||
.center-content .ant-pagination {
|
||||
margin: 2rem 1.5rem;
|
||||
text-align: right;
|
||||
margin: 2rem auto !important;
|
||||
text-align: center;
|
||||
.ant-pagination-item:focus, .ant-pagination-item:hover, .ant-pagination-item-active, .ant-pagination-prev:hover a, .ant-pagination-next:hover a, .ant-pagination-options-quick-jumper input:focus, .ant-pagination-options-quick-jumper input:hover{
|
||||
|
|
@ -123,6 +122,10 @@ span.list-gray {
|
|||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
.center-right-but, .center-left-but{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.center-right-but .ant-input:hover, .center-content .ant-pagination-prev:hover{
|
||||
border-color: #4154f1 !important;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ for (const item of taskStatusAllArr) {
|
|||
}
|
||||
|
||||
export default ({ location, history, current_user, showNotification }) => {
|
||||
console.log(current_user);
|
||||
let defaultValue = decodeURI(location.search.split("=")[1] || "");
|
||||
|
||||
const [identity, setIdentity] = useState('1');
|
||||
|
|
|
|||
|
|
@ -43,6 +43,9 @@ export default Form.create()(({ form, showNotification, history}) => {
|
|||
setLoading(true);
|
||||
complainPaperList(params).then(data => {
|
||||
if (data) {
|
||||
if((data.rows && data.rows.length<=0) && curPage>1){
|
||||
setCurPage(curPage-1);
|
||||
}
|
||||
setTaskList(data.rows);
|
||||
setTotal(data.total);
|
||||
}
|
||||
|
|
@ -139,19 +142,21 @@ export default Form.create()(({ form, showNotification, history}) => {
|
|||
{
|
||||
title: '审核状态',
|
||||
dataIndex: 'status',
|
||||
key: 'status',
|
||||
render: (text, record) => {
|
||||
return text !== 2 ? paperComplainStatus[text] : <React.Fragment>
|
||||
<Button className="mr5 font-12" type="primary" size="small" onClick={() => { checkPaperItem(record.id, 1) }}>通过</Button>
|
||||
<Button className="mr5 font-12" type="info" size="small" onClick={() => { setActiveId(record.id); setVisible(true) }}>不通过</Button>
|
||||
<Button className="mr5 font-12" type="info" size="small" onClick={() => { setActiveId(record.id); setFieldsValue({message: ''}); setVisible(true) }}>不通过</Button>
|
||||
</React.Fragment>
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'status',
|
||||
key: 'action',
|
||||
render: (text, record) => (
|
||||
<Link className="line_1 color-grey3" to={`/task/taskDetail/${record.taskId}`}>查看详情</Link>
|
||||
),
|
||||
render: (text, record) => {
|
||||
return text === 0 ? <span style={{color:'gray'}}>查看详情</span> : <Link className="line_1 color-grey3" to={`/task/taskDetail/${record.taskId}`}>查看详情</Link>
|
||||
},
|
||||
},
|
||||
]
|
||||
}, []);
|
||||
|
|
@ -187,7 +192,7 @@ export default Form.create()(({ form, showNotification, history}) => {
|
|||
}, []);
|
||||
|
||||
return (
|
||||
<div className="centerbox task-manage">
|
||||
<div className="task-manage">
|
||||
|
||||
|
||||
<div className="center-screen" >
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ export default Form.create()(({ current_user, form, showNotification, match, his
|
|||
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [searchObj, setSearchObj] = useState({
|
||||
checkStatus: '0',
|
||||
checkStatus: '2',
|
||||
parentId: 0,
|
||||
});
|
||||
const [curPage, setCurPage] = useState(1);
|
||||
|
|
@ -41,6 +41,9 @@ export default Form.create()(({ current_user, form, showNotification, match, his
|
|||
setLoading(true);
|
||||
readyCheckPapers(params).then(data => {
|
||||
if (data) {
|
||||
if((data.rows && data.rows.length<=0) && curPage>1){
|
||||
setCurPage(curPage-1);
|
||||
}
|
||||
setTaskList(data.rows);
|
||||
setTotal(data.total);
|
||||
}
|
||||
|
|
@ -81,6 +84,7 @@ export default Form.create()(({ current_user, form, showNotification, match, his
|
|||
checkPaper({
|
||||
paperId,
|
||||
auditingVo: {
|
||||
// pass传参:通过(1) 不通过但允许申诉(2) 不通过不允许申诉(0)
|
||||
pass: passStatus ? 1 : values.pass,
|
||||
message: values.message,
|
||||
}
|
||||
|
|
@ -141,7 +145,7 @@ export default Form.create()(({ current_user, form, showNotification, match, his
|
|||
title: '审核状态',
|
||||
dataIndex: 'checkStatus',
|
||||
render: (text, record) => {
|
||||
return text === 0 ? <React.Fragment>
|
||||
return text === 2 ? <React.Fragment>
|
||||
<Button className="mr5 font-12" type="primary" size="small" onClick={() => { checkPaperItem(record.id, true) }}>通过</Button>
|
||||
<Button className="mr5 font-12" type="info" size="small" onClick={() => { disagree(record) }}>不通过</Button>
|
||||
</React.Fragment> : checkStatusArr[text]
|
||||
|
|
@ -189,7 +193,7 @@ export default Form.create()(({ current_user, form, showNotification, match, his
|
|||
function changeStatus(e) {
|
||||
setSearchObj({
|
||||
...searchObj,
|
||||
checkStatus: e,
|
||||
checkStatus: e === '0,1,2' ? '' : e,
|
||||
});
|
||||
setCurPage(1);
|
||||
}
|
||||
|
|
@ -203,11 +207,11 @@ export default Form.create()(({ current_user, form, showNotification, match, his
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="centerbox task-manage">
|
||||
<div className="task-manage">
|
||||
<div className="center-screen" >
|
||||
<div className="center-left-but">
|
||||
{helper(
|
||||
"",
|
||||
"审核状态",
|
||||
"checkStatus",
|
||||
[],
|
||||
<Select
|
||||
|
|
@ -222,11 +226,11 @@ export default Form.create()(({ current_user, form, showNotification, match, his
|
|||
})
|
||||
}
|
||||
</Select>,
|
||||
'0'
|
||||
'2'
|
||||
)}
|
||||
|
||||
{helper(
|
||||
"",
|
||||
"审核类型",
|
||||
"parentId",
|
||||
[],
|
||||
<Select
|
||||
|
|
|
|||
|
|
@ -25,12 +25,15 @@ export default Form.create()(({ current_user, form, showNotification, match, his
|
|||
...searchObj,
|
||||
status:approve,
|
||||
type:'',
|
||||
currentPage:curPage,
|
||||
curPage,
|
||||
pageSize: 10,
|
||||
};
|
||||
setLoading(true);
|
||||
uploadPayProofList(params).then(data => {
|
||||
if (data) {
|
||||
if((data.rows && data.rows.length<=0) && curPage>1){
|
||||
setCurPage(curPage-1);
|
||||
}
|
||||
setTaskList(data.rows);
|
||||
setTotal(data.total);
|
||||
}
|
||||
|
|
@ -75,7 +78,7 @@ export default Form.create()(({ current_user, form, showNotification, match, his
|
|||
}, [])
|
||||
|
||||
return (
|
||||
<div className="centerbox task-manage">
|
||||
<div className="task-manage">
|
||||
|
||||
|
||||
<div className="center-screen" >
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@ export default Form.create()(({ current_user, form, showNotification, match, his
|
|||
setLoading(true);
|
||||
proofList(params).then(data => {
|
||||
if (data) {
|
||||
if((data.rows && data.rows.length<=0) && curPage>1){
|
||||
setCurPage(curPage-1);
|
||||
}
|
||||
setTaskList(data.rows);
|
||||
setTotal(data.total);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@ export default Form.create()(({ current_user, form, showNotification, match, his
|
|||
setLoading(true);
|
||||
publicityComplainList(params).then(data => {
|
||||
if (data) {
|
||||
if((data.rows && data.rows.length<=0) && curPage>1){
|
||||
setCurPage(curPage-1);
|
||||
}
|
||||
setTaskList(data.rows);
|
||||
setTotal(data.total);
|
||||
}
|
||||
|
|
@ -82,7 +85,7 @@ export default Form.create()(({ current_user, form, showNotification, match, his
|
|||
}, [])
|
||||
|
||||
return (
|
||||
<div className="centerbox task-manage">
|
||||
<div className="task-manage">
|
||||
|
||||
<div className="center-screen" >
|
||||
<div className="center-left-but">
|
||||
|
|
|
|||
|
|
@ -106,9 +106,9 @@ export const applyStatusAllArr = [
|
|||
];
|
||||
|
||||
export const paperCheckStatusArr = [
|
||||
{ dicItemCode: "0", name: "待审核", dicItemName: "待审核" },
|
||||
{ dicItemCode: "2", name: "待审核", dicItemName: "待审核" },
|
||||
{ dicItemCode: "1", name: "通过", dicItemName: "通过" },
|
||||
{ dicItemCode: "2", name: "未通过", dicItemName: "未通过" },
|
||||
{ dicItemCode: "0", name: "未通过", dicItemName: "未通过" },
|
||||
];
|
||||
|
||||
export const paperCheckTextArr = [
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
import React, { useCallback, useEffect, useState, useMemo } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { Input, Select, Button, Form, DatePicker, Table, Pagination, Modal, message } from 'antd';
|
||||
import { Input, Select, Button, Form, DatePicker, Modal, message, Popover } from 'antd';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import { paperCheckStatusArr, publishModeArr, taskStatusAllArr, showUserModeArr, main_web_site_url, expertReviewArr } from '../static';
|
||||
import { paperCheckStatusArr, publishModeArr, taskStatusAllArr, showUserModeArr, main_web_site_url } from '../static';
|
||||
import { getTaskAdminList, changeShowUserMode, deleteTask, recommendTask, addExpertReview, publishExpertsAndRules } from '../api';
|
||||
import '../index.scss';
|
||||
import './index.scss';
|
||||
import { getRules, selectExpertList } from 'src/military/expert/api';
|
||||
import PaginationTable from '../../../../src/military/components/paginationTable';
|
||||
import PaginationTable from '../../../components/pagination-table';
|
||||
const format = "YYYY-MM-DD HH:mm:ss";
|
||||
const Option = Select.Option;
|
||||
|
||||
|
|
@ -21,7 +21,7 @@ for (const item of paperCheckStatusArr) {
|
|||
checkStatusArr[item.dicItemCode] = item.dicItemName;
|
||||
}
|
||||
|
||||
|
||||
// 管理端 创客任务列表
|
||||
export default Form.create()(({ form, showNotification, match, history, state }) => {
|
||||
const { getFieldDecorator, setFieldsValue, getFieldsValue } = form;
|
||||
const { hash} = history && history.location;
|
||||
|
|
@ -48,6 +48,8 @@ export default Form.create()(({ form, showNotification, match, history, state })
|
|||
const [rules, setRules] = useState(undefined);
|
||||
const [selectedExperts, setSelectedExperts] = useState(undefined);
|
||||
const [publicTaskId, setPublicTaskId] = useState(undefined);
|
||||
// 加入专家评审的创客id数组
|
||||
const [reviewTaskId, setReviewTaskId] = useState(undefined);
|
||||
|
||||
useEffect(()=>{
|
||||
setCurPage(hashDate(hash) || 1);
|
||||
|
|
@ -69,6 +71,11 @@ export default Form.create()(({ form, showNotification, match, history, state })
|
|||
setLoading(true);
|
||||
getTaskAdminList(params).then(data => {
|
||||
if (data) {
|
||||
let taskIds = [];
|
||||
for(const item of data.rows){
|
||||
item.expertReview && (taskIds[taskIds.length] = item.id)
|
||||
}
|
||||
setReviewTaskId(taskIds.toString());
|
||||
setTaskList(data.rows);
|
||||
setTotal(data.total);
|
||||
}
|
||||
|
|
@ -102,116 +109,78 @@ export default Form.create()(({ form, showNotification, match, history, state })
|
|||
startTime: '',
|
||||
endTime: '',
|
||||
nameInput: '',
|
||||
enterpriseNameInput: ''
|
||||
enterpriseNameInput: '',
|
||||
taskMode: '0,1,2,3,4,5,6,7,8,9',
|
||||
showUserMode: '0,1,2',
|
||||
publishMode1: '0,1',
|
||||
expertReviewStatus: '-1',
|
||||
showStatus: '0',
|
||||
isRecommend: 'all',
|
||||
sortBy: 'createdAt'
|
||||
});
|
||||
setStatusString('0,1,2,3,4,5,6,7,8,9');
|
||||
setShowUserMode('0,1,2');
|
||||
setPublishMode('0,1');
|
||||
setExpertReview('-1');
|
||||
setIsDelete('0');
|
||||
setRecommend('');
|
||||
setOrder("createdAt");
|
||||
setSearchObj({});
|
||||
}
|
||||
|
||||
const columns = useMemo(() => {
|
||||
return [
|
||||
{
|
||||
title: '任务编号',
|
||||
dataIndex: 'number',
|
||||
width: "26%"
|
||||
},
|
||||
{
|
||||
title: '任务名称',
|
||||
dataIndex: 'name',
|
||||
width: "13%",
|
||||
width: "10%",
|
||||
render: (text, record) => (
|
||||
<Link className="line_1 primary-link" target="_blank" to={`/task/taskDetail/${record.id}`} >{text}</Link>
|
||||
<Popover content = {
|
||||
<div className='taskPopover'>
|
||||
<p><span>任务名称:</span>{text}</p>
|
||||
<p className='mt5'><span>截稿时间:</span>{record.collectingEndTime && record.collectingEndTime.replaceAll('-','/').substring(0,16) || '--'}</p>
|
||||
<p className='mt5'><span>稿件数:</span>{record.papersCount || '--'}</p>
|
||||
</div>
|
||||
}>
|
||||
<Link className="line_1 primary-link" target="_blank" to={`/task/taskDetail/${record.id}`} >{text}</Link>
|
||||
</Popover>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: <Select
|
||||
className="column-select"
|
||||
showArrow
|
||||
defaultValue={'-1'}
|
||||
onChange={(value)=>{setExpertReview(value);setCurPage1(1);}}
|
||||
>
|
||||
<Option key={'-1'} >专家评审</Option>
|
||||
<Option key={'1'} >已提交评审</Option>
|
||||
<Option key={'0'} >未提交评审</Option>
|
||||
</Select>,
|
||||
dataIndex: 'expertReview',
|
||||
title: '发布主体',
|
||||
dataIndex: 'enterpriseName',
|
||||
},
|
||||
{
|
||||
title: '发布时间',
|
||||
dataIndex: 'publishedAt',
|
||||
width: "8%",
|
||||
render: (text, record) => {
|
||||
return <Select
|
||||
className="column-select"
|
||||
showArrow
|
||||
defaultValue={text?1:-1}
|
||||
onChange={(key) => { changeExpertReviewStatus(key, record.id) }}
|
||||
disabled={record.assignRuleAndExperts || !(record.status == 1 || record.status == 3)}
|
||||
>
|
||||
{
|
||||
expertReviewArr.map(item => {
|
||||
return <Option key={item.dicItemCode} value={item.dicItemCode}>{item.dicItemName}</Option>
|
||||
})
|
||||
}
|
||||
</Select>
|
||||
text = text && text.replaceAll('-','/').substring(0,16);
|
||||
return text || '--'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: <Select
|
||||
className="column-select"
|
||||
showArrow
|
||||
defaultValue={'0,1'}
|
||||
onChange={(value)=>{setPublishMode(value);setCurPage1(1);}}
|
||||
>
|
||||
<Option key={'0,1'} >发布方式</Option>
|
||||
<Option key={'0'} >自主提交</Option>
|
||||
<Option key={'1'} >统筹任务</Option>
|
||||
</Select>,
|
||||
title: '发布方式',
|
||||
dataIndex: 'publishMode',
|
||||
render: (text, record) => {
|
||||
return publishModeArr[text]
|
||||
return <span className={`publishMode mode${text}`}>{publishModeArr[text]}</span>
|
||||
}
|
||||
},
|
||||
{
|
||||
title: <Select
|
||||
className="column-select"
|
||||
showArrow
|
||||
defaultValue={'0,1,2,3,4,5,6,7,8,9'}
|
||||
onChange={(value)=>{setStatusString(value);setCurPage1(1);}}
|
||||
>
|
||||
<Option key={'0,1,2,3,4,5,6,7,8,9'} >任务状态</Option>
|
||||
{
|
||||
taskStatusAllArr.map(item => {
|
||||
return <Option key={item.dicItemCode} >{item.dicItemName}</Option>
|
||||
})
|
||||
}
|
||||
</Select>,
|
||||
width: '6%',
|
||||
title: '任务状态',
|
||||
dataIndex: 'status',
|
||||
render: (text, record) => {
|
||||
return record.exceptClosedBoolean ? '已关闭' : statusArr[text]
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '发布主体',
|
||||
dataIndex: 'enterpriseName',
|
||||
width: '9%',
|
||||
},
|
||||
{
|
||||
title: '发布时间',
|
||||
dataIndex: 'publishedAt',
|
||||
width: '7%',
|
||||
render: (text, record) => {
|
||||
return text || '--'
|
||||
}
|
||||
},
|
||||
{
|
||||
// title: '应征者名单公示',
|
||||
title: <Select
|
||||
className="column-select"
|
||||
showArrow
|
||||
placeholder="请选择审核状态"
|
||||
defaultValue={'0,1,2'}
|
||||
onChange={setShowUserMode}
|
||||
>
|
||||
<Option key={'0,1,2'}>应征者公示</Option>
|
||||
{
|
||||
showUserModeArr.map(item => {
|
||||
return <Option key={item.dicItemCode}>{item.dicItemName}</Option>
|
||||
})
|
||||
}
|
||||
</Select>,
|
||||
title: '应征者公示',
|
||||
dataIndex: 'showUserMode',
|
||||
width:'8%',
|
||||
render: (text, record) => {
|
||||
return <Select
|
||||
className="column-select"
|
||||
|
|
@ -228,44 +197,21 @@ export default Form.create()(({ form, showNotification, match, history, state })
|
|||
</Select>
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '评审规则',
|
||||
dataIndex: 'ruleEditedCount',
|
||||
render: (text, record) => {
|
||||
return record.assignRuleAndExperts ? <Button size='small' type="primary" onClick={()=>{viewRules(record)}}>查看</Button> : record.expertReview && (record.status === 1 || record.status === 3) ? <Link className="line_1 primary-link" to={`/managements/expert/task/review/rules/${1}/${record.id}/?status=${record.status}&name=${record.name}&createdAt=${record.createdAt}&collectingEndTime=${record.collectingEndTime}&choosingDays=${record.choosingDays}`}>编辑</Link> : <span className='gary_span'>编辑</span>
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '专家选取',
|
||||
dataIndex: 'expertSelectedCount',
|
||||
render: (text, record) => {
|
||||
return record.assignRuleAndExperts ? <Button size='small' type="primary" onClick={()=>{viewExperts(record)}}>查看</Button> : record.expertReview && (record.status === 1 || record.status === 3) ? <Link className="line_1 primary-link" to={`/managements/expert/task/review/select/${1}/${record.id}/?name=${record.name}`}>选择</Link> : <span className='gary_span'>选择</span>
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '评审任务',
|
||||
dataIndex: 'expertReview1',
|
||||
render: (text, record) => {
|
||||
return record.assignRuleAndExperts ? <span className='gary_span'>已发布</span> : record.expertReview && (record.status === 1 || record.status === 3) ? <Button size='small' type="primary" onClick={()=>{publishTaskReview(record)}}>发布</Button> : <span className='gary_span'>发布</span>
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '评审结果',
|
||||
dataIndex: 'expertReview2',
|
||||
render: (text, record) => {
|
||||
return record.assignRuleAndExperts ? <Link className="line_1 primary-link" to={`/managements/expert/task/review/results/${1}/${record.id}/#status=${record.status}&name=${record.name}&taskModeId=${record.taskModeId}`}>查看</Link>:<span className='gary_span'>查看</span>
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: '6%',
|
||||
render: (text, record) => (
|
||||
dataIndex: 'expertReview',
|
||||
align: 'center',
|
||||
render: (text, record) => {
|
||||
const disabled = record.assignRuleAndExperts || !(record.status == 1 || record.status == 3);
|
||||
return(
|
||||
<React.Fragment>
|
||||
|
||||
{
|
||||
isDelete == '0' ? <Button className="mr5 font-12" type="danger" size="small" onClick={() => { deleteItem(record.id, '1') }}>隐藏</Button>
|
||||
: <Button className="mr5 font-12" type="primary" size="small" onClick={() => { deleteItem(record.id, '0') }}>恢复</Button>
|
||||
<Button className="mr5 f20" onClick={() => { deleteItem(record.id,isDelete == '0' ? '1':'0') }}>{isDelete == '0' ? '隐藏任务':'恢复任务'}</Button>
|
||||
<Button className="mr5 f89" onClick={() => { recommendItem(record.id, record.recommend ? '0' :'1') }}>{record.recommend ? '撤销推荐':'首页推荐'}</Button>
|
||||
<Button className={`mr5 c2a3 ${text ? 'bor':'full'} ${disabled && 'disabled'}`} onClick={() => { changeExpertReviewStatus(text ? '-1':'1', record.id) }} disabled={disabled}>{text ? '取消专家评审':'加入专家评审'}</Button>
|
||||
{/* {
|
||||
isDelete == '0' ? <Button className="mr5 font-12" type="danger" size="small" onClick={() => { deleteItem(record.id, '1') }}>隐藏任务</Button>
|
||||
: <Button className="mr5 font-12" type="primary" size="small" onClick={() => { deleteItem(record.id, '0') }}>恢复任务</Button>
|
||||
}
|
||||
|
||||
{
|
||||
|
|
@ -274,11 +220,10 @@ export default Form.create()(({ form, showNotification, match, history, state })
|
|||
|
||||
{
|
||||
record.recommend && <Button className="mr5 font-12" type="danger" size="small" onClick={() => { recommendItem(record.id, '0') }}>撤销推荐</Button>
|
||||
}
|
||||
|
||||
} */}
|
||||
{/* <Link className="line_1 color-grey3" to={`/task/taskDetail/${record.taskId}`}>查看</Link> */}
|
||||
</React.Fragment>
|
||||
),
|
||||
)},
|
||||
},
|
||||
]
|
||||
}, [isDelete, curPage]);
|
||||
|
|
@ -370,7 +315,6 @@ export default Form.create()(({ form, showNotification, match, history, state })
|
|||
|
||||
//监听lookRules,lookExperts,pulicReview的变化,弹框
|
||||
useEffect(()=>{
|
||||
|
||||
//评审规则
|
||||
lookRules && rules && Modal.info({
|
||||
className: 'publishReview',
|
||||
|
|
@ -544,10 +488,13 @@ export default Form.create()(({ form, showNotification, match, history, state })
|
|||
});
|
||||
|
||||
const ExpertDetail = (record)=>{
|
||||
const unDisabled = record.expertReview && (record.status === 1 || record.status === 3);
|
||||
return <div className="expert_detail_div">
|
||||
<div> 任务编号:{record.number} </div>
|
||||
<div> 截稿时间:{record.collectingEndTime || '--'} </div>
|
||||
<div> 稿件数:{record.papersCount || '--'} </div>
|
||||
<div> 专家评审信息: </div>
|
||||
<div> 评审规则 {record.assignRuleAndExperts ? <Button className='c2a3 bor' onClick={()=>{viewRules(record)}}>查看</Button> : unDisabled ? <Button className="c2a3 bor" href={`/managements/expert/task/review/rules/${1}/${record.id}/?status=${record.status}&name=${record.name}&createdAt=${record.createdAt}&collectingEndTime=${record.collectingEndTime}&choosingDays=${record.choosingDays}`}>编辑</Button> : <Button className='c2a3 disabled'>编辑</Button>}</div>
|
||||
<div> 专家选取 {record.assignRuleAndExperts ? <Button className='c2a3 bor' onClick={()=>{viewExperts(record)}}>查看</Button> : unDisabled ? <Button className="c2a3 bor" href={`/managements/expert/task/review/select/${1}/${record.id}/?name=${record.name}`}>选择</Button> : <Button className='c2a3 disabled'>选择</Button>}</div>
|
||||
<div> 评审任务 {record.assignRuleAndExperts ? <Button className='c2a3 disabled'>已发布</Button> : unDisabled ? <Button className='c2a3 full' onClick={()=>{publishTaskReview(record)}}>发布</Button> : <Button className='c2a3 disabled'>发布</Button>}</div>
|
||||
<div> 评审结果 {record.assignRuleAndExperts ? <Button className="c2a3 bor" href={`/managements/expert/task/review/results/${1}/${record.id}/#status=${record.status}&name=${record.name}&taskModeId=${record.taskModeId}`}>查看</Button>:<Button className='c2a3 disabled'>查看</Button>}</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
|
@ -556,28 +503,29 @@ export default Form.create()(({ form, showNotification, match, history, state })
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="centerbox task-manage-all ">
|
||||
|
||||
<div className="search-screen" >
|
||||
{helper(
|
||||
"任务名称",
|
||||
"nameInput",
|
||||
[{ max: 20, message: '长度不能超过20个字符' }],
|
||||
<Input
|
||||
placeholder="输入任务名称进行检索"
|
||||
/>
|
||||
)}
|
||||
<div className="task-manage-all ">
|
||||
<div className='management-content-head'>
|
||||
<p className='font-18'>创客任务列表</p>
|
||||
<div className="search-task" >
|
||||
{helper(
|
||||
"任务名称",
|
||||
"nameInput",
|
||||
[{ max: 20, message: '长度不能超过20个字符' }],
|
||||
<Input
|
||||
placeholder="输入任务名称进行检索"
|
||||
/>
|
||||
)}
|
||||
|
||||
{helper(
|
||||
"发布主体名称",
|
||||
"enterpriseNameInput",
|
||||
[{ max: 20, message: '长度不能超过20个字符' }],
|
||||
<Input
|
||||
placeholder="输入发布主体名称进行检索"
|
||||
/>
|
||||
)}
|
||||
{helper(
|
||||
"发布主体名称",
|
||||
"enterpriseNameInput",
|
||||
[{ max: 20, message: '长度不能超过20个字符' }],
|
||||
<Input
|
||||
placeholder="输入发布主体名称进行检索"
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className="center-right-but">
|
||||
<div className="center-right-but time">
|
||||
|
||||
{helper(
|
||||
"发布时间:",
|
||||
|
|
@ -600,83 +548,151 @@ export default Form.create()(({ form, showNotification, match, history, state })
|
|||
placeholder="请选择结束时间"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div className="button-div">
|
||||
{/* <a href="/admin/tasks.xlsx" class="fr edu-default-btn edu-blueback-btn plr30">导出</a> */}
|
||||
<Button className="mr10" type="primary" onClick={onSearch}>搜索</Button>
|
||||
<Button className="mr10" onClick={clearSearch}>清除</Button>
|
||||
<Button className="mr10" type="primary" onClick={downloadFile}>导出</Button>
|
||||
</div>
|
||||
|
||||
{helper(
|
||||
"任务状态",
|
||||
"taskMode",
|
||||
[],
|
||||
<Select
|
||||
className="column-select"
|
||||
showArrow
|
||||
onChange={(value)=>{setStatusString(value);setCurPage1(1);}}
|
||||
>
|
||||
<Option key={'0,1,2,3,4,5,6,7,8,9'} >全部</Option>
|
||||
{
|
||||
taskStatusAllArr.map(item => {
|
||||
return <Option key={item.dicItemCode} >{item.dicItemName}</Option>
|
||||
})
|
||||
}
|
||||
</Select>,
|
||||
'0,1,2,3,4,5,6,7,8,9'
|
||||
)}
|
||||
|
||||
{helper(
|
||||
"应征者公示",
|
||||
"showUserMode",
|
||||
[],
|
||||
<Select
|
||||
className="column-select"
|
||||
showArrow
|
||||
placeholder="请选择审核状态"
|
||||
onChange={(value)=>{setShowUserMode(value);setCurPage1(1);}}
|
||||
>
|
||||
<Option key={'0,1,2'}>全部</Option>
|
||||
{
|
||||
showUserModeArr.map(item => {
|
||||
return <Option key={item.dicItemCode}>{item.dicItemName}</Option>
|
||||
})
|
||||
}
|
||||
</Select>,
|
||||
'0,1,2'
|
||||
)}
|
||||
|
||||
|
||||
{helper(
|
||||
"发布方式",
|
||||
"publishMode1",
|
||||
[],
|
||||
<Select
|
||||
className="column-select"
|
||||
showArrow
|
||||
onChange={(value)=>{setPublishMode(value);setCurPage1(1);}}
|
||||
>
|
||||
<Option key={'0,1'} >全部</Option>
|
||||
<Option key={'0'} >自主提交</Option>
|
||||
<Option key={'1'} >统筹任务</Option>
|
||||
</Select>,
|
||||
'0,1'
|
||||
)}
|
||||
{helper(
|
||||
"专家评审状态",
|
||||
"expertReviewStatus",
|
||||
[],
|
||||
<Select
|
||||
className="column-select"
|
||||
showArrow
|
||||
onChange={(value)=>{setExpertReview(value);setCurPage1(1);}}
|
||||
>
|
||||
<Option key={'-1'} >全部</Option>
|
||||
<Option key={'1'} >已提交评审</Option>
|
||||
<Option key={'0'} >未提交评审</Option>
|
||||
</Select>,
|
||||
'-1'
|
||||
)}
|
||||
{/* <div className='center-right-but search'> */}
|
||||
{helper(
|
||||
"显示状态",
|
||||
"showStatus",
|
||||
[],
|
||||
<Select
|
||||
className="column-select"
|
||||
showArrow
|
||||
onChange={changeShow}
|
||||
>
|
||||
<Option key={'0'} >正常显示</Option>
|
||||
<Option key={'1'} >已隐藏</Option>
|
||||
</Select>,
|
||||
'0'
|
||||
)}
|
||||
{helper(
|
||||
"是否推荐",
|
||||
"isRecommend",
|
||||
[],
|
||||
<Select
|
||||
className="column-select"
|
||||
showArrow
|
||||
onChange={changeRecommend}
|
||||
>
|
||||
<Option key={'all'} >不限</Option>
|
||||
<Option key={'0'} >未推荐</Option>
|
||||
<Option key={'1'} >已推荐</Option>
|
||||
</Select>,
|
||||
'all'
|
||||
)}
|
||||
{helper(
|
||||
"排序",
|
||||
"sortBy",
|
||||
[],
|
||||
<Select
|
||||
className="column-select"
|
||||
showArrow
|
||||
onChange={changeSortName}
|
||||
>
|
||||
<Option key={'createdAt'} >创建时间</Option>
|
||||
<Option key={'publishedAt'} >发布时间</Option>
|
||||
</Select>,
|
||||
'createdAt'
|
||||
)}
|
||||
<div className="button-div">
|
||||
{/* <a href="/admin/tasks.xlsx" class="fr edu-default-btn edu-blueback-btn plr30">导出</a> */}
|
||||
<Button className="mr10" type="primary" onClick={onSearch}>搜索</Button>
|
||||
<Button className="mr10" onClick={clearSearch}>清除</Button>
|
||||
<Button className="mr10" type="primary" onClick={downloadFile}>导出</Button>
|
||||
</div>
|
||||
<span className={classNames({ "sort-active": sort === 'Desc', 'sort-icon': true, 'mt5': true })} onClick={() => { changeSort('Desc') }}>
|
||||
<i className="fa fa-long-arrow-down font-16 "></i>
|
||||
</span>
|
||||
<span className={classNames({ "sort-active": sort === 'Asc', 'sort-icon': true, 'mt5': true })} onClick={() => { changeSort('Asc') }}>
|
||||
<i className="fa fa-long-arrow-up font-16 "></i>
|
||||
</span>
|
||||
{/* </div> */}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="select-box">
|
||||
<Form.Item className="inline-form" label="显示状态">
|
||||
<Select
|
||||
style={{ width: '200px' }}
|
||||
showArrow
|
||||
onChange={changeShow}
|
||||
defaultValue='0'
|
||||
>
|
||||
<Option key={'0'} >正常显示(默认)</Option>
|
||||
<Option key={'1'} >已隐藏</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item className="inline-form" label="是否推荐">
|
||||
<Select
|
||||
style={{ width: '200px' }}
|
||||
showArrow
|
||||
onChange={changeRecommend}
|
||||
defaultValue='all'
|
||||
>
|
||||
<Option key={'all'} >全部</Option>
|
||||
<Option key={'0'} >未推荐</Option>
|
||||
<Option key={'1'} >已推荐</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item className="inline-form" label="排序">
|
||||
<Select
|
||||
style={{ width: '200px' }}
|
||||
showArrow
|
||||
onChange={changeSortName}
|
||||
defaultValue='createdAt'
|
||||
>
|
||||
<Option key={'createdAt'} >创建时间</Option>
|
||||
<Option key={'publishedAt'} >发布时间</Option>
|
||||
</Select>
|
||||
|
||||
<span className={classNames({ "sort-active": sort === 'Desc', 'sort-icon': true, 'ml10': true })} onClick={() => { changeSort('Desc') }}>
|
||||
<i className="fa fa-long-arrow-down font-16 "></i>
|
||||
</span>
|
||||
<span className={classNames({ "sort-active": sort === 'Asc', 'sort-icon': true })} onClick={() => { changeSort('Asc') }}>
|
||||
<i className="fa fa-long-arrow-up font-16 "></i>
|
||||
</span>
|
||||
|
||||
</Form.Item>
|
||||
</div>
|
||||
|
||||
<div className="center-content">
|
||||
|
||||
<Table
|
||||
<div className="center-content taskListCont">
|
||||
<PaginationTable
|
||||
loading={loading}
|
||||
rowKey={(row) => row.id}
|
||||
dataSource={taskList}
|
||||
columns={columns}
|
||||
pagination={false}
|
||||
className="mt10"
|
||||
total={total}
|
||||
current={curPage}
|
||||
setCurPage={(page)=>{setCurPage1(page)}}
|
||||
className="expertReviewTable"
|
||||
expandedRowRender={ExpertDetail}
|
||||
expandedRowKeys={reviewTaskId}
|
||||
/>
|
||||
{total > 10 &&
|
||||
<Pagination
|
||||
onChange={(page) => { setCurPage1(page) }}
|
||||
current={curPage}
|
||||
total={total}
|
||||
/>}
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,34 @@
|
|||
.search-screen {
|
||||
.management-content-head{
|
||||
background-color: #fff;
|
||||
margin-top: 1rem;
|
||||
padding: 1.5rem;
|
||||
border-radius:4px;
|
||||
box-shadow:0px 0px 10px rgba(88, 116, 255, 0.18);
|
||||
>p{
|
||||
color:#18191e;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px solid #e2e6f5;
|
||||
}
|
||||
}
|
||||
.taskPopover{
|
||||
p{
|
||||
color:#20294a;
|
||||
&:last-child{
|
||||
margin-left: 14px;
|
||||
}
|
||||
span{
|
||||
color:#596078;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.search-task {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
justify-content: space-between;
|
||||
margin: 1.25rem 0;
|
||||
padding: 1.25rem;
|
||||
background-color: #fff;
|
||||
border-bottom: 1px solid #dedede;
|
||||
|
||||
justify-content: flex-start;
|
||||
margin: 20px 0 0;
|
||||
> .ant-row {
|
||||
min-width: 41%;
|
||||
min-width: 20%;
|
||||
margin-right: 2rem;
|
||||
.ant-form-item-label {
|
||||
float: left;
|
||||
|
|
@ -19,34 +39,75 @@
|
|||
}
|
||||
|
||||
.center-right-but {
|
||||
display: flex;
|
||||
.ant-form-item {
|
||||
margin: 0 1rem 0 0;
|
||||
}
|
||||
.ant-form-item-control-wrapper {
|
||||
display: inline-block;
|
||||
}
|
||||
&.search .ant-form-item{
|
||||
margin: 0 5rem 0 0;
|
||||
}
|
||||
&.time{
|
||||
margin: 0 2rem 24px 0;
|
||||
|
||||
}
|
||||
}
|
||||
.button-div {
|
||||
margin-right: 1.5rem;
|
||||
.ant-row .ant-form-item-label{
|
||||
margin-right: 20px;
|
||||
label::after{
|
||||
content: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.task-manage-all {
|
||||
.column-select {
|
||||
min-width: 100px;
|
||||
.ant-select-selection {
|
||||
background: #fafafa;
|
||||
border: 0;
|
||||
}
|
||||
width: 100%;
|
||||
}
|
||||
.ant-table-thead > tr > th,
|
||||
.ant-table-tbody > tr > td {
|
||||
padding: 1rem 0.1rem;
|
||||
text-align: center;
|
||||
padding: 1rem 1rem;
|
||||
text-align: left;
|
||||
&, & div{
|
||||
color:#20294a;
|
||||
}
|
||||
.ant-btn{
|
||||
padding: 0 9px;
|
||||
}
|
||||
.f20{
|
||||
border-color:#f20000;
|
||||
span{
|
||||
color:#f20000;
|
||||
}
|
||||
}
|
||||
.f89{
|
||||
border-color:#f89d00;
|
||||
span{
|
||||
color:#f89d00;
|
||||
}
|
||||
}
|
||||
.c2a3{
|
||||
border-color:#2a3ee9;
|
||||
&.bor{
|
||||
background-color: #fff;
|
||||
span{color:#2a3ee9;}
|
||||
}
|
||||
&.full{
|
||||
background-color:#2a3ee9;
|
||||
span{color: white;}
|
||||
}
|
||||
&.disabled{
|
||||
background-color:#f2f2f2;
|
||||
border: none;
|
||||
span{color:#a6adc4;}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a.primary-link {
|
||||
color: #1890ff;
|
||||
color: #20294a;
|
||||
}
|
||||
|
||||
.select-box{
|
||||
|
|
@ -60,12 +121,16 @@
|
|||
}
|
||||
.expert_detail_div{
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
div{
|
||||
margin-right: 48px;
|
||||
.ant-btn{
|
||||
margin-left: 10px;
|
||||
width: 66px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// .ant-table-row-collapsed::after, .ant-table-row-expanded::after {
|
||||
// content: url('./image/down.svg');
|
||||
// }
|
||||
}
|
||||
|
||||
.inline-form {
|
||||
|
|
@ -138,3 +203,31 @@
|
|||
padding: 3px 8px;
|
||||
}
|
||||
}
|
||||
.taskListCont{
|
||||
.publishMode{
|
||||
position: relative;
|
||||
&:before{
|
||||
content: ' ';
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
left: -12px;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
.mode0:before{
|
||||
background-color: #2a3ee9;
|
||||
}
|
||||
.mode1:before{
|
||||
background-color: #00dc51;
|
||||
}
|
||||
table tr td:first-child, table tr th:first-child{
|
||||
display: none;
|
||||
}
|
||||
tr.ant-table-expanded-row, tr.ant-table-expanded-row:hover{
|
||||
background-color:#fbfbff;
|
||||
// td{padding: 0.5rem 1rem;}
|
||||
}
|
||||
tr.ant-table-expanded-row td{padding: 0.5rem 1rem;}
|
||||
}
|
||||
|
|
@ -47,6 +47,9 @@ export default Form.create()(({ form, showNotification, match, history }) => {
|
|||
setLoading(true);
|
||||
getTaskAdminList(params).then(data => {
|
||||
if (data) {
|
||||
if((data.rows && data.rows.length<=0) && curPage>1){
|
||||
setCurPage(curPage-1);
|
||||
}
|
||||
setTaskList(data.rows);
|
||||
setTotal(data.total);
|
||||
}
|
||||
|
|
@ -100,7 +103,7 @@ export default Form.create()(({ form, showNotification, match, history }) => {
|
|||
}, [])
|
||||
|
||||
return (
|
||||
<div className="centerbox task-manage">
|
||||
<div className="task-manage">
|
||||
<div className="center-screen" >
|
||||
<div className="center-left-but">
|
||||
<Button className="circle-button" type={approve === 1 ? 'primary' : ''} onClick={() => { changeApprove(1) }}>待审批</Button>
|
||||
|
|
|
|||
|
|
@ -54,14 +54,10 @@ class NewHeader extends Component {
|
|||
settings: null,
|
||||
goshowqqgtounp: false,
|
||||
visiblemyss: false,
|
||||
isExpert: false,
|
||||
visible:false, //浮动消息框展示控制
|
||||
}
|
||||
}
|
||||
componentDidMount() {
|
||||
getUserInfo().then(response =>{
|
||||
response && this.setState({isExpert: response.data && response.data.expert});
|
||||
});
|
||||
// this.getAppdata();
|
||||
this.geturlsdata();
|
||||
window._header_componentHandler = this;
|
||||
|
|
@ -638,7 +634,7 @@ class NewHeader extends Component {
|
|||
goshowqqgtounp,
|
||||
visible,
|
||||
} = this.state;
|
||||
let activeIndex =match.path === '/'?true: '';
|
||||
let activeIndex =match.path === '/' || (match.path&&match.path.startsWith('/managements')) || (match.path&&match.path.startsWith('/admin'))?true: '';
|
||||
let headtypes = '/';
|
||||
if (settings) {
|
||||
if (settings.navbar) {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ body>.-task-title {
|
|||
min-width: 1200px;
|
||||
max-width: unset;
|
||||
height: 100%;
|
||||
min-height: 70vh;
|
||||
min-height: calc(100vh - 177px);
|
||||
overflow: hidden;
|
||||
}
|
||||
.newHeaders{
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import Header from '../../forge/Head/Header';
|
|||
import NewHeader from './NewHeader';
|
||||
import NewFooter from './NewFooter';
|
||||
import { downloadFile } from 'educoder';
|
||||
import { getCurrentExpert } from 'src/military/expert/api';
|
||||
import { getCurrentExpert, getUserInfo } from 'src/military/expert/api';
|
||||
import axios from 'axios';
|
||||
import { Spin } from 'antd';
|
||||
import './TPMIndex.css';
|
||||
|
|
@ -28,13 +28,14 @@ export function TPMIndexHOC(WrappedComponent, headFoot) {
|
|||
dataquerys: {},
|
||||
isloginCancel: undefined,
|
||||
mygetHelmetapi: null,
|
||||
giteaVisible:false,
|
||||
email:undefined,
|
||||
completeProfile:false,
|
||||
showCP:false,
|
||||
showNotice:true,
|
||||
giteaVisible: false,
|
||||
email: undefined,
|
||||
completeProfile: false,
|
||||
showCP: false,
|
||||
showNotice: true,
|
||||
gopage: undefined,
|
||||
Footerdown: undefined,
|
||||
menuList:[],
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -158,11 +159,11 @@ export function TPMIndexHOC(WrappedComponent, headFoot) {
|
|||
fetchUsers = () => {
|
||||
if (this.props.match.path === "/") {
|
||||
this.setState({
|
||||
publicNav:true
|
||||
publicNav: true
|
||||
})
|
||||
}else{
|
||||
} else {
|
||||
this.setState({
|
||||
publicNav:false
|
||||
publicNav: false
|
||||
})
|
||||
}
|
||||
let url = `/users/get_user_info.json`;
|
||||
|
|
@ -171,21 +172,21 @@ export function TPMIndexHOC(WrappedComponent, headFoot) {
|
|||
this.initCommonState(response.data)
|
||||
this.setState({
|
||||
tpmLoading: false,
|
||||
completeProfile:response.data.profile_completed
|
||||
completeProfile: response.data.profile_completed
|
||||
})
|
||||
if(response.data && response.data.login){
|
||||
if(response.data.need_edit_info){
|
||||
if (response.data && response.data.login) {
|
||||
if (response.data.need_edit_info) {
|
||||
this.setState({
|
||||
giteaVisible:true,
|
||||
email:response.data.email
|
||||
giteaVisible: true,
|
||||
email: response.data.email
|
||||
})
|
||||
}
|
||||
}
|
||||
if(response.data && response.data.login){
|
||||
if(response.data.need_edit_info){
|
||||
if (response.data && response.data.login) {
|
||||
if (response.data.need_edit_info) {
|
||||
this.setState({
|
||||
giteaVisible:true,
|
||||
email:response.data.email
|
||||
giteaVisible: true,
|
||||
email: response.data.email
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -195,7 +196,7 @@ export function TPMIndexHOC(WrappedComponent, headFoot) {
|
|||
|
||||
// 考虑到以后部分系统不会用到专家评审系统,所以这里没有使用Promise.All
|
||||
getCurrentExpert().then(res => {
|
||||
if(res){
|
||||
if (res) {
|
||||
let isExpert = false;
|
||||
let expertId = '';
|
||||
let expertDraft = false;
|
||||
|
|
@ -218,6 +219,18 @@ export function TPMIndexHOC(WrappedComponent, headFoot) {
|
|||
}).catch((error) => {
|
||||
console.log(error)
|
||||
});
|
||||
|
||||
getUserInfo().then(response => {
|
||||
// response && this.setState({isExpert: response.data && response.data.expert});
|
||||
if (response) {
|
||||
// this.setState({ isExpert: response.data && response.data.expert });
|
||||
// localStorage.setItem('menuList', JSON.stringify(response.data.menuNodes));
|
||||
this.setState({menuList:response.data.menuNodes})
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
});
|
||||
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error)
|
||||
|
|
@ -244,56 +257,56 @@ export function TPMIndexHOC(WrappedComponent, headFoot) {
|
|||
return this.state.current_user && this.state.current_user.login != ''
|
||||
}
|
||||
|
||||
onOk =(values)=>{
|
||||
onOk = (values) => {
|
||||
let url = `/users/sync_user_info.json`;
|
||||
const { current_user } = this.state;
|
||||
axios.post(url,{
|
||||
login:current_user && current_user.login,
|
||||
axios.post(url, {
|
||||
login: current_user && current_user.login,
|
||||
...values
|
||||
}).then(result=>{
|
||||
if(result && result.data && result.data.status === 0){
|
||||
}).then(result => {
|
||||
if (result && result.data && result.data.status === 0) {
|
||||
this.setState({
|
||||
giteaVisible:false,
|
||||
email:undefined
|
||||
giteaVisible: false,
|
||||
email: undefined
|
||||
})
|
||||
window.location.reload();
|
||||
}
|
||||
}).catch(error=>{})
|
||||
}).catch(error => { })
|
||||
}
|
||||
hideSystemNotice=()=>{
|
||||
hideSystemNotice = () => {
|
||||
this.setState({
|
||||
showNotice:false
|
||||
showNotice: false
|
||||
})
|
||||
}
|
||||
|
||||
showCompeleteDialog=()=>{
|
||||
showCompeleteDialog = () => {
|
||||
this.setState({
|
||||
showCP:true
|
||||
showCP: true
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
let { isRender , current_user , giteaVisible , email , completeProfile , showCP , showNotice , publicNav , mygetHelmetapi ,Footerdown} = this.state;
|
||||
let { isRender, current_user, giteaVisible, email, completeProfile, showCP, showNotice, publicNav, mygetHelmetapi, Footerdown } = this.state;
|
||||
const common = {
|
||||
showLoginDialog: this.showLoginDialog,
|
||||
checkIfLogin: this.checkIfLogin,
|
||||
resetUserInfo:this.fetchUsers,
|
||||
showCompeleteDialog:this.showCompeleteDialog
|
||||
resetUserInfo: this.fetchUsers,
|
||||
showCompeleteDialog: this.showCompeleteDialog
|
||||
};
|
||||
let competition = this.props.match.path.includes('/competition');
|
||||
return (
|
||||
<div className="indexHOC">
|
||||
<SystemNotice
|
||||
<SystemNotice
|
||||
showNotice={showNotice}
|
||||
system_notification={mygetHelmetapi && mygetHelmetapi.system_notification}
|
||||
history={this.props.history}
|
||||
system_notification={mygetHelmetapi && mygetHelmetapi.system_notification}
|
||||
history={this.props.history}
|
||||
login={current_user && current_user.login}
|
||||
hideSystemNotice={this.hideSystemNotice}
|
||||
/>
|
||||
<EducoderAccount visible={giteaVisible} email={email} onOk={this.onOk}/>
|
||||
<ProfileModal
|
||||
visible={!completeProfile && showCP}
|
||||
onCancel={()=>{this.setState({showCP:false})}}
|
||||
<EducoderAccount visible={giteaVisible} email={email} onOk={this.onOk} />
|
||||
<ProfileModal
|
||||
visible={!completeProfile && showCP}
|
||||
onCancel={() => { this.setState({ showCP: false }) }}
|
||||
history={this.props.history}
|
||||
/>
|
||||
{isRender === true ? <LoginDialog
|
||||
|
|
|
|||
|
|
@ -14,3 +14,47 @@
|
|||
.login-box{
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
/* 新版首页头部样式 */
|
||||
.homePage.newHeaders {
|
||||
background-color: #0037af;
|
||||
z-index: 1000;
|
||||
}
|
||||
.homePage .newFooter{
|
||||
background: inherit;
|
||||
}
|
||||
.homePage .head-nav {
|
||||
min-width: auto;
|
||||
}
|
||||
.homePage .head-nav ul#header-nav li a {
|
||||
font-size: 1em;
|
||||
color: #fff;
|
||||
}
|
||||
.homePage .head-nav ul#header-nav li:hover a,
|
||||
.homePage .head-nav ul#header-nav li.active a {
|
||||
color: #ffa13a;
|
||||
}
|
||||
.homePage .head-nav ul#header-nav li.active a::after {
|
||||
background-color: #ffa13a;
|
||||
}
|
||||
|
||||
.homePage .logoDiv img {
|
||||
min-width: 2.8125em;
|
||||
height: 2.8125em;
|
||||
}
|
||||
|
||||
.homePage .color-home {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.homePage .color-home:hover {
|
||||
color: #4154f1;
|
||||
}
|
||||
|
||||
.homePage .register-button {
|
||||
height: 3em;
|
||||
margin-left: 1.25em;
|
||||
padding: 0 1.5625em;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
/* 新版首页头部样式 */
|
||||
|
|
|
|||
Loading…
Reference in New Issue