wenlele 2 years ago
parent
commit
fbb123e4d7
  1. 15
      api/app/lib/controllers/auth/index.js
  2. 23
      api/app/lib/controllers/customerContactsFollup/index.js
  3. 262
      api/app/lib/controllers/report/achievement.js
  4. 10
      api/app/lib/controllers/report/index.js
  5. 65
      api/app/lib/models/customerContactsFollup.js
  6. 8
      api/app/lib/routes/customerContactsFollup/index.js
  7. 3
      api/app/lib/routes/report/index.js
  8. 13
      web/client/src/sections/business/actions/achievement-report.js
  9. 61
      web/client/src/sections/business/containers/performanceReport/achievementDetails.jsx
  10. 55
      web/client/src/sections/business/containers/performanceReport/backMoneyDetails.jsx
  11. 47
      web/client/src/sections/business/containers/performanceReport/contractDetails.jsx
  12. 24
      web/client/src/utils/webapi.js

15
api/app/lib/controllers/auth/index.js

@ -9,9 +9,18 @@ async function login (ctx, next) {
try {
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, }
})
} else if (params.token) {
emisLoginRes = await ctx.app.fs.emisRequest.get('user-info', {
query: {
token: params.token,
}
})
}
if (!emisLoginRes) {
throw "无此用户,请使用正确的登录信息"

23
api/app/lib/controllers/customerContactsFollup/index.js

@ -0,0 +1,23 @@
'use strict';
// 查询储备项目统计表
async function getCustomerContactsFollowup(ctx, next) {
const { type } = ctx.params;
let rslt = null;
try {
rslt = await ctx.fs.dc.models.ReserveItemReport.findAll({
order: [['id', 'DESC']],
// where: { type: type }
})
ctx.status = 200
ctx.body = rslt
} catch (error) {
ctx.fs.logger.error(`path:${ctx.path},error:${error}`)
ctx.status = 400;
ctx.body = { name: 'FindAllError', message: '获取失败' }
}
}
module.exports = {
getCustomerContactsFollowup
}

262
api/app/lib/controllers/report/achievement.js

@ -5,22 +5,33 @@ const moment = require('moment');
async function getReceivedDetail(ctx) {
try {
const { models } = ctx.fs.dc;
const { keywordTarget, keyword, limit, page } = ctx.query
const { keywordTarget, keyword, limit, page, toExport } = ctx.query
let where = {}
if (keywordTarget == 'contract' && keyword) {
where.contractNo = { $like: `%${keyword}%` }
}
let res = await models.ReceivableDetail.findAndCountAll({
let findOption = {
where: where,
offset: Number(page) * Number(limit),
limit: Number(limit),
order: [['id', 'DESC']]
})
ctx.status = 200
ctx.body = {
count: res.count,
rows: res.rows
};
}
if (!toExport) {//非导出时考虑分页
if (limit) {
findOption.limit = Number(limit)
}
if (page && limit) {
findOption.offset = Number(page) * Number(limit)
}
}
let res = await models.ReceivableDetail.findAndCountAll(findOption);
if (toExport) {//数据导出相关
await exportReceivedDetail(ctx, res.rows);
} else {
ctx.status = 200
ctx.body = {
count: res.count,
rows: res.rows
};
}
} catch (error) {
ctx.fs.logger.error(`path:${ctx.path},error:${error}`)
ctx.status = 400;
@ -28,10 +39,87 @@ async function getReceivedDetail(ctx) {
}
}
async function exportReceivedDetail(ctx, dataList) {
try {
let header = [{
title: '年度',
key: 'year',
}, {
title: '序号',
key: 'serialNo',
}, {
title: '编号',
key: 'number',
}, {
title: '部门',
key: 'department',
}, {
title: '销售人员',
key: 'sale',
}, {
title: '合同编号',
key: 'contractNo',
}, {
title: '客户名称',
key: 'customer',
}, {
title: '项目名称',
key: 'item',
}, {
title: '合同金额',
key: 'amount',
}, {
title: '变更后合同金额',
key: 'changeAmount',
}, {
title: '回款年份',
key: 'receivableYear',
}, {
title: '回款日期',
key: 'receivableDate',
}, {
title: '回款金额',
key: 'receivableAmount',
}, {
title: '开票-回款',
key: 'invoicedBack',
}, {
title: '剩余合同金额',
key: 'remainConAmount',
}, {
title: '收入确认时间',
key: 'incomeConfirmdate',
}, {
title: '第三方付款单位',
key: 'thirdPayment',
}, {
title: '备注',
key: 'remark',
}]
const { utils: { simpleExcelDown } } = ctx.app.fs;
let exportData = []
for (let { dataValues: item } of dataList) {
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
}
}
}
async function getAchievementDetail(ctx) {
try {
const { models } = ctx.fs.dc;
const { keywordTarget, keyword, limit, page } = ctx.query
const { keywordTarget, keyword, limit, page, toExport } = ctx.query
let where = {}
if (keywordTarget == 'saler' && keyword) {
where.sale = { $like: `%${keyword}%` }
@ -42,25 +130,161 @@ async function getAchievementDetail(ctx) {
if (keywordTarget == 'dep' && keyword) {
where.department = { $like: `%${keyword}%` }
}
let res = await models.PerformanceDetail.findAndCountAll({
let findOption = {
where: where,
order: [['id', 'DESC']]
}
if (!toExport) {//非导出时考虑分页
if (limit) {
findOption.limit = Number(limit)
}
if (page && limit) {
findOption.offset = Number(page) * Number(limit)
}
}
let res = await models.PerformanceDetail.findAndCountAll(findOption);
if (toExport) {//数据导出相关
await exportAchievementDetail(ctx, res.rows);
} else {
ctx.status = 200
ctx.body = {
count: res.count,
rows: res.rows
};
}
} catch (error) {
ctx.fs.logger.error(`path:${ctx.path},error:${error}`)
ctx.status = 400;
ctx.body = { name: 'FindAllError', message: '获取失败' }
}
}
async function exportAchievementDetail(ctx, dataList) {
try {
let header = [{
title: '收到合同日期',
key: 'recConDate',
}, {
title: '月份',
key: 'month',
}, {
title: '部门',
key: 'department',
}, {
title: '销售人员',
key: 'sale',
}, {
title: '客户名称',
key: 'customer',
}, {
title: '项目名称',
key: 'item',
}, {
title: '合同金额',
key: 'amount',
}, {
title: '实际业绩',
key: 'realPerformance',
}, {
title: '考核业绩',
key: 'assessmentPerformance',
}, {
title: '价格是否特批',
key: 'isApproval',
}, {
title: '特批折算比例',
key: 'approvalProp',
}, {
title: '预支提成及委外费用',
key: 'cost',
}, {
title: '业务线',
key: 'serviceLine',
}, {
title: '客户类型',
key: 'cusType',
}, {
title: '行业',
key: 'industry',
}, {
title: '信息来源',
key: 'source',
}, {
title: '项目类型',
key: 'itemType',
}, {
title: '客户省份',
key: 'cusProvince',
}, {
title: '客户属性',
key: 'cusAttribute',
}, {
title: '复购次数',
key: 'repurchaseCount',
}, {
title: '是否可复制的业务路径',
key: 'reproducible',
}, {
title: '省外业务1.1',
key: 'outProvince',
}, {
title: '复购业务1.05',
key: 'repurchase',
}, {
title: '可复制的业务路径1.1',
key: 'isreproduce',
}]
const { utils: { simpleExcelDown } } = ctx.app.fs;
let exportData = []
for (let { dataValues: item } of dataList) {
item.isApproval = item.isApproval ? '是' : '否';
item.reproducible = item.reproducible ? '是' : '否';
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
}
}
}
/**
* 查询合同明细表数据
* @param {*} ctx ctx ctx.query:{keywordTarget-关键字项keyword-关键字内容limit-页宽, page-页码}
*/
async function getContractDetail(ctx) {
try {
const { models } = ctx.fs.dc;
const { keywordTarget, keyword, limit, page } = ctx.query;
const where = {};
if (keywordTarget && keyword) {
where[keywordTarget] = { $iLike: `%${keyword}%` };
}
let contractDetail = await models.ContractDetail.findAndCountAll({
where: where,
offset: Number(page) * Number(limit),
limit: Number(limit),
order: [['id', 'DESC']]
})
});
ctx.status = 200
ctx.body = {
count: res.count,
rows: res.rows
};
ctx.body = contractDetail;
} catch (error) {
ctx.fs.logger.error(`path:${ctx.path},error:${error}`)
ctx.status = 400;
ctx.body = { name: 'FindAllError', message: '获取失败' }
ctx.body = { name: 'FindError', message: '查询合同明细表数据失败' }
}
}
module.exports = {
getReceivedDetail,//回款
getAchievementDetail,//业绩
getContractDetail,
}

10
api/app/lib/controllers/report/index.js

@ -133,12 +133,12 @@ async function exportSalesDetail(ctx, dataList) {
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.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 || '-';
//item.hireDate = item.hireDate || '-';
exportData.push(item)
}
const fileName = `销售人员分布明细表_${moment().format('YYYYMMDDHHmmss')}` + '.xlsx'

65
api/app/lib/models/customerContactsFollup.js

@ -0,0 +1,65 @@
/* eslint-disable*/
'use strict';
module.exports = dc => {
const DataTypes = dc.ORM;
const sequelize = dc.orm;
const ReserveItemReport = sequelize.define("reserveItemReport", {
id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
field: "id",
autoIncrement: true,
},
customer: {
type: DataTypes.STRING,
allowNull: true,
field: "customer",
},
items: {
type: DataTypes.STRING,
allowNull: true,
field: "items",
},
department: {
type: DataTypes.STRING,
allowNull: false,
field: "department",
},
sale: {
type: DataTypes.STRING,
allowNull: true,
field: "sale",
},
updatetime: {
type: DataTypes.DATE,
allowNull: false,
field: "updatetime",
},
customerContacts: {
type: DataTypes.STRING,
allowNull: true,
field: "customer_contacts",
},
phone: {
type: DataTypes.STRING,
allowNull: true,
field: "phone",
},
visitStyle: {
type: DataTypes.STRING,
allowNull: true,
field: "visit_style",
},
itemText: {
type: DataTypes.STRING,
allowNull: true,
field: "item_text",
}
}, {
tableName: "customer_contacts_followup",
});
dc.models.ReserveItemReport = ReserveItemReport;
return ReserveItemReport;
};

8
api/app/lib/routes/customerContactsFollup/index.js

@ -0,0 +1,8 @@
'use strict';
const report = require('../../controllers/customerContactsFollup');
module.exports = function (app, router, opts) {
app.fs.api.logAttr['GET/customerContactsFollup'] = { content: '客户联系人对接跟进', visible: false };
router.get('/customerContactsFollup', report.getReserveItemReport);
};

3
api/app/lib/routes/report/index.js

@ -15,4 +15,7 @@ module.exports = function (app, router, opts) {
app.fs.api.logAttr['GET/detail/achievement'] = { content: '查询业绩明细表', visible: false };
router.get('/detail/achievement', achieve.getAchievementDetail);
app.fs.api.logAttr['GET/contract/detail'] = { content: '查询合同明细表', visible: false };
router.get('/contract/detail', achieve.getContractDetail);
};

13
web/client/src/sections/business/actions/achievement-report.js

@ -26,4 +26,17 @@ export function getAchievementDetail(query) {
msg: { option: "查询业绩明细表" },
reducer: { name: "AchievementDetail", params: { noClear: true } },
});
}
//查询合同明细表
export function getContractDetail(query) {
return (dispatch) => basicAction({
type: "get",
dispatch: dispatch,
actionType: "GET_CONTRACT_DETAIL",
query: query,
url: `${ApiTable.getContractDetail}`,
msg: { option: "查询合同明细表" },
reducer: { name: "ContractDetail", params: { noClear: true } },
});
}

61
web/client/src/sections/business/containers/performanceReport/achievementDetails.jsx

@ -1,18 +1,20 @@
import React, { useRef, useEffect, useState, useMemo } from 'react';
import { connect } from 'react-redux';
import { Select, Input, Button, Popconfirm, Radio, Tooltip, Table, Pagination, Skeleton } from '@douyinfe/semi-ui';
import moment from 'moment'
import { Select, Input, Button, Toast, 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 { dispatch, actions } = props
const { dispatch, actions, user } = props
const { businessManagement } = actions
const [keywordTarget, setKeywordTarget] = useState('saler');
const [keyword, setKeyword] = useState('');//
const [limits, setLimits] = useState()//
const [query, setQuery] = useState({ limit: 10, page: 0 }); //
const [tableData, setTableData] = useState([]);
const [exportUrl, setExportUrl] = useState('')
const page = useRef(query.page);
function seachValueChange(value) {
setKeyword(value)
@ -22,6 +24,10 @@ const AchievementDetails = (props) => {
getAchievementDetails()
}, []);
useEffect(() => {
getAchievementDetails()
}, [query])
function getAchievementDetails() {
dispatch(businessManagement.getAchievementDetail({ keywordTarget, keyword, ...query })).then(r => {
if (r.success) {
@ -36,121 +42,145 @@ const AchievementDetails = (props) => {
dataIndex: 'recConDate',
key: 'recConDate',
width: 120,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '月份',
dataIndex: 'month',
key: 'month',
width: 120,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '部门',
dataIndex: 'department',
key: 'department',
width: 140,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '销售人员',
dataIndex: 'sale',
key: 'sale',
width: 140,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '客户名称',
dataIndex: 'customer',
key: 'customer',
width: 140,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '项目名称',
dataIndex: 'item',
key: 'item',
width: 140,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '合同金额',
dataIndex: 'amount',
key: 'amount',
width: 140,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '实际业绩',
dataIndex: 'realPerformance',
key: 'realPerformance',
width: 140,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '考核业绩',
dataIndex: 'assessmentPerformance',
key: 'assessmentPerformance',
width: 120,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '价格是否特批',
dataIndex: 'isApproval',
key: 'isApproval',
width: 120,
render: (text, record) => <span>{text ? '是' : '否'}</span>
}, {
title: '特批折算比例',
dataIndex: 'approvalProp',
key: 'approvalProp',
width: 120,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '预支提成及委外费用',
dataIndex: 'cost',
key: 'cost',
width: 140,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '业务线',
dataIndex: 'serviceLine',
key: 'serviceLine',
width: 120,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '客户类型',
dataIndex: 'cusType',
key: 'cusType',
width: 140,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '行业',
dataIndex: 'industry',
key: 'industry',
width: 140,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '信息来源',
dataIndex: 'source',
key: 'source',
width: 120,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '项目类型',
dataIndex: 'itemType',
key: 'itemType',
width: 120,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '客户省份',
dataIndex: 'cusProvince',
key: 'cusProvince',
width: 140,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '客户属性',
dataIndex: 'cusAttribute',
key: 'cusAttribute',
width: 140,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '复购次数',
dataIndex: 'repurchaseCount',
key: 'repurchaseCount',
width: 120,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '是否可复制的业务路径',
dataIndex: 'reproducible',
key: 'reproducible',
width: 120,
render: (text, record) => <span>{text ? '是' : '否'}</span>
}, {
title: '省外业务1.1',
dataIndex: 'outProvince',
key: 'outProvince',
width: 140,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '复购业务1.05',
dataIndex: 'repurchase',
key: 'repurchase',
width: 140,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '可复制的业务路径1.1',
dataIndex: 'isreproduce',
key: 'isreproduce',
width: 120,
render: (text, record) => <span>{text || '-'}</span>
}]
function handleRow(record, index) {//
if (index % 2 === 0) {
@ -163,6 +193,23 @@ const AchievementDetails = (props) => {
return {};
}
}
const exportAllData = () => {
dispatch(businessManagement.getAchievementDetail({ limit: 1 })).then((res) => {//
if (res.success) {
if (res.payload.data.count) {
let url = `detail/achievement?token=${user.token}&toExport=1&timestamp=${moment().valueOf()}`
setExportUrl(url);
} else {
Toast.info({
content: '暂无可导出的数据',
duration: 3,
})
}
}
})
}
const scroll = useMemo(() => ({}), []);
return (
<>
@ -206,12 +253,15 @@ const AchievementDetails = (props) => {
setQuery({ limit: 10, page: 0 })
}}>查询</Button>
</div>
<div style={{ display: 'flex', marginRight: 20 }}>
<div style={{ display: 'flex' }}>
<div style={{ padding: '6px 20px', background: '#0F7EFB', color: '#FFFFFF', fontSize: 14, cursor: "pointer" }}
onClick={() => { setImportModalV(true); }}>
导入
</div>
<div style={{ padding: '6px 20px', background: '#00BA85', color: '#FFFFFF', fontSize: 14, marginLeft: 18 }}>
<div style={{ padding: '6px 20px', background: '#00BA85', color: '#FFFFFF', fontSize: 14, cursor: "pointer", marginLeft: 18 }}
onClick={() => {
exportAllData()
}}>
导出全部
</div>
</div>
@ -257,6 +307,9 @@ const AchievementDetails = (props) => {
</div>
</div>
</div>
{
exportUrl ? <iframe src={`/_api/${exportUrl}`} style={{ display: 'none' }} /> : ''
}
</div>
</>
)

55
web/client/src/sections/business/containers/performanceReport/backMoneyDetails.jsx

@ -1,18 +1,20 @@
import React, { useRef, useEffect, useState, useMemo } from 'react';
import { connect } from 'react-redux';
import { Select, Input, Button, Popconfirm, Radio, Tooltip, Table, Pagination, Skeleton } from '@douyinfe/semi-ui';
import moment from 'moment'
import { Select, Input, Button, Toast, Radio, Tooltip, Table, Pagination, Skeleton } from '@douyinfe/semi-ui';
import { IconSearch } from '@douyinfe/semi-icons';
import { SkeletonScreen } from "$components";
import '../../style.less';
const BackMoneyDetails = (props) => {
const { dispatch, actions } = props
const { dispatch, actions, user } = props
const { businessManagement } = actions
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 [exportUrl, setExportUrl] = useState('')
const page = useRef(query.page);
function seachValueChange(value) {
setKeyword(value)
@ -22,6 +24,10 @@ const BackMoneyDetails = (props) => {
getBackMoneyDetails()
}, []);
useEffect(() => {
getBackMoneyDetails()
}, [query])
function getBackMoneyDetails() {
dispatch(businessManagement.getReceivedDetail({ keywordTarget, keyword, ...query })).then(r => {
if (r.success) {
@ -36,91 +42,109 @@ const BackMoneyDetails = (props) => {
dataIndex: 'year',
key: 'year',
width: 120,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '序号',
dataIndex: 'serialNo',
key: 'serialNo',
width: 120,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '编号',
dataIndex: 'number',
key: 'number',
width: 120,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '部门',
dataIndex: 'department',
key: 'department',
width: 140,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '销售人员',
dataIndex: 'sale',
key: 'sale',
width: 140,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '合同编号',
dataIndex: 'contractNo',
key: 'contractNo',
width: 140,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '客户名称',
dataIndex: 'customer',
key: 'customer',
width: 140,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '项目名称',
dataIndex: 'item',
key: 'item',
width: 140,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '合同金额',
dataIndex: 'amount',
key: 'amount',
width: 140,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '变更后合同金额',
dataIndex: 'changeAmount',
key: 'changeAmount',
width: 140,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '回款年份',
dataIndex: 'receivableYear',
key: 'receivableYear',
width: 120,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '回款日期',
dataIndex: 'receivableDate',
key: 'receivableDate',
width: 120,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '回款金额',
dataIndex: 'receivableAmount',
key: 'receivableAmount',
width: 120,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '开票-回款',
dataIndex: 'invoicedBack',
key: 'invoicedBack',
width: 140,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '剩余合同金额',
dataIndex: 'remainConAmount',
key: 'remainConAmount',
width: 120,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '收入确认时间',
dataIndex: 'incomeConfirmdate',
key: 'incomeConfirmdate',
width: 140,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '第三方付款单位',
dataIndex: 'thirdPayment',
key: 'thirdPayment',
width: 140,
render: (text, record) => <span>{text || '-'}</span>
}, {
title: '备注',
dataIndex: 'remark',
key: 'remark',
width: 120,
render: (text, record) => <span>{text || '-'}</span>
}]
function handleRow(record, index) {//
if (index % 2 === 0) {
@ -133,6 +157,23 @@ const BackMoneyDetails = (props) => {
return {};
}
}
const exportAllData = () => {
dispatch(businessManagement.getReceivedDetail({ limit: 1 })).then((res) => {//
if (res.success) {
if (res.payload.data.count) {
let url = `detail/received/back?token=${user.token}&toExport=1&timestamp=${moment().valueOf()}`
setExportUrl(url);
} else {
Toast.info({
content: '暂无可导出的数据',
duration: 3,
})
}
}
})
}
const scroll = useMemo(() => ({}), []);
return (
<>
@ -176,12 +217,15 @@ const BackMoneyDetails = (props) => {
setQuery({ limit: 10, page: 0 })
}}>查询</Button>
</div>
<div style={{ display: 'flex', marginRight: 20 }}>
<div style={{ display: 'flex' }}>
<div style={{ padding: '6px 20px', background: '#0F7EFB', color: '#FFFFFF', fontSize: 14, cursor: "pointer" }}
onClick={() => { setImportModalV(true); }}>
导入
</div>
<div style={{ padding: '6px 20px', background: '#00BA85', color: '#FFFFFF', fontSize: 14, marginLeft: 18 }}>
<div style={{ padding: '6px 20px', background: '#00BA85', color: '#FFFFFF', fontSize: 14, cursor: "pointer", marginLeft: 18 }}
onClick={() => {
exportAllData()
}}>
导出全部
</div>
</div>
@ -227,6 +271,9 @@ const BackMoneyDetails = (props) => {
</div>
</div>
</div>
{
exportUrl ? <iframe src={`/_api/${exportUrl}`} style={{ display: 'none' }} /> : ''
}
</div>
</>
)

47
web/client/src/sections/business/containers/performanceReport/contractDetails.jsx

@ -1,6 +1,6 @@
import React, { useEffect, useState, useRef, useMemo } from 'react';
import { connect } from 'react-redux';
import { Select, Input, Button, Table, Pagination, Skeleton } from '@douyinfe/semi-ui';
import { Select, Input, Button, Table, Pagination, Skeleton, Toast, } from '@douyinfe/semi-ui';
import { SkeletonScreen, Setup } from "$components";
import { IconSearch } from '@douyinfe/semi-icons';
import ImportContractDetailsModal from './importContractDetailsModal';
@ -10,7 +10,7 @@ import moment from 'moment'
const ContractDetails = (props) => {
const { dispatch, actions } = props
const { } = actions;
const { businessManagement } = actions;
const [keywordTarget, setKeywordTarget] = useState('contractNo');
const [keyword, setKeyword] = useState('');//
const [limits, setLimits] = useState()//
@ -20,6 +20,10 @@ const ContractDetails = (props) => {
const [setup, setSetup] = useState(false);//
const [setupp, setSetupp] = useState([]);//
const [exportUrl, setExportUrl] = useState('');
const page = useRef(query.page);
const CONTRACTDETAILS = "contractDetails";
const renderColumns = (columnKeys) => {
let columns = [];
@ -52,6 +56,7 @@ const ContractDetails = (props) => {
)
: "";
attribute();
getContractDetailData();
}, []);
//
function attribute() {
@ -66,9 +71,16 @@ const ContractDetails = (props) => {
}
setSetupp(newColumns);
}
useEffect(() => {
}, [query])
function getContractDetailData(param) {
let queryParam = param || query;
dispatch(businessManagement.getContractDetail({ keywordTarget, keyword, ...queryParam })).then(r => {
if (r.success) {
setTableData(r.payload?.data?.rows);
setLimits(r.payload?.data?.count);
}
})
}
function handleRow(record, index) {//
if (index % 2 === 0) {
return {
@ -80,6 +92,22 @@ const ContractDetails = (props) => {
return {};
}
}
const exportAllData = () => {
dispatch(businessManagement.getContractDetail({ limit: 1, page: 0 })).then((res) => {
if (res.success) {
if (res.payload.data.count) {
let url = `export/contract/detail?token=${user.token}&timestamp=${moment().valueOf()}`
setExportUrl(url);
} else {
Toast.info({
content: '暂无可导出的数据',
duration: 3,
})
}
}
})
}
const scroll = useMemo(() => ({}), []);
return (
<>
@ -121,6 +149,7 @@ const ContractDetails = (props) => {
<Button theme='solid' type='primary' style={{ width: 80, borderRadius: 2, height: 32, background: '#DBECFF', color: '#005ABD' }}
onClick={() => {
setQuery({ limit: 10, page: 0 })
getContractDetailData({ limit: 10, page: 0 })
}}>查询</Button>
</div>
<div style={{ display: 'flex', marginRight: 20 }}>
@ -131,7 +160,9 @@ const ContractDetails = (props) => {
onClick={() => { setImportModalV(true); }}>
导入
</div>
<div style={{ padding: '6px 20px', background: '#00BA85', color: '#FFFFFF', fontSize: 14, marginLeft: 18 }}>
<div style={{ padding: '6px 20px', background: '#00BA85', color: '#FFFFFF', fontSize: 14, marginLeft: 18 }} onClick={() => {
exportAllData()
}}>
导出全部
</div>
</div>
@ -172,7 +203,8 @@ const ContractDetails = (props) => {
pageSizeOpts={[10, 20, 30, 40]}
onChange={(currentPage, pageSize) => {
setQuery({ limit: pageSize, page: currentPage - 1 });
page.current = currentPage - 1
getContractDetailData({ limit: pageSize, page: currentPage - 1 });
page.current = currentPage - 1;
}}
/>
</div>
@ -186,6 +218,9 @@ const ContractDetails = (props) => {
setImportModalV(false);
}} /> : ''
}
{
exportUrl ? <iframe src={`/_api/${exportUrl}`} style={{ display: 'none' }} /> : ''
}
</div>
{setup ? (
<Setup

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

@ -5,24 +5,25 @@ export const AxyRequest = new ProxyRequest("_axy");
export const EmisRequest = new ProxyRequest("_emis")
export const webUtils = new customWebUtils({
userKey: 'dcUser'
userKey: 'dcUser'
});
const { basicAction, RouteRequest } = webUtils
export {
basicAction, RouteRequest
basicAction, RouteRequest
}
export const ApiTable = {
login: "login",
logout: "logout",
login: "login",
logout: "logout",
//项目报表
getReserveItemReport: "reserveItem/report/{type}",
//销售人员分布明细表
getSalesList: 'sales/member/list',
//业绩报表
getReceivedDetail: 'detail/received/back',
getAchievementDetail: 'detail/achievement',
//项目报表
getReserveItemReport: "reserveItem/report/{type}",
//销售人员分布明细表
getSalesList: 'sales/member/list',
//业绩报表
getReceivedDetail: 'detail/received/back',
getAchievementDetail: 'detail/achievement',
getContractDetail: 'contract/detail',
};
export const RouteTable = {
apiRoot: "/api/root",
@ -30,5 +31,4 @@ export const RouteTable = {
cleanUpUploadTrash: "/_upload/cleanup",
getServiceUrl: '/_service/url',
getDomain: '/domain',
};

Loading…
Cancel
Save