package com.xjrsoft.module.organization.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.secure.BCrypt;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.type.TypeReference;
import com.github.yulichang.toolkit.MPJWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.xjrsoft.common.annotation.XjrLog;
import com.xjrsoft.common.constant.GlobalConstant;
import com.xjrsoft.common.enums.*;
import com.xjrsoft.common.exception.MyException;
import com.xjrsoft.common.model.result.R;
import com.xjrsoft.common.model.result.RT;
import com.xjrsoft.common.page.ConventPage;
import com.xjrsoft.common.page.PageOutput;
import com.xjrsoft.common.sms.SmsCtcc;
import com.xjrsoft.common.utils.RedisUtil;
import com.xjrsoft.common.utils.TreeUtil;
import com.xjrsoft.common.utils.UploadUtil;
import com.xjrsoft.common.utils.VoToColumnUtil;
import com.xjrsoft.config.FileCheckRuleConfig;
import com.xjrsoft.module.base.entity.BaseClass;
import com.xjrsoft.module.base.entity.BaseGrade;
import com.xjrsoft.module.base.entity.WhitelistManagement;
import com.xjrsoft.module.base.service.IBaseClassService;
import com.xjrsoft.module.base.service.IBaseGradeService;
import com.xjrsoft.module.base.service.IWhitelistManagementService;
import com.xjrsoft.module.hikvision.util.DataUtil;
import com.xjrsoft.module.oa.dto.OfficialDocumentReceivedHandlePageDto;
import com.xjrsoft.module.oa.service.IOfficialDocumentReceivedHandleService;
import com.xjrsoft.module.oa.vo.OfficialDocumentReceivedHandlePageVo;
import com.xjrsoft.module.organization.dto.*;
import com.xjrsoft.module.organization.entity.*;
import com.xjrsoft.module.organization.service.*;
import com.xjrsoft.module.organization.utils.OrganizationUtil;
import com.xjrsoft.module.organization.vo.*;
import com.xjrsoft.module.oss.factory.OssFactory;
import com.xjrsoft.module.student.entity.BaseNewStudent;
import com.xjrsoft.module.student.entity.BaseStudent;
import com.xjrsoft.module.student.entity.BaseStudentSchoolRoll;
import com.xjrsoft.module.student.entity.BaseStudentUser;
import com.xjrsoft.module.student.service.IBaseNewStudentService;
import com.xjrsoft.module.student.service.IBaseStudentSchoolRollService;
import com.xjrsoft.module.system.entity.DictionaryDetail;
import com.xjrsoft.module.system.entity.File;
import com.xjrsoft.module.system.service.IFileService;
import com.xjrsoft.module.teacher.entity.BaseTeacher;
import com.xjrsoft.module.teacher.entity.BaseTeacherRegular;
import com.xjrsoft.module.teacher.entity.XjrUser;
import com.xjrsoft.module.workflow.constant.WorkflowConstant;
import com.xjrsoft.module.workflow.entity.WorkflowCirculated;
import com.xjrsoft.module.workflow.entity.WorkflowExtra;
import com.xjrsoft.module.workflow.entity.WorkflowFormRelation;
import com.xjrsoft.module.workflow.entity.WorkflowSchema;
import com.xjrsoft.module.workflow.service.IWorkflowCirculatedService;
import com.xjrsoft.module.workflow.service.IWorkflowExecuteService;
import com.xjrsoft.module.workflow.service.IWorkflowExtraService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.ObjectUtils;
import org.camunda.bpm.engine.HistoryService;
import org.camunda.bpm.engine.history.HistoricProcessInstance;
import org.camunda.bpm.engine.history.HistoricProcessInstanceQuery;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
/**
*
* 用户 前端控制器
*
*
* @author tzx
* @since 2022-03-02
*/
@RestController
@RequestMapping(GlobalConstant.ORGANIZATION_MODULE_PREFIX + "/user")
@Api(value = GlobalConstant.ORGANIZATION_MODULE_PREFIX + "/user", tags = "用户")
@AllArgsConstructor
public class UserController {
private final IUserService userService;
private final IDepartmentService departmentService;
private final IPostService postService;
private final IRoleService roleService;
private final IUserRoleRelationService userRoleRelationService;
private final IUserDeptRelationService userDeptRelationService;
private final IUserPostRelationService userPostRelationService;
private final RedisUtil redisUtil;
private final IFileService fileService;
private final SmsCtcc smsCtcc;
private final IBaseGradeService baseGradeService;
private final IUserStudentService userStudentService;
private final IBaseClassService baseClassService;
private final IWorkflowExecuteService workflowExecuteService;
private final HistoryService historyService;
private final IBaseStudentSchoolRollService baseStudentSchoolRollService;
private final IWhitelistManagementService whitelistManagementService;
private final IWorkflowCirculatedService circulatedService;
private final IBaseNewStudentService baseNewStudentService;
private final IWorkflowExtraService workflowExtraService;
private final IOfficialDocumentReceivedHandleService documentReceivedHandleService;
@GetMapping(value = "/list")
@ApiOperation(value = "用户列表(不分页)")
@SaCheckPermission("user:list")
@XjrLog(value = "用户列表(不分页)")
public R list(String keyword) {
List list = userService.list(Wrappers.lambdaQuery(User.class)
.like(StrUtil.isNotBlank(keyword), User::getUserName, keyword)
.like(StrUtil.isNotBlank(keyword), User::getCode, keyword)
.like(StrUtil.isNotBlank(keyword), User::getName, keyword)
.like(StrUtil.isNotBlank(keyword), User::getMobile, keyword)
.select(User.class, x -> VoToColumnUtil.fieldsToColumns(UserListVo.class).contains(x.getProperty())));
List userListVos = BeanUtil.copyToList(list, UserListVo.class);
return R.ok(userListVos);
}
@GetMapping(value = "/page")
@ApiOperation(value = "用户列表(分页)")
@SaCheckPermission("user:page")
@XjrLog(value = "用户列表(分页)")
public R page(UserPageDto dto) {
List deptIds = new ArrayList<>();
if (ObjectUtil.isNotNull(dto.getDepartmentId())) {
List list = redisUtil.get(GlobalConstant.DEP_CACHE_KEY, new TypeReference>() {
});
//当前部门的层级
String hierarchy = list.stream().filter(x -> x.getId().equals(dto.getDepartmentId())).findFirst().orElse(new Department()).getHierarchy();
if (StrUtil.isNotBlank(hierarchy)) {
//层级里面包含当前部门层级的就是它的子集,如1-1,下面包含了1-1、1-1-2这种
deptIds = list.stream().filter(x -> StrUtil.isNotBlank(x.getHierarchy()) && x.getHierarchy().contains(hierarchy)).map(Department::getId).collect(Collectors.toList());
} else {
//如果不存在层级就查询自己的数据
deptIds.add(dto.getDepartmentId());
}
}
//因为多表关联 会有多个表都使用了id字段, 所以必须专门指定主表的Id
if (ObjectUtil.isNotNull(dto.getDepartmentId())) {//不为空联合查询
MPJLambdaWrapper queryUser = new MPJLambdaWrapper<>();
queryUser
.disableSubLogicDel()
.distinct()
.like(StrUtil.isNotBlank(dto.getKeyword()), User::getName, dto.getKeyword())
.or(StrUtil.isNotBlank(dto.getKeyword()), x -> x.like(StrUtil.isNotBlank(dto.getKeyword()), User::getCode, dto.getKeyword()))
.in(ObjectUtil.isNotNull(dto.getDepartmentId()), UserDeptRelation::getDeptId, deptIds)
.like(StrUtil.isNotBlank(dto.getUserName()), User::getUserName, dto.getUserName())
.like(StrUtil.isNotBlank(dto.getCode()), User::getCode, dto.getCode())
.like(StrUtil.isNotBlank(dto.getName()), User::getName, dto.getName())
.like(StrUtil.isNotBlank(dto.getTeachingStatus()), BaseTeacherRegular::getTeachingStatus, dto.getTeachingStatus())
.like(StrUtil.isNotBlank(dto.getMobile()), User::getMobile, dto.getMobile())
.eq((ObjectUtil.isNotNull(dto.getTreeType()) && dto.getTreeType() == 1), Role::getId, dto.getTreeId())
.eq((ObjectUtil.isNotNull(dto.getTreeType()) && dto.getTreeType() == 2), UserDeptRelation::getDeptId, dto.getTreeId())
.eq((ObjectUtil.isNotNull(dto.getTreeType()) && dto.getTreeType() == 3), BaseStudentSchoolRoll::getGradeId, dto.getTreeId())
.eq((ObjectUtil.isNotNull(dto.getTreeType()) && dto.getTreeType() == 4), BaseStudentSchoolRoll::getClassId, dto.getTreeId())
.eq(ObjectUtils.isNotEmpty(dto.getUserType()) && dto.getUserType() != 0, Role::getId, dto.getUserType())
.eq(ObjectUtil.isNotNull(dto.getEmployType()), BaseTeacher::getEmployType, dto.getEmployType())
.eq(ObjectUtil.isNotNull(dto.getEmployWay()), BaseTeacher::getEmployWay, dto.getEmployWay())
.eq(ObjectUtil.isNotNull(dto.getClassId()), BaseStudentSchoolRoll::getClassId, dto.getClassId())
.eq(ObjectUtil.isNotNull(dto.getRoleId()), UserRoleRelation::getRoleId, dto.getRoleId())
.eq(ObjectUtil.isNotNull(dto.getIsTeach()), BaseTeacherRegular::getIsTeach, dto.getIsTeach())
.orderByDesc(User::getId)
.select(User::getId)
.select("d1.name", UserPageVo::getEmployWay)
.select("d2.name", UserPageVo::getEmployType)
.selectAs(BaseStudentSchoolRoll::getClassId, UserPageVo::getClassId)
.select(User.class, x -> VoToColumnUtil.fieldsToColumns(UserPageVo.class).contains(x.getProperty()))
.leftJoin(UserDeptRelation.class, UserDeptRelation::getUserId, User::getId)
.leftJoin(UserRoleRelation.class, UserRoleRelation::getUserId, User::getId)
.leftJoin(BaseTeacher.class, BaseTeacher::getUserId, User::getId)
.leftJoin(BaseTeacherRegular.class, BaseTeacherRegular::getUserId, User::getId)
.leftJoin(BaseStudentSchoolRoll.class, BaseStudentSchoolRoll::getUserId, User::getId)
.leftJoin(DictionaryDetail.class, "d1", DictionaryDetail::getCode, BaseTeacher::getEmployWay)
.leftJoin(DictionaryDetail.class, "d2", DictionaryDetail::getCode, BaseTeacher::getEmployType)
.leftJoin(Role.class, Role::getId, UserRoleRelation::getRoleId);
if (ObjectUtil.isNotNull(dto.getUserType())) {
if (dto.getUserType() == 2) {
queryUser.eq(BaseTeacher::getIsNormal, 1);
}
if (dto.getUserType() == 3) {
queryUser.leftJoin(BaseStudent.class, BaseStudent::getUserId, User::getId)
.eq(BaseStudent::getIsNormal, 1);
}
}
IPage page = userService.selectJoinListPage(ConventPage.getPage(dto), UserPageVo.class, queryUser);
for (UserPageVo record : page.getRecords()) {
record.setGenderCn(GenderDictionaryEnum.getValue(record.getGender()));
}
PageOutput pageOutput = ConventPage.getPageOutput(page, UserPageVo.class);
return R.ok(pageOutput);
} else {
// LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
// queryWrapper.like(StrUtil.isNotBlank(dto.getKeyword()), User::getName, dto.getKeyword())
// .or(StrUtil.isNotBlank(dto.getKeyword()), x -> x.like(StrUtil.isNotBlank(dto.getKeyword()), User::getCode, dto.getKeyword()))
// .like(StrUtil.isNotBlank(dto.getUserName()), User::getUserName, dto.getUserName())
// .like(StrUtil.isNotBlank(dto.getCode()), User::getCode, dto.getCode())
// .like(StrUtil.isNotBlank(dto.getName()), User::getName, dto.getName())
// .like(StrUtil.isNotBlank(dto.getMobile()), User::getMobile, dto.getMobile())
// .orderByDesc(User::getCreateDate)
// .select(User.class, x -> VoToColumnUtil.fieldsToColumns(UserPageVo.class).contains(x.getProperty()));
//
// IPage page = userService.page(ConventPage.getPage(dto),queryWrapper);
MPJLambdaWrapper queryUser = new MPJLambdaWrapper<>();
queryUser
.disableSubLogicDel()
.distinct()
.like(StrUtil.isNotBlank(dto.getKeyword()), User::getName, dto.getKeyword())
.or(StrUtil.isNotBlank(dto.getKeyword()), x -> x.like(StrUtil.isNotBlank(dto.getKeyword()), User::getCode, dto.getKeyword()))
.like(StrUtil.isNotBlank(dto.getUserName()), User::getUserName, dto.getUserName())
.like(StrUtil.isNotBlank(dto.getCode()), User::getCode, dto.getCode())
.like(StrUtil.isNotBlank(dto.getName()), User::getName, dto.getName())
.like(StrUtil.isNotBlank(dto.getMobile()), User::getMobile, dto.getMobile())
.like(StrUtil.isNotBlank(dto.getTeachingStatus()), BaseTeacherRegular::getTeachingStatus, dto.getTeachingStatus())
.eq(ObjectUtil.isNotNull(dto.getUserType()), Role::getId, dto.getUserType())
.eq((ObjectUtil.isNotNull(dto.getTreeType()) && dto.getTreeType() == 1), Role::getId, dto.getTreeId())
.eq((ObjectUtil.isNotNull(dto.getTreeType()) && dto.getTreeType() == 2), UserDeptRelation::getDeptId, dto.getTreeId())
.eq((ObjectUtil.isNotNull(dto.getTreeType()) && dto.getTreeType() == 3), BaseStudentSchoolRoll::getGradeId, dto.getTreeId())
.eq((ObjectUtil.isNotNull(dto.getTreeType()) && dto.getTreeType() == 4), BaseStudentSchoolRoll::getClassId, dto.getTreeId())
.eq(ObjectUtil.isNotNull(dto.getEmployType()), BaseTeacher::getEmployType, dto.getEmployType())
.eq(ObjectUtil.isNotNull(dto.getEmployWay()), BaseTeacher::getEmployWay, dto.getEmployWay())
.eq(ObjectUtil.isNotNull(dto.getClassId()), BaseStudentSchoolRoll::getClassId, dto.getClassId())
.eq(ObjectUtil.isNotNull(dto.getRoleId()), UserRoleRelation::getRoleId, dto.getRoleId())
.orderByDesc(User::getId)
.select(User::getId)
.select("d1.name", UserPageVo::getEmployWay)
.select("d2.name", UserPageVo::getEmployType)
.selectAs(BaseStudentSchoolRoll::getClassId, UserPageVo::getClassId)
.select(User.class, x -> VoToColumnUtil.fieldsToColumns(UserPageVo.class).contains(x.getProperty()))
.leftJoin(UserRoleRelation.class, UserRoleRelation::getUserId, User::getId)
.leftJoin(BaseStudentSchoolRoll.class, BaseStudentSchoolRoll::getUserId, User::getId)
.leftJoin(UserDeptRelation.class, UserDeptRelation::getUserId, User::getId)
.leftJoin(BaseTeacher.class, BaseTeacher::getUserId, User::getId)
.leftJoin(BaseTeacherRegular.class, BaseTeacherRegular::getUserId, User::getId)
.leftJoin(DictionaryDetail.class, "d1", DictionaryDetail::getCode, BaseTeacher::getEmployWay)
.leftJoin(DictionaryDetail.class, "d2", DictionaryDetail::getCode, BaseTeacher::getEmployType)
.leftJoin(Role.class, Role::getId, UserRoleRelation::getRoleId);
if (ObjectUtil.isNotNull(dto.getUserType())) {
if (dto.getUserType() == 2) {
queryUser.eq(BaseTeacher::getIsNormal, 1);
}
if (dto.getUserType() == 3) {
queryUser.leftJoin(BaseStudent.class, BaseStudent::getUserId, User::getId)
.eq(BaseStudent::getIsNormal, 1);
}
}
IPage page = userService.selectJoinListPage(ConventPage.getPage(dto), UserPageVo.class, queryUser);
for (UserPageVo record : page.getRecords()) {
record.setGenderCn(GenderDictionaryEnum.getValue(record.getGender()));
}
PageOutput pageOutput = ConventPage.getPageOutput(page, UserPageVo.class);
return R.ok(pageOutput);
}
}
@GetMapping(value = "/person-page")
@ApiOperation(value = "人员选择组件(分页)")
@SaCheckPermission("user:personpage")
@XjrLog(value = "人员选择组件(分页)")
public R personPage(PersonPageDto dto) {
Page voPage = userService.personPage(new Page<>(dto.getLimit(), dto.getSize()), dto);
PageOutput pageOutput = ConventPage.getPageOutput(voPage, PersonPageVo.class);
return R.ok(pageOutput);
}
@GetMapping(value = "/info")
@ApiOperation(value = "根据id查询用户信息")
@SaCheckPermission("user:info")
@XjrLog(value = "根据id查询用户信息", saveResponseData = true)
public R info(@RequestParam Long id) {
User user = userService.getById(id);
if (user == null) {
R.error("找不到此用户!");
}
UserVo userVo = BeanUtil.toBean(user, UserVo.class);
userVo.setGenderCn(GenderDictionaryEnum.getValue(userVo.getGender()));
List deptIds = userDeptRelationService.list(Wrappers.lambdaQuery(UserDeptRelation.class)
.eq(UserDeptRelation::getUserId, user.getId()))
.stream().map(UserDeptRelation::getDeptId).collect(Collectors.toList());
String allDeptIdStr = StrUtil.join(StringPool.COMMA, deptIds);
userVo.setDepartmentIds(allDeptIdStr);
List roleIds = userRoleRelationService.list(
Wrappers.lambdaQuery(UserRoleRelation.class)
.eq(UserRoleRelation::getUserId, user.getId())
).stream().map(UserRoleRelation::getRoleId).collect(Collectors.toList());
userVo.setRoleIds(roleIds);
return R.ok(userVo);
}
@GetMapping(value = "/detail")
@ApiOperation(value = "根据id查询用户信息")
@SaCheckPermission("user:detail")
@XjrLog(value = "根据id查询用户信息", saveResponseData = true)
public RT detail(@RequestParam Long id) {
User user = userService.getById(id);
if (user == null) {
R.error("找不到此用户!");
}
UserDetailVo userVo = BeanUtil.toBean(user, UserDetailVo.class);
List deptIds = userDeptRelationService.list(Wrappers.lambdaQuery(UserDeptRelation.class)
.eq(UserDeptRelation::getUserId, user.getId()))
.stream().map(UserDeptRelation::getDeptId).collect(Collectors.toList());
String allDeptIdStr = StrUtil.join(StringPool.COMMA, deptIds);
userVo.setDepartmentIds(allDeptIdStr);
return RT.ok(userVo);
}
@PostMapping
@ApiOperation(value = "新增用户")
@SaCheckPermission("user:add")
@XjrLog(value = "新增用户", saveRequestData = false, saveResponseData = true)
public R add(@Valid @RequestBody AddUserDto dto) {
if (!OrganizationUtil.validatePassword(dto.getPassword())) {
return R.error("密码必须包含大写字母、小写字母、数字和特殊字符,长度8~16位");
}
return R.ok(userService.add(dto));
}
@PutMapping
@ApiOperation(value = "修改用户 不能修改用户名")
@SaCheckPermission("user:edit")
@XjrLog(value = "修改用户 不能修改用户名", saveRequestData = false, saveResponseData = true)
public R update(@Valid @RequestBody UpdateUserDto dto) {
return R.ok(userService.update(dto));
}
@GetMapping(value = "/current/info")
@ApiOperation(value = "当前登录用户信息")
@SaCheckPermission("user:currentinfo")
@XjrLog(value = "当前登录用户信息", saveResponseData = true)
public R info() {
SaSession tokenSession = StpUtil.getTokenSession();
User user = tokenSession.get(GlobalConstant.LOGIN_USER_INFO_KEY, new User());
List roleIds = userRoleRelationService.list(Wrappers.lambdaQuery(UserRoleRelation.class)
.eq(UserRoleRelation::getUserId, user.getId()))
.stream().map(UserRoleRelation::getRoleId).collect(Collectors.toList());
List deptIds = userDeptRelationService.list(Wrappers.lambdaQuery(UserDeptRelation.class)
.eq(UserDeptRelation::getUserId, user.getId()))
.stream().map(UserDeptRelation::getDeptId).collect(Collectors.toList());
List postIds = userPostRelationService.list(Wrappers.lambdaQuery(UserPostRelation.class)
.eq(UserPostRelation::getUserId, user.getId()))
.stream().map(UserPostRelation::getPostId).collect(Collectors.toList());
UserInfoVo vo = BeanUtil.toBean(user, UserInfoVo.class);
vo.setGenderCn(GenderDictionaryEnum.getValue(vo.getGender()));
if (roleIds.size() > 0) {
List list = roleService.list(Wrappers.lambdaQuery(Role.class).in(Role::getId, roleIds));
List userRoleVoList = BeanUtil.copyToList(list, UserRoleVo.class);
vo.setRoles(userRoleVoList);
}
if (deptIds.size() > 0) {
List list = departmentService.list(Wrappers.lambdaQuery(Department.class).in(Department::getId, deptIds));
List userDeptVoList = BeanUtil.copyToList(list, UserDeptVo.class);
vo.setDepartments(userDeptVoList);
}
if (postIds.size() > 0) {
List list = postService.list(Wrappers.lambdaQuery(Post.class).in(Post::getId, postIds));
List userPostVoList = BeanUtil.copyToList(list, UserPostVo.class);
vo.setPosts(userPostVoList);
}
// 家长
List list = baseClassService.getStudents(user.getId());
if (list != null) {
vo.setStudents(list);
}
// 学生
UserStudentVo userStudentVo = baseClassService.getClassInfo(user.getId());
if (userStudentVo != null) {
vo.setClassId(userStudentVo.getClassId());
vo.setClassName(userStudentVo.getClassName());
vo.setTeacherId(userStudentVo.getTeacherId());
vo.setTeacherName(userStudentVo.getTeacherName());
vo.setTeacherMobile(userStudentVo.getTeacherMobile());
}
List fileList = fileService.list(Wrappers.lambdaQuery(File.class).eq(File::getFolderId, user.getSignFolderId()));
if (!fileList.isEmpty()) {
vo.setSignUrl(fileList.get(0).getFileUrl());
}
return R.ok(vo);
}
@GetMapping(value = "/pending/count")
@ApiOperation(value = "当前待办数量统计")
@SaCheckPermission("user:pendingcount")
@XjrLog(value = "当前待办数量统计", saveResponseData = true)
public RT pendingCount() {
PendingCountDto pendingCountDto = new PendingCountDto();
pendingCountDto.setWfPendingCount(workflowExecuteService.pendingCount());
List extraList = workflowExtraService.list(
new MPJLambdaWrapper()
.select(WorkflowExtra::getId)
.select(WorkflowExtra.class, x -> VoToColumnUtil.fieldsToColumns(WorkflowExtra.class).contains(x.getProperty()))
.innerJoin(WorkflowFormRelation.class, WorkflowFormRelation::getProcessId, WorkflowExtra::getProcessId)
.eq(WorkflowFormRelation::getCurrentState, HistoricProcessInstance.STATE_ACTIVE)
.eq(WorkflowExtra::getStartUserId, StpUtil.getLoginIdAsLong())
.isNull(WorkflowFormRelation::getEndTime)
);
Set processIdSet = extraList.stream().map(WorkflowExtra::getProcessId).collect(Collectors.toSet());
// HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery()
// .variableValueEquals(WorkflowConstant.PROCESS_START_USER_ID_KEY, StpUtil.getLoginIdAsLong())
// .variableValueEquals(WorkflowConstant.PROCESS_ISRECYCLE_FLAG_KEY, WorkflowIsRecycleType.NO.getCode());
// List historicProcessInstances = historicProcessInstanceQuery.orderByProcessInstanceStartTime().desc().list();
//
// //获取到所有流程id
// int myApplicationCount = 0;
// for (HistoricProcessInstance historicProcessInstance : historicProcessInstances) {
// Long countByProcessId = workflowExecuteService.getCountByProcessId(historicProcessInstance.getId());
// if (countByProcessId == 0L) {
// continue;
//
// }
// if (!ObjectUtil.isNotNull(historicProcessInstance.getEndTime())) {
// myApplicationCount++;
// }
// }
pendingCountDto.setMyApplicationCount(processIdSet.size());
long circulatedCount = circulatedService.count(
MPJWrappers.lambdaJoin()
.eq(WorkflowCirculated::getCirculatedUserId, StpUtil.getLoginIdAsLong())
.eq(WorkflowCirculated::getIsRead, 0)
.select(WorkflowCirculated::getId)
.leftJoin(User.class, User::getId, WorkflowCirculated::getStartUserId)
.leftJoin(WorkflowSchema.class, WorkflowSchema::getId, WorkflowCirculated::getSchemaId)
);
pendingCountDto.setCirculatedCount(circulatedCount);
//增加查询收文承办数量
OfficialDocumentReceivedHandlePageDto dto = new OfficialDocumentReceivedHandlePageDto();
dto.setLoginUserId(StpUtil.getLoginIdAsLong());
dto.setIsHandle(0);
Page page = documentReceivedHandleService.getPage(new Page<>(1, 15), dto);
pendingCountDto.setDocumentReceivedHandleCount(page.getTotal());
return RT.ok(pendingCountDto);
}
@GetMapping(value = "/reset-user-page")
@ApiOperation(value = "移动端用户列表")
@SaCheckPermission("user:resetuserpage")
@XjrLog(value = "移动端用户列表")
public RT> resetUserPage(UserPageDto dto) {
PageOutput userPage = userService.getResetUserPage(dto);
return RT.ok(userPage);
}
@GetMapping(value = "/reset-page-role-list")
@ApiOperation(value = "移动端用户列表分类")
@SaCheckPermission("user:resetpagerolelist")
@XjrLog(value = "移动端用户列表分类")
public RT> resetUserTree() {
List roleList = new ArrayList<>();
roleList.add(new ResetUserRoleVo() {{
setId(null);
setName("全部");
}});
roleList.add(new ResetUserRoleVo() {{
setId(2L);
setName("教师");
}});
roleList.add(new ResetUserRoleVo() {{
setId(3L);
setName("学生");
}});
roleList.add(new ResetUserRoleVo() {{
setId(4L);
setName("家长");
}});
return RT.ok(roleList);
}
@GetMapping(value = "/pc-role-tree")
@ApiOperation(value = "pc端用户列表分类")
@SaCheckPermission("user:pcroletree")
@XjrLog(value = "pc端用户列表分类")
public RT> pcRoleTree() {
List departmentList = departmentService.list(
new QueryWrapper().lambda()
.eq(Department::getDeleteMark, DeleteMark.NODELETE.getCode())
);
List voList = new ArrayList<>();
for (Department department : departmentList) {
ResetUserRoleVo roleVo = BeanUtil.toBean(department, ResetUserRoleVo.class);
roleVo.setType(2);
voList.add(roleVo);
}
List treeVoList = TreeUtil.build(voList);
List roleList = new ArrayList<>();
ResetUserRoleVo roleVo = new ResetUserRoleVo() {{
setId(2L);
setType(1);
setName("教师");
setChildren(treeVoList);
}};
roleList.add(roleVo);
List gradeClassList = new ArrayList<>();
baseClassService.list(
new QueryWrapper().lambda().eq(BaseClass::getDeleteMark, DeleteMark.NODELETE.getCode())
).forEach(e -> {
ResetUserRoleVo gradeClass = new ResetUserRoleVo();
gradeClass.setType(4);
gradeClass.setName(e.getName());
gradeClass.setId(e.getId());
gradeClass.setParentId(e.getGradeId());
gradeClassList.add(gradeClass);
});
baseGradeService.list(
new QueryWrapper().lambda().eq(BaseGrade::getDeleteMark, DeleteMark.NODELETE.getCode())
).forEach(e -> {
ResetUserRoleVo gradeClass = new ResetUserRoleVo();
gradeClass.setType(3);
gradeClass.setName(e.getName());
gradeClass.setId(e.getId());
gradeClass.setParentId(3L);
gradeClassList.add(gradeClass);
});
List gradeClassTreeVoList = TreeUtil.build(gradeClassList);
roleList.add(new ResetUserRoleVo() {{
setId(3L);
setType(1);
setName("学生");
setChildren(gradeClassTreeVoList);
}});
roleList.add(new ResetUserRoleVo() {{
setId(4L);
setType(1);
setName("家长");
}});
return RT.ok(roleList);
}
@PutMapping("/update/info")
@ApiOperation(value = "登陆人修改自己得用户信息")
@SaCheckPermission("user:updateinfo")
@XjrLog(value = "登陆人修改自己得用户信息", saveResponseData = true)
public R updateInfo(@RequestBody @Valid UpdateInfoDto dto) {
User updateUserInfo = BeanUtil.toBean(dto, User.class);
updateUserInfo.setId(StpUtil.getLoginIdAsLong());
CompletableFuture.runAsync(() -> {
List list = userService.list();
redisUtil.set(GlobalConstant.USER_CACHE_KEY, list);
});
return R.ok(userService.updateById(updateUserInfo));
}
@PutMapping("/update/password")
@ApiOperation(value = "当前登录用户修改本人密码")
@SaCheckPermission("user:updatepassword")
@XjrLog(value = "当前登录用户修改本人密码", saveRequestData = false, saveResponseData = true)
public RT updatePassword(@RequestBody @Valid UpdatePasswordDto dto) {
if (!OrganizationUtil.validatePassword(dto.getNewPassword())) {
return RT.error("密码必须包含大写字母、小写字母、数字和特殊字符,长度8~16位");
}
User user = userService.getById(StpUtil.getLoginIdAsLong());
if (!BCrypt.checkpw(dto.getOldPassword(), user.getPassword())) {
return RT.error("当前密码填写错误!");
}
// 新密码与原密码应该不一致
if (BCrypt.checkpw(dto.getNewPassword(), user.getPassword())) {
return RT.error("新密码和旧密码不能相同!");
}
if (!StrUtil.equals(dto.getNewPassword(), dto.getConfirmPassword())) {
return RT.error("2次密码输入不一致!");
}
return RT.ok(userService.updatePassword(dto));
}
@PutMapping("/login/reset-password")
@ApiOperation(value = "登录后修改密码")
@SaCheckPermission("user:resetpassword")
@XjrLog(value = "登录后修改密码", saveRequestData = false, saveResponseData = true)
public RT loginResetPassword(@RequestBody @Valid LoginResetPasswordDto dto) {
if (!OrganizationUtil.validatePassword(dto.getNewPassword())) {
return RT.error("密码必须包含大写字母、小写字母、数字和特殊字符,长度8~16位");
}
User user = userService.getById(StpUtil.getLoginIdAsLong());
// 新密码与原密码应该不一致
if (BCrypt.checkpw(dto.getNewPassword(), user.getPassword())) {
return RT.error("新密码和旧密码不能相同!");
}
if (!StrUtil.equals(dto.getNewPassword(), dto.getConfirmPassword())) {
return RT.error("2次密码输入不一致!");
}
UpdatePasswordDto pd = BeanUtil.toBean(dto, UpdatePasswordDto.class);
return RT.ok(userService.updatePassword(pd));
}
@PostMapping("/update/avatar")
@ApiOperation(value = "当前登录用户修改头像")
@SaCheckPermission("user:updateavatar")
@XjrLog(value = "当前登录用户修改头像", saveRequestData = false, saveResponseData = true)
public R uploadAvatar(@RequestParam("file") MultipartFile file) throws Exception {
if (file.isEmpty()) {
throw new MyException("上传文件不能为空");
}
// 文件上传mime校验
UploadUtil.fileTypeValidate(file, FileCheckRuleConfig.IMAGE);
//上传文件
String suffix = Objects.requireNonNull(file.getOriginalFilename()).substring(file.getOriginalFilename().lastIndexOf(StringPool.DOT));
String url = Objects.requireNonNull(OssFactory.build()).uploadSuffix(file.getBytes(), suffix);
User updateUser = new User();
updateUser.setId(StpUtil.getLoginIdAsLong());
updateUser.setAvatar(url);
userService.updateById(updateUser);
SaSession tokenSession = StpUtil.getTokenSession();
User user = tokenSession.get(GlobalConstant.LOGIN_USER_INFO_KEY, new User());
user.setAvatar(url);
tokenSession.set(GlobalConstant.LOGIN_USER_INFO_KEY, user);
return R.ok(url);
}
@DeleteMapping
@ApiOperation(value = "删除用户(可批量)")
@SaCheckPermission("user:delete")
@XjrLog(value = "删除用户(可批量)", saveResponseData = true)
public R delete(@RequestBody List ids) {
if (ids.contains(GlobalConstant.SUPER_ADMIN_USER_ID)) {
R.error("管理员账户不能删除!");
}
if (ids.contains(StpUtil.getLoginIdAsLong())) {
R.error("当前登录账户不能删除!");
}
//删除海康的用户信息
DataUtil dataUtil = new DataUtil();
dataUtil.deletePerson(ids);
//删除时需要同时删除用户部门关联表和用户角色关联表和用户岗位关系表数据。
return R.ok(userService.deleteBatch(ids));
}
@PostMapping(value = "/change-status")
@ApiOperation(value = "修改状态")
@SaCheckPermission("classroom:changestatus")
@XjrLog(value = "修改状态", saveResponseData = true)
public RT changeStatus(@Valid @RequestBody UserChangeStatusDto dto) throws Exception {
List list = userService.list(new QueryWrapper().lambda()
.in(User::getId, dto.getUserIds())
);
for (User user : list) {
user.setEnabledMark(dto.getStatus());
userService.updateById(user);
}
return RT.ok(true);
}
@GetMapping("/info/multi")
@ApiOperation(value = "批量获取用户信息")
@SaCheckPermission("user:infomulti")
@XjrLog(value = "批量获取用户信息")
public R usersInfo(@RequestParam String ids) {
return R.ok(userService.getUsersInfo(ids));
}
@GetMapping("/enabled")
@ApiOperation(value = "启用/禁用用户")
@SaCheckPermission("user:enabled")
@XjrLog(value = "启用/禁用用户", saveResponseData = true)
public R enabled(@RequestParam Long id) {
User user = userService.getOne(Wrappers.query().lambda().select(User::getEnabledMark).eq(User::getId, id), false);
if (user != null) {
User updateUser = new User();
updateUser.setId(id);
updateUser.setEnabledMark(user.getEnabledMark() == EnabledMark.ENABLED.getCode() ? EnabledMark.DISABLED.getCode() : EnabledMark.ENABLED.getCode());
return R.ok(userService.updateById(updateUser));
}
CompletableFuture.runAsync(() -> {
List list = userService.list();
redisUtil.set(GlobalConstant.USER_CACHE_KEY, list);
});
return R.error("该用户不存在!");
}
@PutMapping("/reset-password")
@ApiOperation(value = "重置密码")
@SaCheckPermission("user:resetpassword")
@XjrLog(value = "重置密码", saveResponseData = true)
public RT resetPassword(@RequestBody ResetPasswordDto dto) {
return RT.ok(userService.resetPassword(dto));
}
@PutMapping("/batch-reset-password")
@ApiOperation(value = "批量重置密码")
@SaCheckPermission("user:batchresetpassword")
@XjrLog(value = "批量重置密码", saveResponseData = true)
public RT batchResetPassword(@RequestBody List ids) {
return RT.ok(userService.batchResetPassword(ids));
}
@PostMapping("/bind-unionid")
@ApiOperation(value = "绑定微信 UnionId")
@SaCheckPermission("user:bindunionid")
@XjrLog(value = "绑定微信 UnionId", saveResponseData = true)
public R bindUnionId(@RequestBody BindOpenidDto dto) {
User user = userService.getOne(Wrappers.query().lambda().select(User::getId, User::getOpenId, User::getUnionId).eq(User::getId, dto.getId()), false);
if (user != null) {
if (StrUtil.isNotBlank(user.getUnionId())) {
return R.error("该用户已经绑定微信!");
}
long count = userService.count(Wrappers.query().lambda().eq(User::getUnionId, dto.getOpenid()));
if (count > 0) {
return R.error("该用户已经绑定微信!");
}
User updateUser = new User();
updateUser.setId(dto.getId());
// updateUser.setOpenId(dto.getOpenid());
updateUser.setUnionId(dto.getOpenid());
return R.ok(userService.updateById(updateUser));
} else {
long count = userService.count(Wrappers.query().lambda().eq(User::getOpenId, dto.getOpenid()));
if (count > 0) {
return R.error("该用户已经绑定微信!");
}
}
return R.error("该用户不存在!");
}
// @PostMapping("/bind-openid")
// @ApiOperation(value = "绑定微信 Openid")
// @XjrLog(value = "绑定微信 Openid", saveResponseData = true)
// public R bindOpenid(@RequestBody BindOpenidDto dto) {
// return R.ok(userService.bindOpenid(dto));
// }
@PostMapping("/bind-openid")
@ApiOperation(value = "绑定微信 Openid")
@SaCheckPermission("user:bindopenid")
@XjrLog(value = "绑定微信 Openid", saveResponseData = true)
public RT bindOpenid(@RequestBody BindOpenidDto dto) {
return RT.ok(userService.bindOpenid(dto));
}
@PostMapping("/unbind-openid")
@ApiOperation(value = "取消绑定微信 UnionId")
@SaCheckPermission("user:unbindopenid")
@XjrLog(value = "取消绑定微信 UnionId", saveResponseData = true)
public R unbindOpenid(@RequestBody UnbindOpenidDto dto) {
return R.ok(userService.unbindOpenid(dto));
}
@PostMapping("/register")
@ApiOperation(value = "家长注册")
@SaCheckPermission("user:register")
@XjrLog(value = "家长注册", saveResponseData = true)
public R register(@Valid @RequestBody RegisterDto dto) {
//验证家长手机号是否已经注册
LambdaQueryWrapper userLambdaQueryWrapper = new LambdaQueryWrapper<>();
userLambdaQueryWrapper
.eq(User::getMobile, dto.getMobile())
.eq(User::getDeleteMark, DeleteMark.NODELETE.getCode())
.last("limit 1")
;
User user = userService.getOne(userLambdaQueryWrapper);
if(ObjectUtils.isNotEmpty(user)){
throw new MyException("当前手机号已被" + user.getName() + "使用,请更换手机号注册!");
}
//验证新生注册家长的手机号是否是学生自己的
LambdaQueryWrapper baseNewStudentLambdaQueryWrapper = new LambdaQueryWrapper<>();
baseNewStudentLambdaQueryWrapper
.eq(BaseNewStudent::getMobile, dto.getMobile())
.eq(BaseNewStudent::getDeleteMark, DeleteMark.NODELETE.getCode())
.last("limit 1")
;
BaseNewStudent baseNewStudent = baseNewStudentService.getOne(baseNewStudentLambdaQueryWrapper);
if(ObjectUtils.isNotEmpty(baseNewStudent)){
throw new MyException("当前手机号为学生" + baseNewStudent.getName() + "填写的学生手机号,请更换手机号注册!");
}
// 验证验证码
if (!smsCtcc.captchaVerify(dto.getMobile(), dto.getSmsCode())) {
return R.error("验证码不正确!");
}
// 赋值家长角色
List roleIds = new ArrayList<>();
roleIds.add(RoleEnum.PARENT.getCode());
dto.setRoleIds(roleIds);
return R.ok(userService.add(dto));
}
@PostMapping("/bind-student")
@ApiOperation(value = "绑定学生")
@SaCheckPermission("user:bindstudent")
@XjrLog(value = "绑定学生", saveResponseData = true)
public R bindStudent(@Valid @RequestBody UserStudentBindDto dto) {
User user = userService.getOne(Wrappers.query().lambda()
.eq(User::getName, dto.getName())
.eq(User::getCredentialNumber, dto.getIdCard())
.eq(StrUtil.isNotBlank(dto.getMobile()), User::getMobile, dto.getMobile())
);
UserStudentAddDto userStudentAddDto = new UserStudentAddDto();
if (user == null) {
return R.error("学生不存在!");
}
userStudentAddDto.setUserId(dto.getUserId());
userStudentAddDto.setStudentId(user.getId());
return R.ok(userStudentService.add(userStudentAddDto));
}
@GetMapping(value = "/validate-student")
@ApiOperation(value = "认证学生")
@SaCheckPermission("user:validatestudent")
@XjrLog(value = "认证学生", saveResponseData = true)
public RT getValidateStudent(UserStudentBindDto dto) {
UserStudentInfoVo userStudentInfoVo = baseStudentSchoolRollService.selectJoinOne(UserStudentInfoVo.class,
MPJWrappers.lambdaJoin()
.innerJoin(User.class, User::getId, BaseStudentSchoolRoll::getUserId)
.leftJoin(BaseClass.class, BaseClass::getId, BaseStudentSchoolRoll::getClassId)
.eq(User::getName, dto.getName())
.eq(User::getCredentialNumber, dto.getIdCard())
.select(User::getId, User::getName, User::getMobile, User::getCredentialNumber)
.select(BaseClass::getTeacherId)
);
if (userStudentInfoVo == null) {
return RT.error("学生不存在!");
}
if (StrUtil.isNotBlank(dto.getMobile()) && !dto.getMobile().equals(userStudentInfoVo.getMobile())) {
return RT.error("该学生的手机号和当前输入的手机号不一致!");
}
List managementList = whitelistManagementService.list(
new QueryWrapper().lambda()
.eq(WhitelistManagement::getUserId, userStudentInfoVo.getId())
);
userStudentInfoVo.setWhitelistStatus(0);
if (!managementList.isEmpty()) {
userStudentInfoVo.setWhitelistStatus(1);
}
return RT.ok(userStudentInfoVo);
}
@DeleteMapping("/unbind-student")
@ApiOperation(value = "解绑学生")
@SaCheckPermission("user:unbindstudent")
@XjrLog(value = "解绑学生", saveResponseData = true)
public R unBindStudent(@Valid @RequestBody UserStudentDeleteDto dto) {
return R.ok(userStudentService.delete(dto));
}
@GetMapping("/student")
@ApiOperation(value = "获取绑定学生")
@SaCheckPermission("user:student")
@XjrLog(value = "获取绑定学生")
public R unBindStudent(@Valid @RequestParam Long id) {
return R.ok(baseClassService.getStudents(id));
}
@GetMapping("/user-student")
@ApiOperation(value = "获取绑定学生")
@SaCheckPermission("user:userstudent")
@XjrLog(value = "获取绑定学生")
public RT> getBindStudent(@Valid @RequestParam Long id) {
List userStudentVoList = userStudentService.selectJoinList(UserStudentVo.class,
MPJWrappers.lambdaJoin()
.innerJoin(BaseStudentSchoolRoll.class, BaseStudentSchoolRoll::getUserId, UserStudent::getStudentId)
.innerJoin(BaseStudentUser.class, BaseStudentUser::getId, UserStudent::getStudentId)
.leftJoin(BaseClass.class, BaseClass::getId, BaseStudentSchoolRoll::getClassId)
.leftJoin(XjrUser.class, XjrUser::getId, BaseClass::getTeacherId)
.select(BaseStudentSchoolRoll::getClassId)
.selectAs(XjrUser::getName, UserStudentVo::getTeacherName)
.selectAs(XjrUser::getMobile, UserStudentVo::getTeacherMobile)
.selectAs(XjrUser::getId, UserStudentVo::getTeacherId)
.select(UserStudent::getStudentId, UserStudent::getStatus)
.selectAs(BaseClass::getName, UserStudentVo::getClassName)
.selectAs(BaseStudentUser::getName, UserStudentVo::getStudentName)
.selectAs(BaseStudentUser::getAvatar, UserStudentVo::getAvatar)
.eq(UserStudent::getUserId, id)
);
return RT.ok(userStudentVoList);
}
@PostMapping("/upload-sign")
@ApiOperation(value = "上传签名")
@SaCheckPermission("user:uploadsign")
@XjrLog(value = "上传签名", saveResponseData = true)
public RT uploadSign(@Valid @RequestBody UploadSignDto dto) {
long loginIdAsLong = StpUtil.getLoginIdAsLong();
User user = userService.getById(loginIdAsLong);
user.setSignFolderId(dto.getFolderId());
user.setSignPassword(BCrypt.hashpw(dto.getPassword(), BCrypt.gensalt()));
return RT.ok(userService.updateById(user));
}
@GetMapping("/getSign")
@ApiOperation(value = "获取登录者的签名url")
@SaCheckPermission("user:getsign")
@XjrLog(value = "获取登录者的签名url", saveResponseData = true)
public RT getSign() {
long loginIdAsLong = StpUtil.getLoginIdAsLong();
User user = userService.getById(loginIdAsLong);
if (user.getSignFolderId() == null) {
return RT.error("未上传签名");
}
List list = fileService.list(Wrappers.lambdaQuery(File.class).eq(File::getFolderId, user.getSignFolderId()));
if (list.isEmpty()) {
return RT.error("签名文件丢失");
}
return RT.ok(list.get(0).getFileUrl());
}
@GetMapping("/check-password")
@ApiOperation(value = "验证登录者的密码")
@SaCheckPermission("user:checkpassword")
@XjrLog(value = "验证登录者的密码", saveRequestData = false, saveResponseData = true)
public RT checkSignpassword(@RequestParam String password) {
long loginIdAsLong = StpUtil.getLoginIdAsLong();
User user = userService.getById(loginIdAsLong);
if (!BCrypt.checkpw(password, user.getPassword())) {
return RT.error("密码填写错误!");
}
return RT.ok(true);
}
@PostMapping("/upload-mobile")
@ApiOperation(value = "修改手机号")
@SaCheckPermission("user:uploadmobile")
@XjrLog(value = "修改手机号", saveResponseData = true)
public R uploadMobile(@Valid @RequestBody UploadMobileDto dto) {
// 验证验证码
if (!smsCtcc.captchaVerify(dto.getOldMobile(), dto.getSmsCode())) {
return R.error("验证码不正确!");
}
if (dto.getUserId() == null) {
dto.setUserId(StpUtil.getLoginIdAsLong());
}
User user = userService.getById(dto.getUserId());
user.setMobile(dto.getMobile());
return R.ok(userService.updateById(user));
}
}