添加考核产值预算表预览
This commit is contained in:
@@ -79,6 +79,59 @@ export interface ProjectBudgetExportReqVO {
|
||||
year?: number
|
||||
}
|
||||
|
||||
export interface ProjectBudgetPreviewRespVO {
|
||||
year?: number
|
||||
projectCode?: string
|
||||
projectName?: string
|
||||
remark?: string
|
||||
budgetRows?: ProjectBudgetPreviewBudgetRow[]
|
||||
quarterBudgetRows?: ProjectBudgetPreviewQuarterRow[]
|
||||
}
|
||||
|
||||
export interface ProjectBudgetPreviewBudgetRow {
|
||||
rowType?: string
|
||||
planningId?: number
|
||||
planningContent?: string
|
||||
displayDesignPart?: string
|
||||
displayBuildingType?: string
|
||||
internalGuidanceUnitPrice?: number
|
||||
designArea?: number
|
||||
buildingOrUnitCount?: number
|
||||
drawingSetFactor?: number
|
||||
scaleFactor?: number
|
||||
modificationFactor?: number
|
||||
complexityFactor?: number
|
||||
subtotalArea?: number
|
||||
currentDesignStageRatio?: number
|
||||
assessmentOutputValueWan?: number
|
||||
}
|
||||
|
||||
export interface ProjectBudgetPreviewQuarterRow {
|
||||
serialNo?: number
|
||||
totalRow?: boolean
|
||||
outputType?: string
|
||||
designContent?: string
|
||||
budgetYear?: number
|
||||
totalDesignArea?: number
|
||||
totalAssessmentArea?: number
|
||||
totalAssessmentOutputWan?: number
|
||||
designStageRatio?: number
|
||||
designStageOutputWan?: number
|
||||
historicalIssuedRatio?: number
|
||||
quarterOneRatio?: number
|
||||
quarterTwoRatio?: number
|
||||
quarterThreeRatio?: number
|
||||
quarterFourRatio?: number
|
||||
currentYearRatio?: number
|
||||
pendingRatio?: number
|
||||
quarterOneAmountWan?: number
|
||||
quarterTwoAmountWan?: number
|
||||
quarterThreeAmountWan?: number
|
||||
quarterFourAmountWan?: number
|
||||
yearTotalAmountWan?: number
|
||||
ratioRemark?: string
|
||||
}
|
||||
|
||||
export interface ProjectQuarterOutputExportReqVO {
|
||||
planningId: number
|
||||
year?: number
|
||||
@@ -158,6 +211,13 @@ export const exportProjectBudget = (params: ProjectBudgetExportReqVO) => {
|
||||
return request.download({ url: '/tjt/report/project-budget/export-excel', params })
|
||||
}
|
||||
|
||||
export const getProjectBudgetPreview = (params: ProjectBudgetExportReqVO) => {
|
||||
return request.get<ProjectBudgetPreviewRespVO>({
|
||||
url: '/tjt/report/project-budget/preview',
|
||||
params: { ...params, _t: Date.now() }
|
||||
})
|
||||
}
|
||||
|
||||
export const exportProjectQuarterOutput = (params: ProjectQuarterOutputExportReqVO) => {
|
||||
return request.download({
|
||||
url: '/tjt/report/project-quarter-output/export-excel',
|
||||
|
||||
@@ -161,7 +161,9 @@
|
||||
<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="mt-6px text-18px font-600">{{ formatAmountText(totalPlanningAmount) }}</div>
|
||||
<div class="mt-6px text-18px font-600">{{
|
||||
formatAmountText(totalPlanningAmount)
|
||||
}}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
@@ -189,7 +191,12 @@
|
||||
<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="项目任务包"
|
||||
min-width="180"
|
||||
prop="planningContent"
|
||||
/>
|
||||
<el-table-column align="center" label="归属类型" width="100">
|
||||
<template #default="scope">
|
||||
{{ getOwnershipTypeLabel(scope.row.ownershipType) }}
|
||||
@@ -217,6 +224,253 @@
|
||||
</template>
|
||||
</SplitPane>
|
||||
|
||||
<ContentWrap v-if="currentProject" v-loading="budgetPreviewLoading">
|
||||
<div class="mb-12px flex flex-wrap items-center justify-between gap-12px">
|
||||
<div>
|
||||
<div class="text-16px font-600">考核产值预算表预览</div>
|
||||
<div class="mt-4px text-12px text-[var(--el-text-color-secondary)]">
|
||||
{{ budgetPreview?.projectName || currentProject.projectName }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-8px">
|
||||
<span class="text-13px text-[var(--el-text-color-secondary)]">年度</span>
|
||||
<el-date-picker
|
||||
v-model="previewYearValue"
|
||||
class="!w-150px"
|
||||
clearable
|
||||
placeholder="请选择年度"
|
||||
type="year"
|
||||
value-format="YYYY"
|
||||
@change="getProjectBudgetPreview"
|
||||
/>
|
||||
<el-button :loading="budgetPreviewLoading" @click="getProjectBudgetPreview">刷新</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<SplitPane>
|
||||
<template #left>
|
||||
<div class="budget-preview-pane">
|
||||
<div class="mb-12px text-14px font-600">建筑(装饰)工程项目考核产值预算表</div>
|
||||
<el-table
|
||||
:data="budgetPreview?.budgetRows || []"
|
||||
:empty-text="budgetPreviewEmptyText"
|
||||
:row-class-name="getBudgetPreviewRowClassName"
|
||||
border
|
||||
class="budget-preview-table"
|
||||
max-height="520"
|
||||
>
|
||||
<el-table-column
|
||||
align="center"
|
||||
fixed="left"
|
||||
label="规划内容"
|
||||
min-width="160"
|
||||
prop="planningContent"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
align="center"
|
||||
fixed="left"
|
||||
label="设计部位"
|
||||
min-width="120"
|
||||
prop="displayDesignPart"
|
||||
/>
|
||||
<el-table-column
|
||||
align="center"
|
||||
label="设计内容/设计类型"
|
||||
min-width="160"
|
||||
prop="displayBuildingType"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column align="center" label="内部指导单价(元/㎡)" min-width="140">
|
||||
<template #default="scope">{{
|
||||
formatNullableAmount(scope.row.internalGuidanceUnitPrice)
|
||||
}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="设计面积(㎡)" min-width="120">
|
||||
<template #default="scope">{{ formatNullableAmount(scope.row.designArea) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
align="center"
|
||||
label="栋数/户型数"
|
||||
min-width="110"
|
||||
prop="buildingOrUnitCount"
|
||||
/>
|
||||
<el-table-column align="center" label="套图系数" min-width="100">
|
||||
<template #default="scope">{{ formatFactor(scope.row.drawingSetFactor) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="规模系数" min-width="100">
|
||||
<template #default="scope">{{ formatFactor(scope.row.scaleFactor) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="修改系数" min-width="100">
|
||||
<template #default="scope">{{ formatFactor(scope.row.modificationFactor) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="复杂系数/复杂等级" min-width="140">
|
||||
<template #default="scope">{{ formatFactor(scope.row.complexityFactor) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="小计(㎡)" min-width="120">
|
||||
<template #default="scope">{{
|
||||
formatNullableAmount(scope.row.subtotalArea)
|
||||
}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="设计阶段占比" min-width="120">
|
||||
<template #default="scope">{{
|
||||
formatNullablePercent(scope.row.currentDesignStageRatio)
|
||||
}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="考核产值小计(万元)" min-width="150">
|
||||
<template #default="scope">{{
|
||||
formatNullableAmount(scope.row.assessmentOutputValueWan)
|
||||
}}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div
|
||||
v-if="budgetPreview?.remark"
|
||||
class="mt-10px text-12px text-[var(--el-text-color-secondary)]"
|
||||
>
|
||||
备注:{{ budgetPreview.remark }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #right>
|
||||
<div class="budget-preview-pane">
|
||||
<div class="mb-12px text-14px font-600">项目考核产值年度季度预算计取表</div>
|
||||
<el-table
|
||||
:data="budgetPreview?.quarterBudgetRows || []"
|
||||
:empty-text="budgetPreviewEmptyText"
|
||||
:row-class-name="getQuarterPreviewRowClassName"
|
||||
border
|
||||
class="budget-preview-table"
|
||||
max-height="520"
|
||||
>
|
||||
<el-table-column align="center" fixed="left" label="序号" width="70">
|
||||
<template #default="scope">{{
|
||||
scope.row.totalRow ? '' : scope.row.serialNo
|
||||
}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
align="center"
|
||||
fixed="left"
|
||||
label="项目名称"
|
||||
min-width="180"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template #default="scope">{{
|
||||
scope.row.totalRow ? '项目合计' : budgetPreview?.projectName
|
||||
}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="产值类型" min-width="120" prop="outputType" />
|
||||
<el-table-column
|
||||
align="center"
|
||||
label="设计内容"
|
||||
min-width="180"
|
||||
prop="designContent"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column align="center" label="总建筑设计面积(㎡)" min-width="150">
|
||||
<template #default="scope">{{
|
||||
formatNullableAmount(scope.row.totalDesignArea)
|
||||
}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="总考核产值面积(㎡)" min-width="150">
|
||||
<template #default="scope">{{
|
||||
formatNullableAmount(scope.row.totalAssessmentArea)
|
||||
}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="总考核产值(万元)" min-width="150">
|
||||
<template #default="scope">{{
|
||||
formatNullableAmount(scope.row.totalAssessmentOutputWan)
|
||||
}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="设计阶段考核产值分配">
|
||||
<el-table-column align="center" label="阶段占比" min-width="110">
|
||||
<template #default="scope">{{
|
||||
scope.row.totalRow ? '' : formatNullablePercent(scope.row.designStageRatio)
|
||||
}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="考核产值" min-width="120">
|
||||
<template #default="scope">{{
|
||||
formatNullableAmount(scope.row.designStageOutputWan)
|
||||
}}</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="发放情况">
|
||||
<el-table-column align="center" label="往年已发放比例" min-width="130">
|
||||
<template #default="scope">{{
|
||||
scope.row.totalRow ? '' : formatNullablePercent(scope.row.historicalIssuedRatio)
|
||||
}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="一季度" min-width="100">
|
||||
<template #default="scope">{{
|
||||
scope.row.totalRow ? '' : formatNullablePercent(scope.row.quarterOneRatio)
|
||||
}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="二季度" min-width="100">
|
||||
<template #default="scope">{{
|
||||
scope.row.totalRow ? '' : formatNullablePercent(scope.row.quarterTwoRatio)
|
||||
}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="三季度" min-width="100">
|
||||
<template #default="scope">{{
|
||||
scope.row.totalRow ? '' : formatNullablePercent(scope.row.quarterThreeRatio)
|
||||
}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="四季度" min-width="100">
|
||||
<template #default="scope">{{
|
||||
scope.row.totalRow ? '' : formatNullablePercent(scope.row.quarterFourRatio)
|
||||
}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="本年度小计" min-width="120">
|
||||
<template #default="scope">{{
|
||||
scope.row.totalRow ? '' : formatNullablePercent(scope.row.currentYearRatio)
|
||||
}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="未发放比例" min-width="120">
|
||||
<template #default="scope">{{
|
||||
scope.row.totalRow ? '' : formatNullablePercent(scope.row.pendingRatio)
|
||||
}}</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="本年度项目考核产值(万元)">
|
||||
<el-table-column align="center" label="一季度" min-width="110">
|
||||
<template #default="scope">{{
|
||||
formatNullableAmount(scope.row.quarterOneAmountWan)
|
||||
}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="二季度" min-width="110">
|
||||
<template #default="scope">{{
|
||||
formatNullableAmount(scope.row.quarterTwoAmountWan)
|
||||
}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="三季度" min-width="110">
|
||||
<template #default="scope">{{
|
||||
formatNullableAmount(scope.row.quarterThreeAmountWan)
|
||||
}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="四季度" min-width="110">
|
||||
<template #default="scope">{{
|
||||
formatNullableAmount(scope.row.quarterFourAmountWan)
|
||||
}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="本年度小计" min-width="120">
|
||||
<template #default="scope">{{
|
||||
formatNullableAmount(scope.row.yearTotalAmountWan)
|
||||
}}</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
align="center"
|
||||
label="备注"
|
||||
min-width="180"
|
||||
prop="ratioRemark"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
</el-table>
|
||||
</div>
|
||||
</template>
|
||||
</SplitPane>
|
||||
</ContentWrap>
|
||||
|
||||
<Dialog v-model="exportDialogVisible" title="导出项目考核产值预算表" width="420">
|
||||
<el-form label-width="88px">
|
||||
<el-form-item label="年度">
|
||||
@@ -261,12 +515,15 @@ const currentYear = new Date().getFullYear()
|
||||
|
||||
const loading = ref(false)
|
||||
const planningLoading = ref(false)
|
||||
const budgetPreviewLoading = ref(false)
|
||||
const exportLoading = ref(false)
|
||||
const exportDialogVisible = ref(false)
|
||||
const previewYear = ref<number>()
|
||||
const exportYear = ref<number>()
|
||||
const total = ref(0)
|
||||
const projectList = ref<ProjectApi.ProjectVO[]>([])
|
||||
const planningList = ref<PlanningApi.ProjectPlanningVO[]>([])
|
||||
const budgetPreview = ref<ReportApi.ProjectBudgetPreviewRespVO>()
|
||||
const currentProject = ref<ProjectApi.ProjectVO>()
|
||||
const queryFormRef = ref()
|
||||
const projectTableRef = ref()
|
||||
@@ -280,7 +537,7 @@ const queryParams = reactive<ProjectApi.ProjectPageReqVO>({
|
||||
})
|
||||
|
||||
const getProjectRowIndex = (index: number) =>
|
||||
(queryParams.pageNo - 1) * queryParams.pageSize + index + 1
|
||||
((queryParams.pageNo || 1) - 1) * (queryParams.pageSize || 10) + index + 1
|
||||
|
||||
const queryProjectStartYearValue = computed({
|
||||
get: () => (queryParams.projectStartYear ? String(queryParams.projectStartYear) : undefined),
|
||||
@@ -296,6 +553,13 @@ const exportYearValue = computed({
|
||||
}
|
||||
})
|
||||
|
||||
const previewYearValue = computed({
|
||||
get: () => (previewYear.value ? String(previewYear.value) : undefined),
|
||||
set: (value?: string) => {
|
||||
previewYear.value = value ? Number(value) : undefined
|
||||
}
|
||||
})
|
||||
|
||||
const totalPlanningAmount = computed(() =>
|
||||
planningList.value.reduce((sum, item) => sum + Number(item.planningAmount || 0), 0)
|
||||
)
|
||||
@@ -303,6 +567,48 @@ const totalAssessmentOutputValue = computed(() =>
|
||||
planningList.value.reduce((sum, item) => sum + Number(item.assessmentOutputValue || 0), 0)
|
||||
)
|
||||
|
||||
const budgetPreviewEmptyText = computed(() =>
|
||||
previewYear.value ? '暂无预算表数据' : '请先选择年度'
|
||||
)
|
||||
|
||||
const formatNullableAmount = (value?: number | string | null) => {
|
||||
if (value === undefined || value === null || value === '') {
|
||||
return ''
|
||||
}
|
||||
return formatAmountText(value)
|
||||
}
|
||||
|
||||
const formatFactor = (value?: number | string | null) => {
|
||||
if (value === undefined || value === null || value === '') {
|
||||
return ''
|
||||
}
|
||||
const numericValue = Number(value)
|
||||
if (Number.isNaN(numericValue)) {
|
||||
return ''
|
||||
}
|
||||
return numericValue.toFixed(2)
|
||||
}
|
||||
|
||||
const formatNullablePercent = (value?: number | string | null) => {
|
||||
if (value === undefined || value === null || value === '') {
|
||||
return ''
|
||||
}
|
||||
const numericValue = Number(value)
|
||||
if (Number.isNaN(numericValue)) {
|
||||
return ''
|
||||
}
|
||||
return `${(numericValue * 100).toFixed(2)}%`
|
||||
}
|
||||
|
||||
const getBudgetPreviewRowClassName = ({ row }: { row: ReportApi.ProjectBudgetPreviewBudgetRow }) =>
|
||||
row?.rowType === 'PART_SUBTOTAL' || row?.rowType === 'PLANNING_TOTAL' ? 'budget-total-row' : ''
|
||||
|
||||
const getQuarterPreviewRowClassName = ({
|
||||
row
|
||||
}: {
|
||||
row: ReportApi.ProjectBudgetPreviewQuarterRow
|
||||
}) => (row?.totalRow ? 'budget-total-row' : '')
|
||||
|
||||
const getProjectList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
@@ -312,6 +618,7 @@ const getProjectList = async () => {
|
||||
if (!projectList.value.length) {
|
||||
currentProject.value = undefined
|
||||
planningList.value = []
|
||||
budgetPreview.value = undefined
|
||||
return
|
||||
}
|
||||
const targetProjectId = currentProject.value?.id || projectList.value[0].id
|
||||
@@ -331,12 +638,30 @@ const getPlanningList = async () => {
|
||||
}
|
||||
planningLoading.value = true
|
||||
try {
|
||||
planningList.value = await PlanningApi.getProjectPlanningListByProjectId(currentProject.value.id)
|
||||
planningList.value = await PlanningApi.getProjectPlanningListByProjectId(
|
||||
currentProject.value.id
|
||||
)
|
||||
} finally {
|
||||
planningLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const getProjectBudgetPreview = async () => {
|
||||
if (!currentProject.value?.id || !previewYear.value) {
|
||||
budgetPreview.value = undefined
|
||||
return
|
||||
}
|
||||
budgetPreviewLoading.value = true
|
||||
try {
|
||||
budgetPreview.value = await ReportApi.getProjectBudgetPreview({
|
||||
projectId: currentProject.value.id,
|
||||
year: previewYear.value
|
||||
})
|
||||
} finally {
|
||||
budgetPreviewLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
getProjectList()
|
||||
@@ -349,7 +674,8 @@ const resetQuery = () => {
|
||||
|
||||
const handleCurrentProjectChange = async (row?: ProjectApi.ProjectVO) => {
|
||||
currentProject.value = row || undefined
|
||||
await getPlanningList()
|
||||
previewYear.value = row?.projectStartYear || currentYear
|
||||
await Promise.all([getPlanningList(), getProjectBudgetPreview()])
|
||||
}
|
||||
|
||||
const handleExportProjectBudget = async () => {
|
||||
@@ -377,7 +703,10 @@ const submitProjectBudgetExport = async () => {
|
||||
projectId: currentProject.value.id,
|
||||
year: exportYear.value
|
||||
})
|
||||
download.excel(data, `${currentProject.value.projectName}_${exportYear.value}_项目考核产值预算表.xlsx`)
|
||||
download.excel(
|
||||
data,
|
||||
`${currentProject.value.projectName}_${exportYear.value}_项目考核产值预算表.xlsx`
|
||||
)
|
||||
exportDialogVisible.value = false
|
||||
} finally {
|
||||
exportLoading.value = false
|
||||
@@ -399,3 +728,14 @@ onActivated(() => {
|
||||
getProjectList()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.budget-preview-pane {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.budget-preview-table :deep(.budget-total-row) {
|
||||
background: var(--el-fill-color-light);
|
||||
font-weight: 700;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user