From 9849801e46a450993752442227445b8120b94bf8 Mon Sep 17 00:00:00 2001 From: wintsa <770775984@qq.com> Date: Fri, 27 Feb 2026 18:05:10 +0800 Subject: [PATCH] fix all --- .../views/pricingView/WorkloadPricingPane.vue | 145 ++++++++++-------- src/lib/diyAgGridOptions.ts | 2 +- 2 files changed, 78 insertions(+), 69 deletions(-) diff --git a/src/components/views/pricingView/WorkloadPricingPane.vue b/src/components/views/pricingView/WorkloadPricingPane.vue index baef48d..f7d79bd 100644 --- a/src/components/views/pricingView/WorkloadPricingPane.vue +++ b/src/components/views/pricingView/WorkloadPricingPane.vue @@ -5,7 +5,7 @@ import type { ColDef } from 'ag-grid-community' import localforage from 'localforage' import { serviceList, taskList } from '@/sql' import { myTheme, gridOptions } from '@/lib/diyAgGridOptions' -import { decimalAggSum, sumByNumber } from '@/lib/decimal' +import { decimalAggSum } from '@/lib/decimal' import { usePricingPaneReloadStore } from '@/pinia/pricingPaneReload' import { AG_GRID_LOCALE_CN } from '@ag-grid-community/locale'; @@ -15,6 +15,7 @@ interface DetailRow { taskCode: string taskName: string unit: string + conversion: number | null workload: number | null budgetBase: string budgetReferenceUnitPrice: string @@ -68,9 +69,11 @@ type taskLite = { name: string basicParam: string unit: string + conversion: number | null maxPrice: number | null minPrice: number | null defPrice: number | null + desc: string | null } const defaultConsultCategoryFactor = computed(() => { @@ -106,6 +109,7 @@ const buildDefaultRows = (): DetailRow[] => { taskCode: task.code, taskName: task.name, unit: task.unit || '', + conversion: typeof task.conversion === 'number' && Number.isFinite(task.conversion) ? task.conversion : null, workload: null, budgetBase: task.basicParam || '', budgetReferenceUnitPrice: formatTaskReferenceUnitPrice(task), @@ -113,7 +117,7 @@ const buildDefaultRows = (): DetailRow[] => { typeof task.defPrice === 'number' && Number.isFinite(task.defPrice) ? task.defPrice : null, consultCategoryFactor: defaultConsultCategoryFactor.value, serviceFee: null, - remark: '', + remark: task.desc|| '', path: [rowId] }) } @@ -125,6 +129,7 @@ const buildDefaultRows = (): DetailRow[] => { taskCode: '无', taskName: '无', unit: '', + conversion: null, workload: null, budgetBase: '无', budgetReferenceUnitPrice: '无', @@ -171,6 +176,27 @@ const parseNumberOrNull = (value: unknown) => { return Number.isFinite(v) ? v : null } +const calcServiceFee = (row: DetailRow | undefined) => { + if (!row || isNoTaskRow(row)) return null + const price = row.budgetAdoptedUnitPrice + const conversion = row.conversion + const workload = row.workload + const factor = row.consultCategoryFactor + if ( + typeof price !== 'number' || + !Number.isFinite(price) || + typeof conversion !== 'number' || + !Number.isFinite(conversion) || + typeof workload !== 'number' || + !Number.isFinite(workload) || + typeof factor !== 'number' || + !Number.isFinite(factor) + ) { + return null + } + return price * conversion * workload * factor +} + const formatEditableNumber = (params: any) => { if (isNoTaskRow(params.data)) return '无' if (!params.node?.group && !params.node?.rowPinned && (params.value == null || params.value === '')) { @@ -180,52 +206,45 @@ const formatEditableNumber = (params: any) => { return Number(params.value).toFixed(2) } -const isRepeatedTaskNameRow = (params: any) => { - const rowIndex = params.node?.rowIndex - if (typeof rowIndex !== 'number' || rowIndex <= 0) return false - const prevData = params.api.getDisplayedRowAtIndex(rowIndex - 1)?.data as DetailRow | undefined - return prevData?.taskName === params.data?.taskName -} +const spanRowsByTaskName = (params: any) => { + const rowA = params?.nodeA?.data as DetailRow | undefined + const rowB = params?.nodeB?.data as DetailRow | undefined + // debugger + if (!rowA || !rowB) return false + if (isNoTaskRow(rowA) || isNoTaskRow(rowB)) return false -const getTaskNameRowSpan = (params: any) => { - if (params.node?.rowPinned) return 1 - if (isRepeatedTaskNameRow(params)) return 1 - const currentName = params.data?.taskName - if (!currentName) return 1 - let span = 1 - let offset = 1 - while (true) { - const nextData = params.api.getDisplayedRowAtIndex((params.node?.rowIndex ?? 0) + offset)?.data as DetailRow | undefined - if (!nextData || nextData.taskName !== currentName) break - span += 1 - offset += 1 - } - return span + return Boolean(rowA.taskName) && Boolean(rowA.budgetBase) && rowA.taskName === rowB.taskName && rowA.budgetBase === rowB.budgetBase } const columnDefs: ColDef[] = [ { headerName: '编码', field: 'taskCode', - minWidth: 150, - width: 170, + minWidth: 100, + width: 120, pinned: 'left', valueFormatter: params => params.value || '' }, { headerName: '名称', field: 'taskName', - minWidth: 220, - width: 260, + minWidth: 150, + width: 220, pinned: 'left', - rowSpan: params => getTaskNameRowSpan(params), - valueFormatter: params => (isRepeatedTaskNameRow(params) ? '' : params.value || '') + autoHeight: true, + + spanRows: true, + valueFormatter: params => params.value || '' }, { headerName: '预算基数', field: 'budgetBase', - minWidth: 170, - flex: 1, + minWidth: 150, + autoHeight: true, + + width: 180, + pinned: 'left', + spanRows: spanRowsByTaskName, valueFormatter: params => params.value || '' }, { @@ -300,18 +319,10 @@ const columnDefs: ColDef[] = [ field: 'serviceFee', minWidth: 150, flex: 1, - editable: params => !params.node?.group && !params.node?.rowPinned && !isNoTaskRow(params.data), - cellClass: params => (!params.node?.group && !params.node?.rowPinned ? 'editable-cell-line' : ''), - cellClassRules: { - 'editable-cell-empty': params => - !params.node?.group && - !params.node?.rowPinned && - !isNoTaskRow(params.data) && - (params.value == null || params.value === '') - }, + editable: false, + valueGetter: params => calcServiceFee(params.data), aggFunc: decimalAggSum, - valueParser: params => parseNumberOrNull(params.newValue), - valueFormatter: formatEditableNumber + // valueFormatter: formatEditableNumber }, { headerName: '说明', @@ -323,10 +334,9 @@ const columnDefs: ColDef[] = [ autoHeight: true, cellStyle: { whiteSpace: 'normal', lineHeight: '1.4' }, - editable: params => !params.node?.group && !params.node?.rowPinned && !isNoTaskRow(params.data), + editable: false, valueFormatter: params => { - if (isNoTaskRow(params.data)) return '无' - if (!params.node?.group && !params.node?.rowPinned && !params.value) return '点击输入' + return params.value || '' }, cellClass: params => (!params.node?.group && !params.node?.rowPinned ? 'editable-cell-line remark-wrap-cell' : ''), @@ -340,26 +350,6 @@ const columnDefs: ColDef[] = [ } ] -const totalWorkload = computed(() => sumByNumber(detailRows.value, row => row.workload)) - -const totalServiceFee = computed(() => sumByNumber(detailRows.value, row => row.serviceFee)) -const pinnedTopRowData = computed(() => [ - { - id: 'pinned-total-row', - taskCode: '', - taskName: '', - unit: '', - workload: totalWorkload.value, - budgetBase: '', - budgetReferenceUnitPrice: '', - budgetAdoptedUnitPrice: null, - consultCategoryFactor: null, - serviceFee: totalServiceFee.value, - remark: '', - path: ['TOTAL'] - } -]) - const saveToIndexedDB = async () => { @@ -441,6 +431,18 @@ const processCellFromClipboard = (params: any) => { } return params.value; }; +const mydiyTheme = myTheme.withParams({ + rowBorder: { + style: "solid", + width: 0.8, + color: "#d8d8dd" + }, + columnBorder: { + style: "solid", + width: 0.8, + color: "#d8d8dd" + } +}) + + diff --git a/src/lib/diyAgGridOptions.ts b/src/lib/diyAgGridOptions.ts index cadafa3..1d73331 100644 --- a/src/lib/diyAgGridOptions.ts +++ b/src/lib/diyAgGridOptions.ts @@ -15,7 +15,7 @@ export const myTheme = themeQuartz.withParams({ wrapperBorder: false, // 表头样式(柔和浅蓝,无加粗,更轻盈) - headerBackgroundColor: "#f9fafb", // 极浅的背景色,替代深一点的 #e7f3fc + headerBackgroundColor: "#f0f2f3", // 极浅的背景色,替代深一点的 #e7f3fc headerTextColor: "#374151", // 深灰色文字,比纯黑更柔和 headerFontSize: 15, // 字体稍大一点,更易读 headerFontWeight: "normal", // 取消加粗,降低视觉重量