|
|
@@ -55,20 +55,6 @@ const detailApiCandidates = [
|
|
|
'cms/importLedger/checkResultPage',
|
|
|
'cms/importLedger/pageDetail'
|
|
|
]
|
|
|
-const importSuccessApiCandidates = [
|
|
|
- 'cms/importLedger/importSuccessData',
|
|
|
- 'cms/importLedger/importSuccess',
|
|
|
- 'cms/importLedger/confirmImport',
|
|
|
- 'cms/importLedger/confirm',
|
|
|
- 'cms/importLedger/saveSuccessData'
|
|
|
-]
|
|
|
-const cancelImportApiCandidates = [
|
|
|
- 'cms/importLedger/cancelImport',
|
|
|
- 'cms/importLedger/cancel',
|
|
|
- 'cms/importLedger/deleteImport',
|
|
|
- 'cms/importLedger/removeImport'
|
|
|
-]
|
|
|
-
|
|
|
const pickValue = (item: any, keys: string[], defaultValue: any = emptyTxt) => {
|
|
|
for (const key of keys) {
|
|
|
const value = item?.[key]
|
|
|
@@ -88,11 +74,11 @@ const normalizeRecord = (item: any, index: number): ImportRecordType => ({
|
|
|
fileName: pickValue(item, ['fileName', 'excelName', 'originFileName', 'originalName', 'name']),
|
|
|
importCount: pickValue(
|
|
|
item,
|
|
|
- ['importCount', 'importNum', 'dataCount', 'totalCount', 'totalNum', 'pcsRegister'],
|
|
|
+ ['pcsTotal', 'importCount', 'importNum', 'dataCount', 'totalCount', 'totalNum', 'pcsRegister'],
|
|
|
0
|
|
|
),
|
|
|
- successCount: pickValue(item, ['successCount', 'successNum', 'okCount', 'okNum'], 0),
|
|
|
- failCount: pickValue(item, ['failCount', 'failNum', 'errorCount', 'errorNum'], 0),
|
|
|
+ successCount: pickValue(item, ['pcsSuccess', 'successCount', 'successNum', 'okCount', 'okNum'], 0),
|
|
|
+ failCount: pickValue(item, ['pcsError', 'failCount', 'failNum', 'errorCount', 'errorNum'], 0),
|
|
|
importDate: pickDateValue(item, ['importTime', 'uploadTime', 'createTime', 'updateTime']),
|
|
|
importUser: pickValue(item, ['importUser', 'importUserName', 'creatorName', 'updateByName']),
|
|
|
raw: item
|
|
|
@@ -113,11 +99,15 @@ const normalizeCheckResult = (value: any) => {
|
|
|
|
|
|
const normalizeDetail = (item: any, index: number): ImportDetailType => {
|
|
|
const result = normalizeCheckResult(
|
|
|
- pickValue(item, ['checkResult', 'validateResult', 'result', 'status', 'successFlag'], '')
|
|
|
+ pickValue(
|
|
|
+ item,
|
|
|
+ ['importIsTrue', 'checkResult', 'validateResult', 'result', 'status', 'successFlag'],
|
|
|
+ ''
|
|
|
+ )
|
|
|
)
|
|
|
const failReason = pickValue(
|
|
|
item,
|
|
|
- ['failReason', 'errorMsg', 'msg', 'reason', 'remark'],
|
|
|
+ ['importErrorMsg', 'failReason', 'errorMsg', 'msg', 'reason', 'remark'],
|
|
|
result === '成功' ? emptyTxt : ''
|
|
|
)
|
|
|
|
|
|
@@ -125,7 +115,7 @@ const normalizeDetail = (item: any, index: number): ImportDetailType => {
|
|
|
id: pickValue(item, ['id', 'detailId', 'rowId'], `detail-${index}`),
|
|
|
rowNum: pickValue(
|
|
|
item,
|
|
|
- ['rowNum', 'rowNo', 'lineNum', 'excelRowNum', 'sort', 'index'],
|
|
|
+ ['importRow', 'rowNum', 'rowNo', 'lineNum', 'excelRowNum', 'sort', 'index'],
|
|
|
index + 1
|
|
|
),
|
|
|
num: pickValue(
|
|
|
@@ -140,10 +130,62 @@ const normalizeDetail = (item: any, index: number): ImportDetailType => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+const parseSnapValue = (value: any) => {
|
|
|
+ if (!value) return null
|
|
|
+ if (Array.isArray(value) || typeof value === 'object') return value
|
|
|
+
|
|
|
+ if (typeof value === 'string') {
|
|
|
+ try {
|
|
|
+ return JSON.parse(value)
|
|
|
+ } catch (error) {
|
|
|
+ return null
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return null
|
|
|
+}
|
|
|
+
|
|
|
const getInlineDetailList = (item: any) => {
|
|
|
+ const snapValue = parseSnapValue(item?.snap)
|
|
|
+ if (Array.isArray(snapValue)) return snapValue
|
|
|
+
|
|
|
+ if (snapValue && typeof snapValue === 'object') {
|
|
|
+ const snapList = pickValue(
|
|
|
+ snapValue,
|
|
|
+ [
|
|
|
+ 'detailList',
|
|
|
+ 'details',
|
|
|
+ 'checkList',
|
|
|
+ 'checkResultList',
|
|
|
+ 'resultList',
|
|
|
+ 'importDetailList',
|
|
|
+ 'importList',
|
|
|
+ 'dataList',
|
|
|
+ 'list',
|
|
|
+ 'rows',
|
|
|
+ 'records'
|
|
|
+ ],
|
|
|
+ null
|
|
|
+ )
|
|
|
+ if (Array.isArray(snapList)) return snapList
|
|
|
+ }
|
|
|
+
|
|
|
const detailList = pickValue(
|
|
|
item,
|
|
|
- ['detailList', 'details', 'checkList', 'checkResultList', 'resultList'],
|
|
|
+ [
|
|
|
+ 'snap',
|
|
|
+ 'detailList',
|
|
|
+ 'details',
|
|
|
+ 'checkList',
|
|
|
+ 'checkResultList',
|
|
|
+ 'resultList',
|
|
|
+ 'importDetailList',
|
|
|
+ 'importList',
|
|
|
+ 'dataList',
|
|
|
+ 'list',
|
|
|
+ 'rows',
|
|
|
+ 'records'
|
|
|
+ ],
|
|
|
null
|
|
|
)
|
|
|
return Array.isArray(detailList) ? detailList : []
|
|
|
@@ -184,14 +226,6 @@ const buildDetailPayload = (record: ImportRecordType, query: DetailQueryType) =>
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-const buildActionPayload = (record: ImportRecordType) => ({
|
|
|
- id: record.id,
|
|
|
- importId: pickValue(record.raw, ['importId'], record.id),
|
|
|
- batchId: pickValue(record.raw, ['batchId'], record.id),
|
|
|
- logId: pickValue(record.raw, ['logId'], record.id),
|
|
|
- fileName: record.fileName
|
|
|
-})
|
|
|
-
|
|
|
const silentPost = async (url: string, data: any) => {
|
|
|
const { token } = getTokenInfo()
|
|
|
try {
|
|
|
@@ -213,17 +247,10 @@ const silentPost = async (url: string, data: any) => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-const requestWithCandidates = async (paths: string[], payload: any) => {
|
|
|
- for (const path of paths) {
|
|
|
- const res = await silentPost(path, payload)
|
|
|
- if (res) return res
|
|
|
- }
|
|
|
- return null
|
|
|
-}
|
|
|
-
|
|
|
function ImportData({ closeFu }: Props) {
|
|
|
const uploadBtnRef = useRef<UpBtnMethods>(null)
|
|
|
const detailApiPathRef = useRef('')
|
|
|
+ const reuploadPendingRef = useRef(false)
|
|
|
|
|
|
const [formData, setFormData] = useState({ pageNum: 1, pageSize: 10 })
|
|
|
const [tableInfo, setTableInfo] = useState({ list: [] as ImportRecordType[], total: 0 })
|
|
|
@@ -243,19 +270,20 @@ function ImportData({ closeFu }: Props) {
|
|
|
total: 0
|
|
|
})
|
|
|
const [detailLoading, setDetailLoading] = useState(false)
|
|
|
- const [actionLoading, setActionLoading] = useState<'confirm' | 'cancel' | ''>('')
|
|
|
+ const [actionLoading, setActionLoading] = useState<'confirm' | ''>('')
|
|
|
+ const [uploadResultData, setUploadResultData] = useState<any>(null)
|
|
|
|
|
|
const fetchImportPage = useCallback(async (payload: { pageNum: number; pageSize: number }) => {
|
|
|
- const res = await http.post('cms/importLedger/pageList', payload)
|
|
|
+ const res = await http.post('cms/importLedger/importPage', payload)
|
|
|
if (res.code !== 0) return { list: [] as ImportRecordType[], total: 0 }
|
|
|
|
|
|
- const records = (res.data?.records || []).map((item: any, index: number) =>
|
|
|
- normalizeRecord(item, index)
|
|
|
+ const records = (res.data?.records || res.data?.list || res.data?.rows || []).map(
|
|
|
+ (item: any, index: number) => normalizeRecord(item, index)
|
|
|
)
|
|
|
|
|
|
return {
|
|
|
list: records,
|
|
|
- total: res.data?.total || 0
|
|
|
+ total: res.data?.total || res.data?.count || res.data?.totalCount || records.length
|
|
|
}
|
|
|
}, [])
|
|
|
|
|
|
@@ -291,32 +319,24 @@ function ImportData({ closeFu }: Props) {
|
|
|
const resolveUploadRecord = useCallback(
|
|
|
async (res: any, file: File) => {
|
|
|
const uploadData = Array.isArray(res?.data) ? res.data[0] : res?.data
|
|
|
- const latestPage = await fetchImportPage({ pageNum: 1, pageSize: formData.pageSize })
|
|
|
-
|
|
|
- setTableInfo(latestPage)
|
|
|
- setFormData(prev => ({
|
|
|
- ...prev,
|
|
|
- pageNum: 1
|
|
|
- }))
|
|
|
-
|
|
|
- const latestMatch =
|
|
|
- latestPage.list.find((item: ImportRecordType) => item.fileName === file.name) ||
|
|
|
- latestPage.list[0] ||
|
|
|
- null
|
|
|
-
|
|
|
- if (latestMatch) return latestMatch
|
|
|
-
|
|
|
- if (uploadData && typeof uploadData === 'object') {
|
|
|
- return normalizeRecord({ ...uploadData, fileName: file.name }, 0)
|
|
|
- }
|
|
|
-
|
|
|
- return normalizeRecord({ fileName: file.name }, 0)
|
|
|
+ const uploadRecord =
|
|
|
+ uploadData && typeof uploadData === 'object'
|
|
|
+ ? normalizeRecord(
|
|
|
+ {
|
|
|
+ ...uploadData,
|
|
|
+ fileName: pickValue(uploadData, ['fileName'], file.name)
|
|
|
+ },
|
|
|
+ 0
|
|
|
+ )
|
|
|
+ : null
|
|
|
+ return uploadRecord || normalizeRecord({ fileName: file.name }, 0)
|
|
|
},
|
|
|
- [fetchImportPage, formData.pageSize]
|
|
|
+ []
|
|
|
)
|
|
|
|
|
|
const handleUploadSuccess = useCallback(
|
|
|
async (res: any, file: File) => {
|
|
|
+ setUploadResultData(res?.data ?? null)
|
|
|
const record = await resolveUploadRecord(res, file)
|
|
|
openDetailModal(record, 'uploadResult')
|
|
|
},
|
|
|
@@ -332,10 +352,8 @@ function ImportData({ closeFu }: Props) {
|
|
|
normalizeDetail(item, index)
|
|
|
)
|
|
|
const filteredList = filterInlineDetails(normalizedList, detailQuery)
|
|
|
- const start = (detailQuery.pageNum - 1) * detailQuery.pageSize
|
|
|
- const end = start + detailQuery.pageSize
|
|
|
setDetailTableInfo({
|
|
|
- list: filteredList.slice(start, end),
|
|
|
+ list: filteredList,
|
|
|
total: filteredList.length
|
|
|
})
|
|
|
return
|
|
|
@@ -343,6 +361,22 @@ function ImportData({ closeFu }: Props) {
|
|
|
|
|
|
setDetailLoading(true)
|
|
|
try {
|
|
|
+ if (detailModalMode === 'view') {
|
|
|
+ const res = await http.get(`cms/importLedger/importDetail/${detailInfo.id}`)
|
|
|
+ const detailData = res.code === 0 ? res.data : null
|
|
|
+ const detailList = Array.isArray(detailData) ? detailData : getInlineDetailList(detailData)
|
|
|
+ const normalizedList = detailList.map((item: any, index: number) =>
|
|
|
+ normalizeDetail(item, index)
|
|
|
+ )
|
|
|
+ const filteredList = filterInlineDetails(normalizedList, detailQuery)
|
|
|
+
|
|
|
+ setDetailTableInfo({
|
|
|
+ list: filteredList,
|
|
|
+ total: filteredList.length
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
const payload = buildDetailPayload(detailInfo, detailQuery)
|
|
|
const tryPaths = detailApiPathRef.current
|
|
|
? [detailApiPathRef.current]
|
|
|
@@ -352,18 +386,14 @@ function ImportData({ closeFu }: Props) {
|
|
|
const res = await silentPost(path, payload)
|
|
|
if (res?.data) {
|
|
|
detailApiPathRef.current = path
|
|
|
- const records = (res.data.records || res.data.list || res.data.rows || []).map(
|
|
|
- (item: any, index: number) => normalizeDetail(item, index)
|
|
|
+ const records = getInlineDetailList(res.data).map((item: any, index: number) =>
|
|
|
+ normalizeDetail(item, index)
|
|
|
)
|
|
|
+ const filteredList = filterInlineDetails(records, detailQuery)
|
|
|
|
|
|
setDetailTableInfo({
|
|
|
- list: records,
|
|
|
- total:
|
|
|
- res.data.total ||
|
|
|
- res.data.count ||
|
|
|
- res.data.totalCount ||
|
|
|
- res.data.recordTotal ||
|
|
|
- records.length
|
|
|
+ list: filteredList,
|
|
|
+ total: filteredList.length
|
|
|
})
|
|
|
return
|
|
|
}
|
|
|
@@ -373,30 +403,34 @@ function ImportData({ closeFu }: Props) {
|
|
|
} finally {
|
|
|
setDetailLoading(false)
|
|
|
}
|
|
|
- }, [detailInfo, detailQuery])
|
|
|
+ }, [detailInfo, detailModalMode, detailQuery])
|
|
|
|
|
|
useEffect(() => {
|
|
|
getDetailListFu()
|
|
|
}, [getDetailListFu])
|
|
|
|
|
|
const closeDetailModal = useCallback(() => {
|
|
|
+ reuploadPendingRef.current = false
|
|
|
setDetailModalMode('view')
|
|
|
setActionLoading('')
|
|
|
+ setUploadResultData(null)
|
|
|
setDetailInfo(null)
|
|
|
setDetailTableInfo({ list: [], total: 0 })
|
|
|
}, [])
|
|
|
|
|
|
- const refreshListToFirstPage = useCallback(async () => {
|
|
|
- const latestPage = await fetchImportPage({ pageNum: 1, pageSize: formData.pageSize })
|
|
|
- setTableInfo(latestPage)
|
|
|
- setFormData(prev => ({
|
|
|
- ...prev,
|
|
|
- pageNum: 1
|
|
|
- }))
|
|
|
- }, [fetchImportPage, formData.pageSize])
|
|
|
+ const handleUploadFileSelected = useCallback(() => {
|
|
|
+ if (!reuploadPendingRef.current) return
|
|
|
+ reuploadPendingRef.current = false
|
|
|
+ closeDetailModal()
|
|
|
+ }, [closeDetailModal])
|
|
|
+
|
|
|
+ const reuploadFu = useCallback(() => {
|
|
|
+ reuploadPendingRef.current = true
|
|
|
+ uploadBtnRef.current?.openPicker()
|
|
|
+ }, [])
|
|
|
|
|
|
const importSuccessData = useCallback(async () => {
|
|
|
- if (!detailInfo) return
|
|
|
+ if (!detailInfo || !uploadResultData) return
|
|
|
if (Number(detailInfo.successCount || 0) <= 0) {
|
|
|
MessageFu.warning('当前没有可导入的校验成功数据')
|
|
|
return
|
|
|
@@ -404,36 +438,24 @@ function ImportData({ closeFu }: Props) {
|
|
|
|
|
|
setActionLoading('confirm')
|
|
|
try {
|
|
|
- const res = await requestWithCandidates(
|
|
|
- importSuccessApiCandidates,
|
|
|
- buildActionPayload(detailInfo)
|
|
|
- )
|
|
|
+ const res = await http.post('cms/importLedger/importRow', uploadResultData)
|
|
|
+
|
|
|
|
|
|
- if (!res) {
|
|
|
+ if (res.code !== 0) return
|
|
|
+ /*
|
|
|
MessageFu.warning('暂未匹配到导入接口,请联系管理员确认')
|
|
|
return
|
|
|
}
|
|
|
|
|
|
MessageFu.success(res.msg || '导入成功')
|
|
|
+ */
|
|
|
+ MessageFu.success(res.msg || '导入成功')
|
|
|
closeDetailModal()
|
|
|
- await refreshListToFirstPage()
|
|
|
- } finally {
|
|
|
- setActionLoading('')
|
|
|
- }
|
|
|
- }, [closeDetailModal, detailInfo, refreshListToFirstPage])
|
|
|
-
|
|
|
- const cancelImport = useCallback(async () => {
|
|
|
- if (!detailInfo) return
|
|
|
-
|
|
|
- setActionLoading('cancel')
|
|
|
- try {
|
|
|
- await requestWithCandidates(cancelImportApiCandidates, buildActionPayload(detailInfo))
|
|
|
- closeDetailModal()
|
|
|
- await refreshListToFirstPage()
|
|
|
+ await getListFu()
|
|
|
} finally {
|
|
|
setActionLoading('')
|
|
|
}
|
|
|
- }, [closeDetailModal, detailInfo, refreshListToFirstPage])
|
|
|
+ }, [closeDetailModal, detailInfo, getListFu, uploadResultData])
|
|
|
|
|
|
const modalTitle = useMemo(() => {
|
|
|
if (!detailInfo) return '上传数据校验结果'
|
|
|
@@ -469,7 +491,8 @@ function ImportData({ closeFu }: Props) {
|
|
|
tit='上传藏品数据'
|
|
|
url='cms/importLedger/uploadExcel'
|
|
|
width={140}
|
|
|
- backFu={() => setFormData(prev => ({ ...prev, pageNum: 1 }))}
|
|
|
+ backFu={getListFu}
|
|
|
+ onFileSelected={handleUploadFileSelected}
|
|
|
onSuccess={handleUploadSuccess}
|
|
|
/>
|
|
|
</div>
|
|
|
@@ -579,9 +602,7 @@ function ImportData({ closeFu }: Props) {
|
|
|
scrollX={160}
|
|
|
loading={detailLoading}
|
|
|
list={detailTableInfo.list}
|
|
|
- total={detailTableInfo.total}
|
|
|
- pageNum={detailQuery.pageNum}
|
|
|
- pageSize={detailQuery.pageSize}
|
|
|
+ pagingInfo={false}
|
|
|
rowKey='id'
|
|
|
columnsTemp={[
|
|
|
['txt', '行数', 'rowNum', 100],
|
|
|
@@ -590,19 +611,12 @@ function ImportData({ closeFu }: Props) {
|
|
|
['txt', '校验结果', 'result', 120],
|
|
|
['txt', '失败原因', 'failReason', 360]
|
|
|
]}
|
|
|
- onChange={(pageNum, pageSize) =>
|
|
|
- setDetailQuery(prev => ({
|
|
|
- ...prev,
|
|
|
- pageNum,
|
|
|
- pageSize
|
|
|
- }))
|
|
|
- }
|
|
|
/>
|
|
|
</div>
|
|
|
|
|
|
{detailModalMode === 'uploadResult' ? (
|
|
|
<div className={styles.A1ImportFooter}>
|
|
|
- <Button onClick={() => uploadBtnRef.current?.openPicker()}>重新上传表格</Button>
|
|
|
+ <Button onClick={reuploadFu}>重新上传表格</Button>
|
|
|
<Button
|
|
|
type='primary'
|
|
|
loading={actionLoading === 'confirm'}
|
|
|
@@ -611,7 +625,7 @@ function ImportData({ closeFu }: Props) {
|
|
|
>
|
|
|
导入校验成功的数据
|
|
|
</Button>
|
|
|
- <Button loading={actionLoading === 'cancel'} onClick={cancelImport}>
|
|
|
+ <Button onClick={closeDetailModal}>
|
|
|
取消导入
|
|
|
</Button>
|
|
|
</div>
|