fix someone
This commit is contained in:
1 parent
c482faacbf
commit
ad4e9cdee0
17 files changed
+1084
-311
No files matched your search
@@ -55,10 +55,14 @@ interface DetailRow {
|
||||
benchmarkBudget: number | null
|
||||
benchmarkBudgetBasic: number | null
|
||||
benchmarkBudgetOptional: number | null
|
||||
benchmarkBudgetBasicChecked: boolean
|
||||
benchmarkBudgetOptionalChecked: boolean
|
||||
basicFormula: string
|
||||
optionalFormula: string
|
||||
consultCategoryFactor: number | null
|
||||
majorFactor: number | null
|
||||
workStageFactor: number | null
|
||||
workRatio: number | null
|
||||
budgetFee: number | null
|
||||
budgetFeeBasic: number | null
|
||||
budgetFeeOptional: number | null
|
||||
@@ -80,6 +84,8 @@ const props = defineProps<{
|
||||
}>()
|
||||
const DB_KEY = computed(() => `tzGMF-${props.contractId}-${props.serviceId}`)
|
||||
const HT_DB_KEY = computed(() => `ht-info-v3-${props.contractId}`)
|
||||
const HT_CONSULT_FACTOR_KEY = computed(() => `ht-consult-category-factor-v1-${props.contractId}`)
|
||||
const HT_MAJOR_FACTOR_KEY = computed(() => `ht-major-factor-v1-${props.contractId}`)
|
||||
const BASE_INFO_KEY = 'xm-base-info-v1'
|
||||
const activeIndustryCode = ref('')
|
||||
const PRICING_CLEAR_SKIP_PREFIX = 'pricing-clear-skip:'
|
||||
@@ -97,8 +103,8 @@ const getDefaultMajorFactorById = (id: string): number | null => majorFactorMap.
|
||||
|
||||
const loadFactorDefaults = async () => {
|
||||
const [consultMap, majorMap] = await Promise.all([
|
||||
loadConsultCategoryFactorMap(),
|
||||
loadMajorFactorMap()
|
||||
loadConsultCategoryFactorMap(HT_CONSULT_FACTOR_KEY.value),
|
||||
loadMajorFactorMap(HT_MAJOR_FACTOR_KEY.value)
|
||||
])
|
||||
consultCategoryFactorMap.value = consultMap
|
||||
majorFactorMap.value = majorMap
|
||||
@@ -216,10 +222,14 @@ const buildDefaultRows = (): DetailRow[] => {
|
||||
benchmarkBudget: null,
|
||||
benchmarkBudgetBasic: null,
|
||||
benchmarkBudgetOptional: null,
|
||||
benchmarkBudgetBasicChecked: true,
|
||||
benchmarkBudgetOptionalChecked: true,
|
||||
basicFormula: '',
|
||||
optionalFormula: '',
|
||||
consultCategoryFactor: null,
|
||||
majorFactor: null,
|
||||
workStageFactor: 1,
|
||||
workRatio: 100,
|
||||
budgetFee: null,
|
||||
budgetFeeBasic: null,
|
||||
budgetFeeOptional: null,
|
||||
@@ -239,10 +249,14 @@ type SourceRow = Pick<DetailRow, 'id'> &
|
||||
| 'benchmarkBudget'
|
||||
| 'benchmarkBudgetBasic'
|
||||
| 'benchmarkBudgetOptional'
|
||||
| 'benchmarkBudgetBasicChecked'
|
||||
| 'benchmarkBudgetOptionalChecked'
|
||||
| 'basicFormula'
|
||||
| 'optionalFormula'
|
||||
| 'consultCategoryFactor'
|
||||
| 'majorFactor'
|
||||
| 'workStageFactor'
|
||||
| 'workRatio'
|
||||
| 'budgetFee'
|
||||
| 'budgetFeeBasic'
|
||||
| 'budgetFeeOptional'
|
||||
@@ -277,6 +291,10 @@ const mergeWithDictRows = (
|
||||
benchmarkBudget: typeof fromDb.benchmarkBudget === 'number' ? fromDb.benchmarkBudget : null,
|
||||
benchmarkBudgetBasic: typeof fromDb.benchmarkBudgetBasic === 'number' ? fromDb.benchmarkBudgetBasic : null,
|
||||
benchmarkBudgetOptional: typeof fromDb.benchmarkBudgetOptional === 'number' ? fromDb.benchmarkBudgetOptional : null,
|
||||
benchmarkBudgetBasicChecked:
|
||||
typeof fromDb.benchmarkBudgetBasicChecked === 'boolean' ? fromDb.benchmarkBudgetBasicChecked : true,
|
||||
benchmarkBudgetOptionalChecked:
|
||||
typeof fromDb.benchmarkBudgetOptionalChecked === 'boolean' ? fromDb.benchmarkBudgetOptionalChecked : true,
|
||||
basicFormula: typeof fromDb.basicFormula === 'string' ? fromDb.basicFormula : '',
|
||||
optionalFormula: typeof fromDb.optionalFormula === 'string' ? fromDb.optionalFormula : '',
|
||||
consultCategoryFactor:
|
||||
@@ -295,6 +313,8 @@ const mergeWithDictRows = (
|
||||
: hasMajorFactor
|
||||
? null
|
||||
: getDefaultMajorFactorById(row.id),
|
||||
workStageFactor: typeof fromDb.workStageFactor === 'number' ? fromDb.workStageFactor : row.workStageFactor,
|
||||
workRatio: typeof fromDb.workRatio === 'number' ? fromDb.workRatio : row.workRatio,
|
||||
budgetFee: typeof fromDb.budgetFee === 'number' ? fromDb.budgetFee : null,
|
||||
budgetFeeBasic: typeof fromDb.budgetFeeBasic === 'number' ? fromDb.budgetFeeBasic : null,
|
||||
budgetFeeOptional: typeof fromDb.budgetFeeOptional === 'number' ? fromDb.budgetFeeOptional : null,
|
||||
@@ -335,10 +355,46 @@ const formatReadonlyMoney = (params: any) => {
|
||||
return formatThousands(roundTo(params.value, 2))
|
||||
}
|
||||
|
||||
type BudgetCheckField = 'benchmarkBudgetBasicChecked' | 'benchmarkBudgetOptionalChecked'
|
||||
|
||||
const createBudgetCellRendererWithCheck = (checkField: BudgetCheckField) => (params: any) => {
|
||||
const valueText = formatReadonlyMoney(params)
|
||||
const hasValue = params.value != null && params.value !== ''
|
||||
if (params.node?.group || params.node?.rowPinned || !params.data || !hasValue) {
|
||||
return valueText
|
||||
}
|
||||
|
||||
const wrapper = document.createElement('div')
|
||||
wrapper.style.display = 'flex'
|
||||
wrapper.style.alignItems = 'center'
|
||||
wrapper.style.justifyContent = 'flex-end'
|
||||
wrapper.style.gap = '6px'
|
||||
wrapper.style.width = '100%'
|
||||
|
||||
const checkbox = document.createElement('input')
|
||||
checkbox.type = 'checkbox'
|
||||
checkbox.className = 'cursor-pointer'
|
||||
|
||||
checkbox.checked = params.data[checkField] !== false
|
||||
checkbox.addEventListener('click', event => event.stopPropagation())
|
||||
checkbox.addEventListener('change', () => {
|
||||
params.data[checkField] = checkbox.checked
|
||||
handleCellValueChanged()
|
||||
})
|
||||
|
||||
const valueSpan = document.createElement('span')
|
||||
valueSpan.textContent = valueText
|
||||
wrapper.append(checkbox, valueSpan)
|
||||
|
||||
return wrapper
|
||||
}
|
||||
|
||||
const getBenchmarkBudgetSplitByAmount = (row?: Pick<DetailRow, 'amount'>) =>
|
||||
getBenchmarkBudgetSplitByScale(row?.amount, 'cost')
|
||||
|
||||
const getBudgetFee = (row?: Pick<DetailRow, 'amount' | 'majorFactor' | 'consultCategoryFactor'>) => {
|
||||
const getBudgetFee = (
|
||||
row?: Pick<DetailRow, 'amount' | 'majorFactor' | 'consultCategoryFactor' | 'workStageFactor' | 'workRatio'>
|
||||
) => {
|
||||
const benchmarkBudgetSplit = getBenchmarkBudgetSplitByAmount(row)
|
||||
if (!benchmarkBudgetSplit) return null
|
||||
|
||||
@@ -346,19 +402,25 @@ const getBudgetFee = (row?: Pick<DetailRow, 'amount' | 'majorFactor' | 'consultC
|
||||
benchmarkBudgetBasic: benchmarkBudgetSplit.basic,
|
||||
benchmarkBudgetOptional: benchmarkBudgetSplit.optional,
|
||||
majorFactor: row?.majorFactor,
|
||||
consultCategoryFactor: row?.consultCategoryFactor
|
||||
consultCategoryFactor: row?.consultCategoryFactor,
|
||||
workStageFactor: row?.workStageFactor,
|
||||
workRatio: row?.workRatio
|
||||
})
|
||||
return splitBudgetFee ? splitBudgetFee.total : null
|
||||
}
|
||||
|
||||
const getBudgetFeeSplit = (row?: Pick<DetailRow, 'amount' | 'majorFactor' | 'consultCategoryFactor'>) => {
|
||||
const getBudgetFeeSplit = (
|
||||
row?: Pick<DetailRow, 'amount' | 'majorFactor' | 'consultCategoryFactor' | 'workStageFactor' | 'workRatio'>
|
||||
) => {
|
||||
const benchmarkBudgetSplit = getBenchmarkBudgetSplitByAmount(row)
|
||||
if (!benchmarkBudgetSplit) return null
|
||||
return getScaleBudgetFeeSplit({
|
||||
benchmarkBudgetBasic: benchmarkBudgetSplit.basic,
|
||||
benchmarkBudgetOptional: benchmarkBudgetSplit.optional,
|
||||
majorFactor: row?.majorFactor,
|
||||
consultCategoryFactor: row?.consultCategoryFactor
|
||||
consultCategoryFactor: row?.consultCategoryFactor,
|
||||
workStageFactor: row?.workStageFactor,
|
||||
workRatio: row?.workRatio
|
||||
})
|
||||
}
|
||||
|
||||
@@ -367,7 +429,7 @@ const columnDefs: Array<ColDef<DetailRow> | ColGroupDef<DetailRow>> = [
|
||||
headerName: '造价金额(万元)',
|
||||
field: 'amount',
|
||||
headerClass: 'ag-right-aligned-header',
|
||||
minWidth: 100,
|
||||
minWidth: 90,
|
||||
flex: 2,
|
||||
|
||||
editable: params => !params.node?.group && !params.node?.rowPinned && Boolean(params.data?.hasCost),
|
||||
@@ -383,37 +445,6 @@ const columnDefs: Array<ColDef<DetailRow> | ColGroupDef<DetailRow>> = [
|
||||
valueParser: params => parseNumberOrNull(params.newValue, { precision: 2 }),
|
||||
valueFormatter: formatEditableMoney
|
||||
},
|
||||
|
||||
{
|
||||
headerName: '咨询分类系数',
|
||||
field: 'consultCategoryFactor',
|
||||
width: 80,
|
||||
minWidth: 70,
|
||||
maxWidth: 90,
|
||||
editable: params => !params.node?.group && !params.node?.rowPinned,
|
||||
cellClass: params => (!params.node?.group && !params.node?.rowPinned ? 'editable-cell-line' : ''),
|
||||
cellClassRules: {
|
||||
'editable-cell-empty': params =>
|
||||
!params.node?.group && !params.node?.rowPinned && (params.value == null || params.value === '')
|
||||
},
|
||||
valueParser: params => parseNumberOrNull(params.newValue, { precision: 2 }),
|
||||
valueFormatter: formatConsultCategoryFactor
|
||||
},
|
||||
{
|
||||
headerName: '专业系数',
|
||||
field: 'majorFactor',
|
||||
width: 80,
|
||||
minWidth: 70,
|
||||
maxWidth: 90,
|
||||
editable: params => !params.node?.group && !params.node?.rowPinned,
|
||||
cellClass: params => (!params.node?.group && !params.node?.rowPinned ? 'editable-cell-line' : ''),
|
||||
cellClassRules: {
|
||||
'editable-cell-empty': params =>
|
||||
!params.node?.group && !params.node?.rowPinned && (params.value == null || params.value === '')
|
||||
},
|
||||
valueParser: params => parseNumberOrNull(params.newValue, { precision: 2 }),
|
||||
valueFormatter: formatMajorFactor
|
||||
},
|
||||
{
|
||||
headerName: '基准预算(元)',
|
||||
marryChildren: true,
|
||||
@@ -431,6 +462,7 @@ const columnDefs: Array<ColDef<DetailRow> | ColGroupDef<DetailRow>> = [
|
||||
params.node?.rowPinned
|
||||
? params.data?.benchmarkBudgetBasic ?? null
|
||||
: getBenchmarkBudgetSplitByAmount(params.data)?.basic ?? null,
|
||||
cellRenderer: createBudgetCellRendererWithCheck('benchmarkBudgetBasicChecked'),
|
||||
valueFormatter: formatReadonlyMoney
|
||||
},
|
||||
{
|
||||
@@ -446,6 +478,22 @@ const columnDefs: Array<ColDef<DetailRow> | ColGroupDef<DetailRow>> = [
|
||||
params.node?.rowPinned
|
||||
? params.data?.benchmarkBudgetOptional ?? null
|
||||
: getBenchmarkBudgetSplitByAmount(params.data)?.optional ?? null,
|
||||
cellRenderer: createBudgetCellRendererWithCheck('benchmarkBudgetOptionalChecked'),
|
||||
valueFormatter: formatReadonlyMoney
|
||||
},
|
||||
{
|
||||
headerName: '小计',
|
||||
field: 'benchmarkBudget',
|
||||
colId: 'benchmarkBudgetTotal',
|
||||
headerClass: 'ag-right-aligned-header',
|
||||
minWidth: 100,
|
||||
flex: 1,
|
||||
cellClass: 'ag-right-aligned-cell',
|
||||
aggFunc: decimalAggSum,
|
||||
valueGetter: params =>
|
||||
params.node?.rowPinned
|
||||
? params.data?.benchmarkBudget ?? null
|
||||
: getBenchmarkBudgetSplitByAmount(params.data)?.total ?? null,
|
||||
valueFormatter: formatReadonlyMoney
|
||||
}
|
||||
]
|
||||
@@ -455,41 +503,71 @@ const columnDefs: Array<ColDef<DetailRow> | ColGroupDef<DetailRow>> = [
|
||||
marryChildren: true,
|
||||
children: [
|
||||
{
|
||||
headerName: '基本工作',
|
||||
field: 'budgetFeeBasic',
|
||||
colId: 'budgetFeeBasic',
|
||||
headerClass: 'ag-right-aligned-header',
|
||||
minWidth: 120,
|
||||
headerName: '咨询分类系数',
|
||||
field: 'consultCategoryFactor',
|
||||
colId: 'consultCategoryFactor',
|
||||
minWidth: 80,
|
||||
flex: 1,
|
||||
cellClass: 'ag-right-aligned-cell',
|
||||
aggFunc: decimalAggSum,
|
||||
valueGetter: params =>
|
||||
params.node?.rowPinned
|
||||
? params.data?.budgetFeeBasic ?? null
|
||||
: getBudgetFeeSplit(params.data)?.basic ?? null,
|
||||
valueFormatter: formatReadonlyMoney
|
||||
editable: params => !params.node?.group && !params.node?.rowPinned,
|
||||
cellClass: params => (!params.node?.group && !params.node?.rowPinned ? 'editable-cell-line' : ''),
|
||||
cellClassRules: {
|
||||
'editable-cell-empty': params =>
|
||||
!params.node?.group && !params.node?.rowPinned && (params.value == null || params.value === '')
|
||||
},
|
||||
valueParser: params => parseNumberOrNull(params.newValue, { precision: 2 }),
|
||||
valueFormatter: formatConsultCategoryFactor
|
||||
},
|
||||
{
|
||||
headerName: '可选工作',
|
||||
field: 'budgetFeeOptional',
|
||||
colId: 'budgetFeeOptional',
|
||||
headerClass: 'ag-right-aligned-header',
|
||||
minWidth: 120,
|
||||
headerName: '专业系数',
|
||||
field: 'majorFactor',
|
||||
colId: 'majorFactor',
|
||||
minWidth: 80,
|
||||
flex: 1,
|
||||
cellClass: 'ag-right-aligned-cell',
|
||||
aggFunc: decimalAggSum,
|
||||
valueGetter: params =>
|
||||
params.node?.rowPinned
|
||||
? params.data?.budgetFeeOptional ?? null
|
||||
: getBudgetFeeSplit(params.data)?.optional ?? null,
|
||||
valueFormatter: formatReadonlyMoney
|
||||
editable: params => !params.node?.group && !params.node?.rowPinned,
|
||||
cellClass: params => (!params.node?.group && !params.node?.rowPinned ? 'editable-cell-line' : ''),
|
||||
cellClassRules: {
|
||||
'editable-cell-empty': params =>
|
||||
!params.node?.group && !params.node?.rowPinned && (params.value == null || params.value === '')
|
||||
},
|
||||
valueParser: params => parseNumberOrNull(params.newValue, { precision: 2 }),
|
||||
valueFormatter: formatMajorFactor
|
||||
},
|
||||
{
|
||||
headerName: '工作环节系数(编审系数)',
|
||||
field: 'workStageFactor',
|
||||
colId: 'workStageFactor',
|
||||
minWidth: 80,
|
||||
flex: 1,
|
||||
editable: params => !params.node?.group && !params.node?.rowPinned,
|
||||
cellClass: params => (!params.node?.group && !params.node?.rowPinned ? 'editable-cell-line' : ''),
|
||||
cellClassRules: {
|
||||
'editable-cell-empty': params =>
|
||||
!params.node?.group && !params.node?.rowPinned && (params.value == null || params.value === '')
|
||||
},
|
||||
valueParser: params => parseNumberOrNull(params.newValue, { precision: 2 }),
|
||||
valueFormatter: formatEditableNumber
|
||||
},
|
||||
{
|
||||
headerName: '工作占比(%)',
|
||||
field: 'workRatio',
|
||||
colId: 'workRatio',
|
||||
minWidth: 80,
|
||||
flex: 1,
|
||||
editable: params => !params.node?.group && !params.node?.rowPinned,
|
||||
cellClass: params => (!params.node?.group && !params.node?.rowPinned ? 'editable-cell-line' : ''),
|
||||
cellClassRules: {
|
||||
'editable-cell-empty': params =>
|
||||
!params.node?.group && !params.node?.rowPinned && (params.value == null || params.value === '')
|
||||
},
|
||||
valueParser: params => parseNumberOrNull(params.newValue, { precision: 2 }),
|
||||
valueFormatter: formatEditableNumber
|
||||
},
|
||||
{
|
||||
headerName: '合计',
|
||||
field: 'budgetFee',
|
||||
colId: 'budgetFeeTotal',
|
||||
headerClass: 'ag-right-aligned-header',
|
||||
minWidth: 130,
|
||||
minWidth: 120,
|
||||
flex: 1,
|
||||
cellClass: 'ag-right-aligned-cell',
|
||||
aggFunc: decimalAggSum,
|
||||
@@ -501,7 +579,7 @@ const columnDefs: Array<ColDef<DetailRow> | ColGroupDef<DetailRow>> = [
|
||||
{
|
||||
headerName: '说明',
|
||||
field: 'remark',
|
||||
minWidth: 180,
|
||||
minWidth: 100,
|
||||
flex: 1.2,
|
||||
cellEditor: 'agLargeTextCellEditor',
|
||||
wrapText: true,
|
||||
@@ -570,10 +648,14 @@ const pinnedTopRowData = computed(() => [
|
||||
benchmarkBudget: totalBenchmarkBudget.value,
|
||||
benchmarkBudgetBasic: totalBenchmarkBudgetBasic.value,
|
||||
benchmarkBudgetOptional: totalBenchmarkBudgetOptional.value,
|
||||
benchmarkBudgetBasicChecked: true,
|
||||
benchmarkBudgetOptionalChecked: true,
|
||||
basicFormula: '',
|
||||
optionalFormula: '',
|
||||
consultCategoryFactor: null,
|
||||
majorFactor: null,
|
||||
workStageFactor: null,
|
||||
workRatio: null,
|
||||
budgetFee: totalBudgetFee.value,
|
||||
budgetFeeBasic: totalBudgetFeeBasic.value,
|
||||
budgetFeeOptional: totalBudgetFeeOptional.value,
|
||||
@@ -582,30 +664,35 @@ const pinnedTopRowData = computed(() => [
|
||||
}
|
||||
])
|
||||
|
||||
const buildPersistDetailRows = () =>
|
||||
detailRows.value.map(row => {
|
||||
const syncComputedValuesToDetailRows = () => {
|
||||
for (const row of detailRows.value) {
|
||||
const benchmarkBudgetSplit = getBenchmarkBudgetSplitByAmount(row)
|
||||
const budgetFeeSplit = benchmarkBudgetSplit
|
||||
? getScaleBudgetFeeSplit({
|
||||
benchmarkBudgetBasic: benchmarkBudgetSplit.basic,
|
||||
benchmarkBudgetOptional: benchmarkBudgetSplit.optional,
|
||||
majorFactor: row.majorFactor,
|
||||
consultCategoryFactor: row.consultCategoryFactor
|
||||
consultCategoryFactor: row.consultCategoryFactor,
|
||||
workStageFactor: row.workStageFactor,
|
||||
workRatio: row.workRatio
|
||||
})
|
||||
: null
|
||||
|
||||
return {
|
||||
...row,
|
||||
benchmarkBudget: benchmarkBudgetSplit?.total ?? null,
|
||||
benchmarkBudgetBasic: benchmarkBudgetSplit?.basic ?? null,
|
||||
benchmarkBudgetOptional: benchmarkBudgetSplit?.optional ?? null,
|
||||
basicFormula: benchmarkBudgetSplit?.basicFormula ?? '',
|
||||
optionalFormula: benchmarkBudgetSplit?.optionalFormula ?? '',
|
||||
budgetFee: budgetFeeSplit?.total ?? null,
|
||||
budgetFeeBasic: budgetFeeSplit?.basic ?? null,
|
||||
budgetFeeOptional: budgetFeeSplit?.optional ?? null
|
||||
}
|
||||
})
|
||||
row.benchmarkBudget = benchmarkBudgetSplit?.total ?? null
|
||||
row.benchmarkBudgetBasic = benchmarkBudgetSplit?.basic ?? null
|
||||
row.benchmarkBudgetOptional = benchmarkBudgetSplit?.optional ?? null
|
||||
row.basicFormula = benchmarkBudgetSplit?.basicFormula ?? ''
|
||||
row.optionalFormula = benchmarkBudgetSplit?.optionalFormula ?? ''
|
||||
row.budgetFee = budgetFeeSplit?.total ?? null
|
||||
row.budgetFeeBasic = budgetFeeSplit?.basic ?? null
|
||||
row.budgetFeeOptional = budgetFeeSplit?.optional ?? null
|
||||
}
|
||||
}
|
||||
|
||||
const buildPersistDetailRows = () => {
|
||||
syncComputedValuesToDetailRows()
|
||||
return detailRows.value.map(row => ({ ...row }))
|
||||
}
|
||||
|
||||
const saveToIndexedDB = async () => {
|
||||
if (shouldSkipPersist()) return
|
||||
@@ -637,30 +724,35 @@ const loadFromIndexedDB = async () => {
|
||||
|
||||
|
||||
await ensureFactorDefaultsLoaded()
|
||||
if (shouldForceDefaultLoad()) {
|
||||
const applyContractDefaultRows = async () => {
|
||||
const htData = await localforage.getItem<{ detailRows: SourceRow[] }>(HT_DB_KEY.value)
|
||||
detailRows.value = htData?.detailRows
|
||||
? mergeWithDictRows(htData.detailRows, { includeAmount: false, includeFactorValues: false })
|
||||
: buildDefaultRows()
|
||||
const hasContractRows = Array.isArray(htData?.detailRows) && htData.detailRows.length > 0
|
||||
detailRows.value = hasContractRows
|
||||
? mergeWithDictRows(htData!.detailRows, { includeFactorValues: true })
|
||||
: buildDefaultRows().map(row => ({
|
||||
...row,
|
||||
consultCategoryFactor: getDefaultConsultCategoryFactor(),
|
||||
majorFactor: getDefaultMajorFactorById(row.id)
|
||||
}))
|
||||
syncComputedValuesToDetailRows()
|
||||
}
|
||||
if (shouldForceDefaultLoad()) {
|
||||
await applyContractDefaultRows()
|
||||
return
|
||||
}
|
||||
|
||||
const data = await localforage.getItem<XmInfoState>(DB_KEY.value)
|
||||
if (data) {
|
||||
detailRows.value = mergeWithDictRows(data.detailRows)
|
||||
syncComputedValuesToDetailRows()
|
||||
return
|
||||
}
|
||||
|
||||
const htData = await localforage.getItem<{ detailRows: SourceRow[] }>(HT_DB_KEY.value)
|
||||
if (htData?.detailRows) {
|
||||
detailRows.value = mergeWithDictRows(htData.detailRows, { includeAmount: false, includeFactorValues: false })
|
||||
return
|
||||
}
|
||||
|
||||
detailRows.value = buildDefaultRows()
|
||||
await applyContractDefaultRows()
|
||||
} catch (error) {
|
||||
console.error('loadFromIndexedDB failed:', error)
|
||||
detailRows.value = buildDefaultRows()
|
||||
syncComputedValuesToDetailRows()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -687,6 +779,15 @@ const importContractData = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
const clearAllData = async () => {
|
||||
try {
|
||||
detailRows.value = buildDefaultRows()
|
||||
await saveToIndexedDB()
|
||||
} catch (error) {
|
||||
console.error('clearAllData failed:', error)
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => pricingPaneReloadStore.getReloadVersion(props.contractId, props.serviceId),
|
||||
(nextVersion, prevVersion) => {
|
||||
@@ -702,10 +803,11 @@ let persistTimer: ReturnType<typeof setTimeout> | null = null
|
||||
|
||||
let gridPersistTimer: ReturnType<typeof setTimeout> | null = null
|
||||
const handleCellValueChanged = () => {
|
||||
syncComputedValuesToDetailRows()
|
||||
if (gridPersistTimer) clearTimeout(gridPersistTimer)
|
||||
gridPersistTimer = setTimeout(() => {
|
||||
void saveToIndexedDB()
|
||||
}, 1000)
|
||||
}, 300)
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
@@ -748,28 +850,52 @@ const processCellFromClipboard = (params: any) => {
|
||||
<div class="rounded-lg border bg-card xmMx flex min-h-0 flex-1 flex-col">
|
||||
<div class="flex items-center justify-between border-b px-4 py-3">
|
||||
<h3 class="text-sm font-semibold text-foreground">投资规模明细</h3>
|
||||
<AlertDialogRoot>
|
||||
<AlertDialogTrigger as-child>
|
||||
<Button type="button" variant="outline" size="sm">使用默认数据</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogPortal>
|
||||
<AlertDialogOverlay class="fixed inset-0 z-50 bg-black/45" />
|
||||
<AlertDialogContent class="fixed left-1/2 top-1/2 z-50 w-[92vw] max-w-md -translate-x-1/2 -translate-y-1/2 rounded-lg border bg-background p-5 shadow-xl">
|
||||
<AlertDialogTitle class="text-base font-semibold">确认覆盖当前明细</AlertDialogTitle>
|
||||
<AlertDialogDescription class="mt-2 text-sm text-muted-foreground">
|
||||
将使用合同默认数据覆盖当前投资规模明细,是否继续?
|
||||
</AlertDialogDescription>
|
||||
<div class="mt-4 flex items-center justify-end gap-2">
|
||||
<AlertDialogCancel as-child>
|
||||
<Button variant="outline">取消</Button>
|
||||
</AlertDialogCancel>
|
||||
<AlertDialogAction as-child>
|
||||
<Button @click="importContractData">确认覆盖</Button>
|
||||
</AlertDialogAction>
|
||||
</div>
|
||||
</AlertDialogContent>
|
||||
</AlertDialogPortal>
|
||||
</AlertDialogRoot>
|
||||
<div class="flex items-center gap-2">
|
||||
<AlertDialogRoot>
|
||||
<AlertDialogTrigger as-child>
|
||||
<Button type="button" variant="outline" size="sm">清空</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogPortal>
|
||||
<AlertDialogOverlay class="fixed inset-0 z-50 bg-black/45" />
|
||||
<AlertDialogContent class="fixed left-1/2 top-1/2 z-50 w-[92vw] max-w-md -translate-x-1/2 -translate-y-1/2 rounded-lg border bg-background p-5 shadow-xl">
|
||||
<AlertDialogTitle class="text-base font-semibold">确认清空当前明细</AlertDialogTitle>
|
||||
<AlertDialogDescription class="mt-2 text-sm text-muted-foreground">
|
||||
将清空当前投资规模明细,是否继续?
|
||||
</AlertDialogDescription>
|
||||
<div class="mt-4 flex items-center justify-end gap-2">
|
||||
<AlertDialogCancel as-child>
|
||||
<Button variant="outline">取消</Button>
|
||||
</AlertDialogCancel>
|
||||
<AlertDialogAction as-child>
|
||||
<Button variant="destructive" @click="clearAllData">确认清空</Button>
|
||||
</AlertDialogAction>
|
||||
</div>
|
||||
</AlertDialogContent>
|
||||
</AlertDialogPortal>
|
||||
</AlertDialogRoot>
|
||||
<AlertDialogRoot>
|
||||
<AlertDialogTrigger as-child>
|
||||
<Button type="button" variant="outline" size="sm">使用默认数据</Button>
|
||||
</AlertDialogTrigger>
|
||||
<AlertDialogPortal>
|
||||
<AlertDialogOverlay class="fixed inset-0 z-50 bg-black/45" />
|
||||
<AlertDialogContent class="fixed left-1/2 top-1/2 z-50 w-[92vw] max-w-md -translate-x-1/2 -translate-y-1/2 rounded-lg border bg-background p-5 shadow-xl">
|
||||
<AlertDialogTitle class="text-base font-semibold">确认覆盖当前明细</AlertDialogTitle>
|
||||
<AlertDialogDescription class="mt-2 text-sm text-muted-foreground">
|
||||
将使用合同默认数据覆盖当前投资规模明细,是否继续?
|
||||
</AlertDialogDescription>
|
||||
<div class="mt-4 flex items-center justify-end gap-2">
|
||||
<AlertDialogCancel as-child>
|
||||
<Button variant="outline">取消</Button>
|
||||
</AlertDialogCancel>
|
||||
<AlertDialogAction as-child>
|
||||
<Button @click="importContractData">确认覆盖</Button>
|
||||
</AlertDialogAction>
|
||||
</div>
|
||||
</AlertDialogContent>
|
||||
</AlertDialogPortal>
|
||||
</AlertDialogRoot>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ag-theme-quartz h-full min-h-0 w-full flex-1">
|
||||
@@ -784,5 +910,3 @@ const processCellFromClipboard = (params: any) => {
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
Reference in new issue
Block a user