添加基础表维护

This commit is contained in:
lzm
2026-04-25 18:10:45 +08:00
parent 8f9205a6a1
commit 38c634f8de
29 changed files with 4710 additions and 686 deletions

View File

@@ -1,5 +1,5 @@
<template>
<Dialog v-model="dialogVisible" title="合约规划编辑" width="1120">
<Dialog v-model="dialogVisible" :title="dialogTitle" width="1120">
<el-form
ref="formRef"
v-loading="formLoading"
@@ -7,16 +7,27 @@
:rules="formRules"
label-width="150px"
>
<el-divider content-position="left">规划信息</el-divider>
<el-divider content-position="left">规划信息</el-divider>
<el-row :gutter="16">
<el-col :span="8">
<el-form-item label="归属类型">
<el-input :model-value="formData.ownershipType" disabled />
<el-input :model-value="ownershipTypeLabel" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="产值计算方式">
<el-input :model-value="formData.calculationMethod" disabled />
<el-form-item label="产值计算方式" prop="calculationMethod">
<el-select
v-model="formData.calculationMethod"
class="!w-1/1"
placeholder="请选择产值计算方式"
>
<el-option
v-for="item in calculationMethodOptions"
:key="String(item.value)"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
@@ -25,6 +36,7 @@
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="8">
<el-form-item label="规划金额(元)">
@@ -32,7 +44,7 @@
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="管理费率(%)">
<el-form-item label="管理费率(%)">
<el-input :model-value="formatPercentText(formData.managementFeeRate)" disabled />
</el-form-item>
</el-col>
@@ -42,6 +54,36 @@
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="8">
<el-form-item label="设计部位" prop="designPart">
<el-select
v-model="formData.designPart"
class="!w-1/1"
clearable
placeholder="请选择设计部位"
>
<el-option
v-for="item in DESIGN_PART_OPTIONS"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="建筑类型" prop="buildingType">
<el-input
v-model="formData.buildingType"
maxlength="100"
placeholder="请输入建筑类型"
/>
</el-form-item>
</el-col>
</el-row>
<el-divider content-position="left">测算参数</el-divider>
<el-row :gutter="16">
<el-col :span="8">
@@ -56,7 +98,7 @@
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="面积()" prop="planningArea">
<el-form-item label="工程总面积()" prop="planningArea">
<el-input-number
v-model="formData.planningArea"
:min="0"
@@ -68,11 +110,12 @@
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="合同单价元/㎡)">
<el-form-item label="合同单价(元/m²)">
<el-input :model-value="contractUnitPricePreview" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="8">
<el-form-item label="设计阶段" prop="designStage">
@@ -82,8 +125,8 @@
placeholder="请选择设计阶段"
>
<el-option
v-for="item in DESIGN_STAGE_OPTIONS"
:key="item.value"
v-for="item in designStageOptions"
:key="String(item.value)"
:label="item.label"
:value="item.value"
/>
@@ -91,6 +134,7 @@
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="8">
<el-form-item label="本次设计阶段比例(%)" prop="currentDesignStageRatio">
@@ -127,6 +171,7 @@
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col v-if="showCalculationRatioField" :span="8">
<el-form-item :label="`${calculationRatioLabel}(%)`" prop="calculationRatio">
@@ -153,20 +198,6 @@
</el-form-item>
</el-col>
</el-row>
<!-- <el-row :gutter="16">
<el-col :span="24">
<el-form-item label="提取进度备注" prop="progressRemark">
<el-input
v-model="formData.progressRemark"
:rows="3"
maxlength="500"
placeholder="请输入合约规划层级的提取进度备注"
show-word-limit
type="textarea"
/>
</el-form-item>
</el-col>
</el-row> -->
<template v-if="showMajorFactorFields">
<el-divider content-position="left">专业所测算参数</el-divider>
@@ -240,7 +271,7 @@
<el-divider content-position="left">指导价法参数</el-divider>
<el-row :gutter="16">
<el-col :span="8">
<el-form-item label="内部指导单价元/㎡)" prop="internalGuidanceUnitPrice">
<el-form-item label="内部指导单价(元/m²)" prop="internalGuidanceUnitPrice">
<el-input-number
v-model="formData.internalGuidanceUnitPrice"
:min="0"
@@ -265,8 +296,8 @@
placeholder="请选择虚拟产值计算方式"
>
<el-option
v-for="item in VIRTUAL_CALCULATION_METHOD_OPTIONS"
:key="item.value"
v-for="item in virtualCalculationMethodOptions"
:key="String(item.value)"
:label="item.label"
:value="item.value"
/>
@@ -298,9 +329,9 @@
</el-form-item>
</el-col>
</el-row>
<el-row v-if="showVirtualGuidanceFields" :gutter="16">
<el-row v-if="showGuidanceUnitPriceField" :gutter="16">
<el-col :span="8">
<el-form-item label="指导单价(元)" prop="guidanceUnitPrice">
<el-form-item label="指导单价(元/m²)" prop="guidanceUnitPrice">
<el-input-number
v-model="formData.guidanceUnitPrice"
:min="0"
@@ -311,6 +342,8 @@
/>
</el-form-item>
</el-col>
</el-row>
<el-row v-if="showGuidanceTotalPriceField" :gutter="16">
<el-col :span="8">
<el-form-item label="指导总价(元)" prop="guidanceTotalPrice">
<el-input-number
@@ -324,20 +357,6 @@
</el-form-item>
</el-col>
</el-row>
<el-row v-if="showVirtualTotalPriceFields" :gutter="16">
<el-col :span="8">
<el-form-item label="虚拟总价(元)" prop="virtualTotalPrice">
<el-input-number
v-model="formData.virtualTotalPrice"
:min="0"
:precision="2"
:step="1000"
class="!w-1/1"
controls-position="right"
/>
</el-form-item>
</el-col>
</el-row>
</template>
</el-form>
<template #footer>
@@ -351,7 +370,10 @@
import type { FormRules } from 'element-plus'
import * as PlanningApi from '@/api/tjt/planning'
import {
CALCULATION_METHOD_OPTIONS,
DEFAULT_WORKING_DAY_UNIT_PRICE,
DESIGN_STAGE_OPTIONS,
OWNERSHIP_TYPE_OPTIONS,
VIRTUAL_CALCULATION_METHOD_OPTIONS,
formatAmountText,
formatPercentText,
@@ -365,14 +387,44 @@ import {
isMajorOwnership,
isSubcontractOwnership,
isVirtualGuidanceMethod,
isVirtualGuidanceTotalPriceMethod,
isVirtualOutputMethod,
isVirtualTotalPriceMethod,
isWorkingDayMethod,
normalizeCalculationMethod,
normalizeDesignStage,
normalizeOwnershipType,
normalizeVirtualCalculationMethod,
toPercentValue
} from '@/views/tjt/shared/planning'
defineOptions({ name: 'TjtPlanningOutputForm' })
const DESIGN_PART_OPTIONS = [
{ label: '地上部分', value: '地上部分' },
{ label: '地下部分', value: '地下部分' }
]
const OWNERSHIP_TYPE_LABELS = ['专业所', '综合所', '专业分包']
const CALCULATION_METHOD_LABELS = ['指导价法', '合同价法', '虚拟产值法']
const DESIGN_STAGE_LABELS = ['方案', '施工图', '方案+施工图']
const VIRTUAL_CALCULATION_METHOD_LABELS = ['指导单价法', '指导总价法', '工日法']
const createDisplayOptions = (
source: Array<{ label: string; value: string }>,
labels: string[]
) => source.map((item, index) => ({ label: labels[index] || item.label, value: item.value }))
const ownershipTypeOptions = createDisplayOptions(OWNERSHIP_TYPE_OPTIONS, OWNERSHIP_TYPE_LABELS)
const calculationMethodOptions = createDisplayOptions(
CALCULATION_METHOD_OPTIONS,
CALCULATION_METHOD_LABELS
)
const designStageOptions = createDisplayOptions(DESIGN_STAGE_OPTIONS, DESIGN_STAGE_LABELS)
const virtualCalculationMethodOptions = createDisplayOptions(
VIRTUAL_CALCULATION_METHOD_OPTIONS,
VIRTUAL_CALCULATION_METHOD_LABELS
)
const { t } = useI18n()
const message = useMessage()
@@ -387,15 +439,31 @@ const formData = ref<PlanningApi.ProjectPlanningVO>({
planningContent: ''
})
const getOptionLabel = (options: Array<{ label: string; value: string }>, value?: string) =>
options.find((item) => item.value === value)?.label || value || ''
const ownershipTypeLabel = computed(() =>
getOptionLabel(ownershipTypeOptions, formData.value.ownershipType)
)
const normalizeFormData = (data: PlanningApi.ProjectPlanningVO): PlanningApi.ProjectPlanningVO => ({
...data,
ownershipType: normalizeOwnershipType(data.ownershipType) || data.ownershipType || '',
calculationMethod: normalizeCalculationMethod(data.calculationMethod) || data.calculationMethod || '',
designPart: DESIGN_PART_OPTIONS.find((item) => item.value === data.designPart)?.value || undefined,
designStage: normalizeDesignStage(data.designStage),
virtualCalculationMethod: normalizeVirtualCalculationMethod(data.virtualCalculationMethod),
reviewOutsourceFlag: data.reviewOutsourceFlag ?? false,
totalDistributionAmount: data.totalDistributionAmount ?? 1,
progressRemark: data.progressRemark ?? '',
drawingSetFactor: data.drawingSetFactor ?? 1,
scaleFactor: data.scaleFactor ?? 1,
modificationFactor: data.modificationFactor ?? 1,
complexityFactor: data.complexityFactor ?? 1
complexityFactor: data.complexityFactor ?? 1,
workingDayUnitPrice:
data.workingDayUnitPrice ??
(isWorkingDayMethod(data.virtualCalculationMethod) ? DEFAULT_WORKING_DAY_UNIT_PRICE : undefined),
guidanceTotalPrice: data.guidanceTotalPrice
})
const planningStartYearValue = computed({
@@ -452,16 +520,19 @@ const showVirtualOutputSection = computed(
isVirtualOutputMethod(formData.value.calculationMethod)
)
const showWorkingDayFields = computed(() => isWorkingDayMethod(formData.value.virtualCalculationMethod))
const showVirtualGuidanceFields = computed(
const showGuidanceUnitPriceField = computed(
() => isVirtualGuidanceMethod(formData.value.virtualCalculationMethod)
)
const showVirtualTotalPriceFields = computed(
() => isVirtualTotalPriceMethod(formData.value.virtualCalculationMethod)
const showGuidanceTotalPriceField = computed(
() => isVirtualGuidanceTotalPriceMethod(formData.value.virtualCalculationMethod)
)
const formRules = reactive<FormRules>({
calculationMethod: [{ required: true, message: '产值计算方式不能为空', trigger: 'change' }],
designPart: [{ required: true, message: '设计部位不能为空', trigger: 'change' }],
buildingType: [{ required: true, message: '建筑类型不能为空', trigger: 'blur' }],
planningStartYear: [{ required: true, message: '开始年度不能为空', trigger: 'change' }],
planningArea: [{ required: true, message: '面积不能为空', trigger: 'blur' }],
planningArea: [{ required: true, message: '工程总面积不能为空', trigger: 'blur' }],
designStage: [{ required: true, message: '设计阶段不能为空', trigger: 'change' }],
currentDesignStageRatio: [
{ required: true, message: '本次设计阶段比例不能为空', trigger: 'blur' }
@@ -482,7 +553,10 @@ const formRules = reactive<FormRules>({
internalGuidanceUnitPrice: [
{
validator: (_rule, value, callback) => {
if (showInternalGuidanceUnitPriceField.value && (value === undefined || value === null || value === '')) {
if (
showInternalGuidanceUnitPriceField.value &&
(value === undefined || value === null || value === '')
) {
callback(new Error('内部指导单价不能为空'))
return
}
@@ -502,6 +576,60 @@ const formRules = reactive<FormRules>({
},
trigger: 'change'
}
],
workingDayCount: [
{
validator: (_rule, value, callback) => {
if (showWorkingDayFields.value && (value === undefined || value === null || value === '')) {
callback(new Error('工日不能为空'))
return
}
callback()
},
trigger: 'blur'
}
],
workingDayUnitPrice: [
{
validator: (_rule, value, callback) => {
if (showWorkingDayFields.value && (value === undefined || value === null || value === '')) {
callback(new Error('工日单价不能为空'))
return
}
callback()
},
trigger: 'blur'
}
],
guidanceUnitPrice: [
{
validator: (_rule, value, callback) => {
if (
showGuidanceUnitPriceField.value &&
(value === undefined || value === null || value === '')
) {
callback(new Error('指导单价不能为空'))
return
}
callback()
},
trigger: 'blur'
}
],
guidanceTotalPrice: [
{
validator: (_rule, value, callback) => {
if (
showGuidanceTotalPriceField.value &&
(value === undefined || value === null || value === '')
) {
callback(new Error('指导总价不能为空'))
return
}
callback()
},
trigger: 'blur'
}
]
})
@@ -528,10 +656,24 @@ const handleReviewOutsourceFlagChange = () => {
applyReviewOutsourceDefault()
}
watch(
() => formData.value.virtualCalculationMethod,
(value) => {
if (
isWorkingDayMethod(value) &&
(formData.value.workingDayUnitPrice === undefined || formData.value.workingDayUnitPrice === null)
) {
formData.value.workingDayUnitPrice = DEFAULT_WORKING_DAY_UNIT_PRICE
}
}
)
const buildSavePayload = (): PlanningApi.ProjectPlanningSaveVO => ({
id: formData.value.id,
projectId: formData.value.projectId,
ownershipType: formData.value.ownershipType,
designPart: formData.value.designPart,
buildingType: formData.value.buildingType,
calculationMethod: formData.value.calculationMethod,
planningContent: formData.value.planningContent,
planningAmount: formData.value.planningAmount,
@@ -556,7 +698,6 @@ const buildSavePayload = (): PlanningApi.ProjectPlanningSaveVO => ({
workingDayUnitPrice: formData.value.workingDayUnitPrice,
guidanceUnitPrice: formData.value.guidanceUnitPrice,
guidanceTotalPrice: formData.value.guidanceTotalPrice,
virtualTotalPrice: formData.value.virtualTotalPrice,
calculationRatio: formData.value.calculationRatio
})