This commit is contained in:
wintsa 2026-03-12 10:38:58 +08:00
parent cd107604a9
commit f4c768df29
6 changed files with 37 additions and 25 deletions

View File

@ -167,9 +167,11 @@ const syncComputedValuesToRows = () => {
let hasValidRow = false
for (const row of detailRows.value) {
if (isSubtotalRow(row)) continue
const hasFeeItem = typeof row.feeItem === 'string' && row.feeItem.trim() !== ''
const hasUnit = typeof row.unit === 'string' && row.unit.trim() !== ''
const quantity = typeof row.quantity === 'number' && Number.isFinite(row.quantity) ? row.quantity : null
const unitPrice = typeof row.unitPrice === 'number' && Number.isFinite(row.unitPrice) ? row.unitPrice : null
if (quantity == null || unitPrice == null) {
if (!hasFeeItem || !hasUnit || quantity == null || unitPrice == null) {
row.budgetFee = null
continue
}

View File

@ -129,7 +129,9 @@ const loadContractServiceFeeBase = async (): Promise<number | null> => {
}
const sumHourlyMethodFee = (state: MethodHourlyState | null): number | null => {
const rows = Array.isArray(state?.detailRows) ? state.detailRows : []
const rows=state?.detailRows?state?.detailRows?.filter(e=>e.serviceBudget!== null):[]
if (rows.length === 0) return null
let total = 0
@ -154,7 +156,7 @@ const sumHourlyMethodFee = (state: MethodHourlyState | null): number | null => {
}
const sumQuantityMethodFee = (state: MethodQuantityState | null): number | null => {
const rows = Array.isArray(state?.detailRows) ? state.detailRows : []
const rows=state?.detailRows?state?.detailRows?.filter(e=>e.budgetFee!== null):[]
if (rows.length === 0) return null
let total = 0
@ -196,6 +198,7 @@ const hydrateRowsFromMethodStores = async (rows: FeeMethodRow[]): Promise<FeeMet
: storedRateFee != null
? round3(storedRateFee)
: null
const hourlyFee = sumHourlyMethodFee(hourlyData)
const quantityUnitPriceFee = sumQuantityMethodFee(quantityData)

View File

@ -309,7 +309,7 @@ interface ExportMethod5 {
interface ExportAdditionalDetail {
id: number
ref?: unknown
code?: unknown
name: string
fee: number
m0?: ExportMethod0
@ -318,14 +318,14 @@ interface ExportAdditionalDetail {
}
interface ExportAdditional {
ref?: unknown
code?: unknown
name: string
fee: number
det: ExportAdditionalDetail[]
}
interface ExportReserve {
ref?: unknown
code?: unknown
name: string
fee: number
m0?: ExportMethod0
@ -1223,11 +1223,10 @@ const buildMethod0 = (payload: RateMethodRowLike | null | undefined): ExportMeth
}
const buildMethod5 = (rows: QuantityMethodRowLike[] | undefined): ExportMethod5 | null => {
console.log(rows)
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 || subtotalRow?.budgetFee == null) return null
if (subtotalFee == null ) return null
const det = rows
.filter(row => String(row?.id || '') !== 'fee-subtotal-fixed')
.map(row => {
@ -1237,20 +1236,14 @@ const buildMethod5 = (rows: QuantityMethodRowLike[] | undefined): ExportMethod5
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
if (row.budgetFee==null) return null
return {
name,
unit,
amount: quantity ?? 0,
price: unitPrice ?? 0,
fee: fee ?? 0,
amount: quantity ,
price: unitPrice ,
fee: fee ,
remark
}
})
@ -1317,7 +1310,7 @@ const buildAdditionalExport = async (contractId: string): Promise<ExportAddition
if (!methodPayload) return null
const item: ExportAdditionalDetail = {
id: index,
ref: { richText: [{ font: { charset: 134, color: { theme: 1 }, italic: true, name: '宋体', size: 10 }, text: 'C' }, { font: { charset: 134, color: { theme: 1 }, italic: true, name: 'Calibri', size: 10, vertAlign: 'subscript' }, text: 'F' }] },
code: { richText: [{ font: { charset: 134, color: { theme: 1 }, italic: true, name: '宋体', size: 10 }, text: 'C' }, { font: { charset: 134, color: { theme: 1 }, italic: true, name: 'Calibri', size: 10, vertAlign: 'subscript' }, text: 'F' }] },
name: row.name,
fee: methodPayload.fee
@ -1332,7 +1325,7 @@ const buildAdditionalExport = async (contractId: string): Promise<ExportAddition
if (det.length === 0) return null
return {
ref: { richText: [{ font: { charset: 134, color: { theme: 1 }, italic: true, name: '宋体', size: 10 }, text: 'C' }, { font: { charset: 134, color: { theme: 1 }, italic: true, name: 'Calibri', size: 10, vertAlign: 'subscript' }, text: 'C' }] },
code: { richText: [{ font: { charset: 134, color: { theme: 1 }, italic: true, name: '宋体', size: 10 }, text: 'C' }, { font: { charset: 134, color: { theme: 1 }, italic: true, name: 'Calibri', size: 10, vertAlign: 'subscript' }, text: 'C' }] },
name: '附加工作',
fee: sumNumbers(det.map(item => item.fee)),
@ -1581,8 +1574,8 @@ const exportReport = async () => {
try {
const now = new Date()
const payload = await buildExportReportPayload()
console.log(payload)
const fileName = `${sanitizeFileNamePart(payload.name)}-报表-${formatExportTimestamp(now)}`
console.log(payload)
await exportFile(fileName, payload)
} catch (error) {
console.error('export report failed:', error)

View File

@ -50,6 +50,19 @@ const resolvePersistOptions = (persist: PersistOption | undefined) => {
return persist
}
const trimStringValuesDeep = (value: unknown): unknown => {
if (typeof value === 'string') return value.trim()
if (Array.isArray(value)) return value.map(item => trimStringValuesDeep(item))
if (value && typeof value === 'object') {
const normalized: Record<string, unknown> = {}
for (const [key, child] of Object.entries(value as Record<string, unknown>)) {
normalized[key] = trimStringValuesDeep(child)
}
return normalized
}
return value
}
export default (config?: PiniaStorageConfig) => {
const finalConfig = { ...baseConfig, ...(config || {}) }
const { mode = 'single', debounce = 300, ...forageConfig } = finalConfig
@ -67,7 +80,10 @@ export default (config?: PiniaStorageConfig) => {
let timer: ReturnType<typeof setTimeout> | null = null
let hydrating = false
let userMutatedBeforeHydrate = false
const writeState = (state: unknown) => lf.setItem(key, JSON.parse(JSON.stringify(state)))
const writeState = (state: unknown) => {
const clonedState = JSON.parse(JSON.stringify(state))
return lf.setItem(key, trimStringValuesDeep(clonedState))
}
const storeExt = context.store as typeof context.store & PersistStoreExt
storeExt.$persistNow = async () => {

View File

@ -65,7 +65,6 @@ export const useTabStore = defineStore(
const closeAllTabs = () => {
tabs.value = createDefaultTabs()
console.log(tabs.value)
activeTabId.value = HOME_TAB_ID
}

View File

@ -728,7 +728,6 @@ async function generateTemplate(data) {
data.contracts[4].reserve = null;
// data.contracts[5].addtional = null;
// data.contracts[5].reserve = null;
console.log(data)
try {
// 获取模板
let templateExcel = 'template20260226001test010';