diff --git a/src/glcc/api.js b/src/glcc/api.js index 89e8e5694..e2afd8d58 100644 --- a/src/glcc/api.js +++ b/src/glcc/api.js @@ -96,4 +96,18 @@ export function getTaskById(id) { url: `/api/applyInformation/task/${id}`, method: 'get' }); +} + +// 学生报名列表查询 +export async function getStudentList(params) { + let res = await fetch({ + url: '/api/studentApply/list', + method: 'get', + params, + }); + if (res.message === 'success') { + return res.data; + } else { + showNotification(res.message || '请求错误'); + } } \ No newline at end of file diff --git a/src/glcc/check/index.jsx b/src/glcc/check/index.jsx new file mode 100644 index 000000000..9b80f3918 --- /dev/null +++ b/src/glcc/check/index.jsx @@ -0,0 +1,401 @@ +import React, { Fragment, useEffect, useState } from 'react'; +import { Checkbox, Input, message, Modal, Table, Tooltip, Breadcrumb, Tabs } from 'antd'; +import { Link } from 'react-router-dom'; +import moment from 'moment'; +import checkTabs from '../img/check_tabs.png'; +import './index.scss'; +import { cancelTaskApply, getStudentList } from '../api'; +// import ProjectDetail from '../component/projectDetail'; +const { TabPane } = Tabs; + + + + +const defaultTask = [{ + "id": 389, + "regId": 49, + "taskName": "日程表", + "taskDesc": "根据日程提示天气信息", + "taskDifficulty": 1, + "taskUrl": "https://testforgeplus.trustie.net/postman/calendar", + "taskReward": "9000", + "tutorName": "Floraachy", + "tutorMail": "1622042529@qq.com", + "tutorPhone": "13429151223", + "projectName": "天气助手-测试项目", + "projectType": "测试", + "createdOn": "2022-06-02 10:38:27", + "sortNo": 0 +}, +{ + "id": 386, + "regId": 47, + "taskName": "添加新的神经形态数据集:ES-UCF101、HARDVS与N-Car", + "taskDesc": "在SJ中,存在大量神经元数据集,用于原生支持SNN。神经形态数据集可以参考:https://spikingjelly.readthedocs.io/zh_CN/latest/spikingjelly.datasets.htmlES-UCF101数据集可以参考以下论文:https://arxiv.org/pdf/1212.0402.pdfHARDVS数据集可以参考如下repo与论文:https://github.com/Computational-Imaging-Lab-IITM/HAR-DVShttps://arxiv.org/pdf/1803.04667.pdf技能要求:Python预期完成效果:在SpikingJelly中可正常调用这一模块", + "taskDifficulty": 1, + "taskUrl": "https://www.gitlink.org.cn/ridger/spikingjelly/issues/60663", + "taskReward": "6000", + "tutorName": "朱芮捷", + "tutorMail": "chenyh@csxjy.com.cn", + "tutorPhone": null, + "projectName": "SpikingJelly惊蛰脉冲神经网络框架", + "projectType": "人工智能", + "createdOn": "2022-05-27 09:23:59", + "sortNo": 0 +}, +{ + "id": 379, + "regId": 46, + "taskName": "Verilog netlist网表解析和扫描链生成", + "taskDesc": "1、题目描述扫描设计是数字电路可测试性设计的基础和通用技术,将逻辑电路中的触发器(或锁存器)转换为扫描单元(Scan Cell),并将所有扫描单元串接成若干移位寄存器,称之为扫描链(Scan Chain),扫描链的输入端是扫描输入管脚,其输出端是扫描输出管脚,从而将同步时序电路转换成内部状态可控制和可观测的时序电路进行测试。该赛题要求在同步时序电路的网表上实现扫描链的自动插入。2、编码任务参考openDACS/ICTest开源的Fault Simulator的Verilog netlist网表解析器,优化网表解析速度、识别触发器单元、完成扫描触发器的替换、根据扫描链的配置输入在网表中自动插入扫描链,并生成扫描结构描述文件、以及可仿真扫描链功能的Testbench。3、技能要求和编程语言熟悉Verilog硬件描述语言,具备数字电路课程基础,C++编程能力强4、预期完成结果预期在出题方提供的不同规模的网表电路上完成扫描链的自动插入,并自动生成扫描结构描述文件、插入扫描链后的网表电路、以及可仿真扫描链功能的Testbench,使用openDACS/ICTest开源的Fault Simulator可正常完成扫描链功能的仿真。根据程序功能的完整性、文档和代码的规范性、程序的性能(网表解析和扫描链插入的速度)确定优胜者。", + "taskDifficulty": 1, + "taskUrl": "https://www.gitlink.org.cn/opendacs/ictest/issues/60879", + "taskReward": "6000", + "tutorName": "叶靖", + "tutorMail": "chenyh@csxjy.com.cn", + "tutorPhone": null, + "projectName": "openDACS开源电路与系统设计自动化", + "projectType": "开发工具", + "createdOn": "2022-05-27 09:23:58", + "sortNo": 0 +}]; +// 课题列表 +function Check({ applyTaskId, setStudentInfoReset, current_user, showLoginDialog, isStudentApplyDate, studentApplyEnd, cancelCount, showNotification }) { + const [visible, setVisible] = useState(false); + const [deleteTaskId, setDeleteTaskId] = useState(undefined); + // 输入搜索框 + const [keyword, setKeyword] = useState(undefined); + const [data, setData] = useState([]); + // table + const [current, setCurrent] = useState(1); + const [total, setTotal] = useState(0); + const [pageSize, setPageSize] = useState(20); + const [loading, setLoading] = useState(false); + const [expandedRowKeys, setExpandedRowKeys] = useState([]); + + const [taskList, setTaskList] = useState(defaultTask); + const [taskId, setTaskId] = useState(defaultTask[0].id); + + const columns = [ + { + title: '学生姓名', + className: "taskTableColumns", + dataIndex: 'studentName', + key: 'studentName', + width: '9%', + ellipsis: true, + render: (text, record) => { + return ( + + {text} + + ); + }, + }, + { + title: '报名时间', + key: 'createdOn', + dataIndex: 'createdOn', + className: "taskTableColumns", + width: '10%', + render: (text, record) => { + return ( + text && moment(text).format('YYYY-MM-DD') + ); + }, + }, + { + title: '所在高校', + key: 'school', + dataIndex: 'school', + className: "taskTableColumns", + width: '14%', + ellipsis: true, + render: (text, record) => { + return ( + + {text} + + ); + }, + }, + { + title: '联系电话', + key: 'phone', + dataIndex: 'phone', + className: "taskTableColumns", + width: '12%', + ellipsis: true, + render: (text, record) => { + return ( + + {text} + + ); + }, + }, + { + title: '邮箱地址', + key: 'mail', + dataIndex: 'mail', + className: "taskTableColumns", + width: '15%', + ellipsis: true, + render: (text, record) => { + return ( + + {text} + + ); + }, + }, + { + title: '申请自荐书', + key: 'memo', + dataIndex: 'memo', + className: 'taskTableColumns', + ellipsis: true, + width: '20%', + render: (text, record) => { + return ( + + {text} + + ); + }, + }, + { + title: '操作', + dataIndex: 'action', + align: 'center', + width: '20%', + className: "actionColumns taskTableColumns", + render: ((text, item, index) => { + return ( +
+ {(isStudentApplyDate || studentApplyEnd) && (applyTaskId && Object.keys(applyTaskId).includes(item.id.toString()) ? + { window.location.href = `/glcc/student/apply/${item.id}` }}>报名详情 + { deleteItem(item.id) }}> + : isStudentApplyDate && + { applyTask(item.id) }}>申请课题)} +
+ ) + }) + }, + ] + + function deleteItem(id) { + if (cancelCount == 1) { + showNotification("您的取消报名次数已用光,请联系导师处理相关报名审核信息"); + } else { + setDeleteTaskId(id); + setVisible(true); + } + } + + const customExpandIcon = (props) => { + if (props.expanded) { + return { + props.onExpand(props.record, e); + }}>更多详情 + } else { + return { + props.onExpand(props.record, e); + }}>更多详情 + } + } + + const expandRow = (record) => { + return
+
+ {(record.grade || record.profession) &&
+ 所学专业 + {record.grade} | {record.profession} +
} + {record.location &&
+ 所在地区 + {record.location} +
} +
+ + {record.memoAttachment &&
+
+ 自荐书附件 + { + window.open( + `${window.location.href.indexOf('localhost') > -1 + ? 'https://testglcc.trustie.net' + : '' + }/busiAttachments/download/${record.memoAttachment.id}`, + ); + }} + > + {record.memoAttachment.fileName} + +
+
} + + {record.proveAttachmentId&&
+
+ 学生证明 + -1 || + window.location.href.indexOf('localhost') > -1 + ? 'https://testforgeplus.trustie.net' + : 'https://www.gitlink.org.cn' + }/api/attachments/${record.proveAttachmentId}`} + > +
+
} +
+ } + + + // 展开收起行回调 + function onExpand(expanded, record) { + const keys = new Set(expandedRowKeys); + if (expanded) { + keys.add(record.id); + } else { + keys.delete(record.id); + } + setExpandedRowKeys(Array.from(keys)); + } + + // 申请课题按钮点击函数 + function applyTask(id) { + // 判断用户是否已经登录 + if (current_user && current_user.login) { + // 判断用户是否已经报名两个课题 + if (applyTaskId && Object.keys(applyTaskId).length >= 2) { + message.error('最多只能同时报名两个课题'); + } else { + // 跳转到学生报名页 + window.location.href = `/glcc/student/apply/${id}`; + } + } else { + showLoginDialog(); + } + } + + // 取消课题按钮点击函数 + function cancelApply() { + const id = []; + id.push(applyTaskId[deleteTaskId]); + const params = { + ids: id + } + // cancelTaskApply(params).then(response => { + // if (response && response.message === "success") { + // setVisible(false); + // setStudentInfoReset(Math.random()); + // message.success('取消成功'); + // } + // }) + } + + // 改变pagesize + function onShowSizeChange(current, pageSize) { + window.scrollTo(0, 0); + setCurrent(1); + setPageSize(pageSize); + } + + // 切换页数 + function changePage(page, pageSize) { + window.scrollTo(0, 0); + setCurrent(page); + } + + // 数组元素置顶方法 + function toFirst(data, index) { + if (index != 0) { + data.unshift(data.splice(index, 1)[0]); + } + } + + useEffect(() => { + setExpandedRowKeys([]); + setLoading(true); + const params = { + curPage: 1, + pageSize: 10, + keyword: '', + // taskId, + // userId: current_user.user_id + } + getStudentList(params).then(res => { + console.log(res.rows); + if (res && Array.isArray(res.rows)) { + setData(res.rows); + setTotal(res.total); + } + setLoading(false); + }) + }, []) + + return ( +
+
+ + 开源夏令营 + 课题及项目列表 + 学生报名 + +
+

申请说明:

+
1、欢迎进入导师审核页!各位导师可查看到您发布课题的全部学生报名信息
+
2、您可根据学生报名信息与学生进行邮箱或电话沟通了解学生详细情况,选择满意的学生
+
3、每个课题仅允许审核通过一个学生,在审核过程中,您可以随时调整各学生的审核状态
+
4、请各位导师在7.1日前完成课题申请的审核,7.1日将根据各导师审核信息,公布各课题学生入选名单
+
+ + setTaskId(e)} activeKey={taskId + ''}> + { + taskList.map((item, i) => { + return + {item.taskName} + + }) + } + + +
+
+
+ + + { setVisible(false) }} + onOk={cancelApply} + wrapClassName='cancelApplyTask' + > +
!确定取消申请此课题?
+

取消申请后将删除此条申请记录。你仅有 {2 - cancelCount} 次取消申请的机会

+
+ + + + ) +} +export default Check; \ No newline at end of file diff --git a/src/glcc/check/index.scss b/src/glcc/check/index.scss new file mode 100644 index 000000000..fe221b216 --- /dev/null +++ b/src/glcc/check/index.scss @@ -0,0 +1,215 @@ +.glcc-check { + .task-tabs { + border: 1px solid #fff; + border-bottom: 0; + margin-top: 30px; + .ant-tabs-nav-container { + background-color: #3758de; + } + } + .ant-tabs-nav .ant-tabs-tab { + padding: 14px 0px; + color: #fff; + margin-right: 64px; + } + .ant-tabs-nav-scroll { + margin-left: 64px; + } + .ant-tabs-nav .ant-tabs-tab-active { + color: #fff; + } + .ant-tabs-bar { + border: 0; + margin: 0; + } + .ant-tabs-ink-bar { + background: #fff; + } + .ant-tabs-tab-prev, + .ant-tabs-tab-next { + width: 163px; + background: url("../img/check_tabs.png") no-repeat; + background-size: 100% 100%; + opacity: 1; + + & > span { + display: none; + } + } + + .ant-tabs-tab-next { + transform: rotate(180deg); + right: 0; + } + + .ant-tabs-tabpane { + padding:0 25px; + } + + .ant-tabs-content { + padding:25px 0; + } + .taskList { + padding:0px 25px 50px 25px; + border-left: 1px solid white; + border-right: 1px solid white; + border-bottom: 1px solid white; + + .line{ + margin: 0 auto 25px; + height: 1px; + border-top: 1px dashed #bec5d5; + } + + .ant-pagination-item-active, + .ant-pagination-item:hover, + .ant-pagination-next:not(.ant-pagination-disabled) + .ant-pagination-item-link:hover, + .ant-select-selection:hover, + .ant-pagination-options-quick-jumper:hover input { + border-color: #466aff; + a { + color: #466aff; + } + } + .ant-pagination-disabled .ant-pagination-item-link:hover .anticon { + color: rgba(0, 0, 0, 0.25); + } + } + .taskTableColumns span div span { + font-size: 16px; + font-weight: 700; + color: #273778; + } + .taskTableColumns span { + font-size: 15px; + color: #353f5e; + } + .ant-table-tbody .taskTableColumns.taskName span { + color: #2545c9; + cursor: pointer; + } + .ant-table-tbody > tr > .taskTableColumns { + background-color: #f1f6ff; + border-bottom: 1px dashed #bec5d5; + } + .ant-table-thead > tr > .taskTableColumns { + background: #e6ecff; + } + .ant-table-tbody + > tr:hover:not(.ant-table-expanded-row):not(.ant-table-row-selected) + > .taskTableColumns { + background-color: #fbfbfc; + } + .actionColumns { + display: flex; + .actionBox, + .actionBox span { + cursor: pointer; + color: #466aff; + &:hover { + color: #5d7cff !important; + } + &:active { + color: #1140ff !important; + } + } + .applyTask, + span.applyTask { + color: #eb9350; + &:hover { + color: #ffb074 !important; + } + &:active { + color: #d66a17 !important; + } + } + .cancelApply { + visibility: hidden; + } + } + tr:hover .actionColumns .cancelApply { + visibility: visible; + color: #e31e1e; + } + .cancelApplyTask { + .ant-modal-close { + top: 0px !important; + } + .ant-modal-header { + padding: 8px 20px; + background-color: #e9edff; + .ant-modal-title { + text-align: left; + } + } + .carefulIcon { + width: 36px; + height: 36px; + background: #ca0002; + display: inline-block; + border-radius: 50%; + text-align: center; + line-height: 36px; + font-size: 18px; + color: white; + margin-right: 15px; + } + .tilTask { + color: #333333; + font-size: 16px; + margin-left: 35px; + } + .tipTask { + color: #666666; + font-size: 14px; + margin: 10px 0 30px 86px !important; + } + .tipTaskTime { + font-size: 36px; + color: #df0002; + } + .ant-modal-footer { + border-top: none; + text-align: center; + padding-bottom: 50px; + .ant-btn { + &.ant-btn-default { + color: #df0002; + } + &:hover { + border-color: #466aff; + color: #466aff; + &.ant-btn-default { + border-color: #df0002; + color: #df0002; + } + } + } + .ant-btn-default { + margin-left: 43px; + } + } + } + + .ant-table-expanded-row td { + padding: 0; + } + .student-expand { + padding:23px; + opacity: 80%; + background-color: #e9efff; + border: 1px solid #ffffff; + + .info-line{ + line-height: 44px; + display: flex; + } + .info-tit{ + display: inline-block; + width: 6em; + margin-right: 18px; + text-align: right; + } + } +} diff --git a/src/glcc/home/index.jsx b/src/glcc/home/index.jsx index 8b62aa127..33ca2fb42 100644 --- a/src/glcc/home/index.jsx +++ b/src/glcc/home/index.jsx @@ -37,6 +37,10 @@ export default (props) => { } } + function goToCheck(){ + history.push("/glcc/check"); + } + return (
{/* */} @@ -66,6 +70,14 @@ export default (props) => {
选择感兴趣的课题,开启您的开源之旅
+ {/* 导师审核 */} +
+
+ + 导师审核 +
+
以赛代筛,挖掘高潜力人才
+
{/* */}
diff --git a/src/glcc/home/index.scss b/src/glcc/home/index.scss index d7b5c4486..4a77cd2fc 100644 --- a/src/glcc/home/index.scss +++ b/src/glcc/home/index.scss @@ -41,6 +41,10 @@ flex-direction: column; justify-content: center; width: 355px; + + &:not(:first-child){ + margin-left: 35px; + } .til{ margin-left: 10px; font-family:PingFang SC; @@ -71,9 +75,7 @@ } } } - .apply:last-child{ - margin-left: 35px; - } + .applyIcon{ width: 30px; } diff --git a/src/glcc/img/check_tabs.png b/src/glcc/img/check_tabs.png new file mode 100644 index 000000000..0787b6080 Binary files /dev/null and b/src/glcc/img/check_tabs.png differ diff --git a/src/glcc/index.jsx b/src/glcc/index.jsx index 0078dfcf1..607cde8ee 100644 --- a/src/glcc/index.jsx +++ b/src/glcc/index.jsx @@ -31,11 +31,16 @@ const Help = Loadable({ loader: () => import("./help"), loading: Loading, }); -// 任务管理审核 +// 学生报名课题 const Student = Loadable({ loader: () => import("./student"), loading: Loading, }); +// 教师审核学生 +const Check = Loadable({ + loader: () => import("./check"), + loading: Loading, +}); // 开源夏令营项目、课题列表页面 const Project = Loadable({ @@ -96,6 +101,13 @@ const Glcc = (propsF) => { )} > + {/* 教师审核 */} + ( + + )} + > {/* 帮助中心 */}