💥 feat(模块): 添加了个很棒的功能

This commit is contained in:
ylj20011123 2025-05-06 19:41:01 +08:00
parent 3dfe0c92c8
commit 03ba594601
7 changed files with 333 additions and 259 deletions

View File

@ -0,0 +1,51 @@
import React, { useEffect, useState } from 'react';
import { Outlet, useLocation, useOutlet, connect } from 'umi';
interface CacheItem {
outlet: React.ReactNode;
pathname: string;
}
// 创建一个缓存路由组件,用于保持路由组件的状态
const KeepAliveOutlet: React.FC<{ global: any }> = (props) => {
const [cacheOutlets, setCacheOutlets] = useState<CacheItem[]>([]);
const location = useLocation();
const { pathname } = location;
const currentOutlet = useOutlet();
const { tabsRoutes = [] } = props.global || {};
// 获取当前打开的所有标签页路径
const activePaths = tabsRoutes.map((tab: any) => tab.path);
// 使用字符串比较来避免不必要的重渲染
const activePathsString = JSON.stringify(activePaths);
useEffect(() => {
// 如果当前路径已经在缓存中,则不需要再次添加
if (!cacheOutlets.find(item => item.pathname === pathname)) {
setCacheOutlets(prev => [...prev, { outlet: currentOutlet, pathname }]);
}
}, [pathname, currentOutlet]);
// 单独处理缓存清理逻辑,避免不必要的重渲染
useEffect(() => {
// 清理已关闭标签页的缓存
if (cacheOutlets.length > 0) {
setCacheOutlets(prev => prev.filter(item => activePaths.includes(item.pathname)));
}
}, [activePathsString]);
return (
<>
{cacheOutlets.map(item => (
<div key={item.pathname} style={{ display: pathname === item.pathname ? 'block' : 'none' }}>
{item.outlet}
</div>
))}
</>
);
};
export default connect(({ global }: { global: any }) => ({
global,
}))(KeepAliveOutlet);

View File

@ -4,6 +4,7 @@ import { useState, useEffect } from 'react';
import { Dropdown, Layout, Menu, Tabs, Tooltip } from 'antd';
import type { MenuProps } from 'antd';
import { Outlet, Link, useLocation, connect, history } from 'umi';
import KeepAliveOutlet from '@/components/KeepAliveOutlet';
import PageAccess from '@/components/PageAccess';
import type { UserConnectedProps, UserModelState } from '@/models/user';
import LayoutWrapper from '@/components/LayoutWrapper';
@ -367,6 +368,7 @@ const BasicLayout: FC<{ user: UserModelState, global: ProfileModelState, dispatc
onEdit={handleEdit}
size="small"
className='main-tab'
destroyInactiveTabPane={false} // 不销毁不活动的标签页面板,保持状态
tabBarExtraContent={
<Tooltip title="关闭选项卡" placement="topRight">
<Dropdown overlay={
@ -412,13 +414,17 @@ const BasicLayout: FC<{ user: UserModelState, global: ProfileModelState, dispatc
{tabsRoutes && tabsRoutes.map((item: any) =>
<TabPane
tab={item.title} key={item?.path}
style={{ padding: 24, paddingTop: 0 }}>
style={{ padding: 24, paddingTop: 0 }}
forceRender={true} /* 强制渲染标签页内容,即使不可见也保持渲染状态 */
>
{
//统一对所有有效路由做页面鉴权的处理
validMenuItem
? (
<PageAccess>
<Outlet />
<div key={item?.path} style={{ display: activeKey === item?.path ? 'block' : 'none' }}>
<KeepAliveOutlet />
</div>
</PageAccess>
)
: <Page404 />

View File

@ -260,14 +260,14 @@ const ErrorRecord: React.FC<{ currentUser: any }> = (props) => {
}
<Popconfirm
{/* <Popconfirm
title={"确认删除?"}
onConfirm={async () => {
deleteRecord(record?.id)
}}
>
<a></a>
</Popconfirm>
</Popconfirm> */}
</Space >
}

View File

@ -230,14 +230,14 @@ const examineModal: React.FC<{ currentUser: any }> = (props) => {
setCurrentRow(record)
handleShowDetail(true)
}}></a> */}
<Popconfirm
{/* <Popconfirm
title={"确认删除?"}
onConfirm={async () => {
deleteQuestion(record?.id)
}}
>
<a></a>
</Popconfirm>
</Popconfirm> */}
<a onClick={() => {
console.log('currentRow', record);
setCurrentRow(record)

View File

@ -612,7 +612,7 @@ const RecordDetail = ({ parentRow, show, detailType, currentUser, onRef, showErr
request={async () => {
const req = {
SERVERPART_ID: formRes.serverPartId,
PROVINCE_CODE: currentUser.provinceCode,
PROVINCE_CODE: currentUser.provinceCode || '510000',
}
const data = await handleGetDealerList(req)
console.log('data', data)
@ -727,127 +727,132 @@ const RecordDetail = ({ parentRow, show, detailType, currentUser, onRef, showErr
</ProForm> : ""
}
<ProTable
actionRef={actionRef}
formRef={tableFormRef}
search={false}
columns={columns}
bordered
toolbar={{
actions: [
<Button type="primary" onClick={(e) => {
handlePrintTable()
}}>
</Button>
]
}}
scroll={{ x: "100%", y: 'calc(100vh - 300px)' }}
pagination={false}
options={false}
request={async () => {
let res = detailType === 'modal' ? parentRow?.questionnaireTemplateQuestions
|| [] : parentRow?.questionResponses || []
console.log('parentRow', parentRow);
console.log('res', res);
{
formRes && formRes.situation === 1 ?
<ProTable
actionRef={actionRef}
formRef={tableFormRef}
search={false}
columns={columns}
bordered
toolbar={{
actions: [
<Button type="primary" onClick={(e) => {
handlePrintTable()
}}>
</Button>
]
}}
scroll={{ x: "100%", y: 'calc(100vh - 300px)' }}
pagination={false}
options={false}
request={async () => {
let res = detailType === 'modal' ? parentRow?.questionnaireTemplateQuestions
|| [] : parentRow?.questionResponses || []
console.log('parentRow', parentRow);
console.log('res', res);
let obj: any = {}
let typeData = await handleGetExamineTypeTreeList({})
console.log('typeData', typeData);
if (typeData && typeData.length > 0) {
typeData.forEach((item: any) => {
obj[item.id] = item.name
if (item.children && item.children.length > 0) {
item.children.forEach((subItem: any) => {
obj[subItem.id] = subItem.name
let obj: any = {}
let typeData = await handleGetExamineTypeTreeList({})
console.log('typeData', typeData);
if (typeData && typeData.length > 0) {
typeData.forEach((item: any) => {
obj[item.id] = item.name
if (item.children && item.children.length > 0) {
item.children.forEach((subItem: any) => {
obj[subItem.id] = subItem.name
})
}
})
}
})
}
setExamineObj(obj)
let tableData = await handeGetTableData(typeData, res)
// 拿到整个数据之后 递归取出tableData中有 question 数据的那一层数据变为一个数组
let tableRes = await handleGetTableRes(tableData, obj)
console.log('tableRes', tableRes);
setExamineObj(obj)
let tableData = await handeGetTableData(typeData, res)
// 拿到整个数据之后 递归取出tableData中有 question 数据的那一层数据变为一个数组
let tableRes = await handleGetTableRes(tableData, obj)
console.log('tableRes', tableRes);
let newTableRes: any = []
if (tableRes && tableRes.length > 0) {
tableRes.forEach((item: any) => {
if (item.score === 0) {
newTableRes.push(item)
let newTableRes: any = []
if (tableRes && tableRes.length > 0) {
tableRes.forEach((item: any) => {
if (item.score === 0) {
newTableRes.push(item)
}
})
}
})
}
// 显示的
// 处理表格数据,为合并单元格做准备
let processedData = processTableDataForMerge(newTableRes);
// 显示的
// 处理表格数据,为合并单元格做准备
let processedData = processTableDataForMerge(newTableRes);
// 打印的
let printData = processTableDataForMerge(tableRes)
// 打印的
let printData = processTableDataForMerge(tableRes)
setTableData(processedData)
setPrintTableData(printData)
setTableData(processedData)
setPrintTableData(printData)
if (processedData && processedData.length > 0) {
return { data: processedData, success: true }
}
return []
if (processedData && processedData.length > 0) {
return { data: processedData, success: true }
}
return []
// let categoriesObj: any = {} // 子父级关系的缓存对象
// let categoriesTypeObj: any = {} // 类型的对象
// let categoriesObj: any = {} // 子父级关系的缓存对象
// let categoriesTypeObj: any = {} // 类型的对象
// let categoriesIdObj = session.get('categoriesIdObj')
// let categoriesTypeSessionObj = session.get('categoriesTypeObj')
// let categoriesIdObj = session.get('categoriesIdObj')
// let categoriesTypeSessionObj = session.get('categoriesTypeObj')
// if (categoriesIdObj) {
// categoriesObj = categoriesIdObj
// categoriesTypeObj = categoriesTypeSessionObj
// } else {
// let typeData = await handleGetExamineTypeTreeList({})
// // 走动式的大类包括小类的缓存 categoriesIdObj
// if (typeData && typeData.length > 0) {
// typeData.forEach((item: any) => {
// let list: any = []
// categoriesTypeObj[item.id] = item.name
// if (item.children && item.children.length > 0) {
// item.children.forEach((subItem: any) => {
// list.push(subItem.id)
// categoriesTypeObj[subItem.id] = item.name
// })
// }
// categoriesObj[item.id] = list
// })
// }
// if (categoriesIdObj) {
// categoriesObj = categoriesIdObj
// categoriesTypeObj = categoriesTypeSessionObj
// } else {
// let typeData = await handleGetExamineTypeTreeList({})
// // 走动式的大类包括小类的缓存 categoriesIdObj
// if (typeData && typeData.length > 0) {
// typeData.forEach((item: any) => {
// let list: any = []
// categoriesTypeObj[item.id] = item.name
// if (item.children && item.children.length > 0) {
// item.children.forEach((subItem: any) => {
// list.push(subItem.id)
// categoriesTypeObj[subItem.id] = item.name
// })
// }
// categoriesObj[item.id] = list
// })
// }
// session.set('categoriesIdObj', categoriesObj)
// session.set('categoriesTypeObj', categoriesTypeObj)
// }
// session.set('categoriesIdObj', categoriesObj)
// session.set('categoriesTypeObj', categoriesTypeObj)
// }
// console.log('categoriesObj', categoriesObj);
// console.log('categoriesTypeObj', categoriesTypeObj);
// console.log('categoriesObj', categoriesObj);
// console.log('categoriesTypeObj', categoriesTypeObj);
// let res = parentRow?.questionResponses || []
// // 在res的数组里面拿到最大一个类型的数据
// if (res && res.length > 0) {
// res.forEach((item: any) => {
// for (let key in categoriesObj) {
// let list = categoriesObj[key]
// if (list && list.length > 0) {
// if (list.indexOf(Number(item.question.categoryId)) !== -1) {
// item.parentCategoryId = key
// }
// }
// }
// let res = parentRow?.questionResponses || []
// // 在res的数组里面拿到最大一个类型的数据
// if (res && res.length > 0) {
// res.forEach((item: any) => {
// for (let key in categoriesObj) {
// let list = categoriesObj[key]
// if (list && list.length > 0) {
// if (list.indexOf(Number(item.question.categoryId)) !== -1) {
// item.parentCategoryId = key
// }
// }
// }
// })
// }
// console.log('table', res);
}}
/> : ""
}
// })
// }
// console.log('table', res);
}}
/>
{/* 移除打印设置弹窗 */}

View File

@ -122,6 +122,43 @@ const examineRecord: React.FC<{ currentUser: any }> = (props) => {
return <span style={{ color: record.situation === 1 ? "red" : "" }}>{record.situation === 1 ? '异常' : record.situation === 0 ? '正常' : ''}</span>
}
},
{
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 record?.situation !== 0 ? <span style={{ color: record.errorStatus === 0 ? "red" : record.errorStatus === 1 ? "#1677ff" : "" }}>{
record.errorStatus === 0
? "待处理"
: record.errorStatus === 1
? "处理中"
: record.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 = record.imgsList
return imgList && imgList.length > 0 ?
<Button type="primary" onClick={() => {
setShowImgList(imgList)
setImagePreviewVisible(true)
}}></Button> : "-"
}
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: "uploadResult",
@ -182,43 +219,6 @@ const examineRecord: React.FC<{ currentUser: any }> = (props) => {
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 record?.situation !== 0 ? <span style={{ color: record.errorStatus === 0 ? "red" : record.errorStatus === 1 ? "#1677ff" : "" }}>{
record.errorStatus === 0
? "待处理"
: record.errorStatus === 1
? "处理中"
: record.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 = record.imgsList
return imgList && imgList.length > 0 ?
<Button type="primary" onClick={() => {
setShowImgList(imgList)
setImagePreviewVisible(true)
}}></Button> : "-"
}
},
{
title: '操作',
dataIndex: 'option',
@ -248,16 +248,14 @@ const examineRecord: React.FC<{ currentUser: any }> = (props) => {
}}>
</a >
}
<Popconfirm
{/* <Popconfirm
title={"确认删除?"}
onConfirm={async () => {
deleteRecord(record?.id)
}}
>
<a></a>
</Popconfirm>
</Popconfirm> */}
</Space >
}

View File

@ -86,14 +86,14 @@ const recordSummary: React.FC<{ currentUser: any }> = (props) => {
width: 150,
ellipsis: true,
render: (_, record) => {
return record?.id && record?.inspectionNumber > 0 ? <span>
return record?.id && record?.inspectionNumber > 0 && record?.type !== 'servicePart' && record?.type !== 'district' ? <span>
<a style={{ color: record?.inspectionNumber === record?.allDay ? '' : 'red' }} onClick={() => {
setCurrentRow(record)
setShowType(1)
// setShowType(1)
setShowDetail(true)
}}>
{record?.inspectionNumber || '-'}
</a> / {record?.allDay}
{record?.inspectionNumber || '-'} / {record?.allDay}
</a>
</span > : record?.allDay ? <span>
<span style={{ color: record?.inspectionNumber === record?.allDay ? '' : 'red' }}>{record?.inspectionNumber || '-'} </span>
<span>/ {record?.allDay}</span>
@ -101,14 +101,14 @@ const recordSummary: React.FC<{ currentUser: any }> = (props) => {
}
},
{
title: <div style={{ textAlign: 'center' }}></div>,
title: <div style={{ textAlign: 'center' }}>(%)</div>,
dataIndex: "inspectionRate",
align: 'center',
hideInSearch: true,
width: 150,
ellipsis: true,
render: (_, record) => {
return record?.inspectionRate ? record?.inspectionRate * 100 + '%' : ""
return record?.inspectionRate ? (record?.inspectionRate * 100).toFixed(2) : ""
}
},
{
@ -119,13 +119,17 @@ const recordSummary: React.FC<{ currentUser: any }> = (props) => {
width: 150,
ellipsis: true,
render: (_, record) => {
return record?.template && record?.template.id && record?.normalNumber > 0 ? <a onClick={() => {
setCurrentRow(record)
setShowType(2)
setShowDetail(true)
}}>
{record?.normalNumber || '-'}
</a> : <span>{record?.normalNumber || '-'}</span>
return record?.template && record?.template.id && record?.normalNumber > 0 ?
<span>{record?.normalNumber || '-'}</span> : ""
// <a onClick={() => {
// setCurrentRow(record)
// setShowType(2)
// setShowDetail(true)
// }}>
// {record?.normalNumber || '-'}
// </a> : ''
// <span>{record?.normalNumber || '-'}</span>
}
},
{
@ -136,13 +140,16 @@ const recordSummary: React.FC<{ currentUser: any }> = (props) => {
width: 150,
ellipsis: true,
render: (_, record) => {
return record?.template && record?.template.id && record?.errorNumber > 0 ? <a onClick={() => {
setCurrentRow(record)
setShowType(3)
setShowDetail(true)
}}>
{record?.errorNumber || '-'}
</a> : ""
return record?.template && record?.template.id && record?.errorNumber > 0 ?
<span>{record?.errorNumber || '-'}</span> : ""
// <a onClick={() => {
// setCurrentRow(record)
// setShowType(3)
// setShowDetail(true)
// }}>
// {record?.errorNumber || '-'}
// </a> : ""
// <span>{record?.errorNumber || '-'}</span>
}
},
@ -171,13 +178,15 @@ const recordSummary: React.FC<{ currentUser: any }> = (props) => {
width: 150,
ellipsis: true,
render: (_, record) => {
return record?.template ? record?.template.errorStatus01 > 0 ? <a onClick={() => {
setCurrentRow(record)
setShowType(5)
setShowDetail(true)
}}>
{record?.template.errorStatus01 || '-'}
</a> : <span>{record?.template.errorStatus01 || '-'}</span> : ""
return record?.template && record?.template.errorStatus01 > 0 ?
<span>{record?.template.errorStatus01 || '-'}</span> : ""
// <a onClick={() => {
// setCurrentRow(record)
// setShowType(5)
// setShowDetail(true)
// }}>
// {record?.template.errorStatus01 || '-'}
// </a> : <span>{record?.template.errorStatus01 || '-'}</span> : ""
}
},
// {
@ -211,29 +220,29 @@ const recordSummary: React.FC<{ currentUser: any }> = (props) => {
// }
// }
{
title: <div style={{ textAlign: 'center' }}></div>,
title: <div style={{ textAlign: 'center' }}>(%)</div>,
dataIndex: "unfinishedRate",
align: 'center',
hideInSearch: true,
width: 150,
ellipsis: true,
render: (_, record) => {
return record?.template && record?.template.unfinishedRate ? <span>{record?.template.unfinishedRate * 100}%</span> : "-"
return record?.template && record?.template.unfinishedRate ? <span>{(record?.template.unfinishedRate * 100).toFixed(2)}</span> : "-"
}
}
]
const drawerColumns: any = [
// {
// title: "巡查类型",
// dataIndex: "inspectionType",
// hideInTable: true,
// valueType: "select",
// valueEnum: {
// "1": '异常',
// "0": "正常"
// }
// },
{
title: "巡查类型",
dataIndex: "inspectionType",
hideInTable: true,
valueType: "select",
valueEnum: {
"1": '异常',
"0": "正常"
}
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: "createdAt",
@ -291,6 +300,21 @@ const recordSummary: React.FC<{ currentUser: any }> = (props) => {
}</a> : ""
}
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: "placeName",
hideInSearch: true,
width: 150,
ellipsis: true,
align: 'center',
render: (_, record) => {
return record.imgsList && record.imgsList.length > 0 ?
<Button type="primary" onClick={() => {
setShowImgList(record.imgsList)
setImagePreviewVisible(true)
}}></Button> : "-"
}
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: "uploadResult",
@ -343,21 +367,7 @@ const recordSummary: React.FC<{ currentUser: any }> = (props) => {
ellipsis: true,
align: 'center',
},
{
title: <div style={{ textAlign: 'center' }}></div>,
dataIndex: "placeName",
hideInSearch: true,
width: 150,
ellipsis: true,
align: 'center',
render: (_, record) => {
return record.imgsList && record.imgsList.length > 0 ?
<Button type="primary" onClick={() => {
setShowImgList(record.imgsList)
setImagePreviewVisible(true)
}}></Button> : "-"
}
}
]
@ -542,7 +552,7 @@ const recordSummary: React.FC<{ currentUser: any }> = (props) => {
thirdItem.processingNumber = thirdItem.template.errorStatus1
thirdItem.processedNumber = thirdItem.template.errorStatus2
normalNumberSum += thirdItem.template.situation0
normalNumberSum = allDay
errorNumberSum += thirdItem.template.situation1
pendingProcessNumberSum += thirdItem.pendingProcessNumber
processingNumberSum += thirdItem.processingNumber
@ -560,7 +570,7 @@ const recordSummary: React.FC<{ currentUser: any }> = (props) => {
bigSuccessSum += Number(subItem.inspectionRate)
inspectionNumberItemSum += subItem.inspectionNumber
normalNumberItemSum += subItem.normalNumber
normalNumberItemSum = allDay
errorNumberItemSum += subItem.errorNumber
pendingProcessNumberItemSum += subItem.pendingProcessNumber
processingNumberItemSum += subItem.processingNumber
@ -651,9 +661,6 @@ const recordSummary: React.FC<{ currentUser: any }> = (props) => {
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?.serverPartId) {
return
}
@ -665,59 +672,66 @@ const recordSummary: React.FC<{ currentUser: any }> = (props) => {
serverPartIds: [currentRow?.serverPartId],
startTime: searchParams?.startTime ? `${searchParams?.startTime}` : "",
endTime: searchParams?.endTime ? `${searchParams?.endTime}` : "",
extend: showType === 1 ? [
{
key: "templateId",
value: currentRow?.template.id,
}
] : showType === 2 ? [
extend: params?.inspectionType ? [
{
key: "situation",
value: 0,
},
{
key: "templateId",
value: currentRow?.template.id,
value: params?.inspectionType
}
] : showType === 3 ? [
{
key: "situation",
value: 1,
},
{
key: "templateId",
value: currentRow?.template.id,
}
] : showType === 4 ? [
{
key: "errorStatus",
value: 0,
},
{
key: "templateId",
value: currentRow?.template.id,
}
] :
showType === 5 ? [
{
key: "errorStatus01",
value: 1,
},
{
key: "templateId",
value: currentRow?.template.id,
}
] :
showType === 6 ? [
{
key: "errorStatus",
value: 2,
},
{
key: "templateId",
value: currentRow?.template.id,
}
] : undefined
] : undefined
// showType === 1 ? [
// {
// key: "templateId",
// value: currentRow?.template.id,
// }
// ] : showType === 2 ? [
// {
// key: "situation",
// value: 0,
// },
// {
// key: "templateId",
// value: currentRow?.template.id,
// }
// ] : showType === 3 ? [
// {
// key: "situation",
// value: 1,
// },
// {
// key: "templateId",
// value: currentRow?.template.id,
// }
// ] : showType === 4 ? [
// {
// key: "errorStatus",
// value: 0,
// },
// {
// key: "templateId",
// value: currentRow?.template.id,
// }
// ] :
// showType === 5 ? [
// {
// key: "errorStatus01",
// value: 1,
// },
// {
// key: "templateId",
// value: currentRow?.template.id,
// }
// ] :
// showType === 6 ? [
// {
// key: "errorStatus",
// value: 2,
// },
// {
// key: "templateId",
// value: currentRow?.template.id,
// }
// ] : undefined
}
console.log('req', req);
const data = await handleNewSummaryList(req)