diff --git a/src/pages/examine/record/components/printStyle.css b/src/pages/examine/record/components/printStyle.css new file mode 100644 index 0000000..ad05641 --- /dev/null +++ b/src/pages/examine/record/components/printStyle.css @@ -0,0 +1,56 @@ +/* 打印样式 */ +@media print { + + /* 隐藏不需要打印的元素 */ + .ant-pro-card-header, + .ant-pro-table-search, + .ant-pro-table-list-toolbar, + .ant-pagination, + .ant-btn, + .ant-pro-table-list-toolbar-container { + display: none !important; + } + + /* 调整表格样式 */ + table { + width: 100%; + border-collapse: collapse; + } + + th, + td { + border: 1px solid #000; + padding: 8px; + text-align: left; + } + + /* 页面设置 */ + @page { + margin: 1cm; + } + + /* 确保内容不会被截断 */ + .print-wrapper { + overflow: visible !important; + } + + /* 处理分页 */ + .page-break { + page-break-after: always; + } + + /* 表格标题样式 */ + .print-title { + font-size: 18px; + font-weight: bold; + text-align: center; + margin-bottom: 20px; + } + + /* 页眉页脚样式 */ + .print-header, + .print-footer { + margin: 20px 0; + white-space: pre-wrap; + } +} \ No newline at end of file diff --git a/src/pages/examine/record/components/recordDetail.tsx b/src/pages/examine/record/components/recordDetail.tsx index b2c3612..478e800 100644 --- a/src/pages/examine/record/components/recordDetail.tsx +++ b/src/pages/examine/record/components/recordDetail.tsx @@ -1,12 +1,14 @@ import { ConnectState } from "@/models/global"; import { ActionType, ProTable } from "@ant-design/pro-components"; import ProForm, { FormInstance, ProFormList, ProFormText } from "@ant-design/pro-form"; -import { Col, Row, Image, Button } from "antd"; +import { Col, Row, Image, Button, Input, Modal } from "antd"; import moment from "moment"; import { useEffect, useRef, useState } from "react"; import { connect } from "umi"; import { handleGetExamineTypeTreeList } from "../../index/service"; import session from "@/utils/session"; +import { TextAreaRef } from "antd/lib/input/TextArea"; +import './printStyle.css'; type DetailProps = { @@ -19,8 +21,43 @@ const RecordDetail = ({ parentRow, show }: DetailProps) => { const actionRef = useRef(); const tableFormRef = useRef(); + // 表格数据 + const [proTableData, setTableData] = useState([]) const [formRes, setFormRes] = useState() + // 打印相关状态 + const [printModalVisible, setPrintModalVisible] = useState(false) + const [headerContent, setHeaderContent] = useState('') + const [footerContent, setFooterContent] = useState('') + const headerRef = useRef(null) + const footerRef = useRef(null) + + const columns: any = [ + { + title: "考核分类", + dataIndex: "" + }, + { + title: "考核子类", + dataIndex: "title", + render: (_, record) => { + return record?.question.title ? record?.question.title : "" + } + }, + { + title: "考核结果", + dataIndex: "title", + render: (_, record) => { + let str: string = '' + if (record.choiceResponse && record?.choiceResponse.length > 0) { + record.choiceResponse.forEach((item: any, index: number) => { + str += `${index > 0 ? ',' : ''}答案${index + 1}:${item}` + }) + } + return str || "" + } + } + ] useEffect(() => { if (show) { @@ -40,6 +77,302 @@ const RecordDetail = ({ parentRow, show }: DetailProps) => { } }, [show]) + // 递归 只有当没有子集的时候 才会把问题的数组 到question 数组中 + const handeGetTableData = async (resList: any, options: any) => { + // resList 需要判断是否有子集的数组 + if (resList && resList.length > 0) { + resList.forEach((item: any) => { + if (item.children && item.children.length > 0) { + handeGetTableData(item.children, options) + } else { + if (options && options.length > 0) { + options.forEach((optionItem: any) => { + if (optionItem.question.categoryId === item.id) { + if (item.question && item.question.length > 0) { + item.question.push(optionItem) + } else { + item.question = [optionItem] + } + } + }) + } + } + }) + } + return resList + } + + // 把需要打印的数组拿到一层中来 + const handleGetTableRes = (list: any) => { + let res: any = []; + if (list && list.length > 0) { + list.forEach((item: any) => { + if (item.question && item.question.length > 0) { + // 如果当前项有question字段且不为空,将其添加到结果数组 + item.question.forEach((questionItem: any) => { + res.push(questionItem); + }); + } + if (item.children && item.children.length > 0) { + // 如果有子项,递归处理子项并合并结果 + const childResults = handleGetTableRes(item.children); + if (childResults && childResults.length > 0) { + res = [...res, ...childResults]; + } + } + }); + } + return res; + } + + // 处理表格数据,为合并单元格做准备 + const processTableDataForMerge = (data: any[]) => { + if (!data || data.length === 0) return []; + + // 深拷贝数据,避免修改原始数据 + const processedData = JSON.parse(JSON.stringify(data)); + + // 添加分类信息 + processedData.forEach((item: any) => { + // 从categoryId获取分类名称 + if (item.question && item.question.categoryId) { + // 这里需要根据实际情况获取分类名称 + // 可以从缓存或其他地方获取 + const categoryInfo = getCategoryInfo(item.question.categoryId); + item.categoryName = categoryInfo?.name || ''; + item.parentCategoryName = categoryInfo?.parentName || ''; + } + }); + + // 计算合并信息 + let currentCategory = ''; + let currentSubCategory = ''; + let categorySpan = 0; + let subCategorySpan = 0; + + processedData.forEach((item: any, index: number) => { + // 处理考核分类合并 + if (item.parentCategoryName === currentCategory) { + categorySpan++; + item._categoryMerged = true; // 标记为已合并 + } else { + // 更新前一个分类的合并信息 + if (categorySpan > 0 && index > 0) { + processedData[index - categorySpan]._categoryRowSpan = categorySpan + 1; + } + currentCategory = item.parentCategoryName; + categorySpan = 0; + item._categoryRowSpan = 1; // 默认占一行 + } + + // 处理考核子类合并 + if (item.categoryName === currentSubCategory) { + subCategorySpan++; + item._subCategoryMerged = true; // 标记为已合并 + } else { + // 更新前一个子类的合并信息 + if (subCategorySpan > 0 && index > 0) { + processedData[index - subCategorySpan]._subCategoryRowSpan = subCategorySpan + 1; + } + currentSubCategory = item.categoryName; + subCategorySpan = 0; + item._subCategoryRowSpan = 1; // 默认占一行 + } + }); + + // 处理最后一组数据的合并信息 + if (categorySpan > 0 && processedData.length > 0) { + const targetIndex = processedData.length - categorySpan - 1; + if (targetIndex >= 0 && targetIndex < processedData.length && processedData[targetIndex]) { + processedData[targetIndex]._categoryRowSpan = categorySpan + 1; + } + } + if (subCategorySpan > 0 && processedData.length > 0) { + const targetIndex = processedData.length - subCategorySpan - 1; + if (targetIndex >= 0 && targetIndex < processedData.length && processedData[targetIndex]) { + processedData[targetIndex]._subCategoryRowSpan = subCategorySpan + 1; + } + } + + return processedData; + }; + + // 获取分类信息的辅助函数 + const getCategoryInfo = (categoryId: number) => { + // 这里需要根据实际情况实现 + // 可以从缓存或其他地方获取分类信息 + // 示例实现 + const categoriesTypeObj = session.get('categoriesTypeObj') || {}; + const categoriesIdObj = session.get('categoriesIdObj') || {}; + + let parentName = ''; + let name = ''; + + // 查找父分类 + for (let key in categoriesIdObj) { + const list = categoriesIdObj[key]; + if (list && list.length > 0 && list.indexOf(Number(categoryId)) !== -1) { + parentName = categoriesTypeObj[key] || ''; + break; + } + } + + // 获取当前分类名称 + name = categoriesTypeObj[categoryId] || ''; + + return { name, parentName }; + }; + + // 打印表格方法 + const handlePrintTable = () => { + // 创建打印内容 + const printWindow = window.open('', '_blank'); + if (!printWindow) { + Modal.error({ title: '打印失败', content: '无法创建打印窗口,请检查浏览器设置。' }); + return; + } + + // 获取表格数据 + const tableData = proTableData || []; + + // 构建HTML内容 + let printContent = ` + + + 考核记录打印 + + + + `; + + // 添加自定义页眉 + if (headerContent) { + printContent += ``; + } + + // 添加基本信息 + printContent += ` +
+
服务区名称: ${formRes?.serverPartName || ''}
+
站点名称: ${formRes?.placeName || ''}
+
巡查内容: ${formRes?.uploadResult || ''}
+
巡查人员: ${formRes?.userName || ''}
+
巡查时间: ${formRes?.submittedAt || ''}
+
+ `; + + // 添加图片信息 + if (formRes?.imgsList && formRes.imgsList.length > 0) { + printContent += ` +
+
附件列表:
+
+ `; + + formRes.imgsList.forEach((item: string) => { + printContent += `
`; + }); + + printContent += ` +
+
+ `; + } + + // 添加表格 + printContent += ` + + + + + + + + + + `; + + // 添加表格数据行 + tableData.forEach((record: any) => { + printContent += ''; + + // 考核分类列 - 处理合并单元格 + if (record._categoryMerged) { + // 如果已合并,不显示单元格 + } else { + printContent += ``; + } + + // 考核子类列 - 处理合并单元格 + if (record._subCategoryMerged) { + // 如果已合并,不显示单元格 + } else { + printContent += ``; + } + + // 考核结果列 + let resultStr = ''; + if (record.choiceResponse && record.choiceResponse.length > 0) { + record.choiceResponse.forEach((item: any, index: number) => { + resultStr += `${index > 0 ? ',' : ''}答案${index + 1}:${item}`; + }); + } + printContent += ``; + + printContent += ''; + }); + + printContent += ` + +
考核分类考核子类考核结果
1 ? `rowspan="${record._categoryRowSpan}"` : ''}>${record.parentCategoryName || ''} 1 ? `rowspan="${record._subCategoryRowSpan}"` : ''}>${record.question?.title || ''}${resultStr || ''}
+ `; + + // 添加自定义页脚 + if (footerContent) { + printContent += ``; + } + + // 添加打印按钮 + printContent += ` +
+ + +
+ `; + + printContent += ` + + + `; + + // 写入打印窗口并打印 + printWindow.document.open(); + printWindow.document.write(printContent); + printWindow.document.close(); + + // 等待图片加载完成后打印 + setTimeout(() => { + printWindow.focus(); + // 自动打印可以取消注释下面的代码 + // printWindow.print(); + }, 500); + + }; + return (
{ actionRef={actionRef} formRef={tableFormRef} search={false} + columns={columns} toolbar={{ actions: [ @@ -143,6 +478,19 @@ const RecordDetail = ({ parentRow, show }: DetailProps) => { }) } + let tableData = await handeGetTableData(typeData, res) + console.log('tableData', tableData); + // 拿到整个数据之后 递归取出tableData中有 question 数据的那一层数据变为一个数组 + let tableRes = await handleGetTableRes(tableData) + console.log('tableRes', tableRes); + + // 处理表格数据,为合并单元格做准备 + let processedData = processTableDataForMerge(tableRes); + setTableData(processedData) + if (processedData && processedData.length > 0) { + return { data: processedData, success: true } + } + return [] // let categoriesObj: any = {} // 子父级关系的缓存对象 @@ -198,11 +546,42 @@ const RecordDetail = ({ parentRow, show }: DetailProps) => { }} /> + { + handlePrintTable(); + setPrintModalVisible(false); + }} + onCancel={() => setPrintModalVisible(false)} + width={600} + > +
+
页眉内容(可选):
+ setHeaderContent(e.target.value)} + placeholder="请输入要在打印页面顶部显示的内容" + /> +
+
+
页脚内容(可选):
+ setFooterContent(e.target.value)} + placeholder="请输入要在打印页面底部显示的内容" + /> +
+
+
) } - export default connect(({ user }: ConnectState) => ({ currentUser: user.data }))(RecordDetail); diff --git a/src/services/user.ts b/src/services/user.ts index baa3110..9750d37 100644 --- a/src/services/user.ts +++ b/src/services/user.ts @@ -32,7 +32,7 @@ export async function retrieveUserAuthority(params: any) { //获取菜单数据 export async function retrieveMenuData(params: any) { - const data = await request.get('/menus', params) + // const data = await request.get('/menus', params) // return data return [ {