wuqun 3 years ago
parent
commit
c70e00be0a
  1. 141
      api/app/lib/controllers/attendance/index.js
  2. 158
      api/app/lib/controllers/member/index.js
  3. 2
      api/app/lib/models/member.js
  4. 11
      api/app/lib/routes/attendance/index.js
  5. 68
      api/app/lib/utils/attendance.js
  6. 239
      api/app/lib/utils/member.js
  7. BIN
      web/client/assets/images/hrImg/!.png
  8. BIN
      web/client/assets/images/hrImg/V.png
  9. BIN
      web/client/assets/images/hrImg/setUp.png
  10. 2
      web/client/index.ejs
  11. 4
      web/client/index.html
  12. 25
      web/client/src/components/setup.jsx
  13. 26
      web/client/src/sections/humanAffairs/actions/employeeInformation.js
  14. 3
      web/client/src/sections/humanAffairs/actions/index.js
  15. 10
      web/client/src/sections/humanAffairs/components/personnelModal.jsx
  16. 432
      web/client/src/sections/humanAffairs/containers/employeeInformation.jsx
  17. 3
      web/client/src/sections/humanAffairs/containers/index.js
  18. 4
      web/client/src/sections/humanAffairs/containers/personnelFiles.jsx
  19. 180
      web/client/src/sections/humanAffairs/containers/personnelFilesDetail.jsx
  20. 10
      web/client/src/sections/humanAffairs/nav-item.jsx
  21. 16
      web/client/src/sections/humanAffairs/routes.js
  22. 9
      web/client/src/sections/humanAffairs/style.less
  23. 3
      web/client/src/utils/webapi.js

141
api/app/lib/controllers/attendance/index.js

@ -0,0 +1,141 @@
'use strict';
const moment = require('moment')
async function overtimeStatistic (ctx) {
try {
const { models } = ctx.fs.dc;
const { clickHouse } = ctx.app.fs
const { memberList, packageUserData, overtimeStatisticListDayType } = ctx.app.fs.utils
const {
keywordTarget, keyword, limit, page, orderBy, orderDirection,
startDate, endDate,
} = ctx.query
const userRes = await memberList({
keywordTarget, keyword, limit, page,
orderBy, orderDirection,
overtimeDayStatisticStartDate: startDate,
overtimeDayStatisticendDate: endDate,
overtimeCountStatistic: true,
overtimeCountStatisticStartDate: startDate,
overtimeCountStatisticendDate: endDate,
})
let { packageUser: returnD, pepUserIds } = await packageUserData(userRes)
const sumRes = await overtimeStatisticListDayType({
startDate, endDate, pepUserIds
})
returnD.forEach(u => {
u.overtimeStatistic = sumRes.filter(s => s.pepUserId == u.pepUserId)
})
ctx.status = 200;
ctx.body = {
count: userRes.count,
rows: returnD
}
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
async function exportOvertimeStatistic (ctx) {
try {
const { models } = ctx.fs.dc;
const { clickHouse } = ctx.app.fs
const { memberList, packageUserData, overtimeStatisticListDayType } = ctx.app.fs.utils
const {
keywordTarget, keyword, limit, page, orderBy, orderDirection,
startDate, endDate,
} = ctx.query
const userRes = await memberList({
keywordTarget, keyword, limit, page,
orderBy, orderDirection,
overtimeDayStatisticStartDate: startDate,
overtimeDayStatisticendDate: endDate,
overtimeCountStatistic: true,
overtimeCountStatisticStartDate: startDate,
overtimeCountStatisticendDate: endDate,
})
let { packageUser: returnD, pepUserIds } = await packageUserData(userRes)
const sumRes = await overtimeStatisticListDayType({
startDate, endDate, pepUserIds
})
returnD.forEach(u => {
u.overtimeStatistic = sumRes.filter(s => s.pepUserId == u.pepUserId)
})
const fileName = `人员信息_${moment().format('YYYYMMDDHHmmss')}` + '.csv'
const filePath = await simpleExcelDown({ data: exportD, header, fileName: fileName })
const fileData = fs.readFileSync(filePath);
ctx.status = 200;
ctx.set('Content-Type', 'application/x-xls');
ctx.set('Content-disposition', 'attachment; filename=' + encodeURI(fileName));
ctx.body = fileData;
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: error`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
async function vacateStatistic (ctx) {
try {
const { models } = ctx.fs.dc;
const { clickHouse } = ctx.app.fs
const { judgeHoliday, memberList, packageUserData, vacateStatisticListDayType } = ctx.app.fs.utils
const {
keywordTarget, keyword, limit, page, orderBy, orderDirection,
startDate, endDate,
} = ctx.query
const userRes = await memberList({
keywordTarget, keyword, limit, page,
orderBy, orderDirection,
vacateDayStatisticStartDate: startDate,
vacateDayStatisticendDate: endDate,
vacateDurationStatistic: true,
vacateCountStatistic: true,
vacateCountStatisticStartDate: startDate,
vacateCountStatisticendDate: endDate,
})
let { packageUser: returnD, pepUserIds } = await packageUserData(userRes)
const sumRes = await vacateStatisticListDayType({
startDate, endDate, pepUserIds
})
returnD.forEach(u => {
u.vacateStatistic = sumRes.filter(s => s.pepUserId == u.pepUserId)
})
ctx.status = 200;
ctx.body = {
count: userRes.count,
rows: returnD
}
} catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400;
ctx.body = {
message: typeof error == 'string' ? error : undefined
}
}
}
module.exports = {
overtimeStatistic,
vacateStatistic,
};

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

@ -37,7 +37,7 @@ async function add (ctx) {
ctx.status = 204; ctx.status = 204;
} catch (error) { } catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: error`); ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400; ctx.status = 400;
ctx.body = { ctx.body = {
message: typeof error == 'string' ? error : undefined message: typeof error == 'string' ? error : undefined
@ -77,7 +77,7 @@ async function edit (ctx) {
ctx.status = 204; ctx.status = 204;
} catch (error) { } catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: error`); ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400; ctx.status = 400;
ctx.body = { ctx.body = {
message: typeof error == 'string' ? error : undefined message: typeof error == 'string' ? error : undefined
@ -161,7 +161,7 @@ async function searchPepMember (ctx) {
ctx.status = 200; ctx.status = 200;
ctx.body = returnD ctx.body = returnD
} catch (error) { } catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: error`); ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400; ctx.status = 400;
ctx.body = { ctx.body = {
message: typeof error == 'string' ? error : undefined message: typeof error == 'string' ? error : undefined
@ -184,7 +184,7 @@ async function del (ctx) {
ctx.status = 204; ctx.status = 204;
} catch (error) { } catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: error`); ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400; ctx.status = 400;
ctx.body = { ctx.body = {
message: typeof error == 'string' ? error : undefined message: typeof error == 'string' ? error : undefined
@ -208,7 +208,7 @@ async function nativePlaceList (ctx) {
ctx.status = 200; ctx.status = 200;
ctx.body = nRes ctx.body = nRes
} catch (error) { } catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: error`); ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400; ctx.status = 400;
ctx.body = { ctx.body = {
message: typeof error == 'string' ? error : undefined message: typeof error == 'string' ? error : undefined
@ -232,7 +232,7 @@ async function workPlaceList (ctx) {
ctx.status = 200; ctx.status = 200;
ctx.body = wRes ctx.body = wRes
} catch (error) { } catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: error`); ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400; ctx.status = 400;
ctx.body = { ctx.body = {
message: typeof error == 'string' ? error : undefined message: typeof error == 'string' ? error : undefined
@ -256,7 +256,7 @@ async function maritalList (ctx) {
ctx.status = 200; ctx.status = 200;
ctx.body = mRes ctx.body = mRes
} catch (error) { } catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: error`); ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400; ctx.status = 400;
ctx.body = { ctx.body = {
message: typeof error == 'string' ? error : undefined message: typeof error == 'string' ? error : undefined
@ -267,82 +267,21 @@ async function maritalList (ctx) {
async function list (ctx) { async function list (ctx) {
try { try {
const { models } = ctx.fs.dc; const { models } = ctx.fs.dc;
const { judgeHoliday, memberList } = ctx.app.fs.utils const { judgeHoliday, memberList, packageUserData } = ctx.app.fs.utils
const { const {
keywordTarget, keyword, limit, page, state, keywordTarget, keyword, limit, page, state,
hiredateStart, hiredateEnd, marital, native, workPlace hiredateStart, hiredateEnd, marital, native, workPlace,
orderBy, orderDirection,
} = ctx.query } = ctx.query
const curDay = moment().format('YYYY-MM-DD')
const nowTime = moment()
const holidayJudge = await judgeHoliday(curDay)
let workTime = false
let dayoffTime = false
if (holidayJudge) {
if (
holidayJudge.workday
&& nowTime.isAfter(moment(curDay + ' 08:30'))
&& nowTime.isBefore(moment(curDay + ' 17:30'))
) {
workTime = true
} else if (holidayJudge.dayoff || holidayJudge.festivals) {
dayoffTime = true
}
}
const userRes = await memberList({ const userRes = await memberList({
keywordTarget, keyword, limit, page, state, keywordTarget, keyword, limit, page, state,
hiredateStart, hiredateEnd, marital, native, workPlace hiredateStart, hiredateEnd, marital, native, workPlace,
orderBy, orderDirection, nowAttendanceTime: true
}) })
let returnD = [] let { packageUser: returnD, pepUserIds } = await packageUserData(userRes, {
userRes.rows.forEach(u => { state: true,
let existUser = returnD.find(r => r.pepUserId == u.pepUserId)
if (existUser) {
if (u.depId && !existUser.departmrnt.some(d => d.id == u.depId)) {
existUser.departmrnt.push({
id: u.depId,
name: u.depName
})
}
if (u.roleId && !existUser.role.some(r => r.id == u.roleId)) {
existUser.role.push({
id: u.roleId,
name: u.roleName
})
}
} else {
let obj = {}
for (let k in u) {
let nextKey = k.replace('hrMember.', '')
.replace('member.', '')
if (nextKey.includes('_')) {
nextKey = nextKey.toLowerCase()
.replace(
/(_)[a-z]/g,
(L) => L.toUpperCase()
)
.replace(/_/g, '')
}
obj[nextKey] = u[k] == '1970-01-01 00:00:00.000000' ? null : u[k]
}
returnD.push({
...obj,
departmrnt: u.depId ? [{
id: u.depId,
name: u.depName
}] : [],
role: u.roleId ? [{
id: u.roleId,
name: u.roleName
}] : [],
state: obj['dimissionDate'] ? 'dimission' :
obj['vacateStartTime'] ? 'vacate' :
workTime ? 'inOffice' :
dayoffTime ? 'dayoff' : 'rest',
del: undefined,
pepuserid: undefined,
})
}
}) })
ctx.status = 200; ctx.status = 200;
@ -351,7 +290,7 @@ async function list (ctx) {
rows: returnD rows: returnD
} }
} catch (error) { } catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: error`); ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400; ctx.status = 400;
ctx.body = { ctx.body = {
message: typeof error == 'string' ? error : undefined message: typeof error == 'string' ? error : undefined
@ -369,8 +308,8 @@ async function overTimeStatistics (ctx) {
const timeOption = [] const timeOption = []
if (startDate && endDate) { if (startDate && endDate) {
timeOption.push( timeOption.push(
`wpStory.create_at <= '${moment(endDate).format('YYYY-MM-DD HH:mm:ss')}' `wpStory.create_at <= '${moment(endDate).endOf('day').format('YYYY-MM-DD HH:mm:ss')}'
AND wpStory.create_at > '${moment(startDate).format('YYYY-MM-DD HH:mm:ss')}'` AND wpStory.create_at >= '${moment(startDate).startOf('day').format('YYYY-MM-DD HH:mm:ss')}'`
) )
} }
const dataRes = await clickHouse.hr.query(` const dataRes = await clickHouse.hr.query(`
@ -440,7 +379,7 @@ async function overTimeStatistics (ctx) {
ctx.status = 200; ctx.status = 200;
ctx.body = returnD ctx.body = returnD
} catch (error) { } catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: error`); ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400; ctx.status = 400;
ctx.body = { ctx.body = {
message: typeof error == 'string' ? error : undefined message: typeof error == 'string' ? error : undefined
@ -458,12 +397,12 @@ async function vacateStatistics (ctx) {
const timeOption = [] const timeOption = []
if (startDate) { if (startDate) {
timeOption.push( timeOption.push(
`wpStory.create_at > '${moment(startDate).format('YYYY-MM-DD HH:mm:ss')}'` `wpStory.create_at > '${moment(startDate).startOf('day').format('YYYY-MM-DD HH:mm:ss')}'`
) )
} }
if (endDate) { if (endDate) {
timeOption.push( timeOption.push(
`wpStory.create_at <= '${moment(endDate).format('YYYY-MM-DD HH:mm:ss')}'` `wpStory.create_at <= '${moment(endDate).endOf('day').format('YYYY-MM-DD HH:mm:ss')}'`
) )
} }
const dataRes = await clickHouse.hr.query(` const dataRes = await clickHouse.hr.query(`
@ -520,7 +459,7 @@ async function vacateStatistics (ctx) {
ctx.status = 200; ctx.status = 200;
ctx.body = returnD ctx.body = returnD
} catch (error) { } catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: error`); ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400; ctx.status = 400;
ctx.body = { ctx.body = {
message: typeof error == 'string' ? error : undefined message: typeof error == 'string' ? error : undefined
@ -532,62 +471,15 @@ async function exportData (ctx) {
try { try {
const { models } = ctx.fs.dc; const { models } = ctx.fs.dc;
const { clickHouse, opts: { qiniu } } = ctx.app.fs const { clickHouse, opts: { qiniu } } = ctx.app.fs
const { simpleExcelDown, memberList } = ctx.app.fs.utils const { simpleExcelDown, memberList, packageUserData } = ctx.app.fs.utils
const { keywordTarget, keyword, limit, page, state, keys = '' } = ctx.query const { keywordTarget, keyword, limit, page, state, keys = '' } = ctx.query
const userRes = await memberList({ keywordTarget, keyword, limit, page, state }) const userRes = await memberList({ keywordTarget, keyword, limit, page, state, nowAttendanceTime: true })
const tableAttributes = models['Member'].tableAttributes const tableAttributes = models['Member'].tableAttributes
const optionKeys = keys.split(',') const optionKeys = keys.split(',')
let exportD = [] let { packageUser: exportD, pepUserIds } = await packageUserData(userRes)
let pepUserIds = []
userRes.rows.forEach(u => {
let existUser = exportD.find(r => r.pepUserId == u.pepUserId)
if (existUser) {
if (u.depId && !existUser.departmrnt.some(d => d.id == u.depId)) {
existUser.departmrnt.push({
id: u.depId,
name: u.depName
})
}
if (u.roleId && !existUser.role.some(r => r.id == u.roleId)) {
existUser.role.push({
id: u.roleId,
name: u.roleName
})
}
} else {
let obj = {}
for (let k in u) {
let nextKey = k.replace('hrMember.', '')
.replace('member.', '')
if (nextKey.includes('_')) {
nextKey = nextKey.toLowerCase()
.replace(
/(_)[a-z]/g,
(L) => L.toUpperCase()
)
.replace(/_/g, '')
}
obj[nextKey] = u[k] == '1970-01-01 00:00:00.000000' ? null : u[k]
}
pepUserIds.push(u.pepUserId)
exportD.push({
...obj,
departmrnt: u.depId ? [{
id: u.depId,
name: u.depName
}] : [],
role: u.roleId ? [{
id: u.roleId,
name: u.roleName
}] : [],
del: undefined,
pepuserid: undefined
})
}
})
let preHeader = [{ let preHeader = [{
title: '姓名', title: '姓名',
@ -668,7 +560,7 @@ async function exportData (ctx) {
ctx.set('Content-disposition', 'attachment; filename=' + encodeURI(fileName)); ctx.set('Content-disposition', 'attachment; filename=' + encodeURI(fileName));
ctx.body = fileData; ctx.body = fileData;
} catch (error) { } catch (error) {
ctx.fs.logger.error(`path: ${ctx.path}, error: error`); ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`);
ctx.status = 400; ctx.status = 400;
ctx.body = { ctx.body = {
message: typeof error == 'string' ? error : undefined message: typeof error == 'string' ? error : undefined

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

@ -82,7 +82,7 @@ module.exports = dc => {
type: DataTypes.STRING, type: DataTypes.STRING,
allowNull: true, allowNull: true,
defaultValue: null, defaultValue: null,
comment: null, comment: '联系方式',
primaryKey: false, primaryKey: false,
field: "phone_number", field: "phone_number",
autoIncrement: false autoIncrement: false

11
api/app/lib/routes/attendance/index.js

@ -0,0 +1,11 @@
'use strict';
const attendance = require('../../controllers/attendance');
module.exports = function (app, router, opts) {
app.fs.api.logAttr['GET/attendance/overtime'] = { content: '加班统计', visible: true };
router.get('/attendance/overtime', attendance.overtimeStatistic);
app.fs.api.logAttr['GET/attendance/vacate'] = { content: '请假统计', visible: true };
router.get('/attendance/vacate', attendance.vacateStatistic);
};

68
api/app/lib/utils/attendance.js

@ -0,0 +1,68 @@
'use strict';
const moment = require('moment')
const request = require('superagent');
module.exports = function (app, opts) {
async function overtimeStatisticListDayType ({
startDate, endDate, pepUserIds = []
}) {
const { clickHouse } = app.fs
const sumRes = await clickHouse.hr.query(`
SELECT
overtime.pep_user_id AS pepUserId,
holiday.type AS dayType,
overtime.compensate AS compensate,
sum(overtime_day.duration) AS duration
FROM overtime_day
INNER JOIN overtime
ON overtime.id = overtime_day.overtime_id
AND overtime.pep_user_id IN (${pepUserIds.join(',')})
LEFT JOIN holiday
ON holiday.day = overtime_day.day
WHERE overtime.pep_user_id IN (${pepUserIds.join(',')})
${startDate ? `
AND overtime_day.day >= '${moment(startDate).format('YYYY-MM-DD')}'
`: ''}
${endDate ? `
AND overtime_day.day <= '${moment(endDate).format('YYYY-MM-DD')}'
` : ''}
GROUP BY holiday.type, overtime.compensate, overtime.pep_user_id
`).toPromise()
return sumRes
}
async function vacateStatisticListDayType ({
startDate, endDate, pepUserIds = []
}) {
const { clickHouse } = app.fs
const sumRes = await clickHouse.hr.query(`
SELECT
vacate.pep_user_id AS pepUserId,
vacate.type AS type,
sum(vacate_day.duration) AS duration
FROM vacate_day
INNER JOIN vacate
ON vacate.id = vacate_day.vacate_id
AND vacate.pep_user_id IN (${pepUserIds.join(',')})
WHERE vacate.pep_user_id IN (${pepUserIds.join(',')})
${startDate ? `
AND vacate_day.day >= '${moment(startDate).format('YYYY-MM-DD')}'
`: ''}
${endDate ? `
AND vacate_day.day <= '${moment(endDate).format('YYYY-MM-DD')}'
` : ''}
GROUP BY vacate.type, vacate.pep_user_id
`).toPromise()
return sumRes
}
return {
overtimeStatisticListDayType,
vacateStatisticListDayType,
}
}

239
api/app/lib/utils/member.js

@ -6,7 +6,13 @@ module.exports = function (app, opts) {
async function memberList ({ async function memberList ({
keywordTarget, keyword, limit, page, state, keywordTarget, keyword, limit, page, state,
hiredateStart, hiredateEnd, marital, native, workPlace hiredateStart, hiredateEnd, marital, native, workPlace,
orderBy, orderDirection,
nowAttendanceTime,
overtimeDayStatisticStartDate, overtimeDayStatisticendDate,
overtimeCountStatistic, overtimeCountStatisticStartDate, overtimeCountStatisticendDate,
vacateDayStatisticStartDate, vacateDayStatisticendDate,
vacateDurationStatistic, vacateCountStatistic, vacateCountStatisticStartDate, vacateCountStatisticendDate
}) { }) {
const { judgeHoliday } = app.fs.utils const { judgeHoliday } = app.fs.utils
const { clickHouse } = app.fs const { clickHouse } = app.fs
@ -58,16 +64,50 @@ module.exports = function (app, opts) {
} }
} }
let overtimeDayStatisticWhere = []
if (overtimeDayStatisticStartDate) {
overtimeDayStatisticWhere.push(`overtime_day.day >= '${moment(overtimeDayStatisticStartDate).format('YYYY-MM-DD')}'`)
}
if (overtimeDayStatisticendDate) {
overtimeDayStatisticWhere.push(`overtime_day.day <= '${moment(overtimeDayStatisticendDate).format('YYYY-MM-DD')}'`)
}
let overtimeCountStatisticWhere = []
if (overtimeCountStatisticStartDate) {
overtimeCountStatisticWhere.push(`overtime.start_time >= '${moment(overtimeCountStatisticStartDate).format('YYYY-MM-DD')}'`)
}
if (overtimeCountStatisticendDate) {
overtimeCountStatisticWhere.push(`overtime.end_time <= '${moment(overtimeCountStatisticendDate).format('YYYY-MM-DD')}'`)
}
let vacateDayStatisticWhere = []
if (vacateDayStatisticStartDate) {
vacateDayStatisticWhere.push(`vacate_day.day >= '${moment(vacateDayStatisticStartDate).format('YYYY-MM-DD')}'`)
}
if (vacateDayStatisticendDate) {
vacateDayStatisticWhere.push(`vacate_day.day <= '${moment(vacateDayStatisticendDate).format('YYYY-MM-DD')}'`)
}
let vacateCountStatisticWhere = []
if (vacateCountStatisticStartDate) {
vacateCountStatisticWhere.push(`vacate.start_time >= '${moment(vacateCountStatisticStartDate).format('YYYY-MM-DD')}'`)
}
if (vacateCountStatisticendDate) {
vacateCountStatisticWhere.push(`vacate.end_time <= '${moment(vacateCountStatisticendDate).format('YYYY-MM-DD')}'`)
}
// CRAZY
const innerSelectQuery = ` const innerSelectQuery = `
FROM member FROM member
INNER JOIN ${pepEmis}.user AS user INNER JOIN ${pepEmis}.user AS user
ON member.pep_user_id = user.id ON member.pep_user_id = user.id
${keywordTarget == 'number' && keyword ? ` ${keywordTarget == 'number' && keyword ? `
AND toString(user.id) LIKE '%${keyword}%' AND user.people_code LIKE '%${keyword}%'
`: ''} `: ''}
${keywordTarget == 'name' && keyword ? ` ${keywordTarget == 'name' && keyword ? `
AND user.name LIKE '%${keyword}%' AND user.name LIKE '%${keyword}%'
`: ''} `: ''}
${nowAttendanceTime ? `
${state == 'vacate' ? 'INNER' : 'LEFT'} JOIN ( ${state == 'vacate' ? 'INNER' : 'LEFT'} JOIN (
SELECT SELECT
pep_user_id, pep_user_id,
@ -80,7 +120,8 @@ module.exports = function (app, opts) {
GROUP BY pep_user_id GROUP BY pep_user_id
) AS hrVacate ) AS hrVacate
ON hrVacate.pep_user_id = member.pep_user_id ON hrVacate.pep_user_id = member.pep_user_id
`: ''}
${nowAttendanceTime ? `
LEFT JOIN ( LEFT JOIN (
SELECT SELECT
pep_user_id, pep_user_id,
@ -93,7 +134,70 @@ module.exports = function (app, opts) {
GROUP BY pep_user_id GROUP BY pep_user_id
) AS hrOvertime ) AS hrOvertime
ON hrOvertime.pep_user_id = member.pep_user_id ON hrOvertime.pep_user_id = member.pep_user_id
`: ''}
${orderBy == 'overtimeTakeRestSum' ||
orderBy == 'overtimePaySum' ||
orderBy == 'overtimeSum' ?
`LEFT JOIN (
SELECT
overtime.pep_user_id AS pepUserId,
sum(overtime_day.duration) AS duration
FROM overtime_day
INNER JOIN overtime
ON overtime.id = overtime_day.overtime_id
${orderBy == 'overtimeTakeRestSum' ? `AND overtime.compensate = '调休'` : ''}
${orderBy == 'overtimePaySum' ? `AND overtime.compensate = '发放加班补偿'` : ''}
${overtimeDayStatisticWhere.length ? `
WHERE ${overtimeDayStatisticWhere.join(' AND ')}
`: ''}
GROUP BY overtime.pep_user_id
) AS overtimeDayStatistic
ON overtimeDayStatistic.pepUserId = member.pep_user_id`: ''}
${overtimeCountStatistic ? `
LEFT JOIN (
SELECT
overtime.pep_user_id AS pepUserId,
count(pep_process_story_id) AS count
FROM overtime
${overtimeCountStatisticWhere.length ? `
WHERE ${overtimeCountStatisticWhere.join(' AND ')}
`: ''}
GROUP BY overtime.pep_user_id
) AS overtimeCountStatistic
ON overtimeCountStatistic.pepUserId = member.pep_user_id
`: ''}
${vacateDurationStatistic ||
orderBy == 'vacateSum' ?
`LEFT JOIN (
SELECT
vacate.pep_user_id AS pepUserId,
sum(vacate_day.duration) AS duration
FROM vacate_day
INNER JOIN vacate
ON vacate.id = vacate_day.vacate_id
${vacateDayStatisticWhere.length ? `
WHERE ${vacateDayStatisticWhere.join(' AND ')}
`: ''}
GROUP BY vacate.pep_user_id
) AS vacateDayStatistic
ON vacateDayStatistic.pepUserId = member.pep_user_id`: ''}
${vacateCountStatistic ? `
LEFT JOIN (
SELECT
vacate.pep_user_id AS pepUserId,
count(pep_process_story_id) AS count
FROM vacate
${vacateCountStatisticWhere.length ? `
WHERE ${vacateCountStatisticWhere.join(' AND ')}
`: ''}
GROUP BY vacate.pep_user_id
) AS vacateCountStatistic
ON vacateCountStatistic.pepUserId = member.pep_user_id
`: ''}
WHERE WHERE
member.del = 0 member.del = 0
${keywordTarget == 'role' && keyword ? ` ${keywordTarget == 'role' && keyword ? `
@ -116,7 +220,7 @@ module.exports = function (app, opts) {
` : ''} ` : ''}
${state == 'dimission' ? `AND member.dimission_date IS NOT null` : ''} ${state == 'dimission' ? `AND member.dimission_date IS NOT null` : ''}
${state == 'onJob' ? `AND member.dimission_date IS null` : ''} ${state == 'onJob' ? `AND member.dimission_date IS null` : ''}
${whereFromSelectOption.length ? `AND ${whereFromSelectOption.join('AND')}` : ''} ${whereFromSelectOption.length && nowAttendanceTime ? `AND ${whereFromSelectOption.join('AND')}` : ''}
${hiredateStart ? ` ${hiredateStart ? `
AND member.hiredate >= '${moment(hiredateStart).format('YYYY-MM-DD')}' AND member.hiredate >= '${moment(hiredateStart).format('YYYY-MM-DD')}'
`: ''} `: ''}
@ -146,18 +250,39 @@ module.exports = function (app, opts) {
department.id AS depId department.id AS depId
FROM ( FROM (
SELECT SELECT
member.*, ${orderBy == 'overtimeTakeRestSum'
|| orderBy == 'overtimePaySum'
|| orderBy == 'overtimeSum' ? `
overtimeDayStatistic.duration AS overtimeDayStatisticDuration
`: ''}
${overtimeCountStatistic ? `
overtimeCountStatistic.count AS overtimeCount,
`: ''}
${orderBy == 'vacateSum' || vacateDurationStatistic ? `
vacateDayStatistic.duration AS vacateDayStatisticDuration,
`: ''}
${vacateCountStatistic ? `
vacateCountStatistic.count AS vacateCount,
`: ''}
${nowAttendanceTime ? `
hrVacate.vacateStartTime AS vacateStartTime, hrVacate.vacateStartTime AS vacateStartTime,
hrVacate.vacateEndTime AS vacateEndTime, hrVacate.vacateEndTime AS vacateEndTime,
hrOvertime.overtimeStartTime AS overtimeStartTime, hrOvertime.overtimeStartTime AS overtimeStartTime,
hrOvertime.overtimeEndTime AS overtimeEndTime hrOvertime.overtimeEndTime AS overtimeEndTime,
`: ''}
member.*
${innerSelectQuery} ${innerSelectQuery}
${limit ? `LIMIT ${limit}` : ''} ${limit ? `LIMIT ${limit}` : ''}
${limit && page ? 'OFFSET ' + parseInt(limit) * parseInt(page) : ''} ${limit && page ? 'OFFSET ' + parseInt(limit) * parseInt(page) : ''}
) AS hrMember ) AS hrMember
LEFT JOIN ${pepEmis}.user AS user LEFT JOIN ${pepEmis}.user AS user
ON hrMember."member.pep_user_id" = user.id ON pepUserId = user.id
LEFT JOIN ${pepEmis}.user_role AS user_role LEFT JOIN ${pepEmis}.user_role AS user_role
ON ${pepEmis}.user_role.user = user.id ON ${pepEmis}.user_role.user = user.id
LEFT JOIN ${pepEmis}.role AS role LEFT JOIN ${pepEmis}.role AS role
@ -167,6 +292,24 @@ module.exports = function (app, opts) {
LEFT JOIN ${pepEmis}.department AS department LEFT JOIN ${pepEmis}.department AS department
ON department.id = department_user.department ON department.id = department_user.department
${whereOption.length ? `WHERE ${whereOption.join(' AND ')}` : ''} ${whereOption.length ? `WHERE ${whereOption.join(' AND ')}` : ''}
ORDER BY ${orderBy == 'code' ?
'user.people_code'
: orderBy == 'hiredate'
? 'hrMember."member.hiredate"'
: orderBy == 'age'
? 'hrMember."member.birthday"'
: orderBy == 'overtimeTakeRestSum'
|| orderBy == 'overtimePaySum'
|| orderBy == 'overtimeSum' ?
'hrMember."member.overtimeDayStatisticDuration"'
: orderBy == 'overtimeCount' ?
'hrMember.overtimeCount'
: orderBy == 'vacateSum' ?
'hrMember.vacateDayStatisticDuration'
: orderBy == 'vacateCount' ?
'hrMember.vacateCount'
: 'user.people_code'}
${orderDirection || 'ASC'}
`).toPromise() `).toPromise()
const countRes = await clickHouse.hr.query(` const countRes = await clickHouse.hr.query(`
@ -181,7 +324,87 @@ module.exports = function (app, opts) {
} }
} }
async function packageUserData (userRes, option = {}) {
const { judgeHoliday, } = app.fs.utils
let workTime = false
let dayoffTime = false
if (option.state) {
const curDay = moment().format('YYYY-MM-DD')
const nowTime = moment()
const holidayJudge = await judgeHoliday(curDay)
if (holidayJudge) {
if (
holidayJudge.workday
&& nowTime.isAfter(moment(curDay + ' 08:30'))
&& nowTime.isBefore(moment(curDay + ' 17:30'))
) {
workTime = true
} else if (holidayJudge.dayoff || holidayJudge.festivals) {
dayoffTime = true
}
}
}
let returnD = []
let pepUserIds = []
userRes.rows.forEach(u => {
let existUser = returnD.find(r => r.pepUserId == u.pepUserId)
if (existUser) {
if (u.depId && !existUser.departmrnt.some(d => d.id == u.depId)) {
existUser.departmrnt.push({
id: u.depId,
name: u.depName
})
}
if (u.roleId && !existUser.role.some(r => r.id == u.roleId)) {
existUser.role.push({
id: u.roleId,
name: u.roleName
})
}
} else {
let obj = {}
for (let k in u) {
let nextKey = k.replace('hrMember.', '')
.replace('member.', '')
if (nextKey.includes('_')) {
nextKey = nextKey.toLowerCase()
.replace(
/(_)[a-z]/g,
(L) => L.toUpperCase()
)
.replace(/_/g, '')
}
obj[nextKey] = u[k] == '1970-01-01 00:00:00.000000' ? null : u[k]
}
pepUserIds.push(u.pepUserId)
returnD.push({
...obj,
departmrnt: u.depId ? [{
id: u.depId,
name: u.depName
}] : [],
role: u.roleId ? [{
id: u.roleId,
name: u.roleName
}] : [],
state: option.state ?
obj['dimissionDate'] ? 'dimission' :
obj['vacateStartTime'] ? 'vacate' :
workTime ? 'inOffice' :
dayoffTime ? 'dayoff' : 'rest'
: undefined,
del: undefined,
pepuserid: undefined
})
}
})
return { packageUser: returnD, pepUserIds }
}
return { return {
memberList memberList,
packageUserData
} }
} }

BIN
web/client/assets/images/hrImg/!.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 554 B

BIN
web/client/assets/images/hrImg/V.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 838 B

BIN
web/client/assets/images/hrImg/setUp.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

2
web/client/index.ejs

@ -9,7 +9,7 @@
<link rel="shortcut icon" href="/assets/images/favicon.ico"> <link rel="shortcut icon" href="/assets/images/favicon.ico">
<script src="https://lf1-cdn-tos.bytegoofy.com/obj/iconpark/icons_19077_10.1efd80a22a5e53e48737fd5ab150ffd2.es5.js"></script> <script src="https://lf1-cdn-tos.bytegoofy.com/obj/iconpark/icons_20231_3.d613c57d3bf10acf9916c8162dae204a.es5.js"></script>
</head> </head>
<body> <body>

4
web/client/index.html

@ -8,8 +8,8 @@
<link rel="shortcut icon" href="/assets/images/favicon.ico"> <link rel="shortcut icon" href="/assets/images/favicon.ico">
<script <script
src="https://lf1-cdn-tos.bytegoofy.com/obj/iconpark/icons_19077_11.27aacefc59cea1cbc86236576463a6d2.es5.js"></script> src="https://lf1-cdn-tos.bytegoofy.com/obj/iconpark/icons_20231_3.d613c57d3bf10acf9916c8162dae204a.es5.js"></script>
</head> </head>
<body> <body>
<div id='HrApp' style="height: 100%;"></div> <div id='HrApp' style="height: 100%;"></div>

25
web/client/src/components/setup.jsx

@ -5,15 +5,13 @@ import {
Checkbox, Checkbox,
} from "@douyinfe/semi-ui"; } from "@douyinfe/semi-ui";
function Setup(props) { function Setup (props) {
const { const {
close, close,
tableType, tableType,
tableList tableList,
length
} = props; } = props;
console.log(tableType,
tableList);
const [check, setCheck] = useState([]); const [check, setCheck] = useState([]);
const checkboxcss = { width: "25%", height: 16, margin: "0 0 20px 0" }; const checkboxcss = { width: "25%", height: 16, margin: "0 0 20px 0" };
@ -21,11 +19,11 @@ function Setup(props) {
useEffect(() => { useEffect(() => {
// //
const checkItem = localStorage.getItem(tableType); const checkItem = localStorage.getItem(tableType);
setCheck(checkItem?JSON.parse(checkItem) : []) setCheck(checkItem ? JSON.parse(checkItem) : [])
ischeck(); ischeck();
}, []); }, []);
function ischeck(value) { function ischeck (value) {
if (check.length >= 8) { if (check.length >= length) {
if (check.includes(value)) { if (check.includes(value)) {
return false; return false;
} else { } else {
@ -49,12 +47,12 @@ function Setup(props) {
textAlign: "center", textAlign: "center",
marginLeft: 6, marginLeft: 6,
background: background:
check.length == 8 check.length == length
? "rgba(40, 123, 255, 1)" ? "rgba(40, 123, 255, 1)"
: "rgba(176, 176, 176, 1)", : "rgba(176, 176, 176, 1)",
}} }}
> >
{check.length}/8 {check.length}/{length}
</span> </span>
</div> </div>
} }
@ -79,8 +77,8 @@ function Setup(props) {
ischeck(); ischeck();
}} }}
> >
{tableList.map((item,index)=>{ {tableList.map((item, index) => {
return( return (
<div <div
key={index} key={index}
style={{ style={{
@ -115,7 +113,8 @@ function Setup(props) {
})} })}
</div> </div>
</div> </div>
)})} )
})}
</CheckboxGroup> </CheckboxGroup>
</Modal> </Modal>
); );

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

@ -0,0 +1,26 @@
'use strict';
import { ApiTable, basicAction } from '$utils'
export function getMemberNativePlace(query) {//查询籍贯列表
return (dispatch) => basicAction({
type: "get",
dispatch: dispatch,
actionType: "GET_MemberNativePlace",
query: query,
url: `${ApiTable.getMemberNativePlace}`,
msg: { option: "查询籍贯列表" },
reducer: { name: "MemberNativePlace", params: { noClear: true } },
});
}
export function getMemberWorkPlace(query) {//查询工作地列表
return (dispatch) => basicAction({
type: "get",
dispatch: dispatch,
actionType: "GET_MemberWorkPlace",
query: query,
url: `${ApiTable.getMemberWorkPlace}`,
msg: { option: "查询工作地列表" },
reducer: { name: "MemberWorkPlace", params: { noClear: true } },
});
}

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

@ -1,6 +1,9 @@
'use strict'; 'use strict';
import * as personnelFiles from './personnelFiles' import * as personnelFiles from './personnelFiles'
import * as employeeInformation from './employeeInformation'
export default { export default {
...personnelFiles, ...personnelFiles,
...employeeInformation
} }

10
web/client/src/sections/humanAffairs/components/personnelModal.jsx

@ -93,7 +93,7 @@ function pushModal (props) {
form.current form.current
.validate() .validate()
.then((values) => { .then((values) => {
if (peoplePro.userCode) { if (peoplePro?.userCode) {
if (values.userCode == peoplePro.userCode) { if (values.userCode == peoplePro.userCode) {
let obj = values let obj = values
if (values.nativePlace) { if (values.nativePlace) {
@ -187,7 +187,9 @@ function pushModal (props) {
rules={[{ required: true, message: "请输入人员编号" }]} /> rules={[{ required: true, message: "请输入人员编号" }]} />
<div style={{ marginLeft: 12, color: '#005ABD', cursor: "pointer", fontSize: 14 }} onClick={() => { <div style={{ marginLeft: 12, color: '#005ABD', cursor: "pointer", fontSize: 14 }} onClick={() => {
let formList = form.current.getValues() let formList = form.current.getValues()
if(formList.userCode){
memberSeach(formList.userCode) memberSeach(formList.userCode)
}
}}> }}>
搜索 搜索
</div> </div>
@ -328,7 +330,7 @@ function pushModal (props) {
label='籍贯:' label='籍贯:'
showClear showClear
style={{ width: 184 }} style={{ width: 184 }}
initValue={editObj?.nativePlace.split('-') || ""} initValue={editObj?.nativePlace?.split('-') || ""}
> >
</Form.Cascader> </Form.Cascader>
</div> </div>
@ -371,7 +373,7 @@ function pushModal (props) {
field='workPlace' field='workPlace'
label='工作地点:' label='工作地点:'
showClear showClear
initValue={editObj?.workPlace.split('-') || ""} initValue={editObj?.workPlace?.split('-') || ""}
style={{ width: 184 }} style={{ width: 184 }}
> >
</Form.Cascader> </Form.Cascader>
@ -547,7 +549,7 @@ function pushModal (props) {
label='工作经验:' label='工作经验:'
maxLength="2" maxLength="2"
style={{ width: 288 }} style={{ width: 288 }}
initValue={editObj?.experienceYear || ""} initValue={String(editObj?.experienceYear) || ""}
placeholder="请输入工作经验,不超过2位数字" placeholder="请输入工作经验,不超过2位数字"
showClear showClear
rules={[{ pattern: "^[0-9]*[1-9][0-9]*$", message: "请输入工作经验,不超过2位数字" },]} rules={[{ pattern: "^[0-9]*[1-9][0-9]*$", message: "请输入工作经验,不超过2位数字" },]}

432
web/client/src/sections/humanAffairs/containers/employeeInformation.jsx

@ -0,0 +1,432 @@
import React, { useEffect, useState, useRef } from 'react';
import { connect } from 'react-redux';
import { Table, Button, Pagination, Skeleton, Form, Tooltip } from '@douyinfe/semi-ui';
import { IconSearch } from '@douyinfe/semi-icons';
import { SkeletonScreen } from "$components";
import '../style.less'
import { Setup } from "$components";
import moment from 'moment'
import { set } from 'nprogress';
const employeeInformation = (props) => {
const { dispatch, actions, history, user, loading, socket, xqMembers } = props
const { humanAffairs } = actions;
const form = useRef();//
let [archivesList, setArchivesList] = useState([]);//
let [workPlaceList, setWorkPlaceList] = useState([]);//
let [nativeList, setNativeList] = useState([]);//
const [setup, setSetup] = useState(false);//
const [setupp, setSetupp] = useState([]);//
const [query, setQuery] = useState({ limit: 10, page: 0 }); //
const [limits, setLimits] = useState()//
const EMPLOYEEINFORMATION = "employeeInformation";
const tableList = [//
{
title: '基础信息',
list: [
{ name: "员工编号", value: "userCode" },
{ name: "姓名", value: "userName" },
{ name: "所属部门", value: "departmrnt" },
// { name: "", value: "monitorCount" },
// { name: "", value: "logCount" },
]
}
];
useEffect(() => {
getMemberNativePlaceList()//
getMemberWorkPlaceList()//
getMemberSearchList()//
attribute();
localStorage.getItem(EMPLOYEEINFORMATION) == null
? localStorage.setItem(
EMPLOYEEINFORMATION,
JSON.stringify(['userCode', 'userName', 'departmrnt'])
)
: "";
}, [])
function getMemberSearchList () {//
let obj = form.current.getValues()
if (form.current.getValues().entryTime?.length > 1) {
obj.hiredateStart = moment(form.current.getValues().entryTime[0]).format('YYYY-MM-DD')
obj.hiredateEnd = moment(form.current.getValues().entryTime[1]).format('YYYY-MM-DD')
}
else {
obj.hiredateStart = ''
obj.hiredateEnd = ''
}
setQuery({ limit: 10, page: 0 })
dispatch(humanAffairs.getMemberList({ ...obj, ...query })).then((res) => {//
if (res.success) {
setArchivesList(res.payload?.data?.rows)
setLimits(res.payload?.data?.count)
}
})
}
function getMemberNativePlaceList () {
dispatch(humanAffairs.getMemberNativePlace()).then((res) => {//
if (res.success) {
setNativeList(res.payload?.data)
}
})
}
function getMemberWorkPlaceList () {
dispatch(humanAffairs.getMemberWorkPlace()).then((res) => {//
if (res.success) {
setWorkPlaceList(res.payload?.data)
}
})
}
const columns = [];
//
function attribute () {
const arr = localStorage.getItem(EMPLOYEEINFORMATION)
? JSON.parse(localStorage.getItem(EMPLOYEEINFORMATION))
: [];
const column = [
{
title: (
<div>
<img src="/assets/images/hrImg/V.png" alt="" style={{ width: 14, height: 14 }} /> 员工编号
</div>
),
dataIndex: "userCode",
key: "userCode",
render: (_, r, index) => {
return r.userCode;
},
}, {
title: (
<div>
<img src="/assets/images/hrImg/V.png" alt="" style={{ width: 14, height: 14 }} /> 姓名
</div>
),
dataIndex: "userName",
key: "userName",
render: (_, r, index) => {
return r.userName;
},
}, {
title: (
<div>
<img src="/assets/images/hrImg/V.png" alt="" style={{ width: 14, height: 14 }} /> 所属部门
</div>
),
dataIndex: "departmrnt",
key: "departmrnt",
render: (_, r, index) => {
return (
<div>
{
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: '#FFFFFF', fontSize: 12, background: 'rgba(0,90,189,0.8)', borderRadius: 2, marginRight: 4, cursor: "pointer", }}>
...
</div>
</Tooltip>
) : ('')
}
</div>
)
})
}
</div>
)
},
},
// {
// title: "",
// dataIndex: "logCount",
// key: "logCount",
// render: (_, r, index) => {
// return (r.logCount + '')
// },
// },
// {
// title: "",
// dataIndex: "monitorCount",
// key: "monitorCount",
// render: (_, r, index) => {
// return r.monitorCount
// },
// },
// {
// title: "",
// dataIndex: "pushWay",
// key: "pushWay",
// render: (_, r, index) => {
// return r.pushWay == 'email' ? '' : '';
// },
// },
// {
// title: "",
// dataIndex: "text1",
// key: "text1",
// render: (_, r, index) => {
// return r.text1
// },
// },
// {
// title: "",
// dataIndex: "text2",
// key: "text2",
// render: (_, r, index) => {
// return r.text2
// },
// },
// {
// title: "",
// dataIndex: "time",
// key: "time",
// render: (_, r, index) => {
// return r.time
// },
// },
];
for (let i = 0; i < arr.length; i++) {
let colum = column.filter((item) => {
return item.key === arr[i];
});
columns.splice(i + 2, 0, colum[0]);
}
setSetupp(columns);
}
function handleRow (record, index) {//
//
if (index % 2 === 0) {
return {
style: {
background: '#FAFCFF',
}
};
} else {
return {};
}
}
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", }}>EMPLOYEE INFORMATION</div>
</div>
</div>
<div style={{ marginRight: 20, marginTop: 18 }}>
<Form
labelPosition="left"
labelAlign="right"
labelWidth="80px"
onValueChange={(values, field) => {
console.log('values', values);
}}
getFormApi={(formApi) => (form.current = formApi)}
>
<div>
<div style={{ display: 'flex', alignItems: 'center' }}>
<Form.Select
pure
field="keywordTarget"
placeholder="请选择搜索类型"
style={{ width: 200 }}
showClear
>
<Form.Select.Option value='role'>职位</Form.Select.Option>
<Form.Select.Option value='dep'>部门</Form.Select.Option>
<Form.Select.Option value='number'>编号</Form.Select.Option>
<Form.Select.Option value='name'>姓名</Form.Select.Option>
</Form.Select>
<Form.Input
suffix={<IconSearch />}
field="keyword"
pure
showClear
style={{ width: 346, marginLeft: 12, marginRight: 12 }}
placeholder="请输入或选择关键词"
/>
<Form.DatePicker
label='入职时间:'
field='entryTime' type="dateRange" density="compact" showClear style={{ width: 370, color: "#F9F9F9" }} />
</div>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<div style={{ display: 'flex', alignItems: 'center' }}>
<Form.Select
label="婚育状态:"
field="marital"
labelPosition="left"
placeholder="全部"
style={{ width: 246, marginRight: 20, color: "#F9F9F9", }}
showClear
>
<Form.Select.Option value=''>
全部
</Form.Select.Option>
<Form.Select.Option value='已婚已育'>
已婚已育
</Form.Select.Option>
<Form.Select.Option value='已婚'>
已婚
</Form.Select.Option>
<Form.Select.Option value='未婚'>
未婚
</Form.Select.Option>
</Form.Select>
<Form.Select
label='户籍地:'
labelPosition="left"
field='native'
style={{ width: 246, marginRight: 20, color: "#F9F9F9", }}
placeholder="全部"
showClear
>
{nativeList.map((item) => {
return (
<Form.Select.Option key={item.nativePlace} value={item.nativePlace}>
{item.nativePlace}
</Form.Select.Option>
);
})}
</Form.Select>
<Form.Select
label='工作地点:'
labelPosition="left"
field='workPlace'
style={{ width: 246, marginRight: 20, color: "#F9F9F9", }}
placeholder="全部"
showClear
>
{workPlaceList.map((item) => {
return (
<Form.Select.Option key={item.workPlace} value={item.workPlace}>
{item.workPlace}
</Form.Select.Option>
);
})}
</Form.Select>
</div>
<div style={{ display: 'flex', alignItems: 'center' }}>
<img src="/assets/images/hrImg/export.png" alt="" style={{ width: 20, height: 20, cursor: "pointer", marginRight: 15 }}
// onClick={() => setSetup(true)}
/>
<img src="/assets/images/hrImg/setup.png" alt="" style={{ width: 20, height: 20, cursor: "pointer", marginRight: 15 }}
onClick={() => setSetup(true)}
/>
<Button theme='solid' type='primary' style={{ width: 80, borderRadius: 2, height: 32, background: '#DBECFF', color: '#005ABD' }}
onClick={() => {
getMemberSearchList()
}}>查询</Button>
</div>
</div>
</div>
</Form>
<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={setupp.filter((s) => s)}
dataSource={archivesList}
bordered={false}
empty="暂无数据"
pagination={false}
onRow={handleRow}
/>
</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>
{setup ? (
<Setup
tableType={EMPLOYEEINFORMATION}
tableList={tableList}
length={25}
close={() => {
setSetup(false);
attribute();
// setcameraSetup(false);
}}
/>
) : (
""
)}
</>
)
}
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)(employeeInformation);

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

@ -2,5 +2,6 @@
import PersonnelFiles from './personnelFiles'; import PersonnelFiles from './personnelFiles';
import PersonnelFilesDetail from './personnelFilesDetail'; import PersonnelFilesDetail from './personnelFilesDetail';
import EmployeeInformation from './employeeInformation';
export { PersonnelFiles, PersonnelFilesDetail }; export { PersonnelFiles, PersonnelFilesDetail, EmployeeInformation };

4
web/client/src/sections/humanAffairs/containers/personnelFiles.jsx

@ -162,7 +162,7 @@ const Rest = (props) => {
<div style={{ marginLeft: 4 }}> <div style={{ marginLeft: 4 }}>
<div style={{ display: 'flex' }}> <div style={{ display: 'flex' }}>
<div style={{ color: '#005ABD', fontSize: 14, marginRight: 6 }}> <div style={{ color: '#005ABD', fontSize: 14, marginRight: 6 }}>
{item.pepUserId} {item.userCode}
</div> </div>
{ {
item.departmrnt.map((ite, idx) => { item.departmrnt.map((ite, idx) => {
@ -256,7 +256,7 @@ const Rest = (props) => {
<div style={{ marginTop: 16, marginLeft: 4 }}> <div style={{ marginTop: 16, marginLeft: 4 }}>
<Button theme='solid' type='primary' style={{ width: 212, borderRadius: 17, height: 28 }} <Button theme='solid' type='primary' style={{ width: 212, borderRadius: 17, height: 28 }}
onClick={() => { onClick={() => {
history.push(`/personnelFilesDetail?${item.pepUserId}`); history.push(`/personnelFilesDetail?${item.userCode}-${item.pepUserId}`);
}}>详情</Button> }}>详情</Button>
</div> </div>
</div> </div>

180
web/client/src/sections/humanAffairs/containers/personnelFilesDetail.jsx

@ -129,6 +129,7 @@ const Rest = (props) => {
}, },
]) ])
const [pepUserCode, setPepUserCode] = useState('');
const [pepUserId, setPepUserId] = useState(''); const [pepUserId, setPepUserId] = useState('');
const [pepObj, setPepObj] = useState({}); const [pepObj, setPepObj] = useState({});
const scroll = useMemo(() => ({ y: 248 }), []); const scroll = useMemo(() => ({ y: 248 }), []);
@ -137,7 +138,8 @@ const Rest = (props) => {
const [endDate, setEndDate] = useState('');// const [endDate, setEndDate] = useState('');//
useEffect(() => { useEffect(() => {
setPepUserId(history?.location?.search.slice(1)) setPepUserCode(history?.location?.search.slice(1).split('-')[0])
setPepUserId(history?.location?.search.slice(1).split('-')[1])
peopleDetail() peopleDetail()
}, []) }, [])
useEffect(() => { useEffect(() => {
@ -145,29 +147,71 @@ const Rest = (props) => {
getLeaveOption()// getLeaveOption()//
}, [startDate, endDate]) }, [startDate, endDate])
function peopleDetail () { function peopleDetail () {
dispatch(humanAffairs.getMemberList({ keywordTarget: 'number', keyword: history?.location?.search.slice(1) })).then((res) => {// dispatch(humanAffairs.getMemberList({ keywordTarget: 'number', keyword: history?.location?.search.slice(1).split('-')[0] })).then((res) => {//
if (res.success) { if (res.success) {
setPepObj(res.payload?.data?.rows[0]) setPepObj(res.payload?.data?.rows[0])
} }
}) })
} }
function getWorkOption () {//线 function getWorkOption () {//线
dispatch(humanAffairs.getMemberOvertime({ pepUserId: history?.location?.search.slice(1), startDate: startDate, endDate: endDate })).then((res) => {// let date = [];
let showdate = []
let showdate1 = []
dispatch(humanAffairs.getMemberOvertime({ pepUserId: history?.location?.search.slice(1).split('-')[1], startDate: startDate, endDate: endDate })).then((res) => {//
if (res.success) { if (res.success) {
setTableData(res.payload?.data?.data) setTableData(res.payload?.data?.data)
setTableStatistic(res.payload?.data) setTableStatistic(res.payload?.data)
let textdate = [];
for (let i = 0; i < res.payload?.data?.dayStatisticData?.length; i++) {
if (textdate.findIndex((ev) => {
return ev.time == moment(res.payload.data.dayStatisticData[i].day).format('YYYY/MM')&&ev.compensate == res.payload.data.dayStatisticData[i].compensate
}) !== -1) {
textdate[textdate.findIndex((ev) => {
return ev.time == moment(res.payload.data.dayStatisticData[i].day).format('YYYY/MM')&&ev.compensate == res.payload.data.dayStatisticData[i].compensate
})].num
=
textdate[textdate.findIndex((ev) => {
return ev.time == moment(res.payload.data.dayStatisticData[i].day).format('YYYY/MM')&&ev.compensate == res.payload.data.dayStatisticData[i].compensate
})].num + res.payload.data.dayStatisticData[i].duration / 3600
} }
else {
textdate.push({
time: moment(res.payload.data.dayStatisticData[i].day).format('YYYY/MM'),
num: res.payload.data.dayStatisticData[i].duration / 3600,
compensate: res.payload.data.dayStatisticData[i].compensate
}) })
var date = []; }
date.push([2017, 6, 1].join("/"));
date.push([2017, 6, 2].join("/")); }
date.push([2017, 6, 3].join("/")); console.log('textdate', textdate);
date.push([2017, 6, 4].join("/")); for (let l = 0; l < textdate.length; l++) {
date.push([2017, 6, 5].join("/")); if (textdate[l].compensate == '调休') {
date.push([2017, 6, 6].join("/")); showdate.push([textdate[l].time, textdate[l].num])
date.push([2017, 6, 7].join("/")); }
date.push([2017, 6, 8].join("/")); else {
date.push([2017, 6, 9].join("/")); showdate1.push([textdate[l].time, textdate[l].num])
}
}
if (!startDate && !endDate) {
for (let i = 0; i < 12; i++) {
date.unshift(moment(new Date()).subtract(i, 'months').format('YYYY/MM'));
}
}
else {
let nowdate = moment(startDate).format('YYYY/MM')
date.push(nowdate)
for (let o = 0; o < 10000; o++) {
if (nowdate !== moment(endDate).format('YYYY/MM')) {
nowdate = moment(nowdate).add(1, 'months').format('YYYY/MM')
date.push(nowdate)
}
else {
break
}
}
}
let data = { let data = {
legend: { legend: {
data: ["调休", "折算"], data: ["调休", "折算"],
@ -217,13 +261,7 @@ const Rest = (props) => {
opacity: 0.1 opacity: 0.1
}, },
smooth: true, smooth: true,
data: [ data: showdate,
["2017/6/1", 1],
["2017/6/3", 3],
["2017/6/5", 5],
["2017/6/7", 4],
["2017/6/9", 4],
],
}, },
{ {
name: "折算", name: "折算",
@ -232,19 +270,18 @@ const Rest = (props) => {
color: 'rgba(254,152,18,0.2)', color: 'rgba(254,152,18,0.2)',
}, },
smooth: true, smooth: true,
data: [ data: showdate1,
["2017/6/2", 3],
["2017/6/4", 1],
["2017/6/6", 6],
["2017/6/8", 3],
],
}, },
], ],
} }
setOption(data) setOption(data)
} }
})
}
function getLeaveOption () {//线 function getLeaveOption () {//线
dispatch(humanAffairs.getMemberVacate({ pepUserId: history?.location?.search.slice(1), startDate: startDate, endDate: endDate })).then((res) => {// let date = [];
let showdate = []
dispatch(humanAffairs.getMemberVacate({ pepUserId: history?.location?.search.slice(1).split('-')[1], startDate: startDate, endDate: endDate })).then((res) => {//
if (res.success) { if (res.success) {
setLeaveData(res.payload?.data?.data) setLeaveData(res.payload?.data?.data)
let year = 0; let year = 0;
@ -270,18 +307,49 @@ const Rest = (props) => {
setLeaveStatistic({ setLeaveStatistic({
compassionate, sick, year, other, all compassionate, sick, year, other, all
}) })
let textdate = [];
for (let i = 0; i < res.payload?.data?.dayStatisticData?.length; i++) {
if (textdate.findIndex((ev) => {
return ev.time == moment(res.payload.data.dayStatisticData[i].day).format('YYYY/MM')
}) !== -1) {
textdate[textdate.findIndex((ev) => {
return ev.time == moment(res.payload.data.dayStatisticData[i].day).format('YYYY/MM')
})].num
=
textdate[textdate.findIndex((ev) => {
return ev.time == moment(res.payload.data.dayStatisticData[i].day).format('YYYY/MM')
})].num + res.payload.data.dayStatisticData[i].duration / 3600
} }
else {
textdate.push({
time: moment(res.payload.data.dayStatisticData[i].day).format('YYYY/MM'),
num: res.payload.data.dayStatisticData[i].duration / 3600
}) })
var date = []; }
date.push([2017, 6, 1].join("/"));
date.push([2017, 6, 2].join("/")); }
date.push([2017, 6, 3].join("/")); for (let l = 0; l < textdate.length; l++) {
date.push([2017, 6, 4].join("/")); showdate.push([textdate[l].time, textdate[l].num])
date.push([2017, 6, 5].join("/")); }
date.push([2017, 6, 6].join("/"));
date.push([2017, 6, 7].join("/")); if (!startDate && !endDate) {
date.push([2017, 6, 8].join("/")); for (let i = 0; i < 12; i++) {
date.push([2017, 6, 9].join("/")); date.unshift(moment(new Date()).subtract(i, 'months').format('YYYY/MM'));
}
}
else {
let nowdate = moment(startDate).format('YYYY/MM')
date.push(nowdate)
for (let o = 0; o < 10000; o++) {
if (nowdate !== moment(endDate).format('YYYY/MM')) {
nowdate = moment(nowdate).add(1, 'months').format('YYYY/MM')
date.push(nowdate)
}
else {
break
}
}
}
let data = { let data = {
color: ['#0F7EFB', '#FE9812'], //线 color: ['#0F7EFB', '#FE9812'], //线
xAxis: [ xAxis: [
@ -325,23 +393,23 @@ const Rest = (props) => {
opacity: 0.1 opacity: 0.1
}, },
smooth: true, smooth: true,
data: [ data: showdate,
["2017/6/1", 1],
["2017/6/3", 3],
["2017/6/5", 5],
["2017/6/7", 4],
["2017/6/9", 4],
],
}, },
], ],
} }
setLeaveOption(data) setLeaveOption(data)
} }
})
}
function handleChange (date) { function handleChange (date) {
console.log('datedatedatedate', date); if (date.length > 1) {
setStartDate(moment(date[0]).format('YYYY-MM-DD')) setStartDate(moment(date[0]).format('YYYY-MM-DD'))
setEndDate(moment(date[1]).format('YYYY-MM-DD')) setEndDate(moment(date[1]).format('YYYY-MM-DD'))
}
else {
setStartDate('')
setEndDate('')
}
} }
return ( return (
<> <>
@ -364,7 +432,7 @@ const Rest = (props) => {
<img src="/assets/images/hrImg/back.png" alt="" style={{ width: '100%', height: '100%' }} /> <img src="/assets/images/hrImg/back.png" alt="" style={{ width: '100%', height: '100%' }} />
</div> </div>
<div style={{ width: 0, height: 20, borderLeft: '3px solid #0F7EFB', borderTop: '3px solid transparent', borderBottom: '3px solid transparent' }}></div> <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 }}>{pepObj.userName}的个人档案</div> <div style={{ fontFamily: "YouSheBiaoTiHei", fontSize: 24, color: '#033C9A', marginLeft: 8 }}>{pepObj?.userName}的个人档案</div>
</div> </div>
<div style={{ display: 'flex', marginRight: 20 }}> <div style={{ display: 'flex', marginRight: 20 }}>
<div style={{ padding: '6px 20px', background: '#0F7EFB', color: '#FFFFFF', fontSize: 14, cursor: "pointer" }} <div style={{ padding: '6px 20px', background: '#0F7EFB', color: '#FFFFFF', fontSize: 14, cursor: "pointer" }}
@ -616,7 +684,7 @@ const Rest = (props) => {
试用期 试用期
</div> </div>
<div style={{ color: '#4A4A4A', fontSize: 13 }}> <div style={{ color: '#4A4A4A', fontSize: 13 }}>
{pepObj.regularDate ? moment(pepObj.regularDate).diff(pepObj.hiredate, 'months', true) + '个月' : '暂无'} {pepObj.regularDate ? moment(pepObj.regularDate).diff(pepObj.hiredate, 'months', true).toFixed(1) + '个月' : '暂无'}
</div> </div>
</div> </div>
{ {
@ -635,7 +703,7 @@ const Rest = (props) => {
</div> </div>
</div> </div>
<div style={{ borderRight: '1px solid #DCDEE0', margin: '-16px 0px -20px 0px' }}></div> <div style={{ borderRight: '1px solid #DCDEE0', margin: '-16px 0px -20px 0px' }}></div>
<div style={{ marginLeft: 30, marginTop: 8, paddingRight: 30 }}> <div style={{ marginLeft: 30, marginTop: 8, paddingRight: 30, width: '38%' }}>
<div style={{ color: '#4A4A4A', fontSize: 14 }}> <div style={{ color: '#4A4A4A', fontSize: 14 }}>
/她的历史工作经历与职务 /她的历史工作经历与职务
</div> </div>
@ -646,8 +714,8 @@ const Rest = (props) => {
</div> </div>
<div style={{ borderBottom: '1px solid #DCDEE0', margin: '24px 0px 24px -20px' }}></div> <div style={{ borderBottom: '1px solid #DCDEE0', margin: '24px 0px 24px -20px' }}></div>
<div style={{ paddingLeft: 17 }}> <div style={{ paddingLeft: 17 }}>
<div style={{ color: '#4A4A4A', fontSize: 14, marginBottom: 10 }}> <div style={{ color: '#4A4A4A', fontSize: 14, marginBottom: 10, fontWeight: 'bold' }}>
动作 动作
</div> </div>
<div style={{ color: '#4A4A4A', fontSize: 14, display: 'flex', alignItems: 'center' }}> <div style={{ color: '#4A4A4A', fontSize: 14, display: 'flex', alignItems: 'center' }}>
时间筛选<DatePicker onChange={handleChange} type="dateRange" density="compact" style={{ width: 242 }} /> 时间筛选<DatePicker onChange={handleChange} type="dateRange" density="compact" style={{ width: 242 }} />
@ -685,7 +753,7 @@ const Rest = (props) => {
工作日 工作日
</div> </div>
<div style={{ fontSize: 14, color: '#005ABD', marginLeft: 5 }}> <div style={{ fontSize: 14, color: '#005ABD', marginLeft: 5 }}>
{tableStatistic.sumPayWorkday / 60 / 60 + tableStatistic.sumTakeRestWorkday / 60 / 60||0}小时 {tableStatistic.sumPayWorkday / 3600 + tableStatistic.sumTakeRestWorkday /3600 || 0}小时
</div> </div>
</div> </div>
<div style={{ display: 'flex', alignItems: 'center', width: '19.87%' }}> <div style={{ display: 'flex', alignItems: 'center', width: '19.87%' }}>
@ -693,7 +761,7 @@ const Rest = (props) => {
普通假日 普通假日
</div> </div>
<div style={{ fontSize: 14, color: '#005ABD', marginLeft: 5 }}> <div style={{ fontSize: 14, color: '#005ABD', marginLeft: 5 }}>
{tableStatistic.sumTakeRestDayoff / 60 / 60 + tableStatistic.sumTakeRestDayoff / 60 / 60||0}小时 {tableStatistic.sumTakeRestDayoff / 3600 + tableStatistic.sumPayDayoff / 3600 || 0}小时
</div> </div>
</div> </div>
<div style={{ display: 'flex', alignItems: 'center', width: '19.03%' }}> <div style={{ display: 'flex', alignItems: 'center', width: '19.03%' }}>
@ -701,7 +769,7 @@ const Rest = (props) => {
法定假日 法定假日
</div> </div>
<div style={{ fontSize: 14, color: '#005ABD', marginLeft: 5 }}> <div style={{ fontSize: 14, color: '#005ABD', marginLeft: 5 }}>
{tableStatistic.sumPayFestivals / 60 / 60 + tableStatistic.sumTakeRestFestivals / 60 / 60||0}小时 {tableStatistic.sumPayFestivals / 3600 + tableStatistic.sumTakeRestFestivals / 3600 || 0}小时
</div> </div>
</div> </div>
<div style={{ display: 'flex', alignItems: 'center', width: '19.217%' }}> <div style={{ display: 'flex', alignItems: 'center', width: '19.217%' }}>
@ -709,7 +777,7 @@ const Rest = (props) => {
累计加班时长 累计加班时长
</div> </div>
<div style={{ fontSize: 14, color: '#005ABD', marginLeft: 5 }}> <div style={{ fontSize: 14, color: '#005ABD', marginLeft: 5 }}>
{tableStatistic.sumPayWorkday / 60 / 60 + tableStatistic.sumTakeRestWorkday / 60 / 60 + tableStatistic.sumTakeRestDayoff / 60 / 60 + tableStatistic.sumTakeRestDayoff / 60 / 60 + tableStatistic.sumPayFestivals / 60 / 60 + tableStatistic.sumTakeRestFestivals / 60 / 60||0}小时 {(tableStatistic.sumPayWorkday / 3600 + tableStatistic.sumTakeRestWorkday / 3600 + tableStatistic.sumTakeRestDayoff / 3600 + tableStatistic.sumPayDayoff /3600 + tableStatistic.sumPayFestivals / 3600 + tableStatistic.sumTakeRestFestivals / 3600) || 0}小时
</div> </div>
</div> </div>
</div> </div>

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

@ -12,11 +12,19 @@ export function getNavItem (user, dispatch) {
{ {
itemKey: 'archivesCenter', itemKey: 'archivesCenter',
text: '档案中心', text: '档案中心',
icon: <iconpark-icon style={{ width: 20, height: 20 }} name="iconjianshezhong"></iconpark-icon>, icon: <iconpark-icon style={{ width: 20, height: 20 }} name="iconcbrengongdangan"></iconpark-icon>,
to: '/humanAffairs/archivesCenter/personnelFiles', to: '/humanAffairs/archivesCenter/personnelFiles',
items: [{ items: [{
itemKey: 'personnelFiles', to: '/humanAffairs/archivesCenter/personnelFiles', text: '人员档案' itemKey: 'personnelFiles', to: '/humanAffairs/archivesCenter/personnelFiles', text: '人员档案'
}] }]
},{
itemKey: 'employeeRelations',
text: '员工关系',
icon: <iconpark-icon style={{ width: 20, height: 20 }} name="iconcbyuangongguanxi"></iconpark-icon>,
to: '/humanAffairs/employeeRelations/employeeInformation',
items: [{
itemKey: 'employeeInformation', to: '/humanAffairs/employeeRelations/employeeInformation', text: '员工信息'
}]
}, },
] ]
}, },

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

@ -1,4 +1,4 @@
import { PersonnelFiles,PersonnelFilesDetail } from './containers'; import { PersonnelFiles, PersonnelFilesDetail, EmployeeInformation } from './containers';
export default [{ export default [{
type: 'inner', type: 'inner',
@ -17,9 +17,19 @@ export default [{
component: PersonnelFiles, component: PersonnelFiles,
breadcrumb: '人员档案', breadcrumb: '人员档案',
}] }]
},] }, {
path: '/employeeRelations',
key: 'employeeRelations',
breadcrumb: '员工关系',
childRoutes: [{
path: '/employeeInformation',
key: 'employeeInformation',
component: EmployeeInformation,
breadcrumb: '员工信息',
}]
}]
} }
},{ }, {
type: 'inner', type: 'inner',
route: { route: {
path: "/personnelFilesDetail", path: "/personnelFilesDetail",

9
web/client/src/sections/humanAffairs/style.less

@ -0,0 +1,9 @@
.semi-table{
.semi-table-row:first-child{
.semi-table-row-head{
background: #F2F3F5;
color: #4A4A4A;
font-size: 14px;
}
}
}

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

@ -26,7 +26,8 @@ export const ApiTable = {
getMemberOvertime: 'member/overtime',//查询单个人员加班统计数据 getMemberOvertime: 'member/overtime',//查询单个人员加班统计数据
getMemberVacate: 'member/vacate',//查询单个人员请假统计数据 getMemberVacate: 'member/vacate',//查询单个人员请假统计数据
getMemberExport: 'member/export',//导出员工信息 getMemberExport: 'member/export',//导出员工信息
getMemberNativePlace: 'member/native_place',//查询籍贯列表
getMemberWorkPlace: 'member/work_place',//查询工作地列表
}; };
export const RouteTable = { export const RouteTable = {
apiRoot: "/api/root", apiRoot: "/api/root",

Loading…
Cancel
Save