/*-----------弹窗模块管理------------------- */
<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>
<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 getEvaluateLevel"
: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
size="mini"
:data="formTabledata"
@selection-change="handleSelectionChange"
:row-key="getRowkey"
height="100%">
<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
@current-change="handleCurrentChange"
:current-page="pageParams.pageNo"
: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: {
projectCode: '', // 项目编号
projectName: '', // 项目名称
projectStartDate: '', // 开始日期
projectEndDate: '', // 结束日期
projectUser: '', // 项目负责人
remark: '', // 备注
sideSlopeDetailList: [] // 边坡详情列表
},
projectDate: [], // 项目日期范围
total: 0, // 总数据量
loading: false, // 加载状态
pageParams: { // 分页参数
pageNo: 1,
pageSize: 10,
},
filterForm: { // 搜索条件
maintenanceCompanyName: "",
routeCode: "",
searchKey: "",
evaluateLevel: "",
},
mulitipleSelection: [],
allSelection: new Map(),
MaintenanceUnitoptions: [], // 管养单位选项
routeCodeOptions: [], // 路线编号选项
formTabledata: [], // 表格数据
rules: { // 表单验证规则
projectName: [
{ required: true, message: "项目名称不能为空", trigger: "blur" },
],
projectCode: [
{ required: true, message: "项目编码不能为空", trigger: "blur" },
],
},
};
},
watch: {
//监听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();
}
},
//监听模式变化
mode(val) {
this.dialogMode = val;
// 当模式从创建变为编辑/查看时,确保加载数据
if (this.dialogVisible && val !== 'create' && this.currentForm.id) {
this.LoadListData();
}
},
//监听初始表单数据变化
initialForm: {
deep: true,
immediate: true,
async handler(val) {
// 新增空值检查
if (!val) {
this.projectDate = [];
return;
}
this.currentForm = { ...val };
//周期赋值
this.projectDate = [];
val.projectStartDate && val.projectEndDate &&
(this.projectDate = [val.projectStartDate, val.projectEndDate]);
// 关键修复:添加空值校验
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();
this.getMaintenanceCompanyList();
},
computed:{
getEvaluateLevel() {
const levelList = mapCfg("Inspection.Regular.RegularEvaluateLevel")();
return levelList.map((item) => ({
value: item.key,
label: item.value,
}))
},
},
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.pageParams.pageNo = 1;
this.LoadListData();
},
// 重置搜索条件
resetSearch() {
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.getEvaluateLevel.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;
}
},
// 当前页码变化
handleCurrentChange(val) {
this.pageParams.pageNo = val;
this.LoadListData();
},
// 提交表单
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;
padding-top: 25px; // 新增
&::before {
content: "待检边坡";
position: absolute;
top: 5px; // 调整到新增的padding区域内部
left: 15px;
background-color: #fff;
padding: 0 8px;
font-size: 13px;
color: #606266;
z-index: 1000;
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>怎么调整dialog的高度