Compare commits
265 Commits
master
...
dev_milita
Author | SHA1 | Date |
---|---|---|
zhangmu | aa7125abd1 | |
谢思 | bf58961a23 | |
zhangmu | a560159a63 | |
何童崇 | 3ecae5ba43 | |
baladiwei | 846a24aef4 | |
baladiwei | 955eed9232 | |
何童崇 | 1bad39e83a | |
何童崇 | c9e7da7df3 | |
何童崇 | 7f0b770dca | |
baladiwei | 70536036e1 | |
baladiwei | 0f92ff94a0 | |
何童崇 | 6507c87bc8 | |
何童崇 | b423e4b7e7 | |
baladiwei | 938be1da55 | |
何童崇 | 162fd200a5 | |
baladiwei | d9bd0387db | |
何童崇 | c0cfe12db4 | |
何童崇 | c3ecbe1f97 | |
何童崇 | a59a8c3693 | |
baladiwei | 97f62a5684 | |
baladiwei | e74a3b6a95 | |
何童崇 | 38878183d5 | |
baladiwei | 0e0c13f1a4 | |
何童崇 | a667a32de0 | |
何童崇 | 230e597787 | |
何童崇 | f0ea3a53c4 | |
何童崇 | 51a4680481 | |
baladiwei | 61a4882e58 | |
何童崇 | 148e8f91eb | |
baladiwei | 8f52a091fa | |
tongChong | 62eabdf7c0 | |
谢思 | d5490d5e71 | |
baladiwei | cef374c52d | |
谢思 | 7be60d3140 | |
durian | feafa5b6f3 | |
谢思 | 2dd6ed108f | |
baladiwei | 969323fdde | |
何童崇 | a73b4ff79a | |
baladiwei | 16ca2a359e | |
baladiwei | 444d954e72 | |
何童崇 | 6fc31c0bb8 | |
何童崇 | cf73f72e19 | |
baladiwei | 745a25a003 | |
tongChong | b080df1449 | |
何童崇 | 0aa2a4aec3 | |
何童崇 | 4dc1c4c814 | |
何童崇 | ddc576b054 | |
谢思 | caef7a0ab3 | |
谢思 | 85f0578302 | |
baladiwei | bff55b6810 | |
baladiwei | 01f71bca87 | |
何童崇 | d3cea0ff3b | |
baladiwei | be6e3d273b | |
何童崇 | 6b8f1e3749 | |
tongChong | b5e145b4b5 | |
何童崇 | 15b63be594 | |
谢思 | 032127bef6 | |
谢思 | f4f843a7b9 | |
何童崇 | 4cf8357463 | |
何童崇 | 0ff1367ad8 | |
何童崇 | 0e44cbbcdd | |
tongChong | e736591a4f | |
tongChong | d15900fc7c | |
谢思 | 4f87542f1f | |
何童崇 | 94ee3601c9 | |
tongChong | 19d09c7901 | |
谢思 | 3b29605321 | |
何童崇 | 6e82862307 | |
tongChong | 700ac5862e | |
谢思 | 4ccab2ed4f | |
何童崇 | 3f3299a3b8 | |
baladiwei | b73a38351b | |
baladiwei | 586c5d6d1d | |
tongChong | 819772d180 | |
谢思 | e733f1886e | |
tongChong | 86d2442958 | |
谢思 | b7fc83edf9 | |
tongChong | 74325b5dc7 | |
xiesi | a25959bfa0 | |
baladiwei | fe72be2f30 | |
baladiwei | 4d41f44100 | |
tongChong | afa839e0b1 | |
xiesi | 83d59a2e64 | |
tongChong | 758f4267ed | |
xiesi | 38948a84cd | |
xiesi | 51d739f4a0 | |
tongChong | 706830928e | |
xiesi | 8dc08c3992 | |
何童崇 | 70ec86569f | |
何童崇 | 00b41844bb | |
何童崇 | 81c93d2580 | |
何童崇 | a87e55103c | |
何童崇 | 05101c5e32 | |
何童崇 | e72b3e687f | |
何童崇 | f25a52622d | |
何童崇 | f5fa216b23 | |
何童崇 | a57b96a1b8 | |
何童崇 | 8efbea44ab | |
何童崇 | fa80b5d1df | |
何童崇 | 6c95ff98f4 | |
何童崇 | cb7170a87c | |
何童崇 | 7757e4b6b7 | |
何童崇 | cad9a4fc3a | |
何童崇 | dc20d3e270 | |
何童崇 | 4503e1b176 | |
何童崇 | 91fe328eaf | |
何童崇 | 8d9d5c3ce3 | |
何童崇 | a2aa344e31 | |
何童崇 | 981e199273 | |
何童崇 | b6d6309c3c | |
何童崇 | 16aac3b835 | |
何童崇 | bdf3a8e72a | |
何童崇 | 507976bf10 | |
何童崇 | b6c2c66321 | |
何童崇 | 0b7fbe564c | |
何童崇 | ce958f3369 | |
何童崇 | 0e176d9334 | |
何童崇 | 3608b7b712 | |
何童崇 | b9888a81f6 | |
何童崇 | 0bb6ec51c2 | |
何童崇 | 7d2c90dfd1 | |
何童崇 | 66c5f09813 | |
何童崇 | a4d38f8c86 | |
何童崇 | 21a3c54754 | |
何童崇 | 4493711521 | |
何童崇 | 76b23f88db | |
何童崇 | bca9499844 | |
何童崇 | 3137048aed | |
何童崇 | 62b5d86082 | |
何童崇 | 7a472651f1 | |
何童崇 | 99c90295c0 | |
何童崇 | d7fd642f7f | |
何童崇 | 97bc41e771 | |
何童崇 | 6156d98af2 | |
caishi | 6facc3e65f | |
何童崇 | c8f6891239 | |
何童崇 | 11b5c87888 | |
caishi | 2f538ff394 | |
何童崇 | 48a153d434 | |
何童崇 | 9c3ecabf47 | |
何童崇 | f18070da47 | |
何童崇 | 1e87e0c8ec | |
何童崇 | bec68aa090 | |
何童崇 | aed83337fa | |
何童崇 | e5b7110090 | |
何童崇 | 716916b7b6 | |
何童崇 | b5ccdbfcd6 | |
何童崇 | 1e7df569e6 | |
何童崇 | 701d9dfc99 | |
何童崇 | e7b3a01c47 | |
何童崇 | b19c084ac8 | |
何童崇 | 1d4bb3f4fc | |
何童崇 | e0b267bd6c | |
何童崇 | 4bf4aa7c78 | |
何童崇 | e3643be01b | |
何童崇 | 9c8add0152 | |
何童崇 | edb7099131 | |
何童崇 | cce818d4e0 | |
caishi | 909663bc47 | |
caishi | 9ea9da9672 | |
何童崇 | 97bd7673e1 | |
何童崇 | 2aa89426ad | |
何童崇 | 5131dacf05 | |
何童崇 | 6b63cd25aa | |
caishi | 8162b8b908 | |
何童崇 | 7a59d43eec | |
caishi | 008ba8d1de | |
何童崇 | 98a9344b02 | |
何童崇 | b8342288dd | |
何童崇 | 09e81b9e78 | |
caishi | 7cf5e23cb9 | |
何童崇 | 8594168d33 | |
caishi | 2d7c6cb82d | |
何童崇 | c36925c136 | |
何童崇 | 6ec6ab2308 | |
何童崇 | 4109e4b07e | |
何童崇 | 216e984740 | |
何童崇 | 92f3934d5e | |
何童崇 | 2ed7e0d4c4 | |
caishi | 6cfe81aea3 | |
何童崇 | 4dcbd51482 | |
caishi | c32b333bc2 | |
caishi | c965da7dd5 | |
caishi | b44399968f | |
caishi | 2591f28ccc | |
caishi | 5530e8c723 | |
caishi | fa26dc9fa5 | |
caishi | 4cf40f9dfc | |
caishi | 2c034f5dff | |
caishi | d68d8318c1 | |
caishi | 41ae6b1f8d | |
caishi | a6e2171fca | |
caishi | 916cc293ac | |
caishi | 5565eac601 | |
caishi | 860b71c7c6 | |
caishi | f1c2841fe0 | |
caishi | c6d5078d42 | |
caishi | ebe2d625fa | |
caishi | b5e1a91af5 | |
caishi | 4b8d72a6eb | |
caishi | f0e1858cd4 | |
caishi | a92468953a | |
caishi | fdab967b6a | |
caishi | 7e8929f166 | |
caishi | 0a39ed80da | |
caishi | 5ed44f1d63 | |
caishi | 64e639ebea | |
caishi | 3fb9eb40f3 | |
caishi | efc2443bb8 | |
caishi | 2c3d917bd4 | |
caishi | 617f139f52 | |
caishi | de550d5f42 | |
caishi | f12230dc91 | |
caishi | 1df2639cd5 | |
caishi | c746e9e634 | |
caishi | d8d464a332 | |
caishi | 83e337b2e9 | |
caishi | 5a6b7bd717 | |
caishi | c68a3dbd6f | |
caishi | 350f9426ea | |
caishi | 5bda100e32 | |
caishi | dde7fa730a | |
caishi | 3f8f1b8083 | |
caishi | 6eef4bd09e | |
caishi | 0dcaea3db4 | |
caishi | 033134fa83 | |
caishi | 1bab0b01f7 | |
caishi | 7b2f233cae | |
caishi | 2ecdd73c7f | |
caishi | 4e7a2fa3d7 | |
caishi | 91662e2e3e | |
sylor_huang@126.com | c2129c994a | |
sylor_huang@126.com | e968ece34c | |
sylor_huang@126.com | 70d407963e | |
sylor_huang@126.com | 00ccba74a1 | |
sylor_huang@126.com | 0790abb6f9 | |
caishi | 6c4c161a1b | |
caishi | 65a2bd43cf | |
sylor_huang@126.com | 10f813a443 | |
sylor_huang@126.com | e79ec30c81 | |
sylor_huang@126.com | 2a7fea3612 | |
sylor_huang@126.com | cc46a3ac30 | |
sylor_huang@126.com | cca5f98c9b | |
sylor_huang@126.com | d4535005c8 | |
sylor_huang@126.com | 73d128e0c9 | |
sylor_huang@126.com | f09457a0ac | |
sylor_huang@126.com | 78c218b12b | |
sylor_huang@126.com | d9f87fdd18 | |
caishi | 33c3395221 | |
sylor_huang@126.com | 74d26a40d3 | |
sylor_huang@126.com | 3f78ed249c | |
caishi | 07e1525f09 | |
sylor_huang@126.com | a9161b86a2 | |
sylor_huang@126.com | e0e6cdcc79 | |
sylor_huang@126.com | 3b0c708d82 | |
sylor_huang@126.com | 0922df3875 | |
sylor_huang@126.com | ad3fe09cfb | |
sylor_huang@126.com | 91f4327eb4 | |
sylor_huang@126.com | f2f910b5e4 | |
sylor_huang@126.com | 85d924db70 | |
Jasder | f1614a4b62 | |
Jasder | 2fa71241db | |
Jasder | 13c6556574 | |
caishi | 5601b71937 | |
Jasder | 1a024f8011 |
|
@ -86,3 +86,6 @@ typings/
|
|||
|
||||
.DS_Store
|
||||
.idea/*
|
||||
|
||||
package.json
|
||||
package-lock.json
|
|
@ -101,9 +101,13 @@ module.exports = {
|
|||
extensions: [".web.js", ".mjs", ".js", ".json", ".web.jsx", ".jsx"],
|
||||
alias: {
|
||||
educoder: __dirname + "/../src/common/educoder.js",
|
||||
src: path.join(paths.appSrc), // 整个源代码目录
|
||||
forge: path.join(paths.appSrc, 'forge'),
|
||||
military: path.join(paths.appSrc, 'military'),
|
||||
// Support React Native Web
|
||||
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
|
||||
"react-native": "react-native-web",
|
||||
'react-dom': '@hot-loader/react-dom',
|
||||
},
|
||||
plugins: [
|
||||
// Prevents users from importing files from outside of src/ (or node_modules/).
|
||||
|
|
|
@ -87,6 +87,9 @@ module.exports = {
|
|||
extensions: [".web.js", ".mjs", ".js", ".json", ".web.jsx", ".jsx"],
|
||||
alias: {
|
||||
educoder: __dirname + "/../src/common/educoder.js",
|
||||
src: path.join(paths.appSrc),
|
||||
forge: path.join(paths.appSrc, 'forge'),
|
||||
military: path.join(paths.appSrc, 'military'),
|
||||
// Support React Native Web
|
||||
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
|
||||
"react-native": "react-native-web",
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"educoder": ["./src/common/educoder.js"],
|
||||
"forge":["./src/forge"],
|
||||
"military":["./src/military"],
|
||||
}
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"build"
|
||||
]
|
||||
}
|
|
@ -107,6 +107,7 @@
|
|||
"styled-components": "^4.4.1",
|
||||
"sw-precache-webpack-plugin": "0.11.4",
|
||||
"url-loader": "0.6.2",
|
||||
"wangeditor-for-react": "^1.4.0",
|
||||
"webpack-cli": "^3.3.11",
|
||||
"webpack-dev-server": "^3.10.3",
|
||||
"webpack-manifest-plugin": "^2.2.0",
|
||||
|
@ -182,6 +183,7 @@
|
|||
"port": "3007",
|
||||
"devDependencies": {
|
||||
"@babel/runtime": "7.0.0-beta.51",
|
||||
"@hot-loader/react-dom": "^16.14.0",
|
||||
"babel-cli": "^6.26.0",
|
||||
"babel-core": "^6.26.0",
|
||||
"babel-plugin-import": "^1.13.0",
|
||||
|
@ -191,6 +193,7 @@
|
|||
"babel-preset-stage-2": "^6.24.1",
|
||||
"compression-webpack-plugin": "^1.1.12",
|
||||
"concat": "^1.0.3",
|
||||
"cross-env": "^7.0.3",
|
||||
"happypack": "^5.0.1",
|
||||
"mockjs": "^1.1.0",
|
||||
"node-sass": "^4.12.0",
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/*头部导航条样式---2018-03-19--by-cs*/
|
||||
.newHeader {
|
||||
background: #24292D !important;
|
||||
width: 100%;
|
||||
height: 60px !important;
|
||||
min-width: 1200px;
|
||||
|
|
|
@ -3971,7 +3971,9 @@ html>body #ajax-indicator {
|
|||
cursor: pointer;
|
||||
position: relative;
|
||||
font-size: 16px;
|
||||
padding:0px 20px;
|
||||
margin-right: 40px;
|
||||
}.head-nav ul#header-nav li:first-child{
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.head-nav ul#header-nav li a {
|
||||
|
|
After Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 9.7 KiB |
|
@ -2,10 +2,11 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name=”Keywords” Content=”trustie,trustieforge,forge,确实让创建更美好,协同开发平台″>
|
||||
<meta name=”Keywords” Content=”TrustieOpenSourceProject″>
|
||||
<meta name=”Keywords” Content=”issue,bug,tracker,软件工程,课程实践″>
|
||||
<meta name=”Description” Content=”持续构建协同、共享、可信的软件创建生态开源创作与软件生产相结合,支持大规模群体开展软件协同创新活动”>
|
||||
<title>红山开源社区</title>
|
||||
<meta name="keywords" content="红山开源,创客空间,群智共享">
|
||||
<meta name="keywords" content="红山开源社区,开源开放,众创,论坛">
|
||||
<meta name="keywords" content="issue,bug,tracker">
|
||||
<meta name="description" content="红山开源是一个依托互联网群体智慧实现世界范围内资源深度融合、开放共享和协同创新的开源社区" />
|
||||
<meta name="theme-color" content="#000000">
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
|
||||
|
||||
|
|
30
src/App.js
|
@ -45,6 +45,21 @@ const OpsDetail = Loadable({
|
|||
loader: () => import('./forge/DevOps/opsDetail'),
|
||||
loading: Loading,
|
||||
})
|
||||
// Notice项目公告
|
||||
const Notice = Loadable({
|
||||
loader: () => import('./military/notice'),
|
||||
loading: Loading,
|
||||
})
|
||||
//任务/需求
|
||||
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'),
|
||||
|
@ -240,6 +255,21 @@ class App extends Component {
|
|||
}
|
||||
}
|
||||
/>
|
||||
{/*公告*/}
|
||||
<Route
|
||||
path={"/notice"}
|
||||
render={
|
||||
(props) => {
|
||||
return (<Notice {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
}>
|
||||
</Route>
|
||||
{/*任务*/}
|
||||
<Route path="/task" component={Task} />
|
||||
|
||||
{/*专家评审*/}
|
||||
<Route path="/expert" component={Expert} />
|
||||
|
||||
{/*403*/}
|
||||
<Route path="/403" component={Shixunauthority} />
|
||||
|
||||
|
|
|
@ -4,16 +4,14 @@ import { broadcastChannelOnmessage, isDev, queryString } from 'educoder';
|
|||
import { notification } from 'antd';
|
||||
import cookie from 'react-cookies';
|
||||
import './index.css';
|
||||
|
||||
let message501 = false;
|
||||
|
||||
broadcastChannelOnmessage('refreshPage', () => {
|
||||
window.location.reload();
|
||||
window.location.reload()
|
||||
})
|
||||
|
||||
function locationurl(list) {
|
||||
if (window.location.port === "3007") {
|
||||
|
||||
} else {
|
||||
if (window.location.port !== "3007") {
|
||||
window.location.href = list
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +32,7 @@ function clearAllCookie() {
|
|||
cookie.remove('autologin_trustie', { path: '/' });
|
||||
setpostcookie()
|
||||
}
|
||||
clearAllCookie();
|
||||
// clearAllCookie();
|
||||
function setpostcookie() {
|
||||
const str = window.location.pathname;
|
||||
if (str.indexOf("/wxcode") !== -1) {
|
||||
|
@ -54,9 +52,12 @@ setpostcookie();
|
|||
|
||||
window._debugType = debugType;
|
||||
export function initAxiosInterceptors(props) {
|
||||
initOnlineOfflineListener();
|
||||
var proxy = "http://localhost:3000";
|
||||
proxy = "https://testforgeplus.trustie.net";
|
||||
initOnlineOfflineListener()
|
||||
// TODO 避免重复的请求 https://github.com/axios/axios#cancellation
|
||||
var
|
||||
proxy = "http://localhost:3000";
|
||||
// proxy = "https://forge.osredm.com";
|
||||
proxy = "http://117.50.100.12:49999";
|
||||
|
||||
const requestMap = {};
|
||||
window.setfalseInRequestMap = function (keyName) {
|
||||
|
@ -90,7 +91,6 @@ export function initAxiosInterceptors(props) {
|
|||
}
|
||||
if (config.url.indexOf('update_file') === -1) {
|
||||
requestMap[config.url] = true;
|
||||
|
||||
window.setTimeout("setfalseInRequestMap('" + config.url + "')", 900)
|
||||
}
|
||||
return config;
|
||||
|
|
|
@ -38,62 +38,91 @@ export function getNextHalfHourOfMoment(moment) {
|
|||
return moment
|
||||
}
|
||||
|
||||
export function formatSeconds(value) {
|
||||
export function formatSeconds(value) {
|
||||
|
||||
var theTime = parseInt(value);// 秒
|
||||
var middle= 0;// 分
|
||||
var hour= 0;// 小时
|
||||
|
||||
if(theTime > 60) {
|
||||
middle= parseInt(theTime/60);
|
||||
theTime = parseInt(theTime%60);
|
||||
if(middle> 60) {
|
||||
hour= parseInt(middle/60);
|
||||
middle= parseInt(middle%60);
|
||||
}
|
||||
}
|
||||
var result = ""+parseInt(theTime)+"秒";
|
||||
if(middle > 0) {
|
||||
var theTime = parseInt(value);// 秒
|
||||
var middle = 0;// 分
|
||||
var hour = 0;// 小时
|
||||
|
||||
if (theTime > 60) {
|
||||
middle = parseInt(theTime / 60);
|
||||
theTime = parseInt(theTime % 60);
|
||||
if (middle > 60) {
|
||||
hour = parseInt(middle / 60);
|
||||
middle = parseInt(middle % 60);
|
||||
}
|
||||
}
|
||||
var result = "" + parseInt(theTime) + "秒";
|
||||
if (middle > 0) {
|
||||
if (hour > 0) {
|
||||
result = ""+parseInt(middle)+"分";
|
||||
result = "" + parseInt(middle) + "分";
|
||||
} else {
|
||||
result = ""+parseInt(middle)+"分"+result;
|
||||
result = "" + parseInt(middle) + "分" + result;
|
||||
}
|
||||
|
||||
}
|
||||
if (hour > 0) {
|
||||
result = "" + parseInt(hour) + "小时" + result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
if(hour> 0) {
|
||||
result = ""+parseInt(hour)+"小时"+result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
export function formatDuring(mss){
|
||||
var days = parseInt(mss / (1000 * 60 * 60 * 24));
|
||||
var hours = parseInt((mss % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
|
||||
var minutes = parseInt((mss % (1000 * 60 * 60)) / (1000 * 60));
|
||||
// console.log("formatDuringformatDuring");
|
||||
// console.log(days);
|
||||
// console.log(hours);
|
||||
// console.log(minutes);
|
||||
// console.log(Math.abs(days));
|
||||
// console.log(Math.abs(hours));
|
||||
// console.log(Math.abs(minutes));
|
||||
export function formatDuring(s) {
|
||||
s = Math.abs(s);
|
||||
let days = Math.floor(s / (60 * 60 * 24));
|
||||
let hours = Math.floor((s % (60 * 60 * 24)) / (60 * 60));
|
||||
let minutes = Math.floor((s % (60 * 60)) / (60));
|
||||
let second = Math.floor(s % 60);
|
||||
|
||||
if (days) {
|
||||
if(hours){
|
||||
return days + "天" + hours + "小时";
|
||||
}
|
||||
return days + "天";
|
||||
}
|
||||
if (hours) {
|
||||
if(minutes){
|
||||
return hours + "小时" + minutes + "分";
|
||||
}
|
||||
return hours + "小时" ;
|
||||
}
|
||||
if (minutes) {
|
||||
return minutes + "分";
|
||||
}
|
||||
return second + "秒";
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
返回:多久以前
|
||||
backDate:以前的某个日期
|
||||
*/
|
||||
export function timeAgo(backDate) {
|
||||
try {
|
||||
days = Math.abs(days);
|
||||
moment(backDate);
|
||||
} catch (e) {
|
||||
|
||||
return;
|
||||
}
|
||||
try {
|
||||
hours = Math.abs(hours);
|
||||
} catch (e) {
|
||||
|
||||
let time = new Date() - moment(backDate);
|
||||
var days = Math.floor(time / (1000 * 60 * 60 * 24));
|
||||
var hours = Math.floor((time % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
|
||||
var minutes = Math.floor((time % (1000 * 60 * 60)) / (1000 * 60));
|
||||
var seconds = Math.floor((time % (1000 * 60 * 60)) / 1000);
|
||||
if (time <= 0) {
|
||||
return "刚刚";
|
||||
}
|
||||
try {
|
||||
minutes = Math.abs(minutes);
|
||||
} catch (e) {
|
||||
|
||||
if (days) {
|
||||
return days + "天前";
|
||||
}
|
||||
if (hours) {
|
||||
return hours + "小时前";
|
||||
}
|
||||
if (minutes) {
|
||||
return minutes + "分前";
|
||||
}
|
||||
if (seconds) {
|
||||
return seconds + "秒前";
|
||||
}
|
||||
return days + "天" + hours + "小时" + minutes + "分";
|
||||
}
|
|
@ -68,7 +68,7 @@ export function appendFileSizeToUploadFile(item) {
|
|||
return `${item.title}${uploadNameSizeSeperator}${item.filesize}`
|
||||
}
|
||||
export function appendFileSizeToUploadFileAll(fileList) {
|
||||
return fileList.map(item => {
|
||||
return fileList && fileList.map(item => {
|
||||
if (item.name.indexOf(uploadNameSizeSeperator) == -1) {
|
||||
return Object.assign({}, item, { name: `${item.name}${uploadNameSizeSeperator}${bytesToSize(item.size)}` })
|
||||
}
|
||||
|
|
|
@ -6,12 +6,13 @@ const { Search } = Input;
|
|||
const $ = window.$;
|
||||
const isDev = window.location.port == 3007;
|
||||
const isdev2= window.location.hostname ==='www.educoder.net'
|
||||
export const TEST_HOST = "https://testforgeplus.trustie.net/"
|
||||
export const TEST_HOST = "http://39.105.176.215:49999"
|
||||
export function getImageUrl(path) {
|
||||
// https://www.educoder.net
|
||||
// https://testbdweb.trustie.net
|
||||
// const local = 'http://localhost:3000'
|
||||
const local = 'https://testforgeplus.trustie.net';
|
||||
const local = 'http://39.105.176.215:49999';
|
||||
|
||||
if (isDev) {
|
||||
return `${local}/${path}`
|
||||
}
|
||||
|
@ -22,7 +23,7 @@ export function getImage(path) {
|
|||
// https://www.educoder.net
|
||||
// https://testbdweb.trustie.net
|
||||
// const local = 'http://localhost:3000'
|
||||
const local = 'https://testforgeplus.trustie.net/';
|
||||
const local = 'http://39.105.176.215:49999';
|
||||
if(path.indexOf("http://")===-1){
|
||||
if (isDev) {
|
||||
return `${local}/images/${path}`
|
||||
|
@ -93,7 +94,7 @@ export function setImagesUrl(path){
|
|||
}
|
||||
|
||||
export function getUrl(path, goTest) {
|
||||
const local = 'https://testforgeplus.trustie.net'
|
||||
const local = 'http://39.105.176.215:49999'
|
||||
if (isDev) {
|
||||
return `${local}${path?path:''}`
|
||||
}
|
||||
|
@ -162,7 +163,7 @@ export function getmyUrl(geturl) {
|
|||
}
|
||||
|
||||
export function getUploadActionUrl(path, goTest) {
|
||||
return `${getUrl()}/api/attachments.json?debug=${window._debugType || 'admin'}`;
|
||||
return `${getUrl()}/api/attachments.json`;
|
||||
}
|
||||
|
||||
export function getUploadLogoActionUrl() {
|
||||
|
|
|
@ -27,7 +27,7 @@ export {
|
|||
markdownToHTML, uploadNameSizeSeperator, appendFileSizeToUploadFile, appendFileSizeToUploadFileAll, isImageExtension,
|
||||
downloadFile, sortDirections, validateLength, mdJSONParse, exportMdtoHtml
|
||||
} from './TextUtil'
|
||||
export { handleDateString, getNextHalfHourOfMoment, formatDuring, formatSeconds } from './DateUtil'
|
||||
export { handleDateString, getNextHalfHourOfMoment, formatDuring, formatSeconds ,timeAgo} from './DateUtil'
|
||||
|
||||
export { configShareForIndex, configShareForPaths, configShareForShixuns, configShareForCourses, configShareForCustom } from './util/ShareUtil'
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ class CloneAddress extends Component {
|
|||
const { http_url, downloadUrl } = this.props;
|
||||
return (
|
||||
<div className="gitAddressClone">
|
||||
{/* <p className="addressTips"><span>版本库地址已变更,请基于新地址提交代码</span></p> */}
|
||||
<p className="addressTips"><span>版本库地址已变更,请基于新地址提交代码</span></p>
|
||||
{
|
||||
http_url && <span>HTTP</span>
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
|
||||
|
||||
import React , { useState , useEffect } from 'react';
|
||||
import { Select } from 'antd';
|
||||
import axios from 'axios';
|
||||
|
@ -57,7 +59,6 @@ const LANGUAGE = [
|
|||
|
||||
export default (({ language , select_language })=>{
|
||||
const [ languages , setLanguage ] = useState(undefined);
|
||||
|
||||
// useEffect(()=>{
|
||||
// const url = '/dev_ops/languages.json';
|
||||
// axios.get(url).then(result=>{
|
||||
|
|
Before Width: | Height: | Size: 64 KiB |
After Width: | Height: | Size: 90 KiB |
After Width: | Height: | Size: 222 KiB |
|
@ -145,7 +145,7 @@ class CoderRootCommit extends Component{
|
|||
)
|
||||
})
|
||||
}
|
||||
{commitDatas && commitDatas.length > 0 && <Nodata _html="暂无数据"/>}
|
||||
{commitDatas && commitDatas.length === 0 && <Nodata _html="暂无数据"/>}
|
||||
</div>
|
||||
</div>
|
||||
{
|
||||
|
|
|
@ -251,7 +251,7 @@ class CoderRootDirectory extends Component {
|
|||
// readme文件内容
|
||||
renderReadMeContent = (readMeContent, permission) => {
|
||||
const { fileDetail, readMeFile } = this.state;
|
||||
if (fileDetail) {
|
||||
if (fileDetail && fileDetail.length !== 0) {
|
||||
return;
|
||||
}
|
||||
if (readMeContent && readMeContent.length > 0) {
|
||||
|
|
|
@ -4,6 +4,7 @@ import { Link, Route, Switch } from 'react-router-dom';
|
|||
import { Content } from '../Component/layout';
|
||||
import '../css/index.scss'
|
||||
import './list.css';
|
||||
import SpecialModal from './SpecialModal';
|
||||
|
||||
import Loadable from 'react-loadable';
|
||||
import Loading from '../../Loading';
|
||||
|
@ -117,19 +118,20 @@ const DevIndex = Loadable({
|
|||
function checkPathname(projectsId,owner,pathname){
|
||||
let name = "";
|
||||
if(pathname && pathname !== `/projects/${owner}/${projectsId}`){
|
||||
if(pathname.indexOf("/about")>-1){
|
||||
let url = pathname.split(`/projects/${owner}/${projectsId}`)[1];
|
||||
if(url.indexOf("/about")>-1){
|
||||
name="about"
|
||||
}else if(pathname.indexOf("/issues")>-1 ||pathname.indexOf("Milepost") > 0){
|
||||
}else if(url.indexOf("/issues")>-1 ||url.indexOf("Milepost") > 0){
|
||||
name = "issues";
|
||||
}else if(pathname.indexOf("/pulls")>-1){
|
||||
}else if(url.indexOf("/pulls")>-1){
|
||||
name="pulls"
|
||||
}else if(pathname.indexOf("/milestones")>-1){
|
||||
}else if(url.indexOf("/milestones")>-1){
|
||||
name="milestones"
|
||||
}else if(pathname.indexOf("/activity")>-1){
|
||||
}else if(url.indexOf("/activity")>-1){
|
||||
name="activity"
|
||||
}else if(pathname.indexOf("/setting")>-1){
|
||||
}else if(url.indexOf("/setting")>-1){
|
||||
name="setting"
|
||||
}else if(pathname.indexOf(`/devops`)>-1){
|
||||
}else if(url.indexOf(`/devops`)>-1){
|
||||
name="devops"
|
||||
}
|
||||
}
|
||||
|
@ -161,7 +163,9 @@ class Detail extends Component {
|
|||
defaultBranch:undefined,
|
||||
|
||||
// 非本平台项目
|
||||
platform:false
|
||||
platform:false,
|
||||
visible:false,
|
||||
user_apply_signatures:[]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -178,6 +182,7 @@ class Detail extends Component {
|
|||
}
|
||||
|
||||
getProject = (num) => {
|
||||
const {user} = this.props;
|
||||
const { projectsId , owner } = this.props.match.params;
|
||||
const url = `/${owner}/${projectsId}/simple.json`;
|
||||
axios.get(url).then((result) => {
|
||||
|
@ -187,6 +192,24 @@ class Detail extends Component {
|
|||
open_devops:result.data.open_devops,
|
||||
platform:result.data.platform && result.data.platform !== 'educoder'
|
||||
})
|
||||
let signa = result.data.user_apply_signatures && result.data.user_apply_signatures[0];
|
||||
if(result.data.is_secret && !result.data.is_member && (!signa || (signa && signa.status !== "passed")) && user.login !== owner){
|
||||
this.setState({
|
||||
visible:true,
|
||||
is_secret:result.data.is_secret,
|
||||
user_apply_signatures:signa
|
||||
})
|
||||
}
|
||||
|
||||
// 工作流:两种状态进入的链接不同
|
||||
const pathname = this.props.history.location.pathname;
|
||||
if(pathname===`/projects/${owner}/${projectsId}/devops`){
|
||||
if(result.data.open_devops && pathname === `/projects/${owner}/${projectsId}/devops`){
|
||||
this.props.history.push(`/projects/${owner}/${projectsId}/devops/list`);
|
||||
}else if(result.data.open_devops===false && pathname !== `/projects/${owner}/${projectsId}/devops`){
|
||||
this.props.history.push(`/projects/${owner}/${projectsId}/devops`);
|
||||
}
|
||||
}
|
||||
|
||||
if (result.data.type !== 0 && result.data.mirror_status === 1) {
|
||||
console.log("--------start channel --------");
|
||||
|
@ -357,13 +380,24 @@ class Detail extends Component {
|
|||
})
|
||||
}
|
||||
|
||||
hideModal=()=>{
|
||||
this.setState({
|
||||
visible:false
|
||||
})
|
||||
}
|
||||
|
||||
sureModal=()=>{
|
||||
this.hideModal();
|
||||
this.props.history.push('/projects');
|
||||
}
|
||||
|
||||
|
||||
|
||||
render() {
|
||||
const { projectDetail, watchers_count, praises_count,
|
||||
forked_count, firstSync , secondSync ,
|
||||
isManager, watched, praised,
|
||||
project , open_devops , platform , defaultBranch } = this.state;
|
||||
project , open_devops , platform , defaultBranch , project_id , user_apply_signatures , visible } = this.state;
|
||||
const url = this.props.history.location.pathname;
|
||||
const urlArr = url.split("/");
|
||||
const urlFlag = (urlArr.length === 3);
|
||||
|
@ -390,18 +424,19 @@ class Detail extends Component {
|
|||
}
|
||||
return (
|
||||
<div>
|
||||
<SpecialModal {...this.props} visible={visible} hideModal={this.sureModal} user_apply_signatures={user_apply_signatures} project_id={project_id} sureModal={this.sureModal}></SpecialModal>
|
||||
<div className="detailHeader-wrapper">
|
||||
<div className="normal">
|
||||
<div className="f-wrap-between pb15" style={{ position: "relative" }}>
|
||||
<p className="font-22 df flex-1 lineH2 mt15" style={{ alignItems: "center" }}>
|
||||
<p className="color-white font-22 df flex-1 lineH2 mt15" style={{ alignItems: "center" }}>
|
||||
{project && project.author &&
|
||||
<Link to={`${project.author.type ==="Organization" ? "/organize":'/users'}/${project.author.login}`} className="show-user-link">
|
||||
<Link to={`/users/${project.author.login}`} className="show-user-link color-white">
|
||||
{project.author.name}
|
||||
</Link>
|
||||
}
|
||||
<span className="ml5 mr5">/</span>
|
||||
<span className="hide-1 flex-1 df">
|
||||
<Link to={`/projects/${owner}/${projectsId}`} className="font-22">{project && project.name}</Link>
|
||||
<Link to={`/projects/${owner}/${projectsId}`} className="color-white font-22">{project && project.name}</Link>
|
||||
{
|
||||
projectDetail && projectDetail.forked_from_project_id && projectDetail.fork_info ?
|
||||
<Tooltip placement={'right'} title={text}>
|
||||
|
@ -438,15 +473,14 @@ class Detail extends Component {
|
|||
<span>{watched ? '取消关注' : '关注'}</span>
|
||||
</a>
|
||||
{
|
||||
watchers_count > 0 ?
|
||||
platform ?
|
||||
<Link className="detail_tag_btn_count" style={{color:`${watched?"#2878FF":"#666"}`}} to={platform?{ pathname: `/projects/${owner}/${projectsId}/watchers`, state }:""}>
|
||||
{watchers_count}
|
||||
</Link>
|
||||
:
|
||||
<span className="detail_tag_btn_count">{watchers_count}</span>
|
||||
:""
|
||||
}
|
||||
|
||||
</span>
|
||||
<span className="detail_tag_btn">
|
||||
<a className="detail_tag_btn_name" style={{cursor:platform?"pointer":"default"}} onClick={() => this.pariseFunc(praised)}>
|
||||
|
@ -454,13 +488,11 @@ class Detail extends Component {
|
|||
<span>{praised ? '取消点赞' : '点赞'}</span>
|
||||
</a>
|
||||
{
|
||||
praises_count > 0 ?
|
||||
platform ?
|
||||
<Link className="detail_tag_btn_count" style={{color:`${praised?"#2878FF":"#666"}`}} to={{ pathname: `/projects/${owner}/${projectsId}/stargazers`, state }}>
|
||||
{praises_count}
|
||||
</Link>:
|
||||
<span className="detail_tag_btn_count">{praises_count}</span>
|
||||
:""
|
||||
}
|
||||
</span>
|
||||
<span className="detail_tag_btn">
|
||||
|
@ -468,14 +500,12 @@ class Detail extends Component {
|
|||
<i className="iconfont icon-fork color-grey-9 mr3"></i>复刻 (Fork)
|
||||
</a>
|
||||
{
|
||||
forked_count > 0 ?
|
||||
platform ?
|
||||
<Link className="detail_tag_btn_count" to={{ pathname: `/projects/${owner}/${projectsId}/fork_users`, state }}>
|
||||
{forked_count}
|
||||
</Link>
|
||||
:
|
||||
<span className="detail_tag_btn_count">{forked_count}</span>
|
||||
:""
|
||||
<span className="detail_tag_btn_count">{praises_count}</span>
|
||||
}
|
||||
</span>
|
||||
</span>
|
||||
|
@ -483,23 +513,23 @@ class Detail extends Component {
|
|||
</div>
|
||||
{
|
||||
firstSync ? "" :
|
||||
<div className="f-wrap-between mt15">
|
||||
<div className="f-wrap-between pb20">
|
||||
<ul className="headerMenu-wrapper">
|
||||
<li className={pathname==="about" ? "active" : ""}>
|
||||
<Link to={{ pathname: `/projects/${owner}/${projectsId}/about`, state }}>
|
||||
<i className={(pathname==="" || urlFlag) ? "iconfont icon-zhuye1 color-grey-3 mr5 font-14":"iconfont icon-zhuye1 color-grey-6 font-14 mr5"}></i>
|
||||
<i className={ pathname === "about" ? "iconfont icon-zhuye1 color-blue mr5 font-14":"iconfont icon-zhuye1 color-white font-14 mr5"}></i>
|
||||
<span>主页</span>
|
||||
</Link>
|
||||
</li>
|
||||
<li className={(pathname==="" || urlFlag) ? "active" : ""}>
|
||||
<Link to={{ pathname: `/projects/${owner}/${projectsId}`, state }}>
|
||||
<i className={(pathname==="" || urlFlag) ? "iconfont icon-daimaku color-grey-3 mr5 font-14":"iconfont icon-daimaku color-grey-6 font-14 mr5"}></i>
|
||||
<i className={(pathname==="" || urlFlag) ? "iconfont icon-daimaku color-blue mr5 font-14":"iconfont icon-daimaku color-white font-14 mr5"}></i>
|
||||
<span>代码库</span>
|
||||
</Link>
|
||||
</li>
|
||||
<li className={pathname==="issues" ? "active" : ""}>
|
||||
<Link to={{ pathname: `/projects/${owner}/${projectsId}/issues`, state }}>
|
||||
<i className={pathname==="issues" ? "iconfont icon-renwu color-grey-3 mr5 font-14":"iconfont icon-renwu color-grey-6 font-14 mr5"}></i>
|
||||
<i className={pathname==="issues" ? "iconfont icon-renwu color-blue mr5 font-14":"iconfont icon-renwu color-white font-14 mr5"}></i>
|
||||
<span>易修 (Issue)</span>
|
||||
{projectDetail && projectDetail.issues_count ? <span className="num">{projectDetail.issues_count}</span> : ""}
|
||||
</Link>
|
||||
|
@ -508,32 +538,32 @@ class Detail extends Component {
|
|||
projectDetail && parseInt(projectDetail.type) !== 2 && platform &&
|
||||
<li className={pathname==="pulls" ? "active" : ""}>
|
||||
<Link to={{ pathname: `/projects/${owner}/${projectsId}/pulls`, state }}>
|
||||
<i className={pathname==="pulls" ? "iconfont icon-hebingqingqiu1 color-grey-3 mr5 font-14":"iconfont icon-hebingqingqiu1 color-grey-6 font-14 mr5"}></i>
|
||||
<i className={pathname==="pulls" ? "iconfont icon-hebingqingqiu1 color-blue mr5 font-14":"iconfont icon-hebingqingqiu1 color-white font-14 mr5"}></i>
|
||||
<span>合并请求</span>
|
||||
{projectDetail && projectDetail.pull_requests_count ? <span className="num">{projectDetail.pull_requests_count}</span> : ""}
|
||||
</Link>
|
||||
</li>
|
||||
}
|
||||
{
|
||||
{/* {
|
||||
platform &&
|
||||
<li className={pathname==="devops" ? "active" : ""}>
|
||||
<Link to={{ pathname: `/projects/${owner}/${projectsId}/devops${open_devops ? `/dispose`:""}`, state }}>
|
||||
<Link to={{ pathname: `/projects/${owner}/${projectsId}/devops${open_devops ? `/list`:""}`, state }}>
|
||||
<i className="iconfont icon-gongzuoliu font-13 mr8"></i>工作流(beta版)
|
||||
{projectDetail && projectDetail.ops_count ? <span>{projectDetail.ops_count}</span> : ""}
|
||||
</Link>
|
||||
</li>
|
||||
}
|
||||
} */}
|
||||
|
||||
<li className={pathname==="milestones" ? "active" : ""}>
|
||||
<Link to={{ pathname: `/projects/${owner}/${projectsId}/milestones`, state }}>
|
||||
<i className={pathname==="milestones" ? "iconfont icon-lichengbei color-grey-3 mr5 font-14":"iconfont icon-lichengbei color-grey-6 font-14 mr5"}></i>
|
||||
<i className={pathname==="milestones" ? "iconfont icon-lichengbei color-blue mr5 font-14":"iconfont icon-lichengbei color-white font-14 mr5"}></i>
|
||||
<span>里程碑</span>
|
||||
{projectDetail && projectDetail.versions_count ? <span className="num">{projectDetail.versions_count}</span> :""}
|
||||
</Link>
|
||||
</li>
|
||||
<li className={pathname==="activity" ? "active" : ""}>
|
||||
<Link to={{ pathname: `/projects/${owner}/${projectsId}/activity`, state }}>
|
||||
<i className={pathname==="activity" ? "iconfont icon-tongzhi color-grey-3 mr5 font-14":"iconfont icon-tongzhi color-grey-6 font-14 mr5"}></i>
|
||||
<i className={pathname==="activity" ? "iconfont icon-tongzhi color-blue mr5 font-14":"iconfont icon-tongzhi color-white font-14 mr5"}></i>
|
||||
<span>动态</span>
|
||||
</Link>
|
||||
</li>
|
||||
|
@ -541,7 +571,7 @@ class Detail extends Component {
|
|||
isManager && platform &&
|
||||
<li className={url.indexOf("/setting") > 0 ? "active" : ""}>
|
||||
<Link to={`/projects/${owner}/${projectsId}/setting`}>
|
||||
<i className={url.indexOf("/setting") > 0 ? "iconfont icon-cangku color-grey-3 mr5 font-14":"iconfont icon-cangku color-grey-6 font-14 mr5"}></i>
|
||||
<i className={url.indexOf("/setting") > 0 ? "iconfont icon-cangku color-blue mr5 font-14":"iconfont icon-cangku color-white font-14 mr5"}></i>
|
||||
<span>仓库设置</span>
|
||||
</Link>
|
||||
</li>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import React, { Component } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Menu, Input , Spin, Pagination , Popover , Select } from 'antd';
|
||||
import { getUrl } from 'educoder';
|
||||
import { Menu, Input , Spin, Pagination , Popover, Affix, } from 'antd';
|
||||
import '../css/index.scss'
|
||||
import './list.css';
|
||||
import './Index.scss';
|
||||
|
@ -9,7 +8,7 @@ import ListItem from './IndexItem'
|
|||
import axios from 'axios';
|
||||
import img_new from '../Images/new.png';
|
||||
import img_array from '../Images/array.png';
|
||||
import banner from '../Images/banner_list.jpg';
|
||||
import banner from '../Images/banner_list.png';
|
||||
const Search = Input.Search;
|
||||
|
||||
class Index extends Component {
|
||||
|
@ -23,7 +22,6 @@ class Index extends Component {
|
|||
sort: undefined,
|
||||
total: 0,
|
||||
isSpin: true,
|
||||
project_type: undefined,
|
||||
category_id: undefined,
|
||||
|
||||
typeList: undefined,
|
||||
|
@ -37,8 +35,8 @@ class Index extends Component {
|
|||
}
|
||||
|
||||
componentDidMount = () => {
|
||||
const { page, limit, search, sort, project_type, category_id , languageId } = this.state;
|
||||
this.getListData(page, limit, search, sort, project_type, category_id , languageId);
|
||||
const { page,search, sort,category_id , languageId } = this.state;
|
||||
this.getListData(page,search, sort,category_id , languageId);
|
||||
|
||||
this.getType();
|
||||
|
||||
|
@ -73,19 +71,24 @@ class Index extends Component {
|
|||
}
|
||||
|
||||
// 获取列表
|
||||
getListData = (page, limit, search, sort, project_type, category_id,languageId) => {
|
||||
getListData = (page,search, sort,category_id,language_id) => {
|
||||
const { current_user } = this.props;
|
||||
const url = `/projects.json`;
|
||||
if(category_id==0){
|
||||
category_id=undefined;
|
||||
}
|
||||
if(language_id==0){
|
||||
language_id=undefined;
|
||||
}
|
||||
axios.get(url, {
|
||||
params: {
|
||||
user_id: current_user && current_user.user_id,
|
||||
page,
|
||||
limit,
|
||||
limit:15,
|
||||
search,
|
||||
sort_by: sort,
|
||||
project_type,
|
||||
category_id,
|
||||
language_id:languageId
|
||||
language_id
|
||||
}
|
||||
}).then((result) => {
|
||||
if (result) {
|
||||
|
@ -103,7 +106,11 @@ class Index extends Component {
|
|||
const url = `/projects/group_type_list.json`;
|
||||
axios.get(url).then((result) => {
|
||||
if (result && result.data) {
|
||||
this.setTypeList(result.data, undefined)
|
||||
result.data.unshift({
|
||||
name:'全部语言',
|
||||
id:0,
|
||||
});
|
||||
this.setTypeList(result.data, 0)
|
||||
}
|
||||
}).catch((error) => { })
|
||||
}
|
||||
|
@ -112,7 +119,7 @@ class Index extends Component {
|
|||
this.setState({
|
||||
typeList: list.map((item, key) => {
|
||||
return (
|
||||
<li key={key} className={active_type && active_type === item.project_type ? 'active' : ''} onClick={() => this.changeType(`${item.project_type}`, list)}>
|
||||
<li key={key} className={ parseInt(active_type) === item.id ? 'active' : ''} onClick={() => this.changeType(`${item.id}`, list)}>
|
||||
<p>
|
||||
<span className="font-16">{item.name}</span>
|
||||
<span className="color-blue">{item.projects_count}</span>
|
||||
|
@ -123,16 +130,16 @@ class Index extends Component {
|
|||
})
|
||||
}
|
||||
|
||||
// 切换类型
|
||||
changeType = (type, list) => {
|
||||
// 切换语言类型
|
||||
changeType = (id, list) => {
|
||||
this.setState({
|
||||
isSpin: true,
|
||||
project_type: type,
|
||||
languageId: id,
|
||||
search: undefined
|
||||
})
|
||||
this.setTypeList(list, type)
|
||||
const { page, limit, sort, category_id , languageId } = this.state;
|
||||
this.getListData(page, limit, undefined, sort, type, category_id , languageId);
|
||||
this.setTypeList(list, id);
|
||||
const { page,sort, category_id} = this.state;
|
||||
this.getListData(page,undefined, sort,category_id , id);
|
||||
}
|
||||
|
||||
// 获取类型
|
||||
|
@ -141,7 +148,11 @@ class Index extends Component {
|
|||
|
||||
axios.get(url).then((result) => {
|
||||
if (result && result.data) {
|
||||
this.setCategoryList(result.data, undefined);
|
||||
result.data.unshift({
|
||||
name:'全部类别',
|
||||
id:0,
|
||||
});
|
||||
this.setCategoryList(result.data, 0);
|
||||
}
|
||||
}).catch((error) => { })
|
||||
}
|
||||
|
@ -150,7 +161,7 @@ class Index extends Component {
|
|||
this.setState({
|
||||
categoryList: list.map((item, key) => {
|
||||
return (
|
||||
<li key={key} className={active_id && parseInt(active_id) === item.id ? 'active' : ''} onClick={() => this.changeCategory(`${item.id}`, list)}>
|
||||
<li key={key} className={ parseInt(active_id) === item.id ? 'active' : ''} onClick={() => this.changeCategory(`${item.id}`, list)}>
|
||||
<p>
|
||||
<span className="font-16">{item.name}</span>
|
||||
<span className="color-blue">{item.projects_count}</span>
|
||||
|
@ -167,8 +178,8 @@ class Index extends Component {
|
|||
page: 1
|
||||
});
|
||||
this.setCategoryList(list, id)
|
||||
const { limit, sort, project_type , languageId } = this.state;
|
||||
this.getListData(1, limit, undefined, sort, project_type, id , languageId);
|
||||
const { sort,languageId } = this.state;
|
||||
this.getListData(1,undefined, sort,id , languageId);
|
||||
}
|
||||
|
||||
// 排序
|
||||
|
@ -179,8 +190,8 @@ class Index extends Component {
|
|||
search: undefined,
|
||||
isSpin: true
|
||||
})
|
||||
const { limit, project_type, category_id , languageId } = this.state;
|
||||
this.getListData(1, limit, undefined, e.key, project_type, category_id , languageId);
|
||||
const {category_id , languageId } = this.state;
|
||||
this.getListData(1,undefined, e.key,category_id , languageId);
|
||||
}
|
||||
|
||||
// 搜索
|
||||
|
@ -192,8 +203,8 @@ class Index extends Component {
|
|||
project_type: undefined,
|
||||
sort: "updated_on"
|
||||
})
|
||||
const { limit, sort, category_id , languageId } = this.state;
|
||||
this.getListData(1, limit, value, sort, undefined, category_id , languageId);
|
||||
const {sort, category_id , languageId } = this.state;
|
||||
this.getListData(1,value, sort,category_id , languageId);
|
||||
}
|
||||
changeSearchValue = (e) => {
|
||||
this.setState({
|
||||
|
@ -205,23 +216,14 @@ class Index extends Component {
|
|||
this.setState({
|
||||
page
|
||||
})
|
||||
const { limit, search, sort, project_type, category_id , languageId } = this.state;
|
||||
this.getListData(page, limit, search, sort, project_type, category_id , languageId);
|
||||
const {search, sort,category_id , languageId } = this.state;
|
||||
this.getListData(page,search, sort, category_id , languageId);
|
||||
}
|
||||
|
||||
getoDetail=(login,identifier)=>{
|
||||
this.props.history.push(`/projects/${login}/${identifier}`);
|
||||
}
|
||||
|
||||
// 选择语言类别
|
||||
changeLanguage=(e)=>{
|
||||
this.setState({
|
||||
isSpin:true,
|
||||
languageId:e === 0 ?undefined:e
|
||||
})
|
||||
const { page, limit, sort , project_type , category_id } = this.state;
|
||||
this.getListData(page, limit, undefined, sort, project_type, category_id ,e === 0 ?undefined:e);
|
||||
}
|
||||
|
||||
menu =()=> {
|
||||
return(
|
||||
|
@ -255,15 +257,14 @@ class Index extends Component {
|
|||
render() {
|
||||
const { current_user } = this.props;
|
||||
|
||||
const { projectsList , recommendList , languageList , languageId ,
|
||||
isSpin, total, search, limit, page, typeList, categoryList } = this.state;
|
||||
const { projectsList , isSpin , total , search , limit , page , typeList , categoryList } = this.state;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<p className="t_project_banner">
|
||||
<img src={banner} width="100%" alt=""/>
|
||||
</p>
|
||||
{
|
||||
{/* {
|
||||
recommendList && recommendList.length>0 &&
|
||||
<div className="recommandProjects">
|
||||
{
|
||||
|
@ -285,44 +286,29 @@ class Index extends Component {
|
|||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
*/}
|
||||
<div className="ProjectListIndex">
|
||||
<div className="list-left">
|
||||
|
||||
<Affix className="affix-list-left" offsetTop={90}>
|
||||
<div className="affix-list-content">
|
||||
<ul className="list-l-Menu">
|
||||
<li className="MenuTitle"><i className="iconfont icon-xiangmuleixing color-grey-9 font-15 mr5"></i>项目类型</li>
|
||||
{typeList}
|
||||
<li className="MenuTitle" onClick={() => {this.getType();this.changeType(undefined, this.state.typeList);}}>
|
||||
<span><i className="iconfont icon-bianchengyuyan color-grey-9 font-15 mr5"></i>
|
||||
语言</span></li>
|
||||
<div className="list-affix">{typeList}</div>
|
||||
</ul>
|
||||
<ul className="list-l-Menu">
|
||||
<li className="MenuTitle"><i className="iconfont icon-xiangmuleibie color-grey-9 font-15 mr5"></i>项目类别</li>
|
||||
{categoryList}
|
||||
<li className="MenuTitle" onClick={() => {this.getCategory();this.changeCategory(undefined, this.state.categoryList);}}>
|
||||
<span><i className="iconfont icon-xiangmuleibie color-grey-9 font-15 mr5"></i>项目类别</span></li>
|
||||
<div className="list-affix">{categoryList}</div>
|
||||
</ul>
|
||||
</div>
|
||||
</Affix>
|
||||
|
||||
<div className="list-right boxShandow radius-2" style={{padding:0}}>
|
||||
<Spin spinning={isSpin}>
|
||||
<div className="list-r-operation">
|
||||
<div>
|
||||
<Select
|
||||
showSearch
|
||||
placeholder="请选择语言"
|
||||
style={{width:"150px",marginRight:"20px"}}
|
||||
size={"large"}
|
||||
onChange={this.changeLanguage}
|
||||
value={languageId}
|
||||
allowClear={true}
|
||||
optionFilterProp="children"
|
||||
filterOption={(input,option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
|
||||
>
|
||||
<Select.Option key={0} value={0}>请选择语言</Select.Option>
|
||||
{
|
||||
languageList && languageList.length>0 && languageList.map((item,key)=>{
|
||||
return(
|
||||
<Select.Option key={item.id} value={item.id}>
|
||||
{item.name}
|
||||
</Select.Option>
|
||||
)
|
||||
})
|
||||
}
|
||||
</Select>
|
||||
<Search
|
||||
placeholder="输入项目名称关键字进行搜索"
|
||||
enterButton="搜索"
|
||||
|
@ -350,7 +336,7 @@ class Index extends Component {
|
|||
</Popover>
|
||||
</div>
|
||||
</div>
|
||||
<ListItem {...this.props} {...this.state} projects={projectsList}></ListItem>
|
||||
<ListItem {...this.props} {...this.state} projects={projectsList} getListData={this.getListData}></ListItem>
|
||||
{this.pagination(total,limit,page)}
|
||||
</Spin>
|
||||
</div>
|
||||
|
|
|
@ -72,3 +72,15 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
.singleBtn{
|
||||
display: inline-block;
|
||||
.ant-upload-list-item{
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
width: 100%;
|
||||
left: 0px;
|
||||
.ant-upload-list-item-name{
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,24 +6,70 @@ import '../css/index.scss';
|
|||
import Nodata from '../Nodata';
|
||||
import './list.css';
|
||||
import img_parise from '../Images/parise.png';
|
||||
import SpecialModal from './SpecialModal';
|
||||
|
||||
class IndexItem extends Component {
|
||||
constructor(props){
|
||||
super(props);
|
||||
this.state={
|
||||
visible:false,
|
||||
user_apply_signatures:[],
|
||||
project_id:undefined
|
||||
}
|
||||
}
|
||||
TurnToDetail = (login, url) => {
|
||||
this.props.history.push({
|
||||
pathname: url,
|
||||
state: login
|
||||
})
|
||||
}
|
||||
/**
|
||||
* link:跳转到详情的地址
|
||||
* user_apply_signatures:是否已经发送访问特殊开源项目的文件
|
||||
* project_id:项目id
|
||||
* is_secret:是否是特殊开源许可证项目
|
||||
* id:创建者login
|
||||
* is_member:是否是项目成员(如果是项目成员可以直接进入项目)
|
||||
* */
|
||||
projectHref=(link , user_apply_signatures,project_id,is_secret , id,is_member)=>{
|
||||
const { user , showLoginDialog } = this.props;
|
||||
if(is_secret && (!user || (user && !user.login))){
|
||||
showLoginDialog();
|
||||
return;
|
||||
}
|
||||
let signa = user_apply_signatures && user_apply_signatures[0];
|
||||
if((is_secret && !is_member && (!signa || (signa && signa.status !== "passed"))) && user.login !== id ){
|
||||
this.setState({
|
||||
visible:true,
|
||||
user_apply_signatures:user_apply_signatures.length>0 ? user_apply_signatures[0] : undefined,
|
||||
project_id
|
||||
})
|
||||
}else{
|
||||
this.props.history.push(link);
|
||||
}
|
||||
}
|
||||
hideModal=()=>{
|
||||
this.setState({
|
||||
visible:false
|
||||
})
|
||||
}
|
||||
|
||||
sureModal=()=>{
|
||||
this.hideModal();
|
||||
const { getListData } = this.props;
|
||||
getListData && getListData(1);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { projects } = this.props;
|
||||
return (
|
||||
<div className="project-list minH-670">
|
||||
{ projects && projects.length > 0 ? projects.map((item, key) => {
|
||||
const { visible , user_apply_signatures , project_id } = this.state;
|
||||
const renderList = (
|
||||
projects && projects.length > 0 ? projects.map((item, key) => {
|
||||
return (
|
||||
<div className="p-r-Item" key={key}>
|
||||
{
|
||||
item.platform === "educoder" ?
|
||||
<a href="javascript:void(0)" style={{cursor:"default"}} className="show-user-link">
|
||||
<a style={{cursor:"default"}} className="show-user-link">
|
||||
<img className="p-r-photo" alt="" src={item.author && item.author.image_url} ></img>
|
||||
</a>
|
||||
:
|
||||
|
@ -33,7 +79,7 @@ class IndexItem extends Component {
|
|||
}
|
||||
<div className="p-r-Infos">
|
||||
<div className="p-r-name">
|
||||
<Link to={`/projects/${item.author.login}/${item.identifier}`} className="hide-1 color-grey-3 font-18 task-hide " style={{ whiteSpace: "wrap", display: 'flex', width: 400 }}>
|
||||
<a onClick={()=>this.projectHref(`/projects/${item.author.login}/${item.identifier}`,item.user_apply_signatures, item.id,item.is_secret,item.author.login,item.is_member)} className="hide-1 color-grey-3 font-18 task-hide fwt-500 " style={{ whiteSpace: "wrap", display: 'flex', width: 400 }}>
|
||||
{item.author.name}/{item.name}
|
||||
{
|
||||
item.forked_from_project_id ?
|
||||
|
@ -52,13 +98,13 @@ class IndexItem extends Component {
|
|||
<i className="iconfont icon-jingxiang font-18 color-green" />
|
||||
</span>:""
|
||||
}
|
||||
</Link>
|
||||
</a>
|
||||
<span className="p-r-tags">
|
||||
<span className="pariseTag"><img src={img_parise} alt="" className="pariseImg" />赞 {item.praises_count}</span>
|
||||
<span><i className="iconfont icon-fork mr3 font-16" style={{ color: "#1B8FFF" }} />fork {item.forked_count}</span>
|
||||
</span>
|
||||
</div>
|
||||
<p className="break_word task-hide-2 mt10" style={{ maxHeight: "44px",lineHeight:"22px" }}>{item.description}</p>
|
||||
<p className="break_word task-hide-2 mt8 color-grey-3 " style={{ maxHeight: "44px",lineHeight:"22px" }}>{item.description}</p>
|
||||
|
||||
<div className="p-r-about">
|
||||
<span className="p-r-detail">
|
||||
|
@ -71,7 +117,12 @@ class IndexItem extends Component {
|
|||
</div>
|
||||
</div>
|
||||
)
|
||||
}) : <Nodata _html="暂无数据~"></Nodata>}
|
||||
}) : <Nodata _html="暂无数据~"></Nodata>
|
||||
)
|
||||
return (
|
||||
<div className="project-list minH-670">
|
||||
<SpecialModal {...this.props} visible={visible} hideModal={this.hideModal} user_apply_signatures={user_apply_signatures} project_id={project_id} sureModal={this.sureModal}></SpecialModal>
|
||||
{renderList}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
import React , { useEffect , useState } from 'react';
|
||||
import { Modal } from 'antd';
|
||||
import UploadSingle from '../Upload/single';
|
||||
import './Index.scss';
|
||||
import axios from 'axios';
|
||||
import { getUrl } from 'educoder';
|
||||
|
||||
function SpecialModal({ visible , hideModal , sureModal , showNotification , user_apply_signatures , project_id }){
|
||||
const [ id ,setId ] = useState(undefined);
|
||||
|
||||
|
||||
function loadFunc(id){
|
||||
setId(id);
|
||||
}
|
||||
|
||||
function sure(){
|
||||
if(!user_apply_signatures || (user_apply_signatures && user_apply_signatures.status !== "waiting")){
|
||||
if(!id || (id && id.length === 0)){
|
||||
showNotification("请先提交文件进行审核!");
|
||||
return;
|
||||
}
|
||||
const url = `/apply_signatures.json`;
|
||||
axios.post(url,{
|
||||
attachment_id:id,
|
||||
project_id:project_id
|
||||
}).then(result=>{
|
||||
if(result && result.data.id){
|
||||
showNotification("已提交文件,正在等待审核!");
|
||||
sureModal();
|
||||
}
|
||||
})
|
||||
}else{
|
||||
sureModal();
|
||||
}
|
||||
}
|
||||
return(
|
||||
<Modal title="提示" visible={visible} closable={false} onCancel={hideModal} onOk={sure}>
|
||||
{
|
||||
!user_apply_signatures || (user_apply_signatures && user_apply_signatures.status !== "waiting") ?
|
||||
<div style={{width:"420px",textAlign:'center',margin:"0 auto",paddingBottom:"30px",position:"relative"}}>
|
||||
<div>该项目为私有项目,请先<a href={getUrl(`/api/apply_signatures/template_file`)} className="color-blue">下载</a>开源协议,阅读并填写<br/>相关信息后,将协议<UploadSingle size={"5"} load={loadFunc} showNotification={showNotification} className={'singleBtn'}><span className="color-blue" style={{cursor:"pointer"}}>上传</span></UploadSingle>,平台审核通过后即可进入当前项目</div>
|
||||
</div>
|
||||
:
|
||||
<p style={{textAlign:'center'}}>您上传的文件正在审核中,通过后才能访问当前项目</p>
|
||||
}
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
export default SpecialModal;
|
|
@ -18,6 +18,14 @@
|
|||
box-sizing: border-box;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.affix-list-left{
|
||||
width: 26%;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.affix-list-content{
|
||||
padding-right:20px;
|
||||
}
|
||||
.list-right{
|
||||
width:74%;
|
||||
background: #fff;
|
||||
|
@ -208,9 +216,7 @@
|
|||
}
|
||||
/* -----------详情------------ */
|
||||
.detailHeader-wrapper{
|
||||
background-color:#FAFBFC;
|
||||
/* background: url(../Images/forgeBanner.jpg) no-repeat center; */
|
||||
/* background-size:cover; */
|
||||
background:linear-gradient(82deg,rgba(82,91,215,1) 0%,rgba(34,24,171,1) 100%);
|
||||
}
|
||||
.headerMenu-wrapper{
|
||||
font-size: 16px;
|
||||
|
@ -222,36 +228,42 @@
|
|||
text-align: center;
|
||||
height: 40px;
|
||||
line-height: 28px;
|
||||
margin-right: 40px;
|
||||
border:1px solid transparent;
|
||||
}
|
||||
.headerMenu-wrapper{
|
||||
font-size: 16px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.headerMenu-wrapper li{
|
||||
padding:0px 18px;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
}
|
||||
.headerMenu-wrapper li a{
|
||||
color: #666;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.headerMenu-wrapper li a > img{
|
||||
margin-right: 8px;
|
||||
}
|
||||
.headerMenu-wrapper li a > span.num{
|
||||
height: 28px;
|
||||
line-height: 29px;
|
||||
margin-left: 8px;
|
||||
font-size: 12px;
|
||||
color: #2878FF;
|
||||
float: right;
|
||||
.headerMenu-wrapper li a > span{
|
||||
display: block;
|
||||
margin-left: 5px;
|
||||
font-size: 16px;
|
||||
}
|
||||
.headerMenu-wrapper li.active::after{
|
||||
position: absolute;
|
||||
bottom:0px;
|
||||
height:2px;
|
||||
background-color: #5091FF;
|
||||
content:'';
|
||||
left: 0px;
|
||||
width:100%;
|
||||
.headerMenu-wrapper li.active{
|
||||
border-radius: 15px;
|
||||
border:1px solid #71A6FF;
|
||||
}
|
||||
.detail_tag_btn{
|
||||
height:26px;
|
||||
line-height: 26px;
|
||||
border-radius:5px;
|
||||
border:1px solid #f1f1f1;
|
||||
border:1px solid #71A6FF;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: 30px
|
||||
|
@ -259,19 +271,26 @@
|
|||
.ant-tooltip {
|
||||
max-width: fit-content!important;
|
||||
}
|
||||
|
||||
.detail_tag_btn_name{
|
||||
padding:0px 10px;
|
||||
color: #666!important;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #fff;
|
||||
}
|
||||
.detail_tag_btn_name img{
|
||||
margin-right: 10px;
|
||||
}
|
||||
.detail_tag_btn_count{
|
||||
padding:0px 10px;
|
||||
background: #fff;
|
||||
color: #fff !important;
|
||||
background: rgba(255,255,255,0.2);
|
||||
border-radius: 0px 4px 4px 0px;
|
||||
font-size: 12px;
|
||||
height:100%;
|
||||
}
|
||||
.detail_tag_btn_count:hover{
|
||||
/* color: #1C91FF !important; */
|
||||
background: rgba(255,255,255,0.5);
|
||||
}
|
||||
.files-md{
|
||||
border:1px solid #eee;
|
||||
|
|
|
@ -47,7 +47,7 @@ function Files({data,history,owner,projectsId}){
|
|||
<span>{item.name}</span>
|
||||
</AlignCenter>
|
||||
<span>
|
||||
<Button className="mr20" onClick={()=>{history.push(`/projects/${owner}/${projectsId}${item.sha ? `/branch/${truncateCommitId(item.sha)}/`:"/"}tree/${item.name}`)}}>查看文件</Button>
|
||||
<Button className="mr20" onClick={()=>{history.push(`/projects/${owner}/${projectsId}/tree/${truncateCommitId(item.sha)}/${item.name}`)}}>查看文件</Button>
|
||||
<span className="color-green">+{item.addition}</span>
|
||||
<span className="color-red ml20">-{item.deletion}</span>
|
||||
</span>
|
||||
|
|
|
@ -43,7 +43,9 @@ class Index extends Component {
|
|||
project_language_name: undefined,
|
||||
project_category_name: undefined,
|
||||
license_name: undefined,
|
||||
ignore_name: undefined
|
||||
ignore_name: undefined,
|
||||
|
||||
licenseForDisabled:undefined
|
||||
}
|
||||
}
|
||||
componentDidMount = () => {
|
||||
|
@ -145,7 +147,7 @@ class Index extends Component {
|
|||
_data = data.filter(item => item.name.toLowerCase().indexOf(name.toLowerCase()) > -1);
|
||||
}
|
||||
let list = _data && _data.map((item) => (
|
||||
<Option key={item.id} value={item.name}>
|
||||
<Option key={item.id} value={item.name} onClick={()=>this.selectSerect(item.is_secret)}>
|
||||
{item.name}
|
||||
</Option>
|
||||
));
|
||||
|
@ -155,6 +157,17 @@ class Index extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
selectSerect=(flag)=>{
|
||||
if(flag){
|
||||
this.props.form.setFieldsValue({
|
||||
private:true
|
||||
})
|
||||
}
|
||||
this.setState({
|
||||
licenseForDisabled:flag
|
||||
})
|
||||
}
|
||||
|
||||
subMitFrom = () => {
|
||||
this.props.form.validateFieldsAndScroll((err, values) => {
|
||||
if (!err) {
|
||||
|
@ -198,7 +211,8 @@ class Index extends Component {
|
|||
}
|
||||
|
||||
ChangePlatform = (value, e, name, list) => {
|
||||
this.setOptionsList(list, name, value)
|
||||
this.setOptionsList(list, name, value);
|
||||
|
||||
this.setState({
|
||||
[name + "_id"]: e.key,
|
||||
[name + "_name"]: value,
|
||||
|
@ -272,6 +286,7 @@ class Index extends Component {
|
|||
project_category_list,
|
||||
license_list,
|
||||
ignore_list,
|
||||
licenseForDisabled,
|
||||
|
||||
mirrorCheck
|
||||
} = this.state;
|
||||
|
@ -477,8 +492,8 @@ class Index extends Component {
|
|||
style={{ margin: "0px" }}
|
||||
className="privatePart"
|
||||
>
|
||||
{getFieldDecorator('private')(
|
||||
<Checkbox value="limit">将项目设为私有<span className="ml15 font-13 color-grey-9">(只有项目所有人或拥有权限的项目成员才能看到)</span></Checkbox>
|
||||
{getFieldDecorator('private',{valuePropName:"checked"})(
|
||||
<Checkbox value="limit" disabled={licenseForDisabled}>将项目设为私有<span className="ml15 font-13 color-grey-9">(只有项目所有人或拥有权限的项目成员才能看到)</span></Checkbox>
|
||||
)}
|
||||
</Form.Item >
|
||||
{
|
||||
|
|
|
@ -15,8 +15,8 @@ const MENU_LIST = [
|
|||
function CollaboratorMember({projectsId,owner,project_id,author,showNotification,newId}){
|
||||
const [ roleName , setRoleName ] = useState(undefined);
|
||||
const [ search , setSearch ] = useState(undefined);
|
||||
const [ page , setPage ] = useState(undefined);
|
||||
const [ isSpin , setIsSpin ] = useState(false);
|
||||
const [ page , setPage ] = useState(1);
|
||||
const [ isSpin , setIsSpin ] = useState(true);
|
||||
const [ role , setRole ] = useState(undefined);
|
||||
const [ listData , setListData ] = useState(undefined);
|
||||
const [ total , setTotal ] = useState(0);
|
||||
|
@ -166,7 +166,11 @@ function CollaboratorMember({projectsId,owner,project_id,author,showNotification
|
|||
<label className={get_color(item.role)}>
|
||||
{operation && operation[0].name}
|
||||
</label>
|
||||
) : (
|
||||
)
|
||||
:
|
||||
item.is_apply_signature ?
|
||||
<label className="text-grey">外围贡献者</label>
|
||||
:(
|
||||
<Dropdown overlay={setRoles(`${item.id}`)} placement={"bottomCenter"}>
|
||||
<span className={get_color(item.role)}>
|
||||
{operation && operation[0].name}
|
||||
|
@ -261,14 +265,8 @@ function CollaboratorMember({projectsId,owner,project_id,author,showNotification
|
|||
</div>
|
||||
</Spin>
|
||||
{total > LIMIT ?
|
||||
<div className="edu-txt-center mt20 mb20">
|
||||
<Pagination
|
||||
showQuickJumper
|
||||
pageSize={LIMIT}
|
||||
current={page}
|
||||
total={total}
|
||||
onChange={()=>setPage(page)}
|
||||
></Pagination>
|
||||
<div className="edu-txt-center mt20 pb20">
|
||||
<Pagination simple current={page} pageSize={LIMIT} total={total} onChange={(page)=>setPage(page)}/>
|
||||
</div>
|
||||
:""}
|
||||
</React.Fragment>
|
||||
|
|
|
@ -28,6 +28,10 @@ const Tags = Loadable({
|
|||
loader: () => import("./new_tags"),
|
||||
loading: Loading,
|
||||
});
|
||||
const Special = Loadable({
|
||||
loader: () => import("./SpecialProject"),
|
||||
loading: Loading,
|
||||
});
|
||||
const Manage = Loadable({
|
||||
loader: () => import("./ManageWeb"),
|
||||
loading: Loading,
|
||||
|
@ -40,6 +44,7 @@ class Index extends Component {
|
|||
render() {
|
||||
const { projectsId , owner } = this.props.match.params;
|
||||
const { pathname } = this.props.history.location;
|
||||
const { projectDetail } = this.props;
|
||||
|
||||
const flag = pathname === `/projects/${owner}/${projectsId}/setting`;
|
||||
return (
|
||||
|
@ -87,6 +92,20 @@ class Index extends Component {
|
|||
</Link>
|
||||
</p>
|
||||
</li>
|
||||
{
|
||||
projectDetail && projectDetail.permission && (projectDetail.permission === "Owner" || projectDetail.permission === "Admin") ?
|
||||
<li
|
||||
className={pathname.indexOf("setting/special") > -1 ? "active" : ""}
|
||||
>
|
||||
<p>
|
||||
<Link to={`/projects/${owner}/${projectsId}/setting/special`} className="w-100">
|
||||
<i className="iconfont icon-jingyan font-18 mr10"></i>
|
||||
特殊开源许可证项目管理
|
||||
</Link>
|
||||
</p>
|
||||
</li>
|
||||
:""
|
||||
}
|
||||
|
||||
{/* <li
|
||||
className={
|
||||
|
@ -112,7 +131,15 @@ class Index extends Component {
|
|||
<Collaborator {...this.props} {...props} {...this.state} />
|
||||
)}
|
||||
></Route>
|
||||
|
||||
<Route
|
||||
path="/projects/:owner/:projectsId/setting/special"
|
||||
render={(props) => (
|
||||
<Special {...this.props} {...props} {...this.state} />
|
||||
)}
|
||||
></Route>
|
||||
{/* 修改仓库信息 */}
|
||||
|
||||
<Route
|
||||
path="/projects/:owner/:projectsId/setting/tags"
|
||||
render={(props) => (
|
||||
|
|
|
@ -15,6 +15,7 @@ class Setting extends Component {
|
|||
CategoryList: undefined,
|
||||
LanguageList: undefined,
|
||||
private_check: undefined,
|
||||
is_secret:false
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -52,10 +53,11 @@ class Setting extends Component {
|
|||
.then((result) => {
|
||||
if (result) {
|
||||
this.props.form.setFieldsValue({
|
||||
...result.data,
|
||||
...result.data
|
||||
});
|
||||
this.setState({
|
||||
private_check: result.data.private,
|
||||
is_secret:result.data.is_secret
|
||||
});
|
||||
}
|
||||
})
|
||||
|
@ -152,7 +154,7 @@ class Setting extends Component {
|
|||
render() {
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
|
||||
const { CategoryList, LanguageList, private_check } = this.state;
|
||||
const { CategoryList, LanguageList, private_check , is_secret } = this.state;
|
||||
return (
|
||||
<div>
|
||||
<WhiteBack style={{paddingBottom:"20px"}}>
|
||||
|
@ -177,6 +179,7 @@ class Setting extends Component {
|
|||
<Checkbox
|
||||
checked={private_check}
|
||||
onChange={this.changePrivate}
|
||||
disabled={is_secret}
|
||||
>
|
||||
将仓库设为私有
|
||||
</Checkbox>
|
||||
|
|
|
@ -0,0 +1,186 @@
|
|||
import React , { useEffect , useState} from 'react';
|
||||
import { Input , Table , Pagination, Button , Dropdown , Menu } from 'antd';
|
||||
import { Banner , WhiteBack , AlignCenterBetween } from '../Component/layout';
|
||||
import axios from 'axios';
|
||||
|
||||
const { Search } = Input;
|
||||
|
||||
const LIMIT = 15;
|
||||
function SpecialProject(props){
|
||||
const [ page , setPage] = useState(1);
|
||||
const [ searchValue , SetSearchValue ] = useState(undefined);
|
||||
const [ total , setTotal ] = useState(0);
|
||||
const [ list , setList ] = useState(undefined);
|
||||
const [ status , setStatus ] = useState(undefined);
|
||||
const [ loading ,setLoading ] = useState(true);
|
||||
|
||||
const { owner , projectsId} = props.match.params;
|
||||
const { project_id } = props;
|
||||
|
||||
useEffect(()=>{
|
||||
if(project_id){
|
||||
setLoading(true);
|
||||
Init(searchValue, status);
|
||||
}
|
||||
},[page,project_id]);
|
||||
|
||||
function Init(search,status){
|
||||
const url = `/apply_signatures.json`;
|
||||
axios.get(url,{
|
||||
params:{
|
||||
project_id,
|
||||
page,limit:LIMIT,search,status
|
||||
}
|
||||
}).then(result=>{
|
||||
setLoading(false);
|
||||
if(result){
|
||||
setList(result.data.apply_signatures);
|
||||
setTotal(result.data.total_count);
|
||||
}
|
||||
}).catch(error=>{})
|
||||
}
|
||||
|
||||
function changePage(page){
|
||||
setLoading(true);
|
||||
setPage(page);
|
||||
}
|
||||
|
||||
const column = [
|
||||
{
|
||||
dataIndex:"column",
|
||||
key:1,
|
||||
width:"12%",
|
||||
title:"序号",
|
||||
render:(txt,item,index)=>{
|
||||
return `${index+1}`
|
||||
}
|
||||
},
|
||||
{
|
||||
dataIndex:"name",
|
||||
key:2,
|
||||
title:"申请人",
|
||||
render:(text,item,m)=>{
|
||||
return item.user && <span className="task-hide" style={{maxWidth:"139px",display:"block"}}>{item.user.name}</span>
|
||||
}
|
||||
},
|
||||
{
|
||||
dataIndex:"email",
|
||||
key:2,
|
||||
title:"邮箱",
|
||||
width:"22%",
|
||||
render:(text,item,m)=>{
|
||||
return item.user && <span>{item.user.email}</span>
|
||||
}
|
||||
},
|
||||
{
|
||||
dataIndex:"attachment",
|
||||
key:3,
|
||||
title:"附件",
|
||||
width:"28%",
|
||||
render:(text,item,m)=>{
|
||||
return item.attachment && <a className="task-hide" style={{maxWidth:"173px",display:"block"}} href={`${item.attachment.path}`}>{item.attachment.filename}</a>
|
||||
}
|
||||
},
|
||||
{
|
||||
dataIndex:"operation",
|
||||
key:4,
|
||||
width:"18%",
|
||||
title:"操作",
|
||||
render:(text, item) =>{
|
||||
return(
|
||||
<React.Fragment>
|
||||
{
|
||||
item.status === "waiting" &&
|
||||
<span>
|
||||
<Button size="small" onClick={()=>operation(item.id,"unpassed")}>拒绝</Button>
|
||||
<Button size="small" onClick={()=>operation(item.id,"passed")} type={"primary"} className="ml20">同意</Button>
|
||||
</span>
|
||||
}
|
||||
{
|
||||
item.status === "unpassed" &&
|
||||
<span style={{color:"#ff041c"}}>已拒绝</span>
|
||||
}
|
||||
{
|
||||
item.status === "passed" &&
|
||||
<span style={{color:"#13b4f1"}}>已同意</span>
|
||||
}
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
]
|
||||
// 拒绝&同意
|
||||
function operation(ids,s){
|
||||
setLoading(true);
|
||||
const url = `/apply_signatures/${ids}.json`;
|
||||
axios.put(url,{
|
||||
project_id:project_id,
|
||||
status:s
|
||||
}).then(result=>{
|
||||
setLoading(false);
|
||||
if(result){
|
||||
props.showNotification(`${s==="passed"?"同意":"拒绝"}此申请已操作成功!`);
|
||||
Init(searchValue,status);
|
||||
}
|
||||
}).catch(error=>{setLoading(false)})
|
||||
}
|
||||
|
||||
function searchList(){
|
||||
setLoading(true);
|
||||
Init(searchValue,status);
|
||||
}
|
||||
|
||||
const menu=(
|
||||
<Menu onClick={chooseStatus}>
|
||||
<Menu.Item key="all">全部</Menu.Item>
|
||||
<Menu.Item key="waiting">审核中</Menu.Item>
|
||||
<Menu.Item key="unpassed">已拒绝</Menu.Item>
|
||||
<Menu.Item key="passed">已同意</Menu.Item>
|
||||
</Menu>
|
||||
)
|
||||
|
||||
function chooseStatus(e){
|
||||
setStatus(e.key);
|
||||
Init(searchValue, e.key);
|
||||
}
|
||||
|
||||
|
||||
return(
|
||||
<WhiteBack style={{minHeight:"500px"}}>
|
||||
<Banner>项目管理</Banner>
|
||||
<AlignCenterBetween style={{padding:"10px 20px",textAlign:"right"}}>
|
||||
<Search
|
||||
placeholder="请输入用户姓名或者邮箱搜索"
|
||||
allowClear
|
||||
enterButton="搜索"
|
||||
style={{width:400}}
|
||||
size="middle"
|
||||
value={searchValue}
|
||||
onChange={(e)=>SetSearchValue(e.target.value)}
|
||||
onSearch={searchList}
|
||||
/>
|
||||
<Dropdown overlay={menu} placement="bottomRight">
|
||||
<span>
|
||||
<span style={{color:status ? "color-blue" : "color-grey-3"}}>{status ==="waiting"?"审核中":status==="unpassed"?"已拒绝":status==="passed"?"已同意":"全部"}</span>
|
||||
<i className="iconfont icon-xiajiantou color-grey-9 font-14 ml8"></i>
|
||||
</span>
|
||||
</Dropdown>
|
||||
</AlignCenterBetween>
|
||||
<Table
|
||||
columns={column}
|
||||
rowKey={(record) => record.id}
|
||||
pagination={false}
|
||||
dataSource={list}
|
||||
loading={loading}
|
||||
></Table>
|
||||
{
|
||||
total > LIMIT &&
|
||||
<div className="center mt20 mb20">
|
||||
<Pagination simple current={page} total={total} pageSize={LIMIT} onChange={changePage}></Pagination>
|
||||
</div>
|
||||
}
|
||||
|
||||
</WhiteBack>
|
||||
)
|
||||
}
|
||||
export default SpecialProject;
|
|
@ -139,6 +139,7 @@
|
|||
.padding15-10{
|
||||
padding:15px 10px;
|
||||
}
|
||||
.center{text-align: center;}
|
||||
.w-100{width: 100%;}
|
||||
.fwb{font-weight: 600;}
|
||||
.text-black{color: #333;}
|
||||
|
@ -151,6 +152,9 @@
|
|||
.text-yellow{color: #FF6E21 !important;}
|
||||
.text-delete{color: #BBBBBB; }
|
||||
.text-delete:hover{color: #db2828; }
|
||||
.text-grey{
|
||||
color: #999;
|
||||
}
|
||||
.new-tag-div{
|
||||
padding: 15px;
|
||||
height: 75px;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { Component } from "react";
|
||||
import { Upload, Button, Icon } from 'antd';
|
||||
import { Upload , Icon } from 'antd';
|
||||
import { getUploadActionUrl, appendFileSizeToUploadFileAll } from 'educoder';
|
||||
|
||||
import axios from 'axios';
|
||||
|
@ -45,8 +45,7 @@ class Index extends Component {
|
|||
deleteAttachment = (file) => {
|
||||
|
||||
const url = `/attachments/${file.response ? file.response.id : file.uid}.json`
|
||||
axios.delete(url, {
|
||||
}).then((response) => {
|
||||
axios.delete(url).then((response) => {
|
||||
if (response.data) {
|
||||
if (response.data.status === 0) {
|
||||
this.setState((state) => {
|
||||
|
@ -71,11 +70,26 @@ class Index extends Component {
|
|||
handleChange = (info) => {
|
||||
const { changeIsComplete } = this.props;
|
||||
changeIsComplete && changeIsComplete(true);
|
||||
|
||||
if (info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') {
|
||||
let fileList = info.fileList;
|
||||
|
||||
this.setState({ fileList: appendFileSizeToUploadFileAll(fileList) });
|
||||
this.fileIdList(fileList);
|
||||
|
||||
if ( info.file.status === 'done') {
|
||||
let filelist = info.fileList && info.fileList.length>0 && info.fileList[info.fileList.length-1];
|
||||
if(filelist && filelist.response && filelist.response.status === -1){
|
||||
this.props.showNotification(filelist.response.message)
|
||||
this.setState((state) => {
|
||||
state.fileList.pop()
|
||||
return {
|
||||
fileList: state.fileList,
|
||||
};
|
||||
});
|
||||
this.fileIdList(this.state.fileList);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
import React, { useEffect , useState } from "react";
|
||||
import { Upload } from 'antd';
|
||||
import { getUploadActionUrl, appendFileSizeToUploadFileAll } from 'educoder';
|
||||
|
||||
import axios from 'axios';
|
||||
|
||||
function Single({ children , showNotification , className , load , size }) {
|
||||
const [ fileList , setFileList ] = useState(undefined);
|
||||
// 移除
|
||||
function onAttachmentRemove(file){
|
||||
if (!file.percent || file.percent === 100) {
|
||||
deleteAttachment(file);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function deleteAttachment(file){
|
||||
let uid = file.response ? file.response.id : file.uid;
|
||||
const url = `/attachments/${uid}.json`
|
||||
axios.delete(url).then((response) => {
|
||||
if (response.data && response.data.status === 0) {
|
||||
let list = fileList.filter(item=> item.response && item.response.id !== uid);
|
||||
setFileList(list);
|
||||
fileIdList(list);
|
||||
}
|
||||
}).catch(error=>{});
|
||||
}
|
||||
|
||||
|
||||
function handleChange(info){
|
||||
if (info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') {
|
||||
let fileList = [info.file];
|
||||
|
||||
let list = appendFileSizeToUploadFileAll(fileList);
|
||||
setFileList(list);
|
||||
if ( info.file.status === 'done') {
|
||||
let f = info.fileList && info.fileList.length>0 && info.fileList[info.fileList.length-1];
|
||||
if(f && f.response && f.response.status === -1){
|
||||
showNotification(f.response.message)
|
||||
setFileList(f);
|
||||
}
|
||||
fileIdList(fileList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function fileIdList(fileList){
|
||||
let l = fileList && fileList.length > 0 && fileList[0];
|
||||
let array = [l && l.response && l.response.id];
|
||||
load && load(array);
|
||||
}
|
||||
|
||||
function beforeUpload(file){
|
||||
if(!size) return;
|
||||
const isLt100M = file.size / 1024 / 1024 < size;
|
||||
if (!isLt100M) {
|
||||
showNotification(`文件大小必须小于${size}MB!`);
|
||||
}
|
||||
return isLt100M;
|
||||
}
|
||||
|
||||
//判断是否已经提交,如已提交评论则上一条评论数据清除
|
||||
const upload = {
|
||||
name: 'file',
|
||||
fileList: fileList,
|
||||
action: `${getUploadActionUrl()}`,
|
||||
onChange: handleChange,
|
||||
onRemove: onAttachmentRemove,
|
||||
beforeUpload: beforeUpload
|
||||
};
|
||||
|
||||
return (
|
||||
<Upload {...upload} className={className}>
|
||||
{children}
|
||||
</Upload>
|
||||
)
|
||||
}
|
||||
export default Single;
|
|
@ -1,21 +0,0 @@
|
|||
|
||||
1.请求URL: https://code.ihub.org.cn/api/v1/mirrors/create.json
|
||||
|
||||
2.请求方式: POST
|
||||
|
||||
3.参数:
|
||||
|
||||
{
|
||||
"image_url": "xxx.git", #必填,且后缀必为.git,
|
||||
"language": "Ruby", #必填,如数据库不存在,则会创建新的记录
|
||||
}
|
||||
|
||||
|
||||
4. 返回值: {
|
||||
"status": 1,
|
||||
"message": "同步成功,项目ID===1806"
|
||||
}
|
||||
|
||||
5. 返回值说明: 仅有当有返回值,且返回值的status 的值为1, 才是创建成功,其余均为创建失败
|
||||
|
||||
|
|
@ -62,6 +62,9 @@
|
|||
.text-yellow{
|
||||
color: #FFA802 !important
|
||||
}
|
||||
.text-grey{
|
||||
color: #999;
|
||||
}
|
||||
.text-gray {
|
||||
color: #888888;
|
||||
}
|
||||
|
|
|
@ -166,7 +166,12 @@ form{
|
|||
margin-bottom: 12px;
|
||||
border-radius:2px;
|
||||
background-color: #fff;
|
||||
&>li{
|
||||
.list-affix{
|
||||
min-height: 20px;
|
||||
max-height: 240px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
& li{
|
||||
font-size: 1rem;
|
||||
padding:0px 0px 0px 20px;
|
||||
box-sizing: border-box;
|
||||
|
@ -205,7 +210,7 @@ form{
|
|||
width: 6px;
|
||||
content: '';
|
||||
height: 33px;
|
||||
background: #4CACFF;
|
||||
background: #1484EF;
|
||||
}
|
||||
.MenuTitle{
|
||||
font-size: 16px;
|
||||
|
@ -215,6 +220,21 @@ form{
|
|||
line-height: 62px;
|
||||
border-bottom: 1px solid #E0E0E0;
|
||||
font-weight: 400;
|
||||
|
||||
span{
|
||||
display: block;
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
span:hover{
|
||||
color: #1484EF;
|
||||
|
||||
.iconfont{
|
||||
color: #1484EF !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
.ant-menu-inline{
|
||||
border:none;
|
||||
|
|
|
@ -6,7 +6,6 @@ import { withRouter } from "react-router";
|
|||
import { SnackbarHOC } from "educoder";
|
||||
import { CNotificationHOC } from "../../modules/courses/common/CNotificationHOC";
|
||||
import { TPMIndexHOC } from "../../modules/tpm/TPMIndexHOC";
|
||||
import Handbook from '../Component/Handbook';
|
||||
const Infos = Loadable({
|
||||
loader: () => import("./Infos"),
|
||||
loading: Loading,
|
||||
|
@ -15,7 +14,6 @@ export default withRouter(
|
|||
(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC((props)=>{
|
||||
return(
|
||||
<div>
|
||||
<Handbook />
|
||||
<Switch>
|
||||
<Route
|
||||
path="/users/:username"
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import React, { Component } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Avatar, Tag, Button, Spin } from "antd";
|
||||
import FocusButton from "../UsersList/focus_button";
|
||||
|
||||
|
@ -52,7 +51,7 @@ class Infos extends Component {
|
|||
isSpin: false,
|
||||
user: undefined,
|
||||
project_type: undefined,
|
||||
route_type: undefined
|
||||
route_type: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -138,7 +137,7 @@ class Infos extends Component {
|
|||
|
||||
|
||||
render() {
|
||||
const { current_user, mygetHelmetapi } = this.props;
|
||||
const { current_user, main_web_site_url } = this.props;
|
||||
const { username } = this.props.match.params;
|
||||
|
||||
const { user, isSpin, project_type, route_type } = this.state;
|
||||
|
@ -147,7 +146,7 @@ class Infos extends Component {
|
|||
<Spin spinning={isSpin}>
|
||||
<div className="new-content-flex">
|
||||
<div className="list-left">
|
||||
<div className="bgcF">
|
||||
<div className="bgcF mb20">
|
||||
<div className="list-l-Menu text-center pd20 ">
|
||||
<Avatar
|
||||
size={110}
|
||||
|
@ -168,11 +167,7 @@ class Infos extends Component {
|
|||
<Button
|
||||
block
|
||||
className="text-button-grey"
|
||||
href={`${
|
||||
mygetHelmetapi &&mygetHelmetapi.new_course&&
|
||||
mygetHelmetapi.new_course.edit_account
|
||||
}`}
|
||||
target="_blank"
|
||||
href={`${main_web_site_url || "https://osredm.com/"}users/${user.login}/profiles`}
|
||||
>
|
||||
{" "}
|
||||
<i className="iconfont icon-shezhi4 font-15 mr5"></i>
|
||||
|
@ -193,22 +188,22 @@ class Infos extends Component {
|
|||
)}
|
||||
</div>
|
||||
<div className="width100 inline-block mt20">
|
||||
<Link
|
||||
to={`/users/${user && user.login}/watchers`}
|
||||
<a
|
||||
href={`/users/${user && user.login}/user_watchlist`}
|
||||
className={`with50 text-center pull-left ${route_type === "watchers" ? "text-primary" : ""}`}
|
||||
onClick={() =>this.route_link("watchers")}
|
||||
>
|
||||
<div>{current_user && user && user.login === current_user.login ? "我关注的" : "TA关注的"}</div>
|
||||
<span>{user && user.watching_count}</span>
|
||||
</Link>
|
||||
<Link
|
||||
to={`/users/${user && user.login}/fan_users`}
|
||||
</a>
|
||||
<a
|
||||
href={`/users/${user && user.login}/user_fanslist`}
|
||||
onClick={() =>this.route_link("fan_users")}
|
||||
className={`with50 text-center pull-left ${route_type === "fan_users" ? "text-primary" : ""}`}
|
||||
>
|
||||
<div>{current_user && user && user.login === current_user.login ? "关注我的" : "关注TA的"}</div>
|
||||
<span>{user && user.watched_count}</span>
|
||||
</Link>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -230,7 +225,7 @@ class Infos extends Component {
|
|||
|
||||
<div className="bgcF">
|
||||
<ul className="list-l-Menu">
|
||||
<li className="MenuTitle" onClick={() => this.change_project_type(undefined)}>
|
||||
<li className="MenuTitle" onClick={() => this.change_project_type()}>
|
||||
<i className="iconfont icon-xiangmuleixing font-15 mr5"></i>
|
||||
项目类型
|
||||
<i className="iconfont icon-youjiantou font-15 mr20 color-grey-9 pull-right"></i>
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
import { Modal } from 'antd';
|
||||
|
||||
export default (
|
||||
handleOk,
|
||||
title,
|
||||
content,
|
||||
handleCancel) => {
|
||||
return Modal.confirm({
|
||||
title: title || "警告",
|
||||
content: content || "确认删除?",
|
||||
okText: '确定',
|
||||
cancelText: '取消',
|
||||
onOk() {
|
||||
handleOk && handleOk();
|
||||
},
|
||||
onCancel() {
|
||||
handleCancel && handleCancel();
|
||||
}
|
||||
});
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
import React, { useEffect, useState } from "react";
|
||||
import { Upload, Button } from 'antd';
|
||||
import { appendFileSizeToUploadFileAll } from 'educoder';
|
||||
import { httpUrl } from '../task/fetch';
|
||||
|
||||
function Uploads({ className, size, actionUrl, fileList, showNotification, load }) {
|
||||
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;
|
||||
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,
|
||||
action: (httpUrl || actionUrl) + `/busiAttachments/upload`,
|
||||
onChange: handleChange,
|
||||
onRemove: onAttachmentRemove,
|
||||
beforeUpload: beforeUpload,
|
||||
};
|
||||
return (
|
||||
<Upload {...upload} className={className}>
|
||||
<Button type="primary">点击上传</Button>
|
||||
<span className="ml10 color-grey-9">(你可以上传小于<span className="color-red">{size}MB</span>的文件)</span>
|
||||
</Upload>
|
||||
)
|
||||
}
|
||||
export default Uploads;
|
|
@ -0,0 +1,28 @@
|
|||
import React, { useEffect, useState,memo } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import './index.scss';
|
||||
|
||||
export default memo((props) => {
|
||||
const { title, options, changeOptionId, type ,size} = props;
|
||||
const [option, setOption] = useState({ code: "", dicItemName: "" ,dicItemCode:""});
|
||||
|
||||
useEffect(() => {
|
||||
changeOptionId(option, type);
|
||||
}, [option])
|
||||
|
||||
return (
|
||||
|
||||
<div className={classNames({"choose-box":true,"choose-box-big":size})}>
|
||||
<div className="choose-title">{title}</div>
|
||||
<div className="choose-list">
|
||||
<div className={classNames({ "choose-item-checked": option.dicItemCode === "", "choose-item": true })} key={"all"} onClick={() => { setOption({ dicItemCode: "", dicItemName: "" }) }}>全部</div>
|
||||
{
|
||||
options.map((item) => {
|
||||
return <div className={classNames({ "choose-item-checked": option.dicItemCode === item.dicItemCode, "choose-item": true })} key={item.dicItemCode} onClick={() => { setOption(item) }} >{item.dicItemName}</div>
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
)
|
||||
})
|
|
@ -0,0 +1,47 @@
|
|||
.nav-content {
|
||||
margin:20px 0;
|
||||
padding:1rem 0.2rem;
|
||||
background: #fff;
|
||||
box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.05);
|
||||
border-radius: 5px;
|
||||
}
|
||||
.choose-box {
|
||||
padding: .35em 0;
|
||||
display: flex;
|
||||
justify-content: start;
|
||||
font-size: .85rem;
|
||||
}
|
||||
.choose-title {
|
||||
width: 6.5em;
|
||||
text-align: center;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
flex:none;
|
||||
}
|
||||
|
||||
.choose-box-big{
|
||||
font-size: 1rem;
|
||||
.choose-title{
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
.choose-list {
|
||||
display: flex;
|
||||
justify-content: start;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.choose-item {
|
||||
color:#666;
|
||||
text-align: center;
|
||||
padding: 0 15px ;
|
||||
cursor: pointer;
|
||||
&:hover{
|
||||
color: #1B8FFF;
|
||||
}
|
||||
}
|
||||
|
||||
.choose-item-checked {
|
||||
background: #f7f7f7;
|
||||
color: #1B8FFF;
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
import { httpUrl } from '../task/fetch';
|
||||
|
||||
export const editorConfig = {
|
||||
placeholder: '请输入',
|
||||
uploadImgServer: httpUrl + '/busiAttachments/upload',
|
||||
uploadFileName: 'file',
|
||||
uploadImgHeaders: {
|
||||
'X-Requested-With': 'XMLHttpRequest'
|
||||
},
|
||||
excludeMenus: [
|
||||
'list',
|
||||
'todo',
|
||||
'emoticon',
|
||||
'video'
|
||||
],
|
||||
uploadImgHooks: {
|
||||
// 图片上传并返回了结果,想要自己把图片插入到编辑器中
|
||||
customInsert: function (insertImgFn, result) {
|
||||
// insertImgFn 可把图片插入到编辑器,传入图片 src ,执行函数即可
|
||||
if (result && result.data && result.data.id) {
|
||||
insertImgFn(`${httpUrl}/busiAttachments/view/${result.data.id}`);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
import React, { useEffect, useState, memo } from 'react';
|
||||
import { Icon, } from 'antd';
|
||||
import classNames from 'classnames';
|
||||
import './index.scss';
|
||||
|
||||
export default memo((props) => {
|
||||
const { options, changeOptionId, type } = props;
|
||||
|
||||
const [myOptions, setMyOptions] = useState(()=>{
|
||||
return JSON.parse(JSON.stringify(options));
|
||||
});
|
||||
const [option, setOption] = useState({
|
||||
name: '综合',
|
||||
type: 'default',
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
changeOptionId(option, type);
|
||||
}, [option]);
|
||||
|
||||
function itemClick(activeItem) {
|
||||
const newOption = {
|
||||
...activeItem,
|
||||
desc: !activeItem.desc
|
||||
};
|
||||
for (const item of myOptions) {
|
||||
if (item.type === activeItem.type) {
|
||||
item.desc = newOption.desc;
|
||||
}
|
||||
}
|
||||
setOption(newOption);
|
||||
setMyOptions(myOptions);
|
||||
}
|
||||
|
||||
console.log('-----options----')
|
||||
return (
|
||||
|
||||
<div className="sort-box">
|
||||
{
|
||||
myOptions.map((item) => {
|
||||
return <div className={classNames({ "sort-item-checked": option.type === item.type, "sort-item": true })} key={item.type} onClick={() => { itemClick(item) }} >
|
||||
{item.name}
|
||||
{
|
||||
item.icon && <span className="caret-up-down">
|
||||
<Icon type="caret-up" className={classNames({ "caret-checked": !item.desc })} />
|
||||
<Icon type="caret-down" className={classNames({ "caret-checked": item.desc })} />
|
||||
</span>}
|
||||
</div>
|
||||
})
|
||||
}
|
||||
</div>
|
||||
|
||||
)
|
||||
})
|
|
@ -0,0 +1,40 @@
|
|||
.sort-box {
|
||||
display: flex;
|
||||
justify-content: start;
|
||||
align-items: center;
|
||||
margin-left: 10px;
|
||||
font-size: 1rem;
|
||||
.sort-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #333;
|
||||
padding: 0 20px;
|
||||
background-color: #fff;
|
||||
&:hover {
|
||||
background-color: #fff;
|
||||
color: #409eff;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.sort-item-checked {
|
||||
// background-color: #409eff;
|
||||
// color: #fff;
|
||||
color: #409eff;
|
||||
}
|
||||
.caret-up-down {
|
||||
display: inline-flex;
|
||||
flex-flow: column nowrap;
|
||||
margin-left:.25em;
|
||||
font-size: .75em;
|
||||
color:#ccc;
|
||||
}
|
||||
.caret-checked{
|
||||
color: #409eff;
|
||||
}
|
||||
.anticon-caret-up{
|
||||
margin-bottom: -.15em;
|
||||
}
|
||||
.anticon-caret-down{
|
||||
margin-top: -.15em;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
import React, { useEffect, useState ,memo} from 'react';
|
||||
import classNames from 'classnames';
|
||||
import './index.scss';
|
||||
|
||||
export default memo((props) => {
|
||||
const { options, changeOptionId, type } = props;
|
||||
|
||||
const [option, setOption] = useState({ code: "", dicItemName: "" ,dicItemCode:""});
|
||||
|
||||
useEffect(() => {
|
||||
changeOptionId(option, type);
|
||||
}, [option])
|
||||
|
||||
return (
|
||||
|
||||
<div className="status-list">
|
||||
<div className={classNames({ "status-item-checked": option.dicItemCode === "", "status-item": true })} key={"all"} onClick={() => { setOption({ dicItemCode: "", dicItemName: "" }) }}>全部</div>
|
||||
{
|
||||
options.map((item) => {
|
||||
return <div className={classNames({ "status-item-checked": option.dicItemCode === item.dicItemCode, "status-item": true })} key={item.dicItemCode} onClick={() => { setOption(item) }} >{item.dicItemName}</div>
|
||||
})
|
||||
}
|
||||
</div>
|
||||
|
||||
)
|
||||
})
|
|
@ -0,0 +1,21 @@
|
|||
.status-list {
|
||||
padding: 1rem 0;
|
||||
display: flex;
|
||||
justify-content: start;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.status-item {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
text-align: center;
|
||||
padding: 3px 15px;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
color: #4cacff;
|
||||
}
|
||||
}
|
||||
|
||||
.status-item-checked {
|
||||
background: #f7f7f7;
|
||||
color: #4cacff ;
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
import React, { Component } from "react";
|
||||
|
||||
import { Route, Switch } from "react-router-dom";
|
||||
import { withRouter } from "react-router";
|
||||
import { SnackbarHOC } from "educoder";
|
||||
import { CNotificationHOC } from "../modules/courses/common/CNotificationHOC";
|
||||
import { TPMIndexHOC } from "../modules/tpm/TPMIndexHOC";
|
||||
import Loadable from "react-loadable";
|
||||
import Loading from "../Loading";
|
||||
import { ImageLayerOfCommentHOC } from "../modules/page/layers/ImageLayerOfCommentHOC";
|
||||
import './index.scss';
|
||||
|
||||
const Register = Loadable({
|
||||
loader: () => import("./expert/register"),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
const Review = Loadable({
|
||||
loader: () => import("./expert/review/review"),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
class Expert extends Component {
|
||||
render() {
|
||||
return (
|
||||
<div className="newMain clearfix">
|
||||
<Switch {...this.props}>
|
||||
<Route
|
||||
path="/expert/register"
|
||||
render={(props) => (
|
||||
<Register {...this.props} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
<Route
|
||||
path="/expert"
|
||||
render={(props) => (
|
||||
<Review {...this.props} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
</Switch>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
export default withRouter(
|
||||
ImageLayerOfCommentHOC({
|
||||
imgSelector: ".imageLayerParent img, .imageLayerParent .imageTarget",
|
||||
parentSelector: ".newMain",
|
||||
})(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(Expert))))
|
||||
);
|
|
@ -0,0 +1 @@
|
|||
import fetch from './fetch';
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
import javaFetch from '../javaFetch';
|
||||
|
||||
|
||||
let settings=JSON.parse(localStorage.chromesetting);
|
||||
let actionUrl = settings.api_urls ? settings.api_urls.expert :'http://10.47.38.56:8088';
|
||||
|
||||
const service = javaFetch(actionUrl);
|
||||
export const httpUrl = actionUrl;
|
||||
export default service;
|
|
@ -0,0 +1,41 @@
|
|||
// 公共样式
|
||||
.but41_fill, .but41_border, .butE3_border{
|
||||
padding: 0 18px;
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -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 |
|
@ -0,0 +1,241 @@
|
|||
import React, { useEffect, useState, useCallback } from 'react';
|
||||
import { Button, Icon, Form, Modal, Input, Cascader } from 'antd';
|
||||
import { Link } from "react-router-dom";
|
||||
import { unitType, natureOfWork, highestEducation, positionLevel, professionalType, reviewArea } from '../static';
|
||||
import './index.scss';
|
||||
import '../index.scss';
|
||||
|
||||
export default Form.create()(({ match, history, showNotification, form }) => {
|
||||
const { getFieldDecorator, validateFields, setFieldsValue } = form;
|
||||
|
||||
// form表单公共处理函数
|
||||
const helper = useCallback(
|
||||
(label, name, rules, widget) => (
|
||||
<Form.Item label={label}>
|
||||
{getFieldDecorator(name, { rules, validateFirst: true, getValueFromEvent: e => e.target.value.replace(/(^\s*)|(\s*$)/g, "") })(widget)}
|
||||
</Form.Item>
|
||||
),
|
||||
[]
|
||||
);
|
||||
|
||||
|
||||
return (
|
||||
<div className="centerbox detail">
|
||||
<div className="navigation">
|
||||
<span>专家评审系统</span> > <span>登记专家资料</span>
|
||||
</div>
|
||||
<div className='center_flex'>
|
||||
<div className='register_left'>
|
||||
<button className="but41_fill">登记专家资料</button>
|
||||
</div>
|
||||
<div className='register_right'>
|
||||
<p>专家资料</p>
|
||||
<div>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
{
|
||||
helper('姓名',
|
||||
'readerName',
|
||||
[{ required: true, message: "请输入用户姓名" }, { max: 50, message: '不能超过50字符' }],
|
||||
<Input
|
||||
placeholder="请输入您的姓名"
|
||||
/>
|
||||
)
|
||||
}
|
||||
</td>
|
||||
<td>
|
||||
{
|
||||
helper('最高学历',
|
||||
'companyName',
|
||||
[{ required: true, message: 'Please select your habitual residence!' }],
|
||||
<Cascader placeholder= "请选择" options={highestEducation}/>
|
||||
)
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
{
|
||||
helper('手机号码',
|
||||
'contactInfo',
|
||||
[{ required: true, message: "请输入联系方式" },
|
||||
{ max: 100, message: '不能超过100字符' },
|
||||
{
|
||||
validator: (rule, val, callback) => {
|
||||
const pattern = /^((\+)?86|((\+)?86)?)0?1[3458]\d{9}$/;
|
||||
if (pattern.test(val)) {
|
||||
callback();
|
||||
} else {
|
||||
callback('请输入正确的手机号码!');
|
||||
}
|
||||
}
|
||||
}],
|
||||
<Input
|
||||
placeholder="请输入您的手机号码"
|
||||
/>
|
||||
)
|
||||
}
|
||||
</td>
|
||||
<td>
|
||||
{
|
||||
helper('工作单位',
|
||||
'companyName',
|
||||
[{ required: true, message: "请输入公司名称" }, { max: 100, message: '不能超过100字符' }],
|
||||
<Input
|
||||
placeholder="请输入您的工作单位"
|
||||
/>
|
||||
)
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
{
|
||||
helper('单位类别',
|
||||
'companyName',
|
||||
[{ required: true, message: "请输入公司名称" }, { max: 100, message: '不能超过100字符' }],
|
||||
<Cascader placeholder="请选择" options={unitType} />
|
||||
)
|
||||
}
|
||||
</td>
|
||||
<td>
|
||||
{
|
||||
helper('工作性质',
|
||||
'companyName',
|
||||
[{ required: true, message: "请输入公司名称" }, { max: 100, message: '不能超过100字符' }],
|
||||
<Cascader placeholder="请选择" options={natureOfWork} />
|
||||
)
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
{helper('专业职称',
|
||||
'companyName',
|
||||
[{ required: true, message: "请输入公司名称" }, { max: 100, message: '不能超过100字符' }],
|
||||
<Input
|
||||
placeholder="请输入您的专业职称"
|
||||
/>)}
|
||||
</td>
|
||||
<td>
|
||||
{helper('职称职级',
|
||||
'companyName',
|
||||
[{ required: true, message: "请输入公司名称" }, { max: 100, message: '不能超过100字符' }],
|
||||
<Cascader placeholder="请选择" options={positionLevel} />)}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
{helper('专业类别',
|
||||
'companyName',
|
||||
[{ required: true, message: "请输入公司名称" }, { max: 100, message: '不能超过100字符' }],
|
||||
<Cascader placeholder="请选择" options={professionalType} />)}
|
||||
</td>
|
||||
<td>
|
||||
{helper('评审领域1',
|
||||
'companyName',
|
||||
[{ required: true, message: "请输入公司名称" }, { max: 100, message: '不能超过100字符' }],
|
||||
<Cascader placeholder="请选择" options={reviewArea} />)}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
{helper('评审领域2',
|
||||
'companyName',
|
||||
[{ required: true, message: "请输入公司名称" }, { max: 100, message: '不能超过100字符' }],
|
||||
<Cascader placeholder="请选择" options={reviewArea} />)}
|
||||
</td>
|
||||
<td>
|
||||
{helper('评审领域3',
|
||||
'companyName',
|
||||
[{ required: true, message: "请输入公司名称" }, { max: 100, message: '不能超过100字符' }],
|
||||
<Cascader placeholder="请选择" options={reviewArea} />)}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
{helper('毕业院校',
|
||||
'companyName',
|
||||
[{ required: true, message: "请输入公司名称" }, { max: 100, message: '不能超过100字符' }],
|
||||
<Input
|
||||
placeholder="请输入您的毕业院校"
|
||||
/>)}
|
||||
</td>
|
||||
<td>
|
||||
{helper('院校专业',
|
||||
'companyName',
|
||||
[{ required: true, message: "请输入公司名称" }, { max: 100, message: '不能超过100字符' }],
|
||||
<Input
|
||||
placeholder="请输入您的专业"
|
||||
/>)}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
{helper('身份证号',
|
||||
'companyName',
|
||||
[{ required: true, message: "请输入公司名称" }, { max: 100, message: '不能超过100字符' }],
|
||||
<Input
|
||||
placeholder="请输入您的身份证号码"
|
||||
/>)}
|
||||
</td>
|
||||
<td>
|
||||
{helper('邮箱地址',
|
||||
'companyName',
|
||||
[{ required: true, message: "请输入公司名称" }, { max: 100, message: '不能超过100字符' }],
|
||||
<Input
|
||||
placeholder="请输入您的常用邮箱地址"
|
||||
/>)}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
{helper('开户银行',
|
||||
'companyName',
|
||||
[{ required: true, message: "请输入公司名称" }, { max: 100, message: '不能超过100字符' }],
|
||||
<Input
|
||||
placeholder="请输入您的开户银行"
|
||||
/>)}
|
||||
</td>
|
||||
<td>
|
||||
{helper('银行账号',
|
||||
'companyName',
|
||||
[{ required: true, message: "请输入公司名称" }, { max: 100, message: '不能超过100字符' }],
|
||||
<Input
|
||||
placeholder="请输入您的银行卡号"
|
||||
/>)}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span>个人简介</span>
|
||||
<button>上传个人简介</button>
|
||||
</td>
|
||||
<td>
|
||||
<span>职称证明</span>
|
||||
<button>上传职称证明</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span>学术成果</span>
|
||||
<button>上传学术成果</button>
|
||||
</td>
|
||||
<td>
|
||||
<span>荣誉称号</span>
|
||||
<button>上传荣誉称号</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div className='buts'>
|
||||
<button className="but41_fill mr20">提交资料</button>
|
||||
<button className="but41_border mr20">保存资料</button>
|
||||
<button className="butE3_border">取消</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
|
@ -0,0 +1,57 @@
|
|||
.centerbox.detail{
|
||||
font-size: 20px;
|
||||
border: 1px solid;
|
||||
& .navigation{
|
||||
font-size: 0.6em;
|
||||
margin: -35px 0 15px;
|
||||
}
|
||||
& .center_flex{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
& .register_left{
|
||||
height: 10em;
|
||||
font-size: 0.7em;
|
||||
background-color: white;
|
||||
padding: 0.4vw;
|
||||
}
|
||||
& .register_right{
|
||||
background-color: white;
|
||||
&>p{
|
||||
height: 5.1vh;
|
||||
line-height: 5.1vh;
|
||||
border-bottom: 1px solid #EEEEEE;
|
||||
padding-left: 2em;
|
||||
color: #181818;
|
||||
font-size: 0.8em;
|
||||
font-weight: bold;
|
||||
}
|
||||
&>div{
|
||||
padding: 2em;
|
||||
&>table{
|
||||
& .ant-form-item-required::before{
|
||||
position: relative;
|
||||
top: -1px;
|
||||
content: url('./image/required.svg');
|
||||
}
|
||||
& .ant-input{
|
||||
width: 30.1em;
|
||||
&:focus, &:hover{
|
||||
border: 1px solid #4154F1 !important;
|
||||
}
|
||||
}
|
||||
& tr td:first-child .ant-row.ant-form-item{
|
||||
margin-right: 9em;
|
||||
}
|
||||
& .ant-input, .ant-input .ant-input-suffix {
|
||||
background-color: #FFFFFF !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
& .buts{
|
||||
font-size: 0.7em;
|
||||
padding: 1.5em 2em;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 |
|
@ -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">
|
||||
<span>首页</span> > <span>专家评审系统</span>
|
||||
</div>
|
||||
<div className="notExpert center_flex">
|
||||
<img src={system} />
|
||||
<p className="ne_title">红山开源平台专家评审系统</p>
|
||||
<p className="ne_tips">您尚未被入选本平台专家团队,可提交专家资料进行注册申请加入专家团队</p>
|
||||
<p className="ne_bar"></p>
|
||||
<Link to='/expert/register'><button className="but41_fill">专家注册</button></Link>
|
||||
</div>
|
||||
</div>)
|
||||
}
|
||||
export default Review;
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
// 专家注册页面需要的静态数据
|
||||
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: "体育活动" }
|
||||
];
|
|
@ -0,0 +1,231 @@
|
|||
// 本模块公共样式
|
||||
.color-grey3 {
|
||||
color: #333;
|
||||
}
|
||||
.color-grey9 {
|
||||
color: #999;
|
||||
}
|
||||
.color-orange {
|
||||
color: #ff6800;
|
||||
}
|
||||
.color-deep-blue {
|
||||
color: #1b8fff;
|
||||
}
|
||||
.centerbox {
|
||||
width: 1200px;
|
||||
margin: 40px auto;
|
||||
position: relative;
|
||||
}
|
||||
.head-navigation {
|
||||
position: absolute;
|
||||
top: -2.3em;
|
||||
// width: 80vw;
|
||||
// max-width: 1280px;
|
||||
// margin: 40px auto;
|
||||
// position: relative;
|
||||
span {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
&:hover {
|
||||
color: #409eff;
|
||||
}
|
||||
}
|
||||
}
|
||||
.center-content {
|
||||
background: #fff;
|
||||
border: 1px solid #dedede;
|
||||
box-shadow: #eee 0px 1px 1px 3px;
|
||||
}
|
||||
.centerScreen {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
height: 46px;
|
||||
background-color: #fff;
|
||||
border-bottom: 1px solid #dedede;
|
||||
}
|
||||
|
||||
// 内容标题左侧样式
|
||||
.center-left-but {
|
||||
display: flex;
|
||||
justify-content: start;
|
||||
align-items: center;
|
||||
margin-left: 20px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.center-left-butD {
|
||||
height: 24px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: 24px;
|
||||
color: #333;
|
||||
padding: 0 10px;
|
||||
background-color: #fff;
|
||||
border: 1px solid #dedede;
|
||||
}
|
||||
.center-left-butD:hover {
|
||||
background-color: #fff;
|
||||
color: #409eff;
|
||||
cursor: pointer;
|
||||
}
|
||||
.center-left-butDACT {
|
||||
background-color: #409eff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
|
||||
// 内容标题左侧样式
|
||||
.center-left-but {
|
||||
display: flex;
|
||||
justify-content: start;
|
||||
align-items: center;
|
||||
margin-left: 20px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
// 内容标题右侧样式
|
||||
.center-right-but {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.center-right-but > span {
|
||||
margin: 0 10px;
|
||||
font-size: 16px;
|
||||
color: #0089ff;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
// 文件预览modal样式
|
||||
.file-modal {
|
||||
width: 800px !important;
|
||||
.ant-modal-body {
|
||||
padding-top: 40px;
|
||||
.pdf-box {
|
||||
height: 70vh;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
}
|
||||
.ant-modal-close {
|
||||
top: 0 !important;
|
||||
}
|
||||
.show-img {
|
||||
width: 100%;
|
||||
}
|
||||
.react-pdf__Page__canvas,
|
||||
.react-pdf__Page__textContent {
|
||||
margin: 0 auto;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.edit-input {
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
.link {
|
||||
color: #0089ff;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
color: #509eff;
|
||||
}
|
||||
}
|
||||
|
||||
.color-grey-a {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.greater {
|
||||
position: relative;
|
||||
top: -1px;
|
||||
}
|
||||
|
||||
.none_panels {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-flow: column nowrap;
|
||||
height: 40vh;
|
||||
}
|
||||
|
||||
.newFooter .footerInfos > ul {
|
||||
padding: 0 40px;
|
||||
box-sizing: border-box;
|
||||
max-width: 25%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.ant-modal-footer {
|
||||
text-align: center;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
// 头像
|
||||
.head-log-big {
|
||||
width: 4rem;
|
||||
height: 4rem;
|
||||
margin-right: 0.5rem;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.head-log-middle {
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
margin-right: 0.35rem;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.head-log-small {
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
margin-right: 0.35rem;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
// 富文本样式
|
||||
.w-e-text table td,
|
||||
.w-e-text table th {
|
||||
height: 30px;
|
||||
}
|
||||
.editor-w-text {
|
||||
table td,
|
||||
table th {
|
||||
border-bottom: 1px solid #ccc;
|
||||
border-right: 1px solid #ccc;
|
||||
padding: 3px 5px;
|
||||
height: 30px;
|
||||
min-height: 30px;
|
||||
}
|
||||
table th {
|
||||
border-bottom: 2px solid #ccc;
|
||||
text-align: center;
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
table {
|
||||
border-top: 1px solid #ccc;
|
||||
border-left: 1px solid #ccc;
|
||||
}
|
||||
blockquote {
|
||||
display: block;
|
||||
border-left: 8px solid #d0e5f2;
|
||||
padding: 5px 10px;
|
||||
margin: 10px 0;
|
||||
line-height: 1.4;
|
||||
font-size: 100%;
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
a {
|
||||
color: #409eff;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.text-center{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1200px) {
|
||||
.centerbox {
|
||||
width: 98%;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
import { notification} from 'antd';
|
||||
import axios from 'axios';
|
||||
import cookie from 'react-cookies';
|
||||
|
||||
export const TokenKey = 'autologin_forge_military';
|
||||
export default function javaFetch(actionUrl){
|
||||
if (window.location.href.indexOf('localhost') < 0) {
|
||||
axios.defaults.withCredentials = true;
|
||||
}
|
||||
|
||||
// 创建axios实例
|
||||
const service = axios.create({
|
||||
baseURL: actionUrl,
|
||||
timeout: 1800000, // 请求超时时间
|
||||
});
|
||||
|
||||
// request拦截器
|
||||
service.interceptors.request.use(config => {
|
||||
if (cookie.load(TokenKey)) {
|
||||
console.log(cookie.load(TokenKey));
|
||||
config.headers['Authorization'] = cookie.load(TokenKey); // 让每个请求携带自定义token 请根据实际情况自行修改
|
||||
}
|
||||
if (window.location.port === "3007") {
|
||||
// 模拟token为登录用户
|
||||
const osredmToken = sessionStorage.osredmToken;
|
||||
if (config.url.indexOf('?') === -1) {
|
||||
config.url = `${config.url}?token=${osredmToken}`;
|
||||
} else {
|
||||
config.url = `${config.url}&token=${osredmToken}`;
|
||||
}
|
||||
}
|
||||
return config;
|
||||
}, error => {
|
||||
// Do something with request error
|
||||
console.log(error); // for debug
|
||||
Promise.reject(error);
|
||||
});
|
||||
// respone拦截器
|
||||
service.interceptors.response.use(
|
||||
response => {
|
||||
const res = response;
|
||||
if (res.status === 400) {
|
||||
notification.open({
|
||||
message: "提示",
|
||||
description: res.data.message || '验证失败',
|
||||
});
|
||||
return Promise.reject('error');
|
||||
}
|
||||
if (res.status === 401) {
|
||||
notification.open({
|
||||
message: "提示",
|
||||
description: res.data.message || '未授权,请登录!',
|
||||
});
|
||||
return Promise.reject('error');
|
||||
}
|
||||
if (res.status === 403) {
|
||||
notification.open({
|
||||
message: "提示",
|
||||
description: res.data.message || '无权限',
|
||||
});
|
||||
return Promise.reject('error');
|
||||
}
|
||||
if (res.status === 40001) {
|
||||
notification.open({
|
||||
message: "提示",
|
||||
description: '账户或密码错误!',
|
||||
});
|
||||
return Promise.reject('error');
|
||||
}
|
||||
if (response.status !== 200 && res.status !== 200) {
|
||||
notification.open({
|
||||
message: "提示",
|
||||
description: res.message,
|
||||
});
|
||||
} else {
|
||||
return response.data;
|
||||
}
|
||||
},
|
||||
error => {
|
||||
console.log(error);
|
||||
let res = error.response||{};
|
||||
if (res.status === 400) {
|
||||
notification.open({
|
||||
message: "提示",
|
||||
description: res.data.message || '操作失败',
|
||||
});
|
||||
return Promise.reject('error');
|
||||
}
|
||||
if (res.status === 401) {
|
||||
notification.open({
|
||||
message: "提示",
|
||||
description: res.data.message || '登录信息已过期',
|
||||
});
|
||||
return Promise.reject('error');
|
||||
}
|
||||
if (res.status === 403) {
|
||||
notification.open({
|
||||
message: "提示",
|
||||
description: res.data.message || '无权限!',
|
||||
});
|
||||
window.location.href="/403";
|
||||
return Promise.reject('error');
|
||||
}
|
||||
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
return service;
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
import React, { Component } from "react";
|
||||
|
||||
import { Route, Switch } from "react-router-dom";
|
||||
import { withRouter } from "react-router";
|
||||
import { SnackbarHOC } from "educoder";
|
||||
import { CNotificationHOC } from "../modules/courses/common/CNotificationHOC";
|
||||
import { TPMIndexHOC } from "../modules/tpm/TPMIndexHOC";
|
||||
import Loadable from "react-loadable";
|
||||
import Loading from "../Loading";
|
||||
import { ImageLayerOfCommentHOC } from "../modules/page/layers/ImageLayerOfCommentHOC";
|
||||
import './index.scss';
|
||||
|
||||
const NoticeList = Loadable({
|
||||
loader: () => import("./notice/noticeList"),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
const NoticeDetail = Loadable({
|
||||
loader: () => import("./notice/noticeDetail"),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
|
||||
class Index extends Component {
|
||||
render() {
|
||||
return (
|
||||
<div className="newMain clearfix">
|
||||
<Switch {...this.props}>
|
||||
|
||||
<Route
|
||||
path="/notice/noticeDetail/:noticeId"
|
||||
render={(props) => (
|
||||
<NoticeDetail {...this.props} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
|
||||
<Route
|
||||
path="/notice"
|
||||
render={(props) => (
|
||||
<NoticeList {...this.props} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
</Switch>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
export default withRouter(
|
||||
ImageLayerOfCommentHOC({
|
||||
imgSelector: ".imageLayerParent img, .imageLayerParent .imageTarget",
|
||||
parentSelector: ".newMain",
|
||||
})(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(Index))))
|
||||
);
|
|
@ -0,0 +1,49 @@
|
|||
import fetch from './fetch';
|
||||
import { notification } from 'antd';
|
||||
|
||||
|
||||
// 公告列表查询
|
||||
export async function getNoticeList(params) {
|
||||
let res = await fetch({
|
||||
url: '/api/announcements/',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
if (res.message === 'success') {
|
||||
return res.data;
|
||||
} else {
|
||||
notification.open({
|
||||
message: "提示",
|
||||
description: res.message || '请求错误',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 公告详情查询
|
||||
export async function getNoticeDetail(id) {
|
||||
let res = await fetch({
|
||||
url: '/api/announcements/' + id,
|
||||
method: 'get',
|
||||
params:{flag:1}
|
||||
});
|
||||
if (res.data) {
|
||||
return res.data;
|
||||
} else {
|
||||
notification.open({
|
||||
message: "提示",
|
||||
description: res.message || '请求错误',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//新增加密公告申请人
|
||||
export function addReader(data) {
|
||||
return fetch({
|
||||
url: '/api/request_contact_reader_info/',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
import React from 'react';
|
||||
import { NewSvg } from '../../svg';
|
||||
import './index.scss';
|
||||
export default (props) => {
|
||||
const { list, itemClick, } = props;
|
||||
|
||||
return (
|
||||
list.map(item => {
|
||||
return (
|
||||
<div className="list-box" key={item.id}>
|
||||
<div className="list-title" onClick={() => { itemClick(item.id) }}>
|
||||
{item.achievementName || item.title} {item.new && <NewSvg color="#ffb300"/>}
|
||||
</div>
|
||||
<div className="list-other">
|
||||
{item.publisher && <p>发布单位:{item.publisher}</p>}
|
||||
<p>发布时间:{(item.publishDate && item.publishDate.split(' ')[0]) || (item.createTime && item.createTime.split(' ')[0])}</p>
|
||||
<p><i className="iconfont icon-dianjiliang mr5 font-12" />{item.visits || 0}</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
)
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
.list-box {
|
||||
position: relative;
|
||||
padding: 17px 20px;
|
||||
background: #fff;
|
||||
border-bottom: 1px dashed #dedede;
|
||||
}
|
||||
.list-title {
|
||||
font-size: 1rem;
|
||||
color: #000;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
svg {
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
}
|
||||
.list-title:hover {
|
||||
color: #409eff;
|
||||
}
|
||||
.list-title span {
|
||||
padding: 3px 5px;
|
||||
margin-left: 0.5em;
|
||||
background: #f8c753;
|
||||
font-size: 13px;
|
||||
color: #fff;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.list-other {
|
||||
margin-top: 0.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
& > p {
|
||||
display: inline-block;
|
||||
font-size: 0.875rem;
|
||||
color: #666;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
p:first-child{
|
||||
width: 50%;
|
||||
}
|
||||
p:nth-child(2){
|
||||
width: 40%;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
import javaFetch from '../javaFetch';
|
||||
|
||||
|
||||
let settings=JSON.parse(localStorage.chromesetting);
|
||||
let actionUrl = settings.api_urls? settings.api_urls.notice :'https://info.osredm.com';
|
||||
|
||||
const service = javaFetch(actionUrl);
|
||||
export const httpUrl = actionUrl;
|
||||
export default service;
|
After Width: | Height: | Size: 168 KiB |
|
@ -0,0 +1,172 @@
|
|||
import React, { useEffect, useState, useCallback } from 'react';
|
||||
import { Button, Icon, Form, Modal, Input } from 'antd';
|
||||
import { Link } from "react-router-dom";
|
||||
import { getNoticeDetail, addReader } from '../api';
|
||||
import { noticeType } from '../static';
|
||||
import './index.scss';
|
||||
|
||||
const noticeTypeArr = [];
|
||||
for (const item of noticeType) {
|
||||
noticeTypeArr[item.code] = item.name;
|
||||
}
|
||||
|
||||
export default Form.create()(({ match, history, showNotification, form }) => {
|
||||
const { getFieldDecorator, validateFields, setFieldsValue } = form;
|
||||
|
||||
const [reload, setReload] = useState(0);
|
||||
const [noticeData, setNoticeData] = useState({});
|
||||
const [visible, setVisible] = useState(false);
|
||||
|
||||
const [readerName,setReaderName]=useState('');
|
||||
|
||||
const id = match.params.noticeId;
|
||||
|
||||
useEffect(() => {
|
||||
id && getNoticeDetail(id).then(data => {
|
||||
if (data) {
|
||||
data.publishDate = data.publishDate.split(' ')[0];
|
||||
data.createdAt = data.createdAt.split(' ')[0];
|
||||
data.closingDate = data.closingDate.split(' ')[0];
|
||||
}
|
||||
setNoticeData(data || {});
|
||||
})
|
||||
}, [id, reload]);
|
||||
|
||||
// form表单公共处理函数
|
||||
const helper = useCallback(
|
||||
(label, name, rules, widget) => (
|
||||
<Form.Item label={label}>
|
||||
{getFieldDecorator(name, { rules, validateFirst: true ,getValueFromEvent: e=>e.target.value.replace(/(^\s*)|(\s*$)/g, "") })(widget)}
|
||||
</Form.Item>
|
||||
),
|
||||
[]
|
||||
);
|
||||
|
||||
function pushInfo() {
|
||||
validateFields((err, values) => {
|
||||
if (!err) {
|
||||
addReader({
|
||||
...values,
|
||||
annId: noticeData.id,
|
||||
}).then(res => {
|
||||
if (res.message === "success") {
|
||||
setVisible(false);
|
||||
setReload(Math.random());
|
||||
} else {
|
||||
res && Modal.error({ content: res.message });
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<div className="centerbox notice-detail">
|
||||
<div className="head-navigation">
|
||||
<Link to="/">首页<span className="greater"> > </span></Link>
|
||||
<Link to="/notice">公告<span className="greater"> > </span></Link>
|
||||
<span>公告详情</span>
|
||||
</div>
|
||||
<div className="center-content">
|
||||
{/* <div className="notice-center-content"> */}
|
||||
<div className="notice-title">
|
||||
{noticeData.title}
|
||||
</div>
|
||||
<div className="notice-detail-content">
|
||||
<div className="center-author">
|
||||
<p key={0}>公告类型:{noticeTypeArr[noticeData.type]}</p>
|
||||
{noticeData.publisher && <p key={1}>发布单位:{noticeData.publisher}</p>}
|
||||
<p key={2}>发布时间:{noticeData.publishDate || noticeData.createdAt}</p>
|
||||
<p key={3}>截止时间:{noticeData.closingDate}</p>
|
||||
<p key={4}>浏览:{noticeData.visits || 0}</p>
|
||||
</div>
|
||||
|
||||
<div className="content-text">
|
||||
<div className="notice-content-title"><Icon type="caret-right" />公告主要内容</div>
|
||||
<div className="editor-w-text" dangerouslySetInnerHTML={{ __html: noticeData.text }}>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{
|
||||
noticeData.contactInfo ? <React.Fragment>
|
||||
<div className="notice-content-title"><Icon type="caret-right" />联系方式</div>
|
||||
<div className="content-secret" dangerouslySetInnerHTML={{ __html: noticeData.contactInfo && noticeData.contactInfo.replace(/\n/g, '</br>') }}>
|
||||
</div>
|
||||
{
|
||||
noticeData.blockedView && <Button type="primary" onClick={() => { setVisible(true) }}>申请查看加密内容</Button>
|
||||
}
|
||||
</React.Fragment> : ''
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
noticeData.fileDownloadPath &&
|
||||
<React.Fragment>
|
||||
<div className="notice-content-title"><Icon type="caret-right" />公告附件</div>
|
||||
<p className="notice-content-download" >
|
||||
<span onClick={() => { window.open(noticeData.fileDownloadPath) }}>
|
||||
<i className="iconfont icon-fujian color-green font-14 mr3"></i>{noticeData.fileName}
|
||||
</span>
|
||||
<span className="link" onClick={() => { window.open(noticeData.fileDownloadPath) }}>下载</span>
|
||||
</p>
|
||||
</React.Fragment>
|
||||
}
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Modal
|
||||
title="提交信息"
|
||||
visible={visible}
|
||||
onOk={pushInfo}
|
||||
onCancel={() => { setVisible(false) }}
|
||||
className="form-edit-modal"
|
||||
>
|
||||
|
||||
{
|
||||
helper('用户姓名',
|
||||
'readerName',
|
||||
[{ required: true, message: "请输入用户姓名" }, { max: 50, message: '不能超过50字符' }],
|
||||
<Input
|
||||
placeholder="请输入用户姓名"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
helper('公司名称',
|
||||
'companyName',
|
||||
[{ required: true, message: "请输入公司名称" }, { max: 100, message: '不能超过100字符' }],
|
||||
<Input
|
||||
placeholder="请输入公司名称"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
helper('联系方式',
|
||||
'contactInfo',
|
||||
[{ required: true, message: "请输入联系方式" },
|
||||
{ max: 100, message: '不能超过100字符' },
|
||||
{ validator: (rule,val,callback) =>{
|
||||
const pattern = /^((\+)?86|((\+)?86)?)0?1[3458]\d{9}$/;
|
||||
if(pattern.test(val)){
|
||||
callback();
|
||||
}else {
|
||||
callback('请输入正确的手机号码!');
|
||||
}
|
||||
}}],
|
||||
<Input
|
||||
placeholder="请输入联系方式"
|
||||
/>
|
||||
)
|
||||
}
|
||||
</Modal>
|
||||
|
||||
</div>
|
||||
|
||||
)
|
||||
}
|
||||
)
|
|
@ -0,0 +1,102 @@
|
|||
.centerbox {
|
||||
position: relative;
|
||||
}
|
||||
.notice-detail {
|
||||
margin-top: 3.5rem;
|
||||
.head-navigation {
|
||||
top: -2.5rem;
|
||||
}
|
||||
.center-content {
|
||||
overflow: auto;
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.notice-detail-content {
|
||||
padding: 2rem 2.5rem 3rem;
|
||||
|
||||
.anticon-caret-right {
|
||||
color: #1890ff;
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.notice-title {
|
||||
margin: 3rem auto 0;
|
||||
text-align: center;
|
||||
font-size: 1.375rem;
|
||||
font-weight: bold;
|
||||
line-height: 1.375rem;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
// 内容详情
|
||||
.item-content {
|
||||
padding: 10px 10px 0 30px;
|
||||
}
|
||||
.content-notice {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.center-author {
|
||||
display: flex;
|
||||
flex-flow:row wrap-reverse;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
padding: .5rem;
|
||||
background: #f9f9f9;
|
||||
color: #333;
|
||||
p {
|
||||
padding: 0 .5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.content-text {
|
||||
margin: 1.25rem 0;
|
||||
min-height: 30vh;
|
||||
}
|
||||
|
||||
.content-secret{
|
||||
min-height: 2em;
|
||||
}
|
||||
|
||||
.notice-content-title {
|
||||
margin: 0.5rem 0;
|
||||
font-size: 1rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.notice-content-download {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 2rem !important;
|
||||
padding: 0 1rem;
|
||||
background: #f9f9f9;
|
||||
span:hover{
|
||||
cursor: pointer;
|
||||
color: #1890ff;
|
||||
}
|
||||
}
|
||||
|
||||
.form-edit-modal {
|
||||
.ant-form-item{
|
||||
display: flex;
|
||||
}
|
||||
.ant-form-item-label{
|
||||
min-width: 5rem;
|
||||
}
|
||||
.ant-form-item-control-wrapper{
|
||||
width: 75%;
|
||||
display: inline-block;
|
||||
}
|
||||
.ant-input-number{
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.ant-modal-footer{
|
||||
border-top: 0;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,267 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { Pagination, Icon, Input, Affix, } from 'antd';
|
||||
import ItemList from '../components/itemList';
|
||||
import Nodata from '../../../forge/Nodata';
|
||||
import Loading from "../../../Loading";
|
||||
import noticePng from '../image/banner.png';
|
||||
import { getNoticeList } from '../api';
|
||||
|
||||
import './index.scss';
|
||||
const Search = Input.Search;
|
||||
|
||||
export default (props) => {
|
||||
|
||||
const [tab, setTab] = useState('0');
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const [title, setTitle] = useState(undefined);
|
||||
const [orderBy, setOrderBy] = useState('publishDateDesc');
|
||||
|
||||
const [curPage, setCurPage] = useState(1);
|
||||
const [total, setTotal] = useState(0);
|
||||
const [noticeList, setNoticeList] = useState([]);
|
||||
|
||||
const [callList, setCallList] = useState([]);
|
||||
const [changeList, setChangeList] = useState([]);
|
||||
const [checkList, setCheckList] = useState([]);
|
||||
const [abandonList, setAbandonList] = useState([]);
|
||||
const [technologyList, setTechnologyList] = useState([]);
|
||||
const [dealList, setDealList] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true);
|
||||
if (tab === '0' || tab === '7') {
|
||||
const params = {
|
||||
orderBy,
|
||||
curPage: 1,
|
||||
isChecked: 1,
|
||||
pageSize: 5,
|
||||
status: 1,
|
||||
type: 1,
|
||||
title,
|
||||
flag: 1, //后台管理查询:2;前台展示:1
|
||||
};
|
||||
getNoticeList(params).then(data => {
|
||||
setChangeList(data.rows);
|
||||
});
|
||||
getNoticeList({ ...params, type: 4 }).then(data => {
|
||||
setCallList(data.rows);
|
||||
setLoading(false);
|
||||
});
|
||||
getNoticeList({ ...params, type: 2 }).then(data => {
|
||||
setCheckList(data.rows);
|
||||
});
|
||||
getNoticeList({ ...params, type: 3 }).then(data => {
|
||||
setAbandonList(data.rows);
|
||||
setLoading(false);
|
||||
});
|
||||
getNoticeList({ ...params, type: 5 }).then(data => {
|
||||
setTechnologyList(data.rows);
|
||||
});
|
||||
getNoticeList({ ...params, type: 6 }).then(data => {
|
||||
setDealList(data.rows);
|
||||
setLoading(false);
|
||||
});
|
||||
} else {
|
||||
const params = {
|
||||
orderBy,
|
||||
curPage,
|
||||
isChecked: 1,
|
||||
pageSize: 10,
|
||||
status: 1,
|
||||
title,
|
||||
type: tab,
|
||||
flag: 1, //后台管理查询:2;前台展示:1
|
||||
};
|
||||
getNoticeList(params).then(data => {
|
||||
setNoticeList(data.rows);
|
||||
setTotal(data.total);
|
||||
setLoading(false);
|
||||
})
|
||||
}
|
||||
}, [tab, title, orderBy, curPage]);
|
||||
|
||||
function changeSort(sortType) {
|
||||
setOrderBy(sortType);
|
||||
setCurPage(1);
|
||||
}
|
||||
|
||||
function noticeClick(id) {
|
||||
props.history.push(`/notice/noticeDetail/${id}`);
|
||||
}
|
||||
|
||||
function sortNav() {
|
||||
return <div className="notice-sort-nav">
|
||||
<Search
|
||||
size="large"
|
||||
maxLength={20}
|
||||
style={{ width: "56%" }}
|
||||
placeholder="输入标题关键字,不能超过20字符"
|
||||
enterButton={<span><Icon type="search" className="mr5" /> 搜索</span>}
|
||||
onSearch={(value) => setTitle(value)} />
|
||||
<div className="center-right-but">
|
||||
<div className={classNames({ sortLink: true, active: orderBy === 'publishDateDesc' })} onClick={() => { changeSort('publishDateDesc') }}>时间降序<Icon type="arrow-down" /></div>
|
||||
<span className="piece">|</span>
|
||||
<div className={classNames({ sortLink: true, active: orderBy === 'publishDateAsc' })} onClick={() => { changeSort('publishDateAsc') }}>时间升序<Icon type="arrow-up" /></div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
function handleClick(e) {
|
||||
setTab(e.key);
|
||||
setCurPage(1);
|
||||
setTitle('');
|
||||
setOrderBy('publishDateDesc');
|
||||
}
|
||||
|
||||
function click(e){
|
||||
console.log("aa");
|
||||
console.log(e);
|
||||
setTab(e);
|
||||
setCurPage(1);
|
||||
setTitle('');
|
||||
setOrderBy('publishDateDesc');
|
||||
}
|
||||
|
||||
function cont(param, titleStr, key, svgStr) {
|
||||
return <React.Fragment>
|
||||
<div className="item-head-title">
|
||||
<div className="item-head-title-content">
|
||||
<i className={svgStr}></i>
|
||||
<span>{titleStr}</span>
|
||||
</div>
|
||||
{param.length === 5 && <span className="link" onClick={() => { handleClick({ key: key }) }}>查看更多 <Icon type="arrow-right" /></span>}
|
||||
</div>
|
||||
{param.length > 0 ? <ItemList
|
||||
list={param}
|
||||
itemClick={noticeClick}
|
||||
/> : <Nodata _html="暂无数据" />}
|
||||
{/* <ItemList
|
||||
list={param}
|
||||
itemClick={noticeClick}
|
||||
/> */}
|
||||
</React.Fragment>
|
||||
}
|
||||
|
||||
function content() {
|
||||
if (tab === '0') {
|
||||
if(callList.length === 0 && changeList.length === 0 && checkList.length === 0 && abandonList.length === 0){
|
||||
return <React.Fragment><Nodata _html="暂无数据" /></React.Fragment>
|
||||
}else{
|
||||
return <React.Fragment>
|
||||
{cont(callList, "招标公告", '4', "iconfont icon-zhaobiaogonggao")}
|
||||
{cont(changeList, "更正公告", '1', "iconfont icon-gengzhenggonggao")}
|
||||
{cont(checkList, "中标公告", '2', "iconfont icon-zhongbiaogonggao")}
|
||||
{cont(abandonList, "废标公告", '3', "iconfont icon-feibiaogonggao")}
|
||||
</React.Fragment>
|
||||
}
|
||||
} else if (tab === '7') {
|
||||
{/* {technologyList.length <= 0 && dealList.length <= 0 ? <Nodata _html="暂无数据" /> : ""} */}
|
||||
{/* {technologyList.length > 0 && cont(technologyList, "技术资产", '5',"iconfont icon-jishuzichan")} */}
|
||||
if(technologyList.length === 0 && dealList.length === 0){
|
||||
return <React.Fragment><Nodata _html="暂无数据" /></React.Fragment>
|
||||
}else{
|
||||
return <React.Fragment>
|
||||
{cont(technologyList, "技术资产", '5', "iconfont icon-jishuzichan")}
|
||||
{cont(dealList, "成交公告", '6', "iconfont icon-chengjiaogonggao")}
|
||||
</React.Fragment>
|
||||
}
|
||||
} else if (tab === '8') {
|
||||
return <div></div>
|
||||
} else {
|
||||
let titleStr;
|
||||
let svgStr;
|
||||
switch (tab) {
|
||||
case '1':
|
||||
titleStr = "更正公告";
|
||||
svgStr = "iconfont icon-gengzhenggonggao"
|
||||
break;
|
||||
case '2':
|
||||
titleStr = "中标公告";
|
||||
svgStr = "iconfont icon-zhongbiaogonggao"
|
||||
break;
|
||||
case '3':
|
||||
titleStr = "废标公告";
|
||||
svgStr = "iconfont icon-feibiaogonggao"
|
||||
break;
|
||||
case '4':
|
||||
titleStr = "招标公告";
|
||||
svgStr = "iconfont icon-zhaobiaogonggao"
|
||||
break;
|
||||
case '5':
|
||||
titleStr = "技术资产";
|
||||
svgStr = "iconfont icon-jishuzichan"
|
||||
break;
|
||||
default:
|
||||
titleStr = "成交公告";
|
||||
svgStr = "iconfont icon-chengjiaogonggao"
|
||||
}
|
||||
return <React.Fragment>
|
||||
<div className="item-head-title">
|
||||
<div className="item-head-title-content">
|
||||
<i className={svgStr}></i>
|
||||
<span>{titleStr}</span>
|
||||
</div>
|
||||
</div>
|
||||
<ItemList
|
||||
list={noticeList}
|
||||
itemClick={noticeClick}
|
||||
/>
|
||||
{/* {noticeList.length === 10 && <div className="edu-txt-center mt30 mb30">
|
||||
<Pagination
|
||||
showQuickJumper
|
||||
onChange={(page) => { setCurPage(page) }}
|
||||
current={curPage}
|
||||
total={total}
|
||||
showTotal={total => `共 ${total} 条`}
|
||||
/>
|
||||
</div>} */}
|
||||
{total > 0 ? total> 10 ? <div className="edu-txt-center mt30 mb30">
|
||||
<Pagination
|
||||
showQuickJumper
|
||||
onChange={(page) => { setCurPage(page) }}
|
||||
current={curPage}
|
||||
total={total}
|
||||
showTotal={total => `共 ${total} 条`}
|
||||
/>
|
||||
</div> : "" : <Nodata _html="暂无数据" />}
|
||||
</React.Fragment>
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<img alt="图片加载失败" src={noticePng} width="100%"></img>
|
||||
<div className="centerbox notice-list clearfix">
|
||||
{/* <div className="head-navigation">
|
||||
<Link to="/">首页<span className="greater"> > </span></Link>
|
||||
<span>公告</span>
|
||||
</div> */}
|
||||
<div className="body">
|
||||
<Affix className="affix-list-left" offsetTop={90}>
|
||||
{/* <div className="affix-list-content"> */}
|
||||
<div className="navigationMenu">
|
||||
<ul className="menu-ul">
|
||||
<li className="MenuTitle" onClick={()=>click('0')}><span><i className="iconfont icon-xiangmugonggao"></i>项目公告</span></li>
|
||||
<li className={tab === '4' ? "active" : ""} onClick={()=>click('4')}><span>招标公告</span></li>
|
||||
<li className={tab === '1' ? "active" : ""} onClick={()=>click('1')}><span>更正公告</span></li>
|
||||
<li className={tab === '2' ? "active" : ""} onClick={()=>click('2')}><span>中标公告</span></li>
|
||||
<li className={tab === '3' ? "active" : ""} onClick={()=>click('3')}><span>废标公告</span></li>
|
||||
</ul>
|
||||
<ul className="menu-ul">
|
||||
<li className="MenuTitle" onClick={()=>click('7')}><span><i className="iconfont icon-chengguo"></i>成果转化</span></li>
|
||||
<li className={tab === '5' ? "active" : ""} onClick={()=>click('5')}><span>技术资产</span></li>
|
||||
<li className={tab === '6' ? "active" : ""} onClick={()=>click('6')}><span>成交公告</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</Affix>
|
||||
<div className="notice-center-content">
|
||||
{sortNav()}
|
||||
{loading ? <Loading /> : content()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,188 @@
|
|||
.notice-list{
|
||||
.ant-tabs {
|
||||
.ant-tabs-left-bar{
|
||||
border: 1px solid #E5E5E5;
|
||||
.ant-tabs-nav-container{
|
||||
margin-right: 0;
|
||||
}
|
||||
.ant-tabs-nav-wrap{
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
svg{
|
||||
margin-right:.75em;
|
||||
}
|
||||
}
|
||||
.ant-tabs-tab{
|
||||
display: flex;
|
||||
justify-content: start;
|
||||
align-items: center;
|
||||
margin-bottom: 0.5rem;
|
||||
width: 13.5rem;
|
||||
height: 2.8125rem;
|
||||
background: #fff;
|
||||
font-size: 1.125rem;
|
||||
|
||||
}
|
||||
.ant-tabs-left-content{
|
||||
border: 0;
|
||||
}
|
||||
.ant-tabs-tab-active{
|
||||
background: #1890FF;
|
||||
color: #fff;
|
||||
}
|
||||
.ant-tabs-ink-bar{
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.notice-sort-nav{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: .3rem 2rem 1.5rem;
|
||||
margin: 0px -1.25rem;
|
||||
// border: 1px solid;
|
||||
border-bottom: 1px solid #E0E0E0;
|
||||
// background: #f5f5f5;
|
||||
}
|
||||
|
||||
.notice-center-content{
|
||||
padding:1.25rem;
|
||||
background: #fff;
|
||||
flex: auto;
|
||||
}
|
||||
|
||||
.item-head-title{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 1.25rem 0 .6rem 0;
|
||||
.item-head-title-content{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 1rem;
|
||||
span{
|
||||
font-weight: bold;
|
||||
}
|
||||
i{
|
||||
margin-right: .25em;
|
||||
color: #1890FF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ant-input-group-addon{
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
.item-head-title{
|
||||
border-bottom: 1px solid #E5E5E5;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.center-right-but{
|
||||
caret-color: rgba(0, 0, 0, 0);
|
||||
.piece{
|
||||
margin:0 .8rem;
|
||||
color: #aaa;
|
||||
}
|
||||
.sortLink{
|
||||
color: #333;
|
||||
cursor: pointer;
|
||||
&:hover{
|
||||
color: #1890FF;
|
||||
}
|
||||
&.active{
|
||||
color: #1890FF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.body{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: -20px;
|
||||
|
||||
.navigationMenu{
|
||||
margin-right: 20px;
|
||||
width: 20.8em;
|
||||
caret-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
.none_p_title{
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-ul{
|
||||
background-color: white;
|
||||
margin-bottom: 12px;
|
||||
border-radius:2px;
|
||||
|
||||
.MenuTitle{
|
||||
border-bottom: 1px solid #E0E0E0;
|
||||
|
||||
span{
|
||||
display: block;
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
border-bottom: 0px solid;
|
||||
i{
|
||||
color: #afaaae;
|
||||
}
|
||||
}
|
||||
|
||||
span:hover{
|
||||
color: #1484EF;
|
||||
.iconfont{
|
||||
color: #1484EF !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
li{
|
||||
padding:0px 0px 0px 20px;
|
||||
position: relative;
|
||||
height: 62px;
|
||||
line-height: 62px;
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
span{
|
||||
display: block;
|
||||
height: 62px;
|
||||
cursor: pointer;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
&:last-child > span{
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
li:hover{
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
.active{
|
||||
background-color: #fafafa;
|
||||
& ::before{
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 15px;
|
||||
width: 6px;
|
||||
content: '';
|
||||
height: 30px;
|
||||
background: #1484EF;
|
||||
}
|
||||
}
|
||||
|
||||
& i{
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-input-group-addon .ant-btn-lg {
|
||||
height: 40px;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
// 公告开始
|
||||
export const noticeStatus = [
|
||||
{ code: 0, name: "关闭", dicItemName: '关闭' },
|
||||
{ code: 1, name: "正常", dicItemName: '正常' },
|
||||
{ code: 2, name: "草稿", dicItemName: '草稿' },
|
||||
];
|
||||
|
||||
export const noticeType = [
|
||||
{ code: 1, name: "更正公告", dicItemName: "更正" },
|
||||
{ code: 2, name: "中标公告", dicItemName: "中标" },
|
||||
{ code: 3, name: "废标公告", dicItemName: "废标" },
|
||||
{ code: 4, name: "招标公告", dicItemName: "招标" },
|
||||
{ code: 5, name: "技术资产", dicItemName: "技术" },
|
||||
{ code: 6, name: "成交公告", dicItemName: "成交" },
|
||||
];
|
||||
|
||||
export const noticeChecked = [
|
||||
{ code: 0, name: "未通过", dicItemName: "未通过" },
|
||||
{ code: 1, name: "通过", dicItemName: "通过" },
|
||||
{ code: 2, name: "未处理", dicItemName: "未处理" },
|
||||
];
|
||||
//公告结束
|
|
@ -0,0 +1,73 @@
|
|||
import React from 'react';
|
||||
|
||||
export function AbandonSvg({ color }) {
|
||||
return <svg width="16" height="15.198" viewBox="0 0 16 15.198">
|
||||
<g id="组_96" data-name="组 96" transform="translate(-54.703 -1778.755)">
|
||||
<g id="组_87" data-name="组 87" transform="translate(63.014 1786.264)">
|
||||
<path id="路径_334" data-name="路径 334" d="M365.033,2110.025H361.89a.591.591,0,1,1,0-1.183h3.143a.591.591,0,1,1,0,1.183Z" transform="translate(-359.618 -2105.589)" fill={color} />
|
||||
<path id="路径_335" data-name="路径 335" d="M316.429,2010.462a3.844,3.844,0,1,0,1.126,2.718A3.819,3.819,0,0,0,316.429,2010.462Zm-.739,4.7a2.8,2.8,0,1,1,0-3.959A2.79,2.79,0,0,1,315.69,2015.16Z" transform="translate(-309.866 -2009.336)" fill={color} />
|
||||
</g>
|
||||
<g id="组_88" data-name="组 88" transform="translate(54.703 1778.755)">
|
||||
<path id="路径_336" data-name="路径 336" d="M61.441,1790.478a5.6,5.6,0,0,1,5.545-5.651,5.476,5.476,0,0,1,1.02.1v-4.368a1.808,1.808,0,0,0-1.8-1.8H56.507a1.808,1.808,0,0,0-1.8,1.8v11.02a1.808,1.808,0,0,0,1.8,1.8h5.718A5.705,5.705,0,0,1,61.441,1790.478Zm-4.155-8.229a.7.7,0,0,1,.728-.666h6.692a.7.7,0,0,1,.728.666h0a.7.7,0,0,1-.728.666H58.014a.7.7,0,0,1-.728-.666Zm3.077,7.351h-2.5a.673.673,0,0,1,0-1.332h2.5a.673.673,0,0,1,0,1.332Zm-2.349-3.44a.7.7,0,0,1-.728-.666h0a.7.7,0,0,1,.728-.666h3.18a.7.7,0,0,1,.728.666h0a.7.7,0,0,1-.728.666Z" transform="translate(-54.703 -1778.755)" fill={color} />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
}
|
||||
|
||||
export function AllSvg({ color }) {
|
||||
return <svg width="16" height="15.198" viewBox="0 0 16 15.198">
|
||||
<g id="组_93" data-name="组 93" transform="translate(696.223 -1778.755)">
|
||||
<path id="路径_337" data-name="路径 337" d="M-365.778,2071.537l-1.4.948h-.467a.313.313,0,0,0-.311.315v1.263a.314.314,0,0,0,.311.316h.467l1.4.947a.315.315,0,0,0,.221-.094.314.314,0,0,0,.09-.222v-3.157A.314.314,0,0,0-365.778,2071.537Z" transform="translate(-317.611 -283.396)" fill={color} />
|
||||
<g id="组_90" data-name="组 90" transform="translate(-688.125 1786.051)">
|
||||
<path id="路径_338" data-name="路径 338" d="M-434.315,2010.493a3.925,3.925,0,0,0-2.794-1.157,3.925,3.925,0,0,0-2.794,1.157,3.925,3.925,0,0,0-1.157,2.794,3.925,3.925,0,0,0,1.157,2.794,3.926,3.926,0,0,0,2.794,1.157,3.926,3.926,0,0,0,2.794-1.157,3.925,3.925,0,0,0,1.157-2.794A3.925,3.925,0,0,0-434.315,2010.493Zm-.76,4.828a2.867,2.867,0,0,1-2.034.841,2.868,2.868,0,0,1-2.034-.841,2.858,2.858,0,0,1-.843-2.034,2.858,2.858,0,0,1,.843-2.034,2.858,2.858,0,0,1,2.034-.843,2.858,2.858,0,0,1,2.034.843A2.88,2.88,0,0,1-435.075,2015.321Z" transform="translate(441.06 -2009.336)" fill={color} />
|
||||
</g>
|
||||
<g id="组_91" data-name="组 91" transform="translate(-696.223 1778.755)">
|
||||
<path id="路径_339" data-name="路径 339" d="M-689.3,1790.466a5.672,5.672,0,0,1,5.7-5.645,5.79,5.79,0,0,1,1.048.1v-4.363a1.832,1.832,0,0,0-1.854-1.8h-9.964a1.832,1.832,0,0,0-1.854,1.8v11.008a1.833,1.833,0,0,0,1.854,1.8h5.877A5.577,5.577,0,0,1-689.3,1790.466Zm-4.27-8.22a.712.712,0,0,1,.748-.665h6.878a.713.713,0,0,1,.748.665h0a.713.713,0,0,1-.748.665h-6.878a.713.713,0,0,1-.748-.665Zm3.163,7.343h-2.573a.633.633,0,0,1-.589-.665.633.633,0,0,1,.589-.665h2.573a.633.633,0,0,1,.589.665A.632.632,0,0,1-690.406,1789.588Zm-2.414-3.437a.713.713,0,0,1-.748-.665h0a.713.713,0,0,1,.748-.665h3.268a.713.713,0,0,1,.748.665h0a.713.713,0,0,1-.748.665Z" transform="translate(696.223 -1778.755)" fill={color} />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
}
|
||||
|
||||
export function ChangeSvg({ color }) {
|
||||
return <svg width="16" height="15.176" viewBox="0 0 16 15.176">
|
||||
<g id="组_94" data-name="组 94" transform="translate(-703.372 -1778.755)">
|
||||
<path id="路径_331" data-name="路径 331" d="M1034.307,2069.547a1.2,1.2,0,0,0-1.2.934,1.17,1.17,0,0,0,.707,1.326c.044.219.063.475-.073.573a1.129,1.129,0,0,0-.885.486v.422h2.865v-.393a1.414,1.414,0,0,0-.949-.523.751.751,0,0,1-.032-.554,1.172,1.172,0,0,0,.739-1.309,1.2,1.2,0,0,0-1.175-.961Z" transform="translate(-318.75 -281.318)" fill={color} />
|
||||
<path id="路径_332" data-name="路径 332" d="M965.772,2010.458a3.832,3.832,0,1,0,1.122,2.709A3.807,3.807,0,0,0,965.772,2010.458Zm-.737,4.682a2.79,2.79,0,1,1,0-3.946A2.781,2.781,0,0,1,965.035,2015.141Z" transform="translate(-247.522 -223.068)" fill={color} />
|
||||
<g id="组_85" data-name="组 85" transform="translate(703.372 1778.755)">
|
||||
<path id="路径_333" data-name="路径 333" d="M710.088,1790.463a5.586,5.586,0,0,1,5.527-5.643,5.441,5.441,0,0,1,1.017.1v-4.362a1.8,1.8,0,0,0-1.8-1.8H705.17a1.8,1.8,0,0,0-1.8,1.8v11.005a1.8,1.8,0,0,0,1.8,1.8h5.7A5.705,5.705,0,0,1,710.088,1790.463Zm-4.141-8.218a.7.7,0,0,1,.726-.665h6.67a.7.7,0,0,1,.726.665h0a.7.7,0,0,1-.726.665h-6.67a.7.7,0,0,1-.726-.665Zm3.067,7.341h-2.5a.673.673,0,0,1,0-1.33h2.5a.673.673,0,0,1,0,1.33Zm-2.341-3.436a.7.7,0,0,1-.726-.665h0a.7.7,0,0,1,.726-.665h3.169a.7.7,0,0,1,.726.665h0a.7.7,0,0,1-.726.665Z" transform="translate(-703.372 -1778.755)" fill={color} />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
}
|
||||
|
||||
export function CheckSvg({ color }) {
|
||||
return <svg width="16" height="14.548" viewBox="0 0 16 14.548">
|
||||
<g id="组_95" data-name="组 95" transform="translate(-1325.073 -1778.755)">
|
||||
<path id="路径_325" data-name="路径 325" d="M1655.311,1844.214" transform="translate(-319.943 -63.419)" fill={color} />
|
||||
<path id="路径_326" data-name="路径 326" d="M1680.948,2109.083a.659.659,0,1,0-.407.609.659.659,0,0,0,.407-.609Z" transform="translate(-343.504 -319.392)" fill={color} />
|
||||
<g id="组_82" data-name="组 82" transform="translate(1333.053 1785.974)">
|
||||
<path id="路径_327" data-name="路径 327" d="M1587.227,2013.456a2.664,2.664,0,1,1-1.177-1.812l.058-.378.585-.39a3.665,3.665,0,1,0,1.565,3,3.7,3.7,0,0,0-.064-.686l-.541.361Z" transform="translate(-1580.931 -2010.216)" fill={color} />
|
||||
<path id="路径_328" data-name="路径 328" d="M1645.528,2074.812a1.261,1.261,0,1,1-.58-2.115l.479-.319a1.734,1.734,0,1,0,.941,1.542c0-.008,0-.016,0-.023l-.514.349A1.254,1.254,0,0,1,1645.528,2074.812Z" transform="translate(-1640.971 -2070.255)" fill={color} />
|
||||
</g>
|
||||
<g id="组_83" data-name="组 83" transform="translate(1337.198 1786.341)">
|
||||
<path id="路径_329" data-name="路径 329" d="M1717.735,2023.462h-.009l-.741-.124h0a.373.373,0,0,1-.271-.406v0l.186-.693,0-.01a.092.092,0,0,0-.05-.125l-.01,0-.009-.006a.132.132,0,0,0-.074-.023.134.134,0,0,0-.075.023l-1.335.89-.133.628-1.246.831.005,0a1.024,1.024,0,0,1,.608.916l1.238-.84.628.121,1.34-.893.005,0c.04-.02.049-.053.05-.148C1717.805,2023.516,1717.773,2023.462,1717.735,2023.462Z" transform="translate(-1713.97 -2022.066)" fill={color} />
|
||||
</g>
|
||||
<path id="路径_330" data-name="路径 330" d="M1331.495,1789.957a5.343,5.343,0,0,1,5.285-5.4,5.206,5.206,0,0,1,.972.091v-4.174a1.725,1.725,0,0,0-1.719-1.72h-9.24a1.725,1.725,0,0,0-1.719,1.72v10.53a1.725,1.725,0,0,0,1.719,1.72h5.45A5.462,5.462,0,0,1,1331.495,1789.957Zm-3.96-7.863a.669.669,0,0,1,.694-.636h6.378a.669.669,0,0,1,.694.636h0a.669.669,0,0,1-.694.636h-6.378a.669.669,0,0,1-.694-.636Zm2.933,7.024h-2.386a.644.644,0,0,1,0-1.272h2.386a.644.644,0,0,1,0,1.272Zm-2.239-3.287a.669.669,0,0,1-.694-.636h0a.669.669,0,0,1,.694-.636h3.031a.669.669,0,0,1,.694.636h0a.669.669,0,0,1-.694.636Z" transform="translate(0 0)" fill={color} />
|
||||
</g>
|
||||
</svg>
|
||||
}
|
||||
|
||||
export function NewSvg({ color }) {
|
||||
return <svg width="33.091" height="14" viewBox="0 0 33.091 14">
|
||||
<g id="组_137" data-name="组 137" transform="translate(-294 -259)">
|
||||
<path id="路径_346" data-name="路径 346" d="M324.546,259h-28A2.553,2.553,0,0,0,294,261.545v8.909A2.553,2.553,0,0,0,296.545,273h28a2.553,2.553,0,0,0,2.545-2.545v-8.909A2.553,2.553,0,0,0,324.546,259ZM302.9,269.818a.642.642,0,0,1-.445.611.983.983,0,0,1-.191.025.664.664,0,0,1-.535-.28l-3.907-5.893v5.524a.636.636,0,1,1-1.273.013v-7.636a.632.632,0,0,1,1.158-.356l3.92,5.88v-5.524a.636.636,0,1,1,1.273,0Zm8.285-4.455a.636.636,0,1,1,0,1.273h-4.455v2.546h4.455a.636.636,0,1,1,0,1.273h-5.091a.63.63,0,0,1-.636-.636v-7.636a.63.63,0,0,1,.636-.636h5.091a.636.636,0,0,1,0,1.273h-4.455v2.545Zm13.211-3.029-2.52,7.522a.63.63,0,0,1-1.2,0l-1.922-5.74-1.922,5.74a.659.659,0,0,1-1.2,0l-2.52-7.522a.636.636,0,0,1,1.209-.395l1.922,5.74,1.922-5.74a.659.659,0,0,1,1.2,0l1.922,5.74,1.922-5.74a.624.624,0,1,1,1.184.395Zm0,0" fill={color} />
|
||||
</g>
|
||||
</svg>
|
||||
}
|
||||
|
||||
export function CallSvg({ color }) {
|
||||
return <svg width="13.925" height="16" viewBox="0 0 13.925 16">
|
||||
<path id="路径_350" data-name="路径 350" d="M1822.1,2425.528h-1.478a1.674,1.674,0,0,1-1.68,1.68h-5.371a1.674,1.674,0,0,1-1.68-1.68h-1.461a1.122,1.122,0,0,0-1.117,1.117v12.485a1.122,1.122,0,0,0,1.117,1.117h11.691a1.122,1.122,0,0,0,1.117-1.117v-12.481A1.155,1.155,0,0,0,1822.1,2425.528Zm-10.052,4.009h4.306a.77.77,0,1,1,0,1.539h-4.306a.77.77,0,1,1,0-1.539Zm0,3.463h4.306a.77.77,0,1,1,0,1.54h-4.306a.77.77,0,0,1,0-1.54Zm5.358,4.781h-5.382a.77.77,0,0,1,0-1.54h5.382a.77.77,0,0,1,0,1.54Zm2.92.052a.822.822,0,1,1,.822-.822A.822.822,0,0,1,1820.33,2437.833Zm.028-4.967-1.245.953v-3.9a.362.362,0,0,1,.331-.382h1.816a.362.362,0,0,1,.331.382l.01,3.9Zm-1.673-6.569h-4.871a1.034,1.034,0,0,1-1.025-1.025,1.045,1.045,0,0,1,1.025-1.025h4.871a1.025,1.025,0,0,1,0,2.049Zm0,0" transform="translate(-1809.317 -2424.247)" fill={color} />
|
||||
</svg>
|
||||
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
import React, { Component, 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 './task/api';
|
||||
import { ImageLayerOfCommentHOC } from "../modules/page/layers/ImageLayerOfCommentHOC";
|
||||
import './index.scss';
|
||||
|
||||
const TaskList = Loadable({
|
||||
loader: () => import("./task/taskList"),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
const TaskDetail = Loadable({
|
||||
loader: () => import("./task/taskDetail"),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
const TaskEdit = Loadable({
|
||||
loader: () => import("./task/taskEdit"),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
const MyTask = Loadable({
|
||||
loader: () => import("./task/myTask"),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
|
||||
const TaskAdminRouter = Loadable({
|
||||
loader: () => import("./task/taskAdminRouter"),
|
||||
loading: Loading,
|
||||
});
|
||||
|
||||
|
||||
|
||||
const Index = (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 = currentUser;
|
||||
|
||||
return (
|
||||
<div className="newMain clearfix">
|
||||
<Switch {...propsF}>
|
||||
|
||||
{/* 任务详情 */}
|
||||
<Route
|
||||
path="/task/taskDetail/:taskId"
|
||||
render={(props) => (
|
||||
<TaskDetail {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
|
||||
{/* 新增任务 */}
|
||||
<Route
|
||||
path="/task/taskAdd"
|
||||
render={(props) => (
|
||||
<TaskEdit {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
|
||||
{/* 编辑任务 */}
|
||||
<Route
|
||||
path="/task/taskEdit/:taskId"
|
||||
render={(props) => (
|
||||
<TaskEdit {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
|
||||
{/* 我的任务 */}
|
||||
<Route
|
||||
path="/task/myTask"
|
||||
render={(props) => (
|
||||
<MyTask {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
|
||||
{/* 管理员管理 */}
|
||||
<Route
|
||||
path="/task/:admin"
|
||||
render={(props) => (
|
||||
<TaskAdminRouter {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
|
||||
{/* 任务列表 */}
|
||||
<Route
|
||||
path="/task"
|
||||
render={(props) => (
|
||||
<TaskList {...propsF} {...props} />
|
||||
)}
|
||||
></Route>
|
||||
|
||||
</Switch>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
// }
|
||||
export default withRouter(
|
||||
ImageLayerOfCommentHOC({
|
||||
imgSelector: ".imageLayerParent img, .imageLayerParent .imageTarget",
|
||||
parentSelector: ".newMain",
|
||||
})(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(Index))))
|
||||
);
|
|
@ -0,0 +1,206 @@
|
|||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { Input, Button, Form, Select } from 'antd';
|
||||
|
||||
import ItemAgreementManage from '../components/itemAgreementManage';
|
||||
import StatusNav from '../../components/statusNav';
|
||||
import { agreementArr } from '../static';
|
||||
import { agreementList } from '../api';
|
||||
import '../index.scss';
|
||||
const Option = Select.Option;
|
||||
|
||||
const agreementOptionArr = agreementArr.slice(0, 2);
|
||||
export default Form.create()(({ form, showNotification, match, history }) => {
|
||||
|
||||
|
||||
const { getFieldDecorator, validateFields, setFieldsValue, } = form;
|
||||
|
||||
const [approve, setApprove] = useState(1);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [searchObj, setSearchObj] = useState({});
|
||||
const [status, setStatus] = useState('2');
|
||||
const [curPage, setCurPage] = useState(1);
|
||||
const [total, setTotal] = useState(0);
|
||||
const [taskList, setTaskList] = useState([]);
|
||||
const [type, setType] = useState('1');
|
||||
|
||||
const [reload, setReload] = useState(0);
|
||||
|
||||
const [loadPaper, setLoadPaper] = useState(0);
|
||||
|
||||
// 加载审核协议列表
|
||||
useEffect(() => {
|
||||
const params = {
|
||||
...searchObj,
|
||||
status,
|
||||
type,
|
||||
currentPage: curPage,
|
||||
pageSize: 10,
|
||||
};
|
||||
setLoading(true);
|
||||
agreementList(params).then(data => {
|
||||
if (data) {
|
||||
if (loadPaper === 0 && data.rows.length === 0) {
|
||||
setLoadPaper(1);
|
||||
} else {
|
||||
setLoadPaper(2);
|
||||
}
|
||||
setTaskList(data.rows);
|
||||
setTotal(data.total);
|
||||
}
|
||||
setLoading(false);
|
||||
});
|
||||
}, [reload, status, curPage, searchObj, type]);
|
||||
|
||||
// 如果第一次加载任务协议审核发现没有数据,那么切换成审核成果协议列表
|
||||
useEffect(() => {
|
||||
if (loadPaper === 1) {
|
||||
const params = {
|
||||
status: '2',
|
||||
type: '2',
|
||||
currentPage: 1,
|
||||
pageSize: 10,
|
||||
};
|
||||
setLoading(true);
|
||||
agreementList(params).then(data => {
|
||||
if (data && data.rows.length > 0) {
|
||||
setTaskList(data.rows);
|
||||
setTotal(data.total);
|
||||
setType('2');
|
||||
setLoadPaper(2);
|
||||
}
|
||||
setLoading(false);
|
||||
});
|
||||
}
|
||||
}, [loadPaper]);
|
||||
|
||||
// form表单公共处理函数
|
||||
const helper = useCallback(
|
||||
(name, rules, widget, initialValue) => (
|
||||
<Form.Item>
|
||||
{getFieldDecorator(name, { rules, initialValue, validateFirst: true, })(widget)}
|
||||
</Form.Item>
|
||||
), []);
|
||||
|
||||
|
||||
function onSearch() {
|
||||
validateFields((err, values) => {
|
||||
if (!err) {
|
||||
setSearchObj(values);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 修改选项
|
||||
const changeOptionId = useCallback((option) => {
|
||||
setStatus(option.dicItemCode.toString() || '0,1');
|
||||
setCurPage(1);
|
||||
}, []);
|
||||
|
||||
// 修改状态
|
||||
function changeApprove(approve) {
|
||||
setApprove(approve);
|
||||
setCurPage(1);
|
||||
if (approve === 1) {
|
||||
setStatus('2');
|
||||
} else {
|
||||
setStatus('0,1');
|
||||
}
|
||||
}
|
||||
|
||||
// 清除查询内容
|
||||
function clearSearch() {
|
||||
setFieldsValue({
|
||||
taskNumber: '',
|
||||
taskName: '',
|
||||
userName: ''
|
||||
});
|
||||
setSearchObj({});
|
||||
}
|
||||
|
||||
// 刷新数据
|
||||
const reloadList = useCallback(() => {
|
||||
setReload(Math.random());
|
||||
}, []);
|
||||
|
||||
|
||||
return (
|
||||
<div className="centerbox task-manage">
|
||||
|
||||
<div className="center-screen" >
|
||||
<div className="center-left-but">
|
||||
{helper(
|
||||
"type",
|
||||
[],
|
||||
<Select
|
||||
showArrow
|
||||
placeholder="请选择协议"
|
||||
onChange={(type) => { setType(type) }}
|
||||
>
|
||||
<Option key={'1'}>委托协议</Option>
|
||||
<Option key={'2'}>成果协议</Option>
|
||||
</Select>,
|
||||
type
|
||||
)}
|
||||
<Button className="circle-button" type={approve === 1 ? 'primary' : ''} onClick={() => { changeApprove(1) }}>待审批</Button>
|
||||
<Button className="circle-button" type={approve === 2 ? 'primary' : ''} onClick={() => { changeApprove(2) }}>已审批</Button>
|
||||
</div>
|
||||
|
||||
<div className="center-right-but">
|
||||
{helper(
|
||||
"taskNumber",
|
||||
[{ max: 20, message: '长度不能超过20个字符' }],
|
||||
<Input
|
||||
placeholder="输入任务编号进行检索"
|
||||
/>
|
||||
)}
|
||||
|
||||
{helper(
|
||||
"taskName",
|
||||
[{ max: 20, message: '长度不能超过20个字符' }],
|
||||
<Input
|
||||
placeholder="输入任务名称进行检索"
|
||||
/>
|
||||
)}
|
||||
|
||||
{helper(
|
||||
"userName",
|
||||
[{ max: 20, message: '长度不能超过20个字符' }],
|
||||
<Input
|
||||
placeholder="输入发布人名称进行检索"
|
||||
/>
|
||||
)}
|
||||
|
||||
<Button className="mr10" type="primary" onClick={onSearch}>搜索</Button>
|
||||
<Button className="mr10" type="" onClick={clearSearch}>清除</Button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div className="center-content">
|
||||
|
||||
{
|
||||
approve === 2 && <StatusNav
|
||||
key={'status'}
|
||||
type={'status'}
|
||||
options={agreementOptionArr}
|
||||
changeOptionId={changeOptionId}
|
||||
/>
|
||||
}
|
||||
<ItemAgreementManage
|
||||
list={taskList}
|
||||
curPage={curPage}
|
||||
total={total}
|
||||
changePage={(page) => { setCurPage(page) }}
|
||||
loading={loading}
|
||||
showNotification={showNotification}
|
||||
reloadList={reloadList}
|
||||
/>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
)
|
|
@ -0,0 +1,577 @@
|
|||
import fetch, { } from './fetch';
|
||||
import { notification } from 'antd';
|
||||
|
||||
// 获取字典分类列表
|
||||
export function getDictionary(id) {
|
||||
return fetch({
|
||||
url: '/dicItem/getData?dicTypeCode=' + id,
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
// 获取用户信息
|
||||
export function getUserInfo() {
|
||||
return fetch({
|
||||
url: '/user/getUserInfo',
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
// 获取用户企业信息
|
||||
export function getCompanyInfo() {
|
||||
return fetch({
|
||||
url: '/api/tasks/getEnterpriseUserInfo',
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
// 获取任务领域
|
||||
export async function getTaskCategory() {
|
||||
let res = await fetch({
|
||||
url: '/api/taskCategory/getTaskCategory',
|
||||
method: 'get',
|
||||
});
|
||||
if (Array.isArray(res.data.rows)) {
|
||||
return res.data.rows;
|
||||
} else {
|
||||
notification.open({
|
||||
message: "提示",
|
||||
description: res.message || '请求错误',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 任务列表查询
|
||||
export async function getTaskList(params) {
|
||||
let res = await fetch({
|
||||
url: '/api/tasks/',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
if (res.data) {
|
||||
return res.data;
|
||||
} else {
|
||||
notification.open({
|
||||
message: "提示",
|
||||
description: res.message || '请求错误',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 管理员任务列表查询
|
||||
export async function getTaskAdminList(params) {
|
||||
let res = await fetch({
|
||||
url: '/api/tasks/backend/list',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
if (res.data) {
|
||||
return res.data;
|
||||
} else {
|
||||
notification.open({
|
||||
message: "提示",
|
||||
description: res.message || '请求错误',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 我的任务列表查询
|
||||
export async function getMyTaskList(params) {
|
||||
let res = await fetch({
|
||||
url: '/api/myTasks/',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
if (res.data) {
|
||||
return res.data;
|
||||
} else {
|
||||
notification.open({
|
||||
message: "提示",
|
||||
description: res.message || '请求错误',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 我参与的任务列表查询
|
||||
export async function getJoinTaskList(params) {
|
||||
let res = await fetch({
|
||||
url: '/api/myTasks/myPapers',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
if (res.data) {
|
||||
return res.data;
|
||||
} else {
|
||||
notification.open({
|
||||
message: "提示",
|
||||
description: res.message || '请求错误',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 详情查询
|
||||
export async function getTaskDetail(id) {
|
||||
let res = await fetch({
|
||||
url: '/api/tasks/getTask/' + id,
|
||||
method: 'get',
|
||||
});
|
||||
if (res.data) {
|
||||
return res.data;
|
||||
} else {
|
||||
if(res.message&&res.message.indexOf('exist')>-1){
|
||||
notification.open({
|
||||
message: "提示",
|
||||
description: "未查到该任务",
|
||||
});
|
||||
}else{
|
||||
notification.open({
|
||||
message: "提示",
|
||||
description: res.message || '请求错误',
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//新增任务
|
||||
export function addTask(data) {
|
||||
return fetch({
|
||||
url: '/api/tasks/add',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
//更新任务
|
||||
export function updateTask(data) {
|
||||
return fetch({
|
||||
url: '/api/tasks/',
|
||||
method: 'PUT',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
//删除
|
||||
export function deleteTask(id, isDelete) {
|
||||
return fetch({
|
||||
url: '/api/tasks/' + id + '?isDelete=' + isDelete,
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//新增成果
|
||||
export function addPaper(data) {
|
||||
return fetch({
|
||||
url: '/api/paper/',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
// 任务成果
|
||||
export async function getTaskPaper(params) {
|
||||
let res = await fetch({
|
||||
url: '/api/paper/',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
if (res.data) {
|
||||
return res.data;
|
||||
} else {
|
||||
notification.open({
|
||||
message: "提示",
|
||||
description: res.message || '请求错误',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 审核任务成果
|
||||
export async function readyCheckPapers(params) {
|
||||
let res = await fetch({
|
||||
url: '/api/paper/admin/readyCheckPapers',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
if (res.data) {
|
||||
return res.data;
|
||||
} else {
|
||||
notification.open({
|
||||
message: "提示",
|
||||
description: res.message || '请求错误',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 我的成果
|
||||
export async function myPapers(params) {
|
||||
let res = await fetch({
|
||||
url: '/api/paper/my',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
if (res.data) {
|
||||
return res.data;
|
||||
} else {
|
||||
notification.open({
|
||||
message: "提示",
|
||||
description: res.message || '请求错误',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//更新成果
|
||||
export function updatePaper(data) {
|
||||
return fetch({
|
||||
url: '/api/paper/',
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
// 删除
|
||||
export function deletePaper(id) {
|
||||
return fetch({
|
||||
url: `api/paper/${id}`,
|
||||
method: 'delete',
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//应征者名单公示
|
||||
export function makePublic(id) {
|
||||
return fetch({
|
||||
url: `/api/tasks/makeApplicantListPublic/${id}`,
|
||||
method: 'put',
|
||||
});
|
||||
}
|
||||
|
||||
//举报成果
|
||||
export function reportPaper(data) {
|
||||
return fetch({
|
||||
url: `/api/paper/${data.paperId}/paperReport`,
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
//点赞成果
|
||||
export function thumbUpPaper(id) {
|
||||
return fetch({
|
||||
url: `/api/paper/${id}/thumbUp`,
|
||||
method: 'post',
|
||||
data: { paperId: id }
|
||||
});
|
||||
}
|
||||
|
||||
// 检查用户是否同意协议
|
||||
export function checkAgreement(taskId) {
|
||||
return fetch({
|
||||
url: `/api/paper/${taskId}/agreement`,
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
// 检查用户是否提交了成果
|
||||
export function checkHavePaper(taskId) {
|
||||
return fetch({
|
||||
url: `/api/paper/${taskId}/check`,
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// 获取协议
|
||||
export function getAgreement() {
|
||||
return fetch({
|
||||
url: '/api/paper/agreementSettings/1',
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
// 同意协议
|
||||
export function agreement(taskId) {
|
||||
return fetch({
|
||||
url: `/api/paper/${taskId}/agreement`,
|
||||
method: 'post',
|
||||
data: { taskId }
|
||||
});
|
||||
}
|
||||
|
||||
// 新增评论
|
||||
export function commentAdd(data) {
|
||||
return fetch({
|
||||
url: `/api/paper/${data.paperId}/comment`,
|
||||
method: 'post',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//管理员审核任务
|
||||
export function checkTask(data) {
|
||||
return fetch({
|
||||
url: `/api/tasks/backend/adminCheck`,
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// 审核成果/评论
|
||||
export function checkPaper(data) {
|
||||
return fetch({
|
||||
url: `/api/paper/admin/complainPaper/${data.paperId}`,
|
||||
method: 'post',
|
||||
data: data.auditingVo
|
||||
});
|
||||
}
|
||||
|
||||
// 成果申诉
|
||||
export function complainPaper(data) {
|
||||
return fetch({
|
||||
url: `/api/paper/complainInfo/${data.paperId}`,
|
||||
method: 'post',
|
||||
data: data.params
|
||||
});
|
||||
}
|
||||
|
||||
// 审核申诉材料列表查询
|
||||
export async function complainPaperList(params) {
|
||||
let res = await fetch({
|
||||
url: '/api/paper/admin/readyComplaintPapers',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
if (res.data) {
|
||||
return res.data;
|
||||
} else {
|
||||
notification.open({
|
||||
message: "提示",
|
||||
description: res.message || '请求错误',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 审核申诉材料
|
||||
export function checkComplain(data) {
|
||||
return fetch({
|
||||
url: `/api/paper/admin/complainMaterial/${data.paperId}`,
|
||||
method: 'post',
|
||||
data: data.auditingVo
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// 佐证上传
|
||||
export function proofAdd(data) {
|
||||
return fetch({
|
||||
url: `/api/taskResultProof/addTaskResultProof`,
|
||||
method: 'post',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
// 审核佐证材料列表查询
|
||||
export async function proofList(params) {
|
||||
let res = await fetch({
|
||||
url: '/api/tasks/backend/proofList',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
if (res.data) {
|
||||
return res.data;
|
||||
} else {
|
||||
notification.open({
|
||||
message: "提示",
|
||||
description: res.message || '请求错误',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 审核佐证
|
||||
export function checkProof(data) {
|
||||
return fetch({
|
||||
url: `/api/taskResultProof/adminCheckResultAndProof`,
|
||||
method: 'post',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
// 应征者公示期申诉
|
||||
export function publicityComplain(data) {
|
||||
return fetch({
|
||||
url: `/api/myTasks/applicantComplaintDuringPublicity`,
|
||||
method: 'post',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
// 审核公示期申诉列表查询
|
||||
export async function publicityComplainList(params) {
|
||||
let res = await fetch({
|
||||
url: '/api/tasks/backend/complaintMaterialList',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
if (res.data) {
|
||||
return res.data;
|
||||
} else {
|
||||
notification.open({
|
||||
message: "提示",
|
||||
description: res.message || '请求错误',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 审核公示期申诉
|
||||
export function checkPublicity(data) {
|
||||
return fetch({
|
||||
url: `/api/tasks/backend/adminCheck/complaintMaterialDuringPublicity`,
|
||||
method: 'post',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
// 选择签订协议的方式
|
||||
export function signMethod(data) {
|
||||
return fetch({
|
||||
url: `/api/sign/method/${data.taskId}/${data.method}`,
|
||||
method: 'post',
|
||||
});
|
||||
}
|
||||
|
||||
// 上传委托协议
|
||||
export function uploadAgreeRequire(data) {
|
||||
return fetch({
|
||||
url: `/api/sign/task/contract/${data.taskId}`,
|
||||
method: 'post',
|
||||
data: data.params
|
||||
});
|
||||
}
|
||||
|
||||
// 审核委托协议列表
|
||||
export async function agreementList(params) {
|
||||
let res = await fetch({
|
||||
url: '/api/sign/task/contract',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
if (res.data) {
|
||||
return res.data;
|
||||
} else {
|
||||
notification.open({
|
||||
message: "提示",
|
||||
description: res.message || '请求错误',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 审核协议
|
||||
export function adminCheckAgreement(data) {
|
||||
return fetch({
|
||||
url: `/api/sign/admin/${data.type === 1 ? 'task' : 'paper'}/contract/${data.agreementId}`,
|
||||
method: 'post',
|
||||
data: data.params
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// 上传委托协议
|
||||
export function uploadAgreePaper(data) {
|
||||
return fetch({
|
||||
url: `/api/sign/paper/contract/${data.paperId}`,
|
||||
method: 'post',
|
||||
data: data.params
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// 上传凭证列表查询
|
||||
export async function uploadPayProofList(params) {
|
||||
let res = await fetch({
|
||||
url: '/api/sign/admin/paper/payOrders',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
if (res.data) {
|
||||
return res.data;
|
||||
} else {
|
||||
notification.open({
|
||||
message: "提示",
|
||||
description: res.message || '请求错误',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 管理员上传支付凭证
|
||||
export function uploadPayProof(data) {
|
||||
return fetch({
|
||||
url: `/api/sign/admin/paper/payment/${data.paperId}`,
|
||||
method: 'post',
|
||||
data: data.params
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// 胜出者确认收款
|
||||
export function confirmReceipt(paperId) {
|
||||
return fetch({
|
||||
url: `/api/sign/paper/money/${paperId}`,
|
||||
method: 'post',
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// 下载协议签订凭证
|
||||
export function downAgreement(params) {
|
||||
return fetch({
|
||||
url: `/api/myTasks/getWinnersContractsByTaskId`,
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
// 管理员修改任务公示方式
|
||||
export function changeShowUserMode(data) {
|
||||
return fetch({
|
||||
url: `/api/tasks/backend/changeShowUserMode`,
|
||||
method: 'post',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
// 延期列表查询
|
||||
export async function delayList(params) {
|
||||
let res = await fetch({
|
||||
url: '/api/tasks/backend/admin/delayList',
|
||||
method: 'get',
|
||||
params,
|
||||
});
|
||||
if (res.data) {
|
||||
return res.data;
|
||||
} else {
|
||||
notification.open({
|
||||
message: "提示",
|
||||
description: res.message || '请求错误',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 延期
|
||||
export function delayTask(data) {
|
||||
return fetch({
|
||||
url: `/api/tasks/backend/admin/task/delay/${data.taskId}`,
|
||||
method: 'post',
|
||||
data: data.params,
|
||||
});
|
||||
}
|
||||
|
||||
// 关闭
|
||||
export function closeTask(taskId) {
|
||||
return fetch({
|
||||
url: `/api/tasks/backend/admin/task/close/${taskId}`,
|
||||
method: 'post',
|
||||
});
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import { Menu, Dropdown, } from 'antd';
|
||||
import { current_main_site_url,main_web_site_url} from '../../static';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
const { SubMenu } = Menu;
|
||||
|
||||
export default props => {
|
||||
|
||||
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>
|
||||
<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><a href={`/task/delayManage`}>延期任务处理</a></Menu.Item>
|
||||
{/* <Menu.Item><a href={`${main_web_site_url}/admin/audit_files`}>协议签订凭证上传</a></Menu.Item> */}
|
||||
<Menu.Item><a href="/task/payProof">支付报酬凭证上传</a></Menu.Item>
|
||||
</SubMenu>
|
||||
|
||||
<Menu.Item><a href="/task/taskAdmin">任务列表</a></Menu.Item>
|
||||
<Menu.Item><a href="/task/paperManage">创意征集评论</a></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>
|
||||
});
|
||||
|
||||
const userMenu = useMemo(() => {
|
||||
return <Menu>
|
||||
<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>
|
||||
});
|
||||
|
||||
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>
|
||||
<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><a href="/task/taskManage/1">统筹任务发布审批</a></Menu.Item>
|
||||
<Menu.Item><a href="/task/taskManage/0">自主任务发布审批</a></Menu.Item>
|
||||
<Menu.Item><a href="/task/paperComplain">成果上传申诉审批</a></Menu.Item>
|
||||
<Menu.Item><a href="/task/publicityComplain">公示期成果申诉审批</a></Menu.Item>
|
||||
<Menu.Item><a href="/task/agreementManage">协议审批</a></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><a href="/task/proofManage">评选佐证材料</a></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={'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>
|
||||
)
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
import React, { useState, } from 'react';
|
||||
import { Modal, Form, Input, } from 'antd';
|
||||
import Upload from 'military/components/Upload';
|
||||
import { uploadAgreePaper } from "../../api";
|
||||
import '../../index.scss';
|
||||
|
||||
|
||||
export default Form.create()(props => {
|
||||
const { visible, setVisible, checkedItem, form, showNotification ,reloadList } = props;
|
||||
const { getFieldDecorator, validateFields, setFieldsValue, } = form;
|
||||
|
||||
const [fileList, setFileList] = useState([]);
|
||||
|
||||
|
||||
// 上传附件后得到的文件数组
|
||||
function uploadFunc(fileList, files) {
|
||||
setFileList(fileList);
|
||||
setFieldsValue({
|
||||
files,
|
||||
});
|
||||
}
|
||||
|
||||
function uploadAgree() {
|
||||
validateFields((err, values) => {
|
||||
if (!err) {
|
||||
uploadAgreePaper({
|
||||
paperId: checkedItem.id,
|
||||
params: {
|
||||
files: values.files,
|
||||
}
|
||||
}).then(res => {
|
||||
if (res.message === 'success') {
|
||||
setFieldsValue({
|
||||
files: '',
|
||||
});
|
||||
setVisible(false);
|
||||
showNotification("上传协议成功!");
|
||||
reloadList();
|
||||
} else {
|
||||
showNotification(res.message || "上传协议失败")
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title="签订协议"
|
||||
visible={visible}
|
||||
onOk={uploadAgree}
|
||||
onCancel={() => { setVisible(false) }}
|
||||
className="form-edit-modal"
|
||||
>
|
||||
<div className="task-popup-content">
|
||||
{/* paperAuditing */}
|
||||
{checkedItem.paperAuditing && <p className=" mb10 color-orange task_tip">审核意见:{checkedItem.paperAuditing.message}</p>}
|
||||
<a href="https://task.osredm.com/busiAttachments/download/121" className="icon icon-attachment font-13 color-blue" length="32">协议样板.word</a>
|
||||
<Form.Item className="upload-form" label="附件上传" required={true}>
|
||||
<Upload
|
||||
load={uploadFunc}
|
||||
size={50}
|
||||
showNotification={showNotification}
|
||||
fileList={fileList}
|
||||
/>
|
||||
{getFieldDecorator('files', {
|
||||
rules: [{ required: visible, message: "请上传文件" }],
|
||||
validateFirst: true
|
||||
})(<Input style={{ display: 'none' }} />)}
|
||||
</Form.Item>
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
)
|
|
@ -0,0 +1,109 @@
|
|||
import React, { useState, useCallback, useMemo} from 'react';
|
||||
import { Modal, Form, Input, } from 'antd';
|
||||
import Upload from 'military/components/Upload';
|
||||
import { complainPaper, publicityComplain, } from "../../api";
|
||||
import '../../index.scss';
|
||||
|
||||
const { TextArea } = Input;
|
||||
|
||||
export default Form.create()(props => {
|
||||
const { visible, setVisible, checkedItem, detailStatus, form, showNotification, reloadList } = props;
|
||||
const { getFieldDecorator, validateFields, setFieldsValue, } = form;
|
||||
|
||||
const [fileList, setFileList] = useState([]);
|
||||
|
||||
// 上传附件后得到的文件数组
|
||||
function uploadFunc(fileList, files) {
|
||||
setFileList(fileList);
|
||||
setFieldsValue({
|
||||
files,
|
||||
});
|
||||
}
|
||||
|
||||
const helper = useCallback(
|
||||
(name, rules, widget) => (
|
||||
<Form.Item>
|
||||
{getFieldDecorator(name, { rules, validateFirst: true })(widget)}
|
||||
</Form.Item>
|
||||
),
|
||||
[]
|
||||
);
|
||||
|
||||
function complain() {
|
||||
validateFields((error, values) => {
|
||||
if (!error) {
|
||||
if (detailStatus === 5) {
|
||||
publicityComplain({
|
||||
content: values.complainValue,
|
||||
files: values.files,
|
||||
paperId: checkedItem.id,
|
||||
}).then(res => {
|
||||
complainDeal(res);
|
||||
});
|
||||
} else {
|
||||
complainPaper({
|
||||
paperId: checkedItem.id,
|
||||
params: {
|
||||
content: values.complainValue,
|
||||
files: values.files,
|
||||
}
|
||||
}).then(res => {
|
||||
complainDeal(res);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function complainDeal(res) {
|
||||
if (res && res.message === 'success') {
|
||||
showNotification('申诉提交成功');
|
||||
setVisible(false);
|
||||
setFileList(null);
|
||||
setFieldsValue({
|
||||
files: ''
|
||||
});
|
||||
reloadList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title="申诉"
|
||||
visible={visible}
|
||||
onOk={complain}
|
||||
onCancel={() => { setVisible(false) }}
|
||||
className="form-edit-modal"
|
||||
>
|
||||
{checkedItem.checkStatus == 2 && detailStatus === 3 && <p className=" mb10 color-orange task_tip">审核意见:{checkedItem.auditing.message}</p>}
|
||||
<p className="edu-txt-center lineh-20 mb10">你的申诉信息将发送给平台管理员</p>
|
||||
<p className="edu-txt-center lineh-20">请如实填写有效的申诉原由,我们将尽快完成审核</p>
|
||||
{
|
||||
helper('complainValue', [{ required: visible, message: "(必填)请在此输入发起申诉的原因,最大限制100个字符" },
|
||||
{ max: 100, message: '长度不能超过100个字符' }],
|
||||
<TextArea
|
||||
placeholder="(必填)请在此输入发起申诉的原因,最大限制100个字符"
|
||||
autoSize={{ minRows: 6 }}
|
||||
className="applyText"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
<Form.Item className="upload-form" label="附件上传" required={true}>
|
||||
<Upload
|
||||
className="commentStyle"
|
||||
load={uploadFunc}
|
||||
size={50}
|
||||
showNotification={showNotification}
|
||||
fileList={fileList}
|
||||
/>
|
||||
{getFieldDecorator('files', {
|
||||
rules: [{ required: visible, message: "请上传文件" }],
|
||||
validateFirst: true
|
||||
})(<Input style={{ display: 'none' }} />)}
|
||||
</Form.Item>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
)
|
|
@ -0,0 +1,204 @@
|
|||
import React, { useEffect, useState, useCallback } from 'react';
|
||||
import { Pagination, Modal, Input, Form, } from 'antd';
|
||||
import { Link } from "react-router-dom";
|
||||
import Nodata from 'forge/Nodata';
|
||||
import Loading from "src/Loading";
|
||||
import { timeAgo, getImageUrl } from 'educoder';
|
||||
import { adminCheckAgreement } from '../../api';
|
||||
import { httpUrl } from '../../fetch';
|
||||
import './index.scss';
|
||||
|
||||
const { TextArea } = Input;
|
||||
export default Form.create()((props) => {
|
||||
const { form, list, curPage, total, changePage, loading, showNotification, reloadList } = props;
|
||||
const { getFieldDecorator, validateFields, setFieldsValue } = form;
|
||||
const [checkedItem, setCheckedItem] = useState({});
|
||||
const [visible, setVisible] = useState(false);
|
||||
const pageSize = props.pageSize || 10;
|
||||
|
||||
|
||||
|
||||
function refuseClick(item) {
|
||||
setCheckedItem(item);
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
function dealAction() {
|
||||
validateFields((error, values) => {
|
||||
if (!error) {
|
||||
adminCheckAgreement({
|
||||
agreementId: checkedItem.id,
|
||||
type: checkedItem.type,
|
||||
params: {
|
||||
pass: 0,
|
||||
message: values.message
|
||||
}
|
||||
}).then(res => {
|
||||
if (res && res.message === 'success') {
|
||||
showNotification('操作成功');
|
||||
reloadList();
|
||||
setFieldsValue({
|
||||
message: '',
|
||||
});
|
||||
setVisible(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function agreeClick(item) {
|
||||
Modal.confirm({
|
||||
title: '确认审批通过?',
|
||||
onOk() {
|
||||
adminCheckAgreement({
|
||||
agreementId: item.id,
|
||||
type: item.type,
|
||||
params: {
|
||||
pass: 1,
|
||||
}
|
||||
}).then(res => {
|
||||
if (res && res.message === 'success') {
|
||||
showNotification('操作成功');
|
||||
reloadList();
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function goUser(login) {
|
||||
window.location.href = `/users/${login}`;
|
||||
}
|
||||
|
||||
function goUserMes(login) {
|
||||
window.location.href = `/users/${login}/message_detail`;
|
||||
}
|
||||
|
||||
function downFile(item) {
|
||||
let url = httpUrl + '/busiAttachments/download/' + item.id;
|
||||
window.open(url);
|
||||
}
|
||||
|
||||
const helper = useCallback(
|
||||
(label, name, rules, widget) => (
|
||||
<Form.Item label={label}>
|
||||
{getFieldDecorator(name, { rules, validateFirst: true })(widget)}
|
||||
</Form.Item>
|
||||
),
|
||||
[]
|
||||
);
|
||||
|
||||
return (
|
||||
loading ? <Loading /> :
|
||||
<React.Fragment>
|
||||
{
|
||||
list.map(item => {
|
||||
return (
|
||||
<div className="list-box" key={item.id}>
|
||||
|
||||
<img alt="" className="radius mr15" height="50px" src={item.user && getImageUrl(item.user.logo)} width="50px" />
|
||||
<div className="flex1">
|
||||
<li className="clearfix mb20">
|
||||
<a className="user-box fl mr15 color-grey-3 font-16" onClick={() => { goUser(item.user.login) }}>{item.user && (item.user.nickname || item.user.login)}</a>
|
||||
<span className="fl color-grey-9 mt3 mr15">{timeAgo(item.createdAt)}</span>
|
||||
<span className="fr">
|
||||
{item.status === 1 && <span className="spanTitle color-grey-6 fl ml20">已同意</span>}
|
||||
{item.status === 0 && <span className="spanTitle color-red fl ml20">已驳回</span>}
|
||||
|
||||
{
|
||||
item.status === 2 && <React.Fragment>
|
||||
<a className="edu-default-btn edu-orangeline-btn ml20 fl" onClick={() => { goUserMes(item.user.login) }}>私信</a>
|
||||
<a className="edu-default-btn edu-blueline-btn ml20 fl" onClick={() => { agreeClick(item) }}>同意</a>
|
||||
<a className="edu-default-btn edu-greyline-btn ml20 fl" onClick={() => { refuseClick(item) }}>驳回</a>
|
||||
</React.Fragment>
|
||||
}
|
||||
</span>
|
||||
</li>
|
||||
<div className="clearfix">
|
||||
<div className="width100 lineh-35">
|
||||
<span className="color-grey-9 fl">任务名称:</span>
|
||||
<span className="fl lineh-35 ml5">
|
||||
<Link className="primary-link" to={`/task/taskDetail/${item.containerId}`}>{item.taskName}</Link>
|
||||
</span>
|
||||
</div>
|
||||
<div className="clearfix"></div>
|
||||
<div className="width100 lineh-35">
|
||||
<span className="color-grey-9 fl">任务编号:</span>
|
||||
<span className="fl lineh-35 ml5">
|
||||
{item.taskNumber}
|
||||
</span>
|
||||
</div>
|
||||
<div className="clearfix"></div>
|
||||
|
||||
{
|
||||
item.paperNumber && <React.Fragment>
|
||||
<div className="width100 lineh-35">
|
||||
<span className="color-grey-9 fl">成果编号:</span>
|
||||
<span className="fl lineh-35 ml5">
|
||||
{item.paperNumber}
|
||||
</span>
|
||||
</div>
|
||||
<div className="clearfix"></div>
|
||||
</React.Fragment>
|
||||
}
|
||||
|
||||
<div className="width100 lineh-35 clearfix">
|
||||
<span className="color-grey-9 fl">协议文件:</span>
|
||||
{
|
||||
item.busiAttachments && item.busiAttachments.map(fileItem => {
|
||||
return <span className="file-list-prof " key={fileItem.id}>
|
||||
<a onClick={() => { downFile(fileItem) }}><i className="iconfont icon-fujian color-green font-14 mr3"></i>
|
||||
{fileItem.fileName} </a>
|
||||
<span className="ml10 color-grey-9">({fileItem.fileSizeString})</span>
|
||||
</span>
|
||||
})
|
||||
}
|
||||
</div>
|
||||
{/* <div className="width100 lineh-35">
|
||||
<span className="color-grey-9 fl">驳回原因:</span>
|
||||
<span className="infos_item">{item.content}</span>
|
||||
</div> */}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
{list.length > 0 ?
|
||||
<div className="edu-txt-center mt20 mb20">
|
||||
{total > pageSize && <Pagination
|
||||
showQuickJumper
|
||||
onChange={(page) => { changePage(page) }}
|
||||
current={curPage}
|
||||
total={total}
|
||||
showTotal={total => `共 ${total} 条`}
|
||||
/>}
|
||||
</div> :
|
||||
<Nodata _html="暂无数据" />}
|
||||
|
||||
<Modal
|
||||
title="驳回协议"
|
||||
visible={visible}
|
||||
onOk={dealAction}
|
||||
onCancel={() => { setVisible(false) }}
|
||||
className="form-edit-modal"
|
||||
>
|
||||
{
|
||||
helper('驳回原因', 'message', [{ required: visible, message: "请输入驳回的原因" }, { max: 200, message: '不能超过200字符' }],
|
||||
<TextArea
|
||||
placeholder="(必填)我想说点什么呢,200字以内"
|
||||
autoSize={{ minRows: 6 }}
|
||||
className="applyText"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
</Modal>
|
||||
</React.Fragment>
|
||||
|
||||
)
|
||||
}
|
||||
)
|
|
@ -0,0 +1,52 @@
|
|||
.list-box {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 20px;
|
||||
margin: 0 1.5rem;
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #dedede;
|
||||
a.edu-orangeline-btn {
|
||||
padding: 0px 10px;
|
||||
}
|
||||
}
|
||||
|
||||
a.primary-link {
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.infos_item {
|
||||
float: left;
|
||||
max-width: 273px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
color: #343434;
|
||||
margin-right: 6px;
|
||||
line-height: 35px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.file-list-prof{
|
||||
background: #fafafa;
|
||||
padding:.25rem .5rem;
|
||||
margin-right:.5rem;
|
||||
}
|
||||
|
||||
.form-edit-modal {
|
||||
.ant-form-item{
|
||||
display: flex;
|
||||
}
|
||||
.ant-form-item-label{
|
||||
min-width: 5rem;
|
||||
}
|
||||
.ant-form-item-control-wrapper{
|
||||
width: 75%;
|
||||
display: inline-block;
|
||||
}
|
||||
.ant-input-number{
|
||||
width: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,269 @@
|
|||
import React, { useEffect, useState, useCallback } from 'react';
|
||||
import { Pagination, Modal, Input, DatePicker, Form } from 'antd';
|
||||
import { Link } from "react-router-dom";
|
||||
import moment from 'moment';
|
||||
import Nodata from 'forge/Nodata';
|
||||
import Loading from "src/Loading";
|
||||
import { getImageUrl, formatDuring } from 'educoder';
|
||||
import { taskStatusAllArr } from '../../static';
|
||||
import { delayTask, closeTask } from '../../api';
|
||||
import './index.scss';
|
||||
|
||||
const format = "YYYY-MM-DD";
|
||||
|
||||
const statusArr = [];
|
||||
for (const item of taskStatusAllArr) {
|
||||
statusArr[item.dicItemCode] = item.dicItemName;
|
||||
}
|
||||
|
||||
const classArr = ['', 'list-done', 'list-error', 'list-red', 'list-yellow', 'list-pay', '', 'list-pay', 'list-gray',];
|
||||
|
||||
function getSomeDayAfter(time, nDay) {
|
||||
return moment(new Date(time).setDate(new Date(time).getDate() + nDay)).format('YYYY-MM-DD HH:mm');
|
||||
}
|
||||
|
||||
export default Form.create()((props) => {
|
||||
|
||||
const { list, curPage, total, changePage, loading, showNotification, reloadList, form } = props;
|
||||
const { getFieldDecorator, validateFields } = form;
|
||||
|
||||
const [checkedItem, setCheckedItem] = useState('');
|
||||
const [visible, setVisible] = useState(false);
|
||||
const pageSize = props.pageSize || 10;
|
||||
|
||||
function closeClick(item) {
|
||||
Modal.confirm({
|
||||
title: '是否关闭?',
|
||||
content: <p class="font-14 lineh-25 mb10 edu-txt-center">关闭后该任务立即结束,无法重新打开</p>,
|
||||
onOk() {
|
||||
closeTask(item.id).then(res => {
|
||||
if (res && res.message === 'success') {
|
||||
showNotification('操作成功');
|
||||
reloadList();
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function delayClick(item) {
|
||||
setCheckedItem(item);
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
function delayTime() {
|
||||
validateFields((err, values) => {
|
||||
if (!err) {
|
||||
delayTask({
|
||||
taskId: checkedItem.id,
|
||||
params: {
|
||||
delayedTo: moment(values.delayedTo).format(format)
|
||||
},
|
||||
}).then(res => {
|
||||
if (res && res.message === 'success') {
|
||||
showNotification('操作成功');
|
||||
reloadList();
|
||||
setVisible(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function goUser(login) {
|
||||
window.location.href = `/users/${login}`;
|
||||
}
|
||||
|
||||
function goUserMes(login) {
|
||||
window.location.href = `/users/${login}/message_detail`;
|
||||
}
|
||||
|
||||
const helper = useCallback(
|
||||
(label, name, rules, widget, initialValue) => (
|
||||
<Form.Item label={label}>
|
||||
{getFieldDecorator(name, { rules, initialValue, validateFirst: true, })(widget)}
|
||||
</Form.Item>
|
||||
), []);
|
||||
|
||||
const surplusTime = useCallback((item) => {
|
||||
let surplus;
|
||||
switch (item.currentStatus) {
|
||||
case 3:
|
||||
surplus = item.collectingDays * 24 * 3600 - (new Date() - new Date(item.publishedAt || item.createdAt)) / 1000;
|
||||
break;
|
||||
case 4:
|
||||
surplus = item.choosingDays * 24 * 3600 - (new Date() - new Date(item.collectingCompleteAt)) / 1000;
|
||||
break;
|
||||
case 5:
|
||||
surplus = item.makePublicDays * 24 * 3600 - (new Date() - new Date(item.makePublicAt)) / 1000;
|
||||
break;
|
||||
case 6:
|
||||
surplus = item.signingDays * 24 * 3600 - (new Date() - new Date(item.publicityCompleteAt)) / 1000;
|
||||
break;
|
||||
case 7:
|
||||
surplus = item.payingDays * 24 * 3600 - (new Date() - new Date(item.signingCompleteAt)) / 1000;
|
||||
break;
|
||||
default:
|
||||
surplus = 0;
|
||||
}
|
||||
let surplusTimetext = formatDuring(surplus);
|
||||
return surplus > 0 ? '剩余' + surplusTimetext : <span>延期 <span className="color-red">{surplusTimetext}</span></span>;
|
||||
}, []);
|
||||
|
||||
const stopTime = useCallback((item) => {
|
||||
switch (item.currentStatus) {
|
||||
case 3:
|
||||
return getSomeDayAfter(item.publishedAt, item.collectingDays);
|
||||
case 4:
|
||||
return getSomeDayAfter(item.collectingCompleteAt, item.choosingDays);
|
||||
case 5:
|
||||
return getSomeDayAfter(item.makePublicAt, item.makePublicDays);
|
||||
case 6:
|
||||
return getSomeDayAfter(item.publicityCompleteAt, item.signingDays);
|
||||
case 7:
|
||||
return getSomeDayAfter(item.signingCompleteAt, item.payingDays);
|
||||
case 8:
|
||||
return item.payingCompleteAt;
|
||||
default:
|
||||
return item.expiredAt;
|
||||
}
|
||||
})
|
||||
|
||||
function disabledDate(current) {
|
||||
return current && current < moment().endOf('day');
|
||||
}
|
||||
|
||||
return (
|
||||
loading ? <Loading /> :
|
||||
<React.Fragment>
|
||||
{
|
||||
list.map(item => {
|
||||
return (
|
||||
<div className="list-box" key={item.id}>
|
||||
|
||||
<img alt="" className="radius mr15" height="50px" src={item.user && getImageUrl(item.user.logo)} width="50px" onClick={() => { goUser(item.user.login) }} />
|
||||
<div className="flex1">
|
||||
|
||||
<div className="clearfix">
|
||||
<span className="lineh-35" style={{ display: "inline-flex" }}>
|
||||
<span className="color-grey-9 fl">任务编号:</span>
|
||||
<span className="infos_item mr15">{item.number}</span>
|
||||
<span className="fl lineh-35 ml5">
|
||||
<Link className="primary-link" to={`/task/taskDetail/${item.id}`}>{item.name}</Link>
|
||||
</span>
|
||||
<span>{item.currentStatus > 0 && <span className={classArr[item.currentStatus] + ' status-tag'}>{statusArr[item.currentStatus]}</span>}</span>
|
||||
</span>
|
||||
|
||||
<span className="fr">
|
||||
{item.cancelStatus === 1 && <span className="spanTitle color-red fl ml20">延期</span>}
|
||||
{item.cancelStatus === 2 && <span className="spanTitle color-grey-6 fl ml20">关闭</span>}
|
||||
|
||||
{
|
||||
item.cancelStatus === 0 && <React.Fragment>
|
||||
<a className="edu-default-btn edu-orangeline-btn ml20 fl" onClick={() => { goUserMes(item.user.login) }}>私信</a>
|
||||
<a className="edu-default-btn edu-blueline-btn ml20 fl" onClick={() => { delayClick(item) }}>延期</a>
|
||||
<a className="edu-default-btn edu-greyline-btn ml20 fl" onClick={() => { closeClick(item) }}>关闭</a>
|
||||
</React.Fragment>
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="clearfix">
|
||||
|
||||
<span className="with40 fl lineh-35">
|
||||
<span className="color-grey-9 fl">主体名称:</span>
|
||||
<span className="infos_item">{item.enterpriseName}</span>
|
||||
</span>
|
||||
|
||||
<span className="with30 fl lineh-35">
|
||||
<span className="color-grey-9 fl">发布方式:</span>
|
||||
<span className="infos_item mr15 fl">{item.publishMode === 1 ? '统筹任务' : '自主提交'}</span>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
<div className="clearfix">
|
||||
<span className="with40 fl lineh-35">
|
||||
<span className="color-grey-9 fl">联系手机:</span>
|
||||
<span className="infos_item">{item.user.phone}(位置分析:{item.belongTo})</span>
|
||||
</span>
|
||||
|
||||
<span className="with40 fl lineh-35 color-orange">
|
||||
{
|
||||
item.status === 4 && item.papersCount > 0 && (!item.isProofBoolean) && '未上传佐证材料'
|
||||
}
|
||||
|
||||
{item.status === 6 && item.agreementSigning === 0 && '未选择协议签订方式'}
|
||||
|
||||
{
|
||||
item.status === 6 && item.agreementSigning === 2 && (item.contractStatus === null || item.contractStatus === 0) && '未上传委托协议'
|
||||
}
|
||||
|
||||
{
|
||||
item.status === 6 && item.agreementSigning === 2 && item.contractStatus === 2 && '已上传委托协议'
|
||||
}
|
||||
|
||||
{
|
||||
item.status === 7 && item.agreementSigning === 2 && '未上传支付报酬凭证'
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="clearfix">
|
||||
<span className="with40 fl lineh-35">
|
||||
<span className="color-grey-9 fl">截止时间:</span>
|
||||
<span className="infos_item">{stopTime(item)}</span>
|
||||
|
||||
{[3, 4, 5, 6, 7].includes(item.currentStatus) && <span className="ml10">{surplusTime(item)}</span>}
|
||||
</span>
|
||||
|
||||
{/* <span className="with40 lineh-35" style={{ display: "inline-flex" }}>
|
||||
<span className="color-grey-9 fl">任务编号:</span>
|
||||
<span className="infos_item mr15">{item.number}</span>
|
||||
<span className="fl lineh-35 ml5">
|
||||
<Link className="primary-link" to={`/task/taskDetail/${item.id}`}>{item.name}</Link>
|
||||
</span>
|
||||
</span> */}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
{list.length > 0 ?
|
||||
<div className="edu-txt-center mt20 mb20">
|
||||
{total > pageSize && <Pagination
|
||||
showQuickJumper
|
||||
onChange={(page) => { changePage(page) }}
|
||||
current={curPage}
|
||||
total={total}
|
||||
showTotal={total => `共 ${total} 条`}
|
||||
/>}
|
||||
</div> :
|
||||
<Nodata _html="暂无数据" />}
|
||||
|
||||
<Modal
|
||||
title="请输入延期截止的具体时间"
|
||||
visible={visible}
|
||||
onOk={delayTime}
|
||||
onCancel={() => { setVisible(false) }}
|
||||
className="time-edit-modal"
|
||||
>
|
||||
{helper(
|
||||
"",
|
||||
"delayedTo",
|
||||
[{ required: true, message: "请选择日期" }],
|
||||
<DatePicker
|
||||
format={format}
|
||||
placeholder="请选择日期"
|
||||
disabledDate={disabledDate}
|
||||
/>,
|
||||
moment(new Date(), format)
|
||||
)}
|
||||
</Modal>
|
||||
</React.Fragment>
|
||||
|
||||
)
|
||||
}
|
||||
)
|
|
@ -0,0 +1,50 @@
|
|||
.list-box {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 20px;
|
||||
margin: 0 1.5rem;
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #dedede;
|
||||
a.edu-orangeline-btn {
|
||||
padding: 0px 10px;
|
||||
}
|
||||
}
|
||||
|
||||
a.primary-link {
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.infos_item {
|
||||
float: left;
|
||||
max-width: 273px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
color: #343434;
|
||||
margin-right: 6px;
|
||||
line-height: 35px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.file-list-prof{
|
||||
background: #fafafa;
|
||||
padding:.25rem .5rem;
|
||||
}
|
||||
|
||||
.status-tag {
|
||||
display: inline-block;
|
||||
padding: 0px 10px;
|
||||
margin-left: .625rem;
|
||||
background: #f8c753;
|
||||
font-size: 12px;
|
||||
color: #fff;
|
||||
border-radius: 14px;
|
||||
line-height: 22px;
|
||||
height: 22px;
|
||||
}
|
||||
|
||||
.time-edit-modal .ant-modal-body{
|
||||
width: 200px;
|
||||
margin:0 auto;
|
||||
}
|
|
@ -0,0 +1,356 @@
|
|||
import React, { useEffect, useState, useCallback, useMemo } from 'react';
|
||||
import { Form, Modal, Input, Pagination, Radio, Table } from 'antd';
|
||||
import { Link } from "react-router-dom";
|
||||
import Nodata from 'forge/Nodata';
|
||||
import Loading from "src/Loading";
|
||||
import Upload from 'military/components/Upload';
|
||||
import ProofModal from '../proofModal';
|
||||
import { publishModeArr, taskStatusAllArr, myPaperStatusArr } from '../../static';
|
||||
import { signMethod, uploadAgreeRequire, downAgreement } from "../../api";
|
||||
import { httpUrl } from '../../fetch';
|
||||
import '../../index.scss';
|
||||
import './index.scss';
|
||||
|
||||
const statusArr = [];
|
||||
for (const item of taskStatusAllArr) {
|
||||
statusArr[item.dicItemCode] = item.dicItemName;
|
||||
}
|
||||
export default Form.create()((props) => {
|
||||
const { form, list, curPage, total, changePage, taskCategoryValueArr, loading, publish, showNotification, reloadList, joinTask } = props;
|
||||
const { getFieldDecorator, validateFields, setFieldsValue, } = form;
|
||||
|
||||
const [visibleProofs, setVisibleProofs] = useState(false);
|
||||
const [taskId, setTaskId] = useState();
|
||||
const [checkItem, setCheckItem] = useState({});
|
||||
const [taskModeId, setTaskModeId] = useState('');
|
||||
const pageSize = props.pageSize || 10;
|
||||
|
||||
const [visibleMethod, setVisibleMethod] = useState(false);
|
||||
const [visibleAgree, setVisibleAgree] = useState(false);
|
||||
const [fileList, setFileList] = useState(null);
|
||||
|
||||
const [dowloadTaskId, setDowloadTaskId] = useState('');
|
||||
const [visibleDownload, setVisibleDownload] = useState(false);
|
||||
const [uploadList, setUploadList] = useState([]);
|
||||
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
visibleDownload && downAgreement({ taskId: dowloadTaskId }).then(res => {
|
||||
if (res && res.message === "success") {
|
||||
setUploadList(res.data);
|
||||
}
|
||||
})
|
||||
}, [visibleDownload])
|
||||
|
||||
function uploadProofs(item) {
|
||||
setVisibleProofs(true);
|
||||
setTaskId(item.id);
|
||||
setTaskModeId(item.taskModeId);
|
||||
}
|
||||
|
||||
function adviceModal(advice) {
|
||||
Modal.info({
|
||||
title: '审核意见',
|
||||
content: advice
|
||||
})
|
||||
}
|
||||
|
||||
function signMethodModal(item) {
|
||||
setVisibleMethod(true);
|
||||
setTaskId(item.id);
|
||||
}
|
||||
|
||||
function uploadAgree(item) {
|
||||
setVisibleAgree(true);
|
||||
setTaskId(item.id);
|
||||
setCheckItem(item);
|
||||
}
|
||||
|
||||
function chooseMethod() {
|
||||
validateFields((err, values) => {
|
||||
if (!err) {
|
||||
signMethod({
|
||||
taskId,
|
||||
method: values.method,
|
||||
}).then(res => {
|
||||
if (res && res.message === 'success') {
|
||||
showNotification('选择协议签订方式成功');
|
||||
setVisibleMethod(false);
|
||||
setFieldsValue({
|
||||
method: ''
|
||||
});
|
||||
reloadList();
|
||||
} else {
|
||||
showNotification((res && res.message) || '操作失败');
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const helper = useCallback(
|
||||
(name, rules, widget) => (
|
||||
<Form.Item>
|
||||
{getFieldDecorator(name, { rules, validateFirst: true, })(widget)}
|
||||
</Form.Item>
|
||||
), []);
|
||||
|
||||
|
||||
function uploadAgreeList() {
|
||||
validateFields((err, values) => {
|
||||
if (!err) {
|
||||
uploadAgreeRequire({
|
||||
taskId,
|
||||
params: {
|
||||
files: values.files
|
||||
}
|
||||
}).then(res => {
|
||||
if (res && res.message === "success") {
|
||||
setFieldsValue({
|
||||
files: ''
|
||||
});
|
||||
reloadList();
|
||||
setVisibleAgree(false);
|
||||
showNotification('上传协议成功');
|
||||
} else {
|
||||
showNotification((res && res.message) || '上传协议失败');
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function uploadFunc(fileList, files) {
|
||||
setFileList(fileList);
|
||||
setFieldsValue({
|
||||
files,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const columns = useMemo(() => {
|
||||
return [
|
||||
{
|
||||
title: '成果物编号',
|
||||
dataIndex: 'paperNumber',
|
||||
},
|
||||
{
|
||||
title: '凭证文件',
|
||||
dataIndex: 'fileName',
|
||||
render: (text, record) => {
|
||||
return <a className="line_1 color-grey3" onClick={() => { download(record.winnerContracts[0].id) }}> {record.winnerContracts && record.winnerContracts[0].fileName}</a >
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'action',
|
||||
render: (text, record) => {
|
||||
return <a className="line_1 color-grey3" onClick={(e) => { download(record.winnerContracts[0].id) }}> 下载凭证</a >
|
||||
}
|
||||
}
|
||||
];
|
||||
}, []);
|
||||
|
||||
function download(id) {
|
||||
window.open(httpUrl + '/busiAttachments/download/' + id);
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<ul className="df mt10 needs_condition_content_nav">
|
||||
<li key={1} className="with35 edu-txt-left">任务</li>
|
||||
<li key={2} className="with15">类型</li>
|
||||
{publish && <li key={3} className="with10 draft_only">应征投稿</li>}
|
||||
<li key={4} className="with10">金额</li>
|
||||
<li key={5} className="flex1">任务状态</li>
|
||||
<li key={6} className="with15">操作</li>
|
||||
</ul>
|
||||
|
||||
{loading ? <Loading /> : <React.Fragment>
|
||||
{
|
||||
list.map(item => {
|
||||
return (
|
||||
<div key={item.id} className="needs_condition_content">
|
||||
<p className="needs_condition_content_t color-dark-grey">
|
||||
任务编号:{item.number}
|
||||
<i className="ml20 mr5 iconfont icon-shijian color-grey9 font-16"></i>
|
||||
{item.createdAt}
|
||||
</p>
|
||||
<ul className="df">
|
||||
<li key={1} className="mytask-title with35 edu-txt-left font-16 font-bd" >
|
||||
<Link className="color-grey3 font-16 font-bd" to={`/task/taskDetail/${item.id}`}>{item.name}</Link>
|
||||
{
|
||||
joinTask ? <React.Fragment>
|
||||
{item.myPaperStatus === 0 && <span className="list_status s_orange ml10">{myPaperStatusArr[item.myPaperStatus]}</span>}
|
||||
{item.myPaperStatus === 1 && <span className="list_status s_grey ml10">{myPaperStatusArr[item.myPaperStatus]}</span>}
|
||||
{item.myPaperStatus === 2 && <span className="list_status s_red ml10">{myPaperStatusArr[item.myPaperStatus]}</span>}
|
||||
|
||||
{item.status === 6 && (item.agreementSigning === 1 || (item.agreementSigning === 2 && item.contractStatus === 1)) && <span className="list_status s_orange ml10">待签订协议</span>}
|
||||
|
||||
{item.status !== 8 && item.delayTime < 0 &&<span className="list_status list-yellow">延期中</span>}
|
||||
{item.status !== 8 && item.cancelStatus === 1 && item.delayTime > 0 && <span className="list_status list-yellow">手动延期中</span>}
|
||||
{item.status !== 8 && item.delayed && item.cancelStatus === 0 && item.delayTime > 0 && item.delayCount>0 &&<span className="list_status list-yellow">系统自动延期中</span>}
|
||||
|
||||
</React.Fragment> : <React.Fragment>
|
||||
{item.status === 6 && (item.agreementSigning === 1 || (item.agreementSigning === 2 && item.auditing && item.auditing.pass === 1)) && <span className="list_status s_orange ml10">待签订协议</span>}
|
||||
|
||||
{item.status !== 8 && item.delayTime < 0 &&<span className="list_status list-yellow">延期中</span>}
|
||||
{item.status !== 8 && item.cancelStatus === 1 && item.delayTime > 0 &&<span className="list_status list-yellow">手动延期中</span>}
|
||||
{item.status !== 8 && item.delayed && item.cancelStatus === 0 && item.delayTime > 0 && item.delayCount>0 && <span className="list_status list-yellow">系统自动延期中</span>}
|
||||
</React.Fragment>
|
||||
}
|
||||
</li>
|
||||
<li key={2} className="with15 flex-column">
|
||||
<span className="line_1">{taskCategoryValueArr[item.categoryId]}</span>
|
||||
<span className="line_1">{publishModeArr[item.publishMode]}</span>
|
||||
</li>
|
||||
|
||||
{publish && <li key={3} className="with10 draft_only">{item.papersCount || 0}</li>}
|
||||
|
||||
<li key={4} className="with10 color-orange">¥{item.bounty}</li>
|
||||
<li className="flex1">
|
||||
<span>
|
||||
<span className="line_1">{item.exceptClosedBoolean ? '已关闭' : statusArr[item.status]}</span>
|
||||
</span>
|
||||
</li>
|
||||
<li key={5} className="with15 flex-column">
|
||||
{
|
||||
joinTask ? <Link className="line_1 color-grey3" to={`/task/taskDetail/${item.id}`}>查看详情</Link>
|
||||
:
|
||||
<React.Fragment>
|
||||
{
|
||||
item.status === 0 || item.status === 9 ?
|
||||
<Link className="line_1 color-grey3" to={`/task/taskEdit/${item.id}`}>编辑草稿</Link> :
|
||||
<Link className="line_1 color-grey3" to={`/task/taskDetail/${item.id}`}>查看详情</Link>
|
||||
}
|
||||
|
||||
{
|
||||
item.status === 4 && item.papersCount > 0 && (!item.isProofBoolean) && (!item.isProofBoolean) &&
|
||||
<a onClick={() => { uploadProofs(item) }} className="line_1 color-blue">上传佐证材料</a>
|
||||
}
|
||||
|
||||
{
|
||||
(!item.isProofBoolean) && (item.taskResultProof && item.taskResultProof.status === 0) &&
|
||||
<a onClick={() => { adviceModal(item.advice) }} className="line_1 color-blue">佐证被拒原因</a>
|
||||
}
|
||||
|
||||
{(item.status === 2 || item.status === 9) && <a onClick={() => { adviceModal(item.repairAdvice) }} className="line_1 color-blue">审核意见</a>}
|
||||
|
||||
{item.status === 6 && item.agreementSigning === 0 && <a className="line_1 color-blue" onClick={() => { signMethodModal(item) }}>选择协议签订方式</a>}
|
||||
|
||||
{item.status === 6 && item.agreementSigning === 2 && (item.contractStatus === null || item.contractStatus === 0) && <a className="line_1 color-blue" onClick={() => { uploadAgree(item) }}>上传委托协议</a>}
|
||||
|
||||
{item.status === 6 && item.agreementSigning === 2 && [1, 2].includes(item.contractStatus) && <a className="line_1 color-grey-9" >已上传委托协议</a>}
|
||||
|
||||
{item.status === 6 && item.agreementSigning === 1 && <span className="line_1 color-grey-9">已选择自主签订协议</span>}
|
||||
|
||||
{item.status === 7 && <span className="line_1 color-grey-9">{item.agreementSigning === 1 ? '待胜出者确认收款' : '待平台上传支付凭证'}</span>}
|
||||
|
||||
{item.status === 7 && <a className="line_1 color-blue" onClick={() => { setDowloadTaskId(item.id); setVisibleDownload(true); }}>下载协议签订凭证</a>}
|
||||
|
||||
</React.Fragment>
|
||||
}
|
||||
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
{list.length > 0 ?
|
||||
<div className="edu-txt-center mt20 mb20">
|
||||
{total > pageSize && <Pagination
|
||||
showQuickJumper
|
||||
onChange={(page) => { changePage(page) }}
|
||||
current={curPage}
|
||||
total={total}
|
||||
showTotal={total => `共 ${total} 条`}
|
||||
/>}
|
||||
</div> :
|
||||
<Nodata _html="暂无数据" />}
|
||||
</React.Fragment>
|
||||
}
|
||||
|
||||
{visibleProofs && <ProofModal
|
||||
taskId={taskId}
|
||||
taskModeId={taskModeId}
|
||||
visible={visibleProofs}
|
||||
changeVisible={setVisibleProofs}
|
||||
showNotification={showNotification}
|
||||
reloadList={reloadList}
|
||||
/>}
|
||||
|
||||
|
||||
<Modal
|
||||
title="选择签订协议方式"
|
||||
visible={visibleMethod}
|
||||
onOk={chooseMethod}
|
||||
onCancel={() => { setVisibleMethod(false) }}
|
||||
className="form-edit-modal"
|
||||
>
|
||||
{
|
||||
helper('method', [{ required: visibleMethod, message: '请选择签订协议的方式' }],
|
||||
<Radio.Group className="vertical-radio">
|
||||
<Radio value={2}>
|
||||
<p>委托平台签订</p>
|
||||
<p className="color-grey-9">以平台名义与评选胜出者签订协议,需要经平台管理员审批需要发布方将奖励经费划归平台,在审核通过后平台自动发送电子协议</p>
|
||||
</Radio>
|
||||
<Radio value={1}>
|
||||
<p>自主签订</p>
|
||||
<p className="color-grey-9">通过线下的方式,以发布方名义与评选胜出者签订协议</p>
|
||||
</Radio>
|
||||
</Radio.Group>)
|
||||
}
|
||||
</Modal>
|
||||
|
||||
|
||||
<Modal
|
||||
title="上传委托协议"
|
||||
visible={visibleAgree}
|
||||
onOk={uploadAgreeList}
|
||||
onCancel={() => { setVisibleAgree(false) }}
|
||||
className="form-edit-modal"
|
||||
>
|
||||
{checkItem.auditing && <p className="color-orange mb10 task_tip">
|
||||
审核意见:{checkItem.auditing.message}
|
||||
</p>}
|
||||
<Form.Item className="upload-form" label="协议上传" required={true}>
|
||||
<Upload
|
||||
load={uploadFunc}
|
||||
size={50}
|
||||
showNotification={showNotification}
|
||||
fileList={fileList}
|
||||
/>
|
||||
{/* 用一个隐藏的input实现上传文件的必填校验 */}
|
||||
{getFieldDecorator('files', {
|
||||
rules: [{ required: visibleAgree, message: "请上传文件" }],
|
||||
validateFirst: true
|
||||
})(<Input style={{ display: 'none' }} />)}
|
||||
</Form.Item>
|
||||
</Modal>
|
||||
|
||||
<Modal
|
||||
title="下载协议签订凭证"
|
||||
visible={visibleDownload}
|
||||
onOk={() => { setVisibleDownload(false) }}
|
||||
onCancel={() => { setVisibleDownload(false) }}
|
||||
className="form-edit-modal"
|
||||
>
|
||||
<Table
|
||||
loading={loading}
|
||||
rowKey={(row) => row.id}
|
||||
dataSource={uploadList}
|
||||
columns={columns}
|
||||
pagination={false}
|
||||
/>
|
||||
|
||||
</Modal>
|
||||
|
||||
</React.Fragment>
|
||||
|
||||
)
|
||||
}
|
||||
)
|
|
@ -0,0 +1,106 @@
|
|||
.needs_condition_content_nav {
|
||||
padding: 0px 20px;
|
||||
background: #f7f7f7;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
color: #656565;
|
||||
text-align: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.needs_condition_content {
|
||||
border: 1px solid #eaeaea;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
|
||||
li {
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
display: -webkit-flex;
|
||||
}
|
||||
|
||||
.mytask-title {
|
||||
justify-content: left;
|
||||
a {
|
||||
word-break: break-all;
|
||||
}
|
||||
span {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list_status {
|
||||
border-radius: 10px;
|
||||
padding: 0px 10px;
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
display: inline-block;
|
||||
color: #fff;
|
||||
background: #fa6400;
|
||||
margin-left: 0.625rem;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.s_orange {
|
||||
background: #ffb121;
|
||||
}
|
||||
|
||||
.s_red {
|
||||
background: #fe0e36;
|
||||
}
|
||||
|
||||
.s_blue {
|
||||
background: #4cacff;
|
||||
}
|
||||
|
||||
.s_grey {
|
||||
background: #bababa;
|
||||
}
|
||||
|
||||
.needs_condition_content_t {
|
||||
height: 40px;
|
||||
padding: 0px 20px;
|
||||
background: #f7f7f7;
|
||||
color: #333;
|
||||
border-bottom: 1px solid #eaeaea;
|
||||
line-height: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-list-box {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 20px;
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #dedede;
|
||||
}
|
||||
|
||||
.flex-column {
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.vertical-radio {
|
||||
.ant-radio-wrapper {
|
||||
display: flex;
|
||||
line-height: 2rem;
|
||||
align-items: flex-start;
|
||||
.ant-radio {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
p {
|
||||
white-space: normal;
|
||||
word-break: break-all;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,297 @@
|
|||
import React, { useEffect, useState, useCallback } from 'react';
|
||||
import { Pagination, Modal, Form, Input, Button } from 'antd';
|
||||
import ReactWEditor from 'wangeditor-for-react';
|
||||
import { timeAgo, getImageUrl } from 'educoder';
|
||||
import Nodata from 'forge/Nodata';
|
||||
import Loading from "src/Loading";
|
||||
import { editorConfig } from 'military/components/config';
|
||||
import AgreementModal from '../agreementModal';
|
||||
import ComplainModal from '../complainModal';
|
||||
import { reportPaper, thumbUpPaper, commentAdd, confirmReceipt } from '../../api';
|
||||
import { paperCheckStatusArr } from '../../static';
|
||||
import { httpUrl } from '../../fetch';
|
||||
import winpng from '../../image/winner.png';
|
||||
import './index.scss';
|
||||
|
||||
const { TextArea } = Input;
|
||||
|
||||
const paperCheckStatus = [];
|
||||
for (const item of paperCheckStatusArr) {
|
||||
paperCheckStatus[item.dicItemCode] = item.dicItemName;
|
||||
}
|
||||
|
||||
export default Form.create()((props) => {
|
||||
const { list, curPage, total, changePage, loading, applyStatusAllNameArr, reloadList, showNotification, current_user, form, detailStatus } = props;
|
||||
const { getFieldDecorator, validateFields, setFieldsValue } = form;
|
||||
const [page, setPage] = useState(1);
|
||||
const pageSize = props.pageSize || 10;
|
||||
const [checkedItem, setCheckedItem] = useState({});
|
||||
const [reportVisible, setReportVisible] = useState(false);
|
||||
const [commentHtml, setCommentHtml] = useState('');
|
||||
|
||||
const [commentId, setCommentId] = useState(undefined);
|
||||
|
||||
const [complainVisible, setComplainVisible] = useState(false);
|
||||
const [agreeVisible, setAgreeVisible] = useState(false);
|
||||
|
||||
|
||||
const [loadingChild, setLoadingChild] = useState(false);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
changePage(page);
|
||||
}, [page]);
|
||||
|
||||
function downFile(item) {
|
||||
let url = httpUrl + '/busiAttachments/download/' + item.id;
|
||||
window.open(url);
|
||||
}
|
||||
|
||||
function report() {
|
||||
validateFields((error, values) => {
|
||||
if (!error) {
|
||||
setLoadingChild(true);
|
||||
reportPaper({
|
||||
paperId: checkedItem.id,
|
||||
content: values.reportValue
|
||||
}).then(res => {
|
||||
if (res && res.message === 'success') {
|
||||
showNotification('举报成功');
|
||||
setReportVisible(false);
|
||||
setFieldsValue({
|
||||
reportValue: '',
|
||||
complainValue: '',
|
||||
});
|
||||
}
|
||||
setLoadingChild(false);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function thumbUp(id) {
|
||||
setLoadingChild(true);
|
||||
thumbUpPaper(id).then(res => {
|
||||
reloadList();
|
||||
setLoadingChild(false);
|
||||
});
|
||||
}
|
||||
|
||||
function commentPush(item) {
|
||||
if (!commentHtml) {
|
||||
showNotification("请输入评价");
|
||||
return;
|
||||
}
|
||||
if (commentHtml.length > 10000) {
|
||||
showNotification("评论过长,请减少评论内容或者简化评论格式");
|
||||
return;
|
||||
}
|
||||
commentAdd({
|
||||
content: commentHtml,
|
||||
paperId: item.id,
|
||||
taskId: item.taskId
|
||||
}).then(res => {
|
||||
if (res.message === 'success') {
|
||||
closeComment();
|
||||
reloadList();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function closeComment() {
|
||||
setCommentId(undefined);
|
||||
setCommentHtml('');
|
||||
}
|
||||
|
||||
function commentEdit(id) {
|
||||
setCommentId(id);
|
||||
setCommentHtml('');
|
||||
}
|
||||
|
||||
function goUser(login) {
|
||||
window.location.href = `/users/${login}`;
|
||||
}
|
||||
|
||||
|
||||
function confirmReceiptModal(paperId) {
|
||||
Modal.confirm({
|
||||
title: '确认收款',
|
||||
content: '确认已经收到任务报酬',
|
||||
onOk: () => {
|
||||
confirmReceipt(paperId).then(res => {
|
||||
if (res && res.message === "success") {
|
||||
showNotification("您已确认收款!");
|
||||
reloadList();
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const helper = useCallback(
|
||||
(name, rules, widget) => (
|
||||
<Form.Item>
|
||||
{getFieldDecorator(name, { rules, validateFirst: true })(widget)}
|
||||
</Form.Item>
|
||||
),
|
||||
[]
|
||||
);
|
||||
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
{loading || loadingChild ? <Loading /> :
|
||||
<React.Fragment>
|
||||
{
|
||||
list.map(item => {
|
||||
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">
|
||||
<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>}
|
||||
</li>
|
||||
<li className="fr">
|
||||
{((item.needComplain && detailStatus === 3) || (detailStatus === 5 && item.publicTaskComplain && item.checkStatus === 1 && item.status !== 2)) && (current_user.login === item.user.login) &&
|
||||
<a className="base_smallBtn blue_line_btn fl" onClick={() => { setComplainVisible(true); setCheckedItem(item) }}>申诉</a>}
|
||||
|
||||
{item.status === 2 && detailStatus === 6 && (current_user.login === item.user.login) && (!item.sign) && (item.canApplicantSign || item.canApplicantSignByPlatform) &&
|
||||
<a className="base_smallBtn blue_line_btn fl" onClick={() => { setAgreeVisible(true); setCheckedItem(item) }}>签订协议</a>}
|
||||
|
||||
{item.status === 2 && detailStatus === 7 && (current_user.login === item.user.login) && (item.task && item.task.agreementSigning === 1) && (!item.isPay) &&
|
||||
<a className="base_smallBtn blue_line_btn fl" onClick={() => { confirmReceiptModal(item.id) }}>确认收款</a>}
|
||||
</li>
|
||||
</ul>
|
||||
<div className="paper-detail-content markdown-body editormd-html-preview editor-w-text" dangerouslySetInnerHTML={{ __html: item.paperDetail ? item.paperDetail.content : '' }}></div>
|
||||
|
||||
<div className="attachments" >
|
||||
{
|
||||
item.paperDetail && item.paperDetail.busiAttachments && item.paperDetail.busiAttachments.map(fileItem => {
|
||||
return <div className="file-list-box" key={fileItem.id}>
|
||||
<a onClick={() => { downFile(fileItem) }}><i className="iconfont icon-fujian color-green font-14 mr3"></i>
|
||||
{fileItem.fileName} </a>
|
||||
<span className="ml10 color-grey-9">({fileItem.fileSizeString})</span>
|
||||
</div>
|
||||
})
|
||||
}
|
||||
</div>
|
||||
|
||||
|
||||
{item.comments && item.comments.length > 0 && <div className="padding20 fileCommentsList">
|
||||
{item.comments.map(commentsItem => {
|
||||
return <div className="comments-item" key={commentsItem.id}>
|
||||
<div className="comments-author">
|
||||
<span className="color-grey3 font-bd mr20">{commentsItem.user.nickname || commentsItem.user.login}</span>
|
||||
<span className="color-grey9">{timeAgo(commentsItem.createdAt)}</span>
|
||||
</div>
|
||||
<div className="editor-w-text comments-content" dangerouslySetInnerHTML={{ __html: commentsItem.details && commentsItem.details.content }}>
|
||||
</div>
|
||||
</div>
|
||||
})
|
||||
}
|
||||
</div>}
|
||||
|
||||
|
||||
<li className="clearfix color-grey-6 mt10 mb20">
|
||||
<span className="mr50 fl"><span className="color-grey9">成果编号:</span>#{item.number}</span>
|
||||
<span className="mr50 fl"><span className="color-grey9">提交时间:</span>{item.createdAt}</span>
|
||||
<span className="fl"><span className="color-grey9">稿件状态:</span>{item.read ? '雇主已浏览' : '雇主未浏览'}</span>
|
||||
{
|
||||
item.user.nickname !== "******" && <span className="fr">
|
||||
{[4, 5].includes(detailStatus) && <a className="mr20" onClick={() => { setReportVisible(true); setCheckedItem(item) }}><i className="iconfont icon-jinggao font-15 mr3"></i>举报</a>}
|
||||
<a className="mr20" onClick={() => { commentEdit(item.id) }}><i className="iconfont icon-huifu1 font-15 mr3"></i>{item.comments ? item.comments.length : 0}</a>
|
||||
<a onClick={() => { thumbUp(item.id) }}><i className="iconfont icon-dianzan11 font-16 mr3"></i>{item.thumbsUp}</a>
|
||||
</span>
|
||||
}
|
||||
|
||||
</li>
|
||||
|
||||
{commentId === item.id && <React.Fragment>
|
||||
<ReactWEditor
|
||||
config={{
|
||||
...editorConfig,
|
||||
placeholder: "请输入评论",
|
||||
}}
|
||||
onChange={(html) => { setCommentHtml(html) }}
|
||||
/>
|
||||
<Button className="mt20 mr20 mb20 fr" type={"primary"} onClick={() => { commentPush(item) }}>发表</Button>
|
||||
<Button className="mt20 mr20 mb20 fr" onClick={closeComment}>取消</Button>
|
||||
</React.Fragment>}
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
{list.length > 0 ?
|
||||
<div className="edu-txt-center mt20 mb20">
|
||||
{total > pageSize && <Pagination
|
||||
showQuickJumper
|
||||
onChange={(page) => { setPage(page) }}
|
||||
current={curPage}
|
||||
total={total}
|
||||
showTotal={total => `共 ${total} 条`}
|
||||
/>}
|
||||
</div> :
|
||||
<Nodata _html="暂无数据" />}
|
||||
</React.Fragment>
|
||||
}
|
||||
|
||||
|
||||
<Modal
|
||||
title="举报"
|
||||
visible={reportVisible}
|
||||
onOk={report}
|
||||
onCancel={() => { setReportVisible(false) }}
|
||||
className="form-edit-modal"
|
||||
>
|
||||
<div className="task-popup-content">
|
||||
<p className="edu-txt-center lineh-20 mb10">你的举报信息将发送给平台管理员</p>
|
||||
<p className="edu-txt-center lineh-20">请如实填写有效的举报原由,我们将尽快完成审核</p>
|
||||
{
|
||||
helper('reportValue', [{ required: reportVisible, message: "(必填)请在此输入发起举报的原因,最大限制100个字符" },
|
||||
{ max: 100, message: '长度不能超过100个字符' }],
|
||||
<TextArea
|
||||
placeholder="(必填)请在此输入发起举报的原因,最大限制100个字符"
|
||||
autoSize={{ minRows: 6 }}
|
||||
className="applyText"
|
||||
/>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
<ComplainModal
|
||||
visible={complainVisible}
|
||||
setVisible={setComplainVisible}
|
||||
checkedItem={checkedItem}
|
||||
detailStatus={detailStatus}
|
||||
showNotification={showNotification}
|
||||
reloadList={reloadList}
|
||||
/>
|
||||
|
||||
{agreeVisible && <AgreementModal
|
||||
paperId={checkedItem.id}
|
||||
checkedItem={checkedItem}
|
||||
visible={agreeVisible}
|
||||
setVisible={setAgreeVisible}
|
||||
showNotification={showNotification}
|
||||
reloadList={reloadList}
|
||||
/>}
|
||||
|
||||
</React.Fragment>
|
||||
|
||||
)
|
||||
}
|
||||
)
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
.blue_line_btn {
|
||||
color: #4cacff !important;
|
||||
border: 1px solid #4cacff;
|
||||
background: #fff !important;
|
||||
}
|
||||
|
||||
.base_smallBtn {
|
||||
color: #ccc;
|
||||
font-size: 14px;
|
||||
background: #ccc;
|
||||
border-radius: 4px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
display: block;
|
||||
width: 100px;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
margin-top: 1.25rem;
|
||||
}
|
||||
|
||||
.fileCommentsList {
|
||||
background: #fafafa;
|
||||
padding-top: .25rem;
|
||||
}
|
||||
|
||||
.comments-item{
|
||||
margin-top:1rem;
|
||||
}
|
||||
.comments-content {
|
||||
text-align: left;
|
||||
font-size: 16px;
|
||||
line-height: 1.6;
|
||||
padding: 20px;
|
||||
overflow: auto;
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.small-head{
|
||||
max-width: 2rem;
|
||||
}
|
||||
|
||||
.clickable:hover{
|
||||
color: #4cacff;
|
||||
cursor: pointer;
|
||||
}
|