From 72bfffcbf5d9301aa0546560760daac80fd10de9 Mon Sep 17 00:00:00 2001 From: wuqun Date: Tue, 29 Nov 2022 15:46:34 +0800 Subject: [PATCH 1/4] =?UTF-8?q?(*)=E9=94=80=E5=94=AE=E4=BA=BA=E5=91=98?= =?UTF-8?q?=E5=88=86=E5=B8=83=E6=B7=BB=E5=8A=A0=E2=80=9C=E4=B8=9A=E5=8A=A1?= =?UTF-8?q?=E7=BA=BF=E2=80=9D=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/.vscode/launch.json | 2 +- .../controllers/salesDistribution/index.js | 27 +++-------- api/app/lib/models/sales_distribution.js | 9 ++++ .../schema/1.sales_distribution_modify.sql | 4 ++ .../salersDistribution/importSalersModal.js | 6 ++- .../personnelDistribution.jsx | 35 +++++++++------ .../salersDistribution/salesMemberModal.js | 45 ++++++++++--------- 7 files changed, 70 insertions(+), 58 deletions(-) create mode 100644 doc/scripts/PEP V3.0.0/schema/1.sales_distribution_modify.sql diff --git a/api/.vscode/launch.json b/api/.vscode/launch.json index cfc15dc..3a4a4a3 100644 --- a/api/.vscode/launch.json +++ b/api/.vscode/launch.json @@ -42,7 +42,7 @@ // 测试 "--clickHouseUrl http://10.8.30.161", - "--clickHousePepEmis pepca_dev", + "--clickHousePepEmis pepca8", "--clickHouseCamworkflow camworkflow", "--clickHouseHr hrm", ] diff --git a/api/app/lib/controllers/salesDistribution/index.js b/api/app/lib/controllers/salesDistribution/index.js index 1e238cd..7da2d1f 100644 --- a/api/app/lib/controllers/salesDistribution/index.js +++ b/api/app/lib/controllers/salesDistribution/index.js @@ -47,20 +47,7 @@ async function salesList(ctx) { let rslt = [] res.rows.map(d => { - //let valid = false; let info = members.find(m => m.pepUserId == d.dataValues.pepUserId); - // if (info) { - // if (placeSearch) { - // let exist1 = d.dataValues.provinces.join(',').indexOf(placeSearch) != -1 - // let exist2 = d.dataValues.cities.join(',').indexOf(placeSearch) != -1 - // if (exist1 || exist2) { - // valid = true; - // } - // } else { - // valid = true; - // } - // } - //if (valid) { let item = { name: info.userName, userCode: info.userCode, @@ -71,10 +58,7 @@ async function salesList(ctx) { ...d.dataValues } rslt.push(item); - //} }) - // let end = Number(page) * Number(limit) + Number(limit) - // let arr = rslt.slice(Number(page) * Number(limit), end) ctx.status = 200; ctx.body = { count: res.count, @@ -92,7 +76,7 @@ async function salesList(ctx) { async function add(ctx) { try { const { models } = ctx.fs.dc; - const { pepUserId, provinces, cities } = ctx.request.body + const { pepUserId, provinces, cities, businessLines } = ctx.request.body const existRes = await models.SalesDistribution.findOne({ where: { pepUserId } @@ -102,7 +86,7 @@ async function add(ctx) { throw '当前销售人员信息已存在' } - let storageData = { pepUserId, provinces, cities, del: false } + let storageData = { pepUserId, provinces, cities, businessLines, del: false } if (existRes && existRes.del) { await models.SalesDistribution.update(storageData, { where: { pepUserId } @@ -123,7 +107,7 @@ async function add(ctx) { async function edit(ctx) { try { const { models } = ctx.fs.dc; - const { pepUserId, provinces, cities } = ctx.request.body + const { pepUserId, provinces, cities, businessLines } = ctx.request.body const existRes = await models.SalesDistribution.findOne({ where: { pepUserId } @@ -133,7 +117,7 @@ async function edit(ctx) { throw '当前销售人员信息不存在' } - let storageData = { pepUserId, provinces, cities, del: false } + let storageData = { pepUserId, provinces, cities, businessLines, del: false } await models.SalesDistribution.update(storageData, { where: { @@ -321,11 +305,12 @@ async function addSalesMemberBulk(ctx) { //处理编辑的 if (editArr.length) { for (let i in editArr) { - let { pepUserId, provinces, cities, del = false } = editArr[i]; + let { pepUserId, provinces, cities, businessLines, del = false } = editArr[i]; let dataToUpdate = { provinces, cities, + businessLines, del } await models.SalesDistribution.update(dataToUpdate, { where: { pepUserId: pepUserId } }); diff --git a/api/app/lib/models/sales_distribution.js b/api/app/lib/models/sales_distribution.js index bdc30dc..1d46830 100644 --- a/api/app/lib/models/sales_distribution.js +++ b/api/app/lib/models/sales_distribution.js @@ -51,6 +51,15 @@ module.exports = dc => { primaryKey: false, field: "del", autoIncrement: false + }, + businessLines: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null, + comment: null, + primaryKey: false, + field: "business_lines", + autoIncrement: false } }, { tableName: "sales_distribution", diff --git a/doc/scripts/PEP V3.0.0/schema/1.sales_distribution_modify.sql b/doc/scripts/PEP V3.0.0/schema/1.sales_distribution_modify.sql new file mode 100644 index 0000000..82a1085 --- /dev/null +++ b/doc/scripts/PEP V3.0.0/schema/1.sales_distribution_modify.sql @@ -0,0 +1,4 @@ + + +alter table sales_distribution + add "business_lines" text; \ No newline at end of file diff --git a/web/client/src/sections/humanAffairs/containers/salersDistribution/importSalersModal.js b/web/client/src/sections/humanAffairs/containers/salersDistribution/importSalersModal.js index 3723dc5..a10cdaa 100644 --- a/web/client/src/sections/humanAffairs/containers/salersDistribution/importSalersModal.js +++ b/web/client/src/sections/humanAffairs/containers/salersDistribution/importSalersModal.js @@ -38,7 +38,7 @@ const ImportSalersModal = props => { const dldCsvMb = () => { //表头 - let head = "员工编号,姓名,销售区域(省/直辖市),销售区域(市)\n" + let head = "员工编号,姓名,销售区域(省/直辖市),销售区域(市),业务线\n" //数据 //let data = 1 + ',' + 2 + ',' + 3 + ',' + 4 + ',' + 5 let templateCsv = "data:text/csv;charset=utf-8,\ufeff" + head; @@ -191,6 +191,7 @@ const ImportSalersModal = props => { let name = judgeNull(d['姓名']); let provinces = judgeNull(d['销售区域(省/直辖市)']); let cities = judgeNull(d['销售区域(市)']); + let businessLines = judgeNull(d['业务线']); if (!number) {//人员编号不为空,唯一,字母和数字 error(`第${i + 2}行人员编号为空,请填写`) return @@ -226,9 +227,10 @@ const ImportSalersModal = props => { error(`第${i + 2}行销售区域(市)错误`) return } + //todo 业务线判断 postData.push({ pepUserId: rzExist.pepUserId, name, number, - provinces: provinces || '', cities: cities || '', + provinces: provinces || '', cities: cities || '', businessLines: businessLines || '', del: false }) } diff --git a/web/client/src/sections/humanAffairs/containers/salersDistribution/personnelDistribution.jsx b/web/client/src/sections/humanAffairs/containers/salersDistribution/personnelDistribution.jsx index 4477e3f..b472776 100644 --- a/web/client/src/sections/humanAffairs/containers/salersDistribution/personnelDistribution.jsx +++ b/web/client/src/sections/humanAffairs/containers/salersDistribution/personnelDistribution.jsx @@ -1,4 +1,4 @@ -import React, { useEffect, useRef, useState } from 'react'; +import React, { useEffect, useRef, useState, useMemo } from 'react'; import { connect } from 'react-redux'; import moment from 'moment' import { Select, Input, Button, Popconfirm, Radio, Tooltip, Table, Pagination, Skeleton } from '@douyinfe/semi-ui'; @@ -100,19 +100,19 @@ const PersonnelDistribution = (props) => { title: '序号', dataIndex: 'id', key: 'id', - width: '5%', + width: 60, render: (text, record, index) => index + 1 }, { title: starHeader('姓名'), dataIndex: 'name', key: 'name', - width: '5%' + width: 80 }, { title: starHeader('部门名称'), dataIndex: 'department', key: 'department', - width: '18%', + width: 200, render: (text, r, index) => { let arrStr = text.map(t => t.name); return getMultis(arrStr); @@ -121,7 +121,7 @@ const PersonnelDistribution = (props) => { title: '销售区域(省/直辖市)', dataIndex: 'provinces', key: 'provinces', - width: '15%', + width: 160, render: (text, record, index) => { return getMultis(text?.split('、') || []); } @@ -129,40 +129,48 @@ const PersonnelDistribution = (props) => { title: '销售区域(市)', dataIndex: 'cities', key: 'cities', - width: '15%', + width: 160, render: (text, record, index) => { - return getMultis(text?.split('、') || []); + return text ? getMultis(text?.split('、') || []) : '-'; + } + }, { + title: '业务线', + dataIndex: 'businessLines', + key: 'businessLines', + width: 120, + render: (text, record, index) => { + return text ? getMultis(text?.split('、') || []) : '-'; } }, { title: starHeader('岗位'), dataIndex: 'post', key: 'post', - width: '11%', + width: 120, render: (text, record) => {text || '-'} }, { title: starHeader('入职时间'), dataIndex: 'hireDate', key: 'hireDate', - width: '8%', + width: 120, render: (text, record) => {text || '-'} }, { title: starHeader('转正时间'), dataIndex: 'regularDate', key: 'regularDate', - width: '8%', + width: 120, render: (text, record) => {text || '-'} }, { title: starHeader('工龄'), dataIndex: 'workYears', key: 'workYears', - width: '5%', + width: 120, render: (_, r, index) => { return (r.hireDate ? {String(moment(new Date()).diff(r.hireDate, 'years', true)).substring(0, 3) + '年'} : '-') }, }, { title: '操作', dataIndex: 'action', - width: '10%', + width: 120, render: (text, record) => { return
onEdit(record)}>编辑   @@ -186,7 +194,7 @@ const PersonnelDistribution = (props) => { } }); } - + const scroll = useMemo(() => ({}), []); return (
招聘
@@ -294,6 +302,7 @@ const PersonnelDistribution = (props) => { justifyContent: "space-between", padding: "20px 20px", }}> +
共{limits}条信息 diff --git a/web/client/src/sections/humanAffairs/containers/salersDistribution/salesMemberModal.js b/web/client/src/sections/humanAffairs/containers/salersDistribution/salesMemberModal.js index d5c2b33..b00f3a5 100644 --- a/web/client/src/sections/humanAffairs/containers/salersDistribution/salesMemberModal.js +++ b/web/client/src/sections/humanAffairs/containers/salersDistribution/salesMemberModal.js @@ -3,10 +3,12 @@ import moment from 'moment'; import { connect } from "react-redux"; import { Select, Modal, Form, Notification } from "@douyinfe/semi-ui"; import cityData from '../../components/city.json'; +const businessLines = ['市政', '地灾', '水利', '智慧城市', '工地', '环保', '安防', '产品投标', '交通', '矿山', '产品线'] const SalesMemberModal = (props) => { const { dispatch, actions, user, meetingList, onConfirm, getMultis, onCancel, close, rzMembers, dataToEdit } = props; const { humanAffairs } = actions; const form = useRef();//表单 + const [lineOptions, setLineOptions] = useState([]); const [options, setOptions] = useState([]); const [cityOptions, setCityOptions] = useState([]); const [peoplePro, setPeoplePro] = useState({}); //人员信息 @@ -18,6 +20,14 @@ const SalesMemberModal = (props) => { }) setOptions(optionItems); + + let lineOptions = businessLines.map((l, index) => { + return + {l} + + }) + setLineOptions(lineOptions); + if (dataToEdit) { setPeoplePro(dataToEdit); onChange(dataToEdit.provinces?.split('、') || []);//市options @@ -59,6 +69,7 @@ const SalesMemberModal = (props) => { if (values.userCode == peoplePro.userCode) { values.provinces = values.provinces.join('、') values.cities = values.cities.join('、') + values.businessLines = values.businessLines.join('、') if (dataToEdit) { dispatch(humanAffairs.editSalesMember({ pepUserId: peoplePro.pepUserId, msg: '编辑销售人员信息', ...values })).then((res) => { if (res.success) { @@ -163,14 +174,6 @@ const SalesMemberModal = (props) => {
} - // const handleDeselect = (value) => {//删除 - // let ranges = cityData.find(td => td.name == value)?.children || [] - // if (ranges) { - // let formList = form.current.getValues().cities; - // } - - // } - const onClear = () => { form.current.setValue('cities', []) } @@ -212,36 +215,36 @@ const SalesMemberModal = (props) => { placeholder='请选择销售区域(省/直辖市)' multiple filter style={{ width: '100%' }} - // optionFilterProp='children' - // getPopupContainer={triggerNode => triggerNode.parentNode} - // filterOption={(input, option) => option.props.children - // .toLowerCase().indexOf(input.toLowerCase()) >= 0} - // value={selectedKeys || []} onClear={() => onClear()} onChange={value => onChange(value)} - //onDeselect={value => handleDeselect(value)} maxTagCount={5} > {options} triggerNode.parentNode} - // filterOption={(input, option) => option.props.children - // .toLowerCase().indexOf(input.toLowerCase()) >= 0} - // value={selectedKeys || []} - //onDeselect={value => handleDeselect(value)} maxTagCount={5} > {cityOptions} + + {lineOptions} + ) From 66b992420ac27d7bfb66c1cd9a02d947c3f1e4b4 Mon Sep 17 00:00:00 2001 From: "gao.zhiyuan" Date: Tue, 29 Nov 2022 16:44:24 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E7=BB=9F=E8=AE=A1=20=E5=8A=A0=E7=8F=AD?= =?UTF-8?q?=E8=AF=B7=E5=81=87=E6=80=BB=E6=97=B6=E9=95=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/.vscode/launch.json | 10 +++++----- api/app/lib/controllers/attendance/index.js | 8 ++++++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/api/.vscode/launch.json b/api/.vscode/launch.json index bda745f..efc0fbb 100644 --- a/api/.vscode/launch.json +++ b/api/.vscode/launch.json @@ -19,9 +19,9 @@ "-g postgres://postgres:123@10.8.30.166:5432/hr-dev", "--redisHost 10.8.30.112", "--redisPort 6379", - // "--apiEmisUrl http://10.8.30.112:14000", + "--apiEmisUrl http://10.8.30.112:14000", // 测试 - "--apiEmisUrl http://10.8.30.161:1111", + // "--apiEmisUrl http://10.8.30.161:1111", "--qnak XuDgkao6cL0HidoMAPnA5OB10Mc_Ew08mpIfRJK5", "--qnsk yewcieZLzKZuDfig0wLZ9if9jKp2P_1jd3CMJPSa", "--qnbkt dev-hr", @@ -42,9 +42,9 @@ // 测试 "--clickHouseUrl http://10.8.30.161", - "--clickHousePepEmis pg_pepca", - "--clickHouseCamworkflow pg_camworkflow", - "--clickHouseHr pg_hrm", + "--clickHousePepEmis pepca8", + "--clickHouseCamworkflow camworkflow", + "--clickHouseHr hrm", ] }, { diff --git a/api/app/lib/controllers/attendance/index.js b/api/app/lib/controllers/attendance/index.js index d5b08c7..c01ca40 100644 --- a/api/app/lib/controllers/attendance/index.js +++ b/api/app/lib/controllers/attendance/index.js @@ -29,7 +29,9 @@ async function overtimeStatistic (ctx) { }) returnD.forEach(u => { - u.overtimeStatistic = sumRes.filter(s => s.pepUserId == u.pepUserId) + let overtimeStatistic = sumRes.filter(s => s.pepUserId == u.pepUserId) + u.overtimeDuration = overtimeStatistic.reduce((sum, os) => sum + os.duration, 0) + u.overtimeStatistic = overtimeStatistic }) ctx.status = 200; ctx.body = { @@ -204,7 +206,9 @@ async function vacateStatistic (ctx) { }) returnD.forEach(u => { - u.vacateStatistic = sumRes.filter(s => s.pepUserId == u.pepUserId) + let vacateStatistic = sumRes.filter(s => s.pepUserId == u.pepUserId) + u.vacateDuration = vacateStatistic.reduce((sum, vs) => sum + vs.duration, 0) + u.vacateStatistic = vacateStatistic }) ctx.status = 200; ctx.body = { From 7f247430b19b58386e25a23020049ae519725e22 Mon Sep 17 00:00:00 2001 From: wuqun Date: Wed, 30 Nov 2022 09:21:23 +0800 Subject: [PATCH 3/4] =?UTF-8?q?(*)=E9=94=80=E5=94=AE=E4=BA=BA=E5=91=98?= =?UTF-8?q?=E5=AF=BC=E5=85=A5=20=E5=8A=A0=E4=B8=8A=E2=80=9C=E4=B8=9A?= =?UTF-8?q?=E5=8A=A1=E7=BA=BF=E2=80=9D=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../salersDistribution/constans.jsx | 4 ++++ .../salersDistribution/importSalersModal.js | 21 ++++++++++++++++++- .../personnelDistribution.jsx | 2 +- .../salersDistribution/salesMemberModal.js | 4 ++-- 4 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 web/client/src/sections/humanAffairs/containers/salersDistribution/constans.jsx diff --git a/web/client/src/sections/humanAffairs/containers/salersDistribution/constans.jsx b/web/client/src/sections/humanAffairs/containers/salersDistribution/constans.jsx new file mode 100644 index 0000000..86adcba --- /dev/null +++ b/web/client/src/sections/humanAffairs/containers/salersDistribution/constans.jsx @@ -0,0 +1,4 @@ + + +export const businessLinesConst = ['市政', '地灾', '水利', '智慧城市', '工地', + '环保', '安防', '产品投标', '交通', '矿山', '产品线'] \ No newline at end of file diff --git a/web/client/src/sections/humanAffairs/containers/salersDistribution/importSalersModal.js b/web/client/src/sections/humanAffairs/containers/salersDistribution/importSalersModal.js index a10cdaa..0a02075 100644 --- a/web/client/src/sections/humanAffairs/containers/salersDistribution/importSalersModal.js +++ b/web/client/src/sections/humanAffairs/containers/salersDistribution/importSalersModal.js @@ -4,6 +4,7 @@ import { connect } from 'react-redux'; import { Modal, Form, Button, Notification } from '@douyinfe/semi-ui'; import { IconUpload } from '@douyinfe/semi-icons'; import cityData from '../../components/city.json'; +import { businessLinesConst } from './constans' import XLSX from 'xlsx' //下载模板和上传文件读取 const ImportSalersModal = props => { @@ -142,6 +143,19 @@ const ImportSalersModal = props => { return !noMark; } + const judgeLines = (businessLines) => { + if (!businessLines) {//可以不填 + return true; + } + let noMark = 0; + businessLines?.split('、')?.map(p => { + if (businessLinesConst.indexOf(p) == -1) { + noMark++ + } + }) + return !noMark; + } + const judgeNull = (value) => { return value ? String(value).trim().replace(/\s*/g, "") : null; } @@ -227,7 +241,11 @@ const ImportSalersModal = props => { error(`第${i + 2}行销售区域(市)错误`) return } - //todo 业务线判断 + let bValid = judgeLines(businessLines); + if (!bValid) { + error(`第${i + 2}行业务线错误`) + return + } postData.push({ pepUserId: rzExist.pepUserId, name, number, provinces: provinces || '', cities: cities || '', businessLines: businessLines || '', @@ -254,6 +272,7 @@ const ImportSalersModal = props => {
姓名:必填,若与员工编号对应的项企用户姓名不同,将以项企数据为准;
销售区域(省/直辖市):必填,省或直辖市顿号隔开,如“北京市、江西省、江苏省”;
销售区域(市):非必填,归属所填省的地级市顿号隔开,如“南昌市、镇江市”。
+
业务线:非必填,顿号隔开,如“智慧城市、工地”。
diff --git a/web/client/src/sections/humanAffairs/containers/salersDistribution/personnelDistribution.jsx b/web/client/src/sections/humanAffairs/containers/salersDistribution/personnelDistribution.jsx index b472776..a40df0c 100644 --- a/web/client/src/sections/humanAffairs/containers/salersDistribution/personnelDistribution.jsx +++ b/web/client/src/sections/humanAffairs/containers/salersDistribution/personnelDistribution.jsx @@ -137,7 +137,7 @@ const PersonnelDistribution = (props) => { title: '业务线', dataIndex: 'businessLines', key: 'businessLines', - width: 120, + width: 140, render: (text, record, index) => { return text ? getMultis(text?.split('、') || []) : '-'; } diff --git a/web/client/src/sections/humanAffairs/containers/salersDistribution/salesMemberModal.js b/web/client/src/sections/humanAffairs/containers/salersDistribution/salesMemberModal.js index b00f3a5..09ca6a1 100644 --- a/web/client/src/sections/humanAffairs/containers/salersDistribution/salesMemberModal.js +++ b/web/client/src/sections/humanAffairs/containers/salersDistribution/salesMemberModal.js @@ -3,7 +3,7 @@ import moment from 'moment'; import { connect } from "react-redux"; import { Select, Modal, Form, Notification } from "@douyinfe/semi-ui"; import cityData from '../../components/city.json'; -const businessLines = ['市政', '地灾', '水利', '智慧城市', '工地', '环保', '安防', '产品投标', '交通', '矿山', '产品线'] +import { businessLinesConst } from './constans' const SalesMemberModal = (props) => { const { dispatch, actions, user, meetingList, onConfirm, getMultis, onCancel, close, rzMembers, dataToEdit } = props; const { humanAffairs } = actions; @@ -21,7 +21,7 @@ const SalesMemberModal = (props) => { }) setOptions(optionItems); - let lineOptions = businessLines.map((l, index) => { + let lineOptions = businessLinesConst.map((l, index) => { return {l} From 6b9e40718bf1bc427f9a4185fd1d72a991ebfcad Mon Sep 17 00:00:00 2001 From: "gao.zhiyuan" Date: Wed, 30 Nov 2022 14:23:32 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E5=8F=AF=E4=BD=BF=E7=94=A8=E9=A1=B9?= =?UTF-8?q?=E4=BC=81=20token=20=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/app/lib/controllers/auth/index.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/api/app/lib/controllers/auth/index.js b/api/app/lib/controllers/auth/index.js index 7b6c00f..022e665 100644 --- a/api/app/lib/controllers/auth/index.js +++ b/api/app/lib/controllers/auth/index.js @@ -10,9 +10,18 @@ async function login (ctx, next) { const models = ctx.fs.dc.models; const params = ctx.request.body; - const emisLoginRes = await ctx.app.fs.emisRequest.post('login', { - data: params - }) + let emisLoginRes = null + if (params.username && params.password) { + emisLoginRes = await ctx.app.fs.emisRequest.post('login', { + data: { ...params, code: 'HR' } + }) + } else if (params.token) { + emisLoginRes = await ctx.app.fs.emisRequest.get('user-info', { + query: { + token: params.token, code: 'HR' + } + }) + } if (!emisLoginRes) { throw "无此用户,请使用正确的登录信息"