diff --git a/api/app/lib/controllers/departmentTrain/index.js b/api/app/lib/controllers/departmentTrain/index.js
index 8750087..02f14b8 100644
--- a/api/app/lib/controllers/departmentTrain/index.js
+++ b/api/app/lib/controllers/departmentTrain/index.js
@@ -1,8 +1,16 @@
'use strict';
-async function getDepartmentTrainRecordList(ctx) {
+async function get(ctx) {
try {
+ const { limit, page } = ctx.query;
+ const models = ctx.fs.dc.models;
+ let res = await models.DeptTraining.findAndCountAll({
+ where: {},
+ offset: Number(page) * Number(limit),
+ limit: Number(limit),
+ order: [['id', 'ASC']]
+ })
ctx.status = 200;
- ctx.body = {};
+ ctx.body = res;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
@@ -10,9 +18,45 @@ async function getDepartmentTrainRecordList(ctx) {
message: '查询部门培训记录列表失败'
}
}
+}
+async function importData(ctx) {
+ let errorMsg = { message: '导入部门培训记录信息失败' };
+ const transaction = await ctx.fs.dc.orm.transaction();
+ try {
+ const models = ctx.fs.dc.models;
+ const data = ctx.request.body;
+ await models.DeptTraining.bulkCreate(data, { transaction });
+ await transaction.commit();
+ ctx.status = 204;
+ } catch (error) {
+ await transaction.rollback();
+ ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
+ ctx.status = 400;
+ ctx.body = errorMsg;
+ }
}
+async function modify(ctx) {
+ try {
+ const { models } = ctx.fs.dc;
+ const { id, ...rest } = ctx.request.body;
+ const existRes = await models.DeptTraining.findOne({ where: { id } });
+ if (!existRes) {
+ throw '当前部门培训记录信息不存在';
+ }
+ await models.DeptTraining.update({ ...rest }, { where: { id: id } });
+ ctx.status = 204;
+ } catch (error) {
+ ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
+ ctx.status = 400;
+ ctx.body = {
+ message: '修改部门培训记录失败'
+ }
+ }
+}
module.exports = {
- getDepartmentTrainRecordList
+ get,
+ importData,
+ modify
}
diff --git a/api/app/lib/routes/departmentTrain/index.js b/api/app/lib/routes/departmentTrain/index.js
index d8458e5..d7635b2 100644
--- a/api/app/lib/routes/departmentTrain/index.js
+++ b/api/app/lib/routes/departmentTrain/index.js
@@ -5,5 +5,11 @@ const departmentTrain = require('../../controllers/departmentTrain');
module.exports = function (app, router, opts) {
app.fs.api.logAttr['GET/department/train/record/list'] = { content: '查询部门培训记录列表', visible: true };
- router.get('/department/train/record/list', departmentTrain.getDepartmentTrainRecordList);
+ router.get('/department/train/record/list', departmentTrain.get);
+
+ app.fs.api.logAttr['POST/department/train/record/bulk'] = { content: '导入部门培训记录信息', visible: true };
+ router.post('/department/train/record/bulk', departmentTrain.importData);
+
+ app.fs.api.logAttr['PUT/department/train/record/modify'] = { content: '编辑部门培训记录信息', visible: true };
+ router.put('/department/train/record/modify', departmentTrain.modify);
};
\ No newline at end of file
diff --git a/web/client/src/sections/humanAffairs/actions/index.js b/web/client/src/sections/humanAffairs/actions/index.js
index 9ce29bf..b583f67 100644
--- a/web/client/src/sections/humanAffairs/actions/index.js
+++ b/web/client/src/sections/humanAffairs/actions/index.js
@@ -4,6 +4,7 @@ import * as personnelFiles from './personnelFiles'
import * as employeeInformation from './employeeInformation'
import * as salesDistribution from './salesDistribution'
import * as departmentTrain from './departmentTrain'
+import * as personalTrainRecord from './personalTrainRecord'
import * as resourceRepository from './resourceRepository'
export default {
@@ -11,5 +12,6 @@ export default {
...employeeInformation,
...salesDistribution,
...departmentTrain,
+ ...personalTrainRecord,
...resourceRepository
}
\ No newline at end of file
diff --git a/web/client/src/sections/humanAffairs/actions/personalTrainRecord.js b/web/client/src/sections/humanAffairs/actions/personalTrainRecord.js
new file mode 100644
index 0000000..277df99
--- /dev/null
+++ b/web/client/src/sections/humanAffairs/actions/personalTrainRecord.js
@@ -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: {},
+// });
+// }
\ No newline at end of file
diff --git a/web/client/src/sections/humanAffairs/containers/importPersonalTrainRecord.jsx b/web/client/src/sections/humanAffairs/containers/importPersonalTrainRecord.jsx
new file mode 100644
index 0000000..1623cfb
--- /dev/null
+++ b/web/client/src/sections/humanAffairs/containers/importPersonalTrainRecord.jsx
@@ -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 (
+