<template>
<el-dialog :title="dialogMode === 'create' ? '新建' : dialogMode === 'edit' ? '修改' : '查看'" :visible.sync="dialogVisible"
:modal-append-to-body="true" append-to-body :close-on-click-modal="false" custom-class="fixed-height-dialog"
width="60%" top="5vh">
<el-form label-width="80px" ref="formRef" :model="currentForm"
style="height: 100%; display: flex; flex-direction: column;" :rules="rules">
<!-- 项目信息区域 -->
<div class="formBorder">
<el-row :gutter="10">
<el-col :span="6">
<el-form-item size="mini" label="项目名称" prop="projectName">
<el-input v-model="currentForm.projectName" clearable style="width:100%" size="mini"
:disabled="dialogMode === 'view'"></el-input>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item size="mini" label="项目编号" prop="projectCode">
<el-input v-model="currentForm.projectCode" clearable style="width:100%" size="mini"
:disabled="dialogMode === 'view'"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item size="mini" label="项目周期" prop="projectDate">
<el-date-picker v-model="projectDate" range-separator="→" start-placeholder="请选择开始日期"
end-placeholder="请选择结束日期" type="daterange" size="mini" style="width: 100%;" unlink-panels
:disabled="dialogMode === 'view'">
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="6">
<el-form-item label="负责人" size="mini" style="width: fit-content;">
<el-input v-model="currentForm.projectUser" clearable style="width:100%" size="mini"
:disabled="dialogMode === 'view'"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="项目概述">
<el-input v-model="currentForm.remark" :rows="2" :disabled="dialogMode === 'view'"></el-input>
</el-form-item>
</el-col>
</el-row>
</div>
<!-- 待检边坡区域 - 使用纯CSS控制高度 -->
<div class="formBorder2">
<el-container style="height: 100%;">
<el-header style="height: auto; flex-shrink: 0; padding-bottom: 10px;">
<el-row :gutter="10" type="flex" class="searchDialog">
<el-col :span="5">
<el-select v-model="filterForm.maintenanceCompanyName" placeholder="请选择管养单位" size="mini" clearable
filterable @clear="resetSearch" :disabled="dialogMode === 'view'">
<el-option v-for="item in MaintenanceUnitoptions" :key="item.value" :label="item.label"
:value="item.value"></el-option>
</el-select>
</el-col>
<el-col :span="5">
<el-select v-model="filterForm.routeCode" placeholder="请选择路线编号" size="mini" clearable filterable
@clear="resetSearch" :disabled="dialogMode === 'view'">
<el-option v-for="item in routeCodeOptions" :key="item.value" :label="item.label"
:value="item.value"></el-option>
</el-select>
</el-col>
<el-col :span="5">
<el-input v-model="filterForm.searchKey" placeholder="请输入边坡编号或名称" size="mini" clearable
@keyup.enter.native="searchForm" @clear="resetSearch" :disabled="dialogMode === 'view'">
<i slot="suffix" class="el-input__icon el-icon-search"></i>
</el-input>
</el-col>
<el-col :span="5">
<el-select v-model="filterForm.evaluateLevel" placeholder="请选择技术状态等级" size="mini" clearable
@clear="resetSearch" :disabled="dialogMode === 'view'">
<el-option v-for="item in evaluateLeveloptions" :key="item.value" :label="item.label"
:value="item.value" />
</el-select>
</el-col>
<el-col :span="2" :offset="4">
<el-button type="primary" size="mini" style="width:100%" icon="el-icon-search" @click="searchForm"
:loading="loading" :disabled="dialogMode === 'view'">搜索</el-button>
</el-col>
</el-row>
</el-header>
<!-- 边坡表格 - 移除动态高度绑定 -->
<el-main style="overflow-y: hidden;">
<el-table ref="scrollTable" v-loading="loading" style="width: 100%;" border :data="formTabledata"
:row-style="{ height: '36px' }" :cell-style="{ padding: '4px 0', textAlign: 'center' }"
:header-cell-style="{
height: '36px',
padding: '4px 0',
lineHeight: '36px',
textAlign: 'center'
}" @selection-change="handleSelectionChange" :row-key="getRowkey">
<!-- 选择列(查看模式禁用) -->
<el-table-column type="selection" width="55" :selectable="isRowSelectable" :reserve-selection="true">
</el-table-column>
<!-- 其他数据列 -->
<el-table-column label="管养单位" prop="maintenanceCompanyName" width="290"
show-overflow-tooltip></el-table-column>
<el-table-column label="路线编号" prop="routeCode" width="100"></el-table-column>
<el-table-column label="边坡编号" prop="sideSlopeCode" width="240" show-overflow-tooltip></el-table-column>
<el-table-column label="边坡名称" prop="sideSlopeName" width="267" show-overflow-tooltip></el-table-column>
<el-table-column label="技术状态等级" width="137">
<template slot-scope="scope">
{{ mapEvaluateLevel(scope.row.evaluateLevel) }}
</template>
</el-table-column>
</el-table>
</el-main>
<!-- 分页区域 -->
<el-footer style="flex-shrink: 0; padding-top: 10px;">
<el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange"
:current-page="pageParams.pageNo" :page-sizes="[10, 20, 50, 100]" :page-size="pageParams.pageSize"
layout="total, prev, pager, next" :total="total">
</el-pagination>
</el-footer>
</el-container>
</div>
</el-form>
<!-- 弹窗底部按钮 -->
<div slot="footer" class="dialog-footer" v-if="dialogMode === 'create' || dialogMode === 'edit'">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitForm">提交</el-button>
</div>
</el-dialog>
</template>
<script>
import { mapCfg } from "@/utils";
import {
getPeriodicInspectionSideSlopePageList,
addPeriodicInspection,
modifyPeriodicInspection,
getSelectedPeriodicInspectionSideSlopeList
} from "../../api/testProject";
import { getMaintenanceCompanyList, getRouteList } from "../../api/basicInformation";
export default {
name: "SideSlopeDialog",
props: {
visible: Boolean, // 控制弹窗显示
mode: String, // 模式:create/edit/view
initialForm: Object, // 初始表单数据
},
data() {
return {
isInitializingSelection: false, // 初始化状态标志
dialogVisible: this.visible, // 弹窗显示状态
dialogMode: this.mode, // 当前模式
currentForm: { ...this.initialForm }, // 当前表单数据
projectDate: [], // 项目日期范围
total: 0, // 总数据量
loading: false, // 加载状态
pageParams: { // 分页参数
pageNo: 1,
pageSize: 10,
},
filterForm: { // 搜索条件
maintenanceCompanyName: "",
routeCode: "",
searchKey: "",
evaluateLevel: "",
},
mulitipleSelection: [],
allSelection: new Map(),
MaintenanceUnitoptions: [], // 管养单位选项
routeCodeOptions: [], // 路线编号选项
formTabledata: [], // 表格数据
evaluateLeveloptions: [], // 技术状态等级选项
rules: { // 表单验证规则
projectName: [
{ required: true, message: "项目名称不能为空", trigger: "blur" },
],
projectCode: [
{ required: true, message: "项目编码不能为空", trigger: "blur" },
],
},
};
},
watch: {
// 修复1:监听visible变化时确保加载数据
async visible(val) {
this.dialogVisible = val;
if (val) {
// 打开对话框时重置状态
this.resetAllData();
// 关键修复:确保在创建模式外加载数据
if (this.dialogMode !== 'create' && this.currentForm.id) {
// 确保在DOM更新后加载数据
await this.$nextTick();
await this.LoadListData();
}
} else {
// 关闭对话框时重置数据
this.resetAllData();
}
},
// 修复2:监听模式变化
mode(val) {
this.dialogMode = val;
// 当模式从创建变为编辑/查看时,确保加载数据
if (this.dialogVisible && val !== 'create' && this.currentForm.id) {
this.LoadListData();
}
},
// 修复3:监听初始表单数据变化
initialForm: {
deep: true,
immediate: true, // 添加立即执行
async handler(val) {
this.currentForm = { ...val };
this.projectDate = [val.projectStartDate, val.projectEndDate];
// 关键修复:当初始表单有ID时立即加载数据
if (this.dialogVisible && val.id && this.dialogMode !== 'create') {
await this.$nextTick();
await this.LoadListData();
}
}
},
// 同步弹窗显示状态到父组件
dialogVisible(val) {
this.$emit("update:visible", val);
},
projectDate: {
deep: true,
handler(value) {
if (value && value.length === 2) {
this.currentForm.projectStartDate = value[0];
this.currentForm.projectEndDate = value[1];
}
},
},
},
async created() {
// 初始化数据
this.getRouteList();
await this.getEvaluateLevel();
this.getMaintenanceCompanyList();
},
methods: {
handleSelectionChange(selection) {
// 跳过初始化阶段的选中状态变更
if (this.isInitializingSelection) return;
// 获取当前页选中项的key集合
const currentPageKeys = new Set(
selection.map(row => row.sideSlopeUniqueCode)
);
// 处理当前页的取消选中操作
this.formTabledata.forEach(row => {
const key = row.sideSlopeUniqueCode;
// 仅当行在全局选中池中但不在当前页选中集合时删除
if (this.allSelection.has(key) && !currentPageKeys.has(key)) {
this.allSelection.delete(key);
}
});
// 添加新选中的项到全局池
selection.forEach(row => {
const key = row.sideSlopeUniqueCode;
if (!this.allSelection.has(key)) {
this.allSelection.set(key, row);
}
});
// 更新当前页选中引用
this.mulitipleSelection = selection;
},
getRowkey(row) {
return row.sideSlopeUniqueCode;
},
// 判断行是否可选(查看模式禁用选择)
isRowSelectable(row, index) {
return this.dialogMode !== "view";
},
// 获取管养单位列表
async getMaintenanceCompanyList() {
const res = await getMaintenanceCompanyList();
this.MaintenanceUnitoptions = res.map((item) => ({
value: item,
label: item,
}));
},
// 获取路线列表
async getRouteList() {
const res = await getRouteList();
this.routeCodeOptions = res.map((item) => ({
value: item.id,
label: item.routeCode,
}));
},
// 搜索方法
searchForm() {
// this.showSelectedOnly = false,
this.pageParams.pageNo = 1;
this.LoadListData();
},
// 重置搜索条件
resetSearch() {
// this.showSelectedOnly = true,
this.filterForm = {
maintenanceCompanyName: "",
routeCode: "",
searchKey: "",
evaluateLevel: "",
};
this.pageParams.pageNo = 1;
this.LoadListData();
},
// 重置组件状态
resetAllData() {
this.resetSelection();
this.formTabledata = []; // 清空表格数据
this.total = 0; // 重置总条数
this.pageParams = { // 重置分页
pageNo: 1,
pageSize: 10
};
// 重置搜索条件(可选)
this.filterForm = {
maintenanceCompanyName: "",
routeCode: "",
searchKey: "",
evaluateLevel: ""
};
},
// 修改原有方法
resetSelection() {
this.allSelection.clear();
this.allSelection = new Map();
if (this.$refs.scrollTable) {
this.$refs.scrollTable.clearSelection();
}
},
// 映射技术状态等级
mapEvaluateLevel(level) {
const option = this.evaluateLeveloptions.find(
(item) => item.value === level
);
return option.label;
},
// 加载表格数据
async LoadListData() {
this.loading = true;
try {
const params = {
orgId: this.filterForm.maintenanceCompanyName,
routeId: this.filterForm.routeCode,
searchKey: this.filterForm.searchKey,
evaluateLevel: this.filterForm.evaluateLevel,
pageSize: this.pageParams.pageSize,
pageNo: this.pageParams.pageNo,
};
// 获取表格数据
const res = await getPeriodicInspectionSideSlopePageList(params);
this.formTabledata = res.entities;
this.total = res.entityCount;
// 处理非创建模式的数据加载
if (this.dialogMode !== 'create' && this.currentForm.id) {
// 首次加载时获取所有选中项
if (this.pageParams.pageNo === 1) {
const selected = await getSelectedPeriodicInspectionSideSlopeList({
periodicId: this.currentForm.id,
pageSize: 10000, // 获取所有选中项
pageNo: 1
});
// 重置全局选中池
this.allSelection.clear();
this.mulitipleSelection = selected.entities;
// 存储全局选中状态
this.mulitipleSelection.forEach(item => {
this.allSelection.set(item.sideSlopeUniqueCode, item);
});
}
// 设置当前页选中状态
this.isInitializingSelection = true;
this.$nextTick(() => {
this.formTabledata.forEach(row => {
if (this.allSelection.has(row.sideSlopeUniqueCode)) {
this.$refs.scrollTable.toggleRowSelection(row, true);
}
});
this.isInitializingSelection = false;
});
}
} catch (error) {
console.error("加载数据失败:", error);
this.$message.error("加载数据失败");
} finally {
this.loading = false;
}
},
// 分页大小变化
handleSizeChange(val) {
this.pageParams.pageSize = val;
this.pageParams.pageNo = 1;
this.LoadListData();
},
// 当前页码变化
handleCurrentChange(val) {
this.pageParams.pageNo = val;
this.LoadListData();
},
// 获取技术状态等级选项
async getEvaluateLevel() {
const levelList = await mapCfg("Inspection.Regular.RegularEvaluateLevel")();
this.evaluateLeveloptions = levelList.map((item) => ({
value: item.key,
label: item.value,
}));
},
// 提交表单
async submitForm() {
this.$refs.formRef.validate(async (valid) => {
if (valid) {
// 验证是否选择了边坡
const selectedItems = Array.from(this.allSelection.values());
if (this.allSelection.size === 0) {
this.$message.warning("请至少选择一个边坡");
return;
}
// 构造提交参数
const params = {
...this.currentForm,
sideSlopeDetailList: selectedItems.map(item => ({
sideSlopeUniqueCode: item.sideSlopeUniqueCode,
evaluateLevel: item.evaluateLevel,
evaluateDate: item.evaluateDate || undefined
})),
};
// 根据模式选择操作
const action = this.dialogMode === "create"
? addPeriodicInspection
: modifyPeriodicInspection;
// 执行操作
try {
const success = await action(params);
if (success) {
this.$message.success(
this.dialogMode === "create" ? "新建成功" : "修改成功"
);
this.$refs.scrollTable.clearSelection();
this.$emit("success");
this.dialogVisible = false;
} else {
this.$message.error("操作失败");
}
} catch (error) {
this.$message.error(error.message || "操作失败");
}
}
});
}
},
};
</script>
<style lang="scss" scoped>
/* 修复1:弹性容器最小高度约束 */
:deep(.fixed-height-dialog),
.formBorder2,
.formBorder2 .el-container,
.formBorder2 .el-main {
min-height: 0 !important;
}
/* 表格行高优化 */
:deep(.el-table) {
.el-table__row {
height: 36px !important;
td {
padding: 4px 0 !important;
}
}
.el-table__header {
th {
padding: 4px 0 !important;
.cell {
line-height: 28px !important;
}
}
}
/* 确保内部滚动 */
.el-table__body-wrapper {
overflow-y: auto !important;
max-height: calc(100vh - 400px) !important;
}
}
/* 表单区域固定 */
.formBorder {
position: relative; ///为伪元素提供定位上下文
border: thin dotted black !important;
padding: 10px !important;
margin-top: 15px !important;
flex-shrink: 0 !important;
height: auto !important;
overflow: visible !important;
margin-bottom: 15px !important;
/* 边框的文字 */
&::before {
content: "项目信息";
position: absolute;
top: -8px; //调整到更合适的位置
left: 15px; //向右移动避免遮挡
background-color: #fff; //背景色需与页面背景一致
padding: 0 8px;
font-size: 13px;
color: #606266;
z-index: 10; //提高层级确保显示
font-weight: 500; //加粗文字
pointer-events: none; //防止点击穿透
}
}
.formBorder2 {
position: relative;
border: thin dotted black;
padding: 10px;
flex: 1;
min-height: 0;
overflow: hidden; // 保留
display: flex;
flex-direction: column;
margin-top: 15px;
&::before {
content: "待检边坡";
position: absolute;
top: -8px; //调整到更合适的位置
left: 15px; //向右移动避免遮挡
background-color: #fff; //背景色需与页面背景一致
padding: 0 8px;
font-size: 13px;
color: #606266;
z-index: 10; //提高层级确保显示
font-weight: 500; //加粗文字
pointer-events: none; //防止点击穿透
}
.el-container {
height: auto !important; // 覆盖行内样式
flex: 1; // 填满剩余空间
display: flex;
flex-direction: column;
min-height: 0;
.el-header {
flex-shrink: 0;
height: auto !important;
padding-bottom: 10px;
}
.el-main {
flex: 1;
overflow: hidden;
position: relative;
padding: 0;
}
.el-footer {
flex-shrink: 0;
padding-top: 10px;
}
}
}
// 弹窗底部按钮区域
.dialog-footer {
padding: 10px 20px;
border-top: 1px solid #ebeef5;
text-align: center;
}
// 搜索区域样式
.searchDialog {
margin-top: 5px;
}
// 空数据样式
:deep(.el-table__empty-block) {
min-height: 200px;
display: flex;
justify-content: center;
align-items: center;
}
// 分页样式
:deep(.el-pagination) {
padding: 5px 0;
}
// 表格高度控制
:deep(.el-table) {
height: 100% !important;
.el-table__body-wrapper {
overflow-y: auto !important;
}
}
</style>为什么待检边坡有一半被margin-top遮住了
最新发布