}
diff --git a/src/forge/Upload/read.js b/src/forge/Upload/read.js
index 781c08415..6f5136471 100644
--- a/src/forge/Upload/read.js
+++ b/src/forge/Upload/read.js
@@ -1,8 +1,5 @@
import React, { Component } from "react";
import { Upload, Icon } from "antd";
-import { getUploadActionUrl, appendFileSizeToUploadFileAll } from "educoder";
-
-import axios from "axios";
const { Dragger } = Upload;
class Read extends Component {
constructor(props) {
@@ -22,53 +19,43 @@ class Read extends Component {
});
};
- handleChange = (info) => {
- let reader = new FileReader();
- reader.readAsText(info.fileList[0].originFileObj, "UTF-8");
- reader.onload = (e) => {
- this.state.fileContent = e.target.result;
- this.props.load && this.props.load(this.state);
- };
- };
-
-
beforeUpload = (file) => {
- const forbidden_type = [
- "jpg",
- "jpeg",
- "png",
- "ico",
- "bmp",
- "gif",
- "pdf",
- "csv",
- "xlsx",
- "xls",
- "tif",
- "svg",
- "psd",
- "cdr",
- "webp",
- ];
const { fileList } = this.state;
const { size } = this.props;
const isLt100M = file.size / 1024 / 1024 < size;
- const file_type = file.type.split("/").slice(-1)[0];
if (fileList && fileList.length > 0) {
this.props.showNotification("文件已存在, 请删除后再上传");
+ return false;
} else if (!isLt100M) {
this.props.showNotification(`文件大小必须小于${size}MB!`);
- } else if (file_type && forbidden_type.indexOf(file_type) !== -1) {
- this.props.showNotification(`不支持${file_type}类型`);
+ return false;
} else {
this.setState({
fileList: [file],
fileName: file.name,
})
}
- return false;
};
+ // 上传 文件转base64
+ customRequest = (option) =>{
+ const formData = new FormData();
+ formData.append('files[]', option.file);
+ const reader = new FileReader();
+ reader.readAsDataURL(option.file);
+ const {load} = this.props;
+ reader.onloadend = function(e){
+ if(e.target.result){
+ option.onSuccess();
+ const base64 = e.target.result.substring(e.target.result.indexOf('base64')+7, e.target.result.length);
+ load({
+ fileName: option.file.name,
+ fileContent: base64
+ });
+ }
+ }
+ }
+
render() {
//判断是否已经提交,如已提交评论则上一条评论数据清除
const { icon, size } = this.props;
@@ -76,10 +63,10 @@ class Read extends Component {
const upload = {
name: "file",
fileList: fileList,
- onChange: this.handleChange,
+ customRequest: this.customRequest,
onRemove: this.onAttachmentRemove,
- beforeUpload: this.beforeUpload
- };
+ beforeUpload: this.beforeUpload,
+ };
return (
@@ -91,9 +78,9 @@ class Read extends Component {
拖动文件或点击此处上传
-
- 暂仅支持文件格式,不支持图片,excel等不可以txt读取的文件
-
+ {/*
+ 暂仅支持文本格式,不支持图片,excel等不可以txt读取的文件
+
*/}
文件名请使用英文且不得超过{size}MB
diff --git a/src/forge/css/index.scss b/src/forge/css/index.scss
index 4bde40a9f..720b02f4e 100644
--- a/src/forge/css/index.scss
+++ b/src/forge/css/index.scss
@@ -62,6 +62,12 @@ ul,ol,dl{
color: #666;
display: inline-block;
}
+.ProjectListIndex{
+ background-color:#f5f7fa;
+ .ant-affix{
+ z-index: 1;
+ }
+}
@media screen and (max-width: 1200px){
.main{
width:100%;
@@ -223,26 +229,34 @@ form{
}
}
.list-l-Menu{
- margin-bottom: 12px!important;
- border-radius:2px;
- background-color: #fff;
- box-shadow: 0px 0px 2px rgba(0,0,0,0.2);
+ margin-bottom: 35px!important;
+ background-image:linear-gradient(180deg,#f4f5f8 0%,#fbfcfd 100%);
+ border:2px solid #ffffff;
.list-affix{
min-height: 20px;
- max-height: 248px;
+ max-height: 285px;
overflow-y: auto;
+ &::-webkit-scrollbar-thumb{
+ background-color:#e6edf9;
+ box-shadow: none
+ }
+ &::-webkit-scrollbar-track{
+ display: none;
+ }
+ &::-webkit-scrollbar{
+ background: none;
+ }
}
li{
font-size: 1rem;
padding:0px 0px 0px 20px;
box-sizing: border-box;
- color: #333;
+ color:#4c5b76;
position: relative;
p{
- height: 62px;
- line-height: 62px;
+ height: 48px;
+ line-height: 48px;
width: 100%;
- border-bottom: 1px solid #eee;
display: flex;
justify-content: space-between;
cursor: pointer;
@@ -251,39 +265,38 @@ form{
a{
width:100%;
}
- & span:last-child{
- color: #999;
- }
}
&:last-child > p{
border-bottom: none;
}
- &:not(.MenuTitle):hover{
- background-color: #fafafa;
+ &:not(.MenuTitle):not(.active):hover{
+ background-color: rgba(225, 225, 225, 0.3);
}
}
li.active{
- background-color: #fafafa;
+ background-color: rgba(70, 106, 255, 0.09);
+ color:#2a3ee9;
}
li.active::before{
position: absolute;
left: 0px;
- top: 15px;
+ top: 10px;
width: 6px;
content: '';
- height: 33px;
+ height: 29px;
background: #4154f1;
}
.MenuTitle{
- font-size: 16px;
+ font-size: 17px;
background-size: 100% 100%;
- color: #333!important;
- height: 62px;
- line-height: 62px;
- border-bottom: 1px solid #E0E0E0;
+ color:#000000;
+ height: 71px;
+ line-height: 48px;
font-weight: 400;
padding-left: 20px;
+ display: flex;
+ align-items: center;
span{
display: block;
width: 50%;
@@ -292,7 +305,6 @@ form{
}
span:hover{
color: #4154f1;
-
.iconfont{
color: #4154f1 !important;
}
diff --git a/src/forge/users/GeneralView/ConcentrateBox.jsx b/src/forge/users/GeneralView/ConcentrateBox.jsx
index 001b598dc..39a598c07 100644
--- a/src/forge/users/GeneralView/ConcentrateBox.jsx
+++ b/src/forge/users/GeneralView/ConcentrateBox.jsx
@@ -1,11 +1,12 @@
import React, { useEffect, useState } from 'react';
import { Modal , Checkbox , Spin , Input } from 'antd';
import Axios from 'axios';
-import CheckProfile from '../../Component/ProfileModal/Profile';
+// import CheckProfile from '../../Component/ProfileModal/Profile';
+import './Index.scss';
const { Search } = Input;
const limit = 20;
-function ConcentrateBox({ visible , onCancel , onSure , username , choosed , history , showCompeleteDialog , completeProfile }) {
+function ConcentrateBox({ visible , onCancel , onSure , getProjectListUrl , choosed , history , showCompeleteDialog , completeProfile, createProjectUrl }) {
const [ page , setPage ]= useState(1);
const [ total , setTotal ]= useState(0);
const [ pageSize , setPageSize ] = useState(false);
@@ -18,7 +19,7 @@ function ConcentrateBox({ visible , onCancel , onSure , username , choosed , his
const [ copyList , setCopyList ] = useState([]);
const [ copyAllList , setCopyAllList ] = useState([]);
-
+
useEffect(()=>{
if(visible){
setIsSpin(true);
@@ -54,7 +55,7 @@ function ConcentrateBox({ visible , onCancel , onSure , username , choosed , his
},[value])
function getProjectList(p,s) {
- const url = `/users/${username}/projects.json`;
+ const url = getProjectListUrl;
Axios.get(url,{
params:{
page:p,limit,is_public: "public",search:s,choosed
@@ -137,7 +138,7 @@ function ConcentrateBox({ visible , onCancel , onSure , username , choosed , his
>
-
最多可选取6个公开仓库
+
最多可选取6个公开仓库
您还没有公开的{search && `“${search}”`}项目,先去
- {history.push(createProjectUrl)}} className="color-blue">新建项目
+ {/* {history.push(`/projects/deposit/new`)}}
- className="color-blue">新建项目
+ sureFunc={()=>{history.push(createProjectUrl)}}
+ className="color-blue">新建项目 */}
}
diff --git a/src/forge/users/GeneralView/ConcentrateProject.jsx b/src/forge/users/GeneralView/ConcentrateProject.jsx
index d3f99e53c..60750f45e 100644
--- a/src/forge/users/GeneralView/ConcentrateProject.jsx
+++ b/src/forge/users/GeneralView/ConcentrateProject.jsx
@@ -49,11 +49,12 @@ function ConcentrateProject({userLogin,current,showCompeleteDialog,completeProfi
visible={visible}
onCancel={()=>setVisible(false)}
onSure={onSure}
- username={userLogin}
+ getProjectListUrl={`/users/${userLogin}/projects.json`}
choosed={value}
completeProfile={completeProfile}
showCompeleteDialog={showCompeleteDialog}
history={history}
+ createProjectUrl={`/projects/deposit/new`}
/>
{
list && list.length>0 &&
diff --git a/src/forge/users/GeneralView/Index.scss b/src/forge/users/GeneralView/Index.scss
index e79f68580..28b574c21 100644
--- a/src/forge/users/GeneralView/Index.scss
+++ b/src/forge/users/GeneralView/Index.scss
@@ -17,8 +17,9 @@
margin-right: 0px;
}
.name{
+ word-break: break-all;
font-size: 16px;
- color: #4CACFF;
+ color: #4154f1;
}
.desc{
color: #999;
@@ -71,6 +72,9 @@
max-height: 210px;
overflow-y: auto;
padding-left: 30px;
+ .ant-checkbox-wrapper + .ant-checkbox-wrapper{
+ margin-left: 0px;
+ }
}
.operateDiv{
padding:20px 30px
@@ -87,8 +91,9 @@
width: 50%;
margin-left: 0px!important;
display: flex;
+ align-items: center;
.ant-checkbox{
- padding-top: 3px;
+ height: 16px;
}
span:last-child{
flex:1;
diff --git a/src/forge/users/Index.scss b/src/forge/users/Index.scss
index e523323d2..60e8a31cf 100644
--- a/src/forge/users/Index.scss
+++ b/src/forge/users/Index.scss
@@ -42,8 +42,8 @@ $flex:flex;
padding:20px 25px;
background-color:rgba(250,250,250,1);
.imgBox{
- width: 190px;
- height: 90px;
+ width: 100px;
+ height: 100px;
display: flex;
align-items: center;
justify-content: center;
@@ -261,7 +261,7 @@ ul.ant-menu.menuStyle{
bottom: -1px;
height: 2px;
left: 0px;
- background-color: #1890ff;
+ background-color: #4154f1;
content:"";
}
}
diff --git a/src/forge/users/InfosUser.js b/src/forge/users/InfosUser.js
index 4a5c7d9bc..fb3375719 100644
--- a/src/forge/users/InfosUser.js
+++ b/src/forge/users/InfosUser.js
@@ -1,6 +1,6 @@
import React, { Component } from "react";
import { Menu, Input, Spin, Pagination, Popover, Button, Divider } from "antd";
-import CheckProfile from '../Component/ProfileModal/Profile';
+// import CheckProfile from '../Component/ProfileModal/Profile';
import axios from "axios";
import ListItem from "../Main/IndexItem";
@@ -114,13 +114,19 @@ class InfosUser extends Component {
);
newItem =()=> (
-
- -
+
+ - {this.props.history.push('/projects/deposit/new')}}>新建项目
+ {/* {this.props.history.push('/projects/deposit/new')}}>新建项目 */}
+
+ - {this.props.history.push('/projects/mirror/new')}}>导入项目
+ {/* {this.props.history.push('/projects/mirror/new')}}>导入项目 */}
+
+ {/* -
{this.props.history.push('/projects/deposit/new')}} >新建项目
-
{this.props.history.push('/projects/mirror/new')}}>导入项目
-
+
*/}
);
diff --git a/src/forge/users/Team.jsx b/src/forge/users/Team.jsx
index bb0bf6eeb..788f17f86 100644
--- a/src/forge/users/Team.jsx
+++ b/src/forge/users/Team.jsx
@@ -1,11 +1,12 @@
import React , { useEffect , useState } from 'react';
import { Dropdown, Menu , Pagination } from 'antd';
+import { Link } from 'react-router-dom';
import Search from '../Component/Search';
import Item from './Team-item';
import Nodata from '../Nodata';
import axios from 'axios';
-import CheckProfile from '../Component/ProfileModal/Profile';
+// import CheckProfile from '../Component/ProfileModal/Profile';
const limit = 15;
function Team(props){
@@ -57,7 +58,8 @@ function Team(props){
{
current_user && current_user.login === username &&
- {props.history.push('/organize/new')}}>新建组织
+ // {props.history.push('/organize/new')}}>新建组织
+ 新建组织
}
排序
diff --git a/src/global.scss b/src/global.scss
new file mode 100644
index 000000000..0ee7a6274
--- /dev/null
+++ b/src/global.scss
@@ -0,0 +1,5 @@
+$primary-color: #466aff;
+$primary-color-hover: #6684FE;
+$primary-color-active: #1A47FF;
+$link-color: #466aff;
+$link-black-color: #05101a;
diff --git a/src/home/FifthSection/index.jsx b/src/home/FifthSection/index.jsx
index 18f81b392..a14db69fb 100644
--- a/src/home/FifthSection/index.jsx
+++ b/src/home/FifthSection/index.jsx
@@ -2,7 +2,7 @@ import React, { memo, useState, useEffect } from 'react';
import { Collapse, Button } from 'antd';
import moment from 'moment';
import Line from '../Line';
-import { getTaskCategory, getTaskList } from '../../military/task/api';
+import { getTaskCategory, getRecommendTasks } from '../../military/task/api';
import { taskModeIdArr } from '../../military/task/static';
import './index.scss';
@@ -61,10 +61,9 @@ function FifthSection({ fifth, history }) {
curPage: 1,
pageSize: 3,
orderBy: 'visitsDesc',
- isDelete: '0',
recommend: '1',
};
- getTaskList(params).then(data => {
+ getRecommendTasks(params).then(data => {
if (data) {
serTaskArr(data.rows);
}
diff --git a/src/home/FifthSection/index.scss b/src/home/FifthSection/index.scss
index 53ea59b9a..f68ff481c 100644
--- a/src/home/FifthSection/index.scss
+++ b/src/home/FifthSection/index.scss
@@ -4,7 +4,7 @@ $deg2: -36deg;
$bgcolorlist:#254dea #e33230 #0766fb #f02c66 #6038ff #f85e55 #c13cff #2cb840 #5744f6 #e9862e;
.home-fifth-section {
- min-height: 50vh;
+ // min-height: 50vh;
background: linear-gradient(#fff 0%, #cbdcff 100%);
.fifth-main {
diff --git a/src/home/FirstSection/index.scss b/src/home/FirstSection/index.scss
index f52d53b9e..10a0e929e 100644
--- a/src/home/FirstSection/index.scss
+++ b/src/home/FirstSection/index.scss
@@ -1,5 +1,5 @@
.home-first-section {
- height: 90vh;
+ height: 93vh;
min-height: 650px;
// background: linear-gradient(
// #1a2358 0%,
@@ -32,6 +32,7 @@
align-items: center;
height: 80vh;
min-height: 600px;
+ margin-top: 6vh;
}
.website {
diff --git a/src/home/Footer/index.scss b/src/home/Footer/index.scss
index 9fdf26659..6bc5d0230 100644
--- a/src/home/Footer/index.scss
+++ b/src/home/Footer/index.scss
@@ -57,5 +57,8 @@
.footerbottom {
background-color: #162046 !important;
}
+ .newFooter{
+ top: 20px;
+ }
}
diff --git a/src/home/QzModal/index.jsx b/src/home/QzModal/index.jsx
index 6d26f158e..8c7ccaf2c 100644
--- a/src/home/QzModal/index.jsx
+++ b/src/home/QzModal/index.jsx
@@ -2,8 +2,9 @@ import React, { memo, useEffect, useState } from 'react';
import { Button, Modal } from 'antd';
import { Link } from 'react-router-dom';
-import bg from '../img/modal.png';
-import bg_local from '../img/modal_local.png';
+// import bg from '../img/modal.png';
+import bg from '../img/ckds.jpg';
+// import bg_local from '../img/modal_local.png';
import './index.scss';
@@ -37,9 +38,9 @@ function QzModal() {
width='728px'
maskClosable={false}
>
-
-1?bg_local: bg} />
-
- 查看详情
+ {/*
-1?bg_local: bg} /> */}
+
+ 查看详情
)
}
diff --git a/src/home/QzModal/index.scss b/src/home/QzModal/index.scss
index 94f079590..99ecbf91f 100644
--- a/src/home/QzModal/index.scss
+++ b/src/home/QzModal/index.scss
@@ -6,6 +6,7 @@
img {
border-radius: 2px;
+ width: 100%;
}
}
diff --git a/src/home/SecondSection/index.jsx b/src/home/SecondSection/index.jsx
index 7ddc44568..51b5d9970 100644
--- a/src/home/SecondSection/index.jsx
+++ b/src/home/SecondSection/index.jsx
@@ -43,12 +43,13 @@ function SecondSection({ second ,main_web_site_url ,btnUrl}) {
if (communicates.length) {
setLeftItem(communicates[0]);
setList(communicates.slice(1, 5));
+ // 当社区动态较少时,仅展示一条,其余轮播
+ communicates.length < 5 && (setting.slidesToShow = 1)
}
}
}).catch(error => { });
}, [])
-
function goDetail(id) {
window.open(`${main_web_site_url}/forums/${id}/detail`);
}
diff --git a/src/home/SeventhSection/index.scss b/src/home/SeventhSection/index.scss
index 6982c33fb..eb78a1af1 100644
--- a/src/home/SeventhSection/index.scss
+++ b/src/home/SeventhSection/index.scss
@@ -129,7 +129,7 @@
.slick-list {
width: 33.75em;
margin: 0 auto;
- z-index: 1001;
+ z-index: 999;
}
.issue-item {
text-align: center;
diff --git a/src/home/ThirdSection/index.jsx b/src/home/ThirdSection/index.jsx
index 9109039ec..930588323 100644
--- a/src/home/ThirdSection/index.jsx
+++ b/src/home/ThirdSection/index.jsx
@@ -42,7 +42,7 @@ function ThirdSection({ third }) {
-
+
9999999?'24px':statisticsNum.users_count>99999?'36px':'48px'}}>
diff --git a/src/home/img/ckds.jpg b/src/home/img/ckds.jpg
new file mode 100644
index 000000000..a4813347e
Binary files /dev/null and b/src/home/img/ckds.jpg differ
diff --git a/src/home/index.jsx b/src/home/index.jsx
index 7e879e708..fb8e82353 100644
--- a/src/home/index.jsx
+++ b/src/home/index.jsx
@@ -3,7 +3,7 @@ import { TPMIndexHOC } from '../modules/tpm/TPMIndexHOC';
import { isMobile } from 'educoder';
import './index.scss';
-import Slider from './Slider';
+// import Slider from './Slider';
// import QzModal from './QzModal';
import FirstSection from './FirstSection';
import SecondSection from './SecondSection';
@@ -128,8 +128,8 @@ function HomePage({ history }) {
return (
-
- {/*
*/}
+ {/*
+
*/}
diff --git a/src/home/index.scss b/src/home/index.scss
index 2a1b113cf..8b6e26d9e 100644
--- a/src/home/index.scss
+++ b/src/home/index.scss
@@ -9,6 +9,7 @@
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
+ word-break: break-all;
}
// 2行省略号
.ellipsis-2 {
@@ -106,52 +107,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;
- }
- // 首页特定头部样式止
}
// 波浪样式起
diff --git a/src/managements/api.js b/src/managements/api.js
new file mode 100644
index 000000000..a40c4fb52
--- /dev/null
+++ b/src/managements/api.js
@@ -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;
+}
\ No newline at end of file
diff --git a/src/managements/common/static.js b/src/managements/common/static.js
new file mode 100644
index 000000000..2c056a90f
--- /dev/null
+++ b/src/managements/common/static.js
@@ -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: "待审核" },
+];
+//公告结束
\ No newline at end of file
diff --git a/src/managements/common/utils.js b/src/managements/common/utils.js
new file mode 100644
index 000000000..c1cda7a47
--- /dev/null
+++ b/src/managements/common/utils.js
@@ -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];
+}
\ No newline at end of file
diff --git a/src/managements/competition/competionCustomize/index.jsx b/src/managements/competition/competionCustomize/index.jsx
index 267a03a32..b7bea09ba 100644
--- a/src/managements/competition/competionCustomize/index.jsx
+++ b/src/managements/competition/competionCustomize/index.jsx
@@ -1,4 +1,4 @@
-import { Button, message, Modal, Select, Tooltip,Table } from "antd";
+import { Button, message, Modal, Select, Tooltip,Table, Popconfirm } from "antd";
import React, { useEffect, useMemo, useState } from "react";
import Link from "react-router-dom/Link";
import axios from "axios";
@@ -46,6 +46,15 @@ function Competition(props){
return
{text}
}
},
+ {
+ title: "报名开始时间",
+ dataIndex: "start_at",
+ key: "start_at",
+ align: "center",
+ render: (text, record)=>{
+ return text ? moment(text).format('YYYY-MM-DD HH:mm:ss'): '--'
+ }
+ },
{
title: "报名截止时间",
dataIndex: "enroll_date",
@@ -73,13 +82,24 @@ function Competition(props){
return text?'是':'否'
}
},
+ {
+ title: "排序",
+ dataIndex: "sort_no",
+ key: "sort_no",
+ align: "center",
+ },
{
title: '操作',
dataIndex: 'id',
key: 'action',
- fixed: 'right',
+ align: "center",
render: (text, record)=>{
- return
+ return
+ {confirm(record)}}>
+
+
+ 编辑
+
}
}
];
@@ -97,7 +117,17 @@ function Competition(props){
}).finally(()=>{
setLoading(false);
})
- }, [])
+ }, [reload])
+
+ // 上架/下架竞赛
+ function confirm(record){
+ axios.post(`/competition_infos/${record.identifier}/online_switch.json`).then(res=>{
+ if(res && res.data && !res.data.status){
+ setReload(Math.random());
+ message.success('修改成功');
+ }
+ })
+ }
return(
diff --git a/src/managements/competition/setting/index.jsx b/src/managements/competition/setting/index.jsx
index c611588f3..df30ecd96 100644
--- a/src/managements/competition/setting/index.jsx
+++ b/src/managements/competition/setting/index.jsx
@@ -1,5 +1,5 @@
import React, { useEffect, useState, useCallback, useRef } from "react";
-import { Input, Row, Col, Button, Form, message, Spin, Checkbox, DatePicker, Upload, Icon } from 'antd';
+import { Input, Row, Col, Button, Form, message, Spin, Checkbox, DatePicker, Upload, Icon,InputNumber } from 'antd';
import axios from "axios";
import moment from 'moment';
import MDEditor from 'src/modules/tpm/challengesnew/tpm-md-editor';
@@ -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(() => {
@@ -35,6 +38,7 @@ export default Form.create()(({ form, match, history, current_user, showNotifica
identifier: details.identifier,
content: details.content,
banner_url: details.banner_url,
+ applet_banner_url: details.applet_banner_url,
video_url: details.video_url,
enroll_template: details.enroll_template,
guide: details.guide,
@@ -42,35 +46,46 @@ export default Form.create()(({ form, match, history, current_user, showNotifica
zones_local: details.zones_local,
sub_competitions: details.sub_competitions,
zones: details.zones,
+ start_at: moment(details.start_at),
enroll_date: moment(details.enroll_date),
upload_date: moment(details.upload_date),
about_us: details.about_us,
- enroll_columns:details.enroll_columns
+ enroll_columns:details.enroll_columns,
+ sort_no:details.sort_no
// 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);
})
+ }else{
+ setTimeout(() => {
+ setContentMd(true);
+ }, 200);
+ setTimeout(() => {
+ setGuideMd(true);
+ }, 300);
}
}, [id])
@@ -125,6 +140,10 @@ export default Form.create()(({ form, match, history, current_user, showNotifica
setFieldsValue({
[key]: `/api/attachments/${info.file.response.id}`
})
+ } else if (key === 'applet_banner_url') {
+ setFieldsValue({
+ [key]: `/api/attachments/${info.file.response.id}`
+ })
}
}
}
@@ -191,6 +210,11 @@ export default Form.create()(({ form, match, history, current_user, showNotifica
{ verify("identifier") }} />
)}
+ {helper('排序号',
+ 'sort_no',
+ [{ required: true, message: "请正确输入排序号" }],
+
+ )}
@@ -212,6 +236,26 @@ export default Form.create()(({ form, match, history, current_user, showNotifica
+
+
+
+ {getFieldDecorator('applet_banner_url', {
+ rules: [],
+ })( { verify("video_url") }} />)}
+
+
+ { handleChange(info, 'applet_banner_url') }}
+ showUploadList={false}
+ >
+
+
+
+
+
+
@@ -252,7 +296,6 @@ export default Form.create()(({ form, match, history, current_user, showNotifica
-
{helper('赛项',
'sub_competitions',
[{ required: true, message: "请填写赛项" }],
@@ -260,6 +303,17 @@ export default Form.create()(({ form, match, history, current_user, showNotifica
'请填写赛项,每个赛项之间以英文“,”隔开。如:赛项1,赛项2,赛项3'
)}
+ {helper(
+ "报名开始时间",
+ "start_at",
+ [],
+
+ )}
+
{helper(
"报名截止时间",
"enroll_date",
@@ -296,14 +350,14 @@ export default Form.create()(({ form, match, history, current_user, showNotifica
{helper('赛区(内网)',
'zones_local',
[{ required: true, message: "请填写赛区,每个赛区之间以英文“,”隔开。如:赛区1,赛区2,赛区3" }],
- { verify("zones_local") }} onBlur={zonesChange} />,
+ ,
'请填写赛区,每个赛区之间以英文“,”隔开。如:赛区1,赛区2,赛区3'
)}
{helper('赛区(外网)',
'zones',
[{ required: true, message: "请填写赛区,每个赛区之间以英文“,”隔开。如:赛区1,赛区2,赛区3" }],
- { verify("zones") }} onBlur={zonesChange} />,
+ ,
'请填写赛区,每个赛区之间以英文“,”隔开。如:赛区1,赛区2,赛区3'
)}
@@ -315,26 +369,26 @@ export default Form.create()(({ form, match, history, current_user, showNotifica
- { onContentChange(value, 'content') }}
- />
+ />}
{getFieldDecorator("content", {
rules: [{ required: true, message: "请输入大赛介绍" }],
})()}
- { onContentChange(value, 'guide') }}
- />
+ />}
{getFieldDecorator("guide", {
rules: [{ required: true, message: "请输入赛事指南" }],
})()}
diff --git a/src/managements/competition/setting/index.scss b/src/managements/competition/setting/index.scss
index b694efb23..8ced7375b 100644
--- a/src/managements/competition/setting/index.scss
+++ b/src/managements/competition/setting/index.scss
@@ -28,4 +28,7 @@
.ant-form-explain+.ant-form-extra{
display: none !important;
}
+ .ant-input-number{
+ width: 200px;
+ }
}
\ No newline at end of file
diff --git a/src/managements/components/DelModal.jsx b/src/managements/components/DelModal.jsx
new file mode 100644
index 000000000..b2ba4434b
--- /dev/null
+++ b/src/managements/components/DelModal.jsx
@@ -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();
+ }
+ });
+}
\ No newline at end of file
diff --git a/src/managements/components/EchartBar/index.jsx b/src/managements/components/EchartBar/index.jsx
new file mode 100644
index 000000000..0f91c59ea
--- /dev/null
+++ b/src/managements/components/EchartBar/index.jsx
@@ -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 (
+
+
+ )
+}
\ No newline at end of file
diff --git a/src/managements/components/EchartLine/index.jsx b/src/managements/components/EchartLine/index.jsx
new file mode 100644
index 000000000..4b5d1349e
--- /dev/null
+++ b/src/managements/components/EchartLine/index.jsx
@@ -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 (
+
+
+ )
+}
\ No newline at end of file
diff --git a/src/managements/components/ShowNotification.jsx b/src/managements/components/ShowNotification.jsx
new file mode 100644
index 000000000..aa76e04d3
--- /dev/null
+++ b/src/managements/components/ShowNotification.jsx
@@ -0,0 +1,8 @@
+import { notification } from 'antd';
+
+export default (message)=>{
+ notification.open({
+ message: "提示",
+ description: message,
+ });
+}
\ No newline at end of file
diff --git a/src/managements/components/Upload.jsx b/src/managements/components/Upload.jsx
new file mode 100644
index 000000000..a16768fb3
--- /dev/null
+++ b/src/managements/components/Upload.jsx
@@ -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 (
+
+
+ (你可以上传小于{size}MB的文件)
+
+ )
+}
+export default Uploads;
\ No newline at end of file
diff --git a/src/managements/components/layouts/config.js b/src/managements/components/layouts/config.js
new file mode 100644
index 000000000..30379d832
--- /dev/null
+++ b/src/managements/components/layouts/config.js
@@ -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: [],
+ },
+ ],
+ },
+];
diff --git a/src/managements/components/layouts/index.jsx b/src/managements/components/layouts/index.jsx
new file mode 100644
index 000000000..32923efdf
--- /dev/null
+++ b/src/managements/components/layouts/index.jsx
@@ -0,0 +1,198 @@
+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 = (
+
+ {item.icon && }
+ {item.title}
+
+ );
+ if (Array.isArray(item.children) && item.children.length > 0) {
+ return (
+ {getMenuList(item.children)}
+ );
+ } else {
+ return (
+
+ {item.location ? { itemClick(item) }}>{title}
+ : title}
+
+ );
+ }
+ }
+ });
+ }
+
+ function head(keyPath) {
+ return keyPath ? keyPath.map((i, index) => {
+ return {titleObj[i]}{index !== keyPath.length - 1 && ' / '}
+ }) : ''
+ }
+
+ 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 (
+
+
+
+
+
+
{head(keyPath)}
+ {/* 如果不是react的新后端,那就用iframe打开 */}
+ {acitve && acitve.urlType && acitve.urlType !== 'self' ?
+
+ : children
+ }
+
+
+ );
+};
diff --git a/src/managements/components/layouts/index.scss b/src/managements/components/layouts/index.scss
new file mode 100644
index 000000000..e5cc64d50
--- /dev/null
+++ b/src/managements/components/layouts/index.scss
@@ -0,0 +1,68 @@
+.layouts {
+ position: fixed;
+ top: 70px;
+ left: 0;
+ width: 13.75rem;
+ height: calc(100vh - 70px);
+ padding-bottom: 5vh;
+ 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;
+ }
+}
diff --git a/src/managements/fetch.js b/src/managements/fetch.js
new file mode 100644
index 000000000..cd96a228b
--- /dev/null
+++ b/src/managements/fetch.js
@@ -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;
\ No newline at end of file
diff --git a/src/managements/index.js b/src/managements/index.js
new file mode 100644
index 000000000..9d5c0669f
--- /dev/null
+++ b/src/managements/index.js
@@ -0,0 +1,355 @@
+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 GatheringList = Loadable({
+ loader: () => import("./needApply/list"),
+ loading: Loading,
+})
+
+const Managements = (propsF) => {
+ useEffect(()=>{
+ const {current_user, history} = propsF;
+ if(current_user && current_user.login){
+ if(!current_user.admin){
+ history.push('/403')
+ }
+ }else{
+ propsF.showLoginDialog();
+ }
+ },[])
+
+ return (
+
+
+
+ {/* 需求申请列表 */}
+ (
+
+ )}
+ >
+ {/* 概览 */}
+ (
+
+ )}
+ >
+
+ {/* 任务管理审核 */}
+ (
+
+ )}
+ >
+
+ {/* 成果管理审核 */}
+ (
+
+ )}
+ >
+
+ {/* 成果申诉管理审核 */}
+ (
+
+ )}
+ >
+
+ {/* 公示期成果申诉管理审核 */}
+ (
+
+ )}
+ >
+
+ {/* 佐证管理审核 */}
+ (
+
+ )}
+ >
+
+ {/* 管理员协议审核 */}
+ (
+
+ )}
+ >
+
+ {/* 管理员上传支付凭证 */}
+ (
+
+ )}
+ >
+
+ {/* 管理员任务列表 */}
+ (
+
+ )}
+ >
+
+ {/* 延期管理 */}
+ (
+
+ )}
+ >
+
+ {/* 协议内容 */}
+ (
+
+ )}
+ >
+
+ {/* 专家审核 */}
+ (
+
+ )}
+ >
+ {/* 专家库列表 */}
+ (
+
+ )}
+ >
+ {/* 创客任务评审规则 */}
+ (
+
+ )}
+ >
+ {/* 创客任务选择评审专家 */}
+ (
+
+ )}
+ >
+ {/* 创客任务评审结果查看 */}
+ (
+
+ )}
+ >
+ {/* 竞赛评审任务列表 */}
+ (
+
+ )}
+ >
+ {/* 非普通用户(管理员)列表 */}
+ (
+
+ )}
+ >
+ {/* 系统角色列表 */}
+ (
+
+ )}
+ >
+ {/* 菜单列表 */}
+ (
+
+ )}
+ >
+
+ {/* 公告管理 */}
+ (
+
+ )}
+ >
+
+ {/* 定制竞赛配置详情 */}
+ (
+
+ )}
+ >
+ (
+
+ )}
+ >
+ {/* 定制竞赛配置列表 */}
+ (
+
+ )}
+ >
+
+
+
+ );
+}
+
+export default withRouter(
+ ImageLayerOfCommentHOC({
+ imgSelector: ".imageLayerParent img, .imageLayerParent .imageTarget",
+ parentSelector: ".newMain",
+ })(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(Managements,{noFooter:true}))))
+);
diff --git a/src/managements/index.scss b/src/managements/index.scss
new file mode 100644
index 000000000..bf6ea144f
--- /dev/null
+++ b/src/managements/index.scss
@@ -0,0 +1,94 @@
+.managementMain{
+ padding:0;
+}
+.managements{
+ margin-left: 13.75rem;
+ padding:0 1.875rem 1.6rem;
+ background: #f6f9fe;
+ min-height: calc(100vh - 70px);
+ .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 );
+ }
+}
\ No newline at end of file
diff --git a/src/managements/jurisdiction/index.scss b/src/managements/jurisdiction/index.scss
new file mode 100644
index 000000000..f1e12ea16
--- /dev/null
+++ b/src/managements/jurisdiction/index.scss
@@ -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;
+ }
+ }
\ No newline at end of file
diff --git a/src/managements/jurisdiction/menuList/index.jsx b/src/managements/jurisdiction/menuList/index.jsx
new file mode 100644
index 000000000..cc685379e
--- /dev/null
+++ b/src/managements/jurisdiction/menuList/index.jsx
@@ -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) => (
+
+ {getFieldDecorator(name, { rules, initialValue, validateFirst: true, })(widget)}
+
+ ), []);
+
+ 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 changeMenuStatus(checked, record.key)}/>
+ }
+ },
+ {
+ title: '操作',
+ key: 'action',
+ dataIndex: 'key',
+ align: 'center',
+ render: (text, record) => {
+ return(
+
+
+ deleteMenuById(text)}>
+
+
+
+ )},
+ },
+ ]
+ }, [curPage, reload]);
+
+ const menuDetail =(
+
+ {helper(
+ "菜单名称",
+ "menuName",
+ [{ max: 20, message: '长度不能超过20个字符' },{required: true, message: "菜单名称不能为空"}],
+
+ )}
+ {helper(
+ "上级菜单",
+ "parentKey",
+ [],
+ setTreeSelectValue(value)}
+ />,
+ )}
+ {helper(
+ "路由",
+ "location",
+ [{ max: 100, message: '长度不能超过100个字符' }],
+
+ )}
+ {helper(
+ "前端图标",
+ "icon",
+ [{ max: 100, message: '长度不能超过100个字符' }],
+
+ )}
+ {helper(
+ "是否显示",
+ "hidden",
+ [],
+
+ 是
+ 否
+ ,
+ )}
+ {helper(
+ "环境",
+ "urlType",
+ [],
+ ,
+ )}
+
+ )
+
+ //菜单是否启用
+ 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 (
+
+
+
菜单列表
+
+
+ setMenuDetailModal(false)}/>
+ setEditMenuModal(false)}/>
+
+
+
+
row.key}
+ dataSource={dataList}
+ columns={columns}
+ total={total}
+ current={curPage}
+ setCurPage={(page)=>{setCurPage(page)}}
+ className="expertReviewTable"
+ indentSize={30}
+ />
+
+
+ )
+})
\ No newline at end of file
diff --git a/src/managements/jurisdiction/menuList/index.scss b/src/managements/jurisdiction/menuList/index.scss
new file mode 100644
index 000000000..eba0f9f10
--- /dev/null
+++ b/src/managements/jurisdiction/menuList/index.scss
@@ -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;
+}
\ No newline at end of file
diff --git a/src/managements/jurisdiction/roles/index.jsx b/src/managements/jurisdiction/roles/index.jsx
new file mode 100644
index 000000000..4b2fb375d
--- /dev/null
+++ b/src/managements/jurisdiction/roles/index.jsx
@@ -0,0 +1,300 @@
+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 = [];
+ // 二级菜单项
+ let twoTree = [];
+
+ const helper = useCallback(
+ (label, name, rules, widget, initialValue) => (
+
+ {getFieldDecorator(name, { rules, initialValue, validateFirst: true, })(widget)}
+
+ ), []);
+
+ 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 changeRoleStatus(checked, record.id)}/>
+ // }
+ // },
+ {
+ title: '操作',
+ key: 'action',
+ dataIndex: 'id',
+ align: 'center',
+ render: (text, record) => {
+ return(
+
+
+
+ deleteRoleById(text)}>
+
+
+
+ )},
+ },
+ ]
+ }, [curPage]);
+
+ const roleDetail =(
+
+ {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();
+ }}],
+
+ )}
+ {helper(
+ "描述",
+ "description",
+ [{ max: 500, message: '长度不能超过500个字符'}],
+
+ )
+
+ const menuTree = (
+ {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 || twoTree.indexOf(item.key.toString()) !== -1) ? null : item.key.toString()
+ });
+ 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'){
+ // 遍历菜单数组找到所有的一级、二级菜单项(原因: antd tree checkedKeys属性如果包含了上级菜单,下级菜单默认是勾选的)
+ response.data.map(item=>{
+ oneTree.push(item.key.toString())
+ if(item.children && item.children.length){
+ item.children.map(i =>{
+ if(i.children && i.children.length){
+ twoTree.push(i.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 (
+
+
+
角色列表
+
+
+ setRoleDetailModal(false)}/>
+ setEditRoleModal(false)}/>
+ setMenuModal(false)}/>
+
+
+
+
row.id}
+ dataSource={dataList}
+ columns={columns}
+ total={total}
+ current={curPage}
+ setCurPage={(page)=>{setCurPage(page)}}
+ className="expertReviewTable"
+ />
+
+
+ )
+})
\ No newline at end of file
diff --git a/src/managements/jurisdiction/roles/index.scss b/src/managements/jurisdiction/roles/index.scss
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/managements/jurisdiction/userList/index.jsx b/src/managements/jurisdiction/userList/index.jsx
new file mode 100644
index 000000000..21159a164
--- /dev/null
+++ b/src/managements/jurisdiction/userList/index.jsx
@@ -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) => (
+
+ {getFieldDecorator(name, { rules, initialValue, validateFirst: true, })(widget)}
+
+ ), []);
+
+ 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(
+
+ )},
+ },
+ ]
+ }, [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 (
+
+
+
+
row.id}
+ dataSource={dataList}
+ columns={columns}
+ total={total}
+ current={curPage}
+ setCurPage={(page)=>{setCurPage(page)}}
+ className="expertReviewTable"
+ />
+
+
+ )
+})
\ No newline at end of file
diff --git a/src/managements/jurisdiction/userList/index.scss b/src/managements/jurisdiction/userList/index.scss
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/managements/needApply/api.js b/src/managements/needApply/api.js
new file mode 100644
index 000000000..30c41c31e
--- /dev/null
+++ b/src/managements/needApply/api.js
@@ -0,0 +1,94 @@
+import fetch from '../fetch';
+import showNotification from '../components/ShowNotification';
+
+//提交开源项目托管申请
+export function projectsGathering(data) {
+ return fetch({
+ url: '/api/projectsGathering/create',
+ method: 'post',
+ data: data
+ });
+}
+
+//提交开源项目托管申请
+export function tasksGathering(data) {
+ return fetch({
+ url: '/api/tasksGathering/create',
+ method: 'post',
+ data: data
+ });
+}
+
+//提交开放竞赛申请
+export function competitionGathering(data) {
+ return fetch({
+ url: '/api/competitionGathering/create',
+ method: 'post',
+ data: data
+ });
+}
+
+//提交成果转化申请
+export function achievementTransformGathering(data) {
+ return fetch({
+ url: '/api/achievementTransformGathering/create',
+ method: 'post',
+ data: data
+ });
+}
+
+// 开源项目托管申请列表
+export async function projectsGatheringList(params) {
+ let res = await fetch({
+ url: '/api/projectsGathering/list',
+ method: 'get',
+ params
+ });
+ if (res.data) {
+ return res.data;
+ } else {
+ showNotification(res.message || '请求错误');
+ }
+}
+
+// 创客任务申请列表
+export async function tasksGatheringList(params) {
+ let res = await fetch({
+ url: '/api/tasksGathering/list',
+ method: 'get',
+ params
+ });
+ if (res.data) {
+ return res.data;
+ } else {
+ showNotification(res.message || '请求错误');
+ }
+}
+
+// 开放竞赛申请列表
+export async function competitionGatheringList(params) {
+ let res = await fetch({
+ url: '/api/competitionGathering/list',
+ method: 'get',
+ params
+ });
+ if (res.data) {
+ return res.data;
+ } else {
+ showNotification(res.message || '请求错误');
+ }
+}
+
+// 成果转化申请列表
+export async function achievementTransformGatheringList(params) {
+ let res = await fetch({
+ url: '/api/achievementTransformGathering/list',
+ method: 'get',
+ params
+ });
+ if (res.data) {
+ return res.data;
+ } else {
+ showNotification(res.message || '请求错误');
+ }
+}
\ No newline at end of file
diff --git a/src/managements/needApply/index.jsx b/src/managements/needApply/index.jsx
new file mode 100644
index 000000000..9abf641b7
--- /dev/null
+++ b/src/managements/needApply/index.jsx
@@ -0,0 +1,279 @@
+import React , { useEffect , useState, forwardRef, useCallback} from 'react';
+import { Form, Input, Radio, Select, Upload, Button, message, Modal } from 'antd';
+import {TPMIndexHOC} from '../../modules/tpm/TPMIndexHOC';
+import {httpUrl} from '../fetch.js';
+import {projectsGathering, tasksGathering, competitionGathering, achievementTransformGathering} from './api';
+import {getTaskCategory} from '../../military/task/api'
+import './index.scss';
+
+function NeedApply(props){
+ const {form, history, showNotification} = props;
+ const { getFieldDecorator} = form;
+ const [activeType, setActiveType] = useState(1);
+ const [visible, setVisible] = useState(false);
+ const [taskCategoryValueArr, setTaskCategoryValueArr] = useState([]);
+ const [fileList, setFileList] = useState(undefined);
+
+ // 获取任务领域数组
+ useEffect(() => {
+ getTaskCategory().then(data => {
+ if (data) {
+ const taskCategoryValueArr = [];
+ for (const item of data) {
+ taskCategoryValueArr[item.id] = item.name;
+ }
+ setTaskCategoryValueArr(taskCategoryValueArr);
+ }
+ });
+ }, []);
+
+ const helper = useCallback((label, name, rules, initialValue, widget, className) => (
+
+ {getFieldDecorator(name, { rules, validateFirst: true, initialValue: initialValue})(widget)}
+
+ ), []);
+
+ const upload = {
+ name: 'file',
+ action: `${httpUrl}/busiAttachments/upload`,
+ fileList,
+ onChange: handleChange,
+ beforeUpload: beforeUpload
+ };
+
+ // 只能上传一个文件
+ function handleChange(info) {
+ if (info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') {
+ const fileList = info.fileList.slice(-1);
+ setFileList(fileList);
+ }
+ }
+
+ // 文件大小限制100m
+ function beforeUpload(file) {
+ const isLt100M = file.size / 1024 / 1024 < 100;
+ if (!isLt100M) {
+ showNotification(`文件大小必须小于${100}MB!`);
+ }
+ return isLt100M;
+ }
+
+ // 表单提交确认按钮
+ function handleSubmit(e){
+ e.preventDefault();
+ form.validateFields((err, values) => {
+ if (!err) {
+ setVisible(true);
+ }
+ })
+ }
+
+ // 表单提交
+ function submit(){
+ form.validateFields((err, values) => {
+ if (!err) {
+ const {type} = values;
+ switch (type) {
+ case 1:
+ projectsGathering(values).then(res=>{
+ if(res && res.message === "success"){
+ setVisible(false);
+ message.success("提交成功");
+ setTimeout(()=>{
+ history.goBack();
+ }, 1000)
+ }
+ })
+ break;
+ case 2:
+ const {assignmentBook1} = values;
+ const assignmentBook = assignmentBook1 && assignmentBook1.file && assignmentBook1.file.response.data.id;
+ values.assignmentBook = assignmentBook;
+ tasksGathering(values).then(res=>{
+ if(res && res.message === "success"){
+ setVisible(false);
+ message.success("提交成功");
+ setTimeout(()=>{
+ history.goBack();
+ }, 1000)
+ }
+ })
+ break;
+ case 3:
+ const {competitionProposal1} = values;
+ const competitionProposal = competitionProposal1 && competitionProposal1.file && competitionProposal1.file.response.data.id;
+ values.competitionProposal = competitionProposal;
+ competitionGathering(values).then(res=>{
+ if(res && res.message === "success"){
+ setVisible(false);
+ message.success("提交成功");
+ setTimeout(()=>{
+ history.goBack();
+ }, 1000)
+ }
+ })
+ break;
+ default:
+ const {achievementMaterial1} = values;
+ const achievementMaterial = achievementMaterial1 && achievementMaterial1.file && achievementMaterial1.file.response.data.id;
+ values.achievementMaterial = achievementMaterial;
+ achievementTransformGathering(values).then(res=>{
+ if(res && res.message === "success"){
+ setVisible(false);
+ message.success("提交成功");
+ setTimeout(()=>{
+ history.goBack();
+ }, 1000)
+ }
+ })
+ }
+ }
+ })
+ }
+
+ return
+
+
需求申请
+
+
申请说明:
1、您可根据不同需求类型进行需求申请;
2、管理员在后台查看到您提交的需求申请后,将通过申请的联系方式与您沟通,请您随时留意;
+
+
+
+
+
+
+
+
{setVisible(false)}} onOk={submit} className="confirmModalBox">
+ !您确认提交需求申请吗?
+ 提交后,管理员将查看到您的申请信息,并及时与您联系。
+
+
+}
+export default TPMIndexHOC(Form.create()(forwardRef(NeedApply)));
\ No newline at end of file
diff --git a/src/managements/needApply/index.scss b/src/managements/needApply/index.scss
new file mode 100644
index 000000000..b2134cc87
--- /dev/null
+++ b/src/managements/needApply/index.scss
@@ -0,0 +1,109 @@
+.backgroundBox{
+ padding-top: 30px;
+ background-color:#f6f9fe;
+}
+.needApplyBox{
+ width:1200px;
+ margin: 0 auto 80px;
+ background-color:#ffffff;
+ box-shadow:0px 0px 12px rgba(217, 236, 255, 0.76);
+ .titleBox{
+ color:#1e2941;
+ background-color:#d9e3ff;
+ text-align: center;
+ padding: 2px 0;
+ }
+ .tipBox{
+ background-color:#fafcff;
+ border:1px solid rgba(42, 97, 255, 0.23);
+ border-radius:3px 3px 0px 0px;
+ color:#3f4f7b;
+ padding: 8px 12px;
+ }
+}
+.needContent{
+ margin: 20px 30px;
+}
+.gatheringForm{
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: space-between;
+ .gathering.ant-row{
+ margin-bottom: 10px;
+ }
+}
+.gathering{
+ width: 48.5%;
+ &.oneLine{
+ width: 100%;
+ }
+ .ant-input:hover, .ant-input-affix-wrapper:hover .ant-input:not(.ant-input-disabled){
+ border-color:#104fd9;
+ }
+ &.errorBox .has-error .ant-form-explain{
+ margin-top: 3px;
+ }
+}
+.gatheringForm .ant-form-item.gatheringButBox{
+ width: 100%;
+ text-align: center;
+ padding: 20px 0 30px;
+ .ant-btn {
+ border-radius: 5px;
+ }
+}
+.confirmModalBox{
+ color:#333333;
+ .ant-modal-close{top: 0px !important;}
+ .ant-modal-header{
+ background-color:#f8f8f8;
+ padding: 10px 24px;
+ }
+ .ant-modal-footer{
+ border-top: none;
+ text-align: center;
+ padding-bottom: 50px;
+ }
+ .ant-modal-title{
+ text-align: left;
+ color:#333333;
+ font-size:13px;
+ font-weight: normal !important;
+ }
+ .redSpanBox{
+ display: inline-block;
+ width:36px;
+ height:36px;
+ border-radius: 50%;
+ line-height: 36px;
+ text-align: center;
+ background-color:#ca0002;
+ border:1.5px solid #ca0002;
+ color: white;
+ }
+ .contBox{
+ color:#666;
+ padding: 30px 0 20px 70px;
+ }
+ .ant-btn{
+ width: 104px;
+ height: 36px;
+ border-radius:4px;
+ }
+}
+.uploadGaBox{
+ display: flex;
+ .ant-upload-list{
+ margin-left: 30px;
+ }
+ .ant-upload-list-item-name{
+ color: #104fd9;
+ }
+ .ant-upload-list-item:hover .ant-upload-list-item-info{
+ background-color: white;
+ }
+ .ant-upload-list-item-card-actions {
+ right: -30px;
+ &:hover .anticon-delete{color: #104fd9;}
+ }
+}
\ No newline at end of file
diff --git a/src/managements/needApply/list.jsx b/src/managements/needApply/list.jsx
new file mode 100644
index 000000000..fa9c67d83
--- /dev/null
+++ b/src/managements/needApply/list.jsx
@@ -0,0 +1,333 @@
+import React , { useEffect, useState, useMemo} from 'react';
+import { Input, Select, Tooltip} from 'antd';
+import {httpUrl} from '../fetch.js';
+import {projectsGatheringList, tasksGatheringList, competitionGatheringList, achievementTransformGatheringList} from './api';
+import PaginationTable from 'src/components/pagination-table';
+import './index.scss';
+
+const fundingObj={
+ '1':'自行携带经费',
+ '2':'红山开源平台提供经费'
+};
+// 管理员查看需求申请列表页面
+function List(props){
+ const [loading, setLoading] = useState(false);
+ const [curPage, setCurPage] = useState(1);
+ const [total, setTotal] = useState(0);
+ const [type, setType] = useState(1);
+ const [search, setSearch] = useState(undefined);
+ const [list, setList] = useState([]);
+
+ useEffect(()=>{
+ setLoading(true);
+ const params = {
+ curPage,
+ keyword: search,
+ pageSize: 10
+ }
+ switch (type) {
+ case 1:
+ projectsGatheringList(params).then(res=>{
+ setList(res.rows);
+ setTotal(res.total);
+ setLoading(false);
+ })
+ break;
+ case 2:
+ tasksGatheringList(params).then(res=>{
+ setList(res.rows);
+ setTotal(res.total);
+ setLoading(false);
+ })
+ break;
+ case 3:
+ competitionGatheringList(params).then(res=>{
+ setList(res.rows);
+ setTotal(res.total);
+ setLoading(false);
+ })
+ break;
+ default:
+ achievementTransformGatheringList(params).then(res=>{
+ setList(res.rows);
+ setTotal(res.total);
+ setLoading(false);
+ })
+ }
+ },[type, search, curPage])
+
+ // 开源项目
+ const columns = useMemo(() => {
+ switch(type){
+ case 1: return [
+ {
+ title: '组织名称',
+ dataIndex: 'organizationName',
+ width: '10%',
+ ellipsis: true,
+ render: (text, record) => {return {text || '--'}}
+ },
+ {
+ title: '项目名称',
+ dataIndex: 'projectName',
+ width: '12%',
+ ellipsis: true,
+ render: (text, record) => {return {text}}
+ },
+ {
+ title: '项目简介',
+ dataIndex: 'projectDescription',
+ width: '15%',
+ ellipsis: true,
+ render: (text, record) => {return {text}}
+ },
+ {
+ title: '项目总数',
+ dataIndex: 'projectTotal',
+ width: '6%',
+ ellipsis: true,
+ render: (text, record) => {return {text || '--'}}
+ },
+ {
+ title: '仓库地址',
+ dataIndex: 'repoUrl',
+ width: '16%',
+ ellipsis: true,
+ render: (text, record) => {
+ return {window.open(text)}}>{text}
+ }
+ },
+ {
+ title: '详细需求',
+ dataIndex: 'requirementDetail',
+ width: '20%',
+ ellipsis: true,
+ render: (text, record) => {return {text}}
+ },
+ {
+ title: '联系人',
+ dataIndex: 'contacts',
+ width: '8%',
+ ellipsis: true,
+ render: (text, record) => {return {text}}
+ },
+ {
+ title: '联系方式',
+ dataIndex: 'contactDetail',
+ ellipsis: true,
+ render: (text, record) => {return {text}}
+ },
+ ]
+ case 2: return [
+ {
+ title: '发布人',
+ dataIndex: 'applicant',
+ width: '10%',
+ ellipsis: true,
+ render: (text, record) => {return {text}}
+ },
+ {
+ title: '所属领域',
+ dataIndex: 'taskCategory',
+ width: '10%',
+ ellipsis: true,
+ render: (text, record) => {return {text}}
+ },
+ {
+ title: '任务简介',
+ dataIndex: 'taskDescription',
+ width: '20%',
+ ellipsis: true,
+ render: (text, record) => {return {text}}
+ },
+ {
+ title: '悬赏金额',
+ dataIndex: 'rewards',
+ width: '12%',
+ ellipsis: true,
+ render: (text, record) => {return {text}}
+ },
+ {
+ title: '悬赏金额来源',
+ dataIndex: 'fundingSource',
+ width: '10%',
+ ellipsis: true,
+ render: (text, record) => {return {fundingObj[text]}}
+ },
+ {
+ title: '联系人',
+ dataIndex: 'contacts',
+ width: '12%',
+ ellipsis: true,
+ render: (text, record) => {return {text}}
+ },
+ {
+ title: '联系方式',
+ dataIndex: 'contactDetail',
+ width: '12%',
+ ellipsis: true,
+ render: (text, record) => {return {text}}
+ },
+ {
+ title: '任务书',
+ dataIndex: 'assignmentBookAttachments',
+ ellipsis: true,
+ render: (text, record) => {return text ? {text[0].fileName} : '--'}
+ },
+ ]
+ case 3: return [
+ {
+ title: '竞赛名称',
+ dataIndex: 'competitionName',
+ width: '12%',
+ ellipsis: true,
+ render: (text, record) => {return {text}}
+ },
+ {
+ title: '竞赛主办方',
+ dataIndex: 'competitionOrganizer',
+ width: '12%',
+ ellipsis: true,
+ render: (text, record) => {return {text}}
+ },
+ {
+ title: '竞赛目标用户',
+ dataIndex: 'competitionTargetUser',
+ width: '12%',
+ ellipsis: true,
+ render: (text, record) => {return {text}}
+ },
+ {
+ title: '竞赛所属领域',
+ dataIndex: 'competitionCategory',
+ width: '12%',
+ ellipsis: true,
+ render: (text, record) => {
+ return {text}
+ }
+ },
+ {
+ title: '竞赛内容简介',
+ dataIndex: 'competitionDescription',
+ width: '12%',
+ ellipsis: true,
+ render: (text, record) => {
+ return {text}
+ }
+ },
+ {
+ title: '联系人',
+ dataIndex: 'contacts',
+ width: '12%',
+ ellipsis: true,
+ render: (text, record) => {return {text}}
+ },
+ {
+ title: '联系方式',
+ dataIndex: 'contactDetail',
+ width: '12%',
+ ellipsis: true,
+ render: (text, record) => {return {text}}
+ },
+ {
+ title: '策划书',
+ dataIndex: 'competitionProposalAttachments',
+ ellipsis: true,
+ render: (text, record) => {return text ? {text[0].fileName} : '--'}
+ },
+ ]
+ default: return [
+ {
+ title: '成果名称',
+ dataIndex: 'achievementName',
+ width: '12%',
+ ellipsis: true,
+ render: (text, record) => {return {text}}
+ },
+ {
+ title: '所属人名称',
+ dataIndex: 'achievementOwner',
+ width: '12%',
+ ellipsis: true,
+ render: (text, record) => {return {text}}
+ },
+ {
+ title: '所属领域',
+ dataIndex: 'achievementCategory',
+ width: '12%',
+ ellipsis: true,
+ render: (text, record) => {return {text}}
+ },
+ {
+ title: '成果简介',
+ dataIndex: 'achievementDescription',
+ width: '12%',
+ ellipsis: true,
+ render: (text, record) => {
+ return {text}
+ }
+ },
+ {
+ title: '成果转化金额',
+ dataIndex: 'achievementRewards',
+ width: '12%',
+ ellipsis: true,
+ render: (text, record) => {return {text}}
+ },
+ {
+ title: '联系人',
+ dataIndex: 'contacts',
+ width: '12%',
+ ellipsis: true,
+ render: (text, record) => {return {text}}
+ },
+ {
+ title: '联系方式',
+ dataIndex: 'contactDetail',
+ width: '12%',
+ ellipsis: true,
+ render: (text, record) => {return {text}}
+ },
+ {
+ title: '成果证明材料',
+ dataIndex: 'achievementMaterialAttachments',
+ ellipsis: true,
+ render: (text, record) => {return text ? {text[0].fileName} : '--'}
+ },
+ ]
+ }
+ }, [list]);
+
+ return
+
+
需求申请列表
+
+ {setCurPage(1);setSearch(e)}} enterButton style={{width: '350px'}} className='mr30' allowClear/>
+
+
+
+
row.id}
+ dataSource={list}
+ columns={columns}
+ total={total}
+ current={curPage}
+ setCurPage={(page)=>{setCurPage(page)}}
+ pageSize={10}
+ className="expertReviewTable"/>
+
+}
+export default List;
\ No newline at end of file
diff --git a/src/managements/notice/api.js b/src/managements/notice/api.js
new file mode 100644
index 000000000..b04d90dc7
--- /dev/null
+++ b/src/managements/notice/api.js
@@ -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 || '请求错误');
+ }
+}
+
diff --git a/src/managements/notice/index.css b/src/managements/notice/index.css
new file mode 100644
index 000000000..a7b79a1a4
--- /dev/null
+++ b/src/managements/notice/index.css
@@ -0,0 +1,42 @@
+.notice-content {
+ min-height: 50vh;
+ margin: 1em;
+ background: #fff;
+ border-radius: 1em;
+ box-shadow: 0 1px 2px #d9d9d9;
+ padding-bottom: 1vh;
+}
+
+.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;
+}
\ No newline at end of file
diff --git a/src/managements/notice/index.jsx b/src/managements/notice/index.jsx
new file mode 100644
index 000000000..6a6dff487
--- /dev/null
+++ b/src/managements/notice/index.jsx
@@ -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 (
+
+ {/* 公告列表 */}
+ (
+
+ )}
+ >
+ {/* 公告详情 */}
+ (
+
+ )}
+ >
+ {/* 公告编辑 */}
+ (
+
+ )}
+ >
+ {/* 公告新增 */}
+ (
+
+ )}
+ >
+ {/* 公告预览 */}
+ (
+
+ )}
+ >
+
+ )
+}
\ No newline at end of file
diff --git a/src/managements/notice/noticeDetail/index.jsx b/src/managements/notice/noticeDetail/index.jsx
new file mode 100644
index 000000000..7ce85cd40
--- /dev/null
+++ b/src/managements/notice/noticeDetail/index.jsx
@@ -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 (
+
+
{ history.go(-1) }}>返回公告详情
+
+
+ {noticeData.status == 1 ? noticeCheckedArr[noticeData.isChecked] : '草稿'}
+ {noticeData.title}
+ {noticeTypeArr[noticeData.type]}
+ {noticeData.publisher}
+
+ {[4, 5, 6].includes(noticeData.type) && ') }}>
}
+
+ { download(noticeData.fileDownloadPath) }}>{noticeData.fileName}
+
+ {noticeData.createdAt}
+ {noticeData.publishDate && {noticeData.publishDate}}
+ {noticeData.closingDate}
+
+ {admin && noticeData.status == 1 && noticeData.isChecked == 2 &&
+
+
+
+
+
+ }
+
+
+
+
+ )
+}
+
+
+export default IndexPage;
diff --git a/src/managements/notice/noticeDetail/index.scss b/src/managements/notice/noticeDetail/index.scss
new file mode 100644
index 000000000..094d94ce3
--- /dev/null
+++ b/src/managements/notice/noticeDetail/index.scss
@@ -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;
+ }
+}
diff --git a/src/managements/notice/noticeEdit/index.jsx b/src/managements/notice/noticeEdit/index.jsx
new file mode 100644
index 000000000..796e2234f
--- /dev/null
+++ b/src/managements/notice/noticeEdit/index.jsx
@@ -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) => (
+
+ {getFieldDecorator(name, { rules, initialValue, validateFirst: true })(widget)}
+
+ ),
+ []
+ );
+
+ const editor = useCallback(() => (
+
+ {(!id || (id && noticeHtml)) &&
+ {
+ changeHtml(html);
+ }}
+ />}
+
+ {getFieldDecorator('text', {
+ rules: [{ required: true, message: "请输入公告描述" }],
+ validateFirst: true
+ })()}
+
+ ), [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 (
+
+
{id ? '修改' : '发布'}公告
+
+
+ {/* 用一个隐藏的input实现上传文件的必填校验 */}
+ {/* {getFieldDecorator('file_name', {
+ rules: [{ required: true, message: "请上传公告文件" }],
+ validateFirst: true
+ })()} */}
+
+
+
+ { changeClosingDate(e.target.value) }}>
+ 一周内
+ 一个月内
+ 三个月内
+ 半年内
+ 自定义
+
+ {getFieldDecorator('closingDate',
+ {
+ rules: [{ required: true, message: "请选择截止时间" }],
+ validateFirst: true
+ })()}
+
+
+
+
+
+
+
+
+
+
+ )
+})
+)
+
+export default NoticeEdit;
\ No newline at end of file
diff --git a/src/managements/notice/noticeList/index.jsx b/src/managements/notice/noticeList/index.jsx
new file mode 100644
index 000000000..df1e67ab1
--- /dev/null
+++ b/src/managements/notice/noticeList/index.jsx
@@ -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) => (
+
+ {record.status == 2 && }
+
+ {admin && record.status == 1 && record.isChecked == 2 && }
+ {(admin || (record.isChecked != 1)) && < Button className="mr5 font-12" type="danger" size="small" onClick={() => { deletItem(record.id) }}>删除}
+
+ ),
+ },
+ ];
+
+ // 如果是已发布,那么增加一项
+ 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 0 ? 'link' : ''}`} onClick={() => { text > 0 && history.push(`/managements/notice/reader/${record.id}`) }}>{text};
+ }
+ });
+ }
+
+
+ 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) => (
+
+ {getFieldDecorator(name, { rules, validateFirst: true, })(widget)}
+
+ ), []);
+
+
+ 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 (
+
+
+
+
+
+ {/*
row.id}
+ dataSource={dataList}
+ columns={columns}
+ pagination={false}
+ />
+
+ {dataList.length > 0 &&
+ { setCurPage(page) }}
+ current={curPage}
+ total={total}
+ />} */}
+
+
+ { setVisible(false) }}
+ className="form-edit-modal"
+ >
+
+ { setCurrentIsChecked(e.target.value) }} >
+
+ 通过
+
+
+ 拒绝
+
+
+
+
+
+
+ );
+})
+)
+
+export default NoticeList;
\ No newline at end of file
diff --git a/src/managements/notice/noticeList/index.scss b/src/managements/notice/noticeList/index.scss
new file mode 100644
index 000000000..7e5dcfacc
--- /dev/null
+++ b/src/managements/notice/noticeList/index.scss
@@ -0,0 +1,7 @@
+
+.searchForm{
+ float: left;
+ min-width: 260px;
+ margin-right:2em !important;
+}
+
diff --git a/src/managements/notice/noticeReader/index.jsx b/src/managements/notice/noticeReader/index.jsx
new file mode 100644
index 000000000..19ea32620
--- /dev/null
+++ b/src/managements/notice/noticeReader/index.jsx
@@ -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 (
+
+
{ history.go(-1) }}>返回浏览过该公告加密内容的用户详情
+
+
+ {noticeData.title}
+ {total}
+
+
+
+
+
+
+ )
+}
+
+
+export default NoticeReader;
diff --git a/src/managements/notice/noticeReader/index.scss b/src/managements/notice/noticeReader/index.scss
new file mode 100644
index 000000000..a98bd260b
--- /dev/null
+++ b/src/managements/notice/noticeReader/index.scss
@@ -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;
+ }
+}
diff --git a/src/managements/statistics/activity/index.jsx b/src/managements/statistics/activity/index.jsx
new file mode 100644
index 000000000..78ec1b6b4
--- /dev/null
+++ b/src/managements/statistics/activity/index.jsx
@@ -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 (
+
+
+
+
+
row.id}
+ dataSource={dataList}
+ columns={columns}
+ pagination={false}
+ onChange={handleTableChange} //预留的排序
+ />
+
+ {dataList.length > 0 &&
+ { setCurPage(page) }}
+ current={curPage}
+ total={total}
+ />}
+
+
+
+ );
+}
diff --git a/src/managements/statistics/global/index.jsx b/src/managements/statistics/global/index.jsx
new file mode 100644
index 000000000..4ee092866
--- /dev/null
+++ b/src/managements/statistics/global/index.jsx
@@ -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 (
+
+
+
+
+
+
+
项目总数
+
{totalProjects}
+
当前项目总数
+
+
+
+
+
+
用户总数
+
{totalMembers}
+
当前用户总数
+
+
+
+
+
{ setType(key) }}>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/*
+
+
+
+
+
+ */}
+
+
+
+
+ );
+}
diff --git a/src/managements/statistics/global/index.scss b/src/managements/statistics/global/index.scss
new file mode 100644
index 000000000..c7ad8874a
--- /dev/null
+++ b/src/managements/statistics/global/index.scss
@@ -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;
+ }
+
+
+
diff --git a/src/managements/statistics/index.jsx b/src/managements/statistics/index.jsx
new file mode 100644
index 000000000..b404f34ba
--- /dev/null
+++ b/src/managements/statistics/index.jsx
@@ -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 (
+
+ {/* 全局统计 */}
+ (
+
+ )}
+ >
+ {/* 成员工作统计 */}
+ (
+
+ )}
+ >
+ {/* 活跃度统计 */}
+ (
+
+ )}
+ >
+
+ )
+}
\ No newline at end of file
diff --git a/src/managements/statistics/member/index.jsx b/src/managements/statistics/member/index.jsx
new file mode 100644
index 000000000..8dc0568b0
--- /dev/null
+++ b/src/managements/statistics/member/index.jsx
@@ -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 (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
详情列表
+
+
+ );
+}
diff --git a/src/managements/statistics/member/index.scss b/src/managements/statistics/member/index.scss
new file mode 100644
index 000000000..d143c6736
--- /dev/null
+++ b/src/managements/statistics/member/index.scss
@@ -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;
+ }
+ }
+
diff --git a/src/managements/statistics/member/table-detail.jsx b/src/managements/statistics/member/table-detail.jsx
new file mode 100644
index 000000000..39a6b40f9
--- /dev/null
+++ b/src/managements/statistics/member/table-detail.jsx
@@ -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 (
+
+
row.id || i}
+ dataSource={dataList}
+ columns={columns}
+ pagination={false}
+ onChange={handleTableChange}
+ />
+
+ {dataList.length > 0 &&
+ { setCurPage(page) }}
+ current={curPage}
+ total={total}
+ loading={loading}
+ />}
+
+ )
+}
\ No newline at end of file
diff --git a/src/military/competition.js b/src/military/competition.js
index 60888d755..e61f10bd8 100644
--- a/src/military/competition.js
+++ b/src/military/competition.js
@@ -8,12 +8,12 @@ import Loadable from "react-loadable";
import Loading from "../Loading";
import { ImageLayerOfCommentHOC } from "../modules/page/layers/ImageLayerOfCommentHOC";
import './competition/index.scss';
-import { Menu, Popover, Spin } from "antd";
+import { Menu, message, Popover, Spin } from "antd";
import InfoModal from './competition/components/infoModal';
-import banner from './competition/image/banner.jpg';
-import banner_local from './competition/image/banner_local.jpg';
+// import banner from './competition/image/banner.jpg';
+// import banner_local from './competition/image/banner_local.jpg';
import logo from './competition/image/logo.png';
-import { getQz2022, userCompetitionStatus } from "./competition/api";
+import { getCompetitionDetail, userCompetitionStatus, follow, unFollow } from "./competition/api";
// import { paths } from "./competition/static";
import Login from './components/login';
@@ -49,6 +49,10 @@ const Refer = Loadable({
loader: () => import('./competition/refer'),
loading: Loading,
})
+const Rank = Loadable({
+ loader: () => import('./competition/rank'),
+ loading: Loading,
+});
const Chat = Loadable({
loader: () => import('./competition/chat'),
loading: Loading,
@@ -66,7 +70,7 @@ const Management = Loadable({
loading: Loading,
})
-const Qz2022 = (props) => {
+const Competition = (props) => {
const { history, current_user, match } = props;
const { location } = history;
const { pathname } = location;
@@ -117,7 +121,7 @@ const Qz2022 = (props) => {
useEffect(() => {
// 获取竞赛详情
- getQz2022(competitionId).then(response => {
+ getCompetitionDetail(competitionId).then(response => {
if (response && response.status === 200) {
setQzDetail(response.data.data);
}
@@ -149,13 +153,49 @@ const Qz2022 = (props) => {
props.showNotification("您还未报名竞赛!");
} else if (enrollStatus && enrollStatus.status === 0) {
props.showNotification("报名信息被管理员驳回!");
- } else if (['ccks','zstp2022'].includes(competitionId)&& enrollStatus && enrollStatus.status === 1) {
+ } else if ( competitionId === 'zstp2022' && enrollStatus && !enrollStatus.second_round) {
+ props.showNotification("很遗憾,您未进入复赛!");
+ } else if (['ccks', 'zstp2022'].includes(competitionId) && enrollStatus && enrollStatus.status === 1) {
props.showNotification("您的报名信息未通过审核!");
- } else {
+ } else if(['ccks', 'zstp2022'].includes(competitionId) && applyStatus ){
+ }else{
!referStatus ? props.showNotification(!referEnd ? `竞赛尚未开始提交作品,提交作品开始时间为:${qzDetail && qzDetail.enroll_date.substring(0, 10)}` : "比赛已结束") : "";
}
}
+ // 关注和取消关注
+ function follow1(){
+ if(current_user && current_user.login){
+ follow({
+ id: competitionId,
+ target_type: 'competition_info'
+ }).then(res=>{
+ if(res && res.status === 200){
+ message.success('关注成功');
+ setReloadDetail(Math.random());
+ }
+ })
+ }else{
+ props.showLoginDialog();
+ }
+ }
+
+ function unfollow(){
+ if(current_user && current_user.login){
+ unFollow({
+ id: competitionId,
+ target_type: 'competition_info'
+ }).then(res=>{
+ if(res && res.status === 200){
+ message.success('取消关注成功');
+ setReloadDetail(Math.random());
+ }
+ })
+ }else{
+ props.showLoginDialog();
+ }
+ }
+
const is_local = qzDetail && qzDetail.is_local;
const banner_url = qzDetail && qzDetail.banner_url && getImageUrl(qzDetail.banner_url);
@@ -163,8 +203,8 @@ const Qz2022 = (props) => {
{/* banner图+选项 */}
- {banner_url&&
}
- {pathname.indexOf("qz2022")>-1 && }
+ {banner_url &&
}
+ {pathname.indexOf("qz2022") > -1 && }
{/* {paths.indexOf(active) !== -1 && */}
@@ -184,16 +224,25 @@ const Qz2022 = (props) => {
通知公告
{/* 处于报名阶段正常跳转到报名页面,不处于右侧弹消息 */}
-
+ {competitionId === 'qz2022' ?
{ current_user && current_user.login ? !applyStatus && props.showNotification("报名时间已截止") : props.showLoginDialog() }}>参赛报名
+ :
+ 1) && current_user && current_user.login ? `/competition/${competitionId}/apply` : '' }} onClick={() => { current_user && current_user.login ? !applyStatus&& ( enrollStatus && enrollStatus.status<2 ) && props.showNotification("报名时间已截止") : props.showLoginDialog() }}>参赛报名
+ }
{competitionId === 'qz2022' ?
提案提交
:
- 提案提交
+ 1 && enrollStatus.second_round ? `/competition/${competitionId}/refer` : '' }} onClick={goToRefer}>提案提交
}
+ {
+ ['ccks', 'zstp2022'].includes(competitionId) &&
+ 排行榜
+
+ }
+
{competitionId === 'qz2022' &&
数据统计
}
@@ -208,6 +257,21 @@ const Qz2022 = (props) => {
后台管理
}
+ {/* 关注 */}
+ {qzDetail &&
+
+ {
+ !qzDetail.watched ?
+
+ 关注
+ :
+
+ 取消关注
+
+ }
+ {qzDetail.watchers_count}
+
+ }
{/* } */}
{/* {paths.indexOf(active) !== -1 && */}
@@ -258,10 +322,16 @@ const Qz2022 = (props) => {
() => (
)
}
>
+ {/* 排行榜 */}
+
()
+ }
+ >
{/* 交流互动 */}
()
+ () => ()
}
>
{/* 联系我们 */}
@@ -303,7 +373,7 @@ const Qz2022 = (props) => {
{/* 大赛介绍 */}
(competitionId=='qz2022'? :)
+ () => (competitionId == 'qz2022' ? : )
}
>
@@ -317,5 +387,5 @@ export default withRouter(
ImageLayerOfCommentHOC({
imgSelector: ".imageLayerParent img, .imageLayerParent .imageTarget",
parentSelector: ".newMain",
- })(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(Qz2022))))
+ })(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(Competition))))
);
diff --git a/src/military/competition/api.js b/src/military/competition/api.js
index c197c6e65..f2a36016f 100644
--- a/src/military/competition/api.js
+++ b/src/military/competition/api.js
@@ -5,39 +5,39 @@ export async function userCompetitionStatus(competitionId) {
return axios.get(`/competition_infos/${competitionId}/enroll_status.json`);
}
-// 启智2022详情接口
-export function getQz2022(competitionId) {
+// 竞赛详情接口
+export function getCompetitionDetail(competitionId) {
return axios.get(`/competition_infos/${competitionId}.json`);
}
// 报名启智2022 竞赛?debug=teacher
-export async function enrollCompetition(data,competitionId){
- return axios.post(`/competition_infos/${competitionId}/enroll.json`,data);
+export async function enrollCompetition(data, competitionId) {
+ return axios.post(`/competition_infos/${competitionId}/enroll.json`, data);
}
// 修改报名信息
-export async function enrollUpdate(data,competitionId){
- return axios.post(`/competition_infos/${competitionId}/enroll_update.json`,data);
+export async function enrollUpdate(data, competitionId) {
+ return axios.post(`/competition_infos/${competitionId}/enroll_update.json`, data);
}
// 统计启智2022 竞赛
-export async function stattistics(competitionId){
- return axios.get( `/competition_infos/${competitionId}/statistics.json`);
+export async function stattistics(competitionId) {
+ return axios.get(`/competition_infos/${competitionId}/statistics.json`);
}
// 竞赛提交作品
-export async function uploadCompetition(data,competitionId){
- return axios.post(`/competition_infos/${competitionId}/upload.json`,data);
+export async function uploadCompetition(data, competitionId) {
+ return axios.post(`/competition_infos/${competitionId}/upload.json`, data);
}
// 管理-竞赛报名列表?debug=admin
-export function getQzEnrollList(params,competitionId) {
- return axios.get(`/competition_infos/${competitionId}/enroll_list.json`,params={params});
+export function getEnrollList(params, competitionId) {
+ return axios.get(`/competition_infos/${competitionId}/enroll_list.json`, params = { params });
}
// 管理-竞赛提交作品列表&debug=admin
-export function getQzProList(params,competitionId) {
- return axios.get(`/competition_infos/${competitionId}/enroll_list.json?upload=true`,params={params});
+export function getProList(params, competitionId) {
+ return axios.get(`/competition_infos/${competitionId}/enroll_list.json?upload=true`, params = { params });
}
// 通知公告列表
@@ -46,36 +46,56 @@ export function getNoticeList(competitionId) {
}
// 通知公告详情
-export function getNoticeDetail(id,competitionId) {
+export function getNoticeDetail(id, competitionId) {
return axios.get(`/competition_infos/${competitionId}/competition_notices/${id}.json`);
}
// 新增通知
-export async function addQz2022Notice(data,competitionId){
- return axios.post(`/competition_infos/${competitionId}/competition_notices.json`,data);
+export async function addCompetitionNotice(data, competitionId) {
+ return axios.post(`/competition_infos/${competitionId}/competition_notices.json`, data);
}
// 编辑通知
-export async function updateQz2022Notice(id,data,competitionId){
- return axios.put(`/competition_infos/${competitionId}/competition_notices/${id}.json`,data);
+export async function updateCompetitionNotice(id, data, competitionId) {
+ return axios.put(`/competition_infos/${competitionId}/competition_notices/${id}.json`, data);
}
// 删除通知
-export async function deleteQz2022Notice(id,competitionId){
+export async function deleteCompetitionNotice(id, competitionId) {
return axios.delete(`/competition_infos/${competitionId}/competition_notices/${id}.json`);
}
// 编辑大赛介绍、大赛指南、关于我
-export async function updateQz2022(data,competitionId){
- return axios.put(`/competition_infos/${competitionId}.json`,data);
+export async function updateCompetition(data, competitionId) {
+ return axios.put(`/competition_infos/${competitionId}.json`, data);
}
// 修改竞赛报名状态
-export async function updateEnroll(data,competitionId){
- return axios.post(`/competition_infos/${competitionId}/enroll_status_update.json`,data);
+export async function updateEnroll(data, competitionId) {
+ return axios.post(`/competition_infos/${competitionId}/enroll_status_update.json`, data);
}
// 报名表扫描件上传
-export async function updateTemplate(data,competitionId){
- return axios.post(`/competition_infos/${competitionId}/upload_enroll_template.json`,data);
+export async function updateTemplate(data, competitionId) {
+ return axios.post(`/competition_infos/${competitionId}/upload_enroll_template.json`, data);
+}
+
+
+export async function rankingList(competitionId, params) {
+ return axios.get(`/competition_infos/${competitionId}/ranking_list.json`, { params });
+}
+
+// 竞赛关注
+export async function follow(data) {
+ return axios.post(`/watchers/follow.json`, data);
+}
+
+// 竞赛取消关注
+export async function unFollow(data) {
+ return axios.delete(`/watchers/unfollow.json`, {data});
+}
+
+// 我关注的竞赛列表
+export async function focusCompetitionList(params) {
+ return axios.get(`/competition_infos.json`, { params });
}
\ No newline at end of file
diff --git a/src/military/competition/apply/ccks.jsx b/src/military/competition/apply/ccks.jsx
index 95100abaa..02877b9c5 100644
--- a/src/military/competition/apply/ccks.jsx
+++ b/src/military/competition/apply/ccks.jsx
@@ -44,7 +44,7 @@ export default Form.create()((props) => {
const applyStatus = qzDetail
? Date.parse(new Date()) < Date.parse(new Date(qzDetail.enroll_date))
: true;
- if ((current_user && !current_user.login) || !applyStatus) {
+ if ((current_user && !current_user.login) || (!applyStatus && (enrollStatus && enrollStatus.status<2))) {
history.push(`/competition/${competitionId}`);
}
if (
@@ -77,7 +77,7 @@ export default Form.create()((props) => {
// form表单公共处理函数
const helper = useCallback(
- (label, name, rules, widget, extra,className) => (
+ (label, name, rules, widget, extra, className) => (
{getFieldDecorator(name, { rules, validateFirst: true })(widget)}
@@ -96,14 +96,14 @@ export default Form.create()((props) => {
// 检查用户填写信息
function checkInfo() {
- if(!files.length){
- setFieldsValue({enroll_template_id:''})
+ if (!files.length) {
+ setFieldsValue({ enroll_template_id: '' })
}
setErrorMessage(undefined);
// 检查用户输入的成员属性是否完全
if (members.length > 0) {
let all = 0;
- const len =3;
+ const len = 3;
// 用户输入的长度是否满足要求
let sizes = 0;
members.map((item) => {
@@ -186,7 +186,7 @@ export default Form.create()((props) => {
info.file.status === "removed"
) {
setFiles(appendFileSizeToUploadFileAll(info.fileList).slice(-1));
-
+
}
}
@@ -199,15 +199,15 @@ export default Form.create()((props) => {
// 进行文件大小检查
function beforeUpload(file) {
const isLt100M = file.size / 1024 / 1024 < 10;
- const isType = file.type === "image/png" || file.type === "image/jpg" || file.type === "image/jpeg" ||file.name.endsWith(".zip") || file.name.endsWith(".rar");
- if(!isType){
+ const isType = file.type === "image/png" || file.type === "image/jpg" || file.type === "image/jpeg" || file.name.endsWith(".zip") || file.name.endsWith(".rar");
+ if (!isType) {
message.error("只能上传指定类型文件");
}
if (!isLt100M) {
message.error("文件大小必须小于10MB");
}
-
- return isLt100M &&isType;
+
+ return isLt100M && isType;
}
return (
@@ -218,11 +218,10 @@ export default Form.create()((props) => {
个人信息
@@ -231,9 +230,8 @@ export default Form.create()((props) => {
报名审核中
@@ -242,9 +240,8 @@ export default Form.create()((props) => {
报名成功
@@ -265,7 +262,7 @@ export default Form.create()((props) => {
您的报名信息正在审核中,请耐心等待
)}
- {enrollStatus && enrollStatus.status === 2 && (
+ {enrollStatus && enrollStatus.enroll_info && (enrollStatus.enroll_info.status === 2 || enrollStatus.enroll_info.status === 3) && (
您已报名成功,请通过链接下载数据集
@@ -379,7 +376,7 @@ export default Form.create()((props) => {
{/*
成员 :
*/}
-
+
{qzDetail && (
{
{enrollStatus && enrollStatus.enroll_info.mail}
-
+
队长单位证明 :
@@ -453,28 +450,28 @@ export default Form.create()((props) => {
)}
- {enrollStatus && enrollStatus.enroll_info.members.length ?
+ {enrollStatus && enrollStatus.enroll_info.members.length ?
成员 :
{
- return item.real_name + ",";
- })
+ return item.real_name;
+ }).join(',')
}
placement="topLeft"
>
{enrollStatus &&
enrollStatus.enroll_info.members &&
enrollStatus.enroll_info.members.map((item) => {
- return item.real_name + ",";
- })}
+ return item.real_name
+ }).join(',')}
-
:''}
+
: ''}
- {enrollStatus && enrollStatus.enroll_info.status == 2 &&qzDetail && qzDetail.enroll_template&& (
+ {enrollStatus && enrollStatus.enroll_info && (enrollStatus.enroll_info.status == 2 || enrollStatus.enroll_info.status == 3) && qzDetail && qzDetail.enroll_template && (
{enrollStatus &&
- (!enrollStatus.enroll_status || enrollStatus.status === 0) && (
+ (!enrollStatus.enroll_status || enrollStatus.status === 0) &&
+ (