5 changed files with 320 additions and 26 deletions
@ -0,0 +1,72 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
import { ApiTable, basicAction } from '$utils' |
||||
|
|
||||
|
export function personalTrainRecordAll(values) { |
||||
|
return dispatch => basicAction({ |
||||
|
type: 'post', |
||||
|
dispatch: dispatch, |
||||
|
actionType: 'SALES_MEMBER_BULK_ADD', |
||||
|
url: ApiTable.addSalesMemberBulk, |
||||
|
data: values, |
||||
|
msg: { option: '导入销售人员信息' }, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
export function getPersonalTrainRecord(query) {//查询
|
||||
|
return (dispatch) => basicAction({ |
||||
|
type: "get", |
||||
|
dispatch: dispatch, |
||||
|
actionType: "GET_PERSONAL_TRAIN_RECORD_LIST", |
||||
|
query: query, |
||||
|
url: `${ApiTable.getPersonalTrainRecord}`, |
||||
|
msg: { option: "查询个人培训记录列表" }, |
||||
|
reducer: { name: "personalTrainRecordList", params: { noClear: true } }, |
||||
|
}); |
||||
|
} |
||||
|
// export function delSalesMember(data) {//删除
|
||||
|
// let msg = ''
|
||||
|
// if (data) {
|
||||
|
// msg = data.msg
|
||||
|
// }
|
||||
|
// return (dispatch) =>
|
||||
|
// basicAction({
|
||||
|
// type: "del",
|
||||
|
// query: data,
|
||||
|
// dispatch: dispatch,
|
||||
|
// actionType: "DEL_SALES_MEMBER",
|
||||
|
// url: `${ApiTable.delSalesMember}`,
|
||||
|
// msg: { option: msg }, //删除
|
||||
|
// reducer: {},
|
||||
|
// });
|
||||
|
// }
|
||||
|
|
||||
|
// export function getMemberExport(query) {//导出员工信息
|
||||
|
// return (dispatch) => basicAction({
|
||||
|
// type: "get",
|
||||
|
// dispatch: dispatch,
|
||||
|
// actionType: "GET_MemberEXPORT",
|
||||
|
// query: query,
|
||||
|
// url: `${ApiTable.getMemberExport}`,
|
||||
|
// msg: { option: "导出员工信息" },
|
||||
|
// reducer: { name: "MemberExport", params: { noClear: true } },
|
||||
|
// });
|
||||
|
// }
|
||||
|
|
||||
|
|
||||
|
// export function editSalesMember(data) {//更新
|
||||
|
// let msg = ''
|
||||
|
// if (data) {
|
||||
|
// msg = data.msg
|
||||
|
// }
|
||||
|
// return (dispatch) =>
|
||||
|
// basicAction({
|
||||
|
// type: "put",
|
||||
|
// dispatch: dispatch,
|
||||
|
// data,
|
||||
|
// actionType: "PUT_SALES_MEMBER",
|
||||
|
// url: `${ApiTable.editSalesMember}`,
|
||||
|
// msg: { option: msg }, //更新
|
||||
|
// reducer: {},
|
||||
|
// });
|
||||
|
// }
|
@ -0,0 +1,222 @@ |
|||||
|
'use strict'; |
||||
|
import React, { useState, useEffect } from 'react'; |
||||
|
import { connect } from 'react-redux'; |
||||
|
import moment from 'moment'; |
||||
|
import { Modal, Form, Button, Notification } from '@douyinfe/semi-ui'; |
||||
|
import { IconUpload } from '@douyinfe/semi-icons'; |
||||
|
import XLSX from 'xlsx' |
||||
|
//下载模板和上传文件读取 |
||||
|
const ImportPerformanceSummaryModal = props => { |
||||
|
const { dispatch, actions, onCancel } = props; |
||||
|
const { businessManagement } = actions |
||||
|
const [msg, setMsg] = useState(''); |
||||
|
const [loading, setLoading] = useState(''); |
||||
|
const [postData, setPostData] = useState([]); |
||||
|
let personalTrainRecord = { index: '序号', personalName: '姓名', departmentName: '部门', trainingType: '培训类型', topic: '课程主题', trainer: '培训讲师', trainDate: '培训时间', trainTime: '培训时长', trainMethod: '培训方式', attendanceScore: '考勤分数', appraisalMethod: '考核形式', appraisalScore: '考核分数', totalScore: '总分' } |
||||
|
//初始化 |
||||
|
|
||||
|
const confirm = () => { |
||||
|
if (postData.length) { |
||||
|
setLoading(true) |
||||
|
// dispatch(businessManagement.importSalePerformance(postData)).then(res => { |
||||
|
// if (res.success) { |
||||
|
// onCancel() |
||||
|
// } |
||||
|
// setLoading(false) |
||||
|
// }) |
||||
|
} else { |
||||
|
Notification.warning({ content: '没有数据可以提交,请上传数据文件', duration: 2 }) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
const dldCsvMb = () => { |
||||
|
//表头 |
||||
|
let head = []; |
||||
|
Object.keys(personalTrainRecord).map(key => { |
||||
|
head.push(personalTrainRecord[key]); |
||||
|
}) |
||||
|
head = head.join(',') + "\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 = () => { |
||||
|
dldCsvMb(); |
||||
|
} |
||||
|
|
||||
|
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 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; |
||||
|
// } |
||||
|
|
||||
|
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; |
||||
|
} |
||||
|
|
||||
|
return ( |
||||
|
<Modal |
||||
|
title="导入" visible={true} |
||||
|
onOk={confirm} width={620} |
||||
|
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 = []; |
||||
|
let zzsPattern = /^[+]{0,1}(\d+)$/;//正整数 |
||||
|
for (let i = 0; i < res.length; i++) { |
||||
|
let d = res[i]; |
||||
|
let obj = {}; |
||||
|
Object.keys(personalTrainRecord).map(key => { |
||||
|
obj[key] = d[personalTrainRecord[key]] || null; |
||||
|
//} |
||||
|
}) |
||||
|
let tValid = judgeTimeValid(obj.recConDate); |
||||
|
// if (!tValid) { |
||||
|
// error(`第${i + 2}行【收到合同日期】错误,请填写yyyy/mm/dd格式`) |
||||
|
// return |
||||
|
// } |
||||
|
|
||||
|
// if (obj.isApproval && ['是', '否'].indexOf(obj.isApproval) == -1) { |
||||
|
// error(`第${i + 2}行【价格是否特批】错误,请填写是或否`) |
||||
|
// return |
||||
|
// } |
||||
|
// //复购次数 正整数 |
||||
|
// if (obj.repurchaseCount && !zzsPattern.test(obj.repurchaseCount)) { |
||||
|
// error(`第${i + 2}行【复购次数】填写错误,需要为非负整数`) |
||||
|
// return |
||||
|
// } |
||||
|
|
||||
|
// if (obj.reproducible && ['是', '否'].indexOf(obj.reproducible) == -1) { |
||||
|
// error(`第${i + 2}行【是否可复制的业务路径】错误,请填写是或否`) |
||||
|
// return |
||||
|
// } |
||||
|
postData.push(obj); |
||||
|
} |
||||
|
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, global } = state; |
||||
|
return { |
||||
|
user: auth.user, |
||||
|
actions: global.actions, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default connect(mapStateToProps)(ImportPerformanceSummaryModal); |
Loading…
Reference in new issue