0509新功能优化

This commit is contained in:
lzm
2026-05-08 17:38:50 +08:00
parent 9ea02751de
commit 92c5071fab
18 changed files with 695 additions and 345 deletions

2
.env
View File

@@ -1,5 +1,5 @@
# 标题
VITE_APP_TITLE=产值管理系统
VITE_APP_TITLE=项目产值管理系统
# 项目本地运行端口号
VITE_PORT=80

View File

@@ -7,11 +7,11 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="keywords"
content="产值管理系统"
content="项目产值管理系统"
/>
<meta
name="description"
content="产值管理系统"
content="项目产值管理系统"
/>
<title>%VITE_APP_TITLE%</title>
</head>

View File

@@ -3,12 +3,18 @@ import request from '@/config/axios'
export interface ProjectPlanningVO {
id?: number
projectId: number
sortNo?: number
ownershipType: string
calculationMethod: string
planningContent: string
planningAmount?: number
contractValueQuantity?: number
contractValueUnitPrice?: number
managementFeeRate?: number
managementFee?: number
vatRate?: number
vatAmount?: number
projectBudgetOutputValue?: number
implementationTeam?: string
planningStartYear?: number
planningArea?: number
@@ -44,7 +50,10 @@ export type ProjectPlanningSaveVO = Omit<
ProjectPlanningVO,
| 'allocatedAmount'
| 'pendingAmount'
| 'planningAmount'
| 'managementFee'
| 'vatAmount'
| 'projectBudgetOutputValue'
| 'contractUnitPrice'
| 'totalAdjustmentFactor'
| 'assessmentArea'

View File

@@ -3,6 +3,7 @@ import request from '@/config/axios'
export interface ProjectProfitVO {
projectId: number
projectName: string
sortNo?: number
contractSignedFlag: boolean
contractAmount?: number
finalSettlementAmount?: number

View File

@@ -13,6 +13,7 @@ export interface ProjectRolePersonVO {
export interface ProjectVO {
id?: number
projectName: string
sortNo?: number
contractSignedFlag: boolean
contractAmount?: number
totalConstructionArea?: number

View File

@@ -115,7 +115,7 @@ export default {
},
login: {
welcome: '欢迎使用本系统',
message: '产值管理系统',
message: '项目产值管理系统',
tenantname: '租户名称',
username: '用户名',
password: '密码',
@@ -374,7 +374,7 @@ export default {
qrSignInFormTitle: '二维码登录',
signUpFormTitle: '注册',
forgetFormTitle: '重置密码',
signInTitle: '产值管理系统',
signInTitle: '项目产值管理系统',
signInDesc: '输入您的个人详细信息开始使用!',
policy: '我同意xxx隐私政策',
scanSign: `扫码后点击"确认",即可完成登录`,

View File

@@ -7,12 +7,12 @@
class="-mb-15px"
label-width="88px"
>
<el-form-item label="工程名称" prop="projectName">
<el-form-item label="项目名称" prop="projectName">
<el-input
v-model="queryParams.projectName"
class="!w-240px"
clearable
placeholder="请输入工程名称"
placeholder="请输入项目名称"
@keyup.enter="handleQuery"
/>
</el-form-item>
@@ -47,14 +47,21 @@
highlight-current-row
@current-change="handleCurrentProjectChange"
>
<el-table-column align="center" label="项目ID" prop="id" width="88" />
<el-table-column align="center" label="工程名称" min-width="220" prop="projectName" />
<el-table-column align="center" label="项目负责人" min-width="180">
<el-table-column
:index="getProjectRowIndex"
align="center"
label="序号"
type="index"
width="80"
/>
<el-table-column align="center" label="项目名称" min-width="220" prop="projectName" />
<el-table-column align="center" label="工程负责人" min-width="180">
<template #default="scope">
{{ getProjectLeadText(scope.row.projectManagerName, scope.row.engineeringPrincipalName) }}
</template>
</el-table-column>
<el-table-column align="center" label="开始年度" prop="projectStartYear" width="120" />
<el-table-column align="center" label="排序" prop="sortNo" width="80" />
</el-table>
<Pagination
v-model:limit="queryParams.pageSize"
@@ -77,7 +84,8 @@
highlight-current-row
@current-change="handleCurrentPlanningChange"
>
<el-table-column align="center" label="规划内容" min-width="180" prop="planningContent" />
<el-table-column align="center" label="序号" type="index" width="70" />
<el-table-column align="center" label="项目任务包" min-width="180" prop="planningContent" />
<el-table-column align="center" label="归属类型" min-width="110">
<template #default="scope">
{{ getOwnershipTypeLabel(scope.row.ownershipType) }}
@@ -89,6 +97,7 @@
{{ formatAmountText(scope.row.assessmentOutputValue) }}
</template>
</el-table-column>
<el-table-column align="center" label="排序" prop="sortNo" width="80" />
</el-table>
</ContentWrap>
</el-col>
@@ -117,8 +126,8 @@
<el-descriptions :column="2" border title="基础信息">
<el-descriptions-item label="项目名称">{{ formData.projectName || '-' }}</el-descriptions-item>
<el-descriptions-item label="规划内容">{{ formData.planningContent || '-' }}</el-descriptions-item>
<el-descriptions-item label="项目负责人">
<el-descriptions-item label="项目任务包">{{ formData.planningContent || '-' }}</el-descriptions-item>
<el-descriptions-item label="工程负责人">
{{ getProjectLeadText(formData.projectManagerName, formData.engineeringLeaderName) }}
</el-descriptions-item>
</el-descriptions>
@@ -288,7 +297,7 @@ interface QuarterYearRow {
}
const annualCategoryOptions: { label: string; value: AnnualCategoryKey }[] = [
{ label: '项目经理/项目负责人', value: 'project_lead' },
{ label: '项目经理/工程负责人', value: 'project_lead' },
{ label: '建筑专业', value: 'arch' },
{ label: '装修专业', value: 'decor' },
{ label: '结构专业', value: 'struct' },
@@ -325,6 +334,9 @@ const queryParams = reactive<ProjectApi.ProjectPageReqVO>({
projectStartYear: undefined
})
const getProjectRowIndex = (index: number) =>
(queryParams.pageNo - 1) * queryParams.pageSize + index + 1
const queryProjectStartYearValue = computed({
get: () => (queryParams.projectStartYear ? String(queryParams.projectStartYear) : undefined),
set: (value?: string) => {
@@ -360,7 +372,7 @@ const buildProjectRows = (model?: OutputSplitApi.ProjectOutputSplitVO) => {
return [
{
key: 'projectLeadRatio',
label: '项目经理/项目负责人',
label: '项目经理/工程负责人',
percentText: formatRatioText(model.projectLeadRatio),
percent: toPercentValue(model.projectLeadRatio),
amount: model.projectLeadAmount

View File

@@ -31,7 +31,7 @@
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="规划内容">
<el-form-item label="项目任务包">
<el-input :model-value="formData.planningContent" disabled />
</el-form-item>
</el-col>
@@ -39,17 +39,53 @@
<el-row :gutter="16">
<el-col :span="8">
<el-form-item label="规划金额(元)">
<el-form-item label="合同产值数量">
<el-input :model-value="formatQuantityText(formData.contractValueQuantity)" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="合同产值单价">
<el-input :model-value="formatQuantityText(formData.contractValueUnitPrice)" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="分项合同产值(元)">
<el-input :model-value="formatAmountText(formData.planningAmount)" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="8">
<el-form-item label="增值税率(%)">
<el-input :model-value="formatPercentText(formData.vatRate)" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="增值税(元)">
<el-input :model-value="formatAmountText(formData.vatAmount)" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="管理费率(%)">
<el-input :model-value="formatPercentText(formData.managementFeeRate)" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="8">
<el-form-item label="实施团队">
<el-form-item label="管理费(元)">
<el-input :model-value="formatAmountText(formData.managementFee)" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="项目预算产值(元)">
<el-input :model-value="formatAmountText(formData.projectBudgetOutputValue)" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="意向实施团队">
<el-input :model-value="formData.implementationTeam || '-'" disabled />
</el-form-item>
</el-col>
@@ -247,7 +283,6 @@
<el-button plain type="primary" @click="addGuideDetailRow">
<template #icon><i class="el-icon-plus"></i></template>新增明细
</el-button>
<span class="text-12px text-gray-400">💡 提示数字字段已隐藏加减箭头以优化显示支持直接输入或复制粘贴</span>
</div>
<el-table :data="guideDetails" border max-height="460" class="optimized-table">
@@ -544,8 +579,13 @@ const createFormData = (): PlanningApi.ProjectPlanningVO => ({
calculationMethod: '',
planningContent: '',
planningAmount: undefined,
contractValueQuantity: undefined,
contractValueUnitPrice: undefined,
managementFeeRate: undefined,
managementFee: undefined,
vatRate: undefined,
vatAmount: undefined,
projectBudgetOutputValue: undefined,
implementationTeam: '',
planningStartYear: undefined,
planningArea: undefined,
@@ -639,6 +679,9 @@ const normalizeFormData = (data: PlanningApi.ProjectPlanningVO): PlanningApi.Pro
...data,
ownershipType: normalizeOwnershipType(data.ownershipType) || data.ownershipType || '',
calculationMethod: normalizeCalculationMethod(data.calculationMethod) || data.calculationMethod || '',
contractValueQuantity: data.contractValueQuantity ?? 1,
contractValueUnitPrice: data.contractValueUnitPrice ?? data.planningAmount,
vatRate: data.vatRate ?? 0.06,
designStage: normalizeDesignStage(data.designStage),
virtualCalculationMethod: normalizeVirtualCalculationMethod(data.virtualCalculationMethod),
reviewOutsourceFlag: data.reviewOutsourceFlag ?? false,
@@ -785,6 +828,13 @@ const formatFactorText = (value?: number, digits = 4) => {
return Number(value).toFixed(digits)
}
const formatQuantityText = (value?: number, digits = 4) => {
if (value === undefined || value === null) {
return '-'
}
return Number(value).toFixed(digits)
}
const setGuideDetailPercentValue = (
row: GuideDetailRow,
field: 'complexityFactor' | 'designRatio',
@@ -940,8 +990,11 @@ const buildSavePayload = (): PlanningApi.ProjectPlanningSaveVO => ({
ownershipType: formData.value.ownershipType,
calculationMethod: formData.value.calculationMethod,
planningContent: formData.value.planningContent,
planningAmount: formData.value.planningAmount,
sortNo: formData.value.sortNo,
contractValueQuantity: formData.value.contractValueQuantity,
contractValueUnitPrice: formData.value.contractValueUnitPrice,
managementFeeRate: formData.value.managementFeeRate,
vatRate: formData.value.vatRate,
implementationTeam: formData.value.implementationTeam,
planningStartYear: formData.value.planningStartYear,
planningArea: showGuideDetailSection.value
@@ -1104,4 +1157,4 @@ const submitForm = async () => {
:deep(.text-primary) {
color: var(--el-color-primary);
}
</style>
</style>

View File

@@ -211,6 +211,9 @@ const open = async (id: number) => {
const planning = await PlanningApi.getProjectPlanning(id)
formData.value = {
...planning,
contractValueQuantity: planning.contractValueQuantity ?? 1,
contractValueUnitPrice: planning.contractValueUnitPrice ?? planning.planningAmount,
vatRate: planning.vatRate ?? 0.06,
totalDistributionAmount: planning.totalDistributionAmount ?? 1,
progressRemark: planning.progressRemark ?? ''
}
@@ -315,11 +318,14 @@ const submitForm = async () => {
await PlanningApi.updateProjectPlanning({
id: formData.value.id,
projectId: formData.value.projectId,
sortNo: formData.value.sortNo,
ownershipType: formData.value.ownershipType,
calculationMethod: formData.value.calculationMethod,
planningContent: formData.value.planningContent,
planningAmount: formData.value.planningAmount,
contractValueQuantity: formData.value.contractValueQuantity,
contractValueUnitPrice: formData.value.contractValueUnitPrice,
managementFeeRate: formData.value.managementFeeRate,
vatRate: formData.value.vatRate,
implementationTeam: formData.value.implementationTeam,
planningStartYear: formData.value.planningStartYear,
planningArea: formData.value.planningArea,

View File

@@ -7,12 +7,12 @@
class="-mb-15px"
label-width="88px"
>
<el-form-item label="工程名称" prop="projectName">
<el-form-item label="项目名称" prop="projectName">
<el-input
v-model="queryParams.projectName"
class="!w-240px"
clearable
placeholder="请输入工程名称"
placeholder="请输入项目名称"
@keyup.enter="handleQuery"
/>
</el-form-item>
@@ -62,10 +62,16 @@
highlight-current-row
@current-change="handleCurrentProjectChange"
>
<el-table-column align="center" label="项目 ID" prop="id" width="88" />
<el-table-column
:index="getProjectRowIndex"
align="center"
label="序号"
type="index"
width="80"
/>
<el-table-column
align="center"
label="工程名称"
label="项目名称"
min-width="220"
prop="projectName"
show-overflow-tooltip
@@ -78,7 +84,7 @@
</template>
</el-table-column>
<el-table-column align="center" label="项目开始年度" prop="projectStartYear" width="120" />
<el-table-column align="center" label="合同金额(元)" width="130">
<el-table-column align="center" label="合同产值(元)" width="130">
<template #default="scope">
{{ formatAmountText(scope.row.contractAmount) }}
</template>
@@ -95,6 +101,7 @@
prop="createTime"
width="180"
/>
<el-table-column align="center" label="排序" prop="sortNo" width="80" />
</el-table>
<Pagination
v-model:limit="queryParams.pageSize"
@@ -120,9 +127,10 @@
highlight-current-row
@current-change="handleCurrentPlanningChange"
>
<el-table-column align="center" label="序号" type="index" width="70" />
<el-table-column
align="center"
label="规划内容"
label="项目任务包"
min-width="170"
prop="planningContent"
show-overflow-tooltip
@@ -137,7 +145,7 @@
{{ getCalculationMethodLabel(scope.row.calculationMethod) }}
</template>
</el-table-column>
<el-table-column align="center" label="规划金额(元)" width="120">
<el-table-column align="center" label="分项合同产值(元)" width="120">
<template #default="scope">
{{ formatAmountText(scope.row.planningAmount) }}
</template>
@@ -152,6 +160,7 @@
{{ formatAmountText(scope.row.assessmentOutputValue) }}
</template>
</el-table-column>
<el-table-column align="center" label="排序" prop="sortNo" width="80" />
</el-table>
</ContentWrap>
</el-col>
@@ -190,7 +199,7 @@
</div>
<el-descriptions :column="2" border title="测算参数">
<el-descriptions-item label="规划金额(元)">
<el-descriptions-item label="分项合同产值(元)">
{{ formatAmountText(currentPlanning.planningAmount) }}
</el-descriptions-item>
<el-descriptions-item label="管理费费率">
@@ -199,7 +208,7 @@
<el-descriptions-item label="管理费(元)">
{{ formatAmountText(currentPlanning.managementFee) }}
</el-descriptions-item>
<el-descriptions-item label="实施团队">
<el-descriptions-item label="意向实施团队">
{{ currentPlanning.implementationTeam || '-' }}
</el-descriptions-item>
<el-descriptions-item label="开始年度">
@@ -429,6 +438,9 @@ const queryParams = reactive<ProjectApi.ProjectPageReqVO>({
projectStartYear: undefined
})
const getProjectRowIndex = (index: number) =>
(queryParams.pageNo - 1) * queryParams.pageSize + index + 1
const queryProjectStartYearValue = computed({
get: () => (queryParams.projectStartYear ? String(queryParams.projectStartYear) : undefined),
set: (value?: string) => {

View File

@@ -7,12 +7,12 @@
class="-mb-15px"
label-width="88px"
>
<el-form-item label="工程名称" prop="projectName">
<el-form-item label="项目名称" prop="projectName">
<el-input
v-model="queryParams.projectName"
class="!w-240px"
clearable
placeholder="请输入工程名称"
placeholder="请输入项目名称"
@keyup.enter="handleQuery"
/>
</el-form-item>
@@ -62,7 +62,14 @@
highlight-current-row
@current-change="handleCurrentProfitChange"
>
<el-table-column align="center" label="工程名称" min-width="220" prop="projectName" />
<el-table-column
:index="getProjectRowIndex"
align="center"
label="序号"
type="index"
width="80"
/>
<el-table-column align="center" label="项目名称" min-width="220" prop="projectName" />
<el-table-column align="center" label="是否签约" width="100">
<template #default="scope">
<el-tag :type="scope.row.contractSignedFlag ? 'success' : 'info'">
@@ -71,7 +78,7 @@
</template>
</el-table-column>
<el-table-column align="center" label="开始年度" prop="projectStartYear" width="100" />
<el-table-column align="center" label="合同金额(元)" width="120">
<el-table-column align="center" label="合同产值(元)" width="120">
<template #default="scope">
{{ formatAmountText(scope.row.contractAmount) }}
</template>
@@ -130,6 +137,7 @@
</span>
</template>
</el-table-column>
<el-table-column align="center" label="排序" prop="sortNo" width="80" />
</el-table>
<Pagination
v-model:limit="queryParams.pageSize"
@@ -149,7 +157,7 @@
</div>
<el-descriptions :column="3" border>
<el-descriptions-item label="合同金额(元)">
<el-descriptions-item label="合同产值(元)">
{{ formatAmountText(currentProfit.contractAmount) }}
</el-descriptions-item>
<el-descriptions-item label="最终结算金额(元)">
@@ -295,6 +303,9 @@ const queryParams = reactive<ProfitApi.ProjectProfitPageReqVO>({
projectStartYear: undefined
})
const getProjectRowIndex = (index: number) =>
(queryParams.pageNo - 1) * queryParams.pageSize + index + 1
const queryProjectStartYearValue = computed({
get: () => (queryParams.projectStartYear ? String(queryParams.projectStartYear) : undefined),
set: (value?: string) => {

View File

@@ -1,5 +1,5 @@
<template>
<Dialog v-model="dialogVisible" :title="dialogTitle" width="920">
<Dialog v-model="dialogVisible" :title="dialogTitle" width="980">
<el-form
ref="formRef"
v-loading="formLoading"
@@ -26,11 +26,11 @@
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="规划内容" prop="planningContent">
<el-form-item label="项目任务包" prop="planningContent">
<el-input
v-model="formData.planningContent"
maxlength="255"
placeholder="请输入规划内容"
placeholder="请输入项目任务包"
/>
</el-form-item>
</el-col>
@@ -38,17 +38,69 @@
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="规划金额(元)" prop="planningAmount">
<el-form-item label="合同产值数量" prop="contractValueQuantity">
<el-input-number
v-model="formData.planningAmount"
v-model="formData.contractValueQuantity"
:min="0"
:precision="2"
:precision="4"
:step="1"
class="!w-1/1"
controls-position="right"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="合同产值单价" prop="contractValueUnitPrice">
<el-input-number
v-model="formData.contractValueUnitPrice"
:min="0"
:precision="4"
:step="1000"
class="!w-1/1"
controls-position="right"
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="分项合同产值(元)">
<el-input :model-value="planningAmountPreview" class="readonly-result" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="意向实施团队" prop="implementationTeam">
<el-input
v-model="formData.implementationTeam"
maxlength="100"
placeholder="请输入意向实施团队"
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="增值税率(%)" prop="vatRate">
<el-input-number
v-model="vatRatePercent"
:min="0"
:precision="2"
:step="0.01"
class="!w-1/1"
controls-position="right"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="增值税(元)">
<el-input :model-value="vatAmountPreview" class="readonly-result" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="管理费率(%)" prop="managementFeeRate">
<el-input-number
@@ -61,20 +113,32 @@
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="管理费(元)">
<el-input :model-value="managementFeePreview" class="readonly-result" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="管理费(元)">
<el-input :model-value="managementFeePreview" disabled />
<el-form-item label="项目预算产值(元)">
<el-input
:model-value="projectBudgetOutputValuePreview"
class="budget-result"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="实施团队" prop="implementationTeam">
<el-input
v-model="formData.implementationTeam"
maxlength="100"
placeholder="请输入实施团队"
<el-form-item label="排序" prop="sortNo">
<el-input-number
v-model="formData.sortNo"
:min="0"
:precision="0"
:step="1"
class="!w-1/1"
controls-position="right"
/>
</el-form-item>
</el-col>
@@ -114,12 +178,18 @@ const createFormData = (
planningAmount?: number
): PlanningApi.ProjectPlanningVO => ({
projectId: projectId || 0,
sortNo: 0,
ownershipType: ownershipTypeOptions[0].value,
calculationMethod: '',
planningContent: '',
planningAmount,
contractValueQuantity: 1,
contractValueUnitPrice: planningAmount,
managementFeeRate: undefined,
implementationTeam: '',
vatRate: 0.06,
vatAmount: undefined,
projectBudgetOutputValue: undefined,
planningStartYear: undefined,
planningArea: undefined,
designStage: undefined,
@@ -164,31 +234,69 @@ const managementFeeRatePercent = computed({
}
})
const managementFeePreview = computed(() => {
const planningAmount = Number(formData.value.planningAmount || 0)
const managementFeeRate = Number(formData.value.managementFeeRate || 0)
return (planningAmount * managementFeeRate).toFixed(2)
const vatRatePercent = computed({
get: () => {
if (formData.value.vatRate === undefined || formData.value.vatRate === null) {
return undefined
}
return Number((Number(formData.value.vatRate) * 100).toFixed(2))
},
set: (value?: number) => {
formData.value.vatRate =
value === undefined || value === null ? undefined : Number((value / 100).toFixed(4))
}
})
const planningAmountPreviewValue = computed(() => {
const quantity = Number(formData.value.contractValueQuantity || 0)
const unitPrice = Number(formData.value.contractValueUnitPrice || 0)
return Number((quantity * unitPrice).toFixed(2))
})
const planningAmountPreview = computed(() => planningAmountPreviewValue.value.toFixed(2))
const managementFeePreview = computed(() => {
const managementFeeRate = Number(formData.value.managementFeeRate || 0)
return (planningAmountPreviewValue.value * managementFeeRate).toFixed(2)
})
const vatAmountPreview = computed(() => {
const vatRate = Number(formData.value.vatRate || 0)
return (planningAmountPreviewValue.value * vatRate).toFixed(2)
})
const projectBudgetOutputValuePreview = computed(() =>
(
planningAmountPreviewValue.value -
Number(managementFeePreview.value || 0) -
Number(vatAmountPreview.value || 0)
).toFixed(2)
)
const normalizeOwnershipType = (value?: string) =>
ownershipTypeOptions.find((item) => item.value === value)?.value || ownershipTypeOptions[0].value
const formRules = reactive<FormRules>({
projectId: [{ required: true, message: '请选择所属项目', trigger: 'change' }],
ownershipType: [{ required: true, message: '归属类型不能为空', trigger: 'change' }],
planningContent: [{ required: true, message: '规划内容不能为空', trigger: 'blur' }],
planningAmount: [{ required: true, message: '规划金额不能为空', trigger: 'blur' }],
managementFeeRate: [{ required: true, message: '管理费率不能为空', trigger: 'blur' }]
planningContent: [{ required: true, message: '项目任务包不能为空', trigger: 'blur' }],
contractValueQuantity: [{ required: true, message: '合同产值数量不能为空', trigger: 'blur' }],
contractValueUnitPrice: [{ required: true, message: '合同产值单价不能为空', trigger: 'blur' }],
managementFeeRate: [{ required: true, message: '管理费率不能为空', trigger: 'blur' }],
vatRate: [{ required: true, message: '增值税率不能为空', trigger: 'blur' }]
})
const buildSavePayload = (): PlanningApi.ProjectPlanningSaveVO => ({
id: formData.value.id,
projectId: formData.value.projectId,
sortNo: formData.value.sortNo ?? 0,
ownershipType: formData.value.ownershipType,
calculationMethod: formData.value.calculationMethod,
planningContent: formData.value.planningContent,
planningAmount: formData.value.planningAmount,
contractValueQuantity: formData.value.contractValueQuantity,
contractValueUnitPrice: formData.value.contractValueUnitPrice,
managementFeeRate: formData.value.managementFeeRate,
vatRate: formData.value.vatRate,
implementationTeam: formData.value.implementationTeam,
planningStartYear: formData.value.planningStartYear,
planningArea: formData.value.planningArea,
@@ -233,7 +341,11 @@ const open = async (
formData.value = {
...createFormData(options.projectId, options.defaultPlanningAmount),
...planning,
ownershipType: normalizeOwnershipType(planning.ownershipType)
ownershipType: normalizeOwnershipType(planning.ownershipType),
contractValueQuantity: planning.contractValueQuantity ?? 1,
contractValueUnitPrice:
planning.contractValueUnitPrice ?? planning.planningAmount ?? options.defaultPlanningAmount,
vatRate: planning.vatRate ?? 0.06
}
} finally {
formLoading.value = false
@@ -273,3 +385,19 @@ const resetForm = (projectId?: number, planningAmount?: number) => {
formRef.value?.resetFields()
}
</script>
<style scoped>
.readonly-result :deep(.el-input__wrapper.is-disabled) {
background-color: var(--el-fill-color-light);
}
.budget-result :deep(.el-input__wrapper.is-disabled) {
background-color: var(--el-color-primary-light-9);
box-shadow: 0 0 0 1px var(--el-color-primary-light-5) inset;
}
.budget-result :deep(.el-input__inner) {
color: var(--el-color-primary);
font-weight: 700;
}
</style>

View File

@@ -5,250 +5,264 @@
v-loading="formLoading"
:model="formData"
:rules="formRules"
label-width="120px"
label-width="130px"
>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="工程名称" prop="projectName">
<el-input v-model="formData.projectName" maxlength="200" placeholder="请输入工程名称" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="是否签订合同" prop="contractSignedFlag">
<el-switch
v-model="formData.contractSignedFlag"
active-text="已签订"
inactive-text="未签订"
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="合同金额(元)" prop="contractAmount">
<el-input-number
v-model="formData.contractAmount"
:min="0"
:precision="2"
:step="1000"
class="!w-1/1"
controls-position="right"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="工程总面积(㎡)" prop="totalConstructionArea">
<el-input-number
v-model="formData.totalConstructionArea"
:min="0"
:precision="2"
:step="100"
class="!w-1/1"
controls-position="right"
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="8">
<el-form-item label="建设单位" prop="constructionUnitName">
<el-input
v-model="formData.constructionUnitName"
maxlength="200"
placeholder="请输入建设单位"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="工程类型" prop="projectType">
<el-select v-model="formData.projectType" class="!w-1/1" clearable placeholder="请选择">
<el-option
v-for="item in PROJECT_TYPE_OPTIONS"
:key="item.value"
:label="item.label"
:value="item.value"
<div class="form-section">
<div class="form-section-title">项目基础信息</div>
<el-row :gutter="16">
<el-col :span="24">
<el-form-item label="项目名称" prop="projectName">
<el-input v-model="formData.projectName" maxlength="200" placeholder="请输入项目名称" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="工程总面积(㎡)" prop="totalConstructionArea">
<el-input-number
v-model="formData.totalConstructionArea"
:min="0"
:precision="2"
:step="100"
class="!w-1/1"
controls-position="right"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="工程类别" prop="projectCategory">
<el-select
v-model="formData.projectCategory"
class="!w-1/1"
clearable
placeholder="请选择"
>
<el-option
v-for="item in PROJECT_CATEGORY_OPTIONS"
:key="item.value"
:label="item.label"
:value="item.value"
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="建设单位" prop="constructionUnitName">
<el-input
v-model="formData.constructionUnitName"
maxlength="200"
placeholder="请输入建设单位"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="联系人" prop="contactName">
<el-input v-model="formData.contactName" maxlength="64" placeholder="请输入联系人" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="联系电话" prop="contactPhone">
<el-input v-model="formData.contactPhone" maxlength="32" placeholder="请输入联系电话" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="合同签订日期" prop="contractSigningDate">
<el-date-picker
v-model="formData.contractSigningDate"
class="!w-1/1"
placeholder="请选择日期"
type="date"
value-format="YYYY-MM-DD"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="项目开始年度" prop="projectStartYear">
<el-date-picker
v-model="projectStartYearValue"
class="!w-1/1"
placeholder="请选择年度"
type="year"
value-format="YYYY"
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="项目状态" prop="projectStatus">
<el-select
v-model="formData.projectStatus"
class="!w-1/1"
clearable
placeholder="请选择项目状态"
>
<el-option
v-for="item in PROJECT_STATUS_OPTIONS"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="statusReasonLabel" :prop="statusReasonProp">
<el-input
v-if="formData.projectStatus === '暂停'"
v-model="formData.pauseReason"
maxlength="255"
placeholder="请输入暂停原因"
/>
<el-input
v-else-if="formData.projectStatus === '中止'"
v-model="formData.terminateReason"
maxlength="255"
placeholder="请输入中止原因"
/>
<el-input v-else disabled placeholder="进行中或完成状态无需填写原因" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="项目经理">
<div class="person-group">
<div
v-for="(item, index) in projectManagerPersons"
:key="`manager-${index}`"
class="person-row"
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="工程类型" prop="projectType">
<el-select v-model="formData.projectType" class="!w-1/1" clearable placeholder="请选择">
<el-option
v-for="item in PROJECT_TYPE_OPTIONS"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="工程类别" prop="projectCategory">
<el-select
v-model="formData.projectCategory"
class="!w-1/1"
clearable
placeholder="请选择"
>
<el-select
:model-value="item.employeeId"
class="!w-1/1"
clearable
filterable
remote
reserve-keyword
placeholder="请输入项目经理姓名搜索"
:remote-method="searchEmployees"
:loading="employeeLoading"
@change="(value) => handleEmployeeChange(item, value)"
<el-option
v-for="item in PROJECT_CATEGORY_OPTIONS"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
</div>
<div class="form-section">
<div class="form-section-title">合同与财务信息</div>
<el-row :gutter="16">
<el-col :span="24">
<el-form-item label="合同状态" prop="contractSignedFlag" required>
<el-radio-group v-model="formData.contractSignedFlag">
<el-radio :value="true">已签订</el-radio>
<el-radio :value="false">未签订</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="合同产值(元)" prop="contractAmount">
<el-input-number
v-model="formData.contractAmount"
:min="0"
:precision="2"
:step="1000"
class="!w-1/1"
controls-position="right"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="签订日期" prop="contractSigningDate">
<el-date-picker
v-model="formData.contractSigningDate"
class="!w-1/1"
placeholder="请选择日期"
type="date"
value-format="YYYY-MM-DD"
/>
</el-form-item>
</el-col>
</el-row>
</div>
<div class="form-section">
<div class="form-section-title">状态与进度</div>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="项目状态" prop="projectStatus">
<el-select
v-model="formData.projectStatus"
class="!w-1/1"
clearable
placeholder="请选择项目状态"
>
<el-option
v-for="item in PROJECT_STATUS_OPTIONS"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="开始年度" prop="projectStartYear">
<el-date-picker
v-model="projectStartYearValue"
class="!w-1/1"
placeholder="请选择年度"
type="year"
value-format="YYYY"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="statusReasonLabel" :prop="statusReasonProp">
<el-input
v-if="formData.projectStatus === '暂停'"
v-model="formData.pauseReason"
maxlength="255"
placeholder="请输入暂停原因"
/>
<el-input
v-else-if="formData.projectStatus === '中止'"
v-model="formData.terminateReason"
maxlength="255"
placeholder="请输入中止原因"
/>
<el-input v-else disabled placeholder="进行中或完成状态无需填写原因" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="排序" prop="sortNo">
<el-input-number
v-model="formData.sortNo"
:min="0"
:precision="0"
:step="1"
class="!w-1/1"
controls-position="right"
/>
</el-form-item>
</el-col>
</el-row>
</div>
<div class="form-section">
<div class="form-section-title">人员与建设单位联系信息</div>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="建设单位联系人" prop="contactName">
<el-input v-model="formData.contactName" maxlength="64" placeholder="请输入建设单位联系人" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="建设单位联系电话" prop="contactPhone">
<el-input v-model="formData.contactPhone" maxlength="32" placeholder="请输入建设单位联系电话" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="项目经理">
<div class="person-group">
<div
v-for="(item, index) in projectManagerPersons"
:key="`manager-${index}`"
class="person-row"
>
<el-option
v-for="employee in employeeOptions"
:key="employee.id"
:label="employee.officeName ? `${employee.employeeName} / ${employee.officeName}` : employee.employeeName"
:value="employee.id"
/>
</el-select>
<el-button text type="danger" @click="removeRolePerson(ROLE_PROJECT_MANAGER, index)">
删除
<el-select
:model-value="item.employeeId"
class="!w-1/1"
clearable
filterable
remote
reserve-keyword
placeholder="请输入项目经理姓名搜索"
:remote-method="searchEmployees"
:loading="employeeLoading"
@change="(value) => handleEmployeeChange(item, value)"
>
<el-option
v-for="employee in employeeOptions"
:key="employee.id"
:label="employee.officeName ? `${employee.employeeName} / ${employee.officeName}` : employee.employeeName"
:value="employee.id"
/>
</el-select>
<el-button text type="danger" @click="removeRolePerson(ROLE_PROJECT_MANAGER, index)">
删除
</el-button>
</div>
<el-button text type="primary" @click="addRolePerson(ROLE_PROJECT_MANAGER)">
<Icon class="mr-5px" icon="ep:plus" />
添加项目经理
</el-button>
</div>
<el-button text type="primary" @click="addRolePerson(ROLE_PROJECT_MANAGER)">
<Icon class="mr-5px" icon="ep:plus" />
添加项目经理
</el-button>
</div>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="项目负责人">
<div class="person-group">
<div
v-for="(item, index) in engineeringPrincipalPersons"
:key="`principal-${index}`"
class="person-row"
>
<el-select
:model-value="item.employeeId"
class="!w-1/1"
clearable
filterable
remote
reserve-keyword
placeholder="请输入项目负责人姓名搜索"
:remote-method="searchEmployees"
:loading="employeeLoading"
@change="(value) => handleEmployeeChange(item, value)"
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="工程负责人">
<div class="person-group">
<div
v-for="(item, index) in engineeringPrincipalPersons"
:key="`principal-${index}`"
class="person-row"
>
<el-option
v-for="employee in employeeOptions"
:key="employee.id"
:label="employee.officeName ? `${employee.employeeName} / ${employee.officeName}` : employee.employeeName"
:value="employee.id"
/>
</el-select>
<el-button
text
type="danger"
@click="removeRolePerson(ROLE_ENGINEERING_PRINCIPAL, index)"
>
删除
<el-select
:model-value="item.employeeId"
class="!w-1/1"
clearable
filterable
remote
reserve-keyword
placeholder="请输入工程负责人姓名搜索"
:remote-method="searchEmployees"
:loading="employeeLoading"
@change="(value) => handleEmployeeChange(item, value)"
>
<el-option
v-for="employee in employeeOptions"
:key="employee.id"
:label="employee.officeName ? `${employee.employeeName} / ${employee.officeName}` : employee.employeeName"
:value="employee.id"
/>
</el-select>
<el-button
text
type="danger"
@click="removeRolePerson(ROLE_ENGINEERING_PRINCIPAL, index)"
>
删除
</el-button>
</div>
<el-button text type="primary" @click="addRolePerson(ROLE_ENGINEERING_PRINCIPAL)">
<Icon class="mr-5px" icon="ep:plus" />
添加工程负责人
</el-button>
</div>
<el-button text type="primary" @click="addRolePerson(ROLE_ENGINEERING_PRINCIPAL)">
<Icon class="mr-5px" icon="ep:plus" />
添加项目负责人
</el-button>
</div>
</el-form-item>
</el-col>
</el-row>
</el-form-item>
</el-col>
</el-row>
</div>
</el-form>
<template #footer>
@@ -315,6 +329,7 @@ const createRolePerson = (
const createFormData = (): ProjectApi.ProjectVO => ({
projectName: '',
sortNo: 0,
contractSignedFlag: true,
contractAmount: undefined,
totalConstructionArea: undefined,
@@ -443,8 +458,8 @@ watch(
)
const formRules = reactive<FormRules>({
projectName: [{ required: true, message: '工程名称不能为空', trigger: 'blur' }],
contractAmount: [{ required: true, message: '合同金额不能为空', trigger: 'blur' }],
projectName: [{ required: true, message: '项目名称不能为空', trigger: 'blur' }],
contractAmount: [{ required: true, message: '合同产值不能为空', trigger: 'blur' }],
totalConstructionArea: [{ required: true, message: '工程总面积不能为空', trigger: 'blur' }],
projectStartYear: [{ required: true, message: '项目开始年度不能为空', trigger: 'change' }],
projectStatus: [{ required: true, message: '项目状态不能为空', trigger: 'change' }],
@@ -497,6 +512,7 @@ const emit = defineEmits(['success'])
const buildSavePayload = (): ProjectApi.ProjectSaveVO => ({
id: formData.value.id,
projectName: formData.value.projectName,
sortNo: formData.value.sortNo ?? 0,
contractSignedFlag: formData.value.contractSignedFlag,
contractAmount: formData.value.contractAmount,
totalConstructionArea: formData.value.totalConstructionArea,
@@ -556,6 +572,22 @@ const resetForm = () => {
</script>
<style lang="scss" scoped>
.form-section {
margin-bottom: 10px;
}
.form-section:last-child {
margin-bottom: 0;
}
.form-section-title {
margin-bottom: 12px;
font-size: 15px;
font-weight: 600;
line-height: 22px;
color: var(--el-text-color-primary);
}
.person-group {
display: flex;
flex-direction: column;

View File

@@ -7,12 +7,12 @@
class="-mb-15px"
label-width="88px"
>
<el-form-item label="工程名称" prop="projectName">
<el-form-item label="项目名称" prop="projectName">
<el-input
v-model="queryParams.projectName"
class="!w-240px"
clearable
placeholder="请输入工程名称"
placeholder="请输入项目名称"
@keyup.enter="handleQuery"
/>
</el-form-item>
@@ -97,12 +97,18 @@
highlight-current-row
@current-change="handleCurrentProjectChange"
>
<el-table-column align="center" label="项目ID" prop="id" width="88" />
<el-table-column align="center" label="工程名称" min-width="220" prop="projectName" />
<el-table-column
:index="getProjectRowIndex"
align="center"
label="序号"
type="index"
width="80"
/>
<el-table-column align="center" label="项目名称" min-width="220" prop="projectName" />
<el-table-column align="center" label="项目经理" min-width="140" prop="projectManagerName" />
<el-table-column
align="center"
label="项目负责人"
label="工程负责人"
min-width="140"
prop="engineeringPrincipalName"
/>
@@ -124,6 +130,7 @@
{{ formatDate(scope.row.createTime as any) }}
</template>
</el-table-column>
<el-table-column align="center" label="排序" prop="sortNo" width="80" />
<el-table-column align="center" fixed="right" label="操作" width="150">
<template #default="scope">
<el-button
@@ -160,7 +167,7 @@
<div class="mt-4px text-13px text-[var(--el-text-color-secondary)]">
建设单位{{ currentProject.constructionUnitName || '-' }}项目经理{{
currentProject.projectManagerName || '-'
}}项目负责人{{ currentProject.engineeringPrincipalName || '-' }}
}}工程负责人{{ currentProject.engineeringPrincipalName || '-' }}
</div>
</div>
<el-button
@@ -177,7 +184,7 @@
<el-row :gutter="16">
<el-col :span="8">
<el-descriptions :column="1" border title="项目概况">
<el-descriptions-item label="工程名称">{{ currentProject.projectName }}</el-descriptions-item>
<el-descriptions-item label="项目名称">{{ currentProject.projectName }}</el-descriptions-item>
<el-descriptions-item label="工程类型">
{{ getProjectTypeText(currentProject.projectType) }}
</el-descriptions-item>
@@ -187,10 +194,10 @@
<el-descriptions-item label="合同签订日期">
{{ currentProject.contractSigningDate || '-' }}
</el-descriptions-item>
<el-descriptions-item label="联系人">
<el-descriptions-item label="建设单位联系人">
{{ currentProject.contactName || '-' }}
</el-descriptions-item>
<el-descriptions-item label="联系电话">
<el-descriptions-item label="建设单位联系电话">
{{ currentProject.contactPhone || '-' }}
</el-descriptions-item>
<el-descriptions-item label="项目状态">
@@ -211,7 +218,7 @@
>
{{ currentProject.terminateReason || '-' }}
</el-descriptions-item>
<el-descriptions-item label="合同金额(元)">
<el-descriptions-item label="合同产值(元)">
{{ formatAmountText(currentProject.contractAmount) }}
</el-descriptions-item>
<el-descriptions-item label="工程总面积(m²)">
@@ -222,9 +229,10 @@
<el-col :span="16">
<el-table v-loading="planningLoading" :data="planningList">
<el-table-column align="center" label="序号" type="index" width="70" />
<el-table-column
align="center"
label="规划内容"
label="项目任务包"
min-width="260"
prop="planningContent"
show-overflow-tooltip
@@ -234,7 +242,17 @@
{{ getOwnershipTypeText(scope.row.ownershipType) }}
</template>
</el-table-column>
<el-table-column align="center" label="规划金额(元)" width="130">
<el-table-column align="center" label="合同产值数量" width="130">
<template #default="scope">
{{ scope.row.contractValueQuantity ?? '-' }}
</template>
</el-table-column>
<el-table-column align="center" label="合同产值单价" width="130">
<template #default="scope">
{{ formatAmountText(scope.row.contractValueUnitPrice) }}
</template>
</el-table-column>
<el-table-column align="center" label="分项合同产值(元)" width="130">
<template #default="scope">
{{ formatAmountText(scope.row.planningAmount) }}
</template>
@@ -249,13 +267,29 @@
{{ formatAmountText(scope.row.managementFee) }}
</template>
</el-table-column>
<el-table-column align="center" label="增值税率" width="100">
<template #default="scope">
{{ formatPercentText(scope.row.vatRate) }}
</template>
</el-table-column>
<el-table-column align="center" label="增值税(元)" width="120">
<template #default="scope">
{{ formatAmountText(scope.row.vatAmount) }}
</template>
</el-table-column>
<el-table-column align="center" label="项目预算产值(元)" width="140">
<template #default="scope">
{{ formatAmountText(scope.row.projectBudgetOutputValue) }}
</template>
</el-table-column>
<el-table-column
align="center"
label="实施团队"
label="意向实施团队"
min-width="140"
prop="implementationTeam"
show-overflow-tooltip
/>
<el-table-column align="center" label="排序" prop="sortNo" width="80" />
<el-table-column align="center" fixed="right" label="操作" width="140">
<template #default="scope">
<el-button
@@ -373,6 +407,9 @@ const queryParams = reactive<ProjectApi.ProjectPageReqVO>({
createTime: []
})
const getProjectRowIndex = (index: number) =>
((queryParams.pageNo ?? 1) - 1) * (queryParams.pageSize ?? 10) + index + 1
const queryProjectStartYearValue = computed({
get: () => (queryParams.projectStartYear ? String(queryParams.projectStartYear) : undefined),
set: (value?: string) => {

View File

@@ -7,12 +7,12 @@
class="-mb-15px"
label-width="88px"
>
<el-form-item label="工程名称" prop="projectName">
<el-form-item label="项目名称" prop="projectName">
<el-input
v-model="queryParams.projectName"
class="!w-240px"
clearable
placeholder="请输入工程名称"
placeholder="请输入项目名称"
@keyup.enter="handleQuery"
/>
</el-form-item>
@@ -62,10 +62,16 @@
highlight-current-row
@current-change="handleCurrentProjectChange"
>
<el-table-column align="center" label="项目ID" prop="id" width="88" />
<el-table-column
:index="getProjectRowIndex"
align="center"
label="序号"
type="index"
width="80"
/>
<el-table-column
align="center"
label="工程名称"
label="项目名称"
min-width="220"
prop="projectName"
show-overflow-tooltip
@@ -80,12 +86,12 @@
<el-table-column align="center" label="项目经理" min-width="120" prop="projectManagerName" />
<el-table-column
align="center"
label="项目负责人"
label="工程负责人"
min-width="120"
prop="engineeringPrincipalName"
/>
<el-table-column align="center" label="开始年度" prop="projectStartYear" width="120" />
<el-table-column align="center" label="合同金额(元)" width="130">
<el-table-column align="center" label="合同产值(元)" width="130">
<template #default="scope">
{{ formatAmountText(scope.row.contractAmount) }}
</template>
@@ -95,6 +101,7 @@
{{ formatAreaText(scope.row.totalConstructionArea) }}
</template>
</el-table-column>
<el-table-column align="center" label="排序" prop="sortNo" width="80" />
</el-table>
<Pagination
v-model:limit="queryParams.pageSize"
@@ -124,16 +131,16 @@
</div>
<el-descriptions :column="1" border title="项目信息">
<el-descriptions-item label="工程名称">
<el-descriptions-item label="项目名称">
{{ currentProject.projectName || '-' }}
</el-descriptions-item>
<el-descriptions-item label="项目经理">
{{ currentProject.projectManagerName || '-' }}
</el-descriptions-item>
<el-descriptions-item label="项目负责人">
<el-descriptions-item label="工程负责人">
{{ currentProject.engineeringPrincipalName || '-' }}
</el-descriptions-item>
<el-descriptions-item label="合同金额(元)">
<el-descriptions-item label="合同产值(元)">
{{ formatAmountText(currentProject.contractAmount) }}
</el-descriptions-item>
<el-descriptions-item label="工程总面积(㎡)">
@@ -153,7 +160,7 @@
</el-col>
<el-col :span="8">
<div class="rounded-8px bg-[var(--el-fill-color-light)] px-12px py-12px">
<div class="text-12px text-[var(--el-text-color-secondary)]">规划金额合计</div>
<div class="text-12px text-[var(--el-text-color-secondary)]">分项合同产值合计</div>
<div class="mt-6px text-18px font-600">{{ formatAmountText(totalPlanningAmount) }}</div>
</div>
</el-col>
@@ -182,7 +189,8 @@
<el-button v-if="currentProject" size="small" @click="getPlanningList">刷新</el-button>
</div>
<el-table v-loading="planningLoading" :data="planningList" border>
<el-table-column align="center" label="规划内容" min-width="180" prop="planningContent" />
<el-table-column align="center" label="序号" type="index" width="70" />
<el-table-column align="center" label="项目任务包" min-width="180" prop="planningContent" />
<el-table-column align="center" label="归属类型" width="100">
<template #default="scope">
{{ getOwnershipTypeLabel(scope.row.ownershipType) }}
@@ -194,7 +202,7 @@
</template>
</el-table-column>
<el-table-column align="center" label="开始年度" width="100" prop="planningStartYear" />
<el-table-column align="center" label="规划金额(元)" width="130">
<el-table-column align="center" label="分项合同产值(元)" width="130">
<template #default="scope">
{{ formatAmountText(scope.row.planningAmount) }}
</template>
@@ -204,6 +212,7 @@
{{ formatAmountText(scope.row.assessmentOutputValue) }}
</template>
</el-table-column>
<el-table-column align="center" label="排序" prop="sortNo" width="80" />
</el-table>
</ContentWrap>
</el-col>
@@ -270,6 +279,9 @@ const queryParams = reactive<ProjectApi.ProjectPageReqVO>({
projectStartYear: undefined
})
const getProjectRowIndex = (index: number) =>
(queryParams.pageNo - 1) * queryParams.pageSize + index + 1
const queryProjectStartYearValue = computed({
get: () => (queryParams.projectStartYear ? String(queryParams.projectStartYear) : undefined),
set: (value?: string) => {

View File

@@ -7,12 +7,12 @@
class="-mb-15px"
label-width="88px"
>
<el-form-item label="工程名称" prop="projectName">
<el-form-item label="项目名称" prop="projectName">
<el-input
v-model="queryParams.projectName"
class="!w-240px"
clearable
placeholder="请输入工程名称"
placeholder="请输入项目名称"
@keyup.enter="handleQuery"
/>
</el-form-item>
@@ -47,14 +47,21 @@
highlight-current-row
@current-change="handleCurrentProjectChange"
>
<el-table-column align="center" label="项目ID" prop="id" width="88" />
<el-table-column align="center" label="工程名称" min-width="220" prop="projectName" />
<el-table-column align="center" label="项目负责人" min-width="180">
<el-table-column
:index="getProjectRowIndex"
align="center"
label="序号"
type="index"
width="80"
/>
<el-table-column align="center" label="项目名称" min-width="220" prop="projectName" />
<el-table-column align="center" label="工程负责人" min-width="180">
<template #default="scope">
{{ getProjectLeadText(scope.row.projectManagerName, scope.row.engineeringPrincipalName) }}
</template>
</el-table-column>
<el-table-column align="center" label="开始年度" prop="projectStartYear" width="120" />
<el-table-column align="center" label="排序" prop="sortNo" width="80" />
</el-table>
<Pagination
v-model:limit="queryParams.pageSize"
@@ -77,7 +84,8 @@
highlight-current-row
@current-change="handleCurrentPlanningChange"
>
<el-table-column align="center" label="规划内容" min-width="180" prop="planningContent" />
<el-table-column align="center" label="序号" type="index" width="70" />
<el-table-column align="center" label="项目任务包" min-width="180" prop="planningContent" />
<el-table-column align="center" label="归属类型" min-width="110">
<template #default="scope">
{{ getOwnershipTypeLabel(scope.row.ownershipType) }}
@@ -89,6 +97,7 @@
{{ formatAmountText(scope.row.assessmentOutputValue) }}
</template>
</el-table-column>
<el-table-column align="center" label="排序" prop="sortNo" width="80" />
</el-table>
</ContentWrap>
</el-col>
@@ -118,15 +127,15 @@
@click="handleExportProjectLeadQuarter"
>
<Icon class="mr-5px" icon="ep:download" />
导出项目负责人计取表
导出工程负责人计取表
</el-button>
</div>
</div>
<el-descriptions :column="2" border title="基础信息">
<el-descriptions-item label="项目名称">{{ formData.projectName || '-' }}</el-descriptions-item>
<el-descriptions-item label="规划内容">{{ formData.planningContent || '-' }}</el-descriptions-item>
<el-descriptions-item label="项目负责人">
<el-descriptions-item label="项目任务包">{{ formData.planningContent || '-' }}</el-descriptions-item>
<el-descriptions-item label="工程负责人">
{{ getProjectLeadText(formData.projectManagerName, formData.engineeringLeaderName) }}
</el-descriptions-item>
<el-descriptions-item label="考核产值(元)">
@@ -269,7 +278,7 @@ interface QuarterYearRow {
type ExportDialogType = 'projectQuarter' | 'projectLeadQuarter'
const annualCategoryOptions: { label: string; value: AnnualCategoryKey }[] = [
{ label: '项目经理/项目负责人', value: 'project_lead' },
{ label: '项目经理/工程负责人', value: 'project_lead' },
{ label: '建筑专业', value: 'arch' },
{ label: '装修专业', value: 'decor' },
{ label: '结构专业', value: 'struct' },
@@ -309,6 +318,9 @@ const queryParams = reactive<ProjectApi.ProjectPageReqVO>({
projectStartYear: undefined
})
const getProjectRowIndex = (index: number) =>
(queryParams.pageNo - 1) * queryParams.pageSize + index + 1
const queryProjectStartYearValue = computed({
get: () => (queryParams.projectStartYear ? String(queryParams.projectStartYear) : undefined),
set: (value?: string) => {
@@ -317,7 +329,7 @@ const queryProjectStartYearValue = computed({
})
const exportDialogTitle = computed(() =>
exportDialogType.value === 'projectQuarter' ? '导出专业间年度季度计取表' : '导出项目负责人计取表'
exportDialogType.value === 'projectQuarter' ? '导出专业间年度季度计取表' : '导出工程负责人计取表'
)
const currentExportLoading = computed(() =>
@@ -361,7 +373,7 @@ const buildProjectRows = (model?: OutputSplitApi.ProjectOutputSplitVO) => {
}
return [
{
label: '项目经理/项目负责人',
label: '项目经理/工程负责人',
percentText: formatRatioText(model.projectLeadRatio),
amount: model.projectLeadAmount
},
@@ -664,7 +676,7 @@ const submitProjectLeadQuarterExport = async () => {
})
download.excel(
data,
`${currentProject.value?.projectName || '项目'}_${exportYear.value}_项目负责人年度季度计取表.xlsx`
`${currentProject.value?.projectName || '项目'}_${exportYear.value}_工程负责人年度季度计取表.xlsx`
)
exportDialogVisible.value = false
} finally {

View File

@@ -7,12 +7,12 @@
class="-mb-15px"
label-width="88px"
>
<el-form-item label="工程名称" prop="projectName">
<el-form-item label="项目名称" prop="projectName">
<el-input
v-model="queryParams.projectName"
class="!w-240px"
clearable
placeholder="请输入工程名称"
placeholder="请输入项目名称"
@keyup.enter="handleQuery"
/>
</el-form-item>
@@ -47,16 +47,23 @@
highlight-current-row
@current-change="handleCurrentProjectChange"
>
<el-table-column align="center" label="项目ID" prop="id" width="88" />
<el-table-column align="center" label="工程名称" min-width="220" prop="projectName" />
<el-table-column
:index="getProjectRowIndex"
align="center"
label="序号"
type="index"
width="80"
/>
<el-table-column align="center" label="项目名称" min-width="220" prop="projectName" />
<el-table-column align="center" label="项目经理" min-width="120" prop="projectManagerName" />
<el-table-column
align="center"
label="项目负责人"
label="工程负责人"
min-width="120"
prop="engineeringPrincipalName"
/>
<el-table-column align="center" label="开始年度" prop="projectStartYear" width="120" />
<el-table-column align="center" label="排序" prop="sortNo" width="80" />
</el-table>
<Pagination
v-model:limit="queryParams.pageSize"
@@ -79,7 +86,8 @@
highlight-current-row
@current-change="handleCurrentPlanningChange"
>
<el-table-column align="center" label="规划内容" min-width="180" prop="planningContent" />
<el-table-column align="center" label="序号" type="index" width="70" />
<el-table-column align="center" label="项目任务包" min-width="180" prop="planningContent" />
<el-table-column align="center" label="归属类型" min-width="110">
<template #default="scope">
{{ getOwnershipTypeLabel(scope.row.ownershipType) }}
@@ -91,6 +99,7 @@
{{ formatAmountText(scope.row.assessmentOutputValue) }}
</template>
</el-table-column>
<el-table-column align="center" label="排序" prop="sortNo" width="80" />
</el-table>
</ContentWrap>
</el-col>
@@ -246,6 +255,9 @@ const queryParams = reactive<ProjectApi.ProjectPageReqVO>({
projectStartYear: undefined
})
const getProjectRowIndex = (index: number) =>
(queryParams.pageNo - 1) * queryParams.pageSize + index + 1
const queryProjectStartYearValue = computed({
get: () => (queryParams.projectStartYear ? String(queryParams.projectStartYear) : undefined),
set: (value?: string) => {

View File

@@ -7,12 +7,12 @@
class="-mb-15px"
label-width="88px"
>
<el-form-item label="工程名称" prop="projectName">
<el-form-item label="项目名称" prop="projectName">
<el-input
v-model="queryParams.projectName"
class="!w-240px"
clearable
placeholder="请输入工程名称"
placeholder="请输入项目名称"
@keyup.enter="handleQuery"
/>
</el-form-item>
@@ -47,16 +47,23 @@
highlight-current-row
@current-change="handleCurrentProjectChange"
>
<el-table-column align="center" label="项目ID" prop="id" width="88" />
<el-table-column align="center" label="工程名称" min-width="220" prop="projectName" />
<el-table-column
:index="getProjectRowIndex"
align="center"
label="序号"
type="index"
width="80"
/>
<el-table-column align="center" label="项目名称" min-width="220" prop="projectName" />
<el-table-column align="center" label="项目经理" min-width="120" prop="projectManagerName" />
<el-table-column
align="center"
label="项目负责人"
label="工程负责人"
min-width="120"
prop="engineeringPrincipalName"
/>
<el-table-column align="center" label="开始年度" prop="projectStartYear" width="120" />
<el-table-column align="center" label="排序" prop="sortNo" width="80" />
</el-table>
<Pagination
v-model:limit="queryParams.pageSize"
@@ -79,7 +86,8 @@
highlight-current-row
@current-change="handleCurrentPlanningChange"
>
<el-table-column align="center" label="规划内容" min-width="180" prop="planningContent" />
<el-table-column align="center" label="序号" type="index" width="70" />
<el-table-column align="center" label="项目任务包" min-width="180" prop="planningContent" />
<el-table-column align="center" label="归属类型" min-width="110">
<template #default="scope">
{{ getOwnershipTypeLabel(scope.row.ownershipType) }}
@@ -91,6 +99,7 @@
{{ formatAmountText(scope.row.assessmentOutputValue) }}
</template>
</el-table-column>
<el-table-column align="center" label="排序" prop="sortNo" width="80" />
</el-table>
</ContentWrap>
</el-col>
@@ -225,7 +234,7 @@
<div v-if="!scope.row.persons?.length" class="person-empty">
{{
isProjectLeadRow(scope.row)
? '暂无人员请先到页面1维护项目经理或项目负责人'
? '暂无人员请先到页面1维护项目经理或工程负责人'
: '暂无人员,请点击“添加人员”'
}}
</div>
@@ -364,6 +373,9 @@ const queryParams = reactive<ProjectApi.ProjectPageReqVO>({
projectStartYear: undefined
})
const getProjectRowIndex = (index: number) =>
(queryParams.pageNo - 1) * queryParams.pageSize + index + 1
const queryProjectStartYearValue = computed({
get: () => (queryParams.projectStartYear ? String(queryParams.projectStartYear) : undefined),
set: (value?: string) => {