明树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
b5720d31
Commit
b5720d31
authored
Feb 02, 2026
by
zhanghan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
测试名称修改
parent
bc9d6526
Pipeline
#106882
passed with stage
in 19 seconds
Changes
3
Pipelines
1
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
131 additions
and
50 deletions
+131
-50
MainLayout.vue
src/layouts/MainLayout.vue
+22
-16
annualAdd.vue
src/views/everydayPage/annualAdd.vue
+27
-2
annualPlan.vue
src/views/everydayPage/annualPlan.vue
+82
-32
No files found.
src/layouts/MainLayout.vue
View file @
b5720d31
...
@@ -9,7 +9,9 @@
...
@@ -9,7 +9,9 @@
<div
class=
"header-right"
>
<div
class=
"header-right"
>
<div>
<div>
<el-dropdown>
<el-dropdown>
<span
class=
"username"
>
管理员
</span>
<span
class=
"username"
>
{{
userInfo
.
name
}}
</span>
<template
#
dropdown
>
<template
#
dropdown
>
<el-dropdown-menu>
<el-dropdown-menu>
<el-dropdown-item
@
click=
"handleLogout"
<el-dropdown-item
@
click=
"handleLogout"
...
@@ -37,13 +39,17 @@
...
@@ -37,13 +39,17 @@
</template>
</template>
<
script
setup
>
<
script
setup
>
import
{
computed
,
onMounted
,
getCurrentInstance
}
from
"vue"
;
import
{
computed
,
ref
,
onMounted
,
getCurrentInstance
}
from
"vue"
;
import
{
useRouter
,
useRoute
}
from
"vue-router"
;
import
{
useRouter
,
useRoute
}
from
"vue-router"
;
import
{
useUserStore
}
from
"@/stores/user.js"
;
import
{
useUserStore
}
from
"@/stores/user.js"
;
import
LeftMenu
from
"./leftMenu.vue"
;
import
LeftMenu
from
"./leftMenu.vue"
;
const
userStore
=
useUserStore
();
const
userStore
=
useUserStore
();
const
{
proxy
}
=
getCurrentInstance
();
const
{
proxy
}
=
getCurrentInstance
();
let
userInfo
=
ref
(
sessionStorage
.
getItem
(
"userInfo"
)
?
JSON
.
parse
(
sessionStorage
.
getItem
(
"userInfo"
))
:
[],
);
const
router
=
useRouter
();
const
router
=
useRouter
();
// 获取资源库数据
// 获取资源库数据
...
@@ -53,7 +59,7 @@ const getResourceData = () => {
...
@@ -53,7 +59,7 @@ const getResourceData = () => {
data
:
{},
data
:
{},
callback
:
(
data
)
=>
{
callback
:
(
data
)
=>
{
sessionStorage
.
setItem
(
"resourceData"
,
JSON
.
stringify
(
data
));
sessionStorage
.
setItem
(
"resourceData"
,
JSON
.
stringify
(
data
));
}
},
});
});
};
};
onMounted
(()
=>
{
onMounted
(()
=>
{
...
@@ -68,8 +74,8 @@ const handleLogout = () => {
...
@@ -68,8 +74,8 @@ const handleLogout = () => {
callback
:
(
data
)
=>
{
callback
:
(
data
)
=>
{
userStore
.
clearUserInfo
();
userStore
.
clearUserInfo
();
router
.
replace
(
"/login"
);
router
.
replace
(
"/login"
);
}
},
})
})
;
};
};
</
script
>
</
script
>
...
@@ -79,7 +85,7 @@ const handleLogout = () => {
...
@@ -79,7 +85,7 @@ const handleLogout = () => {
overflow: hidden;
overflow: hidden;
display: flex;
display: flex;
flex-direction: column;
flex-direction: column;
.container-main{
.container-main
{
flex: 1;
flex: 1;
height: 0;
height: 0;
}
}
...
...
src/views/everydayPage/annualAdd.vue
View file @
b5720d31
...
@@ -635,7 +635,7 @@
...
@@ -635,7 +635,7 @@
<div
class=
"annualPlans"
>
<div
class=
"annualPlans"
>
<annualPlan
<annualPlan
v-model=
"formData.xmndjh"
v-model=
"formData.xmndjh"
:dynamic-time-list=
"
d
ynamicTimeList"
:dynamic-time-list=
"
annualD
ynamicTimeList"
:is-preview=
"isPreview"
:is-preview=
"isPreview"
@
handleAnnualPlanChange=
"handleAnnualPlanTableChange"
@
handleAnnualPlanChange=
"handleAnnualPlanTableChange"
></annualPlan>
></annualPlan>
...
@@ -785,6 +785,20 @@ import { ElMessage } from "element-plus";
...
@@ -785,6 +785,20 @@ import { ElMessage } from "element-plus";
import
annualPlan
from
"./annualPlan.vue"
;
import
annualPlan
from
"./annualPlan.vue"
;
import
DynamicTable
from
"@/components/FormDynamicTable/index.vue"
;
import
DynamicTable
from
"@/components/FormDynamicTable/index.vue"
;
const
annualDynamicTimeList
=
ref
([
"2025及以前"
,
"2026"
,
"2026-小记"
,
"2026-一季度"
,
"2026-二季度"
,
"2026-三季度"
,
"2026-四季度"
,
"2027"
,
"2028"
,
"2029"
,
"2030"
,
"2031"
,
]);
// ========== 动态表格列配置(参股单位出资修正) ==========
// ========== 动态表格列配置(参股单位出资修正) ==========
const
transferColumns
=
ref
([
const
transferColumns
=
ref
([
{
{
...
@@ -1342,6 +1356,12 @@ const getJsqtzjcDetail = () => {
...
@@ -1342,6 +1356,12 @@ const getJsqtzjcDetail = () => {
Object
.
assign
(
formData
,
data
);
// 回填基础字段
Object
.
assign
(
formData
,
data
);
// 回填基础字段
if
(
data
.
xmndjh
&&
Array
.
isArray
(
data
.
xmndjh
)
&&
data
.
xmndjh
.
length
>
0
)
{
annualDynamicTimeList
.
value
=
Object
.
keys
(
data
.
xmndjh
[
0
]).
filter
(
(
key
)
=>
/^
\d{4}
.*/
.
test
(
key
),
);
}
// 步骤1:提取/生成时间列表(共用表头)
// 步骤1:提取/生成时间列表(共用表头)
if
(
data
.
kyjcxx
&&
Array
.
isArray
(
data
.
kyjcxx
)
&&
data
.
kyjcxx
.
length
>
0
)
{
if
(
data
.
kyjcxx
&&
Array
.
isArray
(
data
.
kyjcxx
)
&&
data
.
kyjcxx
.
length
>
0
)
{
dynamicTimeList
.
value
=
Object
.
keys
(
data
.
kyjcxx
[
0
]).
filter
((
key
)
=>
dynamicTimeList
.
value
=
Object
.
keys
(
data
.
kyjcxx
[
0
]).
filter
((
key
)
=>
...
@@ -1370,6 +1390,9 @@ const getJsqtzjcDetail = () => {
...
@@ -1370,6 +1390,9 @@ const getJsqtzjcDetail = () => {
// ========== 保存表单:两个表格的提交数据完全独立拆分 ==========
// ========== 保存表单:两个表格的提交数据完全独立拆分 ==========
const
saveClick
=
()
=>
{
const
saveClick
=
()
=>
{
console
.
log
(
formData
.
xmndjh
,
"formData.xmndjh"
);
console
.
log
(
annualDynamicTimeList
,
"formData.xmndjh"
);
if
(
!
formData
.
projectId
)
return
ElMessage
.
warning
(
"请选择项目信息"
);
if
(
!
formData
.
projectId
)
return
ElMessage
.
warning
(
"请选择项目信息"
);
loading
.
value
=
true
;
loading
.
value
=
true
;
const
url
=
rcCgqyglId
.
value
const
url
=
rcCgqyglId
.
value
...
@@ -1394,7 +1417,9 @@ const saveClick = () => {
...
@@ -1394,7 +1417,9 @@ const saveClick = () => {
// 2. 项目年度计划表格:专属提交数据(仅自身字段,子组件绑定的xmndjh)
// 2. 项目年度计划表格:专属提交数据(仅自身字段,子组件绑定的xmndjh)
xmndjh
:
formData
.
xmndjh
.
map
((
row
)
=>
{
xmndjh
:
formData
.
xmndjh
.
map
((
row
)
=>
{
const
filterRow
=
{
id
:
row
.
id
,
total
:
row
.
total
};
const
filterRow
=
{
id
:
row
.
id
,
total
:
row
.
total
};
dynamicTimeList
.
value
.
forEach
((
time
)
=>
(
filterRow
[
time
]
=
row
[
time
]));
annualDynamicTimeList
.
value
.
forEach
(
(
time
)
=>
(
filterRow
[
time
]
=
row
[
time
]),
);
return
filterRow
;
return
filterRow
;
}),
}),
};
};
...
...
src/views/everydayPage/annualPlan.vue
View file @
b5720d31
...
@@ -140,27 +140,92 @@
...
@@ -140,27 +140,92 @@
</template>
</template>
<
script
setup
>
<
script
setup
>
import
{
defineProps
,
defineEmits
,
watch
,
onMounted
}
from
"vue"
;
import
{
defineProps
,
computed
,
defineEmits
,
watch
,
onMounted
}
from
"vue"
;
// 🔥 核心:接收父组件参数,v-model双向绑定核心(modelValue对应父组件v-model值)
const
props
=
defineProps
({
const
props
=
defineProps
({
// 双向绑定的表格数据源(父组件formData.xmndjh)
modelValue
:
{
type
:
Array
,
default
:
()
=>
[]
},
modelValue
:
{
dynamicTimeList
:
{
type
:
Array
,
default
:
()
=>
[]
},
type
:
Array
,
isPreview
:
{
type
:
Boolean
,
default
:
false
},
default
:
()
=>
[],
});
},
// ✅ 新增1:处理时间列表 - 去重+非空,避免异常列,兼容所有自定义字符串字段
// 父组件传递的动态时间列表(替代子组件内部定义)
const
validDynamicTimeList
=
computed
(()
=>
{
dynamicTimeList
:
{
return
[...
new
Set
(
props
.
dynamicTimeList
)].
filter
(
type
:
Array
,
(
time
)
=>
!!
time
&&
typeof
time
===
"string"
,
default
:
()
=>
[],
);
});
// ✅ 新增2:核心方法 - 初始化行的时间字段,无值则补0(解决2025及以前无默认值问题)
const
initRowTimeField
=
(
row
)
=>
{
if
(
!
row
)
return
;
validDynamicTimeList
.
value
.
forEach
((
time
)
=>
{
// 字段不存在/非数字,自动补0,确保v-model绑定有效
if
(
row
[
time
]
===
undefined
||
isNaN
(
Number
(
row
[
time
])))
{
row
[
time
]
=
0
;
}
});
};
// ✅ 新增3:核心方法 - 计算行合计(基于处理后的时间列表)
const
calcRowTotal
=
(
row
)
=>
{
if
(
!
row
)
return
0
;
return
validDynamicTimeList
.
value
.
reduce
((
sum
,
time
)
=>
{
return
sum
+
(
Number
(
row
[
time
])
||
0
);
},
0
);
};
// 监听数据源变化 - 优化:新增字段初始化+容错
watch
(
()
=>
props
.
modelValue
,
(
newVal
)
=>
{
if
(
newVal
.
length
===
0
)
return
;
const
newData
=
[...
newVal
];
// 深拷贝避免响应式引用问题
newData
.
forEach
((
row
)
=>
{
if
(
row
)
{
initRowTimeField
(
row
);
// ✅ 新增:初始化字段(补0)
row
.
total
=
calcRowTotal
(
row
);
// 改用统一的合计方法
}
});
emit
(
"update:modelValue"
,
newData
);
// 同步父组件
},
},
// 预览状态(禁用输入)
{
deep
:
true
,
immediate
:
true
},
isPreview
:
{
);
type
:
Boolean
,
default
:
false
,
// ✅ 新增4:监听时间列表变化 - 新增/修改2025及以前这类字段时,自动初始化所有行
watch
(
()
=>
validDynamicTimeList
.
value
,
()
=>
{
if
(
props
.
modelValue
.
length
===
0
)
return
;
const
newData
=
[...
props
.
modelValue
];
newData
.
forEach
((
row
)
=>
{
initRowTimeField
(
row
);
row
.
total
=
calcRowTotal
(
row
);
});
emit
(
"update:modelValue"
,
newData
);
emit
(
"handleAnnualPlanChange"
,
newData
);
},
},
{
deep
:
true
,
immediate
:
true
},
);
// 获取对应行的合计值 - 优化:增加数字校验,避免报错
const
getRowTotal
=
(
index
)
=>
{
const
row
=
props
.
modelValue
[
index
-
1
];
if
(
!
row
||
isNaN
(
Number
(
row
.
total
)))
return
"0.00"
;
return
Number
(
row
.
total
).
toFixed
(
2
);
};
onMounted
(()
=>
{
console
.
log
(
"兼容后的时间列表:"
,
validDynamicTimeList
.
value
);
});
});
// ✅ 修复5:handleChange - 输入后同步父组件,左侧合计实时刷新(核心!)
const
handleChange
=
(
row
)
=>
{
if
(
props
.
isPreview
||
!
row
)
return
;
row
.
total
=
calcRowTotal
(
row
);
// 计算合计
const
newData
=
[...
props
.
modelValue
];
// 深拷贝
// 触发双向绑定+原有事件,保证兼容
emit
(
"update:modelValue"
,
newData
);
emit
(
"handleAnnualPlanChange"
,
newData
);
};
// 🔥 核心:触发双向绑定更新+原有事件兼容
// 🔥 核心:触发双向绑定更新+原有事件兼容
const
emit
=
defineEmits
([
const
emit
=
defineEmits
([
"update:modelValue"
,
// v-model必须的更新事件,同步数据给父组件
"update:modelValue"
,
// v-model必须的更新事件,同步数据给父组件
...
@@ -187,22 +252,6 @@ watch(
...
@@ -187,22 +252,6 @@ watch(
);
);
// 获取对应行的合计值(父组件数据源,保留2位小数)
// 获取对应行的合计值(父组件数据源,保留2位小数)
const
getRowTotal
=
(
index
)
=>
{
const
row
=
props
.
modelValue
[
index
-
1
];
return
row
?.
total
?
row
.
total
.
toFixed
(
2
)
:
"0.00"
;
};
onMounted
(()
=>
{
console
.
log
(
props
.
dynamicTimeList
,
" props.dynamicTimeList"
);
});
// 右侧数据变更:计算行合计 + 双向同步父组件 + 触发原有事件
const
handleChange
=
(
row
)
=>
{
// 计算当前行合计(适配父组件动态时间列表)
row
.
total
=
props
.
dynamicTimeList
.
reduce
((
sum
,
time
)
=>
{
return
sum
+
(
Number
(
row
[
time
])
||
0
);
},
0
);
};
// 合计行样式(和父组件表格样式统一)
// 合计行样式(和父组件表格样式统一)
const
tableCellStyle
=
({
row
})
=>
const
tableCellStyle
=
({
row
})
=>
...
@@ -226,6 +275,7 @@ const tableCellStyle = ({ row }) =>
...
@@ -226,6 +275,7 @@ const tableCellStyle = ({ row }) =>
.left-table
{
.left-table
{
flex-shrink
:
0
;
flex-shrink
:
0
;
}
}
// 左侧原生表格样式(160px列宽 + 48px行高 + 无缝边框)
// 左侧原生表格样式(160px列宽 + 48px行高 + 无缝边框)
.investment-table
{
.investment-table
{
width
:
fit-content
;
width
:
fit-content
;
...
...
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