diff --git a/web/client/src/sections/humanAffairs/components/importPositionRating.jsx b/web/client/src/sections/humanAffairs/components/importPositionRating.jsx
new file mode 100644
index 0000000..0c5dba7
--- /dev/null
+++ b/web/client/src/sections/humanAffairs/components/importPositionRating.jsx
@@ -0,0 +1,213 @@
+'use strict';
+import React, { useState, useEffect } from 'react';
+import { Modal, Form, Button, Notification, Toast } from '@douyinfe/semi-ui';
+import { IconUpload } from '@douyinfe/semi-icons';
+import XLSX from 'xlsx';
+
+const IMPORT_FIELD = {
+ userCode: { label: "员工编号" },
+ ratingTime: { label: "评级时间" },
+ theoryBasicScore: { label: "理论基础测评成绩" },
+ theoryPassed: { label: "理论基础测评是否通过(≥60)" },
+ totalScore: { label: "评级总成绩" },
+ totalRatingPassed: { label: "评级总成绩是否通过(K≥60)" },
+ technicalGrade: { label: "技术职级等级" }
+}
+const SHEETNAME = "岗位评级";
+
+const ImportPositionRatingModal = props => {
+ const { onCancel, user, memberList } = props;
+ const [msg, setMsg] = useState('');
+ const [loading, setLoading] = useState('');
+ const [postData, setPostData] = useState([]);
+ const fileLimit = '.xlsx';
+ //初始化
+
+ const confirm = () => {
+ if (postData.length) {
+ setLoading(true)
+ // dispatch(postAllPersonalTrainRecord(postData)).then(res => {
+ // if (res.success) {
+ // onCancel()
+ // dispatch(getPersonalTrainRecord(query))
+ // }
+ // setLoading(false)
+ // })
+ } else {
+ Notification.warning({ content: '没有数据可以提交,请上传数据文件', duration: 2 })
+ }
+ }
+
+ const download = () => {
+ const head = [Object.keys(IMPORT_FIELD).map(key => IMPORT_FIELD[key].label)];
+ let workbook = { SheetNames: [SHEETNAME], Sheets: {} };
+ workbook.Sheets[SHEETNAME] = XLSX.utils.aoa_to_sheet(head);//json转excel
+ workbook.Sheets[SHEETNAME]['!cols'] = [
+ { wch: 13 }, { wch: 12 }, { wch: 18 }, { wch: 30 }, { wch: 11 },
+ { wch: 30 }, { wch: 13 }];
+ let wopts = { bookType: 'xlsx', type: 'buffer' };// 生成excel的配置项
+ XLSX.writeFile(workbook, `${SHEETNAME}导入模板.xlsx`, wopts);
+ }
+
+ const getFileBlob = (url) => {
+ return new Promise((resolve, reject) => {
+ let request = new XMLHttpRequest()
+ request.open("GET", url, true)
+ request.responseType = "blob"
+ request.onreadystatechange = e => {
+ if (request.readyState == 4) {
+ if (request.status == 200) {
+ if (window.FileReader) {
+ let reader = new FileReader();
+
+ reader.readAsBinaryString(request.response);
+
+ reader.onload = event => {
+ try {
+ const { result } = event.target;
+ // 以二进制流方式读取得到整份excel表格对象
+ const workbook = XLSX.read(result, {
+ type: "binary",
+ cellDates: true,//设为true,将天数的时间戳转为时间格式
+ codepage: 936,//解决了乱码问题
+ });
+ let data = []; // 存储获取到的数据
+ // 遍历每张工作表进行读取(这里默认只读取第一张表)
+ for (const sheet in workbook.Sheets) {
+ if (workbook.Sheets.hasOwnProperty(sheet)) {
+ data = data.concat(XLSX.utils.sheet_to_json(workbook.Sheets[sheet]));
+ }
+ }
+ resolve(data);//导出数据
+ } catch (e) {
+ reject("失败");
+ }
+ }
+ }
+ }
+ }
+ }
+ request.send();
+ })
+ }
+ const changeTime = (v) => {
+ //注意的点:xlsx将excel中的时间内容解析后,会小一天
+ //如2020/8/1,xlsx会解析成 Fri Jul 31 2020 23:59:17 GMT+0800 小了43秒
+ let a = new Date(v);
+ a.setTime(a.getTime() + 43 * 1000);
+ return a;
+ }
+
+ return (
+ {
+ setMsg('')
+ setLoading(false)
+ setPostData([])
+ onCancel()
+ }}
+ >
+
+ {
+ setMsg('');
+ setPostData([]);
+ }}
+ customRequest={(data) => {
+ const { file, onSuccess, onError } = data
+ getFileBlob(file.url).then(res => {
+
+ const error = (msg) => {
+ setMsg(msg)
+ onError({ message: msg })
+ }
+ if (res.length > 1000) {
+ error('一次性上传数据行数应小于1000行,请分批上传')
+ return
+ }
+ if (!res.length) {
+ error('请填写至少一行数据')
+ return
+ }
+ let postData = [];
+ for (let i = 0; i < res.length; i++) {
+ let d = res[i];
+ let obj = {};
+
+ Object.keys(IMPORT_FIELD).map(key => {
+ obj[key] = d[IMPORT_FIELD[key].label] || null;
+ })
+ let errmsg = null;
+ for (let item in obj) {
+ if (!obj[item]) {
+ errmsg = `第${i + 2}行【${IMPORT_FIELD[item].label}】为空,请填写`;
+ break;
+ } else {
+ if ("userCode" == item) {
+ const member = memberList.find(m => m.userCode == obj.userCode);
+ if (!member) {
+ errmsg = `第${i + 2}行【${IMPORT_FIELD[item].label}】${obj.userCode}未匹配到数据,请检查该员工是否添加`;
+ break;
+ } else if (postData.find(m => m.userCode == obj.userCode)) {
+ errmsg = `第${i + 2}行【${IMPORT_FIELD[item].label}】${obj.userCode}已存在,请检查`;
+ break;
+ } else {
+ obj.pepUserId = member.pepUserId;
+ }
+ }
+ else if (["theoryPassed", "totalRatingPassed"].includes(item)) {
+ if (!["是", "否"].includes(obj[item])) {
+ errmsg = `第${i + 2}行【${IMPORT_FIELD[item].label}】不合法,请修改`;
+ break;
+ }
+ }
+ else if ("ratingTime" == item) {
+ if (obj.ratingTime.toString().match(/^(\d{1,4})(-|.|\/)(\d{1,2})\2(\d{1,2})$/)) {
+ obj["ratingTime"] = changeTime(obj.ratingTime);
+ } else {
+ errmsg = `第${i + 2}行【${IMPORT_FIELD[item].label}】不合法,请修改`;
+ break;
+ }
+ } else if (["theoryBasicScore", "totalScore"].includes(item)) {
+ if (isNaN(obj[item])) {
+ errmsg = `第${i + 2}行【${IMPORT_FIELD[item].label}】不合法,请修改`;
+ break;
+ }
+ }
+ }
+ }
+ if (errmsg) {
+ error(errmsg);
+ return
+ }
+ postData.push(obj);
+ }
+ setPostData(postData)
+ let msg = '文件解析完成,点击确定按钮上传保存!'
+ setMsg(msg)
+ onSuccess({ message: msg })
+ })
+ }}>
+ } theme="light">请选择文件
+
+ {msg}
+ 最大不超过200M,导入文件需与
+ download()} style={{ cursor: 'pointer', color: '#0066FF' }}>导入模板
+ 一致
+
+
+ )
+}
+
+export default ImportPositionRatingModal;
\ No newline at end of file
diff --git a/web/client/src/sections/humanAffairs/containers/positionRating.jsx b/web/client/src/sections/humanAffairs/containers/positionRating.jsx
index 63749a5..6e6519f 100644
--- a/web/client/src/sections/humanAffairs/containers/positionRating.jsx
+++ b/web/client/src/sections/humanAffairs/containers/positionRating.jsx
@@ -5,39 +5,28 @@ import { Table, Button, Pagination, Skeleton, Form, Tooltip } from '@douyinfe/se
import { IconSearch } from '@douyinfe/semi-icons';
import { SkeletonScreen, Setup } from "$components";
import { UserAttribute } from '$utils';
+import ImportPositionRatingModal from '../components/importPositionRating';
import '../style.less';
const PositionRating = (props) => {
- const { dispatch, actions, history, user, loading, socket, xqMembers } = props
-
+ const { dispatch, actions, memberList, history, user, loading, socket, xqMembers } = props
const { humanAffairs } = actions;
+ const { getMemberList, getPositionRating } = actions.humanAffairs;
const form = useRef();//表单
let [archivesList, setArchivesList] = useState([]);//人员列表
-
- const [setup, setSetup] = useState(false);//表格设置是否显现
- const [setupp, setSetupp] = useState([]);//实际显示的表格列表
- const [lookup, setLookup] = useState({});//搜索
const [query, setQuery] = useState({ limit: 10, page: 0 }); //页码信息
const [order, setOrder] = useState({ orderBy: 'hiredate', orderDirection: 'DESC' }); //页码信息
+ const [importModal, setImportModal] = useState(false);
const [limits, setLimits] = useState()//每页实际条数
const page = useRef(query.page);//哪一页
useEffect(() => {
- getMemberSearchList()//查询人员列表
- }, [query, order])
+ getMainList()
+ }, [query])
- function getMemberSearchList() {//查询人员列表
- let obj = lookup
- if (lookup.entryTime?.length > 1) {
- obj.hiredateStart = moment(lookup.entryTime[0]).format('YYYY-MM-DD')
- obj.hiredateEnd = moment(lookup.entryTime[1]).format('YYYY-MM-DD')
- }
- else {
- obj.hiredateStart = ''
- obj.hiredateEnd = ''
- }
- dispatch(humanAffairs.getPositionRating({ ...obj, ...query, ...order })).then((res) => {//查询人员列表
+ function getMainList() {
+ dispatch(getPositionRating(query)).then((res) => {
if (res.success) {
setArchivesList(res.payload?.data?.rows)
setLimits(res.payload?.data?.count)
@@ -120,32 +109,32 @@ const PositionRating = (props) => {
}, {
title: '评级时间',
width: 100,
- dataIndex: "time",
- key: "time",
+ dataIndex: "ratingTime",
+ key: "ratingTime",
render: (_, r, index) => -,
}, {
title: '理论基础测评成绩',
width: 150,
- dataIndex: "technicalGrade",
- key: "technicalGrade",
+ dataIndex: "theoryBasicScore",
+ key: "theoryBasicScore",
render: (_, r, index) => -,
}, {
title: '理论基础测评是否通过(≥60)',
width: 150,
- dataIndex: "technicalGrade",
- key: "technicalGrade",
+ dataIndex: "theoryPassed",
+ key: "theoryPassed",
render: (_, r, index) => -,
}, {
title: '评级总成绩',
width: 150,
- dataIndex: "technicalGrade",
- key: "technicalGrade",
+ dataIndex: "totalScore",
+ key: "totalScore",
render: (_, r, index) => -,
}, {
title: '评级总成绩是否通过(K≥60)',
width: 150,
- dataIndex: "technicalGrade",
- key: "technicalGrade",
+ dataIndex: "totalRatingPassed",
+ key: "totalRatingPassed",
render: (_, r, index) => -,
}, {
title: '技术职级等级',
@@ -155,7 +144,6 @@ const PositionRating = (props) => {
render: (_, r, index) => -,
}];
-
function handleRow(record, index) {//斑马条纹
// 给偶数行设置斑马纹
if (index % 2 === 0) {
@@ -168,6 +156,12 @@ const PositionRating = (props) => {
return {};
}
}
+ const handleImportModal = () => {
+ if (!memberList.length) {
+ dispatch(getMemberList())//查询人员列表
+ }
+ setImportModal(true);
+ }
const scroll = useMemo(() => ({}), []);
return (
<>
@@ -188,6 +182,15 @@ const PositionRating = (props) => {
+
+
+
{ handleImportModal(); }}
+ >
+ 导入
+
+
+
表格中带有认证标识"
@@ -260,6 +263,11 @@ const PositionRating = (props) => {
+ {importModal ?
+ { setImportModal(false) }}
+ /> : ''}
>
@@ -267,13 +275,12 @@ const PositionRating = (props) => {
}
function mapStateToProps(state) {
- const { auth, global, MemberSearch, webSocket } = state;
+ const { auth, global, MemberSearch, MemberList } = state;
return {
- // loading: members.isRequesting,
user: auth.user,
actions: global.actions,
xqMembers: MemberSearch.data,
- // socket: webSocket.socket
+ memberList: MemberList.data && MemberList.data.rows || []
};
}