feat:优化问题

main^2
chenhao 2024-10-16 14:27:48 +08:00
parent e5c3868c27
commit 6504c57330
16 changed files with 219 additions and 58 deletions

View File

@ -59,7 +59,7 @@ public class ProjectController extends BaseController
*
*/
// @PreAuthorize("@ss.hasPermi('system:dept:list')")
@PostMapping("/update")
@PutMapping("/update")
@Log(title = "项目管理", businessType = BusinessType.UPDATE)
public AjaxResult updateDate(@RequestBody Project project)
{

View File

@ -37,6 +37,16 @@ public class WorkHourController extends BaseController {
service.insert(workLogger);
return success();
}
/**
*
*/
// @PreAuthorize("@ss.hasPermi('system:dept:list')")
@PutMapping("/update")
@Log(title = "工作日志", businessType = BusinessType.UPDATE)
public AjaxResult updateData(@RequestBody WorkLogger workLogger) {
service.update(workLogger);
return success();
}
/**
*
@ -47,6 +57,15 @@ public class WorkHourController extends BaseController {
return success(service.getInfo(workLogger));
}
/**
*
*/
// @PreAuthorize("@ss.hasPermi('system:dept:list')")
@PostMapping("/remaining")
public AjaxResult remaining(@RequestBody WorkLogger workLogger) {
return AjaxResult.success(null,service.getRemaining(workLogger));
}
/**
*

View File

@ -1,3 +1,5 @@
server:
port: 8181
# 数据源配置
spring:
datasource:
@ -6,9 +8,9 @@ spring:
druid:
# 主库数据源
master:
url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
url: jdbc:mysql://192.168.124.202:3306/unis_pms_pro?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: password
password: unissense
# 从库数据源
slave:
# 从数据源开关/默认关闭
@ -58,4 +60,25 @@ spring:
merge-sql: true
wall:
config:
multi-statement-allow: true
multi-statement-allow: true
redis:
# 地址
host: 192.168.124.103
# 端口默认为6379
port: 6379
# 数据库索引
database: 14
# 密码
password: zghz@123
# 连接超时时间
timeout: 10s
lettuce:
pool:
# 连接池中的最小空闲连接
min-idle: 0
# 连接池中的最大空闲连接
max-idle: 8
# 连接池的最大数据库连接数
max-active: 8
# #连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1ms

View File

@ -1,12 +1,12 @@
package tech.unissense.pms.business.project.domain;
import java.util.Date;
import java.io.Serializable;
import java.util.List;
import tech.unissense.pms.common.core.domain.BaseEntity;
import lombok.AccessLevel;
import lombok.Data;
import tech.unissense.pms.business.projectteam.domain.ProjectTeam;
import lombok.Getter;
import tech.unissense.pms.common.core.domain.BaseEntity;
import tech.unissense.pms.common.utils.DateUtils;
import java.util.Date;
/**
* (Project)

View File

@ -2,7 +2,9 @@ package tech.unissense.pms.business.project.mapper;
import tech.unissense.pms.business.project.domain.Project;
import org.apache.ibatis.annotations.Param;
import tech.unissense.pms.common.core.domain.entity.SysRole;
import java.util.Date;
import java.util.List;
/**
@ -80,5 +82,9 @@ public interface ProjectMapper {
int deleteById(Integer projectId);
int logicalDeleteById(Integer projectId);
Project checkProjectUnique(Project project);
String selectProjectCode(Date date);
}

View File

@ -1,6 +1,7 @@
package tech.unissense.pms.business.project.service.impl;
import cn.hutool.core.collection.CollUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tech.unissense.pms.business.project.domain.Project;
@ -16,6 +17,8 @@ import tech.unissense.pms.business.work.logger.domain.WorkLogger;
import tech.unissense.pms.business.work.logger.service.IWorkLoggerService;
import tech.unissense.pms.business.work.logger.vo.StaticsHourVo;
import tech.unissense.pms.common.core.domain.entity.SysUser;
import tech.unissense.pms.common.core.redis.RedisCache;
import tech.unissense.pms.common.exception.ServiceException;
import tech.unissense.pms.common.utils.DateUtils;
import tech.unissense.pms.common.utils.SecurityUtils;
import tech.unissense.pms.common.utils.StringUtils;
@ -25,11 +28,11 @@ import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -39,6 +42,7 @@ import java.util.stream.Stream;
* @author ch
* @since 2024-10-08 11:47:01
*/
@Slf4j
@Service("projectService")
public class ProjectServiceImpl implements IProjectService {
@Resource
@ -48,6 +52,9 @@ public class ProjectServiceImpl implements IProjectService {
@Autowired
private IWorkLoggerService workLoggerService;
private static final ConcurrentHashMap<String, AtomicInteger> DAILY_SEQUENCE_MAP = new ConcurrentHashMap<>();
@Autowired
private RedisCache redisCache;
/**
* ID
*
@ -67,7 +74,22 @@ public class ProjectServiceImpl implements IProjectService {
*/
public List<Project> permissisonList(Project project) {
dataPermissions(project);
return this.projectMapper.list(project);
List<Project> list = this.projectMapper.list(project);
Date nowDate = DateUtils.getNowDate();
list.forEach(item -> {
if (item.getStartDate() == null || item.getEndDate() == null) {
return;
}
if (nowDate.before(item.getStartDate())) {
item.setProjectState("0");
} else if (nowDate.after(item.getStartDate()) && nowDate.before(item.getEndDate())) {
item.setProjectState("1");
} else if (nowDate.after(item.getEndDate())) {
item.setProjectState("2");
}
});
return list;
}
private void dataPermissions(Project project) {
@ -84,8 +106,8 @@ public class ProjectServiceImpl implements IProjectService {
if (user.getRoles().stream().anyMatch(item-> "企业管理员".equals(item.getRoleName())|| "公司领导".equals(item.getRoleName()))){
}else if (user.getRoles().stream().anyMatch(item -> "项目经理".equals(item.getRoleName()))){
sql.append("and (t1.project_id in (select project_id from pms_project_team where user_id={} ) or t1.project_leader={})");
project.getParams().put("dataScope", StringUtils.format(sql.toString(), user.getUserId(), user.getUserId()));
sql.append("and (t1.project_id in (select project_id from pms_project_team where user_id={} ) or t1.project_leader={} or t1.create_by={})");
project.getParams().put("dataScope", StringUtils.format(sql.toString(), user.getUserId(), user.getUserId(), user.getUserId()));
}else{
sql.append("and (t1.project_id in (select project_id from pms_project_team where user_id={} ))");
project.getParams().put("dataScope", StringUtils.format(sql.toString(), user.getUserId()));
@ -93,6 +115,14 @@ public class ProjectServiceImpl implements IProjectService {
}
public String checkProjectUnique(Project project) {
Integer projectId = StringUtils.isNull(project.getProjectId()) ? -1 : project.getProjectId();
Project info = projectMapper.checkProjectUnique(project);
if (StringUtils.isNotNull(info) && !projectId.equals(info.getProjectId())) {
return project.getProjectName().equals(info.getProjectName()) ? "项目名称已存在" : "项目编号已存在";
}
return "";
}
/**
*
*
@ -101,9 +131,42 @@ public class ProjectServiceImpl implements IProjectService {
*/
@Override
public Project insert(Project project) {
String errorMsg = checkProjectUnique(project);
if (StringUtils.isNotEmpty(errorMsg)) {
throw new ServiceException(errorMsg);
}
if (StringUtils.isEmpty(project.getState())){
project.setState("0");
}
if (StringUtils.isEmpty(project.getProjectCode())) {
// PM+年月日+四位编码
LocalDate currentDate = LocalDate.now();
String dateStr = currentDate.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
// 使用computeIfAbsent来初始化或获取当天的AtomicInteger
AtomicInteger sequence = DAILY_SEQUENCE_MAP.compute(dateStr, (key, existingValue) -> {
if (existingValue == null) {
// 清除旧的日期数据
DAILY_SEQUENCE_MAP.clear();
String existProjectCode = projectMapper.selectProjectCode(DateUtils.toDate(currentDate));
int initValue = 1;
try {
initValue = StringUtils.isNotEmpty(existProjectCode) ? Integer.parseInt(existProjectCode.substring(existProjectCode.length() - 4)) + 1 : 1;
} catch (NumberFormatException e) {
log.error("项目编码格式化错误,项目编码为:{}",existProjectCode);
}
return new AtomicInteger(initValue);
} else {
return existingValue.incrementAndGet() > 9999 ? new AtomicInteger(1) : existingValue;
}
});
// 格式化为四位编码
String sequenceStr = String.format("%04d", sequence.get());
// 生成项目编码
String projectCode = "PM" + dateStr + sequenceStr;
project.setProjectCode(projectCode);
}
// 新增项目
this.projectMapper.insert(project);
// project.getProjectTeamList().forEach(item -> item.setProjectId(project.getProjectId()));
@ -120,6 +183,10 @@ public class ProjectServiceImpl implements IProjectService {
*/
@Override
public Project update(Project project) {
String errorMsg = checkProjectUnique(project);
if (StringUtils.isNotEmpty(errorMsg)) {
throw new ServiceException(errorMsg);
}
this.projectMapper.update(project);
return this.queryById(project.getProjectId());
}
@ -150,19 +217,19 @@ public class ProjectServiceImpl implements IProjectService {
// 获取每个成员的工时统计并转换为Map
Map<String, BigDecimal> workHourVo = workLoggerService.personStatics(projectId).stream()
.collect(Collectors.toMap(StaticsHourVo::getName, StaticsHourVo::getWorkDay,(v1, v2)->v1));
.collect(Collectors.toMap(StaticsHourVo::getName, StaticsHourVo::getWorkTime, (v1, v2) -> v1));
// 返回每个成员的工时信息
return projectTeamList.stream().map(item -> {
String userIdStr = String.valueOf(item.getUserId());
BigDecimal workDay = workHourVo.getOrDefault(userIdStr, BigDecimal.ZERO);
BigDecimal workTime = workHourVo.getOrDefault(userIdStr, BigDecimal.ZERO);
TeamStaticsVo teamStaticsVo = new TeamStaticsVo();
teamStaticsVo.setTeamId(item.getTeamId());
teamStaticsVo.setUserName(item.getUserName());
teamStaticsVo.setUserId(item.getUserId());
teamStaticsVo.setPostId(item.getPostId());
teamStaticsVo.setWorkDay(workDay);
teamStaticsVo.setWorkTime(workTime);
return teamStaticsVo;
}).collect(Collectors.toList());
}
@ -183,7 +250,7 @@ public class ProjectServiceImpl implements IProjectService {
Map<String, BigDecimal> workTimeMap = workLoggers.stream()
.collect(Collectors.toMap(
item -> item.getProjectId() + "_" + DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, item.getLoggerDate()),
WorkLogger::getWorkDay,
item -> new BigDecimal(item.getWorkTime()),
BigDecimal::add));
LocalDate startDate = workLogger.getStartDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

View File

@ -22,6 +22,7 @@ import java.util.List;
public class ProjectExecutionVo {
private Integer projectId;
private String projectName;
private String projectState;
private Integer budgetDate;
private BigDecimal allWorkTime;
private List<BigDecimal> detailList;

View File

@ -23,5 +23,5 @@ public class TeamStaticsVo {
private String userName;
private Integer userId;
private String postId;
private BigDecimal workDay;
private BigDecimal workTime;
}

View File

@ -37,7 +37,7 @@ public class WorkLogger extends BaseEntity {
/**
*
*/
private Integer workTime;
private String workTime;
/**
*
*/
@ -50,12 +50,7 @@ public class WorkLogger extends BaseEntity {
private Date startDate;
private Date endDate;
private List<Integer> projectIdList;
public BigDecimal getWorkDay(){
if (workTime==null){
return BigDecimal.ZERO;
}
return new BigDecimal(workTime).divide(new BigDecimal(8),1,BigDecimal.ROUND_HALF_UP);
}
}

View File

@ -64,4 +64,8 @@ public interface IWorkLoggerService {
List<StaticsHourVo> personStatics(Integer projectId);
List<WorkLogger> listUser(WorkLogger workLogger);
String getRemaining(WorkLogger workLogger);
}

View File

@ -9,13 +9,13 @@ import tech.unissense.pms.business.work.logger.service.IWorkLoggerService;
import tech.unissense.pms.business.work.logger.vo.CalendarVo;
import tech.unissense.pms.business.work.logger.vo.StaticsHourVo;
import tech.unissense.pms.common.utils.DateUtils;
import tech.unissense.pms.common.utils.SecurityUtils;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
@ -139,7 +139,7 @@ public class WorkLoggerServiceImpl implements IWorkLoggerService {
Map<Integer, BigDecimal> workHourMap = list.stream()
.collect(Collectors.toMap(
WorkLogger::getProjectId,
WorkLogger::getWorkDay,
item->new BigDecimal(item.getWorkTime()),
BigDecimal::add
));
@ -160,7 +160,7 @@ public class WorkLoggerServiceImpl implements IWorkLoggerService {
Map<String, BigDecimal> personWorkHourMap = workLoggers.stream()
.collect(Collectors.toMap(
WorkLogger::getCreateBy,
WorkLogger::getWorkDay,
item->new BigDecimal(item.getWorkTime()),
BigDecimal::add
));
@ -173,6 +173,29 @@ public class WorkLoggerServiceImpl implements IWorkLoggerService {
return workLoggerMapper.listUser(workLogger);
}
@Override
public String getRemaining(WorkLogger workLogger) {
// 获取当前登录用户的ID
Long userId = SecurityUtils.getLoginUser().getUserId();
// 设置用户ID和当天的零点时间
workLogger.setUserId(userId.intValue());
if (workLogger.getLoggerDate()==null) {
workLogger.setLoggerDate(DateUtils.getNowDate());
}
workLogger.setLoggerDate(DateUtils.toDate(workLogger.getLoggerDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate()));
// 查询工作日志列表
List<WorkLogger> list = workLoggerMapper.list(workLogger);
// 计算workTime之和
BigDecimal totalWorkTime = list.stream()
.map(item->new BigDecimal(item.getWorkTime())) // 假设WorkLogger有getWorkTime方法返回BigDecimal
.reduce(BigDecimal.ZERO, BigDecimal::add);
// 返回总和的字符串表示
return BigDecimal.ONE.subtract(totalWorkTime).toString();
}
// 泛型方法,用于生成统计工时的列表,适用于项目统计
private <T> List<StaticsHourVo> generateStaticsHourVoList(List<T> items, Map<Integer, BigDecimal> workDayMap,
Function<T, Integer> idExtractor, Function<T, String> nameExtractor) {
@ -192,12 +215,12 @@ public class WorkLoggerServiceImpl implements IWorkLoggerService {
}
// 创建StaticsHourVo对象计算工时并格式化为字符串
private StaticsHourVo createStaticsHourVo(String name, BigDecimal workDay,Integer projectId) {
private StaticsHourVo createStaticsHourVo(String name, BigDecimal workTime,Integer projectId) {
StaticsHourVo vo = new StaticsHourVo();
vo.setProjectId(projectId);
vo.setName(name);
// 将总工时除以8表示为工作日并保留两位小数
vo.setWorkDay(workDay);
vo.setWorkTime(workTime);
return vo;
}

View File

@ -22,5 +22,5 @@ public class StaticsHourVo {
private Integer projectId;
private String name;
private BigDecimal workDay;
private BigDecimal workTime;
}

View File

@ -41,21 +41,22 @@
</sql>
<!--查询单个-->
<select id="queryById" resultMap="ProjectMap">
select project_id,
tenant_id,
project_name,
project_code,
project_leader,
start_date,
end_date,
budget_date,
state,
project_state,
create_by,
update_by,
update_time,
create_time
from pms_project
select t1.project_id,
t1.tenant_id,
t1.project_name,
t1.project_code,
t1.project_leader,
t1.start_date,
t1.end_date,
t1.budget_date,
t1.state,
t1.project_state,
t1.create_by,
t1.update_by,
t1.update_time,
t1.create_time,
t2.nick_name project_leader_name
from pms_project t1 left join sys_user t2 on t1.project_leader=t2.user_id
where project_id = #{projectId}
</select>
@ -75,7 +76,7 @@
and t1.tenant_id = #{tenantId}
</if>
<if test="projectName != null and projectName != ''">
and t1.project_name = #{projectName}
and t1.project_name like concat('%',#{projectName},'%')
</if>
<if test="projectCode != null and projectCode != ''">
and t1.project_code = #{projectCode}
@ -96,7 +97,18 @@
and t1.state = #{state}
</if>
<if test="projectState != null and projectState != ''">
and t1.project_state = #{projectState}
<!-- and t1.project_state = #{projectState} -->
<choose>
<when test="projectState=='0'.toString()">
and t1.start_date <![CDATA[ > ]]> sysdate()
</when>
<when test="projectState=='1'.toString()">
and sysdate() between t1.start_date and t1.end_date
</when>
<when test="projectState=='2'.toString()">
and t1.end_date <![CDATA[ < ]]> sysdate()
</when>
</choose>
</if>
<if test="createBy != null">
and t1.create_by = #{createBy}
@ -168,6 +180,17 @@
</if>
</where>
</select>
<select id="checkProjectUnique" resultMap="ProjectMap">
<include refid="base_query"/>
where (project_name=#{projectName} or project_code=#{projectCode}) and state=0 limit 1
</select>
<select id="selectProjectCode" resultType="java.lang.String">
SELECT project_code
FROM pms_project
WHERE project_code LIKE CONCAT('PM', DATE_FORMAT(#{date}, '%Y%m%d'), '%')
ORDER BY project_code DESC
LIMIT 1
</select>
<!--新增所有列-->
<insert id="insert" keyProperty="projectId" useGeneratedKeys="true">

View File

@ -8,7 +8,7 @@
<result property="projectId" column="project_id" jdbcType="INTEGER"/>
<result property="userId" column="user_id" jdbcType="INTEGER"/>
<result property="userName" column="user_name" jdbcType="VARCHAR"/>
<result property="workTime" column="work_time" jdbcType="INTEGER"/>
<result property="workTime" column="work_time" jdbcType="VARCHAR"/>
<result property="workContent" column="work_content" jdbcType="VARCHAR"/>
<result property="state" column="state" jdbcType="VARCHAR"/>
<result property="createBy" column="create_by" jdbcType="VARCHAR"/>

View File

@ -107,10 +107,10 @@ public class DataScopeAspect
{
continue;
}
if (!StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
{
continue;
}
// if (!StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
// {
// continue;
// }
if (DATA_SCOPE_ALL.equals(dataScope))
{
sqlString = new StringBuilder();

View File

@ -42,7 +42,7 @@ public class SysDeptServiceImpl implements ISysDeptService
* @return
*/
@Override
@DataScope(deptAlias = "d")
@DataScope(deptAlias = "d",permission = "system:user:list")
public List<SysDept> selectDeptList(SysDept dept)
{
return deptMapper.selectDeptList(dept);