Browse Source

(*)岗位评级框架

master
周沫沫历险记 2 years ago
parent
commit
47b91176ab
  1. 4
      .vscode/launch.json
  2. 9
      api/app/lib/models/member.js
  3. 94
      api/app/lib/models/position_rating.js
  4. 3
      web/client/src/sections/humanAffairs/containers/index.js
  5. 280
      web/client/src/sections/humanAffairs/containers/positionRating.jsx
  6. 2
      web/client/src/sections/humanAffairs/nav-item.jsx
  7. 23
      web/client/src/sections/humanAffairs/routes.js
  8. 1
      web/routes/attachment/index.js

4
.vscode/launch.json

@ -16,14 +16,14 @@
"-p 4700",
"-f http://localhost:4700",
//
// "-g postgres://postgres:123@10.8.30.166:5432/hr-dev",
"-g postgres://postgres:123@10.8.30.166:5432/hr-dev",
"--redisHost localhost",
"--redisPort 6379",
"--apiEmisUrl http://localhost:14000",
//
// "--apiEmisUrl http://10.8.30.161:1111",
// "--redisHost 10.8.30.112",
"-g postgres://postgres:123@10.8.30.166:5432/HRM",
// "-g postgres://postgres:123@10.8.30.166:5432/HRM",
"--qnak 5XrM4wEB9YU6RQwT64sPzzE6cYFKZgssdP5Kj3uu",
"--qnsk w6j2ixR_i-aelc6I7S3HotKIX-ukMzcKmDfH6-M5",
"--qnbkt pep-resource",

9
api/app/lib/models/member.js

@ -203,6 +203,15 @@ module.exports = dc => {
primaryKey: false,
field: "del",
autoIncrement: false
},
technicalGrade: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: "技术职级等级",
primaryKey: false,
field: "technical_grade",
autoIncrement: false
}
}, {
tableName: "member",

94
api/app/lib/models/position_rating.js

@ -0,0 +1,94 @@
/* eslint-disable*/
'use strict';
module.exports = dc => {
const DataTypes = dc.ORM;
const sequelize = dc.orm;
const PositionRating = sequelize.define("positionRating", {
id: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: true,
field: "id",
autoIncrement: true,
unique: "position_rating_id_uindex"
},
pepUserId: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "pep_user_id",
autoIncrement: false,
references: {
key: "pep_user_id",
model: "member"
}
},
ratingTime: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: null,
comment: "评级时间",
primaryKey: false,
field: "rating_time",
autoIncrement: false
},
theoryBasicScore: {
type: DataTypes.DOUBLE,
allowNull: false,
defaultValue: null,
comment: "理论基础测评成绩",
primaryKey: false,
field: "theory_basic_score",
autoIncrement: false
},
theoryPassed: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: null,
comment: "理论基础测评是否通过(≥60",
primaryKey: false,
field: "theory_passed",
autoIncrement: false
},
totalScore: {
type: DataTypes.DOUBLE,
allowNull: false,
defaultValue: null,
comment: "评级总成绩",
primaryKey: false,
field: "total_score",
autoIncrement: false
},
totalRatingPassed: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: null,
comment: "评级总成绩是否通过(K≥60)",
primaryKey: false,
field: "total_rating_passed",
autoIncrement: false
},
technicalGrade: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: null,
comment: "技术职级等级",
primaryKey: false,
field: "technical_grade",
autoIncrement: false
}
}, {
tableName: "position_rating",
comment: "",
indexes: []
});
dc.models.PositionRating = PositionRating;
return PositionRating;
};

3
web/client/src/sections/humanAffairs/containers/index.js

@ -3,6 +3,7 @@
import PersonnelFiles from './personnelFiles';
import EmployeeInformation from './employeeInformation';
import DeptArchives from './deptArchives';
import PositionRating from './positionRating';
//员工关系
import AttendanceStatistics from './attendanceStatistics';
import LeaveStatistics from './leaveStatistics';
@ -34,7 +35,7 @@ import PersonnelFilesDetail from './personnelFilesDetail';
export {
PersonnelFiles, EmployeeInformation, DeptArchives,
PersonnelFiles, EmployeeInformation, DeptArchives,PositionRating,
AttendanceStatistics, LeaveStatistics, OvertimeStatistics,
AppointmentRecords, PersonnelDistribution,
ResourceRepository, DepartmentTrainRecord,

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

@ -0,0 +1,280 @@
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 { SkeletonScreen, Setup } from "$components";
import { UserAttribute } from '$utils';
import '../style.less';
const PositionRating = (props) => {
const { dispatch, actions, history, user, loading, socket, xqMembers } = props
const { humanAffairs } = actions;
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 [limits, setLimits] = useState()//
const page = useRef(query.page);//
useEffect(() => {
getMemberSearchList()//
}, [query, order])
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.getMemberList({ ...obj, ...query, ...order })).then((res) => {//
if (res.success) {
setArchivesList(res.payload?.data?.rows)
setLimits(res.payload?.data?.count)
}
})
}
//
const columns = [{
title: '序号',
width: 70,
dataIndex: "number",
key: "number",
render: (_, r, index) => <span>{index + 1}</span>,
}, {
title: (
<div>
<img src="/assets/images/hrImg/V.png" alt="" style={{ width: 14, height: 14 }} /> 部门名称
</div>
),
width: 160,
dataIndex: "departmrnt",
key: "departmrnt",
render: (_, r, index) => {
return (
<div style={{ display: 'flex' }}>
{
r.departmrnt.map((ite, idx) => {
let departmentsArr = []
for (let i = 0; i < r.departmrnt.length; i++) {
departmentsArr.push(r.departmrnt[i].name)
}
return (
<div key={idx} style={{ display: 'flex' }}>
{idx == 0 ?
(<div style={{ padding: '0px 4px 1px 4px ', color: '#FFFFFF', fontSize: 12, background: 'rgba(0,90,189,0.8)', borderRadius: 2, marginRight: 4 }}>
{ite.name}
</div>) : ('')
}
{
r.departmrnt.length > 1 && idx == 1 ? (
<Tooltip content={departmentsArr.join(',')} trigger="click" style={{ lineHeight: 2 }}>
<div style={{ padding: '0px 4px 1px 4px ', color: 'rgba(0,90,189,0.8)', fontSize: 12, marginRight: 4, cursor: "pointer", }}>
+{r.departmrnt.length - 1}
</div>
</Tooltip>
) : ('')
}
</div>
)
})
}
</div>
)
},
}, {
title: (
<div>
<img src="/assets/images/hrImg/V.png" alt="" style={{ width: 14, height: 14 }} /> 姓名
</div>
),
width: 100,
dataIndex: "userName",
key: "userName",
render: (_, r, index) => {
return (r.userName ? r.userName : '-');
},
}, {
title: (
<div>
<img src="/assets/images/hrImg/V.png" alt="" style={{ width: 14, height: 14 }} /> 现在职岗位
</div>
),
width: 120,
dataIndex: "userPost",
key: "userPost",
render: (_, r, index) => {
return r.userPost || '-';
},
}, {
title: '评级时间',
width: 100,
dataIndex: "time",
key: "time",
render: (_, r, index) => <span>-</span>,
}, {
title: '理论基础测评成绩',
width: 150,
dataIndex: "technicalGrade",
key: "technicalGrade",
render: (_, r, index) => <span>-</span>,
}, {
title: '理论基础测评是否通过(≥60)',
width: 150,
dataIndex: "technicalGrade",
key: "technicalGrade",
render: (_, r, index) => <span>-</span>,
}, {
title: '评级总成绩',
width: 150,
dataIndex: "technicalGrade",
key: "technicalGrade",
render: (_, r, index) => <span>-</span>,
}, {
title: '评级总成绩是否通过(K≥60)',
width: 150,
dataIndex: "technicalGrade",
key: "technicalGrade",
render: (_, r, index) => <span>-</span>,
}, {
title: '技术职级等级',
width: 150,
dataIndex: "technicalGrade",
key: "technicalGrade",
render: (_, r, index) => <span>-</span>,
}];
function handleRow(record, index) {//
//
if (index % 2 === 0) {
return {
style: {
background: '#FAFCFF',
}
};
} else {
return {};
}
}
const scroll = useMemo(() => ({}), []);
return (
<>
<div style={{ padding: '0px 12px' }}>
<div style={{ display: 'flex' }}>
<div style={{ color: 'rgba(0,0,0,0.45)', fontSize: 14 }}>档案中心</div>
<div style={{ color: 'rgba(0,0,0,0.45)', fontSize: 14, margin: '0px 8px' }}>/</div>
<div style={{ color: 'rgba(0,0,0,0.45)', fontSize: 14 }}>人员档案</div>
<div style={{ color: '#033C9A', fontSize: 14, margin: '0px 8px' }}>/</div>
<div style={{ color: '#033C9A', fontSize: 14 }}>岗位评级</div>
</div>
<div style={{ background: '#FFFFFF', boxShadow: '0px 0px 12px 2px rgba(220,222,224,0.2)', borderRadius: 2, padding: '20px 0px 20px 19px ', marginTop: 12 }}>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<div style={{ display: 'flex', alignItems: 'baseline' }}>
<div style={{ width: 0, height: 20, borderLeft: '3px solid #0F7EFB', borderTop: '3px solid transparent', borderBottom: '3px solid transparent' }}></div>
<div style={{ fontFamily: "YouSheBiaoTiHei", fontSize: 24, color: '#033C9A', marginLeft: 8 }}>岗位评级</div>
<div style={{ marginLeft: 6, fontSize: 12, color: '#969799', fontFamily: "DINExp", }}>POSITION RATING</div>
</div>
</div>
<div style={{ marginRight: 20, marginTop: 18 }}>
<div style={{ border: '1px solid #C7E1FF', background: '#F4F8FF', borderRadius: 2, height: 32, width: 669, padding: '8px 0px 7px 12px', display: 'flex', alignItems: 'center', color: '#0F7EFB', fontSize: 12 }}>
<img src="/assets/images/hrImg/!.png" alt="" style={{ width: 14, height: 14, marginRight: 8 }} />
表格中带有认证标识"
<img src="/assets/images/hrImg/V.png" alt="" style={{ width: 14, height: 14 }} />
"信息的为系统基础数据来源于项企PEP钉钉等系统其他数据均为导入或自定义数据
</div>
<div style={{ marginTop: 20 }}>
<Skeleton
// loading={loading}
loading={false}
active={true}
placeholder={SkeletonScreen()}
>
<Table
columns={columns}
dataSource={archivesList}
bordered={false}
empty="暂无数据"
pagination={false}
// onChange={({ sorter }) => {
// if (sorter.key == 'userCode') {
// if (sorter.sortOrder == 'descend') {
// setOrder({ orderBy: 'code', orderDirection: 'DESC' })
// } else {
// setOrder({ orderBy: 'code', orderDirection: 'ASC' })
// }
// } else if (sorter.key == 'age') {
// if (sorter.sortOrder == 'descend') {
// setOrder({ orderBy: 'age', orderDirection: 'DESC' })
// } else {
// setOrder({ orderBy: 'age', orderDirection: 'ASC' })
// }
// } else {
// if (sorter.sortOrder == 'descend') {
// setOrder({ orderBy: 'hiredate', orderDirection: 'DESC' })
// } else {
// setOrder({ orderBy: 'hiredate', orderDirection: 'ASC' })
// }
// }
// }}
onRow={handleRow}
scroll={scroll}
/>
</Skeleton>
<div
style={{
display: "flex",
justifyContent: "space-between",
padding: "20px 20px",
}}
>
<div>
</div>
<div style={{ display: 'flex', }}>
<span style={{ lineHeight: "30px", fontSize: 13, color: 'rgba(0,90,189,0.8)' }}>
{limits}条信息
</span>
<Pagination
className="22"
total={limits}
showSizeChanger
currentPage={query.page + 1}
pageSizeOpts={[10, 20, 30, 40]}
onChange={(currentPage, pageSize) => {
setQuery({ limit: pageSize, page: currentPage - 1 });
page.current = currentPage - 1
}}
/>
</div>
</div>
</div>
</div>
</div>
</div>
</>
)
}
function mapStateToProps(state) {
const { auth, global, MemberSearch, webSocket } = state;
return {
// loading: members.isRequesting,
user: auth.user,
actions: global.actions,
xqMembers: MemberSearch.data,
// socket: webSocket.socket
};
}
export default connect(mapStateToProps)(PositionRating);

2
web/client/src/sections/humanAffairs/nav-item.jsx

@ -17,6 +17,8 @@ export function getNavItem(user, dispatch) {
itemKey: 'personnelFiles', to: '/humanAffairs/archivesCenter/personnelArchives/personnelFiles', text: '人员档案'
}, {
itemKey: 'employeeInformation', to: '/humanAffairs/archivesCenter/personnelArchives/employeeInformation', text: '员工信息'
}, {
itemKey: 'positionRating', to: '/humanAffairs/archivesCenter/personnelArchives/positionRating', text: '岗位评级'
}]
}, {
itemKey: 'deptArchives',

23
web/client/src/sections/humanAffairs/routes.js

@ -1,5 +1,5 @@
import {
PersonnelFiles, EmployeeInformation, //人员档案
PersonnelFiles, EmployeeInformation, PositionRating, //人员档案
DeptArchives, //部门档案
AttendanceStatistics, LeaveStatistics, OvertimeStatistics,
AppointmentRecords, PersonnelDistribution,
@ -41,6 +41,11 @@ export default [{
key: 'employeeInformation',
component: EmployeeInformation,
breadcrumb: '员工信息',
}, {
path: '/positionRating',
key: 'positionRating',
component: PositionRating,
breadcrumb: '岗位评级'
}]
}, {
path: '/deptArchives',
@ -77,6 +82,21 @@ export default [{
component: OvertimeStatistics,
breadcrumb: '加班统计',
}]
<<<<<<< HEAD
},
// {
// path: '/communication',
// key: 'communication',
// breadcrumb: '员工沟通',
// childRoutes: [{
// path: '/employeeCommunication',
// key: 'employeeCommunication',
// component: EmployeeCommunication,
// breadcrumb: '员工沟通统计',
// }]
// }
]
=======
}, {
path: '/communication',
key: 'communication',
@ -88,6 +108,7 @@ export default [{
breadcrumb: '员工沟通统计',
}]
}]
>>>>>>> dfde26653d43d65f3734d7b787e34d37d51c55de
}, {
path: '/recruit',
key: 'recruit',

1
web/routes/attachment/index.js

@ -52,7 +52,6 @@ module.exports = {
let upload = async function (ctx, next) {
try {
console.log('-------------');
const { token } = ctx.request.query
console.log(token);
if (token) {

Loading…
Cancel
Save