diff --git a/web/client/assets/images/hrImg/!.png b/web/client/assets/images/hrImg/!.png new file mode 100644 index 0000000..f9c334f Binary files /dev/null and b/web/client/assets/images/hrImg/!.png differ diff --git a/web/client/assets/images/hrImg/V.png b/web/client/assets/images/hrImg/V.png new file mode 100644 index 0000000..fd5a097 Binary files /dev/null and b/web/client/assets/images/hrImg/V.png differ diff --git a/web/client/assets/images/hrImg/setUp.png b/web/client/assets/images/hrImg/setUp.png new file mode 100644 index 0000000..ea73217 Binary files /dev/null and b/web/client/assets/images/hrImg/setUp.png differ diff --git a/web/client/index.ejs b/web/client/index.ejs index 54e5c56..49ff0b5 100644 --- a/web/client/index.ejs +++ b/web/client/index.ejs @@ -9,7 +9,7 @@ - + diff --git a/web/client/index.html b/web/client/index.html index b4cac35..cba0f37 100644 --- a/web/client/index.html +++ b/web/client/index.html @@ -2,23 +2,23 @@ - - + + - + - - + + -
+
- - + + - - + - + - + \ No newline at end of file diff --git a/web/client/src/components/setup.jsx b/web/client/src/components/setup.jsx index c4cd070..a02fd3e 100644 --- a/web/client/src/components/setup.jsx +++ b/web/client/src/components/setup.jsx @@ -9,7 +9,8 @@ function Setup(props) { const { close, tableType, - tableList + tableList, + length } = props; console.log(tableType, @@ -25,7 +26,7 @@ function Setup(props) { ischeck(); }, []); function ischeck(value) { - if (check.length >= 8) { + if (check.length >= length) { if (check.includes(value)) { return false; } else { @@ -49,12 +50,12 @@ function Setup(props) { textAlign: "center", marginLeft: 6, background: - check.length == 8 + check.length == length ? "rgba(40, 123, 255, 1)" : "rgba(176, 176, 176, 1)", }} > - {check.length}/8 + {check.length}/length } diff --git a/web/client/src/sections/humanAffairs/containers/employeeInformation.jsx b/web/client/src/sections/humanAffairs/containers/employeeInformation.jsx new file mode 100644 index 0000000..768ad91 --- /dev/null +++ b/web/client/src/sections/humanAffairs/containers/employeeInformation.jsx @@ -0,0 +1,344 @@ +import React, { useEffect, useState, useRef } from 'react'; +import { connect } from 'react-redux'; +import { Select, SkeletonScreen, Button, Pagination, Skeleton, Form } from '@douyinfe/semi-ui'; +import { IconSearch } from '@douyinfe/semi-icons'; +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([]); + const [personnelModal, setPersonnelModal] = useState(false);//档案弹框 + const [exportModalVs, setExportModalVs] = useState(false); + const [keyword, setKeyword] = useState('');//搜索内容 + const [keywordTarget, setKeywordTarget] = useState('');//搜索类型 + const [downloadUrl, setDownloadUrl] = useState('') + let [typeChoose, setTypeChoose] = 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: "pushWay" }, + { name: "推送机制", value: "noticeWay" }, + { name: "监听设备数量", value: "monitorCount" }, + { name: "累计推送次数", value: "logCount" }, + ] + } + ]; + useEffect(() => { + getMemberSearchList() + + + // attribute(); + // localStorage.getItem(EMPLOYEEINFORMATION) == null + // ? localStorage.setItem( + // EMPLOYEEINFORMATION, + // JSON.stringify(['pushWay','noticeWay','logCount','monitorCount']) + // ) + // : ""; + }, [typeChoose]) + + function getMemberSearchList () {//搜索项企用户 + dispatch(humanAffairs.getMemberList({ keywordTarget, keyword, state: typeChoose })).then((res) => {//搜索项企用户 + if (res.success) { + setArchivesList(res.payload?.data?.rows) + } + }) + } + + function typeOnChange (e) {//角色选择 + setTypeChoose(e.target.value); + } + function seachValueChange (value) { + setKeyword(value) + } + //获取表格属性设置 + function attribute () { + const arr = localStorage.getItem(EMPLOYEEINFORMATION) + ? JSON.parse(localStorage.getItem(EMPLOYEEINFORMATION)) + : []; + + const column = [ + { + title: "关联项目", + dataIndex: "noticeWay", + key: "noticeWay", + render: (_, r, index) => { + return r.noticeWay; + }, + }, + { + 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); + } + return ( + <> +
+
+
人事管理
+
/
+
档案中心
+
/
+
人员档案
+
+
+
+
+
+
员工信息
+
EMPLOYEE INFORMATION
+
+
+
+
{ + console.log('values', values); + }} + getFormApi={(formApi) => (form.current = formApi)} + > +
+
+ + 职位 + 部门 + 编号 + 姓名 + + } + pure + showClear + placeholder='请输入或选择关键词' + value={keyword} + style={{ width: 346, marginLeft: 12, marginRight: 12 }} + onChange={seachValueChange}> + + +
+
+
+ + {/* {.map((item) => { + return ( + + {item.name} + + ); + })} */} + + + {/* {.map((item) => { + return ( + + {item.name} + + ); + })} */} + + + {/* {.map((item) => { + return ( + + {item.name} + + ); + })} */} + +
+
+ setSetup(true)} + /> + setSetup(true)} + /> + +
+
+
+
+
+ + 表格中带有认证标识" + + "信息的为系统基础数据,来源于项企PEP、钉钉等系统,其他数据均为导入或自定义数据 +
+ {/*
+ + s)} + dataSource={tableData} + bordered={false} + empty="暂无数据" + pagination={false} + onRow={handleRow} + rowSelection={rowSelection} + /> + +
+
+
+
+ + 共{limits}条信息 + + { + setQuery({ limit: pageSize, page: currentPage - 1 }); + page.current = currentPage - 1 + }} + /> +
+
+ */} + + + + {setup ? ( + { + 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); diff --git a/web/client/src/sections/humanAffairs/containers/index.js b/web/client/src/sections/humanAffairs/containers/index.js index 59a3f85..eff5a17 100644 --- a/web/client/src/sections/humanAffairs/containers/index.js +++ b/web/client/src/sections/humanAffairs/containers/index.js @@ -2,5 +2,6 @@ import PersonnelFiles from './personnelFiles'; import PersonnelFilesDetail from './personnelFilesDetail'; +import EmployeeInformation from './employeeInformation'; -export { PersonnelFiles, PersonnelFilesDetail }; \ No newline at end of file +export { PersonnelFiles, PersonnelFilesDetail, EmployeeInformation }; \ No newline at end of file diff --git a/web/client/src/sections/humanAffairs/containers/personnelFiles.jsx b/web/client/src/sections/humanAffairs/containers/personnelFiles.jsx index d87ea29..4a2e67a 100644 --- a/web/client/src/sections/humanAffairs/containers/personnelFiles.jsx +++ b/web/client/src/sections/humanAffairs/containers/personnelFiles.jsx @@ -161,7 +161,7 @@ const Rest = (props) => {
- {item.pepUserId} + {item.userCode}
{ item.departmrnt.map((ite, idx) => { diff --git a/web/client/src/sections/humanAffairs/containers/personnelFilesDetail.jsx b/web/client/src/sections/humanAffairs/containers/personnelFilesDetail.jsx index 4bd6cee..2bc385d 100644 --- a/web/client/src/sections/humanAffairs/containers/personnelFilesDetail.jsx +++ b/web/client/src/sections/humanAffairs/containers/personnelFilesDetail.jsx @@ -151,99 +151,134 @@ const Rest = (props) => { } }) } - function getWorkOption () {//请假折线图 + function getWorkOption () {//加班折线图 + let date = []; + let showdate = [] + let showdate1 = [] dispatch(humanAffairs.getMemberOvertime({ pepUserId: history?.location?.search.slice(1), startDate: startDate, endDate: endDate })).then((res) => {//搜索项企用户 if (res.success) { setTableData(res.payload?.data?.data) setTableStatistic(res.payload?.data) - } - }) - var date = []; - date.push([2017, 6, 1].join("/")); - date.push([2017, 6, 2].join("/")); - date.push([2017, 6, 3].join("/")); - date.push([2017, 6, 4].join("/")); - date.push([2017, 6, 5].join("/")); - date.push([2017, 6, 6].join("/")); - date.push([2017, 6, 7].join("/")); - date.push([2017, 6, 8].join("/")); - date.push([2017, 6, 9].join("/")); - let data = { - legend: { - data: ["调休", "折算"], - left: 'right', - icon: 'roundRect', - itemHeight: 3, // 粗细 - }, - color: ['#0F7EFB', '#FE9812'], //两条折线的颜色 - xAxis: [ - { - boundaryGap: false, - data: date, - }, - ], - yAxis: [ - { - type: "value", - name: '小时' - }, - ], - dataZoom: [ - { - id: "dataZoomX", - type: "slider", - start: 0, - end: 100, - handleIcon: - "M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4v1.3h1.3v-1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7V23h6.6V24.4z M13.3,19.6H6.7v-1.4h6.6V19.6z", - handleSize: "80%", - }, - ], - tooltip: { - trigger: 'axis', - axisPointer: { - type: 'cross', - label: { - backgroundColor: '#6a7985' + 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, + compensate: res.payload.data.dayStatisticData[i].compensate + }) + } + + } + console.log('textdate',textdate); + for (let l = 0; l < textdate.length; l++) { + if (textdate[l].compensate == '调休') { + showdate.push([textdate[l].time, textdate[l].num]) + } + else { + showdate1.push([textdate[l].time, textdate[l].num]) } + } - }, - series: [ - { - name: "调休", - type: "line", - areaStyle: { - color: 'rgba(14,156,255,0.5)', - opacity: 0.1 + + 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 = { + legend: { + data: ["调休", "折算"], + left: 'right', + icon: 'roundRect', + itemHeight: 3, // 粗细 }, - smooth: true, - data: [ - ["2017/6/1", 1], - ["2017/6/3", 3], - ["2017/6/5", 5], - ["2017/6/7", 4], - ["2017/6/9", 4], + color: ['#0F7EFB', '#FE9812'], //两条折线的颜色 + xAxis: [ + { + boundaryGap: false, + data: date, + }, + ], + yAxis: [ + { + type: "value", + name: '小时' + }, ], - }, - { - name: "折算", - type: "line", - areaStyle: { - color: 'rgba(254,152,18,0.2)', + dataZoom: [ + { + id: "dataZoomX", + type: "slider", + start: 0, + end: 100, + handleIcon: + "M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4v1.3h1.3v-1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7V23h6.6V24.4z M13.3,19.6H6.7v-1.4h6.6V19.6z", + handleSize: "80%", + }, + ], + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'cross', + label: { + backgroundColor: '#6a7985' + } + } }, - smooth: true, - data: [ - ["2017/6/2", 3], - ["2017/6/4", 1], - ["2017/6/6", 6], - ["2017/6/8", 3], + series: [ + { + name: "调休", + type: "line", + areaStyle: { + color: 'rgba(14,156,255,0.5)', + opacity: 0.1 + }, + smooth: true, + data: showdate, + }, + { + name: "折算", + type: "line", + areaStyle: { + color: 'rgba(254,152,18,0.2)', + }, + smooth: true, + data: showdate1, + }, ], - }, - ], - } - setOption(data) + } + setOption(data) + } + }) } function getLeaveOption () {//请假折线图 + let date = []; + let showdate = [] dispatch(humanAffairs.getMemberVacate({ pepUserId: history?.location?.search.slice(1), startDate: startDate, endDate: endDate })).then((res) => {//搜索项企用户 if (res.success) { setLeaveData(res.payload?.data?.data) @@ -270,78 +305,109 @@ const Rest = (props) => { setLeaveStatistic({ compassionate, sick, year, other, all }) - } - }) - var date = []; - date.push([2017, 6, 1].join("/")); - date.push([2017, 6, 2].join("/")); - date.push([2017, 6, 3].join("/")); - date.push([2017, 6, 4].join("/")); - date.push([2017, 6, 5].join("/")); - date.push([2017, 6, 6].join("/")); - date.push([2017, 6, 7].join("/")); - date.push([2017, 6, 8].join("/")); - date.push([2017, 6, 9].join("/")); - let data = { - color: ['#0F7EFB', '#FE9812'], //两条折线的颜色 - xAxis: [ - { - boundaryGap: false, - data: date, - }, - ], - yAxis: [ - { - type: "value", - name: '小时' - }, - ], - dataZoom: [ - { - id: "dataZoomX", - type: "slider", - start: 0, - end: 100, - handleIcon: - "M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4v1.3h1.3v-1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7V23h6.6V24.4z M13.3,19.6H6.7v-1.4h6.6V19.6z", - handleSize: "80%", - }, - ], - tooltip: { - trigger: 'axis', - axisPointer: { - type: 'cross', - label: { - backgroundColor: '#6a7985' + 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 + }) } + } - }, - series: [ - { - name: "调休", - type: "line", - areaStyle: { - color: 'rgba(14,156,255,0.5)', - opacity: 0.1 + for (let l = 0; l < textdate.length; l++) { + showdate.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 = { + color: ['#0F7EFB', '#FE9812'], //两条折线的颜色 + xAxis: [ + { + boundaryGap: false, + data: date, + }, + ], + yAxis: [ + { + type: "value", + name: '小时' + }, + ], + dataZoom: [ + { + id: "dataZoomX", + type: "slider", + start: 0, + end: 100, + handleIcon: + "M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4v1.3h1.3v-1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7V23h6.6V24.4z M13.3,19.6H6.7v-1.4h6.6V19.6z", + handleSize: "80%", + }, + ], + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'cross', + label: { + backgroundColor: '#6a7985' + } + } }, - smooth: true, - data: [ - ["2017/6/1", 1], - ["2017/6/3", 3], - ["2017/6/5", 5], - ["2017/6/7", 4], - ["2017/6/9", 4], + series: [ + { + name: "调休", + type: "line", + areaStyle: { + color: 'rgba(14,156,255,0.5)', + opacity: 0.1 + }, + smooth: true, + data: showdate, + }, ], - }, - ], - } - setLeaveOption(data) + } + setLeaveOption(data) + } + }) } function handleChange (date) { - console.log('datedatedatedate', date); - setStartDate(moment(date[0]).format('YYYY-MM-DD')) - setEndDate(moment(date[1]).format('YYYY-MM-DD')) - + if (date.length > 1) { + setStartDate(moment(date[0]).format('YYYY-MM-DD')) + setEndDate(moment(date[1]).format('YYYY-MM-DD')) + } + else { + setStartDate('') + setEndDate('') + } } return ( <> @@ -646,8 +712,8 @@ const Rest = (props) => {
-
- 基础动作 +
+ 基本动作
时间筛选: @@ -685,7 +751,7 @@ const Rest = (props) => { 工作日:
- {tableStatistic.sumPayWorkday / 60 / 60 + tableStatistic.sumTakeRestWorkday / 60 / 60||0}小时 + {tableStatistic.sumPayWorkday / 60 / 60 + tableStatistic.sumTakeRestWorkday / 60 / 60 || 0}小时
@@ -693,7 +759,7 @@ const Rest = (props) => { 普通假日:
- {tableStatistic.sumTakeRestDayoff / 60 / 60 + tableStatistic.sumTakeRestDayoff / 60 / 60||0}小时 + {tableStatistic.sumTakeRestDayoff / 60 / 60 + tableStatistic.sumTakeRestDayoff / 60 / 60 || 0}小时
@@ -701,7 +767,7 @@ const Rest = (props) => { 法定假日:
- {tableStatistic.sumPayFestivals / 60 / 60 + tableStatistic.sumTakeRestFestivals / 60 / 60||0}小时 + {tableStatistic.sumPayFestivals / 60 / 60 + tableStatistic.sumTakeRestFestivals / 60 / 60 || 0}小时
@@ -709,7 +775,7 @@ const Rest = (props) => { 累计加班时长:
- {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 / 60 / 60 + tableStatistic.sumTakeRestWorkday / 60 / 60 + tableStatistic.sumTakeRestDayoff / 60 / 60 + tableStatistic.sumTakeRestDayoff / 60 / 60 + tableStatistic.sumPayFestivals / 60 / 60 + tableStatistic.sumTakeRestFestivals / 60 / 60 || 0}小时
diff --git a/web/client/src/sections/humanAffairs/nav-item.jsx b/web/client/src/sections/humanAffairs/nav-item.jsx index e2f2869..a80967a 100644 --- a/web/client/src/sections/humanAffairs/nav-item.jsx +++ b/web/client/src/sections/humanAffairs/nav-item.jsx @@ -12,11 +12,19 @@ export function getNavItem (user, dispatch) { { itemKey: 'archivesCenter', text: '档案中心', - icon: , + icon: , to: '/humanAffairs/archivesCenter/personnelFiles', items: [{ itemKey: 'personnelFiles', to: '/humanAffairs/archivesCenter/personnelFiles', text: '人员档案' }] + },{ + itemKey: 'employeeRelations', + text: '员工关系', + icon: , + to: '/humanAffairs/employeeRelations/employeeInformation', + items: [{ + itemKey: 'employeeInformation', to: '/humanAffairs/employeeRelations/employeeInformation', text: '员工信息' + }] }, ] }, diff --git a/web/client/src/sections/humanAffairs/routes.js b/web/client/src/sections/humanAffairs/routes.js index 9fb9882..3e000e7 100644 --- a/web/client/src/sections/humanAffairs/routes.js +++ b/web/client/src/sections/humanAffairs/routes.js @@ -1,4 +1,4 @@ -import { PersonnelFiles,PersonnelFilesDetail } from './containers'; +import { PersonnelFiles, PersonnelFilesDetail, EmployeeInformation } from './containers'; export default [{ type: 'inner', @@ -17,9 +17,19 @@ export default [{ component: PersonnelFiles, breadcrumb: '人员档案', }] - },] + }, { + path: '/employeeRelations', + key: 'employeeRelations', + breadcrumb: '员工关系', + childRoutes: [{ + path: '/employeeInformation', + key: 'employeeInformation', + component: EmployeeInformation, + breadcrumb: '员工信息', + }] + }] } -},{ +}, { type: 'inner', route: { path: "/personnelFilesDetail",