明树Git Lab

Commit b5720d31 authored by zhanghan's avatar zhanghan

测试名称修改

parent bc9d6526
Pipeline #106882 passed with stage
in 19 seconds
......@@ -9,7 +9,9 @@
<div class="header-right">
<div>
<el-dropdown>
<span class="username">管理员</span>
<span class="username">
{{ userInfo.name }}
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="handleLogout"
......@@ -37,23 +39,27 @@
</template>
<script setup>
import { computed, onMounted, getCurrentInstance } from "vue";
import { computed, ref, onMounted, getCurrentInstance } from "vue";
import { useRouter, useRoute } from "vue-router";
import { useUserStore } from "@/stores/user.js";
import LeftMenu from "./leftMenu.vue";
const userStore = useUserStore();
const { proxy } = getCurrentInstance();
let userInfo = ref(
sessionStorage.getItem("userInfo")
? JSON.parse(sessionStorage.getItem("userInfo"))
: [],
);
const router = useRouter();
// 获取资源库数据
const getResourceData = () => {
proxy.$post({
url: "/api/resource/listResourceAll",
data: {},
callback: (data) => {
sessionStorage.setItem("resourceData", JSON.stringify(data));
}
url: "/api/resource/listResourceAll",
data: {},
callback: (data) => {
sessionStorage.setItem("resourceData", JSON.stringify(data));
},
});
};
onMounted(() => {
......@@ -63,13 +69,13 @@ onMounted(() => {
const handleLogout = () => {
// 清除登录状态
proxy.$post({
url: "/api/user/logout",
data: {},
callback: (data) => {
userStore.clearUserInfo();
router.replace("/login");
}
})
url: "/api/user/logout",
data: {},
callback: (data) => {
userStore.clearUserInfo();
router.replace("/login");
},
});
};
</script>
......@@ -79,7 +85,7 @@ const handleLogout = () => {
overflow: hidden;
display: flex;
flex-direction: column;
.container-main{
.container-main {
flex: 1;
height: 0;
}
......
......@@ -635,7 +635,7 @@
<div class="annualPlans">
<annualPlan
v-model="formData.xmndjh"
:dynamic-time-list="dynamicTimeList"
:dynamic-time-list="annualDynamicTimeList"
:is-preview="isPreview"
@handleAnnualPlanChange="handleAnnualPlanTableChange"
></annualPlan>
......@@ -785,6 +785,20 @@ import { ElMessage } from "element-plus";
import annualPlan from "./annualPlan.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([
{
......@@ -1342,6 +1356,12 @@ const getJsqtzjcDetail = () => {
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:提取/生成时间列表(共用表头)
if (data.kyjcxx && Array.isArray(data.kyjcxx) && data.kyjcxx.length > 0) {
dynamicTimeList.value = Object.keys(data.kyjcxx[0]).filter((key) =>
......@@ -1370,6 +1390,9 @@ const getJsqtzjcDetail = () => {
// ========== 保存表单:两个表格的提交数据完全独立拆分 ==========
const saveClick = () => {
console.log(formData.xmndjh, "formData.xmndjh");
console.log(annualDynamicTimeList, "formData.xmndjh");
if (!formData.projectId) return ElMessage.warning("请选择项目信息");
loading.value = true;
const url = rcCgqyglId.value
......@@ -1394,7 +1417,9 @@ const saveClick = () => {
// 2. 项目年度计划表格:专属提交数据(仅自身字段,子组件绑定的xmndjh)
xmndjh: formData.xmndjh.map((row) => {
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;
}),
};
......
......@@ -140,27 +140,92 @@
</template>
<script setup>
import { defineProps, defineEmits, watch, onMounted } from "vue";
// 🔥 核心:接收父组件参数,v-model双向绑定核心(modelValue对应父组件v-model值)
import { defineProps, computed, defineEmits, watch, onMounted } from "vue";
const props = defineProps({
// 双向绑定的表格数据源(父组件formData.xmndjh)
modelValue: {
type: Array,
default: () => [],
},
// 父组件传递的动态时间列表(替代子组件内部定义)
dynamicTimeList: {
type: Array,
default: () => [],
modelValue: { type: Array, default: () => [] },
dynamicTimeList: { type: Array, default: () => [] },
isPreview: { type: Boolean, default: false },
});
// ✅ 新增1:处理时间列表 - 去重+非空,避免异常列,兼容所有自定义字符串字段
const validDynamicTimeList = computed(() => {
return [...new Set(props.dynamicTimeList)].filter(
(time) => !!time && typeof time === "string",
);
});
// ✅ 新增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); // 同步父组件
},
// 预览状态(禁用输入)
isPreview: {
type: Boolean,
default: false,
{ deep: true, immediate: true },
);
// ✅ 新增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([
"update:modelValue", // v-model必须的更新事件,同步数据给父组件
......@@ -187,22 +252,6 @@ watch(
);
// 获取对应行的合计值(父组件数据源,保留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 }) =>
......@@ -226,6 +275,7 @@ const tableCellStyle = ({ row }) =>
.left-table {
flex-shrink: 0;
}
// 左侧原生表格样式(160px列宽 + 48px行高 + 无缝边框)
.investment-table {
width: fit-content;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment