ylj20011123 d3a4c2ad28 update
2025-09-01 18:27:05 +08:00

399 lines
13 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 { Avatar, Button, Menu, message, Space, Spin, Tree } from "antd";
import useRequest from "@ahooksjs/use-request";
import {
getFieldEnum,
getFieldEnumTree,
getFieldEnumTreeNoSession,
getServerpartTree,
handleCallLogs
} 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 SubMenu from "antd/lib/menu/SubMenu";
import moment from "moment/moment";
import { handleGetServerpartShopDDL, handleGetYSABNORMALITYList } from "@/pages/reports/audit/abnormalAmount/service";
import PageTitleBox from "@/components/PageTitleBox";
const abnormalAmount: React.FC<{ currentUser: CurrentUser }> = (props) => {
const { currentUser } = props
const downloadBtnRef = 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 { 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 [showLoading, setShowLoading] = useState<boolean>(false)
// 显示点击服务区 请求门店的加载效果
const [serverpartShopLoading, setServerpartShopLoading] = useState<boolean>(false)
// 是否显示打印的表格
const [showExportTable, setShowExportTable] = useState<boolean>(false)
const [currenMenu, setCurrenMenu] = useState<any>(); // 当前选中左侧菜单的服务区节点
const [defaultValue, setDefaultValue] = useState<any>()
const [serverpartShopObj, setServerpartShopObj] = useState<any>()
const columns: any = [
{
title: '门店',
dataIndex: 'SERVERPARTSHOP_ID',
valueType: 'select',
hideInTable: true,
valueEnum: serverpartShopObj,
fieldProps: {
showSearch: true,
filterOption: (input, option) => (option?.label ?? '').toLowerCase().includes(input.toLowerCase()),
}
},
{
title: '序号',
dataIndex: 'index',
width: 70,
align: 'center',
hideInSearch: true,
valueType: 'index'
},
{
title: <div style={{ textAlign: 'center' }}></div>,
width: 140,
dataIndex: 'SHOPNAME',
hideInSearch: true,
},
{
title: '异常类型',
width: 100,
align: 'center',
dataIndex: 'ABNORMALITY_TYPE',
valueType: 'treeSelect',
request: async () => {
console.log('2')
const data = await getFieldEnumTreeNoSession({ FieldExplainField: 'EXCEPTION_TYPE', FieldEnumPID: 13854, FieldEnumStatus: true });
return data
},
fieldProps: {
treeDefaultExpandAll: true
},
initialValue: defaultValue
},
{
title: '统计时间',
align: 'center',
dataIndex: 'search_date',
valueType: 'dateRange',
hideInTable: true,
hideInDescriptions: true,
colSize: 1,
initialValue: [moment().add(-7, 'day').format('YYYY-MM-DD'), moment().format('YYYY-MM-DD')],
search: {
transform: (value) => {
return {
Start_Date: value[0],
End_Date: value[1],
};
},
},
fieldProps: {
disabledDate: (current: any) => current && current > moment()
}
},
{
title: <div style={{ textAlign: 'center' }}></div>,
align: 'right',
width: 100,
valueType: 'digit',
dataIndex: 'COMMOTITY_COUNT',
hideInSearch: true,
},
{
title: <div style={{ textAlign: 'center' }}></div>,
align: 'right',
width: 100,
valueType: 'digit',
dataIndex: 'TOTALAMOUNT',
hideInSearch: true,
},
{
title: <div style={{ textAlign: 'center' }}></div>,
align: 'center',
width: 150,
dataIndex: 'ABNORMALITY_TIME',
hideInSearch: true,
},
{
title: <div style={{ textAlign: 'center' }}></div>,
width: 200,
dataIndex: 'ABNORMALITY_DESC',
ellipsis: true,
hideInSearch: true,
},
{
title: '服务区',
align: 'center',
width: 140,
dataIndex: 'SERVERPART_NAME',
ellipsis: true,
hideInSearch: true,
},
{
title: '收银机号',
align: 'center',
width: 120,
dataIndex: 'MACHINECODE',
hideInSearch: true,
},
{
title: '收银员',
align: 'center',
width: 100,
dataIndex: 'SELLWORK_NAME',
hideInSearch: true,
},
]
const exportTable = (e) => {
e.stopPropagation(); // 防止Collapse组件收起
const main = document.getElementsByClassName('abnormalExamineHideBox')[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-abnormalAmount'); // 给table添加id值与按钮上的table字段对应
container.appendChild(tempTable); // 把创建的节点添加到页面容器中
setShowLoading(false)
downloadBtnRef.current.handleDownload();
setShowExportTable(false)
tempTable.remove() // 防止重复打印一个内容
}
// 获取门店列表
const handleGetShopList = async (id: any) => {
const req = {
ProvinceCode: currentUser?.ProvinceCode,
ServerpartId: id,
ShowWholePower: true
}
const data = await handleGetServerpartShopDDL(req)
console.log('data', data)
const obj: any = {}
if (data && data.length > 0) {
data.forEach((item: any) => {
obj[item.value] = item.label
})
}
setServerpartShopObj(obj)
}
// 查询的条件
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={'abnormalExamineHideBox'} 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' }}>
{
serverpartShopLoading ?
<div style={{ width: '100%', height: '100%', background: 'rgba(0,0,0,0.1)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<div style={{ display: 'flex', alignItems: 'center', padding: '15px 20px 10px', background: '#fff', borderRadius: '8px' }}>
<Spin />
<span style={{ marginLeft: '5px' }}>...</span>
</div>
</div>
: ''
}
<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)
if (selectedIds.map(n => n?.value)?.toString().indexOf(',') === -1) {
handleGetShopList(selectedIds)
} else {
setServerpartShopObj({})
}
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
headerTitle={<PageTitleBox props={props} />}
scroll={{ x: '100%', y: 'calc(100vh - 430px)' }}
search={{ span: 6 }}
pagination={{ pageSize: 20 }}
request={async (params) => {
console.log('params', params)
if (!selectedId) {
return
}
const req = {
SearchParameter: {
...params,
SERVERPART_IDS: selectedId,
EXCEPTION_TYPE: 3000
},
PageIndex: 1,
PageSize: 999999
}
handleCallLogs()
setSearchParams(params)
const data = await handleGetYSABNORMALITYList(req)
console.log('data', data)
if (data && data.length > 0) {
setReqDetailList(data)
return { data, success: true }
}
return { data: [], success: true }
}}
toolbar={{
actions: [
<span style={{ visibility: 'hidden' }}>
<ReactHTMLTableToExcel
buttonText={'导出excel'}
ref={downloadBtnRef}
table="table-to-xls-abnormalAmount"
filename={`销售金额异常${searchParams?.Start_Date}-${searchParams?.End_Date}`}
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>
]
}}
/>
</div>
</div>
</div>
)
}
export default connect(({ user }: ConnectState) => ({
currentUser: user.currentUser
}))(abnormalAmount);