zlwu 1 год назад
Родитель
Сommit
bf25ceba66

+ 52 - 11
backend/ruoyi-modules/ruoyi-xg/src/main/java/org/dromara/xg/service/impl/XgHolidayStayServiceImpl.java

@@ -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 - 1
web/src/api/xg/xgss/holidayStay/holidayStay/index-sg.ts

@@ -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';
 
 /**
  * 查询假期留宿管理列表

+ 105 - 13
web/src/views/xg/xgss/holidayStay/holidayStay/index-sg.vue

@@ -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'; // 失效 - 红色
+  }
 };
 
 // 文件类型判断

+ 69 - 21
web/src/views/xg/xgss/xsssgly/components/AdminDialog.vue

@@ -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 // 保存性别
             };