From b26546d4599142e6fcb6bf5a2a6e231b4ac25ddf Mon Sep 17 00:00:00 2001 From: zty Date: Wed, 29 Jul 2026 02:40:22 -0400 Subject: [PATCH] =?UTF-8?q?fix(ms):=20=E6=9D=90=E6=96=99=E5=AF=BC=E5=85=A5?= =?UTF-8?q?=E6=A8=A1=E6=9D=BF=E9=87=8D=E5=BB=BA=20+=20IIS=E5=AD=90?= =?UTF-8?q?=E7=9B=AE=E5=BD=95=E8=B7=AF=E5=BE=84=E4=BF=AE=E5=A4=8D=20+=20?= =?UTF-8?q?=E9=9A=90=E8=97=8F=E5=88=86=E7=B1=BB=E6=95=B0=E6=8D=AE=E5=88=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 按用户参考模板重建 imft.xlsx,保持表头/行结构一致 - fetch路径加 /iapip-ms/ 前缀适配 IIS 子目录部署 - 动态写入的分类数据列设为 hidden,用户下载时不可见 Co-Authored-By: Claude Opus 4.6 Claude-Session: https://claude.ai/code/session_01T71oHHhfhLAWAL9EuoFuYh --- .../管理端/iapip-ms/public/fts/imft.xlsx | Bin 12640 -> 9646 bytes .../import-file-modal/materials.tsx | 5 +- .../import-file-modal/templates.tsx | 270 ++++++++++++++++++ 3 files changed, 273 insertions(+), 2 deletions(-) create mode 100644 空气质量预测/源码/管理端/iapip-ms/src/components/import-file-modal/templates.tsx diff --git a/空气质量预测/源码/管理端/iapip-ms/public/fts/imft.xlsx b/空气质量预测/源码/管理端/iapip-ms/public/fts/imft.xlsx index e744a72a2ea6c92c54e240b6b388dc4de2a6ae62..d8f0bcdc1a193bc37e65d9421458ed269cb6f0e2 100644 GIT binary patch delta 6312 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 { setDownloading(true) try { - const file = await fetch('/fts/imft.xlsx') - // const file = await fetch('/iapip-ms/fts/imft.xlsx') + const file = await fetch('/iapip-ms/fts/imft.xlsx') const wb = new ExcelJS.Workbook() await wb.xlsx.load(await file.arrayBuffer()) const ws = wb.getWorksheet(1) @@ -200,9 +199,11 @@ const ImportMaterialsModal: React.FC<{ const categories = await api.config.getMtrlCatList() categories.forEach((fc, i) => { ws.getCell(1 + i, 43).value = fc.first_category + ws.getColumn(43).hidden = true ws.getColumn(44 + i).values = fc.second_categories.map( (sc) => sc.second_category ) + ws.getColumn(44 + i).hidden = true }) } await downloadXLSX( diff --git a/空气质量预测/源码/管理端/iapip-ms/src/components/import-file-modal/templates.tsx b/空气质量预测/源码/管理端/iapip-ms/src/components/import-file-modal/templates.tsx new file mode 100644 index 0000000..b54607b --- /dev/null +++ b/空气质量预测/源码/管理端/iapip-ms/src/components/import-file-modal/templates.tsx @@ -0,0 +1,270 @@ +import { ExcelValidator } from '@/common/excel-validator' +import { AnyObj, FROM_TYPE } from '@/common/types' +import { downloadXLSX, toNum } from '@/common/utils' +import api from '@/services/api' +import { ModalForm } from '@ant-design/pro-components' +import { Alert, Button, Divider, Tag, Upload, message, theme } from 'antd' +import { RcFile } from 'antd/es/upload' +import * as ExcelJS from 'exceljs' +import React, { useState } from 'react' +import ImportFile from '../apply-request-modal/import-file' + +const ImportTemplatesModal: React.FC<{ + title: string + trigger: JSX.Element +}> = ({ title, trigger }) => { + const { token } = theme.useToken() + const [open, setOpen] = useState(false) + const [downloading, setDownloading] = useState(false) + const [uploading, setUploading] = useState(false) + const [errMsg, setErrMsg] = useState() + const [parsedResult, setParseResult] = useState() + const [uploadFile, setUploadFile] = useState() + const beforeUpload = async (file: RcFile) => { + setUploading(true) + const msgKey = 'UPLOADING_TEMPLATES' + try { + message.open({ + key: msgKey, + type: 'loading', + content: '正在解析' + }) + const wb = new ExcelJS.Workbook() + await wb.xlsx.load(await file.arrayBuffer()) + const ws = wb.getWorksheet(1) + if (ws) { + const templates: AnyObj[] = [] + ws.getRows(6, 10)?.forEach((row, idx) => { + const id = row.getCell(1).value?.toString() + const name = row.getCell(2).value?.toString() + const category = row.getCell(3).value?.toString() + const province = row.getCell(4).value?.toString() + const city = row.getCell(5).value?.toString() + const constr_area = toNum(row.getCell(6).value?.toString()) + if (id && name && category && province && city && constr_area) { + templates.push({ + id, + idx: 6 + idx, + name, + category, + province, + city, + constr_area, + display: 1, + from: FROM_TYPE.IMPORT, + spaces: [] as AnyObj + }) + } + }) + ws.getRows(20, 500)?.forEach((row, idx) => { + const temp_id = row.getCell(2).value?.toString() + const name = row.getCell(5).value?.toString() + const category = row.getCell(6).value?.toString() + const area = toNum(row.getCell(7).value?.toString()) + const volume = toNum(row.getCell(8).value?.toString()) + const env_temp = toNum(row.getCell(9).value?.toString()) + const env_hum = toNum(row.getCell(10).value?.toString()) + const env_vent_rate = toNum(row.getCell(11).value?.toString()) + const apc_lmt_std_id = row.getCell(12).value?.toString() + if (temp_id && name && category && area && volume && apc_lmt_std_id) { + templates.find((temp) => { + if (temp.id === temp_id) { + temp.spaces.push({ + idx: 20 + idx, + name, + category, + layout: 0, + area, + volume, + env_temp, + env_hum, + env_vent_rate, + apc_lmt_std_id + }) + return true + } + return false + }) + } + }) + const excelValidator = new ExcelValidator() + if (await excelValidator.importTemplates(templates)) { + message.open({ + key: msgKey, + type: 'success', + content: '上传成功', + duration: 2 + }) + setErrMsg(undefined) + setParseResult(templates) + setUploadFile(file) + setUploading(false) + return file + } + setErrMsg(excelValidator.errorMessage) + } + } catch (err) {} + message.destroy(msgKey) + setUploading(false) + return false + } + return ( + setOpen(false) + }} + onOpenChange={(v) => { + if (!v) { + setParseResult(undefined) + setUploadFile(undefined) + } + }} + submitter={{ + render: () => ( +
+ {!parsedResult ? ( + <> + + + + + + ) : ( + <> + + + + + 确认导入 + + } + onFinish={async (data) => { + if (uploadFile) { + if (parsedResult.length) { + try { + await api.audit.importTemplates({ + file: uploadFile, + data: parsedResult, + qty: parsedResult.length, + desc: data.desc + }) + message.success('申请成功') + setOpen(false) + return true + } catch (err) {} + } else { + message.error('至少包含一条解析数据') + } + } else { + message.error('找不到上传文件,请重新上传') + } + return false + }} + /> + + )} +
+ ) + }} + trigger={React.cloneElement(trigger, { onClick: () => setOpen(true) })} + > + + {errMsg ? : ''} +
+ +
+ 1. 请下载文件模板, 并根据要求填写后上传文件进行解析 +
+
+ 2. 解析成功后, 确认解析数量是否一致, 点击确认即可导入 +
+
+ {parsedResult ? ( + <> + +
+
+ + +
+
+ + 解析成功, 请确认解析数量一致后点击确认导入 +
+
+ 共 + {parsedResult.length} + 条数据 +
+
+ + ) : ( + '' + )} + +
+ ) +} + +export default ImportTemplatesModal