This commit is contained in:
zwgczx committed 2026-02-27 18:25:19 +08:00
1 parent 9849801e46
commit e97707ac59
6 files changed
+153 -59

No files matched your search

@@ -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 } from '@/lib/decimal'
import { decimalAggSum, roundTo, toDecimal } from '@/lib/decimal'
import { usePricingPaneReloadStore } from '@/pinia/pricingPaneReload'
import { AG_GRID_LOCALE_CN } from '@ag-grid-community/locale';
@@ -91,14 +91,20 @@ const formatTaskReferenceUnitPrice = (task: taskLite) => {
return ''
}
const buildDefaultRows = (): DetailRow[] => {
const rows: DetailRow[] = []
const getSourceTaskIds = () => {
const currentServiceId = Number(props.serviceId)
const sourceTaskIds = Object.entries(taskList as Record<string, taskLite>)
return Object.entries(taskList as Record<string, taskLite>)
.filter(([, task]) => Number(task.serviceID) === currentServiceId)
.map(([key]) => Number(key))
.filter(Number.isFinite)
.sort((a, b) => a - b)
}
const isWorkloadMethodApplicable = computed(() => getSourceTaskIds().length > 0)
const buildDefaultRows = (): DetailRow[] => {
const rows: DetailRow[] = []
const sourceTaskIds = getSourceTaskIds()
for (const [order, taskId] of sourceTaskIds.entries()) {
const task = (taskList as Record<string, taskLite | undefined>)[String(taskId)]
@@ -122,25 +128,6 @@ const buildDefaultRows = (): DetailRow[] => {
})
}
if (rows.length === 0) {
const emptyRowId = `task-none-${String(props.serviceId)}`
rows.push({
id: emptyRowId,
taskCode: '无',
taskName: '无',
unit: '',
conversion: null,
workload: null,
budgetBase: '无',
budgetReferenceUnitPrice: '无',
budgetAdoptedUnitPrice: null,
consultCategoryFactor: null,
serviceFee: null,
remark: '',
path: [emptyRowId]
})
}
return rows
}
@@ -194,7 +181,7 @@ const calcServiceFee = (row: DetailRow | undefined) => {
) {
return null
}
return price * conversion * workload * factor
return roundTo(toDecimal(price).mul(conversion).mul(workload).mul(factor), 2)
}
const formatEditableNumber = (params: any) => {
@@ -206,6 +193,12 @@ const formatEditableNumber = (params: any) => {
return Number(params.value).toFixed(2)
}
const formatReadonlyNumber = (params: any) => {
if (isNoTaskRow(params.data)) return '无'
if (params.value == null || params.value === '') return ''
return roundTo(params.value, 2).toFixed(2)
}
const spanRowsByTaskName = (params: any) => {
const rowA = params?.nodeA?.data as DetailRow | undefined
const rowB = params?.nodeB?.data as DetailRow | undefined
@@ -322,7 +315,7 @@ const columnDefs: ColDef<DetailRow>[] = [
editable: false,
valueGetter: params => calcServiceFee(params.data),
aggFunc: decimalAggSum,
// valueFormatter: formatEditableNumber
valueFormatter: formatReadonlyNumber
},
{
headerName: '说明',
@@ -353,6 +346,7 @@ const columnDefs: ColDef<DetailRow>[] = [
const saveToIndexedDB = async () => {
if (!isWorkloadMethodApplicable.value) return
if (shouldSkipPersist()) return
try {
const payload = {
@@ -367,6 +361,11 @@ const saveToIndexedDB = async () => {
const loadFromIndexedDB = async () => {
try {
if (!isWorkloadMethodApplicable.value) {
detailRows.value = []
return
}
if (shouldForceDefaultLoad()) {
detailRows.value = buildDefaultRows()
return
@@ -451,11 +450,11 @@ const mydiyTheme = myTheme.withParams({
<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>
<h3 class="text-sm font-semibold text-foreground">工作量明细</h3>
<div class="text-xs text-muted-foreground">导入导出</div>
</div>
<div class="ag-theme-quartz h-full min-h-0 w-full flex-1">
<div v-if="isWorkloadMethodApplicable" class="ag-theme-quartz h-full min-h-0 w-full flex-1">
<AgGridVue :style="{ height: '100%' }" :rowData="detailRows"
:columnDefs="columnDefs" :gridOptions="gridOptions" :theme="mydiyTheme" :treeData="false"
:enableCellSpan="true"
@@ -469,6 +468,15 @@ const mydiyTheme = myTheme.withParams({
:processCellForClipboard="processCellForClipboard" :processCellFromClipboard="processCellFromClipboard"
:undoRedoCellEditing="true" :undoRedoCellEditingLimit="20" />
</div>
<div
v-else
class="flex h-full min-h-0 w-full flex-1 items-center justify-center bg-[radial-gradient(circle_at_top,_rgba(220,38,38,0.18),rgba(0,0,0,0.03)_46%,transparent_72%)] p-6"
>
<div class="w-full max-w-xl rounded-2xl border border-red-300/85 bg-white/90 px-8 py-10 text-center shadow-[0_18px_38px_-22px_rgba(153,27,27,0.6)] backdrop-blur">
<p class="text-lg font-semibold tracking-wide text-neutral-900">该服务不适用工作量法</p>
<p class="mt-2 text-sm leading-6 text-red-700">当前服务没有关联工作量法任务,无需填写此部分内容。</p>
</div>
</div>
</div>
</div>
</template>