1
This commit is contained in:
parent
0f71fff9ac
commit
cd107604a9
@ -433,7 +433,7 @@ const sumNullableBy = <T>(rows: T[], pick: (row: T) => unknown): number | null =
|
|||||||
})
|
})
|
||||||
return hasValid ? total : null
|
return hasValid ? total : null
|
||||||
}
|
}
|
||||||
const totalServiceBudget = computed(() => sumNullableBy(detailRows.value, row => calcServiceBudget(row)))
|
const totalServiceBudget = computed(() => sumNullableBy(detailRows.value.filter(e => e.serviceBudget !== null && e.serviceBudget !== undefined), row => calcServiceBudget(row)))
|
||||||
const pinnedTopRowData = computed(() => [
|
const pinnedTopRowData = computed(() => [
|
||||||
{
|
{
|
||||||
id: 'pinned-total-row',
|
id: 'pinned-total-row',
|
||||||
|
|||||||
@ -164,14 +164,18 @@ const formatReadonlyBudgetFee = (params: any) => {
|
|||||||
|
|
||||||
const syncComputedValuesToRows = () => {
|
const syncComputedValuesToRows = () => {
|
||||||
let totalBudgetFee = 0
|
let totalBudgetFee = 0
|
||||||
|
let hasValidRow = false
|
||||||
for (const row of detailRows.value) {
|
for (const row of detailRows.value) {
|
||||||
if (isSubtotalRow(row)) continue
|
if (isSubtotalRow(row)) continue
|
||||||
if (row.quantity == null || row.unitPrice == null) {
|
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) {
|
||||||
row.budgetFee = null
|
row.budgetFee = null
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
row.budgetFee = roundTo(toDecimal(row.quantity).mul(row.unitPrice), 2)
|
row.budgetFee = roundTo(toDecimal(quantity).mul(unitPrice), 2)
|
||||||
if (typeof row.budgetFee === 'number' && Number.isFinite(row.budgetFee)) {
|
if (typeof row.budgetFee === 'number' && Number.isFinite(row.budgetFee)) {
|
||||||
|
hasValidRow = true
|
||||||
totalBudgetFee = roundTo(toDecimal(totalBudgetFee).add(row.budgetFee), 2)
|
totalBudgetFee = roundTo(toDecimal(totalBudgetFee).add(row.budgetFee), 2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -181,7 +185,7 @@ const syncComputedValuesToRows = () => {
|
|||||||
subtotalRow.unit = ''
|
subtotalRow.unit = ''
|
||||||
subtotalRow.quantity = null
|
subtotalRow.quantity = null
|
||||||
subtotalRow.unitPrice = null
|
subtotalRow.unitPrice = null
|
||||||
subtotalRow.budgetFee = totalBudgetFee
|
subtotalRow.budgetFee = hasValidRow ? totalBudgetFee : null
|
||||||
subtotalRow.remark = ''
|
subtotalRow.remark = ''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -93,8 +93,24 @@ const isSummaryRow = (row: FeeMethodRow | null | undefined) => row?.id === SUMMA
|
|||||||
const toFinite = (value: number | null | undefined) =>
|
const toFinite = (value: number | null | undefined) =>
|
||||||
typeof value === 'number' && Number.isFinite(value) ? value : 0
|
typeof value === 'number' && Number.isFinite(value) ? value : 0
|
||||||
const round3 = (value: number) => Number(value.toFixed(3))
|
const round3 = (value: number) => Number(value.toFixed(3))
|
||||||
const getRowSubtotal = (row: FeeMethodRow | null | undefined) =>
|
const sumNullableField = (rows: FeeMethodRow[], pick: (row: FeeMethodRow) => number | null | undefined): number | null => {
|
||||||
row ? round3(toFinite(row.rateFee) + toFinite(row.hourlyFee) + toFinite(row.quantityUnitPriceFee)) : null
|
let hasValid = false
|
||||||
|
let total = 0
|
||||||
|
for (const row of rows) {
|
||||||
|
const value = pick(row)
|
||||||
|
if (typeof value !== 'number' || !Number.isFinite(value)) continue
|
||||||
|
total += value
|
||||||
|
hasValid = true
|
||||||
|
}
|
||||||
|
return hasValid ? round3(total) : null
|
||||||
|
}
|
||||||
|
const getRowSubtotal = (row: FeeMethodRow | null | undefined) => {
|
||||||
|
if (!row) return null
|
||||||
|
const values = [row.rateFee, row.hourlyFee, row.quantityUnitPriceFee]
|
||||||
|
const hasValid = values.some(value => typeof value === 'number' && Number.isFinite(value))
|
||||||
|
if (!hasValid) return null
|
||||||
|
return round3(toFinite(row.rateFee) + toFinite(row.hourlyFee) + toFinite(row.quantityUnitPriceFee))
|
||||||
|
}
|
||||||
const toFiniteUnknown = (value: unknown): number | null => {
|
const toFiniteUnknown = (value: unknown): number | null => {
|
||||||
const numeric = Number(value)
|
const numeric = Number(value)
|
||||||
return Number.isFinite(numeric) ? numeric : null
|
return Number.isFinite(numeric) ? numeric : null
|
||||||
@ -117,11 +133,13 @@ const sumHourlyMethodFee = (state: MethodHourlyState | null): number | null => {
|
|||||||
|
|
||||||
if (rows.length === 0) return null
|
if (rows.length === 0) return null
|
||||||
let total = 0
|
let total = 0
|
||||||
|
let hasValid = false
|
||||||
for (const row of rows) {
|
for (const row of rows) {
|
||||||
|
|
||||||
const rowBudget = toFiniteUnknown(row?.serviceBudget)
|
const rowBudget = toFiniteUnknown(row?.serviceBudget)
|
||||||
if (rowBudget != null) {
|
if (rowBudget != null) {
|
||||||
total += rowBudget
|
total += rowBudget
|
||||||
|
hasValid = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
const adopted = toFiniteUnknown(row?.adoptedBudgetUnitPrice)
|
const adopted = toFiniteUnknown(row?.adoptedBudgetUnitPrice)
|
||||||
@ -130,31 +148,32 @@ const sumHourlyMethodFee = (state: MethodHourlyState | null): number | null => {
|
|||||||
|
|
||||||
if (adopted == null || personnel == null || workday == null) continue
|
if (adopted == null || personnel == null || workday == null) continue
|
||||||
total += adopted * personnel * workday
|
total += adopted * personnel * workday
|
||||||
|
hasValid = true
|
||||||
}
|
}
|
||||||
return round3(total)
|
return hasValid ? round3(total) : null
|
||||||
}
|
}
|
||||||
|
|
||||||
const sumQuantityMethodFee = (state: MethodQuantityState | null): number | null => {
|
const sumQuantityMethodFee = (state: MethodQuantityState | null): number | null => {
|
||||||
const rows = Array.isArray(state?.detailRows) ? state.detailRows : []
|
const rows = Array.isArray(state?.detailRows) ? state.detailRows : []
|
||||||
if (rows.length === 0) return null
|
if (rows.length === 0) return null
|
||||||
const subtotalRow = rows.find(row => String(row?.id || '') === 'fee-subtotal-fixed')
|
|
||||||
const subtotalBudget = toFiniteUnknown(subtotalRow?.budgetFee)
|
|
||||||
if (subtotalBudget != null) return round3(subtotalBudget)
|
|
||||||
|
|
||||||
let total = 0
|
let total = 0
|
||||||
|
let hasValid = false
|
||||||
for (const row of rows) {
|
for (const row of rows) {
|
||||||
if (String(row?.id || '') === 'fee-subtotal-fixed') continue
|
if (String(row?.id || '') === 'fee-subtotal-fixed') continue
|
||||||
const budget = toFiniteUnknown(row?.budgetFee)
|
const budget = toFiniteUnknown(row?.budgetFee)
|
||||||
if (budget != null) {
|
if (budget != null) {
|
||||||
total += budget
|
total += budget
|
||||||
|
hasValid = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
const quantity = toFiniteUnknown(row?.quantity)
|
const quantity = toFiniteUnknown(row?.quantity)
|
||||||
const unitPrice = toFiniteUnknown(row?.unitPrice)
|
const unitPrice = toFiniteUnknown(row?.unitPrice)
|
||||||
if (quantity == null || unitPrice == null) continue
|
if (quantity == null || unitPrice == null) continue
|
||||||
total += quantity * unitPrice
|
total += quantity * unitPrice
|
||||||
|
hasValid = true
|
||||||
}
|
}
|
||||||
return round3(total)
|
return hasValid ? round3(total) : null
|
||||||
}
|
}
|
||||||
|
|
||||||
const hydrateRowsFromMethodStores = async (rows: FeeMethodRow[]): Promise<FeeMethodRow[]> => {
|
const hydrateRowsFromMethodStores = async (rows: FeeMethodRow[]): Promise<FeeMethodRow[]> => {
|
||||||
@ -209,25 +228,15 @@ const detailRows = computed<FeeMethodRow[]>({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
const summaryRow = computed<FeeMethodRow>(() => {
|
const summaryRow = computed<FeeMethodRow>(() => {
|
||||||
const totals = detailRows.value.reduce(
|
const rateFee = sumNullableField(detailRows.value, row => row.rateFee)
|
||||||
(acc, row) => {
|
const hourlyFee = sumNullableField(detailRows.value, row => row.hourlyFee)
|
||||||
acc.rateFee += toFinite(row.rateFee)
|
const quantityUnitPriceFee = sumNullableField(detailRows.value, row => row.quantityUnitPriceFee)
|
||||||
acc.hourlyFee += toFinite(row.hourlyFee)
|
|
||||||
acc.quantityUnitPriceFee += toFinite(row.quantityUnitPriceFee)
|
|
||||||
return acc
|
|
||||||
},
|
|
||||||
{
|
|
||||||
rateFee: 0,
|
|
||||||
hourlyFee: 0,
|
|
||||||
quantityUnitPriceFee: 0
|
|
||||||
}
|
|
||||||
)
|
|
||||||
const result: FeeMethodRow = {
|
const result: FeeMethodRow = {
|
||||||
id: SUMMARY_ROW_ID,
|
id: SUMMARY_ROW_ID,
|
||||||
name: '小计',
|
name: '小计',
|
||||||
rateFee: round3(totals.rateFee),
|
rateFee,
|
||||||
hourlyFee: round3(totals.hourlyFee),
|
hourlyFee,
|
||||||
quantityUnitPriceFee: round3(totals.quantityUnitPriceFee)
|
quantityUnitPriceFee
|
||||||
}
|
}
|
||||||
result.subtotal = getRowSubtotal(result)
|
result.subtotal = getRowSubtotal(result)
|
||||||
return result
|
return result
|
||||||
|
|||||||
@ -63,8 +63,8 @@ interface DetailRow {
|
|||||||
benchmarkBudgetOptional: number | null
|
benchmarkBudgetOptional: number | null
|
||||||
benchmarkBudgetBasicChecked: boolean
|
benchmarkBudgetBasicChecked: boolean
|
||||||
benchmarkBudgetOptionalChecked: boolean
|
benchmarkBudgetOptionalChecked: boolean
|
||||||
basicFormula: string | null
|
basicFormula: string |null
|
||||||
optionalFormula: string | null
|
optionalFormula: string |null
|
||||||
consultCategoryFactor: number | null
|
consultCategoryFactor: number | null
|
||||||
majorFactor: number | null
|
majorFactor: number | null
|
||||||
workStageFactor: number | null
|
workStageFactor: number | null
|
||||||
@ -535,7 +535,6 @@ const mergeWithDictRows = (
|
|||||||
if (!fromDb) return row
|
if (!fromDb) return row
|
||||||
const hasConsultCategoryFactor = Object.prototype.hasOwnProperty.call(fromDb, 'consultCategoryFactor')
|
const hasConsultCategoryFactor = Object.prototype.hasOwnProperty.call(fromDb, 'consultCategoryFactor')
|
||||||
const hasMajorFactor = Object.prototype.hasOwnProperty.call(fromDb, 'majorFactor')
|
const hasMajorFactor = Object.prototype.hasOwnProperty.call(fromDb, 'majorFactor')
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...row,
|
...row,
|
||||||
amount: includeAmount && row.hasCost && typeof fromDb.amount === 'number' ? fromDb.amount : null,
|
amount: includeAmount && row.hasCost && typeof fromDb.amount === 'number' ? fromDb.amount : null,
|
||||||
@ -931,7 +930,7 @@ const autoGroupColumnDef: ColDef = {
|
|||||||
minWidth: 250,
|
minWidth: 250,
|
||||||
flex: 2,
|
flex: 2,
|
||||||
|
|
||||||
// wrapText: true,
|
// wrapText: true,
|
||||||
// cellStyle: { whiteSpace: 'normal', lineHeight: '1.5', padding: '2px' },
|
// cellStyle: { whiteSpace: 'normal', lineHeight: '1.5', padding: '2px' },
|
||||||
|
|
||||||
// autoHeight: true,
|
// autoHeight: true,
|
||||||
@ -966,7 +965,6 @@ const autoGroupColumnDef: ColDef = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const totalAmount = computed(() => sumByNumber(detailRows.value, row => row.amount))
|
|
||||||
|
|
||||||
const sumNullableBy = <T>(rows: T[], pick: (row: T) => unknown): number | null => {
|
const sumNullableBy = <T>(rows: T[], pick: (row: T) => unknown): number | null => {
|
||||||
let hasValid = false
|
let hasValid = false
|
||||||
@ -981,7 +979,9 @@ const sumNullableBy = <T>(rows: T[], pick: (row: T) => unknown): number | null =
|
|||||||
|
|
||||||
const totalBudgetFeeBasic = computed(() => sumNullableBy(detailRows.value, row => getBudgetFeeSplit(row)?.basic))
|
const totalBudgetFeeBasic = computed(() => sumNullableBy(detailRows.value, row => getBudgetFeeSplit(row)?.basic))
|
||||||
const totalBudgetFeeOptional = computed(() => sumNullableBy(detailRows.value, row => getBudgetFeeSplit(row)?.optional))
|
const totalBudgetFeeOptional = computed(() => sumNullableBy(detailRows.value, row => getBudgetFeeSplit(row)?.optional))
|
||||||
const totalBudgetFee = computed(() => sumNullableBy(detailRows.value, row => getBudgetFee(row)))
|
const totalBudgetFee = computed(() =>
|
||||||
|
sumNullableBy(detailRows.value.filter(e => e.budgetFee !== null && e.budgetFee !== undefined), row => getBudgetFee(row))
|
||||||
|
)
|
||||||
const pinnedTopRowData = computed(() => {
|
const pinnedTopRowData = computed(() => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@ -1303,14 +1303,16 @@ const processCellFromClipboard = (params: any) => {
|
|||||||
<h3 class="text-sm font-semibold text-foreground">投资规模明细</h3>
|
<h3 class="text-sm font-semibold text-foreground">投资规模明细</h3>
|
||||||
<div v-if="isMutipleService" class="flex items-center gap-2">
|
<div v-if="isMutipleService" class="flex items-center gap-2">
|
||||||
<span class="text-xs text-muted-foreground">项目数量</span>
|
<span class="text-xs text-muted-foreground">项目数量</span>
|
||||||
<NumberFieldRoot v-model="projectCount" :min="1" :step="1"
|
<NumberFieldRoot
|
||||||
|
v-model="projectCount"
|
||||||
|
:min="1"
|
||||||
|
:step="1"
|
||||||
class="inline-flex items-center rounded-md border bg-background"
|
class="inline-flex items-center rounded-md border bg-background"
|
||||||
@update:model-value="value => void applyProjectCountChange(value)">
|
@update:model-value="value => void applyProjectCountChange(value)"
|
||||||
<NumberFieldDecrement class="cursor-pointer px-2 py-1 text-xs text-muted-foreground hover:bg-muted">-
|
>
|
||||||
</NumberFieldDecrement>
|
<NumberFieldDecrement class="cursor-pointer px-2 py-1 text-xs text-muted-foreground hover:bg-muted">-</NumberFieldDecrement>
|
||||||
<NumberFieldInput class="h-7 w-14 border-x bg-transparent px-2 text-center text-xs outline-none" />
|
<NumberFieldInput class="h-7 w-14 border-x bg-transparent px-2 text-center text-xs outline-none" />
|
||||||
<NumberFieldIncrement class="cursor-pointer px-2 py-1 text-xs text-muted-foreground hover:bg-muted">+
|
<NumberFieldIncrement class="cursor-pointer px-2 py-1 text-xs text-muted-foreground hover:bg-muted">+</NumberFieldIncrement>
|
||||||
</NumberFieldIncrement>
|
|
||||||
</NumberFieldRoot>
|
</NumberFieldRoot>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -1321,8 +1323,7 @@ const processCellFromClipboard = (params: any) => {
|
|||||||
</AlertDialogTrigger>
|
</AlertDialogTrigger>
|
||||||
<AlertDialogPortal>
|
<AlertDialogPortal>
|
||||||
<AlertDialogOverlay class="fixed inset-0 z-50 bg-black/45" />
|
<AlertDialogOverlay class="fixed inset-0 z-50 bg-black/45" />
|
||||||
<AlertDialogContent
|
<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">
|
||||||
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>
|
<AlertDialogTitle class="text-base font-semibold">确认清空当前明细</AlertDialogTitle>
|
||||||
<AlertDialogDescription class="mt-2 text-sm text-muted-foreground">
|
<AlertDialogDescription class="mt-2 text-sm text-muted-foreground">
|
||||||
将清空当前投资规模明细,是否继续?
|
将清空当前投资规模明细,是否继续?
|
||||||
@ -1344,8 +1345,7 @@ const processCellFromClipboard = (params: any) => {
|
|||||||
</AlertDialogTrigger>
|
</AlertDialogTrigger>
|
||||||
<AlertDialogPortal>
|
<AlertDialogPortal>
|
||||||
<AlertDialogOverlay class="fixed inset-0 z-50 bg-black/45" />
|
<AlertDialogOverlay class="fixed inset-0 z-50 bg-black/45" />
|
||||||
<AlertDialogContent
|
<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">
|
||||||
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>
|
<AlertDialogTitle class="text-base font-semibold">确认覆盖当前明细</AlertDialogTitle>
|
||||||
<AlertDialogDescription class="mt-2 text-sm text-muted-foreground">
|
<AlertDialogDescription class="mt-2 text-sm text-muted-foreground">
|
||||||
将使用合同默认数据覆盖当前投资规模明细,是否继续?
|
将使用合同默认数据覆盖当前投资规模明细,是否继续?
|
||||||
|
|||||||
@ -835,7 +835,9 @@ const sumNullableBy = <T>(rows: T[], pick: (row: T) => unknown): number | null =
|
|||||||
|
|
||||||
const totalBudgetFeeBasic = computed(() => sumNullableBy(detailRows.value, row => getBudgetFeeSplit(row)?.basic))
|
const totalBudgetFeeBasic = computed(() => sumNullableBy(detailRows.value, row => getBudgetFeeSplit(row)?.basic))
|
||||||
const totalBudgetFeeOptional = computed(() => sumNullableBy(detailRows.value, row => getBudgetFeeSplit(row)?.optional))
|
const totalBudgetFeeOptional = computed(() => sumNullableBy(detailRows.value, row => getBudgetFeeSplit(row)?.optional))
|
||||||
const totalBudgetFee = computed(() => sumNullableBy(detailRows.value, row => getBudgetFee(row)))
|
const totalBudgetFee = computed(() =>
|
||||||
|
sumNullableBy(detailRows.value.filter(e => e.budgetFee !== null && e.budgetFee !== undefined), row => getBudgetFee(row))
|
||||||
|
)
|
||||||
const pinnedTopRowData = computed(() => [
|
const pinnedTopRowData = computed(() => [
|
||||||
{
|
{
|
||||||
id: 'pinned-total-row',
|
id: 'pinned-total-row',
|
||||||
|
|||||||
@ -399,7 +399,6 @@ const columnDefs: ColDef<DetailRow>[] = [
|
|||||||
|
|
||||||
const totalWorkload = computed(() => sumByNumber(detailRows.value, row => row.workload))
|
const totalWorkload = computed(() => sumByNumber(detailRows.value, row => row.workload))
|
||||||
const totalBasicFee = computed(() => sumByNumber(detailRows.value, row => calcBasicFee(row)))
|
const totalBasicFee = computed(() => sumByNumber(detailRows.value, row => calcBasicFee(row)))
|
||||||
|
|
||||||
const sumNullableBy = <T>(rows: T[], pick: (row: T) => unknown): number | null => {
|
const sumNullableBy = <T>(rows: T[], pick: (row: T) => unknown): number | null => {
|
||||||
let hasValid = false
|
let hasValid = false
|
||||||
const total = sumByNumber(rows, row => {
|
const total = sumByNumber(rows, row => {
|
||||||
@ -411,7 +410,7 @@ const sumNullableBy = <T>(rows: T[], pick: (row: T) => unknown): number | null =
|
|||||||
return hasValid ? total : null
|
return hasValid ? total : null
|
||||||
}
|
}
|
||||||
|
|
||||||
const totalServiceFee = computed(() => sumNullableBy(detailRows.value, row => calcServiceFee(row)))
|
const totalServiceFee = computed(() => sumNullableBy(detailRows.value.filter(e => e.basicFee !== null && e.basicFee !== undefined), row => calcServiceFee(row)))
|
||||||
const pinnedTopRowData = computed(() => [
|
const pinnedTopRowData = computed(() => [
|
||||||
{
|
{
|
||||||
id: 'pinned-total-row',
|
id: 'pinned-total-row',
|
||||||
|
|||||||
@ -124,7 +124,7 @@ interface QuantityMethodRowLike {
|
|||||||
unit?: unknown
|
unit?: unknown
|
||||||
quantity?: unknown
|
quantity?: unknown
|
||||||
unitPrice?: unknown
|
unitPrice?: unknown
|
||||||
budgetFee?: unknown
|
budgetFee?: number|null
|
||||||
remark?: unknown
|
remark?: unknown
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,12 +286,7 @@ interface ExportContract {
|
|||||||
reserve: ExportReserve | null
|
reserve: ExportReserve | null
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ExportRichTextCode {
|
|
||||||
richText: Array<{
|
|
||||||
text: string
|
|
||||||
font?: Record<string, unknown>
|
|
||||||
}>
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ExportMethod0 {
|
interface ExportMethod0 {
|
||||||
coe: number
|
coe: number
|
||||||
@ -314,8 +309,7 @@ interface ExportMethod5 {
|
|||||||
|
|
||||||
interface ExportAdditionalDetail {
|
interface ExportAdditionalDetail {
|
||||||
id: number
|
id: number
|
||||||
code: ExportRichTextCode
|
ref?: unknown
|
||||||
ref?: ExportRichTextCode
|
|
||||||
name: string
|
name: string
|
||||||
fee: number
|
fee: number
|
||||||
m0?: ExportMethod0
|
m0?: ExportMethod0
|
||||||
@ -324,16 +318,14 @@ interface ExportAdditionalDetail {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface ExportAdditional {
|
interface ExportAdditional {
|
||||||
code: ExportRichTextCode
|
ref?: unknown
|
||||||
ref?: ExportRichTextCode
|
|
||||||
name: string
|
name: string
|
||||||
fee: number
|
fee: number
|
||||||
det: ExportAdditionalDetail[]
|
det: ExportAdditionalDetail[]
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ExportReserve {
|
interface ExportReserve {
|
||||||
code: ExportRichTextCode
|
ref?: unknown
|
||||||
ref?: ExportRichTextCode
|
|
||||||
name: string
|
name: string
|
||||||
fee: number
|
fee: number
|
||||||
m0?: ExportMethod0
|
m0?: ExportMethod0
|
||||||
@ -1032,7 +1024,7 @@ const buildMethod1 = (rows: ScaleMethodRowLike[] | undefined): ExportMethod1 | n
|
|||||||
const det = rows
|
const det = rows
|
||||||
.map(row => {
|
.map(row => {
|
||||||
const major = toSafeInteger(row.id)
|
const major = toSafeInteger(row.id)
|
||||||
if (major == null || row.budgetFee ==null) return null
|
if (major == null || row.budgetFee == null) return null
|
||||||
const cost = toFiniteNumber(row.amount)
|
const cost = toFiniteNumber(row.amount)
|
||||||
const basicFee = toFiniteNumber(row.budgetFee)
|
const basicFee = toFiniteNumber(row.budgetFee)
|
||||||
if (basicFee != null) hasTotalValue = true
|
if (basicFee != null) hasTotalValue = true
|
||||||
@ -1065,7 +1057,6 @@ const buildMethod1 = (rows: ScaleMethodRowLike[] | undefined): ExportMethod1 | n
|
|||||||
.filter((item): item is ExportMethod1Detail => Boolean(item))
|
.filter((item): item is ExportMethod1Detail => Boolean(item))
|
||||||
|
|
||||||
if (det.length === 0 || !hasTotalValue) return null
|
if (det.length === 0 || !hasTotalValue) return null
|
||||||
console.log(det)
|
|
||||||
return {
|
return {
|
||||||
cost: sumNumbers(det.map(item => item.cost)),
|
cost: sumNumbers(det.map(item => item.cost)),
|
||||||
basicFee: sumNumbers(det.map(item => item.basicFee)),
|
basicFee: sumNumbers(det.map(item => item.basicFee)),
|
||||||
@ -1082,7 +1073,7 @@ const buildMethod2 = (rows: ScaleMethodRowLike[] | undefined): ExportMethod2 | n
|
|||||||
const det = rows
|
const det = rows
|
||||||
.map(row => {
|
.map(row => {
|
||||||
const major = toSafeInteger(row.id)
|
const major = toSafeInteger(row.id)
|
||||||
if (major == null || row.budgetFee ==null) return null
|
if (major == null || row.budgetFee == null) return null
|
||||||
const area = toFiniteNumber(row.landArea)
|
const area = toFiniteNumber(row.landArea)
|
||||||
const basicFee = toFiniteNumber(row.budgetFee)
|
const basicFee = toFiniteNumber(row.budgetFee)
|
||||||
if (basicFee != null) hasTotalValue = true
|
if (basicFee != null) hasTotalValue = true
|
||||||
@ -1131,7 +1122,7 @@ const buildMethod3 = (rows: WorkloadMethodRowLike[] | undefined): ExportMethod3
|
|||||||
const det = rows
|
const det = rows
|
||||||
.map(row => {
|
.map(row => {
|
||||||
const task = getTaskIdFromRowId(row.id)
|
const task = getTaskIdFromRowId(row.id)
|
||||||
if (task == null) return null
|
if (task == null || row.basicFee == null) return null
|
||||||
const amount = toFiniteNumber(row.workload)
|
const amount = toFiniteNumber(row.workload)
|
||||||
const basicFee = toFiniteNumber(row.basicFee)
|
const basicFee = toFiniteNumber(row.basicFee)
|
||||||
const fee = toFiniteNumber(row.serviceFee)
|
const fee = toFiniteNumber(row.serviceFee)
|
||||||
@ -1165,7 +1156,7 @@ const buildMethod4 = (rows: HourlyMethodRowLike[] | undefined): ExportMethod4 |
|
|||||||
const det = rows
|
const det = rows
|
||||||
.map(row => {
|
.map(row => {
|
||||||
const expert = getExpertIdFromRowId(row.id)
|
const expert = getExpertIdFromRowId(row.id)
|
||||||
if (expert == null) return null
|
if (expert == null || row.serviceBudget == null) return null
|
||||||
const personNum = toFiniteNumber(row.personnelCount)
|
const personNum = toFiniteNumber(row.personnelCount)
|
||||||
const workDay = toFiniteNumber(row.workdayCount)
|
const workDay = toFiniteNumber(row.workdayCount)
|
||||||
const fee = toFiniteNumber(row.serviceBudget)
|
const fee = toFiniteNumber(row.serviceBudget)
|
||||||
@ -1214,7 +1205,7 @@ const buildServiceFee = (
|
|||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
const createRichTextCode = (...parts: string[]): ExportRichTextCode => ({
|
const createRichTextCode = (...parts: string[]): unknown => ({
|
||||||
richText: parts
|
richText: parts
|
||||||
.map(item => String(item || '').trim())
|
.map(item => String(item || '').trim())
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
@ -1232,10 +1223,11 @@ const buildMethod0 = (payload: RateMethodRowLike | null | undefined): ExportMeth
|
|||||||
}
|
}
|
||||||
|
|
||||||
const buildMethod5 = (rows: QuantityMethodRowLike[] | undefined): ExportMethod5 | null => {
|
const buildMethod5 = (rows: QuantityMethodRowLike[] | undefined): ExportMethod5 | null => {
|
||||||
|
console.log(rows)
|
||||||
if (!Array.isArray(rows) || rows.length === 0) return null
|
if (!Array.isArray(rows) || rows.length === 0) return null
|
||||||
const subtotalRow = rows.find(row => String(row?.id || '') === 'fee-subtotal-fixed')
|
const subtotalRow = rows.find(row => String(row?.id || '') === 'fee-subtotal-fixed')
|
||||||
const subtotalFee = toFiniteNumber(subtotalRow?.budgetFee)
|
const subtotalFee = toFiniteNumber(subtotalRow?.budgetFee)
|
||||||
if (subtotalFee == null) return null
|
if (subtotalFee == null || subtotalRow?.budgetFee == null) return null
|
||||||
const det = rows
|
const det = rows
|
||||||
.filter(row => String(row?.id || '') !== 'fee-subtotal-fixed')
|
.filter(row => String(row?.id || '') !== 'fee-subtotal-fixed')
|
||||||
.map(row => {
|
.map(row => {
|
||||||
@ -1292,6 +1284,8 @@ const loadHtFeeMethodsByRow = async (mainStorageKey: string, rowId: string) => {
|
|||||||
zxFwPricingStore.loadHtFeeMethodState<DetailRowsStorageLike<QuantityMethodRowLike>>(mainStorageKey, rowId, 'quantity-unit-price-fee')
|
zxFwPricingStore.loadHtFeeMethodState<DetailRowsStorageLike<QuantityMethodRowLike>>(mainStorageKey, rowId, 'quantity-unit-price-fee')
|
||||||
])
|
])
|
||||||
const m0 = buildMethod0(rateState)
|
const m0 = buildMethod0(rateState)
|
||||||
|
|
||||||
|
|
||||||
const m4 = buildMethod4(Array.isArray(hourlyState?.detailRows) ? hourlyState?.detailRows : undefined)
|
const m4 = buildMethod4(Array.isArray(hourlyState?.detailRows) ? hourlyState?.detailRows : undefined)
|
||||||
const m5 = buildMethod5(Array.isArray(quantityState?.detailRows) ? quantityState?.detailRows : undefined)
|
const m5 = buildMethod5(Array.isArray(quantityState?.detailRows) ? quantityState?.detailRows : undefined)
|
||||||
if (!m0 && !m4 && !m5) return null
|
if (!m0 && !m4 && !m5) return null
|
||||||
@ -1303,7 +1297,7 @@ const loadHtFeeMethodsByRow = async (mainStorageKey: string, rowId: string) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const buildAdditionalDetailCode = (index: number, name: string): ExportRichTextCode => {
|
const buildAdditionalDetailCode = (index: number, name: string): unknown => {
|
||||||
const dictionaryIndex = additionalWorkList.findIndex(item => item === name)
|
const dictionaryIndex = additionalWorkList.findIndex(item => item === name)
|
||||||
const useIndex = dictionaryIndex >= 0 ? dictionaryIndex : index
|
const useIndex = dictionaryIndex >= 0 ? dictionaryIndex : index
|
||||||
const suffix = useIndex === 0 ? 'F' : useIndex === 1 ? 'X' : String(useIndex + 1)
|
const suffix = useIndex === 0 ? 'F' : useIndex === 1 ? 'X' : String(useIndex + 1)
|
||||||
@ -1323,11 +1317,11 @@ const buildAdditionalExport = async (contractId: string): Promise<ExportAddition
|
|||||||
if (!methodPayload) return null
|
if (!methodPayload) return null
|
||||||
const item: ExportAdditionalDetail = {
|
const item: ExportAdditionalDetail = {
|
||||||
id: index,
|
id: index,
|
||||||
code: buildAdditionalDetailCode(index, row.name),
|
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' }] },
|
||||||
name: row.name || `附加工作-${index + 1}`,
|
|
||||||
|
name: row.name,
|
||||||
fee: methodPayload.fee
|
fee: methodPayload.fee
|
||||||
}
|
}
|
||||||
item.ref = item.code
|
|
||||||
if (methodPayload.m0) item.m0 = methodPayload.m0
|
if (methodPayload.m0) item.m0 = methodPayload.m0
|
||||||
if (methodPayload.m4) item.m4 = methodPayload.m4
|
if (methodPayload.m4) item.m4 = methodPayload.m4
|
||||||
if (methodPayload.m5) item.m5 = methodPayload.m5
|
if (methodPayload.m5) item.m5 = methodPayload.m5
|
||||||
@ -1337,10 +1331,9 @@ const buildAdditionalExport = async (contractId: string): Promise<ExportAddition
|
|||||||
).filter((item): item is ExportAdditionalDetail => Boolean(item))
|
).filter((item): item is ExportAdditionalDetail => Boolean(item))
|
||||||
|
|
||||||
if (det.length === 0) return null
|
if (det.length === 0) return null
|
||||||
const addtionalCode = createRichTextCode('C', 'C')
|
|
||||||
return {
|
return {
|
||||||
code: addtionalCode,
|
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' }] },
|
||||||
ref: addtionalCode,
|
|
||||||
name: '附加工作',
|
name: '附加工作',
|
||||||
fee: sumNumbers(det.map(item => item.fee)),
|
fee: sumNumbers(det.map(item => item.fee)),
|
||||||
det
|
det
|
||||||
@ -1357,11 +1350,9 @@ const buildReserveExport = async (contractId: string): Promise<ExportReserve | n
|
|||||||
const methodPayload = await loadHtFeeMethodsByRow(storageKey, row.id)
|
const methodPayload = await loadHtFeeMethodsByRow(storageKey, row.id)
|
||||||
if (!methodPayload) continue
|
if (!methodPayload) continue
|
||||||
const reserve: ExportReserve = {
|
const reserve: ExportReserve = {
|
||||||
code: createRichTextCode('Y', 'B'),
|
|
||||||
name: row.name || '预备费',
|
name: row.name || '预备费',
|
||||||
fee: methodPayload.fee
|
fee: methodPayload.fee
|
||||||
}
|
}
|
||||||
reserve.ref = reserve.code
|
|
||||||
if (methodPayload.m0) reserve.m0 = methodPayload.m0
|
if (methodPayload.m0) reserve.m0 = methodPayload.m0
|
||||||
if (methodPayload.m4) reserve.m4 = methodPayload.m4
|
if (methodPayload.m4) reserve.m4 = methodPayload.m4
|
||||||
if (methodPayload.m5) reserve.m5 = methodPayload.m5
|
if (methodPayload.m5) reserve.m5 = methodPayload.m5
|
||||||
@ -1466,11 +1457,11 @@ const buildExportReportPayload = async (): Promise<ExportReportPayload> => {
|
|||||||
zxFwPricingStore.loadServicePricingMethodState<WorkloadMethodRowLike>(contractId, serviceIdText, 'workload'),
|
zxFwPricingStore.loadServicePricingMethodState<WorkloadMethodRowLike>(contractId, serviceIdText, 'workload'),
|
||||||
zxFwPricingStore.loadServicePricingMethodState<HourlyMethodRowLike>(contractId, serviceIdText, 'hourly')
|
zxFwPricingStore.loadServicePricingMethodState<HourlyMethodRowLike>(contractId, serviceIdText, 'hourly')
|
||||||
])
|
])
|
||||||
|
|
||||||
const method1Raw = method1State ? { detailRows: method1State.detailRows } : null
|
const method1Raw = method1State ? { detailRows: method1State.detailRows } : null
|
||||||
const method2Raw = method2State ? { detailRows: method2State.detailRows } : null
|
const method2Raw = method2State ? { detailRows: method2State.detailRows } : null
|
||||||
const method3Raw = method3State ? { detailRows: method3State.detailRows } : null
|
const method3Raw = method3State ? { detailRows: method3State.detailRows } : null
|
||||||
const method4Raw = method4State ? { detailRows: method4State.detailRows } : null
|
const method4Raw = method4State ? { detailRows: method4State.detailRows } : null
|
||||||
|
|
||||||
const method1 = buildMethod1(method1Raw?.detailRows)
|
const method1 = buildMethod1(method1Raw?.detailRows)
|
||||||
const method2 = buildMethod2(method2Raw?.detailRows)
|
const method2 = buildMethod2(method2Raw?.detailRows)
|
||||||
const method3 = buildMethod3(method3Raw?.detailRows)
|
const method3 = buildMethod3(method3Raw?.detailRows)
|
||||||
|
|||||||
@ -17,7 +17,9 @@ export const getBenchmarkBudgetSplitByScale = (
|
|||||||
mode: ScaleMode
|
mode: ScaleMode
|
||||||
): ScaleFeeSplitResult | null => {
|
): ScaleFeeSplitResult | null => {
|
||||||
const scaleValue = toFiniteNumberOrNull(value)
|
const scaleValue = toFiniteNumberOrNull(value)
|
||||||
|
|
||||||
const result = getBasicFeeFromScale(scaleValue, mode)
|
const result = getBasicFeeFromScale(scaleValue, mode)
|
||||||
|
|
||||||
if (!result) return null
|
if (!result) return null
|
||||||
|
|
||||||
const basic = roundTo(result.basic, 2)
|
const basic = roundTo(result.basic, 2)
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
{"root":["./src/main.ts","./src/sql.ts","./src/components/ui/button/index.ts","./src/components/ui/card/index.ts","./src/components/ui/scroll-area/index.ts","./src/components/ui/tooltip/index.ts","./src/lib/decimal.ts","./src/lib/diyaggridoptions.ts","./src/lib/number.ts","./src/lib/numberformat.ts","./src/lib/pricingmethodtotals.ts","./src/lib/pricingscalefee.ts","./src/lib/utils.ts","./src/lib/xmfactordefaults.ts","./src/lib/zwarchive.ts","./src/lib/zxfwpricingsync.ts","./src/pinia/htfeemethodreload.ts","./src/pinia/pricingpanereload.ts","./src/pinia/tab.ts","./src/app.vue","./src/components/common/hourlyfeegrid.vue","./src/components/common/htfeegrid.vue","./src/components/common/htfeemethodgrid.vue","./src/components/common/methodunavailablenotice.vue","./src/components/common/xmfactorgrid.vue","./src/components/common/xmcommonaggrid.vue","./src/components/ui/button/button.vue","./src/components/ui/card/card.vue","./src/components/ui/card/cardaction.vue","./src/components/ui/card/cardcontent.vue","./src/components/ui/card/carddescription.vue","./src/components/ui/card/cardfooter.vue","./src/components/ui/card/cardheader.vue","./src/components/ui/card/cardtitle.vue","./src/components/ui/scroll-area/scrollarea.vue","./src/components/ui/scroll-area/scrollbar.vue","./src/components/ui/tooltip/tooltipcontent.vue","./src/components/views/ht.vue","./src/components/views/htadditionalworkfee.vue","./src/components/views/htconsultcategoryfactor.vue","./src/components/views/htfeemethodtypelineview.vue","./src/components/views/htfeeratemethodform.vue","./src/components/views/htmajorfactor.vue","./src/components/views/htreservefee.vue","./src/components/views/servicecheckboxselector.vue","./src/components/views/xmconsultcategoryfactor.vue","./src/components/views/xmmajorfactor.vue","./src/components/views/zxfwview.vue","./src/components/views/htcard.vue","./src/components/views/htinfo.vue","./src/components/views/info.vue","./src/components/views/xmcard.vue","./src/components/views/xminfo.vue","./src/components/views/zxfw.vue","./src/components/views/pricingview/hourlypricingpane.vue","./src/components/views/pricingview/investmentscalepricingpane.vue","./src/components/views/pricingview/landscalepricingpane.vue","./src/components/views/pricingview/workloadpricingpane.vue","./src/layout/tab.vue","./src/layout/typeline.vue"],"version":"5.9.3"}
|
{"root":["./src/main.ts","./src/sql.ts","./src/components/ui/button/index.ts","./src/components/ui/card/index.ts","./src/components/ui/scroll-area/index.ts","./src/components/ui/tooltip/index.ts","./src/lib/decimal.ts","./src/lib/diyaggridoptions.ts","./src/lib/number.ts","./src/lib/numberformat.ts","./src/lib/pricingmethodtotals.ts","./src/lib/pricingscalefee.ts","./src/lib/utils.ts","./src/lib/xmfactordefaults.ts","./src/lib/zwarchive.ts","./src/lib/zxfwpricingsync.ts","./src/pinia/kv.ts","./src/pinia/tab.ts","./src/pinia/zxfwpricing.ts","./src/pinia/plugin/indexdb.ts","./src/pinia/plugin/types.d.ts","./src/app.vue","./src/components/common/hourlyfeegrid.vue","./src/components/common/htfeegrid.vue","./src/components/common/htfeemethodgrid.vue","./src/components/common/methodunavailablenotice.vue","./src/components/common/xmfactorgrid.vue","./src/components/common/xmcommonaggrid.vue","./src/components/ui/button/button.vue","./src/components/ui/card/card.vue","./src/components/ui/card/cardaction.vue","./src/components/ui/card/cardcontent.vue","./src/components/ui/card/carddescription.vue","./src/components/ui/card/cardfooter.vue","./src/components/ui/card/cardheader.vue","./src/components/ui/card/cardtitle.vue","./src/components/ui/scroll-area/scrollarea.vue","./src/components/ui/scroll-area/scrollbar.vue","./src/components/ui/tooltip/tooltipcontent.vue","./src/components/views/ht.vue","./src/components/views/htadditionalworkfee.vue","./src/components/views/htconsultcategoryfactor.vue","./src/components/views/htfeemethodtypelineview.vue","./src/components/views/htfeeratemethodform.vue","./src/components/views/htmajorfactor.vue","./src/components/views/htreservefee.vue","./src/components/views/servicecheckboxselector.vue","./src/components/views/xmconsultcategoryfactor.vue","./src/components/views/xmmajorfactor.vue","./src/components/views/zxfwview.vue","./src/components/views/htcard.vue","./src/components/views/htinfo.vue","./src/components/views/info.vue","./src/components/views/xmcard.vue","./src/components/views/xminfo.vue","./src/components/views/zxfw.vue","./src/components/views/pricingview/hourlypricingpane.vue","./src/components/views/pricingview/investmentscalepricingpane.vue","./src/components/views/pricingview/landscalepricingpane.vue","./src/components/views/pricingview/workloadpricingpane.vue","./src/layout/tab.vue","./src/layout/typeline.vue"],"version":"5.9.3"}
|
||||||
Loading…
x
Reference in New Issue
Block a user