心理健康2.0
This commit is contained in:
1 parent
067957256d
commit
3b492479b5
63 files changed
+10278
-642
No files matched your search
@@ -93,6 +93,12 @@
|
||||
<artifactId>ruoyi-xg</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 系统模块 - 用于访问用户信息 -->
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-system</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
package org.dromara.stgl.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import org.dromara.common.excel.utils.ExcelUtil;
|
||||
import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.dromara.stgl.domain.StglAnnualReviewAudit;
|
||||
import org.dromara.stgl.domain.bo.StglAnnualReviewApprovalBo;
|
||||
import org.dromara.stgl.service.IStglAnnualReviewAuditService;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 社团年审审批
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2024-01-01
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/stgl/annualReviewAudit")
|
||||
public class StglAnnualReviewAuditController extends BaseController {
|
||||
|
||||
private final IStglAnnualReviewAuditService stglAnnualReviewAuditService;
|
||||
|
||||
/**
|
||||
* 查询社团年审审批详细
|
||||
*/
|
||||
@SaCheckPermission("stgl:annualReviewAudit:query")
|
||||
@GetMapping("/{id}")
|
||||
public R<StglAnnualReviewAudit> getInfo(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long id) {
|
||||
return R.ok(stglAnnualReviewAuditService.queryById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据年审记录ID查询审批记录
|
||||
*/
|
||||
@SaCheckPermission("stgl:annualReviewAudit:query")
|
||||
@GetMapping("/byAnnualReview/{annualReviewId}")
|
||||
public R<List<StglAnnualReviewAudit>> getByAnnualReviewId(@NotNull(message = "年审记录ID不能为空")
|
||||
@PathVariable Long annualReviewId) {
|
||||
return R.ok(stglAnnualReviewAuditService.queryByAnnualReviewId(annualReviewId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据审批人ID查询待审批记录
|
||||
*/
|
||||
@SaCheckPermission("stgl:annualReviewAudit:query")
|
||||
@GetMapping("/pending/{approverId}")
|
||||
public R<List<StglAnnualReviewAudit>> getPendingByApproverId(@NotNull(message = "审批人ID不能为空")
|
||||
@PathVariable Long approverId) {
|
||||
return R.ok(stglAnnualReviewAuditService.queryPendingByApproverId(approverId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增社团年审审批
|
||||
*/
|
||||
@SaCheckPermission("stgl:annualReviewAudit:add")
|
||||
@Log(title = "社团年审审批", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody StglAnnualReviewAudit stglAnnualReviewAudit) {
|
||||
return toAjax(stglAnnualReviewAuditService.insertByBo(stglAnnualReviewAudit));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改社团年审审批
|
||||
*/
|
||||
@SaCheckPermission("stgl:annualReviewAudit:edit")
|
||||
@Log(title = "社团年审审批", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody StglAnnualReviewAudit stglAnnualReviewAudit) {
|
||||
return toAjax(stglAnnualReviewAuditService.updateByBo(stglAnnualReviewAudit));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除社团年审审批
|
||||
*/
|
||||
@SaCheckPermission("stgl:annualReviewAudit:remove")
|
||||
@Log(title = "社团年审审批", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||
@PathVariable Long[] ids) {
|
||||
return toAjax(stglAnnualReviewAuditService.deleteWithValidByIds(List.of(ids), true));
|
||||
}
|
||||
|
||||
/**
|
||||
* 审批年审记录
|
||||
*/
|
||||
@SaCheckPermission("stgl:annualReviewAudit:approve")
|
||||
@Log(title = "社团年审审批", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PostMapping("/approve")
|
||||
public R<Void> approve(@Validated @RequestBody StglAnnualReviewApprovalBo approvalBo) {
|
||||
return toAjax(stglAnnualReviewAuditService.approveAnnualReview(approvalBo));
|
||||
}
|
||||
}
|
||||
+179
@@ -0,0 +1,179 @@
|
||||
package org.dromara.stgl.controller;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.constraints.*;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.excel.utils.ExcelUtil;
|
||||
import org.dromara.stgl.domain.vo.StglAuditorVo;
|
||||
import org.dromara.stgl.domain.bo.StglAuditorBo;
|
||||
import org.dromara.stgl.service.IStglAuditorService;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.system.service.ISysUserService;
|
||||
import org.dromara.system.domain.vo.SysUserVo;
|
||||
|
||||
/**
|
||||
* 社团管理审核人配置
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2024-01-01
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/stgl/auditor")
|
||||
public class StglAuditorController extends BaseController {
|
||||
|
||||
private final IStglAuditorService stglAuditorService;
|
||||
private final ISysUserService sysUserService;
|
||||
|
||||
/**
|
||||
* 查询社团管理审核人配置列表
|
||||
*/
|
||||
@SaCheckPermission("stgl:auditor:list")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<StglAuditorVo> list(StglAuditorBo bo, PageQuery pageQuery) {
|
||||
return stglAuditorService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出社团管理审核人配置列表
|
||||
*/
|
||||
@SaCheckPermission("stgl:auditor:export")
|
||||
@Log(title = "社团管理审核人配置", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(StglAuditorBo bo, HttpServletResponse response) {
|
||||
List<StglAuditorVo> list = stglAuditorService.queryList(bo);
|
||||
ExcelUtil.exportExcel(list, "社团管理审核人配置", StglAuditorVo.class, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取社团管理审核人配置详细信息
|
||||
*/
|
||||
@SaCheckPermission("stgl:auditor:query")
|
||||
@GetMapping("/{id}")
|
||||
public R<StglAuditorVo> getInfo(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long id) {
|
||||
return R.ok(stglAuditorService.queryById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增社团管理审核人配置
|
||||
*/
|
||||
@SaCheckPermission("stgl:auditor:add")
|
||||
@Log(title = "社团管理审核人配置", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody StglAuditorBo bo) {
|
||||
return toAjax(stglAuditorService.insertByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改社团管理审核人配置
|
||||
*/
|
||||
@SaCheckPermission("stgl:auditor:edit")
|
||||
@Log(title = "社团管理审核人配置", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody StglAuditorBo bo) {
|
||||
return toAjax(stglAuditorService.updateByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除社团管理审核人配置
|
||||
*/
|
||||
@SaCheckPermission("stgl:auditor:remove")
|
||||
@Log(title = "社团管理审核人配置", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||
@PathVariable Long[] ids) {
|
||||
return toAjax(stglAuditorService.deleteWithValidByIds(List.of(ids)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量添加审核人
|
||||
*/
|
||||
@SaCheckPermission("stgl:auditor:add")
|
||||
@Log(title = "批量添加审核人", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping("/batchAdd")
|
||||
public R<Void> batchAdd(@RequestBody BatchAddRequest request) {
|
||||
return toAjax(stglAuditorService.batchAddAuditors(request.getUserIds(), request.getRemark()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询我配置的审核人列表
|
||||
*/
|
||||
@SaCheckPermission("stgl:auditor:list")
|
||||
@GetMapping("/myConfig")
|
||||
public TableDataInfo<StglAuditorVo> myConfigList(StglAuditorBo bo, PageQuery pageQuery) {
|
||||
return stglAuditorService.queryMyConfigList(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量启用审核人
|
||||
*/
|
||||
@SaCheckPermission("stgl:auditor:edit")
|
||||
@Log(title = "启用审核人", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/enable")
|
||||
public R<Void> enable(@RequestBody List<Long> ids) {
|
||||
return toAjax(stglAuditorService.enableAuditors(ids));
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量停用审核人
|
||||
*/
|
||||
@SaCheckPermission("stgl:auditor:edit")
|
||||
@Log(title = "停用审核人", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/disable")
|
||||
public R<Void> disable(@RequestBody List<Long> ids) {
|
||||
return toAjax(stglAuditorService.disableAuditors(ids));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据部门ID获取用户列表
|
||||
*/
|
||||
@SaCheckPermission("stgl:auditor:list")
|
||||
@GetMapping("/users/{deptId}")
|
||||
public R<List<SysUserVo>> listUserByDeptId(@PathVariable String deptId) {
|
||||
List<SysUserVo> users = sysUserService.selectUserListByDept(Long.valueOf(deptId));
|
||||
return R.ok(users);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量添加请求对象
|
||||
*/
|
||||
public static class BatchAddRequest {
|
||||
private List<Long> userIds;
|
||||
private String remark;
|
||||
|
||||
public List<Long> getUserIds() {
|
||||
return userIds;
|
||||
}
|
||||
|
||||
public void setUserIds(List<Long> userIds) {
|
||||
this.userIds = userIds;
|
||||
}
|
||||
|
||||
public String getRemark() {
|
||||
return remark;
|
||||
}
|
||||
|
||||
public void setRemark(String remark) {
|
||||
this.remark = remark;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
package org.dromara.stgl.domain;
|
||||
|
||||
import org.dromara.common.tenant.core.TenantEntity;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 社团年审审批对象 stgl_annual_review_audit
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2024-01-01
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("stgl_annual_review_audit")
|
||||
public class StglAnnualReviewAudit extends TenantEntity {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 删除标志(0代表存在 1代表删除)
|
||||
*/
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
/**
|
||||
* 年审记录ID
|
||||
*/
|
||||
private Long annualReviewId;
|
||||
|
||||
/**
|
||||
* 节点代码(advisor_approve/college_approve/youth_league_approve)
|
||||
*/
|
||||
private String nodeCode;
|
||||
|
||||
/**
|
||||
* 节点名称(指导老师审批/学院审批/校团委审批)
|
||||
*/
|
||||
private String nodeName;
|
||||
|
||||
/**
|
||||
* 节点顺序(1.1,1.2,2,3)
|
||||
*/
|
||||
private BigDecimal nodeOrder;
|
||||
|
||||
/**
|
||||
* 节点状态(pending/waiting/approved)
|
||||
*/
|
||||
@TableField("audit_status")
|
||||
private String nodeStatus;
|
||||
|
||||
/**
|
||||
* 审批人ID
|
||||
*/
|
||||
private Long approverId;
|
||||
|
||||
/**
|
||||
* 审批人姓名
|
||||
*/
|
||||
private String approverName;
|
||||
|
||||
/**
|
||||
* 审批结果(通过/不通过)
|
||||
*/
|
||||
private String approveResult;
|
||||
|
||||
/**
|
||||
* 审批意见
|
||||
*/
|
||||
@TableField("audit_opinion")
|
||||
private String approveOpinion;
|
||||
|
||||
/**
|
||||
* 审批时间
|
||||
*/
|
||||
@TableField("audit_time")
|
||||
private Date approveTime;
|
||||
}
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
package org.dromara.stgl.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.dromara.common.tenant.core.TenantEntity;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 社团管理审核人配置对象 stgl_auditor
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2024-01-01
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("stgl_auditor")
|
||||
public class StglAuditor extends TenantEntity implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 用户姓名
|
||||
*/
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 用户昵称
|
||||
*/
|
||||
private String nickName;
|
||||
|
||||
/**
|
||||
* 部门ID
|
||||
*/
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 部门名称
|
||||
*/
|
||||
private String deptName;
|
||||
|
||||
/**
|
||||
* 联系电话
|
||||
*/
|
||||
private String phoneNumber;
|
||||
|
||||
/**
|
||||
* 邮箱地址
|
||||
*/
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* 状态(1正常 0停用)
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 备注说明
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 配置人ID
|
||||
*/
|
||||
private Long configBy;
|
||||
|
||||
/**
|
||||
* 配置人姓名
|
||||
*/
|
||||
private String configByName;
|
||||
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package org.dromara.stgl.domain;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 社团管理用户和部门完整信息
|
||||
* 用于批量添加审核人时获取完整的用户数据
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-03
|
||||
*/
|
||||
@Data
|
||||
public class StglUserWithDeptInfo {
|
||||
|
||||
/** 用户ID */
|
||||
private Long userId;
|
||||
|
||||
/** 用户账号 */
|
||||
private String userName;
|
||||
|
||||
/** 用户昵称 */
|
||||
private String nickName;
|
||||
|
||||
/** 部门ID */
|
||||
private Long deptId;
|
||||
|
||||
/** 部门名称 */
|
||||
private String deptName;
|
||||
|
||||
/** 手机号码 */
|
||||
private String phonenumber;
|
||||
|
||||
/** 用户邮箱 */
|
||||
private String email;
|
||||
|
||||
/** 帐号状态(1正常 0停用) */
|
||||
private String status;
|
||||
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
package org.dromara.stgl.domain.bo;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 社团年审审批请求业务对象
|
||||
*
|
||||
* @author system
|
||||
* @date 2025-01-03
|
||||
*/
|
||||
@Data
|
||||
public class StglAnnualReviewApprovalBo {
|
||||
|
||||
/**
|
||||
* 审批记录ID
|
||||
*/
|
||||
@NotNull(message = "审批记录ID不能为空")
|
||||
private Long auditId;
|
||||
|
||||
/**
|
||||
* 审批结果
|
||||
*/
|
||||
@NotBlank(message = "审批结果不能为空")
|
||||
private String approveResult;
|
||||
|
||||
/**
|
||||
* 审批意见
|
||||
*/
|
||||
private String approveOpinion;
|
||||
|
||||
/**
|
||||
* 下一步审核人列表
|
||||
*/
|
||||
private List<NextAuditor> nextAuditors;
|
||||
|
||||
/**
|
||||
* 下一步审核人信息
|
||||
*/
|
||||
@Data
|
||||
public static class NextAuditor {
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 昵称
|
||||
*/
|
||||
private String nickName;
|
||||
}
|
||||
}
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
package org.dromara.stgl.domain.bo;
|
||||
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||
import org.dromara.stgl.domain.StglAuditor;
|
||||
|
||||
import jakarta.validation.constraints.*;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 社团管理审核人配置业务对象 stgl_auditor
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2024-01-01
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@AutoMapper(target = StglAuditor.class, reverseConvertGenerate = false)
|
||||
public class StglAuditorBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@NotNull(message = "主键ID不能为空", groups = { EditGroup.class })
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
@NotNull(message = "用户ID不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 用户姓名
|
||||
*/
|
||||
@NotBlank(message = "用户姓名不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 用户昵称
|
||||
*/
|
||||
@NotBlank(message = "用户昵称不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String nickName;
|
||||
|
||||
/**
|
||||
* 部门ID
|
||||
*/
|
||||
@NotNull(message = "部门ID不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 部门名称
|
||||
*/
|
||||
@NotBlank(message = "部门名称不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String deptName;
|
||||
|
||||
/**
|
||||
* 联系电话
|
||||
*/
|
||||
private String phoneNumber;
|
||||
|
||||
/**
|
||||
* 邮箱地址
|
||||
*/
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* 状态(1正常 0停用)
|
||||
*/
|
||||
@NotBlank(message = "状态不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 备注说明
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 配置人ID
|
||||
*/
|
||||
private Long configBy;
|
||||
|
||||
/**
|
||||
* 配置人姓名
|
||||
*/
|
||||
private String configByName;
|
||||
|
||||
/**
|
||||
* 分页大小
|
||||
*/
|
||||
private Integer pageSize;
|
||||
|
||||
/**
|
||||
* 页码
|
||||
*/
|
||||
private Integer pageNum;
|
||||
|
||||
/**
|
||||
* 搜索值
|
||||
*/
|
||||
private String searchValue;
|
||||
|
||||
/**
|
||||
* 创建时间范围
|
||||
*/
|
||||
private List<Date> createTimeRange;
|
||||
|
||||
}
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
package org.dromara.stgl.domain.vo;
|
||||
|
||||
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import cn.idev.excel.annotation.ExcelProperty;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
import org.dromara.common.excel.annotation.ExcelDictFormat;
|
||||
import org.dromara.common.excel.convert.ExcelDictConvert;
|
||||
import org.dromara.stgl.domain.StglAuditor;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 社团管理审核人配置视图对象 stgl_auditor
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2024-01-01
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
@AutoMapper(target = StglAuditor.class)
|
||||
public class StglAuditorVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@ExcelProperty(value = "主键ID")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
@ExcelProperty(value = "用户ID")
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 用户姓名
|
||||
*/
|
||||
@ExcelProperty(value = "用户姓名")
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 用户昵称
|
||||
*/
|
||||
@ExcelProperty(value = "用户昵称")
|
||||
private String nickName;
|
||||
|
||||
/**
|
||||
* 部门ID
|
||||
*/
|
||||
@ExcelProperty(value = "部门ID")
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 部门名称
|
||||
*/
|
||||
@ExcelProperty(value = "部门名称")
|
||||
private String deptName;
|
||||
|
||||
/**
|
||||
* 联系电话
|
||||
*/
|
||||
@ExcelProperty(value = "联系电话")
|
||||
private String phoneNumber;
|
||||
|
||||
/**
|
||||
* 邮箱地址
|
||||
*/
|
||||
@ExcelProperty(value = "邮箱地址")
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* 状态(1正常 0停用)
|
||||
*/
|
||||
@ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(dictType = "sys_normal_disable")
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 备注说明
|
||||
*/
|
||||
@ExcelProperty(value = "备注说明")
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 配置人ID
|
||||
*/
|
||||
private Long configBy;
|
||||
|
||||
/**
|
||||
* 配置人姓名
|
||||
*/
|
||||
@ExcelProperty(value = "配置人")
|
||||
private String configByName;
|
||||
|
||||
/**
|
||||
* 租户编号
|
||||
*/
|
||||
private String tenantId;
|
||||
|
||||
/**
|
||||
* 创建部门
|
||||
*/
|
||||
private Long createDept;
|
||||
|
||||
/**
|
||||
* 创建者ID
|
||||
*/
|
||||
private Long createBy;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@ExcelProperty(value = "创建时间")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新者ID
|
||||
*/
|
||||
private Long updateBy;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@ExcelProperty(value = "更新时间")
|
||||
private Date updateTime;
|
||||
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package org.dromara.stgl.mapper;
|
||||
|
||||
import org.dromara.stgl.domain.StglAnnualReviewAudit;
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 社团年审审批Mapper接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2024-01-01
|
||||
*/
|
||||
public interface StglAnnualReviewAuditMapper extends BaseMapperPlus<StglAnnualReviewAudit, StglAnnualReviewAudit> {
|
||||
|
||||
/**
|
||||
* 根据年审记录ID查询审批记录
|
||||
*
|
||||
* @param annualReviewId 年审记录ID
|
||||
* @return 审批记录列表
|
||||
*/
|
||||
List<StglAnnualReviewAudit> selectByAnnualReviewId(Long annualReviewId);
|
||||
|
||||
/**
|
||||
* 根据年审记录ID和节点代码查询审批记录
|
||||
*
|
||||
* @param annualReviewId 年审记录ID
|
||||
* @param nodeCode 节点代码
|
||||
* @return 审批记录列表
|
||||
*/
|
||||
List<StglAnnualReviewAudit> selectByAnnualReviewIdAndNodeCode(Long annualReviewId, String nodeCode);
|
||||
|
||||
/**
|
||||
* 根据审批人ID查询待审批记录
|
||||
*
|
||||
* @param approverId 审批人ID
|
||||
* @return 审批记录列表
|
||||
*/
|
||||
List<StglAnnualReviewAudit> selectPendingByApproverId(Long approverId);
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
package org.dromara.stgl.mapper;
|
||||
|
||||
import org.dromara.stgl.domain.StglAuditor;
|
||||
import org.dromara.stgl.domain.vo.StglAuditorVo;
|
||||
import org.dromara.stgl.domain.StglUserWithDeptInfo;
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 社团管理审核人配置Mapper接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2024-01-01
|
||||
*/
|
||||
public interface StglAuditorMapper extends BaseMapperPlus<StglAuditor, StglAuditorVo> {
|
||||
|
||||
/**
|
||||
* 查询社团管理审核人配置
|
||||
*
|
||||
* @param id 社团管理审核人配置主键
|
||||
* @return 社团管理审核人配置
|
||||
*/
|
||||
StglAuditorVo selectStglAuditorVoById(Long id);
|
||||
|
||||
/**
|
||||
* 查询社团管理审核人配置列表
|
||||
*
|
||||
* @param stglAuditor 社团管理审核人配置
|
||||
* @return 社团管理审核人配置集合
|
||||
*/
|
||||
List<StglAuditorVo> selectStglAuditorVoList(StglAuditor stglAuditor);
|
||||
|
||||
/**
|
||||
* 根据用户ID检查是否已存在审核人配置
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 记录数
|
||||
*/
|
||||
int checkUserExists(@Param("userId") Long userId);
|
||||
|
||||
/**
|
||||
* 批量启用审核人
|
||||
*
|
||||
* @param ids 审核人ID列表
|
||||
* @return 影响行数
|
||||
*/
|
||||
int enableAuditorsByIds(@Param("ids") List<Long> ids);
|
||||
|
||||
/**
|
||||
* 批量停用审核人
|
||||
*
|
||||
* @param ids 审核人ID列表
|
||||
* @return 影响行数
|
||||
*/
|
||||
int disableAuditorsByIds(@Param("ids") List<Long> ids);
|
||||
|
||||
/**
|
||||
* 查询完整的用户信息(包含部门信息)用于批量添加
|
||||
*
|
||||
* @param userIds 用户ID列表
|
||||
* @return 用户和部门完整信息列表
|
||||
*/
|
||||
List<StglUserWithDeptInfo> selectUsersWithDeptInfo(@Param("userIds") List<Long> userIds);
|
||||
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
package org.dromara.stgl.service;
|
||||
|
||||
import org.dromara.stgl.domain.StglAnnualReviewAudit;
|
||||
import org.dromara.stgl.domain.bo.StglAnnualReviewApprovalBo;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 社团年审审批Service接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2024-01-01
|
||||
*/
|
||||
public interface IStglAnnualReviewAuditService {
|
||||
|
||||
/**
|
||||
* 查询社团年审审批
|
||||
*
|
||||
* @param id 社团年审审批主键
|
||||
* @return 社团年审审批
|
||||
*/
|
||||
StglAnnualReviewAudit queryById(Long id);
|
||||
|
||||
/**
|
||||
* 根据年审记录ID查询审批记录
|
||||
*
|
||||
* @param annualReviewId 年审记录ID
|
||||
* @return 审批记录列表
|
||||
*/
|
||||
List<StglAnnualReviewAudit> queryByAnnualReviewId(Long annualReviewId);
|
||||
|
||||
/**
|
||||
* 根据年审记录ID和节点代码查询审批记录
|
||||
*
|
||||
* @param annualReviewId 年审记录ID
|
||||
* @param nodeCode 节点代码
|
||||
* @return 审批记录列表
|
||||
*/
|
||||
List<StglAnnualReviewAudit> queryByAnnualReviewIdAndNodeCode(Long annualReviewId, String nodeCode);
|
||||
|
||||
/**
|
||||
* 根据审批人ID查询待审批记录
|
||||
*
|
||||
* @param approverId 审批人ID
|
||||
* @return 审批记录列表
|
||||
*/
|
||||
List<StglAnnualReviewAudit> queryPendingByApproverId(Long approverId);
|
||||
|
||||
/**
|
||||
* 新增社团年审审批
|
||||
*
|
||||
* @param stglAnnualReviewAudit 社团年审审批
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean insertByBo(StglAnnualReviewAudit stglAnnualReviewAudit);
|
||||
|
||||
/**
|
||||
* 修改社团年审审批
|
||||
*
|
||||
* @param stglAnnualReviewAudit 社团年审审批
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean updateByBo(StglAnnualReviewAudit stglAnnualReviewAudit);
|
||||
|
||||
/**
|
||||
* 校验并批量删除社团年审审批信息
|
||||
*
|
||||
* @param ids 需要删除的社团年审审批主键集合
|
||||
* @param isValid 是否校验,true-删除前校验,false-不校验
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||
|
||||
/**
|
||||
* 创建指导老师审批记录
|
||||
*
|
||||
* @param annualReviewId 年审记录ID
|
||||
* @param advisorIds 指导老师ID列表
|
||||
* @param advisorNames 指导老师姓名列表
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean createAdvisorApprovalRecords(Long annualReviewId, List<Long> advisorIds, List<String> advisorNames);
|
||||
|
||||
/**
|
||||
* 审批年审记录
|
||||
*
|
||||
* @param auditId 审批记录ID
|
||||
* @param approveResult 审批结果
|
||||
* @param approveOpinion 审批意见
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean approveAnnualReview(Long auditId, String approveResult, String approveOpinion);
|
||||
|
||||
/**
|
||||
* 审批年审记录(支持动态审核人选择)
|
||||
*
|
||||
* @param approvalBo 审批请求对象
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean approveAnnualReview(StglAnnualReviewApprovalBo approvalBo);
|
||||
}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
package org.dromara.stgl.service;
|
||||
|
||||
import org.dromara.stgl.domain.vo.StglAuditorVo;
|
||||
import org.dromara.stgl.domain.bo.StglAuditorBo;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 社团管理审核人配置Service接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2024-01-01
|
||||
*/
|
||||
public interface IStglAuditorService {
|
||||
|
||||
/**
|
||||
* 查询社团管理审核人配置
|
||||
*
|
||||
* @param id 主键
|
||||
* @return 社团管理审核人配置
|
||||
*/
|
||||
StglAuditorVo queryById(Long id);
|
||||
|
||||
/**
|
||||
* 查询社团管理审核人配置列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return 社团管理审核人配置集合
|
||||
*/
|
||||
TableDataInfo<StglAuditorVo> queryPageList(StglAuditorBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询社团管理审核人配置列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return 社团管理审核人配置集合
|
||||
*/
|
||||
List<StglAuditorVo> queryList(StglAuditorBo bo);
|
||||
|
||||
/**
|
||||
* 新增社团管理审核人配置
|
||||
*
|
||||
* @param bo 社团管理审核人配置
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean insertByBo(StglAuditorBo bo);
|
||||
|
||||
/**
|
||||
* 修改社团管理审核人配置
|
||||
*
|
||||
* @param bo 社团管理审核人配置
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean updateByBo(StglAuditorBo bo);
|
||||
|
||||
/**
|
||||
* 校验并批量删除社团管理审核人配置信息
|
||||
*
|
||||
* @param ids 需要删除的主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids);
|
||||
|
||||
/**
|
||||
* 批量添加审核人
|
||||
*
|
||||
* @param userIds 用户ID列表
|
||||
* @param remark 备注
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean batchAddAuditors(List<Long> userIds, String remark);
|
||||
|
||||
/**
|
||||
* 查询我配置的审核人列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return 审核人列表
|
||||
*/
|
||||
TableDataInfo<StglAuditorVo> queryMyConfigList(StglAuditorBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 批量启用审核人
|
||||
*
|
||||
* @param ids 审核人ID列表
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean enableAuditors(List<Long> ids);
|
||||
|
||||
/**
|
||||
* 批量停用审核人
|
||||
*
|
||||
* @param ids 审核人ID列表
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean disableAuditors(List<Long> ids);
|
||||
|
||||
}
|
||||
+409
@@ -0,0 +1,409 @@
|
||||
package org.dromara.stgl.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.stgl.domain.StglAnnualReviewAudit;
|
||||
import org.dromara.stgl.domain.StglClubAnnualReview;
|
||||
import org.dromara.stgl.domain.bo.StglAnnualReviewApprovalBo;
|
||||
import org.dromara.stgl.mapper.StglAnnualReviewAuditMapper;
|
||||
import org.dromara.stgl.mapper.StglClubAnnualReviewMapper;
|
||||
import org.dromara.stgl.service.IStglAnnualReviewAuditService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 社团年审审批Service业务层处理
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2024-01-01
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class StglAnnualReviewAuditServiceImpl implements IStglAnnualReviewAuditService {
|
||||
|
||||
private final StglAnnualReviewAuditMapper baseMapper;
|
||||
private final StglClubAnnualReviewMapper annualReviewMapper;
|
||||
|
||||
/**
|
||||
* 查询社团年审审批
|
||||
*/
|
||||
@Override
|
||||
public StglAnnualReviewAudit queryById(Long id) {
|
||||
return baseMapper.selectById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据年审记录ID查询审批记录
|
||||
*/
|
||||
@Override
|
||||
public List<StglAnnualReviewAudit> queryByAnnualReviewId(Long annualReviewId) {
|
||||
return baseMapper.selectByAnnualReviewId(annualReviewId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据年审记录ID和节点代码查询审批记录
|
||||
*/
|
||||
@Override
|
||||
public List<StglAnnualReviewAudit> queryByAnnualReviewIdAndNodeCode(Long annualReviewId, String nodeCode) {
|
||||
return baseMapper.selectByAnnualReviewIdAndNodeCode(annualReviewId, nodeCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据审批人ID查询待审批记录
|
||||
*/
|
||||
@Override
|
||||
public List<StglAnnualReviewAudit> queryPendingByApproverId(Long approverId) {
|
||||
return baseMapper.selectPendingByApproverId(approverId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增社团年审审批
|
||||
*/
|
||||
@Override
|
||||
public Boolean insertByBo(StglAnnualReviewAudit bo) {
|
||||
StglAnnualReviewAudit add = BeanUtil.toBean(bo, StglAnnualReviewAudit.class);
|
||||
validEntityBeforeSave(add);
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
if (flag) {
|
||||
bo.setId(add.getId());
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改社团年审审批
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateByBo(StglAnnualReviewAudit bo) {
|
||||
StglAnnualReviewAudit update = BeanUtil.toBean(bo, StglAnnualReviewAudit.class);
|
||||
validEntityBeforeSave(update);
|
||||
return baseMapper.updateById(update) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(StglAnnualReviewAudit entity) {
|
||||
// TODO 做一些数据校验,如唯一约束
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除社团年审审批
|
||||
*/
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||
if (isValid) {
|
||||
// TODO 做一些业务上的校验,判断是否需要校验
|
||||
}
|
||||
return baseMapper.deleteByIds(ids) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建指导老师审批记录
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public Boolean createAdvisorApprovalRecords(Long annualReviewId, List<Long> advisorIds, List<String> advisorNames) {
|
||||
if (ObjectUtil.isEmpty(advisorIds) || ObjectUtil.isEmpty(advisorNames) || advisorIds.size() != advisorNames.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 删除已存在的指导老师审批记录
|
||||
LambdaQueryWrapper<StglAnnualReviewAudit> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.eq(StglAnnualReviewAudit::getAnnualReviewId, annualReviewId)
|
||||
.eq(StglAnnualReviewAudit::getNodeCode, "advisor_approve");
|
||||
baseMapper.delete(wrapper);
|
||||
|
||||
// 创建新的指导老师审批记录
|
||||
for (int i = 0; i < advisorIds.size(); i++) {
|
||||
StglAnnualReviewAudit audit = new StglAnnualReviewAudit();
|
||||
audit.setAnnualReviewId(annualReviewId);
|
||||
audit.setNodeCode("advisor_approve");
|
||||
audit.setNodeName("指导老师审批");
|
||||
|
||||
// 设置节点顺序:单个指导老师为1.0,多个指导老师为1.1, 1.2, 1.3...
|
||||
if (advisorIds.size() == 1) {
|
||||
audit.setNodeOrder(new BigDecimal("1.0"));
|
||||
} else {
|
||||
audit.setNodeOrder(new BigDecimal("1." + (i + 1)));
|
||||
}
|
||||
|
||||
// 设置节点状态:第一个为pending,其他为waiting
|
||||
audit.setNodeStatus(i == 0 ? "pending" : "waiting");
|
||||
audit.setApproverId(advisorIds.get(i));
|
||||
audit.setApproverName(advisorNames.get(i));
|
||||
|
||||
baseMapper.insert(audit);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 审批年审记录
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public Boolean approveAnnualReview(Long auditId, String approveResult, String approveOpinion) {
|
||||
// 1. 获取当前审批记录
|
||||
StglAnnualReviewAudit currentAudit = baseMapper.selectById(auditId);
|
||||
if (currentAudit == null || !"pending".equals(currentAudit.getNodeStatus())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. 更新当前审批记录
|
||||
currentAudit.setNodeStatus("approved");
|
||||
currentAudit.setApproveResult(approveResult);
|
||||
currentAudit.setApproveOpinion(approveOpinion);
|
||||
currentAudit.setApproveTime(new Date());
|
||||
baseMapper.updateById(currentAudit);
|
||||
|
||||
// 3. 如果审批不通过,直接更新年审记录状态为4(审核不通过)
|
||||
if ("不通过".equals(approveResult)) {
|
||||
StglClubAnnualReview annualReview = annualReviewMapper.selectById(currentAudit.getAnnualReviewId());
|
||||
if (annualReview != null) {
|
||||
annualReview.setStatus("4");
|
||||
annualReviewMapper.updateById(annualReview);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// 4. 如果审批通过,检查是否有下一个待审批的同环节审批人
|
||||
List<StglAnnualReviewAudit> samePhaseAudits = baseMapper.selectByAnnualReviewIdAndNodeCode(
|
||||
currentAudit.getAnnualReviewId(), currentAudit.getNodeCode());
|
||||
|
||||
// 查找下一个waiting状态的审批记录
|
||||
StglAnnualReviewAudit nextAudit = null;
|
||||
for (StglAnnualReviewAudit audit : samePhaseAudits) {
|
||||
if ("waiting".equals(audit.getNodeStatus()) &&
|
||||
audit.getNodeOrder().compareTo(currentAudit.getNodeOrder()) > 0) {
|
||||
if (nextAudit == null || audit.getNodeOrder().compareTo(nextAudit.getNodeOrder()) < 0) {
|
||||
nextAudit = audit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 如果有下一个审批人,将其状态改为pending
|
||||
if (nextAudit != null) {
|
||||
nextAudit.setNodeStatus("pending");
|
||||
baseMapper.updateById(nextAudit);
|
||||
} else {
|
||||
// 6. 如果同环节所有审批人都审批通过,检查是否是第一个审批节点,决定是否更新状态为2(审核中)
|
||||
boolean allApproved = samePhaseAudits.stream()
|
||||
.allMatch(audit -> "approved".equals(audit.getNodeStatus()) && "通过".equals(audit.getApproveResult()));
|
||||
|
||||
if (allApproved) {
|
||||
// 只有第一个审批节点(node_order=1.1)通过时才设置为2-审核中
|
||||
if (isFirstApprovalNode(currentAudit)) {
|
||||
StglClubAnnualReview annualReview = annualReviewMapper.selectById(currentAudit.getAnnualReviewId());
|
||||
if (annualReview != null) {
|
||||
annualReview.setStatus("2");
|
||||
annualReviewMapper.updateById(annualReview);
|
||||
log.info("第一个审批节点通过,年审记录状态更新为2-审核中,年审记录ID: {}", annualReview.getId());
|
||||
}
|
||||
} else {
|
||||
log.info("非第一个审批节点通过,保持当前状态,当前节点: {}, node_order: {}",
|
||||
currentAudit.getNodeName(), currentAudit.getNodeOrder());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 审批年审记录(支持动态审核人选择)
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public Boolean approveAnnualReview(StglAnnualReviewApprovalBo approvalBo) {
|
||||
// 调用原有方法进行基础审批
|
||||
Boolean result = approveAnnualReview(approvalBo.getAuditId(),
|
||||
approvalBo.getApproveResult(),
|
||||
approvalBo.getApproveOpinion());
|
||||
|
||||
// 如果审批通过且有指定下一步审核人,创建新的审批记录
|
||||
if (result && "通过".equals(approvalBo.getApproveResult()) &&
|
||||
approvalBo.getNextAuditors() != null && !approvalBo.getNextAuditors().isEmpty()) {
|
||||
|
||||
// 获取当前审批记录
|
||||
StglAnnualReviewAudit currentAudit = baseMapper.selectById(approvalBo.getAuditId());
|
||||
if (currentAudit != null) {
|
||||
// 创建下一步审核人的审批记录
|
||||
createNextStepAuditRecords(currentAudit.getAnnualReviewId(), approvalBo.getNextAuditors());
|
||||
}
|
||||
} else if (result && "通过".equals(approvalBo.getApproveResult()) &&
|
||||
(approvalBo.getNextAuditors() == null || approvalBo.getNextAuditors().isEmpty())) {
|
||||
|
||||
// 如果审批通过且没有下一步审核人,检查是否是校团委最后节点,决定是否结束流程
|
||||
StglAnnualReviewAudit currentAudit = baseMapper.selectById(approvalBo.getAuditId());
|
||||
if (currentAudit != null && isSchoolCommitteeLastNode(currentAudit)) {
|
||||
// 校团委最后节点审批通过,流程结束,将年审记录状态设置为3(审核通过)
|
||||
StglClubAnnualReview annualReview = annualReviewMapper.selectById(currentAudit.getAnnualReviewId());
|
||||
if (annualReview != null) {
|
||||
annualReview.setStatus("3");
|
||||
annualReviewMapper.updateById(annualReview);
|
||||
log.info("校团委最后节点审批通过,年审流程结束,年审记录ID: {}, 状态更新为: 3", annualReview.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建下一步审批记录
|
||||
*/
|
||||
private void createNextStepAuditRecords(Long annualReviewId, List<StglAnnualReviewApprovalBo.NextAuditor> nextAuditors) {
|
||||
// 查询已有的审批记录,确定下一个审批层级
|
||||
List<StglAnnualReviewAudit> existingAudits = baseMapper.selectByAnnualReviewId(annualReviewId);
|
||||
|
||||
// 确定下一个审批层级
|
||||
int nextLevel = determineNextApprovalLevel(existingAudits);
|
||||
|
||||
for (int i = 0; i < nextAuditors.size(); i++) {
|
||||
StglAnnualReviewApprovalBo.NextAuditor auditor = nextAuditors.get(i);
|
||||
|
||||
StglAnnualReviewAudit nextAudit = new StglAnnualReviewAudit();
|
||||
nextAudit.setAnnualReviewId(annualReviewId);
|
||||
nextAudit.setNodeCode(getNodeCodeByLevel(nextLevel));
|
||||
nextAudit.setNodeName(getNodeNameByLevel(nextLevel));
|
||||
|
||||
// 根据层级和顺序设置node_order
|
||||
if (nextAuditors.size() == 1 && nextLevel == 3) {
|
||||
// 校团委审批单个审核人为3.0
|
||||
nextAudit.setNodeOrder(new BigDecimal(nextLevel + ".0"));
|
||||
} else {
|
||||
// 其他情况按 层级.序号 格式设置
|
||||
nextAudit.setNodeOrder(new BigDecimal(nextLevel + "." + (i + 1)));
|
||||
}
|
||||
|
||||
nextAudit.setApproverId(auditor.getUserId());
|
||||
nextAudit.setApproverName(auditor.getNickName() != null ? auditor.getNickName() : auditor.getUserName());
|
||||
nextAudit.setNodeStatus(i == 0 ? "pending" : "waiting"); // 第一个为pending,其余为waiting
|
||||
nextAudit.setCreateTime(new Date());
|
||||
|
||||
baseMapper.insert(nextAudit);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 确定下一个审批层级
|
||||
*/
|
||||
private int determineNextApprovalLevel(List<StglAnnualReviewAudit> existingAudits) {
|
||||
int maxLevel = 1; // 默认从指导老师审批层级开始
|
||||
|
||||
for (StglAnnualReviewAudit audit : existingAudits) {
|
||||
BigDecimal nodeOrder = audit.getNodeOrder();
|
||||
if (nodeOrder != null) {
|
||||
int level = nodeOrder.intValue(); // 获取整数部分作为层级
|
||||
if (level > maxLevel) {
|
||||
maxLevel = level;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return maxLevel + 1; // 下一个层级
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据层级获取节点代码
|
||||
*/
|
||||
private String getNodeCodeByLevel(int level) {
|
||||
switch (level) {
|
||||
case 1:
|
||||
return "advisor_approve";
|
||||
case 2:
|
||||
return "college_approve";
|
||||
case 3:
|
||||
return "youth_league_approve";
|
||||
default:
|
||||
return "college_approve"; // 默认为二级学院审批
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据层级获取节点名称
|
||||
*/
|
||||
private String getNodeNameByLevel(int level) {
|
||||
switch (level) {
|
||||
case 1:
|
||||
return "指导老师审批";
|
||||
case 2:
|
||||
return "二级学院审批";
|
||||
case 3:
|
||||
return "校团委审批";
|
||||
default:
|
||||
return "二级学院审批"; // 默认为二级学院审批
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为第一个审批节点(node_order=1.1)
|
||||
*/
|
||||
private boolean isFirstApprovalNode(StglAnnualReviewAudit currentAudit) {
|
||||
// 检查node_order是否为1.1
|
||||
return currentAudit != null &&
|
||||
currentAudit.getNodeOrder() != null &&
|
||||
currentAudit.getNodeOrder().compareTo(new BigDecimal("1.1")) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断当前是否是校团委审批的最后一个节点
|
||||
*/
|
||||
private boolean isSchoolCommitteeLastNode(StglAnnualReviewAudit currentAudit) {
|
||||
if (currentAudit == null || currentAudit.getNodeOrder() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String currentNodeName = currentAudit.getNodeName();
|
||||
BigDecimal currentNodeOrder = currentAudit.getNodeOrder();
|
||||
|
||||
// 检查是否是校团委审批节点且node_order是3.X格式
|
||||
boolean isSchoolCommitteeNode = "校团委审批".equals(currentNodeName);
|
||||
boolean isNodeOrder3X = currentNodeOrder.compareTo(new BigDecimal("3")) >= 0 &&
|
||||
currentNodeOrder.compareTo(new BigDecimal("4")) < 0;
|
||||
|
||||
if (!isSchoolCommitteeNode || !isNodeOrder3X) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 获取同一环节的所有节点
|
||||
List<StglAnnualReviewAudit> samePhaseNodes = baseMapper.selectByAnnualReviewIdAndNodeCode(
|
||||
currentAudit.getAnnualReviewId(), currentAudit.getNodeCode());
|
||||
|
||||
if (samePhaseNodes.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 找出同一环节中最大的nodeOrder
|
||||
BigDecimal maxNodeOrder = samePhaseNodes.stream()
|
||||
.map(StglAnnualReviewAudit::getNodeOrder)
|
||||
.filter(order -> order != null)
|
||||
.max(BigDecimal::compareTo)
|
||||
.orElse(BigDecimal.ZERO);
|
||||
|
||||
// 当前节点的nodeOrder等于同环节最大nodeOrder时,表示是最后一个节点
|
||||
boolean isLastNode = currentNodeOrder.compareTo(maxNodeOrder) == 0;
|
||||
|
||||
log.info("校团委最后节点判断: 节点名称={}, nodeOrder={}, 是否校团委={}, 是否3.X={}, 是否最后节点={}",
|
||||
currentNodeName, currentNodeOrder, isSchoolCommitteeNode, isNodeOrder3X, isLastNode);
|
||||
|
||||
return isLastNode;
|
||||
}
|
||||
}
|
||||
+266
@@ -0,0 +1,266 @@
|
||||
package org.dromara.stgl.service.impl;
|
||||
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.dromara.stgl.domain.bo.StglAuditorBo;
|
||||
import org.dromara.stgl.domain.vo.StglAuditorVo;
|
||||
import org.dromara.stgl.domain.StglAuditor;
|
||||
import org.dromara.stgl.domain.StglUserWithDeptInfo;
|
||||
import org.dromara.stgl.mapper.StglAuditorMapper;
|
||||
import org.dromara.stgl.service.IStglAuditorService;
|
||||
import org.dromara.system.service.ISysUserService;
|
||||
import org.dromara.system.domain.vo.SysUserVo;
|
||||
import org.dromara.common.satoken.utils.LoginHelper;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Collection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 社团管理审核人配置Service业务层处理
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2024-01-01
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class StglAuditorServiceImpl implements IStglAuditorService {
|
||||
|
||||
private final StglAuditorMapper baseMapper;
|
||||
private final ISysUserService sysUserService;
|
||||
|
||||
/**
|
||||
* 查询社团管理审核人配置
|
||||
*/
|
||||
@Override
|
||||
public StglAuditorVo queryById(Long id) {
|
||||
StglAuditor entity = baseMapper.selectById(id);
|
||||
if (entity == null) {
|
||||
return null;
|
||||
}
|
||||
return MapstructUtils.convert(entity, StglAuditorVo.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询社团管理审核人配置列表
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<StglAuditorVo> queryPageList(StglAuditorBo bo, PageQuery pageQuery) {
|
||||
// 直接使用查询条件构建器
|
||||
LambdaQueryWrapper<StglAuditor> lqw = buildQueryWrapper(bo);
|
||||
Page<StglAuditor> entityPage = baseMapper.selectPage(pageQuery.build(), lqw);
|
||||
|
||||
// 转换为 VO 对象
|
||||
List<StglAuditorVo> voList = new ArrayList<>();
|
||||
for (StglAuditor entity : entityPage.getRecords()) {
|
||||
StglAuditorVo vo = MapstructUtils.convert(entity, StglAuditorVo.class);
|
||||
voList.add(vo);
|
||||
}
|
||||
|
||||
// 构建分页结果
|
||||
Page<StglAuditorVo> voPage = new Page<>(entityPage.getCurrent(), entityPage.getSize(), entityPage.getTotal());
|
||||
voPage.setRecords(voList);
|
||||
|
||||
return TableDataInfo.build(voPage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询社团管理审核人配置列表
|
||||
*/
|
||||
@Override
|
||||
public List<StglAuditorVo> queryList(StglAuditorBo bo) {
|
||||
LambdaQueryWrapper<StglAuditor> lqw = buildQueryWrapper(bo);
|
||||
List<StglAuditor> entityList = baseMapper.selectList(lqw);
|
||||
|
||||
// 转换为 VO 对象
|
||||
List<StglAuditorVo> voList = new ArrayList<>();
|
||||
for (StglAuditor entity : entityList) {
|
||||
StglAuditorVo vo = MapstructUtils.convert(entity, StglAuditorVo.class);
|
||||
voList.add(vo);
|
||||
}
|
||||
|
||||
return voList;
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<StglAuditor> buildQueryWrapper(StglAuditorBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
LambdaQueryWrapper<StglAuditor> lqw = Wrappers.<StglAuditor>lambdaQuery();
|
||||
lqw.eq(bo.getUserId() != null, StglAuditor::getUserId, bo.getUserId());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getUserName()), StglAuditor::getUserName, bo.getUserName());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getNickName()), StglAuditor::getNickName, bo.getNickName());
|
||||
lqw.eq(bo.getDeptId() != null, StglAuditor::getDeptId, bo.getDeptId());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getStatus()), StglAuditor::getStatus, bo.getStatus());
|
||||
lqw.eq(bo.getConfigBy() != null, StglAuditor::getConfigBy, bo.getConfigBy());
|
||||
lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
|
||||
StglAuditor::getCreateTime, params.get("beginCreateTime"), params.get("endCreateTime"));
|
||||
lqw.orderByDesc(StglAuditor::getCreateTime);
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增社团管理审核人配置
|
||||
*/
|
||||
@Override
|
||||
public Boolean insertByBo(StglAuditorBo bo) {
|
||||
StglAuditor add = MapstructUtils.convert(bo, StglAuditor.class);
|
||||
validEntityBeforeSave(add);
|
||||
|
||||
// 设置配置人信息
|
||||
Long currentUserId = LoginHelper.getUserId();
|
||||
add.setConfigBy(currentUserId);
|
||||
|
||||
// 获取当前用户信息设置配置人姓名
|
||||
try {
|
||||
SysUserVo currentUser = sysUserService.selectUserById(currentUserId);
|
||||
if (currentUser != null) {
|
||||
add.setConfigByName(currentUser.getUserName());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 如果获取失败,使用默认值
|
||||
add.setConfigByName("系统管理员");
|
||||
}
|
||||
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
if (flag) {
|
||||
bo.setId(add.getId());
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改社团管理审核人配置
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateByBo(StglAuditorBo bo) {
|
||||
StglAuditor update = MapstructUtils.convert(bo, StglAuditor.class);
|
||||
validEntityBeforeSave(update);
|
||||
return baseMapper.updateById(update) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(StglAuditor entity) {
|
||||
if (entity.getUserId() != null) {
|
||||
// 检查用户是否已存在(新增时或修改用户ID时)
|
||||
if (entity.getId() == null) {
|
||||
// 新增时检查
|
||||
int count = baseMapper.checkUserExists(entity.getUserId());
|
||||
if (count > 0) {
|
||||
throw new ServiceException("该用户已配置为审核人,不能重复添加");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除社团管理审核人配置
|
||||
*/
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids) {
|
||||
return baseMapper.deleteBatchIds(ids) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量添加审核人
|
||||
*/
|
||||
@Override
|
||||
public Boolean batchAddAuditors(List<Long> userIds, String remark) {
|
||||
if (userIds == null || userIds.isEmpty()) {
|
||||
throw new ServiceException("用户ID列表不能为空");
|
||||
}
|
||||
|
||||
Long currentUserId = LoginHelper.getUserId();
|
||||
String currentUserName = "系统管理员";
|
||||
|
||||
// 获取当前用户信息
|
||||
try {
|
||||
SysUserVo currentUser = sysUserService.selectUserById(currentUserId);
|
||||
if (currentUser != null) {
|
||||
currentUserName = currentUser.getUserName();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 使用默认值
|
||||
}
|
||||
|
||||
// 1. 获取完整的用户信息(包含部门信息)
|
||||
List<StglUserWithDeptInfo> users = baseMapper.selectUsersWithDeptInfo(userIds);
|
||||
if (users.isEmpty()) {
|
||||
throw new ServiceException("没有找到有效的用户信息");
|
||||
}
|
||||
|
||||
// 2. 过滤已存在的审核人
|
||||
List<Long> existingUserIds = baseMapper.selectList(Wrappers.<StglAuditor>lambdaQuery()
|
||||
.in(StglAuditor::getUserId, userIds))
|
||||
.stream().map(StglAuditor::getUserId).collect(Collectors.toList());
|
||||
|
||||
// 3. 构建新增审核人列表
|
||||
List<StglAuditor> auditorList = new ArrayList<>();
|
||||
for (StglUserWithDeptInfo user : users) {
|
||||
if (!existingUserIds.contains(user.getUserId())) {
|
||||
StglAuditor auditor = new StglAuditor();
|
||||
auditor.setUserId(user.getUserId());
|
||||
auditor.setUserName(user.getUserName());
|
||||
auditor.setNickName(user.getNickName());
|
||||
auditor.setDeptId(user.getDeptId());
|
||||
auditor.setDeptName(user.getDeptName() != null ? user.getDeptName() : "");
|
||||
auditor.setPhoneNumber(user.getPhonenumber());
|
||||
auditor.setEmail(user.getEmail());
|
||||
auditor.setStatus("1"); // 默认正常状态
|
||||
auditor.setRemark(remark);
|
||||
auditor.setConfigBy(currentUserId);
|
||||
auditor.setConfigByName(currentUserName);
|
||||
auditorList.add(auditor);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 批量保存
|
||||
if (auditorList.isEmpty()) {
|
||||
throw new ServiceException("所有用户都已存在,无需重复添加");
|
||||
}
|
||||
|
||||
return baseMapper.insertBatch(auditorList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询我配置的审核人列表
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<StglAuditorVo> queryMyConfigList(StglAuditorBo bo, PageQuery pageQuery) {
|
||||
bo.setConfigBy(LoginHelper.getUserId());
|
||||
return queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量启用审核人
|
||||
*/
|
||||
@Override
|
||||
public Boolean enableAuditors(List<Long> ids) {
|
||||
if (ids == null || ids.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return baseMapper.enableAuditorsByIds(ids) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量停用审核人
|
||||
*/
|
||||
@Override
|
||||
public Boolean disableAuditors(List<Long> ids) {
|
||||
if (ids == null || ids.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return baseMapper.disableAuditorsByIds(ids) > 0;
|
||||
}
|
||||
|
||||
}
|
||||
+77
-1
@@ -24,8 +24,10 @@ import org.dromara.stgl.mapper.StglClubAnnualReviewActivityMapper;
|
||||
import org.dromara.stgl.service.IStglClubAnnualReviewService;
|
||||
import org.dromara.stgl.service.IStglActivityService;
|
||||
import org.dromara.stgl.service.IStglClubService;
|
||||
import org.dromara.stgl.service.IStglAnnualReviewAuditService;
|
||||
import org.dromara.stgl.domain.bo.StglActivityBo;
|
||||
import org.dromara.stgl.domain.vo.StglClubVo;
|
||||
import org.dromara.stgl.domain.StglClub;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -60,6 +62,7 @@ public class StglClubAnnualReviewServiceImpl implements IStglClubAnnualReviewSer
|
||||
private final StglClubAnnualReviewActivityMapper activityMapper;
|
||||
private final IStglActivityService stglActivityService;
|
||||
private final IStglClubService stglClubService;
|
||||
private final IStglAnnualReviewAuditService auditService;
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
/**
|
||||
@@ -539,9 +542,82 @@ public class StglClubAnnualReviewServiceImpl implements IStglClubAnnualReviewSer
|
||||
throw new RuntimeException("只能提交草稿状态的年审记录");
|
||||
}
|
||||
|
||||
// 获取社团信息,提取指导老师信息
|
||||
StglClubVo club = stglClubService.queryById(entity.getClubId());
|
||||
if (club == null) {
|
||||
throw new RuntimeException("社团信息不存在");
|
||||
}
|
||||
|
||||
// 提取指导老师信息
|
||||
List<Long> advisorIds = new ArrayList<>();
|
||||
List<String> advisorNames = new ArrayList<>();
|
||||
|
||||
try {
|
||||
// 优先从JSON字段读取指导老师数据
|
||||
if (StringUtils.isNotBlank(club.getAdvisorsJson())) {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
List<Map<String, Object>> advisors = mapper.readValue(club.getAdvisorsJson(),
|
||||
new com.fasterxml.jackson.core.type.TypeReference<List<Map<String, Object>>>() {});
|
||||
|
||||
for (Map<String, Object> advisor : advisors) {
|
||||
// 提取用户ID和姓名
|
||||
Object userIdObj = null;
|
||||
String advisorName = null;
|
||||
|
||||
// 尝试直接从advisor对象获取userId和name(兼容旧格式)
|
||||
if (advisor.containsKey("userId")) {
|
||||
userIdObj = advisor.get("userId");
|
||||
advisorName = (String) advisor.get("name");
|
||||
}
|
||||
// 尝试从teacher子对象获取userId和name(新格式)
|
||||
else if (advisor.containsKey("teacher")) {
|
||||
Object teacherObj = advisor.get("teacher");
|
||||
if (teacherObj instanceof Map) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> teacher = (Map<String, Object>) teacherObj;
|
||||
userIdObj = teacher.get("userId");
|
||||
advisorName = (String) teacher.get("nickName");
|
||||
if (StringUtils.isBlank(advisorName)) {
|
||||
advisorName = (String) teacher.get("userName");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (userIdObj != null && StringUtils.isNotBlank(advisorName)) {
|
||||
Long userId = Long.valueOf(userIdObj.toString());
|
||||
advisorIds.add(userId);
|
||||
advisorNames.add(advisorName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有JSON数据,尝试从单一字段获取
|
||||
if (advisorIds.isEmpty() && StringUtils.isNotBlank(club.getAdvisorName())) {
|
||||
// 这种情况下无法获取用户ID,暂时跳过审批流程
|
||||
log.warn("社团 {} 的指导老师信息不完整,无法创建审批记录", club.getClubName());
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("解析指导老师信息失败", e);
|
||||
throw new RuntimeException("解析指导老师信息失败");
|
||||
}
|
||||
|
||||
// 更新年审记录状态
|
||||
entity.setStatus("1");
|
||||
entity.setReviewTime(new Date());
|
||||
return baseMapper.updateById(entity) > 0;
|
||||
boolean updateResult = baseMapper.updateById(entity) > 0;
|
||||
|
||||
// 如果有指导老师信息,创建审批记录
|
||||
if (!advisorIds.isEmpty() && updateResult) {
|
||||
try {
|
||||
auditService.createAdvisorApprovalRecords(id, advisorIds, advisorNames);
|
||||
} catch (Exception e) {
|
||||
log.error("创建审批记录失败", e);
|
||||
throw new RuntimeException("创建审批记录失败");
|
||||
}
|
||||
}
|
||||
|
||||
return updateResult;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
<?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="org.dromara.stgl.mapper.StglAnnualReviewAuditMapper">
|
||||
|
||||
<resultMap type="org.dromara.stgl.domain.StglAnnualReviewAudit" id="StglAnnualReviewAuditResult">
|
||||
<result property="id" column="id" />
|
||||
<result property="tenantId" column="tenant_id" />
|
||||
<result property="createDept" column="create_dept" />
|
||||
<result property="createBy" column="create_by" />
|
||||
<result property="createTime" column="create_time" />
|
||||
<result property="updateBy" column="update_by" />
|
||||
<result property="updateTime" column="update_time" />
|
||||
<result property="deleted" column="deleted" />
|
||||
<result property="annualReviewId" column="annual_review_id" />
|
||||
<result property="nodeCode" column="node_code" />
|
||||
<result property="nodeName" column="node_name" />
|
||||
<result property="nodeOrder" column="node_order" />
|
||||
<result property="nodeStatus" column="audit_status" />
|
||||
<result property="approverId" column="approver_id" />
|
||||
<result property="approverName" column="approver_name" />
|
||||
<result property="approveResult" column="approve_result" />
|
||||
<result property="approveOpinion" column="audit_opinion" />
|
||||
<result property="approveTime" column="audit_time" />
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectStglAnnualReviewAuditVo">
|
||||
select id, tenant_id, create_dept, create_by, create_time, update_by, update_time, deleted,
|
||||
annual_review_id, node_code, node_name, node_order, audit_status,
|
||||
approver_id, approver_name, approve_result, audit_opinion, audit_time
|
||||
from stgl_annual_review_audit
|
||||
</sql>
|
||||
|
||||
<!-- 根据年审记录ID查询审批记录 -->
|
||||
<select id="selectByAnnualReviewId" parameterType="Long" resultMap="StglAnnualReviewAuditResult">
|
||||
<include refid="selectStglAnnualReviewAuditVo"/>
|
||||
where annual_review_id = #{annualReviewId} and deleted = 0
|
||||
order by node_order
|
||||
</select>
|
||||
|
||||
<!-- 根据年审记录ID和节点代码查询审批记录 -->
|
||||
<select id="selectByAnnualReviewIdAndNodeCode" resultMap="StglAnnualReviewAuditResult">
|
||||
<include refid="selectStglAnnualReviewAuditVo"/>
|
||||
where annual_review_id = #{annualReviewId} and node_code = #{nodeCode} and deleted = 0
|
||||
order by node_order
|
||||
</select>
|
||||
|
||||
<!-- 根据审批人ID查询待审批记录 -->
|
||||
<select id="selectPendingByApproverId" parameterType="Long" resultMap="StglAnnualReviewAuditResult">
|
||||
<include refid="selectStglAnnualReviewAuditVo"/>
|
||||
where approver_id = #{approverId} and audit_status = 'pending' and deleted = 0
|
||||
order by create_time desc
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
<?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="org.dromara.stgl.mapper.StglAuditorMapper">
|
||||
|
||||
<resultMap type="org.dromara.stgl.domain.vo.StglAuditorVo" id="StglAuditorResult">
|
||||
<result property="id" column="id" />
|
||||
<result property="userId" column="user_id" />
|
||||
<result property="userName" column="user_name" />
|
||||
<result property="nickName" column="nick_name" />
|
||||
<result property="deptId" column="dept_id" />
|
||||
<result property="deptName" column="dept_name" />
|
||||
<result property="phoneNumber" column="phone_number" />
|
||||
<result property="email" column="email" />
|
||||
<result property="status" column="status" />
|
||||
<result property="remark" column="remark" />
|
||||
<result property="configBy" column="config_by" />
|
||||
<result property="configByName" column="config_by_name" />
|
||||
<result property="createBy" column="create_by" />
|
||||
<result property="createTime" column="create_time" />
|
||||
<result property="updateBy" column="update_by" />
|
||||
<result property="updateTime" column="update_time" />
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectStglAuditorVo">
|
||||
SELECT
|
||||
sa.id,
|
||||
sa.user_id,
|
||||
sa.user_name,
|
||||
sa.nick_name,
|
||||
sa.dept_id,
|
||||
sa.dept_name,
|
||||
sa.phone_number,
|
||||
sa.email,
|
||||
sa.status,
|
||||
sa.remark,
|
||||
sa.config_by,
|
||||
sa.config_by_name,
|
||||
sa.create_by,
|
||||
sa.create_time,
|
||||
sa.update_by,
|
||||
sa.update_time
|
||||
FROM stgl_auditor sa
|
||||
</sql>
|
||||
|
||||
<select id="selectStglAuditorVoList" parameterType="org.dromara.stgl.domain.StglAuditor" resultMap="StglAuditorResult">
|
||||
<include refid="selectStglAuditorVo"/>
|
||||
<where>
|
||||
sa.deleted = 0
|
||||
<if test="userId != null">
|
||||
AND sa.user_id = #{userId}
|
||||
</if>
|
||||
<if test="userName != null and userName != ''">
|
||||
AND sa.user_name LIKE CONCAT('%', #{userName}, '%')
|
||||
</if>
|
||||
<if test="nickName != null and nickName != ''">
|
||||
AND sa.nick_name LIKE CONCAT('%', #{nickName}, '%')
|
||||
</if>
|
||||
<if test="deptId != null">
|
||||
AND sa.dept_id = #{deptId}
|
||||
</if>
|
||||
<if test="status != null and status != ''">
|
||||
AND sa.status = #{status}
|
||||
</if>
|
||||
<if test="configBy != null">
|
||||
AND sa.config_by = #{configBy}
|
||||
</if>
|
||||
<if test="params.beginCreateTime != null and params.beginCreateTime != ''">
|
||||
AND sa.create_time >= #{params.beginCreateTime}
|
||||
</if>
|
||||
<if test="params.endCreateTime != null and params.endCreateTime != ''">
|
||||
AND sa.create_time <= #{params.endCreateTime}
|
||||
</if>
|
||||
</where>
|
||||
ORDER BY sa.create_time DESC
|
||||
</select>
|
||||
|
||||
<select id="selectStglAuditorVoById" parameterType="Long" resultMap="StglAuditorResult">
|
||||
<include refid="selectStglAuditorVo"/>
|
||||
<where>
|
||||
sa.id = #{id} AND sa.deleted = 0
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<select id="checkUserExists" parameterType="Long" resultType="int">
|
||||
SELECT COUNT(1) FROM stgl_auditor
|
||||
WHERE user_id = #{userId} AND deleted = 0
|
||||
</select>
|
||||
|
||||
<update id="enableAuditorsByIds">
|
||||
UPDATE stgl_auditor
|
||||
SET status = '1', update_time = NOW()
|
||||
WHERE id IN
|
||||
<foreach collection="ids" item="id" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
AND deleted = 0
|
||||
</update>
|
||||
|
||||
<update id="disableAuditorsByIds">
|
||||
UPDATE stgl_auditor
|
||||
SET status = '0', update_time = NOW()
|
||||
WHERE id IN
|
||||
<foreach collection="ids" item="id" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
AND deleted = 0
|
||||
</update>
|
||||
|
||||
<!-- 查询完整的用户信息(包含部门信息)用于批量添加 -->
|
||||
<select id="selectUsersWithDeptInfo" resultType="org.dromara.stgl.domain.StglUserWithDeptInfo">
|
||||
select
|
||||
u.user_id as userId,
|
||||
u.user_name as userName,
|
||||
u.nick_name as nickName,
|
||||
u.dept_id as deptId,
|
||||
d.dept_name as deptName,
|
||||
u.phonenumber as phonenumber,
|
||||
u.email as email,
|
||||
u.status as status
|
||||
from sys_user u
|
||||
left join sys_dept d on u.dept_id = d.dept_id
|
||||
where u.status = '0'
|
||||
and u.user_id in
|
||||
<foreach item="userId" collection="userIds" open="(" separator="," close=")">
|
||||
#{userId}
|
||||
</foreach>
|
||||
order by u.dept_id, u.user_name
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
+85
-49
@@ -6,6 +6,7 @@ import org.dromara.common.web.core.BaseController;
|
||||
import org.dromara.xljk.domain.bo.XljkConsultationAppointmentBo;
|
||||
import org.dromara.xljk.domain.vo.XljkConsultationAppointmentVo;
|
||||
import org.dromara.xljk.domain.vo.TimeSlotDetailVo;
|
||||
import org.dromara.xljk.domain.vo.ScheduleWithStatusVo;
|
||||
import org.dromara.xljk.service.IXljkConsultationAppointmentService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
@@ -161,52 +162,10 @@ public class XljkConsultationAppointmentController extends BaseController {
|
||||
|
||||
// 从请求体中获取参数
|
||||
String status = requestBody.get("status").toString();
|
||||
Date actualVisitTime = null;
|
||||
Integer communicationDuration = null;
|
||||
String consultationContent = "";
|
||||
String counselorSuggestion = "";
|
||||
|
||||
// 处理actualVisitTime
|
||||
if (requestBody.get("actualVisitTime") != null) {
|
||||
try {
|
||||
String actualVisitTimeStr = requestBody.get("actualVisitTime").toString();
|
||||
log.info("解析实际到访时间字符串: {}", actualVisitTimeStr);
|
||||
|
||||
// 尝试多种日期格式
|
||||
SimpleDateFormat[] dateFormats = {
|
||||
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"),
|
||||
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"),
|
||||
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"),
|
||||
new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"),
|
||||
new SimpleDateFormat("yyyy-MM-dd")
|
||||
};
|
||||
|
||||
boolean parsed = false;
|
||||
for (SimpleDateFormat sdf : dateFormats) {
|
||||
try {
|
||||
actualVisitTime = sdf.parse(actualVisitTimeStr);
|
||||
parsed = true;
|
||||
log.info("成功解析实际到访时间: {}, 使用格式: {}", actualVisitTime, sdf.toPattern());
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
// 继续尝试下一个格式
|
||||
}
|
||||
}
|
||||
|
||||
if (!parsed) {
|
||||
log.error("无法解析实际到访时间: {}", actualVisitTimeStr);
|
||||
// 使用当前时间作为默认值
|
||||
actualVisitTime = new Date();
|
||||
log.info("使用当前时间作为默认值: {}", actualVisitTime);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("解析actualVisitTime失败", e);
|
||||
// 使用当前时间作为默认值
|
||||
actualVisitTime = new Date();
|
||||
log.info("使用当前时间作为默认值: {}", actualVisitTime);
|
||||
}
|
||||
}
|
||||
|
||||
// 处理communicationDuration
|
||||
if (requestBody.get("communicationDuration") != null) {
|
||||
try {
|
||||
@@ -227,8 +186,47 @@ public class XljkConsultationAppointmentController extends BaseController {
|
||||
counselorSuggestion = requestBody.get("counselorSuggestion").toString();
|
||||
}
|
||||
|
||||
boolean result = service.recordConsultation(id, actualVisitTime, communicationDuration,
|
||||
consultationContent, counselorSuggestion, status);
|
||||
// 处理心理病史相关字段
|
||||
Integer psychologicalHistory = null;
|
||||
String psychologicalHistoryDetail = "";
|
||||
String basicSituation = "";
|
||||
String majorLifeEvents = "";
|
||||
Integer needReferral = null;
|
||||
|
||||
if (requestBody.get("psychologicalHistory") != null) {
|
||||
try {
|
||||
psychologicalHistory = Integer.parseInt(requestBody.get("psychologicalHistory").toString());
|
||||
} catch (Exception e) {
|
||||
log.error("解析psychologicalHistory失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (requestBody.get("psychologicalHistoryDetail") != null) {
|
||||
psychologicalHistoryDetail = requestBody.get("psychologicalHistoryDetail").toString();
|
||||
}
|
||||
|
||||
if (requestBody.get("basicSituation") != null) {
|
||||
basicSituation = requestBody.get("basicSituation").toString();
|
||||
}
|
||||
|
||||
if (requestBody.get("majorLifeEvents") != null) {
|
||||
majorLifeEvents = requestBody.get("majorLifeEvents").toString();
|
||||
}
|
||||
|
||||
if (requestBody.get("needReferral") != null) {
|
||||
try {
|
||||
needReferral = Integer.parseInt(requestBody.get("needReferral").toString());
|
||||
} catch (Exception e) {
|
||||
log.error("解析needReferral失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
log.info("解析的心理病史相关字段: psychologicalHistory={}, psychologicalHistoryDetail={}, basicSituation={}, majorLifeEvents={}, needReferral={}",
|
||||
psychologicalHistory, psychologicalHistoryDetail, basicSituation, majorLifeEvents, needReferral);
|
||||
|
||||
boolean result = service.recordConsultation(id, communicationDuration,
|
||||
consultationContent, counselorSuggestion, status,
|
||||
psychologicalHistory, psychologicalHistoryDetail, basicSituation, majorLifeEvents, needReferral);
|
||||
if (result) {
|
||||
return R.ok(true);
|
||||
} else {
|
||||
@@ -284,7 +282,7 @@ public class XljkConsultationAppointmentController extends BaseController {
|
||||
XSSFSheet sheet = workbook.createSheet("预约记录");
|
||||
|
||||
// 表头
|
||||
String[] headers = {"序号", "学生姓名", "学号", "院系", "专业", "班级", "咨询原因", "咨询师", "预约日期", "预约时段", "状态", "咨询结果", "实际到访时间", "沟通时长", "咨询内容", "咨询师建议"};
|
||||
String[] headers = {"序号", "学生姓名", "学号", "院系", "专业", "班级", "咨询主题", "咨询原因", "咨询师", "预约日期", "预约时段", "状态", "咨询结果", "沟通时长", "心理病史", "心理病史详情", "基本情况", "重大生活事件", "本次咨询过程", "是否需要转介", "本学期到访次数"};
|
||||
XSSFRow headerRow = sheet.createRow(0);
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
headerRow.createCell(i).setCellValue(headers[i]);
|
||||
@@ -303,6 +301,7 @@ public class XljkConsultationAppointmentController extends BaseController {
|
||||
row.createCell(col++).setCellValue(vo.getCollegeName());
|
||||
row.createCell(col++).setCellValue(vo.getMajorName());
|
||||
row.createCell(col++).setCellValue(vo.getClassName());
|
||||
row.createCell(col++).setCellValue(vo.getConsultTheme() != null ? vo.getConsultTheme() : ""); // 咨询主题
|
||||
row.createCell(col++).setCellValue(vo.getReason());
|
||||
row.createCell(col++).setCellValue(vo.getCounselorName());
|
||||
row.createCell(col++).setCellValue(vo.getAppointmentDate() != null ? dateFormat.format(vo.getAppointmentDate()) : "");
|
||||
@@ -315,15 +314,43 @@ public class XljkConsultationAppointmentController extends BaseController {
|
||||
case 1: status = "已到访"; break;
|
||||
case 2: status = "已取消"; break;
|
||||
case 3: status = "未到访"; break;
|
||||
case 4: status = "待审核"; break;
|
||||
case 5: status = "已驳回"; break;
|
||||
default: status = "未知状态";
|
||||
}
|
||||
}
|
||||
row.createCell(col++).setCellValue(status);
|
||||
row.createCell(col++).setCellValue(status); // 咨询结果
|
||||
row.createCell(col++).setCellValue(vo.getActualVisitTime() != null ? dateTimeFormat.format(vo.getActualVisitTime()) : "");
|
||||
row.createCell(col++).setCellValue(vo.getCommunicationDuration() != null ? vo.getCommunicationDuration().toString() : "");
|
||||
row.createCell(col++).setCellValue(vo.getConsultationContent());
|
||||
row.createCell(col++).setCellValue(vo.getCounselorSuggestion());
|
||||
row.createCell(col++).setCellValue(vo.getCommunicationDuration() != null ? vo.getCommunicationDuration().toString() + "分钟" : "");
|
||||
|
||||
// 心理病史
|
||||
String psychologicalHistory = "";
|
||||
if (vo.getPsychologicalHistory() != null) {
|
||||
psychologicalHistory = vo.getPsychologicalHistory() == 2 ? "是" : "否";
|
||||
}
|
||||
row.createCell(col++).setCellValue(psychologicalHistory);
|
||||
|
||||
// 心理病史详情
|
||||
row.createCell(col++).setCellValue(vo.getPsychologicalHistoryDetail() != null ? vo.getPsychologicalHistoryDetail() : "");
|
||||
|
||||
// 基本情况
|
||||
row.createCell(col++).setCellValue(vo.getBasicSituation() != null ? vo.getBasicSituation() : "");
|
||||
|
||||
// 重大生活事件
|
||||
row.createCell(col++).setCellValue(vo.getMajorLifeEvents() != null ? vo.getMajorLifeEvents() : "");
|
||||
|
||||
// 本次咨询过程(原咨询内容)
|
||||
row.createCell(col++).setCellValue(vo.getConsultationContent() != null ? vo.getConsultationContent() : "");
|
||||
|
||||
// 是否需要转介
|
||||
String needReferral = "";
|
||||
if (vo.getNeedReferral() != null) {
|
||||
needReferral = vo.getNeedReferral() == 2 ? "是" : "否";
|
||||
}
|
||||
row.createCell(col++).setCellValue(needReferral);
|
||||
|
||||
// 本学期到访次数
|
||||
row.createCell(col++).setCellValue(vo.getSemesterVisitCount() != null ? vo.getSemesterVisitCount().toString() + "次" : "0次");
|
||||
}
|
||||
|
||||
// 写入字节流
|
||||
@@ -350,6 +377,15 @@ public class XljkConsultationAppointmentController extends BaseController {
|
||||
.body(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取日历视图的排班数据(带预约状态)
|
||||
*/
|
||||
@GetMapping("/calendar-schedules")
|
||||
public R<List<ScheduleWithStatusVo>> getCalendarSchedules(@RequestParam String startDate, @RequestParam String endDate) {
|
||||
List<ScheduleWithStatusVo> schedules = service.getCalendarSchedules(startDate, endDate);
|
||||
return R.ok(schedules);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转义CSV字段中的特殊字符
|
||||
*/
|
||||
|
||||
+46
-3
@@ -14,6 +14,7 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import org.dromara.xljk.domain.vo.XljkConsultationScheduleSummaryVo;
|
||||
|
||||
@RestController
|
||||
@@ -57,10 +58,14 @@ public class XljkConsultationScheduleController {
|
||||
batchBo.setCounselorId(Long.valueOf(requestMap.get("counselorId").toString()));
|
||||
}
|
||||
|
||||
if (requestMap.containsKey("office")) {
|
||||
batchBo.setOffice(requestMap.get("office").toString());
|
||||
}
|
||||
|
||||
batchBo.setStartDate(requestMap.get("startDate").toString());
|
||||
batchBo.setEndDate(requestMap.get("endDate").toString());
|
||||
|
||||
// 设置上午时段
|
||||
// 设置中午时段(字段名保持morning以兼容前端)
|
||||
if (requestMap.containsKey("morningEnabled")) {
|
||||
batchBo.setMorningEnabled(Boolean.valueOf(requestMap.get("morningEnabled").toString()));
|
||||
}
|
||||
@@ -73,6 +78,26 @@ public class XljkConsultationScheduleController {
|
||||
batchBo.setMorningEndTime(requestMap.get("morningEndTime").toString());
|
||||
}
|
||||
|
||||
// 设置中午时段(新版本)
|
||||
if (requestMap.containsKey("noonEnabled")) {
|
||||
batchBo.setNoonEnabled(Boolean.valueOf(requestMap.get("noonEnabled").toString()));
|
||||
}
|
||||
|
||||
if (requestMap.containsKey("noonTimeSlots")) {
|
||||
List<Map<String, Object>> noonSlots = (List<Map<String, Object>>) requestMap.get("noonTimeSlots");
|
||||
if (noonSlots != null) {
|
||||
List<XljkConsultationScheduleBatchBo.TimeSlot> timeSlots = noonSlots.stream()
|
||||
.map(slot -> {
|
||||
XljkConsultationScheduleBatchBo.TimeSlot timeSlot = new XljkConsultationScheduleBatchBo.TimeSlot();
|
||||
timeSlot.setStartTime(slot.get("startTime").toString());
|
||||
timeSlot.setEndTime(slot.get("endTime").toString());
|
||||
return timeSlot;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
batchBo.setNoonTimeSlots(timeSlots);
|
||||
}
|
||||
}
|
||||
|
||||
// 设置下午时段
|
||||
if (requestMap.containsKey("afternoonEnabled")) {
|
||||
batchBo.setAfternoonEnabled(Boolean.valueOf(requestMap.get("afternoonEnabled").toString()));
|
||||
@@ -86,6 +111,21 @@ public class XljkConsultationScheduleController {
|
||||
batchBo.setAfternoonEndTime(requestMap.get("afternoonEndTime").toString());
|
||||
}
|
||||
|
||||
if (requestMap.containsKey("afternoonTimeSlots")) {
|
||||
List<Map<String, Object>> afternoonSlots = (List<Map<String, Object>>) requestMap.get("afternoonTimeSlots");
|
||||
if (afternoonSlots != null) {
|
||||
List<XljkConsultationScheduleBatchBo.TimeSlot> timeSlots = afternoonSlots.stream()
|
||||
.map(slot -> {
|
||||
XljkConsultationScheduleBatchBo.TimeSlot timeSlot = new XljkConsultationScheduleBatchBo.TimeSlot();
|
||||
timeSlot.setStartTime(slot.get("startTime").toString());
|
||||
timeSlot.setEndTime(slot.get("endTime").toString());
|
||||
return timeSlot;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
batchBo.setAfternoonTimeSlots(timeSlots);
|
||||
}
|
||||
}
|
||||
|
||||
// 设置其他字段
|
||||
if (requestMap.containsKey("status")) {
|
||||
batchBo.setStatus(requestMap.get("status").toString());
|
||||
@@ -166,10 +206,13 @@ public class XljkConsultationScheduleController {
|
||||
*/
|
||||
@GetMapping("/options/counselors")
|
||||
public R<List<Map<String, Object>>> getCounselorOptions() {
|
||||
String sql = "SELECT u.user_id as id, u.nick_name as name FROM sys_user u " +
|
||||
String sql = "SELECT u.user_id as id, u.nick_name as name, c.office as office " +
|
||||
"FROM sys_user u " +
|
||||
"JOIN sys_user_role ur ON u.user_id = ur.user_id " +
|
||||
"JOIN sys_role r ON ur.role_id = r.role_id " +
|
||||
"WHERE r.role_key = 'xljk_consultant' AND u.del_flag = '0'";
|
||||
"LEFT JOIN xljk_consulter c ON u.user_id = c.user_id AND c.deleted = 0 " +
|
||||
"WHERE r.role_key = 'xljk_consultant' AND u.del_flag = '0' " +
|
||||
"ORDER BY u.nick_name";
|
||||
|
||||
List<Map<String, Object>> counselorOptions = jdbcTemplate.queryForList(sql);
|
||||
return R.ok(counselorOptions);
|
||||
|
||||
+179
@@ -0,0 +1,179 @@
|
||||
package org.dromara.xljk.controller;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.constraints.*;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.dromara.common.idempotent.annotation.RepeatSubmit;
|
||||
import org.dromara.common.log.annotation.Log;
|
||||
import org.dromara.common.web.core.BaseController;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import org.dromara.common.log.enums.BusinessType;
|
||||
import org.dromara.common.excel.utils.ExcelUtil;
|
||||
import org.dromara.xljk.domain.vo.XljkConsulterVo;
|
||||
import org.dromara.xljk.domain.bo.XljkConsulterBo;
|
||||
import org.dromara.xljk.service.IXljkConsulterService;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.system.service.ISysUserService;
|
||||
import org.dromara.system.domain.vo.SysUserVo;
|
||||
|
||||
/**
|
||||
* 心理咨询师配置
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2024-01-01
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/xljk/consulter")
|
||||
public class XljkConsulterController extends BaseController {
|
||||
|
||||
private final IXljkConsulterService xljkConsulterService;
|
||||
private final ISysUserService sysUserService;
|
||||
|
||||
/**
|
||||
* 查询心理咨询师配置列表
|
||||
*/
|
||||
@SaCheckPermission("xljk:consulter:list")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<XljkConsulterVo> list(XljkConsulterBo bo, PageQuery pageQuery) {
|
||||
return xljkConsulterService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出心理咨询师配置列表
|
||||
*/
|
||||
@SaCheckPermission("xljk:consulter:export")
|
||||
@Log(title = "心理咨询师配置", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(XljkConsulterBo bo, HttpServletResponse response) {
|
||||
List<XljkConsulterVo> list = xljkConsulterService.queryList(bo);
|
||||
ExcelUtil.exportExcel(list, "心理咨询师配置", XljkConsulterVo.class, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取心理咨询师配置详细信息
|
||||
*/
|
||||
@SaCheckPermission("xljk:consulter:query")
|
||||
@GetMapping("/{id}")
|
||||
public R<XljkConsulterVo> getInfo(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long id) {
|
||||
return R.ok(xljkConsulterService.queryById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增心理咨询师配置
|
||||
*/
|
||||
@SaCheckPermission("xljk:consulter:add")
|
||||
@Log(title = "心理咨询师配置", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping()
|
||||
public R<Void> add(@Validated(AddGroup.class) @RequestBody XljkConsulterBo bo) {
|
||||
return toAjax(xljkConsulterService.insertByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改心理咨询师配置
|
||||
*/
|
||||
@SaCheckPermission("xljk:consulter:edit")
|
||||
@Log(title = "心理咨询师配置", businessType = BusinessType.UPDATE)
|
||||
@RepeatSubmit()
|
||||
@PutMapping()
|
||||
public R<Void> edit(@Validated(EditGroup.class) @RequestBody XljkConsulterBo bo) {
|
||||
return toAjax(xljkConsulterService.updateByBo(bo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除心理咨询师配置
|
||||
*/
|
||||
@SaCheckPermission("xljk:consulter:remove")
|
||||
@Log(title = "心理咨询师配置", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public R<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||
@PathVariable Long[] ids) {
|
||||
return toAjax(xljkConsulterService.deleteWithValidByIds(List.of(ids)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量添加咨询师
|
||||
*/
|
||||
@SaCheckPermission("xljk:consulter:add")
|
||||
@Log(title = "批量添加咨询师", businessType = BusinessType.INSERT)
|
||||
@RepeatSubmit()
|
||||
@PostMapping("/batchAdd")
|
||||
public R<Void> batchAdd(@RequestBody BatchAddRequest request) {
|
||||
return toAjax(xljkConsulterService.batchAddConsulters(request.getUserIds(), request.getRemark()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询我配置的咨询师列表
|
||||
*/
|
||||
@SaCheckPermission("xljk:consulter:list")
|
||||
@GetMapping("/myConfig")
|
||||
public TableDataInfo<XljkConsulterVo> myConfigList(XljkConsulterBo bo, PageQuery pageQuery) {
|
||||
return xljkConsulterService.queryMyConfigList(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量启用咨询师
|
||||
*/
|
||||
@SaCheckPermission("xljk:consulter:edit")
|
||||
@Log(title = "启用咨询师", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/enable")
|
||||
public R<Void> enable(@RequestBody List<Long> ids) {
|
||||
return toAjax(xljkConsulterService.enableConsulters(ids));
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量停用咨询师
|
||||
*/
|
||||
@SaCheckPermission("xljk:consulter:edit")
|
||||
@Log(title = "停用咨询师", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/disable")
|
||||
public R<Void> disable(@RequestBody List<Long> ids) {
|
||||
return toAjax(xljkConsulterService.disableConsulters(ids));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据部门ID获取用户列表
|
||||
*/
|
||||
@SaCheckPermission("xljk:consulter:list")
|
||||
@GetMapping("/users/{deptId}")
|
||||
public R<List<SysUserVo>> listUserByDeptId(@PathVariable String deptId) {
|
||||
List<SysUserVo> users = sysUserService.selectUserListByDept(Long.valueOf(deptId));
|
||||
return R.ok(users);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量添加请求对象
|
||||
*/
|
||||
public static class BatchAddRequest {
|
||||
private List<Long> userIds;
|
||||
private String remark;
|
||||
|
||||
public List<Long> getUserIds() {
|
||||
return userIds;
|
||||
}
|
||||
|
||||
public void setUserIds(List<Long> userIds) {
|
||||
this.userIds = userIds;
|
||||
}
|
||||
|
||||
public String getRemark() {
|
||||
return remark;
|
||||
}
|
||||
|
||||
public void setRemark(String remark) {
|
||||
this.remark = remark;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+13
-1
@@ -3,6 +3,7 @@ package org.dromara.xljk.domain;
|
||||
import java.util.Date;
|
||||
import java.io.Serializable;
|
||||
import lombok.Data;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
|
||||
@Data
|
||||
public class XljkConsultationAppointment implements Serializable {
|
||||
@@ -21,9 +22,20 @@ public class XljkConsultationAppointment implements Serializable {
|
||||
private String appointmentTime;
|
||||
private String appointmentDetailTime; // 具体预约时间段,如"08:30-09:00"
|
||||
private String reason;
|
||||
|
||||
@TableField("consult_theme")
|
||||
private String consultTheme; // 咨询主题
|
||||
|
||||
private String status;
|
||||
private Date actualVisitTime;
|
||||
private Integer communicationDuration;
|
||||
private String consultationContent;
|
||||
private String counselorSuggestion;
|
||||
|
||||
// 新增心理健康相关字段
|
||||
private String studentName; // 学生姓名(冗余字段)
|
||||
private Integer psychologicalHistory; // 心理病史(1-否,2-是)
|
||||
private String psychologicalHistoryDetail; // 心理病史详情
|
||||
private String basicSituation; // 基本情况
|
||||
private String majorLifeEvents; // 重大生活事件
|
||||
private Integer needReferral; // 是否需要转介(1-不需要,2-需要)
|
||||
}
|
||||
+2
-1
@@ -15,8 +15,9 @@ public class XljkConsultationSchedule implements Serializable {
|
||||
private Date updateTime;
|
||||
private Integer deleted;
|
||||
private Long counselorId;
|
||||
private String office; // 办公室
|
||||
private Date scheduleDate;
|
||||
private String timeSlot; // 0上午 1下午
|
||||
private String timeSlot; // 0中午 1下午
|
||||
private String startTime; // 开始时间 HH:mm 格式
|
||||
private String endTime; // 结束时间 HH:mm 格式
|
||||
private String status; // 0正常 1停用
|
||||
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
package org.dromara.xljk.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.dromara.common.tenant.core.TenantEntity;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 心理咨询师配置对象 xljk_consulter
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2024-01-01
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("xljk_consulter")
|
||||
public class XljkConsulter extends TenantEntity implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 用户姓名
|
||||
*/
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 用户昵称
|
||||
*/
|
||||
private String nickName;
|
||||
|
||||
/**
|
||||
* 部门ID
|
||||
*/
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 部门名称
|
||||
*/
|
||||
private String deptName;
|
||||
|
||||
/**
|
||||
* 联系电话
|
||||
*/
|
||||
private String phoneNumber;
|
||||
|
||||
/**
|
||||
* 办公室
|
||||
*/
|
||||
private String office;
|
||||
|
||||
/**
|
||||
* 邮箱地址
|
||||
*/
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* 状态(1正常 0停用)
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 备注说明
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 配置人ID
|
||||
*/
|
||||
private Long configBy;
|
||||
|
||||
/**
|
||||
* 配置人姓名
|
||||
*/
|
||||
private String configByName;
|
||||
|
||||
/**
|
||||
* 删除标志(0代表存在 1代表删除)
|
||||
*/
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package org.dromara.xljk.domain;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 心理咨询用户和部门完整信息
|
||||
* 用于批量添加咨询师时获取完整的用户数据
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2025-01-03
|
||||
*/
|
||||
@Data
|
||||
public class XljkUserWithDeptInfo {
|
||||
|
||||
/** 用户ID */
|
||||
private Long userId;
|
||||
|
||||
/** 用户账号 */
|
||||
private String userName;
|
||||
|
||||
/** 用户昵称 */
|
||||
private String nickName;
|
||||
|
||||
/** 部门ID */
|
||||
private Long deptId;
|
||||
|
||||
/** 部门名称 */
|
||||
private String deptName;
|
||||
|
||||
/** 手机号码 */
|
||||
private String phonenumber;
|
||||
|
||||
/** 用户邮箱 */
|
||||
private String email;
|
||||
|
||||
/** 帐号状态(1正常 0停用) */
|
||||
private String status;
|
||||
|
||||
}
|
||||
+8
-1
@@ -22,12 +22,19 @@ public class XljkConsultationAppointmentBo {
|
||||
private String appointmentTime;
|
||||
private String appointmentDetailTime; // 具体预约时间段,如"08:30-09:00"
|
||||
private String reason;
|
||||
private String consultTheme; // 咨询主题
|
||||
private String status;
|
||||
private Date actualVisitTime;
|
||||
private Integer communicationDuration;
|
||||
private String consultationContent;
|
||||
private String counselorSuggestion;
|
||||
|
||||
// 新增心理健康相关字段
|
||||
private Integer psychologicalHistory; // 心理病史(1-否,2-是)
|
||||
private String psychologicalHistoryDetail; // 心理病史详情
|
||||
private String basicSituation; // 基本情况
|
||||
private String majorLifeEvents; // 重大生活事件
|
||||
private Integer needReferral; // 是否需要转介(1-不需要,2-需要)
|
||||
|
||||
// 查询参数字段
|
||||
private String studentName;
|
||||
private String studentNo;
|
||||
|
||||
+35
-5
@@ -2,6 +2,7 @@ package org.dromara.xljk.domain.bo;
|
||||
|
||||
import lombok.Data;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 批量创建预约时段的业务对象
|
||||
@@ -13,6 +14,11 @@ public class XljkConsultationScheduleBatchBo {
|
||||
*/
|
||||
private Long counselorId;
|
||||
|
||||
/**
|
||||
* 办公室
|
||||
*/
|
||||
private String office;
|
||||
|
||||
/**
|
||||
* 开始日期
|
||||
*/
|
||||
@@ -24,35 +30,50 @@ public class XljkConsultationScheduleBatchBo {
|
||||
private String endDate;
|
||||
|
||||
/**
|
||||
* 是否启用上午时段
|
||||
* 是否启用中午时段(字段名保持morningEnabled以兼容前端)
|
||||
*/
|
||||
private Boolean morningEnabled;
|
||||
|
||||
/**
|
||||
* 上午开始时间 (HH:mm)
|
||||
* 中午开始时间 (HH:mm)(字段名保持morningStartTime以兼容前端)
|
||||
*/
|
||||
private String morningStartTime;
|
||||
|
||||
/**
|
||||
* 上午结束时间 (HH:mm)
|
||||
* 中午结束时间 (HH:mm)(字段名保持morningEndTime以兼容前端)
|
||||
*/
|
||||
private String morningEndTime;
|
||||
|
||||
/**
|
||||
* 是否启用中午时段
|
||||
*/
|
||||
private Boolean noonEnabled;
|
||||
|
||||
/**
|
||||
* 中午时段列表
|
||||
*/
|
||||
private List<TimeSlot> noonTimeSlots;
|
||||
|
||||
/**
|
||||
* 是否启用下午时段
|
||||
*/
|
||||
private Boolean afternoonEnabled;
|
||||
|
||||
/**
|
||||
* 下午开始时间 (HH:mm)
|
||||
* 下午开始时间 (HH:mm)(兼容旧版本)
|
||||
*/
|
||||
private String afternoonStartTime;
|
||||
|
||||
/**
|
||||
* 下午结束时间 (HH:mm)
|
||||
* 下午结束时间 (HH:mm)(兼容旧版本)
|
||||
*/
|
||||
private String afternoonEndTime;
|
||||
|
||||
/**
|
||||
* 下午时段列表
|
||||
*/
|
||||
private List<TimeSlot> afternoonTimeSlots;
|
||||
|
||||
/**
|
||||
* 状态 (0正常 1停用)
|
||||
*/
|
||||
@@ -67,4 +88,13 @@ public class XljkConsultationScheduleBatchBo {
|
||||
* 批次ID,用于标识同一批次创建的预约时段
|
||||
*/
|
||||
private String batchId;
|
||||
|
||||
/**
|
||||
* 时段内部类
|
||||
*/
|
||||
@Data
|
||||
public static class TimeSlot {
|
||||
private String startTime;
|
||||
private String endTime;
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -14,8 +14,9 @@ public class XljkConsultationScheduleBo {
|
||||
private Date updateTime;
|
||||
private Integer deleted;
|
||||
private Long counselorId;
|
||||
private String office; // 办公室
|
||||
private Date scheduleDate;
|
||||
private String timeSlot; // 0上午 1下午
|
||||
private String timeSlot; // 0中午 1下午
|
||||
private String startTime; // 开始时间 HH:mm 格式
|
||||
private String endTime; // 结束时间 HH:mm 格式
|
||||
private String status;
|
||||
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
package org.dromara.xljk.domain.bo;
|
||||
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.dromara.common.core.validate.AddGroup;
|
||||
import org.dromara.common.core.validate.EditGroup;
|
||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||
import org.dromara.xljk.domain.XljkConsulter;
|
||||
|
||||
import jakarta.validation.constraints.*;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 心理咨询师配置业务对象 xljk_consulter
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2024-01-01
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@AutoMapper(target = XljkConsulter.class, reverseConvertGenerate = false)
|
||||
public class XljkConsulterBo extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@NotNull(message = "主键ID不能为空", groups = { EditGroup.class })
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
@NotNull(message = "用户ID不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 用户姓名
|
||||
*/
|
||||
@NotBlank(message = "用户姓名不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 用户昵称
|
||||
*/
|
||||
@NotBlank(message = "用户昵称不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String nickName;
|
||||
|
||||
/**
|
||||
* 部门ID
|
||||
*/
|
||||
@NotNull(message = "部门ID不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 部门名称
|
||||
*/
|
||||
@NotBlank(message = "部门名称不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String deptName;
|
||||
|
||||
/**
|
||||
* 联系电话
|
||||
*/
|
||||
private String phoneNumber;
|
||||
|
||||
/**
|
||||
* 办公室
|
||||
*/
|
||||
private String office;
|
||||
|
||||
/**
|
||||
* 邮箱地址
|
||||
*/
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* 状态(1正常 0停用)
|
||||
*/
|
||||
@NotBlank(message = "状态不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 备注说明
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 配置人ID
|
||||
*/
|
||||
private Long configBy;
|
||||
|
||||
/**
|
||||
* 配置人姓名
|
||||
*/
|
||||
private String configByName;
|
||||
|
||||
/**
|
||||
* 分页大小
|
||||
*/
|
||||
private Integer pageSize;
|
||||
|
||||
/**
|
||||
* 页码
|
||||
*/
|
||||
private Integer pageNum;
|
||||
|
||||
/**
|
||||
* 搜索值
|
||||
*/
|
||||
private String searchValue;
|
||||
|
||||
/**
|
||||
* 创建时间范围
|
||||
*/
|
||||
private List<Date> createTimeRange;
|
||||
|
||||
}
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
package org.dromara.xljk.domain.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 带预约状态的排班数据视图对象
|
||||
*/
|
||||
@Data
|
||||
public class ScheduleWithStatusVo {
|
||||
|
||||
/**
|
||||
* 排班ID
|
||||
*/
|
||||
private Long scheduleId;
|
||||
|
||||
/**
|
||||
* 咨询师ID
|
||||
*/
|
||||
private Long counselorId;
|
||||
|
||||
/**
|
||||
* 咨询师姓名
|
||||
*/
|
||||
private String counselorName;
|
||||
|
||||
/**
|
||||
* 排班日期
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private String date;
|
||||
|
||||
/**
|
||||
* 时段类型(0中午 1下午 2晚上)
|
||||
*/
|
||||
private String timeSlot;
|
||||
|
||||
/**
|
||||
* 开始时间(HH:mm)
|
||||
*/
|
||||
private String startTime;
|
||||
|
||||
/**
|
||||
* 结束时间(HH:mm)
|
||||
*/
|
||||
private String endTime;
|
||||
|
||||
/**
|
||||
* 时段显示文本(如:中午 08:30-12:00)
|
||||
*/
|
||||
private String timeDisplay;
|
||||
|
||||
/**
|
||||
* 是否已预约满
|
||||
*/
|
||||
private Boolean isFullyBooked;
|
||||
|
||||
/**
|
||||
* 是否已过期
|
||||
*/
|
||||
private Boolean isExpired;
|
||||
|
||||
/**
|
||||
* 可预约数量
|
||||
*/
|
||||
private Integer availableSlots;
|
||||
|
||||
/**
|
||||
* 总预约数量
|
||||
*/
|
||||
private Integer totalSlots;
|
||||
|
||||
// 以下是基础字段,用于避免MyBatis映射错误
|
||||
private Long createBy; // 创建者
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createTime; // 创建时间
|
||||
private Long updateBy; // 更新者
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date updateTime; // 更新时间
|
||||
}
|
||||
+11
-3
@@ -30,14 +30,12 @@ public class XljkConsultationAppointmentVo {
|
||||
private String appointmentTime;
|
||||
private String appointmentDetailTime; // 具体预约时间段,如"08:30-09:00"
|
||||
private String reason;
|
||||
private String consultTheme; // 咨询主题
|
||||
/**
|
||||
* 状态(0待咨询 1已完成 2已取消 3未到访)
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date actualVisitTime;
|
||||
|
||||
private Integer communicationDuration;
|
||||
private String consultationContent;
|
||||
private String counselorSuggestion;
|
||||
@@ -51,4 +49,14 @@ public class XljkConsultationAppointmentVo {
|
||||
// 新增院系和专业字段
|
||||
private String collegeName; // 院系名称
|
||||
private String majorName; // 专业名称
|
||||
|
||||
// 新增心理健康相关字段
|
||||
private Integer psychologicalHistory; // 心理病史(1-否,2-是)
|
||||
private String psychologicalHistoryDetail; // 心理病史详情
|
||||
private String basicSituation; // 基本情况
|
||||
private String majorLifeEvents; // 重大生活事件
|
||||
private Integer needReferral; // 是否需要转介(1-不需要,2-需要)
|
||||
|
||||
// 本学期到访次数(计算字段,不存储在数据库)
|
||||
private Integer semesterVisitCount;
|
||||
}
|
||||
+3
-2
@@ -18,11 +18,12 @@ public class XljkConsultationScheduleSummaryVo {
|
||||
private Integer deleted;
|
||||
private Long counselorId;
|
||||
private String counselorName; // 咨询师姓名,用于前端显示
|
||||
private String office; // 办公室,用于前端显示
|
||||
|
||||
// 汇总信息
|
||||
private String dateRange; // 日期范围,如"2025-07-01 至 2025-07-10"
|
||||
private Boolean morningEnabled; // 是否启用上午时段
|
||||
private String morningTime; // 上午时间,如"08:30-12:00"
|
||||
private Boolean morningEnabled; // 是否启用中午时段(字段名保持不变以兼容前端)
|
||||
private String morningTime; // 中午时间,如"08:30-12:00"
|
||||
private Boolean afternoonEnabled; // 是否启用下午时段
|
||||
private String afternoonTime; // 下午时间,如"14:30-17:00"
|
||||
private String status; // 状态
|
||||
|
||||
+2
-1
@@ -15,8 +15,9 @@ public class XljkConsultationScheduleVo {
|
||||
private Integer deleted;
|
||||
private Long counselorId;
|
||||
private String counselorName; // 咨询师姓名,用于前端显示
|
||||
private String office; // 办公室
|
||||
private Date scheduleDate;
|
||||
private String timeSlot; // 0上午 1下午
|
||||
private String timeSlot; // 0中午 1下午
|
||||
private String startTime; // 开始时间 HH:mm 格式
|
||||
private String endTime; // 结束时间 HH:mm 格式
|
||||
private String status;
|
||||
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
package org.dromara.xljk.domain.vo;
|
||||
|
||||
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import cn.idev.excel.annotation.ExcelProperty;
|
||||
import io.github.linpeilie.annotations.AutoMapper;
|
||||
import lombok.Data;
|
||||
import org.dromara.common.excel.annotation.ExcelDictFormat;
|
||||
import org.dromara.common.excel.convert.ExcelDictConvert;
|
||||
import org.dromara.xljk.domain.XljkConsulter;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 心理咨询师配置视图对象 xljk_consulter
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2024-01-01
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
@AutoMapper(target = XljkConsulter.class)
|
||||
public class XljkConsulterVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@ExcelProperty(value = "主键ID")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
@ExcelProperty(value = "用户ID")
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 用户姓名
|
||||
*/
|
||||
@ExcelProperty(value = "用户姓名")
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 用户昵称
|
||||
*/
|
||||
@ExcelProperty(value = "用户昵称")
|
||||
private String nickName;
|
||||
|
||||
/**
|
||||
* 部门ID
|
||||
*/
|
||||
@ExcelProperty(value = "部门ID")
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 部门名称
|
||||
*/
|
||||
@ExcelProperty(value = "部门名称")
|
||||
private String deptName;
|
||||
|
||||
/**
|
||||
* 联系电话
|
||||
*/
|
||||
@ExcelProperty(value = "联系电话")
|
||||
private String phoneNumber;
|
||||
|
||||
/**
|
||||
* 办公室
|
||||
*/
|
||||
@ExcelProperty(value = "办公室")
|
||||
private String office;
|
||||
|
||||
/**
|
||||
* 邮箱地址
|
||||
*/
|
||||
@ExcelProperty(value = "邮箱地址")
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* 状态(1正常 0停用)
|
||||
*/
|
||||
@ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
|
||||
@ExcelDictFormat(dictType = "sys_normal_disable")
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 备注说明
|
||||
*/
|
||||
@ExcelProperty(value = "备注说明")
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 配置人ID
|
||||
*/
|
||||
private Long configBy;
|
||||
|
||||
/**
|
||||
* 配置人姓名
|
||||
*/
|
||||
@ExcelProperty(value = "配置人")
|
||||
private String configByName;
|
||||
|
||||
/**
|
||||
* 租户编号
|
||||
*/
|
||||
private String tenantId;
|
||||
|
||||
/**
|
||||
* 创建部门
|
||||
*/
|
||||
private Long createDept;
|
||||
|
||||
/**
|
||||
* 创建者ID
|
||||
*/
|
||||
private Long createBy;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@ExcelProperty(value = "创建时间")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新者ID
|
||||
*/
|
||||
private Long updateBy;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@ExcelProperty(value = "更新时间")
|
||||
private Date updateTime;
|
||||
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
package org.dromara.xljk.mapper;
|
||||
|
||||
import org.dromara.xljk.domain.XljkConsulter;
|
||||
import org.dromara.xljk.domain.vo.XljkConsulterVo;
|
||||
import org.dromara.xljk.domain.XljkUserWithDeptInfo;
|
||||
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 心理咨询师配置Mapper接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2024-01-01
|
||||
*/
|
||||
public interface XljkConsulterMapper extends BaseMapperPlus<XljkConsulter, XljkConsulterVo> {
|
||||
|
||||
/**
|
||||
* 查询心理咨询师配置
|
||||
*
|
||||
* @param id 心理咨询师配置主键
|
||||
* @return 心理咨询师配置
|
||||
*/
|
||||
XljkConsulterVo selectXljkConsulterVoById(Long id);
|
||||
|
||||
/**
|
||||
* 查询心理咨询师配置列表
|
||||
*
|
||||
* @param xljkConsulter 心理咨询师配置
|
||||
* @return 心理咨询师配置集合
|
||||
*/
|
||||
List<XljkConsulterVo> selectXljkConsulterVoList(XljkConsulter xljkConsulter);
|
||||
|
||||
/**
|
||||
* 根据用户ID检查是否已存在咨询师配置
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 记录数
|
||||
*/
|
||||
int checkUserExists(@Param("userId") Long userId);
|
||||
|
||||
/**
|
||||
* 批量启用咨询师
|
||||
*
|
||||
* @param ids 咨询师ID列表
|
||||
* @return 影响行数
|
||||
*/
|
||||
int enableConsultersByIds(@Param("ids") List<Long> ids);
|
||||
|
||||
/**
|
||||
* 批量停用咨询师
|
||||
*
|
||||
* @param ids 咨询师ID列表
|
||||
* @return 影响行数
|
||||
*/
|
||||
int disableConsultersByIds(@Param("ids") List<Long> ids);
|
||||
|
||||
/**
|
||||
* 查询完整的用户信息(包含部门信息)用于批量添加
|
||||
*
|
||||
* @param userIds 用户ID列表
|
||||
* @return 用户和部门完整信息列表
|
||||
*/
|
||||
List<XljkUserWithDeptInfo> selectUsersWithDeptInfo(@Param("userIds") List<Long> userIds);
|
||||
|
||||
}
|
||||
+19
-4
@@ -4,6 +4,7 @@ import org.dromara.xljk.domain.XljkConsultationAppointment;
|
||||
import org.dromara.xljk.domain.bo.XljkConsultationAppointmentBo;
|
||||
import org.dromara.xljk.domain.vo.XljkConsultationAppointmentVo;
|
||||
import org.dromara.xljk.domain.vo.TimeSlotDetailVo;
|
||||
import org.dromara.xljk.domain.vo.ScheduleWithStatusVo;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import java.util.List;
|
||||
@@ -43,7 +44,7 @@ public interface IXljkConsultationAppointmentService {
|
||||
/**
|
||||
* 获取可用的详细时段列表(30分钟一个时段)
|
||||
* @param date 日期
|
||||
* @param timeSlot 时段类型(0上午 1下午)
|
||||
* @param timeSlot 时段类型(0中午 1下午)
|
||||
* @return 详细时段列表
|
||||
*/
|
||||
List<TimeSlotDetailVo> getAvailableDetailSlots(Date date, String timeSlot);
|
||||
@@ -65,15 +66,21 @@ public interface IXljkConsultationAppointmentService {
|
||||
/**
|
||||
* 记录咨询结果
|
||||
* @param id 预约ID
|
||||
* @param actualVisitTime 实际到访时间
|
||||
* @param communicationDuration 沟通时长
|
||||
* @param consultationContent 咨询内容
|
||||
* @param counselorSuggestion 咨询师建议
|
||||
* @param status 状态(1已完成/3未到访)
|
||||
* @param psychologicalHistory 心理病史(1-否,2-是)
|
||||
* @param psychologicalHistoryDetail 心理病史详情
|
||||
* @param basicSituation 基本情况
|
||||
* @param majorLifeEvents 重大生活事件
|
||||
* @param needReferral 是否需要转介(1-不需要,2-需要)
|
||||
* @return 是否成功
|
||||
*/
|
||||
boolean recordConsultation(Long id, Date actualVisitTime, Integer communicationDuration,
|
||||
String consultationContent, String counselorSuggestion, String status);
|
||||
boolean recordConsultation(Long id, Integer communicationDuration,
|
||||
String consultationContent, String counselorSuggestion, String status,
|
||||
Integer psychologicalHistory, String psychologicalHistoryDetail,
|
||||
String basicSituation, String majorLifeEvents, Integer needReferral);
|
||||
|
||||
/**
|
||||
* 获取院系选项
|
||||
@@ -95,4 +102,12 @@ public interface IXljkConsultationAppointmentService {
|
||||
* @return 班级选项列表
|
||||
*/
|
||||
List<Map<String, Object>> getClassOptions(String collegeName, String majorName);
|
||||
|
||||
/**
|
||||
* 获取日历视图的排班数据(带预约状态)
|
||||
* @param startDate 开始日期
|
||||
* @param endDate 结束日期
|
||||
* @return 排班数据列表
|
||||
*/
|
||||
List<ScheduleWithStatusVo> getCalendarSchedules(String startDate, String endDate);
|
||||
}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
package org.dromara.xljk.service;
|
||||
|
||||
import org.dromara.xljk.domain.vo.XljkConsulterVo;
|
||||
import org.dromara.xljk.domain.bo.XljkConsulterBo;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 心理咨询师配置Service接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2024-01-01
|
||||
*/
|
||||
public interface IXljkConsulterService {
|
||||
|
||||
/**
|
||||
* 查询心理咨询师配置
|
||||
*
|
||||
* @param id 主键
|
||||
* @return 心理咨询师配置
|
||||
*/
|
||||
XljkConsulterVo queryById(Long id);
|
||||
|
||||
/**
|
||||
* 查询心理咨询师配置列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return 心理咨询师配置集合
|
||||
*/
|
||||
TableDataInfo<XljkConsulterVo> queryPageList(XljkConsulterBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 查询心理咨询师配置列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return 心理咨询师配置集合
|
||||
*/
|
||||
List<XljkConsulterVo> queryList(XljkConsulterBo bo);
|
||||
|
||||
/**
|
||||
* 新增心理咨询师配置
|
||||
*
|
||||
* @param bo 心理咨询师配置
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean insertByBo(XljkConsulterBo bo);
|
||||
|
||||
/**
|
||||
* 修改心理咨询师配置
|
||||
*
|
||||
* @param bo 心理咨询师配置
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean updateByBo(XljkConsulterBo bo);
|
||||
|
||||
/**
|
||||
* 校验并批量删除心理咨询师配置信息
|
||||
*
|
||||
* @param ids 需要删除的主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean deleteWithValidByIds(Collection<Long> ids);
|
||||
|
||||
/**
|
||||
* 批量添加咨询师
|
||||
*
|
||||
* @param userIds 用户ID列表
|
||||
* @param remark 备注
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean batchAddConsulters(List<Long> userIds, String remark);
|
||||
|
||||
/**
|
||||
* 查询我配置的咨询师列表
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @param pageQuery 分页参数
|
||||
* @return 咨询师列表
|
||||
*/
|
||||
TableDataInfo<XljkConsulterVo> queryMyConfigList(XljkConsulterBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 批量启用咨询师
|
||||
*
|
||||
* @param ids 咨询师ID列表
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean enableConsulters(List<Long> ids);
|
||||
|
||||
/**
|
||||
* 批量停用咨询师
|
||||
*
|
||||
* @param ids 咨询师ID列表
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean disableConsulters(List<Long> ids);
|
||||
|
||||
}
|
||||
+393
-67
@@ -10,6 +10,7 @@ import org.dromara.xljk.domain.XljkConsultationSchedule;
|
||||
import org.dromara.xljk.domain.bo.XljkConsultationAppointmentBo;
|
||||
import org.dromara.xljk.domain.vo.XljkConsultationAppointmentVo;
|
||||
import org.dromara.xljk.domain.vo.TimeSlotDetailVo;
|
||||
import org.dromara.xljk.domain.vo.ScheduleWithStatusVo;
|
||||
import org.dromara.xljk.mapper.XljkConsultationAppointmentMapper;
|
||||
import org.dromara.xljk.mapper.XljkConsultationScheduleMapper;
|
||||
import org.dromara.xljk.service.IXljkConsultationAppointmentService;
|
||||
@@ -38,6 +39,8 @@ import org.dromara.common.core.utils.SpringUtils;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import java.time.LocalDate;
|
||||
import java.time.Month;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@@ -71,9 +74,8 @@ public class XljkConsultationAppointmentServiceImpl implements IXljkConsultation
|
||||
BeanUtils.copyProperties(entity, vo);
|
||||
|
||||
// 记录关键字段
|
||||
log.info("复制后的VO对象关键字段:status={}, actualVisitTime={}, communicationDuration={}, consultationContent长度={}, counselorSuggestion长度={}",
|
||||
log.info("复制后的VO对象关键字段:status={}, communicationDuration={}, consultationContent长度={}, counselorSuggestion长度={}",
|
||||
vo.getStatus(),
|
||||
vo.getActualVisitTime(),
|
||||
vo.getCommunicationDuration(),
|
||||
vo.getConsultationContent() != null ? vo.getConsultationContent().length() : 0,
|
||||
vo.getCounselorSuggestion() != null ? vo.getCounselorSuggestion().length() : 0);
|
||||
@@ -128,23 +130,8 @@ public class XljkConsultationAppointmentServiceImpl implements IXljkConsultation
|
||||
|
||||
// 再次检查关键字段
|
||||
if (vo.getStatus() != null && vo.getStatus() == 1) {
|
||||
log.info("已到访状态,检查咨询结果相关字段:actualVisitTime={}, communicationDuration={}",
|
||||
vo.getActualVisitTime(), vo.getCommunicationDuration());
|
||||
|
||||
// 如果是已到访状态但实际到访时间为空,尝试从数据库直接查询
|
||||
if (vo.getActualVisitTime() == null) {
|
||||
log.warn("已到访状态但实际到访时间为空,尝试从数据库直接查询");
|
||||
try {
|
||||
String timeSql = "SELECT actual_visit_time FROM xljk_consultation_appointment WHERE id = " + id;
|
||||
Date actualVisitTime = jdbcTemplate.queryForObject(timeSql, Date.class);
|
||||
if (actualVisitTime != null) {
|
||||
log.info("从数据库查询到实际到访时间: {}", actualVisitTime);
|
||||
vo.setActualVisitTime(actualVisitTime);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("查询实际到访时间失败", e);
|
||||
}
|
||||
}
|
||||
log.info("已到访状态,检查咨询结果相关字段:communicationDuration={}",
|
||||
vo.getCommunicationDuration());
|
||||
}
|
||||
|
||||
log.info("返回预约记录详情: {}", vo);
|
||||
@@ -238,6 +225,9 @@ public class XljkConsultationAppointmentServiceImpl implements IXljkConsultation
|
||||
return resultList.stream().map(row -> {
|
||||
XljkConsultationAppointmentVo vo = new XljkConsultationAppointmentVo();
|
||||
|
||||
// 获取学生ID用于计算本学期到访次数
|
||||
Long studentId = row.get("student_id") != null ? ((Number) row.get("student_id")).longValue() : null;
|
||||
|
||||
// 设置基本字段
|
||||
vo.setId(((Number) row.get("id")).longValue());
|
||||
vo.setTenantId((String) row.get("tenant_id"));
|
||||
@@ -291,11 +281,44 @@ public class XljkConsultationAppointmentServiceImpl implements IXljkConsultation
|
||||
vo.setStatus(0); // 默认为待咨询
|
||||
}
|
||||
|
||||
vo.setActualVisitTime(convertToDate(row.get("actual_visit_time")));
|
||||
vo.setCommunicationDuration(row.get("communication_duration") != null ? ((Number) row.get("communication_duration")).intValue() : null);
|
||||
vo.setConsultationContent((String) row.get("consultation_content"));
|
||||
vo.setCounselorSuggestion((String) row.get("counselor_suggestion"));
|
||||
|
||||
// 设置咨询主题字段
|
||||
vo.setConsultTheme((String) row.get("consult_theme"));
|
||||
|
||||
// 设置心理健康相关字段
|
||||
Object psychologicalHistoryObj = row.get("psychological_history");
|
||||
if (psychologicalHistoryObj != null) {
|
||||
if (psychologicalHistoryObj instanceof Number) {
|
||||
vo.setPsychologicalHistory(((Number) psychologicalHistoryObj).intValue());
|
||||
} else if (psychologicalHistoryObj instanceof String) {
|
||||
try {
|
||||
vo.setPsychologicalHistory(Integer.parseInt((String) psychologicalHistoryObj));
|
||||
} catch (NumberFormatException e) {
|
||||
vo.setPsychologicalHistory(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vo.setPsychologicalHistoryDetail((String) row.get("psychological_history_detail"));
|
||||
vo.setBasicSituation((String) row.get("basic_situation"));
|
||||
vo.setMajorLifeEvents((String) row.get("major_life_events"));
|
||||
|
||||
Object needReferralObj = row.get("need_referral");
|
||||
if (needReferralObj != null) {
|
||||
if (needReferralObj instanceof Number) {
|
||||
vo.setNeedReferral(((Number) needReferralObj).intValue());
|
||||
} else if (needReferralObj instanceof String) {
|
||||
try {
|
||||
vo.setNeedReferral(Integer.parseInt((String) needReferralObj));
|
||||
} catch (NumberFormatException e) {
|
||||
vo.setNeedReferral(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 设置关联字段
|
||||
vo.setStudentName((String) row.get("student_name"));
|
||||
vo.setStudentNo((String) row.get("student_no"));
|
||||
@@ -304,9 +327,68 @@ public class XljkConsultationAppointmentServiceImpl implements IXljkConsultation
|
||||
vo.setCollegeName((String) row.get("college_name"));
|
||||
vo.setMajorName((String) row.get("major_name"));
|
||||
|
||||
// 计算本学期到访次数
|
||||
if (studentId != null) {
|
||||
vo.setSemesterVisitCount(calculateSemesterVisitCount(studentId));
|
||||
} else {
|
||||
vo.setSemesterVisitCount(0);
|
||||
}
|
||||
|
||||
return vo;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算学生本学期到访次数
|
||||
* 上学期:3月1日-8月31日
|
||||
* 下学期:9月1日-2月29日
|
||||
* @param studentId 学生ID
|
||||
* @return 本学期到访次数
|
||||
*/
|
||||
private int calculateSemesterVisitCount(Long studentId) {
|
||||
try {
|
||||
// 获取当前日期
|
||||
LocalDate now = LocalDate.now();
|
||||
String startDate, endDate;
|
||||
|
||||
// 判断当前处于哪个学期
|
||||
if (now.getMonthValue() >= 3 && now.getMonthValue() <= 8) {
|
||||
// 上学期:3月1日-8月31日
|
||||
startDate = now.getYear() + "-03-01";
|
||||
endDate = now.getYear() + "-08-31";
|
||||
} else if (now.getMonthValue() >= 9) {
|
||||
// 下学期:9月1日-次年2月29日(当年9月到次年2月)
|
||||
startDate = now.getYear() + "-09-01";
|
||||
// 计算次年2月的最后一天
|
||||
int nextYear = now.getYear() + 1;
|
||||
LocalDate nextFeb = LocalDate.of(nextYear, Month.FEBRUARY, 1);
|
||||
LocalDate lastDayOfFeb = nextFeb.withDayOfMonth(nextFeb.lengthOfMonth());
|
||||
endDate = lastDayOfFeb.toString();
|
||||
} else {
|
||||
// 1月、2月属于上一学年的下学期
|
||||
int prevYear = now.getYear() - 1;
|
||||
startDate = prevYear + "-09-01";
|
||||
// 当年2月的最后一天
|
||||
LocalDate currentFeb = LocalDate.of(now.getYear(), Month.FEBRUARY, 1);
|
||||
LocalDate lastDayOfFeb = currentFeb.withDayOfMonth(currentFeb.lengthOfMonth());
|
||||
endDate = lastDayOfFeb.toString();
|
||||
}
|
||||
|
||||
// 查询该学生在当前学期内状态为已到访(status=1)的记录数
|
||||
String sql = "SELECT COUNT(*) FROM xljk_consultation_appointment " +
|
||||
"WHERE student_id = ? AND status = 1 AND deleted = 0 " +
|
||||
"AND appointment_date >= ? AND appointment_date <= ?";
|
||||
|
||||
Integer count = jdbcTemplate.queryForObject(sql, Integer.class, studentId, startDate, endDate);
|
||||
|
||||
log.debug("学生ID: {}, 学期时间段: {} - {}, 到访次数: {}", studentId, startDate, endDate, count);
|
||||
|
||||
return count != null ? count : 0;
|
||||
} catch (Exception e) {
|
||||
log.error("计算学生本学期到访次数失败,学生ID: {}", studentId, e);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean insert(XljkConsultationAppointmentBo bo) {
|
||||
@@ -341,7 +423,7 @@ public class XljkConsultationAppointmentServiceImpl implements IXljkConsultation
|
||||
LambdaQueryWrapper<XljkConsultationAppointment> appointmentQueryWrapper = new LambdaQueryWrapper<>();
|
||||
appointmentQueryWrapper.ge(XljkConsultationAppointment::getAppointmentDate, startDate)
|
||||
.le(XljkConsultationAppointment::getAppointmentDate, endDate)
|
||||
.in(XljkConsultationAppointment::getStatus, Arrays.asList("0", "1")); // 待咨询或已完成的
|
||||
.in(XljkConsultationAppointment::getStatus, Arrays.asList("0", "1", "4")); // 待咨询、已完成或待审核的
|
||||
|
||||
List<XljkConsultationAppointment> appointments = mapper.selectList(appointmentQueryWrapper);
|
||||
|
||||
@@ -365,9 +447,10 @@ public class XljkConsultationAppointmentServiceImpl implements IXljkConsultation
|
||||
String dateStr = new SimpleDateFormat("yyyy-MM-dd").format(schedule.getScheduleDate());
|
||||
String key = dateStr + "_" + schedule.getId();
|
||||
|
||||
// 检查该时段的可用详细时段
|
||||
// 检查该时段的可用详细时段(用于时间判断,但总容量固定为1)
|
||||
List<TimeSlotDetailVo> detailSlots = TimeSlotUtils.generateTimeSlots(schedule.getStartTime(), schedule.getEndTime());
|
||||
int totalDetailSlots = detailSlots.size();
|
||||
int totalDetailSlots = detailSlots.size(); // 保留用于时间过期判断
|
||||
int totalSlots = 1; // 每个时段只能预约1个人
|
||||
int bookedCount = 0;
|
||||
boolean isExpired = false;
|
||||
|
||||
@@ -408,15 +491,11 @@ public class XljkConsultationAppointmentServiceImpl implements IXljkConsultation
|
||||
isExpired = false;
|
||||
}
|
||||
|
||||
// 检查已预约的详细时段
|
||||
// 检查已预约数量(按整个时段计算,不再按详细时段计算)
|
||||
if (bookedDetailSlots.containsKey(key)) {
|
||||
List<String> bookedTimes = bookedDetailSlots.get(key);
|
||||
for (TimeSlotDetailVo slot : detailSlots) {
|
||||
String detailTime = slot.getStartTime() + "-" + slot.getEndTime();
|
||||
if (bookedTimes.contains(detailTime)) {
|
||||
bookedCount++;
|
||||
}
|
||||
}
|
||||
// 只要有任何预约,就算已预约1个(因为每个时段只能预约1个人)
|
||||
bookedCount = bookedTimes.isEmpty() ? 0 : 1;
|
||||
}
|
||||
|
||||
// 创建时段信息
|
||||
@@ -427,8 +506,8 @@ public class XljkConsultationAppointmentServiceImpl implements IXljkConsultation
|
||||
slot.put("timeSlot", schedule.getTimeSlot());
|
||||
slot.put("startTime", schedule.getStartTime());
|
||||
slot.put("endTime", schedule.getEndTime());
|
||||
slot.put("allBooked", bookedCount >= totalDetailSlots); // 是否全部约满
|
||||
slot.put("availableCount", totalDetailSlots - bookedCount); // 可用数量
|
||||
slot.put("allBooked", bookedCount >= totalSlots); // 是否全部约满
|
||||
slot.put("availableCount", totalSlots - bookedCount); // 可用数量
|
||||
slot.put("isExpired", isExpired); // 是否已过期
|
||||
|
||||
// 查询咨询师姓名
|
||||
@@ -463,21 +542,34 @@ public class XljkConsultationAppointmentServiceImpl implements IXljkConsultation
|
||||
.eq(XljkConsultationSchedule::getTimeSlot, timeSlot)
|
||||
.eq(XljkConsultationSchedule::getStatus, "0"); // 0表示正常可用
|
||||
|
||||
XljkConsultationSchedule schedule = scheduleMapper.selectOne(scheduleQueryWrapper);
|
||||
// 修改:使用selectList()而不是selectOne(),因为可能有多条记录
|
||||
List<XljkConsultationSchedule> schedules = scheduleMapper.selectList(scheduleQueryWrapper);
|
||||
|
||||
if (schedule == null) {
|
||||
if (schedules == null || schedules.isEmpty()) {
|
||||
// 该日期没有排班
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
// 2. 生成30分钟时段列表
|
||||
List<TimeSlotDetailVo> timeSlots = TimeSlotUtils.generateTimeSlots(schedule.getStartTime(), schedule.getEndTime());
|
||||
// 2. 合并所有排班的时段,生成完整的30分钟时段列表
|
||||
List<TimeSlotDetailVo> allTimeSlots = new ArrayList<>();
|
||||
Set<String> uniqueTimeSlots = new LinkedHashSet<>(); // 用于去重,保持顺序
|
||||
|
||||
// 3. 查询已预约的时段
|
||||
for (XljkConsultationSchedule schedule : schedules) {
|
||||
List<TimeSlotDetailVo> timeSlots = TimeSlotUtils.generateTimeSlots(schedule.getStartTime(), schedule.getEndTime());
|
||||
for (TimeSlotDetailVo slot : timeSlots) {
|
||||
String slotKey = slot.getStartTime() + "-" + slot.getEndTime();
|
||||
if (uniqueTimeSlots.add(slotKey)) {
|
||||
allTimeSlots.add(slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 查询已预约的时段(查询所有相关排班的预约)
|
||||
List<Long> scheduleIds = schedules.stream().map(XljkConsultationSchedule::getId).collect(Collectors.toList());
|
||||
LambdaQueryWrapper<XljkConsultationAppointment> appointmentQueryWrapper = new LambdaQueryWrapper<>();
|
||||
appointmentQueryWrapper.eq(XljkConsultationAppointment::getAppointmentDate, date)
|
||||
.eq(XljkConsultationAppointment::getScheduleId, schedule.getId()) // 按排班ID过滤,确保只查询当前时段的预约
|
||||
.in(XljkConsultationAppointment::getStatus, Arrays.asList("0", "1")); // 待咨询或已完成的
|
||||
.in(XljkConsultationAppointment::getScheduleId, scheduleIds) // 按排班ID列表过滤
|
||||
.in(XljkConsultationAppointment::getStatus, Arrays.asList("0", "1", "4")); // 待咨询、已完成或待审核的
|
||||
|
||||
List<XljkConsultationAppointment> appointments = mapper.selectList(appointmentQueryWrapper);
|
||||
|
||||
@@ -491,7 +583,7 @@ public class XljkConsultationAppointmentServiceImpl implements IXljkConsultation
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(date);
|
||||
|
||||
for (TimeSlotDetailVo slot : timeSlots) {
|
||||
for (TimeSlotDetailVo slot : allTimeSlots) {
|
||||
String detailTime = slot.getStartTime() + "-" + slot.getEndTime();
|
||||
|
||||
// 检查是否已预约
|
||||
@@ -532,7 +624,7 @@ public class XljkConsultationAppointmentServiceImpl implements IXljkConsultation
|
||||
}
|
||||
}
|
||||
|
||||
return timeSlots;
|
||||
return allTimeSlots;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -582,7 +674,7 @@ public class XljkConsultationAppointmentServiceImpl implements IXljkConsultation
|
||||
XljkConsultationAppointment entity = new XljkConsultationAppointment();
|
||||
BeanUtils.copyProperties(bo, entity);
|
||||
entity.setStudentId(studentId); // 使用验证后的学生ID
|
||||
entity.setStatus("0"); // 0表示待咨询
|
||||
entity.setStatus("4"); // 4表示待审核
|
||||
entity.setCreateTime(new Date()); // 设置创建时间
|
||||
return mapper.insert(entity) > 0;
|
||||
}
|
||||
@@ -645,10 +737,6 @@ if (statusObj != null) {
|
||||
vo.setScheduleId(((Number) row.get("schedule_id")).longValue());
|
||||
}
|
||||
|
||||
if (row.get("actual_visit_time") != null) {
|
||||
vo.setActualVisitTime(convertToDate(row.get("actual_visit_time")));
|
||||
}
|
||||
|
||||
if (row.get("communication_duration") != null) {
|
||||
vo.setCommunicationDuration(((Number) row.get("communication_duration")).intValue());
|
||||
}
|
||||
@@ -691,9 +779,11 @@ if (statusObj != null) {
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public boolean recordConsultation(Long id, Date actualVisitTime, Integer communicationDuration,
|
||||
String consultationContent, String counselorSuggestion, String status) {
|
||||
log.info("记录咨询结果,ID: {}, 状态: {}, 实际到访时间: {}", id, status, actualVisitTime);
|
||||
public boolean recordConsultation(Long id, Integer communicationDuration,
|
||||
String consultationContent, String counselorSuggestion, String status,
|
||||
Integer psychologicalHistory, String psychologicalHistoryDetail,
|
||||
String basicSituation, String majorLifeEvents, Integer needReferral) {
|
||||
log.info("记录咨询结果,ID: {}, 状态: {}, 心理病史: {}, 转介: {}", id, status, psychologicalHistory, needReferral);
|
||||
|
||||
XljkConsultationAppointment entity = mapper.selectById(id);
|
||||
if (entity == null) {
|
||||
@@ -717,29 +807,42 @@ if (statusObj != null) {
|
||||
|
||||
// 只有在已到访状态(1)时,才设置咨询结果相关字段
|
||||
if (statusInt == 1) {
|
||||
if (actualVisitTime == null) {
|
||||
log.warn("实际到访时间为空,使用当前时间");
|
||||
actualVisitTime = new Date();
|
||||
}
|
||||
|
||||
entity.setActualVisitTime(actualVisitTime);
|
||||
entity.setCommunicationDuration(communicationDuration != null ? communicationDuration : 30);
|
||||
entity.setConsultationContent(consultationContent);
|
||||
entity.setCounselorSuggestion(counselorSuggestion);
|
||||
|
||||
log.info("设置咨询结果相关字段:实际到访时间={}, 沟通时长={}, 咨询内容长度={}, 咨询师建议长度={}",
|
||||
actualVisitTime,
|
||||
// 设置心理病史相关字段
|
||||
entity.setPsychologicalHistory(psychologicalHistory);
|
||||
entity.setPsychologicalHistoryDetail(psychologicalHistoryDetail);
|
||||
entity.setBasicSituation(basicSituation);
|
||||
entity.setMajorLifeEvents(majorLifeEvents);
|
||||
entity.setNeedReferral(needReferral);
|
||||
|
||||
log.info("设置咨询结果相关字段:沟通时长={}, 咨询内容长度={}, 咨询师建议长度={}",
|
||||
communicationDuration,
|
||||
consultationContent != null ? consultationContent.length() : 0,
|
||||
counselorSuggestion != null ? counselorSuggestion.length() : 0);
|
||||
|
||||
log.info("设置心理病史相关字段:心理病史={}, 心理病史详情长度={}, 基本情况长度={}, 重大生活事件长度={}, 转介={}",
|
||||
psychologicalHistory,
|
||||
psychologicalHistoryDetail != null ? psychologicalHistoryDetail.length() : 0,
|
||||
basicSituation != null ? basicSituation.length() : 0,
|
||||
majorLifeEvents != null ? majorLifeEvents.length() : 0,
|
||||
needReferral);
|
||||
} else {
|
||||
// 未到访状态,清空咨询结果相关字段
|
||||
log.info("非已到访状态,清空咨询结果相关字段");
|
||||
entity.setActualVisitTime(null);
|
||||
entity.setCommunicationDuration(0);
|
||||
entity.setConsultationContent("");
|
||||
entity.setCounselorSuggestion("");
|
||||
|
||||
// 清空心理病史相关字段
|
||||
entity.setPsychologicalHistory(null);
|
||||
entity.setPsychologicalHistoryDetail("");
|
||||
entity.setBasicSituation("");
|
||||
entity.setMajorLifeEvents("");
|
||||
entity.setNeedReferral(null);
|
||||
|
||||
// 如果是未到访状态(3),创建未到访记录
|
||||
if (statusInt == 3) {
|
||||
log.info("记录未到访,创建未到访记录");
|
||||
@@ -1323,10 +1426,19 @@ if (statusObj != null) {
|
||||
public TableDataInfo<XljkConsultationAppointmentVo> selectPageList(XljkConsultationAppointmentBo bo, PageQuery pageQuery) {
|
||||
log.info("分页查询预约记录列表,页码: {}, 每页数量: {}", pageQuery.getPageNum(), pageQuery.getPageSize());
|
||||
|
||||
// 将变量定义移到try块外,确保catch块可以访问
|
||||
StringBuilder sqlBuilder = new StringBuilder();
|
||||
List<Object> params = new ArrayList<>();
|
||||
|
||||
try {
|
||||
// 构建查询条件
|
||||
StringBuilder sqlBuilder = new StringBuilder();
|
||||
sqlBuilder.append("SELECT a.*, s.name AS student_name, s.student_no, ");
|
||||
sqlBuilder.append("SELECT a.id, a.tenant_id, a.student_id, a.counselor_id, a.schedule_id, ");
|
||||
sqlBuilder.append("a.appointment_date, a.appointment_time, a.appointment_detail_time, ");
|
||||
sqlBuilder.append("a.reason, a.status, a.communication_duration, a.consultation_content, ");
|
||||
sqlBuilder.append("a.counselor_suggestion, a.psychological_history, a.psychological_history_detail, ");
|
||||
sqlBuilder.append("a.basic_situation, a.major_life_events, a.need_referral, ");
|
||||
sqlBuilder.append("a.create_by, a.create_time, a.update_by, a.update_time, ");
|
||||
sqlBuilder.append("s.name AS student_name, s.student_no, ");
|
||||
sqlBuilder.append("s.college_name, s.major_name, s.class_name, ");
|
||||
sqlBuilder.append("u.nick_name AS counselor_name ");
|
||||
sqlBuilder.append("FROM xljk_consultation_appointment a ");
|
||||
@@ -1334,8 +1446,6 @@ if (statusObj != null) {
|
||||
sqlBuilder.append("LEFT JOIN sys_user u ON a.counselor_id = u.user_id ");
|
||||
sqlBuilder.append("WHERE a.deleted = 0 ");
|
||||
|
||||
List<Object> params = new ArrayList<>();
|
||||
|
||||
// 添加查询条件
|
||||
if (bo.getStudentName() != null && !bo.getStudentName().isEmpty()) {
|
||||
sqlBuilder.append("AND s.name LIKE ? ");
|
||||
@@ -1457,10 +1567,6 @@ if (statusObj != null) {
|
||||
vo.setScheduleId(((Number) row.get("schedule_id")).longValue());
|
||||
}
|
||||
|
||||
if (row.get("actual_visit_time") != null) {
|
||||
vo.setActualVisitTime(convertToDate(row.get("actual_visit_time")));
|
||||
}
|
||||
|
||||
if (row.get("communication_duration") != null) {
|
||||
vo.setCommunicationDuration(((Number) row.get("communication_duration")).intValue());
|
||||
}
|
||||
@@ -1468,6 +1574,37 @@ if (statusObj != null) {
|
||||
vo.setConsultationContent((String) row.get("consultation_content"));
|
||||
vo.setCounselorSuggestion((String) row.get("counselor_suggestion"));
|
||||
|
||||
// 新增字段映射
|
||||
Object psychologicalHistoryObj = row.get("psychological_history");
|
||||
if (psychologicalHistoryObj != null) {
|
||||
if (psychologicalHistoryObj instanceof Number) {
|
||||
vo.setPsychologicalHistory(((Number) psychologicalHistoryObj).intValue());
|
||||
} else if (psychologicalHistoryObj instanceof String) {
|
||||
try {
|
||||
vo.setPsychologicalHistory(Integer.parseInt((String) psychologicalHistoryObj));
|
||||
} catch (NumberFormatException e) {
|
||||
vo.setPsychologicalHistory(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vo.setPsychologicalHistoryDetail((String) row.get("psychological_history_detail"));
|
||||
vo.setBasicSituation((String) row.get("basic_situation"));
|
||||
vo.setMajorLifeEvents((String) row.get("major_life_events"));
|
||||
|
||||
Object needReferralObj = row.get("need_referral");
|
||||
if (needReferralObj != null) {
|
||||
if (needReferralObj instanceof Number) {
|
||||
vo.setNeedReferral(((Number) needReferralObj).intValue());
|
||||
} else if (needReferralObj instanceof String) {
|
||||
try {
|
||||
vo.setNeedReferral(Integer.parseInt((String) needReferralObj));
|
||||
} catch (NumberFormatException e) {
|
||||
vo.setNeedReferral(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 其他通用字段
|
||||
if (row.get("create_by") != null) {
|
||||
vo.setCreateBy(((Number) row.get("create_by")).longValue());
|
||||
@@ -1485,6 +1622,13 @@ if (statusObj != null) {
|
||||
vo.setUpdateTime(convertToDate(row.get("update_time")));
|
||||
}
|
||||
|
||||
// 计算本学期到访次数
|
||||
if (vo.getStudentId() != null) {
|
||||
vo.setSemesterVisitCount(calculateSemesterVisitCount(vo.getStudentId()));
|
||||
} else {
|
||||
vo.setSemesterVisitCount(0);
|
||||
}
|
||||
|
||||
result.add(vo);
|
||||
}
|
||||
|
||||
@@ -1496,12 +1640,194 @@ if (statusObj != null) {
|
||||
return tableDataInfo;
|
||||
} catch (Exception e) {
|
||||
log.error("分页查询预约记录列表异常", e);
|
||||
log.error("SQL: {}", sqlBuilder.toString());
|
||||
log.error("参数: {}", params);
|
||||
TableDataInfo<XljkConsultationAppointmentVo> emptyResult = new TableDataInfo<>();
|
||||
emptyResult.setRows(new ArrayList<>());
|
||||
emptyResult.setTotal(0);
|
||||
emptyResult.setCode(200);
|
||||
emptyResult.setMsg("查询失败");
|
||||
emptyResult.setMsg("查询失败: " + e.getMessage());
|
||||
return emptyResult;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ScheduleWithStatusVo> getCalendarSchedules(String startDate, String endDate) {
|
||||
try {
|
||||
// 1. 查询指定日期范围内的所有排班数据
|
||||
LambdaQueryWrapper<XljkConsultationSchedule> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.ge(XljkConsultationSchedule::getScheduleDate, startDate)
|
||||
.le(XljkConsultationSchedule::getScheduleDate, endDate)
|
||||
.eq(XljkConsultationSchedule::getStatus, "0") // 0表示正常可用
|
||||
.orderByAsc(XljkConsultationSchedule::getScheduleDate)
|
||||
.orderByAsc(XljkConsultationSchedule::getTimeSlot)
|
||||
.orderByAsc(XljkConsultationSchedule::getStartTime);
|
||||
|
||||
List<XljkConsultationSchedule> schedules = scheduleMapper.selectList(queryWrapper);
|
||||
|
||||
if (schedules.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
// 2. 查询该日期范围内的所有预约记录
|
||||
List<Long> scheduleIds = schedules.stream().map(XljkConsultationSchedule::getId).collect(Collectors.toList());
|
||||
LambdaQueryWrapper<XljkConsultationAppointment> appointmentQueryWrapper = new LambdaQueryWrapper<>();
|
||||
appointmentQueryWrapper.in(XljkConsultationAppointment::getScheduleId, scheduleIds)
|
||||
.in(XljkConsultationAppointment::getStatus, Arrays.asList("0", "1", "4")); // 待咨询、已完成或待审核的
|
||||
|
||||
List<XljkConsultationAppointment> appointments = mapper.selectList(appointmentQueryWrapper);
|
||||
|
||||
// 3. 构建排班ID到预约记录的映射
|
||||
Map<Long, List<XljkConsultationAppointment>> appointmentMap = appointments.stream()
|
||||
.collect(Collectors.groupingBy(XljkConsultationAppointment::getScheduleId));
|
||||
|
||||
// 4. 获取咨询师信息映射
|
||||
Map<Long, String> counselorMap = getCounselorNameMap();
|
||||
|
||||
// 5. 获取当前时间
|
||||
Date now = new Date();
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
||||
SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm");
|
||||
|
||||
// 6. 构建结果列表
|
||||
List<ScheduleWithStatusVo> result = new ArrayList<>();
|
||||
|
||||
for (XljkConsultationSchedule schedule : schedules) {
|
||||
ScheduleWithStatusVo vo = new ScheduleWithStatusVo();
|
||||
|
||||
// 基本信息
|
||||
vo.setScheduleId(schedule.getId());
|
||||
vo.setCounselorId(schedule.getCounselorId());
|
||||
vo.setCounselorName(counselorMap.get(schedule.getCounselorId()));
|
||||
vo.setDate(dateFormat.format(schedule.getScheduleDate()));
|
||||
vo.setTimeSlot(schedule.getTimeSlot());
|
||||
vo.setStartTime(schedule.getStartTime());
|
||||
vo.setEndTime(schedule.getEndTime());
|
||||
|
||||
// 构建时段显示文本
|
||||
String timeSlotText = getTimeSlotText(schedule.getTimeSlot());
|
||||
vo.setTimeDisplay(timeSlotText + " " + schedule.getStartTime() + "-" + schedule.getEndTime());
|
||||
|
||||
// 计算预约状态
|
||||
List<XljkConsultationAppointment> scheduleAppointments = appointmentMap.get(schedule.getId());
|
||||
int bookedCount = scheduleAppointments != null ? scheduleAppointments.size() : 0;
|
||||
|
||||
// 每个时段只能预约1个人(无论时段长度)
|
||||
// 生成30分钟时段用于详细时段显示,但总预约数量固定为1
|
||||
List<TimeSlotDetailVo> timeSlots = TimeSlotUtils.generateTimeSlots(schedule.getStartTime(), schedule.getEndTime());
|
||||
int totalSlots = 1; // 每个时段只能预约1个人
|
||||
|
||||
vo.setTotalSlots(totalSlots);
|
||||
vo.setAvailableSlots(Math.max(0, totalSlots - bookedCount));
|
||||
vo.setIsFullyBooked(bookedCount >= totalSlots);
|
||||
|
||||
// 检查是否已过期
|
||||
boolean isExpired = false;
|
||||
try {
|
||||
Date scheduleDate = schedule.getScheduleDate();
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(scheduleDate);
|
||||
|
||||
// 设置具体的结束时间
|
||||
String[] endTimeParts = schedule.getEndTime().split(":");
|
||||
calendar.set(Calendar.HOUR_OF_DAY, Integer.parseInt(endTimeParts[0]));
|
||||
calendar.set(Calendar.MINUTE, Integer.parseInt(endTimeParts[1]));
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
|
||||
Date scheduleEndTime = calendar.getTime();
|
||||
isExpired = scheduleEndTime.before(now);
|
||||
} catch (Exception e) {
|
||||
log.warn("检查时段过期状态失败: " + schedule.getId(), e);
|
||||
}
|
||||
|
||||
vo.setIsExpired(isExpired);
|
||||
|
||||
// 设置基础字段
|
||||
vo.setCreateBy(schedule.getCreateBy());
|
||||
vo.setCreateTime(schedule.getCreateTime());
|
||||
vo.setUpdateBy(schedule.getUpdateBy());
|
||||
vo.setUpdateTime(schedule.getUpdateTime());
|
||||
|
||||
result.add(vo);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("获取日历排班数据失败", e);
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取时段类型文本
|
||||
*/
|
||||
private String getTimeSlotText(String timeSlot) {
|
||||
switch (timeSlot) {
|
||||
case "0": return "中午";
|
||||
case "1": return "下午";
|
||||
case "2": return "晚上";
|
||||
default: return "未知";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取咨询师名称映射
|
||||
*/
|
||||
private Map<Long, String> getCounselorNameMap() {
|
||||
try {
|
||||
Map<Long, String> counselorMap = new HashMap<>();
|
||||
|
||||
// 1. 查询所有已创建排班的咨询师ID
|
||||
LambdaQueryWrapper<XljkConsultationSchedule> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.select(XljkConsultationSchedule::getCounselorId)
|
||||
.eq(XljkConsultationSchedule::getStatus, "0") // 只查询正常状态的
|
||||
.groupBy(XljkConsultationSchedule::getCounselorId); // 去重
|
||||
|
||||
List<XljkConsultationSchedule> schedules = scheduleMapper.selectList(queryWrapper);
|
||||
if (schedules.isEmpty()) {
|
||||
return counselorMap;
|
||||
}
|
||||
|
||||
// 2. 提取咨询师ID列表
|
||||
List<Long> counselorIds = schedules.stream()
|
||||
.map(XljkConsultationSchedule::getCounselorId)
|
||||
.filter(Objects::nonNull)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (counselorIds.isEmpty()) {
|
||||
return counselorMap;
|
||||
}
|
||||
|
||||
// 3. 批量查询咨询师信息
|
||||
List<SysUserVo> counselors = userService.selectUserByIds(counselorIds, null);
|
||||
|
||||
// 4. 构建ID到姓名的映射
|
||||
counselorMap = counselors.stream()
|
||||
.filter(user -> user.getUserId() != null)
|
||||
.collect(Collectors.toMap(
|
||||
SysUserVo::getUserId,
|
||||
user -> {
|
||||
// 优先使用昵称,如果没有昵称则使用用户名
|
||||
String name = user.getNickName();
|
||||
if (StringUtils.isBlank(name)) {
|
||||
name = user.getUserName();
|
||||
}
|
||||
if (StringUtils.isBlank(name)) {
|
||||
name = "未知咨询师";
|
||||
}
|
||||
return name;
|
||||
},
|
||||
(existing, replacement) -> existing // 如果ID重复,保留第一个
|
||||
));
|
||||
|
||||
log.info("成功加载咨询师信息映射,共{}个咨询师", counselorMap.size());
|
||||
return counselorMap;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("获取咨询师信息失败", e);
|
||||
return new HashMap<>();
|
||||
}
|
||||
}
|
||||
}
|
||||
+94
-28
@@ -13,6 +13,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
@@ -26,6 +27,7 @@ import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class XljkConsultationScheduleServiceImpl implements IXljkConsultationScheduleService {
|
||||
@Autowired
|
||||
@@ -43,11 +45,16 @@ public class XljkConsultationScheduleServiceImpl implements IXljkConsultationSch
|
||||
// 查询咨询师姓名
|
||||
if (entity.getCounselorId() != null) {
|
||||
String sql = "SELECT nick_name FROM sys_user WHERE user_id = ?";
|
||||
List<Map<String, Object>> result = jdbcTemplate.queryForList(sql, entity.getCounselorId());
|
||||
if (!result.isEmpty()) {
|
||||
vo.setCounselorName((String) result.get(0).get("nick_name"));
|
||||
try {
|
||||
String counselorName = jdbcTemplate.queryForObject(sql, String.class, entity.getCounselorId());
|
||||
vo.setCounselorName(counselorName);
|
||||
} catch (Exception e) {
|
||||
log.error("查询咨询师姓名失败,counselorId: {}", entity.getCounselorId(), e);
|
||||
}
|
||||
}
|
||||
|
||||
// office字段直接从排班记录中获取
|
||||
vo.setOffice(entity.getOffice());
|
||||
return vo;
|
||||
}
|
||||
|
||||
@@ -65,11 +72,15 @@ public class XljkConsultationScheduleServiceImpl implements IXljkConsultationSch
|
||||
// 查询咨询师姓名
|
||||
if (entity.getCounselorId() != null) {
|
||||
String sql = "SELECT nick_name FROM sys_user WHERE user_id = ?";
|
||||
List<Map<String, Object>> result = jdbcTemplate.queryForList(sql, entity.getCounselorId());
|
||||
if (!result.isEmpty()) {
|
||||
vo.setCounselorName((String) result.get(0).get("nick_name"));
|
||||
try {
|
||||
String counselorName = jdbcTemplate.queryForObject(sql, String.class, entity.getCounselorId());
|
||||
vo.setCounselorName(counselorName);
|
||||
} catch (Exception e) {
|
||||
log.error("查询咨询师姓名失败,counselorId: {}", entity.getCounselorId(), e);
|
||||
}
|
||||
}
|
||||
// office字段直接从排班记录中获取
|
||||
vo.setOffice(entity.getOffice());
|
||||
return vo;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
@@ -87,6 +98,11 @@ public class XljkConsultationScheduleServiceImpl implements IXljkConsultationSch
|
||||
queryWrapper.eq(XljkConsultationSchedule::getCounselorId, bo.getCounselorId());
|
||||
}
|
||||
|
||||
// 添加办公室筛选条件
|
||||
if (bo.getOffice() != null && !bo.getOffice().isEmpty()) {
|
||||
queryWrapper.like(XljkConsultationSchedule::getOffice, bo.getOffice());
|
||||
}
|
||||
|
||||
// 按创建时间倒序查询所有记录
|
||||
queryWrapper.orderByDesc(XljkConsultationSchedule::getCreateTime);
|
||||
|
||||
@@ -144,12 +160,17 @@ public class XljkConsultationScheduleServiceImpl implements IXljkConsultationSch
|
||||
// 查询咨询师姓名
|
||||
if (batchGroup.getCounselorId() != null) {
|
||||
String sql = "SELECT nick_name FROM sys_user WHERE user_id = ?";
|
||||
List<Map<String, Object>> result = jdbcTemplate.queryForList(sql, batchGroup.getCounselorId());
|
||||
if (!result.isEmpty()) {
|
||||
summary.setCounselorName((String) result.get(0).get("nick_name"));
|
||||
try {
|
||||
String counselorName = jdbcTemplate.queryForObject(sql, String.class, batchGroup.getCounselorId());
|
||||
summary.setCounselorName(counselorName);
|
||||
} catch (Exception e) {
|
||||
log.error("查询咨询师姓名失败,counselorId: {}", batchGroup.getCounselorId(), e);
|
||||
}
|
||||
}
|
||||
|
||||
// office字段直接从排班记录中获取
|
||||
summary.setOffice(batchGroup.getOffice());
|
||||
|
||||
// 确保创建时间不为空
|
||||
if (summary.getCreateTime() == null) {
|
||||
summary.setCreateTime(new Date());
|
||||
@@ -226,12 +247,17 @@ public class XljkConsultationScheduleServiceImpl implements IXljkConsultationSch
|
||||
// 查询咨询师姓名
|
||||
if (firstSchedule.getCounselorId() != null) {
|
||||
String sql = "SELECT nick_name FROM sys_user WHERE user_id = ?";
|
||||
List<Map<String, Object>> result = jdbcTemplate.queryForList(sql, firstSchedule.getCounselorId());
|
||||
if (!result.isEmpty()) {
|
||||
summary.setCounselorName((String) result.get(0).get("nick_name"));
|
||||
try {
|
||||
String counselorName = jdbcTemplate.queryForObject(sql, String.class, firstSchedule.getCounselorId());
|
||||
summary.setCounselorName(counselorName);
|
||||
} catch (Exception e) {
|
||||
log.error("查询咨询师姓名失败,counselorId: {}", firstSchedule.getCounselorId(), e);
|
||||
}
|
||||
}
|
||||
|
||||
// office字段直接从排班记录中获取
|
||||
summary.setOffice(firstSchedule.getOffice());
|
||||
|
||||
summaryList.add(summary);
|
||||
}
|
||||
}
|
||||
@@ -283,9 +309,12 @@ public class XljkConsultationScheduleServiceImpl implements IXljkConsultationSch
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 检查是否至少启用了一个时段
|
||||
if ((batchBo.getMorningEnabled() == null || !batchBo.getMorningEnabled()) &&
|
||||
(batchBo.getAfternoonEnabled() == null || !batchBo.getAfternoonEnabled())) {
|
||||
// 检查是否至少启用了一个时段(兼容新旧版本)
|
||||
boolean hasMorning = (batchBo.getMorningEnabled() != null && batchBo.getMorningEnabled());
|
||||
boolean hasNoon = (batchBo.getNoonEnabled() != null && batchBo.getNoonEnabled());
|
||||
boolean hasAfternoon = (batchBo.getAfternoonEnabled() != null && batchBo.getAfternoonEnabled());
|
||||
|
||||
if (!hasMorning && !hasNoon && !hasAfternoon) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -321,12 +350,13 @@ public class XljkConsultationScheduleServiceImpl implements IXljkConsultationSch
|
||||
|
||||
// 如果是周末且设置了跳过周末,则跳过
|
||||
if (!(isWeekend && Boolean.TRUE.equals(batchBo.getSkipWeekends()))) {
|
||||
// 创建上午时段
|
||||
// 创建中午时段(字段名保持morning以兼容前端)
|
||||
if (Boolean.TRUE.equals(batchBo.getMorningEnabled())) {
|
||||
XljkConsultationSchedule morningSchedule = new XljkConsultationSchedule();
|
||||
morningSchedule.setCounselorId(batchBo.getCounselorId());
|
||||
morningSchedule.setOffice(batchBo.getOffice());
|
||||
morningSchedule.setScheduleDate(currentDate);
|
||||
morningSchedule.setTimeSlot("0"); // 上午
|
||||
morningSchedule.setTimeSlot("0"); // 中午
|
||||
morningSchedule.setStartTime(batchBo.getMorningStartTime());
|
||||
morningSchedule.setEndTime(batchBo.getMorningEndTime());
|
||||
morningSchedule.setStatus(batchBo.getStatus());
|
||||
@@ -335,18 +365,54 @@ public class XljkConsultationScheduleServiceImpl implements IXljkConsultationSch
|
||||
schedules.add(morningSchedule);
|
||||
}
|
||||
|
||||
// 创建下午时段
|
||||
// 创建中午时段(新版本)
|
||||
if (Boolean.TRUE.equals(batchBo.getNoonEnabled()) && batchBo.getNoonTimeSlots() != null) {
|
||||
for (XljkConsultationScheduleBatchBo.TimeSlot timeSlot : batchBo.getNoonTimeSlots()) {
|
||||
XljkConsultationSchedule noonSchedule = new XljkConsultationSchedule();
|
||||
noonSchedule.setCounselorId(batchBo.getCounselorId());
|
||||
noonSchedule.setOffice(batchBo.getOffice());
|
||||
noonSchedule.setScheduleDate(currentDate);
|
||||
noonSchedule.setTimeSlot("0"); // 中午时段
|
||||
noonSchedule.setStartTime(timeSlot.getStartTime());
|
||||
noonSchedule.setEndTime(timeSlot.getEndTime());
|
||||
noonSchedule.setStatus(batchBo.getStatus());
|
||||
noonSchedule.setBatchId(batchId); // 设置批次ID
|
||||
noonSchedule.setCreateTime(now); // 设置创建时间
|
||||
schedules.add(noonSchedule);
|
||||
}
|
||||
}
|
||||
|
||||
// 创建下午时段(兼容新旧版本)
|
||||
if (Boolean.TRUE.equals(batchBo.getAfternoonEnabled())) {
|
||||
XljkConsultationSchedule afternoonSchedule = new XljkConsultationSchedule();
|
||||
afternoonSchedule.setCounselorId(batchBo.getCounselorId());
|
||||
afternoonSchedule.setScheduleDate(currentDate);
|
||||
afternoonSchedule.setTimeSlot("1"); // 下午
|
||||
afternoonSchedule.setStartTime(batchBo.getAfternoonStartTime());
|
||||
afternoonSchedule.setEndTime(batchBo.getAfternoonEndTime());
|
||||
afternoonSchedule.setStatus(batchBo.getStatus());
|
||||
afternoonSchedule.setBatchId(batchId); // 设置批次ID
|
||||
afternoonSchedule.setCreateTime(now); // 设置创建时间
|
||||
schedules.add(afternoonSchedule);
|
||||
if (batchBo.getAfternoonTimeSlots() != null && !batchBo.getAfternoonTimeSlots().isEmpty()) {
|
||||
// 新版本:支持多时段
|
||||
for (XljkConsultationScheduleBatchBo.TimeSlot timeSlot : batchBo.getAfternoonTimeSlots()) {
|
||||
XljkConsultationSchedule afternoonSchedule = new XljkConsultationSchedule();
|
||||
afternoonSchedule.setCounselorId(batchBo.getCounselorId());
|
||||
afternoonSchedule.setOffice(batchBo.getOffice());
|
||||
afternoonSchedule.setScheduleDate(currentDate);
|
||||
afternoonSchedule.setTimeSlot("1"); // 下午
|
||||
afternoonSchedule.setStartTime(timeSlot.getStartTime());
|
||||
afternoonSchedule.setEndTime(timeSlot.getEndTime());
|
||||
afternoonSchedule.setStatus(batchBo.getStatus());
|
||||
afternoonSchedule.setBatchId(batchId); // 设置批次ID
|
||||
afternoonSchedule.setCreateTime(now); // 设置创建时间
|
||||
schedules.add(afternoonSchedule);
|
||||
}
|
||||
} else if (batchBo.getAfternoonStartTime() != null && batchBo.getAfternoonEndTime() != null) {
|
||||
// 旧版本:单时段
|
||||
XljkConsultationSchedule afternoonSchedule = new XljkConsultationSchedule();
|
||||
afternoonSchedule.setCounselorId(batchBo.getCounselorId());
|
||||
afternoonSchedule.setOffice(batchBo.getOffice());
|
||||
afternoonSchedule.setScheduleDate(currentDate);
|
||||
afternoonSchedule.setTimeSlot("1"); // 下午
|
||||
afternoonSchedule.setStartTime(batchBo.getAfternoonStartTime());
|
||||
afternoonSchedule.setEndTime(batchBo.getAfternoonEndTime());
|
||||
afternoonSchedule.setStatus(batchBo.getStatus());
|
||||
afternoonSchedule.setBatchId(batchId); // 设置批次ID
|
||||
afternoonSchedule.setCreateTime(now); // 设置创建时间
|
||||
schedules.add(afternoonSchedule);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+329
@@ -0,0 +1,329 @@
|
||||
package org.dromara.xljk.service.impl;
|
||||
|
||||
import org.dromara.common.core.utils.MapstructUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
||||
import org.dromara.common.mybatis.core.page.PageQuery;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.dromara.xljk.domain.bo.XljkConsulterBo;
|
||||
import org.dromara.xljk.domain.vo.XljkConsulterVo;
|
||||
import org.dromara.xljk.domain.XljkConsulter;
|
||||
import org.dromara.xljk.domain.XljkUserWithDeptInfo;
|
||||
import org.dromara.xljk.mapper.XljkConsulterMapper;
|
||||
import org.dromara.xljk.service.IXljkConsulterService;
|
||||
import org.dromara.system.service.ISysUserService;
|
||||
import org.dromara.system.service.ISysRoleService;
|
||||
import org.dromara.system.domain.vo.SysUserVo;
|
||||
import org.dromara.system.domain.vo.SysRoleVo;
|
||||
import org.dromara.system.domain.SysRole;
|
||||
import org.dromara.system.domain.SysUserRole;
|
||||
import org.dromara.system.domain.bo.SysRoleBo;
|
||||
import org.dromara.system.mapper.SysUserRoleMapper;
|
||||
import org.dromara.common.satoken.utils.LoginHelper;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Collection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 心理咨询师配置Service业务层处理
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2024-01-01
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class XljkConsulterServiceImpl implements IXljkConsulterService {
|
||||
|
||||
private final XljkConsulterMapper baseMapper;
|
||||
private final ISysUserService sysUserService;
|
||||
private final ISysRoleService sysRoleService;
|
||||
private final SysUserRoleMapper sysUserRoleMapper;
|
||||
|
||||
/**
|
||||
* 查询心理咨询师配置
|
||||
*/
|
||||
@Override
|
||||
public XljkConsulterVo queryById(Long id) {
|
||||
XljkConsulter entity = baseMapper.selectById(id);
|
||||
if (entity == null) {
|
||||
return null;
|
||||
}
|
||||
return MapstructUtils.convert(entity, XljkConsulterVo.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询心理咨询师配置列表
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<XljkConsulterVo> queryPageList(XljkConsulterBo bo, PageQuery pageQuery) {
|
||||
// 直接使用查询条件构建器
|
||||
LambdaQueryWrapper<XljkConsulter> lqw = buildQueryWrapper(bo);
|
||||
Page<XljkConsulter> entityPage = baseMapper.selectPage(pageQuery.build(), lqw);
|
||||
|
||||
// 转换为 VO 对象
|
||||
List<XljkConsulterVo> voList = new ArrayList<>();
|
||||
for (XljkConsulter entity : entityPage.getRecords()) {
|
||||
XljkConsulterVo vo = MapstructUtils.convert(entity, XljkConsulterVo.class);
|
||||
voList.add(vo);
|
||||
}
|
||||
|
||||
// 构建分页结果
|
||||
Page<XljkConsulterVo> voPage = new Page<>(entityPage.getCurrent(), entityPage.getSize(), entityPage.getTotal());
|
||||
voPage.setRecords(voList);
|
||||
|
||||
return TableDataInfo.build(voPage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询心理咨询师配置列表
|
||||
*/
|
||||
@Override
|
||||
public List<XljkConsulterVo> queryList(XljkConsulterBo bo) {
|
||||
LambdaQueryWrapper<XljkConsulter> lqw = buildQueryWrapper(bo);
|
||||
List<XljkConsulter> entityList = baseMapper.selectList(lqw);
|
||||
|
||||
// 转换为 VO 对象
|
||||
List<XljkConsulterVo> voList = new ArrayList<>();
|
||||
for (XljkConsulter entity : entityList) {
|
||||
XljkConsulterVo vo = MapstructUtils.convert(entity, XljkConsulterVo.class);
|
||||
voList.add(vo);
|
||||
}
|
||||
|
||||
return voList;
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<XljkConsulter> buildQueryWrapper(XljkConsulterBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
LambdaQueryWrapper<XljkConsulter> lqw = Wrappers.<XljkConsulter>lambdaQuery();
|
||||
lqw.eq(bo.getUserId() != null, XljkConsulter::getUserId, bo.getUserId());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getUserName()), XljkConsulter::getUserName, bo.getUserName());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getNickName()), XljkConsulter::getNickName, bo.getNickName());
|
||||
lqw.eq(bo.getDeptId() != null, XljkConsulter::getDeptId, bo.getDeptId());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getStatus()), XljkConsulter::getStatus, bo.getStatus());
|
||||
lqw.eq(bo.getConfigBy() != null, XljkConsulter::getConfigBy, bo.getConfigBy());
|
||||
lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
|
||||
XljkConsulter::getCreateTime, params.get("beginCreateTime"), params.get("endCreateTime"));
|
||||
lqw.orderByDesc(XljkConsulter::getCreateTime);
|
||||
return lqw;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增心理咨询师配置
|
||||
*/
|
||||
@Override
|
||||
public Boolean insertByBo(XljkConsulterBo bo) {
|
||||
XljkConsulter add = MapstructUtils.convert(bo, XljkConsulter.class);
|
||||
validEntityBeforeSave(add);
|
||||
|
||||
// 设置配置人信息
|
||||
Long currentUserId = LoginHelper.getUserId();
|
||||
add.setConfigBy(currentUserId);
|
||||
|
||||
// 获取当前用户信息设置配置人姓名
|
||||
try {
|
||||
SysUserVo currentUser = sysUserService.selectUserById(currentUserId);
|
||||
if (currentUser != null) {
|
||||
add.setConfigByName(currentUser.getUserName());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 如果获取失败,使用默认值
|
||||
add.setConfigByName("系统管理员");
|
||||
}
|
||||
|
||||
boolean flag = baseMapper.insert(add) > 0;
|
||||
if (flag) {
|
||||
bo.setId(add.getId());
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改心理咨询师配置
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateByBo(XljkConsulterBo bo) {
|
||||
XljkConsulter update = MapstructUtils.convert(bo, XljkConsulter.class);
|
||||
validEntityBeforeSave(update);
|
||||
return baseMapper.updateById(update) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存前的数据校验
|
||||
*/
|
||||
private void validEntityBeforeSave(XljkConsulter entity) {
|
||||
if (entity.getUserId() != null) {
|
||||
// 检查用户是否已存在(新增时或修改用户ID时)
|
||||
if (entity.getId() == null) {
|
||||
// 新增时检查
|
||||
int count = baseMapper.checkUserExists(entity.getUserId());
|
||||
if (count > 0) {
|
||||
throw new ServiceException("该用户已配置为咨询师,不能重复添加");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除心理咨询师配置
|
||||
*/
|
||||
@Override
|
||||
public Boolean deleteWithValidByIds(Collection<Long> ids) {
|
||||
return baseMapper.deleteBatchIds(ids) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量添加咨询师
|
||||
*/
|
||||
@Override
|
||||
public Boolean batchAddConsulters(List<Long> userIds, String remark) {
|
||||
if (userIds == null || userIds.isEmpty()) {
|
||||
throw new ServiceException("用户ID列表不能为空");
|
||||
}
|
||||
|
||||
Long currentUserId = LoginHelper.getUserId();
|
||||
String currentUserName = "系统管理员";
|
||||
|
||||
// 获取当前用户信息
|
||||
try {
|
||||
SysUserVo currentUser = sysUserService.selectUserById(currentUserId);
|
||||
if (currentUser != null) {
|
||||
currentUserName = currentUser.getUserName();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 使用默认值
|
||||
}
|
||||
|
||||
// 1. 获取完整的用户信息(包含部门信息)
|
||||
List<XljkUserWithDeptInfo> users = baseMapper.selectUsersWithDeptInfo(userIds);
|
||||
if (users.isEmpty()) {
|
||||
throw new ServiceException("没有找到有效的用户信息");
|
||||
}
|
||||
|
||||
// 2. 过滤已存在的咨询师
|
||||
List<Long> existingUserIds = baseMapper.selectList(Wrappers.<XljkConsulter>lambdaQuery()
|
||||
.in(XljkConsulter::getUserId, userIds))
|
||||
.stream().map(XljkConsulter::getUserId).collect(Collectors.toList());
|
||||
|
||||
// 3. 构建新增咨询师列表
|
||||
List<XljkConsulter> consulterList = new ArrayList<>();
|
||||
for (XljkUserWithDeptInfo user : users) {
|
||||
if (!existingUserIds.contains(user.getUserId())) {
|
||||
XljkConsulter consulter = new XljkConsulter();
|
||||
consulter.setUserId(user.getUserId());
|
||||
consulter.setUserName(user.getUserName());
|
||||
consulter.setNickName(user.getNickName());
|
||||
consulter.setDeptId(user.getDeptId());
|
||||
consulter.setDeptName(user.getDeptName() != null ? user.getDeptName() : "");
|
||||
consulter.setPhoneNumber(user.getPhonenumber());
|
||||
consulter.setEmail(user.getEmail());
|
||||
consulter.setStatus("1"); // 默认正常状态
|
||||
consulter.setRemark(remark);
|
||||
consulter.setConfigBy(currentUserId);
|
||||
consulter.setConfigByName(currentUserName);
|
||||
consulterList.add(consulter);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 批量保存
|
||||
if (consulterList.isEmpty()) {
|
||||
throw new ServiceException("所有用户都已存在,无需重复添加");
|
||||
}
|
||||
|
||||
boolean result = baseMapper.insertBatch(consulterList);
|
||||
|
||||
// 5. 为新添加的咨询师自动分配 xljk_consultant 角色
|
||||
if (result) {
|
||||
assignConsultantRole(consulterList);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 为咨询师分配 xljk_consultant 角色
|
||||
*/
|
||||
private void assignConsultantRole(List<XljkConsulter> consulterList) {
|
||||
try {
|
||||
// 1. 根据角色键查询角色信息
|
||||
SysRoleBo roleBo = new SysRoleBo();
|
||||
roleBo.setRoleKey("xljk_consultant");
|
||||
List<SysRoleVo> roleList = sysRoleService.selectRoleList(roleBo);
|
||||
|
||||
if (roleList == null || roleList.isEmpty()) {
|
||||
throw new ServiceException("未找到角色键为 'xljk_consultant' 的角色,请联系管理员创建该角色");
|
||||
}
|
||||
|
||||
Long roleId = roleList.get(0).getRoleId();
|
||||
|
||||
// 2. 为每个用户分配角色
|
||||
List<SysUserRole> userRoleList = new ArrayList<>();
|
||||
for (XljkConsulter consulter : consulterList) {
|
||||
// 检查用户是否已有该角色
|
||||
Long count = sysUserRoleMapper.selectCount(
|
||||
Wrappers.<SysUserRole>lambdaQuery()
|
||||
.eq(SysUserRole::getUserId, consulter.getUserId())
|
||||
.eq(SysUserRole::getRoleId, roleId)
|
||||
);
|
||||
|
||||
// 如果用户还没有该角色,则添加
|
||||
if (count == 0) {
|
||||
SysUserRole userRole = new SysUserRole();
|
||||
userRole.setUserId(consulter.getUserId());
|
||||
userRole.setRoleId(roleId);
|
||||
userRoleList.add(userRole);
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 批量插入用户角色关联
|
||||
if (!userRoleList.isEmpty()) {
|
||||
sysUserRoleMapper.insertBatch(userRoleList);
|
||||
System.out.println("成功为 " + userRoleList.size() + " 个用户分配了 'xljk_consultant' 角色");
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
// 记录错误但不影响主流程
|
||||
System.err.println("为咨询师分配角色失败: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询我配置的咨询师列表
|
||||
*/
|
||||
@Override
|
||||
public TableDataInfo<XljkConsulterVo> queryMyConfigList(XljkConsulterBo bo, PageQuery pageQuery) {
|
||||
bo.setConfigBy(LoginHelper.getUserId());
|
||||
return queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量启用咨询师
|
||||
*/
|
||||
@Override
|
||||
public Boolean enableConsulters(List<Long> ids) {
|
||||
if (ids == null || ids.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return baseMapper.enableConsultersByIds(ids) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量停用咨询师
|
||||
*/
|
||||
@Override
|
||||
public Boolean disableConsulters(List<Long> ids) {
|
||||
if (ids == null || ids.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return baseMapper.disableConsultersByIds(ids) > 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
<?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="org.dromara.xljk.mapper.XljkConsulterMapper">
|
||||
|
||||
<resultMap type="org.dromara.xljk.domain.vo.XljkConsulterVo" id="XljkConsulterVoResult">
|
||||
<result property="id" column="id"/>
|
||||
<result property="userId" column="user_id"/>
|
||||
<result property="userName" column="user_name"/>
|
||||
<result property="nickName" column="nick_name"/>
|
||||
<result property="deptId" column="dept_id"/>
|
||||
<result property="deptName" column="dept_name"/>
|
||||
<result property="phoneNumber" column="phone_number"/>
|
||||
<result property="office" column="office"/>
|
||||
<result property="email" column="email"/>
|
||||
<result property="status" column="status"/>
|
||||
<result property="remark" column="remark"/>
|
||||
<result property="configBy" column="config_by"/>
|
||||
<result property="configByName" column="config_by_name"/>
|
||||
<result property="tenantId" column="tenant_id"/>
|
||||
<result property="createDept" column="create_dept"/>
|
||||
<result property="createBy" column="create_by"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
<result property="updateBy" column="update_by"/>
|
||||
<result property="updateTime" column="update_time"/>
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectXljkConsulterVo">
|
||||
select id, user_id, user_name, nick_name, dept_id, dept_name, phone_number, office, email, status, remark, config_by, config_by_name, tenant_id, create_dept, create_by, create_time, update_by, update_time from xljk_consulter
|
||||
</sql>
|
||||
|
||||
<select id="selectXljkConsulterVoById" parameterType="Long" resultMap="XljkConsulterVoResult">
|
||||
<include refid="selectXljkConsulterVo"/>
|
||||
where id = #{id}
|
||||
</select>
|
||||
|
||||
<select id="selectXljkConsulterVoList" parameterType="org.dromara.xljk.domain.XljkConsulter" resultMap="XljkConsulterVoResult">
|
||||
<include refid="selectXljkConsulterVo"/>
|
||||
<where>
|
||||
<if test="userId != null">and user_id = #{userId}</if>
|
||||
<if test="userName != null and userName != ''">and user_name like concat('%', #{userName}, '%')</if>
|
||||
<if test="nickName != null and nickName != ''">and nick_name like concat('%', #{nickName}, '%')</if>
|
||||
<if test="deptId != null">and dept_id = #{deptId}</if>
|
||||
<if test="status != null and status != ''">and status = #{status}</if>
|
||||
<if test="configBy != null">and config_by = #{configBy}</if>
|
||||
<if test="params.beginCreateTime != null and params.beginCreateTime != '' and params.endCreateTime != null and params.endCreateTime != ''">
|
||||
and create_time between #{params.beginCreateTime} and #{params.endCreateTime}
|
||||
</if>
|
||||
</where>
|
||||
order by create_time desc
|
||||
</select>
|
||||
|
||||
<!-- 检查用户是否已存在 -->
|
||||
<select id="checkUserExists" resultType="int">
|
||||
SELECT COUNT(1) FROM xljk_consulter WHERE user_id = #{userId} AND deleted = 0
|
||||
</select>
|
||||
|
||||
<!-- 批量启用咨询师 -->
|
||||
<update id="enableConsultersByIds">
|
||||
UPDATE xljk_consulter SET status = '1' WHERE id IN
|
||||
<foreach collection="ids" item="id" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
AND deleted = 0
|
||||
</update>
|
||||
|
||||
<!-- 批量停用咨询师 -->
|
||||
<update id="disableConsultersByIds">
|
||||
UPDATE xljk_consulter SET status = '0' WHERE id IN
|
||||
<foreach collection="ids" item="id" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
AND deleted = 0
|
||||
</update>
|
||||
|
||||
<!-- 查询完整的用户信息(包含部门信息)用于批量添加 -->
|
||||
<select id="selectUsersWithDeptInfo" resultType="org.dromara.xljk.domain.XljkUserWithDeptInfo">
|
||||
SELECT
|
||||
u.user_id as userId,
|
||||
u.user_name as userName,
|
||||
u.nick_name as nickName,
|
||||
u.dept_id as deptId,
|
||||
d.dept_name as deptName,
|
||||
u.phonenumber as phonenumber,
|
||||
u.email as email,
|
||||
u.status as status
|
||||
FROM sys_user u
|
||||
LEFT JOIN sys_dept d ON u.dept_id = d.dept_id
|
||||
WHERE u.user_id IN
|
||||
<foreach collection="userIds" item="userId" open="(" separator="," close=")">
|
||||
#{userId}
|
||||
</foreach>
|
||||
AND u.del_flag = '0'
|
||||
AND u.status = '0'
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
Reference in new issue
Block a user