From 3702e8d175c8c1363a2993fd38d9f65f3385ee40 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=A3=B7=E5=8F=B6?=
 <14103883+leaf-phos@user.noreply.gitee.com>
Date: Sat, 7 Dec 2024 16:21:49 +0800
Subject: [PATCH] =?UTF-8?q?=E4=B8=B4=E6=97=B6=E8=B0=83=E7=8F=AD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../ruoyi/common/annotation/DataScope.java    |   4 +-
 .../com/ruoyi/common/enums/LogBizType.java    |   3 +-
 .../typehandler/LongSplitListTypeHandler.java |  30 ++++
 .../ruoyi/framework/util/DataScopeUtil.java   |  81 +++++-----
 .../ruoyi/system/service/ISysUserService.java |  11 ++
 .../service/impl/SysUserServiceImpl.java      |  11 ++
 .../system/user/domain/SysUserShiftQuery.java |  23 +++
 .../system/user/mapper/SysUserMapper.java     |   6 +
 .../system/user/mapper/SysUserMapper.xml      |  35 ++++-
 .../java/com/ruoyi/yh/shift/domain/Shift.java |  64 ++++++++
 .../com/ruoyi/yh/shift/domain/ShiftQuery.java |  16 ++
 .../com/ruoyi/yh/shift/domain/ShiftVO.java    |  25 +++
 .../ruoyi/yh/shift/mapper/ShiftMapper.java    |  69 ++++++++
 .../com/ruoyi/yh/shift/mapper/ShiftMapper.xml | 148 ++++++++++++++++++
 .../ruoyi/yh/shift/service/IShiftService.java |  68 ++++++++
 .../yh/shift/service/ShiftConverter.java      |  20 +++
 .../service/impl/ShiftConverterImpl.java      |  49 ++++++
 .../shift/service/impl/ShiftServiceImpl.java  | 103 ++++++++++++
 .../ruoyi/web/system/SysUserController.java   |  17 +-
 .../com/ruoyi/web/yh/ShiftController.java     | 140 +++++++++++++++++
 20 files changed, 875 insertions(+), 48 deletions(-)
 create mode 100644 common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/mybatis/typehandler/LongSplitListTypeHandler.java
 create mode 100644 common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/system/user/domain/SysUserShiftQuery.java
 create mode 100644 common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/domain/Shift.java
 create mode 100644 common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/domain/ShiftQuery.java
 create mode 100644 common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/domain/ShiftVO.java
 create mode 100644 common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/mapper/ShiftMapper.java
 create mode 100644 common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/mapper/ShiftMapper.xml
 create mode 100644 common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/service/IShiftService.java
 create mode 100644 common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/service/ShiftConverter.java
 create mode 100644 common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/service/impl/ShiftConverterImpl.java
 create mode 100644 common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/service/impl/ShiftServiceImpl.java
 create mode 100644 ruoyi-web/src/main/java/com/ruoyi/web/yh/ShiftController.java

diff --git a/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java b/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java
index be49c80..f13453b 100644
--- a/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java
+++ b/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java
@@ -8,7 +8,7 @@ import java.lang.annotation.Target;
 
 /**
  * 数据权限过滤注解
- * 
+ *
  * @author ruoyi
  */
 @Target(ElementType.METHOD)
@@ -17,7 +17,7 @@ import java.lang.annotation.Target;
 public @interface DataScope
 {
     /**
-     * 部门表的别名
+     * 部门表的别名,可多选,逗号分隔
      */
     public String deptAlias() default "";
 
diff --git a/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/enums/LogBizType.java b/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/enums/LogBizType.java
index 06a150a..25830e0 100644
--- a/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/enums/LogBizType.java
+++ b/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/enums/LogBizType.java
@@ -17,7 +17,8 @@ public enum LogBizType {
     REPORT("2", "报表"),
     PROD_ORDER("3", "生产订单" ),
     MATERIAL("4", "物料"),
-    UNIT("5", "单位");
+    UNIT("5", "单位"),
+    SHIFT("6", "调班");
 
     private final String type;
     private final String msg;
diff --git a/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/mybatis/typehandler/LongSplitListTypeHandler.java b/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/mybatis/typehandler/LongSplitListTypeHandler.java
new file mode 100644
index 0000000..76d8491
--- /dev/null
+++ b/common-ruoyi/ruoyi-common/src/main/java/com/ruoyi/common/mybatis/typehandler/LongSplitListTypeHandler.java
@@ -0,0 +1,30 @@
+package com.ruoyi.common.mybatis.typehandler;
+
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @author wjh
+ * 2024/12/7
+ */
+public class LongSplitListTypeHandler extends AbstractSplitListTypeHandler<Long>{
+    /**
+     * 转换为列表
+     *
+     * @param data
+     * @param delimiter
+     */
+    @Override
+    public List<Long> parseToList(String data, String delimiter) {
+        if (StringUtils.isBlank(data)) {
+            return new ArrayList<>();
+        }
+        String[] split = data.split(delimiter);
+        return Arrays.stream(split)
+                .filter(Objects::nonNull)
+                .map(Long::valueOf)
+                .collect(Collectors.toList());
+    }
+}
diff --git a/common-ruoyi/ruoyi-framework/src/main/java/com/ruoyi/framework/util/DataScopeUtil.java b/common-ruoyi/ruoyi-framework/src/main/java/com/ruoyi/framework/util/DataScopeUtil.java
index 278bece..72eebd5 100644
--- a/common-ruoyi/ruoyi-framework/src/main/java/com/ruoyi/framework/util/DataScopeUtil.java
+++ b/common-ruoyi/ruoyi-framework/src/main/java/com/ruoyi/framework/util/DataScopeUtil.java
@@ -8,9 +8,11 @@ import com.ruoyi.common.core.domain.model.LoginUser;
 import com.ruoyi.common.core.text.Convert;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.collection.CollectionUtils;
 import com.ruoyi.framework.security.context.PermissionContextHolder;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -71,7 +73,8 @@ public class DataScopeUtil {
     }
 
     public static StringBuilder getSqlString(SysUser user, String deptAlias, String userAlias, String permission) {
-
+        List<String> deptList = StringUtils.hasText(deptAlias) ? Arrays.asList(deptAlias.split(",")) : new ArrayList<>();
+        List<String> userList = StringUtils.hasText(userAlias) ? Arrays.asList(userAlias.split(",")) : new ArrayList<>();
         StringBuilder sqlString = new StringBuilder();
         List<String> conditions = new ArrayList<String>();
         List<String> scopeCustomIds = new ArrayList<String>();
@@ -82,67 +85,73 @@ public class DataScopeUtil {
             }
         });
 
-        for (SysRole role : user.getRoles())
-        {
+        // 多个角色,逐一判断权限
+        for (SysRole role : user.getRoles()) {
             String dataScope = role.getDataScope();
-            if (conditions.contains(dataScope) || StringUtils.equals(role.getStatus(), UserConstants.ROLE_DISABLE))
-            {
+            if (conditions.contains(dataScope) || StringUtils.equals(role.getStatus(), UserConstants.ROLE_DISABLE)) {
                 continue;
             }
-            if (!StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
-            {
+            if (!StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission))) {
                 continue;
             }
-            if (DATA_SCOPE_ALL.equals(dataScope))
-            {
+            // 全部数据范围
+            if (DATA_SCOPE_ALL.equals(dataScope)) {
                 sqlString = new StringBuilder();
                 conditions.add(dataScope);
                 break;
             }
-            else if (DATA_SCOPE_CUSTOM.equals(dataScope))
-            {
-                if (scopeCustomIds.size() > 1)
-                {
+            // 自定义数据范围
+            else if (DATA_SCOPE_CUSTOM.equals(dataScope)) {
+                if (scopeCustomIds.size() > 1) {
                     // 多个自定数据权限使用in查询,避免多次拼接。
-                    sqlString.append(StringUtils.format(" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id in ({}) ) ", deptAlias, String.join(",", scopeCustomIds)));
-                }
-                else
-                {
-                    sqlString.append(StringUtils.format(" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias, role.getRoleId()));
+                    sqlString.append(getForeachSql(" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id in ({}) ) ", deptList,  String.join(",", scopeCustomIds)));
+                } else {
+                    sqlString.append(getForeachSql(" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptList, role.getRoleId()));
                 }
             }
-            else if (DATA_SCOPE_DEPT.equals(dataScope))
-            {
-                sqlString.append(StringUtils.format(" OR {}.dept_id = {} ", deptAlias, user.getDeptId()));
+            // 仅本部门
+            else if (DATA_SCOPE_DEPT.equals(dataScope)) {
+                sqlString.append(getForeachSql(" OR {}.dept_id = {} ", deptList, user.getDeptId()));
             }
-            else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope))
-            {
-                sqlString.append(StringUtils.format(" OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )", deptAlias, user.getDeptId(), user.getDeptId()));
+            // 本部门及下级部门
+            else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) {
+                sqlString.append(getForeachSql(" OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )", deptList, user.getDeptId(), user.getDeptId()));
             }
-            else if (DATA_SCOPE_SELF.equals(dataScope))
-            {
-                if (StringUtils.isNotBlank(userAlias))
-                {
-                    sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias, user.getUserId()));
-                }
-                else
-                {
+            // 仅本人
+            else if (DATA_SCOPE_SELF.equals(dataScope)) {
+                if (CollectionUtils.isNotEmpty(userList)) {
+                    sqlString.append(getForeachSql(" OR {}.user_id = {} ", userList, user.getUserId()));
+                } else {
                     // 数据权限为仅本人且没有userAlias别名不查询任何数据
-                    sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias));
+                    sqlString.append(" OR 1=0 ");
                 }
             }
             conditions.add(dataScope);
         }
 
         // 角色都不包含传递过来的权限字符,这个时候sqlString也会为空,所以要限制一下,不查询任何数据
-        if (StringUtils.isEmpty(conditions))
-        {
-            sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias));
+        if (StringUtils.isEmpty(conditions)) {
+            sqlString.append(" OR 1=0 ");
         }
 
         return sqlString;
     }
 
+    /**
+     * 获取列表循环SQL
+     */
+    private static String getForeachSql(String template, List<String> list, Object ...others) {
+        StringBuilder sb = new StringBuilder();
+        for (String s : list) {
+            // 创建一个新的数组,包含 s 和 others 的所有元素
+            Object[] params = new Object[others.length + 1];
+            params[0] = s; // 将 s 放在第一个位置
+            System.arraycopy(others, 0, params, 1, others.length); // 将 others 中的元素依次放入新数组中
+            sb.append(StringUtils.format(template, params));
+        }
+        return sb.toString();
+    }
+
     public static void joinSqlString(BaseEntity baseEntity, StringBuilder sqlString) {
         String scope = (String) baseEntity.getParams().get(DATA_SCOPE);
         baseEntity.getParams().put(DATA_SCOPE, getJoinSqlString(sqlString, scope));
diff --git a/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java b/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
index fc7f2d5..1ff08fb 100644
--- a/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
+++ b/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
@@ -3,6 +3,7 @@ package com.ruoyi.system.service;
 import java.util.List;
 import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.system.user.domain.SysUserQuery;
+import com.ruoyi.system.user.domain.SysUserShiftQuery;
 import com.ruoyi.system.user.domain.SysUserVO;
 
 /**
@@ -231,4 +232,14 @@ public interface ISysUserService
      * 解绑微信
      */
     int unbindWx(Long userId);
+
+    /**
+     * 查询调班用户列表
+     */
+    List<SysUserVO> selectUserWithShiftList(SysUserShiftQuery query);
+
+    /**
+     * 查询用户列表
+     */
+    List<SysUserVO> selectUserList(SysUserQuery query);
 }
diff --git a/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java b/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
index ed5c7d6..779c279 100644
--- a/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
+++ b/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
@@ -16,6 +16,7 @@ import com.ruoyi.common.core.validate.ValidGroup;
 import com.ruoyi.common.utils.ServiceUtil;
 import com.ruoyi.common.utils.collection.CollectionUtils;
 import com.ruoyi.system.user.domain.SysUserQuery;
+import com.ruoyi.system.user.domain.SysUserShiftQuery;
 import com.ruoyi.system.user.domain.SysUserVO;
 import com.ruoyi.system.service.ISysRoleService;
 import com.ruoyi.system.user.service.UserValidator;
@@ -684,6 +685,16 @@ public class SysUserServiceImpl implements ISysUserService
         return userMapper.unbindWxOpenId(userId);
     }
 
+    @Override
+    public List<SysUserVO> selectUserWithShiftList(SysUserShiftQuery query) {
+        return userMapper.selectUserWithShiftList(query);
+    }
+
+    @Override
+    public List<SysUserVO> selectUserList(SysUserQuery query) {
+        return userMapper.selectUserList(query);
+    }
+
     private SysUserVO selectOne(SysUserQuery query) {
         PageHelper.startPage(1, 1);
         List<SysUserVO> list = userMapper.selectUserList(query);
diff --git a/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/system/user/domain/SysUserShiftQuery.java b/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/system/user/domain/SysUserShiftQuery.java
new file mode 100644
index 0000000..4dc4744
--- /dev/null
+++ b/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/system/user/domain/SysUserShiftQuery.java
@@ -0,0 +1,23 @@
+package com.ruoyi.system.user.domain;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDate;
+
+/**
+ * @author wjh
+ * 2024/12/7
+ */
+@Data
+public class SysUserShiftQuery extends SysUserQuery {
+
+    @ApiModelProperty("调班日期")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    private LocalDate shiftDate;
+
+    @ApiModelProperty("目标部门ID")
+    private Long targetDeptId;
+
+}
diff --git a/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/system/user/mapper/SysUserMapper.java b/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/system/user/mapper/SysUserMapper.java
index 0e5ad70..1361e46 100644
--- a/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/system/user/mapper/SysUserMapper.java
+++ b/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/system/user/mapper/SysUserMapper.java
@@ -3,6 +3,7 @@ package com.ruoyi.system.user.mapper;
 import java.util.List;
 
 import com.ruoyi.system.user.domain.SysUserQuery;
+import com.ruoyi.system.user.domain.SysUserShiftQuery;
 import com.ruoyi.system.user.domain.SysUserVO;
 import org.apache.ibatis.annotations.Param;
 import com.ruoyi.common.core.domain.entity.SysUser;
@@ -142,4 +143,9 @@ public interface SysUserMapper
      * 解绑微信
      */
     int unbindWxOpenId(Long userId);
+
+    /**
+     * 查询用户列表(含调班)
+     */
+    List<SysUserVO> selectUserWithShiftList(SysUserShiftQuery query);
 }
diff --git a/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/system/user/mapper/SysUserMapper.xml b/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/system/user/mapper/SysUserMapper.xml
index 4897bd1..3fdbfc5 100644
--- a/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/system/user/mapper/SysUserMapper.xml
+++ b/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/system/user/mapper/SysUserMapper.xml
@@ -128,11 +128,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 				#{item}
 			</foreach>
 		</if>
+		<!-- 数据范围过滤 -->
+		${@com.ruoyi.framework.util.DataScopeUtil@dataScope("d", "u", needScope)}
+		${params.dataScope}
 	</sql>
 
-    <select id="selectUserList" parameterType="SysUserQuery" resultMap="SysUserResult">
+	<sql id="selectListVo">
 		select
-		    u.user_id,
+			u.user_id,
 			u.dept_id,
 			u.user_name,
 			u.nick_name,
@@ -153,14 +156,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 			u.employ_status,
 			u.wx_open_id,
 			d.dept_name,
-			d.leader from sys_user u
-		left join sys_dept d on u.dept_id = d.dept_id
+			d.leader
+		from sys_user u
+			left join sys_dept d on u.dept_id = d.dept_id
+    </sql>
+
+    <select id="selectUserList" parameterType="SysUserQuery" resultMap="SysUserResult">
+		<include refid="selectListVo"/>
 		<where>
 			<include refid="searchCondition"/>
 		</where>
-		<!-- 数据范围过滤 -->
-		${@com.ruoyi.framework.util.DataScopeUtil@dataScope("d", "u", needScope)}
-		${params.dataScope}
 	</select>
 
 	<select id="selectAllocatedList" parameterType="SysUser" resultMap="SysUserResult">
@@ -228,6 +233,22 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 		</where>
 	</select>
 
+    <select id="selectUserWithShiftList" resultMap="SysUserResult">
+		<include refid="selectListVo"/>
+			left join bst_shift bs on FIND_IN_SET(u.user_id, bs.user_ids)
+			left join sys_dept sdt on sdt.dept_id = bs.target_dept_id
+		<where>
+			<include refid="searchCondition"/>
+			<if test="shiftDate != null">
+				and if(bs.shift_id is not null, date(bs.shift_time_start) &lt;= #{shiftDate}, true)
+				and if(bs.shift_id is not null, date(bs.shift_time_end) >= #{shiftDate}, true)
+			</if>
+			<if test="targetDeptId != null">
+				and if(bs.shift_id is not null, bs.target_dept_id, u.dept_id) = #{targetDeptId}
+			</if>
+		</where>
+	</select>
+
     <insert id="insertUser" parameterType="SysUser" useGeneratedKeys="true" keyProperty="userId">
  		insert into sys_user(
  			<if test="userId != null and userId != 0">user_id,</if>
diff --git a/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/domain/Shift.java b/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/domain/Shift.java
new file mode 100644
index 0000000..34ebf4e
--- /dev/null
+++ b/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/domain/Shift.java
@@ -0,0 +1,64 @@
+package com.ruoyi.yh.shift.domain;
+
+import java.time.LocalDateTime;
+import java.util.Date;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.common.core.interfaces.LogBizParam;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 调班对象 bst_shift
+ *
+ * @author ruoyi
+ * @date 2024-12-07
+ */
+@Data
+public class Shift extends BaseEntity implements LogBizParam
+{
+    private static final long serialVersionUID = 1L;
+
+    private Long shiftId;
+
+    @Excel(name = "调班用户ID列表,逗号隔开")
+    @ApiModelProperty("调班用户ID列表,逗号隔开")
+    private List<Long> userIds;
+
+    @Excel(name = "调班时间(起始)")
+    @ApiModelProperty("调班时间(起始)")
+    private LocalDateTime shiftTimeStart;
+
+    @Excel(name = "调班时间(结束)")
+    @ApiModelProperty("调班时间(结束)")
+    private LocalDateTime shiftTimeEnd;
+
+    @Excel(name = "目标部门ID")
+    @ApiModelProperty("目标部门ID")
+    private Long targetDeptId;
+
+    @Excel(name = "创建人ID")
+    @ApiModelProperty("创建人ID")
+    private Long createId;
+
+    @Excel(name = "更新人ID")
+    @ApiModelProperty("更新人ID")
+    private Long updateId;
+
+    @Excel(name = "创建部门ID")
+    @ApiModelProperty("创建部门ID")
+    private Long deptId;
+
+    /**
+     * 获取日志业务ID
+     */
+    @Override
+    public Object logBizId() {
+        return shiftId;
+    }
+}
diff --git a/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/domain/ShiftQuery.java b/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/domain/ShiftQuery.java
new file mode 100644
index 0000000..f834bab
--- /dev/null
+++ b/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/domain/ShiftQuery.java
@@ -0,0 +1,16 @@
+package com.ruoyi.yh.shift.domain;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * @author wjh
+ * 2024/12/7
+ */
+@Data
+public class ShiftQuery extends ShiftVO{
+
+    @ApiModelProperty("用户名称")
+    private String userName;
+
+}
diff --git a/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/domain/ShiftVO.java b/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/domain/ShiftVO.java
new file mode 100644
index 0000000..53426fc
--- /dev/null
+++ b/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/domain/ShiftVO.java
@@ -0,0 +1,25 @@
+package com.ruoyi.yh.shift.domain;
+
+import com.ruoyi.system.user.domain.SysUserVO;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author wjh
+ * 2024/12/7
+ */
+@Data
+public class ShiftVO extends Shift{
+
+    @ApiModelProperty("目标部门名称")
+    private String targetDeptName;
+
+    @ApiModelProperty("创建部门名称")
+    private String deptName;
+
+    @ApiModelProperty("调班用户列表")
+    private List<SysUserVO> userList;
+
+}
diff --git a/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/mapper/ShiftMapper.java b/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/mapper/ShiftMapper.java
new file mode 100644
index 0000000..f43ec58
--- /dev/null
+++ b/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/mapper/ShiftMapper.java
@@ -0,0 +1,69 @@
+package com.ruoyi.yh.shift.mapper;
+
+import java.util.List;
+import com.ruoyi.yh.shift.domain.Shift;
+import com.ruoyi.yh.shift.domain.ShiftVO;
+import com.ruoyi.yh.shift.domain.ShiftQuery;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * 调班Mapper接口
+ *
+ * @author ruoyi
+ * @date 2024-12-07
+ */
+public interface ShiftMapper
+{
+    /**
+     * 查询调班
+     *
+     * @param shiftId 调班主键
+     * @return 调班
+     */
+    public ShiftVO selectShiftByShiftId(Long shiftId);
+
+    /**
+     * 查询调班列表
+     *
+     * @param query 调班
+     * @return 调班集合
+     */
+    public List<ShiftVO> selectShiftList(@Param("query")ShiftQuery query);
+
+    /**
+     * 新增调班
+     *
+     * @param shift 调班
+     * @return 结果
+     */
+    public int insertShift(Shift shift);
+
+    /**
+     * 修改调班
+     *
+     * @param shift 调班
+     * @return 结果
+     */
+    public int updateShift(@Param("data") Shift shift);
+
+    /**
+     * 删除调班
+     *
+     * @param shiftId 调班主键
+     * @return 结果
+     */
+    public int deleteShiftByShiftId(Long shiftId);
+
+    /**
+     * 批量删除调班
+     *
+     * @param shiftIds 需要删除的数据主键集合
+     * @return 结果
+     */
+    public int deleteShiftByShiftIds(Long[] shiftIds);
+
+    /**
+     * 逻辑删除
+     */
+    int logicDel(@Param("shiftIds") List<Long> shiftIds);
+}
diff --git a/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/mapper/ShiftMapper.xml b/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/mapper/ShiftMapper.xml
new file mode 100644
index 0000000..43a7ce5
--- /dev/null
+++ b/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/mapper/ShiftMapper.xml
@@ -0,0 +1,148 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.yh.shift.mapper.ShiftMapper">
+
+    <resultMap type="ShiftVO" id="ShiftResult" autoMapping="true">
+        <id property="shiftId" column="shift_id"/>
+        <result property="userIds" column="user_ids" typeHandler="com.ruoyi.common.mybatis.typehandler.LongSplitListTypeHandler"/>
+        <collection property="userList" javaType="java.util.List" ofType="SysUserVO">
+            <id column="user_id" property="userId"/>
+            <result column="nick_name" property="nickName"/>
+        </collection>
+    </resultMap>
+
+    <sql id="selectShiftVo">
+        select
+            bs.shift_id,
+            bs.user_ids,
+            bs.shift_time_start,
+            bs.shift_time_end,
+            bs.target_dept_id,
+            bs.create_time,
+            bs.create_id,
+            bs.update_time,
+            bs.update_id,
+            bs.dept_id,
+            bs.remark,
+            bs.create_by,
+            bs.update_by,
+            bs.deleted,
+            sd.dept_name as dept_name,
+            sdt.dept_name as target_dept_name,
+            su.user_id,
+            su.nick_name as nick_name
+        from bst_shift bs
+            left join sys_dept sd on sd.dept_id = bs.dept_id
+            left join sys_dept sdt on sdt.dept_id = bs.target_dept_id
+            left join sys_user su on find_in_set(su.user_id, bs.user_ids)
+    </sql>
+
+    <sql id="searchCondition">
+        <if test="query.shiftId != null "> and bs.shift_id = #{query.shiftId}</if>
+        <if test="query.targetDeptId != null "> and bs.target_dept_id = #{query.targetDeptId}</if>
+        <if test="query.createId != null "> and bs.create_id = #{query.createId}</if>
+        <if test="query.updateId != null "> and bs.update_id = #{query.updateId}</if>
+        <if test="query.deptId != null "> and bs.dept_id = #{query.deptId}</if>
+        <if test="query.deleted != null "> and bs.deleted = #{query.deleted}</if>
+        <if test="query.deleted == null "> and bs.deleted = false</if>
+        <if test="query.remark != null  and query.remark != ''"> and bs.remark like concat('%', #{query.remark}, '%')</if>
+        <if test="query.createBy != null  and query.createBy != ''"> and bs.create_by like concat('%', #{query.createBy}, '%')</if>
+        <if test="query.updateBy != null  and query.updateBy != ''"> and bs.update_by like concat('%', #{query.updateBy}, '%')</if>
+        <if test="query.userName != null  and query.userName != ''">
+            and su.nick_name like concat('%', #{query.userName}, '%')
+        </if>
+        ${query.params.dataScope}
+    </sql>
+
+    <select id="selectShiftList" parameterType="ShiftQuery" resultMap="ShiftResult">
+        <include refid="selectShiftVo"/>
+        <where>
+            <include refid="searchCondition"/>
+        </where>
+    </select>
+
+    <select id="selectShiftByShiftId" parameterType="Long" resultMap="ShiftResult">
+        <include refid="selectShiftVo"/>
+        where bs.shift_id = #{shiftId}
+    </select>
+
+    <insert id="insertShift" parameterType="Shift" useGeneratedKeys="true" keyProperty="shiftId">
+        insert into bst_shift
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="userIds != null and userIds != ''">user_ids,</if>
+            <if test="shiftTimeStart != null">shift_time_start,</if>
+            <if test="shiftTimeEnd != null">shift_time_end,</if>
+            <if test="targetDeptId != null">target_dept_id,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="createId != null">create_id,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="updateId != null">update_id,</if>
+            <if test="deptId != null">dept_id,</if>
+            <if test="remark != null">remark,</if>
+            <if test="createBy != null">create_by,</if>
+            <if test="updateBy != null">update_by,</if>
+            <if test="deleted != null">deleted,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="userIds != null and userIds != ''">#{userIds,typeHandler=com.ruoyi.common.mybatis.typehandler.LongSplitListTypeHandler},</if>
+            <if test="shiftTimeStart != null">#{shiftTimeStart},</if>
+            <if test="shiftTimeEnd != null">#{shiftTimeEnd},</if>
+            <if test="targetDeptId != null">#{targetDeptId},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="createId != null">#{createId},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="updateId != null">#{updateId},</if>
+            <if test="deptId != null">#{deptId},</if>
+            <if test="remark != null">#{remark},</if>
+            <if test="createBy != null">#{createBy},</if>
+            <if test="updateBy != null">#{updateBy},</if>
+            <if test="deleted != null">#{deleted},</if>
+         </trim>
+    </insert>
+
+    <update id="updateShift" parameterType="Shift">
+        update bst_shift
+        <trim prefix="SET" suffixOverrides=",">
+            <include refid="updateColumns"/>
+        </trim>
+        where shift_id = #{data.shiftId}
+    </update>
+    <update id="logicDel">
+        update bst_shift
+        set deleted = true
+        where shift_id in
+        <foreach collection="shiftIds" item="item" open="(" separator="," close=")">
+            #{item}
+        </foreach>
+        and deleted = false
+    </update>
+
+    <sql id="updateColumns">
+        <if test="data.userIds != null and data.userIds != ''">user_ids = #{data.userIds,typeHandler=com.ruoyi.common.mybatis.typehandler.LongSplitListTypeHandler},</if>
+        <if test="data.shiftTimeStart != null">shift_time_start = #{data.shiftTimeStart},</if>
+        <if test="data.shiftTimeEnd != null">shift_time_end = #{data.shiftTimeEnd},</if>
+        <if test="data.targetDeptId != null">target_dept_id = #{data.targetDeptId},</if>
+        <if test="data.createTime != null">create_time = #{data.createTime},</if>
+        <if test="data.createId != null">create_id = #{data.createId},</if>
+        <if test="data.updateTime != null">update_time = #{data.updateTime},</if>
+        <if test="data.updateId != null">update_id = #{data.updateId},</if>
+        <if test="data.deptId != null">dept_id = #{data.deptId},</if>
+        <if test="data.remark != null">remark = #{data.remark},</if>
+        <if test="data.createBy != null">create_by = #{data.createBy},</if>
+        <if test="data.updateBy != null">update_by = #{data.updateBy},</if>
+        <if test="data.deleted != null">deleted = #{data.deleted},</if>
+    </sql>
+
+    <delete id="deleteShiftByShiftId" parameterType="Long">
+        delete from bst_shift where shift_id = #{shiftId}
+    </delete>
+
+    <delete id="deleteShiftByShiftIds" parameterType="String">
+        delete from bst_shift where shift_id in
+        <foreach item="shiftId" collection="array" open="(" separator="," close=")">
+            #{shiftId}
+        </foreach>
+    </delete>
+</mapper>
diff --git a/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/service/IShiftService.java b/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/service/IShiftService.java
new file mode 100644
index 0000000..14b6a98
--- /dev/null
+++ b/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/service/IShiftService.java
@@ -0,0 +1,68 @@
+package com.ruoyi.yh.shift.service;
+
+import java.util.List;
+import com.ruoyi.yh.shift.domain.Shift;
+import com.ruoyi.yh.shift.domain.ShiftVO;
+import com.ruoyi.yh.shift.domain.ShiftQuery;
+
+/**
+ * 调班Service接口
+ *
+ * @author ruoyi
+ * @date 2024-12-07
+ */
+public interface IShiftService
+{
+    /**
+     * 查询调班
+     *
+     * @param shiftId 调班主键
+     * @return 调班
+     */
+    public ShiftVO selectShiftByShiftId(Long shiftId);
+
+    /**
+     * 查询调班列表
+     *
+     * @param shift 调班
+     * @return 调班集合
+     */
+    public List<ShiftVO> selectShiftList(ShiftQuery shift);
+
+    /**
+     * 新增调班
+     *
+     * @param shift 调班
+     * @return 结果
+     */
+    public int insertShift(Shift shift);
+
+    /**
+     * 修改调班
+     *
+     * @param shift 调班
+     * @return 结果
+     */
+    public int updateShift(Shift shift);
+
+    /**
+     * 批量删除调班
+     *
+     * @param shiftIds 需要删除的调班主键集合
+     * @return 结果
+     */
+    public int deleteShiftByShiftIds(Long[] shiftIds);
+
+    /**
+     * 删除调班信息
+     *
+     * @param shiftId 调班主键
+     * @return 结果
+     */
+    public int deleteShiftByShiftId(Long shiftId);
+
+    /**
+     * 逻辑删除
+     */
+    int logicDel(List<Long> shiftIds);
+}
diff --git a/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/service/ShiftConverter.java b/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/service/ShiftConverter.java
new file mode 100644
index 0000000..4631066
--- /dev/null
+++ b/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/service/ShiftConverter.java
@@ -0,0 +1,20 @@
+package com.ruoyi.yh.shift.service;
+
+import com.ruoyi.yh.shift.domain.Shift;
+
+/**
+ * @author wjh
+ * 2024/12/7
+ */
+public interface ShiftConverter {
+
+    /**
+     * 新增 po
+     */
+    Shift toPoByCreate(Shift data);
+
+    /**
+     * 修改 po
+     */
+    Shift toPoByUpdate(Shift data);
+}
diff --git a/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/service/impl/ShiftConverterImpl.java b/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/service/impl/ShiftConverterImpl.java
new file mode 100644
index 0000000..8955bdd
--- /dev/null
+++ b/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/service/impl/ShiftConverterImpl.java
@@ -0,0 +1,49 @@
+package com.ruoyi.yh.shift.service.impl;
+
+import com.ruoyi.yh.shift.domain.Shift;
+import com.ruoyi.yh.shift.service.ShiftConverter;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author wjh
+ * 2024/12/7
+ */
+@Service
+public class ShiftConverterImpl implements ShiftConverter {
+    @Override
+    public Shift toPoByCreate(Shift data) {
+        if (data == null) {
+            return null;
+        }
+
+        Shift po = new Shift();
+        po.setUserIds(data.getUserIds());
+        po.setShiftTimeStart(data.getShiftTimeStart());
+        po.setShiftTimeEnd(data.getShiftTimeEnd());
+        po.setTargetDeptId(data.getTargetDeptId());
+        po.setCreateId(data.getCreateId());
+        po.setDeptId(data.getDeptId());
+        po.setCreateBy(data.getCreateBy());
+        po.setRemark(data.getRemark());
+        return po;
+    }
+
+    @Override
+    public Shift toPoByUpdate(Shift data) {
+        if (data == null) {
+            return null;
+        }
+
+        Shift po = new Shift();
+        po.setShiftId(data.getShiftId());
+        po.setUserIds(data.getUserIds());
+        po.setShiftTimeStart(data.getShiftTimeStart());
+        po.setShiftTimeEnd(data.getShiftTimeEnd());
+        po.setTargetDeptId(data.getTargetDeptId());
+        po.setRemark(data.getRemark());
+        po.setUpdateId(data.getUpdateId());
+        po.setUpdateBy(data.getUpdateBy());
+        po.setUpdateId(data.getUpdateId());
+        return po;
+    }
+}
diff --git a/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/service/impl/ShiftServiceImpl.java b/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/service/impl/ShiftServiceImpl.java
new file mode 100644
index 0000000..7c9ef24
--- /dev/null
+++ b/common-ruoyi/ruoyi-system/src/main/java/com/ruoyi/yh/shift/service/impl/ShiftServiceImpl.java
@@ -0,0 +1,103 @@
+package com.ruoyi.yh.shift.service.impl;
+
+import java.util.List;
+import com.ruoyi.common.utils.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.yh.shift.mapper.ShiftMapper;
+import com.ruoyi.yh.shift.domain.Shift;
+import com.ruoyi.yh.shift.domain.ShiftVO;
+import com.ruoyi.yh.shift.domain.ShiftQuery;
+import com.ruoyi.yh.shift.service.IShiftService;
+
+/**
+ * 调班Service业务层处理
+ *
+ * @author ruoyi
+ * @date 2024-12-07
+ */
+@Service
+public class ShiftServiceImpl implements IShiftService
+{
+    @Autowired
+    private ShiftMapper shiftMapper;
+
+    /**
+     * 查询调班
+     *
+     * @param shiftId 调班主键
+     * @return 调班
+     */
+    @Override
+    public ShiftVO selectShiftByShiftId(Long shiftId)
+    {
+        return shiftMapper.selectShiftByShiftId(shiftId);
+    }
+
+    /**
+     * 查询调班列表
+     *
+     * @param shift 调班
+     * @return 调班
+     */
+    @Override
+    public List<ShiftVO> selectShiftList(ShiftQuery shift)
+    {
+        return shiftMapper.selectShiftList(shift);
+    }
+
+    /**
+     * 新增调班
+     *
+     * @param shift 调班
+     * @return 结果
+     */
+    @Override
+    public int insertShift(Shift shift)
+    {
+        shift.setCreateTime(DateUtils.getNowDate());
+        return shiftMapper.insertShift(shift);
+    }
+
+    /**
+     * 修改调班
+     *
+     * @param shift 调班
+     * @return 结果
+     */
+    @Override
+    public int updateShift(Shift shift)
+    {
+        shift.setUpdateTime(DateUtils.getNowDate());
+        return shiftMapper.updateShift(shift);
+    }
+
+    /**
+     * 批量删除调班
+     *
+     * @param shiftIds 需要删除的调班主键
+     * @return 结果
+     */
+    @Override
+    public int deleteShiftByShiftIds(Long[] shiftIds)
+    {
+        return shiftMapper.deleteShiftByShiftIds(shiftIds);
+    }
+
+    /**
+     * 删除调班信息
+     *
+     * @param shiftId 调班主键
+     * @return 结果
+     */
+    @Override
+    public int deleteShiftByShiftId(Long shiftId)
+    {
+        return shiftMapper.deleteShiftByShiftId(shiftId);
+    }
+
+    @Override
+    public int logicDel(List<Long> shiftIds) {
+        return shiftMapper.logicDel(shiftIds);
+    }
+}
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/system/SysUserController.java b/ruoyi-web/src/main/java/com/ruoyi/web/system/SysUserController.java
index 2f5a72d..445080f 100644
--- a/ruoyi-web/src/main/java/com/ruoyi/web/system/SysUserController.java
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/system/SysUserController.java
@@ -4,9 +4,11 @@ import java.util.List;
 import java.util.stream.Collectors;
 import javax.servlet.http.HttpServletResponse;
 
+import com.ruoyi.common.annotation.DataScope;
 import com.ruoyi.common.core.validate.ValidGroup;
 import com.ruoyi.system.domain.dto.SysDeptQuery;
 import com.ruoyi.system.user.domain.SysUserQuery;
+import com.ruoyi.system.user.domain.SysUserShiftQuery;
 import com.ruoyi.system.user.domain.SysUserVO;
 import org.apache.commons.lang3.ArrayUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -78,11 +80,21 @@ public class SysUserController extends BaseController
     {
         SysUserQuery query = new SysUserQuery();
         query.setUserIds(userIds);
-        query.setNeedScope(true);
-        List<SysUserVO> list = userService.selectUserListScope(query);
+        List<SysUserVO> list = userService.selectUserList(query);
         return success(list);
     }
 
+    /**
+     * 获取包含调班的用户列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:user:list')")
+    @GetMapping("/shiftList")
+    @DataScope(deptAlias = "d,sdt")
+    public TableDataInfo shiftList(SysUserShiftQuery query) {
+        startPage();
+        return getDataTable(userService.selectUserWithShiftList(query));
+    }
+
     @Log(title = "用户管理", businessType = BusinessType.EXPORT)
     @PreAuthorize("@ss.hasPermi('system:user:export')")
     @PostMapping("/export")
@@ -237,4 +249,5 @@ public class SysUserController extends BaseController
     {
         return success(deptService.selectDeptTreeList(dept));
     }
+
 }
diff --git a/ruoyi-web/src/main/java/com/ruoyi/web/yh/ShiftController.java b/ruoyi-web/src/main/java/com/ruoyi/web/yh/ShiftController.java
new file mode 100644
index 0000000..61b3463
--- /dev/null
+++ b/ruoyi-web/src/main/java/com/ruoyi/web/yh/ShiftController.java
@@ -0,0 +1,140 @@
+package com.ruoyi.web.yh;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.ruoyi.common.annotation.DataScope;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.enums.LogBizType;
+import com.ruoyi.yh.shift.service.ShiftConverter;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.yh.shift.domain.Shift;
+import com.ruoyi.yh.shift.domain.ShiftVO;
+import com.ruoyi.yh.shift.domain.ShiftQuery;
+import com.ruoyi.yh.shift.service.IShiftService;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * 调班Controller
+ *
+ * @author ruoyi
+ * @date 2024-12-07
+ */
+@RestController
+@RequestMapping("/yh/shift")
+public class ShiftController extends BaseController
+{
+    @Autowired
+    private IShiftService shiftService;
+
+    @Autowired
+    private ShiftConverter shiftConverter;
+
+    /**
+     * 查询本部门创建的调班列表
+     */
+    @PreAuthorize("@ss.hasPermi('yh:shift:list')")
+    @GetMapping("/list")
+    @DataScope(deptAlias = "sd")
+    public TableDataInfo list(ShiftQuery query)
+    {
+        startPage();
+        startOrderBy();
+        List<ShiftVO> list = shiftService.selectShiftList(query);
+        return getDataTable(list);
+    }
+
+    /**
+     * 查询调到本部门的调班列表
+     */
+    @PreAuthorize("@ss.hasPermi('yh:shift:list')")
+    @GetMapping("/targetList")
+    @DataScope(deptAlias = "sdt")
+    public TableDataInfo targetList(ShiftQuery query) {
+        startPage();
+        startOrderBy();
+        List<ShiftVO> list = shiftService.selectShiftList(query);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出调班列表
+     */
+    @PreAuthorize("@ss.hasPermi('yh:shift:export')")
+    @Log(title = "调班", businessType = BusinessType.EXPORT, bizType = LogBizType.SHIFT)
+    @PostMapping("/export")
+    @DataScope(deptAlias = "sd")
+    public void export(HttpServletResponse response, ShiftQuery query)
+    {
+        List<ShiftVO> list = shiftService.selectShiftList(query);
+        ExcelUtil<ShiftVO> util = new ExcelUtil<ShiftVO>(ShiftVO.class);
+        util.exportExcel(response, list, "调班数据");
+    }
+
+    /**
+     * 获取调班详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('yh:shift:query')")
+    @GetMapping(value = "/{shiftId}")
+    public AjaxResult getInfo(@PathVariable("shiftId") Long shiftId)
+    {
+        return success(shiftService.selectShiftByShiftId(shiftId));
+    }
+
+    /**
+     * 新增调班
+     */
+    @PreAuthorize("@ss.hasPermi('yh:shift:add')")
+    @Log(title = "调班", businessType = BusinessType.INSERT, bizType = LogBizType.SHIFT, bizIdName = "arg0")
+    @PostMapping
+    public AjaxResult add(@RequestBody Shift shift)
+    {
+        SysUser user = getLoginUser().getUser();
+        shift.setCreateId(user.getUserId());
+        shift.setCreateBy(user.getNickName());
+        shift.setDeptId(user.getDeptId());
+        Shift po = shiftConverter.toPoByCreate(shift);
+        return toAjax(shiftService.insertShift(po));
+    }
+
+    /**
+     * 修改调班
+     */
+    @PreAuthorize("@ss.hasPermi('yh:shift:edit')")
+    @Log(title = "调班", businessType = BusinessType.UPDATE, bizType = LogBizType.SHIFT, bizIdName = "arg0")
+    @PutMapping
+    public AjaxResult edit(@RequestBody Shift shift)
+    {
+        SysUser user = getLoginUser().getUser();
+        shift.setUpdateId(user.getUserId());
+        shift.setUpdateBy(user.getNickName());
+        Shift po = shiftConverter.toPoByUpdate(shift);
+        return toAjax(shiftService.updateShift(po));
+    }
+
+    /**
+     * 删除调班
+     */
+    @PreAuthorize("@ss.hasPermi('yh:shift:remove')")
+    @Log(title = "调班", businessType = BusinessType.DELETE, bizType = LogBizType.SHIFT, bizIdName = "arg0")
+	@DeleteMapping("/{shiftIds}")
+    public AjaxResult remove(@PathVariable List<Long> shiftIds)
+    {
+        return toAjax(shiftService.logicDel(shiftIds));
+    }
+}