ylj20011123 debd5be7f6 update
2025-08-28 18:50:55 +08:00

508 lines
27 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 { Drawer } from "antd";
import { Button, message, Space, Spin, Tree } from "antd";
import useRequest from "@ahooksjs/use-request";
import { getFieldEnum, getServerpartTree } from "@/services/options";
import type { ActionType } from "@ant-design/pro-table";
import ProTable from "@ant-design/pro-table";
import ReactHTMLTableToExcel from "react-html-table-to-excel";
import { handleGetServerPartShopNewList, handleSynchroServerPartShopNew } from "./service";
import session from "@/utils/session";
import moment from 'moment'
import Detail from "./component/detail";
import PageTitleBox from "@/components/PageTitleBox";
const serviceArea: React.FC<{ currentUser: CurrentUser }> = (props) => {
const { currentUser } = props
const downloadBtnRef = useRef<any>()
const detailChildrenRef = useRef<any>()
const actionRef = useRef<ActionType>();
const formRef = useRef<FormInstance>();
const [reqDetailList, setReqDetailList] = useState<any>(); // 合计项数据源
const [printOut, setPrintOut] = useState<any>(); // 打印数据的内容
const [collapsible, setCollapsible] = useState<boolean>(false)
const [treeView, setTreeView] = useState<any>()
const [printIndex, setPrintIndex] = useState<number>(new Date().getTime())
// 加载服务区树
const { loading: treeLoading, data: treeViews } = useRequest(async () => {
const data = await getServerpartTree(currentUser?.ProvinceCode, currentUser?.CityAuthority, true, true, true)
setTreeView(data)
return data
})
const businessTypeObj = session.get('BUSINESSTYPEObj')
const businessStateObj = session.get('businessStateObj')
// 树相关的属性和方法
const [selectedId, setSelectedId] = useState<string>()
// 导出的加载效果
const [showLoading, setShowLoading] = useState<boolean>(false)
// 是否显示打印的表格
const [showExportTable, setShowExportTable] = useState<boolean>(false)
// 显示添加和编辑的抽屉
const [showDetailDrawer, setShowDetailDrawer] = useState<boolean>(false)
// 点击行的数据
const [currentRow, setCurrentRow] = useState<any>()
// 抽屉的类型 编辑还是新增
const [drawerType, setDrawerType] = useState<string>('')
// 新增和编辑的保存的loading效果
const [btnLoading, setBtnLoading] = useState<boolean>(false)
const columns: any = [
{
title: '商品业态',
width: 120,
align: 'center',
dataIndex: 'SHOPTRADE',
hideInSearch: true,
valueType: 'select',
request: async () => {
return await getFieldEnum({ FieldExplainField: 'BUSINESSTYPE', sessionName: 'BUSINESSTYPE', notformate: true });
},
},
{
title: '经营品牌',
width: 120,
align: 'center',
dataIndex: 'BRAND_NAME',
hideInSearch: true,
},
{
title: '服务区名称',
width: 150,
align: 'center',
ellipsis: true,
dataIndex: 'SERVERPART_NAME',
hideInSearch: true,
},
{
title: <div style={{ textAlign: 'center' }}></div>,
width: 300,
dataIndex: 'SHOPNAME',
align: 'left',
ellipsis: true,
hideInSearch: true,
render: (_, record) => {
return <a onClick={() => {
console.log('record', record);
setDrawerType('edit')
setCurrentRow(record)
setShowDetailDrawer(true)
}}>{record?.SHOPNAME || ''}</a>
}
},
{
width: 150,
title: '停业时间',
align: 'center',
dataIndex: 'BUSINESS_ENDDATE',
hideInSearch: true,
render: (_, record) => {
return record?.BUSINESS_ENDDATE ? moment(record?.BUSINESS_ENDDATE).format('YYYY-MM-DD') : '-'
}
},
{
width: 150,
title: '经营模式',
align: 'center',
dataIndex: 'BUSINESS_TYPE',
valueType: 'select',
valueEnum: businessTypeObj
},
{
width: 150,
title: '经营状态',
dataIndex: 'BUSINESS_STATE',
valueType: 'select',
align: 'center',
valueEnum: businessStateObj,
render: (_, record) => {
return <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<div style={{ display: 'flex', justifyContent: 'flex-start', alignItems: 'center', marginRight: '12px' }}>
<span className={record?.BUSINESS_STATE === 1000 ? 'ant-badge-status-dot ant-badge-status-processing' :
record?.BUSINESS_STATE === 1010 ? 'ant-badge-status-dot ant-badge-status-default' :
record?.BUSINESS_STATE === 2000 ? 'ant-badge-status-dot ant-badge-status-warning' :
record?.BUSINESS_STATE === 3000 ? 'ant-badge-status-dot ant-badge-status-error'
: ''}></span>
</div>
<span>{record?.BUSINESS_STATE ? businessStateObj[record?.BUSINESS_STATE] : ''}</span>
</div>
}
},
{
width: 150,
title: '经营单位',
dataIndex: 'BUSINESS_UNIT',
align: 'center',
hideInSearch: true,
},
]
const exportTable = (e) => {
e.stopPropagation(); // 防止Collapse组件收起
const main = document.getElementsByClassName(`saleReportHideBox${printIndex}`)[0]
const thead = main.querySelector('thead').cloneNode(true); // 深克隆DOM节点
const tbody = main.querySelector('tbody').cloneNode(true); // 深克隆DOM节点
const container = document.querySelector('#hiddenBox');
const tempTable = document.createElement('table');
tempTable.appendChild(thead);
tempTable.appendChild(tbody);
tempTable.setAttribute('id', 'table-to-xls-serviceArea'); // 给table添加id值与按钮上的table字段对应
container.appendChild(tempTable); // 把创建的节点添加到页面容器中
setShowLoading(false)
downloadBtnRef.current.handleDownload();
setShowExportTable(false)
tempTable.remove() // 防止重复打印一个内容
}
// 查询的条件
const [searchParams, setSearchParams] = useState<any>()
return (
<div ref={(el) => {
// 打印报表
if (!reqDetailList || reqDetailList.length === 0) return;
setPrintOut(el);
}} >
{
showLoading ?
<div
style={{
width: '100%',
height: '100%',
background: 'rgba(0,0,0,0.1)',
position: 'fixed',
zIndex: 5,
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}}
>
<div style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
padding: '15px 20px 10px',
background: '#fff',
borderRadius: '8px',
width: '200px'
}}>
<Spin />
<span style={{ marginLeft: '5px' }}>...</span>
</div>
</div> : ''
}
<div className={`saleReportHideBox${printIndex}`} style={{ position: 'fixed', zIndex: -1, top: 0, left: 0 }}>
{
showExportTable && reqDetailList && reqDetailList.length > 0 ?
<ProTable
columns={columns}
dataSource={reqDetailList}
pagination={false}
expandable={{
defaultExpandAllRows: true
}}
/> : ''
}
</div>
<div id='hiddenBox' style={{ position: 'fixed', zIndex: -1, top: 0, left: 0 }} />
<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: !collapsible ? 'calc(100% - 300px)' : 'calc(100% - 60px)',
paddingTop: 0,
paddingBottom: 0,
paddingRight: 0
}}>
<ProTable
actionRef={actionRef}
formRef={formRef}
columns={columns}
bordered
expandable={{
expandRowByClick: true
}}
headerTitle={<PageTitleBox props={props} />}
search={{ span: 6 }}
request={async (params) => {
if (!selectedId) {
return
}
setSearchParams(params)
console.log('params', params);
const req: any = {
serverPartId: selectedId || '',
businessState: params?.BUSINESS_STATE || '',
businessType: params?.BUSINESS_TYPE || ''
}
console.log('req', req);
const data = await handleGetServerPartShopNewList(req)
console.log('data', data);
if (data && data.length > 0) {
return { data, success: true }
}
return { data: [], success: true }
}}
toolbar={{
actions: [
<span style={{ visibility: 'hidden' }}>
<ReactHTMLTableToExcel
buttonText={'导出excel'}
ref={downloadBtnRef}
table="table-to-xls-serviceArea"
filename={`单品销售排行统计${searchParams?.StartDate}-${searchParams?.EndDate}`}
sheet="sheet1"
/>
</span>,
<Button
key="new"
type="primary"
onClick={(e) => {
if (reqDetailList && reqDetailList.length > 0) {
setShowLoading(true)
setTimeout(() => {
setShowExportTable(true)
setTimeout(() => {
exportTable(e)
}, 100)
}, 100)
} else {
message.error('暂无数据可导出!')
}
}}
>
excel
</Button>,
<Button type={"primary"} onClick={() => {
setShowDetailDrawer(true)
}}>
</Button>
]
}}
/>
</div>
</div>
<Drawer
width="60%"
visible={showDetailDrawer} // 抽屉弹框是否显示状态
onClose={() => { // 关闭抽屉 则在清空选中行数据 并 设置抽屉状态为关闭
setDrawerType('')
setCurrentRow(undefined)
setShowDetailDrawer(false)
}}
bodyStyle={{ backgroundColor: "#f9f9f9", padding: 0 }}
closable={false}
destroyOnClose
footer={
<div style={{ width: '100%', display: 'flex', alignItems: 'center', justifyContent: 'flex-end', boxSizing: 'border-box', paddingRight: '16px' }}>
<Button loading={btnLoading} type='primary' onClick={() => {
detailChildrenRef?.current.formRef.current?.validateFields().then((res: any) => {
if (res) {
detailChildrenRef?.current.formSecondRef.current?.validateFields().then(async (result: any) => {
if (result) {
let req: any = {}
setBtnLoading(true)
if (drawerType === 'edit') {
console.log('detailChildrenRef', detailChildrenRef);
// 不是两个数据的数据
// 查到的详情数据 然后表格数据 顶掉查的相同字段的数据
const formDetail: any = detailChildrenRef?.current.formRef?.current.getFieldsValue()
const oldDetail: any = detailChildrenRef?.current.detailData?.ServerPartShop
const topDetail: any = {
...oldDetail,
...formDetail,
}
const selectType: number = detailChildrenRef?.current.radioValue
topDetail.BUSINESS_REGION = selectType === 2 ? 1000 : selectType === 1 ? 1010 : selectType === 4 ? 2000 : selectType === 3 ? 2010 : null
topDetail.BUSINESS_DATE = topDetail?.BUSINESS_DATE ? moment(topDetail?.BUSINESS_DATE).format('YYYY-MM-DD') : ''
topDetail.BUSINESS_ENDDATE = topDetail?.BUSINESS_ENDDATE ? moment(topDetail?.BUSINESS_ENDDATE).format('YYYY-MM-DD') : ''
console.log('topDetail', topDetail);
// 底部表格数据
const bottomTableData = detailChildrenRef?.current.tableData
// 中间表格数据
const midOldFormDataList: any = detailChildrenRef?.current.detailData.ShopBusinessStateList
const midFormData: any = detailChildrenRef?.current.formSecondRef?.current.getFieldsValue()
console.log('detailChildrenRef?.current.detailData', detailChildrenRef?.current.detailData);
console.log('中间的表格数据', midFormData);
const list: any = []
if (midOldFormDataList && midOldFormDataList.length > 0) {
midOldFormDataList.forEach((item: any, index: number) => {
if (index === 0) {
item.ShopRegion = midFormData.ShopRegion
item.ShopName = midFormData.ShopName
item.BusinessType = midFormData.BusinessType
item.BusinessState = midFormData.BusinessState
item.BusinessDate = midFormData.BusinessDate ? moment(midFormData.BusinessDate).format('YYYY-MM-DD') : ''
item.BusinessEndDate = midFormData.BusinessEndDate ? moment(midFormData.BusinessEndDate).format('YYYY-MM-DD') : ''
list.push(item)
} else if (index === 1) {
item.ShopRegion = midFormData.ShopRegionSecond
item.ShopName = midFormData.SHOPNAMESecond
item.BusinessType = midFormData.BUSINESS_TYPESecond
item.BusinessState = midFormData.BUSINESS_STATESecond
item.BusinessDate = midFormData.BusinessDateSecond ? moment(midFormData.BusinessDateSecond).format('YYYY-MM-DD') : ''
item.BusinessEndDate = midFormData.BusinessEndDateSecond ? moment(midFormData.BusinessEndDateSecond).format('YYYY-MM-DD') : ''
list.push(item)
}
})
}
req = {
ServerPartShop: {
...topDetail,
STAFF_ID: currentUser?.ID,
STAFF_NAME: currentUser?.Name,
OPERATE_DATE: moment().format('YYYY-MM-DD HH:mm:ss')
},
ShopBusinessStateList: list,
RtServerPartShopList: bottomTableData && bottomTableData.length > 0 ? bottomTableData : []
}
} else {
const formDetail: any = detailChildrenRef?.current.formRef?.current.getFieldsValue()
const selectType: number = detailChildrenRef?.current.radioValue
const topDetail: any = {
ISVALID: 1,
...formDetail,
}
topDetail.BUSINESS_REGION = selectType === 2 ? 1000 : selectType === 1 ? 1010 : selectType === 4 ? 2000 : selectType === 3 ? 2010 : null
const list: any = []
const midFormData: any = detailChildrenRef?.current.formSecondRef?.current.getFieldsValue()
if (selectType === 2 || selectType === 4) {
list.push(
{
ShopRegion: midFormData.ShopRegion,
ShopName: midFormData.ShopName,
BusinessType: midFormData.BusinessType,
BusinessState: midFormData.BusinessState,
BusinessDate: midFormData.BusinessDate ? moment(midFormData.BusinessDate).format('YYYY-MM-DD') : '',
BusinessEndDate: midFormData.BusinessEndDate ? moment(midFormData.BusinessEndDate).format('YYYY-MM-DD') : '',
}
)
list.push(
{
ShopRegion: midFormData.ShopRegionSecond,
ShopName: midFormData.SHOPNAMESecond,
BusinessType: midFormData.BUSINESS_TYPESecond,
BusinessState: midFormData.BUSINESS_STATESecond,
BusinessDate: midFormData.BusinessDateSecond ? moment(midFormData.BusinessDateSecond).format('YYYY-MM-DD') : '',
BusinessEndDate: midFormData.BusinessEndDateSecond ? moment(midFormData.BusinessEndDateSecond).format('YYYY-MM-DD') : '',
}
)
} else {
list.push(
{
ShopRegion: midFormData.ShopRegion,
ShopName: midFormData.ShopName,
BusinessType: midFormData.BusinessType,
BusinessState: midFormData.BusinessState,
BusinessDate: midFormData.BusinessDate ? moment(midFormData.BusinessDate).format('YYYY-MM-DD') : '',
BusinessEndDate: midFormData.BusinessEndDate ? moment(midFormData.BusinessEndDate).format('YYYY-MM-DD') : '',
}
)
}
console.log('reqListdsds', list);
req = {
ServerPartShop: {
...topDetail,
STAFF_ID: currentUser?.ID,
STAFF_NAME: currentUser?.Name,
OPERATE_DATE: moment().format('YYYY-MM-DD HH:mm:ss')
},
ShopBusinessStateList: list,
RtServerPartShopList: []
}
}
console.log('req', req);
const data = await handleSynchroServerPartShopNew(req)
console.log('data', data);
if (data.Result_Code === 100) {
message.success(data.Result_Desc)
// 关闭抽屉带的执行方法
setDrawerType('')
setCurrentRow(undefined)
setShowDetailDrawer(false)
actionRef.current?.reload()
} else {
message.error(data.Result_Desc)
}
setBtnLoading(false)
}
})
}
})
}}>{drawerType === 'edit' ? '保存' : '新增'}</Button>
</div>
}
>
<Detail onRef={detailChildrenRef} currentRow={currentRow} type={drawerType} showDrawer={showDetailDrawer} closeDrawer={setShowDetailDrawer} />
</Drawer>
</div>
)
}
export default connect(({ user }: ConnectState) => ({
currentUser: user.currentUser
}))(serviceArea);