“培训申请修复v1.3”
This commit is contained in:
1 parent
53e5afaafe
commit
4fbd380a07
3 files changed
+239
-115
No files matched your search
+55
@@ -0,0 +1,55 @@
|
||||
package org.dromara.rs.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 用户基本信息VO
|
||||
* 用于培训申请/记录中的同行人信息展示
|
||||
* 不限制账号类型,只返回必要的基础信息
|
||||
*
|
||||
* @author weizzzz
|
||||
* @date 2025-11-06
|
||||
*/
|
||||
@Data
|
||||
public class SysUserBasicVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 用户账号
|
||||
*/
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 用户昵称(真实姓名)
|
||||
*/
|
||||
private String nickName;
|
||||
|
||||
/**
|
||||
* 账号类型(0-学生 1-教师 2-其他)
|
||||
*/
|
||||
private String accountType;
|
||||
|
||||
/**
|
||||
* 账号状态(0-正常 1-停用)
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 部门ID
|
||||
*/
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 部门名称
|
||||
*/
|
||||
private String deptName;
|
||||
}
|
||||
+125
-111
@@ -5,6 +5,8 @@ import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.dromara.common.mybatis.annotation.DataColumn;
|
||||
import org.dromara.common.mybatis.annotation.DataPermission;
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
import org.dromara.system.domain.SysUser;
|
||||
import org.dromara.system.domain.vo.SysTeacherVo;
|
||||
@@ -28,25 +30,26 @@ public interface SysTeacherMapper extends BaseMapperPlus<SysUser, SysTeacherVo>
|
||||
* @return 教师信息分页列表
|
||||
*/
|
||||
@Select("""
|
||||
SELECT
|
||||
u.user_id,
|
||||
u.user_name,
|
||||
u.nick_name,
|
||||
u.phonenumber,
|
||||
u.email,
|
||||
u.dept_id,
|
||||
d.dept_name,
|
||||
u.sex,
|
||||
u.status,
|
||||
u.create_time
|
||||
FROM sys_user u
|
||||
LEFT JOIN sys_dept d ON u.dept_id = d.dept_id
|
||||
WHERE u.del_flag = '0'
|
||||
AND u.account_type = '1'
|
||||
${ew.customSqlSegment}
|
||||
ORDER BY u.create_time DESC
|
||||
""")
|
||||
Page<SysTeacherVo> selectPageTeacherList(@Param("page") Page<SysTeacherVo> page, @Param(Constants.WRAPPER) Wrapper<SysUser> wrapper);
|
||||
SELECT
|
||||
u.user_id,
|
||||
u.user_name,
|
||||
u.nick_name,
|
||||
u.phonenumber,
|
||||
u.email,
|
||||
u.dept_id,
|
||||
d.dept_name,
|
||||
u.sex,
|
||||
u.status,
|
||||
u.create_time
|
||||
FROM sys_user u
|
||||
LEFT JOIN sys_dept d ON u.dept_id = d.dept_id
|
||||
WHERE u.del_flag = '0'
|
||||
AND u.account_type = '1'
|
||||
${ew.customSqlSegment}
|
||||
ORDER BY u.create_time DESC
|
||||
""")
|
||||
Page<SysTeacherVo> selectPageTeacherList(@Param("page") Page<SysTeacherVo> page,
|
||||
@Param(Constants.WRAPPER) Wrapper<SysUser> wrapper);
|
||||
|
||||
/**
|
||||
* 查询教师信息列表
|
||||
@@ -55,24 +58,24 @@ public interface SysTeacherMapper extends BaseMapperPlus<SysUser, SysTeacherVo>
|
||||
* @return 教师信息列表
|
||||
*/
|
||||
@Select("""
|
||||
SELECT
|
||||
u.user_id,
|
||||
u.user_name,
|
||||
u.nick_name,
|
||||
u.phonenumber,
|
||||
u.email,
|
||||
u.dept_id,
|
||||
d.dept_name,
|
||||
u.sex,
|
||||
u.status,
|
||||
u.create_time
|
||||
FROM sys_user u
|
||||
LEFT JOIN sys_dept d ON u.dept_id = d.dept_id
|
||||
WHERE u.del_flag = '0'
|
||||
AND u.account_type = '1'
|
||||
${ew.customSqlSegment}
|
||||
ORDER BY u.create_time DESC
|
||||
""")
|
||||
SELECT
|
||||
u.user_id,
|
||||
u.user_name,
|
||||
u.nick_name,
|
||||
u.phonenumber,
|
||||
u.email,
|
||||
u.dept_id,
|
||||
d.dept_name,
|
||||
u.sex,
|
||||
u.status,
|
||||
u.create_time
|
||||
FROM sys_user u
|
||||
LEFT JOIN sys_dept d ON u.dept_id = d.dept_id
|
||||
WHERE u.del_flag = '0'
|
||||
AND u.account_type = '1'
|
||||
${ew.customSqlSegment}
|
||||
ORDER BY u.create_time DESC
|
||||
""")
|
||||
List<SysTeacherVo> selectTeacherList(@Param(Constants.WRAPPER) Wrapper<SysUser> wrapper);
|
||||
|
||||
/**
|
||||
@@ -83,78 +86,89 @@ public interface SysTeacherMapper extends BaseMapperPlus<SysUser, SysTeacherVo>
|
||||
* @return 教师信息列表
|
||||
*/
|
||||
@Select("""
|
||||
SELECT
|
||||
u.user_id,
|
||||
u.user_name,
|
||||
u.nick_name,
|
||||
u.phonenumber,
|
||||
u.email,
|
||||
u.dept_id,
|
||||
d.dept_name,
|
||||
u.sex,
|
||||
u.status,
|
||||
u.create_time
|
||||
FROM sys_user u
|
||||
LEFT JOIN sys_dept d ON u.dept_id = d.dept_id
|
||||
WHERE u.del_flag = '0'
|
||||
AND u.account_type = '1'
|
||||
AND (u.nick_name LIKE CONCAT('%', #{name}, '%')
|
||||
OR u.user_name LIKE CONCAT('%', #{name}, '%')
|
||||
OR u.phonenumber LIKE CONCAT('%', #{name}, '%'))
|
||||
AND u.status = '0'
|
||||
ORDER BY u.create_time DESC
|
||||
LIMIT #{limit}
|
||||
""")
|
||||
SELECT
|
||||
u.user_id,
|
||||
u.user_name,
|
||||
u.nick_name,
|
||||
u.phonenumber,
|
||||
u.email,
|
||||
u.dept_id,
|
||||
d.dept_name,
|
||||
u.sex,
|
||||
u.status,
|
||||
u.create_time
|
||||
FROM sys_user u
|
||||
LEFT JOIN sys_dept d ON u.dept_id = d.dept_id
|
||||
WHERE u.del_flag = '0'
|
||||
AND u.account_type = '1'
|
||||
AND (u.nick_name LIKE CONCAT('%', #{name}, '%')
|
||||
OR u.user_name LIKE CONCAT('%', #{name}, '%')
|
||||
OR u.phonenumber LIKE CONCAT('%', #{name}, '%'))
|
||||
AND u.status = '0'
|
||||
ORDER BY u.create_time DESC
|
||||
LIMIT #{limit}
|
||||
""")
|
||||
List<SysTeacherVo> searchTeachersByName(@Param("name") String name, @Param("limit") Integer limit);
|
||||
|
||||
/**
|
||||
* 根据部门ID获取教师列表
|
||||
* 根据部门ID获取教师列表(带数据权限控制)
|
||||
*
|
||||
* 说明:添加数据权限注解后,只会返回用户有权限访问的部门的教师
|
||||
*
|
||||
* @param deptId 部门ID
|
||||
* @return 教师信息列表
|
||||
*/
|
||||
@DataPermission({
|
||||
@DataColumn(key = "deptName", value = "u.dept_id")
|
||||
})
|
||||
@Select("""
|
||||
SELECT
|
||||
u.user_id,
|
||||
u.user_name,
|
||||
u.nick_name,
|
||||
u.phonenumber,
|
||||
u.email,
|
||||
u.dept_id,
|
||||
d.dept_name,
|
||||
u.sex,
|
||||
u.status,
|
||||
u.create_time
|
||||
FROM sys_user u
|
||||
LEFT JOIN sys_dept d ON u.dept_id = d.dept_id
|
||||
WHERE u.del_flag = '0'
|
||||
AND u.account_type = '1'
|
||||
AND u.dept_id = #{deptId}
|
||||
AND u.status = '0'
|
||||
ORDER BY u.create_time DESC
|
||||
""")
|
||||
SELECT
|
||||
u.user_id,
|
||||
u.user_name,
|
||||
u.nick_name,
|
||||
u.phonenumber,
|
||||
u.email,
|
||||
u.dept_id,
|
||||
d.dept_name,
|
||||
u.sex,
|
||||
u.status,
|
||||
u.create_time
|
||||
FROM sys_user u
|
||||
LEFT JOIN sys_dept d ON u.dept_id = d.dept_id
|
||||
WHERE u.del_flag = '0'
|
||||
AND u.account_type = '1'
|
||||
AND u.dept_id = #{deptId}
|
||||
AND u.status = '0'
|
||||
ORDER BY u.create_time DESC
|
||||
""")
|
||||
List<SysTeacherVo> selectTeachersByDeptId(@Param("deptId") Long deptId);
|
||||
|
||||
/**
|
||||
* 获取部门树形结构(只包含有教师的部门)
|
||||
* 获取部门树形结构(只包含有教师且用户有权限访问的部门)
|
||||
*
|
||||
* 说明:添加数据权限注解后,只会返回用户有权限访问的部门
|
||||
* 这样可以避免在同行人选择器中显示用户无权访问的部门
|
||||
*
|
||||
* @return 部门树信息集合
|
||||
*/
|
||||
@DataPermission({
|
||||
@DataColumn(key = "deptName", value = "d.dept_id")
|
||||
})
|
||||
@Select("""
|
||||
SELECT DISTINCT
|
||||
d.dept_id as id,
|
||||
d.parent_id,
|
||||
d.dept_name as label,
|
||||
d.order_num
|
||||
FROM sys_dept d
|
||||
INNER JOIN sys_user u ON d.dept_id = u.dept_id
|
||||
WHERE d.del_flag = '0'
|
||||
AND d.status = '0'
|
||||
AND u.del_flag = '0'
|
||||
AND u.account_type = '1'
|
||||
AND u.status = '0'
|
||||
ORDER BY d.order_num
|
||||
""")
|
||||
SELECT DISTINCT
|
||||
d.dept_id as id,
|
||||
d.parent_id,
|
||||
d.dept_name as label,
|
||||
d.order_num
|
||||
FROM sys_dept d
|
||||
INNER JOIN sys_user u ON d.dept_id = u.dept_id
|
||||
WHERE d.del_flag = '0'
|
||||
AND d.status = '0'
|
||||
AND u.del_flag = '0'
|
||||
AND u.account_type = '1'
|
||||
AND u.status = '0'
|
||||
ORDER BY d.order_num
|
||||
""")
|
||||
List<SysDeptTreeVo> selectDeptTreeWithTeachers();
|
||||
|
||||
/**
|
||||
@@ -164,21 +178,21 @@ public interface SysTeacherMapper extends BaseMapperPlus<SysUser, SysTeacherVo>
|
||||
* @return 父级部门信息集合
|
||||
*/
|
||||
@Select("""
|
||||
<script>
|
||||
SELECT DISTINCT
|
||||
dept_id as id,
|
||||
parent_id,
|
||||
dept_name as label,
|
||||
order_num
|
||||
FROM sys_dept
|
||||
WHERE del_flag = '0'
|
||||
AND status = '0'
|
||||
AND dept_id IN
|
||||
<foreach collection="deptIds" item="deptId" open="(" separator="," close=")">
|
||||
#{deptId}
|
||||
</foreach>
|
||||
ORDER BY order_num
|
||||
</script>
|
||||
""")
|
||||
<script>
|
||||
SELECT DISTINCT
|
||||
dept_id as id,
|
||||
parent_id,
|
||||
dept_name as label,
|
||||
order_num
|
||||
FROM sys_dept
|
||||
WHERE del_flag = '0'
|
||||
AND status = '0'
|
||||
AND dept_id IN
|
||||
<foreach collection="deptIds" item="deptId" open="(" separator="," close=")">
|
||||
#{deptId}
|
||||
</foreach>
|
||||
ORDER BY order_num
|
||||
</script>
|
||||
""")
|
||||
List<SysDeptTreeVo> selectDeptsByIds(@Param("deptIds") List<Long> deptIds);
|
||||
}
|
||||
}
|
||||
@@ -64,6 +64,15 @@
|
||||
<!-- 右侧教师列表 -->
|
||||
<div class="teacher-panel">
|
||||
<div v-if="!selectedDeptId" class="empty-tip">请选择左侧部门查看教师列表</div>
|
||||
<div v-else-if="loading" class="empty-tip">
|
||||
<el-icon class="is-loading"><Loading /></el-icon>
|
||||
<span style="margin-left: 8px">加载中...</span>
|
||||
</div>
|
||||
<div v-else-if="permissionDenied" class="permission-denied-tip">
|
||||
<el-icon><Lock /></el-icon>
|
||||
<p>您没有权限查看该部门的教师信息</p>
|
||||
<p class="tip-desc">请联系管理员配置数据权限或选择其他部门</p>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="panel-header">
|
||||
<span>{{ selectedDeptName }} - 教师列表</span>
|
||||
@@ -100,7 +109,7 @@
|
||||
性别:{{ teacher.sex === '0' ? '男' : teacher.sex === '1' ? '女' : '未知' }} | 电话:{{ teacher.phonenumber || '暂无' }} | 邮箱:{{ teacher.email || '暂无' }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="filteredTeachers.length === 0" class="empty-tip">暂无教师数据</div>
|
||||
<div v-if="filteredTeachers.length === 0 && !permissionDenied" class="empty-tip">该部门暂无教师数据</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -118,7 +127,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch, onMounted, nextTick } from 'vue';
|
||||
import { Search } from '@element-plus/icons-vue';
|
||||
import { Search, Loading, Lock } from '@element-plus/icons-vue';
|
||||
import { getDeptTreeData, getTeachersByDeptId } from '@/api/system/teacher';
|
||||
import { TeacherVO, DeptTreeNode } from '@/api/system/teacher/types';
|
||||
import { ElMessage } from 'element-plus';
|
||||
@@ -152,6 +161,8 @@ const treeData = ref<DeptTreeNode[]>([]);
|
||||
const teacherList = ref<TeacherVO[]>([]);
|
||||
const selectedDeptId = ref<number | null>(null);
|
||||
const selectedDeptName = ref('');
|
||||
const loading = ref(false); // 加载状态
|
||||
const permissionDenied = ref(false); // 权限被拒标识
|
||||
|
||||
// 显示值计算
|
||||
const displayValue = computed(() => {
|
||||
@@ -230,6 +241,8 @@ const closeDialog = () => {
|
||||
selectedDeptName.value = '';
|
||||
teacherList.value = [];
|
||||
teacherSearchText.value = '';
|
||||
loading.value = false;
|
||||
permissionDenied.value = false;
|
||||
}, 300);
|
||||
};
|
||||
|
||||
@@ -290,14 +303,34 @@ const handleTreeNodeClick = async (data: DeptTreeNode) => {
|
||||
selectedDeptId.value = Number(data.id);
|
||||
selectedDeptName.value = data.label;
|
||||
teacherSearchText.value = '';
|
||||
loading.value = true;
|
||||
permissionDenied.value = false;
|
||||
|
||||
try {
|
||||
const response = await getTeachersByDeptId(Number(data.id));
|
||||
teacherList.value = response.data || [];
|
||||
} catch (error) {
|
||||
ElMessage.error('加载教师列表失败');
|
||||
|
||||
// 如果返回空列表,可能是权限问题(也可能真的没有教师)
|
||||
// 后端添加数据权限后,无权限的部门会被过滤,理论上不会出现在部门树中
|
||||
// 但为了更好的用户体验,仍然保留这个逻辑
|
||||
if (teacherList.value.length === 0) {
|
||||
console.log(`部门 ${data.label} 没有教师数据`);
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error('加载教师列表失败:', error);
|
||||
|
||||
// 根据错误信息判断是否为权限问题
|
||||
const errorMsg = error?.msg || error?.message || '';
|
||||
if (error?.code === 403 || errorMsg.includes('权限') || errorMsg.includes('permission')) {
|
||||
permissionDenied.value = true;
|
||||
console.warn(`用户没有权限访问部门 ${data.label} 的教师列表`);
|
||||
} else {
|
||||
ElMessage.error('加载教师列表失败');
|
||||
}
|
||||
|
||||
teacherList.value = [];
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -424,6 +457,28 @@ onMounted(() => {
|
||||
padding: 40px 0;
|
||||
}
|
||||
|
||||
.permission-denied-tip {
|
||||
text-align: center;
|
||||
padding: 60px 20px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.permission-denied-tip .el-icon {
|
||||
font-size: 48px;
|
||||
color: #f56c6c;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.permission-denied-tip p {
|
||||
margin: 8px 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.permission-denied-tip .tip-desc {
|
||||
font-size: 12px;
|
||||
color: #c0c4cc;
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
Reference in new issue
Block a user