diff --git a/.vscode/launch.json b/.vscode/launch.json index 4951e72..dd08d4d 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -63,8 +63,9 @@ // "--clickHouseCamworkflow camworkflow", // "--clickHouseHr hr_dev", // 测试 - "--clickHouseUrl http://10.8.16.221", - "--clickHousePepEmis pg_pepca", + "--clickHouseUrl http://10.8.30.161", + "--clickHousePepEmis pepca8", + "--clickHouseHr hrm", ] }, { diff --git a/api/app/lib/controllers/report/index.js b/api/app/lib/controllers/report/index.js index 930fd12..3b98a20 100644 --- a/api/app/lib/controllers/report/index.js +++ b/api/app/lib/controllers/report/index.js @@ -1,5 +1,6 @@ 'use strict'; - +const fs = require('fs'); +const moment = require('moment'); // 查询储备项目统计表 async function getReserveItemReport(ctx, next) { const { type } = ctx.params; @@ -27,6 +28,136 @@ async function getReserveItemReport(ctx, next) { } } +async function getSalersReport(ctx) { + try { + const { clickHouse } = ctx.app.fs + const { memberList, packageUserData } = ctx.app.fs.utils + const { + keywordTarget, keyword, limit, page, state, + hiredateStart, hiredateEnd, marital, native, workPlace, + orderBy, orderDirection, placeSearch, toExport + } = ctx.query + + const userRes = await memberList({ + keywordTarget, keyword, limit: '', page: '', state, + hiredateStart, hiredateEnd, marital, native, workPlace, + orderBy, orderDirection, + nowAttendanceTime: true + }) + + let { packageUser: members } = await packageUserData(userRes, { + state: true, + }) + let mIds = members.map(m => m.pepUserId); + + let innerSelectQuery = `where del=false and pep_user_id in [${mIds}]` + + `${placeSearch ? ` + and (sales.provinces LIKE '%${placeSearch}%' or sales.cities LIKE '%${placeSearch}%') + `: ''}` + + const salersRes = await clickHouse.hr.query(` + SELECT * from sales_distribution as sales + ${innerSelectQuery} + order by id desc + ${!toExport && limit ? `LIMIT ${limit}` : ''} + ${!toExport && limit && page ? 'OFFSET ' + parseInt(limit) * parseInt(page) : ''} + `).toPromise() + + const countRes = await clickHouse.hr.query(` + SELECT + count(sales.pep_user_id) AS count from sales_distribution as sales + ${innerSelectQuery} + `).toPromise() + let rslt = [] + salersRes.map(d => { + let info = members.find(m => m.pepUserId == d.pep_user_id); + let item = { + name: info.userName, + userCode: info.userCode, + post: info.userPost, + department: info.departmrnt, + hireDate: info.hiredate,//入职时间 + regularDate: info.regularDate,//转正时间 + businessLines: d.business_lines,//业务线 + ...d + } + rslt.push(item); + }) + if (toExport) { + await exportSalesDetail(ctx, rslt);//导出 + } else { + ctx.status = 200; + ctx.body = { + count: countRes.length ? countRes[0].count : 0, + rows: rslt + }; + } + } catch (error) { + ctx.fs.logger.error(`path:${ctx.path},error:${error}`) + ctx.status = 400; + ctx.body = { name: 'FindAllError', message: '获取销售人员分布明细表数据失败' } + } +} + +async function exportSalesDetail(ctx, dataList) { + try { + let header = [{ + title: "姓名", + key: 'name' + }, { + title: "部门名称", + key: 'department' + }, { + title: "销售区域(省/直辖市)", + key: 'provinces' + }, { + title: "销售区域(市)", + key: 'cities' + }, { + title: "业务线", + key: 'businessLines' + }, { + title: "岗位", + key: 'post' + }, { + title: "入职时间", + key: 'hireDate' + }, { + title: "转正时间", + key: 'regularDate' + }, { + title: "工龄", + key: 'workYears' + }]; + const { utils: { simpleExcelDown } } = ctx.app.fs; + let exportData = [] + for (let item of dataList) { + item.department = item.department.map(t => t.name).join('、') || '-'; + item.cities = item.cities || '-'; + item.businessLines = item.businessLines || '-'; + item.post = item.post || '-'; + item.regularDate = item.regularDate || '-'; + item.workYears = item.hireDate ? String(moment(new Date()).diff(item.hireDate, 'years', true)).substring(0, 3) + '年' : '-' + item.hireDate = item.hireDate || '-'; + exportData.push(item) + } + const fileName = `销售人员分布明细表_${moment().format('YYYYMMDDHHmmss')}` + '.xlsx' + const filePath = await simpleExcelDown({ data: exportData, 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 + } + } +} + module.exports = { - getReserveItemReport + getReserveItemReport, + getSalersReport } \ No newline at end of file diff --git a/api/app/lib/routes/report/index.js b/api/app/lib/routes/report/index.js index 0d4e04f..7873b82 100644 --- a/api/app/lib/routes/report/index.js +++ b/api/app/lib/routes/report/index.js @@ -5,4 +5,7 @@ const report = require('../../controllers/report'); module.exports = function (app, router, opts) { app.fs.api.logAttr['GET/reserveItem/report/:type'] = { content: '查询储备项目统计表', visible: false }; router.get('/reserveItem/report/:type', report.getReserveItemReport); + + app.fs.api.logAttr['GET/sales/member/list'] = { content: '查询销售人员分布明细表', visible: false }; + router.get('/sales/member/list', report.getSalersReport); }; \ No newline at end of file diff --git a/api/app/lib/utils/member.js b/api/app/lib/utils/member.js new file mode 100644 index 0000000..6088ef8 --- /dev/null +++ b/api/app/lib/utils/member.js @@ -0,0 +1,415 @@ +'use strict'; +const moment = require('moment') +const request = require('superagent'); + +module.exports = function (app, opts) { + + async function memberList({ + keywordTarget, keyword, limit, page, state, + 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 { clickHouse } = app.fs + const { database: pepEmis } = clickHouse.pepEmis.opts.config + + const curDay = moment().format('YYYY-MM-DD') + const nowTime = moment() + let whereOption = [] + let whereFromSelectOption = [] + let returnEmpty = false + if (state == 'inOffice') { + // 在岗 + //const holidayJudge = await judgeHoliday(curDay) + // if (holidayJudge) { + // if ( + // holidayJudge.workday + // && nowTime.isAfter(moment(curDay + ' 08:30')) + // && nowTime.isBefore(moment(curDay + ' 17:30')) + // ) { + // // 在工作日的工作时间范围 无请假记录 + // whereFromSelectOption.push(`vacateStartTime = '1970-01-01 00:00:00.000000'`) + // } else { + // returnEmpty = true + // } + // } else { + // returnEmpty = true + // } + } + if (state == 'dayoff') { + // 放假 + // const holidayJudge = await judgeHoliday(curDay) + // if (holidayJudge) { + // if ( + // holidayJudge.dayoff || holidayJudge.festivals + // ) { + // // 在休息日范围内且无加班申请 + // whereFromSelectOption.push(`overtimeStartTime = '1970-01-01 00:00:00.000000'`) + // } else { + // returnEmpty = true + // } + // } else { + // returnEmpty = true + // } + } + if (returnEmpty) { + return { + count: 0, + rows: [] + } + } + + 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).startOf('day').format('YYYY-MM-DD HH:mm:ss')}'`) + // } + // if (overtimeCountStatisticendDate) { + // overtimeCountStatisticWhere.push(`overtime.end_time <= '${moment(overtimeCountStatisticendDate).endOf('day').format('YYYY-MM-DD HH:mm:ss')}'`) + // } + + 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).startOf('day').format('YYYY-MM-DD HH:mm:ss')}'`) + // } + // if (vacateCountStatisticendDate) { + // vacateCountStatisticWhere.push(`vacate.end_time <= '${moment(vacateCountStatisticendDate).endOf('day').format('YYYY-MM-DD HH:mm:ss')}'`) + // } + // CRAZY + const innerSelectQuery = ` + FROM member + INNER JOIN ${pepEmis}.user AS user + ON member.pep_user_id = user.id + ${keywordTarget == 'number' && keyword ? ` + AND user.people_code LIKE '%${keyword}%' + `: ''} + ${keywordTarget == 'name' && keyword ? ` + AND user.name LIKE '%${keyword}%' + `: ''} + + ${nowAttendanceTime ? ` + ${state == 'vacate' ? 'INNER' : 'LEFT'} JOIN ( + SELECT + pep_user_id, + any(start_time) AS vacateStartTime, + any(end_time) AS vacateEndTime + FROM vacate + WHERE + start_time <= '${nowTime.format('YYYY-MM-DD HH:mm:ss')}' + AND end_time > '${nowTime.format('YYYY-MM-DD HH:mm:ss')}' + GROUP BY pep_user_id + ) AS hrVacate + ON hrVacate.pep_user_id = member.pep_user_id + `: ''} + ${nowAttendanceTime ? ` + LEFT JOIN ( + SELECT + pep_user_id, + any(start_time) AS overtimeStartTime, + any(end_time) AS overtimeEndTime + FROM overtime + WHERE + start_time <= '${nowTime.format('YYYY-MM-DD HH:mm:ss')}' + AND end_time > '${nowTime.format('YYYY-MM-DD HH:mm:ss')}' + GROUP BY pep_user_id + ) AS hrOvertime + 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 + member.del = '0' + ${keywordTarget == 'post' && keyword ? ` + AND user.post IN ( + SELECT basicDataPost.id + FROM ${pepEmis}.basicdata_post AS basicDataPost + where basicDataPost.name LIKE '%${keyword}%' + ) + ` : ''} + ${keywordTarget == 'dep' && keyword ? ` + AND user.id IN ( + SELECT department_user.user + FROM ${pepEmis}.department_user AS department_user + INNER JOIN ${pepEmis}.department AS department + ON department.id = department_user.department + AND department.name LIKE '%${keyword}%' + ) + ` : ''} + ${state == 'dimission' ? `AND member.dimission_date IS NOT null` : ''} + ${state == 'onJob' ? `AND member.dimission_date IS null` : ''} + ${whereFromSelectOption.length && nowAttendanceTime ? `AND ${whereFromSelectOption.join('AND')}` : ''} + ${hiredateStart ? ` + AND member.hiredate >= '${moment(hiredateStart).format('YYYY-MM-DD')}' + `: ''} + ${hiredateEnd ? ` + AND member.hiredate <= '${moment(hiredateEnd).format('YYYY-MM-DD')}' + ` : ''} + ${marital ? ` + AND member.marital = '${marital}' + `: ''} + ${native ? ` + AND member.native_place = '${native}' + `: ''} + ${workPlace ? ` + AND member.work_place = '${workPlace}' + `: ''} + ` + + const userRes = await clickHouse.hr.query(` + SELECT + hrMember."member.pep_user_id" AS pepUserId, + hrMember.*, + user.name AS userName, + user.people_code AS userCode, + basicDataPost.name AS userPost, + role.name AS roleName, + role.id AS roleId, + department.name AS depName, + department.id AS depId, + user.job AS userJob, + user.active_status AS userActiveStatus, + user.organization AS userOrganization + FROM ( + SELECT + ${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.vacateEndTime AS vacateEndTime, + hrOvertime.overtimeStartTime AS overtimeStartTime, + hrOvertime.overtimeEndTime AS overtimeEndTime, + `: ''} + + member.* + ${innerSelectQuery} + ${limit ? `LIMIT ${limit}` : ''} + ${limit && page ? 'OFFSET ' + parseInt(limit) * parseInt(page) : ''} + ) AS hrMember + + LEFT JOIN ${pepEmis}.user AS user + ON pepUserId = user.id + LEFT JOIN ${pepEmis}.user_role AS user_role + ON ${pepEmis}.user_role.user = user.id + LEFT JOIN ${pepEmis}.role AS role + ON ${pepEmis}.role.id = user_role.role + LEFT JOIN ${pepEmis}.basicdata_post AS basicDataPost + ON ${pepEmis}.basicdata_post.id = user.post + LEFT JOIN ${pepEmis}.department_user AS department_user + ON department_user.user = user.id + LEFT JOIN ${pepEmis}.department AS department + ON department.id = department_user.department + ${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.overtimeDayStatisticDuration' + : orderBy == 'overtimeCount' ? + 'hrMember.overtimeCount' + : orderBy == 'vacateSum' ? + 'hrMember.vacateDayStatisticDuration' + : orderBy == 'vacateCount' ? + 'hrMember.vacateCount' + : 'user.people_code'} + ${orderDirection || 'ASC'} + `).toPromise() + + const countRes = await clickHouse.hr.query(` + SELECT + count(member.pep_user_id) AS count + ${innerSelectQuery} + `).toPromise() + + return { + count: countRes[0].count, + rows: userRes + } + } + + 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 = [-1] + 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' || u[k] == '1970-01-01 08:00:00.000000' ? null : u[k] + } + pepUserIds.push(u.pepUserId) + console.log("查询到的用户信息:", obj); + 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 { + memberList, + packageUserData + } +} \ No newline at end of file diff --git a/api/config.js b/api/config.js index c20c7b2..d4891d1 100644 --- a/api/config.js +++ b/api/config.js @@ -27,6 +27,7 @@ args.option('qndmn', 'qiniuDomain'); args.option('clickHouseUrl', 'clickHouse Url'); args.option('clickHousePort', 'clickHouse Port'); args.option('clickHousePepEmis', 'clickHouse 项企数据库名称'); +args.option('clickHouseHr', 'clickHouse 人资数据库名称'); const flags = args.parse(process.argv); @@ -52,6 +53,7 @@ const CLICKHOUST_PORT = process.env.CLICKHOUST_PORT || flags.clickHousePort const CLICKHOUST_USER = process.env.CLICKHOUST_USER || flags.clickHouseUser const CLICKHOUST_PASSWORD = process.env.CLICKHOUST_PASSWORD || flags.clickHousePassword const CLICKHOUST_PEP_EMIS = process.env.CLICKHOUST_PEP_EMIS || flags.clickHousePepEmis +const CLICKHOUST_HR = process.env.CLICKHOUST_HR || flags.clickHouseHr if ( !RC_DB @@ -59,7 +61,7 @@ if ( || !API_EMIS_URL || !QINIU_DOMAIN_QNDMN_RESOURCE || !QINIU_BUCKET_RESOURCE || !QINIU_AK || !QINIU_SK || !CLICKHOUST_URL || !CLICKHOUST_PORT - || !CLICKHOUST_PEP_EMIS + || !CLICKHOUST_PEP_EMIS || !CLICKHOUST_HR ) { console.log('缺少启动参数,异常退出'); args.showHelp(); @@ -117,6 +119,10 @@ const product = { { name: 'pepEmis', db: CLICKHOUST_PEP_EMIS + }, + { + name: 'hr', + db: CLICKHOUST_HR } ] } diff --git a/web/client/src/sections/business/actions/index.js b/web/client/src/sections/business/actions/index.js index bc09861..a50aa64 100644 --- a/web/client/src/sections/business/actions/index.js +++ b/web/client/src/sections/business/actions/index.js @@ -1,6 +1,7 @@ 'use strict'; import * as reserveItem from './reserve-item'; - +import * as salersReport from './salers-report'; export default { - ...reserveItem + ...reserveItem, + ...salersReport } \ No newline at end of file diff --git a/web/client/src/sections/business/actions/salers-report.js b/web/client/src/sections/business/actions/salers-report.js new file mode 100644 index 0000000..2d66bf5 --- /dev/null +++ b/web/client/src/sections/business/actions/salers-report.js @@ -0,0 +1,17 @@ +'use strict'; + +import { ApiTable, basicAction } from '$utils' + +export function getSalesList(query) {//查询 + return (dispatch) => basicAction({ + type: "get", + dispatch: dispatch, + actionType: "GET_SALES_MENBER_LIST", + query: query, + url: `${ApiTable.getSalesList}`, + msg: { option: "查询销售人员列表" }, + reducer: { name: "SalesMemberList", params: { noClear: true } }, + }); +} + + diff --git a/web/client/src/sections/business/containers/performanceReport/achievementDetails.jsx b/web/client/src/sections/business/containers/performanceReport/achievementDetails.jsx index 403dd48..dc3c30b 100644 --- a/web/client/src/sections/business/containers/performanceReport/achievementDetails.jsx +++ b/web/client/src/sections/business/containers/performanceReport/achievementDetails.jsx @@ -1,18 +1,154 @@ -import React, { useEffect, useState } from 'react'; +import React, { useRef, useEffect, useState, useMemo } from 'react'; import { connect } from 'react-redux'; -import { Table } from '@douyinfe/semi-ui'; +import { Select, Input, Button, Popconfirm, Radio, Tooltip, Table, Pagination, Skeleton } from '@douyinfe/semi-ui'; +import { IconSearch } from '@douyinfe/semi-icons'; +import { SkeletonScreen } from "$components"; import '../../style.less'; const AchievementDetails = (props) => { - - const columns = [ - { - title: '序号', - dataIndex: 'index', - render: (text, record, index) => index + 1 - }, - ]; - const data = []; + const { dispatch, actions } = props + const [keywordTarget, setKeywordTarget] = useState('contract'); + const [keyword, setKeyword] = useState('');//搜索内容 + const [limits, setLimits] = useState()//每页实际条数 + const [query, setQuery] = useState({ limit: 10, page: 0 }); //页码信息 + const [tableData, setTableData] = useState([]); + const page = useRef(query.page); + function seachValueChange(value) { + setKeyword(value) + } + const columns = [{ + title: '收到合同日期', + dataIndex: 'year', + key: 'year', + width: 120, + }, { + title: '月份', + dataIndex: 'id', + key: 'id', + width: 120, + }, { + title: '部门', + dataIndex: 'department', + key: 'department', + width: 140, + }, { + title: '销售人员', + dataIndex: 'salers', + key: 'salers', + width: 140, + }, { + title: '客户名称', + dataIndex: 'name', + key: 'name', + width: 140, + }, { + title: '项目名称', + dataIndex: 'projectName', + key: 'projectName', + width: 140, + }, { + title: '合同金额', + dataIndex: 'money', + key: 'money', + width: 140, + }, { + title: '实际业绩', + dataIndex: 'moneyAfterChange', + key: 'moneyAfterChange', + width: 140, + }, { + title: '考核业绩', + dataIndex: 'backYear', + key: 'backYear', + width: 120, + }, { + title: '价格是否特批', + dataIndex: 'backDate', + key: 'backDate', + width: 120, + }, { + title: '特批折算比例', + dataIndex: 'backMoney', + key: 'backMoney', + width: 120, + }, { + title: '预支提成及委外费用', + dataIndex: 'invoiceBack', + key: 'invoiceBack', + width: 140, + }, { + title: '业务线', + dataIndex: 'leaveMoney', + key: 'leaveMoney', + width: 120, + }, { + title: '客户类型', + dataIndex: 'payConfirmTime', + key: 'payConfirmTime', + width: 140, + }, { + title: '行业', + dataIndex: 'thirdPayer', + key: 'thirdPayer', + width: 140, + }, { + title: '信息来源', + dataIndex: 'desc', + key: 'desc', + width: 120, + }, { + title: '项目类型', + dataIndex: 'leaveMoney', + key: 'leaveMoney', + width: 120, + }, { + title: '客户省份', + dataIndex: 'payConfirmTime', + key: 'payConfirmTime', + width: 140, + }, { + title: '客户属性', + dataIndex: 'thirdPayer', + key: 'thirdPayer', + width: 140, + }, { + title: '复购次数', + dataIndex: 'desc', + key: 'desc', + width: 120, + }, { + title: '是否可复制的业务路径', + dataIndex: 'leaveMoney', + key: 'leaveMoney', + width: 120, + }, { + title: '省外业务1.1', + dataIndex: 'payConfirmTime', + key: 'payConfirmTime', + width: 140, + }, { + title: '复购业务1.05', + dataIndex: 'thirdPayer', + key: 'thirdPayer', + width: 140, + }, { + title: '可复制的业务路径1.1', + dataIndex: 'desc', + key: 'desc', + width: 120, + }] + function handleRow(record, index) {// 给偶数行设置斑马纹 + if (index % 2 === 0) { + return { + style: { + background: '#FAFCFF', + } + }; + } else { + return {}; + } + } + const scroll = useMemo(() => ({}), []); return ( <>