人力资源
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

381 lines
19 KiB

'use strict';
import moment from 'moment';
import React, { useState } from 'react';
import { connect } from 'react-redux';
import { Modal, Form, Button, Notification } from '@douyinfe/semi-ui';
import { IconUpload } from '@douyinfe/semi-icons';
import cityData from '../components/city.json';
import XLSX from 'xlsx'
import { membersBulkAdd } from '../actions/personnelFiles'
import ExportJsonExcel from 'js-export-excel';
import { rule } from './table-input-rule'
//下载模板和上传文件读取
const ImportMembersModal = props => {
const { dispatch, onCancel, xqMembers } = props
const [msg, setMsg] = useState('')
const [loading, setLoading] = useState('')
const [postData, setPostData] = useState([])
const confirm = () => {
if (postData.length) {
setLoading(true)
dispatch(membersBulkAdd(postData)).then(res => {
if (res.success) {
//Notification.success({ content: '导入员工信息成功', duration: 2 })
onCancel()
}
setLoading(false)
})
} else {
Notification.warning({ content: '没有数据可以提交,请上传数据文件', duration: 2 })
}
}
const dldCsvMb = () => {
//表头
let head = "人员编号,姓名,证件号,性别(男/女),出生年月日(例2022/02/01),籍贯,婚育状态(已婚/未婚/已婚已育),政治面貌,联系方式,工作地点,毕业院校,学历,专业,毕业时间,入职时间,转试用期时间,转正时间,离职日期,工作经验(年),历史工作经历与职务\n"
//数据
//let data = 1 + ',' + 2 + ',' + 3 + ',' + 4 + ',' + 5
let templateCsv = "data:text/csv;charset=utf-8,\ufeff" + head;
//创建一个a标签
let link = document.createElement("a");
//为a标签设置属性
link.setAttribute("href", templateCsv);
link.setAttribute("download", "人资系统人员信息导入模板.csv");
//点击a标签
link.click();
}
const download = () => {
//dldTemplate();
dldCsvMb();
let str = "";
rule.forEach((v, i) => {
str += `${v}\r\n`
})
dldText("填写说明.txt", str);
}
// const dldTemplate = () => {
// let dataTable = [];
// let option = {};
// option.fileName = '人资系统人员信息导入模板';
// option.datas = [
// {
// sheetData: dataTable,
// sheetName: '人资系统人员信息导入模板',
// sheetFilter: ['人员编号', '姓名', '证件号', '性别(男/女)', '出生年月日(例2022/02/01)', '籍贯', '婚育状态(已婚/未婚/已婚已育)', '政治面貌', '联系方式', '工作地点', '毕业院校', '学历', '专业', '毕业时间', '入职时间', '转试用期时间', '转正时间', '离职日期', '工作经验(年)', '历史工作经历与职务'], //excel文件中需显示的列数据
// sheetHeader: ['人员编号', '姓名', '证件号', '性别(男/女)', '出生年月日(例2022/02/01)', '籍贯', '婚育状态(已婚/未婚/已婚已育)', '政治面貌', '联系方式', '工作地点', '毕业院校', '学历', '专业', '毕业时间', '入职时间', '转试用期时间', '转正时间', '离职日期', '工作经验(年)', '历史工作经历与职务'], //excel文件中每列的表头名称
// }
// ]
// let toExcel = new ExportJsonExcel(option); //生成excel文件
// toExcel.saveExcel(); //下载excel文件
// }
const dldText = (filename, text) => {
var element = document.createElement('a');
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
element.setAttribute('download', filename);
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
//const action = '/file/qiniu/upload?type=excel&token=' + user.token;
const fileLimit = '.csv';
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 judgePlace = (place) => {
let valid = true;
if (!place) {//可以不填
return valid;
}
if (place.split('-').length == 1) {//判断籍贯
if (['北京市', '上海市', '天津市', '重庆市'].indexOf(place) == -1) {
valid = false;
}
} else if (place.split('-').length == 2) {
let province = place.split('-')[0];
let city = place.split('-')[1];
let existProvince = cityData.find(cd => cd.name == province);
if (!existProvince) {
valid = false;
} else {
let existCity = existProvince.children.find(cd => cd.name == city);
if (!existCity) {
valid = false;
}
}
} else {
valid = false;
}
return valid;
}
const judgeTimeValid = (time) => {
let valid = true;
if (!time) {
return valid;//可以不填
}
const ymd = /^((19|20)[0-9]{2})[\/\-]((0[1-9])|(1[0-2]))[\/\-]((0[1-9])|((1|2)[0-9])|(3[0-1]))$/;//年月日
if (time instanceof Date) {
let timeStr = moment(time).format('YYYY/MM/DD');
if (!ymd.test(timeStr)) {
valid = false;
}
} else {
valid = false;
}
return valid;
}
const judgeNull = (value) => {
return value ? String(value).trim().replace(/\s*/g, "") : null;
}
const judgeNullTime = (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 v ? a : null;
}
return (
<Modal
title="导入信息" visible={true}
onOk={confirm}
confirmLoading={loading}
onCancel={() => {
setMsg('')
setLoading(false)
setPostData([])
onCancel()
}}
>
<div style={{ borderBottom: '1px solid #DCDEE0', margin: '0px -24px' }}></div>
<Form>
<Form.Upload
label={'员工信息'} labelPosition='left'
action={'/'} accept={fileLimit}
maxSize={200} limit={1}
onRemove={(currentFile, fileList, fileItem) => {
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 = [];
const zmsz = /^[A-Za-z0-9]+$/;//字母数字组合
const pattern = /^1[3|4|5|6|7|8|9]\d{9}$/;
const sfz = /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/;//身份证
//const ymd = /^((19|20)[0-9]{2})[\/\-]((0[1-9])|(1[0-2]))[\/\-]((0[1-9])|((1|2)[0-9])|(3[0-1]))$/;//年月日
const num0 = /^\d+(\.\d+)?$/;//非负浮点数
for (let i = 0; i < res.length; i++) {
let d = res[i];
let number = judgeNull(d['人员编号']);
let name = judgeNull(d['姓名']);
let idNumber = judgeNull(d['证件号']);
let gender = judgeNull(d['性别(男/女)']);
let birthday = judgeNullTime(d['出生年月日(例2022/02/01)']);//-------判断时间
let nativePlace = judgeNull(d['籍贯']);
let marital = judgeNull(d['婚育状态(已婚/未婚/已婚已育)']);
let politicsStatus = judgeNull(d['政治面貌']);
let phoneNumber = judgeNull(d['联系方式']);
let workPlace = judgeNull(d['工作地点']);
let graduatedFrom = judgeNull(d['毕业院校']);
let educationBackground = judgeNull(d['学历']);
let specialty = judgeNull(d['专业']);
let graduationDate = judgeNullTime(d['毕业时间']);//-------------------判断时间
let hiredate = judgeNullTime(d['入职时间']);//-------------------------判断时间
let turnProbationPeriod = judgeNullTime(d['转试用期时间']);//-----------判断时间
let regularDate = judgeNullTime(d['转正时间']);//----------------------判断时间
let dimissionDate = judgeNullTime(d['离职日期']);//---------------------判断时间
let experienceYear = judgeNull(d['工作经验(年)']);
let occupationalHistory = judgeNull(d['历史工作经历与职务']);
if (!number) {//人员编号不为空,唯一,字母和数字
error(`${i + 2}行人员编号为空,请填写`)
return
}
let xqExist = xqMembers.find(m => m.userCode == number);
if (!xqExist) {
error(`${i + 2}行的人员编号无对应的员工信息`)
return
}
if (postData.some(p => p.number == number)) {//人员编号 唯一
error(`${i + 2}行人员编号重复,请更改后重新上传`)
return
}
if (!zmsz.test(number)) {
error(`${i + 2}行人员编号错误,请填写字母和数字的组合`)
return
}
if (!name) {//姓名必填
error(`${i + 2}行姓名为空,请填写`)
return
}
if (idNumber && !sfz.test(idNumber)) {
error(`${i + 2}行证件号错误`)
return
}
if (gender && ['男', '女'].indexOf(gender) == -1) {
error(`${i + 2}行性别错误`)
return
}
let bsdValid = judgeTimeValid(birthday);
if (!bsdValid) {
error(`${i + 2}行出生年月日错误,请填写yyyy/mm/dd格式`)
return
}
let jgValid = judgePlace(nativePlace);
if (!jgValid) {
error(`${i + 2}行籍贯错误`)
return
}
if (marital && ['已婚', '未婚', '已婚已育'].indexOf(marital) == -1) {
error(`${i + 2}行婚育状态错误`)
return
}
if (politicsStatus && ['群众', '党员'].indexOf(politicsStatus) == -1) {
error(`${i + 2}行政治面貌错误`)
return
}
if (phoneNumber && !pattern.test(phoneNumber)) {
error(`${i + 2}行联系方式错误`)
return
}
let wpValid = judgePlace(workPlace);
if (!wpValid) {
error(`${i + 2}行工作地点错误`)
return
}
if (educationBackground && ['小学', '初中', '高中', '大专', '本科', '研究生', '博士'].indexOf(educationBackground) == -1) {
error(`${i + 2}行学历错误`)
return
}
let byValid = judgeTimeValid(graduationDate);
if (!byValid) {
error(`${i + 2}行毕业时间错误,请填写yyyy/mm/dd格式`)
return
}
let rzhValid = judgeTimeValid(hiredate);
if (!rzhValid) {
error(`${i + 2}行入职时间错误,请填写yyyy/mm/dd格式`)
return
}
let shyValid = judgeTimeValid(turnProbationPeriod);
if (!shyValid) {
error(`${i + 2}行转试用期时间错误,请填写yyyy/mm/dd格式`)
return
}
let zhzhValid = judgeTimeValid(regularDate);
if (!zhzhValid) {
error(`${i + 2}行转正时间错误,请填写yyyy/mm/dd格式`)
return
}
let lzhValid = judgeTimeValid(dimissionDate);
if (!lzhValid) {
error(`${i + 2}行离职日期错误,请填写yyyy/mm/dd格式`)
return
}
if (experienceYear && !num0.test(experienceYear)) {
error(`${i + 2}行工作经验(年)错误,请填写非负数`)
return
}
postData.push({
pepUserId: xqExist.pepUserId, name, idNumber, gender, birthday, nativePlace, marital,
politicsStatus, phoneNumber, workPlace, graduatedFrom, educationBackground, specialty, graduationDate,
hiredate, turnProbationPeriod, regularDate, dimissionDate, experienceYear, occupationalHistory,
del: false, number
})
}
//if (postData.length) {
setPostData(postData)
//}
let msg = '文件解析完成,点击确定按钮上传保存!'
setMsg(msg)
onSuccess({ message: msg })
})
}}>
<Button icon={<IconUpload />} theme="light">
请选择文件
</Button>
</Form.Upload>
<span>{msg}</span>
<div style={{ color: '#ccc' }}>最大不超过200M导入文件需与
<span onClick={() => download()} style={{ cursor: 'pointer', color: '#0066FF' }}>导入模板</span>
一致</div>
</Form>
</Modal >
)
}
function mapStateToProps(state) {
const { auth } = state;
return {
user: auth.user,
}
}
export default connect(mapStateToProps)(ImportMembersModal);