提交宿舍区去除的业务修改

This commit is contained in:
zlwu committed 2025-09-04 12:29:51 +08:00
1 parent 99b771bb51
commit 2a38245ae2
24 files changed
+1139 -557

No files matched your search

@@ -1,7 +1,7 @@
<template>
<el-dialog :title="dialogTitle" v-model="dialogVisible" width="1200px" append-to-body @close="handleClose">
<el-form ref="dormHygieneCheckFormRef" :model="form" :rules="rules" label-width="120px">
<!-- 第一行:检查标题、校区名称、宿舍区名称 -->
<!-- 第一行:检查标题、校区名称、宿舍楼名称 -->
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="检查标题" prop="checkTitle">
@@ -23,26 +23,6 @@
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="宿舍区名称" prop="areaId">
<el-select
v-model="form.areaId"
placeholder="请选择宿舍区"
clearable
filterable
:loading="dormLoading"
@change="handleAreaChange"
style="width: 100%"
:disabled="!form.campusId"
>
<el-option v-for="area in areaOptions" :key="area.id" :label="area.areaName" :value="area.id" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<!-- 第二行:宿舍楼名称、房间名称、宿舍总分 -->
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="宿舍楼名称" prop="buildingId">
<el-select
@@ -53,12 +33,16 @@
:loading="dormLoading"
@change="handleBuildingChange"
style="width: 100%"
:disabled="!form.areaId"
:disabled="!form.campusId"
>
<el-option v-for="building in buildingOptions" :key="building.id" :label="building.buildingName" :value="building.id" />
<el-option v-for="building in buildingOptions" :key="building.id" :label="getBuildingDisplayName(building)" :value="building.id" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<!-- 第二行:房间名称、宿舍扣分、卫生等级 -->
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="房间名称" prop="roomId">
<el-select
@@ -76,10 +60,10 @@
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="宿舍总分" prop="totalScore">
<el-form-item label="宿舍扣分" prop="totalScore">
<el-input
v-model="form.totalScore"
placeholder="请输入宿舍总分(0-100分)"
placeholder="请输入宿舍扣分(默认0分)"
type="number"
:min="0"
:max="100"
@@ -88,10 +72,6 @@
/>
</el-form-item>
</el-col>
</el-row>
<!-- 第三行:卫生等级、检查类型、检查级别 -->
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="卫生等级" prop="hygieneGrade">
<el-select v-model="form.hygieneGrade" placeholder="请选择卫生等级" style="width: 100%" @change="handleHygieneGradeChange">
@@ -99,6 +79,10 @@
</el-select>
</el-form-item>
</el-col>
</el-row>
<!-- 第三行:检查类型、检查级别、检查员姓名 -->
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="检查类型" prop="checkType">
<el-select v-model="form.checkType" placeholder="请选择检查类型" style="width: 100%">
@@ -113,10 +97,6 @@
</el-select>
</el-form-item>
</el-col>
</el-row>
<!-- 第四行:检查员姓名、检查日期 -->
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="检查员姓名" prop="checkerName">
<el-select
@@ -140,6 +120,10 @@
</el-select>
</el-form-item>
</el-col>
</el-row>
<!-- 第四行:检查日期 -->
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="检查日期" prop="checkDate">
<el-date-picker
@@ -167,12 +151,12 @@
<div class="room-students-container">
<div class="room-students-table-wrapper">
<el-table :data="roomStudents" stripe size="small" table-layout="auto">
<!-- 学生个人得分 -->
<el-table-column label="个人得分" width="120" fixed="left">
<!-- 学生个人扣分 -->
<el-table-column label="个人扣分" width="120" fixed="left">
<template #default="scope">
<el-input
v-model="scope.row.student_score"
placeholder="0-100分"
placeholder="默认0分"
size="small"
type="number"
:min="0"
@@ -415,14 +399,10 @@ interface CampusOptionVO {
campusName: string;
}
interface AreaOptionVO {
id: string | number;
areaName: string;
}
interface BuildingOptionVO {
id: string | number;
buildingName: string;
buildingType?: string; // 宿舍楼类型(1男生楼 2女生楼 3混合楼)
}
interface RoomOptionVO {
@@ -457,7 +437,6 @@ const dormHygieneCheckFormRef = ref();
// 宿舍级联选择器相关状态
const campusOptions = ref<CampusOptionVO[]>([]);
const areaOptions = ref<AreaOptionVO[]>([]);
const buildingOptions = ref<BuildingOptionVO[]>([]);
const roomOptions = ref<RoomOptionVO[]>([]);
const dormLoading = ref(false);
@@ -517,11 +496,9 @@ const initFormData: DormHygieneCheckForm = {
roomName: undefined,
buildingId: undefined,
buildingName: undefined,
areaId: undefined,
areaName: undefined,
campusId: undefined,
campusName: undefined,
totalScore: undefined,
totalScore: 0,
hygieneGrade: 'A', // 默认 A - 优秀
attachmentIds: undefined,
checkSummary: undefined,
@@ -722,8 +699,7 @@ const resetForm = () => {
attachmentList.value = [];
roomStudents.value = [];
// 清空宿舍级联选项
areaOptions.value = [];
// 清空宿舍级联选项 - 移除宿舍区相关
buildingOptions.value = [];
roomOptions.value = [];
@@ -812,15 +788,12 @@ const loadCampusOptions = async () => {
/** 校区选择变化处理 */
const handleCampusChange = async (campusId: string | number) => {
console.log('校区选择变化处理', campusId);
// 清空下级选项
form.areaId = undefined;
form.areaName = undefined;
// 清空下级选项 - 移除宿舍区相关字段
form.buildingId = undefined;
form.buildingName = undefined;
form.roomId = undefined;
form.roomName = undefined;
areaOptions.value = [];
buildingOptions.value = [];
roomOptions.value = [];
@@ -832,77 +805,22 @@ const handleCampusChange = async (campusId: string | number) => {
form.campusName = selectedCampus.campusName;
}
// 加载宿舍区选项
await loadAreaOptions(campusId);
// 直接加载宿舍楼选项(根据校区过滤)
await loadBuildingOptions(campusId);
} else {
form.campusId = undefined;
form.campusName = undefined;
}
};
/** 加载宿舍区选项 */
const loadAreaOptions = async (campusId: string | number) => {
try {
const cacheKey = `area_${campusId}`;
const cachedData = getCachedData(cacheKey);
if (cachedData) {
areaOptions.value = cachedData;
return;
}
dormLoading.value = true;
const res = await request({
url: '/ssqxx/dormArea/list',
method: 'get',
params: { campusId }
});
const data = res.rows || [];
areaOptions.value = data;
setCachedData(cacheKey, data);
} catch (error) {
console.error('加载宿舍区选项失败:', error);
areaOptions.value = [];
} finally {
dormLoading.value = false;
}
};
/** 宿舍区选择变化处理 */
const handleAreaChange = async (areaId: string | number) => {
// 清空下级选项
form.buildingId = undefined;
form.buildingName = undefined;
form.roomId = undefined;
form.roomName = undefined;
buildingOptions.value = [];
roomOptions.value = [];
if (areaId) {
// 设置宿舍区名称
const selectedArea = areaOptions.value.find((area) => area.id === areaId);
if (selectedArea) {
form.areaId = areaId;
form.areaName = selectedArea.areaName;
}
// 加载宿舍楼选项
await loadBuildingOptions(areaId);
} else {
form.areaId = undefined;
form.areaName = undefined;
}
};
/** 加载宿舍楼选项 */
const loadBuildingOptions = async (areaId: string | number) => {
/** 加载宿舍楼选项 - 修改为直接根据校区ID过滤 */
const loadBuildingOptions = async (campusId: string | number) => {
try {
dormLoading.value = true;
const res = await request({
url: '/sslxx/dormBuilding/list',
method: 'get',
params: { areaId }
params: { campusId } // 直接使用校区ID过滤,不再使用areaId
});
buildingOptions.value = res.rows || [];
} catch (error) {
@@ -1075,18 +993,13 @@ const loadCascadeOptionsForUpdate = async (formData: DormHygieneCheckForm) => {
// 并行加载所有需要的宿舍选项,提升性能
const loadTasks = [];
// 如果有校区ID,加载宿舍区选项
// 如果有校区ID,加载宿舍楼选项
if (formData.campusId) {
loadTasks.push(loadAreaOptions(formData.campusId));
loadTasks.push(loadBuildingOptions(formData.campusId));
// 如果有宿舍区ID,加载宿舍楼选项
if (formData.areaId) {
loadTasks.push(loadBuildingOptions(formData.areaId));
// 如果有宿舍楼ID,加载房间选项
if (formData.buildingId) {
loadTasks.push(loadRoomOptions(formData.buildingId));
}
// 如果有宿舍楼ID,加载房间选项
if (formData.buildingId) {
loadTasks.push(loadRoomOptions(formData.buildingId));
}
}
@@ -1163,7 +1076,7 @@ const loadRoomStudents = async () => {
// 为每个学生设置默认值
roomStudents.value = res.data.map((student: any) => ({
...student,
student_score: student.student_score || null, // 个人得分,默认为空
student_score: 0, // 个人得分,新增时默认为0
attendance_status: student.attendance_status || '1', // 出勤状态,默认1-在寝
student_grade: student.student_grade || 'A' // 学生评级,默认A-优秀
}));
@@ -1414,6 +1327,20 @@ const handleAttachmentData = async () => {
}
};
// 宿舍楼选项显示格式
const getBuildingDisplayName = (building: BuildingOptionVO) => {
let displayName = building.buildingName;
if (building.buildingType) {
if (building.buildingType === '1') {
displayName = `(男)${displayName}`;
} else if (building.buildingType === '2') {
displayName = `(女)${displayName}`;
}
// 混合楼(3)不显示性别标识
}
return displayName;
};
// 组件挂载时加载校区选项
const initCampusOptions = async () => {
await loadCampusOptions();
@@ -1482,21 +1409,29 @@ const handleStudentGradeChange = (student: any) => {
// 处理宿舍总分变化 - 自动填写学生个人得分
const handleTotalScoreChange = () => {
// 验证宿舍总分范围
if (form.totalScore !== null && form.totalScore !== undefined && form.totalScore !== 0 && String(form.totalScore) !== '0') {
if (form.totalScore !== null && form.totalScore !== undefined && form.totalScore !== '') {
const score = parseFloat(form.totalScore.toString());
if (isNaN(score) || score < 0 || score > 100) {
ElMessage.warning('宿舍总分必须在0-100分之间');
form.totalScore = null;
form.totalScore = 0;
return;
}
// 如果分数有效且有学生,自动为所有学生设置相同的个人得分
// 如果分数有效且有学生,自动为所有学生设置相同的个人得分(包括0分)
if (roomStudents.value.length > 0) {
roomStudents.value.forEach((student: any) => {
student.student_score = score;
});
ElMessage.success(`已自动为${roomStudents.value.length}名学生设置个人得分:${score}分`);
}
} else if (form.totalScore === 0 || form.totalScore === '0') {
// 特别处理0分的情况
if (roomStudents.value.length > 0) {
roomStudents.value.forEach((student: any) => {
student.student_score = 0;
});
ElMessage.success(`已自动为${roomStudents.value.length}名学生设置个人得分:0分`);
}
}
};
@@ -106,9 +106,8 @@
</el-table-column>
<el-table-column label="房间名称" align="center" prop="roomName" />
<el-table-column label="宿舍楼名称" align="center" prop="buildingName" />
<el-table-column label="宿舍区名称" align="center" prop="areaName" />
<el-table-column label="校区名称" align="center" prop="campusName" />
<el-table-column label="宿舍总分" align="center" prop="totalScore" />
<el-table-column label="宿舍扣分" align="center" prop="totalScore" />
<el-table-column label="卫生等级" align="center" prop="hygieneGrade">
<template #default="scope">
<dict-tag :options="xg_dorm_hygiene_grade" :value="scope.row.hygieneGrade" />
@@ -138,16 +137,17 @@
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
<pagination v-show="total > 0" :total="total" :page="queryParams.pageNum" :limit="queryParams.pageSize" @pagination="getList" />
</el-card>
<!-- 宿舍卫生检查弹窗组件 -->
<DormHygieneCheckDialog
v-model="dialog.visible"
:visible="dialog.visible"
:title="dialog.title"
:form-data="form"
@submit="handleDialogSubmit"
@close="handleDialogClose"
@update:visible="(value) => (dialog.visible = value)"
/>
</div>
</template>
@@ -164,7 +164,7 @@ import {
addDormHygieneCheck,
updateDormHygieneCheck,
exportDormHygieneCheck
} from '@/api/xg/xgss/dormHygieneCheck/dormHygieneCheck';
} from '@/api/xg/xgss/dormHygieneCheck/dormHygieneCheck/index';
import {
DormHygieneCheckVO,
DormHygieneCheckQuery,
@@ -223,7 +223,7 @@ const initFormData: DormHygieneCheckForm = {
areaName: undefined,
campusId: undefined,
campusName: undefined,
totalScore: undefined,
totalScore: 0,
hygieneGrade: 'A',
attachmentIds: undefined,
checkSummary: undefined,
@@ -17,24 +17,11 @@
</el-col>
<el-col :span="6">
<el-form-item label="所属校区" prop="campusId">
<el-select v-model="queryParams.campusId" placeholder="请选择所属校区" clearable @change="handleCampusChange">
<el-select v-model="queryParams.campusId" placeholder="请选择所属校区" clearable>
<el-option v-for="item in campusList" :key="item.id" :label="item.campusName" :value="item.id" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="所属宿舍区" prop="areaId">
<el-tree-select
v-model="queryParams.areaId"
:data="areaTreeData"
:props="{ label: 'areaName', value: 'id' }"
placeholder="请选择所属宿舍区"
clearable
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="6">
<el-form-item label="宿舍楼类型" prop="buildingType">
<el-select v-model="queryParams.buildingType" placeholder="请选择宿舍楼类型" clearable>
@@ -72,9 +59,6 @@
>删除</el-button
>
</el-col>
<!-- <el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['sslxx:dormBuilding:export']">导出</el-button>
</el-col> -->
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
@@ -85,7 +69,6 @@
<el-table-column label="宿舍楼编码" align="center" prop="buildingCode" />
<el-table-column label="宿舍楼名称" align="center" prop="buildingName" />
<el-table-column label="所属校区" align="center" prop="campusName" />
<el-table-column label="所属宿舍区" align="center" prop="areaName" />
<el-table-column label="总楼层数" align="center" prop="floors" />
<el-table-column label="宿舍楼类型" align="center" prop="buildingType">
<template #default="scope">
@@ -112,19 +95,10 @@
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="dormBuildingFormRef" :model="form" :rules="rules" label-width="120px">
<el-form-item label="所属校区" prop="campusId">
<el-select v-model="form.campusId" placeholder="请选择所属校区" clearable @change="handleFormCampusChange">
<el-select v-model="form.campusId" placeholder="请选择所属校区" clearable>
<el-option v-for="item in campusList" :key="item.id" :label="item.campusName" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="所属宿舍区" prop="areaId">
<el-tree-select
v-model="form.areaId"
:data="formAreaTreeData"
:props="{ label: 'areaName', value: 'id' }"
placeholder="请选择所属宿舍区"
clearable
/>
</el-form-item>
<el-form-item label="宿舍楼编码" prop="buildingCode">
<el-input v-model="form.buildingCode" placeholder="请输入宿舍楼编码" />
</el-form-item>
@@ -171,13 +145,12 @@ import {
delDormBuilding,
addDormBuilding,
updateDormBuilding,
listCampusOptions,
listAreaTreeData
listCampusOptions
} from '@/api/xg/xgss/sslxx/dormBuilding';
import { DormBuildingVO, DormBuildingQuery, DormBuildingForm } from '@/api/xg/xgss/sslxx/dormBuilding/types';
import { DormCampusVO } from '@/api/xg/xgss/xqxx/dormCampus/types';
import { DormAreaVO } from '@/api/xg/xgss/ssqxx/dormArea/types';
import { getCurrentInstance, ComponentInternalInstance, ref, reactive, toRefs, onMounted } from 'vue';
import { ElForm, ElMessageBox, ElMessage } from 'element-plus';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { dorm_type } = toRefs<any>(proxy?.useDict('dorm_type'));
@@ -191,11 +164,9 @@ const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const campusList = ref<DormCampusVO[]>([]); // 校区列表
const areaTreeData = ref<any[]>([]); // 宿舍区树形数据
const formAreaTreeData = ref<any[]>([]); // 表单宿舍区树形数据
const queryFormRef = ref<ElFormInstance>();
const dormBuildingFormRef = ref<ElFormInstance>();
const queryFormRef = ref<InstanceType<typeof ElForm>>();
const dormBuildingFormRef = ref<InstanceType<typeof ElForm>>();
const dialog = reactive<DialogOption>({
visible: false,
@@ -206,7 +177,6 @@ const initFormData: DormBuildingForm = {
id: undefined,
buildingCode: undefined,
buildingName: undefined,
areaId: undefined,
campusId: undefined,
buildingType: undefined,
buildingDescription: undefined,
@@ -220,7 +190,6 @@ const data = reactive<PageData<DormBuildingForm, DormBuildingQuery>>({
pageSize: 10,
buildingCode: undefined,
buildingName: undefined,
areaId: undefined,
campusId: undefined,
buildingType: undefined,
sortOrder: undefined,
@@ -230,7 +199,6 @@ const data = reactive<PageData<DormBuildingForm, DormBuildingQuery>>({
id: [{ required: true, message: '主键ID不能为空', trigger: 'blur' }],
buildingCode: [{ required: true, message: '宿舍楼编码不能为空', trigger: 'blur' }],
buildingName: [{ required: true, message: '宿舍楼名称不能为空', trigger: 'blur' }],
areaId: [{ required: true, message: '所属宿舍区ID不能为空', trigger: 'blur' }],
campusId: [{ required: true, message: '所属校区ID不能为空', trigger: 'blur' }]
}
});
@@ -252,102 +220,6 @@ const loadCampusOptions = async () => {
campusList.value = res.rows || [];
};
/** 加载宿舍区树形数据 */
const loadAreaTreeData = async (campusId?: string | number) => {
const res = await listAreaTreeData(campusId);
if (campusId) {
// 如果指定了校区ID,只展示该校区的宿舍区
areaTreeData.value = res.rows || [];
formAreaTreeData.value = res.rows || []; // 同时更新表单树形数据
} else {
// 如果没有指定校区ID,按照校区分组展示宿舍区
const campusMap = new Map();
// 先将校区列表转为Map
campusList.value.forEach((campus) => {
campusMap.set(campus.id, {
id: campus.id,
areaName: campus.campusName,
children: []
});
});
// 将宿舍区按校区分组
const areas = res.rows || [];
areas.forEach((area: DormAreaVO) => {
if (campusMap.has(area.campusId)) {
campusMap.get(area.campusId).children.push({
id: area.id,
areaName: area.areaName
});
}
});
// 转换为树形结构
areaTreeData.value = Array.from(campusMap.values());
formAreaTreeData.value = Array.from(campusMap.values());
}
};
/** 校区选择变化处理函数 */
const handleCampusChange = (value: string | number) => {
queryParams.value.areaId = undefined; // 清空已选择的宿舍区
loadAreaTreeData(value);
};
/** 表单校区选择变化处理函数 */
const handleFormCampusChange = (value: string | number) => {
form.value.areaId = undefined; // 清空已选择的宿舍区
loadFormAreaTreeData(value);
};
/** 加载表单宿舍区树形数据 */
const loadFormAreaTreeData = async (campusId?: string | number) => {
const res = await listAreaTreeData(campusId);
if (campusId) {
// 如果指定了校区ID,只展示该校区的宿舍区
formAreaTreeData.value = res.rows || [];
} else {
// 如果没有指定校区ID,按照校区分组展示宿舍区
const campusMap = new Map();
// 先将校区列表转为Map
campusList.value.forEach((campus) => {
campusMap.set(campus.id, {
id: campus.id,
areaName: campus.campusName,
children: []
});
});
// 将宿舍区按校区分组
const areas = res.rows || [];
areas.forEach((area: DormAreaVO) => {
if (campusMap.has(area.campusId)) {
campusMap.get(area.campusId).children.push({
id: area.id,
areaName: area.areaName
});
}
});
// 转换为树形结构
formAreaTreeData.value = Array.from(campusMap.values());
}
};
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
dormBuildingFormRef.value?.resetFields();
};
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
@@ -363,7 +235,7 @@ const resetQuery = () => {
/** 多选框选中数据 */
const handleSelectionChange = (selection: DormBuildingVO[]) => {
ids.value = selection.map((item) => item.id);
single.value = selection.length != 1;
single.value = selection.length !== 1;
multiple.value = !selection.length;
};
@@ -380,10 +252,6 @@ const handleUpdate = async (row?: DormBuildingVO) => {
const _id = row?.id || ids.value[0];
const res = await getDormBuilding(_id);
Object.assign(form.value, res.data);
// 加载表单中的宿舍区数据
if (form.value.campusId) {
loadFormAreaTreeData(form.value.campusId);
}
dialog.visible = true;
dialog.title = '修改宿舍楼信息';
};
@@ -394,13 +262,22 @@ const submitForm = () => {
if (valid) {
buttonLoading.value = true;
if (form.value.id) {
await updateDormBuilding(form.value).finally(() => (buttonLoading.value = false));
await updateDormBuilding(form.value)
.then(() => {
ElMessage.success('修改成功');
dialog.visible = false;
getList();
})
.finally(() => (buttonLoading.value = false));
} else {
await addDormBuilding(form.value).finally(() => (buttonLoading.value = false));
await addDormBuilding(form.value)
.then(() => {
ElMessage.success('新增成功');
dialog.visible = false;
getList();
})
.finally(() => (buttonLoading.value = false));
}
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
}
});
};
@@ -408,148 +285,48 @@ const submitForm = () => {
/** 删除按钮操作 */
const handleDelete = async (row?: DormBuildingVO) => {
const _ids = row?.id || ids.value;
let confirmMsg = '';
if (row) {
confirmMsg = `是否确认删除宿舍楼信息编号为"${row?.buildingName}"的数据项?`;
} else if (Array.isArray(ids.value) && ids.value.length > 1) {
confirmMsg = `是否确认删除选中的${ids.value.length}个宿舍楼信息?`;
} else {
confirmMsg = '是否确认删除选中的宿舍楼信息?';
}
await proxy?.$modal.confirm(confirmMsg).finally(() => (loading.value = false));
await delDormBuilding(_ids);
proxy?.$modal.msgSuccess('删除成功');
await getList();
await ElMessageBox.confirm('是否确认删除宿舍楼信息编号为"' + _ids + '"的数据项?')
.then(() => {
loading.value = true;
return delDormBuilding(_ids);
})
.then(() => {
loading.value = false;
getList();
ElMessage.success('删除成功');
})
.catch(() => {
loading.value = false;
});
};
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download(
'sslxx/dormBuilding/export',
{
...queryParams.value
},
`dormBuilding_${new Date().getTime()}.xlsx`
);
/** 重置操作表单 */
const reset = () => {
form.value = { ...initFormData };
dormBuildingFormRef.value?.resetFields();
};
/** 取消按钮 */
const cancel = () => {
dialog.visible = false;
reset();
};
onMounted(() => {
getList();
loadCampusOptions().then(() => {
loadAreaTreeData();
});
loadCampusOptions();
});
</script>
<style scoped>
/* 页面容器样式 */
.page-container {
padding: 8px;
background-color: #f5f5f5;
}
/* 表格卡片布局 */
.table-card {
margin-top: 0;
}
.table-card :deep(.el-card__body) {
padding: 0px 20px 20px 20px !important;
}
/* 移除按钮栏底部边框 */
.button-card :deep(.el-card__header) {
border-bottom: none !important;
}
.image-gallery {
display: flex;
flex-wrap: wrap;
gap: 12px;
padding: 8px;
}
.image-item {
display: flex;
align-items: center;
justify-content: center;
border: 1px solid #dcdfe6;
border-radius: 6px;
background-color: #fff;
padding: 4px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
}
.image-item:hover {
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
}
.no-image {
display: flex;
align-items: center;
justify-content: center;
width: 120px;
height: 80px;
border: 1px dashed #dcdfe6;
border-radius: 4px;
background-color: #fafafa;
}
.no-image-text {
color: #909399;
font-size: 12px;
text-align: center;
}
.table-no-image {
display: flex;
align-items: center;
justify-content: center;
width: 50px;
height: 50px;
border: 1px dashed #dcdfe6;
border-radius: 4px;
background-color: #fafafa;
margin: 0 auto;
}
.table-no-image-text {
color: #909399;
font-size: 10px;
text-align: center;
}
.view-text {
font-size: 14px;
color: #303133;
line-height: 1.5;
}
.view-description {
padding: 12px;
border: 1px solid #e4e7ed;
border-radius: 4px;
width: 100%;
height: 200px;
font-size: 14px;
color: #303133;
line-height: 1.6;
white-space: pre-wrap;
word-break: break-word;
overflow-y: auto;
}
/* 搜索按钮容器样式 */
.search-btn-container {
display: flex;
justify-content: flex-end;
margin-top: 10px;
.el-form-item {
margin-bottom: 0 !important;
}
text-align: left;
}
.fixed-width-input {
width: 100%;
}
+123 -45
View File
@@ -98,52 +98,73 @@
</el-row>
</template>
<!-- 楼层卡片 -->
<div v-for="floor in floorList" :key="floor" class="mb-4">
<el-divider>
<el-tag type="success" effect="dark" class="mr-2">{{ floor }}层</el-tag>
<el-button type="primary" icon="Plus" size="small" @click="handleAddAllRoom(floor)">自动添加房间</el-button>
<el-button type="primary" icon="Plus" size="small" @click="handleAddRoom(floor)">添加房间</el-button>
</el-divider>
<div class="room-container">
<el-empty v-if="getRoomsByFloor(floor).length === 0" description="暂无房间数据" />
<div v-else class="room-grid">
<el-card
v-for="room in getRoomsByFloor(floor)"
:key="room.id"
class="room-card"
:class="{ 'room-disabled': room.roomStatus !== '0' }"
>
<template #header>
<div class="flex items-center justify-between">
<span class="font-bold">{{ room.roomName }}</span>
<div>
<el-tag v-if="room.roomStatus === '0'" type="success" size="small">正常</el-tag>
<el-tag v-else-if="room.roomStatus === '1'" type="warning" size="small">维修中</el-tag>
<el-tag v-else type="danger" size="small">停用</el-tag>
</div>
</div>
</template>
<div class="room-info">
<div class="mb-2">
<span class="text-gray-500">类型:</span>{{ room.roomType === '1' ? '标准间' : room.roomType === '2' ? '单人间' : '套间' }}
</div>
<div class="mb-2"><span class="text-gray-500">床位:</span>{{ room.currentBeds || 0 }}/{{ room.actualBeds }}</div>
<div class="mb-2"><span class="text-gray-500">排序:</span>{{ room.sort || 0 }}</div>
<div class="flex justify-between mt-4">
<div>
<el-button type="primary" link size="small" @click="handleManageBeds(room)">床位管理</el-button>
</div>
<div>
<el-button type="primary" link icon="Edit" @click="handleEditRoom(room)" />
<el-button type="danger" link icon="Delete" @click="handleDeleteRoom(room)" />
</div>
</div>
</div>
</el-card>
<!-- 右侧房间信息区域 -->
<div class="room-info-area">
<!-- 加载状态 -->
<div v-if="roomLoading" class="loading-container">
<div class="loading-content">
<el-icon class="loading-icon" :size="32">
<Loading />
</el-icon>
<p class="loading-text">正在加载房间数据...</p>
</div>
</div>
<!-- 房间数据展示 -->
<div v-else-if="roomList.length > 0" class="room-display">
<div v-for="floor in floorList" :key="floor" class="mb-4">
<el-divider>
<el-tag type="success" effect="dark" class="mr-2">{{ floor }}层</el-tag>
<el-button type="primary" icon="Plus" size="small" @click="handleAddAllRoom(floor)">自动添加房间</el-button>
<el-button type="primary" icon="Plus" size="small" @click="handleAddRoom(floor)">添加房间</el-button>
</el-divider>
<div class="room-container">
<el-empty v-if="getRoomsByFloor(floor).length === 0" description="暂无房间数据" />
<div v-else class="room-grid">
<el-card
v-for="room in getRoomsByFloor(floor)"
:key="room.id"
class="room-card"
:class="{ 'room-disabled': room.roomStatus !== '0' }"
>
<template #header>
<div class="flex items-center justify-between">
<span class="font-bold">{{ room.roomName }}</span>
<div>
<el-tag v-if="room.roomStatus === '0'" type="success" size="small">正常</el-tag>
<el-tag v-else-if="room.roomStatus === '1'" type="warning" size="small">维修中</el-tag>
<el-tag v-else type="danger" size="small">停用</el-tag>
</div>
</div>
</template>
<div class="room-info">
<div class="mb-2">
<span class="text-gray-500">类型:</span
>{{ room.roomType === '1' ? '标准间' : room.roomType === '2' ? '单人间' : '套间' }}
</div>
<div class="mb-2"><span class="text-gray-500">床位:</span>{{ room.currentBeds || 0 }}/{{ room.actualBeds }}</div>
<div class="mb-2"><span class="text-gray-500">排序:</span>{{ room.sort || 0 }}</div>
<div class="flex justify-between mt-4">
<div>
<el-button type="primary" size="small" @click="handleManageBeds(room)">床位管理</el-button>
</div>
<div>
<el-button type="primary" link size="small" icon="Edit" @click="handleEditRoom(room)" />
<el-button type="danger" link size="small" icon="Delete" @click="handleDeleteRoom(room)" />
</div>
</div>
</div>
</el-card>
</div>
</div>
</div>
</div>
<!-- 空状态展示 -->
<div v-else class="empty-state">
<el-empty description="请先选择左侧宿舍楼查看房间信息" />
</div>
</div>
</el-card>
</template>
@@ -213,7 +234,7 @@
<script setup name="DormRoomManagement" lang="ts">
import { ref, computed, reactive, onMounted, nextTick, watch } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { InfoFilled, Search } from '@element-plus/icons-vue';
import { InfoFilled, Search, Loading } from '@element-plus/icons-vue';
import { DormTreeNode, BedInfo, DormQuery, BedForm } from '@/api/xg/xgss/xsssfjgl/types';
import { DormRoomVO, DormRoomQuery } from '@/api/xg/xgss/dormRoom/types';
import { getDormTree } from '@/api/xg/xgss/xsssfjgl';
@@ -230,6 +251,8 @@ const dormTreeRef = ref();
const queryFormRef = ref();
const buildingName = ref('');
const showSearch = ref(true);
// 添加房间数据加载状态
const roomLoading = ref(false);
const animate = reactive({
searchAnimate: {
enter: 'animate__animated animate__fadeInDown',
@@ -356,6 +379,9 @@ const handleNodeClick = (data: DormTreeNode) => {
const loadRoomData = async () => {
if (!queryParams.buildingId) return;
// 开始加载,设置loading状态
roomLoading.value = true;
try {
const res = await listDormRoom(queryParams);
roomList.value = res?.rows;
@@ -375,6 +401,9 @@ const loadRoomData = async () => {
);
} catch (error) {
console.error('获取房间列表失败', error);
} finally {
// 加载完成,取消loading状态
roomLoading.value = false;
}
};
@@ -862,4 +891,53 @@ watch(
min-width: 100%; /* 确保树至少占满容器宽度 */
width: max-content; /* 允许内容扩展 */
}
/* 加载状态样式 */
.loading-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 400px;
background: #fafafa;
border-radius: 8px;
border: 1px dashed #d9d9d9;
margin: 20px 0;
}
.loading-content {
display: flex;
flex-direction: column;
align-items: center;
gap: 16px;
}
.loading-icon {
color: var(--el-color-primary);
animation: rotate 1s linear infinite;
}
@keyframes rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.loading-text {
font-size: 14px;
color: var(--el-text-color-regular);
margin: 0;
font-weight: 500;
}
/* 空状态样式 */
.empty-state {
min-height: 400px;
display: flex;
align-items: center;
justify-content: center;
}
</style>
+2 -1
View File
@@ -103,8 +103,8 @@
</el-table>
</el-card>
</el-tab-pane>
<!-- 隐藏宿舍区管理员tab页
<el-tab-pane label="宿舍区管理员" name="area">
<!-- 检索栏(宿舍区管理员) -->
<div class="mb-[10px]">
<el-card shadow="hover">
<el-form :inline="true" :model="areaSearchForm" class="search-form">
@@ -155,6 +155,7 @@
</el-table>
</el-card>
</el-tab-pane>
-->
<el-tab-pane label="宿舍楼管理员" name="building">
<!-- 检索栏(宿舍楼管理员) -->
<div class="mb-[10px]">