系数字段修改
This commit is contained in:
1 parent
21d3f0379c
commit
fc26a87bee
12 files changed
+782
-105
No files matched your search
@@ -5,8 +5,8 @@ import type { ColDef, ColGroupDef } from 'ag-grid-community'
|
||||
import localforage from 'localforage'
|
||||
import { getMajorDictEntries, getServiceDictItemById, industryTypeList, isMajorIdInIndustryScope } from '@/sql'
|
||||
import { myTheme, gridOptions } from '@/lib/diyAgGridOptions'
|
||||
import { decimalAggSum, roundTo, sumByNumber } from '@/lib/decimal'
|
||||
import { formatThousands } from '@/lib/numberFormat'
|
||||
import { addNumbers, decimalAggSum, roundTo, sumByNumber } from '@/lib/decimal'
|
||||
import { formatThousandsFlexible } from '@/lib/numberFormat'
|
||||
import { syncPricingTotalToZxFw, ZXFW_RELOAD_SERVICE_KEY } from '@/lib/zxFwPricingSync'
|
||||
import { usePricingPaneReloadStore } from '@/pinia/pricingPaneReload'
|
||||
import { loadConsultCategoryFactorMap, loadMajorFactorMap } from '@/lib/xmFactorDefaults'
|
||||
@@ -212,8 +212,9 @@ const detailDict: DictGroup[] = (() => {
|
||||
|
||||
const hasCost = item.hasCost !== false
|
||||
const hasArea = item.hasArea !== false
|
||||
// 特殊规则:投资规模法中,hasCost && hasArea 的专业不参与明细行
|
||||
if (hasCost && hasArea) continue
|
||||
// 投资规模法仅保留可按造价计价且非用地规模的专业
|
||||
if (!hasCost) continue
|
||||
if (hasArea) continue
|
||||
|
||||
groupMap.get(parentCode)!.children.push({
|
||||
id: key,
|
||||
@@ -292,7 +293,18 @@ const getOnlyCostScaleMajorFactorDefault = () => {
|
||||
|
||||
const buildOnlyCostScaleRow = (
|
||||
amount: number | null,
|
||||
fromDb?: Partial<Pick<DetailRow, 'consultCategoryFactor' | 'majorFactor' | 'workStageFactor' | 'workRatio' | 'remark'>>
|
||||
fromDb?: Partial<
|
||||
Pick<
|
||||
DetailRow,
|
||||
| 'consultCategoryFactor'
|
||||
| 'majorFactor'
|
||||
| 'workStageFactor'
|
||||
| 'workRatio'
|
||||
| 'remark'
|
||||
| 'benchmarkBudgetBasicChecked'
|
||||
| 'benchmarkBudgetOptionalChecked'
|
||||
>
|
||||
>
|
||||
): DetailRow => ({
|
||||
id: ONLY_COST_SCALE_ROW_ID,
|
||||
groupCode: 'TOTAL',
|
||||
@@ -305,8 +317,10 @@ const buildOnlyCostScaleRow = (
|
||||
benchmarkBudget: null,
|
||||
benchmarkBudgetBasic: null,
|
||||
benchmarkBudgetOptional: null,
|
||||
benchmarkBudgetBasicChecked: true,
|
||||
benchmarkBudgetOptionalChecked: true,
|
||||
benchmarkBudgetBasicChecked:
|
||||
typeof fromDb?.benchmarkBudgetBasicChecked === 'boolean' ? fromDb.benchmarkBudgetBasicChecked : true,
|
||||
benchmarkBudgetOptionalChecked:
|
||||
typeof fromDb?.benchmarkBudgetOptionalChecked === 'boolean' ? fromDb.benchmarkBudgetOptionalChecked : true,
|
||||
basicFormula: '',
|
||||
optionalFormula: '',
|
||||
consultCategoryFactor:
|
||||
@@ -416,7 +430,7 @@ const formatEditableNumber = (params: any) => {
|
||||
return '请输入'
|
||||
}
|
||||
if (params.value == null) return ''
|
||||
return Number(params.value).toFixed(2)
|
||||
return formatThousandsFlexible(params.value, 3)
|
||||
}
|
||||
|
||||
const formatConsultCategoryFactor = (params: any) => {
|
||||
@@ -431,7 +445,7 @@ const formatEditableMoney = (params: any) => {
|
||||
if (isOnlyCostScaleService.value) {
|
||||
if (!params.node?.rowPinned) return ''
|
||||
if (params.value == null || params.value === '') return '点击输入'
|
||||
return formatThousands(params.value)
|
||||
return formatThousandsFlexible(params.value, 3)
|
||||
}
|
||||
if (!params.node?.group && !params.node?.rowPinned && !params.data?.hasCost) {
|
||||
return ''
|
||||
@@ -440,12 +454,12 @@ const formatEditableMoney = (params: any) => {
|
||||
return '点击输入'
|
||||
}
|
||||
if (params.value == null) return ''
|
||||
return formatThousands(params.value)
|
||||
return formatThousandsFlexible(params.value, 3)
|
||||
}
|
||||
|
||||
const formatReadonlyMoney = (params: any) => {
|
||||
if (params.value == null || params.value === '') return ''
|
||||
return formatThousands(roundTo(params.value, 2))
|
||||
return formatThousandsFlexible(roundTo(params.value, 3), 3)
|
||||
}
|
||||
|
||||
type BudgetCheckField = 'benchmarkBudgetBasicChecked' | 'benchmarkBudgetOptionalChecked'
|
||||
@@ -453,14 +467,14 @@ type BudgetCheckField = 'benchmarkBudgetBasicChecked' | 'benchmarkBudgetOptional
|
||||
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) {
|
||||
if (params.node?.group || (params.node?.rowPinned && !isOnlyCostScaleService.value) || !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.justifyContent = 'space-between'
|
||||
wrapper.style.gap = '6px'
|
||||
wrapper.style.width = '100%'
|
||||
|
||||
@@ -471,8 +485,27 @@ const createBudgetCellRendererWithCheck = (checkField: BudgetCheckField) => (par
|
||||
checkbox.checked = params.data[checkField] !== false
|
||||
checkbox.addEventListener('click', event => event.stopPropagation())
|
||||
checkbox.addEventListener('change', () => {
|
||||
params.data[checkField] = checkbox.checked
|
||||
const isOnlyCostScalePinned = isOnlyCostScaleService.value && Boolean(params.node?.rowPinned)
|
||||
const targetRow =
|
||||
isOnlyCostScalePinned
|
||||
? detailRows.value[0]
|
||||
: (params.data as DetailRow | undefined)
|
||||
if (!targetRow) return
|
||||
|
||||
targetRow[checkField] = checkbox.checked
|
||||
params.node?.setDataValue?.(checkField, checkbox.checked)
|
||||
|
||||
if (!checkbox.checked) {
|
||||
const budgetField = checkField === 'benchmarkBudgetBasicChecked' ? 'benchmarkBudgetBasic' : 'benchmarkBudgetOptional'
|
||||
targetRow[budgetField] = 0
|
||||
params.node?.setDataValue?.(budgetField, 0)
|
||||
}
|
||||
|
||||
handleCellValueChanged()
|
||||
params.api?.refreshCells?.({
|
||||
rowNodes: params.node ? [params.node] : undefined,
|
||||
force: true
|
||||
})
|
||||
})
|
||||
|
||||
const valueSpan = document.createElement('span')
|
||||
@@ -485,10 +518,34 @@ const createBudgetCellRendererWithCheck = (checkField: BudgetCheckField) => (par
|
||||
const getBenchmarkBudgetSplitByAmount = (row?: Pick<DetailRow, 'amount'>) =>
|
||||
getBenchmarkBudgetSplitByScale(row?.amount, 'cost')
|
||||
|
||||
const getBudgetFee = (
|
||||
row?: Pick<DetailRow, 'amount' | 'majorFactor' | 'consultCategoryFactor' | 'workStageFactor' | 'workRatio'>
|
||||
const getCheckedBenchmarkBudgetSplitByAmount = (
|
||||
row?: Pick<DetailRow, 'amount' | 'benchmarkBudgetBasicChecked' | 'benchmarkBudgetOptionalChecked'>
|
||||
) => {
|
||||
const benchmarkBudgetSplit = getBenchmarkBudgetSplitByAmount(row)
|
||||
const split = getBenchmarkBudgetSplitByAmount(row)
|
||||
if (!split) return null
|
||||
const basic = row?.benchmarkBudgetBasicChecked === false ? 0 : split.basic
|
||||
const optional = row?.benchmarkBudgetOptionalChecked === false ? 0 : split.optional
|
||||
return {
|
||||
...split,
|
||||
basic,
|
||||
optional,
|
||||
total: roundTo(addNumbers(basic, optional), 2)
|
||||
}
|
||||
}
|
||||
|
||||
const getBudgetFee = (
|
||||
row?: Pick<
|
||||
DetailRow,
|
||||
| 'amount'
|
||||
| 'benchmarkBudgetBasicChecked'
|
||||
| 'benchmarkBudgetOptionalChecked'
|
||||
| 'majorFactor'
|
||||
| 'consultCategoryFactor'
|
||||
| 'workStageFactor'
|
||||
| 'workRatio'
|
||||
>
|
||||
) => {
|
||||
const benchmarkBudgetSplit = getCheckedBenchmarkBudgetSplitByAmount(row)
|
||||
if (!benchmarkBudgetSplit) return null
|
||||
|
||||
const splitBudgetFee = getScaleBudgetFeeSplit({
|
||||
@@ -503,9 +560,18 @@ const getBudgetFee = (
|
||||
}
|
||||
|
||||
const getBudgetFeeSplit = (
|
||||
row?: Pick<DetailRow, 'amount' | 'majorFactor' | 'consultCategoryFactor' | 'workStageFactor' | 'workRatio'>
|
||||
row?: Pick<
|
||||
DetailRow,
|
||||
| 'amount'
|
||||
| 'benchmarkBudgetBasicChecked'
|
||||
| 'benchmarkBudgetOptionalChecked'
|
||||
| 'majorFactor'
|
||||
| 'consultCategoryFactor'
|
||||
| 'workStageFactor'
|
||||
| 'workRatio'
|
||||
>
|
||||
) => {
|
||||
const benchmarkBudgetSplit = getBenchmarkBudgetSplitByAmount(row)
|
||||
const benchmarkBudgetSplit = getCheckedBenchmarkBudgetSplitByAmount(row)
|
||||
if (!benchmarkBudgetSplit) return null
|
||||
return getScaleBudgetFeeSplit({
|
||||
benchmarkBudgetBasic: benchmarkBudgetSplit.basic,
|
||||
@@ -517,6 +583,17 @@ const getBudgetFeeSplit = (
|
||||
})
|
||||
}
|
||||
|
||||
const getMergeColSpanBeforeTotal = (params: any) => {
|
||||
if (!params.node?.group && !params.node?.rowPinned) return 1
|
||||
if (isOnlyCostScaleService.value && params.node?.rowPinned) return 1
|
||||
const displayedColumns = params.api?.getAllDisplayedColumns?.()
|
||||
if (!Array.isArray(displayedColumns) || !params.column) return 1
|
||||
const currentIndex = displayedColumns.findIndex((column: any) => column.getColId() === params.column.getColId())
|
||||
const totalIndex = displayedColumns.findIndex((column: any) => column.getColId() === 'budgetFeeTotal')
|
||||
if (currentIndex < 0 || totalIndex <= currentIndex) return 1
|
||||
return totalIndex - currentIndex
|
||||
}
|
||||
|
||||
const columnDefs: Array<ColDef<DetailRow> | ColGroupDef<DetailRow>> = [
|
||||
{
|
||||
headerName: '造价金额(万元)',
|
||||
@@ -541,7 +618,7 @@ const columnDefs: Array<ColDef<DetailRow> | ColGroupDef<DetailRow>> = [
|
||||
? params.value == null || params.value === ''
|
||||
: !params.node?.group && !params.node?.rowPinned && Boolean(params.data?.hasCost) && (params.value == null || params.value === '')
|
||||
},
|
||||
valueParser: params => parseNumberOrNull(params.newValue, { precision: 2 }),
|
||||
valueParser: params => parseNumberOrNull(params.newValue, { precision: 3 }),
|
||||
valueFormatter: formatEditableMoney
|
||||
},
|
||||
{
|
||||
@@ -558,8 +635,8 @@ const columnDefs: Array<ColDef<DetailRow> | ColGroupDef<DetailRow>> = [
|
||||
cellClass: 'ag-right-aligned-cell',
|
||||
valueGetter: params =>
|
||||
params.node?.rowPinned
|
||||
? null
|
||||
: getBenchmarkBudgetSplitByAmount(params.data)?.basic ?? null,
|
||||
? (isOnlyCostScaleService.value ? getCheckedBenchmarkBudgetSplitByAmount(params.data)?.basic ?? null : null)
|
||||
: getCheckedBenchmarkBudgetSplitByAmount(params.data)?.basic ?? null,
|
||||
cellRenderer: createBudgetCellRendererWithCheck('benchmarkBudgetBasicChecked'),
|
||||
valueFormatter: formatReadonlyMoney
|
||||
},
|
||||
@@ -573,8 +650,8 @@ const columnDefs: Array<ColDef<DetailRow> | ColGroupDef<DetailRow>> = [
|
||||
cellClass: 'ag-right-aligned-cell',
|
||||
valueGetter: params =>
|
||||
params.node?.rowPinned
|
||||
? null
|
||||
: getBenchmarkBudgetSplitByAmount(params.data)?.optional ?? null,
|
||||
? (isOnlyCostScaleService.value ? getCheckedBenchmarkBudgetSplitByAmount(params.data)?.optional ?? null : null)
|
||||
: getCheckedBenchmarkBudgetSplitByAmount(params.data)?.optional ?? null,
|
||||
cellRenderer: createBudgetCellRendererWithCheck('benchmarkBudgetOptionalChecked'),
|
||||
valueFormatter: formatReadonlyMoney
|
||||
},
|
||||
@@ -588,8 +665,8 @@ const columnDefs: Array<ColDef<DetailRow> | ColGroupDef<DetailRow>> = [
|
||||
cellClass: 'ag-right-aligned-cell',
|
||||
valueGetter: params =>
|
||||
params.node?.rowPinned
|
||||
? null
|
||||
: getBenchmarkBudgetSplitByAmount(params.data)?.total ?? null,
|
||||
? (isOnlyCostScaleService.value ? getCheckedBenchmarkBudgetSplitByAmount(params.data)?.total ?? null : null)
|
||||
: getCheckedBenchmarkBudgetSplitByAmount(params.data)?.total ?? null,
|
||||
valueFormatter: formatReadonlyMoney
|
||||
}
|
||||
]
|
||||
@@ -620,7 +697,7 @@ const columnDefs: Array<ColDef<DetailRow> | ColGroupDef<DetailRow>> = [
|
||||
? params.value == null || params.value === ''
|
||||
: !params.node?.group && !params.node?.rowPinned && (params.value == null || params.value === '')
|
||||
},
|
||||
valueParser: params => parseNumberOrNull(params.newValue, { precision: 2 }),
|
||||
valueParser: params => parseNumberOrNull(params.newValue, { precision: 3 }),
|
||||
valueFormatter: formatConsultCategoryFactor
|
||||
},
|
||||
{
|
||||
@@ -645,7 +722,7 @@ const columnDefs: Array<ColDef<DetailRow> | ColGroupDef<DetailRow>> = [
|
||||
? params.value == null || params.value === ''
|
||||
: !params.node?.group && !params.node?.rowPinned && (params.value == null || params.value === '')
|
||||
},
|
||||
valueParser: params => parseNumberOrNull(params.newValue, { precision: 2 }),
|
||||
valueParser: params => parseNumberOrNull(params.newValue, { precision: 3 }),
|
||||
valueFormatter: formatMajorFactor
|
||||
},
|
||||
{
|
||||
@@ -670,7 +747,7 @@ const columnDefs: Array<ColDef<DetailRow> | ColGroupDef<DetailRow>> = [
|
||||
? params.value == null || params.value === ''
|
||||
: !params.node?.group && !params.node?.rowPinned && (params.value == null || params.value === '')
|
||||
},
|
||||
valueParser: params => parseNumberOrNull(params.newValue, { precision: 2 }),
|
||||
valueParser: params => parseNumberOrNull(params.newValue, { precision: 3 }),
|
||||
valueFormatter: formatEditableNumber
|
||||
},
|
||||
{
|
||||
@@ -695,7 +772,7 @@ const columnDefs: Array<ColDef<DetailRow> | ColGroupDef<DetailRow>> = [
|
||||
? params.value == null || params.value === ''
|
||||
: !params.node?.group && !params.node?.rowPinned && (params.value == null || params.value === '')
|
||||
},
|
||||
valueParser: params => parseNumberOrNull(params.newValue, { precision: 2 }),
|
||||
valueParser: params => parseNumberOrNull(params.newValue, { precision: 3 }),
|
||||
valueFormatter: formatEditableNumber
|
||||
},
|
||||
{
|
||||
@@ -738,8 +815,8 @@ const columnDefs: Array<ColDef<DetailRow> | ColGroupDef<DetailRow>> = [
|
||||
const autoGroupColumnDef: ColDef = {
|
||||
headerName: '专业编码以及工程专业名称',
|
||||
minWidth: 250,
|
||||
pinned: 'left',
|
||||
flex: 2,
|
||||
|
||||
// wrapText: true,
|
||||
// cellStyle: { whiteSpace: 'normal', lineHeight: '1.5', padding: '2px' },
|
||||
|
||||
@@ -747,6 +824,7 @@ const autoGroupColumnDef: ColDef = {
|
||||
cellRendererParams: {
|
||||
suppressCount: true
|
||||
},
|
||||
colSpan: getMergeColSpanBeforeTotal,
|
||||
valueFormatter: params => {
|
||||
if (params.node?.rowPinned) {
|
||||
return totalLabel.value
|
||||
@@ -766,9 +844,7 @@ const totalAmount = computed(() => sumByNumber(detailRows.value, row => row.amou
|
||||
const visibleDetailRows = computed(() => (isOnlyCostScaleService.value ? [] : detailRows.value))
|
||||
const onlyCostScaleSourceRow = computed(() => detailRows.value[0] ?? buildOnlyCostScaleRow(null))
|
||||
|
||||
const totalBenchmarkBudgetBasic = computed(() => sumByNumber(detailRows.value, row => getBenchmarkBudgetSplitByAmount(row)?.basic))
|
||||
const totalBenchmarkBudgetOptional = computed(() => sumByNumber(detailRows.value, row => getBenchmarkBudgetSplitByAmount(row)?.optional))
|
||||
const totalBenchmarkBudget = computed(() => sumByNumber(detailRows.value, row => getBenchmarkBudgetSplitByAmount(row)?.total))
|
||||
|
||||
|
||||
const totalBudgetFeeBasic = computed(() => sumByNumber(detailRows.value, row => getBudgetFeeSplit(row)?.basic))
|
||||
const totalBudgetFeeOptional = computed(() => sumByNumber(detailRows.value, row => getBudgetFeeSplit(row)?.optional))
|
||||
@@ -786,8 +862,8 @@ const pinnedTopRowData = computed(() => [
|
||||
benchmarkBudget: null,
|
||||
benchmarkBudgetBasic: null,
|
||||
benchmarkBudgetOptional: null,
|
||||
benchmarkBudgetBasicChecked: true,
|
||||
benchmarkBudgetOptionalChecked: true,
|
||||
benchmarkBudgetBasicChecked: isOnlyCostScaleService.value ? onlyCostScaleSourceRow.value.benchmarkBudgetBasicChecked !== false : true,
|
||||
benchmarkBudgetOptionalChecked: isOnlyCostScaleService.value ? onlyCostScaleSourceRow.value.benchmarkBudgetOptionalChecked !== false : true,
|
||||
basicFormula: '',
|
||||
optionalFormula: '',
|
||||
consultCategoryFactor: isOnlyCostScaleService.value ? onlyCostScaleSourceRow.value.consultCategoryFactor : null,
|
||||
@@ -804,7 +880,8 @@ const pinnedTopRowData = computed(() => [
|
||||
|
||||
const syncComputedValuesToDetailRows = () => {
|
||||
for (const row of detailRows.value) {
|
||||
const benchmarkBudgetSplit = getBenchmarkBudgetSplitByAmount(row)
|
||||
const benchmarkBudgetRawSplit = getBenchmarkBudgetSplitByAmount(row)
|
||||
const benchmarkBudgetSplit = getCheckedBenchmarkBudgetSplitByAmount(row)
|
||||
const budgetFeeSplit = benchmarkBudgetSplit
|
||||
? getScaleBudgetFeeSplit({
|
||||
benchmarkBudgetBasic: benchmarkBudgetSplit.basic,
|
||||
@@ -819,8 +896,8 @@ const syncComputedValuesToDetailRows = () => {
|
||||
row.benchmarkBudget = benchmarkBudgetSplit?.total ?? null
|
||||
row.benchmarkBudgetBasic = benchmarkBudgetSplit?.basic ?? null
|
||||
row.benchmarkBudgetOptional = benchmarkBudgetSplit?.optional ?? null
|
||||
row.basicFormula = benchmarkBudgetSplit?.basicFormula ?? ''
|
||||
row.optionalFormula = benchmarkBudgetSplit?.optionalFormula ?? ''
|
||||
row.basicFormula = benchmarkBudgetRawSplit?.basicFormula ?? ''
|
||||
row.optionalFormula = benchmarkBudgetRawSplit?.optionalFormula ?? ''
|
||||
row.budgetFee = budgetFeeSplit?.total ?? null
|
||||
row.budgetFeeBasic = budgetFeeSplit?.basic ?? null
|
||||
row.budgetFeeOptional = budgetFeeSplit?.optional ?? null
|
||||
@@ -951,7 +1028,7 @@ let persistTimer: ReturnType<typeof setTimeout> | null = null
|
||||
|
||||
let gridPersistTimer: ReturnType<typeof setTimeout> | null = null
|
||||
const applyOnlyCostScalePinnedValue = (field: string, rawValue: unknown) => {
|
||||
const parsedValue = parseNumberOrNull(rawValue, { precision: 2 })
|
||||
const parsedValue = parseNumberOrNull(rawValue, { precision: 3 })
|
||||
const current = detailRows.value[0]
|
||||
if (!current) {
|
||||
detailRows.value = [buildOnlyCostScaleRow(field === 'amount' ? parsedValue : null)]
|
||||
|
||||
Reference in new issue
Block a user