提交代码

This commit is contained in:
zlwu committed 2025-09-08 00:26:14 +08:00
1 parent 652285005a
commit bf25ceba66
4 files changed
+227 -46

No files matched your search

@@ -21,6 +21,7 @@ import org.dromara.xg.service.IXgHolidayStayService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.ArrayList;
/**
* 假期留宿管理Service业务层处理
@@ -90,15 +91,42 @@ public class XgHolidayStayServiceImpl implements IXgHolidayStayService {
lqw.like(StringUtils.isNotBlank(bo.getCampusName()), XgHolidayStay::getCampusName, bo.getCampusName());
lqw.eq(bo.getAreaId() != null, XgHolidayStay::getAreaId, bo.getAreaId());
lqw.like(StringUtils.isNotBlank(bo.getAreaName()), XgHolidayStay::getAreaName, bo.getAreaName());
lqw.eq(bo.getBuildingId() != null, XgHolidayStay::getBuildingId, bo.getBuildingId());
// 楼栋ID过滤逻辑:支持单个楼栋ID和多个楼栋ID的查询
if (bo.getBuildingId() != null) {
// 单个楼栋ID查询
lqw.eq(XgHolidayStay::getBuildingId, bo.getBuildingId());
} else if (params != null && params.containsKey("buildingIds")) {
// 多个楼栋ID查询,从params中获取buildingIds(逗号分隔的字符串)
String buildingIdsStr = (String) params.get("buildingIds");
if (StringUtils.isNotBlank(buildingIdsStr)) {
String[] buildingIdArray = buildingIdsStr.split(",");
if (buildingIdArray.length > 0) {
List<Long> buildingIds = new ArrayList<>();
for (String buildingIdStr : buildingIdArray) {
try {
Long buildingId = Long.parseLong(buildingIdStr.trim());
buildingIds.add(buildingId);
} catch (NumberFormatException e) {
log.warn("无效的楼栋ID: {}", buildingIdStr);
}
}
if (!buildingIds.isEmpty()) {
lqw.in(XgHolidayStay::getBuildingId, buildingIds);
log.debug("添加多楼栋ID过滤条件: {}", buildingIds);
}
}
}
}
lqw.like(StringUtils.isNotBlank(bo.getBuildingName()), XgHolidayStay::getBuildingName, bo.getBuildingName());
lqw.eq(bo.getRoomId() != null, XgHolidayStay::getRoomId, bo.getRoomId());
lqw.like(StringUtils.isNotBlank(bo.getRoomName()), XgHolidayStay::getRoomName, bo.getRoomName());
lqw.eq(bo.getBedId() != null, XgHolidayStay::getBedId, bo.getBedId());
lqw.like(StringUtils.isNotBlank(bo.getBedName()), XgHolidayStay::getBedName, bo.getBedName());
lqw.eq(StringUtils.isNotBlank(bo.getHolidayType()), XgHolidayStay::getHolidayType, bo.getHolidayType());
lqw.ge(bo.getApplyStartDate() != null, XgHolidayStay::getApplyStartDate, bo.getApplyStartDate());
lqw.le(bo.getApplyEndDate() != null, XgHolidayStay::getApplyEndDate, bo.getApplyEndDate());
lqw.eq(bo.getApplyStartDate() != null, XgHolidayStay::getApplyStartDate, bo.getApplyStartDate());
lqw.eq(bo.getApplyEndDate() != null, XgHolidayStay::getApplyEndDate, bo.getApplyEndDate());
lqw.like(StringUtils.isNotBlank(bo.getStayReason()), XgHolidayStay::getStayReason, bo.getStayReason());
lqw.eq(StringUtils.isNotBlank(bo.getStayReasonType()), XgHolidayStay::getStayReasonType,
bo.getStayReasonType());
@@ -110,9 +138,9 @@ public class XgHolidayStayServiceImpl implements IXgHolidayStayService {
lqw.eq(StringUtils.isNotBlank(bo.getParentConsent()), XgHolidayStay::getParentConsent, bo.getParentConsent());
lqw.like(StringUtils.isNotBlank(bo.getAttachmentOssIds()), XgHolidayStay::getAttachmentOssIds,
bo.getAttachmentOssIds());
lqw.eq(StringUtils.isNotBlank(bo.getExtField1()), XgHolidayStay::getExtField1, bo.getExtField1());
lqw.eq(StringUtils.isNotBlank(bo.getExtField2()), XgHolidayStay::getExtField2, bo.getExtField2());
lqw.eq(StringUtils.isNotBlank(bo.getExtField3()), XgHolidayStay::getExtField3, bo.getExtField3());
lqw.like(StringUtils.isNotBlank(bo.getExtField1()), XgHolidayStay::getExtField1, bo.getExtField1());
lqw.like(StringUtils.isNotBlank(bo.getExtField2()), XgHolidayStay::getExtField2, bo.getExtField2());
lqw.like(StringUtils.isNotBlank(bo.getExtField3()), XgHolidayStay::getExtField3, bo.getExtField3());
// 添加创建人过滤条件 - 实现班主任权限控制,只能查看自己创建的数据
lqw.eq(bo.getCreateBy() != null, XgHolidayStay::getCreateBy, bo.getCreateBy());
@@ -137,17 +165,30 @@ public class XgHolidayStayServiceImpl implements IXgHolidayStayService {
if (StringUtils.isNotBlank(statusType) && StringUtils.isNotBlank(currentTime)) {
if ("valid".equals(statusType)) {
// 有效状态:结束时间 >= 当前时间 AND 结束时间不为空
lqw.ge(XgHolidayStay::getApplyEndDate, currentTime)
// 有效状态:当前时间在留宿开始时间和结束时间之间(包含边界)
// 条件:applyStartDate <= currentTime AND applyEndDate >= currentTime
// AND applyStartDate IS NOT NULL AND applyEndDate IS NOT NULL
lqw.le(XgHolidayStay::getApplyStartDate, currentTime)
.ge(XgHolidayStay::getApplyEndDate, currentTime)
.isNotNull(XgHolidayStay::getApplyStartDate)
.isNotNull(XgHolidayStay::getApplyEndDate);
log.debug("添加有效状态过滤条件: apply_end_date >= {} AND apply_end_date IS NOT NULL", currentTime);
log.debug(
"添加有效状态过滤条件: apply_start_date <= {} AND apply_end_date >= {} AND start/end dates are not null",
currentTime, currentTime);
} else if ("invalid".equals(statusType)) {
// 失效状态:结束时间 < 当前时间 OR 结束时间为空
// 失效状态:当前时间不在留宿时间范围内
// 条件:applyStartDate > currentTime OR applyEndDate < currentTime
// OR applyStartDate IS NULL OR applyEndDate IS NULL
lqw.and(wrapper -> wrapper
.gt(XgHolidayStay::getApplyStartDate, currentTime)
.or()
.lt(XgHolidayStay::getApplyEndDate, currentTime)
.or()
.isNull(XgHolidayStay::getApplyStartDate)
.or()
.isNull(XgHolidayStay::getApplyEndDate));
log.debug("添加失效状态过滤条件: apply_end_date < {} OR apply_end_date IS NULL", currentTime);
log.debug("添加失效状态过滤条件: apply_start_date > {} OR apply_end_date < {} OR start/end dates are null",
currentTime, currentTime);
}
}
}
@@ -1,6 +1,6 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { HolidayStayVO, HolidayStayForm, HolidayStayQuery, StudentOptionVO, StudentOptionQuery } from '@/api/xg/xgss/holidayStay/holidayStay/types';
import { HolidayStayVO, HolidayStayForm, HolidayStayQuery, StudentOptionVO, StudentOptionQuery } from '@/api/xg/xgss/holidayStay/holidayStay/types-sg';
/**
* 查询假期留宿管理列表
@@ -723,7 +723,7 @@ const data = reactive<PageData<HolidayStayForm, HolidayStayQuery>>({
extField1: undefined,
extField2: undefined,
extField3: undefined,
status: undefined,
status: 'valid', // 默认展示有效状态的数据
params: {}
},
rules: {
@@ -756,6 +756,56 @@ const uploadData = computed(() => {
};
});
// 宿管员权限相关状态
const dormManagerBuildingIds = ref<(string | number)[]>([]);
const hasDormManagerPermission = ref(false);
/** 获取宿管员权限范围内的楼栋ID列表 */
const getDormManagerBuildingIds = async () => {
try {
// 调用宿舍楼树接口,该接口会根据当前用户权限自动过滤
const response = await request({
url: '/xgss/dormBuildingTree/list',
method: 'get'
});
if (response.code === 200 && response.data) {
const buildingIds: (string | number)[] = [];
// 提取所有楼栋ID(递归遍历树形结构)
const extractBuildingIds = (nodes: any[]) => {
nodes.forEach((node: any) => {
// 如果是楼栋节点(type为building或者有buildingId)
if (node.type === 'building' || (node.id && !node.children)) {
buildingIds.push(node.id);
}
// 递归处理子节点
if (node.children && node.children.length > 0) {
extractBuildingIds(node.children);
}
});
};
extractBuildingIds(response.data);
dormManagerBuildingIds.value = buildingIds;
hasDormManagerPermission.value = buildingIds.length > 0;
console.log('宿管员权限楼栋ID列表:', buildingIds);
return buildingIds;
} else {
console.warn('获取宿管员权限楼栋失败:', response.msg);
dormManagerBuildingIds.value = [];
hasDormManagerPermission.value = false;
return [];
}
} catch (error) {
console.error('获取宿管员权限楼栋失败:', error);
dormManagerBuildingIds.value = [];
hasDormManagerPermission.value = false;
return [];
}
};
/** 查询假期留宿管理列表 */
const getList = async () => {
loading.value = true;
@@ -765,25 +815,48 @@ const getList = async () => {
await userStore.getInfo();
}
// 获取宿管员权限楼栋列表
const buildingIds = await getDormManagerBuildingIds();
// 如果没有宿管员权限,直接返回空列表
if (!hasDormManagerPermission.value || buildingIds.length === 0) {
holidayStayList.value = [];
total.value = 0;
loading.value = false;
console.log('当前用户没有宿管员权限或没有分配管理楼栋');
return;
}
// 处理状态过滤逻辑
const requestParams = { ...queryParams.value };
// 添加创建人过滤条件 - 班主任只能看到自己创建的数据
requestParams.createBy = userStore.userId;
// 宿管员权限过滤:添加楼栋ID过滤条件
if (buildingIds.length === 1) {
// 单个楼栋直接设置buildingId
requestParams.buildingId = buildingIds[0];
} else {
// 多个楼栋使用in查询,通过params传递
requestParams.params = {
...requestParams.params,
buildingIds: buildingIds.join(',')
};
}
// 根据状态设置时间过滤条件
if (requestParams.status) {
const currentTime = new Date().toISOString().slice(0, 19).replace('T', ' ');
if (requestParams.status === 'valid') {
// 查询有效状态:结束时间大于等于当前时间
// 查询有效状态:当前时间在留宿开始时间和结束时间之间
// 条件:currentTime >= applyStartDate AND currentTime <= applyEndDate
requestParams.params = {
...requestParams.params,
statusType: 'valid',
currentTime: currentTime
};
} else if (requestParams.status === 'invalid') {
// 查询失效状态:结束时间小于当前时间
// 查询失效状态:当前时间不在留宿时间范围内
// 条件:currentTime < applyStartDate OR currentTime > applyEndDate
requestParams.params = {
...requestParams.params,
statusType: 'invalid',
@@ -795,10 +868,17 @@ const getList = async () => {
delete requestParams.status;
}
const res = await listHolidayStay(requestParams);
holidayStayList.value = res.rows;
total.value = res.total;
loading.value = false;
try {
const res = await listHolidayStay(requestParams);
holidayStayList.value = res.rows;
total.value = res.total;
} catch (error) {
console.error('查询假期留宿列表失败:', error);
holidayStayList.value = [];
total.value = 0;
} finally {
loading.value = false;
}
};
/** 取消按钮 */
@@ -1315,26 +1395,38 @@ const loadCascadeOptionsForUpdate = async (formData: HolidayStayForm) => {
/** 获取状态文本 */
const getStatusText = (row: HolidayStayVO) => {
if (!row.applyEndDate) {
if (!row.applyStartDate || !row.applyEndDate) {
return '未知';
}
const currentTime = new Date();
const startTime = new Date(row.applyStartDate);
const endTime = new Date(row.applyEndDate);
return currentTime > endTime ? '失效' : '有效';
// 有效条件:当前时间在留宿开始时间和结束时间之间(包含边界)
if (currentTime >= startTime && currentTime <= endTime) {
return '有效';
} else {
return '失效';
}
};
/** 获取状态标签类型 */
const getStatusType = (row: HolidayStayVO) => {
if (!row.applyEndDate) {
if (!row.applyStartDate || !row.applyEndDate) {
return 'info';
}
const currentTime = new Date();
const startTime = new Date(row.applyStartDate);
const endTime = new Date(row.applyEndDate);
return currentTime > endTime ? 'danger' : 'success';
// 有效条件:当前时间在留宿开始时间和结束时间之间(包含边界)
if (currentTime >= startTime && currentTime <= endTime) {
return 'success'; // 有效 - 绿色
} else {
return 'danger'; // 失效 - 红色
}
};
// 文件类型判断
@@ -47,7 +47,7 @@
<script lang="ts">
import { defineComponent, ref, reactive, computed, watch, onMounted } from 'vue';
import { searchTeacherByName } from '@/api/system/teacher';
import { getTeacherList } from '@/api/xg/xgss/xsssgly/dormManager';
import { addDormManager, updateDormManager } from '@/api/xg/xgss/ssglyxx/dormManager/index';
import { ElMessage } from 'element-plus';
@@ -121,17 +121,33 @@ export default defineComponent({
const queryTeachers = async (query: string) => {
loading.value = true;
try {
const res = await searchTeacherByName(query, 20);
const res = await getTeacherList(
query,
(() => {
switch (props.type) {
case 'school':
return '1';
case 'campus':
return '2';
case 'area':
return '3';
case 'building':
return '4';
default:
return '1';
}
})()
);
if (res.code === 200 && res.data) {
teacherOptions.value = res.data.map((item: any) => {
return {
value: item.userId,
label: item.nickName,
username: item.userName,
nickName: item.nickName,
userId: item.userId,
phonenumber: item.phonenumber,
sex: item.sex
value: item.value,
label: item.label,
username: item.username,
nickName: item.label,
userId: item.value, // 直接使用API返回的value作为userId
phonenumber: item.phonenumber, // 保存手机号码
sex: item.sex // 保存性别
};
});
}
@@ -181,15 +197,31 @@ export default defineComponent({
const handleFocus = async () => {
loading.value = true;
try {
const res = await searchTeacherByName('', 100);
const res = await getTeacherList(
'',
(() => {
switch (props.type) {
case 'school':
return '1';
case 'campus':
return '2';
case 'area':
return '3';
case 'building':
return '4';
default:
return '1';
}
})()
);
if (res.code === 200 && res.data) {
teacherOptions.value = res.data.map((item: any) => {
return {
value: item.userId,
label: item.nickName,
username: item.userName,
userId: item.userId,
nickName: item.nickName,
value: item.value,
label: item.label,
username: item.username,
userId: item.value,
nickName: item.label,
phonenumber: item.phonenumber, // 保存手机号码
sex: item.sex // 保存性别
};
@@ -205,15 +237,31 @@ export default defineComponent({
// 页面加载时预加载一些教师数据
onMounted(async () => {
try {
const res = await searchTeacherByName('', 100);
const res = await getTeacherList(
'',
(() => {
switch (props.type) {
case 'school':
return '1';
case 'campus':
return '2';
case 'area':
return '3';
case 'building':
return '4';
default:
return '1';
}
})()
);
if (res.code === 200 && res.data) {
teacherOptions.value = res.data.map((item: any) => {
return {
value: item.userId,
label: item.nickName,
username: item.userName,
userId: item.userId,
nickName: item.nickName,
value: item.value,
label: item.label,
username: item.username,
userId: item.value,
nickName: item.label,
phonenumber: item.phonenumber, // 保存手机号码
sex: item.sex // 保存性别
};