fix(ms): 材料导入模板重建 + IIS子目录路径修复 + 隐藏分类数据列
- 按用户参考模板重建 imft.xlsx,保持表头/行结构一致 - fetch路径加 /iapip-ms/ 前缀适配 IIS 子目录部署 - 动态写入的分类数据列设为 hidden,用户下载时不可见 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T71oHHhfhLAWAL9EuoFuYh
This commit is contained in:
parent
8ee0784f20
commit
b26546d459
Binary file not shown.
|
|
@ -191,8 +191,7 @@ const ImportMaterialsModal: React.FC<{
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
setDownloading(true)
|
setDownloading(true)
|
||||||
try {
|
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()
|
const wb = new ExcelJS.Workbook()
|
||||||
await wb.xlsx.load(await file.arrayBuffer())
|
await wb.xlsx.load(await file.arrayBuffer())
|
||||||
const ws = wb.getWorksheet(1)
|
const ws = wb.getWorksheet(1)
|
||||||
|
|
@ -200,9 +199,11 @@ const ImportMaterialsModal: React.FC<{
|
||||||
const categories = await api.config.getMtrlCatList()
|
const categories = await api.config.getMtrlCatList()
|
||||||
categories.forEach((fc, i) => {
|
categories.forEach((fc, i) => {
|
||||||
ws.getCell(1 + i, 43).value = fc.first_category
|
ws.getCell(1 + i, 43).value = fc.first_category
|
||||||
|
ws.getColumn(43).hidden = true
|
||||||
ws.getColumn(44 + i).values = fc.second_categories.map(
|
ws.getColumn(44 + i).values = fc.second_categories.map(
|
||||||
(sc) => sc.second_category
|
(sc) => sc.second_category
|
||||||
)
|
)
|
||||||
|
ws.getColumn(44 + i).hidden = true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
await downloadXLSX(
|
await downloadXLSX(
|
||||||
|
|
|
||||||
|
|
@ -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<string>()
|
||||||
|
const [parsedResult, setParseResult] = useState<AnyObj[]>()
|
||||||
|
const [uploadFile, setUploadFile] = useState<RcFile>()
|
||||||
|
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 (
|
||||||
|
<ModalForm
|
||||||
|
open={open}
|
||||||
|
title={title}
|
||||||
|
width={690}
|
||||||
|
modalProps={{
|
||||||
|
maskClosable: false,
|
||||||
|
destroyOnClose: true,
|
||||||
|
styles: {
|
||||||
|
content: {
|
||||||
|
paddingTop: 20,
|
||||||
|
paddingBottom: 16
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onCancel: () => setOpen(false)
|
||||||
|
}}
|
||||||
|
onOpenChange={(v) => {
|
||||||
|
if (!v) {
|
||||||
|
setParseResult(undefined)
|
||||||
|
setUploadFile(undefined)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
submitter={{
|
||||||
|
render: () => (
|
||||||
|
<div className="w-full flex pt-1 justify-center space-x-4">
|
||||||
|
{!parsedResult ? (
|
||||||
|
<>
|
||||||
|
<Button
|
||||||
|
style={{ width: 120 }}
|
||||||
|
loading={downloading}
|
||||||
|
onClick={async () => {
|
||||||
|
setDownloading(true)
|
||||||
|
try {
|
||||||
|
const file = await fetch('/iapip-ms/fts/itft.xlsx')
|
||||||
|
const wb = new ExcelJS.Workbook()
|
||||||
|
await wb.xlsx.load(await file.arrayBuffer())
|
||||||
|
const ws = wb.getWorksheet(1)
|
||||||
|
if (ws) {
|
||||||
|
const categories = await api.config.getProjSpaceCatList()
|
||||||
|
categories.forEach((pc, i) => {
|
||||||
|
ws.getCell(1 + i, 19).value = pc.project_category
|
||||||
|
ws.getColumn(20 + i).values = pc.space_categories.map(
|
||||||
|
(sc) => sc.space_category
|
||||||
|
)
|
||||||
|
})
|
||||||
|
const cities = await api.config.getCityInfoList()
|
||||||
|
cities.forEach((p, i) => {
|
||||||
|
ws.getCell(1 + i, 56).value = p.province
|
||||||
|
ws.getColumn(57 + i).values = p.cities.map((c) => c.city)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
await downloadXLSX(
|
||||||
|
await wb.xlsx.writeBuffer(),
|
||||||
|
'批量导入模板(文件模板).xlsx'
|
||||||
|
)
|
||||||
|
} catch (err) {}
|
||||||
|
setDownloading(false)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{downloading ? '正在下载' : '下载文件模板'}
|
||||||
|
</Button>
|
||||||
|
<Upload accept=".xlsx" showUploadList={false} beforeUpload={beforeUpload}>
|
||||||
|
<Button type="primary" style={{ width: 120 }} disabled={uploading}>
|
||||||
|
上传文件解析
|
||||||
|
</Button>
|
||||||
|
</Upload>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Upload accept=".xlsx" showUploadList={false} beforeUpload={beforeUpload}>
|
||||||
|
<Button style={{ width: 120 }} disabled={uploading}>
|
||||||
|
重新上传
|
||||||
|
</Button>
|
||||||
|
</Upload>
|
||||||
|
<ImportFile
|
||||||
|
title="导入公共模板申请"
|
||||||
|
trigger={
|
||||||
|
<Button type="primary" style={{ width: 120 }}>
|
||||||
|
确认导入
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
trigger={React.cloneElement(trigger, { onClick: () => setOpen(true) })}
|
||||||
|
>
|
||||||
|
<Divider style={{ marginTop: 16, marginBottom: 12 }} />
|
||||||
|
{errMsg ? <Alert message={errMsg} type="error" showIcon style={{ marginBottom: 12 }} /> : ''}
|
||||||
|
<div className="px-6 pt-3 pb-6 space-y-2">
|
||||||
|
<label>导入说明</label>
|
||||||
|
<div style={{ color: token.colorTextSecondary }}>
|
||||||
|
1. 请下载文件模板, 并根据要求填写后上传文件进行解析
|
||||||
|
</div>
|
||||||
|
<div style={{ color: token.colorTextSecondary }}>
|
||||||
|
2. 解析成功后, 确认解析数量是否一致, 点击确认即可导入
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{parsedResult ? (
|
||||||
|
<>
|
||||||
|
<Divider style={{ margin: 0 }} />
|
||||||
|
<div className="p-6 space-y-2">
|
||||||
|
<div>
|
||||||
|
<label className="mr-4">导入文件:</label>
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
style={{ padding: 0 }}
|
||||||
|
onClick={async () => {
|
||||||
|
if (uploadFile) {
|
||||||
|
await downloadXLSX(await uploadFile.arrayBuffer(), uploadFile.name)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{uploadFile?.name ?? '下载'}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="mr-4">解析结果:</label>
|
||||||
|
解析成功, 请确认解析数量一致后点击确认导入
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label className="mr-4">解析数据:</label>共
|
||||||
|
<Tag style={{ marginInline: 5 }}>{parsedResult.length}</Tag>
|
||||||
|
条数据
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
''
|
||||||
|
)}
|
||||||
|
<Divider style={{ margin: 0 }} />
|
||||||
|
</ModalForm>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ImportTemplatesModal
|
||||||
Loading…
Reference in New Issue