This commit is contained in:
zwgczx committed 2026-03-11 17:41:08 +08:00
1 parent 3d26b0b259
commit 0f71fff9ac
11 files changed
+873 -205

No files matched your search

+378 -60
View File
@@ -22,7 +22,8 @@ import {
AlertDialogTrigger,
} from 'reka-ui'
import { decodeZwArchive, encodeZwArchive, ZW_FILE_EXTENSION } from '@/lib/zwArchive'
import { exportFile, serviceList } from '@/sql'
import { addNumbers, roundTo } from '@/lib/decimal'
import { exportFile, serviceList, additionalWorkList } from '@/sql'
interface DataEntry {
key: string
@@ -59,12 +60,14 @@ type XmInfoLike = {
interface ScaleRowLike {
id: string
amount?: unknown
landArea?: unknown
amount: number | null
landArea: number | null
}
interface XmInfoStorageLike extends XmInfoLike {
detailRows?: ScaleRowLike[]
detailRows?: ScaleRowLike[],
totalAmount?: number,
roughCalcEnabled?: boolean
}
interface XmScaleStorageLike {
detailRows?: ScaleRowLike[]
@@ -78,6 +81,7 @@ interface ContractCardItem {
interface ZxFwRowLike {
id: string
process?: unknown
subtotal?: unknown
investScale?: unknown
landScale?: unknown
@@ -86,6 +90,8 @@ interface ZxFwRowLike {
}
interface ZxFwStorageLike {
selectedIds?: string[]
selectedCodes?: string[]
detailRows?: ZxFwRowLike[]
}
@@ -97,6 +103,28 @@ interface ScaleMethodRowLike extends ScaleRowLike {
budgetFeeOptional?: unknown
consultCategoryFactor?: unknown
majorFactor?: unknown
workStageFactor?: unknown
workRatio?: unknown
remark?: unknown
}
interface HtFeeMainRowLike {
id?: unknown
name?: unknown
}
interface RateMethodRowLike {
rate?: unknown
budgetFee?: unknown
}
interface QuantityMethodRowLike {
id?: unknown
feeItem?: unknown
unit?: unknown
quantity?: unknown
unitPrice?: unknown
budgetFee?: unknown
remark?: unknown
}
@@ -120,7 +148,11 @@ interface HourlyMethodRowLike {
}
interface DetailRowsStorageLike<T> {
detailRows?: T[]
detailRows?: T[],
roughCalcEnabled?: boolean,
totalAmount?: number,
}
interface FactorRowLike {
@@ -132,8 +164,8 @@ interface FactorRowLike {
interface ExportScaleRow {
major: number
cost: number
area: number
cost: number | null
area: number | null
}
interface ExportMethod1Detail {
@@ -250,8 +282,63 @@ interface ExportContract {
serviceCoes: ExportServiceCoe[]
majorCoes: ExportMajorCoe[]
services: ExportService[]
addtional: []
reserve: []
addtional: ExportAdditional | null
reserve: ExportReserve | null
}
interface ExportRichTextCode {
richText: Array<{
text: string
font?: Record<string, unknown>
}>
}
interface ExportMethod0 {
coe: number
fee: number
}
interface ExportMethod5Detail {
name: string
unit: string
amount: number
price: number
fee: number
remark: string
}
interface ExportMethod5 {
fee: number
det: ExportMethod5Detail[]
}
interface ExportAdditionalDetail {
id: number
code: ExportRichTextCode
ref?: ExportRichTextCode
name: string
fee: number
m0?: ExportMethod0
m4?: ExportMethod4
m5?: ExportMethod5
}
interface ExportAdditional {
code: ExportRichTextCode
ref?: ExportRichTextCode
name: string
fee: number
det: ExportAdditionalDetail[]
}
interface ExportReserve {
code: ExportRichTextCode
ref?: ExportRichTextCode
name: string
fee: number
m0?: ExportMethod0
m4?: ExportMethod4
m5?: ExportMethod5
}
interface ExportReportPayload {
@@ -872,6 +959,15 @@ const getExpertIdFromRowId = (value: string): number | null => {
const hasServiceId = (serviceId: string) =>
Object.prototype.hasOwnProperty.call(serviceList as Record<string, unknown>, serviceId)
const sortServiceIdsByDict = (ids: string[]) =>
[...ids].sort((left, right) => {
const leftOrder = Number((serviceList as Record<string, any>)[left]?.order)
const rightOrder = Number((serviceList as Record<string, any>)[right]?.order)
const safeLeft = Number.isFinite(leftOrder) ? leftOrder : Number.MAX_SAFE_INTEGER
const safeRight = Number.isFinite(rightOrder) ? rightOrder : Number.MAX_SAFE_INTEGER
return safeLeft - safeRight
})
const mapIndustryCodeToExportIndustry = (value: unknown): number => {
const raw = typeof value === 'string' ? value.trim().toUpperCase() : ''
if (!raw) return 0
@@ -886,12 +982,12 @@ const buildProjectServiceCoes = (rows: FactorRowLike[] | undefined): ExportServi
return rows
.map(row => {
const serviceid = toSafeInteger(row.id)
if (serviceid == null) return null
const coe = toFiniteNumber(row.budgetValue) ?? toFiniteNumber(row.standardFactor) ?? 0
if (serviceid == null || row.budgetValue == null) return null
const coe = toFiniteNumber(row.budgetValue)
return {
serviceid,
coe,
remark: typeof row.remark === 'string' ? row.remark : ''
remark: row.remark
}
})
.filter((item): item is ExportServiceCoe => Boolean(item))
@@ -902,42 +998,44 @@ const buildProjectMajorCoes = (rows: FactorRowLike[] | undefined): ExportMajorCo
return rows
.map(row => {
const majorid = toSafeInteger(row.id)
if (majorid == null) return null
const coe = toFiniteNumber(row.budgetValue) ?? toFiniteNumber(row.standardFactor) ?? 0
if (majorid == null || row.budgetValue == null) return null
const coe = toFiniteNumber(row.budgetValue)
return {
majorid,
coe,
remark: typeof row.remark === 'string' ? row.remark : ''
remark: row.remark
}
})
.filter((item): item is ExportMajorCoe => Boolean(item))
}
const buildScaleRows = (rows: ScaleRowLike[] | undefined): ExportScaleRow[] => {
const toExportScaleRows = (rows: ScaleRowLike[] | undefined): ExportScaleRow[] => {
if (!Array.isArray(rows)) return []
return rows
.map(row => {
const major = toSafeInteger(row.id)
const cost = toFiniteNumber(row.amount)
const area = toFiniteNumber(row.landArea)
if (major == null || (cost == null && area == null)) return null
if (row.id == null || (row.amount == null && row.landArea == null)) return null
return {
major,
cost: cost ?? 0,
area: area ?? 0
major: toSafeInteger(row.id),
cost: row.amount,
area: row.landArea
}
})
.filter((item): item is ExportScaleRow => Boolean(item))
}
const buildMethod1 = (rows: ScaleMethodRowLike[] | undefined): ExportMethod1 | null => {
if (!Array.isArray(rows)) return null
let hasTotalValue = false
const det = rows
.map(row => {
const major = toSafeInteger(row.id)
if (major == null) return null
if (major == null || row.budgetFee ==null) return null
const cost = toFiniteNumber(row.amount)
const basicFee = toFiniteNumber(row.budgetFee)
if (basicFee != null) hasTotalValue = true
const basicFeeBasic = toFiniteNumber(row.budgetFeeBasic)
const basicFeeOptional = toFiniteNumber(row.budgetFeeOptional)
const remark = typeof row.remark === 'string' ? row.remark : ''
@@ -958,15 +1056,16 @@ const buildMethod1 = (rows: ScaleMethodRowLike[] | undefined): ExportMethod1 | n
basicFee_optional: basicFeeOptional ?? 0,
serviceCoe: toFiniteNumberOrZero(row.consultCategoryFactor),
majorCoe: toFiniteNumberOrZero(row.majorFactor),
processCoe: 1,
proportion: 1,
processCoe: toFiniteNumber(row.workStageFactor) ?? 1,
proportion: toFiniteNumber(row.workRatio) ?? 1,
fee: basicFee ?? 0,
remark
}
})
.filter((item): item is ExportMethod1Detail => Boolean(item))
if (det.length === 0) return null
if (det.length === 0 || !hasTotalValue) return null
console.log(det)
return {
cost: sumNumbers(det.map(item => item.cost)),
basicFee: sumNumbers(det.map(item => item.basicFee)),
@@ -979,12 +1078,14 @@ const buildMethod1 = (rows: ScaleMethodRowLike[] | undefined): ExportMethod1 | n
const buildMethod2 = (rows: ScaleMethodRowLike[] | undefined): ExportMethod2 | null => {
if (!Array.isArray(rows)) return null
let hasTotalValue = false
const det = rows
.map(row => {
const major = toSafeInteger(row.id)
if (major == null) return null
if (major == null || row.budgetFee ==null) return null
const area = toFiniteNumber(row.landArea)
const basicFee = toFiniteNumber(row.budgetFee)
if (basicFee != null) hasTotalValue = true
const basicFeeBasic = toFiniteNumber(row.budgetFeeBasic)
const basicFeeOptional = toFiniteNumber(row.budgetFeeOptional)
const remark = typeof row.remark === 'string' ? row.remark : ''
@@ -1005,15 +1106,15 @@ const buildMethod2 = (rows: ScaleMethodRowLike[] | undefined): ExportMethod2 | n
basicFee_optional: basicFeeOptional ?? 0,
serviceCoe: toFiniteNumberOrZero(row.consultCategoryFactor),
majorCoe: toFiniteNumberOrZero(row.majorFactor),
processCoe: 1,
proportion: 1,
processCoe: toFiniteNumber(row.workStageFactor) ?? 1,
proportion: toFiniteNumber(row.workRatio) ?? 1,
fee: basicFee ?? 0,
remark
}
})
.filter((item): item is ExportMethod2Detail => Boolean(item))
if (det.length === 0) return null
if (det.length === 0 || !hasTotalValue) return null
return {
area: sumNumbers(det.map(item => item.area)),
basicFee: sumNumbers(det.map(item => item.basicFee)),
@@ -1026,6 +1127,7 @@ const buildMethod2 = (rows: ScaleMethodRowLike[] | undefined): ExportMethod2 | n
const buildMethod3 = (rows: WorkloadMethodRowLike[] | undefined): ExportMethod3 | null => {
if (!Array.isArray(rows)) return null
let hasTotalValue = false
const det = rows
.map(row => {
const task = getTaskIdFromRowId(row.id)
@@ -1033,6 +1135,7 @@ const buildMethod3 = (rows: WorkloadMethodRowLike[] | undefined): ExportMethod3
const amount = toFiniteNumber(row.workload)
const basicFee = toFiniteNumber(row.basicFee)
const fee = toFiniteNumber(row.serviceFee)
if (fee != null) hasTotalValue = true
const remark = typeof row.remark === 'string' ? row.remark : ''
const hasValue = amount != null || basicFee != null || fee != null || isNonEmptyString(remark)
if (!hasValue) return null
@@ -1048,7 +1151,7 @@ const buildMethod3 = (rows: WorkloadMethodRowLike[] | undefined): ExportMethod3
})
.filter((item): item is ExportMethod3Detail => Boolean(item))
if (det.length === 0) return null
if (det.length === 0 || !hasTotalValue) return null
return {
basicFee: sumNumbers(det.map(item => item.basicFee)),
fee: sumNumbers(det.map(item => item.fee)),
@@ -1058,6 +1161,7 @@ const buildMethod3 = (rows: WorkloadMethodRowLike[] | undefined): ExportMethod3
const buildMethod4 = (rows: HourlyMethodRowLike[] | undefined): ExportMethod4 | null => {
if (!Array.isArray(rows)) return null
let hasTotalValue = false
const det = rows
.map(row => {
const expert = getExpertIdFromRowId(row.id)
@@ -1065,6 +1169,7 @@ const buildMethod4 = (rows: HourlyMethodRowLike[] | undefined): ExportMethod4 |
const personNum = toFiniteNumber(row.personnelCount)
const workDay = toFiniteNumber(row.workdayCount)
const fee = toFiniteNumber(row.serviceBudget)
if (fee != null) hasTotalValue = true
const remark = typeof row.remark === 'string' ? row.remark : ''
const hasValue = personNum != null || workDay != null || fee != null || isNonEmptyString(remark)
if (!hasValue) return null
@@ -1079,7 +1184,7 @@ const buildMethod4 = (rows: HourlyMethodRowLike[] | undefined): ExportMethod4 |
})
.filter((item): item is ExportMethod4Detail => Boolean(item))
if (det.length === 0) return null
if (det.length === 0 || !hasTotalValue) return null
return {
person_num: sumNumbers(det.map(item => item.person_num)),
work_day: sumNumbers(det.map(item => item.work_day)),
@@ -1089,26 +1194,182 @@ const buildMethod4 = (rows: HourlyMethodRowLike[] | undefined): ExportMethod4 |
}
const buildServiceFee = (
row: ZxFwRowLike,
row: ZxFwRowLike | null | undefined,
method1: ExportMethod1 | null,
method2: ExportMethod2 | null,
method3: ExportMethod3 | null,
method4: ExportMethod4 | null
) => {
const subtotal = toFiniteNumber(row.subtotal)
const subtotal = toFiniteNumber(row?.subtotal)
if (subtotal != null) return subtotal
const methodSum = sumNumbers([method1?.fee, method2?.fee, method3?.fee, method4?.fee])
if (methodSum !== 0) return methodSum
return sumNumbers([
toFiniteNumber(row.investScale),
toFiniteNumber(row.landScale),
toFiniteNumber(row.workload),
toFiniteNumber(row.hourly)
toFiniteNumber(row?.investScale),
toFiniteNumber(row?.landScale),
toFiniteNumber(row?.workload),
toFiniteNumber(row?.hourly)
])
}
const createRichTextCode = (...parts: string[]): ExportRichTextCode => ({
richText: parts
.map(item => String(item || '').trim())
.filter(Boolean)
.map(text => ({ text }))
})
const buildMethod0 = (payload: RateMethodRowLike | null | undefined): ExportMethod0 | null => {
const coe = toFiniteNumber(payload?.rate)
const fee = toFiniteNumber(payload?.budgetFee)
if (fee == null) return null
return {
coe: coe ?? 0,
fee
}
}
const buildMethod5 = (rows: QuantityMethodRowLike[] | undefined): ExportMethod5 | null => {
if (!Array.isArray(rows) || rows.length === 0) return null
const subtotalRow = rows.find(row => String(row?.id || '') === 'fee-subtotal-fixed')
const subtotalFee = toFiniteNumber(subtotalRow?.budgetFee)
if (subtotalFee == null) return null
const det = rows
.filter(row => String(row?.id || '') !== 'fee-subtotal-fixed')
.map(row => {
const quantity = toFiniteNumber(row.quantity)
const unitPrice = toFiniteNumber(row.unitPrice)
const fee = toFiniteNumber(row.budgetFee)
const name = typeof row.feeItem === 'string' ? row.feeItem : ''
const unit = typeof row.unit === 'string' ? row.unit : ''
const remark = typeof row.remark === 'string' ? row.remark : ''
const hasValue =
quantity != null ||
unitPrice != null ||
fee != null ||
isNonEmptyString(name) ||
isNonEmptyString(unit) ||
isNonEmptyString(remark)
if (!hasValue) return null
return {
name,
unit,
amount: quantity ?? 0,
price: unitPrice ?? 0,
fee: fee ?? 0,
remark
}
})
.filter((item): item is ExportMethod5Detail => Boolean(item))
if (det.length === 0) return null
return {
fee: subtotalFee,
det
}
}
const normalizeHtFeeMainRows = (rows: HtFeeMainRowLike[] | undefined) => {
if (!Array.isArray(rows)) return [] as Array<{ id: string; name: string }>
return rows
.map(row => {
const id = String(row?.id || '').trim()
if (!id) return null
return {
id,
name: typeof row?.name === 'string' ? row.name : ''
}
})
.filter((item): item is { id: string; name: string } => Boolean(item))
}
const loadHtFeeMethodsByRow = async (mainStorageKey: string, rowId: string) => {
const [rateState, hourlyState, quantityState] = await Promise.all([
zxFwPricingStore.loadHtFeeMethodState<RateMethodRowLike>(mainStorageKey, rowId, 'rate-fee'),
zxFwPricingStore.loadHtFeeMethodState<DetailRowsStorageLike<HourlyMethodRowLike>>(mainStorageKey, rowId, 'hourly-fee'),
zxFwPricingStore.loadHtFeeMethodState<DetailRowsStorageLike<QuantityMethodRowLike>>(mainStorageKey, rowId, 'quantity-unit-price-fee')
])
const m0 = buildMethod0(rateState)
const m4 = buildMethod4(Array.isArray(hourlyState?.detailRows) ? hourlyState?.detailRows : undefined)
const m5 = buildMethod5(Array.isArray(quantityState?.detailRows) ? quantityState?.detailRows : undefined)
if (!m0 && !m4 && !m5) return null
return {
fee: sumNumbers([m0?.fee, m4?.fee, m5?.fee]),
m0,
m4,
m5
}
}
const buildAdditionalDetailCode = (index: number, name: string): ExportRichTextCode => {
const dictionaryIndex = additionalWorkList.findIndex(item => item === name)
const useIndex = dictionaryIndex >= 0 ? dictionaryIndex : index
const suffix = useIndex === 0 ? 'F' : useIndex === 1 ? 'X' : String(useIndex + 1)
return createRichTextCode('C', suffix)
}
const buildAdditionalExport = async (contractId: string): Promise<ExportAdditional | null> => {
const storageKey = `htExtraFee-${contractId}-additional-work`
const mainState = await zxFwPricingStore.loadHtFeeMainState<HtFeeMainRowLike>(storageKey)
const rows = normalizeHtFeeMainRows(mainState?.detailRows)
if (rows.length === 0) return null
const det = (
await Promise.all(
rows.map(async (row, index) => {
const methodPayload = await loadHtFeeMethodsByRow(storageKey, row.id)
if (!methodPayload) return null
const item: ExportAdditionalDetail = {
id: index,
code: buildAdditionalDetailCode(index, row.name),
name: row.name || `附加工作-${index + 1}`,
fee: methodPayload.fee
}
item.ref = item.code
if (methodPayload.m0) item.m0 = methodPayload.m0
if (methodPayload.m4) item.m4 = methodPayload.m4
if (methodPayload.m5) item.m5 = methodPayload.m5
return item
})
)
).filter((item): item is ExportAdditionalDetail => Boolean(item))
if (det.length === 0) return null
const addtionalCode = createRichTextCode('C', 'C')
return {
code: addtionalCode,
ref: addtionalCode,
name: '附加工作',
fee: sumNumbers(det.map(item => item.fee)),
det
}
}
const buildReserveExport = async (contractId: string): Promise<ExportReserve | null> => {
const storageKey = `htExtraFee-${contractId}-reserve`
const mainState = await zxFwPricingStore.loadHtFeeMainState<HtFeeMainRowLike>(storageKey)
const rows = normalizeHtFeeMainRows(mainState?.detailRows)
if (rows.length === 0) return null
for (const row of rows) {
const methodPayload = await loadHtFeeMethodsByRow(storageKey, row.id)
if (!methodPayload) continue
const reserve: ExportReserve = {
code: createRichTextCode('Y', 'B'),
name: row.name || '预备费',
fee: methodPayload.fee
}
reserve.ref = reserve.code
if (methodPayload.m0) reserve.m0 = methodPayload.m0
if (methodPayload.m4) reserve.m4 = methodPayload.m4
if (methodPayload.m5) reserve.m5 = methodPayload.m5
return reserve
}
return null
}
const buildExportReportPayload = async (): Promise<ExportReportPayload> => {
const [projectInfoRaw, projectScaleRaw, consultCategoryFactorRaw, majorFactorRaw, contractCardsRaw] = await Promise.all([
kvStore.getItem<XmInfoLike>(PROJECT_INFO_DB_KEY),
@@ -1120,8 +1381,14 @@ const buildExportReportPayload = async (): Promise<ExportReportPayload> => {
const projectInfo = projectInfoRaw || {}
const projectScaleSource = projectScaleRaw || {}
const projectScale = buildScaleRows(projectScaleSource.detailRows)
const projectScaleCost = sumNumbers(projectScale.map(item => item.cost))
const projectScale = projectScaleSource.roughCalcEnabled ? [] : toExportScaleRows(projectScaleSource.detailRows)
const projectScaleCost = toFiniteNumber(projectScaleSource.totalAmount) ?? sumNumbers(projectScale.map(item => item.cost))
projectScale.push({
major: -1, cost: projectScaleCost,
area: null
})
const projectServiceCoes = buildProjectServiceCoes(consultCategoryFactorRaw?.detailRows)
const projectMajorCoes = buildProjectMajorCoes(majorFactorRaw?.detailRows)
const projectName = isNonEmptyString(projectInfo.projectName) ? projectInfo.projectName.trim() : '造价项目'
@@ -1139,21 +1406,59 @@ const buildExportReportPayload = async (): Promise<ExportReportPayload> => {
for (let index = 0; index < contractCards.length; index++) {
const contract = contractCards[index]
const contractId = contract.id
const [htInfoRaw, zxFwRaw] = await Promise.all([
await zxFwPricingStore.loadContract(contractId)
const [htInfoRaw, zxFwRaw, htConsultCategoryFactorRaw, htMajorFactorRaw] = await Promise.all([
kvStore.getItem<DetailRowsStorageLike<ScaleRowLike>>(`ht-info-v3-${contractId}`),
kvStore.getItem<ZxFwStorageLike>(`zxFW-${contractId}`)
kvStore.getItem<ZxFwStorageLike>(`zxFW-${contractId}`),
kvStore.getItem<DetailRowsStorageLike<FactorRowLike>>(`ht-consult-category-factor-v1-${contractId}`),
kvStore.getItem<DetailRowsStorageLike<FactorRowLike>>(`ht-major-factor-v1-${contractId}`)
])
const zxRows = Array.isArray(zxFwRaw?.detailRows) ? zxFwRaw.detailRows : []
const fixedRow = zxRows.find(row => row.id === 'fixed-budget-c')
const serviceRows = zxRows.filter(row => row.id !== 'fixed-budget-c' && hasServiceId(String(row.id)))
const contractState = zxFwPricingStore.getContractState(contractId)
const zxRowsFromStore: ZxFwRowLike[] = Array.isArray(contractState?.detailRows)
? contractState.detailRows.map(row => ({
id: String(row.id || ''),
process: row.process,
subtotal: row.subtotal,
investScale: row.investScale,
landScale: row.landScale,
workload: row.workload,
hourly: row.hourly
}))
: []
const zxRowsFromKv = Array.isArray(zxFwRaw?.detailRows) ? zxFwRaw.detailRows : []
const zxRows = zxRowsFromStore.length > 0 ? zxRowsFromStore : zxRowsFromKv
const selectedIdsFromStore = Array.isArray(contractState?.selectedIds)
? contractState.selectedIds.map(id => String(id || '').trim()).filter(Boolean)
: []
const selectedIdsFromKv = Array.isArray(zxFwRaw?.selectedIds)
? zxFwRaw.selectedIds.map(id => String(id || '').trim()).filter(Boolean)
: []
const selectedIds = Array.from(new Set([...selectedIdsFromStore, ...selectedIdsFromKv])).filter(hasServiceId)
let fixedRow: ZxFwRowLike | undefined
const serviceRowMap = new Map<string, ZxFwRowLike>()
for (const row of zxRows) {
const rowId = String(row?.id || '').trim()
if (!rowId) continue
if (rowId === 'fixed-budget-c') {
fixedRow = row
continue
}
if (!hasServiceId(rowId)) continue
serviceRowMap.set(rowId, row)
}
const fallbackServiceIds = Array.from(serviceRowMap.keys())
const serviceIdTexts = sortServiceIdsByDict(
(selectedIds.length > 0 ? selectedIds : fallbackServiceIds).filter(hasServiceId)
)
const services = (
await Promise.all(
serviceRows.map(async row => {
const serviceIdText = String(row.id)
serviceIdTexts.map(async serviceIdText => {
const serviceId = toSafeInteger(serviceIdText)
if (serviceId == null) return null
const sourceRow = serviceRowMap.get(serviceIdText)
const [method1State, method2State, method3State, method4State] = await Promise.all([
zxFwPricingStore.loadServicePricingMethodState<ScaleMethodRowLike>(contractId, serviceIdText, 'investScale'),
@@ -1170,11 +1475,11 @@ const buildExportReportPayload = async (): Promise<ExportReportPayload> => {
const method2 = buildMethod2(method2Raw?.detailRows)
const method3 = buildMethod3(method3Raw?.detailRows)
const method4 = buildMethod4(method4Raw?.detailRows)
const fee = buildServiceFee(row, method1, method2, method3, method4)
const fee = buildServiceFee(sourceRow, method1, method2, method3, method4)
const process = Number(sourceRow?.process) === 1 ? 1 : 0
const service: ExportService = {
id: serviceId,
process: 0,
process,
fee
}
if (method1) service.method1 = method1
@@ -1195,9 +1500,21 @@ const buildExportReportPayload = async (): Promise<ExportReportPayload> => {
toFiniteNumber(fixedRow?.hourly)
])
const serviceFee = fixedSubtotal ?? (serviceFeeSum !== 0 ? serviceFeeSum : fixedMethodSum)
const addtionalFee = 0
const reserveFee = 0
const contractFee = serviceFee + addtionalFee + reserveFee
const [addtional, reserve] = await Promise.all([
buildAdditionalExport(contractId),
buildReserveExport(contractId)
])
const addtionalFee = addtional ? addtional.fee : 0
const reserveFee = reserve ? reserve.fee : 0
const contractFee = roundTo(addNumbers(serviceFee, addtionalFee, reserveFee), 3)
const contractScale = htInfoRaw?.roughCalcEnabled ? [] : toExportScaleRows(htInfoRaw?.detailRows)
contractScale.push({
major: -1, cost: contractFee,
area: null
})
const contractServiceCoesRaw = buildProjectServiceCoes(htConsultCategoryFactorRaw?.detailRows)
const contractMajorCoesRaw = buildProjectMajorCoes(htMajorFactorRaw?.detailRows)
contracts.push({
name: isNonEmptyString(contract.name) ? contract.name : `合同段-${index + 1}`,
@@ -1205,12 +1522,12 @@ const buildExportReportPayload = async (): Promise<ExportReportPayload> => {
addtionalFee,
reserveFee,
fee: contractFee,
scale: buildScaleRows(htInfoRaw?.detailRows),
serviceCoes: projectServiceCoes.map(item => ({ ...item })),
majorCoes: projectMajorCoes.map(item => ({ ...item })),
scale: contractScale,
serviceCoes: contractServiceCoesRaw,
majorCoes: contractMajorCoesRaw,
services,
addtional: [],
reserve: []
addtional,
reserve
})
}
@@ -1273,11 +1590,12 @@ const exportReport = async () => {
try {
const now = new Date()
const payload = await buildExportReportPayload()
console.log(payload)
const fileName = `${sanitizeFileNamePart(payload.name)}-报表-${formatExportTimestamp(now)}`
await exportFile(fileName, payload)
} catch (error) {
console.error('export report failed:', error)
window.alert('导出报表失败,请重试。')
// window.alert('导出报表失败,请重试。')
} finally {
dataMenuOpen.value = false
}