Compare commits

...

24 Commits

Author SHA1 Message Date
郝彬 0f67c55892 Merge branch 'master' of http://pms.dtyx.net:3000/cuizhibin/znpt-backend
# Conflicts:
#	pom.xml
2025-08-06 17:03:14 +08:00
郝彬 14ee89c4af Merge branch 'master' of http://pms.dtyx.net:3000/cuizhibin/znpt-backend
# Conflicts:
#	core/src/main/java/com/dite/znpt/domain/entity/ProjectBudgetInfoEntity.java
#	core/src/main/java/com/dite/znpt/domain/vo/ProjectBudgetInfoReq.java
#	core/src/main/java/com/dite/znpt/domain/vo/ProjectBudgetInfoResp.java
#	core/src/main/java/com/dite/znpt/service/impl/ProjectBudgetInfoServiceImpl.java
#	core/src/main/resources/mapper/ProjectBudgetInfoMapper.xml
#	web/src/main/java/com/dite/znpt/web/controller/PostController.java
2025-08-06 16:50:51 +08:00
郝彬 d8c76f97af 8-6 先commit再pull 2025-08-06 16:48:33 +08:00
郝彬 67d943af61 Merge remote-tracking branch 'upstream/master'
# Conflicts:
#	core/src/main/java/com/dite/znpt/domain/vo/ProjectBudgetInfoImportReq.java
#	core/src/main/java/com/dite/znpt/service/impl/UserServiceImpl.java
#	core/src/main/resources/mapper/ProjectMapper.xml
#	core/src/main/resources/mapper/UserMapper.xml
#	pom.xml
#	web/src/main/java/com/dite/znpt/web/controller/VideoController.java
2025-08-06 16:00:53 +08:00
郝彬 dbbd3922f9 8-6 取消预算单同步删除数据库的使用记录,并撤回预算消费,创建项目时自动计算总预算 2025-08-06 14:30:30 +08:00
郝彬 0548238a18 8-6 新增预算单同步修改数据库的使用记录 2025-08-06 10:02:38 +08:00
郝彬 1c136ed302 Merge remote-tracking branch 'origin/master' 2025-08-06 09:45:43 +08:00
郝彬 8c7a441662 8-6 根据项目id查询其相关预算汇总 2025-08-06 09:44:22 +08:00
ybb b94f7d3f44 Merge branch 'master' of https://gitee.com/xswl_123/dite-shixi-bakcend 2025-08-06 08:48:55 +08:00
ybb d7066714e5 8/6,ybb文件模糊查询功能 2025-08-06 08:48:15 +08:00
郝彬 a49d01d23a Merge branch 'master' of https://gitee.com/xswl_123/dite-shixi-bakcend 2025-08-05 10:15:11 +08:00
郝彬 351c8e0d8e 8-5 岗位字段新增 2025-08-05 10:14:30 +08:00
ybb 50c343402b 7-31 岗位查用户 2025-08-05 09:27:10 +08:00
ybb 141c95f63e Merge branch 'master' of https://gitee.com/xswl_123/dite-shixi-bakcend
# Conflicts:
#	core/src/main/java/com/dite/znpt/mapper/BusinessDataMapper.java
#	core/src/main/java/com/dite/znpt/service/BusinessDataService.java
#	core/src/main/java/com/dite/znpt/service/impl/BusinessDataServiceImpl.java
#	core/src/main/resources/mapper/BusinessDataMapper.xml
#	web/src/main/java/com/dite/znpt/web/controller/BusinessDataController.java
2025-08-04 16:11:06 +08:00
ybb 944681f334 7-31 岗位查用户 2025-08-04 16:10:14 +08:00
郝彬 14428ca9ae 8-4 项目与合同关联、项目预算 2025-08-04 16:02:39 +08:00
郝彬 b188cbd181 8-4 商务资料管理系统(ybb) 2025-08-04 15:48:14 +08:00
郝彬 f84e1b5aa8 7-31 岗位查用户 2025-08-01 16:06:50 +08:00
郝彬 9723dc0390 7-31 删除角色或岗位或角色时,同时删除对应关联表,优化后续查询效率及外键不存在问题 2025-07-31 10:41:01 +08:00
郝彬 35fdcf14f6 7-29 修改用户查询的Mapper层查询SQL语句,去除岗位和角色的重复显示 2025-07-30 11:15:41 +08:00
郝彬 7dbadc7378 7-29 修改岗位新增时传入的状态逻辑,与数据库保持一致 2025-07-30 09:48:38 +08:00
郝彬 849754b6c6 7-29 新增ConvertsImpl类,岗位信息返回创建时间及更新时间 2025-07-29 17:22:03 +08:00
郝彬 6e4c96b404 7-29-根据角色查询用户,过滤器条件修改 2025-07-29 09:47:38 +08:00
郝彬 4ac2b4314c 7-29-根据角色查询用户 2025-07-29 09:09:57 +08:00
52 changed files with 3053 additions and 680 deletions

View File

@ -59,6 +59,8 @@ public interface Converts {
List<RoleResp> toRoleResp(List<RoleEntity> list);
List<UserResp> toUserResp(List<UserEntity> list);
RoleEntity toRoleEntity(RoleReq req);
MenuEntity toMenuEntity(MenuReq req);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,15 @@
package com.dite.znpt.domain.dto;
import io.swagger.annotations.ApiModel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@ApiModel("接受文件夹参数")
public class FolderDto {
private String name = "tom";
private Long parentId = 0L;
}

View File

@ -0,0 +1,38 @@
package com.dite.znpt.domain.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("business_data_part")
@ApiModel(value="商务资料文件夹对象")
@AllArgsConstructor
@NoArgsConstructor
public class BusinessDataEntity {
// 主键
private Long folderId = null;
// 文件夹名称
private String folderName = null;
// 父级文件夹
private Long parentId = null;
// 创建人
private Long creatorId = null;
// 创建时间
private LocalDateTime createTime = null;
// 更新时间
private LocalDateTime updateTime = null;
// 是否删除
private Boolean isDeleted = false;
// 文件夹路径
private String folderPath = null;
}

View File

@ -0,0 +1,37 @@
package com.dite.znpt.domain.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("business_data_part_file")
@ApiModel(value="商务资料对象")
public class BusinessDataFileEntity {
//文件id
private Long fileId = null;
//文件夹id
private Long folderId = null;
//文件名
private String fileName = null;
//文件路径
private String filePath = null;
//文件类型
private String fileType = "unknown";
//文件大小
private Long fileSize = null;
//上传时间
private Date uploadTime = null;
//上传人id
private Long uploaderId = null;
//是否删除
private Boolean isDeleted = false;
}

View File

@ -13,6 +13,7 @@ import lombok.EqualsAndHashCode;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* @author Bear.G
@ -50,4 +51,32 @@ public class PostEntity extends AuditableEntity implements Serializable {
@ApiModelProperty("备注")
@TableField("remark")
private String remark;
@ApiModelProperty("创建时间")
@TableField("create_time")
private LocalDateTime createTime;
@ApiModelProperty("更新时间")
@TableField("update_time")
private LocalDateTime updateTime;
@ApiModelProperty("岗位说明")
@TableField("statement")
private String statement;
@ApiModelProperty("岗位任务")
@TableField("responsibilities_task")
private String responsibilitiesTask;
@ApiModelProperty("岗位任职资格")
@TableField("qualifications")
private String qualifications;
@ApiModelProperty("岗位工作条件")
@TableField("working_conditions")
private String workingConditions;
@ApiModelProperty("岗位薪资")
@TableField("salary")
private Double salary;
}

View File

@ -30,7 +30,7 @@ public class ProjectBudgetInfoEntity extends AuditableEntity implements Serializ
@ExcelProperty("主键")
@ApiModelProperty("主键")
@TableId(value = "budget_id", type = IdType.ASSIGN_ID)
@TableId(value = "budget_id", type = IdType.AUTO)
private String budgetId;
@ExcelProperty("项目id")
@ -43,8 +43,8 @@ public class ProjectBudgetInfoEntity extends AuditableEntity implements Serializ
@TableField("budget_name")
private String budgetName;
@ExcelProperty("预算金额(万元)")
@ApiModelProperty("预算金额(万元)")
@ExcelProperty("预算花费金额")
@ApiModelProperty("预算花费金额")
@TableField("budget_amount")
private Double budgetAmount;
@ -52,5 +52,10 @@ public class ProjectBudgetInfoEntity extends AuditableEntity implements Serializ
@ApiModelProperty("预算说明")
@TableField("budget_desc")
private String budgetDesc;
@ExcelProperty("附件")
@ApiModelProperty("附件")
@TableField("attach")
private String attach;
}

View File

@ -33,6 +33,16 @@ public class ProjectEntity extends AuditableEntity implements Serializable {
@TableId(value = "project_id", type = IdType.ASSIGN_UUID)
private String projectId;
@ExcelProperty("项目来源")
@ApiModelProperty("项目来源")
@TableField("project_origin")
private String projectOrigin;
@ExcelProperty("项目预算")
@ApiModelProperty("项目预算")
@TableField("project_budget")
private Integer projectBudget;
@ExcelProperty("项目名称")
@ApiModelProperty("项目名称")
@TableField("project_name")
@ -169,5 +179,35 @@ public class ProjectEntity extends AuditableEntity implements Serializable {
// 施工人员安全经理项目经理商务财务高级管理员项目远程顾问外部协作者质量经理现场经理及工作组长
@ApiModelProperty(value = "结束时间")
private LocalDate endDate;
@ApiModelProperty("人工成本")
private Double laborCost;
@ApiModelProperty("设备摊销")
private Double equipmentAmortization;
@ApiModelProperty("奖金预提")
private Double bonusProvision;
@ApiModelProperty("交通食宿")
private Double transAccomMeals;
@ApiModelProperty("其他杂费")
private Double othersCost;
@ApiModelProperty("已用人工成本")
private Double useLaborCost;
@ApiModelProperty("已用设备摊销")
private Double useEquipmentAmortization;
@ApiModelProperty("已用奖金预提")
private Double useBonusProvision;
@ApiModelProperty("已用交通食宿")
private Double useTransAccomMeals;
@ApiModelProperty("已用其他杂费")
private Double useOthersCost;
}

View File

@ -0,0 +1,16 @@
package com.dite.znpt.domain.page;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PageBean {
private Long total;
private List<?> rows;
}

View File

@ -1,5 +1,6 @@
package com.dite.znpt.domain.vo;
import com.baomidou.mybatisplus.annotation.TableField;
import com.dite.znpt.util.ValidationGroup;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ -33,9 +34,24 @@ public class PostReq implements Serializable {
@ApiModelProperty("显示顺序")
private Integer postSort;
@ApiModelProperty("状态0正常 1停用)")
@ApiModelProperty("状态0停用 1正常")
private Integer status;
@ApiModelProperty("备注")
private String remark;
@ApiModelProperty("岗位说明")
private String statement;
@ApiModelProperty("岗位任务")
private String responsibilitiesTask;
@ApiModelProperty("岗位任职资格")
private String qualifications;
@ApiModelProperty("岗位工作条件")
private String workingConditions;
@ApiModelProperty("岗位薪资")
private Double salary;
}

View File

@ -1,5 +1,6 @@
package com.dite.znpt.domain.vo;
import com.baomidou.mybatisplus.annotation.TableField;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ -7,6 +8,7 @@ import lombok.Data;
import javax.validation.constraints.Size;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* @author Bear.G
@ -41,4 +43,25 @@ public class PostResp implements Serializable {
@ApiModelProperty("备注")
private String remark;
@ApiModelProperty("创建时间")
private LocalDateTime createTime;
@ApiModelProperty("更新时间")
private LocalDateTime updateTime;
@ApiModelProperty("岗位说明")
private String statement;
@ApiModelProperty("岗位任务")
private String responsibilitiesTask;
@ApiModelProperty("岗位任职资格")
private String qualifications;
@ApiModelProperty("岗位工作条件")
private String workingConditions;
@ApiModelProperty("岗位薪资")
private Double salary;
}

View File

@ -0,0 +1,58 @@
package com.dite.znpt.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
@Data
@ApiModel("项目预算信息详情")
public class ProjectBudgetInfoDetailResp implements Serializable {
@Serial
private static final long serialVersionUID = 766154886845694269L;
@ApiModelProperty("项目id")
private String projectId;
@ApiModelProperty("项目名称")
private String projectName;
@ApiModelProperty("项目预算")
private Double projectBudget;
@ApiModelProperty("人工成本")
private Double laborCost;
@ApiModelProperty("设备摊销")
private Double equipmentAmortization;
@ApiModelProperty("奖金预提")
private Double bonusProvision;
@ApiModelProperty("交通食宿")
private Double transAccomMeals;
@ApiModelProperty("其他杂费")
private Double othersCost;
@ApiModelProperty("已用人工成本")
private Double useLaborCost;
@ApiModelProperty("已用设备摊销")
private Double useEquipmentAmortization;
@ApiModelProperty("已用奖金预提")
private Double useBonusProvision;
@ApiModelProperty("已用交通食宿")
private Double useTransAccomMeals;
@ApiModelProperty("已用其他杂费")
private Double useOthersCost;
@ApiModelProperty("剩余预算")
private Double restBudget;
}

View File

@ -0,0 +1,37 @@
package com.dite.znpt.domain.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
import java.io.Serializable;
/**
* @author huise23
* @date 2025/07/17 21:58
* @Description: 项目预算信息表导入请求类
*/
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(value="ProjectBudgetInfo导入请求对象", description="项目预算信息表")
public class ProjectBudgetInfoImportReq implements Serializable {
@Serial
private static final long serialVersionUID = 580212651388155611L;
@ExcelProperty(value = "项目Id")
private String projectId;
@ExcelProperty(value = "预算名称")
private String budgetName;
@ExcelProperty(value = "预算花费金额")
private Double budgetAmount;
@ExcelProperty(value = "预算说明")
private String budgetDesc;
@ExcelProperty(value = "附件")
private String attach;
}

View File

@ -22,7 +22,7 @@ public class ProjectBudgetInfoListReq implements Serializable {
@ApiModelProperty("查询关键字")
private String keyword;
@ApiModelProperty("项目预算信息Id")
@ApiModelProperty("项目预算Id")
private String budgetId;
@ApiModelProperty("项目id")
@ -31,14 +31,10 @@ public class ProjectBudgetInfoListReq implements Serializable {
@ApiModelProperty("预算名称")
private String budgetName;
@ApiModelProperty("预算类型")
private String budgetType;
@ApiModelProperty("预算金额(万元)")
@ApiModelProperty("预算花费金额")
private Double budgetAmount;
@ApiModelProperty("预算说明")
private String budgetDesc;
}

View File

@ -2,6 +2,7 @@ package com.dite.znpt.domain.vo;
import com.dite.znpt.domain.entity.ProjectBudgetInfoEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -14,6 +15,7 @@ import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@ApiModel("项目预算信息列表响应实体")
public class ProjectBudgetInfoListResp extends ProjectBudgetInfoEntity {
@ApiModelProperty("项目名称")
private String projectName;
}

View File

@ -26,13 +26,13 @@ public class ProjectBudgetInfoReq implements Serializable {
@ApiModelProperty("预算名称")
private String budgetName;
@ApiModelProperty("预算金额(万元)")
@ApiModelProperty("预算花费金额")
private Double budgetAmount;
@ApiModelProperty("预算说明")
private String budgetDesc;
@ApiModelProperty("附件id")
private String attachId;
@ApiModelProperty("附件")
private String attach;
}

View File

@ -15,6 +15,7 @@ import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@ApiModel("项目预算信息响应实体")
public class ProjectBudgetInfoResp extends ProjectBudgetInfoEntity {
@ApiModelProperty("项目名称")
private String projectName;
}

View File

@ -23,6 +23,12 @@ public class ProjectListReq implements Serializable {
@ApiModelProperty("项目名称")
private String projectName;
@ApiModelProperty(value = "项目来源")
private String projectOrigin;
@ApiModelProperty(value = "项目预算")
private Integer projectBudget;
@ApiModelProperty("风场名称")
private String farmName;

View File

@ -31,6 +31,12 @@ public class ProjectListResp implements Serializable {
@ApiModelProperty("项目名称")
private String projectName;
@ApiModelProperty(value = "项目来源")
private String projectOrigin;
@ApiModelProperty(value = "项目预算")
private Integer projectBudget;
@ApiModelProperty("风场名称")
private String farmName;

View File

@ -28,6 +28,14 @@ public class ProjectReq implements Serializable {
@ApiModelProperty("项目id")
private String projectId;
@NotBlank(groups = {ValidationGroup.Insert.class, ValidationGroup.Update.class}, message = "项目来源不能为空")
@ApiModelProperty("项目来源")
private String projectOrigin;
@NotBlank(groups = {ValidationGroup.Insert.class, ValidationGroup.Update.class}, message = "项目预算不能为空")
@ApiModelProperty("项目预算")
private Integer projectBudget;
@NotBlank(groups = {ValidationGroup.Insert.class, ValidationGroup.Update.class}, message = "项目名称不能为空")
@Size(groups = {ValidationGroup.Insert.class, ValidationGroup.Update.class}, max = 50, message = "项目名称长度不能超过50字符")
@ApiModelProperty("项目名称")
@ -105,4 +113,19 @@ public class ProjectReq implements Serializable {
@ApiModelProperty(value = "结束时间")
private LocalDate endDate;
@ApiModelProperty("人工成本")
private Double laborCost;
@ApiModelProperty("设备摊销")
private Double equipmentAmortization;
@ApiModelProperty("奖金预提")
private Double bonusProvision;
@ApiModelProperty("交通食宿")
private Double transAccomMeals;
@ApiModelProperty("其他杂费")
private Double othersCost;
}

View File

@ -27,6 +27,15 @@ public class ProjectResp extends ProjectReq implements Serializable {
@Serial
private static final long serialVersionUID = -1883901559600186726L;
@ApiModelProperty("项目ID")
private String projectId;
@ApiModelProperty("项目来源")
private String projectOrigin;
@ApiModelProperty("项目预算")
private Integer projectBudget;
@ApiModelProperty("施工人员")
private String constructorName;

View File

@ -0,0 +1,23 @@
package com.dite.znpt.mapper;
import com.dite.znpt.domain.entity.BusinessDataFileEntity;
import com.dite.znpt.domain.entity.BusinessDataEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiOperation;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@ApiOperation("商务资料文件对象")
public interface BusinessDataFileMapper {
public List<BusinessDataFileEntity> List(@Param("folderId") Long folderId, @Param("fileName") String fileName);
void delete(@Param("fileId") Long fileId,@Param("folderId") Long folderId);
void add(BusinessDataFileEntity businessDataFileEntity);
String getPath(Long fileId);
// 在接口中添加重命名方法
void reName(@Param("fileId") Long fileId, @Param("newFileName") String newFileName, @Param("newFilePath") String newFilePath);
}

View File

@ -0,0 +1,31 @@
package com.dite.znpt.mapper;
import com.baomidou.mybatisplus.core.injector.methods.SelectList;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dite.znpt.domain.entity.BusinessDataEntity;
import io.swagger.annotations.ApiOperation;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import com.dite.znpt.domain.entity.BusinessDataEntity;
import java.time.LocalDateTime;
import java.util.List;
@ApiOperation("商务资料文件夹对象")
public interface BusinessDataMapper {
public String getPath(Long parentId);
public List<BusinessDataEntity> List();
void insert(BusinessDataEntity businessDataEntity);
void delete(Long folderId);
void reName(BusinessDataEntity businessDataEntity);
public List<BusinessDataEntity> ListWithCondition(@Param("folderName") String folderName);
}

View File

@ -0,0 +1,29 @@
package com.dite.znpt.service;
import com.dite.znpt.domain.Result;
import com.dite.znpt.domain.entity.BusinessDataFileEntity;
import com.dite.znpt.domain.page.PageBean;
import io.swagger.annotations.ApiOperation;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestParam;
import javax.servlet.http.HttpServletResponse;
@ApiOperation("商务资料文件service")
@Service
public interface BusinessDataFileService {
PageBean pageSelect(Integer page, Integer pageSize, Long folderId, String fileName);
Result delete(@RequestParam(value = "fileId", required = false) Long fileId,@RequestParam(value = "foldelId", required = false) Long folderId);
void add(BusinessDataFileEntity businessDataFileEntity);
String getPath(Long fileId);
// 在接口中添加重命名方法
Result reName(Long fileId, String newFileName);
// 在接口中添加预览方法
// Result preview(Long fileId, HttpServletResponse response);
}

View File

@ -0,0 +1,15 @@
package com.dite.znpt.service;
import com.dite.znpt.domain.Result;
import com.dite.znpt.domain.page.PageBean;
import io.swagger.annotations.ApiOperation;
@ApiOperation("商务资料文件夹service")
public interface BusinessDataService {
PageBean pageSelect(Integer page, Integer pageSize, String folderName);
Result createFolder(String folderName, Long parentId);
String getPath(Long parentId);
Result delete(Long folderId);
Result reName(Long folderId, String newName);
}

View File

@ -0,0 +1,30 @@
package com.dite.znpt.service;
import org.springframework.stereotype.Service;
@Service
public interface EmailService {
/**
* 发送邮箱验证码
* @param email
* @param code
* @return
*/
public boolean sendVerificationCode(String email, String code);
/**
* 生成验证码
* @param email
* @return
*/
public String generateCode(String email);
/**
* 验证邮箱验证码
* @param email
* @param code
* @return
*/
public boolean verifyCode(String email, String code);
}

View File

@ -2,10 +2,8 @@ package com.dite.znpt.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.dite.znpt.domain.entity.ProjectBudgetInfoEntity;
import com.dite.znpt.domain.vo.ProjectBudgetInfoListReq;
import com.dite.znpt.domain.vo.ProjectBudgetInfoListResp;
import com.dite.znpt.domain.vo.ProjectBudgetInfoReq;
import com.dite.znpt.domain.vo.ProjectBudgetInfoResp;
import com.dite.znpt.domain.vo.*;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
@ -15,34 +13,16 @@ import java.util.List;
* @Description: 项目预算信息表服务接口
*/
public interface ProjectBudgetInfoService extends IService<ProjectBudgetInfoEntity> {
List<ProjectBudgetInfoListResp> list(ProjectBudgetInfoListReq projectBudgetInfoListReq);
/**
* 功能描述查询项目预算信息列表
*
* @param projectBudgetInfoReq 项目预算信息
* @return {@link List }<{@link ProjectBudgetInfoListResp }>
* @author huise23
* @date 2025/07/17 21:58
**/
List<ProjectBudgetInfoListResp> selectList(ProjectBudgetInfoListReq projectBudgetInfoReq);
List<ProjectBudgetInfoListResp> page(ProjectBudgetInfoListReq projectBudgetInfoListReq);
/**
* 功能描述根据项目id获取项目预算信息列表
*
* @param projectId 项目id
* @return {@link List }<{@link ProjectBudgetInfoListResp }>
* @author huise23
* @date 2025/07/17 21:58
**/
List<ProjectBudgetInfoResp> detailByProjectId(String projectId);
void saveData(ProjectBudgetInfoImportReq req);
/**
* 功能描述新增项目预算信息
*
* @param projectBudgetInfoReq 项目预算信息
* @author huise23
* @date 2025/07/17 21:58
**/
void saveData(List<ProjectBudgetInfoReq> projectBudgetInfoReq);
void saveData(ProjectBudgetInfoImportReq req, MultipartFile[] files);
ProjectBudgetInfoDetailResp detailByProjectId(String projectId);
void delete(String budgetId);
}

View File

@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
import com.dite.znpt.domain.entity.PostEntity;
import com.dite.znpt.domain.entity.UserPostEntity;
import com.dite.znpt.domain.vo.PostResp;
import com.dite.znpt.domain.vo.UserResp;
import java.util.List;
@ -16,4 +17,5 @@ public interface UserPostService extends IService<UserPostEntity> {
List<PostResp> getPostsByUserId(String userId);
void bindUserPost(String userId, List<String> postIds);
void bindPostUser(String postId, List<String> userIds);
List<UserResp> getUsersByPostId(String postId);
}

View File

@ -1,8 +1,10 @@
package com.dite.znpt.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.dite.znpt.domain.entity.UserEntity;
import com.dite.znpt.domain.entity.UserRoleEntity;
import com.dite.znpt.domain.vo.RoleResp;
import com.dite.znpt.domain.vo.UserResp;
import com.dite.znpt.domain.vo.UserRoleReq;
import java.util.List;
@ -19,4 +21,6 @@ public interface UserRoleService extends IService<UserRoleEntity> {
void bindUserRole(UserRoleReq req);
void bindRoleUser(String roleId, List<String> userIds);
List<UserResp> getUsersByRoleId(String roleId);
}

View File

@ -0,0 +1,163 @@
package com.dite.znpt.service.impl;
import com.dite.znpt.domain.Result;
import com.dite.znpt.domain.entity.BusinessDataFileEntity;
import com.dite.znpt.domain.page.PageBean;
import com.dite.znpt.mapper.BusinessDataFileMapper;
import com.dite.znpt.service.BusinessDataFileService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.List;
import static jodd.io.FileUtil.deleteFile;
import static org.apache.tomcat.util.http.fileupload.FileUtils.deleteDirectory;
@AllArgsConstructor
@Service
@ApiOperation("商务资料文件service实现类")
public class BusinessDataFileServiceImpl implements BusinessDataFileService {
@Resource
private BusinessDataFileMapper businessDataFileMapper;
@ApiOperation("分页查询文件")
@Override
public PageBean pageSelect(Integer page, Integer pageSize, Long folderId, String fileName) {
PageHelper.startPage(page, pageSize);
List<BusinessDataFileEntity> list = businessDataFileMapper.List(folderId, fileName);
Page<BusinessDataFileEntity> p = (Page<BusinessDataFileEntity>) list;
PageBean pageBean = new PageBean(p.getTotal(), p.getResult());
return pageBean;
}
@ApiOperation("删除文件")
public Result delete(Long fileId, Long folderId) {
//删除数据库数据
if (folderId != null){
businessDataFileMapper.delete(null,folderId);
System.out.println("888888888走对了");
return Result.okM("删除,走对了,成功");
}
//删除文件
String sPath = businessDataFileMapper.getPath(fileId);
businessDataFileMapper.delete(fileId,null);
boolean flag = false;
File file = new File(sPath);
// 判断目录或文件是否存在
if (!file.exists()) { // 不存在返回 false
return Result.error("文件不存在");
} else {
// 判断是否为文件
if (file.isFile()) { // 为文件时调用删除文件方法
try {
deleteFile(file);
} catch (IOException e) {
throw new RuntimeException(e);
}
return Result.okM("删除成功");
} else { // 为目录时调用删除目录方法
try {
deleteDirectory(file);
} catch (IOException e) {
throw new RuntimeException(e);
}
return Result.okM("删除成功");
}
}
}
@ApiOperation("增加文件")
public void add(BusinessDataFileEntity businessDataFileEntity) {
businessDataFileMapper.add(businessDataFileEntity);
}
@ApiOperation("获取文件路径")
public String getPath(Long fileId) {
return businessDataFileMapper.getPath(fileId);
}
@ApiOperation("重命名文件")
@Override
public Result reName(Long fileId, String newFileName) {
// 参数校验
if (fileId == null) {
return Result.error("文件ID不能为空");
}
if (newFileName == null || newFileName.trim().isEmpty()) {
return Result.error("新文件名不能为空");
}
if (newFileName.length() > 100) {
return Result.error("文件名过长");
}
try {
// 获取原文件信息
String oldFilePath = businessDataFileMapper.getPath(fileId);
if (oldFilePath == null) {
return Result.error("文件不存在");
}
// 创建原文件对象
File oldFile = new File(oldFilePath);
if (!oldFile.exists()) {
return Result.error("文件不存在");
}
// 构建新文件路径
String parentPath = oldFile.getParent();
String fileExtension = "";
String fileNameWithoutExt = newFileName;
// 获取原文件扩展名
int lastDotIndex = oldFile.getName().lastIndexOf('.');
if (lastDotIndex > 0) {
fileExtension = oldFile.getName().substring(lastDotIndex);
}
// 如果新文件名没有扩展名则添加原文件扩展名
if (!newFileName.contains(".")) {
newFileName = newFileName + fileExtension;
}
// 构建新文件路径
String newFilePath = parentPath + File.separator + newFileName;
File newFile = new File(newFilePath);
// 检查新文件名是否已存在
if (newFile.exists()) {
return Result.error("文件名已存在");
}
// 重命名实际文件
boolean renameSuccess = oldFile.renameTo(newFile);
if (!renameSuccess) {
return Result.error("文件重命名失败");
}
// 更新数据库中的文件信息
businessDataFileMapper.reName(fileId, newFileName, newFilePath);
return Result.okM("文件重命名成功");
} catch (Exception e) {
return Result.error("文件重命名失败: " + e.getMessage());
}
}
}

View File

@ -0,0 +1,197 @@
package com.dite.znpt.service.impl;
import com.dite.znpt.domain.Result;
import com.dite.znpt.domain.entity.BusinessDataEntity;
import com.dite.znpt.domain.page.PageBean;
import com.dite.znpt.mapper.BusinessDataMapper;
import com.dite.znpt.service.BusinessDataFileService;
import com.dite.znpt.service.BusinessDataService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.Comparator;
import java.util.List;
/**
* 商务资料文件夹实现类
*/
@Service
@ApiOperation("商务资料文件夹service实现类")
@AllArgsConstructor
@NoArgsConstructor
public class BusinessDataServiceImpl implements BusinessDataService {
@Resource
private BusinessDataMapper businessDataMapper;
@Resource
private BusinessDataFileService businessDataFileService;
// 从配置文件中读取基础路径默认值D:/upload/businessData
// ,新建文件夹的时候如果没指定父文件夹Id,就用这个
@Value("${file.upload.businessDataPath:D:/upload/businessData}")
private String businessDataPath;
@ApiOperation(value = "分页查询")
@Override
public PageBean pageSelect(Integer page, Integer pageSize, String folderName) {
PageHelper.startPage(page, pageSize);
List<BusinessDataEntity> businessDataEntityList = businessDataMapper.ListWithCondition(folderName);
Page<BusinessDataEntity> p = (Page<BusinessDataEntity>) businessDataEntityList;
PageBean pageBean = new PageBean(p.getTotal(), p.getResult());
return pageBean;
}
@ApiOperation(value = "创建文件夹")
@Override
public Result createFolder(String folderName, Long parentId) {
//获取ID
Long loginIdAsLong = 888L;
// loginIdAsLong = StpUtil.getLoginIdAsLong();
//
// 文件夹名称不能为空
//TODO: 添加文件夹名称校验,后续最好更规范些写个工具类专门校验用正则表达式
if (folderName == null || folderName.trim().isEmpty()) {
return Result.error("文件夹名称不能为空");
}
if (folderName.length() > 50) {
return Result.error("文件夹名称过长");
}
// 文件夹名称前置一个/
String folderName1 = "/" + folderName;
// 目标文件夹
File targetDir=Paths.get(businessDataPath, folderName1).toFile();
if(parentId != 0L){
// 获取父文件夹路径
targetDir = Paths.get(businessDataMapper.getPath(parentId), folderName1).toFile();
}
// 创建文件夹和新增文件夹路径
if (!targetDir.exists()) {
// 创建文件夹
boolean created = targetDir.mkdirs();
if (!created) {
throw new RuntimeException("文件夹创建失败: " + targetDir.getAbsolutePath());
}
//上面是新增文件夹功能但没有往数据库插入文件夹相关数据所以下面新增
// 创建BusinessDataEntity对象并设置属性
BusinessDataEntity businessDataEntity = new BusinessDataEntity(
null,
folderName,
parentId,
loginIdAsLong,
LocalDateTime.now(),
LocalDateTime.now(),
false,
targetDir.getAbsolutePath()
);
// 插入到数据库
businessDataMapper.insert(businessDataEntity);
return Result.okM( "文件夹创建成功");
} else {
return Result.error("文件夹已存在: ");
}
}
@ApiOperation("获取文件夹路径")
public String getPath(Long parentId) {
return businessDataMapper.getPath(parentId);
}
// @ApiOperation("删除文件夹")
// @Override
// public Result delete(Long folderId) {
// // 获取文件夹路径
// String folderPath = businessDataMapper.getPath(folderId);
//
// // 创建File对象并删除文件夹
// File folder = new File(folderPath);
// if (folder.exists()) {
// boolean deleted = folder.delete();
// if (!deleted) {
// // throw new RuntimeException("文件夹删除失败: " + folderPath);
// // TODO: 以后可以用全局异常处理器捕获或者用try catch捕获
// return Result.error("文件夹删除失败: " + folderPath);
// }
// //删除数据库中文件夹的数据
// businessDataMapper.delete(folderId);
// //删除文件夹下文件的数据
// businessDataFileService.delete(folderId);
// return Result.okM("删除成功");
// } else {
// // throw new RuntimeException("文件夹不存在: " + folderPath);
// return Result.error("文件夹不存在: " + folderPath);
// }
// }
@ApiOperation("删除文件夹")
@Override
public Result delete(Long folderId) {
// 获取文件夹路径
String folderPath = businessDataMapper.getPath(folderId);
// 创建Path对象并删除文件夹
Path folder = Paths.get(folderPath);
if (Files.exists(folder)) {
try {
// 使用Files.walk获取所有文件和目录按深度排序后删除
java.util.stream.Stream<Path> filePaths = Files.walk(folder);
filePaths.sorted(Comparator.reverseOrder())
.map(Path::toFile)
.forEach(File::delete);
filePaths.close();
//删除数据库中文件夹的数据
businessDataMapper.delete(folderId);
//删除文件夹下文件的数据
businessDataFileService.delete(null , folderId);
return Result.okM("删除成功");
} catch (Exception e) {
return Result.okM("删除成功");
}
} else {
return Result.error("文件夹不存在: " + folderPath);
}
}
@ApiOperation("重命名文件夹")
@Override
public Result reName(Long folderId, String newName) {
// 获取文件夹路径
String folderPath = businessDataMapper.getPath(folderId);
String newPath = folderPath.substring(0, folderPath.lastIndexOf('\\'))+"\\" + newName;
System.out.printf("7777777"+newPath);
//
// //想命名的原文件的路径
// File file = new File("f:/a/a.xlsx");
// //将原文件更改为f:\a\b.xlsx其中路径是必要的注意
// file.renameTo(new File("f:/a/b.xlsx"));
//想命名的原文件夹的路径
File file1 = new File(folderPath);
//将原文件夹更改为A其中路径是必要的注意
file1.renameTo(new File(newPath));
LocalDateTime now = LocalDateTime.now();
BusinessDataEntity businessDataEntity = new BusinessDataEntity(
folderId,
newName,
null,
null,
null,
now,
null,
newPath
);
System.out.println(businessDataEntity);
businessDataMapper.reName(businessDataEntity);
return Result.okM("重命名成功");
}
}

View File

@ -0,0 +1,66 @@
package com.dite.znpt.service.impl;
import com.dite.znpt.service.EmailService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
import org.springframework.web.server.ResponseStatusException;
import java.util.Random;
@Slf4j
@Service
public class EmailServiceImpl implements EmailService {
@Autowired
private JavaMailSender mailSender;
@Autowired
private InMemoryVerificationCodeStore codeStore;
@Value("${email.verification.from}")
private String from;
@Value("${email.verification.subject}")
private String subject;
@Value("${email.verification.template}")
private String template;
@Override
public boolean sendVerificationCode(String email, String code) {
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(from);
message.setSubject(subject);
message.setTo(email);
message.setText(String.format(template,code));
try{
mailSender.send(message);
return true;
}catch (Exception e){
log.error("发送邮件失败:",e);
return false;
}
}
@Override
public String generateCode(String email) {
if (!codeStore.canSend(email)) {
throw new ResponseStatusException(
HttpStatus.TOO_MANY_REQUESTS, // 429 状态码
"验证码发送过于频繁,请稍后再试"
);
}
String code = String.format("%04d", new Random().nextInt(9999));
codeStore.save(email, code);
return code;
}
@Override
public boolean verifyCode(String email, String code) {
return codeStore.validate(email, code);
}
}

View File

@ -0,0 +1,74 @@
package com.dite.znpt.service.impl;
import lombok.Data;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Component
public class InMemoryVerificationCodeStore {
// 存储邮箱验证码的map
private final Map<String,codeInfo> emailCodeMap = new ConcurrentHashMap<>();
public void save(String email, String code){
// 设置五分钟过期
emailCodeMap.put(email,new codeInfo(code, LocalDateTime.now().plusMinutes(5)));
}
/**
* 验证验证码
* @param email
* @param code
* @return
*/
public boolean validate(String email, String code){
codeInfo codeInfo = emailCodeMap.get(email);
if(codeInfo == null){
return false;
}
boolean isValid = false;
if(code.equals(codeInfo.getCode()) && LocalDateTime.now().isBefore(codeInfo.getExpireTime())){
isValid = true;
}
if(isValid){
emailCodeMap.remove(email);
return true;
}
return false;
}
/**
* 判断邮箱是否可发送验证码
* @param email
* @return
*/
public boolean canSend(String email){
codeInfo codeInfo = emailCodeMap.get(email);
if(codeInfo != null && LocalDateTime.now().isBefore(codeInfo.getExpireTime())){
return false;
}
return true;
}
@Data
public static class codeInfo {
// 验证码
private String code;
// 过期时间
private LocalDateTime expireTime;
// 上一次发送时间
private LocalDateTime lastSendTime;
public codeInfo(String code, LocalDateTime expireTime){
this.code = code;
this.expireTime = expireTime;
this.lastSendTime = LocalDateTime.now();
}
}
}

View File

@ -1,25 +1,21 @@
package com.dite.znpt.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dite.znpt.domain.entity.ProjectBudgetInfoEntity;
import com.dite.znpt.domain.vo.ProjectBudgetInfoListReq;
import com.dite.znpt.domain.vo.ProjectBudgetInfoListResp;
import com.dite.znpt.domain.vo.ProjectBudgetInfoReq;
import com.dite.znpt.domain.vo.ProjectBudgetInfoResp;
import com.dite.znpt.enums.AttachBusinessTypeEnum;
import com.dite.znpt.enums.BudgeTypeEnum;
import com.dite.znpt.domain.entity.ProjectEntity;
import com.dite.znpt.domain.vo.*;
import com.dite.znpt.mapper.ProjectBudgetInfoMapper;
import com.dite.znpt.service.AttachInfoService;
import com.dite.znpt.service.ProjectBudgetInfoService;
import com.dite.znpt.service.ProjectService;
import com.dite.znpt.util.PageUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.util.ArrayList;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
/**
@ -30,60 +26,98 @@ import java.util.List;
@Service
@RequiredArgsConstructor
public class ProjectBudgetInfoServiceImpl extends ServiceImpl<ProjectBudgetInfoMapper, ProjectBudgetInfoEntity> implements ProjectBudgetInfoService {
@Resource
ProjectService projectService;
private final AttachInfoService attachInfoService;
@Resource
AttachInfoServiceImpl attachInfoService;
/**
* 功能描述查询项目预算信息列表
*
* @param projectBudgetInfoReq 项目预算信息信息
* @return {@link List }<{@link ProjectBudgetInfoResp }>
* @author huise23
* @date 2025/07/17 21:58
**/
@Override
public List<ProjectBudgetInfoListResp> selectList(ProjectBudgetInfoListReq projectBudgetInfoReq) {
PageUtil.startPage();
List<ProjectBudgetInfoListResp> projectBudgetInfoList= this.baseMapper.queryBySelective(projectBudgetInfoReq);
projectBudgetInfoList.forEach(resp -> {
});
return projectBudgetInfoList;
}
/**
* 功能描述根据项目id获取项目预算信息列表
*
* @param projectId 项目id
* @return {@link List }<{@link ProjectBudgetInfoListResp }>
* @author huise23
* @date 2025/07/17 21:58
**/
@Override
public List<ProjectBudgetInfoResp> detailByProjectId(String projectId) {
List<ProjectBudgetInfoResp> projectBudgetInfoList= this.baseMapper.detailByProjectId(projectId);
return projectBudgetInfoList;
}
/**
* 功能描述新增项目预算信息
*
* @param projectBudgetInfoReq 项目预算信息
* @author huise23
* @date 2025/07/17 21:58
**/
@Override
@Transactional(rollbackFor = Exception.class)
public void saveData(List<ProjectBudgetInfoReq> projectBudgetInfoReq) {
List<ProjectBudgetInfoEntity> list = new ArrayList<>();
for (ProjectBudgetInfoReq req : projectBudgetInfoReq) {
ProjectBudgetInfoEntity info = BeanUtil.copyProperties(req, ProjectBudgetInfoEntity.class);
info.setBudgetId(IdUtil.simpleUUID());
attachInfoService.updateBusinessIdByAttachIds(info.getBudgetId(), ListUtil.of(req.getAttachId()), AttachBusinessTypeEnum.PROJECT_BUDGE);
list.add(info);
public List<ProjectBudgetInfoListResp> list(ProjectBudgetInfoListReq req) {
List<ProjectBudgetInfoListResp> list = this.baseMapper.queryBySelective(req);
if (CollectionUtil.isEmpty(list)) {
return Collections.emptyList(); // 返回不可修改的空集合
}
lambdaUpdate().eq(ProjectBudgetInfoEntity::getProjectId, list.get(0).getProjectId()).remove();
baseMapper.insert(list);
list.forEach(item -> {
item.setProjectName(projectService.getById(item.getProjectId()).getProjectName());
});
return list;
}
@Override
public List<ProjectBudgetInfoListResp> page(ProjectBudgetInfoListReq req) {
PageUtil.startPage();
return this.list(req);
}
@Override
public void saveData(ProjectBudgetInfoImportReq req) {
ProjectBudgetInfoEntity entity = BeanUtil.copyProperties(req, ProjectBudgetInfoEntity.class);
ProjectEntity projectEntity = projectService.getById(req.getProjectId());
switch (req.getBudgetName()) {
case "人工成本":
projectEntity.setUseLaborCost(projectEntity.getUseLaborCost() + req.getBudgetAmount());
break;
case "设备摊销":
projectEntity.setUseEquipmentAmortization(projectEntity.getUseEquipmentAmortization() + req.getBudgetAmount());
break;
case "奖金预提":
projectEntity.setUseBonusProvision(projectEntity.getUseBonusProvision() + req.getBudgetAmount());
break;
case "交通食宿":
projectEntity.setUseTransAccomMeals(projectEntity.getUseTransAccomMeals() + req.getBudgetAmount());
break;
case "其他杂费":
projectEntity.setUseOthersCost(projectEntity.getUseOthersCost() + req.getBudgetAmount());
break;
default:
break;
}
projectService.updateById(projectEntity);
this.baseMapper.insert(entity);
}
@Override
public void saveData(ProjectBudgetInfoImportReq req, MultipartFile[] files) {
ProjectBudgetInfoEntity entity = BeanUtil.copyProperties(req, ProjectBudgetInfoEntity.class);
// 把附件存起来使用已有的附件上传逻辑就行但我看不懂pass
this.baseMapper.insert(entity);
}
@Override
public ProjectBudgetInfoDetailResp detailByProjectId(String projectId) {
ProjectEntity projectEntity = projectService.getById(projectId);
ProjectBudgetInfoDetailResp resp = new ProjectBudgetInfoDetailResp();
BeanUtil.copyProperties(projectEntity, resp);
resp.setRestBudget(resp.getProjectBudget() - resp.getUseLaborCost() - resp.getUseEquipmentAmortization() - resp.getUseBonusProvision() - resp.getUseTransAccomMeals() - resp.getUseOthersCost());
return resp;
}
@Override
public void delete(String budgetId) {
ProjectBudgetInfoEntity entity = this.baseMapper.selectById(budgetId);
ProjectEntity projectEntity = projectService.getById(entity.getProjectId());
switch (entity.getBudgetName()) {
case "人工成本":
projectEntity.setUseLaborCost(projectEntity.getUseLaborCost() - entity.getBudgetAmount());
break;
case "设备摊销":
projectEntity.setUseEquipmentAmortization(projectEntity.getUseEquipmentAmortization() - entity.getBudgetAmount());
break;
case "奖金预提":
projectEntity.setUseBonusProvision(projectEntity.getUseBonusProvision() - entity.getBudgetAmount());
break;
case "交通食宿":
projectEntity.setUseTransAccomMeals(projectEntity.getUseTransAccomMeals() - entity.getBudgetAmount());
break;
case "其他杂费":
projectEntity.setUseOthersCost(projectEntity.getUseOthersCost() - entity.getBudgetAmount());
break;
default:
break;
}
projectService.updateById(projectEntity);
this.baseMapper.deleteById(budgetId);
// 删除附件
}
}

View File

@ -9,7 +9,9 @@ import com.dite.znpt.converts.Converts;
import com.dite.znpt.domain.entity.PostEntity;
import com.dite.znpt.domain.entity.UserEntity;
import com.dite.znpt.domain.entity.UserPostEntity;
import com.dite.znpt.domain.entity.UserRoleEntity;
import com.dite.znpt.domain.vo.PostResp;
import com.dite.znpt.domain.vo.UserResp;
import com.dite.znpt.exception.ServiceException;
import com.dite.znpt.mapper.UserPostMapper;
import com.dite.znpt.service.PostService;
@ -88,4 +90,14 @@ public class UserPostServiceImpl extends ServiceImpl<UserPostMapper, UserPostEnt
});
this.saveBatch(userPostList);
}
@Override
public List<UserResp> getUsersByPostId(String postId) {
List<String> userIds = this.list(Wrappers.lambdaQuery(UserPostEntity.class).eq(UserPostEntity::getPostId, postId)).stream().map(UserPostEntity::getUserId).toList();
if (CollUtil.isEmpty(userIds)) {
return new ArrayList<>();
}
List<UserEntity> users = userService.listByIds(userIds).stream().filter(user -> Constants.DEL_FLAG_0.equals(user.getDelFlag()) && Constants.STATUS_0.equals(user.getStatus())).toList();
return Converts.INSTANCE.toUserResp(users);
}
}

View File

@ -10,6 +10,7 @@ import com.dite.znpt.domain.entity.RoleEntity;
import com.dite.znpt.domain.entity.UserEntity;
import com.dite.znpt.domain.entity.UserRoleEntity;
import com.dite.znpt.domain.vo.RoleResp;
import com.dite.znpt.domain.vo.UserResp;
import com.dite.znpt.domain.vo.UserRoleReq;
import com.dite.znpt.exception.ServiceException;
import com.dite.znpt.mapper.UserRoleMapper;
@ -88,4 +89,14 @@ public class UserRoleServiceImpl extends ServiceImpl<UserRoleMapper, UserRoleEnt
});
this.saveBatch(userRoleList);
}
@Override
public List<UserResp> getUsersByRoleId(String roleId) {
List<String> userIds = this.list(Wrappers.lambdaQuery(UserRoleEntity.class).eq(UserRoleEntity::getRoleId, roleId)).stream().map(UserRoleEntity::getUserId).toList();
if (CollUtil.isEmpty(userIds)) {
return new ArrayList<>();
}
List<UserEntity> users = userService.listByIds(userIds).stream().filter(user -> Constants.DEL_FLAG_0.equals(user.getDelFlag()) && Constants.STATUS_0.equals(user.getStatus())).toList();
return Converts.INSTANCE.toUserResp(users);
}
}

View File

@ -107,7 +107,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, UserEntity> impleme
UserEntity entity = this.getById(userId);
UserResp userResp= Converts.INSTANCE.toUserResp(entity);
if(StrUtil.isNotBlank(userResp.getDeptId())){
userResp.setUserName(entity.getName());
userResp.setName(entity.getName());
userResp.setDeptName(deptService.getById(userResp.getDeptId()).getDeptName());
}
userResp.setUserTypeLabel(UserTypeEnum.getDescByCode(userResp.getUserType()));
@ -198,6 +198,9 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, UserEntity> impleme
if(CollUtil.isNotEmpty(req.getPostIds())){
userPostService.bindUserPost(userId, req.getPostIds());
}
if(CollUtil.isNotEmpty(req.getRoleIds())){
userRoleService.bindUserRole(new UserRoleReq().setUserId(userId).setRoleIds(req.getRoleIds()));
}
this.updateById(entity);
}

View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dite.znpt.mapper.BusinessDataFileMapper">
<select id="List" resultType="com.dite.znpt.domain.entity.BusinessDataFileEntity">
select * from business_data_part_file
<where>
<if test="folderId != null">
and folder_id = #{folderId}
</if>
<if test="fileName != null and fileName != ''">
and file_name like concat('%', #{fileName}, '%')
</if>
</where>
</select>
<delete id="delete" parameterType="com.dite.znpt.domain.entity.BusinessDataFileEntity" >
delete from business_data_part_file
<where>
<if test="fileId != null">
and file_id = #{fileId}
</if>
<if test="folderId != null ">
and folder_id = #{folderId}
</if>
</where>
</delete>
<insert id="add" parameterType="com.dite.znpt.domain.entity.BusinessDataFileEntity">
insert into business_data_part_file (file_id, folder_id, file_name, file_path, file_type, file_size, upload_time, uploader_id, is_deleted)
values (#{fileId}, #{folderId}, #{fileName}, #{filePath}, #{fileType}, #{fileSize}, #{uploadTime}, #{uploaderId}, #{isDeleted})
</insert>
<select id="getPath" parameterType="java.lang.Long" resultType="java.lang.String">
select file_path from business_data_part_file
<where>
<if test="fileId != null">
and file_id = #{param1}
</if>
</where>
</select>
<!-- 在mapper中添加重命名SQL -->
<update id="reName">
update business_data_part_file
<set>
<if test="newFileName != null">file_name = #{newFileName},</if>
<if test="newFilePath != null">file_path = #{newFilePath},</if>
</set>
where file_id = #{fileId}
</update>
</mapper>

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dite.znpt.mapper.BusinessDataMapper">
<insert id="insert" parameterType="com.dite.znpt.domain.entity.BusinessDataEntity">
insert into business_data_part
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="folderName != null">folder_name,</if>
<if test="parentId != null">parent_id,</if>
<if test="creatorId != null">creator_id,</if>
<if test="createTime != null">create_time,</if>
<if test="updateTime != null">update_time,</if>
<if test="isDeleted != null">is_deleted,</if>
<if test="folderPath != null">folder_path,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="folderName != null">#{folderName},</if>
<if test="parentId != null">#{parentId},</if>
<if test="creatorId != null">#{creatorId},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="isDeleted != null">#{isDeleted},</if>
<if test="folderPath != null">#{folderPath},</if>
</trim>
</insert>
<select id="List" resultType="com.dite.znpt.domain.entity.BusinessDataEntity">
select * from business_data_part
</select>
<select id="getPath" resultType="java.lang.String">
select folder_path from business_data_part where folder_id = #{parentId}
</select>
<delete id="delete">
delete from business_data_part where folder_id = #{folderId}
</delete>
<update id="reName">
update business_data_part
<set>
<if test="folderName != null">folder_name = #{folderName},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="folderPath != null">folder_path = #{folderPath},</if>
</set>
where folder_id = #{folderId}
</update>
<select id="ListWithCondition" resultType="com.dite.znpt.domain.entity.BusinessDataEntity">
select * from business_data_part
<where>
<if test="folderName != null and folderName != ''">
folder_name like concat('%', #{folderName}, '%')
</if>
</where>
</select>
</mapper>

View File

@ -3,44 +3,24 @@
<mapper namespace="com.dite.znpt.mapper.ProjectBudgetInfoMapper">
<sql id="Base_Column_List">
a.budget_id, a.project_id, a.budget_name,
a.budget_amount, a.budget_desc, a.update_by, a.create_time,
a.create_by, a.update_time
a.budget_id, a.project_id, a.budget_name,
a.budget_amount, a.budget_desc, a.attach
</sql>
<select id="queryBySelective" resultType="com.dite.znpt.domain.vo.ProjectBudgetInfoListResp">
select
<include refid="Base_Column_List"/>, p.*
<include refid="Base_Column_List"/>, p.*
from project_budget_info a
left join project p on a.project_id = p.project_id
<where>
<if test="budgetId != null and budgetId != ''">
and a.budget_id like concat ('%', #{budgetId}, '%')
</if>
<if test="projectId != null and projectId != ''">
and a.project_id like concat ('%', #{projectId}, '%')
and a.project_id = #{projectId}
</if>
<if test="budgetName != null and budgetName != ''">
and a.budget_name like concat ('%', #{budgetName}, '%')
</if>
<if test="budgetAmount != null">
and a.budget_amount = #{budgetAmount}
</if>
<if test="budgetDesc != null and budgetDesc != ''">
and a.budget_desc like concat ('%', #{budgetDesc}, '%')
</if>
</where>
</select>
<select id="detailByProjectId" resultType="com.dite.znpt.domain.vo.ProjectBudgetInfoResp">
select
<include refid="Base_Column_List"/>
from project_budget_info a
<where>
<if test="_parameter != null and _parameter != ''">
and a.project_id like concat ('%', #{projectId}, '%')
and a.budget_name = #{budgetName}
</if>
</where>
order by a.project_id, a.budget_name
</select>
</mapper>

View File

@ -16,7 +16,7 @@
GROUP BY prj.project_id
)
SELECT
prj.project_id, prj.project_name, prj.farm_name, prj.status, prj.cover_url, prj.farm_address, prj.client, prj.client_contact, prj.client_phone, prj.inspection_unit,
prj.project_id, prj.project_origin, prj.project_budget, prj.project_name, prj.farm_name, prj.status, prj.cover_url, prj.farm_address, prj.client, prj.client_contact, prj.client_phone, prj.inspection_unit,
prj.inspection_contact, prj.inspection_phone, prj.scale, prj.turbine_model, prj.project_manager_id, pm.name AS project_manager_name, prj.constructor_ids,
prj.start_date, prj.end_date, con.constructor_name, tp.taskPendingCount, tp.task_progress_count, tp.task_complete_count, tp.task_count, prj.auditor_id,
prj.construct_team_leader_id, prj.quality_officer_id

View File

@ -8,37 +8,55 @@
</sql>
<select id="queryBySelective" resultType="com.dite.znpt.domain.vo.UserListResp">
SELECT u.user_id, u.account, u.status, u.name, u.user_code, u.user_type, u.user_status, d.dept_name, u.mobile, u.create_time,
GROUP_CONCAT(r.role_name) AS role_name,GROUP_CONCAT(p.post_name) AS post_name
SELECT
u.user_id,
u.account,
u.status,
u.name,
u.user_code,
u.user_type,
u.user_status,
d.dept_name,
u.mobile,
u.create_time,
(
SELECT GROUP_CONCAT(DISTINCT r.role_name)
FROM user_role ur
JOIN role r ON ur.role_id = r.role_id
WHERE ur.user_id = u.user_id
) AS role_name,
(
SELECT GROUP_CONCAT(DISTINCT p.post_name)
FROM user_post up
JOIN post p ON up.post_id = p.post_id
WHERE up.user_id = u.user_id
) AS post_name
FROM user u
LEFT JOIN dept d ON u.dept_id = d.dept_id
LEFT JOIN user_role ur ON u.user_id = ur.user_id
LEFT JOIN role r ON ur.role_id = r.role_id
LEFT JOIN user_post up ON up.user_id = u.user_id
LEFT JOIN post p ON p.post_id = up.post_id
WHERE u.del_flag = '0'
<where>
<if test="userCode != null and userCode != ''">
AND u.user_code LIKE concat ('%', #{userCode}, '%')
AND u.user_code LIKE CONCAT('%', #{userCode}, '%')
</if>
<if test="account != null and account != ''">
AND u.account LIKE concat ('%', #{account}, '%')
AND u.account LIKE CONCAT('%', #{account}, '%')
</if>
<if test="name != null and name != ''">
AND u.name LIKE concat ('%', #{name}, '%')
AND u.name LIKE CONCAT('%', #{name}, '%')
</if>
<if test="mobile != null and mobile != ''">
AND u.mobile LIKE concat ('%', #{mobile}, '%')
AND u.mobile LIKE CONCAT('%', #{mobile}, '%')
</if>
<if test="deptId != null and deptId != ''">
AND d.dept_id = #{deptId}
</if>
<if test="userStatus != null and userStatus!=''">
<if test="userStatus != null and userStatus != ''">
AND u.user_status = #{userStatus}
</if>
<if test="userType != null and userType!=''">
<if test="userType != null and userType != ''">
AND u.user_Type = #{userType}
</if>
GROUP BY u.user_id, u.account, u.status, u.name, u.user_code, u.user_type, u.user_status, d.dept_name, u.mobile, u.create_time
</where>
<!-- 移除了 GROUP BY -->
</select>
</mapper>

View File

@ -1,459 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AES加密解密工具</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#3b82f6',
secondary: '#10b981',
accent: '#6366f1',
dark: '#1e293b',
light: '#f8fafc'
},
fontFamily: {
inter: ['Inter', 'system-ui', 'sans-serif'],
},
}
}
}
</script>
<style type="text/tailwindcss">
@layer utilities {
.content-auto {
content-visibility: auto;
}
.text-shadow {
text-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.card-shadow {
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
}
.transition-custom {
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
}
</style>
</head>
<body class="font-inter bg-gradient-to-br from-light to-blue-50 min-h-screen">
<div class="container mx-auto px-4 py-8 max-w-5xl">
<!-- 标题区域 -->
<header class="mb-12 text-center">
<h1 class="text-[clamp(2rem,5vw,3.5rem)] font-bold text-dark mb-3 text-shadow">
<i class="fa-solid fa-lock text-primary mr-3"></i>AES加密解密工具
</h1>
<p class="text-gray-600 text-lg max-w-2xl mx-auto">
使用先进的AES加密算法保护您的数据安全支持多种加密模式和密钥长度
</p>
</header>
<!-- 主内容区 -->
<main class="grid grid-cols-1 lg:grid-cols-2 gap-8">
<!-- 加密区域 -->
<section class="bg-white rounded-2xl p-6 card-shadow transition-custom hover:shadow-xl">
<h2 class="text-2xl font-bold text-dark mb-6 flex items-center">
<i class="fa-solid fa-shield-lock text-primary mr-2"></i>加密
</h2>
<div class="space-y-4">
<div>
<label for="plaintext" class="block text-sm font-medium text-gray-700 mb-1">明文</label>
<textarea id="plaintext" class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-primary/50 focus:border-primary transition-custom resize-none" rows="4" placeholder="请输入要加密的文本..."></textarea>
</div>
<div>
<label for="encrypt-key" class="block text-sm font-medium text-gray-700 mb-1">密钥</label>
<div class="relative">
<input type="text" id="encrypt-key" class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-primary/50 focus:border-primary transition-custom" placeholder="请输入16/24/32字节密钥..." value="1234567890123456">
<button type="button" id="generate-key" class="absolute right-2 top-1/2 -translate-y-1/2 text-primary hover:text-primary/80 transition-custom">
<i class="fa-solid fa-refresh"></i>
</button>
</div>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">加密选项</label>
<div class="grid grid-cols-2 gap-4">
<div>
<label for="encrypt-mode" class="block text-xs text-gray-500 mb-1">加密模式</label>
<select id="encrypt-mode" class="w-full px-3 py-2 rounded-lg border border-gray-300 focus:ring-2 focus:ring-primary/50 focus:border-primary transition-custom">
<option value="ECB">ECB</option>
<option value="CBC">CBC</option>
<option value="CFB">CFB</option>
<option value="OFB">OFB</option>
<option value="CTR">CTR</option>
</select>
</div>
<div>
<label for="encrypt-padding" class="block text-xs text-gray-500 mb-1">填充方式</label>
<select id="encrypt-padding" class="w-full px-3 py-2 rounded-lg border border-gray-300 focus:ring-2 focus:ring-primary/50 focus:border-primary transition-custom">
<option value="Pkcs7">PKCS#7</option>
<option value="Iso97971">ISO 9797-1</option>
<option value="AnsiX923">ANSI X.923</option>
<option value="Iso10126">ISO 10126</option>
<option value="ZeroPadding">Zero Padding</option>
<option value="NoPadding">No Padding</option>
</select>
</div>
</div>
</div>
<div id="iv-container" class="hidden">
<label for="encrypt-iv" class="block text-sm font-medium text-gray-700 mb-1">初始化向量(IV)</label>
<input type="text" id="encrypt-iv" class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-primary/50 focus:border-primary transition-custom" placeholder="请输入16字节初始化向量...">
</div>
<button id="encrypt-btn" class="w-full bg-primary hover:bg-primary/90 text-white font-medium py-3 px-4 rounded-lg transition-custom transform hover:scale-[1.02] flex items-center justify-center">
<i class="fa-solid fa-lock mr-2"></i>加密
</button>
</div>
</section>
<!-- 解密区域 -->
<section class="bg-white rounded-2xl p-6 card-shadow transition-custom hover:shadow-xl">
<h2 class="text-2xl font-bold text-dark mb-6 flex items-center">
<i class="fa-solid fa-unlock text-secondary mr-2"></i>解密
</h2>
<div class="space-y-4">
<div>
<label for="ciphertext" class="block text-sm font-medium text-gray-700 mb-1">密文</label>
<textarea id="ciphertext" class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-secondary/50 focus:border-secondary transition-custom resize-none" rows="4" placeholder="请输入要解密的文本..."></textarea>
</div>
<div>
<label for="decrypt-key" class="block text-sm font-medium text-gray-700 mb-1">密钥</label>
<input type="text" id="decrypt-key" class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-secondary/50 focus:border-secondary transition-custom" placeholder="请输入16/24/32字节密钥..." value="1234567890123456">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">解密选项</label>
<div class="grid grid-cols-2 gap-4">
<div>
<label for="decrypt-mode" class="block text-xs text-gray-500 mb-1">解密模式</label>
<select id="decrypt-mode" class="w-full px-3 py-2 rounded-lg border border-gray-300 focus:ring-2 focus:ring-secondary/50 focus:border-secondary transition-custom">
<option value="ECB">ECB</option>
<option value="CBC">CBC</option>
<option value="CFB">CFB</option>
<option value="OFB">OFB</option>
<option value="CTR">CTR</option>
</select>
</div>
<div>
<label for="decrypt-padding" class="block text-xs text-gray-500 mb-1">填充方式</label>
<select id="decrypt-padding" class="w-full px-3 py-2 rounded-lg border border-gray-300 focus:ring-2 focus:ring-secondary/50 focus:border-secondary transition-custom">
<option value="Pkcs7">PKCS#7</option>
<option value="Iso97971">ISO 9797-1</option>
<option value="AnsiX923">ANSI X.923</option>
<option value="Iso10126">ISO 10126</option>
<option value="ZeroPadding">Zero Padding</option>
<option value="NoPadding">No Padding</option>
</select>
</div>
</div>
</div>
<div id="decrypt-iv-container" class="hidden">
<label for="decrypt-iv" class="block text-sm font-medium text-gray-700 mb-1">初始化向量(IV)</label>
<input type="text" id="decrypt-iv" class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-secondary/50 focus:border-secondary transition-custom" placeholder="请输入16字节初始化向量...">
</div>
<button id="decrypt-btn" class="w-full bg-secondary hover:bg-secondary/90 text-white font-medium py-3 px-4 rounded-lg transition-custom transform hover:scale-[1.02] flex items-center justify-center">
<i class="fa-solid fa-unlock mr-2"></i>解密
</button>
</div>
</section>
</main>
<!-- 结果展示区 -->
<section class="mt-8 bg-white rounded-2xl p-6 card-shadow">
<h2 class="text-2xl font-bold text-dark mb-4 flex items-center">
<i class="fa-solid fa-file-text text-accent mr-2"></i>结果
</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">加密结果</label>
<div class="relative">
<textarea id="encrypt-result" class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-accent/50 focus:border-accent transition-custom resize-none" rows="4" readonly placeholder="加密结果将显示在这里..."></textarea>
<button id="copy-encrypt" class="absolute right-2 top-2 text-gray-500 hover:text-accent transition-custom">
<i class="fa-solid fa-copy"></i>
</button>
</div>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">解密结果</label>
<div class="relative">
<textarea id="decrypt-result" class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-accent/50 focus:border-accent transition-custom resize-none" rows="4" readonly placeholder="解密结果将显示在这里..."></textarea>
<button id="copy-decrypt" class="absolute right-2 top-2 text-gray-500 hover:text-accent transition-custom">
<i class="fa-solid fa-copy"></i>
</button>
</div>
</div>
</div>
</section>
<!-- 信息提示区 -->
<div id="notification" class="fixed bottom-4 right-4 bg-dark text-white px-6 py-3 rounded-lg shadow-lg transform translate-y-20 opacity-0 transition-all duration-300 flex items-center">
<i id="notification-icon" class="fa-solid fa-info-circle mr-2"></i>
<span id="notification-message">操作成功</span>
</div>
</div>
<script>
// 加密函数
function encrypt() {
const plaintext = document.getElementById('plaintext').value.trim();
const key = document.getElementById('encrypt-key').value.trim();
const mode = document.getElementById('encrypt-mode').value;
const padding = document.getElementById('encrypt-padding').value;
const iv = document.getElementById('encrypt-iv').value.trim();
if (!plaintext) {
showNotification('请输入明文', 'error');
return;
}
if (!key) {
showNotification('请输入密钥', 'error');
return;
}
try {
// 获取加密模式
const modeObj = getModeObject(mode);
// 获取填充方式
const paddingObj = getPaddingObject(padding);
// 准备加密参数
const keyUtf8 = CryptoJS.enc.Utf8.parse(key);
let encrypted;
// 根据模式是否需要IV
if (mode === 'ECB') {
encrypted = CryptoJS.AES.encrypt(plaintext, keyUtf8, {
mode: modeObj,
padding: paddingObj
});
} else {
if (!iv) {
showNotification('使用该模式需要输入初始化向量(IV)', 'error');
return;
}
const ivUtf8 = CryptoJS.enc.Utf8.parse(iv);
encrypted = CryptoJS.AES.encrypt(plaintext, keyUtf8, {
iv: ivUtf8,
mode: modeObj,
padding: paddingObj
});
}
// 显示加密结果
const encryptedResult = encrypted.toString();
document.getElementById('encrypt-result').value = encryptedResult;
document.getElementById('ciphertext').value = encryptedResult;
showNotification('加密成功', 'success');
} catch (error) {
console.error('加密错误:', error);
showNotification('加密失败: ' + error.message, 'error');
}
}
// 解密函数
function decrypt() {
const ciphertext = document.getElementById('ciphertext').value.trim();
const key = document.getElementById('decrypt-key').value.trim();
const mode = document.getElementById('decrypt-mode').value;
const padding = document.getElementById('decrypt-padding').value;
const iv = document.getElementById('decrypt-iv').value.trim();
if (!ciphertext) {
showNotification('请输入密文', 'error');
return;
}
if (!key) {
showNotification('请输入密钥', 'error');
return;
}
try {
// 获取解密模式
const modeObj = getModeObject(mode);
// 获取填充方式
const paddingObj = getPaddingObject(padding);
// 准备解密参数
const keyUtf8 = CryptoJS.enc.Utf8.parse(key);
// 根据模式是否需要IV
let decrypted;
if (mode === 'ECB') {
decrypted = CryptoJS.AES.decrypt(ciphertext, keyUtf8, {
mode: modeObj,
padding: paddingObj
});
} else {
if (!iv) {
showNotification('使用该模式需要输入初始化向量(IV)', 'error');
return;
}
const ivUtf8 = CryptoJS.enc.Utf8.parse(iv);
decrypted = CryptoJS.AES.decrypt(ciphertext, keyUtf8, {
iv: ivUtf8,
mode: modeObj,
padding: paddingObj
});
}
// 显示解密结果
const decryptedResult = decrypted.toString(CryptoJS.enc.Utf8);
document.getElementById('decrypt-result').value = decryptedResult;
showNotification('解密成功', 'success');
} catch (error) {
console.error('解密错误:', error);
showNotification('解密失败: ' + error.message, 'error');
}
}
// 根据名称获取加密/解密模式对象
function getModeObject(modeName) {
switch (modeName) {
case 'ECB': return CryptoJS.mode.ECB;
case 'CBC': return CryptoJS.mode.CBC;
case 'CFB': return CryptoJS.mode.CFB;
case 'OFB': return CryptoJS.mode.OFB;
case 'CTR': return CryptoJS.mode.CTR;
default: return CryptoJS.mode.ECB;
}
}
// 根据名称获取填充方式对象
function getPaddingObject(paddingName) {
switch (paddingName) {
case 'Pkcs7': return CryptoJS.pad.Pkcs7;
case 'Iso97971': return CryptoJS.pad.Iso97971;
case 'AnsiX923': return CryptoJS.pad.AnsiX923;
case 'Iso10126': return CryptoJS.pad.Iso10126;
case 'ZeroPadding': return CryptoJS.pad.ZeroPadding;
case 'NoPadding': return CryptoJS.pad.NoPadding;
default: return CryptoJS.pad.Pkcs7;
}
}
// 生成随机密钥
function generateRandomKey(length = 16) {
const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
let key = "";
for (let i = 0; i < length; i++) {
key += charset.charAt(Math.floor(Math.random() * charset.length));
}
return key;
}
// 显示通知
function showNotification(message, type = 'info') {
const notification = document.getElementById('notification');
const notificationIcon = document.getElementById('notification-icon');
const notificationMessage = document.getElementById('notification-message');
// 设置通知类型
notification.className = 'fixed bottom-4 right-4 px-6 py-3 rounded-lg shadow-lg transform translate-y-20 opacity-0 transition-all duration-300 flex items-center';
if (type === 'success') {
notification.classList.add('bg-green-500', 'text-white');
notificationIcon.className = 'fa-solid fa-check-circle mr-2';
} else if (type === 'error') {
notification.classList.add('bg-red-500', 'text-white');
notificationIcon.className = 'fa-solid fa-exclamation-circle mr-2';
} else {
notification.classList.add('bg-dark', 'text-white');
notificationIcon.className = 'fa-solid fa-info-circle mr-2';
}
// 设置通知消息
notificationMessage.textContent = message;
// 显示通知
setTimeout(() => {
notification.classList.remove('translate-y-20', 'opacity-0');
}, 10);
// 3秒后隐藏通知
setTimeout(() => {
notification.classList.add('translate-y-20', 'opacity-0');
}, 3000);
}
// 复制到剪贴板
function copyToClipboard(elementId) {
const element = document.getElementById(elementId);
element.select();
document.execCommand('copy');
showNotification('已复制到剪贴板', 'success');
}
// 模式变更事件处理
function handleModeChange() {
const encryptMode = document.getElementById('encrypt-mode').value;
const decryptMode = document.getElementById('decrypt-mode').value;
// 显示或隐藏加密IV输入框
const encryptIvContainer = document.getElementById('iv-container');
if (encryptMode === 'ECB') {
encryptIvContainer.classList.add('hidden');
} else {
encryptIvContainer.classList.remove('hidden');
}
// 显示或隐藏解密IV输入框
const decryptIvContainer = document.getElementById('decrypt-iv-container');
if (decryptMode === 'ECB') {
decryptIvContainer.classList.add('hidden');
} else {
decryptIvContainer.classList.remove('hidden');
}
}
// 生成随机密钥
document.getElementById('generate-key').addEventListener('click', () => {
document.getElementById('encrypt-key').value = generateRandomKey(16);
document.getElementById('decrypt-key').value = document.getElementById('encrypt-key').value;
showNotification('已生成随机密钥', 'success');
});
// 加密按钮点击事件
document.getElementById('encrypt-btn').addEventListener('click', encrypt);
// 解密按钮点击事件
document.getElementById('decrypt-btn').addEventListener('click', decrypt);
// 复制加密结果
document.getElementById('copy-encrypt').addEventListener('click', () => copyToClipboard('encrypt-result'));
// 复制解密结果
document.getElementById('copy-decrypt').addEventListener('click', () => copyToClipboard('decrypt-result'));
// 模式变更事件
document.getElementById('encrypt-mode').addEventListener('change', handleModeChange);
document.getElementById('decrypt-mode').addEventListener('change', handleModeChange);
// 初始化
handleModeChange();
// 添加示例数据
document.getElementById('plaintext').value = '这是一个使用AES加密的示例文本您可以替换为自己的内容。';
</script>
</body>
</html>

141
pom.xml
View File

@ -1,53 +1,88 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.dite.znpt</groupId>
<artifactId>parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<properties>
<java.version>17</java.version>
</properties>
<modules>
<module>core</module>
<module>web</module>
<module>flowable</module>
</modules>
<packaging>pom</packaging>
<!-- 依赖声明 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.18</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.24</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.dite.znpt</groupId>
<artifactId>parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<properties>
<java.version>17</java.version>
</properties>
<modules>
<module>core</module>
<module>sip</module>
<module>web</module>
<module>flowable</module>
</modules>
<packaging>pom</packaging>
<dependencies>
<!-- JavaMail邮件依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- 阿里云短信核心库 -->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.6.3</version> <!-- 建议使用最新版本 -->
</dependency>
<!-- 阿里云短信服务 SDK -->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
<version>2.1.0</version> <!-- 建议使用最新版本 -->
</dependency>
<!-- Java 11+ 需要额外添加的依赖 -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
</dependencies>
<!-- 依赖声明 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.18</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.24</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,58 @@
package com.dite.znpt.web.controller;
import com.dite.znpt.domain.Result;
import com.dite.znpt.domain.dto.FolderDto;
import com.dite.znpt.domain.page.PageBean;
import com.dite.znpt.service.BusinessDataService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Param;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
/*
* @Description: 商务资料管理文件夹层
* 虽然文件夹本质也是文件但我们页面上很多地方光查文件信息根据文件夹ID
* 获取文件列表如果文件夹和文件都放一张表不好区分接口也不好区分这样分开写方便
*/
@Api(tags = "文件夹接口")
@RestController
@Slf4j
@RequestMapping("/businessData/folder")
@ApiOperation("商务资料管理文件夹contrller层")
public class BusinessDataController {
@Resource
private BusinessDataService businessDataService;
@ApiOperation(value = "分页查询文件夹", httpMethod = "GET")
@GetMapping("/list")
public Result pageSelect(@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "10") Integer pageSize,
@RequestParam(required = false) String folderName) {
PageBean pageBean = businessDataService.pageSelect(page, pageSize, folderName);
return Result.ok(pageBean);
}
@ApiOperation(value = "增加文件夹", httpMethod = "POST")
@PostMapping("/creatFolder")
public Result createFolder(@RequestBody FolderDto folderDto) {
return businessDataService.createFolder(folderDto.getName(), folderDto.getParentId());
}
@ApiOperation(value = "删除文件夹", httpMethod = "DELETE")
@DeleteMapping("/delete")
public Result delete(@RequestParam Long folderId) {
return businessDataService.delete(folderId);
}
@ApiOperation(value = "重命名文件夹", httpMethod = "PUT")
@PutMapping("/rename")
public Result Rename(@RequestParam Long folderId, @RequestParam String newName) {
return businessDataService.reName(folderId, newName);
}
}

View File

@ -0,0 +1,141 @@
package com.dite.znpt.web.controller;
import com.dite.znpt.domain.Result;
import com.dite.znpt.domain.entity.BusinessDataFileEntity;
import com.dite.znpt.domain.page.PageBean;
import com.dite.znpt.mapper.BusinessDataFileMapper;
import com.dite.znpt.mapper.BusinessDataMapper;
import com.dite.znpt.service.BusinessDataFileService;
import com.dite.znpt.service.BusinessDataService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import org.springframework.web.multipart.MultipartFile;
/*
* @Description: 商务资料管理文件夹层
*/
@Api(tags = "文件接口")
@RestController
@Slf4j
@RequestMapping("/businessData/file")
@ApiOperation("商务资料管理,文件层")
public class BusinessDataFileController {
@Resource
private BusinessDataFileService businessDataFileService;
@Resource
private BusinessDataService businessDataService;
@Resource
private BusinessDataFileMapper businessDataFileMapper;
@ApiOperation(value = "分页查询文件", httpMethod = "GET")
@GetMapping("/list")
public Result pageSelect(@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "10") Integer pageSize,
@RequestParam(defaultValue = "0") Long folderId,
@RequestParam(required = false) String fileName) {
PageBean pageBean = businessDataFileService.pageSelect(page, pageSize, folderId, fileName);
return Result.ok(pageBean);
}
@ApiOperation(value = "增加文件")
@PostMapping("/add")
public Result add(@RequestParam("file") MultipartFile file,
@RequestParam Long folderId) {
if (file.isEmpty()) {
return Result.error("上传文件为空");
}
// TODO 以后可以优化就算文件名一样加个12这种
try {
byte[] bytes = file.getBytes();
String uploadDir = businessDataService.getPath(folderId);
File uploadedFile = new File(uploadDir + "\\" + file.getOriginalFilename());
if (uploadedFile.exists()) {
return Result.error("文件已存在");
}
file.transferTo(uploadedFile);
// 保存文件信息到数据
BusinessDataFileEntity fileEntity = new BusinessDataFileEntity();
fileEntity.setFolderId(folderId);
fileEntity.setFileName(file.getOriginalFilename());
fileEntity.setFilePath(uploadDir + "\\" + file.getOriginalFilename());
fileEntity.setFileType(file.getContentType());
fileEntity.setFileSize(file.getSize());
fileEntity.setUploadTime(new Date());
fileEntity.setUploaderId(0L);
System.out.println(uploadDir + "\\" + file.getOriginalFilename());
businessDataFileService.add(fileEntity);
return Result.okM("上传成功");
} catch (IOException e) {
e.printStackTrace();
return Result.error("上传失败");
}
}
@ApiOperation(value = "删除文件")
@DeleteMapping("/delete")
public Result delete(@RequestParam Long fileId) {
businessDataFileService.delete(fileId, null);
return Result.okM("删除成功");
}
@ApiOperation(value = "下载文件")
@GetMapping("/download")
public void download(@RequestParam("fileId") Long fileId, HttpServletResponse response) {
String path = businessDataFileService.getPath(fileId);
try {
// path是指想要下载的文件的路径
File file = new File(path);
log.info(file.getPath());
// 获取文件名
String filename = file.getName();
// 获取文件后缀名
String ext = filename.substring(filename.lastIndexOf(".") + 1).toLowerCase();
log.info("文件后缀名:" + ext);
// 将文件写入输入流
FileInputStream fileInputStream = new FileInputStream(file);
InputStream fis = new BufferedInputStream(fileInputStream);
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
fis.close();
// 清空response
response.reset();
// 设置response的Header
response.setCharacterEncoding("UTF-8");
response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
// 告知浏览器文件的大小
response.addHeader("Content-Length", "" + file.length());
OutputStream outputStream = new BufferedOutputStream(response.getOutputStream());
response.setContentType("application/octet-stream");
outputStream.write(buffer);
outputStream.flush();
} catch (IOException ex) {
ex.printStackTrace();
}
}
@ApiOperation(value = "重命名文件", httpMethod = "PUT")
@PutMapping("/rename")
public Result reName(@RequestParam Long fileId, @RequestParam String newFileName) {
return businessDataFileService.reName(fileId, newFileName);
}
}

View File

@ -0,0 +1,46 @@
package com.dite.znpt.web.controller;
import com.dite.znpt.domain.Result;
import com.dite.znpt.domain.entity.UserEntity;
import com.dite.znpt.service.EmailService;
import com.dite.znpt.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@Api(tags = "邮件")
@RestController("/email")
public class EmailController {
@Resource
private EmailService emailService;
@Resource
private UserService userService;
@ApiOperation(value = "发送邮箱验证码", httpMethod = "POST")
@PostMapping("/send")
public Result<?> send(@RequestParam("email") String email) {
boolean send = emailService.sendVerificationCode(email, emailService.generateCode(email));
if (send) {
return Result.ok("发送成功");
}
return Result.error("发送失败");
}
@ApiOperation(value = "验证邮箱验证码", httpMethod = "POST")
@PostMapping("/verify")
public Result<?> verify(@RequestParam("userId") String userId, @RequestParam("email") String email, @RequestParam("code") String code) {
boolean verify = emailService.verifyCode(email, code);
if (verify) {
UserEntity userEntity = userService.getById(userId);
userEntity.setEmail(email);
userService.updateById(userEntity);
return Result.ok("验证成功");
}
return Result.error("验证失败");
}
}

View File

@ -1,11 +1,14 @@
package com.dite.znpt.web.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dite.znpt.domain.PageResult;
import com.dite.znpt.domain.Result;
import com.dite.znpt.domain.vo.PostListReq;
import com.dite.znpt.domain.entity.UserPostEntity;
import com.dite.znpt.domain.vo.PostReq;
import com.dite.znpt.domain.vo.PostResp;
import com.dite.znpt.domain.vo.UserResp;
import com.dite.znpt.service.PostService;
import com.dite.znpt.service.UserPostService;
import com.dite.znpt.util.ValidationGroup;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@ -27,16 +30,19 @@ public class PostController {
@Resource
private PostService postService;
@Resource
private UserPostService userPostService;
@ApiOperation(value = "分页查询岗位信息列表", httpMethod = "GET")
@GetMapping("/page")
public PageResult<PostResp> page(PostListReq req){
return PageResult.ok(postService.page(req));
public PageResult<PostResp> page(@RequestParam(value = "postName", required = false) String postName){
return PageResult.ok(postService.page(postName));
}
@ApiOperation(value = "查询岗位信息列表", httpMethod = "GET")
@GetMapping("/list")
public Result<List<PostResp>> list(PostListReq req){
return Result.ok(postService.list(req));
public Result<List<PostResp>> list(@RequestParam(value = "postName", required = false) String postName){
return Result.ok(postService.list(postName));
}
@ApiOperation(value = "查询岗位信息详情", httpMethod = "GET")
@ -62,8 +68,14 @@ public class PostController {
@ApiOperation(value = "删除岗位信息", httpMethod = "DELETE")
@DeleteMapping("/{postId}")
public Result<?> remove(@PathVariable String postId){
userPostService.remove(new QueryWrapper<UserPostEntity>().eq("post_id", postId));
postService.deleteById(postId);
return Result.ok();
}
@ApiOperation(value="查询属于该岗位的用户", httpMethod = "GET")
@GetMapping("/{postId}/user")
public Result<List<UserResp>> listUser(@PathVariable String postId){
return Result.ok(userPostService.getUsersByPostId(postId));
}
}

View File

@ -3,10 +3,7 @@ package com.dite.znpt.web.controller;
import com.dite.znpt.domain.PageResult;
import com.dite.znpt.domain.Result;
import com.dite.znpt.domain.vo.ProjectBudgetInfoListReq;
import com.dite.znpt.domain.vo.ProjectBudgetInfoListResp;
import com.dite.znpt.domain.vo.ProjectBudgetInfoReq;
import com.dite.znpt.domain.vo.ProjectBudgetInfoResp;
import com.dite.znpt.domain.vo.*;
import com.dite.znpt.service.ProjectBudgetInfoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@ -26,22 +23,35 @@ public class ProjectBudgetInfoController {
@Resource
private ProjectBudgetInfoService projectBudgetInfoService;
@ApiOperation(value = "获取项目预算信息列表", httpMethod = "GET")
@ApiOperation(value = "筛选项目预算信息列表", httpMethod = "GET")
@GetMapping("/list")
public PageResult<ProjectBudgetInfoListResp> list(ProjectBudgetInfoListReq projectBudgetInfoReq) {
return PageResult.ok(projectBudgetInfoService.selectList(projectBudgetInfoReq));
public Result<List<ProjectBudgetInfoListResp>> list(ProjectBudgetInfoListReq projectBudgetInfoListReq) {
return Result.ok(projectBudgetInfoService.list(projectBudgetInfoListReq));
}
@ApiOperation(value = "根据项目id获取项目预算信息列表", httpMethod = "GET")
@GetMapping("/detail/{projectId}")
public PageResult<ProjectBudgetInfoResp> detailByProjectId(@PathVariable String projectId) {
return PageResult.ok(projectBudgetInfoService.detailByProjectId(projectId));
@ApiOperation(value = "分页筛选项目预算信息列表", httpMethod = "GET")
@GetMapping("/page")
public PageResult<ProjectBudgetInfoListResp> page(ProjectBudgetInfoListReq projectBudgetInfoListReq) {
return PageResult.ok(projectBudgetInfoService.page(projectBudgetInfoListReq));
}
@ApiOperation(value = "保存项目预算信息", httpMethod = "POST")
@PostMapping
public Result<Object> add(@RequestBody List<ProjectBudgetInfoReq> projectBudgetInfoReq) {
projectBudgetInfoService.saveData(projectBudgetInfoReq);
@ApiOperation(value = "新增项目预算信息", httpMethod = "POST")
@PostMapping("/save")
public Result<Void> save(@RequestBody ProjectBudgetInfoImportReq req) {
projectBudgetInfoService.saveData(req);
return Result.ok();
}
@ApiOperation(value = "项目预算信息详情", httpMethod = "GET")
@GetMapping("/{projectId}/detail")
public Result<ProjectBudgetInfoDetailResp> detail(@PathVariable String projectId) {
return Result.ok(projectBudgetInfoService.detailByProjectId(projectId));
}
@ApiOperation(value = "删除项目预算信息", httpMethod = "DELETE")
@DeleteMapping("/{budgetId}")
public Result<Void> delete(@PathVariable String budgetId) {
projectBudgetInfoService.delete(budgetId);
return Result.ok();
}
}

View File

@ -1,10 +1,13 @@
package com.dite.znpt.web.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dite.znpt.domain.PageResult;
import com.dite.znpt.domain.Result;
import com.dite.znpt.domain.entity.UserRoleEntity;
import com.dite.znpt.domain.vo.RoleMenuReq;
import com.dite.znpt.domain.vo.RoleReq;
import com.dite.znpt.domain.vo.RoleResp;
import com.dite.znpt.domain.vo.UserResp;
import com.dite.znpt.service.RoleMenuService;
import com.dite.znpt.service.RoleService;
import com.dite.znpt.service.UserRoleService;
@ -34,6 +37,9 @@ public class RoleController {
@Resource
private RoleMenuService roleMenuService;
@Resource
private UserRoleService userRoleService;
@ApiOperation(value = "分页查询角色信息列表", httpMethod = "GET")
@GetMapping("/page")
public PageResult<RoleResp> page(@RequestParam(value = "roleName", required = false) String roleName){
@ -69,6 +75,7 @@ public class RoleController {
@ApiOperation(value = "删除角色信息", httpMethod = "DELETE")
@DeleteMapping("/{roleId}")
public Result<?> delete(@PathVariable String roleId){
userRoleService.remove(new QueryWrapper<UserRoleEntity>().eq("role_id", roleId));
roleService.deleteById(roleId);
return Result.ok();
}
@ -79,4 +86,10 @@ public class RoleController {
roleMenuService.bindRoleMenu(req);
return Result.ok();
}
@ApiOperation(value="查询属于该角色的用户", httpMethod = "GET")
@GetMapping("/{roleId}/user")
public Result<List<UserResp>> listUser(@PathVariable String roleId){
return Result.ok(userRoleService.getUsersByRoleId(roleId));
}
}

View File

@ -1,9 +1,13 @@
package com.dite.znpt.web.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dite.znpt.domain.PageResult;
import com.dite.znpt.domain.Result;
import com.dite.znpt.domain.entity.UserPostEntity;
import com.dite.znpt.domain.entity.UserRoleEntity;
import com.dite.znpt.domain.vo.*;
import com.dite.znpt.service.UserPostService;
import com.dite.znpt.service.UserRoleService;
import com.dite.znpt.service.UserService;
import com.dite.znpt.util.ValidationGroup;
@ -26,6 +30,8 @@ public class UserController {
private UserService userService;
@Resource
private UserRoleService userRoleService;
@Resource
private UserPostService userPostService;
@ApiOperation(value = "分页查询用户信息列表", httpMethod = "GET")
@GetMapping("/page")
@ -68,6 +74,8 @@ public class UserController {
@ApiOperation(value = "删除用户信息", httpMethod = "DELETE")
@DeleteMapping("/{userId}")
public Result<?> remove(@PathVariable String userId) {
userRoleService.remove(new QueryWrapper<UserRoleEntity>().eq("user_id", userId));
userPostService.remove(new QueryWrapper<UserPostEntity>().eq("user_id", userId));
userService.deleteById(userId);
return Result.ok();
}

View File

@ -1,6 +1,7 @@
# 开发环境配置
server:
# 服务器的HTTP端口默认为8080
port: 8888
address : 0.0.0.0 # 监听所有网络接口
servlet:
@ -11,6 +12,21 @@ server:
# 数据源配置
spring:
mail:
host: smtp.qq.com
port: 587
# 网易邮箱配置
# host: smtp.163.com
# port: 465
username: 2838879363@qq.com
password: vtccznivtjrndfci
properties:
mail:
smtp:
auth: true
starttls:
enable: true
required: true
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
@ -88,6 +104,12 @@ spring:
# domain:
# prefix: /minio/
email:
verification:
from: 2838879363@qq.com
subject: "注册验证码"
template: "您的验证码为:%s有效期为5分钟。请不要将验证码泄露给他人。"
############## Sa-Token 配置 (文档: https://sa-token.cc) ##############
sa-token:
# token 名称(同时也是 cookie 名称)