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

This commit is contained in:
cclu 2025-03-17 19:04:26 +08:00
parent 1d35b458fa
commit 637f0cd1c8
3 changed files with 192 additions and 161 deletions

View File

@ -1,6 +1,5 @@
/* 打印样式 */
@media print {
/* 隐藏不需要打印的元素 */
.ant-pro-card-header,
.ant-pro-table-search,
@ -21,7 +20,7 @@
td {
border: 1px solid #000;
padding: 8px;
text-align: left;
text-align: center;
}
/* 页面设置 */
@ -53,4 +52,21 @@
margin: 20px 0;
white-space: pre-wrap;
}
/* 确保iframe内的打印内容可见 */
iframe {
display: block !important;
visibility: visible !important;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
/* 确保打印内容可见 */
.print-content, .print-content * {
visibility: visible !important;
display: block !important;
}
}

View File

@ -38,7 +38,7 @@ const RecordDetail = ({ parentRow, show, detailType }: DetailProps) => {
const columns: any = [
{
title: "考核分类",
dataIndex: "name"
dataIndex: "parentName"
},
{
title: "考核子类",
@ -121,7 +121,7 @@ const RecordDetail = ({ parentRow, show, detailType }: DetailProps) => {
}
// 把需要打印的数组拿到一层中来
const handleGetTableRes = (list: any) => {
const handleGetTableRes = (list: any, fieldObj?: any) => {
console.log('list', list);
let res: any = [];
@ -132,13 +132,14 @@ const RecordDetail = ({ parentRow, show, detailType }: DetailProps) => {
item.question.forEach((questionItem: any) => {
res.push({
...questionItem,
parentId: item.parentId ? item.parentId : "-"
parentId: item.parentId ? item.parentId : "-",
parentName: fieldObj && item.parentId ? fieldObj[item.parentId] : "-"
});
});
}
if (item.children && item.children.length > 0) {
// 如果有子项,递归处理子项并合并结果
const childResults = handleGetTableRes(item.children);
const childResults = handleGetTableRes(item.children, fieldObj);
if (childResults && childResults.length > 0) {
res = [...res, ...childResults];
}
@ -161,61 +162,100 @@ const RecordDetail = ({ parentRow, show, detailType }: DetailProps) => {
// 从categoryId获取分类名称
if (item.question && item.question.categoryId) {
// 这里需要根据实际情况获取分类名称
// 可以从缓存或其他地方获取
// const categoryInfo = getCategoryInfo(item.question.categoryId);
item.name = examineObj && item.parentId ? examineObj[item.parentId] : ""
item.categoryName = item?.question.title || '';
item.parentCategoryName = item?.name || '';
}
});
// 按照考核分类和考核子类排序,确保相同的分类和子类相邻
processedData.sort((a, b) => {
// 先按考核分类排序
if (a.parentCategoryName !== b.parentCategoryName) {
return a.parentCategoryName.localeCompare(b.parentCategoryName);
}
// 再按考核子类排序
return a.categoryName.localeCompare(b.categoryName);
});
// 计算合并信息
let currentCategory = '';
let currentSubCategory = '';
let categorySpan = 0;
let subCategorySpan = 0;
let categoryStartIndex = 0;
let subCategoryStartIndex = 0;
processedData.forEach((item: any, index: number) => {
// 初始化合并标记
item._categoryMerged = false;
item._subCategoryMerged = false;
// 处理考核分类合并
if (item.parentCategoryName === currentCategory) {
categorySpan++;
item._categoryMerged = true; // 标记为已合并
} else {
// 更新前一个分类的合并信息
if (categorySpan > 0 && index > 0) {
processedData[index - categorySpan]._categoryRowSpan = categorySpan + 1;
if (index === 0 || item.parentCategoryName !== currentCategory) {
// 如果是新的分类,更新前一个分类的合并信息
if (index > 0) {
const span = index - categoryStartIndex;
if (span > 1) { // 只有当跨度大于1时才需要合并
processedData[categoryStartIndex]._categoryRowSpan = span;
// 标记除第一行外的其他行为已合并
for (let i = categoryStartIndex + 1; i < index; i++) {
processedData[i]._categoryMerged = true;
}
}
}
// 记录新分类的开始位置
categoryStartIndex = index;
currentCategory = item.parentCategoryName;
categorySpan = 0;
item._categoryRowSpan = 1; // 默认占一行
// 重置子类信息,因为新的分类开始了
currentSubCategory = '';
subCategoryStartIndex = index;
}
// 处理考核子类合并
if (item.categoryName === currentSubCategory) {
subCategorySpan++;
item._subCategoryMerged = true; // 标记为已合并
} else {
// 更新前一个子类的合并信息
if (subCategorySpan > 0 && index > 0) {
processedData[index - subCategorySpan]._subCategoryRowSpan = subCategorySpan + 1;
if (index === 0 || item.categoryName !== currentSubCategory || item.parentCategoryName !== currentCategory) {
// 如果是新的子类或新的分类,更新前一个子类的合并信息
if (index > 0 && currentSubCategory) {
const span = index - subCategoryStartIndex;
if (span > 1) { // 只有当跨度大于1时才需要合并
processedData[subCategoryStartIndex]._subCategoryRowSpan = span;
// 标记除第一行外的其他行为已合并
for (let i = subCategoryStartIndex + 1; i < index; i++) {
processedData[i]._subCategoryMerged = true;
}
}
}
// 记录新子类的开始位置
subCategoryStartIndex = index;
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;
const lastIndex = processedData.length - 1;
if (lastIndex >= 0) {
// 处理最后一个分类的合并
const categorySpan = lastIndex - categoryStartIndex + 1;
if (categorySpan > 1) {
processedData[categoryStartIndex]._categoryRowSpan = categorySpan;
for (let i = categoryStartIndex + 1; i <= lastIndex; i++) {
processedData[i]._categoryMerged = true;
}
} else {
// 如果只有一行,不需要合并
processedData[categoryStartIndex]._categoryRowSpan = 1;
processedData[categoryStartIndex]._categoryMerged = false;
}
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;
// 处理最后一个子类的合并
const subCategorySpan = lastIndex - subCategoryStartIndex + 1;
if (subCategorySpan > 1) {
processedData[subCategoryStartIndex]._subCategoryRowSpan = subCategorySpan;
for (let i = subCategoryStartIndex + 1; i <= lastIndex; i++) {
processedData[i]._subCategoryMerged = true;
}
} else {
// 如果只有一行,不需要合并
processedData[subCategoryStartIndex]._subCategoryRowSpan = 1;
processedData[subCategoryStartIndex]._subCategoryMerged = false;
}
}
@ -250,73 +290,58 @@ const RecordDetail = ({ parentRow, show, detailType }: DetailProps) => {
// 打印表格方法
const handlePrintTable = () => {
// 创建打印内容
const printWindow = window.open('', '_blank');
if (!printWindow) {
Modal.error({ title: '打印失败', content: '无法创建打印窗口,请检查浏览器设置。' });
return;
}
// 获取表格数据
const tableData = proTableData || [];
// 构建HTML内容
// 创建一个iframe用于打印这样可以避免CSS冲突
const printIframe = document.createElement('iframe');
printIframe.style.position = 'absolute';
printIframe.style.width = '0';
printIframe.style.height = '0';
printIframe.style.border = '0';
document.body.appendChild(printIframe);
// 构建打印内容
let printContent = `
<!DOCTYPE html>
<html>
<head>
<title></title>
<title></title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.print-header, .print-footer { margin: 20px 0; white-space: pre-wrap; }
table { width: 100%; border-collapse: collapse; margin: 20px 0; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #f2f2f2; }
.info-section { margin-bottom: 20px; }
.info-item { margin-bottom: 10px; }
.info-label { font-weight: bold; display: inline-block; width: 100px; }
.image-container { display: flex; flex-wrap: wrap; margin-top: 10px; }
.image-item { margin-right: 10px; margin-bottom: 10px; }
@media print {
button { display: none; }
}
/* 重置样式 */
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: Arial, sans-serif; padding: 32px; }
/* 表格样式 */
table { width: 100%; border-collapse: collapse; margin: 8px 0; }
th, td { border: 1px solid #000; padding: 8px; text-align: center; }
th { background-color: #f2f2f2; font-weight: bold; }
/* 打印设置 */
@page { margin: 1cm; }
/* 确保所有内容可见 */
.print-content { visibility: visible !important; }
</style>
</head>
<body>
<div class="print-content">
`;
// 添加自定义页眉
if (headerContent) {
printContent += `<div class="print-header">${headerContent}</div>`;
}
// 添加基本信息
// 加一下页眉
printContent += `
<div class="info-section">
<div class="info-item"><span class="info-label">:</span> ${formRes?.serverPartName || ''}</div>
<div class="info-item"><span class="info-label">:</span> ${formRes?.placeName || ''}</div>
<div class="info-item"><span class="info-label">:</span> ${formRes?.uploadResult || ''}</div>
<div class="info-item"><span class="info-label">:</span> ${formRes?.userName || ''}</div>
<div class="info-item"><span class="info-label">:</span> ${formRes?.submittedAt || ''}</div>
<div style="width:100%;text-align:center;font-size: 32px;font-weight: bold;margin-bottom: 20px">
<div>${parentRow?.serverPartName || '-'}</div>
<div></div>
</div>
`;
// 添加图片信息
if (formRes?.imgsList && formRes.imgsList.length > 0) {
printContent += `
<div class="info-section">
<div class="info-label">:</div>
<div class="image-container">
`;
formRes.imgsList.forEach((item: string) => {
printContent += `<div class="image-item"><img src="${item}" style="width: 150px; height: 150px;" /></div>`;
});
printContent += `
<div style="width:100%;display:flex;align-items: center;justify-content: space-between;">
<div></div>
<div>${parentRow?.title || '-'}</div>
</div>
<div style="width:100%;display:flex;align-items: center;justify-content: space-between;">
<div>${parentRow?.operator || '-'}</div>
<div>${parentRow?.createdAt ? moment(parentRow?.createdAt).format('YYYY-MM-DD HH:mm:ss') : '-'}</div>
</div>
`;
}
`
// 添加表格
printContent += `
@ -325,12 +350,14 @@ const RecordDetail = ({ parentRow, show, detailType }: DetailProps) => {
<tr>
<th></th>
<th></th>
<th></th>
<th>${detailType !== 'modal' ? '考核结果' : '考核选项'}</th>
</tr>
</thead>
<tbody>
`;
console.log('tableData', tableData);
// 添加表格数据行
tableData.forEach((record: any) => {
printContent += '<tr>';
@ -339,7 +366,7 @@ const RecordDetail = ({ parentRow, show, detailType }: DetailProps) => {
if (record._categoryMerged) {
// 如果已合并,不显示单元格
} else {
printContent += `<td ${record._categoryRowSpan && record._categoryRowSpan > 1 ? `rowspan="${record._categoryRowSpan}"` : ''}>${record.parentCategoryName || ''}</td>`;
printContent += `<td ${record._categoryRowSpan && record._categoryRowSpan > 1 ? `rowspan="${record._categoryRowSpan}"` : ''}>${record.parentName || ''}</td>`;
}
// 考核子类列 - 处理合并单元格
@ -361,41 +388,58 @@ const RecordDetail = ({ parentRow, show, detailType }: DetailProps) => {
printContent += '</tr>';
});
// 加一个页脚
// printContent += `
// <table>
// <tbody>
// <tr>
// <td>巡检人员</td>
// <td></td>
// <td>巡检时间</td>
// <td></td>
// </tr>
// </tbody>
// </table>
// `
printContent += `
</tbody>
</table>
`;
// 添加自定义页脚
if (footerContent) {
printContent += `<div class="print-footer">${footerContent}</div>`;
}
// 添加打印按钮
printContent += `
<div style="text-align: center; margin-top: 20px;">
<button onclick="window.print();" style="padding: 8px 16px;"></button>
<button onclick="window.close();" style="padding: 8px 16px; margin-left: 10px;"></button>
</div>
`;
printContent += `
</body>
</html>
`;
// 写入打印窗口并打印
printWindow.document.open();
printWindow.document.write(printContent);
printWindow.document.close();
console.log('printContent', printContent);
// 等待图片加载完成后打印
// 获取iframe的文档对象
const iframeDocument = printIframe.contentWindow?.document;
if (iframeDocument) {
// 打开文档进行写入
iframeDocument.open();
iframeDocument.write(printContent);
iframeDocument.close();
// 等待内容渲染完成后打印
setTimeout(() => {
printWindow.focus();
// 自动打印可以取消注释下面的代码
// printWindow.print();
}, 500);
try {
// 使用iframe的打印功能
printIframe.contentWindow?.print();
} catch (error) {
console.error('打印失败:', error);
} finally {
// 打印完成后移除iframe
setTimeout(() => {
document.body.removeChild(printIframe);
}, 100);
}
}, 500); // 增加等待时间确保内容完全渲染
} else {
console.error('无法获取iframe文档对象');
}
};
return (
@ -481,16 +525,17 @@ const RecordDetail = ({ parentRow, show, detailType }: DetailProps) => {
formRef={tableFormRef}
search={false}
columns={columns}
bordered
toolbar={{
actions: [
<Button type="primary" onClick={(e) => {
setPrintModalVisible(true)
handlePrintTable()
}}>
</Button>
]
}}
scroll={{ x: "100%", y: 'calc(100vh - 400px)' }}
scroll={{ x: "100%", y: 'calc(100vh - 300px)' }}
pagination={false}
options={false}
request={async () => {
@ -516,7 +561,7 @@ const RecordDetail = ({ parentRow, show, detailType }: DetailProps) => {
let tableData = await handeGetTableData(typeData, res)
console.log('tableData', tableData);
// 拿到整个数据之后 递归取出tableData中有 question 数据的那一层数据变为一个数组
let tableRes = await handleGetTableRes(tableData)
let tableRes = await handleGetTableRes(tableData, obj)
console.log('tableRes', tableRes);
// 处理表格数据,为合并单元格做准备
@ -582,37 +627,7 @@ const RecordDetail = ({ parentRow, show, detailType }: DetailProps) => {
}}
/>
<Modal
title="打印设置"
open={printModalVisible}
onOk={() => {
handlePrintTable();
setPrintModalVisible(false);
}}
onCancel={() => setPrintModalVisible(false)}
width={600}
>
<div style={{ marginBottom: 16 }}>
<div style={{ marginBottom: 8 }}></div>
<Input.TextArea
ref={headerRef}
rows={4}
value={headerContent}
onChange={(e) => setHeaderContent(e.target.value)}
placeholder="请输入要在打印页面顶部显示的内容"
/>
</div>
<div>
<div style={{ marginBottom: 8 }}></div>
<Input.TextArea
ref={footerRef}
rows={4}
value={footerContent}
onChange={(e) => setFooterContent(e.target.value)}
placeholder="请输入要在打印页面底部显示的内容"
/>
</div>
</Modal>
{/* 移除打印设置弹窗 */}
</div>
)

View File

@ -2,7 +2,7 @@ import request from "@/utils/request"
// 拿到记录
export async function handleGetRecordList(params?: any) {
const data = await request.post('/questionnaire-templates/search', params)
const data = await request.post('/questionnaire-templates/search/many', params)
if (data.code === 200) {
return data.data
}