diff --git a/package.json b/package.json index 05b98768..4fb71301 100644 --- a/package.json +++ b/package.json @@ -222,7 +222,7 @@ "webpack": "^4.42.1", "webpack-bundle-analyzer": "^3.7.0" }, - "volta":{ - "node":"8.12.0" + "volta": { + "node": "8.12.0" } } diff --git a/src/App.js b/src/App.js index 53d55bc0..b86b837f 100644 --- a/src/App.js +++ b/src/App.js @@ -59,6 +59,11 @@ const Notice = Loadable({ loader: () => import('./military/notice'), loading: Loading, }) +// 成果库 +const Achievement = Loadable({ + loader: () => import('./military/achievement'), + loading: Loading, +}) //任务/需求 const Task = Loadable({ loader: () => import('./military/task'), @@ -156,7 +161,7 @@ const Managements = Loadable({ // }) // 此处仅维护前端可能的一级路由,不用进行项目或者组织判断的字段。 -const keyWord = ["explore", "settings", "setting", "mulan", "wiki", "issues", "setting", "trending", "code", "projects", "pulls", "mine", "login", "register", "email", "export", "nopage", "404", "403", "500", "501", "search", "organize", "login", "register", "resetPassword", "aboutus","educoder","task","notice","managements","expert","competition","administration", "needs"]; +const keyWord = ["explore", "settings", "setting", "mulan", "wiki", "issues", "setting", "trending", "code", "projects", "pulls", "mine", "login", "register", "email", "export", "nopage", "404", "403", "500", "501", "search", "organize", "login", "register", "resetPassword", "aboutus","educoder","task","notice","achievement","managements","expert","competition","administration", "needs"]; class App extends Component { constructor(props) { @@ -176,7 +181,6 @@ class App extends Component { initAxiosInterceptors(this.props); let pathname = window.location.pathname ? window.location.pathname.split('/')[1] : ''; pathname && this.getPathnameType(pathname); - // 添加路由监听,决定组织还是个人 this.unlisten = this.props.history.listen((location,history) => { let newPathname = location.pathname.split('/')[1]; @@ -192,7 +196,7 @@ class App extends Component { return true; } // 阻止个人与组织切换时(组件渲染)请求导致的404 - if (nextProps.location.pathname.split('/')[1] !== this.props.location.pathname.split('/')[1] && nextState.pathType === this.state.pathType) { + if (nextProps.location.pathname.split('/')[1] !== this.props.location.pathname.split('/')[1] && nextState.pathType === this.state.pathType &&!keyWord.includes( this.state.pathType)) { return false; } else { return true; @@ -388,6 +392,15 @@ class App extends Component { } }> + {/*成果*/} + { + return () + } + }> + {/*任务*/} {/*专家评审*/} diff --git a/src/AppConfig.js b/src/AppConfig.js index 6e20bcf2..34432e15 100644 --- a/src/AppConfig.js +++ b/src/AppConfig.js @@ -33,7 +33,8 @@ export function initAxiosInterceptors(props) { initOnlineOfflineListener(); // var proxy = "http://192.168.1.40:3000"; - var proxy = "http://111.8.36.180:8000"; + // var proxy = "http://111.8.36.180:8000"; + var proxy = "http://117.50.100.12:49999"; // var proxy = "https://www.osredm.com"; //响应前的设置 diff --git a/src/components/pagination-table/index.jsx b/src/components/pagination-table/index.jsx index 91647e0b..c9c634da 100644 --- a/src/components/pagination-table/index.jsx +++ b/src/components/pagination-table/index.jsx @@ -8,6 +8,7 @@ export default (props) => { return (
row.id||i} {...props} pagination={false} onRow={handleRow} diff --git a/src/forge/Head/Header.js b/src/forge/Head/Header.js index a7f8219d..5b41c33c 100644 --- a/src/forge/Head/Header.js +++ b/src/forge/Head/Header.js @@ -199,7 +199,8 @@ class NewHeader extends Component { const hostname = window.location.hostname; const port = window.location.port; const isDev = window.location.port == 3007; - let isdev2= isDev ?'http://192.168.1.40:3000':`http://${hostname}`; + let isdev2= isDev ?'http://117.50.100.12:49999':`http://${hostname}`; + console.log(url,isdev2,isDev); let str = ""; if(url.indexOf("http")>-1){ if(url.indexOf("https")>-1){ @@ -326,22 +327,7 @@ class NewHeader extends Component { { settings.navbar && settings.navbar.map((item, key) => { var new_link = item.link; - // var user_login = current_user && current_user.login; var is_hidden = item.hidden; - // if (new_link && (new_link.indexOf("courses") > -1 || new_link.indexOf("contests") > -1)) { - // if (user_login) { - // if (new_link.indexOf("courses") > -1) { - // new_link = new_link.replace(/courses/g, user_login + "/courses") - // } else if (new_link.indexOf("contests") > -1) { - // new_link = new_link.replace(/contests/g, user_login + "/contests") - // } - // } else { - // is_hidden = true - // } - // } - // if (user_login && (new_link && new_link.indexOf("homes") > -1)) { - // new_link = new_link.replace(/homes/g, user_login + "/user_activities") - // } var waiLian = (new_link && str.filter(item=>new_link.indexOf(item)>-1) ); var wl = waiLian && waiLian.length>0; return ( diff --git a/src/forge/Main/Detail.js b/src/forge/Main/Detail.js index e2177f65..393abfc5 100644 --- a/src/forge/Main/Detail.js +++ b/src/forge/Main/Detail.js @@ -395,6 +395,7 @@ class Detail extends Component { forked_count: result.data.forked_count, defaultBranch: result.data.default_branch }) + document.title = `${result.data.author.name}/${result.data.name}${result.data.description?':'+result.data.description:''}`; } }).catch((error) => { }) } diff --git a/src/forge/Order/order_form.js b/src/forge/Order/order_form.js index 205f476f..f4929f9c 100644 --- a/src/forge/Order/order_form.js +++ b/src/forge/Order/order_form.js @@ -36,7 +36,8 @@ class order_form extends Component { show_token: false, cannot_edit: false, issue_current_user: true, - atWhoLoginList:undefined + atWhoLoginList:undefined, + endDisableData:undefined }; } componentDidUpdate=(prevPros)=>{ @@ -276,7 +277,11 @@ class order_form extends Component { changeBeginTime = (start_date, value) => { this.setState({ start_date: value, + endDisableData:c=>c { this.setState({ @@ -347,13 +352,12 @@ class order_form extends Component { }); } }; - render() { const { getFieldDecorator } = this.props.form; const { projectsId , owner } = this.props.match.params; const { orderId } = this.props.match.params; const { form_type } = this.props; - const {issue_chosen,branches,description,get_attachments,isSpin,start_date,due_date} = this.state; + const {issue_chosen,branches,description,get_attachments,isSpin,start_date,due_date,endDisableData} = this.state; return (
@@ -523,6 +527,7 @@ class order_form extends Component { style={{ width: "100%" }} placeholder="请选择结束日期" onChange={this.changeEndTime} + disabledDate={endDisableData} /> diff --git a/src/forge/users/Infos.js b/src/forge/users/Infos.js index cae6e5c9..ed9d5ef6 100644 --- a/src/forge/users/Infos.js +++ b/src/forge/users/Infos.js @@ -136,6 +136,7 @@ class Infos extends Component { isSpin: false, undo_events:e }); + document.title = result.data.username+'('+ username +')'; }) .catch((error) => { this.setState({ @@ -238,9 +239,9 @@ class Infos extends Component { { user && user.gender===1? - - : + : + } diff --git a/src/managements/achievement/api.js b/src/managements/achievement/api.js new file mode 100644 index 00000000..746e256b --- /dev/null +++ b/src/managements/achievement/api.js @@ -0,0 +1,80 @@ +import fetch from 'military/achievement/fetch'; +import showNotification from '../components/ShowNotification'; + + +// 成果列表查询 +export async function getNoticeList(params) { + let res = await fetch({ + url: '/api/announcements/', + method: 'get', + params, + }); + if (res.message === 'success') { + return res.data; + } else { + showNotification(res.message || '请求错误'); + } +} + +//新增成果 +export function addNotice(data) { + return fetch({ + url: '/api/announcements/add', + method: 'post', + data: data + }); +} + +//删除成果 +export function deleteNotice(id) { + return fetch({ + url: '/api/announcements/' + id, + method: 'DELETE', + }); +} + +//更新成果 +export function editNotice(data) { + return fetch({ + url: '/api/announcements/update', + method: 'put', + data: data + }); +} + +//审核成果 +export function checkNotice(data) { + return fetch({ + url: '/api/announcements/check', + method: 'put', + data: data + }); +} + +// 成果详情查询 +export async function getNoticeDetail(id) { + let res = await fetch({ + url: '/api/announcements/' + id, + method: 'get', + }); + if (res.data) { + return res.data; + } else { + showNotification(res.message || '请求错误'); + } +} + +// 成果密文查看人详情 +export async function getNoticeReader(params) { + let res = await fetch({ + url: '/api/request_contact_reader_info/', + method: 'get', + params, + }); + if (res.data) { + return res.data; + } else { + showNotification(res.message || '请求错误'); + } +} + diff --git a/src/managements/achievement/index.jsx b/src/managements/achievement/index.jsx new file mode 100644 index 00000000..99d523c4 --- /dev/null +++ b/src/managements/achievement/index.jsx @@ -0,0 +1,67 @@ +import React from "react"; +import { Route, Switch } from "react-router-dom"; +import Loadable from "react-loadable"; +import Loading from "../../Loading"; + +// 成果管理 +const NoticeList = Loadable({ + loader: () => import("./noticeList"), + loading: Loading, +}); +// 成果管理详情 +const NoticeDetail = Loadable({ + loader: () => import("./noticeDetail"), + loading: Loading, +}); +// 成果管理编辑 +const NoticeEdit = Loadable({ + loader: () => import("./noticeEdit"), + loading: Loading, +}); +// 成果reader +const NoticeReader = Loadable({ + loader: () => import("./noticeReader"), + loading: Loading, +}); + +export default (propsF)=>{ + return ( + + {/* 成果列表 */} + ( + + )} + > + {/* 成果详情 */} + ( + + )} + > + {/* 成果编辑 */} + ( + + )} + > + {/* 成果新增 */} + ( + + )} + > + {/* 成果预览 */} + ( + + )} + > + + ) +} \ No newline at end of file diff --git a/src/managements/achievement/index.scss b/src/managements/achievement/index.scss new file mode 100644 index 00000000..cdc786eb --- /dev/null +++ b/src/managements/achievement/index.scss @@ -0,0 +1,60 @@ +.notice-content { + min-height: 50vh; + margin: 1em; + background: #fff; + border-radius: 1em; + box-shadow: 0 1px 2px #d9d9d9; + padding-bottom: 1vh; +} + +.notice-title { + padding: 0.75em; + border-bottom: 1px solid #e5e5e5; +} + + + +.my-search-button{ + margin-top:4px; +} + +.encrypt-item{ + margin-top: -24px; +} + +.encrypt-item .ant-form-item-label{ + visibility: hidden; +} + +.ant-radio-checked .ant-radio-inner{ + border-color: #4154f1; +} +.ant-radio-inner::after{ + background-color: #4154f1; +} +.ant-radio-wrapper:hover .ant-radio, .ant-radio:hover .ant-radio-inner, .ant-radio-input:focus + .ant-radio-inner{ + border-color: #4154f1; +} +.ant-radio-checked::after{ + border: 1px solid #4154f1; +} + +.but41_fill { + color: white; + background-color: #4154f1; + &:hover { + background-color: #5d6eff; + } + &:active { + background-color: #374bf2; + } +} + +.importFile{ + margin:30px auto; + text-align: center; +} +.mess.fail span{ + color: #f5222d; + margin:0 4px; +} \ No newline at end of file diff --git a/src/managements/achievement/noticeDetail/index.jsx b/src/managements/achievement/noticeDetail/index.jsx new file mode 100644 index 00000000..5ba85460 --- /dev/null +++ b/src/managements/achievement/noticeDetail/index.jsx @@ -0,0 +1,91 @@ +import React, { useCallback, useEffect, useState } from 'react'; +import { Button, Descriptions, Icon } from 'antd'; +import ShowNotification from '../../components/ShowNotification'; +import { noticeChecked } from '../../common/static'; +import { achieveSource, achieveType } from 'military/achievement/static'; +import { getNoticeDetail, checkNotice } from '../api'; +import '../index.scss'; +import './index.scss'; + +const achieveSourceArr = []; +for (const item of achieveSource) { + achieveSourceArr[item.code] = (item.name); +} +const achieveTypeArr = []; +for (const item of achieveType) { + achieveTypeArr[item.code] = (item.name); +} +const noticeCheckedArr = []; +for (const item of noticeChecked) { + noticeCheckedArr[item.code] = (item.name); +} + +const IndexPage = ({ match, history, current_user: { admin } }) => { + const [noticeData, setNoticeData] = useState({}); + const id = match.params.noticeId; + + useEffect(() => { + id && getNoticeDetail(id).then(data => { + setNoticeData(data || {}); + }) + }, [id]); + + // 审核 + function checkItem(isChecked) { + checkNotice({ + id: noticeData.id, + isChecked, + }).then(res => { + if (res && res.code == '1') { + ShowNotification("操作成功"); + history.go(-1); + } else { + ShowNotification(res.message || "操作失败"); + history.go(-1); + } + }) + } + + function download(url) { + if (window.location.href.indexOf('localhost') > -1) { + url = 'http://106.75.31.211:58088' + url; + } + window.open(url); + } + + return ( +
+

{ history.go(-1) }}>返回成果详情

+ + + {noticeData.status == 1 ? noticeCheckedArr[noticeData.isChecked] : '草稿'} + {noticeData.title} + {achieveSourceArr[noticeData.achievementSource]} + {achieveTypeArr[noticeData.achievementCategory]} + {noticeData.publisher} +
+ {noticeData.achievementIntro} +
') }}>
+ +
{ download(noticeData.fileDownloadPath) }}>{noticeData.fileName}
+
+ {noticeData.createdAt} + {noticeData.publishDate && {noticeData.publishDate}} + {/* {noticeData.closingDate} */} + + {admin && noticeData.status == 1 && noticeData.isChecked == 2 && + + + + + + } + +
+ +
+ ) +} + + +export default IndexPage; diff --git a/src/managements/achievement/noticeDetail/index.scss b/src/managements/achievement/noticeDetail/index.scss new file mode 100644 index 00000000..094d94ce --- /dev/null +++ b/src/managements/achievement/noticeDetail/index.scss @@ -0,0 +1,22 @@ +.itemContent { + padding: 10px 10px 0 30px; +} +.statusColor{ + color: #1890ff; +} +.alignTop{ + display: flex; + align-items: flex-start; +} +.backList{ + margin-right:1em; + &:hover{ + color: #1890ff; + } +} + +:global{ + .ant-descriptions-item-label{ + min-width: 5em; + } +} diff --git a/src/managements/achievement/noticeEdit/index.jsx b/src/managements/achievement/noticeEdit/index.jsx new file mode 100644 index 00000000..fe170620 --- /dev/null +++ b/src/managements/achievement/noticeEdit/index.jsx @@ -0,0 +1,391 @@ +import React, { Fragment, useCallback, useEffect, useState } from 'react'; +import ReactWEditor from 'wangeditor-for-react'; +import { Form, Input, Button, Radio, Checkbox, Modal, Upload } from 'antd'; +import cookie from 'react-cookies'; +import { achieveSource, achieveType } from 'military/achievement/static'; +import ShowNotification from '../../components/ShowNotification'; +import { getNoticeDetail, addNotice, editNotice } from '../api'; +import { httpUrl } from 'military/achievement/fetch'; +import { Info } from 'military/components/ModalFun'; +import UploadMine from 'military/components/Upload'; + +import '../index.scss'; +const format = "YYYY-MM-DD HH:mm:ss"; +const { TextArea } = Input; + +let actionUrl = httpUrl; + +const NoticeEdit = Form.create()(({ form, match, history, showNotification }) => { + + const [fileList, setFileList] = useState(null); + const [noticeHtml, setNoticeHtml] = useState(''); + const id = match.params.noticeId; + const { getFieldDecorator, validateFields, setFieldsValue } = form; + const [typeValue, setTypeValue] = useState(4); + const [isSecret, setIsSecret] = useState(); + const [visible, setVisible] = useState(false); + + useEffect(() => { + id && getNoticeDetail(id).then(data => { + const formValue = { + type: data.type, + achievementSource: data.achievementSource, + achievementCategory: data.achievementCategory, + achievementIntro: data.achievementIntro, + title: data.title, + publisher: data.publisher, + text: data.text, + contactInfo: data.contactInfo, + }; + setFieldsValue(formValue); + setNoticeHtml(data.text || ''); + setIsSecret(Boolean(data.isSecret)); + if (data.fileName) { + setFileList([{ + name: data.fileName, + fileName: data.fileName, + fileDownloadPath: data.fileDownloadPath, + uid: "rc-upload" + data.id + }]) + } + }) + }, [id]); + + // 上传附件后得到的文件数组 + function UploadFunc(fileList) { + setFileList(fileList); + } + + const helper = useCallback( + (label, name, rules, widget, initialValue) => ( + + {getFieldDecorator(name, { rules, initialValue, validateFirst: true })(widget)} + + ), + [] + ); + + const editor = useCallback(() => ( + + {(!id || (id && noticeHtml)) && + { + changeHtml(html); + }} + />} + + {getFieldDecorator('text', { + rules: [{ required: true, message: "请输入成果描述" }], + validateFirst: true + })()} + + ), [noticeHtml]) + + const formItemLayout = { + labelCol: { + xs: { span: 10 }, + sm: { span: 8 }, + lg: { span: 3 }, + }, + wrapperCol: { + xs: { span: 14 }, + sm: { span: 16 }, + lg: { span: 16 }, + }, + }; + + const tailFormItemLayout = { + wrapperCol: { + xs: { + span: 20, + offset: 4, + }, + sm: { + span: 20, + offset: 4, + }, + }, + }; + + // 修改 + function saveItem(status) { + validateFields((error, values) => { + if (!error) { + let params = { + ...values, + status, + fileDownloadPath: '', + fileName: '', + templateUrl: '', + type: 7 + }; + params.isSecret = Number(params.isSecret); + if (fileList && fileList.length) { + params.fileName = fileList[0].fileName || fileList[0].response.data.fileName; + params.fileDownloadPath = fileList[0].fileDownloadPath || `${actionUrl}/busiAttachments/download/${fileList[0].response.data.id}`; + } + if (id) { + // 编辑 + params.id = id; + editNotice(params).then(res => { + if (res.message === 'success') { + ShowNotification("操作成功!"); + if (status == 1) { + history.push('/managements/achievement/list/1'); + } else { + history.push('/managements/achievement/list/draft'); + } + } else { + ShowNotification(res.message); + } + }); + } else { + // 新增 + addNotice(params).then(res => { + if (res.message === 'success') { + ShowNotification("成果新增成功!"); + if (status == 1) { + history.push('/managements/achievement/list/1'); + } else { + history.push('/managements/achievement/list/draft'); + } + } else { + ShowNotification(res.message); + } + }); + } + } + }) + } + + + function changeHtml(html) { + setFieldsValue({ + text: html + }); + // setNoticeHtml(html); + } + + function beforeUpload(file) { + const isExcel = file.type.indexOf('xlsx') || file.type.indexOf('xls') || file.type.indexOf('sheet'); + if (!isExcel) { + showNotification(`只支持.xlsx、xls格式!`); + } + return isExcel; + } + + function handleChange(info) { + if (info.file.status === 'uploading' || info.file.status === 'done') { + if (info.file.response) { + let resData = info.file.response.data; + if (resData) { + Info({ + title: '提示', + content:
+
执行成功!
+ {resData.successMessages &&
+

导入成功:

+
} + {resData.failMessages &&
+

导入失败:

+

+
} +
, + }); + setVisible(false); + } else { + setVisible(false); + showNotification(info.file.response.message || '系统错误'); + } + } + } + if (info.file.status === 'error') { + showNotification(info.file.response.message || '系统错误'); + } + } + + + const upload = { + name: 'file', + action: `${httpUrl}/api/announcements/importAchievementByExcel`, + onChange: handleChange, + beforeUpload: beforeUpload, + size: 10, + accept: ".xlsx,.xls", + showUploadList: true, + withCredentials: true, + headers: { + Authorization: cookie.load('autologin_trustie') || sessionStorage.osredmToken, + }, + }; + + const urlHost = window.location.host; + return ( +
+

{id ? '修改' : '发布'}成果

+ +
+ + {helper( + "成果来源:", + "achievementSource", + [{ required: true, message: "请选择成果类型" }], + { setTypeValue(e.target.value) }} + > + { + achieveSource.map(item => { + return {item.name} + }) + } + + )} + + {helper( + "成果类型:", + "achievementCategory", + [{ required: true, message: "请选择成果类型" }], + { setTypeValue(e.target.value) }} + > + { + achieveType.map(item => { + return {item.name} + }) + } + + )} + + {helper( + "成果名称:", + "title", + [{ required: true, message: "请输入成果名称" }, + { max: 255, message: '长度不能超过255个字符' }], + + )} + + + {editor()} + + {helper( + "发布单位:", + "publisher", + [{ required: true, message: "请输入发布单位" }, + { max: 255, message: '长度不能超过255个字符' }], + + )} + + {helper( + "联系人:", + "achievementIntro", + [{ max: 255, message: '长度不能超过255个字符' }], + + )} + + + {helper( + "联系方式:", + "contactInfo", + [{ max: 5000, message: '长度不能超过5000个字符' }], +