Browse Source

(*)岗位评级导入、删除

master
周沫沫历险记 2 years ago
parent
commit
b305766ad3
  1. 71
      api/app/lib/controllers/member/index.js
  2. 8
      api/app/lib/routes/member/index.js
  3. 25
      web/client/src/sections/humanAffairs/actions/employeeInformation.js
  4. 15
      web/client/src/sections/humanAffairs/components/importPositionRating.jsx
  5. 60
      web/client/src/sections/humanAffairs/containers/positionRating.jsx
  6. 2
      web/client/src/utils/webapi.js

71
api/app/lib/controllers/member/index.js

@ -746,9 +746,12 @@ async function getPositionRating(ctx) {
const userInfo = userRes && userRes.filter(u => item.pepUserId == u.userId);
item.dataValues.department = userInfo.map(u => { return { depName: u.depName, depId: u.depId } });
item.dataValues.userName = userInfo.length && userInfo[0].userName;
item.d
const { theoryPassed, totalRatingPassed, ratingTime, ...rest } = item.dataValues
rslt.push({
...item.dataValues,
...rest,
theoryPassed: theoryPassed ? '是' : '否',
totalRatingPassed: totalRatingPassed ? '是' : '否',
ratingTime: moment(ratingTime).format('YYYY-MM-DD'),
department: userInfo.map(u => { return { depName: u.depName, depId: u.depId } }),
userName: userInfo.length && userInfo[0].userName,
userPost: userInfo.length && userInfo[0].userPost
@ -772,6 +775,66 @@ async function getPositionRating(ctx) {
}
}
}
//新增岗位评级
async function postPositionRating(ctx) {
let errorMsg = { message: '导入岗位绩效失败' };
const transaction = await ctx.fs.dc.orm.transaction();
try {
const models = ctx.fs.dc.models;
const data = ctx.request.body;
//处理新增的
if (data) {
if (data.length) {
const dataToSave = [];
const dataToUpdate = [];
data.map((item) => {
const { pepUserId, technicalGrade } = item;
dataToUpdate.push({ pepUserId, technicalGrade });
})
await models.PositionRating.bulkCreate(data, { transaction });
for (let item in dataToUpdate) {
await models.Member.update({ technicalGrade: dataToUpdate[item].technicalGrade },
{ where: { pepUserId: dataToUpdate[item].pepUserId }, transaction });
}
}
else {
await models.PositionRating.create(data, { transaction });
await models.Member.update({ technicalGrade: data.technicalGrade },
{ where: { pepUserId: data.pepUserId }, transaction });
}
//更新member表字段
}
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 delPositionRating(ctx) {
try {
const { models } = ctx.fs.dc;
const { id } = ctx.params;
const oldData = await models.PositionRating.findOne({ where: { id: id } });
if (oldData) {
//todo 更新memeber技术等级字段
await models.PositionRating.destory({ where: { id: id }, transaction });
}
ctx.status = 204;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
module.exports = {
add,
edit,
@ -785,5 +848,7 @@ module.exports = {
nativePlaceList,
workPlaceList,
maritalList,
getPositionRating
getPositionRating,
postPositionRating,
delPositionRating
}

8
api/app/lib/routes/member/index.js

@ -39,6 +39,12 @@ module.exports = function (app, router, opts) {
app.fs.api.logAttr['GET/members/export'] = { content: '导出员工信息', visible: true };
router.get('/members/export', member.exportData);
app.fs.api.logAttr['GET/members/position_rating'] = { content: '查询岗位评级信息', visible: true };
app.fs.api.logAttr['GET/members/position_rating'] = { content: '查询岗位评级信息', visible: false };
router.get('/members/position_rating', member.getPositionRating);
app.fs.api.logAttr['POST/members/position_rating'] = { content: '新增岗位评级信息', visible: true };
router.post('/members/position_rating', member.postPositionRating);
app.fs.api.logAttr['DEL/members/position_rating/:id'] = { content: '删除岗位评级信息', visible: true };
router.del('/members/position_rating/:id', member.delPositionRating);
};

25
web/client/src/sections/humanAffairs/actions/employeeInformation.js

@ -57,7 +57,7 @@ export function getAttendanceOvertime(query) {//加班统计
reducer: { name: "AttendanceOvertime", params: { noClear: true } },
});
}
export function getPositionRating(query){//岗位评级
export function getPositionRating(query) {//岗位评级
return (dispatch) => basicAction({
type: "get",
dispatch: dispatch,
@ -68,3 +68,26 @@ export function getPositionRating(query){//岗位评级
reducer: { name: "positionRating", params: { noClear: true } },
});
}
export function postPositionRating(data) {
return (dispatch) =>
basicAction({
type: "post",
dispatch: dispatch,
data,
actionType: "POST_POSITION_RATING",
url: `${ApiTable.postPositionRating}`,
msg: { option: "导入岗位评级" }
})
}
export function delPositionRating(id) {
return (dispatch) =>
basicAction({
type: "del",
dispatch: dispatch,
actionType: "DEL_POSITIONRATING",
url: `${ApiTable.delPositionRating.replace("{id}", id)}`,
msg: { option: "删除岗位评级" }
});
}

15
web/client/src/sections/humanAffairs/components/importPositionRating.jsx

@ -16,23 +16,16 @@ const IMPORT_FIELD = {
const SHEETNAME = "岗位评级";
const ImportPositionRatingModal = props => {
const { onCancel, user, memberList } = props;
const { onCancel, onOk, 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)
// })
setLoading(true);
onOk(postData);
} else {
Notification.warning({ content: '没有数据可以提交,请上传数据文件', duration: 2 })
}
@ -170,6 +163,8 @@ const ImportPositionRatingModal = props => {
if (!["是", "否"].includes(obj[item])) {
errmsg = `${i + 2}行【${IMPORT_FIELD[item].label}】不合法,请修改`;
break;
} else {
obj[item] = "是" == obj[item] ? true : false;
}
}
else if ("ratingTime" == item) {

60
web/client/src/sections/humanAffairs/containers/positionRating.jsx

@ -1,17 +1,13 @@
import React, { useEffect, useState, useRef, useMemo } from 'react';
import { connect } from 'react-redux';
import moment from 'moment'
import { Table, Button, Pagination, Skeleton, Form, Tooltip } from '@douyinfe/semi-ui';
import { IconSearch } from '@douyinfe/semi-icons';
import { Table, Button, Pagination, Skeleton, Popconfirm, Tooltip } from '@douyinfe/semi-ui';
import { SkeletonScreen, Setup } from "$components";
import { UserAttribute } from '$utils';
import ImportPositionRatingModal from '../components/importPositionRating';
import '../style.less';
const PositionRating = (props) => {
const { dispatch, actions, memberList, history, user, loading, socket, xqMembers } = props
const { humanAffairs } = actions;
const { getMemberList, getPositionRating } = actions.humanAffairs;
const { dispatch, actions, memberList } = props
const { getMemberList, getPositionRating, postPositionRating, delPositionRating } = actions.humanAffairs;
const form = useRef();//
let [archivesList, setArchivesList] = useState([]);//
@ -25,8 +21,8 @@ const PositionRating = (props) => {
getMainList()
}, [query])
function getMainList() {
dispatch(getPositionRating(query)).then((res) => {
function getMainList(queryObj) {
dispatch(getPositionRating(queryObj || query)).then((res) => {
if (res.success) {
setArchivesList(res.payload?.data?.rows)
setLimits(res.payload?.data?.count)
@ -103,45 +99,50 @@ const PositionRating = (props) => {
width: 120,
dataIndex: "userPost",
key: "userPost",
render: (_, r, index) => {
return r.userPost || '-';
},
}, {
title: '评级时间',
width: 100,
width: 120,
dataIndex: "ratingTime",
key: "ratingTime",
render: (_, r, index) => <span>-</span>,
}, {
title: '理论基础测评成绩',
width: 150,
dataIndex: "theoryBasicScore",
key: "theoryBasicScore",
render: (_, r, index) => <span>-</span>,
}, {
title: '理论基础测评是否通过(≥60)',
width: 150,
width: 130,
dataIndex: "theoryPassed",
key: "theoryPassed",
render: (_, r, index) => <span>-</span>,
}, {
title: '评级总成绩',
width: 150,
width: 100,
dataIndex: "totalScore",
key: "totalScore",
render: (_, r, index) => <span>-</span>,
}, {
title: '评级总成绩是否通过(K≥60)',
width: 150,
width: 130,
dataIndex: "totalRatingPassed",
key: "totalRatingPassed",
render: (_, r, index) => <span>-</span>,
}, {
title: '技术职级等级',
width: 150,
dataIndex: "technicalGrade",
key: "technicalGrade",
render: (_, r, index) => <span>-</span>,
}, {
title: '操作',
width: 100,
dataIndex: "action",
key: "action",
render: (text, record) => <div style={{ color: "#1890FF" }}><Popconfirm
style={{ minWidth: "max-content" }}
title="提示"
content="确认删除条信息?"
onConfirm={() => { handleDel(record.id) }}
position={"leftBottom"}
>
<a style={{ cursor: 'pointer' }}>删除</a>
</Popconfirm></div>
}];
function handleRow(record, index) {//
@ -162,6 +163,20 @@ const PositionRating = (props) => {
}
setImportModal(true);
}
const handleImportOk = (dataToSave) => {
dispatch(postPositionRating(dataToSave)).then(res => {
setImportModal(false);
setQuery({ limit: 10, page: 0 });
getMainList({ limit: 10, page: 0 });
})
}
const handleDel = (id) => {
dispatch(delPositionRating(id)).then(res => {
setQuery({ limit: 10, page: 0 });
getMainList({ limit: 10, page: 0 });
})
}
const scroll = useMemo(() => ({}), []);
return (
<>
@ -266,6 +281,7 @@ const PositionRating = (props) => {
{importModal ?
<ImportPositionRatingModal
memberList={memberList}
onOk={handleImportOk}
onCancel={() => { setImportModal(false) }}
/> : ''}
</div>

2
web/client/src/utils/webapi.js

@ -38,6 +38,8 @@ export const ApiTable = {
delSalesMember: 'sales/member/del',
addSalesMemberBulk: 'add/sales/members/bulk',
getPositionRating: 'members/position_rating',
postPositionRating: 'members/position_rating',
delPositionRating: 'members/position_rating/{id}',
//部门培训记录
getDepartmentTrainRecord: 'department/train/record/list',

Loading…
Cancel
Save