合并代码

This commit is contained in:
何童崇 2022-02-09 16:58:30 +08:00
commit ad27cfb042
103 changed files with 10070 additions and 20031 deletions

View File

@ -154,7 +154,7 @@ module.exports = {
{
libraryName: "antd",
libraryDirectory: "es",
style: "css",
style: true,
},
],
],
@ -212,6 +212,23 @@ module.exports = {
},
],
},
{
test: /\.less$/,
use: [{
loader: 'style-loader',
}, {
loader: 'css-loader', // translates CSS into CommonJS
}, {
loader: 'less-loader', // compiles Less to CSS
options: {
modifyVars: {
'primary-color': '#4154f1',
'link-color': '#4154f1',
},
javascriptEnabled: true,
},
}]
},
// "file" loader makes sure those assets get served by WebpackDevServer.
// When you `import` an asset, you get its (virtual) filename.
// In production, they would get copied to the `build` folder.

View File

@ -148,7 +148,7 @@ module.exports = {
{
libraryName: "antd",
libraryDirectory: "es",
style: "css",
style: true,
},
],
],
@ -211,6 +211,23 @@ module.exports = {
},
],
},
{
test: /\.less$/,
use: [{
loader: 'style-loader',
}, {
loader: 'css-loader', // translates CSS into CommonJS
}, {
loader: 'less-loader', // compiles Less to CSS
options: {
modifyVars: {
'primary-color': '#4154f1',
'link-color': '#4154f1',
},
javascriptEnabled: true,
},
}]
},
// "file" loader makes sure assets end up in the `build` folder.
// When you `import` an asset, you get its filename.
// This loader doesn't use a "test" so it will catch all modules

19785
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -206,6 +206,8 @@
"concat": "^1.0.3",
"cross-env": "^7.0.3",
"happypack": "^5.0.1",
"less": "^3.9.0",
"less-loader": "^4.1.0",
"mockjs": "^1.1.0",
"node-sass": "^4.12.0",
"optimize-css-assets-webpack-plugin": "^5.0.3",

View File

@ -1,8 +1,8 @@
@font-face {
font-family: "iconfont"; /* Project id 2340181 */
src: url('iconfont.woff2?t=1640585290619') format('woff2'),
url('iconfont.woff?t=1640585290619') format('woff'),
url('iconfont.ttf?t=1640585290619') format('truetype');
src: url('iconfont.woff2?t=1642391410353') format('woff2'),
url('iconfont.woff?t=1642391410353') format('woff'),
url('iconfont.ttf?t=1642391410353') format('truetype');
}
.iconfont {
@ -13,6 +13,30 @@
-moz-osx-font-smoothing: grayscale;
}
.icon-a-2:before {
content: "\e90f";
}
.icon-a-3:before {
content: "\e910";
}
.icon-icon1:before {
content: "\e911";
}
.icon-ioon:before {
content: "\e90e";
}
.icon-shanchu_tc_icon1:before {
content: "\e90c";
}
.icon-zhuanjiaicon:before {
content: "\e90d";
}
.icon-shengming:before {
content: "\e90b";
}

File diff suppressed because one or more lines are too long

View File

@ -5,6 +5,48 @@
"css_prefix_text": "icon-",
"description": "",
"glyphs": [
{
"icon_id": "27200759",
"name": "2",
"font_class": "a-2",
"unicode": "e90f",
"unicode_decimal": 59663
},
{
"icon_id": "27200760",
"name": "3",
"font_class": "a-3",
"unicode": "e910",
"unicode_decimal": 59664
},
{
"icon_id": "27200761",
"name": "icon",
"font_class": "icon1",
"unicode": "e911",
"unicode_decimal": 59665
},
{
"icon_id": "27041503",
"name": "ioon",
"font_class": "ioon",
"unicode": "e90e",
"unicode_decimal": 59662
},
{
"icon_id": "26470602",
"name": "shanchu_tc_icon",
"font_class": "shanchu_tc_icon1",
"unicode": "e90c",
"unicode_decimal": 59660
},
{
"icon_id": "26470603",
"name": "专家icon",
"font_class": "zhuanjiaicon",
"unicode": "e90d",
"unicode_decimal": 59661
},
{
"icon_id": "12505154",
"name": "声明",

View File

@ -63,6 +63,11 @@ const Task = Loadable({
loader: () => import('./military/task'),
loading: Loading,
})
// 专家
const Expert = Loadable({
loader: () => import('./military/expert'),
loading: Loading,
})
//403页面
const Shixunauthority = Loadable({
loader: () => import('./modules/403/Shixunauthority'),
@ -351,6 +356,9 @@ class App extends Component {
</Route>
{/*任务*/}
<Route path="/task" component={Task} />
{/*专家评审*/}
<Route path="/expert" component={Expert} />
<Route exact path="/explore/all"
render={
(props) => (

3159
src/college/iconfont.css Normal file

File diff suppressed because it is too large Load Diff

View File

@ -68,8 +68,11 @@ export function appendFileSizeToUploadFile(item) {
return `${item.title}${uploadNameSizeSeperator}${item.filesize}`
}
export function appendFileSizeToUploadFileAll(fileList) {
return fileList.map(item => {
if (item.name.indexOf(uploadNameSizeSeperator) === -1) {
return fileList && fileList.map(item => {
if(!item.name)item.name=item.fileName;
if(!item.uid)item.uid="rc-upload" + item.id;
if(!item.size)item.size=item.fileSize;
if ((item.name).indexOf(uploadNameSizeSeperator) == -1) {
return Object.assign({}, item, { name: `${item.name}${uploadNameSizeSeperator}${bytesToSize(item.size)}` })
}
return item

View File

@ -1,14 +1,19 @@
import React from "react";
import md5 from 'md5';
import {Input} from "antd";
import { Input } from "antd";
const { Search } = Input;
const $ = window.$;
const isDev = window.location.port == 3007;
const isdev2= window.location.hostname ==='www.educoder.net'
export const TEST_HOST = "http://192.168.1.40:3000"
// export const TEST_HOST = "http://39.105.176.215:49999"
export const TEST_HOST = "http://117.50.100.12:49999";
export function getImageUrl(path) {
const local = TEST_HOST;
// https://www.educoder.net
// https://testbdweb.trustie.net
// const local = 'http://localhost:3000'
// const local = 'http://39.105.176.215:49999';
const local = 'http://117.50.100.12:49999';
if (isDev) {
return `${local}/${path}`
@ -37,25 +42,28 @@ export function getImage(path) {
// https://www.educoder.net
// https://testbdweb.trustie.net
// const local = 'http://localhost:3000'
const local = TEST_HOST;
if(path.indexOf("http://")===-1){
const local = 'http://39.105.176.215:49999';
if (path&&path.indexOf("http://") === -1) {
if (isDev) {
return `${local}/images/${path}`
}
return `/${path}`;
}else{
} else {
return path;
}
}
export function getTestImage(path) {
// https://www.educoder.net
// https://testbdweb.trustie.net
// const local = 'http://localhost:3000'
const local = 'http://117.50.100.12:49999';
if(path && path.indexOf("http://")===-1){
if (path && path.indexOf("http://") === -1) {
if (isDev) {
return `${local}${path}`
}
return `${path}`;
}else{
} else {
return path;
}
}
@ -74,31 +82,31 @@ export function getcdnImageUrl(path) {
// https://testbdweb.trustie.net
// const local = 'http://localhost:3000'
const testlocal = 'https://testali-cdn.educoder.net'
const local='https://ali-cdn.educoder.net'
let firstStr=path.substr(0,1);
const local = 'https://ali-cdn.educoder.net'
let firstStr = path.substr(0, 1);
if (isdev2) {
return `${local}/${path}`;
}else{
if(firstStr=="/"){
} else {
if (firstStr == "/") {
return `${path}`
}else{
} else {
return `/${path}`
}
}
// return `${local}/${path}`;
}
export function setcndImagesUrl(path){
export function setcndImagesUrl(path) {
const testlocal = 'https://testali-cdn.educoder.net'
const local='https://ali-cdn.educoder.net'
let firstStr=path.substr(0,1);
if(firstStr=="/"){
const local = 'https://ali-cdn.educoder.net'
let firstStr = path.substr(0, 1);
if (firstStr == "/") {
if (!isdev2) {
return `${path}`
}
return `${local}${path}`;
//return isDev?`${testlocal}${path}`:`${local}${path}`;
}else{
} else {
if (!isdev2) {
return `/${path}`
}
@ -109,17 +117,17 @@ export function setcndImagesUrl(path){
export function setImagesUrl(path){
export function setImagesUrl(path) {
const testlocal = 'https://testali-cdn.educoder.net'
const local='https://ali-cdn.educoder.net'
let firstStr=path.substr(0,1);
if(firstStr=="/"){
const local = 'https://ali-cdn.educoder.net'
let firstStr = path.substr(0, 1);
if (firstStr == "/") {
if (!isdev2) {
return `${path}`
}
return `${local}${path}`;
// return isDev?`${testlocal}${path}`:`${path}`;
}else{
} else {
if (!isdev2) {
return `/${path}`
}
@ -131,9 +139,9 @@ export function setImagesUrl(path){
export function getUrl(path, goTest) {
const local = TEST_HOST;
if (isDev) {
return `${local}${path?path:''}`
return `${local}${path ? path : ''}`
}
return `${path ? path: ''}`;
return `${path ? path : ''}`;
}
export function getUrlmys(path, goTest) {
@ -147,9 +155,9 @@ export function getUrlmys(path, goTest) {
// const local = 'https://testeduplus2.educoder.net'
const local = 'https://test-jupyterweb.educoder.net'
if (isDev) {
return `${local}${path?path:''}`
return `${local}${path ? path : ''}`
}
return `${path ? path: ''}`;
return `${path ? path : ''}`;
}
export function getStaticUrl() {
const local = TEST_HOST;
@ -162,25 +170,27 @@ export function getStaticUrl() {
export function getUrl2(path, goTest) {
const local = 'http://localhost:3000'
if (isDev) {
return `${local}${path?path:''}`
return `${local}${path ? path : ''}`
}
return `${path ? path: ''}`;
return `${path ? path : ''}`;
}
const newopens ="79e33abd4b6588941ab7622aed1e67e8";
const newopens = "79e33abd4b6588941ab7622aed1e67e8";
let newtimestamp;
let checkSubmitFlgs = false;
function railsgettimess(proxy) {
if(checkSubmitFlgs===false){
$.ajax({url:proxy,
async:false,success:function(data){
if(data.status===0){
newtimestamp=data.message;
if (checkSubmitFlgs === false) {
$.ajax({
url: proxy,
async: false, success: function (data) {
if (data.status === 0) {
newtimestamp = data.message;
checkSubmitFlgs = true;
}
}})
}
})
window.setTimeout(function () {
checkSubmitFlgs=false;
checkSubmitFlgs = false;
}, 2500);
}
}
@ -223,8 +233,8 @@ export function getUploadActionUrlOfAuth(id) {
}
export function getRandomNumber(type) {
let anewopens=md5(newopens+newtimestamp);
return type===true?`randomcode=${newtimestamp}&client_key=${anewopens}`:`?randomcode=${newtimestamp}&client_key=${anewopens}`
let anewopens = md5(newopens + newtimestamp);
return type === true ? `randomcode=${newtimestamp}&client_key=${anewopens}` : `?randomcode=${newtimestamp}&client_key=${anewopens}`
}
export function test(path) {
@ -258,14 +268,14 @@ export function htmlEncode(str) {
return s;
}
export function publicSearchs(Placeholder,onSearch,onInputs,onChanges,loadings) {
return(<Search
placeholder= { Placeholder || "请输入内容进行搜索" }
export function publicSearchs(Placeholder, onSearch, onInputs, onChanges, loadings) {
return (<Search
placeholder={Placeholder || "请输入内容进行搜索"}
onSearch={onSearch}
// value={searchValue}
onInput={onInputs}
onChange={onChanges}
loading={loadings||false}
loading={loadings || false}
allowClear={true}
></Search>)
}

View File

@ -6,7 +6,7 @@ export {
getUploadLogoActionUrl as getUploadLogoActionUrl,numFormat as numFormat,
getImageUrl as getImageUrl,getImage as getImage, getmyUrl as getmyUrl, getRandomNumber as getRandomNumber, getUrl as getUrl, publicSearchs as publicSearchs, getRandomcode as getRandomcode, getUrlmys as getUrlmys, getUrl2 as getUrl2, setImagesUrl as setImagesUrl
, getUploadActionUrl as getUploadActionUrl, getUploadActionUrltwo as getUploadActionUrltwo, getUploadActionUrlthree as getUploadActionUrlthree, getUploadActionUrlOfAuth as getUploadActionUrlOfAuth
, getTaskUrlById as getTaskUrlById, TEST_HOST, htmlEncode as htmlEncode, getupload_git_file as getupload_git_file, getcdnImageUrl as getcdnImageUrl,getTestImage as getTestImage,
, getTaskUrlById as getTaskUrlById, TEST_HOST, htmlEncode as htmlEncode, getupload_git_file as getupload_git_file, getcdnImageUrl as getcdnImageUrl,getTestImage as getTestImage,getLogoImageUrl as getLogoImageUrl,
turnbar,returnbar,getUrlToken as getUrlToken
} from './UrlTool';

View File

@ -314,7 +314,7 @@ class NewHeader extends Component {
{
settings && settings.nav_logo_url ?
<a href={settings && settings.new_course.default_url} className={"fl mr50"}>
<img alt="可控开源社区" className="logoimg" src={getImageUrl(`/${settings.nav_logo_url}`)}></img>
<img alt="红山开源" className="logoimg" src={getImageUrl(`/${settings.nav_logo_url}`)}></img>
</a>
:
""

View File

@ -212,6 +212,8 @@ class Infos extends Component {
}
render() {
let settings = JSON.parse(localStorage.chromesetting);
let main_web_site_url = settings.main_web_site_url;
const { current_user } = this.props;
const { username } = this.props.match.params;
const { user, isSpin, route_type , undo_events , menuKey , avatarVisible } = this.state;
@ -260,8 +262,7 @@ class Infos extends Component {
<Button
block
className="text-button-grey"
onClick={()=>this.props.history.push(`/${user.login}/info`)}
type="primary"
href={`${main_web_site_url || "https://osredm.com"}/users/${user.login}/profiles`}
>
{" "}
<i className="iconfont icon-shezhi4 font-15 mr5"></i>

View File

@ -155,7 +155,7 @@ function FifthSection({ fifth, history }) {
<div className="task-main">
<h2 className="homePage-blue-tit">创客空间</h2>
<h4 className="homePage-subhead">开源项目版块集项目托管版本管理等功能于一体为开源协作和群智汇聚提供创作环境</h4>
<h4 className="homePage-subhead">创客空间版块面向大众智慧群体征集技术成果创意概念和解决方案实现供需高效对接</h4>
<Line />
<Collapse
accordion

View File

@ -9,18 +9,18 @@ $bgcolorlist:#254dea #e33230 #0766fb #f02c66 #6038ff #f85e55 #c13cff #2cb840 #57
.fifth-main {
display: flex;
margin: 5vh auto 3vh;
margin: 5vh auto 0;
justify-content: space-between;
}
.homepage-btn {
margin-bottom: 10vh;
margin-bottom: 8vh;
}
.circle-wave {
position: relative;
width: 37.5em;
height: 43.75em;
height: 42.75em;
flex: none;
&:hover .icon-circle {

View File

@ -25,7 +25,7 @@ let setting = {
}
function SecondSection({ second ,main_web_site_url}) {
function SecondSection({ second ,main_web_site_url ,btnUrl}) {
const [leftItem, setLeftItem] = useState({});
const [list, setList] = useState([]);
@ -56,7 +56,7 @@ function SecondSection({ second ,main_web_site_url}) {
return (
<React.Fragment>
<h2 className="homePage-blue-tit">社区动态</h2>
<h4 className="homePage-subhead">为社区用户提供自主交流空间实现思维碰撞和智慧融合</h4>
<h4 className="homePage-subhead">关注开源热点资讯与技术分享红山观点与活动</h4>
<Line />
<div className="homepage-main community-main">
@ -77,7 +77,7 @@ function SecondSection({ second ,main_web_site_url}) {
</div>
<div className="text-center">
<Button className="homepage-btn" type="primary" onClick={() => { window.open(`${main_web_site_url}/forums`)}}>更多动态 <i className="iconfont icon-gengduoicon"></i></Button>
<Button className="homepage-btn" type="primary" onClick={() => { window.open(btnUrl)}}>更多动态 <i className="iconfont icon-gengduoicon"></i></Button>
</div>
</div>

View File

@ -27,7 +27,7 @@ let setting = {
}
function SeventhSection({ main_web_site_url }) {
function SeventhSection({ main_web_site_url,btnUrl }) {
const [list, setList] = useState([]);
@ -79,7 +79,7 @@ function SeventhSection({ main_web_site_url }) {
</Slider>
<Button className="homepage-btn" type="primary" onClick={() => { window.open(`${main_web_site_url}/forums`) }}>参与交流 <i className="iconfont icon-gengduoicon"></i></Button>
<Button className="homepage-btn" type="primary" onClick={() => { window.open(btnUrl) }}>参与交流 <i className="iconfont icon-gengduoicon"></i></Button>
</div>

View File

@ -3,7 +3,7 @@
text-align: center;
padding-top: 2.5em;
padding-bottom: 0.625em;
z-index: 100000;
z-index: 100;
margin-bottom: -0.625em;
border-bottom: 1px solid #cbdcff;
.seventh-main {
@ -15,7 +15,6 @@
height: 31.25em;
left: 0;
bottom: 2.5em;
// z-index: 10;
.client {
position: absolute;
width: 6.25em;
@ -130,7 +129,7 @@
.slick-list {
width: 33.75em;
margin: 0 auto;
z-index: 10000;
z-index: 1001;
}
.issue-item {
text-align: center;
@ -159,21 +158,21 @@
.issue-content {
text-align: left;
text-indent: 2em;
font-size: 15px;
font-size: 0.95em;
font-weight: 400;
color: #3c476e;
line-height: 28px;
line-height: 1.75em;
}
.issue-time {
height: 28px;
font-size: 15px;
height: 1.75em;
font-size: 0.95em;
color: #3c476e;
line-height: 28px;
line-height: 1.75em;
}
}
.homepage-btn {
margin-top: 50px;
margin-top: 3.125em;
}
@keyframes zoomin {

View File

@ -17,7 +17,7 @@ import './index.scss';
let iconArr = [completeIcon1, completeIcon2, completeIcon3];
function SixthSection({ sixth, main_web_site_url }) {
function SixthSection({ sixth, main_web_site_url,btnUrl }) {
const [list, setList] = useState();
@ -78,7 +78,7 @@ function SixthSection({ sixth, main_web_site_url }) {
</div>
<Button className="homepage-btn" type="primary" onClick={() => { window.open(`${main_web_site_url}/competitions`) }}>我要参赛 <i className="iconfont icon-gengduoicon"></i></Button>
<Button className="homepage-btn" type="primary" onClick={() => { window.open(btnUrl) }}>我要参赛 <i className="iconfont icon-gengduoicon"></i></Button>
<svg className="waves"
viewBox="0 24 150 28" preserveAspectRatio="none" shapeRendering="auto">
<defs>

View File

@ -33,6 +33,18 @@ function HomePage({ history }) {
let settings = JSON.parse(localStorage.chromesetting);
let main_web_site_url = settings.main_web_site_url;
let forumUrl ="";
let competitionUrl ="";
if(settings.navbar){
for (const item of settings.navbar){
if(item.name.indexOf("论坛")>-1){
forumUrl=item.link;
}
if(item.name.indexOf("竞赛")>-1){
competitionUrl=item.link;
}
}
}
function scrollListener() {
@ -120,7 +132,7 @@ function HomePage({ history }) {
<div id="home-second-section" className="home-second-section">
<SecondSection second={second} main_web_site_url={main_web_site_url} />
<SecondSection second={second} main_web_site_url={main_web_site_url} btnUrl={forumUrl}/>
</div>
@ -137,11 +149,11 @@ function HomePage({ history }) {
</div>
<div id="home-sixth-section" className="home-sixth-section">
<SixthSection sixth={sixth} main_web_site_url={main_web_site_url} />
<SixthSection sixth={sixth} main_web_site_url={main_web_site_url} btnUrl={competitionUrl}/>
</div>
<div id="home-seventh-section" className="home-seventh-section">
<SeventhSection main_web_site_url={main_web_site_url} />
<SeventhSection main_web_site_url={main_web_site_url} btnUrl={forumUrl}/>
</div>
<Footer />

View File

@ -112,6 +112,10 @@
&.newHeaders {
// background-color: #1a2358;
background-color: #0037af;
z-index: 1000000;
}
.newFooter{
background: inherit;
}
.head-nav {
min-width: auto;

View File

@ -0,0 +1,133 @@
/* eslint-disable react/jsx-no-duplicate-props */
import React, { useState } from 'react';
import * as ReactDOM from 'react-dom';
import { Modal, Button } from 'antd';
import './index.scss';
//
InitModal.defaultProps = {
okText: '确认', //
cancelText: '取消', //
className: '', //
inputId: 'copyText', //ID
onCancel:()=>{}, //
onOk:()=>{}, //
title:'提示', //
contentTitle:'', //
content:'', //
afterClose:()=>{}, //
};
// 使
export default function DelModal(props) {
renderModal({ ...props, type: 'delete' })
}
// 使
export function Confirm(props) {
renderModal({ ...props, type: 'confirm' })
}
// 使
export function Info(props) {
renderModal({ ...props, type: 'info' })
}
function renderModal(props) {
const { type, afterClose } = props;
const div = document.createElement('div');
document.body.appendChild(div);
function destroy() {
afterClose && afterClose();
const unmountResult = ReactDOM.unmountComponentAtNode(div);
if (unmountResult && div.parentNode) {
div.parentNode.removeChild(div);
}
}
function modalType(type) {
if (type === 'delete') {
return <InitModal
title="删除"
contentTitle="确定要删除吗?"
okText="确认删除"
{...props}
afterClose={destroy}
contentTitle={<React.Fragment>
<i className="red-circle iconfont icon-shanchu_tc_icon mr3"></i>
{props.contentTitle}
</React.Fragment>}
/>
} else if (type === 'confirm') {
return <InitModal title="选择" afterClose={destroy} {...props} />
} else if (type === 'info') {
return <InitModal title="选择" afterClose={destroy} {...props} okText="知道了" cancelButtonProps={""}/>
} else {
return <InitModal title="选择" afterClose={destroy} {...props} />
}
}
function render() {
setTimeout(() => {
ReactDOM.render(
modalType(type),
div,
);
});
}
render();
}
//
function InitModal({
onCancel,
onOk,
title,
contentTitle,
content,
okText,
cancelText,
afterClose,
className,
}) {
const [visible, setVisible] = useState(true);
function onCancelModal() {
setVisible(false);
onCancel && onCancel()
}
function onSuccess() {
setVisible(false);
onOk && onOk();
}
return (
<Modal
visible={visible}
onCancel={onCancelModal}
afterClose={afterClose}
title={title}
className={`myself-modal ${className}`}
centered
footer={[
<Button type="default" key="back" onClick={onCancelModal}>
{cancelText}
</Button>,
<Button type="primary" className="foot-submit" key="submit" onClick={onSuccess}>
{okText}
</Button>,
]}
>
<div>
{contentTitle && <p className="content-title">{contentTitle}</p>}
<p className="content-descibe">{content}</p>
</div>
</Modal>
)
}

View File

@ -0,0 +1,70 @@
.myself-modal {
.ant-modal-header {
padding: 9px 24px;
background: #f8f8f8;
border-bottom: 1px solid #eee;
}
.ant-modal-title {
text-align: left;
}
.ant-modal-close {
top: 0px !important;
}
.ant-modal-close-x {
font-size: 24px;
}
.ant-modal-body {
text-align: center;
}
.content-title {
display: flex;
justify-content: center;
align-items: center;
margin: 2rem 0 1rem !important;
font-size: 16px;
color: #333;
letter-spacing: 0;
line-height: 29px;
font-weight: 400;
}
.red-circle {
align-self: flex-start;
color: #ca0002;
font-size: 1.5rem !important;
}
.content-descibe {
font-size: 14px;
color: #666;
line-height: 33px;
font-weight: 400;
}
.ant-modal-footer {
padding: 2rem 0;
text-align: center;
border: 0;
.ant-btn {
width: 6rem;
}
}
.ant-btn-primary {
margin-left: 3rem;
background: #4154f1;
border-color: #4154f1;
&:hover,
&:active,
&:focus {
background: #5d6eff;
border-color: #5d6eff;
}
}
.ant-btn-default {
&:hover,
&:active,
&:focus {
color: #5d6eff;
border-color: #5d6eff;
}
}
}

View File

@ -0,0 +1,160 @@
import React, { useMemo,useState } from 'react';
import { Link } from "react-router-dom";
import { Menu, Dropdown, } from 'antd';
import './index.scss';
const { SubMenu } = Menu;
export default props => {
const main_web_site_url =localStorage.chromesetting&& JSON.parse(localStorage.chromesetting).main_web_site_url;
const current_main_site_url =localStorage.chromesetting&& JSON.parse(localStorage.chromesetting).current_main_site_url;
const [current,setCurrent]=useState(JSON.parse(sessionStorage.adminRouter||'[]'));
function handleClick (e){
setCurrent([e.key]);
sessionStorage.setItem( 'adminRouter',JSON.stringify([e.key]));
};
const projectMenu = useMemo(() => {
return <Menu>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${current_main_site_url}/admins`}>项目管理后台</a></Menu.Item>
</Menu>
});
const taskMenu = useMemo(() => {
return <Menu selectedKeys={current} onClick={handleClick}>
<SubMenu title="基础数据" >
<Menu.Item><a href={`${main_web_site_url}/admin/categories/list`}>任务领域</a></Menu.Item>
<Menu.Item><a href={`${main_web_site_url}/admin/industries/list`}>行业信息</a></Menu.Item>
<Menu.Item><a href={`${main_web_site_url}/admin/placements/list`}>职位信息</a></Menu.Item>
<Menu.Item><a href={`${main_web_site_url}/admin/task_templates/list`}>需求导入模板</a></Menu.Item>
<Menu.Item><a href={`${main_web_site_url}/admin/agreement_setting`}>签订协议内容</a></Menu.Item>
<Menu.Item><a href={`${main_web_site_url}/admin/sign_agreement_setting`}>应征投稿协议内容</a></Menu.Item>
</SubMenu>
<SubMenu title="代办事项" >
<Menu.Item key="delayManage"><Link to={`/task/delayManage`}>延期任务处理</Link></Menu.Item>
{/* <Menu.Item><a href={`${main_web_site_url}/admin/audit_files`}>协议签订凭证上传</a></Menu.Item> */}
<Menu.Item key="payProof"><Link to="/task/payProof">支付报酬凭证上传</Link></Menu.Item>
</SubMenu>
<Menu.Item key="taskAdmin"><Link to="/task/taskAdmin">创客任务列表</Link></Menu.Item>
</Menu>
});
const competitionMenu = useMemo(() => {
return <Menu>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/admin/competitions/list`}>竞赛列表</a></Menu.Item>
<Menu.Item><Link to="/expert/admin/competition">评审任务列表</Link></Menu.Item>
</Menu>
});
// const expertMenu = useMemo(() => {
// return <Menu>
// <Menu.Item><Link to={`/expert/admin/register`}></Link></Menu.Item>
// <Menu.Item><Link to={`/expert/admin/list`}></Link></Menu.Item>
// </Menu>
// });
const userMenu = useMemo(() => {
return <Menu selectedKeys={current} onClick={handleClick}>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/managements/users`}>用户列表</a></Menu.Item>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/admin/entities`}>主体信息列表</a></Menu.Item>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/managements/users_trial`}>试用授权列表</a></Menu.Item>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/managements/auto_users_trial`}>自动授权列表</a></Menu.Item>
<Menu.Item key={'register'}><Link to={`/expert/admin/register`}>专家注册列表</Link></Menu.Item>
<Menu.Item key={'expertList'}><Link to={`/expert/admin/list`}>专家库列表</Link></Menu.Item>
</Menu>
});
const forumMenu = useMemo(() => {
return <Menu >
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/managements/messages_list`}>帖子</a></Menu.Item>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/managements/apply_destroy_memos`}>申请删帖</a></Menu.Item>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/managements/memo_reply_list`}>回复</a></Menu.Item>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/admin/forum_sections`}>版块配置</a></Menu.Item>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/admin/banned_users`}>禁言列表</a></Menu.Item>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/admin/forum_applies`}>版主审批</a></Menu.Item>
</Menu>
});
const checkMenu = useMemo(() => {
return <Menu selectedKeys={current} onClick={handleClick}>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/managements/enterprise_authentication`}>企业认证</a></Menu.Item>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/admin/reviews/projects_list`}>开源项目</a></Menu.Item>
<Menu.Item key={"taskManage1"}><Link to="/task/taskManage/1">统筹任务发布审批</Link></Menu.Item>
<Menu.Item key={"taskManage0"}><Link to="/task/taskManage/0">自主任务发布审批</Link></Menu.Item>
<Menu.Item key={"paperManage"}><Link to="/task/paperManage">成果/评论审批</Link></Menu.Item>
<Menu.Item key={"paperComplain"}><Link to="/task/paperComplain">成果上传申诉审批</Link></Menu.Item>
<Menu.Item key={"publicityComplain"}><Link to="/task/publicityComplain">公示期成果申诉审批</Link></Menu.Item>
<Menu.Item key={"agreementManage"}><Link to="/task/agreementManage">协议审批</Link></Menu.Item>
<Menu.Item ><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/admin/tasks/report_result_tasks`}>成果举报申诉</a></Menu.Item>
<Menu.Item key={"proofManage"}><Link to="/task/proofManage">评选佐证材料</Link></Menu.Item>
</Menu>
});
const limitsMenu = useMemo(() => {
return <Menu>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/managements/user_admin_roles`}>权限组配置</a></Menu.Item>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/managements/admin_role_permissions`}>权限操作配置</a></Menu.Item>
</Menu>
});
const configMenu = useMemo(() => {
return <Menu>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/admin/about_infos/new"`}>关于我们</a></Menu.Item>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/admin/home_sections"`}>首页版块</a></Menu.Item>
<Menu.Item><a target="_blank" rel="noopener noreferrer" href={`${main_web_site_url}/admin/partners`}>合作伙伴</a></Menu.Item>
</Menu>
});
return (
<div className="centerbox managements_menus clearfix">
<Dropdown key={'projectMenu'} overlay={projectMenu} placement="bottomLeft">
<div className="drop-div">
项目
</div>
</Dropdown>
<Dropdown key={'taskMenu'} overlay={taskMenu} placement="bottomLeft">
<div className="drop-div">
创客
</div>
</Dropdown>
<Dropdown key={'competitionMenu'} overlay={competitionMenu} placement="bottomLeft">
<div className="drop-div">竞赛</div>
</Dropdown>
{/* <Dropdown key={'expert'} overlay={expertMenu} placement="bottomLeft">
<div className="drop-div">专家</div>
</Dropdown> */}
<Dropdown key={'userMenu'} overlay={userMenu} placement="bottomLeft">
<div className="drop-div">用户</div>
</Dropdown>
<Dropdown key={'forumMenu'} overlay={forumMenu} placement="bottomLeft">
<div className="drop-div">论坛交流</div>
</Dropdown>
<Dropdown key={'checkMenu'} overlay={checkMenu} placement="bottomLeft">
<div className="drop-div">审批</div>
</Dropdown>
<Dropdown key={'limitsMenu'} overlay={limitsMenu} placement="bottomLeft">
<div className="drop-div">权限管理</div>
</Dropdown>
<Dropdown key={'configMenu'} overlay={configMenu} placement="bottomLeft">
<div className="drop-div">网站配置</div>
</Dropdown>
</div>
)
}

View File

@ -0,0 +1,24 @@
.managements_menus {
background: #fff;
border: 1px solid #eee;
.drop-div {
position: relative;
float: left;
width: 108px;
text-align: center;
padding: 15px 0px;
box-sizing: border-box;
position: relative;
cursor: pointer;
&::after {
content: "";
position: absolute;
right: 1px;
top: 20px;
width: 1px;
height: 20px;
background-color: #ddd;
}
}
}

View File

@ -36,12 +36,12 @@
padding: 0 15px ;
cursor: pointer;
&:hover{
color: #1B8FFF;
color: #4154f1;
}
}
.choose-item-checked {
background: #f7f7f7;
color: #1B8FFF;
color: #4154f1;
}

View File

@ -0,0 +1,36 @@
import React, { Fragment } from 'react';
import { Table, Pagination } from 'antd';
import './index.scss';
export default (props) => {
const { loading, dataSource, columns, handleRow, total, setCurPage, current, rowSelection, expandedRowRender, expandIconColumnIndex, expandIconAsCell, onShowSizeChange, showSizeChanger, pagination, scroll } = props;
return (
<div className='pagination-table'>
<Table
{...props}
loading={loading}
rowKey={(row,i) => row.id || i}
dataSource={dataSource}
columns={columns}
pagination={false}
onRow={handleRow}
rowSelection={rowSelection}
expandedRowRender={expandedRowRender}
expandIconColumnIndex={expandIconColumnIndex}
expandIconAsCell={expandIconAsCell}
scroll={scroll}
/>
{total > 10 && (!pagination) &&
<Pagination
showQuickJumper
onShowSizeChange={onShowSizeChange}
onChange={setCurPage}
current={current}
total={total}
showSizeChanger={showSizeChanger}
/>}
</div>
)
}

View File

@ -0,0 +1,39 @@
.pagination-table {
.ant-table {
border: 1px solid #ececec;
border-radius: 0 0 4px 4px;
}
.ant-table-thead tr th div {
color: #181818;
font-weight: 500;
}
.ant-table-wrapper {
::-webkit-scrollbar {
width: 5px;
height: 5px;
}
.ant-table-hide-scrollbar {
margin-bottom: -5px;
overflow-y: hidden !important;
::-webkit-scrollbar {
width: 5px;
height: 5px;
}
}
}
.ant-table-thead > tr > th, .ant-table-tbody > tr > td{
padding: 14px 8px;
}
.ant-pagination {
margin-top: 1.25rem;
text-align: right;
}
// .ant-table-row-cell-break-word{
// .ant-btn{
// display: inline-block;
// }
// }
}

View File

@ -12,14 +12,14 @@
background-color: #fff;
&:hover {
background-color: #fff;
color: #409eff;
color: #4154f1;
cursor: pointer;
}
}
.sort-item-checked {
// background-color: #409eff;
// background-color: #4154f1;
// color: #fff;
color: #409eff;
color: #4154f1;
}
.caret-up-down {
display: inline-flex;
@ -29,7 +29,7 @@
color:#ccc;
}
.caret-checked{
color: #409eff;
color: #4154f1;
}
.anticon-caret-up{
margin-bottom: -.15em;

View File

@ -11,11 +11,11 @@
padding: 3px 15px;
cursor: pointer;
&:hover {
color: #4cacff;
color: #4154f1;
}
}
.status-item-checked {
background: #f7f7f7;
color: #4cacff ;
color: #4154f1 ;
}

83
src/military/expert.js Normal file
View File

@ -0,0 +1,83 @@
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 { getUserInfo } from './expert/api';
import { ImageLayerOfCommentHOC } from "../modules/page/layers/ImageLayerOfCommentHOC";
import './index.scss';
const Review = Loadable({
loader: () => import("./expert/review/review"),
loading: Loading,
});
const AdminRouter = Loadable({
loader: () => import("./expert/adminRouter"),
loading: Loading,
});
// const ReviewTasks = Loadable({
// loader: () => import("./expert/reviewTasks"),
// loading: Loading,
// })
const ExpertUser = Loadable({
loader: () => import("./expert/expertUser"),
loading: Loading,
})
const Expert = (propsTransmit) => {
// 开发时,从代理的位置获取用户信息
const [currentUser, setCurrentUser] = useState(propsTransmit.current_user);
// const isDev = window.location.href.indexOf('3007') > -1 ? true : false;
useEffect(() => {
getUserInfo().then(res => {
if (res && res.data) {
setCurrentUser(res.data);
}
})
}, []);
let propsF = { ...propsTransmit };
propsF.current_user = {...propsF.current_user,...currentUser};
return (
<div className="newMain clearfix">
<Switch {...propsF}>
{/* 专家注册、专家评审任务 */}
<Route
path="/expert/user/:functional"
render={(props) => (
<ExpertUser {...propsF} {...props} />
)}
></Route>
{/* 管理员管理 */}
<Route
path="/expert/admin/:admin"
render={(props) => (
<AdminRouter {...propsF} {...props} />
)}
></Route>
<Route
path="/expert"
render={(props) => (
<Review {...propsF} {...props} />
)}
></Route>
</Switch>
</div>
);
}
export default withRouter(
ImageLayerOfCommentHOC({
imgSelector: ".imageLayerParent img, .imageLayerParent .imageTarget",
parentSelector: ".newMain",
})(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(Expert))))
);

View File

@ -0,0 +1,92 @@
import React from "react";
import { Route, Switch } from "react-router-dom";
import Loadable from "react-loadable";
import Loading from "../../Loading";
import AdminRouter from "../components/adminRouter";
// 专家库
const ExpertList = Loadable({
loader: () => import("./expertList"),
loading: Loading,
});
// 专家审核
const RegisterList = Loadable({
loader: () => import("./registerList"),
loading: Loading,
});
//创客任务评审规则
const ReviewRules = Loadable({
loader : () => import("./reviewRules"),
loading: Loading,
});
//创客任务选择评审专家
const SelectExpert = Loadable({
loader: () => import("./selectExpert"),
loading: Loading,
});
//创客任务评审结果查看
const ReviewResult = Loadable({
loader: () => import("./reviewResult"),
loading: Loading,
});
//竞赛评审任务列表
const CompetitionList = Loadable({
loader: () => import("./competionList"),
loading: Loading,
})
const AdminPage = (propsF) => {
return (
<React.Fragment>
<AdminRouter {...propsF} />
<Switch {...propsF}>
{/* 专家审核 */}
<Route
path="/expert/admin/register"
render={(props) => (
<RegisterList {...propsF} {...props} />
)}
></Route>
{/* 专家库列表 */}
<Route
path="/expert/admin/list"
render={(props) => (
<ExpertList {...propsF} {...props} />
)}
></Route>
{/* 创客任务评审规则 */}
<Route
path="/expert/admin/task/review/rules/:containerType/:containerId"
render={(props) => (
<ReviewRules {...propsF} {...props} />
)}
></Route>
{/* 创客任务选择评审专家 */}
<Route
path="/expert/admin/task/review/select/:containerType/:containerId"
render={(props) => (
<SelectExpert {...propsF} {...props} />
)}
></Route>
{/* 创客任务评审结果查看 */}
<Route
path="/expert/admin/task/review/results/:containerType/:containerId"
render={(props) => (
<ReviewResult {...propsF} {...props} />
)}
></Route>
{/* 竞赛评审任务列表 */}
<Route
path="/expert/admin/competition"
render={(props) => (
<CompetitionList {...propsF} {...props} />
)}
></Route>
</Switch>
</React.Fragment>
);
}
// }
export default AdminPage;

256
src/military/expert/api.js Normal file
View File

@ -0,0 +1,256 @@
import fetch,{main_web_site_url} from './fetch';
import { notification } from 'antd';
// 专家列表查询
export async function expertList(params) {
let res = await fetch({
url: '/api/experts/',
method: 'get',
params,
});
if (res.data) {
return res.data;
} else {
notification.open({
message: "提示",
description: res.message || '请求错误',
});
}
}
//删除专家
export function deleteExpert(expertId) {
return fetch({
url: `/api/experts/${expertId}?isDelete=1`,
method: 'delete'
});
}
// 获取用户信息
export function getUserInfo() {
return fetch({
url: '/user/getUserInfo',
method: 'get'
});
}
// 查看当前登录用户专家信息
export function getCurrentExpert(params) {
return fetch({
url: '/api/experts/getCurrentExpert',
method: 'get',
params
});
}
//专家注册
export async function expertRegister(data){
let res = await fetch({
url: '/api/experts/register',
method: 'post',
data,
});
return res;
}
//更新专家信息
export async function expertUpdate(data){
let res = await fetch({
url: '/api/experts/',
method: 'put',
data,
});
return res;
}
//管理员审核专家信息
export async function registerCheck(data){
let res = await fetch({
url: '/api/experts/adminCheckExpert',
method: 'post',
data,
});
return res;
}
// 获取文件信息
export function getFile(id) {
return fetch({
url: `/busiAttachments/${id}`,
method: 'get'
});
}
// 获取评审任务列表
export function getExpertTasks(params) {
return fetch({
url: `/api/taskExpert/getExpertTasksPageList`,
method: 'get',
params,
});
}
// 获取竞赛作品列表
export function getCompetition(id) {
return fetch({
url: `${main_web_site_url}/api/v1/competitions/${id}/works`,
method: 'get',
});
}
// 获取竞赛详情接口
export function getCompetitionDetail(id) {
return fetch({
url: `${main_web_site_url}/api/v1/competitions/${id}`,
method: 'get',
});
}
// 查看竞赛/任务的评分细则
export function getScoringDetails(params) {
return fetch({
url: `/api/expertScoringDetails/getExpertScoringDetailsList`,
method: 'get',
params,
});
}
// 查看最终得分排行
export function getFinalScoreRankingList(params) {
return fetch({
url: `/api/expertScoringDetails/getFinalScoreRankingList`,
method: 'get',
params,
});
}
// 查看单个竞赛/任务的所有评分细则
export function getOpsScoringDetails(params) {
return fetch({
url: `/api/expertScoringDetails/getOpsExpertScoringDetailsList`,
method: 'get',
params,
});
}
// 初始化评分细则
export function initScoringDetails(data){
return fetch({
url: '/api/expertScoringDetails/initExpertScoringDetails',
method: 'post',
data,
})
}
// 更新评分细则
export function updateScoringDetails(data){
return fetch({
url: '/api/expertScoringDetails/',
method: 'put',
data,
});
}
//评选胜出者和公示者
export function selectWinnersAndPublicists(data){
return fetch({
url: '/api/expertScoringDetails/selectWinnersAndPublicists',
method: 'post',
data,
});
}
//查看胜出者和公示名单
export function getWinnersAndPublicists(params) {
return fetch({
url: `/api/expertScoringDetails/getWinnersAndPublicists`,
method: 'get',
params,
});
}
//获取创客任务评审规则
export async function getRules(params){
let response = await fetch({
url: `/api/taskRuleCriteria/getRuleAndCriteria`,
method: 'get',
params
});
if(response && response.message === "success"){
let criterias = [];
response.data.criteriaOne && (criterias[criterias.length] = (criterias.length+1)+"、"+response.data.criteriaOne);
response.data.criteriaTwo && (criterias[criterias.length] = (criterias.length+1)+"、"+response.data.criteriaTwo);
response.data.criteriaThree && (criterias[criterias.length] = (criterias.length+1)+"、"+response.data.criteriaThree);
response.data.criteriaFour && (criterias[criterias.length] = (criterias.length+1)+"、"+response.data.criteriaFour);
response.data.criteriaFive && (criterias[criterias.length] = (criterias.length+1)+"、"+response.data.criteriaFive);
response.data.criterias = criterias;
response.data.reviewData = response.data.reviewStartOn.substring(0,response.data.reviewStartOn.length-3) + " ~ " + response.data.reviewEndOn.substring(0,response.data.reviewEndOn.length-3)
}
return response;
}
//编辑评审规则(第一次)
export async function editRules(data){
let res = await fetch({
url: '/api/taskRuleCriteria/editRuleAndCriteria',
method: 'post',
data,
});
return res;
}
//更新评审规则(第一次)
export async function updateRules(data){
let res = await fetch({
url: '/api/taskRuleCriteria/',
method: 'put',
data,
});
return res;
}
//为创客任务添加评审专家
export async function assignExperts(data){
let res = await fetch({
url: '/api/taskExpert/assignExperts',
method: 'post',
data,
});
return res;
}
//删除指派专家
export function deleteExperts(taskExpertId,isDelete) {
console.log('taskExpertId',taskExpertId,'isDelete',isDelete);
return fetch({
url: `/api/taskExpert/${taskExpertId}?isDelete=${isDelete}`,
method: 'delete'
});
}
//已选专家列表
export function selectExpertList(params) {
return fetch({
url: `/api/taskExpert/selectedExpertPageList`,
method: 'get',
params
});
}
//竞赛任务列表
export function getCompetitionList(params) {
return fetch({
url: `/api/competitionExpert/getCompetitionList`,
method: 'get',
params
});
}
// 修改竞赛是否加入专家评审流程
export function updateCompetitionReview(data) {
return fetch({
url: `${main_web_site_url}/api/v1/competitions/update_expert_audit`,
method: 'post',
data,
});
}

View File

@ -0,0 +1,385 @@
import { Button, message, Modal, Select, Tooltip } from "antd";
import React, { useEffect, useMemo, useState } from "react";
import Link from "react-router-dom/Link";
import { publishExpertsAndRules } from "src/military/task/api";
import PaginationTable from "../../components/paginationTable";
import { expertReviewArr } from "../../task/static";
import { getCompetitionList, getRules, selectExpertList, updateCompetitionReview } from "../api";
import { competitionStatus } from "../static";
import './index.scss';
const Option = Select.Option;
const statusArr = [];
for (const item of competitionStatus) {
statusArr[item.value] = item.label;
}
// current_status 1 2 3 4 5 6
function Competition(props){
const {mygetHelmetapi, showNotification, history} = props;
const {main_web_site_url} = mygetHelmetapi;
const {hash} = history && history.location;
const [loading, setLoading] = useState(false);
const [curPage, setCurPage] = useState(hashDate(hash) || 1);
//
const [expertReview,setExpertReview] = useState(undefined);
//
const [total, setTotal] = useState()
//
const [competitionList, setCompetitionList] = useState(undefined);
//
const [lookRules, setLookRules] = useState(false);
const [lookExperts, setLookExperts] = useState(false);
const [pulicReview, setPublicReview] = useState(false);
const [rules, setRules] = useState(undefined);
const [selectedExperts, setSelectedExperts] = useState(undefined);
const [publicTaskId, setPublicTaskId] = useState(undefined);
const [reload, setReload] = useState(undefined);
//
const columns = useMemo(() => {
return [
{
title: "序号",
dataIndex: "index",
width: 50,
align: "center",
},
{
title: "竞赛主标题",
dataIndex: "title",
key: "title",
align: "center",
render:(text, record)=>{
return <Tooltip title={`标识: ${record.identifier}, 竞赛副标题: ${record.subtitle}`}><a href={`${main_web_site_url}/competitions/${record.identifier}/home`} target="_blank" className="primary-link">{text}</a></Tooltip>
}
},
{
title: <Select
className="column-select"
showArrow
defaultValue={' '}
onChange={(value)=>{setExpertReview(value);updateUrl(1);}}
>
<Option key={' '} >专家评审</Option>
<Option key={true} >已提交评审</Option>
<Option key={false} >未提交评审</Option>
</Select>,
dataIndex: 'is_expert_audit',
align: "center",
render: (text, record) => {
return <Select
className="column-select"
showArrow
defaultValue={text?1:-1}
onChange={(key) => { changeExpertReviewStatus(key, record.id) }}
disabled={record.current_status >3 || record.assignRuleAndExperts}
>
{
expertReviewArr.map(item => {
return <Option key={item.dicItemCode} value={item.dicItemCode}>{item.dicItemName}</Option>
})
}
</Select>
}
},
{
title: "竞赛状态",
dataIndex: "current_status",
key: "current_status",
align: "center",
render:(text, record)=>{
return statusArr[text];
}
},
{
title: "开始时间",
dataIndex: "start_time",
key: "startTime",
align: "center",
},
{
title: "截止时间",
dataIndex: "end_time",
key: "endTime",
align: "center",
},
{
title: "报名人数",
dataIndex: "team_members_count",
key: "teamMembersCount",
align: "center",
},
{
title: '评审规则',
dataIndex: 'current_status',
key: "rules",
render: (text, record) => {
return record.assignRuleAndExperts ? <Button size='small' type="primary" onClick={()=>{viewRules(record)}}>查看</Button> : record.is_expert_audit && text<4 ? <Link className="primary-link" to={`/expert/admin/task/review/rules/${2}/${record.id}/?identifier=${record.identifier}&status=${record.current_status}&name=${record.title}&reviewStartTime=${record.end_time}&reviewEndTime=${record.review_time}`}>编辑</Link> : <span className='gary_span'>编辑</span>
}
},
{
title: '专家选取',
dataIndex: 'current_status',
key: "experts",
render: (text, record) => {
return record.assignRuleAndExperts ? <Button size='small' type="primary" onClick={()=>{viewExperts(record)}}>查看</Button> : record.is_expert_audit && text<4 ? <Link className="primary-link" to={`/expert/admin/task/review/select/${2}/${record.id}/?identifier=${record.identifier}&name=${record.title}`}>选择</Link> : <span className='gary_span'>选择</span>
}
},
{
title: '评审任务',
dataIndex: 'current_status',
key: "review",
render: (text, record) => {
return record.assignRuleAndExperts ? <span className='gary_span'>已发布</span> : record.is_expert_audit && text<4 ? <Button size='small' type="primary" onClick={()=>{publishTaskReview(record)}}>发布</Button> : <span className='gary_span'>发布</span>
}
},
{
title: '评审结果',
dataIndex: 'assignRuleAndExperts',
key: "results",
render: (text, record) => {
return text ? <Link className="primary-link" to={`/expert/admin/task/review/results/${2}/${record.id}/#status=${record.current_status}&identifier=${record.identifier}&name=${record.title}`}>查看</Link>:<span className='gary_span'>查看</span>
}
}
];
}, [competitionList, curPage]);
//
const columnsExperts = useMemo(() => {
return [
{
title: '编号',
dataIndex: 'index',
width: 80,
align: 'center',
},
{
title: '专家姓名',
dataIndex: 'expertName',
key: 'expertName',
width: 120,
},
{
title: '手机号码',
dataIndex: 'phone',
width: 130,
key: 'phone',
},
{
title: '最高学历',
dataIndex: 'highestDegree',
key: 'highestDegree',
},
{
title: '专业职称',
dataIndex: 'professionalTitle',
},
{
title: '专家类别',
dataIndex: 'expertType',
},
{
title: '评审领域',
dataIndex: 'reviewAreas',
align: 'center',
width: 260,
},
{
title: '专家评分',
dataIndex: 'expertScore',
align: 'center',
render:(text,record)=>{
return record.expertScore || '--';
}
}
];
}, []);
//
function publishTaskReview(record){
if(!record.ruleEdited || !record.expertSelected){
message.error("请先编辑评审规则以及选取评选专家再发布此任务");
}else{
getRules({containerId: record.id, containerType: 2, statusString: 3}).then(response=>{
if(response && response.message === "success"){
setRules(response.data);
}
})
selectExpertList({containerId: record.id, containerType: 2, pageSize: 10000, curPage: 1}).then(response=>{
if(response && response.message === "success" && Array.isArray(response.data.rows)){
let index = 1;
for (const item of response.data.rows) {
item.reviewAreas = `${item.reviewAreaOne} ${item.reviewAreaTwo ? `${item.reviewAreaTwo}`:''} ${item.reviewAreaThree ? `${item.reviewAreaThree}`:''}`;
item.index = (index++) + (curPage > 1 ? (curPage - 1) * 10 : 0);
}
setPublicTaskId(record.id);
setSelectedExperts(response.data.rows);
setPublicReview(true);
}
});
}
}
//
function viewRules(record){
getRules({containerId: record.id, containerType: 2, statusString: '-1,1,2'}).then(response=>{
if(response && response.message === "success"){
setRules(response.data);
setLookRules(true);
}
});
}
//
function viewExperts(record){
selectExpertList({containerId: record.id, containerType: 2, pageSize: 10000, curPage: 1,}).then(response=>{
if(response && response.message === "success" && Array.isArray(response.data.rows)){
let index = 1;
for (const item of response.data.rows) {
item.reviewAreas = `${item.reviewAreaOne} ${item.reviewAreaTwo ? `${item.reviewAreaTwo}`:''} ${item.reviewAreaThree ? `${item.reviewAreaThree}`:''}`;
item.index = (index++) + (curPage > 1 ? (curPage - 1) * 10 : 0);
}
setSelectedExperts(response.data.rows);
setLookExperts(true);
}
});
}
//
function changeExpertReviewStatus(expertReviewStatus, taskId) {
updateCompetitionReview({id: taskId, is_expert_audit: expertReviewStatus==1}).then(res => {
if (res && res.message === '更新成功') {
showNotification('操作成功!');
setReload(Math.random());
} else {
showNotification('操作失败');
}
})
}
// ,
function updateUrl(page){
setCurPage(page);
window.location.href=`/expert/admin/competition/#page=${page}`;
}
function hashDate(hash) {
return parseInt(hash.split("&")[0].substring(hash.split("&")[0].indexOf("=")+1));
}
//
useEffect(()=>{
setLoading(true);
const params = {
curPage,
pageSize: 10,
isExpertAudit: expertReview
}
getCompetitionList(params).then(response=>{
if(response && response.message === "success"){
response.data.map((item, i)=>{
item.index = ++i;
item.start_time = item.start_time.replace('T', ' ').substring(0,16);
item.end_time = item.end_time.replace('T', ' ').substring(0,16);
})
setCompetitionList(response.data || []);
setTotal(response.total);
}
}).finally(()=>{
setLoading(false);
})
}, [curPage, expertReview, reload])
//lookRules,lookExperts,pulicReview
useEffect(()=>{
//
lookRules && rules && Modal.info({
className: 'publishReview',
title: "评审规则",
content:
<React.Fragment>
<div>{rules && rules.rule}</div>
<p>评分标准</p>
<div>
{rules.criterias.map(item=>{return <p key={Math.random()}>{item}</p>})}
</div>
<p>评审时间</p>
<div>{rules.reviewData}</div>
</React.Fragment>
,
});
lookRules && setLookRules(false);
//
lookExperts && selectedExperts && Modal.info({
className: 'publishReview',
title: "已选取评审专家",
content:
<PaginationTable
dataSource={selectedExperts}
columns={columnsExperts}
scroll={{ y: 395 }}/>,
});
lookExperts && setLookExperts(false);
//
pulicReview && rules && selectedExperts && Modal.confirm({
className: 'publishReview',
title: "发布评审任务",
centered: true,
content:
<React.Fragment>
<div className='tip'>
<i className='iconfont icon-erciqueren_icon'></i>
<span className='publicTitle'>确定发布此评审任务确定发布后评审规则与评审专家信息将无法重新编辑</span>
</div>
<p>评审规则</p>
<div>{rules && rules.rule}</div>
<p>评分标准</p>
<div>
{rules.criterias.map(item=>{return <p key={Math.random()}>{item}</p>})}
</div>
<p>评审时间</p>
<div>{rules.reviewData}</div>
<p>已选取评审专家</p>
<PaginationTable
dataSource={selectedExperts}
columns={columnsExperts}
scroll={{ y: 230 }}/>
</React.Fragment>
,
okText: '确定',
cancelText: '取消',
onOk() {
publishExpertsAndRules(publicTaskId, 2).then(response=>{
if(response && response.message==="发布成功"){
setReload(Math.random());
}
})
},
});
pulicReview && setPublicReview(false);
},[lookRules,lookExperts,pulicReview])
//hash
useEffect(()=>{
setCurPage(hashDate(hash) || 1);
},[hash])
return(
<div className="centerbox competitionList">
<PaginationTable
loading={loading}
dataSource={competitionList}
columns={columns}
total={total}
setCurPage={(page)=>{updateUrl(page)}}
current={curPage}
/>
</div>
)
}
export default Competition;

View File

@ -0,0 +1,63 @@
a.primary-link{
color: #4154f1;
&:hover{
opacity: 0.8;
}
}
.gary_span{
color: rgba(176, 176, 176, 1);
}
// 发布评审任务弹框样式
.publishReview{
width: 1050px !important;
.ant-modal-body{
padding: 0;
}
.ant-modal-confirm-btns {
margin: 15px 35px 10px;
}
.ant-modal-confirm-title{
border-bottom: 1px solid #eeeeee;
padding: 20px 25px;
background: #f2f2ff;
font-size: 18px;
}
.ant-modal-confirm-body > .anticon{
display: none;
}
.ant-modal-confirm-body > .anticon + .ant-modal-confirm-title + .ant-modal-confirm-content{
margin-left: 0;
}
.ant-modal-confirm-content{
&>p{
font-size: 16px;
color: #333333;
border-bottom: 1px solid #eeeeee;
padding: 10px 35px;
font-weight: bold;
}
&>div{
padding: 10px 45px;
}
.tip{
padding: 10px 35px;
i{
color: #ca0002;
}
.publicTitle {
font-size: 15px;
margin-left: 3px;
}
}
}
.pagination-table .ant-table-tbody > tr > td{
padding: 3px 8px;
}
}
.competitionList{
.ant-select-selection{
width: 115px;
}
}

View File

@ -0,0 +1,94 @@
import React, { useEffect, useState } from "react";
import { Upload, Button } from 'antd';
import { appendFileSizeToUploadFileAll } from 'educoder';
import { httpUrl } from '../fetch';
function Uploads({ className, size, actionUrl, fileList, showNotification, load, accept, disabled,count }) {
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);
backFiles(nf);
}
function backFiles(fileList) {
let filesId = [];
for (const item of fileList) {
if (item) {
let itemId = (item.response && item.response.data && item.response.data.id) || item.id;
itemId && filesId.push(itemId);
}
}
load && load(fileList, filesId.join());
}
function handleChange(info) {
if (info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') {
let fileList = info.fileList;
if(count){
fileList = fileList.slice(-count);
}
setFiles(appendFileSizeToUploadFileAll(fileList));
if (info.file.response) {
for (let i = 0; i < fileList.length; i++) {
if (fileList[i].response && !fileList[i].response.data) {
fileList.splice(i, 1);
}
}
backFiles(fileList);
if (!info.file.response.data) {
info.file.response && showNotification(info.file.response.message)
}
}
}
}
function beforeUpload(file) {
const isLt100M = file.size / 1024 / 1024 < size;
if (!isLt100M) {
showNotification(`文件大小必须小于${size}MB!`);
}
return isLt100M;
}
const upload = {
name: 'file',
fileList: files,
disabled: disabled,
action: (httpUrl || actionUrl) + `/busiAttachments/upload`,
onChange: handleChange,
onRemove: onAttachmentRemove,
beforeUpload: beforeUpload,
};
return (
<Upload {...upload} className={className}>
<Button type="primary" disabled={disabled}>点击上传</Button>
<span className="ml10 color-grey-9">(你可以上传小于<span className="color-red">{size}MB</span>的文件)</span>
</Upload>
)
}
export default Uploads;

View File

@ -0,0 +1,152 @@
export const exportExcel = (tableClass, fileName) => {
if (getExplorer() === 'ie') {
//创建AX对象excel
const curTbl = document.querySelector(tableClass).cloneNode(true);
// eslint-disable-next-line no-undef
let oXL = new ActiveXObject("Excel.Application");
let oWB = oXL.Workbooks.Add(); //获取workbook对象
let xlSheet = oWB.Worksheets(1); //激活当前sheet
let sel = document.body.createTextRange(); //把表格中的内容移到TextRange中
sel.moveToElementText(curTbl);
sel.select;//全选TextRange中内容
sel.execCommand("Copy");//复制TextRange中内容
xlSheet.Paste(); //粘贴到活动的EXCEL中
oXL.Visible = true; //设置excel可见属性
let fName = null;
try {
fName = oXL.Application.GetSaveAsFilename("Excel.xls", "Excel Spreadsheets (*.xls), *.xls");
} catch (e) {
} finally {
oWB.SaveAs(fName);
// oWB.Close(savechanges = false);
oXL.Quit();
oXL = null;
// 下面代码用于解决IE call Excel的一个BUG, MSDN中提供的方法:
// setTimeout(CollectGarbage, 1);
// 由于不能清除(或同步)网页的受信任状态, 所以将导致SaveAs()等方法在
// 下次调用时无效.
window.location.reload();
}
} else {
tableToExcel(tableClass, fileName, 'worksheet')
}
}
const traverseNodes = (node, newTd) => {
if (node.hasChildNodes) {
const sonNodes = node.childNodes;
const filterElement = ['button'];
for (let sonNode of sonNodes) {
if (!filterElement.includes(sonNode.nodeName.toLowerCase())) { // 对不必要对element过滤
traverseNodes(sonNode, newTd);
}
}
}
return display(node, newTd);
}
const display = (node, newTd) => {
const {nodeName, nodeValue} = node;
let newSpan = document.createElement("span");
newSpan.innerText = nodeValue;
if (nodeName === 'INPUT' || nodeName === 'TEXTAREA') { // 对 input 处理
const {type, checked, value} = node;
newSpan.innerText = value;
if (type === 'radio' || type === 'checkbox') {
console.log("type", type)
newSpan.innerText = type === 'radio' ? (checked ? "●" : "○") : (checked ? "■" : "□");
newSpan.style.fontSize = '16px';
newSpan.style.paddingLeft = '15px';
}
}
if (node.nodeName === 'IMG') {
const {width, height} = node;
newTd.appendChild(node);
newTd.style.height = height + "px";
newTd.style.width = width + "px";
}
if (newSpan.innerText.trim()) {
newTd.appendChild(newSpan);
}
return newTd
}
const tableToExcel = (table, fileName, worksheet) => {
const uri = 'data:application/vnd.ms-excel;base64,';
// 定义文档的类型
const template = '<html><head><meta charset="UTF-8"></head><body><table border="1">{table}</table></body></html>';
const base64 = function (s) {
return window.btoa(unescape(encodeURIComponent(s)))
};
// 将template中的变量替换为页面内容ctx获取到的值
const format = function (s, c) {
return s.replace(/{(\w+)}/g, function (m, p) {
return c[p];
})
}
if (!table.nodeType) {
table = document.querySelector(table).cloneNode(true);
}
let newTable = document.createElement("table");
const trArray = table.getElementsByTagName('tr');
for (let trItem of trArray) {
let newTr = document.createElement("tr");
const thArray = trItem.getElementsByTagName('th');
const tdArray = trItem.getElementsByTagName('td');
for (let thItem of thArray) {
let newTh = document.createElement("th");
const {rowSpan = 1, colSpan = 1, style} = thItem;
traverseNodes(thItem, newTh);
newTh.rowSpan = rowSpan; //跨行
newTh.colSpan = colSpan; //跨列
newTh.style = style; // 样式
newTr.appendChild(newTh);
}
for (let tdItem of tdArray) {
let newTd = document.createElement("td");
const {rowSpan = 1, colSpan = 1, style} = tdItem;
traverseNodes(tdItem, newTd);
newTd.rowSpan = rowSpan; //跨行
newTd.colSpan = colSpan; //跨列
newTd.style = style; // 样式
newTr.appendChild(newTd);
}
if (newTr.childNodes.length > 1) {
newTable.appendChild(newTr);
}
}
newTable.innerHTML = newTable.innerHTML.replace(/<td/g, "<td STYLE='MSO-NUMBER-FORMAT:\\@'");
const ctx = {worksheet, table: newTable.innerHTML}; // 获取表单的名字和表单查询的内容
const a = document.createElement("a"); // 虚拟一个a 标签
// format()函数:通过格式操作使任意类型的数据转换成一个字符串
// base64():进行编码
a.href = uri + base64(format(template, ctx));
a.download = fileName + ".xls";//设置文件的名字
a.click();// 下载
}
// 获取当前浏览器
const getExplorer = () => {
const explorer = window.navigator.userAgent;
if (explorer.indexOf("MSIE") >= 0) { //ie
return 'ie';
}
else if (explorer.indexOf("Firefox") >= 0) { //firefox
return 'Firefox';
}
else if (explorer.indexOf("Chrome") >= 0) { //Chrome
return 'Chrome';
}
else if (explorer.indexOf("Opera") >= 0) { //Opera
return 'Opera';
}
else if (explorer.indexOf("Safari") >= 0) { //Safari
return 'Safari';
}
}

View File

@ -0,0 +1,200 @@
import React, {Component} from 'react';
import {Button} from 'antd';
import PropTypes from "prop-types";
const propTypes = {
tableClass: PropTypes.string, // tableClass
fileName: PropTypes.string, // 导出文件的名字
worksheet: PropTypes.string, //导出工作簿名字
// colors: PropTypes.string, // button 样式
// size: PropTypes.string, //按钮大小(lg xg sm md)
// style: PropTypes.string, // 按钮样式
// exportIcon: PropTypes.element, // 自定义导出图标
title: PropTypes.element, //名称标题
filterElement: PropTypes.array, //过滤元素
};
const defaultProps = {
tableClass: '',
fileName: "filename",
worksheet: 'worksheet',
// colors: "primary",
// size: 'sm',
// style: '',
exportIcon: null,
title: '导出',
filterElement: ['button']
};
class ExportExcel extends Component {
exportExcel = () => {
const {tableClass, fileName, worksheet} = this.props;
if (this.getExplorer() === 'ie') {
//创建AX对象excel
const curTbl = document.querySelector(tableClass).cloneNode(true);
// eslint-disable-next-line no-undef
let oXL = new ActiveXObject("Excel.Application");
let oWB = oXL.Workbooks.Add(); //获取workbook对象
let xlSheet = oWB.Worksheets(1); //激活当前sheet
let sel = document.body.createTextRange(); //把表格中的内容移到TextRange中
sel.moveToElementText(curTbl);
sel.select;//全选TextRange中内容
sel.execCommand("Copy");//复制TextRange中内容
xlSheet.Paste(); //粘贴到活动的EXCEL中
oXL.Visible = true; //设置excel可见属性
let fName = null;
try {
fName = oXL.Application.GetSaveAsFilename("Excel.xls", "Excel Spreadsheets (*.xls), *.xls");
} catch (e) {
} finally {
oWB.SaveAs(fName);
// oWB.Close(savechanges = false);
oXL.Quit();
oXL = null;
// 下面代码用于解决IE call Excel的一个BUG, MSDN中提供的方法:
// setTimeout(CollectGarbage, 1);
// 由于不能清除(或同步)网页的受信任状态, 所以将导致SaveAs()等方法在
// 下次调用时无效.
window.location.reload();
}
} else {
this.tableToExcel(tableClass, fileName, worksheet)
}
}
traverseNodes = (node, newTd) => {
if (node.hasChildNodes) {
const sonNodes = node.childNodes;
const {filterElement} = this.props;
for (let sonNode of sonNodes) {
if (!filterElement.includes(sonNode.nodeName.toLowerCase())) { // 对不必要对element过滤
this.traverseNodes(sonNode, newTd);
}
}
}
return this.display(node, newTd);
}
display = (node, newTd) => {
const {nodeName, nodeValue} = node;
let newSpan = document.createElement("span");
newSpan.innerText = nodeValue;
if (nodeName === 'INPUT' || nodeName === 'TEXTAREA') { // 对 input 处理
const {type, checked, value} = node;
newSpan.innerText = value;
if (type === 'radio' || type === 'checkbox') {
console.log("type", type)
newSpan.innerText = type === 'radio' ? (checked ? "●" : "○") : (checked ? "■" : "□");
newSpan.style.fontSize = '16px';
newSpan.style.paddingLeft = '15px';
}
}
if (node.nodeName === 'IMG') {
const {width, height} = node;
newTd.appendChild(node);
newTd.style.height = height + "px";
newTd.style.width = width + "px";
}
if (newSpan.innerText.trim()) {
newTd.appendChild(newSpan);
}
return newTd
}
tableToExcel = (table, fileName, worksheet) => {
const uri = 'data:application/vnd.ms-excel;base64,';
// 定义文档的类型
const template = '<html><head><meta charset="UTF-8"></head><body><table border="1">{table}</table></body></html>';
const base64 = function (s) {
return window.btoa(unescape(encodeURIComponent(s)))
};
// 将template中的变量替换为页面内容ctx获取到的值
const format = function (s, c) {
return s.replace(/{(\w+)}/g, function (m, p) {
return c[p];
})
}
if (!table.nodeType) {
table = document.querySelector(table).cloneNode(true);
}
let newTable = document.createElement("table");
const trArray = table.getElementsByTagName('tr');
for (let trItem of trArray) {
let newTr = document.createElement("tr");
const thArray = trItem.getElementsByTagName('th');
const tdArray = trItem.getElementsByTagName('td');
for (let thItem of thArray) {
let newTh = document.createElement("th");
const {rowSpan = 1, colSpan = 1, style} = thItem;
this.traverseNodes(thItem, newTh);
newTh.rowSpan = rowSpan; //跨行
newTh.colSpan = colSpan; //跨列
newTh.style = style; // 样式
newTr.appendChild(newTh);
}
for (let tdItem of tdArray) {
let newTd = document.createElement("td");
const {rowSpan = 1, colSpan = 1, style} = tdItem;
this.traverseNodes(tdItem, newTd);
newTd.rowSpan = rowSpan; //跨行
newTd.colSpan = colSpan; //跨列
newTd.style = style; // 样式
newTr.appendChild(newTd);
}
if (newTr.childNodes.length > 1) {
newTable.appendChild(newTr);
}
}
const ctx = {worksheet, table: newTable.innerHTML}; // 获取表单的名字和表单查询的内容
const a = document.createElement("a"); // 虚拟一个a 标签
// format()函数:通过格式操作使任意类型的数据转换成一个字符串
// base64():进行编码
a.href = uri + base64(format(template, ctx));
a.download = fileName + ".xls";//设置文件的名字
a.click();// 下载
}
// 获取当前浏览器
getExplorer = () => {
const explorer = window.navigator.userAgent;
if (explorer.indexOf("MSIE") >= 0) { //ie
return 'ie';
}
else if (explorer.indexOf("Firefox") >= 0) { //firefox
return 'Firefox';
}
else if (explorer.indexOf("Chrome") >= 0) { //Chrome
return 'Chrome';
}
else if (explorer.indexOf("Opera") >= 0) { //Opera
return 'Opera';
}
else if (explorer.indexOf("Safari") >= 0) { //Safari
return 'Safari';
}
}
render() {
const {colors, exportIcon, size, title} = this.props;
return (
<Button
// colors={colors}
// size={size}
onClick={this.exportExcel}
>
{/*{exportIcon}{title}*/}
导出
</Button>
)
}
}
ExportExcel.propTypes = propTypes;
ExportExcel.defaultProps = defaultProps;
export default ExportExcel;

View File

@ -0,0 +1,22 @@
import React, { useState, forwardRef, useEffect } from "react";
import { Input } from 'antd';
const { TextArea } = Input;
//
const WordsInput = forwardRef((props, _ref) => {
const [wordCount, setWordCount] = useState(0);
const {value} = props;
//
useEffect(()=>{
setWordCount(value && value.length || 0);
},[props])
return(
<div style={{position:'relative'}}>
<TextArea {...props} onChange={(e)=>{setWordCount(e.target.value.length);props.onChange(e.target.value)}}/>
<span style={{ position: 'absolute', bottom: '-4px', right: '12px', fontSize: '12px' }}>{wordCount}/{props.maxLength}</span>
</div>
)
})
export default WordsInput;

View File

@ -0,0 +1,401 @@
import React, { useState, useMemo, useEffect } from "react";
import { Input, Select, Button, Form, Table, Upload, Modal, Popconfirm, message } from 'antd';
import cookie from 'react-cookies';
import { exportExcel } from '../components/exportExcel.js';
import Paginationtable from "../../components/paginationTable";
import { Info } from '../../components/ModalFun';
import { expertList, deleteExpert } from "../api";
import { professionalType, reviewArea } from "../static";
import { httpUrl } from '../fetch';
import './index.scss';
import '../index.scss';
const { Search } = Input;
const Option = Select.Option;
function RegisterList({ showNotification }) {
const [reload, setReload] = useState();
const [loading, setLoading] = useState(false);
const [curPage, setCurPage] = useState(1);
const [pageSize, setPageSize] = useState(10);
const [dataList, setDataList] = useState([]);
const [total, setTotal] = useState(0);
const [searchInput, setSearchInput] = useState('');
const [searchReviewArea, setSearchReviewArea] = useState('');
const [expertType, setExpertType] = useState('')
const [dataAll, setDataAll] = useState([]);
const [download, setDownload] = useState();
const [downloading, setDownloading] = useState(false);
const [visible, setVisible] = useState(false);
function onShowSizeChange(current, pageSize) {
setCurPage(current);
setPageSize(pageSize);
}
const columns = useMemo(() => {
return [{
title: '姓名',
dataIndex: 'expertName',
width: 85,
key: 'expertName',
fixed: 'left',
},
{
title: '手机号码',
dataIndex: 'phone',
key: 'phone',
},
{
title: '最高学历',
dataIndex: 'highestDegree',
key: 'highestDegree',
width: 80,
},
{
title: '专家评估',
dataIndex: 'expertScore',
key: 'expertScore',
width: 80,
render: (text, record) => {
return text || '--'
}
},
{
title: '工作单位',
dataIndex: 'workplace',
key: 'workplace',
// width: 250,
},
{
title: '单位类别',
dataIndex: 'workplaceType',
key: 'workplaceType',
width: 80,
},
{
title: '工作性质',
dataIndex: 'workNature',
key: 'workNature',
width: 80,
},
{
title: '专业职称',
dataIndex: 'professionalTitle',
key: 'professionalTitle',
width: 120,
},
{
title: '职称职级',
dataIndex: 'titleRank',
key: 'titleRank',
width: 80,
},
{
title: '专家类别',
dataIndex: 'expertType',
key: 'expertType',
width: 80,
},
{
title: '评审领域1',
dataIndex: 'reviewAreaOne',
key: 'reviewAreaOne',
width: 100,
},
{
title: '评审领域2',
dataIndex: 'reviewAreaTwo',
key: 'reviewAreaTwo',
width: 100,
},
{
title: '评审领域3',
dataIndex: 'reviewAreaThree',
key: 'reviewAreaThree',
width: 100,
},
{
title: '毕业院校',
dataIndex: 'graduatedFrom',
key: 'graduatedFrom',
},
{
title: '院校专业',
dataIndex: 'major',
key: 'major',
},
{
title: '身份证号',
dataIndex: 'idNumber',
key: 'idNumber',
width: 170,
},
{
title: '邮箱地址',
dataIndex: 'expertEmail',
key: 'expertEmail',
width: 200,
},
{
title: '开户银行',
dataIndex: 'bankName',
key: 'bankName',
width: 110,
},
{
title: '银行账号',
dataIndex: 'bankAccount',
key: 'bankAccount',
render: (text, record) => {
return '\t' + text
}
},
{
title: '个人简介',
dataIndex: 'resumeAttachments',
key: 'resumeAttachments',
render: (text, record) => {
return text && text.map(item => {
return <a key={item.id} className="link" onClick={() => { downFile(item.id) }}>{item.fileName}</a>
})
}
},
{
title: '职称证明',
dataIndex: 'titleCertificateAttachments',
key: 'titleCertificateAttachments',
render: (text, record) => {
return text && text.map(item => {
return <a key={item.id} className="link" onClick={() => { downFile(item.id) }}>{item.fileName}</a>
})
}
},
{
title: '学术成果',
dataIndex: 'academicAchievementsAttachments',
key: 'academicAchievementsAttachments',
render: (text, record) => {
return text && text.map(item => {
return <a key={item.id} className="link" onClick={() => { downFile(item.id) }}>{item.fileName}</a>
})
}
},
{
title: '荣誉称号',
dataIndex: 'honorsAttachments',
key: 'honorsAttachments',
render: (text, record) => {
return text && text.map(item => {
return <a key={item.id} className="link" onClick={() => { downFile(item.id) }}>{item.fileName}</a>
})
}
},
{
title: '操作',
dataIndex: 'id',
key: 'action',
fixed: 'right',
render: (text, record)=>{
return <Popconfirm placement="bottom" title="你确认要删除此专家吗?" onConfirm={() => { delExpert(text);}} okText="是" cancelText="否"><Button size="small" type="primary">删除</Button></Popconfirm>
}
}
];
}, []);
function downFile(id) {
let url = httpUrl + '/busiAttachments/download/' + id;
window.open(url);
}
//
useEffect(() => {
setLoading(true);
let params = {
searchInput,
reviewArea: searchReviewArea,
expertType,
pageSize,
curPage,
statusString: '1',
};
expertList(params).then(data => {
setDataList(data.rows || []);
setLoading(false);
setTotal(data && data.total);
});
}, [curPage, reload, searchInput, searchReviewArea, expertType, pageSize]);
//
useEffect(() => {
if (!download) {
return;
}
setDownloading(true);
let params = {
searchInput,
reviewArea: searchReviewArea,
expertType,
pageSize: 10000000,
curPage: 1,
statusString: '1',
};
expertList(params).then(data => {
setDataAll(data.rows || []);
setDownloading(false);
exportExcel("#exportList .ant-table-scroll", "专家列表");
});
}, [download]);
//
const delExpert=(expertId)=>{
setLoading(true);
deleteExpert(expertId).then(response=>{
if(response && response.message === "删除专家成功"){
message.success("删除成功");
setReload(Math.random());
}else{
message.error("删除失败");
}
}).finally(()=>{
setLoading(false);
})
}
function beforeUpload(file) {
const isExcel = file.type.indexOf('xlsx') || file.type.indexOf('xls') || file.type.indexOf('sheet');
if (!isExcel) {
showNotification(`只支持.xlsx、xls格式!`);
}
return isExcel;
}
function handleChange(info) {
if (info.file.status === 'uploading' || info.file.status === 'done') {
if (info.file.response) {
let resData = info.file.response.data;
if (resData) {
Info({
title: '提示',
content: <div className="import-important">
{resData.successMessage && <div>
<p>导入成功</p>
<p dangerouslySetInnerHTML={{ __html: `导入成功! 登录账号为手机号码默认密码为12345678` }} className="mess"></p>
</div>}
{resData.failMessage && <div>
<p>导入失败</p>
<p dangerouslySetInnerHTML={{ __html: resData.failMessage }} className="mess fail"></p>
</div>}
</div>,
});
setReload(Math.random());
setVisible(false);
} else {
showNotification(info.file.response.message || '系统错误');
}
}
}
if (info.file.status === 'error') {
showNotification(info.file.response.message || '系统错误');
}
}
const upload = {
name: 'file',
action: `${httpUrl}/api/experts/registerByExcel`,
onChange: handleChange,
beforeUpload: beforeUpload,
accept: ".xlsx,.xls",
showUploadList: true,
withCredentials: true,
headers: {
Authorization: cookie.load('autologin_forge_military') || sessionStorage.osredmToken,
},
};
return (
<div className="expert-list centerbox">
<div className="center-screen" >
<div className="center-right-but">
<Form.Item label={"姓名/手机"}>
<Search
maxLength={20}
style={{ width: "300px" }}
placeholder="请输入专家姓名或手机号"
onSearch={(value) => { setSearchInput(value); setCurPage(1); }}
/>
</Form.Item>
<Form.Item label={"专家类别"}>
<Select
style={{ width: "150px" }}
placeholder="所有类别"
dropdownClassName="expert_register"
onChange={(value) => { setExpertType(value) }}>
<Option key={'all'} value="">所有类别</Option>
{professionalType.map(item => {
return <Option key={item.value} value={item.value}>{item.label}</Option>
})}
</Select>
</Form.Item>
<Form.Item label={"评审领域"}>
<Select
style={{ width: "150px" }}
placeholder="所有领域"
dropdownClassName="expert_register"
onChange={(value) => { setSearchReviewArea(value) }}>
<Option key={'all'} value="">所有领域</Option>
{reviewArea.map(item => {
return <Option key={item.value} value={item.value}>{item.label}</Option>
})}
</Select>
</Form.Item>
</div>
<div className="btn-group">
<Button type="primary" className="ml10 but41_fill" onClick={() => { setVisible(true) }}>导入</Button>
<Button type="primary" loading={downloading} className="ml10 but41_fill" onClick={() => { setDownload(Math.random()) }}>导出</Button>
</div>
</div>
<Paginationtable
loading={loading}
dataSource={dataList}
columns={columns}
total={total}
setCurPage={setCurPage}
current={curPage}
scroll={{ x: 2700 }}
onShowSizeChange={onShowSizeChange}
showSizeChanger
/>
<Table
id="exportList"
style={{ display: "none" }}
columns={columns}
dataSource={dataAll}
pagination={false}
rowKey={(row) => row.id}
/>
<Modal
title="上传"
visible={visible}
// onOk={refuse}
onCancel={() => { setVisible(false) }}
className="upload-modal"
footer={<Button onClick={() => { setVisible(false) }}>取消</Button>}
key={Math.random()}
>
<Upload
{...upload}
>
<button className="but41_fill">导入</button>
</Upload>
<p className="link" onClick={() => { window.open(httpUrl + '/busiAttachments/download/883') }}>专家注册表模板.xlsx</p>
<p className='hint'>提示只能在导入模版上增减数据才能导入成功</p>
</Modal>
</div>)
}
export default RegisterList;

View File

@ -0,0 +1,52 @@
.expert-list{
.ant-table-thead > tr > th, .ant-table-tbody > tr > td{
padding:16px 6px;
}
.center-screen{
display: flex;
justify-content: space-between;
}
.center-right-but{
flex:auto;
justify-content: space-between;
margin-right: 4em;
}
.ant-form-item-control-wrapper{
display: inline-block;
}
.btn-group{
display: flex;
}
}
.import-important{
text-align: left;
.mess{
padding-left: 20px;
&.fail{
max-height: 300px;
overflow-y: auto;
}
}
span{
color: #df0002;
margin-left: 5px;
}
}
.upload-modal{
.ant-modal-body{
text-align: center;
}
p{
line-height: 2rem;
}
.hint{
color: #df0002;
}
.link{
color: #4154f1;
&:hover{
opacity: 0.8;
}
}
}

View File

@ -0,0 +1,79 @@
import React from "react";
import { Route, Switch, Link } from "react-router-dom";
import Loadable from "react-loadable";
import Loading from "src/Loading";
import '../index.scss';
import './index.scss';
const Register = Loadable({
loader: () => import("./register"),
loading: Loading,
});
const ReviewTasks = Loadable({
loader: () => import("./reviewTasks"),
loading: Loading,
})
const TaskDetail = Loadable({
loader: () => import("./taskDetail"),
loading: Loading,
})
const ExpertUser = (propsF) => {
const functional = propsF.match.params.functional;
return (
<div className="centerbox detail">
<div className="navigation">
<span>专家评审系统</span>&nbsp;&gt;&nbsp;
{functional === 'register' && <Link to="/expert/user/register">登记专家资料</Link>}
{functional === 'tasks' && <Link to="/expert/user/tasks">我的评审任务</Link>}
</div>
<div className='center_flex'>
<div className='register_left'>
<Link to="/expert/user/register" className={`${functional === 'register' && 'active'}`}>登记专家资料</Link>
{propsF.current_user.isExpert && <Link to="/expert/user/tasks" className={`${functional === 'tasks' && 'active'}`}>我的评审任务</Link>}
</div>
<Switch {...propsF}>
{
}
<Route
path="/expert/user/tasks/:containerType/:containerId"
render={(props) => (
<TaskDetail {...propsF} {...props}/>
)}
></Route>
<Route
path="/expert/user/tasks"
render={(props) => (
<ReviewTasks {...propsF} {...props}/>
)}
></Route>
<Route
path="/expert/user/register"
render={(props) => (
<Register {...propsF} {...props}/>
)}
></Route>
<Route
path="/expert/user"
render={(props) => (
<Register {...propsF} {...props}/>
)}
></Route>
</Switch>
</div>
</div>
);
}
export default ExpertUser;

View File

@ -0,0 +1,58 @@
.centerbox.detail {
font-size: 20px;
.navigation {
font-size: 0.6em;
margin: -35px 0 15px;
a:hover{
color: #4154f1;
}
}
.center_flex {
display: flex;
justify-content: space-between;
.register_left {
display: flex;
flex-direction: column;
height: 10em;
width: 9.375rem;
font-size: 0.7em;
background-color: white;
padding: 0.4vw;
flex: none;
a{
padding: 0 1.3em;
margin: 5px;
height: 2.55em;
line-height: 2.55em;
border-radius: 4px;
&:hover{
color: #4154f1;
}
&.active {
color: white;
background-color: #4154f1;
&:hover{
opacity: .8;
}
}
}
}
.register_right {
flex: auto;
margin-left: .95rem;
.user-title{
border-bottom: 1px solid #eeeeee;
padding: 0.5em 2em;
color: #181818;
font-size: 1rem;
font-weight: bold;
background: white;
}
}
}
}

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="8px" height="8px" viewBox="0 0 8 8" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>必填@2x</title>
<g id="首页/竞赛" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="3-专家资料附件样式" transform="translate(-551.000000, -189.000000)" fill="#FF3838" fill-rule="nonzero">
<g id="姓名" transform="translate(551.000000, 180.000000)">
<g id="必填" transform="translate(0.000000, 9.000000)">
<path d="M4.27654412,3.29770588 C4.65431878,3.11552402 5.02835189,2.92568336 5.39841176,2.72830147 C5.75230147,2.53817647 6.03840441,2.39605147 6.24922059,2.30852206 C6.46005882,2.22194118 6.62569853,2.17488971 6.75370588,2.17488971 C6.96452206,2.17488971 7.14525,2.24547794 7.30334559,2.39605147 C7.45394118,2.54664706 7.53677206,2.72830147 7.53677206,2.94946324 C7.53677206,3.07652206 7.49911765,3.21017647 7.42383088,3.34475735 C7.34852206,3.47936029 7.26571324,3.56688971 7.18288235,3.60641912 C6.40736029,3.93017647 5.54148529,4.16735294 4.60782353,4.30947794 C4.78098529,4.46759559 4.98430147,4.68970588 5.23275,4.96641176 C5.48124265,5.24311765 5.60922794,5.38524265 5.62429412,5.40875735 C5.71464706,5.54336029 5.84265441,5.70994853 6.00829412,5.90759559 C6.17395588,6.10524265 6.28689706,6.25581618 6.34711765,6.36593382 C6.40733824,6.477 6.44499265,6.61065441 6.44499265,6.76969853 C6.44594618,6.96841039 6.36731868,7.15923578 6.22665441,7.29959559 C6.07968409,7.45302778 5.87428811,7.53655013 5.66194853,7.52922794 C5.43606618,7.52922794 5.17252941,7.339125 4.88640441,6.96734559 C4.60030147,6.60311029 4.22382353,5.93205882 3.77205882,4.95888971 C3.31277206,5.82853676 3.00405882,6.41393382 2.85346324,6.69063971 C2.69534559,6.96734559 2.54477206,7.18005882 2.40169853,7.32311029 C2.27249489,7.45965707 2.09274292,7.53694212 1.90475735,7.53677206 C1.69176274,7.5427387 1.48730495,7.45293529 1.34759559,7.29205147 C1.21205332,7.15136352 1.13414528,6.96499497 1.12923529,6.76969853 C1.12923529,6.59558824 1.15934559,6.46852941 1.21958824,6.38194853 C1.77677206,5.59136029 2.35652206,4.894875 2.95888235,4.31794853 C2.50348809,4.24448093 2.0513352,4.15216638 1.60358824,4.04124265 C1.16806177,3.92483944 0.742549134,3.773769 0.331125,3.58947794 C0.255816176,3.550875 0.188051471,3.46334559 0.120286765,3.32876471 C0.0465462897,3.21881617 0.0072275008,3.08939438 0.00734558824,2.95700735 C0.000185417937,2.74722261 0.0855322486,2.54488078 0.240772059,2.40359559 C0.380985405,2.25952228 0.574326753,2.17952584 0.775345588,2.18241176 C0.918419118,2.18241176 1.099125,2.22946324 1.31746324,2.31699265 C1.53582353,2.41111765 1.80688235,2.53817647 2.14570588,2.71983088 C2.48452941,2.89394118 2.86100735,3.09158824 3.29018382,3.30522794 C3.214875,2.90241176 3.14711029,2.443125 3.09441176,1.92924265 C3.04169118,1.41536029 3.019125,1.05959559 3.019125,0.869470588 C3.019125,0.632294118 3.08688971,0.434647059 3.22994118,0.268058824 C3.36156326,0.0990585155 3.56543001,0.00235741925 3.77958088,0.00734558824 C3.99794118,0.00734558824 4.17864706,0.0939485294 4.32169853,0.260536765 C4.46477206,0.434647059 4.53253676,0.655830882 4.53253676,0.932536765 C4.53253676,1.01159559 4.51747059,1.16216912 4.50240441,1.38430147 C4.48736029,1.61300735 4.44970588,1.88216912 4.41205147,2.19840441 C4.366875,2.52218382 4.32169853,2.88547059 4.27652206,3.29770588 L4.27654412,3.29770588 Z" id="路径"></path>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="32px" height="32px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>shanchu_tc_icon</title>
<g id="首页/竞赛" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="7-资料未保存提示语" transform="translate(-804.000000, -400.000000)" fill-rule="nonzero">
<g id="弹窗" transform="translate(684.000000, 298.000000)">
<g id="编组-3备份" transform="translate(121.000000, 102.000000)">
<g id="shanchu_tc_icon" transform="translate(0.000000, 1.000000)">
<path d="M15,0 C6.7155,0 0,6.7155 0,15 C0,23.2845 6.7155,30 15,30 C23.2845,30 30,23.2845 30,15 C30,6.7155 23.2845,0 15,0 Z" id="路径" stroke="#CA0002" stroke-width="1.5" fill="#CA0002"></path>
<path d="M16,20.844 C16,21.3962847 15.5522847,21.844 15,21.844 C14.4477153,21.844 14,21.3962847 14,20.844 L14,20.344 C14,19.7917152 14.4477153,19.344 15,19.344 C15.5522847,19.344 16,19.7917152 16,20.344 L16,20.844 Z" id="路径" fill="#FFFFFF"></path>
<path d="M16,16.656 C16,17.2082847 15.5522847,17.656 15,17.656 C14.4477153,17.656 14,17.2082847 14,16.656 L14,9.15600001 C14,8.60371526 14.4477153,8.15600001 15,8.15600001 C15.5522847,8.15600001 16,8.60371526 16,9.15600001 L16,16.656 Z" id="路径" fill="#FFFFFF"></path>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,593 @@
import React, { useEffect, useState, useCallback } from 'react';
import { Button, Icon, Form, Modal, Input, Select, message } from 'antd';
import Upload from '../../components/Upload';
import { unitType, natureOfWork, highestEducation, positionLevel, professionalType, reviewArea } from '../../static';
import { expertRegister, getCurrentExpert, getFile, expertUpdate } from '../../api';
import './index.scss';
import '../../index.scss';
const Option = Select.Option;
export default Form.create()(({ match, history, showNotification, form, current_user }) => {
const { getFieldDecorator, validateFields, setFieldsValue } = form;
const [cancelConfirmValue, setCancelConfirmValue] = useState(false);
const [submitConfirmValue, setSubmitConfirmValue] = useState(false);
const [expertRegisterValues, setExpertRegisterValues] = useState();
const [lastRegister, setLastRegister] = useState();
const [forbidden, setForbidden] = useState(false);
const [resumeList, setResumeList] = useState([]);
const [resumeIds, setResumeIds] = useState();
const [titleCertList, setTitleCertList] = useState([]);
const [titleCertIds, setTitleCertIds] = useState();
const [achievementList, setAchievementList] = useState([]);
const [achievementIds, setAchievementIds] = useState();
const [honorList, setHonorList] = useState([]);
const [honorIds, setHonorIds] = useState();
const [reload, setReload] = useState();
const [reviewAreaOne, setReviewAreaOne] = useState();
const [reviewAreaTwo, setReviewAreaTwo] = useState();
const [reviewAreaThree, setReviewAreaThree] = useState();
//
useEffect(() => {
let params = {};
getCurrentExpert(params).then(async res => {
if (res && res.data && res.data.length) {
let lastRegister = res.data[0];
if (res.data.length > 1 && res.data[0].status === 1) {
lastRegister = res.data[1];
}
let params = {
bankAccount: lastRegister.bankAccount || "",
bankName: lastRegister.bankName || "",
expertEmail: lastRegister.expertEmail || "",
expertName: lastRegister.expertName || "",
expertType: lastRegister.expertType || "",
graduatedFrom: lastRegister.graduatedFrom || "",
highestDegree: lastRegister.highestDegree || "",
idNumber: lastRegister.idNumber || "",
major: lastRegister.major || "",
phone: lastRegister.phone || "",
professionalTitle: lastRegister.professionalTitle || "",
reviewAreaOne: lastRegister.reviewAreaOne || "",
reviewAreaTwo: lastRegister.reviewAreaTwo || "",
reviewAreaThree: lastRegister.reviewAreaThree || "",
titleRank: lastRegister.titleRank || "",
workNature: lastRegister.workNature || "",
workplace: lastRegister.workplace || "",
workplaceType: lastRegister.workplaceType || "",
}
setReviewAreaOne(lastRegister.reviewAreaOne);
setReviewAreaTwo(lastRegister.reviewAreaTwo);
setReviewAreaThree(lastRegister.reviewAreaThree);
setFieldsValue(params);
setExpertRegisterValues(params);
setLastRegister(lastRegister);
setForbidden(lastRegister && lastRegister.status === -1);
//
if (lastRegister.resume) {
setResumeList(lastRegister.resumeAttachments);
setResumeIds(lastRegister.resume);
}
if (lastRegister.titleCertificate) {
setTitleCertList(lastRegister.titleCertificateAttachments);
setTitleCertIds(lastRegister.titleCertificate);
}
if (lastRegister.academicAchievements) {
setAchievementList(lastRegister.academicAchievementsAttachments);
setAchievementIds(lastRegister.academicAchievements);
}
if (lastRegister.honors) {
setHonorList(lastRegister.honorsAttachments);
setHonorIds(lastRegister.honors);
}
} else if(res && res.message=="未登录"){
history.push('/403');
}
else {
setForbidden(false);
}
});
}, [reload]);
function getFiles(ids) {
let idArr = ids.split(',');
let requireArr = idArr.map(i => {
return new Promise((resolve) => {
getFile(i).then((res) => {
if (res) {
res.data && resolve(res.data);
}
});
});
})
return Promise.all(requireArr);
}
//
function uploadResume(fileList, files) {
setResumeList(fileList);
setResumeIds(files);
}
function uploadTitleCert(fileList, files) {
setTitleCertList(fileList);
setTitleCertIds(files);
}
function uploadAchievement(fileList, files) {
setAchievementList(fileList);
setAchievementIds(files);
}
function uploadHonor(fileList, files) {
setHonorList(fileList);
setHonorIds(files);
}
// form
const helper = useCallback(
(label, name, rules, widget) => (
<Form.Item label={label}>
{getFieldDecorator(name, { rules, validateFirst: true })(widget)}
</Form.Item>
),
[]
);
//
function expertRegisterSubmit(e) {
form.validateFields((err, values) => {
if (!err) {
setSubmitConfirmValue(true);
setExpertRegisterValues(values);
}
})
}
//
function expertRegisterOk() {
if (expertRegisterValues) {
let params = {
bankAccount: expertRegisterValues.bankAccount || "",
bankName: expertRegisterValues.bankName || "",
expertEmail: expertRegisterValues.expertEmail || "",
expertName: expertRegisterValues.expertName || "",
expertType: expertRegisterValues.expertType || "",
graduatedFrom: expertRegisterValues.graduatedFrom || "",
highestDegree: expertRegisterValues.highestDegree || "",
idNumber: expertRegisterValues.idNumber || "",
major: expertRegisterValues.major || "",
phone: expertRegisterValues.phone || "",
professionalTitle: expertRegisterValues.professionalTitle || "",
reviewAreaOne: expertRegisterValues.reviewAreaOne || "",
reviewAreaTwo: expertRegisterValues.reviewAreaTwo || "",
reviewAreaThree: expertRegisterValues.reviewAreaThree || "",
titleRank: expertRegisterValues.titleRank || "",
workNature: expertRegisterValues.workNature || "",
workplace: expertRegisterValues.workplace || "",
workplaceType: expertRegisterValues.workplaceType || "",
resume: resumeIds,
titleCertificate: titleCertIds,
academicAchievements: achievementIds,
honors: honorIds,
userId: current_user && current_user.user_id,
status: -1,
};
if (lastRegister && [2, 3].includes(lastRegister.status)) {
expertUpdate({
...params,
id: lastRegister.id
}).then(res => {
dealBack(res);
});
} else {
expertRegister(params).then(res => {
dealBack(res)
});
}
}
}
function draft() {
form.validateFields((err, values) => {
if (!err) {
let params = {
...values,
resume: resumeIds,
titleCertificate: titleCertIds,
academicAchievements: achievementIds,
honors: honorIds,
userId: current_user.user_id,
status: 3
};
if (lastRegister && [2, 3].includes(lastRegister.status)) {
expertUpdate({
...params,
id: lastRegister.id
}).then(res => {
dealBack(res);
});
} else {
expertRegister(params).then(res => {
dealBack(res)
});
}
}
})
}
function dealBack(res) {
if (res && res.message && (res.message.indexOf("成功") > -1 || res.message.indexOf("更新") > -1)) {
message.success("保存成功")
setSubmitConfirmValue(false);
setReload(Math.random());
} else {
message.error(res && res.message || "保存失败");
}
}
function cancel() {
if (lastRegister && lastRegister.status === -1) {
history.go(-1);
} else {
setCancelConfirmValue(true);
}
}
return (
<div className='register_right'>
{
lastRegister && lastRegister.status === -1 && <p className='advance checking'>
<i className="iconfont icon-shijianicon font-15 mr10 ver-middle"></i>您的资料正在审核请耐心等待
</p>
}
{
lastRegister && lastRegister.status === 2 && <p className='advance fail'>
<i className="iconfont icon-sousuo_shanchuicon font-15 mr10 ver-middle"></i>您提交的资料已被拒绝请完善资料后重新提交
{lastRegister.reviewerAdvice && <div className='ml25'>拒绝原因{lastRegister.reviewerAdvice}</div>}
</p>
}
{
lastRegister && lastRegister.status === 1 && <p className='advance succeed'>
<i className="iconfont icon-duigou font-15 mr10 ver-middle"></i>您的资料已审核通过已成为专家若修改资料修改后需要管理员重新审核审核过程中不会影响您的专家身份
</p>
}
<div className='user-title'>专家资料</div>
<Form className='register-form'>
{
helper('姓名',
'expertName',
[{ required: true, message: "姓名不能为空" },
{ max: 20, message: '长度不能超过20个字符' }],
<Input
placeholder="请输入您的姓名"
disabled={forbidden}
/>
)
}
{
helper('最高学历',
'highestDegree',
[{ required: true, message: '请选择最高学历' }],
<Select disabled={forbidden} placeholder="请选择" dropdownClassName="expert_register">
{highestEducation.map(item => {
return <Option key={item.value} value={item.value}>{item.label}</Option>
})}
</Select>
)
}
{
helper('手机号码',
'phone',
[{ required: true, message: "手机号码不能为空" },
{
validator: (rule, val, callback) => {
const pattern = /^((\+)?86|((\+)?86)?)0?1[3456789]\d{9}$/;
if (pattern.test(val)) {
callback();
} else {
callback('请输入正确的手机号码!');
}
}
}],
<Input
placeholder="请输入您的手机号码"
disabled={forbidden}
/>
)
}
{
helper('工作单位',
'workplace',
[{ required: true, message: "工作单位不能为空" },
{ max: 50, message: '长度不能超过50个字符' }
],
<Input
placeholder="请输入您的工作单位"
disabled={forbidden}
/>
)
}
{
helper('单位类别',
'workplaceType',
[{ required: true, message: "请选择单位类别" }],
<Select disabled={forbidden} placeholder="请选择" dropdownClassName="expert_register">
{unitType.map(item => {
return <Option key={item.value} value={item.value}>{item.label}</Option>
})}
</Select>
)
}
{
helper('工作性质',
'workNature',
[{ required: true, message: "请选择工作性质" }],
<Select disabled={forbidden} placeholder="请选择" dropdownClassName="expert_register">
{natureOfWork.map(item => {
return <Option key={item.value} value={item.value}>{item.label}</Option>
})}
</Select>
)
}
{
helper('专业职称',
'professionalTitle',
[{ required: true, message: "专业职称不能为空" },
{ max: 50, message: '长度不能超过50个字符' }],
<Input
placeholder="请输入您的专业职称"
disabled={forbidden}
/>
)
}
{
helper('职称职级',
'titleRank',
[{ required: true, message: "请选择职称职级" }],
<Select disabled={forbidden} placeholder="请选择" dropdownClassName="expert_register">
{positionLevel.map(item => {
return <Option key={item.value} value={item.value}>{item.label}</Option>
})}
</Select>
)
}
{
helper('专家类别',
'expertType',
[{ required: true, message: "请选择专家类别" }],
<Select disabled={forbidden} placeholder="请选择" dropdownClassName="expert_register">
{professionalType.map(item => {
return <Option key={item.value} value={item.value}>{item.label}</Option>
})}
</Select>
)
}
{
helper('评审领域1',
'reviewAreaOne',
[{ required: true, message: "请选择评审领域" }],
<Select
disabled={forbidden}
placeholder="请选择"
dropdownClassName="expert_register"
onChange={(value) => { setReviewAreaOne(value) }}
>
{reviewArea.map(item => {
return <Option key={item.value} value={item.value}
disabled={item.value === reviewAreaTwo || item.value === reviewAreaThree}
>{item.label}</Option>
})}
</Select>
)
}
{
helper('评审领域2',
'reviewAreaTwo', [],
<Select
disabled={forbidden}
placeholder="请选择"
dropdownClassName="expert_register"
onChange={(value) => { setReviewAreaTwo(value) }}
>
{reviewArea.map(item => {
return <Option key={item.value} value={item.value}
disabled={item.value === reviewAreaOne || item.value === reviewAreaThree}
>{item.label}</Option>
})}
</Select>
)
}
{
helper('评审领域3',
'reviewAreaThree', [],
<Select
disabled={forbidden}
placeholder="请选择"
dropdownClassName="expert_register"
onChange={(value) => { setReviewAreaThree(value) }}
>
{reviewArea.map(item => {
return <Option key={item.value} value={item.value}
disabled={item.value === reviewAreaTwo || item.value === reviewAreaOne}
>{item.label}</Option>
})}
</Select>
)
}
{
helper('毕业院校',
'graduatedFrom', [{ max: 50, message: '长度不能超过50个字符' }],
<Input
placeholder="请输入您的毕业院校"
disabled={forbidden}
/>
)
}
{
helper('院校专业',
'major', [{ max: 50, message: '长度不能超过50个字符' }],
<Input
placeholder="请输入您的专业"
disabled={forbidden}
/>
)
}
{
helper('身份证号',
'idNumber', [{
validator: (rule, val, callback) => {
let _IDRe18 = /^([1-6][1-9]|50)\d{4}(18|19|20)\d{2}((0[1-9])|10|11|12)(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/
let _IDre15 = /^([1-6][1-9]|50)\d{4}\d{2}((0[1-9])|10|11|12)(([0-2][1-9])|10|20|30|31)\d{3}$/
//
if (!val) {
callback();
return
}
if (_IDRe18.test(val) || _IDre15.test(val)) {
callback();
}
else {
callback('请输入正确的身份证号码!');
}
}
}],
<Input
placeholder="请输入您的身份证号码"
disabled={forbidden}
/>
)
}
{
helper('邮箱地址',
'expertEmail', [{
validator: (rule, val, callback) => {
const pattern = /^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;
if (!val) {
callback();
return;
}
if (pattern.test(val)) {
callback();
} else {
callback('请输入正确的邮箱地址!');
}
}
}],
<Input
placeholder="请输入您的常用邮箱地址"
disabled={forbidden}
/>
)
}
{
helper('开户银行',
'bankName', [{ max: 50, message: '长度不能超过50个字符' }],
<Input
placeholder="请输入您的开户银行"
disabled={forbidden}
/>
)
}
{
helper('银行账号',
'bankAccount', [{ max: 50, message: '长度不能超过50个字符' }],
<Input
placeholder="请输入您的银行卡号"
disabled={forbidden}
/>
)
}
<Form.Item className="upload-form" label="个人简介">
<Upload
load={uploadResume}
size={100}
showNotification={showNotification}
fileList={resumeList}
disabled={forbidden}
count={1}
/>
</Form.Item>
<Form.Item className="upload-form" label="职称证明">
<Upload
load={uploadTitleCert}
size={100}
showNotification={showNotification}
fileList={titleCertList}
disabled={forbidden}
count={1}
/>
</Form.Item>
<Form.Item className="upload-form" label="学术成果">
<Upload
load={uploadAchievement}
size={100}
showNotification={showNotification}
fileList={achievementList}
disabled={forbidden}
count={1}
/>
</Form.Item>
<Form.Item className="upload-form" label="荣誉称号">
<Upload
load={uploadHonor}
size={100}
showNotification={showNotification}
fileList={honorList}
disabled={forbidden}
count={1}
/>
</Form.Item>
<div className='hint'>提示个人简介职称证明学术成果荣誉称号都只能上传一个文件建议上传zip或rar格式的压缩文件</div>
</Form>
<div className='buts'>
{/* 专家: 修改,非专家: 提交 */}
<Button className="but41_fill mr20" type="primary" disabled={forbidden} onClick={() => expertRegisterSubmit(true)}>{current_user.expert ? '修改' : '提交'}资料</Button>
{(!lastRegister || lastRegister.status !== 1) && <Button className="but41_border mr20" disabled={forbidden} onClick={draft}>保存资料</Button>}
<Button className="butE3_border" onClick={cancel}>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</Button>
<Modal
title={`${lastRegister && lastRegister.status === 1 ? '修改' : '提交'}资料`}
visible={submitConfirmValue}
onOk={expertRegisterOk}
onCancel={() => setSubmitConfirmValue(false)}
wrapClassName="expert_modal submit"
closeIcon={<Icon className='iconfont icon-guanbi1' />}
>
<p className=''>资料提交后无法修改将等待管理员审核</p>
<p className=''>确认{lastRegister && lastRegister.status === 1 ? '修改' : '提交'}</p>
</Modal>
<Modal
title="提交资料"
visible={cancelConfirmValue}
onOk={() => { history.go(-1) }}
onCancel={() => setCancelConfirmValue(false)}
wrapClassName="expert_modal"
>
<p className='weight_bold warning'>有内容没有保存确定退出编辑吗</p>
<p className='ml30'>退出编辑后更新的内容不会自动保存</p>
</Modal>
</div>
</div>
)
})

View File

@ -0,0 +1,101 @@
.center_flex {
display: flex;
justify-content: space-between;
.register_left {
height: 10em;
font-size: 0.7em;
background-color: white;
padding: 0.4vw;
}
.register_right {
.advance {
padding: 0.5em 2em;
color: #181818;
font-size: 0.9rem;
font-weight: bold;
margin-bottom: 1.25rem !important;
background: white;
}
.iconfont {
font-weight: 400;
}
.fail {
background: #ffefef;
border: 1px solid #ff3838;
color: #ff3838;
}
.checking {
background: #edf2ff;
border: 1px solid #4154f1;
color: #4154f1;
}
.succeed {
background: #edf2ff;
border: 1px solid green;
color: green;
}
.ant-form {
background-color: white;
padding: 1em 0;
}
.register-form {
.ant-form-item {
display: inline-block;
width: 44%;
margin: 1em 2.5% 0;
}
.hint {
margin: 1em 3% 0 4%;
color: #999;
}
.upload-form {
display: inline-flex;
align-items: flex-start;
}
.ant-form-item-label {
width: 6em;
line-height: 2.8em;
}
.ant-form-item-required::before {
position: relative;
top: -1px;
content: url("./image/required.svg");
}
.ant-form-item-control-wrapper {
width: 70%;
display: inline-block;
}
.ant-input,
.ant-select-selection {
// width: 30.1em;
box-shadow: none;
&:focus,
&:hover {
border: 1px solid #4154f1 !important;
}
}
.ant-input,
.ant-input .ant-input-suffix {
background-color: #ffffff !important;
}
.ant-select-open .ant-select-selection {
border: 1px solid #4154f1 !important;
}
}
.ant-cascader-menu-item:hover {
background: #f2f3ff;
}
.buts {
font-size: 0.7em;
padding: 1.5em 2em;
background-color: #f5f5f5;
}
}
}
.expert_register .ant-select-dropdown-menu-item:hover,
.ant-select-dropdown-menu-item-active:not(.ant-select-dropdown-menu-item-disabled) {
background-color: #f2f3ff;
}

View File

@ -0,0 +1,203 @@
import React, { useState, useCallback, useMemo, useEffect } from "react";
import { Input, Select, Button, Form, DatePicker, Table, Pagination, Upload, Modal } from 'antd';
import { Link } from "react-router-dom";
import { formatDuring } from 'educoder';
import Paginationtable from "../../../components/paginationTable";
import { getExpertTasks } from "../../api";
import { taskType, expertTaskStatus } from "../../static";
import { main_web_site_url } from '../../fetch';
import './index.scss';
import '../../index.scss';
const Option = Select.Option;
function ReviewTasks({ form, showNotification, match, history }) {
const { getFieldDecorator, setFieldsValue, getFieldsValue } = form;
const [reload, setReload] = useState();
const [loading, setLoading] = useState(false);
const [curPage, setCurPage] = useState(1);
const [pageSize, setPageSize] = useState(10);
const [dataList, setDataList] = useState([]);
const [total, setTotal] = useState(0);
let initSearchObj = sessionStorage.expertTask ? JSON.parse(sessionStorage.expertTask) : {
containerName: '',
containerType: 1,
statusString: -1,
};
const [searchObj, setSearchObj] = useState(initSearchObj);
useEffect(() => {
setFieldsValue(initSearchObj);
}, []);
const columns = useMemo(() => {
return [
{
title: '序号',
dataIndex: 'index',
render: (text, record, index) => {
return index + 1
}
},
{
title: '任务名称',
dataIndex: 'containerName',
key: 'containerName',
render: (text, record) => {
return record.containerType===1?<Link to={`/task/taskDetail/${record.containerId}`}>{text}</Link>:
<a className="taskLink ml10" target="_blank" href={`${main_web_site_url}/competitions/${record.containerIdentifier}/home`} >{text}</a>
}
},
{
title: '评审截止时间',
dataIndex: 'reviewEndOn',
key: 'reviewEndOn',
},
{
title: '剩余评审时间',
dataIndex: 'surplus',
key: 'surplus',
},
{
title: '评审状态',
dataIndex: 'status',
key: 'status',
render: (text, record) => {
return text === -1 ? '未评审' : record.commitReview ? '已评审' : '已过期'
}
},
{
title: '操作',
dataIndex: 'status',
key: 'action',
render: (text, record) => {
return <Link to={`/expert/user/tasks/${record.containerType}/${record.containerId}`} className="toReview">{text === -1 ? '评审' : '查看结果'}</Link>
}
}
];
}, []);
//
useEffect(() => {
setLoading(true);
let params = {
...searchObj,
pageSize,
curPage,
};
getExpertTasks(params).then(res => {
for (const item of res.data.rows) {
if (new Date(item.reviewEndOn) > new Date()) {
item.surplus = formatDuring((new Date(item.reviewEndOn) - new Date()) / 1000);
} else {
item.surplus = '- -';
}
}
setDataList(res.data.rows || []);
setLoading(false);
setTotal(res.data.total);
});
}, [searchObj, curPage, reload, pageSize]);
function onSearch() {
let values = getFieldsValue(['containerName', 'containerType', 'statusString']);
sessionStorage.setItem('expertTask', JSON.stringify(values));
setSearchObj(values);
}
function clearSearch() {
let initSearchObj={
containerName: '',
containerType: 1,
statusString: -1,
};
setFieldsValue(initSearchObj);
setSearchObj(initSearchObj);
sessionStorage.setItem('expertTask', JSON.stringify(initSearchObj));
setCurPage(1);
}
const helper = useCallback(
(label, name, rules, widget, initialValue) => (
<Form.Item label={label}>
{getFieldDecorator(name, { rules, initialValue, validateFirst: true, })(widget)}
</Form.Item>
), []);
function onShowSizeChange(current, pageSize) {
setCurPage(current);
setPageSize(pageSize);
}
return (
<div className='register_right task_right'>
<p className="task-head">
我的评审任务
</p>
<div className="search-list" >
{helper(
"任务名称",
"containerName",
[{ max: 20, message: '长度不能超过20个字符' }],
<Input
style={{ width: "250px" }}
placeholder="输入任务名称进行检索"
/>
)}
{helper(
"任务类型",
"containerType",
[],
<Select
style={{ width: "250px" }}
placeholder="所有领域"
dropdownClassName="expert_register"
>
{taskType.map(item => {
return <Option key={item.value} value={item.value}>{item.label}</Option>
})}
</Select>,
1
)}
{helper(
"评审状态",
"statusString",
[],
<Select
style={{ width: "250px" }}
placeholder="所有领域"
dropdownClassName="expert_register"
>
{expertTaskStatus.map(item => {
return <Option key={item.value} value={item.value}>{item.label}</Option>
})}
</Select>,
-1
)}
<div className="button-div">
<Button className="mr10" type="primary" onClick={onSearch}>搜索</Button>
<Button className="mr10" onClick={clearSearch}>清除</Button>
</div>
</div>
<Paginationtable
loading={loading}
dataSource={dataList}
columns={columns}
total={total}
setCurPage={setCurPage}
current={curPage}
onShowSizeChange={onShowSizeChange}
/>
</div>
)
}
export default Form.create()(ReviewTasks);

View File

@ -0,0 +1,45 @@
.register_right.task_right {
background: #fff;
padding-bottom: 1rem;
.search-list {
display: flex;
flex-wrap: wrap;
margin: 0;
padding: 1rem 2rem;
// align-items: center;
.ant-form-item {
width: 48%;
margin-bottom:1rem;
label{
font-weight: bold;
}
}
.ant-col{
display: inline-block;
}
}
.pagination-table .ant-table-thead tr th div {
font-weight: bold;
}
.task-head {
border-bottom: 1px solid #eeeeee;
padding: 0.5em 2em;
color: #181818;
background: #fff;
font-size: 0.8em;
font-weight: bold;
}
.button-div {
margin-left:.25rem;
line-height: 1.5;
}
.pagination-table{
margin:0 2rem;
.toReview{
color: #4154f1;
&:hover{
opacity: 0.8;
}
}
}
}

View File

@ -0,0 +1,511 @@
import React, { useState, useCallback, useMemo, useEffect } from "react";
import { Tabs, Button, Form, InputNumber, Modal, Tooltip, } from 'antd';
import { Link } from "react-router-dom";
import Paginationtable from "../../../components/paginationTable";
import { Info, Confirm } from '../../../components/ModalFun';
import WordsInput from 'military/expert/components/wordsInput';
import { getScoringDetails, initScoringDetails, getRules, updateScoringDetails, getCompetition } from "../../api";
import { readyCheckPapers } from "../../../task/api";
import { httpUrl, main_web_site_url } from '../../fetch';
import './index.scss';
import '../../index.scss';
const { TabPane } = Tabs;
function ReviewTasks({ showNotification, match, history, current_user }) {
const containerId = match.params.containerId;
const containerType = match.params.containerType;
// table
const [reload, setReload] = useState();
const [loading, setLoading] = useState(false);
const [dataList, setDataList] = useState([]);
const [taskId, setTaskId] = useState();
const [competitionId, setCompetitionId] = useState();
//
const [rules, setRules] = useState({});
//
const [visible, setVisible] = useState(false);
const [activeIndex, setActiveIndex] = useState(false);
const [comments, setComments] = useState();
//
const [disabled, setDisabled] = useState(false);
//
const columns = [
{
title: '序号',
dataIndex: 'index',
width: 50,
render: (text, record, index) => {
return index + 1
}
},
{
title: '投稿详情',
dataIndex: 'opsContent',
key: 'opsContent',
className: 'text-tooltip',
render: (text, record, index) => {
return <Tooltip overlayClassName="expert-tooltip" title={text} placement="top">{text}</Tooltip>
}
},
{
title: '附件下载',
dataIndex: 'opsFilesAttachments',
key: 'opsFilesAttachments',
className: 'text-tooltip',
render: (text, record) => {
return text && text.map(item => {
return <Tooltip key={item.id} overlayClassName="expert-tooltip" title={item.fileName} placement="top">
<p className="link" onClick={() => { downFile(item) }}>{item.fileName}</p>
</Tooltip>
})
}
},
{
title: '平均分',
dataIndex: 'gradesAverage',
key: 'gradesAverage',
width: 70,
},
{
title: '评审意见',
dataIndex: 'comments',
key: 'comments',
width: 80,
render: (text, record, index) => {
return <Tooltip overlayClassName="expert-tooltip" title={text} placement="top">
<a className="link" onClick={() => { writeComments(text, index, 'comments') }}>{record.status === 2 ? text ? '编辑' : '填写' : '查看'}意见</a>
</Tooltip>
}
},
];
//
const gradesColumns = [{
title: '评分一',
dataIndex: 'gradesOne',
key: 'gradesOne',
render: (text, record, index) => {
return <InputNumber min={0} max={100} value={text} precision={0} disabled={disabled}
onChange={(value) => { editGrade(value, index, 'gradesOne') }}
/>
}
},
{
title: '评分二',
dataIndex: 'gradesTwo',
key: 'gradesTwo',
render: (text, record, index) => {
return <InputNumber min={0} max={100} value={text} precision={0} disabled={disabled}
onChange={(value) => { editGrade(value, index, 'gradesTwo') }}
/>
}
},
{
title: '评分三',
dataIndex: 'gradesThree',
key: 'gradesThree',
render: (text, record, index) => {
return <InputNumber min={0} max={100} value={text} precision={0} disabled={disabled}
onChange={(value) => { editGrade(value, index, 'gradesThree') }}
/>
}
},
{
title: '评分四',
dataIndex: 'gradesFour',
key: 'gradesFour',
render: (text, record, index) => {
return <InputNumber min={0} max={100} value={text} precision={0} disabled={disabled}
onChange={(value) => { editGrade(value, index, 'gradesFour') }}
/>
}
},
{
title: '评分五',
dataIndex: 'gradesFive',
key: 'gradesFive',
render: (text, record, index) => {
return <InputNumber min={0} max={100} value={text} precision={0} disabled={disabled}
onChange={(value) => { editGrade(value, index, 'gradesFive') }}
/>
}
}];
let gradesNum = rules.criterias && rules.criterias.length;
if (gradesNum) {
let thisGradesColumns = gradesColumns.slice(0, gradesNum);
columns.splice(3, 0, ...thisGradesColumns);
}
useEffect(() => {
getRules({ containerId, containerType }).then(res => {
if (res && res.message === "success") {
setRules(res.data);
if (res.data.status === 1 || res.data.status === 2) {
setDisabled(true);
}
}
});
}, [])
//
useEffect(() => {
let params = {
taskId,
checkStatus: '1',
pageSize: 10000,
curPage: 1,
status: '',
parentId: 0,
}
//
!dataList.length && taskId && current_user.expertId && readyCheckPapers(params).then(data => {
let dataArr = [];
if (data && Array.isArray(data.rows)) {
for (const item of data.rows) {
dataArr.push({
comments: "",
expertId: current_user.expertId,
gradesAverage: '',
gradesFive: '',
gradesFour: '',
gradesOne: '',
gradesThree: '',
gradesTwo: '',
opsContent: item.paperDetail && item.paperDetail.content,
opsFiles: item.paperDetail && item.paperDetail.files,
opsFilesAttachments: item.paperDetail && item.paperDetail.busiAttachments,
opsId: item.id,
opsParentId: containerId,
opsParentType: containerType,
opsType: containerType,
status: 2
});
}
}
setDataList(dataArr);
disabled && setLoading(false);
!disabled && dataArr.length && rules && initScoringDetails(dataArr).then(res => {
if (res) {
setReload(Math.random());
setLoading(false);
}
});
});
}, [taskId, disabled, current_user.expertId]);
//
useEffect(() => {
//
!dataList.length && competitionId && current_user.expertId && getCompetition(competitionId).then(res => {
let dataArr = [];
if (res && Array.isArray(res.data)) {
for (const item of res.data) {
dataArr.push({
comments: "",
expertId: current_user.expertId,
gradesAverage: '',
gradesFive: '',
gradesFour: '',
gradesOne: '',
gradesThree: '',
gradesTwo: '',
opsContent: item.works_remark,
opsFiles: item.work_file.id,
opsFilesAttachments: item.work_file,
opsId: item.id,
opsParentId: containerId,
opsParentType: containerType,
opsType: containerType,
status: 2
});
}
}
setDataList(dataArr);
!dataArr.length && setLoading(false);
disabled && setLoading(false);
!disabled && dataArr.length && rules && initScoringDetails(dataArr).then(res => {
if (res) {
setReload(Math.random());
setLoading(false);
}
});
});
}, [competitionId, disabled, current_user.expertId]);
function downFile(item) {
if (containerType == 1) {
let url = httpUrl + '/busiAttachments/download/' + item.id;
window.open(url);
} else {
let url = main_web_site_url + `/attachments/send_file/${item.id}?disposition=attachment`;
window.open(url);
}
}
function editGrade(value, index, dataIndex) {
let dataListNew = dataList.slice();
dataListNew[index][dataIndex] = value;
//
if (gradesNum) {
let gradesArr = [];
let item = dataListNew[index];
typeof item.gradesOne === 'number' && gradesArr.push(item.gradesOne);
typeof item.gradesTwo === 'number' && gradesArr.push(item.gradesTwo);
typeof item.gradesThree === 'number' && gradesArr.push(item.gradesThree);
typeof item.gradesFour === 'number' && gradesArr.push(item.gradesFour);
typeof item.gradesFive === 'number' && gradesArr.push(item.gradesFive);
if (gradesArr.length === gradesNum) {
const sum = gradesArr.reduce((previousValue, currentValue) => { return previousValue + currentValue }, 0);
const ave = (sum / gradesNum).toFixed(2);
dataListNew[index].gradesAverage = ave > 100 ? 100 : ave;
} else {
dataListNew[index].gradesAverage = '';
}
}
setDataList(dataListNew);
}
//
useEffect(() => {
setLoading(true);
let params = {
containerId,
containerType,
expertId: current_user.expertId,
};
current_user.expertId && getScoringDetails(params).then(res => {
if (res.data && res.data.length) {
setDataList(res.data);
setLoading(false);
if (res.data[0].status === 1) {
setDisabled(true);
}
} else {
containerType == 1 ? setTaskId(containerId) : setCompetitionId(containerId);
}
});
}, [reload, current_user.expertId]);
function cancel() {
history.go(-1);
}
function writeComments(text, index) {
setVisible(true);
setActiveIndex(index);
setComments(text);
}
//
function commit() {
if (disabled) {
setVisible(false);
return;
}
if (comments) {
let data = dataList[activeIndex];
let dataListNew = dataList.slice();
data.comments = comments;
updateScoringDetails([data]).then(res => {
if (res && res.message) {
if (res.message.indexOf("成功")) {
showNotification("保存成功");
dataListNew[activeIndex].comments = comments;
setDataList(dataListNew);
setVisible(false);
} else {
showNotification(res.message);
}
}
})
}
}
// 稿
function draft() {
updateScoringDetails(dataList).then(res => dealCommitRes(res));
}
//
function commitGrades() {
if (verify()) {
Confirm({
title: '提醒',
okText: '确定提交',
content: <div>
<p>提交后将完成此次评审无法继续修改评分与评审意见</p>
<p>确定提交此次评审结果</p>
</div>,
onOk: () => {
let dataArr = dataList.slice();
for (const item of dataArr) {
item.status = 1;
}
updateScoringDetails(dataArr).then(res => dealCommitRes(res));
}
});
}
}
//
function verify() {
let errorArr = [];
let commentsError = [];
let scoringArr = [];
for (const [index, item] of dataList.entries()) {
let gradesArr = [];
typeof item.gradesOne === 'number' && gradesArr.push(item.gradesOne);
typeof item.gradesTwo === 'number' && gradesArr.push(item.gradesTwo);
typeof item.gradesThree === 'number' && gradesArr.push(item.gradesThree);
typeof item.gradesFour === 'number' && gradesArr.push(item.gradesFour);
typeof item.gradesFive === 'number' && gradesArr.push(item.gradesFive);
if (gradesArr.length < gradesNum && gradesArr.length) {
errorArr.push(index + 1);
} else if (!item.comments && gradesArr.length) {
commentsError.push(index + 1);
} else if (gradesArr.length) {
scoringArr.push(index);
}
}
if (errorArr.length) {
Info({
title: '提醒',
content: `${errorArr.join('')}行数据请填写完整`,
});
return;
}
if (commentsError.length) {
Info({
title: '提醒',
content: `${commentsError.join('')}行数据请填写意见`,
});
return;
}
if (!scoringArr.length) {
Info({
title: '提醒',
content: '请至少填写一行分数',
});
return;
}
return !errorArr.length && !commentsError.length;
}
function dealCommitRes(res) {
if (res && res.message) {
if (res.message.indexOf("成功")) {
showNotification("保存成功");
setReload(Math.random());
} else {
showNotification(res.message);
}
}
}
return (
<div className='register_right task_detail'>
<p className="task-head">
{containerType == 1 ? '创客成果' : '竞赛作品'}评审
<button className="back-button but41_border" onClick={() => { history.goBack() }}>返回上一页</button>
</p>
<Tabs defaultActiveKey="0" animated={false}>
<TabPane tab="评审信息" key="0">
<div className="task-rules">
<div className="rules-box">
<p className="rules-head">{containerType == 1 ? '任务信息' : '赛事信息'}</p>
<div className="rules-content">
<div className="rules-content-item">
<span className="font-w">{containerType == 1 ? '任务' : '赛事'}名称</span>
<span className="ml10">{rules.containerName}</span>
</div>
<div className="rules-content-item">
<span className="font-w">{containerType == 1 ? '任务' : '赛事'}链接</span>
{containerType == 1 && <Link className="taskLink ml10" target="_blank" to={`/task/taskDetail/${rules.containerId}`} >{`${window.location.origin}/task/taskDetail/${rules.containerId}`}</Link>}
{containerType == 2 && <a className="taskLink ml10" target="_blank" href={`${main_web_site_url}/competitions/${rules.containerIdentifier}/home`} >{`${main_web_site_url}/competitions/${rules.containerIdentifier}/home`}</a>}
</div>
</div>
</div>
<div className="rules-box">
<p className="rules-head">评审规则</p>
<div className="rules-content">{rules.rule}</div>
</div>
<div className="rules-box">
<p className="rules-head">评分标准</p>
<div className="rules-content">
{rules.criterias && rules.criterias.map((item, index) => { return <p className="rules-content-item" key={index}>{item}</p> })}
</div>
</div>
<div className="rules-box">
<p className="rules-head">评审时间</p>
<div className="rules-content-last">{rules.reviewData}</div>
</div>
</div>
</TabPane>
<TabPane tab="专家评分" key="1">
<div>
<div className="box"></div>
<div className="warning">对单个作品评分时需填写完整每个评分项及评审意见请勿少填漏填</div>
<Paginationtable
loading={loading}
dataSource={dataList}
columns={columns}
pagination={false}
/>
<div className="text-center">
<Button className="mr10" type="primary" disabled={disabled} onClick={commitGrades}>提交评审结果</Button>
<Button className="mr10" disabled={disabled} onClick={draft}>保存评审结果</Button>
<Button className="butE3_border" onClick={cancel}>取消</Button>
</div>
</div>
</TabPane>
</Tabs>
<Modal
title="填写意见"
visible={visible}
onOk={commit}
onCancel={() => { setVisible(false) }}
className="form-edit-modal"
>
<Form.Item >
<WordsInput
value={comments}
placeholder="请填写"
autoSize={{ minRows: 6 }}
className="applyText"
maxLength={250}
onChange={setComments}
disabled={disabled}
/>
</Form.Item>
</Modal>
</div>
)
}
export default ReviewTasks;

View File

@ -0,0 +1,115 @@
.register_right.task_detail {
background: #fff;
padding-bottom: 1rem;
.ant-tabs {
background: #f5f5f5;
.ant-tabs-content {
background: #fff;
}
.ant-tabs-bar {
background: #fff;
margin-bottom: 1.25rem;
}
.ant-tabs-tab {
margin: 0;
padding: 19px 32px;
font-size: 1rem;
&:hover {
color: #4154f1;
}
}
.ant-tabs-ink-bar {
background-color: #4154f1;
}
}
.ant-tabs-nav .ant-tabs-tab-active, .taskLink {
color: #4154f1;
}
.taskLink:hover{
opacity: 0.8;
}
.rules-head, .task-head, .ant-tabs-nav .ant-tabs-tab-active, .font-w, .pagination-table .ant-table-thead tr th div{
font-weight: bold;
}
.task-head {
position: relative;
border-bottom: 1px solid #eeeeee;
padding: 0.5em 2em;
color: #181818;
background: #fff;
font-size: 0.8em;
.back-button{
position: absolute;
z-index: 1;
right: 1rem;
bottom: -52px;
padding: 0 10px;
}
}
.button-div {
line-height: 1.5;
}
.pagination-table {
margin: .75rem 1.75rem 1.25rem;
a{
color: #4154f1;
&:hover{
opacity: 0.8;
}
}
}
.task-rules {
background: #f5f5f5;
.rules-box{
margin-bottom: 1.25rem;
background: #fff;
}
.rules-head {
font-size: 16px;
color: rgba(51, 51, 51, 1);
border-bottom: 1px solid #eeeeee;
padding: 10px 20px;
}
.rules-content{
padding: 10px 20px 30px;
}
.rules-content-last{
padding: 10px 20px;
}
.rules-content-item{
line-height: 2rem;
}
}
.warning{
color: #DE0000;
font-size: .7rem;
margin: .75rem 1.75rem;
}
.text-tooltip{
max-width: 150px;
overflow: hidden;
span{
display: block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.link{
color: #4154f1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
&:hover{
opacity: 0.8;
}
}
}
}

View File

@ -0,0 +1,11 @@
import javaFetch from '../javaFetch';
let settings = localStorage.chromesetting && JSON.parse(localStorage.chromesetting);
let actionUrl = settings && settings.api_urls && settings.api_urls.expert ? settings.api_urls.expert : 'http://117.50.100.12:8066';
// http://117.50.100.12:8067/
const service = javaFetch(actionUrl);
export const httpUrl = actionUrl;
export const main_web_site_url = settings && settings.main_web_site_url;
export default service;

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="32px" height="32px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>shanchu_tc_icon</title>
<g id="首页/竞赛" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="7-资料未保存提示语" transform="translate(-804.000000, -400.000000)" fill-rule="nonzero">
<g id="弹窗" transform="translate(684.000000, 298.000000)">
<g id="编组-3备份" transform="translate(121.000000, 102.000000)">
<g id="shanchu_tc_icon" transform="translate(0.000000, 1.000000)">
<path d="M15,0 C6.7155,0 0,6.7155 0,15 C0,23.2845 6.7155,30 15,30 C23.2845,30 30,23.2845 30,15 C30,6.7155 23.2845,0 15,0 Z" id="路径" stroke="#CA0002" stroke-width="1.5" fill="#CA0002"></path>
<path d="M16,20.844 C16,21.3962847 15.5522847,21.844 15,21.844 C14.4477153,21.844 14,21.3962847 14,20.844 L14,20.344 C14,19.7917152 14.4477153,19.344 15,19.344 C15.5522847,19.344 16,19.7917152 16,20.344 L16,20.844 Z" id="路径" fill="#FFFFFF"></path>
<path d="M16,16.656 C16,17.2082847 15.5522847,17.656 15,17.656 C14.4477153,17.656 14,17.2082847 14,16.656 L14,9.15600001 C14,8.60371526 14.4477153,8.15600001 15,8.15600001 C15.5522847,8.15600001 16,8.60371526 16,9.15600001 L16,16.656 Z" id="路径" fill="#FFFFFF"></path>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,181 @@
// 公共样式
.but41_fill,
.but41_border,
.butE3_border {
padding: 0 1.3em;
height: 36px;
border-radius: 4px;
cursor: pointer;
}
.but41_fill {
color: white;
background-color: #4154f1;
&:hover {
background-color: #5d6eff;
}
&:active {
background-color: #374bf2;
}
}
.but41_border {
color: #4154f1;
border: 1px solid #4154f1;
&:hover {
color: #5d6eff;
border: 1px solid #5d6eff;
}
&:active {
color: #374bf2;
border: 1px solid #374bf2;
}
}
.butE3_border {
color: #404660;
border: 1px solid #e3e7ed;
&:hover {
background-color: #f8f8f8;
border: 1px solid #e3e7ed;
}
&:active {
background-color: #f3f3f3;
border: 1px solid #e3e7ed;
}
}
.ant-btn-primary {
background-color: #4154f1;
border-color: #4154f1;
&:hover,
&:active,
&:focus {
background-color: #5d6eff;
border-color: #5d6eff;
}
}
.font-w{
font-weight: bold;
}
.font-color-18{
color: #181818;
}
.mt10.pb20 .taskLink{
color:#4154F1;
&:hover{opacity: 0.8;}
}
//弹出确认框样式
.expert_modal .ant-modal-content {
width: 550px;
height: 318px;
.ant-modal-header {
padding: 0.6em 2.1em;
background: #f2f2ff;
.ant-modal-title {
text-align: left;
}
}
.ant-modal-body {
padding-left: 120px;
p {
font-size: 16px;
color: #666666;
font-family: PingFangSC-Regular, PingFang SC;
line-height: 2.9em;
}
.weight_bold {
font-weight: bold;
}
.warning::before {
content: url("./image/warning.svg");
width: 32px;
position: relative;
top: 11px;
left: -15px;
}
}
.ant-btn {
padding: 0 1.3em;
height: 2.55em;
border-radius: 4px;
cursor: pointer;
color: #404660;
border: 1px solid #e3e7ed;
width: 7em;
&:hover {
background-color: #f8f8f8;
border: 1px solid #e3e7ed;
}
&:active {
background-color: #f3f3f3;
border: 1px solid #e3e7ed;
}
}
.ant-btn.ant-btn-primary {
color: white;
background-color: #4154f1;
margin-left: 2.5em;
&:hover {
background-color: #5d6eff;
}
&:active {
background-color: #374bf2;
}
}
.ant-modal-footer {
margin-top: 15px;
}
}
.expert_modal.submit .ant-modal-body {
padding-left: 0;
text-align: center;
}
.ant-form-explain,
.ant-form-split {
position: absolute;
margin-top: -5px;
font-size: 12px;
color: #f5222d;
}
.form-edit-modal {
.ant-modal-header {
background: #f2f2ff;
padding: 9px 24px;
.ant-modal-title {
text-align: left;
}
}
.ant-modal-close {
top: 0px !important;
}
.ant-modal-body{
padding-bottom: 0;
}
.ant-form-item{
margin-bottom: 24px;
}
.ant-form-explain, .ant-form-extra{
margin-top: 0;
}
.ant-modal-footer{
padding-bottom: 1.5rem;
}
}
.expert-tooltip{
.ant-tooltip-inner{
background-color: #fff;
color: #333;
}
.ant-tooltip-arrow::before{
background-color: #fff;
}
}

View File

@ -0,0 +1,300 @@
import React, { useState, useCallback, useMemo, useEffect } from "react";
import { Input, Select, Button, Form, Modal } from 'antd';
import Paginationtable from "../../components/paginationTable";
import { Confirm } from '../../components/ModalFun';
import { expertList, registerCheck } from "../api";
import { httpUrl } from '../fetch';
import './index.scss';
import '../index.scss';
const { Search, TextArea } = Input;
function RegisterList({ showNotification, form }) {
const { getFieldDecorator, validateFields, setFieldsValue, } = form;
const [reload, setReload] = useState();
const [loading, setLoading] = useState(false);
const [curPage, setCurPage] = useState(1);
const [dataList, setDataList] = useState([]);
const [total, setTotal] = useState(0);
const [searchInput, setSearchInput] = useState('');
const [pageSize, setPageSize] = useState(10);
const [visible, setVisible] = useState(false);
const [active, setActive] = useState({});
const columns = useMemo(() => {
return [{
title: '姓名',
dataIndex: 'expertName',
width: 75,
key: 'expertName',
fixed: 'left',
// render: (text, record) => {
// return record.user ? record.user.nickname || record.user.login : ''
// }
},
{
title: '最高学历',
dataIndex: 'highestDegree',
key: 'highestDegree',
width: 80,
},
{
title: '手机号码',
dataIndex: 'phone',
key: 'phone',
},
{
title: '工作单位',
dataIndex: 'workplace',
key: 'workplace',
},
{
title: '单位类别',
dataIndex: 'workplaceType',
width: 80,
},
{
title: '工作性质',
dataIndex: 'workNature',
width: 80,
},
{
title: '专业职称',
dataIndex: 'professionalTitle',
width: 120,
},
{
title: '职称职级',
dataIndex: 'titleRank',
width: 80,
},
{
title: '专家类别',
dataIndex: 'expertType',
width: 80,
},
{
title: '评审领域1',
dataIndex: 'reviewAreaOne',
width: 100,
},
{
title: '评审领域2',
dataIndex: 'reviewAreaTwo',
width: 100,
},
{
title: '评审领域3',
dataIndex: 'reviewAreaThree',
width: 100,
},
{
title: '毕业院校',
dataIndex: 'graduatedFrom',
},
{
title: '院校专业',
dataIndex: 'major',
},
{
title: '身份证号',
dataIndex: 'idNumber',
width: 170,
},
{
title: '邮箱地址',
dataIndex: 'expertEmail',
width: 200,
},
{
title: '开户银行',
dataIndex: 'bankName',
width: 110,
},
{
title: '银行账号',
dataIndex: 'bankAccount',
},
{
title: '个人简介',
dataIndex: 'resumeAttachments',
render: (text, record) => {
return text && text.map(item => {
return <a className="link" onClick={()=>{downFile(item.id)}}>{item.fileName}</a>
})
}
},
{
title: '职称证明',
dataIndex: 'titleCertificateAttachments',
render: (text, record) => {
return text && text.map(item => {
return <a className="link" onClick={()=>{downFile(item.id)}}>{item.fileName}</a>
})
}
},
{
title: '学术成果',
dataIndex: 'academicAchievementsAttachments',
render: (text, record) => {
return text && text.map(item => {
return <a className="link" onClick={()=>{downFile(item.id)}}>{item.fileName}</a>
})
}
},
{
title: '荣誉称号',
dataIndex: 'honorsAttachments',
render: (text, record) => {
return text && text.map(item => {
return <a className="link" onClick={()=>{downFile(item.id)}}>{item.fileName}</a>
})
}
},
{
title: '操作',
dataIndex: 'action',
width: 120,
fixed: 'right',
render: (text, record) => {
return <React.Fragment>
<Button className="mr5 font-12" type="primary" size="small" onClick={() => { check(record, '1') }}>通过</Button>
<Button className="mr5 font-12" type="danger" size="small" onClick={() => { setVisible(true); setActive(record) }}>拒绝</Button>
</React.Fragment>
}
}
];
}, []);
function downFile(id) {
let url = httpUrl + '/busiAttachments/download/' + id;
window.open(url);
}
function onShowSizeChange(current, pageSize){
setCurPage(current);
setPageSize(pageSize);
}
//
useEffect(() => {
setLoading(true);
let params = {
searchInput,
pageSize,
curPage,
statusString: '-1',
};
expertList(params).then(data => {
if (data && Array.isArray(data.rows)) {
for (const item of data.rows) {
item.detail = item.paperDetail && item.paperDetail.content;
}
}
setDataList(data.rows || []);
setLoading(false);
setTotal(data.total);
});
}, [curPage, reload, searchInput]);
function check(record, checkStatus) {
Confirm({
title: "提醒",
content: checkStatus == '1' ? "您确定要审核通过吗?通过后该用户将成为专家库的一员" : "您确定要拒绝吗?拒绝后该用户此次不能成为专家",
okText: '确定',
cancelText: '取消',
onOk() {
registerCheck({
expertId: record.id,
isPassed: checkStatus,
userId: record.userId,
}).then(res => {
if (res.message === 'success') {
showNotification('操作成功!');
setReload(Math.random());
}
});
},
});
}
const helper = useCallback(
(name, rules, widget) => (
<Form.Item>
{getFieldDecorator(name, { rules, validateFirst: true })(widget)}
</Form.Item>
),
[]
);
function refuse() {
validateFields((err, values) => {
if (!err) {
registerCheck({
expertId: active.id,
isPassed: 2,
userId: active.userId,
reviewerAdvice:values.reviewerAdvice,
}).then(res => {
if (res.message === 'success') {
showNotification('操作成功!');
setReload(Math.random());
setFieldsValue({
reviewerAdvice:''
});
setVisible(false);
setActive({});
}
});
}
});
}
return (
<div className="expert-list centerbox">
<div className="center-screen mb30" >
<Search
maxLength={20}
style={{ width: "300px" }}
placeholder="请输入专家姓名或手机号"
onSearch={(value) => { setSearchInput(value); setCurPage(1); }}
/>
</div>
<Paginationtable
loading={loading}
dataSource={dataList}
columns={columns}
total={total}
setCurPage={setCurPage}
current={curPage}
scroll={{ x: 2700 }}
onShowSizeChange={onShowSizeChange}
showSizeChanger
/>
<Modal
title="拒绝的原因"
visible={visible}
onOk={refuse}
onCancel={() => { setVisible(false) }}
className="form-edit-modal"
>
{helper(
"reviewerAdvice",
[{ required: visible, message: '请给出拒绝的原因' }],
<TextArea
placeholder="(必填)我想给点什么意见呢200字以内"
autoSize={{ minRows: 6 }}
className="applyText"
maxLength={200}
/>
)}
</Modal>
</div>)
}
export default Form.create()(RegisterList);

View File

@ -0,0 +1,5 @@
.expert-list{
.ant-table-thead > tr > th, .ant-table-tbody > tr > td{
padding:16px 6px;
}
}

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="60px" height="60px" viewBox="0 0 60 60" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>专家icon</title>
<g id="首页/竞赛" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="1-专家注册页" transform="translate(-931.000000, -190.000000)">
<g id="编组-3" transform="translate(713.000000, 190.000000)">
<g id="专家icon" transform="translate(218.000000, 0.000000)">
<rect id="矩形" x="0" y="0" width="60" height="60"></rect>
<g id="icon" transform="translate(5.000000, 4.000000)">
<g id="组织专家评审" fill="#333333" fill-rule="nonzero">
<path d="M3.11770945,3.49761811 C3.11492271,3.36209631 3.1687138,3.23153283 3.2661718,3.1372655 C3.36622022,3.04865657 3.49325526,2.99637688 3.62672326,2.98888504 L12.4496289,2.98888504 L12.4496289,7.48269356 C12.450103,7.88563237 12.6193084,8.26997793 12.9162248,8.54255409 C13.2157443,8.82015688 13.6106392,8.97195578 14.019088,8.96649828 L30.6256628,8.96649828 C31.073504,8.98344877 31.5067222,8.80561799 31.8133616,8.47896245 C32.110278,8.2063863 32.2794834,7.82204074 32.2799576,7.41910193 L32.2799576,2.98888504 L41.1028632,2.98888504 C41.2379887,2.98855385 41.3677009,3.04193527 41.4634147,3.1372655 C41.5646992,3.23076578 41.6255588,3.360021 41.6330859,3.49761811 L41.6330859,23.3170095 C41.8573141,23.9253641 42.4372188,24.3295174 43.0858961,24.3295174 C43.7345733,24.3295174 44.314478,23.9253641 44.5387063,23.3170095 L44.5387063,3.49761811 C44.5359821,2.56148343 44.1533081,1.66652008 43.4782609,1.01754451 C42.8080709,0.379339986 41.9223724,0.0161769046 40.9968187,3.88596243e-05 L3.62672326,3.88596243e-05 C2.67828295,-0.00433465779 1.76541073,0.360612829 1.0816543,1.01754451 C0.400828118,1.66434798 0.0106943895,2.55886701 0,3.49761811 L0,47.2910539 C0.0106943895,48.229805 0.400828118,49.1243241 1.0816543,49.7711275 C1.76541073,50.4280592 2.67828295,50.7930067 3.62672326,50.7885936 L20.233298,50.7885936 C20.7954522,50.8182746 21.3272274,50.532092 21.611877,50.0466913 C21.908614,49.5811812 21.908614,48.9860022 21.611877,48.5204921 C21.3184253,48.0467686 20.7900006,47.7705143 20.233298,47.799787 L3.62672326,47.799787 C3.49325526,47.7922952 3.36622022,47.7400155 3.2661718,47.6514066 C3.16391014,47.5604711 3.10916439,47.4275905 3.11770945,47.2910539 L3.11770945,3.49761811 Z M15.5673383,5.97769166 L15.5673383,2.98888504 L29.0562036,2.98888504 L29.0562036,5.97769166 L15.5673383,5.97769166 Z" id="形状"></path>
<path d="M11.940615,18.929187 C11.3988209,18.9154194 10.8903181,19.1896982 10.6044539,19.6498921 C10.3188267,20.1261925 10.3188267,20.7209881 10.6044539,21.1972884 C10.8995061,21.6825503 11.4367887,21.9673158 12.0042418,21.9391908 L31.728526,21.9391908 C32.2885262,21.9594535 32.8157739,21.6757075 33.107105,21.1972884 C33.3939683,20.7224969 33.3919365,20.1274438 33.1018375,19.6546202 C32.8117385,19.1817966 32.2820113,18.9101518 31.728526,18.9503842 L11.940615,18.929187 Z M11.940615,29.8669474 L21.2089077,29.8669474 C21.771062,29.8372664 22.3028372,30.123449 22.5874868,30.6088497 C22.8842238,31.0743598 22.8842238,31.6695387 22.5874868,32.1350488 C22.294035,32.6087724 21.7656104,32.8850267 21.2089077,32.855754 L11.940615,32.855754 C11.4018484,32.8571795 10.8989788,32.5859393 10.6044539,32.1350488 C10.3272225,31.6640431 10.3272225,31.0798555 10.6044539,30.6088497 C10.8995061,30.1235878 11.4367887,29.8388224 12.0042418,29.8669474 L11.940615,29.8669474 Z" id="形状"></path>
</g>
<g transform="translate(25.609756, 25.395349)">
<polygon id="矩形" fill="#999999" points="3.31619216 21.8539034 21.0806678 21.8539034 21.0806678 26.2527878 3.31619216 26.2527878"></polygon>
<g id="编组-2" fill="#333333" fill-rule="nonzero">
<path d="M23.9983967,5.58180217 L12.0765574,0.075352286 C11.8689657,-0.0251174287 11.627648,-0.0251174287 11.4200563,0.075352286 L0.380907507,5.58180217 C0.158205753,5.71635527 0.0156774511,5.95380651 0.000120780161,6.21597981 C-0.00527494294,6.51710193 0.170529421,6.79137428 0.444350891,6.90882586 L6.09908726,9.61316045 C6.20487178,9.63271696 6.31327807,9.63271696 6.41906259,9.61316045 C6.32584093,10.0100205 6.27133057,10.4151944 6.25631652,10.8228473 C6.21854272,13.0286472 7.39269744,15.0734113 9.30435734,16.1309421 C7.67105786,16.6145993 6.18197665,17.5016342 4.9708984,18.7123524 C3.11044804,20.5966976 2.08679334,23.1664209 2.13525499,25.8307868 C2.13525224,26.2570916 2.47566403,26.6031122 2.89657559,26.6046512 L21.4965206,26.6046512 C21.9163538,26.601581 22.2550938,26.2560077 22.2550828,25.8307868 C22.3155355,21.3018461 19.305521,17.3202384 14.9728858,16.1979917 C16.8174399,15.1743025 17.9802127,13.2292917 18.0209266,11.099427 C18.0184384,10.5790059 17.9517192,10.0609414 17.8223212,9.55728577 C18.008209,9.63281666 18.2156991,9.63281666 18.4015869,9.55728577 L23.9515038,6.93117573 C24.2192037,6.80434797 24.3902439,6.53206782 24.3902439,6.23274221 C24.3902439,5.9334166 24.2192037,5.66113646 23.9515038,5.53430869 L23.9983967,5.58180217 Z M20.7048576,25.0597162 L3.70478913,25.0597162 C3.8620379,23.0904716 4.71159482,21.2437043 6.09908726,19.8549896 C7.7462411,18.2104918 9.97632321,17.3046193 12.2889548,17.3406289 C16.6633609,17.2681371 20.3437655,20.6438134 20.7048576,25.0597162 L20.7048576,25.0597162 Z M12.1979273,15.3933963 C9.84041013,15.3332364 7.96017332,13.3803352 7.96017332,10.9918682 C7.96017332,8.60340126 9.84041013,6.65050002 12.1979273,6.59034017 L12.2751627,6.59034017 C13.4201345,6.62385405 14.5077179,7.10551509 15.3094115,7.93412627 C16.0984799,8.76340204 16.5360487,9.87233629 16.5286279,11.0239962 C16.4757666,13.4211163 14.5649215,15.3490369 12.1979273,15.3933963 L12.1979273,15.3933963 Z M17.8857646,8.12968765 C17.7427915,8.19926945 17.6250576,8.31264673 17.5492388,8.45376081 C16.6041322,6.41679515 14.6016514,5.09753922 12.3799822,5.04819896 C10.8013913,5.02832136 9.27669212,5.62918732 8.12651713,6.72443941 C7.64858946,7.20562533 7.25247653,7.76350963 6.95419374,8.37553625 C6.90315678,8.31251581 6.84035536,8.26030218 6.7693804,8.22188088 L2.4855728,6.20480487 L11.7731325,1.57279376 L21.8495969,6.20480487 L17.8857646,8.12968765 Z" id="形状"></path>
<path d="M23.3418956,9.13822566 C22.920984,9.13976467 22.5805722,9.48578518 22.580575,9.91209 L22.580575,12.4264507 C22.5635221,12.713513 22.7050474,12.9864779 22.948058,13.1352283 C23.1910687,13.2839786 23.4954809,13.2839786 23.7384916,13.1352283 C23.9815022,12.9864779 24.1230275,12.713513 24.1059746,12.4264507 L24.1059746,9.91209 C24.1059746,9.48469653 23.7638848,9.13822566 23.3418956,9.13822566 L23.3418956,9.13822566 Z" id="路径"></path>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.9 KiB

View File

@ -0,0 +1,23 @@
import React from "react";
import { Link } from "react-router-dom";
import system from './image/system.svg';
import './review.scss';
import '../index.scss';
function Review(){
return(
<div className="expert_review_system centerbox">
<div className="navigation">
<Link to='/'>首页</Link>&nbsp;&gt;&nbsp;<span>专家评审系统</span>
</div>
<div className="notExpert center_flex">
<img src={system} alt="img not found"/>
<p className="ne_title">红山开源平台专家评审系统</p>
<p className="ne_tips">您尚未被入选本平台专家团队可提交专家资料进行注册申请加入专家团队</p>
<p className="ne_bar"></p>
<Link to='/expert/user/register'><button className="but41_fill">专家注册</button></Link>
</div>
</div>)
}
export default Review;

View File

@ -0,0 +1,40 @@
.expert_review_system{
height: 500px;
font-size: 20px;
.center_flex{
display: flex;
align-items: center;
justify-content: center;
}
.navigation{
font-size: 0.6em;
margin: -35px 0 15px;
}
.notExpert{
height: 80%;
flex-direction: column;
background: #FAFCFF;
border-radius: 4px 4px 0px 0px;
border: 1px solid rgba(42, 97, 255, 0.23);
&>img{
width: 5.5vw;
}
.ne_title{
font-size: 1em;
font-weight: bold;
color: #181818;
}
.ne_tips{
font-size: 0.75em;
color: #595959;
}
.ne_bar{
width: 30vw;
border-top: 1px solid #EEEEEE;
margin: 50px 0 30px !important;
}
.but41_fill{
font-size: 0.7em;
}
}
}

View File

@ -0,0 +1,162 @@
import React, { useState, useEffect } from "react";
import { Modal } from 'antd';
import Paginationtable from "../../../components/paginationTable";
import { getOpsScoringDetails, getRules } from "../../api";
import sucess from '../image/sucess.svg';
import './index.scss';
import '../../index.scss';
function GradesModal({ setVisible, visible, taskId, opsDetail, containerType }) {
// table
const [loading, setLoading] = useState(false);
const [dataList, setDataList] = useState([]);
//
const [rules, setRules] = useState({});
//
const columns = [
{
title: '评审专家',
dataIndex: 'expertName',
key: 'expertName',
width: 100,
},
{
title: '电话',
dataIndex: 'expertPhone',
key: 'expertPhone',
width: 130,
},
{
title: '评审打分',
dataIndex: 'gradesAverage',
key: 'gradesAverage',
render: (text, record, index) => {
return text == 0 ? 0 : text || '--'
}
},
{
title: '评审意见',
dataIndex: 'comments',
key: 'comments',
width: 250,
render: (text, record, index) => {
return text|| '--'
}
},
{
title: '评审时间',
dataIndex: 'reviewedOn',
key: 'reviewedOn',
render: (text, record, index) => {
return text|| '--'
}
},
];
//
const gradesColumns = [{
title: '评分一',
dataIndex: 'gradesOne',
key: 'gradesOne',
render: (text, record, index) => {
return text == 0 ? 0 : text || '--'
}
},
{
title: '评分二',
dataIndex: 'gradesTwo',
key: 'gradesTwo',
render: (text, record, index) => {
return text == 0 ? 0 : text || '--'
}
},
{
title: '评分三',
dataIndex: 'gradesThree',
key: 'gradesThree',
render: (text, record, index) => {
return text == 0 ? 0 : text || '--'
}
},
{
title: '评分四',
dataIndex: 'gradesFour',
key: 'gradesFour',
render: (text, record, index) => {
return text == 0 ? 0 : text || '--'
}
},
{
title: '评分五',
dataIndex: 'gradesFive',
key: 'gradesFive',
render: (text, record, index) => {
return text == 0 ? 0 : text || '--'
}
}];
let gradesNum = rules && rules.criterias && rules.criterias.length || 5;
if (gradesNum) {
let thisGradesColumns = gradesColumns.slice(0, gradesNum);
columns.splice(4, 0, ...thisGradesColumns);
}
//
useEffect(() => {
setLoading(true);
let params = {
opsId: opsDetail && opsDetail.opsId,
opsType: opsDetail && opsDetail.opsType,
orderBy: 'gradesAverageDesc',
containerId: taskId,
containerType,
};
//
const paramsRule = {
containerId: taskId,
containerType,
statusString: '-1,1',
};
taskId && getRules(paramsRule).then(response=>{
if(response && response.message === "success"){
setRules(response.data);
}
});
opsDetail && opsDetail.opsId && getOpsScoringDetails(params).then(res => {
if (res.data && res.data.length) {
setDataList(res.data);
setLoading(false);
}
});
}, [opsDetail]);
return (
<Modal
title="评审明细"
visible={visible}
onCancel={() => { setVisible(false) }}
footer={null}
draggable={true}
width={1050}
wrapClassName="task_review_detail"
>
<div className="opsDetail">
综合排名: {opsDetail && opsDetail.id}
<span className="ml30">应征者:&nbsp;&nbsp;</span> {opsDetail && (opsDetail.applicantInfo.nickname == null ? opsDetail.applicantInfo.login : opsDetail.applicantInfo.nickname)}
<span className="ml30">平均得分:&nbsp;&nbsp;</span> {opsDetail && opsDetail.finalGrades || `--`}
<span className="ml30">是否胜出:&nbsp;&nbsp;</span> {opsDetail && opsDetail.isWin ? <div className="sucess df"><img src={sucess}/>胜出</div> : '未胜出'}
</div>
<Paginationtable
loading={loading}
dataSource={dataList}
columns={columns}
pagination={false}
scroll={{ y: 430 }}
/>
</Modal>
)
}
export default GradesModal;

View File

@ -0,0 +1,97 @@
.register_right.task_detail {
background: #fff;
padding-bottom: 1rem;
.ant-tabs {
background: #f5f5f5;
.ant-tabs-content {
background: #fff;
}
.ant-tabs-bar {
background: #fff;
margin-bottom: 1.25rem;
}
.ant-tabs-tab {
margin: 0;
padding: 19px 32px;
font-size: 1rem;
&:hover {
color: #4154f1;
}
}
.ant-tabs-ink-bar {
background-color: #4154f1;
}
}
.ant-tabs-nav .ant-tabs-tab-active {
color: #4154f1;
}
.task-head {
position: relative;
border-bottom: 1px solid #eeeeee;
padding: 0.5em 2em;
color: #181818;
background: #fff;
font-size: 0.8em;
font-weight: bold;
.back-button{
position: absolute;
z-index: 1;
right: 1rem;
bottom: -52px;
}
}
.button-div {
line-height: 1.5;
}
.pagination-table {
margin: .75rem 1.75rem 1.25rem;
}
.task-rules {
background: #f5f5f5;
.rules-box{
margin-bottom: 1.25rem;
background: #fff;
}
.rules-head {
font-size: 16px;
color: rgba(51, 51, 51, 1);
border-bottom: 1px solid #eeeeee;
padding: 10px 20px;
}
.rules-content{
padding: 10px 20px 30px;
}
.rules-content-last{
padding: 10px 20px;
}
.rules-content-item{
line-height: 2rem;
}
}
.warning{
color: #DE0000;
font-size: .7rem;
margin: .75rem 1.75rem;
}
}
.task_review_detail .pagination-table .ant-table-thead tr th div {
font-weight: bold;
}
.opsDetail{
display: flex;
margin-bottom: 15px;
color: #333;
.sucess{
color: #fd7700;
justify-content: center;
img{width: 20px;}
}
}

View File

@ -0,0 +1 @@
<svg id="图层_1" data-name="图层 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 400 400"><defs><style>.cls-1{fill:url(#未命名的渐变_7);}.cls-2{fill:#fedd7c;}.cls-3{fill:#feb448;}.cls-4{fill:#dfac63;}.cls-5{fill:#d9993e;}.cls-6{fill:url(#未命名的渐变_7-2);}.cls-7,.cls-8{fill:#fff;}.cls-8{stroke:#fff;stroke-miterlimit:10;}</style><linearGradient id="未命名的渐变_7" x1="144.96" y1="168.72" x2="257.82" y2="364.21" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#ffd46e"/><stop offset="1" stop-color="#ffac09"/></linearGradient><linearGradient id="未命名的渐变_7-2" x1="218.84" y1="17.66" x2="186.91" y2="17.66" xlink:href="#未命名的渐变_7"/></defs><title>未标题-1</title><polygon class="cls-1" points="197.56 399 84.04 328.05 84.04 203.89 197.56 157.78 318.17 203.89 318.17 328.05 197.56 399"/><polygon class="cls-2" points="84.04 79.73 133.7 186.16 201.1 186.16 201.1 19.43 147.89 115.21 84.04 79.73"/><polygon class="cls-3" points="318.17 79.73 268.5 186.16 201.1 186.16 201.1 19.43 254.31 115.21 318.17 79.73"/><polygon class="cls-4" points="84.04 79.73 159.19 94.88 147.89 115.21 84.04 79.73"/><polygon class="cls-5" points="318.17 79.73 244.46 97.47 254.31 115.21 318.17 79.73"/><circle class="cls-6" cx="202.88" cy="17.66" r="15.96"/><circle class="cls-3" cx="313.03" cy="81.63" r="15.96"/><circle class="cls-2" cx="86.03" cy="81.64" r="15.96"/><rect class="cls-7" x="186.05" y="121.44" width="30.1" height="30.1" transform="translate(-37.61 182.18) rotate(-45)"/><polygon class="cls-8" points="212.32 258.6 240.8 262.89 220.07 282.88 224.79 311.29 199.37 297.75 173.81 311.01 178.83 282.66 158.32 262.45 186.84 258.46 199.72 232.71 212.32 258.6"/></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1,236 @@
import React, { useEffect, useState } from "react";
import Link from "react-router-dom/Link";
import PaginationTable from "src/military/components/paginationTable";
import GradesModal from "./gradesModal";
import { getCompetitionDetail, getFinalScoreRankingList, getWinnersAndPublicists, selectWinnersAndPublicists } from "../api";
import { getTaskDetail } from "src/military/task/api";
import { Checkbox, Input, message, Modal, Spin } from "antd";
import sucess from './image/sucess.svg';
import './index.scss';
import '../index.scss';
import { queryString } from "educoder";
function ReviewResult({ history, match, mygetHelmetapi}) {
const {main_web_site_url} = mygetHelmetapi;
//ididcontainerType12
const {containerId, containerType} = match.params;
let {identifier, status, name, taskModeId} = queryString.parse(window.location.hash.slice(1));
const [dataList, setDateList] = useState(undefined);
const [openResultVisible, setOpenResultVisible] = useState(false);
const [winIds, setWinIds] = useState(undefined);
const [openRange, setOpenRange] = useState(undefined);
const [errorMessage,setErrorMessage] = useState();
const [result, setResult] = useState(undefined);
const [goNum, setGoNum] = useState(-1);
const [loading, setLoading] = useState(false);
//
const [opsDetail, setOpsDetail] = useState(undefined);
const [visible, setVisible] = useState(false);
const columns = [
{
title: '综合排名',
dataIndex: 'id',
},
{
title: '应征者',
dataIndex: 'applicantInfo.nickname',
key: 'expertName',
render: (text, record) => {
return text === null ? record.applicantInfo.login : text
}
},
{
title: '平均得分',
dataIndex: 'finalGrades',
key: 'phone',
},
{
title: '评审明细',
ket: 'detali',
render: (text, record) => {
return <a className="lookDetail" onClick={()=>{detail(record)}}>查看明细</a>
}
}
];
//
if(containerType == 1){
columns.splice(4, 0, {
title: '是否胜出',
ket: 'isWin',
align: 'center',
render: (text, record) => {
return record.isWin ? <div className="sucess df"><img src={sucess}/>胜出</div> : status == 4 ? <Checkbox onChange={(e)=>{changeIsWin(record.applicantInfo.id, e.target.checked)}}>胜出</Checkbox> : '未胜出';
}
});
}
useEffect(()=>{
//
const params = {
containerId,
containerType,
orderBy: 'finalGradesDesc'
}
getFinalScoreRankingList(params).then(response=>{
if(response && Array.isArray(response.data)){
//finalGrades null 0
let index = 1;
response.data.map(item=>{item.id = index++;setResult(item.finalGrades) })
containerType == 1 && status >4 ? getWinnersAndPublicists({
containerId,
containerType
}).then(res=>{
if(res && res.message === "success"){
response.data.map(item=>{
item.isWin = res.data.winUserIds.indexOf(item.applicantInfo.id) !== -1;
item.isPublic = res.data.publicityUserIds.indexOf(item.applicantInfo.id) !== -1;
})
}
setDateList(response.data);
}):setDateList(response.data)
}
})
},[status])
//status, name, taskModeId
useEffect(()=>{
const bool = status && name && taskModeId;
if(containerType == 1 && !bool){
setLoading(true);
//
containerId && getTaskDetail(containerId).then(response=>{
if(response){
window.location.href=`${window.location.href}#status=${response.status}&name=${response.name}&taskModeId=${response.taskModeId}`;
}
}).finally(()=>{
setLoading(false);
})
}
const competitionBool = status && name && identifier;
if(containerType == 2 && !competitionBool){
setLoading(true);
//
containerId && getCompetitionDetail(containerId).then(response=>{
if(response && response.message == "success"){
window.location.href=`${window.location.href}#status=${response.data.current_status}&identifier=${response.data.identifier}&name=${response.data.title}`;
}
}).finally(()=>{
setLoading(false);
})
}
},[status, name, taskModeId, identifier])
function detail(item){
setOpsDetail(item);
setVisible(true);
}
function changeIsWin(id, checked){
const ids = new Set(winIds);
checked ? ids.add(id) : ids.delete(id);
setWinIds(Array.from(ids));
}
function openResult(){
if(result === null){
message.error("还没有到评审结束时间,不能公示结果! ");
return;
}
containerType == 2 && setOpenResultVisible(true);
if(containerType ==1 && winIds && winIds.length>0){
taskModeId == 1 && winIds.length >1 ? message.error("此任务是单人悬赏模式, 只能设置一个中标者 ! ") : setOpenResultVisible(true);
}
}
function onOk(){
setErrorMessage("");
let ids = [];
if(!openRange){
dataList.map(i=> {ids[ids.length] = i.applicantInfo.id;});
}else if(openRange && isNaN(openRange)){
setErrorMessage('请输入数字!');
}else if(openRange && (openRange.indexOf('.')!==-1 || openRange.indexOf('-')!==-1)){
setErrorMessage('请输入正整数!');
}else if(openRange && containerType == 1 && openRange < winIds.length){
setErrorMessage('公示范围不能少于获胜人数!');
}else if(openRange && openRange > dataList.length){
setErrorMessage('公示范围超过应征者总数!');
}else{
ids[ids.length] = dataList.filter(item=>item.id<=openRange).map(i=>i.applicantInfo.id);
}
let params = {
containerId,
containerType,
id: 0,
publicityUserIds : ids.toString()
};
containerType==1 && (params[`winUserIds`] = winIds.toString());
ids.length!=0 && selectWinnersAndPublicists(params).then(response=>{
if(response && response.message === "success"){
message.success("操作成功");
if(containerType==1){
window.location.href=`${window.location.href.replace('status=4','status=5')}`;
status = 5;
setGoNum(-2);
}
setOpenResultVisible(false);
}
})
}
return (
<Spin spinning={loading}>
<div className="expert_review_system centerbox">
<div className="head_title mb20">
<div className="df pb10 pt10">
<span className="font-16 font-w">评审结果</span>
<button className="but41_border goback_but" onClick={()=>{history.go(goNum)}}>返回上一页</button>
</div>
<p className="mt10"><span className="font-w">{containerType ==1 ? '任务':'竞赛'}名称</span><span className="ml10">{decodeURI(name)}</span></p>
<p className="mt10 pb20">
<span className="font-w color-grey3">{containerType ==1 ? '任务':'竞赛'}链接</span>
{containerType == 1 && <Link className="taskLink ml10" target="_blank" to={`/task/taskDetail/${containerId}`} >{`${window.location.origin}/task/taskDetail/${containerId}`}</Link>}
{containerType == 2 && <a href={`${main_web_site_url}/competitions/${identifier}/home`} target="_blank" className="taskLink ml10">{`${main_web_site_url}/competitions/${identifier}/home`}</a>}
</p>
</div>
{status > 3 ? <React.Fragment>
<p className="font-16 font-w mb10">应征者排名</p>
<PaginationTable
dataSource= {dataList}
columns= {columns}
scroll={{ y: 384 }}
/>
<div className="openResult">
{status == 4 && <button className={(containerType ==1 && winIds && taskModeId == 1 && winIds.length >1) || result === null ? 'disableBut': 'but41_fill'} onClick={openResult}>公示结果</button>}
</div>
</React.Fragment>:<div className="nodata font-20">暂无数据此任务暂未进入成果评选阶段</div>}
<Modal
title= "请确认公示范围"
visible= {openResultVisible}
wrapClassName="openResultModal"
width={390}
onCancel= {()=>setOpenResultVisible(false)}
onOk={onOk}>
<div className="df">
公示排名前
<Input placeholder="请输入" onChange={(e)=>{setOpenRange(e.target.value)}}/>
</div>
<p className={`mt5 ${errorMessage && 'errorMes'}`}>{errorMessage || "若未填写此排名,则公示所有名次"}</p>
</Modal>
<GradesModal
visible={visible}
setVisible={setVisible}
taskId={containerId}
opsDetail={opsDetail}
containerType={containerType}
/>
</div>
</Spin>
)
}
export default ReviewResult;

View File

@ -0,0 +1,64 @@
.expert_review_system.centerbox{
background: white;
font-family: 'PingFangSC-Semibold';
padding: 0 1.5em;
.font-w{
font-weight: bold;
}
.df{
display: flex;
justify-content: space-between;
align-items: center;
}
.mt10.pb20{border-bottom: 1px solid #eeeeee;}
.openResult{
text-align: center;
padding: 35px 0;
}
.lookDetail{
color: #4154F1;
&:hover{
opacity: 0.8;
}
}
.disableBut{
background: #f8f8f8;
padding: 0 1.3em;
height: 2.55em;
border-radius: 4px;
cursor: pointer
}
.pagination-table .ant-table-thead > tr > th span{
font-weight: bold;
}
.nodata{
height: 300px;
line-height: 300px;
text-align: center;
}
.sucess{
color: #fd7700;
justify-content: center;
img{width: 20px;}
}
}
.openResultModal{
.ant-modal-body{
text-align: center;
}
.df{
justify-content: center;
align-items: center;
input{
width: 65px;
margin: 0 12px;
font-size: 13px;
}
}
.ant-modal-title {
text-align: left;
}
.errorMes{
color: #d40000;
}
}

View File

@ -0,0 +1,11 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
<g id="组_58" data-name="组 58" transform="translate(-465 -602)">
<g id="注意_2_" data-name="注意 (2)" transform="translate(465 602)">
<path id="形状" d="M0,8a8,8,0,1,1,8,8A8,8,0,0,1,0,8Z" fill="#3078ff"/>
</g>
<g id="感叹号2" transform="translate(-3.7 417.189)">
<path id="路径_12" data-name="路径 12" d="M486.4,189.83v4.85a.3.3,0,0,0,.591,0v-4.85A.3.3,0,0,0,486.4,189.83Z" transform="translate(-9.727)" fill="#fff"/>
<path id="路径_13" data-name="路径 13" d="M476.969,759.04m-.409,0a.409.409,0,1,0,.409-.409A.409.409,0,0,0,476.559,759.04Z" transform="translate(0 -562.513)" fill="#fff"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 748 B

View File

@ -0,0 +1,196 @@
import React, { useEffect, useState } from "react";
import { DatePicker, Form, message } from "antd";
import WordsInput from "../components/wordsInput";
import './index.scss';
import '../index.scss';
import Link from "react-router-dom/Link";
import { editRules, getRules, updateRules } from "../api";
import moment from "moment";
import { queryString } from "educoder";
const {RangePicker} = DatePicker;
function ReviewRules({form, history, match, mygetHelmetapi}) {
const {main_web_site_url} = mygetHelmetapi;
//ididcontainerType12
const {containerId, containerType} = match.params;
const {identifier, name, status, createdAt, collectingEndTime, choosingDays, reviewStartTime, reviewEndTime} = queryString.parse(window.location.search.slice(1));
const { getFieldDecorator,setFieldsValue } = form;
//
const [ initValue, setInitValue] = useState(false);
const disabledDate = (current) =>{
if(containerType == 1){
//
if(status == 1){
const start = new Date((new Date(createdAt.replace("%20", " "))/1000 - 86400)*1000);
return current && current < moment(start).endOf('day');
}else if(status == 3){
const start = new Date((new Date(collectingEndTime.replace("%20", " "))/1000 - 86400)*1000);
const endDate = new Date((new Date(collectingEndTime.replace("%20", " "))/1000 + 86400*(choosingDays))*1000);
return current && current < moment(start).endOf('day') || current > moment(endDate).endOf('day');
}
}else{
//
const start = new Date((new Date(reviewStartTime.replace("%20", " "))/1000 - 86400)*1000);
return current && current < moment(start).endOf('day') || current > moment(new Date(reviewEndTime.replace("%20", " "))).endOf('day');
}
}
useEffect(()=>{
//
const params = {
containerId,
containerType,
statusString: 3,
};
getRules(params).then(response=>{
if(response && response.message === "success"){
const { criteriaFive, criteriaFour, criteriaOne, criteriaThree, criteriaTwo, rule } = response.data;
const data = { criteriaFive, criteriaFour, criteriaOne, criteriaThree, criteriaTwo, rule }
setFieldsValue(data);
setInitValue(response.data);
}
})
}, [])
function rulesSubmit(){
form.validateFields((err, values) => {
if (!err) {
let data = {
containerId,
containerName: decodeURI(name),
containerType,
criteriaOne: values.criteriaOne,
reviewStartOn: values.reviewDate[0].format('YYYY-MM-DD HH:mm:ss'),
reviewEndOn: values.reviewDate[1].format('YYYY-MM-DD HH:mm:ss'),
rule: values.rule,
criteriaTwo: values.criteriaTwo,
criteriaThree: values.criteriaThree,
criteriaFour: values.criteriaFour,
criteriaFive: values.criteriaFive,
status: 3
}
containerType == 2 && (data[`containerIdentifier`]=identifier);
if(initValue){
//
updateRules({...data, id: initValue.id}).then(response=>{
if(response && response.message === '更新成功'){
message.success('更新成功');
history.go(-1);
}else{
message.error(response.message);
}
})
}else{
//
editRules(data).then(response=>{
if(response && response.message === '成功'){
message.success('保存成功');
history.go(-1);
setInitValue({id: response.data});
}else{
message.error(response.message);
}
})
}
}
})
}
return (
<div className="centerbox setRules">
<div className="head_title mb20">
<div className="-layout pb10">
<span className="font-16 font-w color-grey3">任务信息</span>
<button className="but41_border goback_but" onClick={()=>{history.goBack()}}>返回上一页</button>
</div>
<p className="mt10"><span className="font-w color-grey3">{containerType ==1 ? '任务':'竞赛'}名称</span><span className="ml10 color-grey3">{decodeURI(name)}</span></p>
<p className="mt10 pb20">
<span className="font-w color-grey3">{containerType ==1 ? '任务':'竞赛'}链接</span>
{containerType == 1 && <Link className="taskLink ml10" target="_blank" to={`/task/taskDetail/${containerId}`} >{`${window.location.origin}/task/taskDetail/${containerId}`}</Link>}
{containerType == 2 && <a href={`${main_web_site_url}/competitions/${identifier}/home`} target="_blank" className="taskLink ml10">{`${main_web_site_url}/competitions/${identifier}/home`}</a>}
</p>
</div>
<Form className="pt10">
<Form.Item
label="评审规则"
>
{getFieldDecorator('rule', {
rules: [{ required: true, message: '请输入评审规则' }],
})(
<WordsInput placeholder="请输入评审规则" rows={4} maxLength='200'/>,
)}
</Form.Item>
<p className="rules_bar"></p>
<p className="font-16 criteria_title mt25 mb10"><span className="font-w">评分标准</span><span className="ml5 be_carful font-14">管理员可设置1-5个评分项及对应评分标准每个评分项固定设置为100分</span></p>
<Form.Item
label="评分标准一"
>
{getFieldDecorator('criteriaOne', {
rules: [{ required: true, message: '请输入一个评分标准' }],
})(
<WordsInput placeholder="请输入评分项对应的评分标准" rows={3} maxLength='100'/>,
)}
</Form.Item>
<Form.Item
label="评分标准二"
>
{getFieldDecorator('criteriaTwo', {
rules: [{}],
})(
<WordsInput placeholder="请输入评分项对应的评分标准" rows={3} maxLength='100' />,
)}
</Form.Item>
<Form.Item
label="评分标准三"
>
{getFieldDecorator('criteriaThree', {
rules: [{}],
})(
<WordsInput placeholder="请输入评分项对应的评分标准" rows={3} maxLength='100'/>,
)}
</Form.Item>
<Form.Item
label="评分标准四"
>
{getFieldDecorator('criteriaFour', {
rules: [{}],
})(
<WordsInput placeholder="请输入评分项对应的评分标准" rows={3} maxLength='100'/>,
)}
</Form.Item>
<Form.Item
label="评分标准五"
>
{getFieldDecorator('criteriaFive', {
rules: [{}],
})(
<WordsInput placeholder="请输入评分项对应的评分标准" rows={3} maxLength='100'/>,
)}
</Form.Item>
<p className="rules_bar"></p>
<Form.Item
label="评审时间"
>
{getFieldDecorator('reviewDate', {
rules: [{ required: true, message: '请选择评审时间' }],
initialValue: initValue && [moment(initValue.reviewStartOn) , moment(initValue.reviewEndOn)]
})(
<RangePicker
showTime={{ format: 'HH:mm' }}
format="YYYY-MM-DD HH:mm"
placeholder={['开始时间', '结束时间']}
disabledDate={disabledDate}
/>,
)}
</Form.Item>
</Form>
<div className="rules_buttom mt20">
<button className="but41_fill" onClick={rulesSubmit}>保存</button>
<button className="butE3_border ml30" onClick={()=>{history.goBack()}}>取消</button>
</div>
</div>
)
}
export default Form.create()(ReviewRules);

View File

@ -0,0 +1,52 @@
.setRules.centerbox{
.head_title, .ant-form{
padding: 0 2em;
background: white;
}
.-layout{
justify-content: space-between;
margin: 0 -2em;
border-bottom: 1px solid #EEEEEE;
padding: 0.5em 1em;
}
.ant-form .ant-form-item label, .criteria_title{
color: #333333;
.be_carful{
color: #E02020;
&::before{
content: url('./image/beCarful.svg');
margin-right: 8px;
}
}
}
.ant-form{
padding: 1em 2em 2em;
.ant-form-item{
margin-bottom: 10px;
&:first-child label, &:last-child label{
font-size: 16px;
font-weight: bold;
}
.ant-form-item-label > label::after{
content: none;
}
}
.ant-input{
background-color: white !important;
&:hover{
border: 1px solid #5d6eff !important;
}
}
}
.rules_buttom{
text-align: center;
}
.but41_fill, .but41_border, .butE3_border{
width: 6.5em;
}
.but41_border{padding: 0;}
.rules_bar{
margin: 25px -2em;
border-bottom: 1px solid #EEEEEE;
}
}

View File

@ -0,0 +1,419 @@
import React, { useState, useEffect, useMemo } from "react";
import { Tabs, Input, Select, Button, Modal, Form, message, Popconfirm } from 'antd';
import { professionalType, reviewArea } from '../static.js';
import { assignExperts, deleteExperts, expertList, selectExpertList } from "../api.js";
import Paginationtable from "../../components/paginationTable";
import './index.scss';
import '../index.scss';
import { Link } from "react-router-dom";
import { queryString } from "educoder";
const { TabPane } = Tabs;
const { Option } = Select;
const { Search } = Input;
function SelectExpert(props) {
const { history, form, current_user, match, mygetHelmetapi } = props;
const {main_web_site_url} = mygetHelmetapi;
//ididcontainerType12
const {containerId, containerType} = match.params;
const {identifier, name} = queryString.parse(window.location.search.slice(1));
const { getFieldDecorator, setFieldsValue } = form;
const [reload, setReload] = useState();
const [loading, setLoading] = useState(false);
const [curPage, setCurPage] = useState(1);
const [dataList, setDataList] = useState([]);
const [total, setTotal] = useState(0);
const [pageSize, setPageSize] = useState(10);
const [searchInput, setSearchInput] = useState('');
const [expertType, setExpertType] = useState('');
const [reviewAreaSel, setReviewAreaSel] = useState('');
//
const [okConfirmExps, setOkConfirmExps] = useState(false);
//
const [okConfirmDelete, setOkConfirmDelete] = useState(false);
//
const [selectedRowKeys, setSelectedRowKeys] = useState(undefined);
//
const [okConfirmExtract, setOkConfirmExtract] = useState(false);
//
const [randomCount, setRandomCount] = useState(undefined);
//
const [randomErrorMessage, setRandomErrorMessage] = useState(undefined);
//tab
const [activeKey, setActiveKey] = useState(0);
//
const [selectedExperts, setSelectExperts] = useState([]);
const [selectedExpertTotal, setSelectedExpertTotal] = useState(0);
//
const [allSelectedExpertsId, setAllSelectedExpertsId] = useState();
const columns = useMemo(() => {
return [
{
title: '编号',
dataIndex: 'index',
width: 80,
align: 'center',
},
{
title: '专家姓名',
dataIndex: 'expertName',
key: 'expertName',
},
{
title: '手机号码',
dataIndex: 'phone',
width: 150,
key: 'phone',
},
{
title: '最高学历',
dataIndex: 'highestDegree',
key: 'highestDegree',
},
{
title: '专业职称',
dataIndex: 'professionalTitle',
width: 120,
},
{
title: '专家类别',
dataIndex: 'expertType',
},
{
title: '评审领域',
dataIndex: 'reviewAreas',
align: 'center',
},
{
title: '专家评估',
dataIndex: 'expertScore',
align: 'center',
render:(text,record)=>{
return record.expertScore || '--';
}
},
{
title: '操作',
dataIndex: 'action',
width: 180,
align: 'center',
render: (text, record) => {
return <React.Fragment>
{activeKey == "1" && <a className="select" onClick={()=>{SelectExperts([record.id])}}>添加</a>}
{activeKey == "0" && <Popconfirm placement="bottom" title="你确认要删除此专家吗?" onConfirm={() => { deleteExpert(record.taskExpertId, record.id)}} okText="是" cancelText="否"><Button className="mr5 font-12" type="danger" size="small">删除</Button></Popconfirm>}
</React.Fragment>
}
}
];
}, [activeKey, allSelectedExpertsId]);
const rowSelection = {
selectedRowKeys,
onChange: (selectedRowKeys, selectedRows) => {
setSelectedRowKeys(selectedRowKeys);
}
};
const ExpertDetail = (record)=>{
return <div className="expert_detail_div df">
<div>
<p>工作单位{record.workplace}</p>
<p>单位类别{record.workplaceType}</p>
<p>工作性质{record.workNature}</p>
<p>职称职级{record.titleRank}</p>
</div>
<div>
<p>邮箱地址{record.expertEmail || '--'}</p>
<p>毕业院校{record.graduatedFrom || '--'}</p>
<p>院校专业{record.major || '--'}</p>
</div>
<div>
<p>身份证号{record.idNumber || '--'}</p>
<p>开户银行{record.bankName || '--'}</p>
<p>银行账号{record.bankAccount || '--'}</p>
</div>
</div>
}
const TaskMess = ()=>{
return <div>
<div className="box"></div>
<p className="font-16 pt15 font-w color-grey3">任务信息</p>
<p className="mt10"><span className="font-w color-grey3">{containerType ==1 ? '任务':'竞赛'}名称</span><span className="ml10 color-grey3">{decodeURI(name)}</span></p>
<p className="mt10 pb20">
<span className="font-w color-grey3">{containerType ==1 ? '任务':'竞赛'}链接</span>
{containerType == 1 && <Link className="taskLink ml10" target="_blank" to={`/task/taskDetail/${containerId}`} >{`${window.location.origin}/task/taskDetail/${containerId}`}</Link>}
{containerType == 2 && <a href={`${main_web_site_url}/competitions/${identifier}/home`} target="_blank" className="taskLink ml10">{`${main_web_site_url}/competitions/${identifier}/home`}</a>}
</p>
</div>
}
//
useEffect(()=>{
setLoading(true);
const params = {
containerId,
containerType,
curPage:curPage,
pageSize: 10000,
curPage: 1,
}
selectExpertList(params).then(response=>{
if (response && response.data && Array.isArray(response.data.rows)) {
const ids = new Set();
response.data.rows.map((item)=>{
ids.add(item.id);
})
setAllSelectedExpertsId(ids);
}
}).finally(()=>{
setLoading(false);
})
},[])
//
useEffect(() => {
setLoading(true);
let params = {
searchInput,
expertType: expertType === 'all' ? '' : expertType,
reviewArea: reviewAreaSel === 'all' ? '' : reviewAreaSel,
pageSize,
curPage,
statusString: '1',
selectedExpertIds: allSelectedExpertsId && Array.from(allSelectedExpertsId).toString()
};
expertList(params).then(data => {
if (data && Array.isArray(data.rows)) {
let index = 1;
for (const item of data.rows) {
item.reviewAreas = `${item.reviewAreaOne} ${item.reviewAreaTwo ? `${item.reviewAreaTwo}`:''} ${item.reviewAreaThree ? `${item.reviewAreaThree}`:''}`;
item.index = (index++) + (curPage > 1 ? (curPage - 1) * 10 : 0);
}
}
setDataList(data && data.rows);
setLoading(false);
setTotal(data && data.total);
});
}, [curPage, reload, searchInput, expertType, reviewAreaSel, allSelectedExpertsId]);
//
useEffect(()=>{
setLoading(true);
const params = {
containerId,
containerType,
curPage,
pageSize,
}
selectExpertList(params).then(response=>{
if (response && response.data && Array.isArray(response.data.rows)) {
let index = 1;
for (const item of response.data.rows) {
item.reviewAreas = `${item.reviewAreaOne} ${item.reviewAreaTwo ? `${item.reviewAreaTwo}`:''} ${item.reviewAreaThree ? `${item.reviewAreaThree}`:''}`;
item.index = (index++) + (curPage > 1 ? (curPage - 1) * 10 : 0);
}
setSelectExperts(response && response.data.rows);
setSelectedExpertTotal(response && response.data.total);
}
}).finally(()=>{
setLoading(false);
})
},[curPage, reload])
//
function random(){
setRandomErrorMessage('');
if(!randomCount){
setRandomErrorMessage('请输入随机抽取的专家数量!');
}else if(isNaN(randomCount)){
setRandomErrorMessage('请输入数字!');
}else if(randomCount.indexOf('.')!==-1 || randomCount.indexOf('-')!==-1){
setRandomErrorMessage('请输入正整数!');
}else{
let params = {
searchInput,
expertType: expertType === 'all' ? '' : expertType,
reviewArea: reviewAreaSel === 'all' ? '' : reviewAreaSel,
randomCount,
curPage:1,
pageSize: 10000,
selectedExpertIds: Array.from(allSelectedExpertsId).toString(),
};
expertList(params).then(response=>{
if(response && Array.isArray(response.rows)){
const randomIds = [];
response.rows.map(item=>{
randomIds[randomIds.length] = item.id;
})
SelectExperts([...randomIds]);
setOkConfirmExtract(false);
}
})
}
}
//
const SelectExperts = (id) =>{
const params = {
assignorId: parseInt(current_user.user_id),
containerId,
containerName: decodeURI(name),
containerType,
expertIds: id.toString(),
status: 3
}
assignExperts(params).then(response=>{
if(response && response.message === '专家指派成功'){
id.map(i=>setAllSelectedExpertsId(allSelectedExpertsId.add(i)));
setOkConfirmExps(false);
message.success(response.message);
setSelectedRowKeys([]);
setReload(Math.random());
}
})
}
//
const deleteExpert=(taskExpertId, expertId)=>{
setLoading(true);
deleteExperts(taskExpertId,1).then(response=>{
if(response && response.message === "删除成功"){
message.success("删除成功");
allSelectedExpertsId.delete(expertId);
setReload(Math.random());
}else{
message.error("删除失败");
}
}).finally(()=>{
setLoading(false);
})
}
return (
<div className="centerbox select_expert">
<div className="df">
<p className="title_one font-16 font-w font-color-18">评审专家选取</p>
<button className="but41_border goback_but mr25" onClick={()=>{history.goBack()}}>返回上一页</button>
</div>
<Tabs defaultActiveKey="0" type="card" onChange={(activeKey)=>{setActiveKey(activeKey);setSelectedRowKeys([]);setCurPage(1);}}>
<TabPane tab="已选专家" key="0">
<TaskMess/>
<div className="df mb20">
<p className="font-16 font-w color-grey3 select_title">已选取评审专家</p>
<div>
{/* <button className="but41_fill" onClick={() => {selectedRowKeys && selectedRowKeys.length>0 && setOkConfirmDelete(true)}}>批量删除</button> */}
<Modal
title="批量删除"
visible={okConfirmDelete}
onOk={() => { history.go(-1) }}
onCancel={() => setOkConfirmDelete(false)}
wrapClassName="expert_modal"
>
<p className='weight_bold warning'>您确定要删除选中的{selectedRowKeys && selectedRowKeys.length}个专家吗</p>
<p className='ml_40'>此操作将删除选中的{selectedRowKeys && selectedRowKeys.length}个专家请进行确认以防数据丢失</p>
</Modal>
</div>
</div>
<Paginationtable
loading={loading}
dataSource={selectedExperts}
columns={columns}
total={selectedExpertTotal}
setCurPage={setCurPage}
current={curPage}
// rowSelection={rowSelection}
expandedRowRender={ExpertDetail}
expandIconColumnIndex={8}
expandIconAsCell={false}
/>
</TabPane>
<TabPane tab="专家选取" key="1">
<TaskMess/>
<div className="df mb20">
<p className="font-16 font-w color-grey3 select_title">添加评审专家</p>
<div>
<button className="but41_fill" onClick={() => {selectedRowKeys && selectedRowKeys.length>0 && setOkConfirmExps(true)}}>批量添加</button>
{allSelectedExpertsId && allSelectedExpertsId.size === total ? <button className="invalid_extraction butE3_border ml20">随机抽取</button> : <button className="but41_fill ml20" onClick={() => setOkConfirmExtract(true)}>随机抽取</button>}
<Modal
title="批量添加"
visible={okConfirmExps}
onOk={() => SelectExperts(selectedRowKeys)}
onCancel={() => setOkConfirmExps(false)}
wrapClassName="expert_modal"
>
<p className='weight_bold warning'>您确定要添加选中的{selectedRowKeys && selectedRowKeys.length}个专家吗</p>
<p className='ml30'>此操作将添加选中的{selectedRowKeys && selectedRowKeys.length}个专家请进行确认</p>
</Modal>
<Modal
title="随机抽取"
visible={okConfirmExtract}
onOk={random}
onCancel={() => setOkConfirmExtract(false)}
wrapClassName="expert_modal extract"
>
<div><span>请输入数量</span><Input placeholder="请输入" onChange={(e)=>{setRandomCount(e.target.value)}}></Input></div>
<p>{randomErrorMessage}</p>
</Modal>
</div>
</div>
<div className="df search">
<Form className="df">
<Form.Item label="查询条件:">
{getFieldDecorator('searchInput', {})(<Search
maxLength={20}
style={{ width: "200px" }}
placeholder="请输入专家姓名或手机号"
onSearch={(value) => { setSearchInput(value); setCurPage(1); }}
/>)}
</Form.Item>
<Form.Item label="专家类别:">
{getFieldDecorator('expertType', {})(
<Select placeholder="所有类别" style={{ width: 220 }} onChange={(value) => { setExpertType(value);setCurPage(1); }}>
<Option value='all'>所有类别</Option>
{professionalType.map(item => {
return <Option key={item.value} value={item.value}>{item.label}</Option>
})}
</Select>)}
</Form.Item>
<Form.Item label="评审领域:">
{getFieldDecorator('reviewAreaSel', {})(
<Select placeholder="所有领域" style={{ width: 220 }} onChange={value => {setReviewAreaSel(value);setCurPage(1);}}>
<Option value='all'>所有领域</Option>
{reviewArea.map(item => {
return <Option key={item.value} value={item.value}>{item.label}</Option>
})}
</Select>)}
</Form.Item>
</Form>
<button className="butE3_border ml120 mb25" onClick={() => {
setSearchInput('');
setExpertType('');
setReviewAreaSel('');
setFieldsValue({
searchInput: '',
expertType: 'all',
reviewAreaSel: 'all'
});
}}>清除</button>
</div>
<Paginationtable
loading={loading}
dataSource={dataList}
columns={columns}
total={total}
setCurPage={(curPage)=>{setCurPage(curPage++);setSelectedRowKeys([])}}
current={curPage}
rowSelection={rowSelection}
expandedRowRender={ExpertDetail}
expandIconColumnIndex={9}
expandIconAsCell={false}
/>
</TabPane>
</Tabs>
</div>)
}
export default Form.create()(SelectExpert);

View File

@ -0,0 +1,112 @@
.centerbox.select_expert{
margin: -10px auto;
margin-bottom: 2vh;
padding-top: 16px;
background: white;
.title_one, .ant-tabs-nav-wrap, .ant-tabs .ant-tabs-top-content{
padding: 0 2em 1vw;
}
.box{
height: 20px;
margin: 0 -2em;
background: #FAFAFA;
}
.df{
display: flex;
justify-content: space-between;
align-items: center;
&.ant-form{
width: 78vw;
}
}
.search{
.ant-form-item{
display: flex;
}
}
.ant-pagination{
text-align: center;
margin: 20px 0;
}
.ant-table-thead > tr > th, .ant-table-tbody > tr > td{
padding: 16px 0 16px 10px;
}
.ml120{
margin-left: 120px;
width: 6em;
}
.ant-table-row-expand-icon{
width: 65px;
height: 26px;
line-height: 24px;
font-size: 12px;
color: white;
background: #4154F1;
}
.ant-table-row-collapsed::after, .ant-table-row-expanded::after {
content: '专家详情';
}
.expert_detail_div{
justify-content: space-around;
align-items: flex-start;
div{width: 28%;}
}
.select{
color: #4154F1;
padding: 0 8px;
}
.selected{
color: #999999;
}
.ant-tabs .ant-tabs-bar{
border: none;
margin: 0;
.ant-tabs-tab{
background: none;
border: none;
color:#666666;
font-size: 16px;
&:hover{color: #4154F1;}
}
.ant-tabs-tab-active{
font-weight: bold;
color: #4154F1;
border-bottom: 1px solid #4154F1;
}
}
.invalid_extraction{
background: #F8F8F8;
}
.pagination-table .ant-table-thead > tr > th span, .ant-form label{
font-weight: bold;
}
.select_title{
height: 36px;
}
}
.expert_modal.extract{
.ant-modal-content {
width: 387px;
height: 230px;
.ant-modal-body {
padding: 3.5vh 3.5vw 0;
div{
display: flex;
align-items: center;
}
p{
color: red;
height: 2.9em;
}
.ml_40{
margin-left: -40px;
}
}
.ant-modal-footer {
margin-top: 0;
}
}
.ant-input{
width: 8vw;
}
}

View File

@ -0,0 +1,74 @@
// 专家注册页面需要的静态数据
export const unitType = [
{ value: "企业", label: "企业" },
{ value: "科研院所", label: "科研院所" },
{ value: "高等院校", label: "高等院校" },
{ value: "医疗机构", label: "医疗机构" },
{ value: "行政机关", label: "行政机关" },
{ value: "社会团体", label: "社会团体" },
{ value: "其他", label: "其他" }
];
export const natureOfWork = [
{ value: "研究", label: "研究" },
{ value: "管理", label: "管理" },
{ value: "开发", label: "开发" },
{ value: "服务", label: "服务" },
{ value: "其他", label: "其他" }
];
export const highestEducation = [
{ value: "博士", label: "博士" },
{ value: "硕士", label: "硕士" },
{ value: "本科", label: "本科" },
{ value: "大专", label: "大专" },
{ value: "其他", label: "其他" }
];
export const positionLevel = [
{ value: "正高级", label: "正高级" },
{ value: "副高级", label: "副高级" },
{ value: "中级", label: "中级" },
{ value: "初级", label: "初级" },
{ value: "未取得", label: "未取得" }
];
export const professionalType = [
{ value: "技术类", label: "技术类" },
{ value: "经济类", label: "经济类" },
{ value: "管理类", label: "管理类" }
];
export const reviewArea = [
{ value: "军事理论", label: "军事理论" },
{ value: "政策法规", label: "政策法规" },
{ value: "医学", label: "医学" },
{ value: "电子", label: "电子" },
{ value: "通信", label: "通信" },
{ value: "计算机科学", label: "计算机科学" },
{ value: "软件工程", label: "软件工程" },
{ value: "有机化学", label: "有机化学" },
{ value: "人工智能", label: "人工智能" },
{ value: "文学交流", label: "文学交流" },
{ value: "体育活动", label: "体育活动" }
];
export const taskType = [
{ value: 1, label: "创客评审任务" },
{ value: 2, label: "竞赛评审任务" },
];
export const expertTaskStatus = [
{ value: -1, label: "未评审" },
{ value: '1,2', label: "已评审" },
];
export const competitionStatus = [
{ value: 0, label: "未开始" },
{ value: 1, label: "报名中" },
{ value: 2, label: "即将开始" },
{ value: 3, label: "竞赛进行中" },
{ value: 4, label: "竞赛评选中" },
{ value: 5, label: "公示中" },
{ value: 6, label: "已结束" },
];

View File

@ -9,7 +9,7 @@
color: #ff6800;
}
.color-deep-blue {
color: #1b8fff;
color: #4154f1;
}
.centerbox {
width: 1200px;
@ -27,7 +27,7 @@
display: inline-flex;
align-items: center;
&:hover {
color: #409eff;
color: #4154f1;
}
}
}
@ -65,11 +65,11 @@
}
.center-left-butD:hover {
background-color: #fff;
color: #409eff;
color: #4154f1;
cursor: pointer;
}
.center-left-butDACT {
background-color: #409eff;
background-color: #4154f1;
color: #fff;
}
@ -215,7 +215,7 @@
background-color: #f1f1f1;
}
a {
color: #409eff;
color: #4154f1;
cursor: pointer;
}
}
@ -224,6 +224,47 @@
text-align: center;
}
.text-left{
text-align: left;
}
.search-screen {
display: flex;
flex-flow: row wrap;
justify-content: space-between;
margin: 1.25rem 0;
padding: 1.25rem;
background-color: #fff;
border-bottom: 1px solid #dedede;
> .ant-row {
min-width: 41%;
margin-right: 2rem;
.ant-form-item-label {
float: left;
}
.ant-form-item-control-wrapper {
overflow: hidden;
}
}
.center-right-but {
.ant-form-item {
margin: 0 1rem 0 0;
}
.ant-form-item-control-wrapper {
display: inline-block;
}
}
.button-div {
margin-right: 1.5rem;
}
.link{
color:#4154f1;
}
}
@media screen and (max-width: 1200px) {
.centerbox {
width: 98%;

View File

@ -66,7 +66,7 @@ service.interceptors.response.use(
});
return Promise.reject('error');
}
if (response.status !== 200 && res.status !== 200) {
if (!res.status.toString().startsWith('2')) {
notification.open({
message: "提示",
description: res.message,
@ -97,7 +97,9 @@ service.interceptors.response.use(
message: "提示",
description: res.data.message || '无权限!',
});
if(window.location.port !== "3007"){
window.location.href="/403";
}
return Promise.reject('error');
}

View File

@ -15,7 +15,7 @@
}
}
.list-title:hover {
color: #409eff;
color: #4154f1;
}
.list-title span {
padding: 3px 5px;

View File

@ -2,8 +2,8 @@
import javaFetch from '../javaFetch';
let settings=JSON.parse(localStorage.chromesetting);
let actionUrl = settings.api_urls? settings.api_urls.notice :'https://info.osredm.com';
let settings =localStorage.chromesetting && JSON.parse(localStorage.chromesetting);
let actionUrl = settings && settings.api_urls ? settings.api_urls.notice : 'https://info.osredm.com';
const service = javaFetch(actionUrl);
export const httpUrl = actionUrl;

View File

@ -51,7 +51,7 @@ const Index = (propsTransmit) => {
})
}, [])
let propsF = { ...propsTransmit };
propsF.current_user = currentUser;
propsF.current_user = {...propsF.current_user,...currentUser};
return (
<div className="newMain clearfix">

View File

@ -582,3 +582,21 @@ export function closeTask(taskId) {
method: 'post',
});
}
// 任务添加专家评审流程,expertReview: 1 加入 -1 不加入
export function addExpertReview(taskId,expertReview){
return fetch({
url: `/api/tasks/backend/joinExpertReview/${taskId}?expertReview=${expertReview}`,
method: 'put',
});
}
//发布评审任务
export function publishExpertsAndRules(taskId, containerType){
return fetch({
url: `/api/taskRuleCriteria/publishExpertsAndRules?containerId=${taskId}&containerType=${containerType}&status=-1`,
method: 'put'
})
}
// 管理页面修改创业

View File

@ -1,6 +1,6 @@
import React, { useMemo } from 'react';
import { Menu, Dropdown, } from 'antd';
import { current_main_site_url,main_web_site_url} from '../../static';
import { current_main_site_url, main_web_site_url } from '../../static';
import './index.scss';
@ -131,6 +131,8 @@ export default props => {
<Dropdown key={'configMenu'} overlay={configMenu} placement="bottomLeft">
<div className="drop-div">网站配置</div>
</Dropdown>
<div className="drop-div" ><a target="_blank" href="http://121.36.15.240:20772/">数据分析管理</a></div>
</div>
)
}

View File

@ -189,7 +189,7 @@ export default Form.create()((props) => {
<span className="with40 fl lineh-35 color-orange">
{
item.status === 4 && item.papersCount > 0 && (!item.isProofBoolean) && '未上传佐证材料'
item.status === 4 && item.papersCount > 0 && (!item.isProofBoolean) && (!item.expertReview) && '未上传佐证材料'
}
{item.status === 6 && item.agreementSigning === 0 && '未选择协议签订方式'}

View File

@ -226,7 +226,7 @@ export default Form.create()((props) => {
}
{
item.status === 4 && item.papersCount > 0 && (!item.isProofBoolean) && (!item.isProofBoolean) &&
!item.expertReview && item.status === 4 && item.papersCount > 0 && (!item.isProofBoolean) && (!item.expertReview) &&
<a onClick={() => { uploadProofs(item) }} className="line_1 color-blue">上传佐证材料</a>
}

View File

@ -11,6 +11,9 @@ import { reportPaper, thumbUpPaper, commentAdd, confirmReceipt } from '../../api
import { paperCheckStatusArr } from '../../static';
import { httpUrl } from '../../fetch';
import winpng from '../../image/winner.png';
import win1 from '../../image/win1.svg';
import win2 from '../../image/win2.svg';
import win3 from '../../image/win3.svg';
import './index.scss';
const { TextArea } = Input;
@ -21,7 +24,7 @@ for (const item of paperCheckStatusArr) {
}
export default Form.create()((props) => {
const { list, curPage, total, changePage, loading, applyStatusAllNameArr, reloadList, showNotification, current_user, form, detailStatus } = props;
const { list, curPage, total, changePage, loading, applyStatusAllNameArr, reloadList, showNotification, current_user, form, detailStatus, expertReview } = props;
const { getFieldDecorator, validateFields, setFieldsValue } = form;
const [page, setPage] = useState(1);
const pageSize = props.pageSize || 10;
@ -144,19 +147,23 @@ export default Form.create()((props) => {
{loading || loadingChild ? <Loading /> :
<React.Fragment>
{
list.map(item => {
list.map((item,i) => {
const winReview = [5,6,7,8].includes(detailStatus) && expertReview && item.reviewFinalGrades!==null;
return (
<div className="fileComments df" key={item.id}>
<img alt="头像加载失败" src={item.user && getImageUrl(item.user.logo)} width="50" height="50" className="bor-radius-all mr20" />
<div className="flex1">
<ul>
<li className="fl pr">
<li className="fl pr taskReview">
<span className={item.user.nickname === "******" ? "font-16 mr20 color-grey3" : "user-box font-16 mr20 color-grey3 clickable"} onClick={() => { item.user.nickname === "******" ? "" : goUser(item.user.login) }}>
{item.user.nickname || item.user.login}
</span>
<span className="color-grey9">{timeAgo(item.createdAt)}</span>
{item.status === 2 ? <img alt="胜出" className="mr5" src={winpng} /> : <span className="color-blue ml10">{item.checkStatus !== 1 ? paperCheckStatus[item.checkStatus] : applyStatusAllNameArr[item.status]}</span>}
{winReview && <span className='paper-grades'>评审得分<span className='paper-grades-num'>{item.reviewFinalGrades}</span></span>}
{winReview && i ==0 && <span className='winReview'><img src={win1}/>第一名</span>}
{winReview && i ==1 && <span className='winReview'><img src={win2}/>第二名</span>}
{winReview && i ==2 && <span className='winReview'><img src={win3}/>第三名</span>}
</li>
<li className="fr">
{((item.needComplain && detailStatus === 3) || (detailStatus === 5 && item.publicTaskComplain && item.checkStatus === 1 && item.status !== 2)) && (current_user.login === item.user.login) &&

View File

@ -20,11 +20,11 @@
.fileCommentsList {
background: #fafafa;
padding-top: .25rem;
padding-top: 0.25rem;
}
.comments-item{
margin-top:1rem;
.comments-item {
margin-top: 1rem;
}
.comments-content {
text-align: left;
@ -36,11 +36,33 @@
background-color: #fff;
}
.small-head{
.small-head {
max-width: 2rem;
}
.clickable:hover{
.clickable:hover {
color: #4cacff;
cursor: pointer;
}
.paper-grades {
margin-left:4rem;
font-size: 1rem;
color: #333333;
.paper-grades-num{
color: #FF0000;
}
}
.taskReview{
width: 100%;
.winReview{
position: absolute;
right: 0px;
color: #ff5f00;
font-size: 18px;
img{
margin-right: 8px;
}
}
}

View File

@ -10,7 +10,7 @@
.user-box{
cursor: pointer;
&:hover{
color: #409eff;
color: #4154f1;
}
.head-log-small{
position: relative;
@ -34,7 +34,7 @@
}
}
.list-title:hover {
color: #409eff;
color: #4154f1;
}
.list-title span {
padding: 0px 10px;

View File

@ -2,8 +2,9 @@
import javaFetch from '../javaFetch';
let settings=JSON.parse(localStorage.chromesetting);
let actionUrl = settings.api_urls? settings.api_urls.task :'https://task.osredm.com';
let settings=localStorage.chromesetting&&JSON.parse(localStorage.chromesetting);
let actionUrl = settings && settings.api_urls? settings.api_urls.task :'https://task.osredm.com';
// let actionUrl = 'http://117.50.100.12:8066'
const service = javaFetch(actionUrl);
export const httpUrl = actionUrl;

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1642486539996" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="25781" width="32" height="32" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"></style></defs><path d="M447.520033 0H123.673469l227.98441 446.09641H675.320648z" fill="#F72426" p-id="25782"></path><path d="M576.85911 0L349.058494 446.09641h323.715282L900.73193 0z" fill="#F72426" p-id="25783"></path><path d="M512.189571 225.962667A393.846154 393.846154 0 1 0 905.85193 619.651282c0-217.403077-176.259282-393.662359-393.662359-393.662359z m0 719.740718c-180.066462 0-326.052103-145.985641-326.052102-326.104616 0-180.066462 145.985641-326.052103 326.052102-326.052102 180.092718 0 326.078359 145.985641 326.078359 326.078359 0 180.092718-145.985641 326.078359-326.078359 326.078359z" fill="#F9E310" p-id="25784"></path><path d="M512.189571 293.546667C332.149366 293.546667 186.163725 439.532308 186.163725 619.651282c0 180.092718 145.985641 326.078359 326.052103 326.078359 180.092718 0 326.078359-145.985641 326.078359-326.104615 0-180.066462-145.985641-326.052103-326.078359-326.052103z m0 602.847179a276.926359 276.926359 0 1 1 276.374975-276.76882c0 152.733538-123.641436 276.637538-276.374975 276.926359v-0.183795z" fill="#F7931E" p-id="25785"></path><path d="M512.189571 342.882462a276.926359 276.926359 0 1 0 276.374975 276.742564c0-152.707282-123.667692-276.558769-276.374975-276.742564z m44.032 412.094359h-44.950974v-219.188513a152.891077 152.891077 0 0 1-62.464 33.240615V524.077949a165.677949 165.677949 0 0 0 39.095795-16.068923c12.550564-7.509333 24.155897-16.541538 34.527179-26.860308h33.792v273.854359z" fill="#FFA357" p-id="25786"></path></svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1642486397508" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="25397" width="32" height="32" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"></style></defs><path d="M447.520033 0H123.673469l227.98441 446.09641H675.320648z" fill="#F72426" p-id="25398"></path><path d="M576.85911 0L349.058494 446.09641h323.715282L900.73193 0z" fill="#F72426" p-id="25399"></path><path d="M512.189571 225.962667A393.846154 393.846154 0 1 0 905.85193 619.651282c0-217.403077-176.259282-393.662359-393.662359-393.662359z m0 719.740718c-180.066462 0-326.052103-145.985641-326.052102-326.104616 0-180.066462 145.985641-326.052103 326.052102-326.052102 180.092718 0 326.078359 145.985641 326.078359 326.078359 0 180.092718-145.985641 326.078359-326.078359 326.078359z" fill="#A2A2A2" p-id="25400"></path><path d="M512.189571 293.546667C332.149366 293.546667 186.163725 439.532308 186.163725 619.651282c0 180.092718 145.985641 326.078359 326.052103 326.078359 180.092718 0 326.078359-145.985641 326.078359-326.104615 0-180.066462-145.985641-326.052103-326.078359-326.052103z m0 602.847179a276.926359 276.926359 0 1 1 276.374975-276.76882c0 152.733538-123.641436 276.637538-276.374975 276.926359v-0.183795z" fill="#CACACA" p-id="25401"></path><path d="M255.927007 513.496615a276.926359 276.926359 0 1 0 532.637539 106.128411c0-152.707282-123.667692-276.558769-276.374975-276.742564a276.926359 276.926359 0 0 0-256.262564 170.614153z" fill="#989898" p-id="25402"></path><path d="M638.771725 761.435897v-45.371076h-168.723692c7.089231-18.432 28.829538-39.699692 65.220923-63.803077 33.555692-22.685538 56.713846-40.644923 69.947077-54.35077 21.740308-24.103385 33.083077-50.569846 33.083077-79.872 0-29.774769-10.397538-53.878154-30.72-72.782769-20.795077-18.904615-47.734154-27.884308-79.872-27.884308-35.918769 0-65.220923 11.815385-86.961231 36.391385-21.267692 22.685538-32.137846 52.932923-32.610462 90.742154h51.515077c0.945231-27.411692 6.616615-47.734154 17.959385-61.912615 10.870154-14.651077 26.939077-21.740308 48.206769-21.740308 19.849846 0 35.446154 4.726154 45.843693 14.178461 10.397538 9.452308 15.596308 23.630769 15.596307 42.535385 0 19.849846-8.034462 38.281846-23.158154 55.296-9.452308 9.924923-25.521231 22.685538-48.206769 38.754462-38.281846 26.466462-63.803077 46.788923-76.091077 61.44-22.685538 25.521231-33.555692 54.823385-33.555692 88.379076h232.526769z" fill="#FFFFFF" p-id="25403"></path></svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1642486410992" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="25589" width="32" height="32" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"></style></defs><path d="M447.520033 0H123.673469l227.98441 446.09641H675.320648z" fill="#F72426" p-id="25590"></path><path d="M576.85911 0L349.058494 446.09641h323.715282L900.73193 0z" fill="#F72426" p-id="25591"></path><path d="M512.189571 225.962667A393.846154 393.846154 0 1 0 905.85193 619.651282c0-217.403077-176.259282-393.662359-393.662359-393.662359z m0 719.740718c-180.066462 0-326.052103-145.985641-326.052102-326.104616 0-180.066462 145.985641-326.052103 326.052102-326.052102 180.092718 0 326.078359 145.985641 326.078359 326.078359 0 180.092718-145.985641 326.078359-326.078359 326.078359z" fill="#FFAE05" p-id="25592"></path><path d="M512.189571 293.546667C332.149366 293.546667 186.163725 439.532308 186.163725 619.651282c0 180.092718 145.985641 326.078359 326.052103 326.078359 180.092718 0 326.078359-145.985641 326.078359-326.104615 0-180.066462-145.985641-326.052103-326.078359-326.052103z m0 602.847179a276.926359 276.926359 0 1 1 276.374975-276.76882c0 152.733538-123.641436 276.637538-276.374975 276.926359v-0.183795z" fill="#FF7327" p-id="25593"></path><path d="M255.927007 513.496615a276.926359 276.926359 0 1 0 532.637539 106.128411c0-152.707282-123.667692-276.558769-276.374975-276.742564a276.926359 276.926359 0 0 0-256.262564 170.614153z" fill="#F69D5A" p-id="25594"></path><path d="M523.926187 768.052513c35.918769 0 65.693538-10.397538 88.379077-30.247385 21.267692-19.849846 32.137846-45.371077 32.137846-76.563692 0-19.849846-5.671385-36.391385-17.014154-49.152-10.397538-12.288-25.521231-21.740308-45.371077-27.884308 36.864-12.288 55.768615-37.336615 55.768615-74.200615 0-28.829538-10.397538-51.515077-30.247384-68.056616-20.795077-16.541538-47.734154-24.576-81.762462-24.576-33.083077 0-60.022154 8.979692-80.817231 27.884308-22.212923 18.904615-34.500923 44.898462-37.336615 78.454154h50.569846c1.890462-20.795077 8.979692-36.391385 20.322462-46.788923 11.342769-10.397538 27.411692-15.596308 47.734154-15.596308 19.849846 0 35.446154 4.253538 45.843692 13.705846 9.452308 8.979692 14.651077 21.740308 14.651077 38.754462s-5.671385 30.247385-16.068923 39.227077c-10.397538 8.979692-25.993846 13.705846-46.788923 13.705846h-24.103385v38.754462h24.576c22.212923 0 39.227077 4.726154 50.569846 14.178461 12.288 9.452308 18.432 24.103385 18.432 43.953231 0 17.014154-6.144 30.72-17.486769 42.062769-13.233231 12.288-30.72 18.904615-52.460308 18.904615-19.849846 0-35.918769-5.671385-48.206769-17.014153-14.178462-12.288-21.267692-29.774769-22.212923-52.460308h-51.987692c2.835692 37.809231 16.068923 66.638769 39.699692 86.488615 20.795077 17.486769 48.679385 26.466462 83.180308 26.466462z" fill="#FFFFFF" p-id="25595"></path></svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -87,7 +87,7 @@ span.list-gray {
background: #bababa;
}
.ant-pagination {
.center-content .ant-pagination {
margin: 2rem auto;
text-align: center;
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1641461455018" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="50275" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M949.696 266.304a34.88 34.88 0 0 0-49.6 0L512 654.4 123.904 266.304a34.88 34.88 0 0 0-49.6 0 34.88 34.88 0 0 0 0 49.6l412.928 412.864c13.696 13.76 35.84 13.76 49.536 0l412.928-412.864a34.944 34.944 0 0 0 0-49.6z" fill="#bfbfbf" p-id="50276"></path></svg>

After

Width:  |  Height:  |  Size: 632 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1641461401607" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="25602" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M761.6 489.6l-432-435.2c-9.6-9.6-25.6-9.6-35.2 0-9.6 9.6-9.6 25.6 0 35.2l416 416-416 425.6c-9.6 9.6-9.6 25.6 0 35.2s25.6 9.6 35.2 0l432-441.6C771.2 515.2 771.2 499.2 761.6 489.6z" p-id="25603" fill="#bfbfbf"></path></svg>

After

Width:  |  Height:  |  Size: 599 B

View File

@ -1,12 +1,14 @@
import React, { useCallback, useEffect, useState, useMemo } from 'react';
import classNames from 'classnames';
import { Input, Select, Button, Form, DatePicker, Table, Pagination, Modal } from 'antd';
import { Link } from "react-router-dom";
import { Input, Select, Button, Form, DatePicker, Table, Pagination, Modal, message } from 'antd';
import { Link } from 'react-router-dom';
import { paperCheckStatusArr, publishModeArr, taskStatusAllArr, showUserModeArr, main_web_site_url } from '../static';
import { getTaskAdminList, changeShowUserMode, deleteTask, recommendTask } from '../api';
import { paperCheckStatusArr, publishModeArr, taskStatusAllArr, showUserModeArr, main_web_site_url, expertReviewArr } from '../static';
import { getTaskAdminList, changeShowUserMode, deleteTask, recommendTask, addExpertReview, publishExpertsAndRules } from '../api';
import '../index.scss';
import './index.scss';
import { getRules, selectExpertList } from 'src/military/expert/api';
import PaginationTable from '../../../../src/military/components/paginationTable';
const format = "YYYY-MM-DD HH:mm:ss";
const Option = Select.Option;
@ -20,9 +22,9 @@ for (const item of paperCheckStatusArr) {
}
export default Form.create()(({ form, showNotification, match, history }) => {
export default Form.create()(({ form, showNotification, match, history, state }) => {
const { getFieldDecorator, setFieldsValue, getFieldsValue } = form;
const { hash} = history && history.location;
const [reload, setReload] = useState();
const [loading, setLoading] = useState(false);
const [statusString, setStatusString] = useState('');
@ -34,10 +36,22 @@ export default Form.create()(({ form, showNotification, match, history }) => {
const [sort, setSort] = useState('Desc');
const [order, setOrder] = useState('createdAt');
const [searchObj, setSearchObj] = useState({});
const [curPage, setCurPage] = useState(1);
const [curPage, setCurPage] = useState(hashDate(hash) || 1);
const [total, setTotal] = useState(0);
const [taskList, setTaskList] = useState([]);
const [expertReview, setExpertReview] = useState('');
//
const [lookRules, setLookRules] = useState(false);
const [lookExperts, setLookExperts] = useState(false);
const [pulicReview, setPublicReview] = useState(false);
const [rules, setRules] = useState(undefined);
const [selectedExperts, setSelectedExperts] = useState(undefined);
const [publicTaskId, setPublicTaskId] = useState(undefined);
useEffect(()=>{
setCurPage(hashDate(hash) || 1);
},[hash])
useEffect(() => {
const params = {
@ -50,6 +64,7 @@ export default Form.create()(({ form, showNotification, match, history }) => {
orderBy: order + sort,
isDelete,
recommend,
expertReview: expertReview==='-1'?"":expertReview,
};
setLoading(true);
getTaskAdminList(params).then(data => {
@ -59,7 +74,7 @@ export default Form.create()(({ form, showNotification, match, history }) => {
}
setLoading(false);
})
}, [statusString, order, sort, publishMode, showUserMode, curPage, searchObj, isDelete, reload, recommend]);
}, [statusString, order, sort, publishMode, showUserMode, curPage, searchObj, isDelete, reload, recommend, expertReview]);
const helper = useCallback(
@ -69,13 +84,17 @@ export default Form.create()(({ form, showNotification, match, history }) => {
</Form.Item>
), []);
function hashDate(hash) {
return parseInt(hash.split("&")[0].substring(hash.split("&")[0].indexOf("=")+1));
}
function onSearch() {
let values = getFieldsValue(['nameInput', 'endTime', 'startTime', 'enterpriseNameInput']);
if (values.startTime) values.startTime = values.startTime.format(format);
if (values.endTime) values.endTime = values.endTime.format(format);
if (values.checkStatus === '0,1,2') values.checkStatus = '';
setSearchObj(values);
setCurPage1(1);
// window.location.href=`/task/taskAdmin`;
}
function clearSearch() {
@ -90,31 +109,48 @@ export default Form.create()(({ form, showNotification, match, history }) => {
const columns = useMemo(() => {
return [
{
title: '序号',
dataIndex: 'index',
render: (text, record, index) => {
return <div style={{ textAlign: 'center' }}>{index + 1}</div>
}
},
{
title: '任务编号',
dataIndex: 'number',
},
{
title: '任务名称',
dataIndex: 'name',
width: "15%",
width: "13%",
render: (text, record) => (
<Link className="line_1 primary-link" target="_blank" to={`/task/taskDetail/${record.id}`} >{text}</Link>
),
},
{
title: <Select
className="column-select"
showArrow
defaultValue={'-1'}
onChange={(value)=>{setExpertReview(value);setCurPage1(1);}}
>
<Option key={'-1'} >专家评审</Option>
<Option key={'1'} >已提交评审</Option>
<Option key={'0'} >未提交评审</Option>
</Select>,
dataIndex: 'expertReview',
render: (text, record) => {
return <Select
className="column-select"
showArrow
defaultValue={text?1:-1}
onChange={(key) => { changeExpertReviewStatus(key, record.id) }}
disabled={record.assignRuleAndExperts || !(record.status == 1 || record.status == 3)}
>
{
expertReviewArr.map(item => {
return <Option key={item.dicItemCode} value={item.dicItemCode}>{item.dicItemName}</Option>
})
}
</Select>
}
},
{
title: <Select
className="column-select"
showArrow
defaultValue={'0,1'}
onChange={setPublishMode}
onChange={(value)=>{setPublishMode(value);setCurPage1(1);}}
>
<Option key={'0,1'} >发布方式</Option>
<Option key={'0'} >自主提交</Option>
@ -130,7 +166,7 @@ export default Form.create()(({ form, showNotification, match, history }) => {
className="column-select"
showArrow
defaultValue={'0,1,2,3,4,5,6,7,8,9'}
onChange={setStatusString}
onChange={(value)=>{setStatusString(value);setCurPage1(1);}}
>
<Option key={'0,1,2,3,4,5,6,7,8,9'} >任务状态</Option>
{
@ -139,30 +175,21 @@ export default Form.create()(({ form, showNotification, match, history }) => {
})
}
</Select>,
width: '10%',
width: '6%',
dataIndex: 'status',
render: (text, record) => {
return record.exceptClosedBoolean ? '已关闭' : statusArr[text]
}
},
{
title: '稿件数',
dataIndex: 'papersCount',
},
{
title: '发布主体',
dataIndex: 'enterpriseName',
width: '9%',
},
{
title: '发布时间',
dataIndex: 'publishedAt',
render: (text, record) => {
return text || '--'
}
},
{
title: '截稿时间',
dataIndex: 'collectingEndTime',
width: '7%',
render: (text, record) => {
return text || '--'
}
@ -176,7 +203,7 @@ export default Form.create()(({ form, showNotification, match, history }) => {
defaultValue={'0,1,2'}
onChange={setShowUserMode}
>
<Option key={'0,1,2'}>应征者名单公示</Option>
<Option key={'0,1,2'}>应征者公示</Option>
{
showUserModeArr.map(item => {
return <Option key={item.dicItemCode}>{item.dicItemName}</Option>
@ -184,6 +211,7 @@ export default Form.create()(({ form, showNotification, match, history }) => {
}
</Select>,
dataIndex: 'showUserMode',
width:'8%',
render: (text, record) => {
return <Select
className="column-select"
@ -200,9 +228,38 @@ export default Form.create()(({ form, showNotification, match, history }) => {
</Select>
}
},
{
title: '评审规则',
dataIndex: 'ruleEditedCount',
render: (text, record) => {
return record.assignRuleAndExperts ? <Button size='small' type="primary" onClick={()=>{viewRules(record)}}>查看</Button> : record.expertReview && (record.status === 1 || record.status === 3) ? <Link className="line_1 primary-link" to={`/expert/admin/task/review/rules/${1}/${record.id}/?status=${record.status}&name=${record.name}&createdAt=${record.createdAt}&collectingEndTime=${record.collectingEndTime}&choosingDays=${record.choosingDays}`}>编辑</Link> : <span className='gary_span'>编辑</span>
}
},
{
title: '专家选取',
dataIndex: 'expertSelectedCount',
render: (text, record) => {
return record.assignRuleAndExperts ? <Button size='small' type="primary" onClick={()=>{viewExperts(record)}}>查看</Button> : record.expertReview && (record.status === 1 || record.status === 3) ? <Link className="line_1 primary-link" to={`/expert/admin/task/review/select/${1}/${record.id}/?name=${record.name}`}>选择</Link> : <span className='gary_span'>选择</span>
}
},
{
title: '评审任务',
dataIndex: 'expertReview1',
render: (text, record) => {
return record.assignRuleAndExperts ? <span className='gary_span'>已发布</span> : record.expertReview && (record.status === 1 || record.status === 3) ? <Button size='small' type="primary" onClick={()=>{publishTaskReview(record)}}>发布</Button> : <span className='gary_span'>发布</span>
}
},
{
title: '评审结果',
dataIndex: 'expertReview2',
render: (text, record) => {
return record.assignRuleAndExperts ? <Link className="line_1 primary-link" to={`/expert/admin/task/review/results/${1}/${record.id}/#status=${record.status}&name=${record.name}&taskModeId=${record.taskModeId}`}>查看</Link>:<span className='gary_span'>查看</span>
}
},
{
title: '操作',
key: 'action',
width: '6%',
render: (text, record) => (
<React.Fragment>
@ -224,7 +281,58 @@ export default Form.create()(({ form, showNotification, match, history }) => {
),
},
]
}, [isDelete]);
}, [isDelete, curPage]);
//
const columnsExperts = useMemo(() => {
return [
{
title: '编号',
dataIndex: 'index',
width: 80,
align: 'center',
},
{
title: '专家姓名',
dataIndex: 'expertName',
key: 'expertName',
width: 120,
},
{
title: '手机号码',
dataIndex: 'phone',
width: 130,
key: 'phone',
},
{
title: '最高学历',
dataIndex: 'highestDegree',
key: 'highestDegree',
},
{
title: '专业职称',
dataIndex: 'professionalTitle',
},
{
title: '专家类别',
dataIndex: 'expertType',
},
{
title: '评审领域',
dataIndex: 'reviewAreas',
align: 'center',
width: 260,
},
{
title: '专家评估',
dataIndex: 'expertScore',
align: 'center',
render:(text,record)=>{
return record.expertScore || '--';
}
}
];
}, []);
function recommendItem(id, recommend) {
Modal.confirm({
@ -260,6 +368,128 @@ export default Form.create()(({ form, showNotification, match, history }) => {
});
}
//lookRules,lookExperts,pulicReview
useEffect(()=>{
//
lookRules && rules && Modal.info({
className: 'publishReview',
title: "评审规则",
content:
<React.Fragment>
<div>{rules && rules.rule}</div>
<p>评分标准</p>
<div>
{rules.criterias.map(item=>{return <p key={Math.random()}>{item}</p>})}
</div>
<p>评审时间</p>
<div>{rules.reviewData}</div>
</React.Fragment>
,
});
lookRules && setLookRules(false);
//
lookExperts && selectedExperts && Modal.info({
className: 'publishReview',
title: "已选取评审专家",
content:
<PaginationTable
dataSource={selectedExperts}
columns={columnsExperts}
scroll={{ y: 395 }}/>,
});
lookExperts && setLookExperts(false);
//
pulicReview && rules && selectedExperts && Modal.confirm({
className: 'publishReview',
title: "发布评审任务",
centered: true,
content:
<React.Fragment>
<div className='tip'>
<i className='iconfont icon-erciqueren_icon'></i>
<span className='publicTitle'>确定发布此评审任务确定发布后评审规则与评审专家信息将无法重新编辑</span>
</div>
<p>评审规则</p>
<div>{rules && rules.rule}</div>
<p>评分标准</p>
<div>
{rules.criterias.map(item=>{return <p key={Math.random()}>{item}</p>})}
</div>
<p>评审时间</p>
<div>{rules.reviewData}</div>
<p>已选取评审专家</p>
<PaginationTable
dataSource={selectedExperts}
columns={columnsExperts}
scroll={{ y: 230 }}/>
</React.Fragment>
,
okText: '确定',
cancelText: '取消',
onOk() {
publishExpertsAndRules(publicTaskId,1).then(response=>{
if(response && response.message==="发布成功"){
setReload(Math.random());
}
})
},
});
pulicReview && setPublicReview(false);
},[lookRules,lookExperts,pulicReview])
//
function publishTaskReview(record){
if(!record.ruleEditedCount || !record.expertSelectedCount){
message.error("请先编辑评审规则以及选取评选专家再发布此任务");
}else{
getRules({containerId: record.id, containerType: 1, statusString: 3}).then(response=>{
if(response && response.message === "success"){
setRules(response.data);
}
})
selectExpertList({containerId: record.id, containerType: 1, curPage:curPage, pageSize: 10000, curPage: 1,}).then(response=>{
if(response && response.message === "success" && Array.isArray(response.data.rows)){
let index = 1;
for (const item of response.data.rows) {
item.reviewAreas = `${item.reviewAreaOne} ${item.reviewAreaTwo ? `${item.reviewAreaTwo}`:''} ${item.reviewAreaThree ? `${item.reviewAreaThree}`:''}`;
item.index = (index++) + (curPage > 1 ? (curPage - 1) * 10 : 0);
}
setPublicTaskId(record.id);
setSelectedExperts(response.data.rows);
setPublicReview(true);
}
});
}
}
//
function viewRules(record){
getRules({containerId: record.id, containerType: 1, statusString: '-1,1,2'}).then(response=>{
if(response && response.message === "success"){
setRules(response.data);
setLookRules(true);
}
});
}
//
function viewExperts(record){
selectExpertList({containerId: record.id, containerType: 1, curPage:curPage, pageSize: 10000, curPage: 1,}).then(response=>{
if(response && response.message === "success" && Array.isArray(response.data.rows)){
let index = 1;
for (const item of response.data.rows) {
item.reviewAreas = `${item.reviewAreaOne} ${item.reviewAreaTwo ? `${item.reviewAreaTwo}`:''} ${item.reviewAreaThree ? `${item.reviewAreaThree}`:''}`;
item.index = (index++) + (curPage > 1 ? (curPage - 1) * 10 : 0);
}
setSelectedExperts(response.data.rows);
setLookExperts(true);
}
});
}
function changeStatus(showUserMode, taskId) {
changeShowUserMode({
taskId,
@ -271,22 +501,37 @@ export default Form.create()(({ form, showNotification, match, history }) => {
})
}
function changeExpertReviewStatus(expertReviewStatus, taskId) {
addExpertReview(taskId,expertReviewStatus).then(res => {
if (res && res.message === 'success') {
showNotification('操作成功!');
setReload(Math.random());
} else {
showNotification('操作失败');
}
})
}
function setCurPage1(page){
setCurPage(page);
window.location.href=`/task/taskAdmin#page=${page}`;
}
//
const changeSortName = useCallback((sortType) => {
setOrder(sortType);
setCurPage(1);
setCurPage1(1);
}, []);
//
const changeSort = useCallback((sort) => {
setSort(sort);
setCurPage(1);
setCurPage1(1);
}, []);
const changeShow = useCallback((isDelete) => {
setIsDelete(isDelete);
setCurPage(1);
setCurPage1(1);
});
const changeRecommend = useCallback((recommend) => {
@ -295,9 +540,17 @@ export default Form.create()(({ form, showNotification, match, history }) => {
} else {
setRecommend(recommend);
}
setCurPage(1);
setCurPage1(1);
});
const ExpertDetail = (record)=>{
return <div className="expert_detail_div">
<div> 任务编号{record.number} </div>
<div> 截稿时间{record.collectingEndTime || '--'} </div>
<div> 稿件数{record.papersCount || '--'} </div>
</div>
}
function downloadFile() {
window.open(main_web_site_url + '/admin/tasks.xlsx');
}
@ -403,10 +656,6 @@ export default Form.create()(({ form, showNotification, match, history }) => {
</Form.Item>
</div>
<div className="center-content">
<Table
@ -416,10 +665,11 @@ export default Form.create()(({ form, showNotification, match, history }) => {
columns={columns}
pagination={false}
className="mt10"
expandedRowRender={ExpertDetail}
/>
{total > 10 &&
<Pagination
onChange={(page) => { setCurPage(page) }}
onChange={(page) => { setCurPage1(page) }}
current={curPage}
total={total}
/>}

View File

@ -41,7 +41,7 @@
}
.ant-table-thead > tr > th,
.ant-table-tbody > tr > td {
padding: 1rem 0.2rem;
padding: 1rem 0.1rem;
text-align: center;
}
@ -53,7 +53,19 @@
display: flex;
justify-content: space-between;
}
.ant-table-row-expand-icon{
width: 35px;
height: 20px;
line-height: 20px;
}
.expert_detail_div{
display: flex;
justify-content: space-around;
}
// .ant-table-row-collapsed::after, .ant-table-row-expanded::after {
// content: url('./image/down.svg');
// }
}
.inline-form {
@ -74,3 +86,55 @@
.sort-active {
color: #29bd8b;
}
.gary_span{
color: rgba(176, 176, 176, 1);
}
// 发布评审任务弹框样式
.publishReview{
width: 1050px !important;
.ant-modal-body{
padding: 0;
}
.ant-modal-confirm-btns {
margin: 15px 35px 10px;
}
.ant-modal-confirm-title{
border-bottom: 1px solid #eeeeee;
padding: 20px 25px;
background: #f2f2ff;
font-size: 18px;
}
.ant-modal-confirm-body > .anticon{
display: none;
}
.ant-modal-confirm-body > .anticon + .ant-modal-confirm-title + .ant-modal-confirm-content{
margin-left: 0;
}
.ant-modal-confirm-content{
&>p{
font-size: 16px;
color: #333333;
border-bottom: 1px solid #eeeeee;
padding: 10px 35px;
font-weight: bold;
}
&>div{
padding: 10px 45px;
}
.tip{
padding: 10px 35px;
i{
color: #ca0002;
}
.publicTitle {
font-size: 15px;
margin-left: 3px;
}
}
}
.pagination-table .ant-table-tbody > tr > td{
padding: 3px 8px;
}
}

View File

@ -3,7 +3,7 @@ import React from "react";
import { Route, Switch } from "react-router-dom";
import Loadable from "react-loadable";
import Loading from "../../Loading";
import AdminRouter from "./components/adminRouter";
import AdminRouter from "../components/adminRouter";
const TaskManage = Loadable({

View File

@ -8,10 +8,11 @@ import Upload from '../../components/Upload';
import StatusNav from '../../components/statusNav';
import ItemListPaper from '../components/itemListPaper';
import ProofModal from '../components/proofModal';
import { getTaskDetail, getTaskCategory, getTaskPaper, makePublic, addPaper, getAgreement, agreement, checkAgreement, checkHavePaper } from '../api';
import { getTaskDetail, getTaskCategory, getTaskPaper, makePublic, addPaper, getAgreement, agreement, checkAgreement, checkHavePaper, addExpertReview } from '../api';
import { taskModeIdArr, applyStatusArr, applyStatusAllArr, agreementContent, paperCheckTextArr } from '../static';
import { httpUrl } from '../fetch';
import './index.scss';
import { getRules } from 'src/military/expert/api';
const { TextArea } = Input;
@ -52,6 +53,8 @@ export default Form.create()(
const [relaodChildList, setRelaodChildList] = useState(0);
const [visibleProofs, setVisibleProofs] = useState(false);
//
const [publishedReviewRules, setPublishedReviewRules] = useState(undefined);
//
useEffect(() => {
@ -73,6 +76,11 @@ export default Form.create()(
history.push('/task');
}
setDetailData(data || {});
if(data && data.assignRuleAndExperts){
getRules({ containerId: data.id, containerType: 1, statusString: '-1,1,2', }).then(response=>{
response && setPublishedReviewRules(response.data || undefined);
})
}
});
}, [id, reload]);
@ -278,6 +286,22 @@ export default Form.create()(
}
}
function addExpertReviewModal(){
Modal.confirm({
title: '提示',
content: '确定将此创客任务添加专家评审流程?',
onOk: () => {
addExpertReview(id,1).then(res => {
if (res && res.message === 'success') {
setReload(Math.random());
} else {
showNotification('操作失败');
}
})
}
})
}
const reloadList = useCallback(() => {
setRelaodChildList(Math.random());
});
@ -435,6 +459,14 @@ export default Form.create()(
<p className="color-grey-6 lineh-20 padding10-15 mb10">
应征者提交的稿件必须是设计作品广告等无效交稿一律不采用
</p>
{publishedReviewRules && <React.Fragment>
<div className="font-16 font-bd">评审规则</div>
<p className="color-grey-6 lineh-20 padding10-15 mb10">{publishedReviewRules.rule}</p>
<div className="font-16 font-bd">评分标准</div>
<p className="color-grey-6 lineh-20 padding10-15 mb10">{publishedReviewRules.criterias.map(item=>{return <p>{item}</p>})}</p>
<div className="font-16 font-bd">评审时间</div>
<p className="color-grey-6 lineh-20 padding10-15 mb10">{publishedReviewRules.reviewData}</p>
</React.Fragment>}
</div>
{!current_user.enterpriseCertification && <div className="edu-back-white padding30 mt20 font-16 text-center mb50">
@ -448,10 +480,12 @@ export default Form.create()(
{!detailData.showUserStatus && <Tooltip placement="top" title={"不公示应征者姓名"}>
<i data-tip-down="不公示应征者姓名" className="iconfont icon-yincang1 color-grey9 font-20"></i>
</Tooltip>}
{detailData.status === 4 && dataList.length && (!detailData.isProofBoolean) && detailData.user && (current_user.admin || current_user.login === detailData.user.login) ?
{detailData.status === 4 && dataList.length && (!detailData.isProofBoolean) && (!detailData.expertReview) && detailData.user && (current_user.admin || current_user.login === detailData.user.login) ?
<a className="line_1 color-blue fr ml20" onClick={() => { setVisibleProofs(true) }}>上传佐证材料</a> : ''}
{dataList.length > 0 && taskLimit && <a className="line_1 color-blue fr ml20" onClick={() => { window.open(`${httpUrl}/api/paper/papers/download/${id}`) }}>一键导出成果物 &gt;&gt;</a>}
{(!detailData.showUserStatus) && taskLimit && <a className="fr color-orange ml20" onClick={showUser}>应征者名单公示 &gt;&gt;</a>}
{(!detailData.showUserStatus) && !detailData.expertReview && taskLimit && <a className="fr color-orange ml20" onClick={showUser}>应征者名单公示 &gt;&gt;</a>}
{/* [添加专家评审流程]按钮入口,仅管理员可见 */}
{taskLimit && !detailData.expertReview && detailData.status<4 && <a className="fr color-orange ml20" onClick={addExpertReviewModal}>添加专家评审流程</a>}
</div>
<StatusNav
key={'applyStatus'}
@ -473,6 +507,7 @@ export default Form.create()(
showNotification={showNotification}
detailStatus={detailData.status}
agreementSigning={detailData.agreementSigning}
expertReview={detailData.expertReview}
/>
</div>

View File

@ -6,7 +6,7 @@
display: inline-flex;
align-items: center;
&:hover {
color: #409eff;
color: #4154f1;
}
}
}
@ -105,7 +105,7 @@
}
.content-download {
color: #409eff;
color: #4154f1;
}
@ -152,8 +152,8 @@
.task-detail{
.ant-btn-primary{
background-color:#409eff;
border-color: #409eff;
background-color:#4154f1;
border-color: #4154f1;
}
}

View File

@ -1,5 +1,5 @@
import React, { forwardRef, useCallback, useEffect, useState } from 'react';
import { Form, Radio, Input, InputNumber, Icon, Button, Modal } from 'antd';
import { Form, Radio, Input, InputNumber, Icon, Button, Modal, Checkbox } from 'antd';
import classNames from 'classnames';
import moment from 'moment';
import ReactWEditor from 'wangeditor-for-react';
@ -358,6 +358,13 @@ export default Form.create()(forwardRef(({ current_user, form, showNotification,
任务发布之后将会公开展示在交易中心不要把与项目客户相关等隐私信息以及QQ号微信号电话号码等联系方式填写在任务中
</p>
<Form.Item >
{getFieldDecorator('expertReview', {
validateFirst: true,
initialValue: false
})(<Checkbox className="color-grey-3 font-bd mb10 font-18">是否增加专家评审流程添加后可联系管理员发布此专家评审任务</Checkbox>)}
</Form.Item>
<Form.Item >
<Upload
className="commentStyle"

View File

@ -17,7 +17,7 @@
top: 3px;
width: 2px;
height: 16px;
background: #459be6;
background: #4154f1;
content: "";
}
@ -42,8 +42,8 @@
}
.choose-button.active {
color: #4cacff !important;
border: 1px solid #4cacff;
color: #4154f1 !important;
border: 1px solid #4154f1;
}
.gray-form {
@ -61,7 +61,7 @@
padding: 0.25em;
font-size: 1rem;
color: #fff;
background: #1484ef;
background: #4154f1;
border-radius: 50%;
cursor: pointer;
}
@ -113,7 +113,7 @@
color: #333;
&:before {
background: #4cacff;
background: #4154f1;
}
}

View File

@ -10,17 +10,13 @@ class Shixunauthority extends Component {
<div className="edu-txt-center mt60 mb60">
{/*mt100 mb100*/}
<img src={getImageUrl("images/warn/pic_403.jpg")} />
<p className="font-16 mt56 newImages">
<p>您尚未被授权访问此页面请先获取相关权限</p>
您可尝试
{(!current_user || !current_user.login) && (
<p style={{display:"inline"}}>您可尝试<a href="//testforgeplus.trustie.net/login" className="color-blue">登录</a></p>
)}
<a href="/"
className="color-blue">返回首页</a>
<p className="font-18 mt40">
您可以稍后尝试&nbsp;<a href="/"
className="color-blue">返回首页</a>
{/* &nbsp;
<a target="_blank"
href="https://qm.qq.com/cgi-bin/qm/qr?k=YVGUhY7uK8ovpyd7tG_lHe2qGZ63LOij&jump_from=webapi"
className="color-blue">QQ</a>
href="//shang.qq.com/wpa/qunwpa?idkey=2f2043d88c1bd61d182b98bf1e061c6185e23055bec832c07d8148fe11c5a6cd"
className="color-blue">QQ反馈&gt;&gt;</a> */}
</p>
</div>
{/*<div style="clear:both;"></div>*/}

View File

@ -26,23 +26,22 @@ class http500 extends Component {
render() {
const { current_user } = this.props;
return (
<div className="newMain newTable clearfix">
<div className=" edu-txt-center mt60">
<div className="newMain clearfix">
{
this.state.isAdmins? <Loading />:<div className=" edu-txt-center mt60 mb60">
{/*mt100 mb100*/}
<img src={getImageUrl("/images/warn/pic_404.jpg")} />
<p className="font-16 mt56 newImages">
<p>你访问的页面不存在</p>
您可尝试
{(!current_user || !current_user.login) && (
<p style={{display:"inline"}}>您可尝试<a href="/login" className="color-blue">登录</a></p>
)}
<a href="/" className="color-blue">返回首页</a>
也可通过
<img src={getImageUrl("images/warn/pic_404.jpg")} />
<p className="font-18 mt40">
您可以稍后尝试&nbsp;<a href="/"
className="color-blue">返回首页</a>
{/* &nbsp;
<a target="_blank"
href="//shang.qq.com/wpa/qunwpa?idkey=2f2043d88c1bd61d182b98bf1e061c6185e23055bec832c07d8148fe11c5a6cd"
className="color-blue">QQ</a>
className="color-blue">QQ反馈&gt;&gt;</a> */}
</p>
</div>
}
{/*<div style="clear:both;"></div>*/}
{/*<div id="ajax-indicator" style="display:none;"><span>载入中...</span></div>*/}
{/*<div id="ajax-modal" style="display:none;"></div>*/}

Some files were not shown because too many files have changed in this diff Show More