明树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
a172f9f8
Commit
a172f9f8
authored
Feb 05, 2026
by
zhanghan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
运营期投资回收
parent
0f4cf72a
Pipeline
#107008
passed with stage
in 19 seconds
Changes
4
Pipelines
1
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
547 additions
and
205 deletions
+547
-205
FinancialTable.vue
src/components/FinancialTable.vue
+313
-0
investmentCecovery.vue
src/views/castbehind/investmentCecovery.vue
+8
-20
investmentCecoveryAdd.vue
src/views/castbehind/investmentCecoveryAdd.vue
+220
-185
annualAdd.vue
src/views/everydayPage/annualAdd.vue
+6
-0
No files found.
src/components/FinancialTable.vue
0 → 100644
View file @
a172f9f8
<
template
>
<div
class=
"mixed-table-wrap"
>
<!-- 调试用:可删除 -->
<!--
{{
tableDataRef
}}
tableData -->
<el-table
:data=
"tableDataRef"
style=
"width: 100%"
border
:cell-style=
"tableCellStyle"
row-key=
"serialNumber"
v-if=
"validConfig"
>
<!-- 序号列:保留原逻辑 -->
<el-table-column
prop=
"serialNumber"
label=
"序号"
width=
"80"
align=
"center"
/>
<!-- 指标项列(层级缩进):保留原逻辑 -->
<el-table-column
prop=
"indicatorName"
label=
"名称"
align=
"left"
width=
"260"
>
<template
#
default=
"
{ row }">
<div
style=
"text-align: left"
>
{{
row
.
indicatorName
}}
</div>
</
template
>
</el-table-column>
<!-- 合计列:文本行隐藏合计值,不显示0.00 → 从内部数据取值 -->
<el-table-column
label=
"合计"
width=
"140"
align=
"right"
>
<
template
#
default=
"{ row }"
>
<span
v-if=
"!row.noTotal"
>
{{
row
.
total
?
Number
(
row
.
total
).
toFixed
(
2
)
:
"0.00"
}}
万元
</span>
<span
v-else
>
</span>
</
template
>
</el-table-column>
<!-- 动态时间列:改用【处理后的有效时间列表】,保留原条件渲染逻辑 -->
<el-table-column
v-for=
"time in validDynamicTimeList"
:key=
"`time-col-${time}`"
:label=
"time"
width=
"140"
align=
"center"
>
<
template
#
default=
"{ row }"
>
<!-- 1. 文本行:多行文本输入框,支持字符串 → 绑定内部数据 -->
<el-input
v-if=
"row.isTextRow"
v-model=
"row[time]"
type=
"textarea"
:rows=
"2"
:disabled=
"isPreview"
placeholder=
"请输入说明"
style=
"width: 100%"
@
input=
"() => handleTextInput(row)"
/>
<!-- 2. 数字行:金额输入框(0+、2位小数)→ 绑定内部数据 -->
<el-input-number
v-else
v-model=
"row[time]"
:min=
"0"
: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)
</div>
</div>
</template>
<
script
setup
>
import
{
ref
,
computed
,
watch
,
nextTick
,
defineProps
,
defineEmits
}
from
"vue"
;
// 1. 重构Props/Emit:对齐参考组件,改用defineProps+defineEmits,隔离v-model循环
// 替代原defineModel,避免对象式v-model的循环更新问题,和参考组件统一
const
props
=
defineProps
({
// 核心配置对象:包含indicatorList/dynamicTimeList/tableData
modelValue
:
{
type
:
Object
,
default
:
()
=>
({
indicatorList
:
[],
dynamicTimeList
:
[],
tableData
:
[]
}),
validator
:
(
val
)
=>
val
&&
Array
.
isArray
(
val
.
indicatorList
)
&&
Array
.
isArray
(
val
.
dynamicTimeList
),
},
// 预览模式:保留原配置
isPreview
:
{
type
:
Boolean
,
default
:
false
,
},
});
// 定义发射事件:双向绑定+业务事件,和参考组件一致
const
emit
=
defineEmits
([
"update:modelValue"
,
// v-model双向绑定更新
"handleTableChange"
,
// 自定义业务变化事件(可让父组件监听)
]);
// 2. 核心:创建组件内部响应式数据,完全隔离外部Props → 参考组件核心设计
// 所有数据操作先改内部,再统一发射,避免直接修改Props导致的循环更新
const
tableDataRef
=
ref
([]);
// 3. 处理动态时间列表:对齐参考组件,做【去重/去空/trim/兜底】→ 关键健壮性改造
// 解决原组件直接用props中可能的无效时间列(空值/空格/重复)问题
const
validDynamicTimeList
=
computed
(()
=>
{
const
rawTimeList
=
props
.
modelValue
.
dynamicTimeList
||
[];
if
(
!
Array
.
isArray
(
rawTimeList
)
||
rawTimeList
.
length
===
0
)
{
// 兜底默认值:保证表格至少有列渲染,不会空白
return
[
"2025"
,
"2026"
,
"2027"
];
}
return
[...
new
Set
(
rawTimeList
)]
.
map
((
time
)
=>
(
typeof
time
===
"string"
?
time
.
trim
()
:
""
))
// 去除隐形空白
.
filter
((
time
)
=>
!!
time
);
// 过滤空值
});
// 4. 配置合法性校验:基于【处理后的有效时间列表】重构,更严谨
const
validConfig
=
computed
(()
=>
{
const
{
indicatorList
}
=
props
.
modelValue
;
return
(
Array
.
isArray
(
indicatorList
)
&&
indicatorList
.
length
>
0
&&
validDynamicTimeList
.
value
.
length
>
0
);
});
// 5. 工具方法:初始化行的时间字段 → 对齐参考组件initRowTimeField
// 针对【文本行/数字行】做差异化初始化,避免类型混乱
const
initRowTimeField
=
(
row
)
=>
{
if
(
!
row
||
typeof
row
!==
"object"
)
return
;
validDynamicTimeList
.
value
.
forEach
((
time
)
=>
{
if
(
row
.
isTextRow
)
{
// 文本行:无值则置空字符串,保留原有字符串
row
[
time
]
=
row
[
time
]
===
undefined
||
row
[
time
]
===
null
?
""
:
String
(
row
[
time
]);
}
else
{
// 数字行:无值/非数字则置0,确保数字类型
row
[
time
]
=
row
[
time
]
===
undefined
||
row
[
time
]
===
null
||
isNaN
(
Number
(
row
[
time
]))
?
0
:
Number
(
row
[
time
]);
}
});
};
// 6. 工具方法:计算单行合计 → 对齐参考组件calcRowTotal
// 仅数字行生效,自动过滤文本行/非数字,解决浮点精度问题
const
calculateRowTotal
=
(
row
)
=>
{
if
(
!
row
||
typeof
row
!==
"object"
||
row
.
noTotal
||
row
.
isTextRow
)
return
0
;
const
total
=
validDynamicTimeList
.
value
.
reduce
((
sum
,
time
)
=>
{
return
sum
+
(
Number
(
row
[
time
])
||
0
);
},
0
);
return
Number
(
total
.
toFixed
(
2
));
// 保留2位小数,避免0.1+0.2=0.30000000000000004
};
// 7. 核心工具方法:深拷贝+数据处理 → 对齐参考组件handleTableData
// 强制保留所有原有字段,仅【初始化时间字段/计算合计】,避免字段丢失
const
handleTableData
=
(
sourceIndicatorList
,
sourceTableData
)
=>
{
if
(
!
validConfig
.
value
)
return
[];
const
newData
=
[];
sourceIndicatorList
.
forEach
((
item
,
index
)
=>
{
const
{
name
,
isTextRow
=
false
,
noTotal
=
false
}
=
item
;
// 深拷贝源数据行:保留所有原有字段(serialNumber/level/indicatorName等)
const
originRow
=
sourceTableData
.
find
((
row
)
=>
row
.
indicatorName
===
name
)
||
{};
const
rowData
=
JSON
.
parse
(
JSON
.
stringify
({
serialNumber
:
index
+
1
,
level
:
0
,
indicatorName
:
name
,
isTextRow
,
noTotal
,
total
:
0
,
...
originRow
,
// 源数据行覆盖默认值,保留原有配置
}),
);
// 初始化时间字段:差异化处理文本/数字行
initRowTimeField
(
rowData
);
// 计算合计:仅数字行/需要合计的行生效
rowData
.
total
=
calculateRowTotal
(
rowData
);
newData
.
push
(
rowData
);
});
return
newData
;
};
// 8. 工具方法:数据变化后统一发射 → 对齐参考组件emitDataChange
// 深拷贝后发射,保留所有字段,避免父组件修改影响内部数据,统一发射逻辑
const
emitDataChange
=
(
newInnerData
)
=>
{
if
(
props
.
isPreview
)
return
;
// 预览模式不发射
// 深拷贝内部数据,避免引用传递
const
emitData
=
JSON
.
parse
(
JSON
.
stringify
(
newInnerData
));
// 构造父组件需要的完整配置对象,保持原数据结构
const
newModelValue
=
{
...
props
.
modelValue
,
tableData
:
emitData
,
};
// 统一发射:双向绑定更新 + 业务事件
emit
(
"update:modelValue"
,
newModelValue
);
emit
(
"handleTableChange"
,
newModelValue
);
};
// 9. 监听Props变化:同步到内部数据 → 对齐参考组件的watch逻辑
// 仅同步,不发射;nextTick确保有效时间列表先处理完成
watch
(
()
=>
props
.
modelValue
,
async
(
newVal
)
=>
{
if
(
!
validConfig
.
value
)
return
;
await
nextTick
();
// 等待有效时间列表计算完成
const
newTableData
=
handleTableData
(
newVal
.
indicatorList
,
newVal
.
tableData
,
);
tableDataRef
.
value
=
newTableData
;
// 只更新内部数据,不直接修改Props
},
{
deep
:
true
,
immediate
:
true
},
// 深度监听+立即执行,组件挂载即初始化
);
// 监听有效时间列表变化:更新内部数据后统一发射 → 对齐参考组件
watch
(
()
=>
validDynamicTimeList
.
value
,
()
=>
{
if
(
!
validConfig
.
value
||
tableDataRef
.
value
.
length
===
0
)
return
;
// 重新初始化时间字段+计算合计
tableDataRef
.
value
.
forEach
((
row
)
=>
{
initRowTimeField
(
row
);
row
.
total
=
calculateRowTotal
(
row
);
});
emitDataChange
(
tableDataRef
.
value
);
},
{
deep
:
true
,
immediate
:
true
},
);
// 10. 数字行输入回调 → 重构,仅更新内部数据,再统一发射
const
handleFinancialChange
=
(
currentRow
)
=>
{
if
(
props
.
isPreview
||
!
currentRow
||
currentRow
.
noTotal
)
return
;
currentRow
.
total
=
calculateRowTotal
(
currentRow
);
// 仅更新内部数据的合计
emitDataChange
(
tableDataRef
.
value
);
// 统一发射所有数据
};
// 11. 文本行输入回调 → 重构,同步内部数据后统一发射(可扩展)
const
handleTextInput
=
(
currentRow
)
=>
{
if
(
props
.
isPreview
||
!
currentRow
)
return
;
emitDataChange
(
tableDataRef
.
value
);
// 文本输入仅同步,统一发射
};
// 12. 表格单元格样式 → 保留原逻辑,微调健壮性
const
tableCellStyle
=
({
row
})
=>
{
// 合计行高亮
if
(
row
?.
isTotal
)
{
return
{
background
:
"#f5f7fa"
,
fontWeight
:
"bold"
,
textAlign
:
"right"
};
}
// 所有行右对齐,文本行输入框单独左对齐(样式层处理)
return
{
textAlign
:
"right"
};
};
</
script
>
<
style
scoped
lang=
"scss"
>
// 外层容器:适配滚动,和参考组件样式统一
.mixed-table-wrap
{
width
:
100%
;
box-sizing
:
border-box
;
overflow-x
:
auto
;
}
// 数字输入框样式:对齐参考组件,填满单元格
:deep
(
.el-input-number
)
{
width
:
100%
;
}
:deep
(
.el-input-number__input
)
{
text-align
:
right
;
padding-right
:
25px
;
width
:
100%
!
important
;
}
// 文本输入框样式:适配表格,和数字框高度对齐,保留原逻辑
:deep
(
.el-input__textarea
)
{
resize
:
none
;
// 禁止手动拉伸
text-align
:
left
!
important
;
// 文本左对齐,符合阅读习惯
min-height
:
40px
!
important
;
// 固定最小高度,和数字框对齐
}
// 表格列头样式:统一对齐,保留原逻辑
:deep
(
.el-table__header-cell
)
{
text-align
:
right
!
important
;
&
.el-table__header-cell--align-center
{
text-align
:
center
!
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/views/castbehind/investmentCecovery.vue
View file @
a172f9f8
...
...
@@ -66,40 +66,28 @@ const { proxy } = getCurrentInstance();
let
tableData
=
ref
([]);
let
tableColumns
=
ref
([
{
prop
:
"
qc
"
,
label
:
"项目
全
称"
,
prop
:
"
projectName
"
,
label
:
"项目
名
称"
,
showOverflowTooltip
:
true
,
},
{
prop
:
"
j
c"
,
label
:
"项目
简
称"
,
prop
:
"
xmgsm
c"
,
label
:
"项目
公司名
称"
,
showOverflowTooltip
:
true
,
},
{
prop
:
"
nbtzglzt
"
,
label
:
"
内部投资管理主体
"
,
prop
:
"
ssejqy
"
,
label
:
"
所属二级企业
"
,
showOverflowTooltip
:
true
,
width
:
170
,
},
{
prop
:
"xm
scjd
"
,
label
:
"项目
所处阶段
"
,
prop
:
"xm
gsmc
"
,
label
:
"项目
公司名称
"
,
showOverflowTooltip
:
true
,
width
:
120
,
},
{
prop
:
"gqjg"
,
label
:
"股权结构"
,
showOverflowTooltip
:
true
,
width
:
120
,
},
{
prop
:
"xmzbjze"
,
label
:
"项目资本金总额(亿元)"
,
showOverflowTooltip
:
true
,
width
:
180
,
},
{
prop
:
"operations"
,
...
...
src/views/castbehind/investmentCecoveryAdd.vue
View file @
a172f9f8
...
...
@@ -15,10 +15,8 @@
<div
class=
"tab-content"
>
<el-form
:model=
"formData"
:label-width=
"200"
:disabled=
"isPreview"
>
<el-collapse
v-model=
"activeCollapse"
>
<el-collapse-item
title=
"测试列表"
name=
"测试列表"
>
</el-collapse-item>
<el-collapse-item
title=
"项目基本信息"
name=
"项目基本信息"
>
<el-row
:gutter=
"2
0
"
>
<el-row
:gutter=
"2
4
"
>
<el-col
:span=
"12"
>
<el-form-item
label=
"项目名称"
required
>
<el-select
...
...
@@ -124,7 +122,7 @@
<DynamicTable
:columns=
"transferColumns"
:disabled=
"isPreview"
v-model=
"formData.
cgdwczqkxz
"
v-model=
"formData.
projectGdxxs
"
>
</DynamicTable>
</el-collapse-item>
...
...
@@ -318,6 +316,44 @@
</el-col>
</el-row>
</el-collapse-item>
<el-collapse-item
title=
"截止12月末累计应收"
name=
"截止12月末累计应收"
>
<FinancialTable
v-model=
"formData.jzymljys"
:is-preview=
"isPreview"
/>
</el-collapse-item>
<el-collapse-item
title=
"截止12月末累计实收"
name=
"截止12月末累计实收"
>
<FinancialTable
v-model=
"formData.jzymljsh"
:is-preview=
"isPreview"
/>
</el-collapse-item>
<el-collapse-item
title=
"投资回收(决策)"
name=
"投资回收(决策)"
>
<FinancialTable
v-model=
"formData.tzhsjc"
:is-preview=
"isPreview"
/>
</el-collapse-item>
<el-collapse-item
title=
"投资回收(计划)"
name=
"投资回收(计划)"
>
<FinancialTable
v-model=
"formData.tzhsjh"
:is-preview=
"isPreview"
/>
</el-collapse-item>
</el-collapse>
</el-form>
</div>
...
...
@@ -330,83 +366,57 @@
<
script
setup
>
import
{
reactive
,
ref
,
onMounted
,
getCurrentInstance
,
h
,
computed
}
from
"vue"
;
import
{
useRouter
,
useRoute
}
from
"vue-router"
;
import
{
ElMessage
,
ElMessageBox
}
from
"element-plus"
;
import
{
useUserStore
}
from
"@/stores/user.js"
;
import
{
number
}
from
"echarts"
;
import
{
ElMessage
}
from
"element-plus"
;
import
DynamicTable
from
"@/components/FormDynamicTable/index.vue"
;
import
FinancialTable
from
"@/components/FinancialTable.vue"
;
const
transferColumns
=
ref
([
{
prop
:
"
mc
"
,
prop
:
"
njfcgbl
"
,
label
:
"能建方持股比例"
,
type
:
"
textarea
"
,
type
:
"
input
"
,
headerGroup
:
"能建内容"
,
placeholder
:
"请填写能建方持股比例"
,
},
{
prop
:
"
mc
"
,
prop
:
"
njfcgblqk
"
,
label
:
"能建方持股比例情况"
,
type
:
"
textarea
"
,
type
:
"
input
"
,
headerGroup
:
"能建内容"
,
placeholder
:
"请填写能建方持股比例情况"
,
},
{
prop
:
"
mc
"
,
prop
:
"
njfcgblqk_nt
"
,
label
:
"能建方持股比例情况"
,
type
:
"
textarea
"
,
type
:
"
input
"
,
headerGroup
:
"能建以外"
,
placeholder
:
"请填写能建方持股比例情况"
,
},
{
prop
:
"
mc
"
,
prop
:
"
zwfcgbl
"
,
label
:
"政府方持股比例"
,
type
:
"
textarea
"
,
type
:
"
input
"
,
headerGroup
:
"能建以外"
,
placeholder
:
"请填写政府方持股比例"
,
},
{
prop
:
"
fj
"
,
prop
:
"
jjcgbl
"
,
label
:
"基金持股比例"
,
type
:
"
textarea
"
,
type
:
"
input
"
,
headerGroup
:
"能建以外"
,
placeholder
:
"请输入基金持股比例"
,
min
:
0
,
},
{
prop
:
"
bz
"
,
prop
:
"
njfglmc
"
,
label
:
"能建方关联名称"
,
headerGroup
:
"能建以外"
,
type
:
"textarea"
,
placeholder
:
"请输入能建方关联名称"
,
},
]);
// 初始化全局变量
const
userStore
=
useUserStore
();
const
router
=
useRouter
();
const
route
=
useRoute
();
const
{
proxy
}
=
getCurrentInstance
();
const
token
=
ref
(
userStore
.
authToken
||
sessionStorage
.
getItem
(
"authToken"
)
||
""
,
);
// 小记金额
const
subtotalNum
=
computed
(()
=>
{
let
totalHtje
=
tzfhs
.
value
.
reduce
((
sum
,
item
)
=>
{
const
num
=
Number
(
item
.
fhje
)
||
0
;
// 兼容空值/非数字
return
sum
+
num
;
},
0
);
let
totalYwlr
=
wtyys
.
value
.
reduce
((
sum
,
item
)
=>
{
const
num
=
Number
(
item
.
ywlr
)
||
0
;
// 兼容空值/非数字
return
sum
+
num
;
},
0
);
return
(
totalHtje
+
totalYwlr
).
toFixed
(
2
);
});
// 折叠面板默认展开项
const
activeCollapse
=
ref
([
...
...
@@ -415,116 +425,167 @@ 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
:
true
,
noTotal
:
true
},
],
// 时间列表(月度)
dynamicTimeList
:
[
"一月"
,
"二月"
,
"三月"
,
"四月"
,
"五月"
,
"六月"
,
"七月"
,
"八月"
,
"九月"
,
"十月"
,
"十一月"
,
"十二月"
,
],
// 表格数据(子组件会自动初始化,父组件可传初始值)
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
:
true
,
noTotal
:
true
},
],
// 时间列表(月度)
dynamicTimeList
:
[
"一月"
,
"二月"
,
"三月"
,
"四月"
,
"五月"
,
"六月"
,
"七月"
,
"八月"
,
"九月"
,
"十月"
,
"十一月"
,
"十二月"
,
],
// 表格数据(子组件会自动初始化,父组件可传初始值)
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
,
},
{
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
:
"建设期政府付费"
,
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
:
[],
},
});
};
const
formData
=
reactive
({
projectName
:
""
,
qc
:
""
,
jc
:
""
,
nbtzglzt
:
""
,
xmscjd
:
""
,
gqjg
:
""
,
xmzbjze
:
""
,
gszbjyczze
:
""
,
gsdqycze
:
""
,
gsdqyjcze
:
""
,
gsdqycwcje
:
""
,
gsdqsycze
:
""
,
cgbczqk
:
""
,
wfqyhttkyd
:
""
,
qyhqjz
:
""
,
qyhqyyd
:
""
,
dbqk
:
""
,
lrfp
:
""
,
sfddlrfptj
:
""
,
ljhqfh
:
""
,
ytrzj
:
""
,
ljtrzj
:
""
,
sxtrzj
:
""
,
jt
:
""
,
zx
:
""
,
lxr
:
""
,
lxfs
:
""
,
bz
:
""
,
projectId
:
""
,
del
:
0
,
// del字段保留0默认值(删除标记,0为正常)
createdAt
:
""
,
updatedAt
:
""
,
jzymljys
:
{},
jzymljsh
:
{},
tzhsjc
:
{},
tzhsjh
:
{},
projectGdxxs
:
[],
});
let
options
=
ref
();
function
sumWtyysColumns
(
param
)
{
const
{
columns
,
data
}
=
param
;
const
sums
=
[];
columns
.
forEach
((
column
,
index
)
=>
{
if
(
index
===
0
)
{
sums
[
index
]
=
h
(
"div"
,
"合计"
);
return
;
}
const
prop
=
column
.
property
;
if
(
prop
===
"lx"
||
prop
===
"fwsj"
||
!
prop
)
{
sums
[
index
]
=
""
;
return
;
}
if
(
prop
===
"htje"
)
{
const
values
=
data
.
map
((
item
)
=>
Number
(
item
.
htje
)
||
0
);
const
total
=
values
.
reduce
((
prev
,
curr
)
=>
prev
+
curr
,
0
);
sums
[
index
]
=
total
.
toFixed
(
2
)
+
"(万元)"
;
return
;
}
if
(
prop
===
"ywlr"
)
{
const
values
=
data
.
map
((
item
)
=>
Number
(
item
.
ywlr
)
||
0
);
const
total
=
values
.
reduce
((
prev
,
curr
)
=>
prev
+
curr
,
0
);
sums
[
index
]
=
total
.
toFixed
(
2
)
+
"(万元)"
;
return
;
}
sums
[
index
]
=
""
;
});
return
sums
;
}
function
sumTzfhsColumns
(
param
)
{
const
{
columns
,
data
}
=
param
;
const
sums
=
[];
columns
.
forEach
((
column
,
index
)
=>
{
if
(
index
===
0
)
{
sums
[
index
]
=
h
(
"div"
,
"合计"
);
return
;
}
const
prop
=
column
.
property
;
if
(
prop
===
"fhsj"
||
!
prop
)
{
sums
[
index
]
=
""
;
return
;
}
// 分红金额合计
if
(
prop
===
"fhje"
)
{
const
values
=
data
.
map
((
item
)
=>
Number
(
item
.
fhje
)
||
0
);
const
total
=
values
.
reduce
((
prev
,
curr
)
=>
prev
+
curr
,
0
);
sums
[
index
]
=
total
.
toFixed
(
2
)
+
"(万元)"
;
return
;
}
sums
[
index
]
=
""
;
});
return
sums
;
}
// ========== 选择项目同步名称(通用) ==========
const
changeProject
=
(
val
)
=>
{
proxy
.
$post
({
...
...
@@ -532,7 +593,16 @@ const changeProject = (val) => {
data
:
{
id
:
val
},
callback
:
(
data
)
=>
{
loading
.
value
=
false
;
Object
.
assign
(
formData
,
data
);
// Object.assign(formData, data);
loading
.
value
=
false
;
formData
.
projectName
=
data
.
projectName
||
""
;
formData
.
sbdw
=
data
.
sbdw
||
""
;
formData
.
xmgsmc
=
data
.
xmgsmc
||
""
;
formData
.
xmkgsjyj
=
data
.
xmkgsjyj
||
""
;
formData
.
xmjgsjyj
=
data
.
xmjgsjyj
||
""
;
formData
.
xmjd
=
data
.
xmjd
||
""
;
formData
.
yynxn
=
data
.
yynxn
||
""
;
formData
.
xmjsqy
=
data
.
xmjsqy
||
""
;
},
error
:
()
=>
{
loading
.
value
=
false
;
...
...
@@ -551,36 +621,6 @@ const projectList = ref([]);
// 当前编辑的记录ID
const
rcCgqyglId
=
ref
(
route
.
query
.
id
||
""
);
let
wtyys
=
ref
([]);
const
addPfyjlsqk
=
()
=>
{
wtyys
.
value
.
push
({});
};
const
deletePfyjlsqk
=
(
index
)
=>
{
ElMessageBox
.
confirm
(
"确认删除该项?"
,
"提示"
,
{
confirmButtonText
:
"确认"
,
cancelButtonText
:
"取消"
,
type
:
"warning"
,
}).
then
(()
=>
{
wtyys
.
value
.
splice
(
index
,
1
);
});
};
let
tzfhs
=
ref
([]);
// 新增
const
addTzfhs
=
()
=>
{
tzfhs
.
value
.
push
({});
};
// 删除
const
deleteTzfhs
=
(
index
)
=>
{
ElMessageBox
.
confirm
(
"确认删除该项?"
,
"提示"
,
{
confirmButtonText
:
"确认"
,
cancelButtonText
:
"取消"
,
type
:
"warning"
,
}).
then
(()
=>
{
tzfhs
.
value
.
splice
(
index
,
1
);
});
};
// 获取项目列表
const
getProjectData
=
()
=>
{
proxy
.
$post
({
...
...
@@ -603,20 +643,15 @@ const getRcCgqyglDetail = () => {
loading
.
value
=
true
;
proxy
.
$post
({
url
:
"/api/project/get
Cgqygl
"
,
url
:
"/api/project/get
YyqtzhsInfo
"
,
data
:
{
id
:
rcCgqyglId
.
value
},
callback
:
(
data
)
=>
{
loading
.
value
=
false
;
console
.
log
(
data
.
jzymljys
.
tableData
[
0
],
"1111"
);
Object
.
assign
(
formData
,
{
...
data
,
});
if
(
data
.
wtyys
)
{
Object
.
assign
(
wtyys
.
value
,
data
.
wtyys
);
}
// 新增:加载
if
(
data
.
tzfhs
)
{
Object
.
assign
(
tzfhs
.
value
,
data
.
tzfhs
);
}
},
});
};
...
...
@@ -636,15 +671,13 @@ const saveClick = () => {
loading
.
value
=
true
;
// 区分新增/编辑
const
url
=
rcCgqyglId
.
value
?
"/api/project/update
Cgqygl
"
:
"/api/project/create
Cgqygl
"
;
?
"/api/project/update
Yyqtzhs
"
:
"/api/project/create
Yyqtzhs
"
;
// 处理空数字字段:空值转为null,避免提交空字符串
const
submitData
=
{
...
formData
,
projectId
:
formData
.
projectId
+
""
,
wtyys
:
wtyys
.
value
,
tzfhs
:
tzfhs
.
value
,
};
proxy
.
$post
({
...
...
@@ -666,6 +699,8 @@ onMounted(() => {
// 如果有ID则加载详情
if
(
rcCgqyglId
.
value
)
{
getRcCgqyglDetail
();
}
else
{
initTableData
();
}
});
</
script
>
...
...
src/views/everydayPage/annualAdd.vue
View file @
a172f9f8
...
...
@@ -790,6 +790,12 @@
name=
"项目年度计划表格(单位:万元)"
>
<div
class=
"annualPlans"
>
{{ formData.xmndjh }}formData.xmndjh
{{ formData.xmndjh }}formData.xmndjh
{{
formData.annualDynamicTimeList
}}formData.annualDynamicTimeList
<annualPlan
v-model=
"formData.xmndjh"
:dynamic-time-list=
"annualDynamicTimeList"
...
...
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