明树Git Lab
Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
J
jt_front
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
jt_front
Commits
bc1354b0
Commit
bc1354b0
authored
Mar 25, 2026
by
zhanghan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
1
parent
5c1a28a5
Pipeline
#108823
passed with stage
in 21 seconds
Changes
9
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
8895 additions
and
2811 deletions
+8895
-2811
settings.local.json
.claude/settings.local.json
+2
-1
FinancialTable.vue
src/components/FinancialTable.vue
+173
-89
InvestmentRecoveryTable.vue
src/components/InvestmentRecoveryTable.vue
+805
-0
manage.less
src/styles/manage.less
+2
-0
investmentCecoveryAdd.vue
src/views/castbehind/investmentCecoveryAdd.vue
+458
-203
costTab1.vue
src/views/elseManage/costTab1.vue
+0
-9
addControl.vue
src/views/investingManage/addControl.vue
+235
-11
decision.vue
src/views/investingManage/decision.vue
+53
-85
decisionAdd.vue
src/views/investingManage/decisionAdd.vue
+7167
-2413
No files found.
.claude/settings.local.json
View file @
bc1354b0
{
"permissions"
:
{
"allow"
:
[
"mcp__zai-mcp-server__analyze_image"
"mcp__zai-mcp-server__analyze_image"
,
"mcp__zai-mcp-server__extract_text_from_screenshot"
]
}
}
src/components/FinancialTable.vue
View file @
bc1354b0
...
...
@@ -69,82 +69,118 @@
</el-table-column>
<!-- 多级时间列表头渲染逻辑 -->
<
template
v-if=
"hasTimeHeaderGroup"
>
<
template
v-for=
"group in timeColumnGroups"
:key=
"`time-group-${group.key}`"
>
<!-- 有一级分组标题 -->
<el-table-column
v-for=
"group in timeColumnGroups"
:key=
"`time-group-$
{group.key}`"
v-if=
"!group.isSingle && group.label"
:label=
"group.label"
align=
"right"
>
<el-table-column
v-for=
"timeItem in group.children"
:key=
"`time-col-$
{timeItem.prop}`"
:label="timeItem.label"
min-width="140"
align="center"
>
<template
#
default=
"
{ row }">
<!-- 🌟 核心修改:优先使用列级isTextRow配置,其次行级 -->
<el-input
v-if=
"timeItem.isTextRow || row.isTextRow"
v-model=
"row[timeItem.prop]"
type=
"textarea"
:rows=
"2"
:disabled=
"isPreview"
placeholder=
"请输入说明"
style=
"width: 100%"
@
input=
"() => handleTextInput(row)"
/>
<!-- 数字行:金额输入框 -->
<el-input
v-else
v-model=
"row[timeItem.prop]"
:precision=
"2"
controls-position=
"right"
:disabled=
"isPreview"
placeholder=
"请输入金额"
style=
"width: 100%"
@
change=
"() => handleFinancialChange(row)"
/>
</
template
>
</el-table-column>
<!-- 遍历一级分组的子项 -->
<template
v-for=
"child in group.children"
:key=
"`child-$
{child.key || child.prop}`">
<!-- 如果是二级分组 -->
<el-table-column
v-if=
"child.isSubGroup"
:label=
"child.label"
align=
"center"
>
<el-table-column
v-for=
"timeItem in child.children"
:key=
"`time-col-$
{timeItem.prop}`"
:label="timeItem.label"
min-width="140"
align="center"
>
<template
#
default=
"
{ row }">
<el-input
v-if=
"timeItem.isTextRow || row.isTextRow"
v-model=
"row[timeItem.prop]"
type=
"textarea"
:rows=
"2"
:disabled=
"isPreview"
placeholder=
"请输入说明"
style=
"width: 100%"
@
input=
"() => handleTextInput(row)"
/>
<el-input
v-else
v-model=
"row[timeItem.prop]"
:precision=
"2"
controls-position=
"right"
:disabled=
"isPreview"
placeholder=
"请输入金额"
style=
"width: 100%"
@
change=
"() => handleFinancialChange(row)"
/>
</
template
>
</el-table-column>
</el-table-column>
<!-- 如果是直接列(没有二级分组) -->
<el-table-column
v-else
:key=
"`time-col-${child.prop}`"
:label=
"child.label"
min-width=
"140"
align=
"center"
>
<
template
#
default=
"{ row }"
>
<el-input
v-if=
"child.isTextRow || row.isTextRow"
v-model=
"row[child.prop]"
type=
"textarea"
:rows=
"2"
:disabled=
"isPreview"
placeholder=
"请输入说明"
style=
"width: 100%"
@
input=
"() => handleTextInput(row)"
/>
<el-input
v-else
v-model=
"row[child.prop]"
:precision=
"2"
controls-position=
"right"
:disabled=
"isPreview"
placeholder=
"请输入金额"
style=
"width: 100%"
@
change=
"() => handleFinancialChange(row)"
/>
</
template
>
</el-table-column>
</template>
</el-table-column>
<!-- 单列(没有分组标题,label 为空) -->
<el-table-column
v-else
v-for=
"timeItem in group.children"
:key=
"`time-col-${timeItem.prop}`"
:label=
"timeItem.label"
min-width=
"140"
align=
"center"
>
<
template
#
default=
"{ row }"
>
<el-input
v-if=
"timeItem.isTextRow || row.isTextRow"
v-model=
"row[timeItem.prop]"
type=
"textarea"
:rows=
"2"
:disabled=
"isPreview"
placeholder=
"请输入说明"
style=
"width: 100%"
@
input=
"() => handleTextInput(row)"
/>
<el-input
v-else
v-model=
"row[timeItem.prop]"
:precision=
"2"
controls-position=
"right"
:disabled=
"isPreview"
placeholder=
"请输入金额"
style=
"width: 100%"
@
change=
"() => handleFinancialChange(row)"
/>
</
template
>
</el-table-column>
</template>
<!-- 无时间列分组 → 单级表头逻辑 -->
<el-table-column
v-else
v-for=
"time in validDynamicTimeConfig"
:key=
"`time-col-${time.prop || time}`"
:label=
"time.label || time"
min-width=
"140"
align=
"center"
>
<
template
#
default=
"{ row }"
>
<!-- 🌟 核心修改:优先使用列级isTextRow配置,其次行级 -->
<el-input
v-if=
"time.isTextRow || row.isTextRow"
v-model=
"row[time.prop || time]"
type=
"textarea"
:rows=
"2"
:disabled=
"isPreview"
placeholder=
"请输入说明"
style=
"width: 100%"
@
input=
"() => handleTextInput(row)"
/>
<!-- 数字行:金额输入框 -->
<el-input
v-else
v-model=
"row[time.prop || time]"
:precision=
"2"
controls-position=
"right"
:disabled=
"isPreview"
placeholder=
"请输入金额"
style=
"width: 100%"
@
change=
"() => handleFinancialChange(row)"
/>
</
template
>
</el-table-column>
</el-table>
<div
v-else
style=
"text-align: center; padding: 20px; color: #909399"
>
请传入合法的表格配置(包含indicatorList、dynamicTimeList)
...
...
@@ -213,6 +249,7 @@ const validDynamicTimeConfig = computed(() => {
label
:
item
.
trim
(),
prop
:
item
.
trim
(),
headerGroup
:
""
,
subGroup
:
""
,
// 支持三级分组
isTextRow
:
false
,
// 字符串格式默认数字列
};
}
...
...
@@ -220,42 +257,88 @@ const validDynamicTimeConfig = computed(() => {
label
:
item
.
label
?.
trim
()
||
""
,
prop
:
item
.
prop
?.
trim
()
||
item
.
label
?.
trim
()
||
""
,
headerGroup
:
item
.
headerGroup
?.
trim
()
||
""
,
subGroup
:
item
.
subGroup
?.
trim
()
||
""
,
// 支持三级分组
isTextRow
:
item
.
isTextRow
===
true
,
// 显式转换为布尔值,默认false
};
})
.
filter
((
item
)
=>
!!
item
.
prop
);
});
// 判断是否有时间列分组
const
hasTimeHeaderGroup
=
computed
(()
=>
{
return
validDynamicTimeConfig
.
value
.
some
((
item
)
=>
!!
item
.
headerGroup
);
});
// 时间列分组计算
// 时间列分组计算(支持三级分组:headerGroup -> subGroup -> 列)
const
timeColumnGroups
=
computed
(()
=>
{
const
timeConfig
=
validDynamicTimeConfig
.
value
;
if
(
!
timeConfig
.
length
)
return
[];
const
groupMap
=
{};
const
groupMap
=
{};
// 一级分组:headerGroup
const
singleColumns
=
[];
// 没有分组的单列
timeConfig
.
forEach
((
item
)
=>
{
const
groupKey
=
item
.
headerGroup
||
`single_
${
item
.
prop
}
`
;
if
(
!
groupMap
[
groupKey
])
{
groupMap
[
groupKey
]
=
{
label
:
item
.
headerGroup
||
item
.
label
,
key
:
groupKey
,
children
:
[],
};
const
headerGroup
=
item
.
headerGroup
?.
trim
();
const
subGroup
=
item
.
subGroup
?.
trim
();
// 如果有有效的 headerGroup,则创建分组
if
(
headerGroup
&&
headerGroup
.
length
>
0
)
{
if
(
!
groupMap
[
headerGroup
])
{
groupMap
[
headerGroup
]
=
{
label
:
headerGroup
,
key
:
headerGroup
,
children
:
[],
};
}
// 如果有 subGroup,在一级分组下创建二级分组
if
(
subGroup
&&
subGroup
.
length
>
0
)
{
let
subGroupItem
=
groupMap
[
headerGroup
].
children
.
find
(
(
child
)
=>
child
.
label
===
subGroup
);
if
(
!
subGroupItem
)
{
subGroupItem
=
{
label
:
subGroup
,
key
:
`
${
headerGroup
}
_
${
subGroup
}
`
,
isSubGroup
:
true
,
// 标记为二级分组
children
:
[],
};
groupMap
[
headerGroup
].
children
.
push
(
subGroupItem
);
}
subGroupItem
.
children
.
push
(
item
);
}
else
{
// 没有 subGroup,直接挂在一级分组下
groupMap
[
headerGroup
].
children
.
push
(
item
);
}
}
else
{
// 没有 headerGroup 的作为单列处理(不显示一级标题)
singleColumns
.
push
({
label
:
""
,
// 空标题,不显示一级分组
key
:
`single_
${
item
.
prop
}
`
,
isSingle
:
true
,
// 标记为单列
children
:
[
item
],
});
}
groupMap
[
groupKey
].
children
.
push
(
item
);
});
// 合并分组和单列,保持原始顺序
const
result
=
[];
const
addedKeys
=
new
Set
();
timeConfig
.
forEach
((
item
)
=>
{
const
groupKey
=
item
.
headerGroup
||
`single_
${
item
.
prop
}
`
;
if
(
!
addedKeys
.
has
(
groupKey
))
{
result
.
push
(
groupMap
[
groupKey
]);
addedKeys
.
add
(
groupKey
);
const
headerGroup
=
item
.
headerGroup
?.
trim
();
// 有分组的
if
(
headerGroup
&&
headerGroup
.
length
>
0
)
{
if
(
!
addedKeys
.
has
(
headerGroup
))
{
result
.
push
(
groupMap
[
headerGroup
]);
addedKeys
.
add
(
headerGroup
);
}
}
else
{
// 单列
const
singleKey
=
`single_
${
item
.
prop
}
`
;
if
(
!
addedKeys
.
has
(
singleKey
))
{
const
singleColumn
=
singleColumns
.
find
((
sc
)
=>
sc
.
key
===
singleKey
);
if
(
singleColumn
)
{
result
.
push
(
singleColumn
);
addedKeys
.
add
(
singleKey
);
}
}
}
});
...
...
@@ -414,6 +497,7 @@ const tableCellStyle = ({ row }) => {
line-height
:
48px
;
background
:
#f5f7fa
;
text-align
:
center
;
margin-bottom
:
0
;
}
:deep
(
.el-input-number
)
{
...
...
src/components/InvestmentRecoveryTable.vue
0 → 100644
View file @
bc1354b0
<
template
>
<div
class=
"investment-recovery-table-wrap"
>
<!-- 总标题 -->
<div
v-if=
"tableTitle"
class=
"table-main-title"
>
{{
tableTitle
}}
</div>
<el-table
:data=
"tableDataRef"
style=
"width: 100%"
border
:cell-style=
"tableCellStyle"
row-key=
"serialNumber"
>
<!-- 序号列 -->
<el-table-column
prop=
"serialNumber"
label=
"序号"
width=
"80"
fixed=
"left"
align=
"center"
/>
<!-- 指标名称列 -->
<el-table-column
prop=
"indicatorName"
label=
"指标名称"
fixed=
"left"
align=
"left"
min-width=
"180"
/>
<!-- 年度更新表格的列 -->
<template
v-if=
"tableType === 'year'"
>
<el-table-column
v-for=
"col in yearColumns"
:key=
"col.prop"
:label=
"col.label"
min-width=
"180"
align=
"center"
>
<template
#
default=
"
{ row }">
<!-- 文本输入 -->
<el-input
v-if=
"col.isText"
v-model=
"row[col.prop]"
type=
"textarea"
:rows=
"2"
:disabled=
"isPreview || row.noEdit"
placeholder=
"请输入"
style=
"width: 100%"
@
input=
"handleTextInput"
/>
<!-- 数字输入 -->
<el-input
v-else-if=
"!col.isCalculated"
v-model=
"row[col.prop]"
type=
"number"
:disabled=
"isPreview || row.noEdit"
placeholder=
"请输入"
@
input=
"handleNumberInput(row)"
/>
<!-- 计算字段 -->
<span
v-else
class=
"calculated-value"
>
{{
formatCalculatedValue
(
row
[
col
.
prop
])
}}
</span>
</
template
>
</el-table-column>
</template>
<!-- 月度更新表格的列 -->
<
template
v-else
>
<!-- 1-12月 -->
<el-table-column
v-for=
"month in 12"
:key=
"`month-$
{month}`"
:label="`${month}月`"
:prop="`m${month}`"
min-width="180"
align="center"
>
<template
#
default=
"
{ row }">
<el-input
v-model=
"row[`m$
{month}`]"
type="number"
:disabled="isPreview || row.noEdit"
placeholder="请输入"
@input="handleMonthInput(row)"
/>
</
template
>
</el-table-column>
<!-- 本年累计 -->
<el-table-column
label=
"本年累计"
prop=
"yearTotal"
min-width=
"180"
align=
"center"
>
<
template
#
default=
"{ row }"
>
<span
v-if=
"row.isTotalRow"
class=
"calculated-value"
>
{{
formatCalculatedValue
(
row
.
yearTotal
)
}}
</span>
<el-input
v-else
v-model=
"row.yearTotal"
type=
"number"
:disabled=
"isPreview || row.noEdit || row.autoCalcYearTotal"
placeholder=
"自动计算"
@
input=
"handleYearTotalInput(row)"
/>
</
template
>
</el-table-column>
<!-- 本年完成率(分组) -->
<el-table-column
label=
"本年完成率"
align=
"center"
>
<el-table-column
label=
"本年决策"
prop=
"yearDecision"
min-width=
"180"
align=
"center"
>
<
template
#
default=
"{ row }"
>
<span
v-if=
"!row.isTotalRow"
class=
"calculated-value"
>
{{
formatCalculatedValue
(
row
.
yearDecision
)
}}
</span>
<span
v-else
class=
"calculated-value"
>
{{
formatCalculatedValue
(
row
.
yearDecision
)
}}
</span>
</
template
>
</el-table-column>
<el-table-column
label=
"本年计划"
prop=
"yearPlan"
align=
"center"
width=
"180"
>
<
template
#
default=
"{ row }"
>
<span
v-if=
"!row.isTotalRow"
class=
"calculated-value"
>
{{
formatCalculatedValue
(
row
.
yearPlan
)
}}
</span>
<span
v-else
class=
"calculated-value"
>
{{
formatCalculatedValue
(
row
.
yearPlan
)
}}
</span>
</
template
>
</el-table-column>
<el-table-column
label=
"本年累计/本年决策"
prop=
"yearCompletionRateDecision"
min-width=
"180"
align=
"center"
>
<
template
#
default=
"{ row }"
>
<span
class=
"calculated-value"
>
{{
formatCalculatedValue
(
row
.
yearCompletionRateDecision
,
"%"
)
}}
</span>
</
template
>
</el-table-column>
<el-table-column
label=
"本年累计/本年计划"
prop=
"yearCompletionRatePlan"
min-width=
"180"
align=
"center"
>
<
template
#
default=
"{ row }"
>
<span
class=
"calculated-value"
>
{{
formatCalculatedValue
(
row
.
yearCompletionRatePlan
,
"%"
)
}}
</span>
</
template
>
</el-table-column>
</el-table-column>
<!-- 截至本年完成(开累) -->
<el-table-column
label=
"截至本年完成(开累)"
prop=
"invoiceCompleted"
min-width=
"180"
align=
"center"
>
<
template
#
default=
"{ row }"
>
<el-input
v-model=
"row.invoiceCompleted"
type=
"number"
:disabled=
"isPreview || row.noEdit"
placeholder=
"请输入"
@
input=
"handleInvoiceInput(row)"
/>
</
template
>
</el-table-column>
<!-- 开累完成率(分组) -->
<el-table-column
label=
"开累完成率"
min-width=
"180"
align=
"center"
>
<el-table-column
min-width=
"180"
label=
"开累决策"
prop=
"invoiceDecision"
align=
"center"
>
<
template
#
default=
"{ row }"
>
<span
v-if=
"!row.isTotalRow"
class=
"calculated-value"
>
{{
formatCalculatedValue
(
row
.
invoiceDecision
)
}}
</span>
<span
v-else
class=
"calculated-value"
>
{{
formatCalculatedValue
(
row
.
invoiceDecision
)
}}
</span>
</
template
>
</el-table-column>
<el-table-column
label=
"开累计划"
min-width=
"180"
prop=
"invoicePlan"
align=
"center"
>
<
template
#
default=
"{ row }"
>
<span
v-if=
"!row.isTotalRow"
class=
"calculated-value"
>
{{
formatCalculatedValue
(
row
.
invoicePlan
)
}}
</span>
<span
v-else
class=
"calculated-value"
>
{{
formatCalculatedValue
(
row
.
invoicePlan
)
}}
</span>
</
template
>
</el-table-column>
<el-table-column
label=
"开累完成/开累决策"
prop=
"invoiceCompletionRateDecision"
min-width=
"180"
align=
"center"
>
<
template
#
default=
"{ row }"
>
<span
class=
"calculated-value"
>
{{
formatCalculatedValue
(
row
.
invoiceCompletionRateDecision
,
"%"
)
}}
</span>
</
template
>
</el-table-column>
<el-table-column
label=
"开累完成/开累计划"
prop=
"invoiceCompletionRatePlan"
min-width=
"180"
align=
"center"
>
<
template
#
default=
"{ row }"
>
<span
class=
"calculated-value"
>
{{
formatCalculatedValue
(
row
.
invoiceCompletionRatePlan
,
"%"
)
}}
</span>
</
template
>
</el-table-column>
</el-table-column>
<!-- 欠收金额 -->
<el-table-column
label=
"欠收金额"
prop=
"shortfallAmount"
min-width=
"180"
align=
"center"
>
<
template
#
default=
"{ row }"
>
<span
class=
"calculated-value"
>
{{
formatCalculatedValue
(
row
.
shortfallAmount
)
}}
</span>
</
template
>
</el-table-column>
<!-- 合同总金额 -->
<el-table-column
label=
"合同总金额"
prop=
"contractTotalAmount"
min-width=
"120"
align=
"center"
>
<
template
#
default=
"{ row }"
>
<el-input
v-model=
"row.contractTotalAmount"
type=
"number"
:disabled=
"isPreview || row.noEdit"
placeholder=
"请输入"
@
input=
"handleContractAmountInput(row)"
/>
</
template
>
</el-table-column>
<!-- 计划差额 -->
<el-table-column
label=
"计划差额"
prop=
"planDifference"
min-width=
"120"
align=
"center"
>
<
template
#
default=
"{ row }"
>
<span
class=
"calculated-value"
>
{{
formatCalculatedValue
(
row
.
planDifference
)
}}
</span>
</
template
>
</el-table-column>
</template>
</el-table>
</div>
</template>
<
script
setup
>
import
{
ref
,
computed
,
watch
,
nextTick
}
from
"vue"
;
const
props
=
defineProps
({
modelValue
:
{
type
:
Object
,
default
:
()
=>
({
tableData
:
[]
}),
},
isPreview
:
{
type
:
Boolean
,
default
:
false
,
},
tableType
:
{
type
:
String
,
default
:
"year"
,
// 'year' 或 'month'
validator
:
(
val
)
=>
[
"year"
,
"month"
].
includes
(
val
),
},
tableTitle
:
{
type
:
String
,
default
:
""
,
},
// 投资回收计划数据(用于自动填充本年计划、开累计划)
planData
:
{
type
:
Object
,
default
:
()
=>
({}),
},
// 投资回收决策数据(用于自动填充本年决策、开累决策)
decisionData
:
{
type
:
Object
,
default
:
()
=>
({}),
},
// 去年投资回收计划数据(用于获取前年数据)
lastYearPlanData
:
{
type
:
Object
,
default
:
()
=>
({}),
},
// 当前年份
currentYear
:
{
type
:
[
String
,
Number
],
default
:
""
,
},
});
const
emit
=
defineEmits
([
"update:modelValue"
]);
const
tableDataRef
=
ref
([]);
// 年度表格列配置
const
yearColumns
=
computed
(()
=>
[
{
prop
:
"decisionReceivable"
,
label
:
"截至年底应收决策应收"
,
width
:
160
,
isText
:
false
,
isCalculated
:
false
,
},
{
prop
:
"actualReceived"
,
label
:
"截至年底实收"
,
width
:
140
,
isText
:
false
,
isCalculated
:
false
,
},
{
prop
:
"shortfall"
,
label
:
"欠收(决策应收-实收)"
,
width
:
180
,
isText
:
false
,
isCalculated
:
true
,
},
{
prop
:
"completionRate"
,
label
:
"完成率"
,
width
:
120
,
isText
:
false
,
isCalculated
:
true
,
},
{
prop
:
"problems"
,
label
:
"存在主要问题"
,
width
:
200
,
isText
:
true
,
isCalculated
:
false
,
},
{
prop
:
"measures"
,
label
:
"采取措施情况"
,
width
:
200
,
isText
:
true
,
isCalculated
:
false
,
},
]);
// 格式化计算值
const
formatCalculatedValue
=
(
value
,
suffix
=
""
)
=>
{
if
(
value
===
null
||
value
===
undefined
||
isNaN
(
value
))
return
"-"
;
if
(
suffix
===
"%"
)
{
return
`
${
Number
(
value
).
toFixed
(
2
)}
%`
;
}
return
Number
(
value
).
toFixed
(
2
);
};
// 初始化行数据
const
initRowData
=
(
indicator
,
index
,
sourceRow
=
{})
=>
{
const
baseRow
=
{
serialNumber
:
index
+
1
,
indicatorName
:
indicator
.
name
,
noEdit
:
indicator
.
noEdit
||
false
,
isTotalRow
:
indicator
.
isTotalRow
||
false
,
};
if
(
props
.
tableType
===
"year"
)
{
return
{
...
baseRow
,
decisionReceivable
:
sourceRow
.
decisionReceivable
||
null
,
actualReceived
:
sourceRow
.
actualReceived
||
null
,
shortfall
:
sourceRow
.
shortfall
||
null
,
completionRate
:
sourceRow
.
completionRate
||
null
,
problems
:
sourceRow
.
problems
||
""
,
measures
:
sourceRow
.
measures
||
""
,
};
}
else
{
// 月度表格
const
monthData
=
{};
for
(
let
i
=
1
;
i
<=
12
;
i
++
)
{
monthData
[
`m
${
i
}
`
]
=
sourceRow
[
`m
${
i
}
`
]
||
null
;
}
return
{
...
baseRow
,
...
monthData
,
yearTotal
:
sourceRow
.
yearTotal
||
null
,
yearCompletionRateDecision
:
sourceRow
.
yearCompletionRateDecision
||
null
,
yearCompletionRatePlan
:
sourceRow
.
yearCompletionRatePlan
||
null
,
invoiceCompleted
:
sourceRow
.
invoiceCompleted
||
null
,
invoiceCompletionRateDecision
:
sourceRow
.
invoiceCompletionRateDecision
||
null
,
invoiceCompletionRatePlan
:
sourceRow
.
invoiceCompletionRatePlan
||
null
,
shortfallAmount
:
sourceRow
.
shortfallAmount
||
null
,
contractTotalAmount
:
sourceRow
.
contractTotalAmount
||
null
,
planDifference
:
sourceRow
.
planDifference
||
null
,
yearDecision
:
sourceRow
.
yearDecision
||
null
,
// 本年决策目标
yearPlan
:
sourceRow
.
yearPlan
||
null
,
// 本年计划目标
invoiceDecision
:
sourceRow
.
invoiceDecision
||
null
,
// 开累决策目标
invoicePlan
:
sourceRow
.
invoicePlan
||
null
,
// 开累计划目标
autoCalcYearTotal
:
indicator
.
autoCalcYearTotal
!==
false
,
// 默认自动计算本年累计
};
}
};
// 指标列表
const
indicators
=
[
{
name
:
"政府付费"
,
noEdit
:
false
},
{
name
:
"建设期"
,
noEdit
:
false
},
{
name
:
"运营期"
,
noEdit
:
false
},
{
name
:
"使用者付费"
,
noEdit
:
false
},
{
name
:
"投资价款"
,
noEdit
:
false
},
{
name
:
"参股项目投资回收"
,
noEdit
:
false
},
{
name
:
"代建工程款"
,
noEdit
:
false
},
{
name
:
"其他"
,
noEdit
:
false
},
{
name
:
"合计"
,
isTotalRow
:
true
,
noEdit
:
true
},
];
// 从计划数据和决策数据中获取对应指标的值
const
getIndicatorValue
=
(
indicatorName
,
dataSource
,
type
)
=>
{
if
(
!
dataSource
||
!
dataSource
.
tableData
)
return
0
;
const
row
=
dataSource
.
tableData
.
find
(
(
r
)
=>
r
.
indicatorName
===
indicatorName
);
if
(
!
row
)
return
0
;
// 根据类型返回对应字段的值
if
(
type
===
"yearDecision"
)
{
// 本年决策:从决策数据中获取当前年度的合计
// 决策数据的时间列表是 ["一季度", "二季度", "三季度", "四季度"]
// 合计 = 一季度 + 二季度 + 三季度 + 四季度
const
q1
=
parseFloat
(
row
[
"一季度"
])
||
0
;
const
q2
=
parseFloat
(
row
[
"二季度"
])
||
0
;
const
q3
=
parseFloat
(
row
[
"三季度"
])
||
0
;
const
q4
=
parseFloat
(
row
[
"四季度"
])
||
0
;
return
q1
+
q2
+
q3
+
q4
;
}
else
if
(
type
===
"yearPlan"
)
{
// 本年计划:从去年投资回收计划数据中获取合计值
return
parseFloat
(
row
.
a1
)
||
0
;
}
else
if
(
type
===
"invoiceDecision"
)
{
// 开累决策:从决策数据中获取开累值
// 这里可能是累计值,需要根据实际业务逻辑确定
const
q1
=
parseFloat
(
row
[
"一季度"
])
||
0
;
const
q2
=
parseFloat
(
row
[
"二季度"
])
||
0
;
const
q3
=
parseFloat
(
row
[
"三季度"
])
||
0
;
const
q4
=
parseFloat
(
row
[
"四季度"
])
||
0
;
return
q1
+
q2
+
q3
+
q4
;
// 暂时用年度合计
}
else
if
(
type
===
"invoicePlan"
)
{
// 开累计划:从计划数据中获取开累值
return
parseFloat
(
row
.
a1
)
||
0
;
// 暂时用年度合计
}
return
0
;
};
// 自动填充决策和计划数据
const
autoFillDecisionAndPlan
=
()
=>
{
if
(
props
.
tableType
!==
"month"
)
return
;
tableDataRef
.
value
.
forEach
((
row
)
=>
{
if
(
row
.
isTotalRow
||
row
.
noEdit
)
return
;
// 自动填充本年决策(从决策数据获取)
if
(
props
.
decisionData
&&
Object
.
keys
(
props
.
decisionData
).
length
>
0
)
{
row
.
yearDecision
=
getIndicatorValue
(
row
.
indicatorName
,
props
.
decisionData
,
"yearDecision"
);
}
// 自动填充本年计划(从去年投资回收计划数据获取)
if
(
props
.
lastYearPlanData
&&
Object
.
keys
(
props
.
lastYearPlanData
).
length
>
0
)
{
row
.
yearPlan
=
getIndicatorValue
(
row
.
indicatorName
,
props
.
lastYearPlanData
,
"yearPlan"
);
}
else
if
(
props
.
planData
&&
Object
.
keys
(
props
.
planData
).
length
>
0
)
{
// 如果没有去年数据,则使用当前年计划数据作为后备
row
.
yearPlan
=
getIndicatorValue
(
row
.
indicatorName
,
props
.
planData
,
"yearPlan"
);
}
// 自动填充开累决策(从决策数据获取)
if
(
props
.
decisionData
&&
Object
.
keys
(
props
.
decisionData
).
length
>
0
)
{
row
.
invoiceDecision
=
getIndicatorValue
(
row
.
indicatorName
,
props
.
decisionData
,
"invoiceDecision"
);
}
// 自动填充开累计划(从计划数据获取)
if
(
props
.
planData
&&
Object
.
keys
(
props
.
planData
).
length
>
0
)
{
row
.
invoicePlan
=
getIndicatorValue
(
row
.
indicatorName
,
props
.
planData
,
"invoicePlan"
);
}
});
// 重新计算完成率
tableDataRef
.
value
.
forEach
((
row
)
=>
{
calculateMonthRow
(
row
);
});
};
// 年度表格计算
const
calculateYearRow
=
(
row
)
=>
{
if
(
row
.
noEdit
||
row
.
isTotalRow
)
return
;
// 欠收 = 决策应收 - 实收
const
decision
=
parseFloat
(
row
.
decisionReceivable
)
||
0
;
const
actual
=
parseFloat
(
row
.
actualReceived
)
||
0
;
row
.
shortfall
=
decision
-
actual
;
// 完成率 = 实收 / 决策应收 * 100
if
(
decision
>
0
)
{
row
.
completionRate
=
(
actual
/
decision
)
*
100
;
}
else
{
row
.
completionRate
=
0
;
}
};
// 月度表格计算
const
calculateMonthRow
=
(
row
)
=>
{
if
(
row
.
noEdit
||
row
.
isTotalRow
)
return
;
// 本年累计 = 1-12月之和
if
(
row
.
autoCalcYearTotal
)
{
let
monthSum
=
0
;
for
(
let
i
=
1
;
i
<=
12
;
i
++
)
{
monthSum
+=
parseFloat
(
row
[
`m
${
i
}
`
])
||
0
;
}
row
.
yearTotal
=
monthSum
;
}
// 本年完成率/本年决策 = 本年累计 / 本年决策 * 100
const
yearDecision
=
parseFloat
(
row
.
yearDecision
)
||
0
;
const
yearTotal
=
parseFloat
(
row
.
yearTotal
)
||
0
;
if
(
yearDecision
>
0
)
{
row
.
yearCompletionRateDecision
=
(
yearTotal
/
yearDecision
)
*
100
;
}
else
{
row
.
yearCompletionRateDecision
=
0
;
}
// 本年完成率/本年计划 = 本年累计 / 本年计划 * 100
const
yearPlan
=
parseFloat
(
row
.
yearPlan
)
||
0
;
if
(
yearPlan
>
0
)
{
row
.
yearCompletionRatePlan
=
(
yearTotal
/
yearPlan
)
*
100
;
}
else
{
row
.
yearCompletionRatePlan
=
0
;
}
// 开累完成率/开累决策 = 开累完成 / 开累决策 * 100
const
invoiceDecision
=
parseFloat
(
row
.
invoiceDecision
)
||
0
;
const
invoiceCompleted
=
parseFloat
(
row
.
invoiceCompleted
)
||
0
;
if
(
invoiceDecision
>
0
)
{
row
.
invoiceCompletionRateDecision
=
(
invoiceCompleted
/
invoiceDecision
)
*
100
;
}
else
{
row
.
invoiceCompletionRateDecision
=
0
;
}
// 开累完成率/本年计划 = 开累完成 / 开累计划 * 100
const
invoicePlan
=
parseFloat
(
row
.
invoicePlan
)
||
0
;
if
(
invoicePlan
>
0
)
{
row
.
invoiceCompletionRatePlan
=
(
invoiceCompleted
/
invoicePlan
)
*
100
;
}
else
{
row
.
invoiceCompletionRatePlan
=
0
;
}
// 欠收金额 = 本年决策 - 本年累计
row
.
shortfallAmount
=
yearDecision
-
yearTotal
;
// 计划差额 = 合同总金额 - 本年计划
const
contractTotal
=
parseFloat
(
row
.
contractTotalAmount
)
||
0
;
row
.
planDifference
=
contractTotal
-
yearPlan
;
};
// 计算合计行
const
calculateTotalRow
=
()
=>
{
const
totalRow
=
tableDataRef
.
value
.
find
((
row
)
=>
row
.
isTotalRow
);
if
(
!
totalRow
)
return
;
if
(
props
.
tableType
===
"year"
)
{
// 年度表格合计
let
totalDecision
=
0
;
let
totalActual
=
0
;
tableDataRef
.
value
.
forEach
((
row
)
=>
{
if
(
!
row
.
isTotalRow
&&
!
row
.
noEdit
)
{
totalDecision
+=
parseFloat
(
row
.
decisionReceivable
)
||
0
;
totalActual
+=
parseFloat
(
row
.
actualReceived
)
||
0
;
}
});
totalRow
.
decisionReceivable
=
totalDecision
;
totalRow
.
actualReceived
=
totalActual
;
totalRow
.
shortfall
=
totalDecision
-
totalActual
;
if
(
totalDecision
>
0
)
{
totalRow
.
completionRate
=
(
totalActual
/
totalDecision
)
*
100
;
}
else
{
totalRow
.
completionRate
=
0
;
}
}
else
{
// 月度表格合计
for
(
let
i
=
1
;
i
<=
12
;
i
++
)
{
let
monthSum
=
0
;
tableDataRef
.
value
.
forEach
((
row
)
=>
{
if
(
!
row
.
isTotalRow
&&
!
row
.
noEdit
)
{
monthSum
+=
parseFloat
(
row
[
`m
${
i
}
`
])
||
0
;
}
});
totalRow
[
`m
${
i
}
`
]
=
monthSum
;
}
// 本年累计
let
yearTotalSum
=
0
;
for
(
let
i
=
1
;
i
<=
12
;
i
++
)
{
yearTotalSum
+=
parseFloat
(
totalRow
[
`m
${
i
}
`
])
||
0
;
}
totalRow
.
yearTotal
=
yearTotalSum
;
}
};
// 处理输入事件
const
handleNumberInput
=
(
row
)
=>
{
calculateYearRow
(
row
);
calculateTotalRow
();
emitChange
();
};
const
handleTextInput
=
()
=>
{
emitChange
();
};
const
handleMonthInput
=
(
row
)
=>
{
calculateMonthRow
(
row
);
calculateTotalRow
();
emitChange
();
};
const
handleYearTotalInput
=
(
row
)
=>
{
calculateMonthRow
(
row
);
calculateTotalRow
();
emitChange
();
};
const
handleInvoiceInput
=
(
row
)
=>
{
calculateMonthRow
(
row
);
calculateTotalRow
();
emitChange
();
};
const
handleContractAmountInput
=
(
row
)
=>
{
calculateMonthRow
(
row
);
calculateTotalRow
();
emitChange
();
};
const
emitChange
=
()
=>
{
if
(
props
.
isPreview
)
return
;
const
newModelValue
=
{
...
props
.
modelValue
,
tableData
:
JSON
.
parse
(
JSON
.
stringify
(
tableDataRef
.
value
)),
};
emit
(
"update:modelValue"
,
newModelValue
);
};
// 表格单元格样式
const
tableCellStyle
=
({
row
})
=>
{
if
(
row
.
isTotalRow
)
{
return
{
background
:
"#f5f7fa"
,
fontWeight
:
"bold"
,
textAlign
:
"center"
};
}
return
{
textAlign
:
"center"
};
};
// 监听数据变化
watch
(
()
=>
props
.
modelValue
,
(
newVal
)
=>
{
nextTick
(()
=>
{
const
sourceData
=
newVal
.
tableData
||
[];
const
newData
=
indicators
.
map
((
indicator
,
index
)
=>
{
const
sourceRow
=
sourceData
.
find
((
r
)
=>
r
.
indicatorName
===
indicator
.
name
)
||
{};
return
initRowData
(
indicator
,
index
,
sourceRow
);
});
tableDataRef
.
value
=
newData
;
// 自动填充决策和计划数据
autoFillDecisionAndPlan
();
});
},
{
deep
:
true
,
immediate
:
true
},
);
// 监听计划数据和决策数据变化
watch
(
[()
=>
props
.
planData
,
()
=>
props
.
decisionData
,
()
=>
props
.
lastYearPlanData
],
()
=>
{
nextTick
(()
=>
{
autoFillDecisionAndPlan
();
});
},
{
deep
:
true
},
);
</
script
>
<
style
scoped
lang=
"scss"
>
.investment-recovery-table-wrap
{
width
:
100%
;
box-sizing
:
border-box
;
overflow-x
:
auto
;
}
.table-main-title
{
font-size
:
16px
;
font-weight
:
600
;
color
:
#1f2937
;
border-bottom
:
1px
solid
#ebeef5
;
height
:
48px
;
line-height
:
48px
;
background
:
#f5f7fa
;
text-align
:
center
;
}
.calculated-value
{
color
:
#409eff
;
font-weight
:
500
;
}
:deep
(
.el-input__wrapper
)
{
width
:
100%
;
}
:deep
(
.el-input__inner
)
{
text-align
:
center
;
}
:deep
(
.el-textarea__inner
)
{
text-align
:
left
;
min-height
:
40px
!
important
;
}
:deep
(
.el-table__cell
)
{
padding
:
4px
8px
!
important
;
height
:
48px
!
important
;
vertical-align
:
middle
!
important
;
}
:deep
(
.el-table__row
)
{
height
:
48px
!
important
;
}
</
style
>
src/styles/manage.less
View file @
bc1354b0
...
...
@@ -116,6 +116,7 @@
color: var(--el-color-primary);
}
}
&-header {
border: none;
height: 64px;
...
...
@@ -130,6 +131,7 @@
height: 0;
display: flex;
flex-direction: column;
.tabs-content {
flex: 1;
height: 0;
...
...
src/views/castbehind/investmentCecoveryAdd.vue
View file @
bc1354b0
...
...
@@ -9,6 +9,18 @@
<el-collapse
v-model=
"activeCollapse"
>
<el-collapse-item
title=
"项目基本信息"
name=
"项目基本信息"
>
<el-row
:gutter=
"24"
>
<el-col
:span=
"6"
>
<el-form-item
label=
"年度"
required
>
<el-date-picker
v-model=
"formData.nd"
type=
"year"
placeholder=
"请选择年度"
format=
"YYYY"
value-format=
"YYYY"
style=
"width: 100%"
/>
</el-form-item>
</el-col>
<el-col
:span=
"6"
>
<el-form-item
label=
"项目名称"
required
>
<el-select
...
...
@@ -172,8 +184,8 @@
</el-collapse-item>
<el-collapse-item
title=
"2025年投资回收累计完成情况-年度更新
"
name=
"2025年投资回收累计完成情况-年度更新
"
:title=
"dynamicTitles.yearlyUpdateTitle
"
:name=
"dynamicTitles.yearlyUpdateTitle
"
>
<el-row
gutter=
"20"
>
<!-- 第一行:决策目标值相关数字项 -->
...
...
@@ -342,11 +354,38 @@
v-model=
"formData.tzhsjh"
:showSerialColumn=
"false"
:is-preview=
"isPreview"
table-title=
"2026年投资回收计划明细"
:showNameColumn=
"false"
:showTotalColumn=
"false"
/>
</el-collapse-item>
<el-collapse-item
:title=
"dynamicTitles.yearlyCompletionTitle"
:name=
"dynamicTitles.yearlyCompletionTitle"
>
<InvestmentRecoveryTable
v-model=
"formData.tzhswcqkndgx"
:is-preview=
"isPreview"
table-type=
"year"
:table-title=
"dynamicTitles.yearlyCompletionTitle"
/>
</el-collapse-item>
<el-collapse-item
:title=
"dynamicTitles.monthlyCompletionTitle"
:name=
"dynamicTitles.monthlyCompletionTitle"
>
<InvestmentRecoveryTable
v-model=
"formData.tzhswcqkydgx"
:is-preview=
"isPreview"
table-type=
"month"
:table-title=
"dynamicTitles.monthlyCompletionTitle"
:plan-data=
"formData.tzhsjh"
:decision-data=
"formData.tzhsjc"
:last-year-plan-data=
"formData.lastyeartzhs"
:current-year=
"currentYear"
/>
</el-collapse-item>
</el-collapse>
</el-form>
</div>
...
...
@@ -366,11 +405,20 @@
</template>
<
script
setup
>
import
{
reactive
,
ref
,
onMounted
,
getCurrentInstance
,
h
,
computed
}
from
"vue"
;
import
{
reactive
,
watch
,
ref
,
onMounted
,
getCurrentInstance
,
h
,
computed
,
}
from
"vue"
;
import
{
useRouter
,
useRoute
}
from
"vue-router"
;
import
{
ElMessage
}
from
"element-plus"
;
import
DynamicTable
from
"@/components/FormDynamicTable/index.vue"
;
import
FinancialTable
from
"@/components/FinancialTable.vue"
;
import
InvestmentRecoveryTable
from
"@/components/InvestmentRecoveryTable.vue"
;
import
routerBack
from
"@/components/common/routerBack.vue"
;
const
transferColumns
=
ref
([
{
...
...
@@ -415,273 +463,439 @@ const router = useRouter();
const
route
=
useRoute
();
const
{
proxy
}
=
getCurrentInstance
();
// 折叠面板默认展开项
const
activeCollapse
=
ref
([
"项目基本信息"
,
"出资情况"
,
"合同约定权益获取"
,
"分红情况"
,
"投资额完成情况(万元)"
,
"投资回收(决策)"
,
"投资回收(计划)"
,
"2025年投资回收累计完成情况-年度更新"
,
"净现金流"
,
"截止12月末累计应收"
,
"截止12月末累计实收"
,
"资金流出"
,
"分红情况"
,
]);
// 表单数据
let
initTableData
=
()
=>
{
Object
.
assign
(
formData
,
{
jzymljys
:
{
indicatorList
:
[
{
name
:
"一月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"二月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"三月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"四月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"五月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"六月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"七月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"八月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"九月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"十月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"十一月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"十二月"
,
isTextRow
:
false
,
noTotal
:
false
},
],
dynamicTimeList
:
[
{
label
:
"政府付费"
,
prop
:
"a1"
},
{
label
:
"政府补贴"
,
prop
:
"a2"
},
{
label
:
"使用者付费"
,
prop
:
"a3"
},
{
label
:
"使用者欠付"
,
prop
:
"a4"
},
{
label
:
"补贴收入"
,
prop
:
"a5"
},
// 使用 Object.assign 直接替换整个对象,而不是合并
formData
.
jzymljys
=
{
indicatorList
:
[
{
name
:
"一月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"二月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"三月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"四月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"五月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"六月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"七月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"八月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"九月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"十月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"十一月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"十二月"
,
isTextRow
:
false
,
noTotal
:
false
},
],
dynamicTimeList
:
[
{
label
:
"政府付费"
,
prop
:
"a1"
},
{
label
:
"政府补贴"
,
prop
:
"a2"
},
{
label
:
"使用者付费"
,
prop
:
"a3"
},
{
label
:
"使用者欠付"
,
prop
:
"a4"
},
{
label
:
"补贴收入"
,
prop
:
"a5"
},
{
label
:
"销售回款(含房地产、水泥、新能源售电、其他生产制造收入等)"
,
prop
:
"a6"
,
},
{
label
:
"资产盘活"
,
prop
:
"a7"
},
{
label
:
"股权分红"
,
prop
:
"a8"
},
{
label
:
"其他"
,
prop
:
"a9"
},
{
label
:
"目标(决策)与计划差异说明"
,
prop
:
"a10"
,
isTextRow
:
true
,
},
],
// 表格数据(子组件自动初始化,无需手动赋值)
tableData
:
[],
};
formData
.
jzymljsh
=
{
indicatorList
:
[
{
name
:
"一月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"二月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"三月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"四月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"五月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"六月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"七月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"八月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"九月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"十月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"十一月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"十二月"
,
isTextRow
:
false
,
noTotal
:
false
,
},
],
dynamicTimeList
:
[
{
label
:
"政府付费"
,
prop
:
"a1"
},
{
label
:
"政府补贴"
,
prop
:
"a2"
},
{
label
:
"使用者付费"
,
prop
:
"a3"
},
{
label
:
"使用者欠付"
,
prop
:
"a4"
},
{
label
:
"补贴收入"
,
prop
:
"a5"
},
{
label
:
"销售回款(含房地产、水泥、新能源售电、其他生产制造收入等)"
,
prop
:
"a6"
,
},
{
label
:
"资产盘活"
,
prop
:
"a7"
},
{
label
:
"股权分红"
,
prop
:
"a8"
},
{
label
:
"其他"
,
prop
:
"a9"
},
{
label
:
"目标(决策)与计划差异说明"
,
prop
:
"a10"
,
isTextRow
:
true
,
},
],
// 表格数据(子组件自动初始化,无需手动赋值)
tableData
:
[],
};
formData
.
tzhsjc
=
{
// 指标列表
indicatorList
:
[
{
name
:
"建设期政府付费"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"运营期政府付费"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"投资价差收取"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"参股项目投资回收"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"代建工程款回收"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"政府付费"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"政府补贴"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"使用者付费"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"使用者欠付"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"补贴收入"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"销售回款(含房地产、水泥、新能源售电、其他生产制造收入等)"
,
isTextRow
:
false
,
noTotal
:
false
,
},
{
name
:
"资产盘活"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"股权分红"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"其他"
,
isTextRow
:
false
,
noTotal
:
false
},
// 关键:标记为文本行+不需要合计
{
name
:
"目标(决策)与计划差异说明"
,
isTextRow
:
true
,
noTotal
:
true
},
],
// 时间列表(月度)
dynamicTimeList
:
[
"一季度"
,
"二季度"
,
"三季度"
,
"四季度"
],
// 表格数据(子组件会自动初始化,父组件可传初始值)
tableData
:
[],
};
formData
.
tzhsjh
=
{
// 指标列表
indicatorList
:
[
{
name
:
" "
,
},
],
// 时间列表(月度)- 使用动态年度
get
dynamicTimeList
()
{
const
year
=
formData
.
nd
;
const
yearStr
=
`
${
year
}
年`
;
const
q1Str
=
`
${
year
}
年(一季度)`
;
const
q2Str
=
`
${
year
}
年(二季度)`
;
const
q3Str
=
`
${
year
}
年(三季度)`
;
const
q4Str
=
`
${
year
}
年(四季度)`
;
return
[
// 第一组:投资回收(决策) -> 动态年度
{
label
:
"销售回款(含房地产、水泥、新能源售电、其他生产制造收入等)"
,
prop
:
"a6"
,
label
:
"合计"
,
prop
:
"a1"
,
headerGroup
:
"投资回收(决策)"
,
subGroup
:
yearStr
,
},
{
label
:
"资产盘活"
,
prop
:
"a7"
},
{
label
:
"股权分红"
,
prop
:
"a8"
},
{
label
:
"其他"
,
prop
:
"a9"
},
{
label
:
"
目标(决策)与计划差异说明
"
,
prop
:
"a
10
"
,
isTextRow
:
true
,
label
:
"
政府付费
"
,
prop
:
"a
2
"
,
headerGroup
:
"投资回收(决策)"
,
subGroup
:
yearStr
,
},
],
// 表格数据(子组件自动初始化,无需手动赋值)
tableData
:
[],
},
jzymljsh
:
{
indicatorList
:
[
{
name
:
"一月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"二月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"三月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"四月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"五月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"六月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"七月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"八月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"九月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"十月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"十一月"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"十二月"
,
isTextRow
:
false
,
noTotal
:
false
,
label
:
"政府补助"
,
prop
:
"a3"
,
headerGroup
:
"投资回收(决策)"
,
subGroup
:
yearStr
,
},
],
dynamicTimeList
:
[
{
label
:
"政府付费"
,
prop
:
"a1"
},
{
label
:
"政府补贴"
,
prop
:
"a2"
},
{
label
:
"使用者付费"
,
prop
:
"a3"
},
{
label
:
"使用者欠付"
,
prop
:
"a4"
},
{
label
:
"补贴收入"
,
prop
:
"a5"
},
{
label
:
"销售回款(含房地产、水泥、新能源售电、其他生产制造收入等)"
,
label
:
"使用者付费"
,
prop
:
"a4"
,
headerGroup
:
"投资回收(决策)"
,
subGroup
:
yearStr
,
},
{
label
:
"使用者欠付"
,
prop
:
"a5"
,
headerGroup
:
"投资回收(决策)"
,
subGroup
:
yearStr
,
},
{
label
:
"补贴收入"
,
prop
:
"a6"
,
headerGroup
:
"投资回收(决策)"
,
subGroup
:
yearStr
,
},
{
label
:
"资产盘活"
,
prop
:
"a7"
},
{
label
:
"股权分红"
,
prop
:
"a8"
},
{
label
:
"其他"
,
prop
:
"a9"
},
{
label
:
"
目标(决策)与计划差异说明
"
,
prop
:
"a
10
"
,
isTextRow
:
true
,
label
:
"
销售回款(含房地产、水泥、新能源售电、其他生产制造收入等)
"
,
prop
:
"a
7
"
,
headerGroup
:
"投资回收(决策)"
,
subGroup
:
yearStr
,
},
],
// 表格数据(子组件自动初始化,无需手动赋值)
tableData
:
[],
},
tzhsjc
:
{
// 指标列表
indicatorList
:
[
{
name
:
"建设期政府付费"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"运营期政府付费"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"投资价差收取"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"参股项目投资回收"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"代建工程款回收"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"政府付费"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"政府补贴"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"使用者付费"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"使用者欠付"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"补贴收入"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"销售回款(含房地产、水泥、新能源售电、其他生产制造收入等)"
,
isTextRow
:
false
,
noTotal
:
false
,
label
:
"资产盘活"
,
prop
:
"a8"
,
headerGroup
:
"投资回收(决策)"
,
subGroup
:
yearStr
,
},
{
name
:
"资产盘活"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"股权分红"
,
isTextRow
:
false
,
noTotal
:
false
},
{
name
:
"其他"
,
isTextRow
:
false
,
noTotal
:
false
},
// 关键:标记为文本行+不需要合计
{
name
:
"目标(决策)与计划差异说明"
,
isTextRow
:
true
,
noTotal
:
true
},
],
// 时间列表(月度)
dynamicTimeList
:
[
"一季度"
,
"二季度"
,
"三季度"
,
"四季度"
],
// 表格数据(子组件会自动初始化,父组件可传初始值)
tableData
:
[],
},
tzhsjh
:
{
// 指标列表
indicatorList
:
[
{
name
:
" "
,
label
:
"股权分红"
,
prop
:
"a9"
,
headerGroup
:
"投资回收(决策)"
,
subGroup
:
yearStr
,
},
],
// 时间列表(月度)
dynamicTimeList
:
[
// 第一组:2026年
{
label
:
"合计"
,
prop
:
"a1"
,
headerGroup
:
"2026年"
},
{
label
:
"政府付费"
,
prop
:
"a2"
,
headerGroup
:
"2026年"
},
{
label
:
"政府补助"
,
prop
:
"a3"
,
headerGroup
:
"2026年"
},
{
label
:
"使用者付费"
,
prop
:
"a4"
,
headerGroup
:
"2026年"
},
{
label
:
"使用者欠付"
,
prop
:
"a5"
,
headerGroup
:
"2026年"
},
{
label
:
"补贴收入"
,
prop
:
"a6"
,
headerGroup
:
"2026年"
},
{
label
:
"销售回款(含房地产、水泥、新能源售电、其他生产制造收入等)"
,
prop
:
"a7"
,
headerGroup
:
"2026年"
,
label
:
"其他"
,
prop
:
"a10"
,
headerGroup
:
"投资回收(决策)"
,
subGroup
:
yearStr
,
},
{
label
:
"资产盘活"
,
prop
:
"a8"
,
headerGroup
:
"2026年"
},
{
label
:
"股权分红"
,
prop
:
"a9"
,
headerGroup
:
"2026年"
},
{
label
:
"其他"
,
prop
:
"a10"
,
headerGroup
:
"2026年"
},
{
label
:
"目标(决策)与计划差异说明"
,
isTextRow
:
true
,
prop
:
"a11"
,
headerGroup
:
"2026年"
,
headerGroup
:
"投资回收(决策)"
,
subGroup
:
yearStr
,
},
// 第三组:2026年(一季度)
{
label
:
"合计"
,
prop
:
"a23"
,
headerGroup
:
"2026年(一季度)"
},
{
label
:
"政府付费"
,
prop
:
"a24"
,
headerGroup
:
"2026年(一季度)"
},
{
label
:
"政府补助"
,
prop
:
"a25"
,
headerGroup
:
"2026年(一季度)"
},
{
label
:
"使用者付费"
,
prop
:
"a26"
,
headerGroup
:
"2026年(一季度)"
},
{
label
:
"使用者欠付"
,
prop
:
"a27"
,
headerGroup
:
"2026年(一季度)"
},
{
label
:
"补贴收入"
,
prop
:
"a28"
,
headerGroup
:
"2026年(一季度)"
},
// 第二组:动态年度
{
label
:
"合计"
,
prop
:
"a12"
,
headerGroup
:
yearStr
},
{
label
:
"政府付费"
,
prop
:
"a13"
,
headerGroup
:
yearStr
},
{
label
:
"政府补助"
,
prop
:
"a14"
,
headerGroup
:
yearStr
},
{
label
:
"使用者付费"
,
prop
:
"a15"
,
headerGroup
:
yearStr
},
{
label
:
"使用者欠付"
,
prop
:
"a16"
,
headerGroup
:
yearStr
},
{
label
:
"补贴收入"
,
prop
:
"a17"
,
headerGroup
:
yearStr
},
{
label
:
"销售回款(含房地产、水泥、新能源售电、其他生产制造收入等)"
,
prop
:
"a18"
,
headerGroup
:
yearStr
,
},
{
label
:
"资产盘活"
,
prop
:
"a19"
,
headerGroup
:
yearStr
},
{
label
:
"股权分红"
,
prop
:
"a20"
,
headerGroup
:
yearStr
},
{
label
:
"其他"
,
prop
:
"a21"
,
headerGroup
:
yearStr
},
{
label
:
"目标(决策)与计划差异说明"
,
isTextRow
:
true
,
prop
:
"a22"
,
headerGroup
:
yearStr
,
},
// 第三组:动态年度(一季度)
{
label
:
"合计"
,
prop
:
"a23"
,
headerGroup
:
q1Str
},
{
label
:
"政府付费"
,
prop
:
"a24"
,
headerGroup
:
q1Str
},
{
label
:
"政府补助"
,
prop
:
"a25"
,
headerGroup
:
q1Str
},
{
label
:
"使用者付费"
,
prop
:
"a26"
,
headerGroup
:
q1Str
},
{
label
:
"使用者欠付"
,
prop
:
"a27"
,
headerGroup
:
q1Str
},
{
label
:
"补贴收入"
,
prop
:
"a28"
,
headerGroup
:
q1Str
},
{
label
:
"销售回款(含房地产、水泥、新能源售电、其他生产制造收入等)"
,
prop
:
"a29"
,
headerGroup
:
"2026年(一季度)"
,
headerGroup
:
q1Str
,
},
{
label
:
"资产盘活"
,
prop
:
"a30"
,
headerGroup
:
"2026年(一季度)"
},
{
label
:
"股权分红"
,
prop
:
"a31"
,
headerGroup
:
"2026年(一季度)"
},
{
label
:
"其他"
,
prop
:
"a32"
,
headerGroup
:
"2026年(一季度)"
},
{
label
:
"资产盘活"
,
prop
:
"a30"
,
headerGroup
:
q1Str
},
{
label
:
"股权分红"
,
prop
:
"a31"
,
headerGroup
:
q1Str
},
{
label
:
"其他"
,
prop
:
"a32"
,
headerGroup
:
q1Str
},
{
label
:
"目标(决策)与计划差异说明"
,
isTextRow
:
true
,
prop
:
"a33"
,
headerGroup
:
"2026年(一季度)"
,
headerGroup
:
q1Str
,
},
// 第四组:投资回收(计划) -> 动态年度
{
label
:
"合计"
,
prop
:
"a34"
,
headerGroup
:
"投资回收(计划)"
,
subGroup
:
yearStr
,
},
{
label
:
"政府付费"
,
prop
:
"a35"
,
headerGroup
:
"投资回收(计划)"
,
subGroup
:
yearStr
,
},
{
label
:
"政府补助"
,
prop
:
"a36"
,
headerGroup
:
"投资回收(计划)"
,
subGroup
:
yearStr
,
},
{
label
:
"使用者付费"
,
prop
:
"a37"
,
headerGroup
:
"投资回收(计划)"
,
subGroup
:
yearStr
,
},
{
label
:
"使用者欠付"
,
prop
:
"a38"
,
headerGroup
:
"投资回收(计划)"
,
subGroup
:
yearStr
,
},
{
label
:
"补贴收入"
,
prop
:
"a39"
,
headerGroup
:
"投资回收(计划)"
,
subGroup
:
yearStr
,
},
// 第四组:2026年(二季度)
{
label
:
"合计"
,
prop
:
"a34"
,
headerGroup
:
"2026年(二季度)"
},
{
label
:
"政府付费"
,
prop
:
"a35"
,
headerGroup
:
"2026年(二季度)"
},
{
label
:
"政府补助"
,
prop
:
"a36"
,
headerGroup
:
"2026年(二季度)"
},
{
label
:
"使用者付费"
,
prop
:
"a37"
,
headerGroup
:
"2026年(二季度)"
},
{
label
:
"使用者欠付"
,
prop
:
"a38"
,
headerGroup
:
"2026年(二季度)"
},
{
label
:
"补贴收入"
,
prop
:
"a39"
,
headerGroup
:
"2026年(二季度)"
},
{
label
:
"销售回款(含房地产、水泥、新能源售电、其他生产制造收入等)"
,
prop
:
"a40"
,
headerGroup
:
"2026年(二季度)"
,
headerGroup
:
"投资回收(计划)"
,
subGroup
:
yearStr
,
},
{
label
:
"资产盘活"
,
prop
:
"a41"
,
headerGroup
:
"投资回收(计划)"
,
subGroup
:
yearStr
,
},
{
label
:
"股权分红"
,
prop
:
"a42"
,
headerGroup
:
"投资回收(计划)"
,
subGroup
:
yearStr
,
},
{
label
:
"其他"
,
prop
:
"a43"
,
headerGroup
:
"投资回收(计划)"
,
subGroup
:
yearStr
,
},
{
label
:
"资产盘活"
,
prop
:
"a41"
,
headerGroup
:
"2026年(二季度)"
},
{
label
:
"股权分红"
,
prop
:
"a42"
,
headerGroup
:
"2026年(二季度)"
},
{
label
:
"其他"
,
prop
:
"a43"
,
headerGroup
:
"2026年(二季度)"
},
{
label
:
"目标(决策)与计划差异说明"
,
isTextRow
:
true
,
prop
:
"a44"
,
headerGroup
:
"2026年(二季度)"
,
headerGroup
:
"投资回收(计划)"
,
subGroup
:
yearStr
,
},
// 第五组:2026年(三季度)
{
label
:
"合计"
,
prop
:
"a45"
,
headerGroup
:
"2026年(三季度)"
},
{
label
:
"政府付费"
,
prop
:
"a46"
,
headerGroup
:
"2026年(三季度)"
},
{
label
:
"政府补助"
,
prop
:
"a47"
,
headerGroup
:
"2026年(三季度)"
},
{
label
:
"使用者付费"
,
prop
:
"a48"
,
headerGroup
:
"2026年(三季度)"
},
{
label
:
"使用者欠付"
,
prop
:
"a49"
,
headerGroup
:
"2026年(三季度)"
},
{
label
:
"补贴收入"
,
prop
:
"a50"
,
headerGroup
:
"2026年(三季度)"
},
// 第五组:动态年度(三季度)
{
label
:
"合计"
,
prop
:
"a45"
,
headerGroup
:
q3Str
},
{
label
:
"政府付费"
,
prop
:
"a46"
,
headerGroup
:
q3Str
},
{
label
:
"政府补助"
,
prop
:
"a47"
,
headerGroup
:
q3Str
},
{
label
:
"使用者付费"
,
prop
:
"a48"
,
headerGroup
:
q3Str
},
{
label
:
"使用者欠付"
,
prop
:
"a49"
,
headerGroup
:
q3Str
},
{
label
:
"补贴收入"
,
prop
:
"a50"
,
headerGroup
:
q3Str
},
{
label
:
"销售回款(含房地产、水泥、新能源售电、其他生产制造收入等)"
,
prop
:
"a51"
,
headerGroup
:
"2026年(三季度)"
,
headerGroup
:
q3Str
,
},
{
label
:
"资产盘活"
,
prop
:
"a52"
,
headerGroup
:
"2026年(三季度)"
},
{
label
:
"股权分红"
,
prop
:
"a53"
,
headerGroup
:
"2026年(三季度)"
},
{
label
:
"其他"
,
prop
:
"a54"
,
headerGroup
:
"2026年(三季度)"
},
{
label
:
"资产盘活"
,
prop
:
"a52"
,
headerGroup
:
q3Str
},
{
label
:
"股权分红"
,
prop
:
"a53"
,
headerGroup
:
q3Str
},
{
label
:
"其他"
,
prop
:
"a54"
,
headerGroup
:
q3Str
},
{
label
:
"目标(决策)与计划差异说明"
,
isTextRow
:
true
,
prop
:
"a55"
,
headerGroup
:
"2026年(三季度)"
,
headerGroup
:
q3Str
,
},
// 第六组:2026年(四季度)
{
label
:
"合计"
,
prop
:
"a56"
,
headerGroup
:
"2026年(四季度)"
},
{
label
:
"政府付费"
,
prop
:
"a57"
,
headerGroup
:
"2026年(四季度)"
},
{
label
:
"政府补助"
,
prop
:
"a58"
,
headerGroup
:
"2026年(四季度)"
},
{
label
:
"使用者付费"
,
prop
:
"a59"
,
headerGroup
:
"2026年(四季度)"
},
{
label
:
"使用者欠付"
,
prop
:
"a60"
,
headerGroup
:
"2026年(四季度)"
},
{
label
:
"补贴收入"
,
prop
:
"a61"
,
headerGroup
:
"2026年(四季度)"
},
// 第六组:动态年度(四季度)
{
label
:
"合计"
,
prop
:
"a56"
,
headerGroup
:
q4Str
},
{
label
:
"政府付费"
,
prop
:
"a57"
,
headerGroup
:
q4Str
},
{
label
:
"政府补助"
,
prop
:
"a58"
,
headerGroup
:
q4Str
},
{
label
:
"使用者付费"
,
prop
:
"a59"
,
headerGroup
:
q4Str
},
{
label
:
"使用者欠付"
,
prop
:
"a60"
,
headerGroup
:
q4Str
},
{
label
:
"补贴收入"
,
prop
:
"a61"
,
headerGroup
:
q4Str
},
{
label
:
"销售回款(含房地产、水泥、新能源售电、其他生产制造收入等)"
,
prop
:
"a62"
,
headerGroup
:
"2026年(四季度)"
,
headerGroup
:
q4Str
,
},
{
label
:
"资产盘活"
,
prop
:
"a63"
,
headerGroup
:
"2026年(四季度)"
},
{
label
:
"股权分红"
,
prop
:
"a64"
,
headerGroup
:
"2026年(四季度)"
},
{
label
:
"其他"
,
prop
:
"a65"
,
headerGroup
:
"2026年(四季度)"
},
{
label
:
"资产盘活"
,
prop
:
"a63"
,
headerGroup
:
q4Str
},
{
label
:
"股权分红"
,
prop
:
"a64"
,
headerGroup
:
q4Str
},
{
label
:
"其他"
,
prop
:
"a65"
,
headerGroup
:
q4Str
},
{
label
:
"目标(决策)与计划差异说明"
,
isTextRow
:
true
,
prop
:
"a66"
,
headerGroup
:
"2026年(四季度)"
,
headerGroup
:
q4Str
,
},
],
// 表格数据(子组件会自动初始化,父组件可传初始值)
tableData
:
[],
];
},
});
// 表格数据(子组件会自动初始化,父组件可传初始值)
tableData
:
[],
};
formData
.
tzhswcqkndgx
=
{
tableData
:
[],
};
formData
.
tzhswcqkydgx
=
{
tableData
:
[],
};
};
const
formData
=
reactive
({
nd
:
new
Date
().
getFullYear
().
toString
(),
// 年度,默认当前年份
jzymljys
:
{},
jzymljsh
:
{},
tzhsjc
:
{},
tzhsjh
:
{},
tzhswcqkndgx
:
{},
tzhswcqkydgx
:
{},
lastyeartzhs
:
null
,
// 去年投资回收计划数据
projectGdxxs
:
[],
});
// 计算属性:动态生成年份相关的标题
const
currentYear
=
computed
(
()
=>
formData
.
nd
||
new
Date
().
getFullYear
().
toString
(),
);
const
lastYear
=
computed
(()
=>
{
const
year
=
parseInt
(
currentYear
.
value
);
return
(
year
-
1
).
toString
();
});
// 动态标题
const
dynamicTitles
=
computed
(()
=>
({
// 投资回收累计完成情况-年度更新
yearlyUpdateTitle
:
`
${
currentYear
.
value
}
年投资回收累计完成情况-年度更新`
,
// 投资回收完成情况-年度更新
yearlyCompletionTitle
:
`
${
currentYear
.
value
}
年投资回收完成情况(年度更新)`
,
// 投资回收完成情况-月度更新
monthlyCompletionTitle
:
`
${
currentYear
.
value
}
年投资回收完成情况(月度更新)`
,
}));
// 折叠面板默认展开项(动态计算)
const
getActiveCollapseItems
=
()
=>
[
"项目基本信息"
,
"出资情况"
,
"合同约定权益获取"
,
"分红情况"
,
"投资额完成情况(万元)"
,
"投资回收(决策)"
,
"投资回收(计划)"
,
dynamicTitles
.
value
.
yearlyUpdateTitle
,
"净现金流"
,
"截止12月末累计应收"
,
"截止12月末累计实收"
,
"资金流出"
,
"分红情况"
,
dynamicTitles
.
value
.
yearlyCompletionTitle
,
dynamicTitles
.
value
.
monthlyCompletionTitle
,
];
const
activeCollapse
=
ref
(
getActiveCollapseItems
());
// 监听年度变化,更新 activeCollapse
watch
(
()
=>
formData
.
nd
,
()
=>
{
activeCollapse
.
value
=
getActiveCollapseItems
();
},
{
immediate
:
false
},
);
let
options
=
ref
();
// ========== 选择项目同步名称(通用) ==========
...
...
@@ -747,10 +961,51 @@ const getRcCgqyglDetail = () => {
data
:
{
id
:
rcCgqyglId
.
value
},
callback
:
(
data
)
=>
{
loading
.
value
=
false
;
console
.
log
(
data
.
jzymljys
.
tableData
[
0
],
"1111"
);
console
.
log
(
data
.
jzymljys
,
"jzymljys详情数据"
);
console
.
log
(
data
.
jzymljsh
,
"jzymljsh详情数据"
);
console
.
log
(
data
.
lastyeartzhs
,
"lastyeartzhs"
);
// 先初始化表格结构(确保 indicatorList 和 dynamicTimeList 存在)
initTableData
();
// 然后合并数据(保留结构配置,只更新 tableData)
if
(
data
.
jzymljys
&&
data
.
jzymljys
.
tableData
)
{
formData
.
jzymljys
.
tableData
=
data
.
jzymljys
.
tableData
;
}
if
(
data
.
jzymljsh
&&
data
.
jzymljsh
.
tableData
)
{
formData
.
jzymljsh
.
tableData
=
data
.
jzymljsh
.
tableData
;
}
if
(
data
.
tzhsjc
&&
data
.
tzhsjc
.
tableData
)
{
formData
.
tzhsjc
.
tableData
=
data
.
tzhsjc
.
tableData
;
}
if
(
data
.
tzhsjh
&&
data
.
tzhsjh
.
tableData
)
{
formData
.
tzhsjh
.
tableData
=
data
.
tzhsjh
.
tableData
;
}
if
(
data
.
tzhswcqkndgx
&&
data
.
tzhswcqkndgx
.
tableData
)
{
formData
.
tzhswcqkndgx
.
tableData
=
data
.
tzhswcqkndgx
.
tableData
;
}
if
(
data
.
tzhswcqkydgx
&&
data
.
tzhswcqkydgx
.
tableData
)
{
formData
.
tzhswcqkydgx
.
tableData
=
data
.
tzhswcqkydgx
.
tableData
;
}
if
(
data
.
lastyeartzhs
)
{
formData
.
lastyeartzhs
=
data
.
lastyeartzhs
;
}
// 合并其他非表格字段
Object
.
assign
(
formData
,
{
...
data
,
nd
:
data
.
nd
||
new
Date
().
getFullYear
().
toString
(),
projectId
:
data
.
projectId
,
sshy
:
data
.
sshy
,
xmgsmc
:
data
.
xmgsmc
,
sbdw
:
data
.
sbdw
,
ssejqy
:
data
.
ssejqy
,
xmjd
:
data
.
xmjd
,
xmlx
:
data
.
xmlx
,
tzms
:
data
.
tzms
,
tzhsfs
:
data
.
tzhsfs
,
xnxmjd
:
data
.
xnxmjd
,
cwbblx
:
data
.
cwbblx
,
projectGdxxs
:
data
.
projectGdxxs
||
[],
});
},
});
...
...
src/views/elseManage/costTab1.vue
View file @
bc1354b0
...
...
@@ -64,15 +64,6 @@
</td>
<!-- 1级指标建议值 -->
<td
class=
"cell-item"
>
<!--
<el-input
type=
"textarea"
rows=
"3"
v-model=
"item.level1Target.value"
:placeholder=
"item.level1Target.placeholder"
size=
"small"
class=
"table-input"
:disabled=
"isPreview"
/>
-->
{{
item
.
level1Target
.
placeholder
}}
</td>
<td
class=
"cell-item"
>
...
...
src/views/investingManage/addControl.vue
View file @
bc1354b0
...
...
@@ -50,6 +50,7 @@
type=
"month"
placeholder=
"请选择"
value-format=
"YYYY-MM"
:disabled-date=
"fyfxkzDisabledDate"
/>
</el-form-item>
</el-col>
...
...
@@ -767,7 +768,7 @@
</el-table-column>
<el-table-column
prop=
"sffsaqzlhbwt"
label=
"是否发生安全质量环保问题被行政处罚"
label=
"是否发生
较大及以上
安全质量环保问题被行政处罚"
>
<
template
#
default=
"scope"
>
<el-radio-group
v-model=
"scope.row.sffsaqzlhbwt"
>
...
...
@@ -790,7 +791,10 @@
</el-table>
</el-col>
<el-col
:span=
"24"
class=
"fileCla"
>
<el-form-item
label=
"文件上传"
>
<el-form-item
label-width=
"320"
label=
"较大及以上安全质量环保问题行政处罚文件上传"
>
<FileUploader
v-model=
"formData.qtjsmbzdpc"
></FileUploader>
...
...
@@ -820,6 +824,78 @@
label=
"财务评价主要边界条件变化对比表"
:label-width=
"230"
></el-form-item>
<el-row
:gutter=
"20"
>
<
template
v-if=
"cwpjIsEdit"
>
<el-col
:span=
"6"
>
<el-form-item
label=
"起始时间"
required
>
<el-date-picker
v-model=
"cwpjFormData.bqsj"
type=
"month"
placeholder=
"请选择"
value-format=
"YYYY-MM"
/>
</el-form-item>
</el-col>
<el-col
:span=
"6"
>
<el-form-item
label=
"截止时间"
required
>
<el-date-picker
v-model=
"cwpjFormData.sqsj"
type=
"month"
placeholder=
"请选择"
value-format=
"YYYY-MM"
:disabled-date=
"cwpjDisabledDate"
/>
</el-form-item>
</el-col>
</
template
>
<el-col
:span=
"6"
:offset=
"cwpjIsEdit ? 6 : 18"
>
<div
class=
"tab-handle"
>
<
template
v-if=
"cwpjIsEdit"
>
<el-button
type=
"default"
size=
"small"
@
click=
"cancelCwpj"
>
取消
</el-button
>
<el-button
type=
"primary"
size=
"small"
@
click=
"saveCwpj"
>
确定
</el-button
>
</
template
>
<
template
v-else
>
<el-select
v-model=
"cwpjSelectRange"
placeholder=
"请选择"
no-data-text=
"暂无数据"
:style=
"
{ width: '200px', marginRight: '20px' }"
@change="changeCwpjRange"
>
<el-option
v-for=
"item in cwpjRangeList"
:key=
"item.key"
:label=
"item.key"
:value=
"item.key"
></el-option>
</el-select>
<el-button
v-if=
"cwpjSelectRange"
type=
"primary"
size=
"small"
@
click=
"editCwpj"
>
编辑
</el-button
>
<el-button
type=
"primary"
size=
"small"
@
click=
"addCwpj"
>
新增
</el-button
>
</
template
>
</div>
</el-col>
</el-row>
<el-table
:data=
"cwpjData"
style=
"width: 100%"
...
...
@@ -831,12 +907,19 @@
<el-table-column
prop=
"bjtj"
label=
"边界条件"
/>
<el-table-column
prop=
"jc"
label=
"决策"
>
<
template
#
default=
"scope"
>
<el-input
v-model=
"scope.row.jc"
/>
<el-input
v-model=
"scope.row.jc"
:disabled=
"!cwpjIsEdit"
/>
</
template
>
</el-table-column>
<el-table-column
prop=
"xz"
label=
"现状"
>
<
template
#
default=
"scope"
>
<el-input
v-model=
"scope.row.xz"
type=
"textarea"
/>
<el-input
v-model=
"scope.row.xz"
type=
"textarea"
:disabled=
"!cwpjIsEdit"
/>
</
template
>
</el-table-column>
<el-table-column
prop=
"zycysm"
label=
"主要差异说明"
>
...
...
@@ -844,6 +927,7 @@
<el-input
v-model=
"scope.row.zycysm"
type=
"textarea"
:disabled=
"!cwpjIsEdit"
/>
</
template
>
</el-table-column>
...
...
@@ -913,6 +997,7 @@ const activeCollapse = reactive([
"投资额控制"
,
"费用分项控制、阶段对比表"
,
"决策条件落实情况"
,
"项目信息"
,
"其他建设目标重大偏差"
,
"投资收益"
,
]);
...
...
@@ -1001,7 +1086,17 @@ const getControlInfo = () => {
Object
.
assign
(
pfyjlsqkData
.
value
,
res
.
tzkzjcpfyjs
);
Object
.
assign
(
gqData
.
value
,
res
.
tzkzgqs
);
Object
.
assign
(
aqzlhbData
.
value
,
res
.
tzkzaqzlhbs
);
Object
.
assign
(
cwpjData
.
value
,
res
.
tzkzcwpjs
);
if
(
res
.
tzkzcwpjs
&&
res
.
tzkzcwpjs
.
length
)
{
cwpjRangeList
.
value
=
res
.
tzkzcwpjs
.
map
((
item
)
=>
{
return
{
...
item
,
bqsj
:
proxy
.
moment
(
item
.
bqsj
).
format
(
"YYYY-MM"
),
sqsj
:
proxy
.
moment
(
item
.
sqsj
).
format
(
"YYYY-MM"
),
};
});
cwpjSelectRange
.
value
=
res
.
tzkzcwpjs
[
0
].
key
;
cwpjData
.
value
=
res
.
tzkzcwpjs
[
0
].
tables
;
}
Object
.
assign
(
tzsyData
.
value
,
res
.
tzkztzsys
);
},
});
...
...
@@ -1021,16 +1116,28 @@ onMounted(() => {
if
(
controlId
)
{
getControlInfo
();
fyfxkzIsEdit
.
value
=
false
;
cwpjIsEdit
.
value
=
false
;
}
else
{
fyfxkzData
.
value
=
JSON
.
parse
(
JSON
.
stringify
(
fyfxkzDefaultData
));
fyfxkzIsEdit
.
value
=
true
;
cwpjData
.
value
=
JSON
.
parse
(
JSON
.
stringify
(
cwpjDefaultData
));
cwpjIsEdit
.
value
=
true
;
}
});
// 费用分项控制:截止时间禁用日期方法
const
fyfxkzDisabledDate
=
(
time
)
=>
{
if
(
!
fyfxkzFormData
.
bqsj
)
return
false
;
const
startTime
=
new
Date
(
fyfxkzFormData
.
bqsj
);
return
time
.
getTime
()
<
startTime
.
getTime
();
};
// 新增费用分项控制、阶段对比表
const
addFyfxkz
=
()
=>
{
selectRange
.
value
=
""
;
fyfxkzIsEdit
.
value
=
true
;
fyfxkzData
.
value
=
JSON
.
parse
(
JSON
.
stringify
(
fyfxkzDefaultData
));
fyfxkzFormData
.
bqsj
=
""
;
fyfxkzFormData
.
sqsj
=
""
;
};
const
editFyfxkz
=
()
=>
{
fyfxkzIsEdit
.
value
=
true
;
...
...
@@ -1042,14 +1149,29 @@ const editFyfxkz = () => {
};
const
saveFyfxkz
=
()
=>
{
if
(
fyfxkzFormData
.
bqsj
&&
fyfxkzFormData
.
sqsj
)
{
// 验证截止时间不能小于起始时间
if
(
fyfxkzFormData
.
sqsj
<
fyfxkzFormData
.
bqsj
)
{
return
ElMessage
.
warning
(
"截止时间不能小于起始时间"
);
}
const
newKey
=
fyfxkzFormData
.
bqsj
+
"至"
+
fyfxkzFormData
.
sqsj
;
// 验证时间范围是否重复(排除当前编辑的记录)
const
isDuplicate
=
rangeList
.
value
.
some
(
(
item
)
=>
item
.
key
===
newKey
&&
item
.
key
!==
selectRange
.
value
);
if
(
isDuplicate
)
{
return
ElMessage
.
warning
(
"该时间范围已存在,请选择其他时间"
);
}
if
(
selectRange
.
value
)
{
rangeList
.
value
=
rangeList
.
value
.
map
((
item
)
=>
{
if
(
item
.
key
===
selectRange
.
value
)
{
selectRange
.
value
=
fyfxkzFormData
.
bqsj
+
"至"
+
fyfxkzFormData
.
sqsj
;
selectRange
.
value
=
newKey
;
return
{
bqsj
:
fyfxkzFormData
.
bqsj
,
sqsj
:
fyfxkzFormData
.
sqsj
,
key
:
fyfxkzFormData
.
bqsj
+
"至"
+
fyfxkzFormData
.
sqsj
,
key
:
newKey
,
tables
:
fyfxkzData
.
value
,
};
}
else
{
...
...
@@ -1062,7 +1184,7 @@ const saveFyfxkz = () => {
rangeList
.
value
.
push
({
bqsj
:
fyfxkzFormData
.
bqsj
,
sqsj
:
fyfxkzFormData
.
sqsj
,
key
:
fyfxkzFormData
.
bqsj
+
"至"
+
fyfxkzFormData
.
sqsj
,
key
:
newKey
,
tables
:
fyfxkzData
.
value
,
});
}
...
...
@@ -1211,8 +1333,16 @@ const downloadFile = (data) => {
a
.
remove
();
};
// 财务评价:截止时间禁用日期方法
const
cwpjDisabledDate
=
(
time
)
=>
{
if
(
!
cwpjFormData
.
bqsj
)
return
false
;
const
startTime
=
new
Date
(
cwpjFormData
.
bqsj
);
return
time
.
getTime
()
<
startTime
.
getTime
();
};
// 财务评价主要边界条件变化对比表
const
cwpjData
=
ref
([
const
cwpjFormData
=
reactive
({});
const
cwpjDefaultData
=
[
{
bjtj
:
"项目总投资(万元)"
,
},
...
...
@@ -1261,7 +1391,96 @@ const cwpjData = ref([
{
bjtj
:
"折旧摊销方式"
,
},
]);
];
let
cwpjData
=
ref
([]);
let
cwpjIsEdit
=
ref
(
false
);
let
cwpjRangeList
=
ref
([]);
const
cwpjSelectRange
=
ref
(
""
);
// 新增财务评价主要边界条件变化对比表
const
addCwpj
=
()
=>
{
cwpjSelectRange
.
value
=
""
;
cwpjIsEdit
.
value
=
true
;
cwpjData
.
value
=
JSON
.
parse
(
JSON
.
stringify
(
cwpjDefaultData
));
};
const
editCwpj
=
()
=>
{
cwpjIsEdit
.
value
=
true
;
let
selectData
=
cwpjRangeList
.
value
.
filter
(
(
item
)
=>
item
.
key
===
cwpjSelectRange
.
value
,
);
cwpjFormData
.
bqsj
=
selectData
[
0
].
bqsj
;
cwpjFormData
.
sqsj
=
selectData
[
0
].
sqsj
;
};
const
saveCwpj
=
()
=>
{
if
(
cwpjFormData
.
bqsj
&&
cwpjFormData
.
sqsj
)
{
// 验证截止时间不能小于起始时间
if
(
cwpjFormData
.
sqsj
<
cwpjFormData
.
bqsj
)
{
return
ElMessage
.
warning
(
"截止时间不能小于起始时间"
);
}
const
newKey
=
cwpjFormData
.
bqsj
+
"至"
+
cwpjFormData
.
sqsj
;
// 验证时间范围是否重复(排除当前编辑的记录)
const
isDuplicate
=
cwpjRangeList
.
value
.
some
(
(
item
)
=>
item
.
key
===
newKey
&&
item
.
key
!==
cwpjSelectRange
.
value
);
if
(
isDuplicate
)
{
return
ElMessage
.
warning
(
"该时间范围已存在,请选择其他时间"
);
}
if
(
cwpjSelectRange
.
value
)
{
cwpjRangeList
.
value
=
cwpjRangeList
.
value
.
map
((
item
)
=>
{
if
(
item
.
key
===
cwpjSelectRange
.
value
)
{
cwpjSelectRange
.
value
=
newKey
;
return
{
bqsj
:
cwpjFormData
.
bqsj
,
sqsj
:
cwpjFormData
.
sqsj
,
key
:
newKey
,
tables
:
cwpjData
.
value
,
};
}
else
{
return
{
...
item
,
};
}
});
}
else
{
cwpjRangeList
.
value
.
push
({
bqsj
:
cwpjFormData
.
bqsj
,
sqsj
:
cwpjFormData
.
sqsj
,
key
:
newKey
,
tables
:
cwpjData
.
value
,
});
}
cwpjIsEdit
.
value
=
false
;
if
(
!
cwpjSelectRange
.
value
)
{
cwpjSelectRange
.
value
=
cwpjRangeList
.
value
[
0
].
key
;
cwpjData
.
value
=
cwpjRangeList
.
value
[
0
].
tables
;
}
else
{
let
selectData
=
cwpjRangeList
.
value
.
filter
(
(
item
)
=>
item
.
key
===
cwpjSelectRange
.
value
,
);
cwpjData
.
value
=
selectData
.
length
?
selectData
[
0
].
tables
:
[];
}
}
else
{
ElMessage
.
warning
(
"请补充本期及上期时间"
);
}
};
const
cancelCwpj
=
()
=>
{
if
(
cwpjSelectRange
.
value
)
{
cwpjData
.
value
=
cwpjRangeList
.
value
[
0
].
tables
;
}
else
if
(
formData
.
id
)
{
cwpjData
.
value
=
[];
}
else
{
cwpjData
.
value
=
JSON
.
parse
(
JSON
.
stringify
(
cwpjDefaultData
));
}
cwpjIsEdit
.
value
=
false
;
};
const
changeCwpjRange
=
(
val
)
=>
{
cwpjData
.
value
=
cwpjRangeList
.
value
.
filter
(
(
item
)
=>
item
.
key
===
val
,
)[
0
].
tables
;
};
// 投资收益指标变化对比表
const
tzsyData
=
ref
([
{
...
...
@@ -1309,6 +1528,11 @@ const saveClick = () => {
if
(
fyfxkzIsEdit
.
value
)
{
return
ElMessage
.
warning
(
"请先保存正在添加的费用分项控制、阶段对比表"
);
}
if
(
cwpjIsEdit
.
value
)
{
return
ElMessage
.
warning
(
"请先保存正在添加的财务评价主要边界条件变化对比表"
,
);
}
let
url
=
formData
.
id
?
"updateTzkz"
:
"createTzkz"
;
let
project
=
projectList
.
value
.
filter
(
(
item
)
=>
item
.
id
===
formData
.
projectId
,
...
...
@@ -1322,7 +1546,7 @@ const saveClick = () => {
tzkzjcpfyjs
:
pfyjlsqkData
.
value
,
tzkzgqs
:
gqData
.
value
,
tzkzaqzlhbs
:
aqzlhbData
.
value
,
tzkzcwpjs
:
cwpj
Data
.
value
,
tzkzcwpjs
:
cwpj
RangeList
.
value
,
tzkztzsys
:
tzsyData
.
value
,
},
callback
:
(
data
)
=>
{
...
...
src/views/investingManage/decision.vue
View file @
bc1354b0
...
...
@@ -4,9 +4,7 @@
<search-form
@
search=
"handleSearch"
/>
<div
class=
"manage-header"
>
<div
class=
"header-left"
></div>
<div
class=
"header-right"
>
<el-button
type=
"primary"
@
click=
"annualAdd"
>
新增
</el-button>
</div>
<div
class=
"header-right"
></div>
</div>
<div
class=
"manage-content"
v-loading=
"loading"
>
<common-table
...
...
@@ -29,22 +27,11 @@
link
type=
"primary"
size=
"small"
@
click=
"previewStatement(row)"
>
查看
</el-button
>
<el-button
link
type=
"primary"
size=
"small"
@
click=
"editStatement(row)"
>
编辑
</el-button
>
<el-button
link
type=
"danger"
size=
"small"
@
click=
"deleteStatement(row)"
>
删除
</el-button
:loading=
"row.loading"
@
click=
"previewProject(row)"
>
{{
canAudit
&&
row
.
projectLzType
==
8
?
"审批"
:
"查看"
}}
</el-button
>
</
template
>
</common-table>
...
...
@@ -54,9 +41,10 @@
</template>
<
script
setup
>
import
{
re
f
,
onMoun
ted
,
getCurrentInstance
}
from
"vue"
;
import
{
re
active
,
ref
,
onMounted
,
compu
ted
,
getCurrentInstance
}
from
"vue"
;
import
{
useRouter
}
from
"vue-router"
;
import
{
ElMessage
,
ElMessageBox
}
from
"element-plus"
;
import
{
useUserStore
}
from
"@/stores/user.js"
;
import
CommonTable
from
"@/components/common/commonTable.vue"
;
import
SearchForm
from
"@/components/common/SearchForm.vue"
;
...
...
@@ -67,6 +55,19 @@ const handleSearch = (formData) => {
};
const
router
=
useRouter
();
const
{
proxy
}
=
getCurrentInstance
();
// 是否是审核角色
const
userStore
=
useUserStore
();
const
userInfo
=
userStore
.
userInfo
||
(
sessionStorage
.
getItem
(
"userInfo"
)
&&
JSON
.
parse
(
sessionStorage
.
getItem
(
"userInfo"
)))
||
{};
let
canAudit
=
ref
(
false
);
userInfo
.
roles
.
map
((
item
)
=>
{
if
([
"xmlx_sp"
,
"xmjc_sp"
].
includes
(
item
.
key
))
{
canAudit
.
value
=
true
;
}
});
let
tableData
=
ref
([]);
let
tableColumns
=
ref
([
...
...
@@ -76,45 +77,41 @@ let tableColumns = ref([
showOverflowTooltip
:
true
,
},
{
prop
:
"projectForeignName"
,
label
:
"项目外文名称"
,
showOverflowTooltip
:
true
,
},
{
prop
:
"sbdw"
,
label
:
"申报单位"
,
showOverflowTooltip
:
true
,
},
{
prop
:
"ssejqy"
,
label
:
"所属二级企业"
,
showOverflowTooltip
:
true
,
},
{
prop
:
"xmgsmc"
,
label
:
"项目公司名称"
,
showOverflowTooltip
:
true
,
},
{
prop
:
"xmkgsjyj"
,
label
:
"项目预计起始时间"
,
prop
:
"projectCode"
,
label
:
"项目编号"
,
showOverflowTooltip
:
true
,
},
{
prop
:
"xmjgsjyj"
,
label
:
"目预计完成时间"
,
showOverflowTooltip
:
true
,
prop
:
"projectLzType"
,
label
:
"状态"
,
width
:
120
,
align
:
"center"
,
formatter
:
(
data
)
=>
{
return
data
.
projectLzType
===
"1"
?
"待立项"
:
data
.
projectLzType
===
"3"
?
"立项审批中"
:
data
.
projectLzType
===
"5"
?
"已立项"
:
data
.
projectLzType
===
"7"
?
"决策填报中"
:
data
.
projectLzType
===
"8"
?
"决策审批中"
:
data
.
projectLzType
===
"9"
?
"已决策"
:
"待立项"
;
},
},
{
prop
:
"operations"
,
label
:
"操作"
,
width
:
1
7
0
,
width
:
1
6
0
,
slot
:
"operations"
,
fixed
:
"right"
,
align
:
"center"
,
},
]);
let
loading
=
ref
(
false
);
let
total
=
ref
(
0
);
let
currentPage
=
ref
(
1
);
...
...
@@ -123,10 +120,12 @@ let pageSize = ref(10);
const
getProjectData
=
(
params
=
{})
=>
{
loading
.
value
=
true
;
proxy
.
$post
({
url
:
"/api/project/
getTzjhLis
t"
,
url
:
"/api/project/
listProjec
t"
,
data
:
{
page
:
currentPage
.
value
,
pagesize
:
pageSize
.
value
,
attributes
:
[],
menuType
:
"xmjc"
,
...
params
,
},
callback
:
(
data
)
=>
{
...
...
@@ -136,6 +135,9 @@ const getProjectData = (params = {}) => {
},
});
};
onMounted
(()
=>
{
getProjectData
();
});
// 分页
const
handleSizeChange
=
(
size
)
=>
{
pageSize
.
value
=
size
;
...
...
@@ -146,49 +148,15 @@ const handleCurrentPageChange = (page) => {
currentPage
.
value
=
page
;
getProjectData
();
};
const
annualAdd
=
()
=>
{
router
.
push
(
"/decisionAdd"
);
};
const
editStatement
=
(
item
)
=>
{
router
.
push
({
name
:
"decisionAdd"
,
query
:
{
id
:
item
.
id
,
},
});
};
const
previewStatement
=
(
item
)
=>
{
const
previewProject
=
(
item
)
=>
{
router
.
push
({
name
:
"
decisionAdd
"
,
name
:
"
addProject
"
,
query
:
{
isPreview
:
true
,
i
d
:
item
.
id
,
projectI
d
:
item
.
id
,
},
});
};
const
deleteStatement
=
(
item
)
=>
{
ElMessageBox
.
confirm
(
"确认删除该项?"
,
"提示"
,
{
confirmButtonText
:
"确认"
,
cancelButtonText
:
"取消"
,
type
:
"warning"
,
})
.
then
(()
=>
{
proxy
.
$post
({
url
:
"/api/project/deleteTzjh"
,
data
:
{
id
:
item
.
id
,
},
callback
:
(
data
)
=>
{
ElMessage
.
success
(
"删除成功"
);
getProjectData
();
},
});
})
.
catch
(()
=>
{});
};
onMounted
(()
=>
{
getProjectData
();
});
</
script
>
<
style
scoped
lang=
"less"
></
style
>
src/views/investingManage/decisionAdd.vue
View file @
bc1354b0
This source diff could not be displayed because it is too large. You can
view the blob
instead.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment