2025-06-13 19:18:28 +08:00

719 lines
24 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { connect } from "umi";
import type { CurrentUser } from "umi";
import type { ConnectState } from "@/models/connect";
import React, { useRef, useState } from "react";
import ProCard from "@ant-design/pro-card";
import { MenuFoldOutlined } from "@ant-design/icons";
import type { FormInstance } from "antd";
import { Button, Card, message, Row, Steps, Tooltip, Typography } from "antd";
import { Drawer } from "antd";
import { Space, Tree } from "antd";
import useRequest from "@ahooksjs/use-request";
import { getServerpartTree } from "@/services/options";
import type { ActionType } from "@ant-design/pro-table";
import ProTable from "@ant-design/pro-table";
import { handleGetExamineList, handleGetMonthAccountProinst } from "@/pages/examine/examineList/service";
import moment from "moment";
import { PageContainer } from "@ant-design/pro-layout";
import ReactHTMLTableToExcel from "react-html-table-to-excel";
import ProDescriptions from "@ant-design/pro-descriptions";
import {
handleGetGetBUSINESSAPPROVALDetail,
handleGetTableMonthlyReconciliation
} from "@/pages/reports/ShopExpenseDetail/service";
import { wrapTreeNode } from "@/utils/format";
import RevenueList from "@/pages/BussinessProject/components/RevenueList";
import './style.less'
import ProjectDetailDrawer from "@/pages/reports/component/ProjectDetailDrawer";
import { handleGetAPPROVALROUTEList } from "@/pages/Setting/serviceConfig/service";
const { Step } = Steps
const examineList: React.FC<{ currentUser: CurrentUser }> = (props) => {
const { currentUser } = props
const actionRef = useRef<ActionType>();
const actionDetailRef = useRef<ActionType>();
const formRef = useRef<FormInstance>();
const formDetailRef = useRef<FormInstance>();
const [reqDetailList, setReqDetailList] = useState<any>(); // 合计项数据源
const [reqDetailListDetail, setReqDetailListDetail] = useState<any>(); // 合计项数据源
const [printOut, setPrintOut] = useState<any>(); // 打印数据的内容
const [collapsible, setCollapsible] = useState<boolean>(false)
const [treeView, setTreeView] = useState<any>()
// 加载服务区树
const { loading: treeLoading, data: treeViews } = useRequest(async () => {
const data = await getServerpartTree(currentUser?.ProvinceCode, currentUser?.CityAuthority, true, true, true)
setTreeView(data)
return data
})
// 树相关的属性和方法
const [selectedId, setSelectedId] = useState<string>()
// 显示详情抽屉
const [showDeatilDrawer, setShowDetailDrawer] = useState<boolean>(false)
const [currentRow, setCurrentRow] = useState<any>()
// 详情的加载效果
const [detailLoading, setDetailLoading] = useState<boolean>(false)
// 详情里面表格加载效果
const [tableLoading, setTableLoading] = useState<boolean>(false)
const [otherData, setOtherData] = useState<any>();// 显示表格上方内容
// 流程进度的当前状态
const [progressState, setProgressState] = useState<number>(0)
// 流程进度的数组
const [progressList, setProgressList] = useState<any>()
// 进度流畅的详情信息
const [progressDetail, setProgressDetail] = useState<any>()
const [showDetail, setShowDetail] = useState<boolean>(false) // 是否显示详情
const [detailCurrentRow, setDetailCurrentRow] = useState<any>()
const [tableAllData, setTableAllData] = useState<any>()
const columns: any = [
{
title: '业务名称',
ellipsis: true,
dataIndex: 'BusinessProcess_Name',
hideInSearch: true,
render: (_, record) => {
return <a onClick={() => {
console.log('record', record)
setCurrentRow(record)
handleGetProcessProgress(record?.BusinessApproval_ID)
handleGetTableData(record?.BusinessProcess_ID, record?.Proinst_ID)
setShowDetailDrawer(true)
}}>{record?.BusinessProcess_Name}</a>
}
},
{
title: '服务区名称',
width: 200,
ellipsis: true,
dataIndex: 'Serverpart_Name',
hideInSearch: true
},
{
title: '经办人',
width: 140,
dataIndex: 'Staff_Name',
hideInSearch: true,
ellipsis: true,
},
// {
// title: '统计时间',
// dataIndex: 'search_date',
// valueType: 'dateRange',
// hideInTable: true,
// hideInDescriptions: true,
// initialValue: [moment().format('YYYY-MM-DD'), moment().format('YYYY-MM-DD')],
// search: {
// transform: (value) => {
// return {
// StartDate: value[0],
// EndDate: value[1],
// };
// },
// },
// fieldProps: {
// disabledDate: (current: any) => current && current > moment().endOf('day')
// }
// },
{
title: '业务时间',
dataIndex: '',
width: 140,
hideInSearch: true,
render: (_, record) => {
return record.BusinessProcess_StartDate ? `${moment(record.BusinessProcess_StartDate).format('YYYY-MM-DD')}` : ''
}
},
{
title: '业务状态',
width: 150,
dataIndex: 'BusinessProcess_State',
valueType: 'select',
request: async () => {
const req: any = {
SearchParameter: {
APPROVALROUTE_VALID: 1,
OPERATION_TYPES: 11
},
SortStr: 'APPROVALROUTE_STATE asc',
PageIndex: 1,
PageSize: 999999
}
const data = await handleGetAPPROVALROUTEList(req)
console.log('data2222', data)
if (data && data.length > 0) {
const list: any = []
data.forEach((item: any) => {
list.push({ label: item.APPROVALROUTE_NAME, value: item.APPROVALROUTE_STATE })
})
list.push({ label: '已审结', value: 9000 })
list.push({ label: '已驳回', value: 3000 })
let str: string = ''
list.forEach((item: any) => {
if (item.value === 3000) {
} else {
if (str) {
str += `,${item.value}`
} else {
str = item.value
}
}
})
return list
}
return []
}
},
{
title: '待审核人名称',
width: 180,
ellipsis: true,
dataIndex: 'ApproveStaff_Name',
hideInSearch: true,
render: (_, record) => {
return record?.BusinessProcess_State === 9000 ? '' : record?.ApproveStaff_Name
}
},
{
title: '备注说明',
width: 250,
ellipsis: true,
dataIndex: 'BusinessProcess_Desc',
hideInSearch: true
},
// {
// dataIndex: 'option',
// title: '操作',
// width: 120,
// valueType: 'option',
// align: 'center',
// fixed:'right',
// hideInSearch: true,
// render: (_,record)=>{
// return (
// <Space>
//
// </Space>
// )
// }
// }
]
const detailColumns: any = [
{
title: '期限',
dataIndex: '',
hideInSearch: true,
children: [
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: 'PeriodIndexStr',
align: 'left',
width: 150,
hideInSearch: true,
render: (_, record) => {
return <span style={{ color: record?.PeriodIndexStr === '项目开始前' ? '#faad14' : '' }}>{record.PeriodIndexStr}</span>
}
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: 'PeriodDesc',
align: 'left',
width: 200,
hideInSearch: true,
render: (_, record) => {
return record?.PeriodDesc !== '合计' ?
<a style={{
color: new Date(record.EndDate).getTime() < new Date().getTime() ? '#1890ff' : '#000000',
cursor: new Date(record.EndDate).getTime() < new Date().getTime() ? 'pointer' : ''
}} onClick={() => {
console.log('record', record)
if (new Date(record.EndDate).getTime() < new Date().getTime()) {
const obj: any = {
...record,
...tableAllData,
STARTDATE: record.StartDate
}
console.log('obj', obj)
setDetailCurrentRow(obj);
setShowDetail(true);
}
}}>
{`${record?.StartDate}-${record?.EndDate}`}
</a> :
<span>{`${record?.PeriodDesc}`}</span>
}
},
]
},
{
title: '租金信息',
dataIndex: '',
hideInSearch: true,
children: [
{
title: <div style={{ textAlign: 'center' }}>/</div>,
dataIndex: 'MinturnOver',
valueType: 'digit',
align: 'right',
width: 170,
hideInSearch: true,
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: 'GuaranteeRatio',
hideInSearch: true,
align: 'right',
width: 120,
render: (_, record) => {
return record?.GuaranteeRatio ? `${record?.GuaranteeRatio}%` : ''
}
}
]
},
{
title: '营业额',
dataIndex: '',
hideInSearch: true,
children: [
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: 'CashAmount',
valueType: 'digit',
align: 'right',
width: 100,
hideInSearch: true,
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: 'MobilePayAmount',
valueType: 'digit',
align: 'right',
width: 100,
hideInSearch: true,
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: 'RevenueAmount',
valueType: 'digit',
align: 'right',
width: 100,
hideInSearch: true,
}
]
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: 'RoyaltyAmount',
valueType: 'digit',
width: 100,
align: 'right',
hideInSearch: true,
},
{
title: '应收费用',
dataIndex: '',
hideInSearch: true,
children: [
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: 'GuaranteeFee',
valueType: 'digit',
align: 'right',
width: 100,
hideInSearch: true,
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: 'PropertyFee',
valueType: 'digit',
align: 'right',
width: 100,
hideInSearch: true,
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: 'HouseRent',
valueType: 'digit',
align: 'right',
width: 100,
hideInSearch: true,
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: 'BreachPenalty',
valueType: 'digit',
align: 'right',
width: 100,
hideInSearch: true,
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: 'ElectricityCharge',
valueType: 'digit',
align: 'right',
width: 100,
hideInSearch: true,
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: 'WaterCharge',
valueType: 'digit',
align: 'right',
width: 100,
hideInSearch: true,
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: 'OtherFee',
valueType: 'digit',
align: 'right',
width: 100,
hideInSearch: true,
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: 'ReceivableAmount',
valueType: 'digit',
align: 'right',
width: 100,
hideInSearch: true,
},
]
},
{
title: <div style={{ textAlign: 'center' }}>退</div>,
dataIndex: 'RefundSupplement',
valueType: 'digit',
align: 'right',
width: 100,
hideInSearch: true,
}
]
// 拿到流程进度的数据
const handleGetProcessProgress = async (id: any) => {
const req: any = {
BUSINESSAPPROVALId: id || currentRow?.BUSINESSAPPROVAL_ID
}
const data = await handleGetGetBUSINESSAPPROVALDetail(req)
console.log('data', data)
setProgressDetail(data)
setProgressState(data.BUSINESSAPPROVAL_STATE)
const list = []
if (data.approveList && data.approveList.length > 0) {
const length: number = data.approveList.length
data.approveList.forEach((item: any, index: number) => {
if (index + 1 < length) {
item.status = 'process'
}
if (item.APPLYAPPROVE_TYPE === 3000) {
item.status = 'error'
}
list.push(item)
})
// const list: any = []
// data.approveList.forEach((item: any)=>{
// list.push({title: item.APPLYAPPROVE_NAME,subTitle: item.APPLYAPPROVE_DATE, status: 'finish',description: item.APPLYAPPROVE_INFO})
// })
}
list.push({
status: 'wait',
APPLYAPPROVE_NAME: data.BUSINESSAPPROVAL_NAME || '',
APPLYAPPROVE_INFO: '',
STAFF_NAME: '',
APPLYAPPROVE_DATE: '',
})
console.log('list', list)
setProgressList(list)
}
// 外面表格的请求数据的方法
const handleGetTableData = async (id?: any, SHOPROYALTY_ID?: any) => {
if (!id) {
return
}
setTableLoading(true)
const req = {
BUSINESSPROJECT_ID: id,
SHOPROYALTY_ID
}
const data = await handleGetTableMonthlyReconciliation(req)
let res: any = {}
let list: any = []
let otherMessage: any = {}
if (data.List && data.List.length > 0) {
res = data.List[0]
setTableAllData(res)
if (data.List[0].ProjectPeriodList) {
otherMessage = data.List[0].ProjectPeriodList.node
const resObj: any = data.List[0].ProjectPeriodList
if (resObj.children && resObj.children.length > 0) {
list = wrapTreeNode(resObj.children)
}
}
}
list.unshift({
PeriodIndexStr: '',
PeriodDesc: '合计',
MinturnOver: otherMessage?.MinturnOver,
GuaranteeRatio: otherMessage?.GuaranteeRatio,
CashAmount: otherMessage?.CashAmount,
MobilePayAmount: otherMessage?.MobilePayAmount,
RevenueAmount: otherMessage?.RevenueAmount,
RoyaltyAmount: otherMessage?.RoyaltyAmount,
GuaranteeFee: otherMessage?.GuaranteeFee,
PropertyFee: otherMessage?.PropertyFee,
HouseRent: otherMessage?.HouseRent,
BreachPenalty: otherMessage?.BreachPenalty,
ElectricityCharge: otherMessage?.ElectricityCharge,
WaterCharge: otherMessage?.WaterCharge,
OtherFee: otherMessage?.OtherFee,
ReceivableAmount: otherMessage?.ReceivableAmount,
RefundSupplement: otherMessage?.RefundSupplement,
})
console.log('list', list)
setReqDetailListDetail(list)
setOtherData({
...data.OtherData,
Dates: `${moment(data.OtherData.PROJECT_STARTDATE).format('YYYY/MM/DD')}-${moment(data.OtherData.PROJECT_ENDDATE).format('YYYY/MM/DD')}`
})
// setOtherData({
// SPREGIONTYPE_NAME: res?.SpregionType_Name,
// SERVERPART_NAME: res?.ServerPart_Name,
// SERVERPARTSHOP_NAME: res?.ServerPartShop_Name,
// MERCHANTS_NAME: res?.Merchants_Name,
// Dates: res?.Dates,
// })
setTableLoading(false)
}
return (
<div ref={(el) => {
// 打印报表
if (!reqDetailList || reqDetailList.length === 0) return;
setPrintOut(el);
}} >
<div style={{ backgroundColor: '#fff', display: 'flex' }}>
{/* <ProCard
style={{width:!collapsible ? "300px" : "60px"}}
className="pageTable-leftnav"
bodyStyle={{padding: 0, paddingTop: 20, paddingLeft: 20,width:!collapsible ? "300px" : "60px"}}
extra={<MenuFoldOutlined onClick={() => {
setCollapsible(!collapsible)
}}/>}
colSpan={!collapsible ? "300px" : "60px"}
title={!collapsible ? "请选择服务区" : ""}
headerBordered
collapsed={collapsible}
>
{treeView && treeView.length > 0 ? <Tree
checkable
treeData={[{
label: '全部',
value: 0,
key: '0-0',
children: treeView
}]}
fieldNames={{
title: "label",
key: "key"
}}
blockNode
defaultExpandedKeys={['0-0']}
onCheck={(checkedKeys: React.Key[] | any, info) => {
const selectedIds = info.checkedNodes.filter(n => n?.type === 1)
setSelectedId(selectedIds.map(n => n?.value)?.toString() || '')
// actionRef?.current?.reload()
// getData(selectedIds.map(n => n?.value)?.toString() || '')
}}
// switcherIcon={<PlusOutlined />}
/> : ''}
</ProCard> */}
<div style={{
width: '100%',
paddingTop: 0,
paddingBottom: 0,
paddingRight: 0
}}>
<ProTable
actionRef={actionRef}
formRef={formRef}
columns={columns}
bordered
headerTitle={'对账审批列表'}
search={{ span: 6 }}
request={async (params) => {
// if (!selectedId){
// return
// }
const req: any = {
SearchParameter: {
// BusinessProcess_Name: params.BusinessProcess_Name,
BusinessProcess_StateSearch: params.BusinessProcess_State || '',
Operation_Type: 11,
PendState: 2
},
keyWord: params.BusinessProcess_Name ? {
key: "BusinessProcess_Name",
value: params.BusinessProcess_Name
} : '',
SortStr: "BusinessProcess_StartDate desc",
pageindex: 1,
pagesize: 999999
}
const data = await handleGetMonthAccountProinst(req)
console.log('data', data)
if (data && data.length > 0) {
data.forEach((item: any) => {
item.BusinessProcess_States = item.BusinessProcess_State
})
return { data, success: true }
}
return { data: [], success: true }
}}
/>
</div>
</div>
<Drawer
width="80%"
zIndex={20}
visible={showDeatilDrawer} // 抽屉弹框是否显示状态
onClose={() => { // 关闭抽屉 则在清空选中行数据 并 设置抽屉状态为关闭
setCurrentRow(undefined);
setShowDetailDrawer(false);
setOtherData(undefined)
setProgressState(0)
setProgressList([])
}}
destroyOnClose
bodyStyle={{ backgroundColor: "#fff", padding: 0 }}
closable={false}
>
<PageContainer
loading={detailLoading}
header={{
title: currentRow?.BusinessProcess_Name,
breadcrumb: {},
}}
content={
<>
<ProjectDetailDrawer id={currentRow?.BusinessProcess_ID} shopName={currentRow?.SERVERPARTSHOP_NAME ? currentRow?.SERVERPARTSHOP_NAME.split(',')[0] : ''} />
</>
}
>
{
progressState !== 1000 ?
<Card title="流程进度" bordered style={{ marginBottom: '12px' }}>
<div className={'processBox'}>
<Steps
// type={'navigation'}
size="small"
current={progressList && progressList.length ? progressList.length : 0}
// progressDot
className="site-navigation-steps"
>
<Step status={'process'} title="发起申请" description={<div>
<Tooltip title={`${progressDetail?.STAFF_NAME || ''}${progressDetail?.BUSINESSAPPROVAL_DESC}`}>
<p>{`${progressDetail?.BUSINESS_STARTDATE}`}</p>
</Tooltip>
</div>} />
{
progressList && progressList.length > 0 ?
progressList.map((item: any, index: number) => {
return <Step status={item.status} title={item.APPLYAPPROVE_NAME} description={item.APPLYAPPROVE_INFO ? <div>
<Tooltip title={`${item.STAFF_NAME || ''}${item.APPLYAPPROVE_INFO}`}>
<p>{`${item.APPLYAPPROVE_DATE || ''}`}</p>
</Tooltip>
</div> : ''} />
// index+1===progressState && progressState!==6?'审批中':''}
}) : ''
}
</Steps>
</div>
</Card> : ''
}
<ProTable
rowKey={(record) => {
return `${record?.SHOPROYALTY_ID}-${record?.PeriodIndexStr}-${record?.PeriodDesc}`
}}
actionRef={actionDetailRef}
formRef={formDetailRef}
columns={detailColumns}
bordered
search={false}
loading={tableLoading}
request={async (params: any) => {
handleGetTableData()
}}
scroll={{ x: 1800 }}
headerTitle={`合作商户合同期结算明细表`} // 列表表头
dataSource={reqDetailListDetail}
pagination={false}
tableExtraRender={() => {
return <div style={{ paddingLeft: 24, background: '#fff' }} className={'showTableExtraRender'}>
<ProDescriptions column={8} className="commity-sale-description" labelStyle={{ color: "#00000073" }}>
<ProDescriptions.Item span={1} label="片区">
<Tooltip title={otherData?.SPREGIONTYPE_NAME}>
{otherData?.SPREGIONTYPE_NAME}
</Tooltip>
</ProDescriptions.Item>
<ProDescriptions.Item span={1} label="服务区">
<Tooltip title={otherData?.SERVERPART_NAME}>
{otherData?.SERVERPART_NAME}
</Tooltip>
</ProDescriptions.Item>
<ProDescriptions.Item span={2} label="门店名称">
<Tooltip title={otherData?.SERVERPARTSHOP_NAME}>
{otherData?.SERVERPARTSHOP_NAME}
</Tooltip>
</ProDescriptions.Item>
<ProDescriptions.Item span={2} label="合作单位名称">
<Tooltip title={otherData?.MERCHANTS_NAME}>
{otherData?.MERCHANTS_NAME}
</Tooltip></ProDescriptions.Item>
<ProDescriptions.Item span={2} label="合同期">
<Tooltip title={otherData?.Dates}>
{otherData?.Dates}
</Tooltip></ProDescriptions.Item>
</ProDescriptions>
</div>
}}
>
</ProTable>
</PageContainer>
</Drawer>
{/* 查看项目详情 右侧弹出的抽屉 */}
<Drawer
width="80%"
zIndex={21}
className="project-drawer"
visible={showDetail} // 抽屉弹框是否显示状态
onClose={() => { // 关闭抽屉 则在清空选中行数据 并 设置抽屉状态为关闭
setDetailCurrentRow(undefined);
setShowDetail(false);
}}
bodyStyle={{ backgroundColor: "#f9f9f9", padding: 0 }}
closable={false}
>
{/* 抽屉打开时 加载项目详情组件 */}
{showDetail && <RevenueList BusinessProjectId={detailCurrentRow.BusinessProject_Id} propsBP={otherData} propsRC={tableAllData}
ShopRoyaltyId={detailCurrentRow?.ShopRoyalty_Id ? detailCurrentRow?.ShopRoyalty_Id : 0}
ShopIds={detailCurrentRow?.ServerPartShop_Id ? detailCurrentRow?.ServerPartShop_Id : ''}
StartDate={moment(detailCurrentRow?.StartDate).format('YYYY-MM-DD')}
EndDate={moment(detailCurrentRow?.EndDate).format('YYYY-MM-DD')}></RevenueList>}
</Drawer>
</div>
)
}
export default connect(({ user }: ConnectState) => ({
currentUser: user.currentUser
}))(examineList);