2025-04-21 19:05:23 +08:00

674 lines
31 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 { ConnectState } from "@/models/global";
import { ActionType, FormInstance, ProTable } from "@ant-design/pro-components";
import { useRef, useState } from "react";
import { connect } from "umi";
import moment from "moment";
import { Button, Drawer, Image, message, Popconfirm, Space } from "antd";
import LeftSelectTree from "@/components/leftSelectTree/leftSelectTree";
import { handleGetRecordTreeList, handleGetResponsesSummary } from "../record/service";
const recordSummary: React.FC<{ currentUser: any }> = (props) => {
const { currentUser } = props
const actionRef = useRef<ActionType>();
const formRef = useRef<FormInstance>();
const drawerActionRef = useRef<ActionType>();
const drawerFormRef = useRef<FormInstance>();
const recordDetailRef = useRef<any>()
// 显示的附件数据
const [showImgList, setShowImgList] = useState<string[]>([])
// 预览图片
const [imagePreviewVisible, setImagePreviewVisible] = useState<boolean>(false)
// 预览的索引
const [previewIndex, setPreviewIndex] = useState<number>(0)
// 当行数据
const [currentRow, setCurrentRow] = useState<any>()
// 显示详情抽屉
const [showDetail, setShowDetail] = useState<boolean>(false)
// 显示类型 1 巡查次数 2 正常 3 异常 4 待处理 5 处理中 6 已处理
const [showType, setShowType] = useState<number>(0)
// 外侧表格的搜索条件
const [searchParams, setSearchParams] = useState<any>()
// 判断是否点了出现的是异常处理的抽屉
const [showAbnormal, setShowAbnormal] = useState<boolean>(false)
// 树相关的属性和方法
const [selectedId, setSelectedId] = useState<string[]>()
const [columnsStateMap, setColumnsStateMap] = useState<any>({
score: { show: false }
})
const [collapsible, setCollapsible] = useState<boolean>(false)
const columns: any = [
{
title: "统计日期",
dataIndex: "staticDate",
hideInTable: true,
valueType: "dateRange",
initialValue: [moment().startOf('M'), moment()],
search: {
transform: (value: any) => {
return {
startTime: moment(value[0]).startOf('m').format('YYYY-MM-DD'),
endTime: moment(value[1]).format('YYYY-MM-DD')
};
},
},
fieldProps: {
picker: "day",
format: 'YYYY-MM-DD',
}
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: "serverPartName",
hideInSearch: true,
width: 200,
ellipsis: true,
render: (_, record) => {
return record?.type === 'district' || record?.type === 'servicePart' ? record?.name :
record?.template ? record?.template.title : "-"
}
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: "inspectionNumber",
align: 'center',
hideInSearch: true,
width: 150,
ellipsis: true,
render: (_, record) => {
return record?.template?.id && record?.inspectionNumber > 0 ? <span>
<a style={{ color: record?.inspectionNumber === record?.allDay ? '' : 'red' }} onClick={() => {
setCurrentRow(record)
setShowType(1)
setShowDetail(true)
}}>
{record?.inspectionNumber || '-'}
</a> / {record?.allDay}
</span > : <span><span style={{ color: record?.inspectionNumber === record?.allDay ? '' : 'red' }}>{record?.inspectionNumber || '-'} </span><span>/ {record?.allDay}</span></span>
}
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: "inspectionRate",
align: 'center',
hideInSearch: true,
width: 150,
ellipsis: true,
render: (_, record) => {
return record?.allDay ?
<span style={{ color: record?.inspectionNumber === record?.allDay ? '' : 'red' }}>
{((record?.inspectionNumber / record?.allDay) * 100).toFixed(2) + '%'}
</span> : ''
}
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: "normalNumber",
align: 'center',
hideInSearch: true,
width: 150,
ellipsis: true,
render: (_, record) => {
return record?.template?.id && record?.normalNumber > 0 ? <a onClick={() => {
setCurrentRow(record)
setShowType(2)
setShowDetail(true)
}}>
{record?.normalNumber || '-'}
</a> : <span>{record?.normalNumber || '-'}</span>
}
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: "errorNumber",
align: 'center',
hideInSearch: true,
width: 150,
ellipsis: true,
render: (_, record) => {
return record?.template?.id && record?.errorNumber > 0 ? <a onClick={() => {
setCurrentRow(record)
setShowType(3)
setShowDetail(true)
}}>
{record?.errorNumber || '-'}
</a> : <span>{record?.errorNumber || '-'}</span>
}
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: "pendingProcessNumber",
align: 'center',
hideInSearch: true,
width: 150,
ellipsis: true,
render: (_, record) => {
return record?.template?.id && record?.pendingProcessNumber > 0 ? <a onClick={() => {
setCurrentRow(record)
setShowType(4)
setShowDetail(true)
}}>
{record?.pendingProcessNumber || '-'}
</a> : <span>{record?.pendingProcessNumber || '-'}</span>
}
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: "processingNumber",
align: 'center',
hideInSearch: true,
width: 150,
ellipsis: true,
render: (_, record) => {
return record?.template?.id && record?.processingNumber > 0 ? <a onClick={() => {
setCurrentRow(record)
setShowType(5)
setShowDetail(true)
}}>
{record?.processingNumber || '-'}
</a> : <span>{record?.processingNumber || '-'}</span>
}
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: "processedNumber",
align: 'center',
hideInSearch: true,
width: 150,
ellipsis: true,
render: (_, record) => {
return record?.template?.id && record?.processedNumber > 0 ? <a onClick={() => {
setCurrentRow(record)
setShowType(6)
setShowDetail(true)
}}>
{record?.processedNumber || '-'}
</a> : <span>{record?.processedNumber || '-'}</span>
}
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: "processedRate",
align: 'center',
hideInSearch: true,
width: 150,
ellipsis: true,
render: (_, record) => {
return record?.errorNumber ? <span style={{ color: record?.processedNumber === record?.errorNumber ? '' : 'red' }}>
{((record?.processedNumber / record?.errorNumber) * 100).toFixed(2)}%
</span> : ""
}
}
]
const drawerColumns: any = [
// {
// title: "巡查类型",
// dataIndex: "inspectionType",
// hideInTable: true,
// valueType: "select",
// valueEnum: {
// "1": '异常',
// "0": "正常"
// }
// },
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: "createdAt",
hideInSearch: true,
width: 150,
ellipsis: true,
fixed: 'left',
align: 'center',
render: (_, record) => {
return record?.createdAt ? moment(record?.createdAt).format('YYYY-MM-DD HH:mm:ss') : '-'
}
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: "serverPartName",
hideInSearch: true,
width: 200,
ellipsis: true,
render: (_, record) => {
return record?.type === 'district' || record?.type === 'servicePart' ? record?.name :
record?.template ? record?.template.title : "-"
}
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: "placeName",
hideInSearch: true,
width: 100,
align: 'center',
ellipsis: true,
render: (_, record) => {
let res: any = record.extend ? JSON.parse(record.extend) : "-"
return <span style={{ color: res.situation === 1 ? "red" : "" }}>{res.situation === 1 ? '异常' : res.situation === 0 ? '正常' : ''}</span>
}
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: "uploadResult",
hideInSearch: true,
width: 200,
ellipsis: true,
render: (_, record) => {
let extendObj = record?.extend ? JSON.parse(record?.extend) : ""
return extendObj?.uploadResult ? extendObj?.uploadResult : "-"
}
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: "uploadResult",
hideInSearch: true,
width: 350,
ellipsis: true,
render: (_, record) => {
let str: string = ''
if (record?.questionResponses && record?.questionResponses.length > 0) {
record?.questionResponses.forEach((item: any, index: number) => {
let anwers: string = ''
if (item.choiceResponse && item.choiceResponse.length > 0) {
item.choiceResponse.forEach((subItem: string, subIndex: number) => {
anwers += `${subIndex > 0 ? '' : ''}${subItem}`
})
}
str += `${index > 0 ? '' : ''}考核内容:${item.question.title},考核结果:${anwers}`
})
}
return str || ''
}
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: "score",
hideInSearch: true,
valueType: 'digit',
width: 100,
align: 'center',
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: "userName",
hideInSearch: true,
width: 100,
ellipsis: true,
align: 'center',
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: "errorStatus",
hideInSearch: true,
width: 100,
ellipsis: true,
align: 'center',
render: (_, record) => {
let res: any = record.extend ? JSON.parse(record.extend) : "-"
return <span style={{ color: res.errorStatus === 0 ? "red" : res.errorStatus === 1 ? "#1677ff" : "" }}>{
res.errorStatus === 0
? "待处理"
: res.errorStatus === 1
? "处理中"
: res.errorStatus === 2
? "已处理"
: "-"
}</span>
}
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: "placeName",
hideInSearch: true,
width: 150,
ellipsis: true,
align: 'center',
render: (_, record) => {
let extendObj = record?.extend ? JSON.parse(record?.extend) : ""
let imgList = extendObj.imgsList
return imgList && imgList.length > 0 ?
<Button type="primary" onClick={() => {
setShowImgList(imgList)
setImagePreviewVisible(true)
}}></Button> : "-"
}
}
]
return (
<div style={{ backgroundColor: '#fff', display: 'flex' }}>
<LeftSelectTree setSelectedId={setSelectedId} setCollapsible={setCollapsible} collapsible={collapsible} currentUser={currentUser} />
<div style={{
width: !collapsible ? 'calc(100% - 300px)' : 'calc(100% - 60px)',
// width: "100%",
paddingTop: 0,
paddingBottom: 0,
paddingRight: 0
}}>
<ProTable
actionRef={actionRef}
formRef={formRef}
columns={columns}
bordered
expandable={{
expandRowByClick: true,
defaultExpandAllRows: true
}}
rowKey={(record) => {
return `${record?.id}-${record?.code}`
}}
scroll={{ x: "100%", y: 'calc(100vh - 400px)' }}
headerTitle={<span style={{ color: "#1890ff", fontSize: 14, fontWeight: 600 }}></span>}
search={{ span: 6 }}
request={async (params) => {
if (!(selectedId && selectedId.length > 0)) {
return
}
const req: any = {
serverPartIds: selectedId && selectedId.length > 0 ? selectedId : [],
startTime: params?.startTime ? `${params?.startTime}` : "",
endTime: params?.endTime ? `${params?.endTime}` : "",
// serverPartId: params?.serverPartId ? params?.serverPartId : undefined,
extend: params?.inspectionType ? [{
key: "situation",
value: params?.inspectionType
}] : undefined
}
let allDay: number = moment(params?.endTime).diff(params?.startTime, 'd') + 1
console.log('allDay', allDay);
setSearchParams(params)
console.log('req', req);
// const data = await handleGetRecordTreeList(req)
const data = await handleGetResponsesSummary(req)
console.log('dat3a333', data);
// 处理一下 根据第三层的实际巡查记录 汇总到第二层来
if (data && data.length > 0) {
data.forEach((item: any) => {
if (item.children && item.children.length > 0) {
item.children.forEach((subItem: any) => {
if (subItem.children && subItem.children.length > 0) {
// 点位的id数据 肯定要求不重复的
let templateIdList: number[] = []
// 遍历完之后 要替换的
let newChildren: any = []
// 因为一天时间内 多条记录 需要被计算为一条 那么这里就要加上时间的对象来筛选
let dateObj: any = {}
subItem.children.forEach((thirdItem: any) => {
let extendObj: any = {}
if (thirdItem.extend) {
extendObj = JSON.parse(thirdItem.extend)
}
let oldDateList = dateObj[moment(thirdItem.createdAt).format('YYYY-MM-DD')]
if (!oldDateList || (oldDateList && oldDateList.indexOf(thirdItem.template.id) === -1)) {
// templateIdList 是判断 newChildren 里面已经有几个点位id了
if (templateIdList.indexOf(thirdItem.template.id) === -1) {
templateIdList.push(thirdItem.template.id)
newChildren.push({
template: thirdItem.template,
templateId: thirdItem.template.Id,
inspectionNumber: 1,
normalNumber: extendObj?.situation === 0 ? 1 : 0,
errorNumber: extendObj?.situation === 1 ? 1 : 0,
pendingProcessNumber: extendObj?.errorStatus === 0 ? 1 : 0,
processingNumber: extendObj?.errorStatus === 1 ? 1 : 0,
processedNumber: extendObj?.errorStatus === 2 ? 1 : 0,
})
} else {
newChildren.forEach((fourthItem: any) => {
if (fourthItem.template.id === thirdItem.template.id) {
fourthItem.inspectionNumber += 1
if (extendObj?.situation === 0) {
fourthItem.normalNumber += 1
} else if (extendObj?.situation === 1) {
fourthItem.errorNumber += 1
}
if (extendObj?.errorStatus === 0) {
fourthItem.pendingProcessNumber += 1
} else if (extendObj?.errorStatus === 1) {
fourthItem.processingNumber += 1
} else if (extendObj?.errorStatus === 2) {
fourthItem.processedNumber += 1
}
}
})
}
if (oldDateList && oldDateList.length > 0) {
oldDateList.push(thirdItem.template.id)
} else {
dateObj[moment(thirdItem.createdAt).format('YYYY-MM-DD')] = [thirdItem.template.id]
}
}
console.log('dateObj', dateObj);
})
subItem.children = newChildren
}
})
}
})
data.forEach((item: any) => {
let inspectionNumberItemSum: number = 0
let normalNumberItemSum: number = 0
let errorNumberItemSum: number = 0
let pendingProcessNumberItemSum: number = 0
let processingNumberItemSum: number = 0
let processedNumberItemSum: number = 0
// 这一次时间段应该查询的次数(天数)
let allItemDaySum: number = 0
if (item.children && item.children.length > 0) {
item.children.forEach((subItem: any) => {
let inspectionNumberSum: number = 0
let normalNumberSum: number = 0
let errorNumberSum: number = 0
let pendingProcessNumberSum: number = 0
let processingNumberSum: number = 0
let processedNumberSum: number = 0
// 这一次时间段应该查询的次数(天数)
let allSubItemDaySum: number = 0
if (subItem.children && subItem.children.length > 0) {
subItem.children.forEach((thirdItem: any) => {
thirdItem.allDay = allDay
allSubItemDaySum += thirdItem.allDay
inspectionNumberSum += thirdItem.inspectionNumber
normalNumberSum += thirdItem.normalNumber
errorNumberSum += thirdItem.errorNumber
pendingProcessNumberSum += thirdItem.pendingProcessNumber
processingNumberSum += thirdItem.processingNumber
processedNumberSum += thirdItem.processedNumber
})
}
subItem.allDay = allSubItemDaySum
subItem.inspectionNumber = inspectionNumberSum
subItem.normalNumber = normalNumberSum
subItem.errorNumber = errorNumberSum
subItem.pendingProcessNumber = pendingProcessNumberSum
subItem.processingNumber = processingNumberSum
subItem.processedNumber = processedNumberSum
inspectionNumberItemSum += subItem.inspectionNumber
normalNumberItemSum += subItem.normalNumber
errorNumberItemSum += subItem.errorNumber
pendingProcessNumberItemSum += subItem.pendingProcessNumber
processingNumberItemSum += subItem.processingNumber
processedNumberItemSum += subItem.processedNumber
allItemDaySum += subItem.allDay
})
item.allDay = allItemDaySum
item.inspectionNumber = inspectionNumberItemSum
item.normalNumber = normalNumberItemSum
item.errorNumber = errorNumberItemSum
item.pendingProcessNumber = pendingProcessNumberItemSum
item.processingNumber = processingNumberItemSum
item.processedNumber = processedNumberItemSum
}
})
}
console.log('resresres', data);
if (data && data.length > 0) {
return { data, success: true }
}
return { data: [], success: true }
}}
toolbar={{
}}
columnsState={{
value: columnsStateMap,
onChange: setColumnsStateMap,
}}
>
</ProTable>
</div>
{
showImgList && showImgList.length > 0 && <div style={{ display: 'none' }}>
<Image.PreviewGroup
preview={{
visible: imagePreviewVisible,
onVisibleChange: vis => {
setImagePreviewVisible(vis)
},
current: previewIndex
}}>
{
showImgList.map((n) =>
<Image src={n} key={n} />
)
}
</Image.PreviewGroup>
</div>
}
<Drawer
title={false}
closeIcon={false}
onClose={() => {
setCurrentRow(undefined)
setShowType(0)
setShowDetail(false)
setShowImgList([])
setImagePreviewVisible(false)
}}
open={showDetail}
destroyOnClose
width={'60%'}
>
<ProTable
actionRef={drawerActionRef}
formRef={drawerFormRef}
columns={drawerColumns}
bordered
expandable={{
expandRowByClick: true,
defaultExpandAllRows: true
}}
rowKey={(record) => {
return `${record?.id}-${record?.code}`
}}
scroll={{ x: "100%", y: 'calc(100vh - 400px)' }}
headerTitle={<span style={{ color: "#1890ff", fontSize: 14, fontWeight: 600 }}></span>}
search={{ span: 6 }}
request={async (params) => {
console.log('searchParams', searchParams);
console.log('currentRow', currentRow);
if (!currentRow?.template?.serverPartId) {
return
}
// showType 1 巡查次数 2 正常 3 异常 4 待处理 5 处理中 6 已处理
const req: any = {
serverPartIds: [currentRow?.template?.serverPartId],
startTime: searchParams?.startTime ? `${searchParams?.startTime}T00:00:00` : "",
endTime: searchParams?.endTime ? `${searchParams?.endTime}T23:59:59` : "",
extend: showType === 1 ? undefined : showType === 2 ? [
{
key: "situation",
value: 0,
},
] : showType === 3 ? [
{
key: "situation",
value: 1,
},
] : showType === 4 ? [
{
key: "errorStatus",
value: 0,
}
] :
showType === 5 ? [
{
key: "errorStatus",
value: 1,
}
] :
showType === 6 ? [
{
key: "errorStatus",
value: 2,
}
] : undefined
}
console.log('req', req);
const data = await handleGetRecordTreeList(req)
console.log('data', data);
if (data && data.length > 0) {
// 最后结果直接输出第三层的数据 好看点
let res: any = []
data.forEach((item: any) => {
if (item.children && item.children.length > 0) {
item.children.forEach((subItem: any) => {
if (subItem.children && subItem.children.length > 0) {
subItem.children.forEach((thirdItem: any) => {
res.push(thirdItem)
})
}
})
}
})
return { data: res, success: true }
}
return { data: [], success: true }
}}
>
</ProTable>
</Drawer>
</div>
)
}
export default connect(({ user }: ConnectState) => ({
currentUser: user.data
}))(recordSummary);