This commit is contained in:
磷叶 2025-01-24 18:06:40 +08:00
parent 9d69470d3f
commit 0abdb3fe32
35 changed files with 768 additions and 42 deletions

View File

@ -17,5 +17,5 @@ public class DictType {
// 任务状态
public static final String TASK_STATUS = "task_status";
// 任务优先级
public static final String TASK_PRIORITY = "task_priority";
public static final String TASK_LEVEL = "task_level";
}

View File

@ -1,6 +1,7 @@
package com.ruoyi.bst.customer.domain;
import java.time.LocalDateTime;
import java.util.List;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@ -72,8 +73,8 @@ public class Customer extends BaseEntity
@Excel(name = "意向")
@ApiModelProperty("意向")
@Size(max = 100, message = "意向长度不能超过100个字符")
private String intent;
@Size(max = 30, message = "意向数量不能超过30个")
private List<String> intents;
@Excel(name = "跟进人ID")
@ApiModelProperty("跟进人ID")

View File

@ -1,7 +1,10 @@
package com.ruoyi.bst.customer.domain;
import java.time.LocalDate;
import java.util.List;
import org.springframework.format.annotation.DateTimeFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ -16,4 +19,11 @@ public class CustomerQuery extends CustomerVO{
@ApiModelProperty("ID列表")
private List<Long> ids;
@ApiModelProperty("意向")
private String intent;
@ApiModelProperty("创建日期")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate createDate;
}

View File

@ -7,6 +7,7 @@ import org.apache.ibatis.annotations.Param;
import com.ruoyi.bst.customer.domain.Customer;
import com.ruoyi.bst.customer.domain.CustomerQuery;
import com.ruoyi.bst.customer.domain.CustomerVO;
import com.ruoyi.common.vo.StringIntegerVO;
/**
* 客户Mapper接口
@ -70,4 +71,11 @@ public interface CustomerMapper
* @return
*/
int selectCount(@Param("query") CustomerQuery query);
/**
* 查询客户数量
* @param query
* @return
*/
List<StringIntegerVO> selectCountGroupByStatus(@Param("query") CustomerQuery query);
}

View File

@ -4,7 +4,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.bst.customer.mapper.CustomerMapper">
<resultMap type="CustomerVO" id="CustomerResult" autoMapping="true"/>
<resultMap type="CustomerVO" id="CustomerResult" autoMapping="true">
<result property="intents" column="intents" typeHandler="com.ruoyi.common.mybatis.typehandler.StringSplitListTypeHandler"/>
</resultMap>
<sql id="selectCustomerVo">
select
@ -16,7 +18,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
bc.mobile,
bc.wechat,
bc.source,
bc.intent,
bc.intents,
bc.follow_id,
bc.last_follow_time,
bc.remark,
@ -35,15 +37,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="query.mobile != null and query.mobile != ''"> and bc.mobile like concat('%', #{query.mobile}, '%')</if>
<if test="query.wechat != null and query.wechat != ''"> and bc.wechat like concat('%', #{query.wechat}, '%')</if>
<if test="query.source != null and query.source != ''"> and bc.source like concat('%', #{query.source}, '%')</if>
<if test="query.intent != null and query.intent != ''"> and bc.intent like concat('%', #{query.intent}, '%')</if>
<if test="query.intent != null and query.intent != ''"> and bc.intents like concat('%', #{query.intent}, '%')</if>
<if test="query.followId != null "> and bc.follow_id = #{query.followId}</if>
<if test="query.remark != null and query.remark != ''"> and bc.remark like concat('%', #{query.remark}, '%')</if>
<if test="query.deleted != null "> and bc.deleted = #{query.deleted}</if>
<if test="query.deleted == null "> and bc.deleted = false</if>
<if test="query.eqCode != null and query.eqCode != ''"> and bc.code = #{query.eqCode}</if>
<if test="query.excludeId != null "> and bc.id != #{query.excludeId}</if>
<if test="query.ids != null and query.ids.size() > 0">
and bc.id in
<if test="query.createDate != null "> and date(bc.create_time) = #{query.createDate}</if>
<if test="query.ids != null and query.ids.size() > 0">
and bc.id in
<foreach collection="query.ids" item="item" open="(" separator="," close=")">
#{item}
</foreach>
@ -73,7 +76,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="mobile != null">mobile,</if>
<if test="wechat != null">wechat,</if>
<if test="source != null and source != ''">source,</if>
<if test="intent != null">intent,</if>
<if test="intents != null and intents.size() > 0">intents,</if>
<if test="followId != null">follow_id,</if>
<if test="lastFollowTime != null">last_follow_time,</if>
<if test="remark != null">remark,</if>
@ -89,7 +92,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="mobile != null">#{mobile},</if>
<if test="wechat != null">#{wechat},</if>
<if test="source != null and source != ''">#{source},</if>
<if test="intent != null">#{intent},</if>
<if test="intents != null and intents.size() > 0">#{intents, typeHandler=com.ruoyi.common.mybatis.typehandler.StringSplitListTypeHandler},</if>
<if test="followId != null">#{followId},</if>
<if test="lastFollowTime != null">#{lastFollowTime},</if>
<if test="remark != null">#{remark},</if>
@ -115,7 +118,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="data.mobile != null">mobile = #{data.mobile},</if>
<if test="data.wechat != null">wechat = #{data.wechat},</if>
<if test="data.source != null and data.source != ''">source = #{data.source},</if>
<if test="data.intent != null">intent = #{data.intent},</if>
<if test="data.intents != null and data.intents.size() > 0">intents = #{data.intents, typeHandler=com.ruoyi.common.mybatis.typehandler.StringSplitListTypeHandler},</if>
<if test="data.followId != null">follow_id = #{data.followId},</if>
<if test="data.lastFollowTime != null">last_follow_time = #{data.lastFollowTime},</if>
<if test="data.remark != null">remark = #{data.remark},</if>
@ -135,7 +138,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</foreach>
</delete>
<!-- selectCount -->
<!-- selectCount -->
<select id="selectCount" parameterType="CustomerQuery" resultType="Integer">
select count(bc.id) from bst_customer bc
@ -143,5 +146,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<include refid="searchCondition"/>
</where>
</select>
<!-- selectCountGroupByStatus -->
<select id="selectCountGroupByStatus" parameterType="CustomerQuery" resultMap="com.ruoyi.common.mapper.CommonMapper.StringIntegerVO">
select
bc.status as `key`,
count(bc.id) as `value`
from bst_customer bc
<where>
<include refid="searchCondition"/>
</where>
group by `key`
</select>
</mapper>

View File

@ -5,6 +5,7 @@ import java.util.List;
import com.ruoyi.bst.customer.domain.Customer;
import com.ruoyi.bst.customer.domain.CustomerQuery;
import com.ruoyi.bst.customer.domain.CustomerVO;
import com.ruoyi.common.vo.StringIntegerVO;
/**
* 客户Service接口
@ -75,4 +76,11 @@ public interface CustomerService
* @return
*/
List<CustomerVO> selectCustomerListByIds(List<Long> ids);
/**
* 查询客户数量
* @param customerQuery
* @return
*/
List<StringIntegerVO> selectCountGroupByStatus(CustomerQuery customerQuery);
}

View File

@ -21,7 +21,7 @@ public class CustomerConverterImpl implements CustomerConverter {
po.setMobile(customer.getMobile());
po.setWechat(customer.getWechat());
po.setSource(customer.getSource());
po.setIntent(customer.getIntent());
po.setIntents(customer.getIntents());
po.setFollowId(customer.getFollowId());
po.setRemark(customer.getRemark());
return po;
@ -41,7 +41,7 @@ public class CustomerConverterImpl implements CustomerConverter {
po.setMobile(customer.getMobile());
po.setWechat(customer.getWechat());
po.setSource(customer.getSource());
po.setIntent(customer.getIntent());
po.setIntents(customer.getIntents());
po.setFollowId(customer.getFollowId());
po.setRemark(customer.getRemark());
return po;

View File

@ -15,6 +15,7 @@ import com.ruoyi.bst.customer.service.CustomerService;
import com.ruoyi.bst.customer.service.CustomerValidator;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.collection.CollectionUtils;
import com.ruoyi.common.vo.StringIntegerVO;
/**
* 客户Service业务层处理
@ -142,4 +143,9 @@ public class CustomerServiceImpl implements CustomerService
query.setIds(ids);
return customerMapper.selectCustomerList(query);
}
@Override
public List<StringIntegerVO> selectCountGroupByStatus(CustomerQuery customerQuery) {
return customerMapper.selectCountGroupByStatus(customerQuery);
}
}

View File

@ -0,0 +1,17 @@
package com.ruoyi.bst.dashboard.domain.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class BriefVO {
@ApiModelProperty("项目概览")
ProjectBriefVO project;
@ApiModelProperty("任务概览")
TaskBriefVO task;
@ApiModelProperty("客户概览")
CustomerBriefVO customer;
}

View File

@ -0,0 +1,53 @@
package com.ruoyi.bst.dashboard.domain.vo;
import java.util.List;
import com.ruoyi.bst.customer.domain.enums.CustomerStatus;
import com.ruoyi.common.vo.StringIntegerVO;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class CustomerBriefVO {
@ApiModelProperty("客户总数")
private Integer total;
@ApiModelProperty("今日新增客户数")
private Integer today;
@ApiModelProperty("潜在客户")
private Integer potential;
@ApiModelProperty("意向客户")
private Integer intention;
@ApiModelProperty("已成交")
private Integer transaction;
@ApiModelProperty("失效客户")
private Integer invalid;
public CustomerBriefVO(List<StringIntegerVO> statusMap) {
this.potential = statusMap.stream()
.filter(vo -> CustomerStatus.POTENTIAL.getStatus().equals(vo.getKey()))
.findFirst().map(StringIntegerVO::getValue).orElse(0);
this.intention = statusMap.stream()
.filter(vo -> CustomerStatus.INTENTION.getStatus().equals(vo.getKey()))
.findFirst().map(StringIntegerVO::getValue).orElse(0);
this.transaction = statusMap.stream()
.filter(vo -> CustomerStatus.TRANSACTION.getStatus().equals(vo.getKey()))
.findFirst().map(StringIntegerVO::getValue).orElse(0);
this.invalid = statusMap.stream()
.filter(vo -> CustomerStatus.INVALID.getStatus().equals(vo.getKey()))
.findFirst().map(StringIntegerVO::getValue).orElse(0);
this.total = statusMap.stream().map(map -> map.getValue()).reduce(0, Integer::sum);
}
}

View File

@ -0,0 +1,57 @@
package com.ruoyi.bst.dashboard.domain.vo;
import java.util.List;
import com.ruoyi.bst.project.domain.enums.ProjectStatus;
import com.ruoyi.common.vo.StringIntegerVO;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class ProjectBriefVO {
@ApiModelProperty("项目总数")
private Integer total;
@ApiModelProperty("已完成")
private Integer completed;
@ApiModelProperty("进行中")
private Integer inProgress;
@ApiModelProperty("维护中")
private Integer maintenance;
@ApiModelProperty("开发超期")
private Integer developmentOverdue;
@ApiModelProperty("维护超期")
private Integer maintenanceOverdue;
public ProjectBriefVO(List<StringIntegerVO> statusMap) {
this.completed = statusMap.stream()
.filter(vo -> ProjectStatus.COMPLETED.getStatus().equals(vo.getKey()))
.findFirst().map(StringIntegerVO::getValue).orElse(0);
this.inProgress = statusMap.stream()
.filter(vo -> ProjectStatus.IN_PROGRESS.getStatus().equals(vo.getKey()))
.findFirst().map(StringIntegerVO::getValue).orElse(0);
this.maintenance = statusMap.stream()
.filter(vo -> ProjectStatus.MAINTENANCE.getStatus().equals(vo.getKey()))
.findFirst().map(StringIntegerVO::getValue).orElse(0);
this.developmentOverdue = statusMap.stream()
.filter(vo -> ProjectStatus.DEVELOPMENT_OVERDUE.getStatus().equals(vo.getKey()))
.findFirst().map(StringIntegerVO::getValue).orElse(0);
this.maintenanceOverdue = statusMap.stream()
.filter(vo -> ProjectStatus.MAINTENANCE_OVERDUE.getStatus().equals(vo.getKey()))
.findFirst().map(StringIntegerVO::getValue).orElse(0);
this.total = statusMap.stream().map(StringIntegerVO::getValue).reduce(0, Integer::sum);
}
}

View File

@ -0,0 +1,50 @@
package com.ruoyi.bst.dashboard.domain.vo;
import java.util.List;
import com.ruoyi.bst.task.domain.enums.TaskStatus;
import com.ruoyi.common.vo.StringIntegerVO;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class TaskBriefVO {
@ApiModelProperty("任务总数")
private Integer total;
@ApiModelProperty("待完成")
private Integer waitCompleted;
@ApiModelProperty("进行中")
private Integer inProgress;
@ApiModelProperty("待确认")
private Integer waitConfirm;
@ApiModelProperty("已完成")
private Integer completed;
public TaskBriefVO(List<StringIntegerVO> statusMap) {
this.waitCompleted = statusMap.stream()
.filter(vo -> TaskStatus.WAIT_COMPLETED.getStatus().equals(vo.getKey()))
.findFirst().map(StringIntegerVO::getValue).orElse(0);
this.inProgress = statusMap.stream()
.filter(vo -> TaskStatus.PROCESSING.getStatus().equals(vo.getKey()))
.findFirst().map(StringIntegerVO::getValue).orElse(0);
this.waitConfirm = statusMap.stream()
.filter(vo -> TaskStatus.WAIT_CONFIRM.getStatus().equals(vo.getKey()))
.findFirst().map(StringIntegerVO::getValue).orElse(0);
this.completed = statusMap.stream()
.filter(vo -> TaskStatus.PASS.getStatus().equals(vo.getKey()))
.findFirst().map(StringIntegerVO::getValue).orElse(0);
this.total = statusMap.stream().map(StringIntegerVO::getValue).reduce(0, Integer::sum);
}
}

View File

@ -0,0 +1,11 @@
package com.ruoyi.bst.dashboard.mapper;
import com.ruoyi.bst.dashboard.domain.vo.ProjectBriefVO;
public interface DashboardMapper {
ProjectBriefVO selectProjectBrief();
}

View File

@ -0,0 +1,26 @@
<?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.ruoyi.bst.dashboard.mapper.DashboardMapper">
<resultMap id="ProjectBriefVO" type="ProjectBriefVO">
<result column="total_count" property="totalCount" typeHandler="com.ruoyi.common.mybatis.typehandler.NonNullIntegerTyperHandler"/>
<result column="finished_count" property="finishedCount" typeHandler="com.ruoyi.common.mybatis.typehandler.NonNullIntegerTyperHandler"/>
<result column="processing_count" property="processingCount" typeHandler="com.ruoyi.common.mybatis.typehandler.NonNullIntegerTyperHandler"/>
<result column="overdue_count" property="overdueCount" typeHandler="com.ruoyi.common.mybatis.typehandler.NonNullIntegerTyperHandler"/>
</resultMap>
<select id="selectProjectBrief" resultMap="ProjectBriefVO">
select
count(*) as total_count,
sum(case when bp.status = '2' then 1 else 0 end) as finished_count,
sum(case when bp.status = '1' then 1 else 0 end) as processing_count,
sum(case when bp.status = '4' then 1 else 0 end) as overdue_count
from bst_project bp
<where>
<include refid="com.ruoyi.bst.project.mapper.ProjectMapper.searchCondition"/>
</where>
</select>
</mapper>

View File

@ -0,0 +1,63 @@
package com.ruoyi.bst.dashboard.service;
import java.time.LocalDate;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.bst.customer.domain.CustomerQuery;
import com.ruoyi.bst.customer.service.CustomerService;
import com.ruoyi.bst.dashboard.domain.vo.BriefVO;
import com.ruoyi.bst.dashboard.domain.vo.CustomerBriefVO;
import com.ruoyi.bst.dashboard.domain.vo.ProjectBriefVO;
import com.ruoyi.bst.dashboard.domain.vo.TaskBriefVO;
import com.ruoyi.bst.project.domain.ProjectQuery;
import com.ruoyi.bst.project.service.ProjectService;
import com.ruoyi.bst.task.domain.TaskQuery;
import com.ruoyi.bst.task.service.TaskService;
import com.ruoyi.common.vo.StringIntegerVO;
@Service
public class DashboardService {
@Autowired
private ProjectService projectService;
@Autowired
private TaskService taskService;
@Autowired
private CustomerService customerService;
public BriefVO selectBrief() {
BriefVO result = new BriefVO();
// 项目概览
List<StringIntegerVO> projectMap = projectService.selectCountGroupByStatus(new ProjectQuery());
ProjectBriefVO projectBriefVO = new ProjectBriefVO(projectMap);
result.setProject(projectBriefVO);
// 任务概览
List<StringIntegerVO> taskMap = taskService.selectCountGroupByStatus(new TaskQuery());
TaskBriefVO taskBriefVO = new TaskBriefVO(taskMap);
result.setTask(taskBriefVO);
// 客户概览
List<StringIntegerVO> customerMap = customerService.selectCountGroupByStatus(new CustomerQuery());
CustomerBriefVO customerBriefVO = new CustomerBriefVO(customerMap);
// 今日新增客户
customerBriefVO.setToday(this.selectTodayCustomerCount());
result.setCustomer(customerBriefVO);
return result;
}
private int selectTodayCustomerCount() {
CustomerQuery query = new CustomerQuery();
query.setCreateDate(LocalDate.now());
return customerService.selectCount(query);
}
}

View File

@ -2,6 +2,7 @@ package com.ruoyi.bst.project.domain;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
@ -30,8 +31,6 @@ public class Project extends BaseEntity
@Excel(name = "项目编号")
@ApiModelProperty("项目编号")
@NotBlank(message = "项目编号不能为空", groups = {ValidGroup.Create.class})
@Size(max = 50, message = "项目编号长度不能超过50个字符")
private String no;
@Excel(name = "项目名称")
@ -45,11 +44,6 @@ public class Project extends BaseEntity
@ApiModelProperty("到期时间")
private LocalDate expireTime;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "运维时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty("运维时间")
private LocalDate operationTime;
@Excel(name = "负责人ID")
@ApiModelProperty("负责人ID")
private Long ownerId;
@ -86,4 +80,23 @@ public class Project extends BaseEntity
@ApiModelProperty("创建人ID")
private Long createId;
@Excel(name = "完成时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty("完成时间")
private LocalDateTime completeTime;
@Excel(name = "预计完成日期", width = 30, dateFormat = "yyyy-MM-dd")
@ApiModelProperty("预计完成日期")
private LocalDate expectedCompleteDate;
@Excel(name = "开始时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty("开始时间")
private LocalDateTime startTime;
@Excel(name = "验收时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty("验收时间")
private LocalDateTime acceptTime;
@Excel(name = "维护到期日期", width = 30, dateFormat = "yyyy-MM-dd")
@ApiModelProperty("维护到期日期")
private LocalDate maintenanceEndDate;
}

View File

@ -1,5 +1,7 @@
package com.ruoyi.bst.project.domain;
import java.util.List;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ -15,4 +17,7 @@ public class ProjectQuery extends ProjectVO {
@ApiModelProperty("排除ID")
private Long excludeId;
@ApiModelProperty("状态列表")
private List<String> statusList;
}

View File

@ -18,4 +18,7 @@ public class ProjectVO extends Project{
@ApiModelProperty("创建人名称")
private String createName;
@ApiModelProperty("客户名称")
private String customerName;
}

View File

@ -0,0 +1,23 @@
package com.ruoyi.bst.project.domain.dto;
import java.time.LocalDate;
import javax.validation.constraints.NotNull;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class ProjectMaintenanceDTO {
@ApiModelProperty("ID")
@NotNull(message = "ID不能为空")
private Long id;
@ApiModelProperty("维护到期日期")
@NotNull(message = "维护到期日期不能为空")
private LocalDate maintenanceEndDate;
@ApiModelProperty("维护费用")
private String operationAmount;
}

View File

@ -0,0 +1,24 @@
package com.ruoyi.bst.project.domain.dto;
import java.time.LocalDate;
import javax.validation.constraints.NotNull;
import org.springframework.format.annotation.DateTimeFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class ProjectStartDTO {
@ApiModelProperty("项目id")
@NotNull(message = "项目id不能为空")
private Long id;
@ApiModelProperty("预计完成日期")
@DateTimeFormat(pattern = "yyyy-MM-dd")
@NotNull(message = "预计完成日期不能为空")
private LocalDate expectedCompleteDate;
}

View File

@ -1,5 +1,8 @@
package com.ruoyi.bst.project.domain.enums;
import java.util.Arrays;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Getter;
@ -7,12 +10,46 @@ import lombok.Getter;
@AllArgsConstructor
public enum ProjectStatus {
IN_PROGRESS("1", "进行中"),
COMPLETED("2", "已完成"),
MAINTENANCE("3", "维护"),
DEVELOPMENT_OVERDUE("4", "开发超期"),
MAINTENANCE_OVERDUE("5", "维护超期");
WAIT_START("WAIT_START", "待开始"),
IN_PROGRESS("IN_PROGRESS", "进行中"),
COMPLETED("COMPLETED", "完成开发"),
ACCEPTED("ACCEPTED", "已验收"),
MAINTENANCE("MAINTENANCE", "维护中"),
MAINTENANCE_OVERDUE("MAINTENANCE_OVERDUE", "维护到期"),
DEVELOPMENT_OVERDUE("DEVELOPMENT_OVERDUE", "开发超期");
private final String status;
private final String name;
/**
* 可以完成的项目状态
* @return
*/
public static List<String> canComplete() {
return Arrays.asList(IN_PROGRESS.getStatus(), DEVELOPMENT_OVERDUE.getStatus());
}
/**
* 可以开始的项目状态
* @return
*/
public static List<String> canStart() {
return Arrays.asList(WAIT_START.getStatus());
}
/**
* 可以验收的项目状态
* @return
*/
public static List<String> canAccept() {
return Arrays.asList(COMPLETED.getStatus());
}
/**
* 可以维护的项目状态
* @return
*/
public static List<String> canMaintenance() {
return Arrays.asList(ACCEPTED.getStatus(), MAINTENANCE_OVERDUE.getStatus());
}
}

View File

@ -8,6 +8,7 @@ import com.ruoyi.bst.project.domain.Project;
import com.ruoyi.bst.project.domain.ProjectQuery;
import com.ruoyi.bst.project.domain.ProjectVO;
import com.ruoyi.bst.project.domain.vo.ProjectNameVO;
import com.ruoyi.common.vo.StringIntegerVO;
/**
* 项目Mapper接口
@ -55,9 +56,9 @@ public interface ProjectMapper
* @param ids 项目主键集合
* @return 结果
*/
public int logicDel(List<Long> ids);
public int logicDel(@Param("ids") List<Long> ids);
/**
/**
* 查询项目名称列表
* @param query 查询条件
* @return 项目名称列表
@ -70,4 +71,19 @@ public interface ProjectMapper
* @return
*/
int selectCount(@Param("query") ProjectQuery query);
/**
* 查询项目数量
* @param query
* @return
*/
List<StringIntegerVO> selectCountGroupByStatus(@Param("query") ProjectQuery query);
/**
* 根据条件更新项目
* @param data 项目数据
* @param query 查询条件
* @return 结果
*/
int updateByQuery(@Param("data") Project data, @Param("query") ProjectQuery query);
}

View File

@ -13,7 +13,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
bp.name,
bp.create_time,
bp.expire_time,
bp.operation_time,
bp.maintenance_end_date,
bp.owner_id,
bp.follow_id,
bp.amount,
@ -24,13 +24,19 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
bp.attaches,
bp.customer_id,
bp.deleted,
bp.complete_time,
bp.expected_complete_date,
bp.start_time,
bp.accept_time,
su.nick_name as owner_name,
sf.nick_name as follow_name,
sc.nick_name as create_name
sc.nick_name as create_name,
bc.name as customer_name
from bst_project bp
left join sys_user su on su.user_id = bp.owner_id
left join sys_user sf on sf.user_id = bp.follow_id
left join sys_user sc on sc.user_id = bp.create_id
left join bst_customer bc on bc.id = bp.customer_id
</sql>
<sql id="searchCondition">
@ -47,8 +53,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="query.ownerName != null and query.ownerName != ''"> and su.nick_name like concat('%', #{query.ownerName}, '%')</if>
<if test="query.followName != null and query.followName != ''"> and sf.nick_name like concat('%', #{query.followName}, '%')</if>
<if test="query.createName != null and query.createName != ''"> and sc.nick_name like concat('%', #{query.createName}, '%')</if>
<if test="query.customerName != null and query.customerName != ''"> and bc.name like concat('%', #{query.customerName}, '%')</if>
<if test="query.excludeId != null "> and bp.id != #{query.excludeId}</if>
<if test="query.eqNo != null and query.eqNo != ''"> and bp.no = #{query.eqNo}</if>
<if test="query.statusList != null and query.statusList.size() > 0">
and bp.status in
<foreach item="item" collection="query.statusList" open="(" separator="," close=")">
#{item}
</foreach>
</if>
${query.params.dataScope}
</sql>
@ -71,7 +84,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="name != null and name != ''">name,</if>
<if test="createTime != null">create_time,</if>
<if test="expireTime != null">expire_time,</if>
<if test="operationTime != null">operation_time,</if>
<if test="maintenanceEndDate != null">maintenance_end_date,</if>
<if test="ownerId != null">owner_id,</if>
<if test="followId != null">follow_id,</if>
<if test="amount != null">amount,</if>
@ -82,14 +95,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="attaches != null">attaches,</if>
<if test="customerId != null">customer_id,</if>
<if test="createId != null">create_id,</if>
<if test="completeTime != null">complete_time,</if>
<if test="deleted != null">deleted,</if>
<if test="expectedCompleteDate != null">expected_complete_date,</if>
<if test="startTime != null">start_time,</if>
<if test="acceptTime != null">accept_time,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="no != null and no != ''">#{no},</if>
<if test="name != null and name != ''">#{name},</if>
<if test="createTime != null">#{createTime},</if>
<if test="expireTime != null">#{expireTime},</if>
<if test="operationTime != null">#{operationTime},</if>
<if test="maintenanceEndDate != null">#{maintenanceEndDate},</if>
<if test="ownerId != null">#{ownerId},</if>
<if test="followId != null">#{followId},</if>
<if test="amount != null">#{amount},</if>
@ -100,7 +117,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="attaches != null">#{attaches},</if>
<if test="customerId != null">#{customerId},</if>
<if test="createId != null">#{createId},</if>
<if test="completeTime != null">#{completeTime},</if>
<if test="deleted != null">#{deleted},</if>
<if test="expectedCompleteDate != null">#{expectedCompleteDate},</if>
<if test="startTime != null">#{startTime},</if>
<if test="acceptTime != null">#{acceptTime},</if>
</trim>
</insert>
@ -117,7 +138,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="data.name != null and data.name != ''">name = #{data.name},</if>
<if test="data.createTime != null">create_time = #{data.createTime},</if>
<if test="data.expireTime != null">expire_time = #{data.expireTime},</if>
<if test="data.operationTime != null">operation_time = #{data.operationTime},</if>
<if test="data.maintenanceEndDate != null">maintenance_end_date = #{data.maintenanceEndDate},</if>
<if test="data.ownerId != null">owner_id = #{data.ownerId},</if>
<if test="data.followId != null">follow_id = #{data.followId},</if>
<if test="data.amount != null">amount = #{data.amount},</if>
@ -129,6 +150,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="data.customerId != null">customer_id = #{data.customerId},</if>
<if test="data.deleted != null">deleted = #{data.deleted},</if>
<if test="data.createId != null">create_id = #{data.createId},</if>
<if test="data.completeTime != null">complete_time = #{data.completeTime},</if>
<if test="data.expectedCompleteDate != null">expected_complete_date = #{data.expectedCompleteDate},</if>
<if test="data.startTime != null">start_time = #{data.startTime},</if>
<if test="data.acceptTime != null">accept_time = #{data.acceptTime},</if>
</sql>
<update id="logicDel" parameterType="String">
@ -157,4 +182,27 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<include refid="searchCondition"/>
</where>
</select>
<select id="selectCountGroupByStatus" parameterType="ProjectQuery" resultMap="com.ruoyi.common.mapper.CommonMapper.StringIntegerVO">
select
bp.status as `key`,
count(bp.id) as `value`
from bst_project bp
<where>
<include refid="searchCondition"/>
</where>
group by `key`
</select>
<!-- updateByQuery -->
<update id="updateByQuery">
update bst_project bp
<trim prefix="SET" suffixOverrides=",">
<include refid="updateColumns"/>
</trim>
<where>
<include refid="searchCondition"/>
</where>
</update>
</mapper>

View File

@ -5,7 +5,10 @@ import java.util.List;
import com.ruoyi.bst.project.domain.Project;
import com.ruoyi.bst.project.domain.ProjectQuery;
import com.ruoyi.bst.project.domain.ProjectVO;
import com.ruoyi.bst.project.domain.dto.ProjectMaintenanceDTO;
import com.ruoyi.bst.project.domain.dto.ProjectStartDTO;
import com.ruoyi.bst.project.domain.vo.ProjectNameVO;
import com.ruoyi.common.vo.StringIntegerVO;
/**
* 项目Service接口
@ -68,4 +71,39 @@ public interface ProjectService
* @return
*/
int selectCount(ProjectQuery query);
/**
* 查询项目数量
* @param query
* @return
*/
List<StringIntegerVO> selectCountGroupByStatus(ProjectQuery query);
/**
* 项目完成
* @param id
* @return
*/
int complete(Long id);
/**
* 项目开始
* @param dto
* @return
*/
int start(ProjectStartDTO dto);
/**
* 项目验收
* @param id
* @return
*/
int accept(Long id);
/**
* 维护
* @param dto
* @return
*/
int maintenance(ProjectMaintenanceDTO dto);
}

View File

@ -22,16 +22,13 @@ public class ProjectConverterImpl implements ProjectConverter {
LoginUser loginUser = SecurityUtils.getLoginUser();
Project po = new Project();
po.setNo(data.getNo());
po.setName(data.getName());
po.setExpireTime(data.getExpireTime());
po.setOperationTime(data.getOperationTime());
po.setOwnerId(data.getOwnerId());
po.setFollowId(data.getFollowId());
po.setAmount(data.getAmount());
po.setReceivedAmount(data.getReceivedAmount());
po.setOperationAmount(data.getOperationAmount());
po.setStatus(ProjectStatus.IN_PROGRESS.getStatus());
po.setStatus(ProjectStatus.WAIT_START.getStatus());
po.setReceivedAmount(BigDecimal.ZERO);
po.setAttaches(data.getAttaches());
po.setCustomerId(data.getCustomerId());
@ -48,15 +45,12 @@ public class ProjectConverterImpl implements ProjectConverter {
Project po = new Project();
po.setId(data.getId());
po.setNo(data.getNo());
po.setName(data.getName());
po.setExpireTime(data.getExpireTime());
po.setOperationTime(data.getOperationTime());
po.setOwnerId(data.getOwnerId());
po.setFollowId(data.getFollowId());
po.setAmount(data.getAmount());
po.setReceivedAmount(data.getReceivedAmount());
po.setOperationAmount(data.getOperationAmount());
po.setAttaches(data.getAttaches());
po.setCustomerId(data.getCustomerId());
po.setRemark(data.getRemark());

View File

@ -1,5 +1,6 @@
package com.ruoyi.bst.project.service.impl;
import java.time.LocalDateTime;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
@ -9,6 +10,9 @@ import org.springframework.transaction.support.TransactionTemplate;
import com.ruoyi.bst.project.domain.Project;
import com.ruoyi.bst.project.domain.ProjectQuery;
import com.ruoyi.bst.project.domain.ProjectVO;
import com.ruoyi.bst.project.domain.dto.ProjectMaintenanceDTO;
import com.ruoyi.bst.project.domain.dto.ProjectStartDTO;
import com.ruoyi.bst.project.domain.enums.ProjectStatus;
import com.ruoyi.bst.project.domain.vo.ProjectNameVO;
import com.ruoyi.bst.project.mapper.ProjectMapper;
import com.ruoyi.bst.project.service.ProjectService;
@ -16,7 +20,10 @@ import com.ruoyi.bst.project.service.ProjectValidator;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.common.utils.SnowFlakeUtil;
import com.ruoyi.common.utils.collection.CollectionUtils;
import com.ruoyi.common.vo.StringIntegerVO;
/**
* 项目Service业务层处理
@ -73,6 +80,7 @@ public class ProjectServiceImpl implements ProjectService
public int insertProject(Project project)
{
project.setCreateTime(DateUtils.getNowDate());
project.setNo(String.valueOf(SnowFlakeUtil.newId()));
Integer result = transactionTemplate.execute(status -> {
int insert = projectMapper.insertProject(project);
@ -153,4 +161,77 @@ public class ProjectServiceImpl implements ProjectService
private void clearCache() {
redisCache.deleteObject(CacheConstants.PROJECT_NAME_LIST);
}
@Override
public List<StringIntegerVO> selectCountGroupByStatus(ProjectQuery query) {
return projectMapper.selectCountGroupByStatus(query);
}
@Override
public int complete(Long id) {
// 查询旧数据
ProjectVO old = this.selectProjectById(id);
ServiceUtil.assertion(old == null, "ID为%s的项目不存在", id);
ServiceUtil.assertion(!ProjectStatus.canComplete().contains(old.getStatus()), "ID为%s的项目当前状态不能完成", id);
// 更新数据
Project data = new Project();
data.setStatus(ProjectStatus.COMPLETED.getStatus());
data.setCompleteTime(LocalDateTime.now());
ProjectQuery query = new ProjectQuery();
query.setId(id);
query.setStatusList(ProjectStatus.canComplete());
return this.updateByQuery(data, query);
}
private int updateByQuery(Project data, ProjectQuery query) {
return projectMapper.updateByQuery(data, query);
}
@Override
public int start(ProjectStartDTO dto) {
ProjectVO old = this.selectProjectById(dto.getId());
ServiceUtil.assertion(old == null, "ID为%s的项目不存在", dto.getId());
ServiceUtil.assertion(!ProjectStatus.canStart().contains(old.getStatus()), "ID为%s的项目当前状态不能开始", dto.getId());
Project data = new Project();
data.setStatus(ProjectStatus.IN_PROGRESS.getStatus());
data.setExpectedCompleteDate(dto.getExpectedCompleteDate());
data.setStartTime(LocalDateTime.now());
ProjectQuery query = new ProjectQuery();
query.setId(dto.getId());
query.setStatusList(ProjectStatus.canStart());
return this.updateByQuery(data, query);
}
@Override
public int accept(Long id) {
ProjectVO old = this.selectProjectById(id);
ServiceUtil.assertion(old == null, "ID为%s的项目不存在", id);
ServiceUtil.assertion(!ProjectStatus.canAccept().contains(old.getStatus()), "ID为%s的项目当前状态不能验收", id);
Project data = new Project();
data.setStatus(ProjectStatus.ACCEPTED.getStatus());
data.setAcceptTime(LocalDateTime.now());
ProjectQuery query = new ProjectQuery();
query.setId(id);
query.setStatusList(ProjectStatus.canAccept());
return this.updateByQuery(data, query);
}
@Override
public int maintenance(ProjectMaintenanceDTO dto) {
ProjectVO old = this.selectProjectById(dto.getId());
ServiceUtil.assertion(old == null, "ID为%s的项目不存在", dto.getId());
ServiceUtil.assertion(!ProjectStatus.canMaintenance().contains(old.getStatus()), "ID为%s的项目当前状态不能维护", dto.getId());
Project data = new Project();
data.setStatus(ProjectStatus.MAINTENANCE.getStatus());
data.setMaintenanceEndDate(dto.getMaintenanceEndDate());
data.setOperationAmount(dto.getOperationAmount());
ProjectQuery query = new ProjectQuery();
query.setId(dto.getId());
query.setStatusList(ProjectStatus.canMaintenance());
return this.updateByQuery(data, query);
}
}

View File

@ -53,7 +53,7 @@ public class Task extends BaseEntity
@Excel(name = "优先级", readConverterExp = "1=高,2=中,3=低")
@ApiModelProperty("优先级")
@NotBlank(message = "优先级不能为空", groups = {ValidGroup.Create.class})
@DictValid(type = DictType.TASK_PRIORITY, message = "非法的优先级值")
@DictValid(type = DictType.TASK_LEVEL, message = "非法的优先级值")
private String level;
@Excel(name = "图片")

View File

@ -7,6 +7,7 @@ import org.apache.ibatis.annotations.Param;
import com.ruoyi.bst.task.domain.Task;
import com.ruoyi.bst.task.domain.TaskQuery;
import com.ruoyi.bst.task.domain.TaskVO;
import com.ruoyi.common.vo.StringIntegerVO;
/**
* 任务Mapper接口
@ -55,4 +56,11 @@ public interface TaskMapper
* @return 结果
*/
public int logicDel(@Param("ids") List<Long> ids);
/**
* 查询任务数量
* @param query
* @return
*/
List<StringIntegerVO> selectCountGroupByStatus(@Param("query") TaskQuery query);
}

View File

@ -124,4 +124,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</foreach>
and deleted = false
</delete>
<!-- selectCountGroupByStatus -->
<select id="selectCountGroupByStatus" parameterType="TaskQuery" resultMap="com.ruoyi.common.mapper.CommonMapper.StringIntegerVO">
select
bt.status as `key`,
count(bt.id) as `value`
from bst_task bt
<where>
<include refid="searchCondition"/>
</where>
group by `key`
</select>
</mapper>

View File

@ -5,6 +5,7 @@ import java.util.List;
import com.ruoyi.bst.task.domain.Task;
import com.ruoyi.bst.task.domain.TaskQuery;
import com.ruoyi.bst.task.domain.TaskVO;
import com.ruoyi.common.vo.StringIntegerVO;
/**
* 任务Service接口
@ -53,4 +54,11 @@ public interface TaskService
* @return 结果
*/
public int logicDel(List<Long> ids);
/**
* 查询任务数量
* @param query
* @return
*/
List<StringIntegerVO> selectCountGroupByStatus(TaskQuery query);
}

View File

@ -11,6 +11,7 @@ import com.ruoyi.bst.task.domain.TaskVO;
import com.ruoyi.bst.task.mapper.TaskMapper;
import com.ruoyi.bst.task.service.TaskService;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.vo.StringIntegerVO;
/**
* 任务Service业务层处理
@ -84,4 +85,9 @@ public class TaskServiceImpl implements TaskService
{
return taskMapper.logicDel(ids);
}
@Override
public List<StringIntegerVO> selectCountGroupByStatus(TaskQuery query) {
return taskMapper.selectCountGroupByStatus(query);
}
}

View File

@ -8,4 +8,9 @@
<result property="value" column="value" typeHandler="com.ruoyi.common.mybatis.typehandler.NonNullDecimalTypeHandler"/>
</resultMap>
<resultMap id="StringIntegerVO" type="com.ruoyi.common.vo.StringIntegerVO">
<result property="key" column="key"/>
<result property="value" column="value" typeHandler="com.ruoyi.common.mybatis.typehandler.NonNullIntegerTyperHandler"/>
</resultMap>
</mapper>

View File

@ -0,0 +1,12 @@
package com.ruoyi.common.vo;
import lombok.Data;
@Data
public class StringIntegerVO {
private String key;
private Integer value;
}

View File

@ -0,0 +1,24 @@
package com.ruoyi.web.bst;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.bst.dashboard.service.DashboardService;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
@RestController
@RequestMapping("/bst/dashboard")
public class DashboardController extends BaseController {
@Autowired
private DashboardService dashboardService;
@GetMapping("/brief")
public AjaxResult brief() {
return AjaxResult.success(dashboardService.selectBrief());
}
}

View File

@ -19,6 +19,8 @@ import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.bst.project.domain.Project;
import com.ruoyi.bst.project.domain.ProjectQuery;
import com.ruoyi.bst.project.domain.ProjectVO;
import com.ruoyi.bst.project.domain.dto.ProjectMaintenanceDTO;
import com.ruoyi.bst.project.domain.dto.ProjectStartDTO;
import com.ruoyi.bst.project.service.ProjectConverter;
import com.ruoyi.bst.project.service.ProjectService;
import com.ruoyi.common.annotation.Log;
@ -124,4 +126,44 @@ public class ProjectController extends BaseController
{
return toAjax(projectService.logicDel(ids));
}
/**
* 项目开始
*/
@PreAuthorize("@ss.hasPermi('bst:project:start')")
@Log(title = "项目", businessType = BusinessType.UPDATE)
@PutMapping("/start")
public AjaxResult start(@RequestBody @Validated ProjectStartDTO dto) {
return toAjax(projectService.start(dto));
}
/**
* 项目开发完成
*/
@PreAuthorize("@ss.hasPermi('bst:project:complete')")
@Log(title = "项目", businessType = BusinessType.UPDATE)
@PutMapping("/complete/{id}")
public AjaxResult complete(@PathVariable("id") Long id) {
return toAjax(projectService.complete(id));
}
/**
* 项目验收
*/
@PreAuthorize("@ss.hasPermi('bst:project:accept')")
@Log(title = "项目", businessType = BusinessType.UPDATE)
@PutMapping("/accept/{id}")
public AjaxResult accept(@PathVariable("id") Long id) {
return toAjax(projectService.accept(id));
}
/**
* 维护
*/
@PreAuthorize("@ss.hasPermi('bst:project:maintenance')")
@Log(title = "项目", businessType = BusinessType.UPDATE)
@PutMapping("/maintenance")
public AjaxResult maintenance(@RequestBody @Validated ProjectMaintenanceDTO dto) {
return toAjax(projectService.maintenance(dto));
}
}