Compare commits
10
Commits
f808efdc80
...
520b4084eb
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
520b4084eb | ||
|
|
ce1f69c9bb | ||
|
|
f88eca848b | ||
|
|
653a50f737 | ||
|
|
429aaedba9 | ||
|
|
cf9798be32 | ||
|
|
c84bf79d9d | ||
|
|
bc2fca4e97 | ||
|
|
542c038801 | ||
|
|
c2295fba2c |
@@ -39,12 +39,16 @@
|
||||
<module>wm-iot</module>
|
||||
<module>wm-data-engine</module>
|
||||
<module>wm-bpm</module>
|
||||
<module>wm-bpm-engine</module>
|
||||
<module>wm-production</module>
|
||||
<module>wm-revenue</module>
|
||||
<module>wm-patrol</module>
|
||||
<module>wm-bi</module>
|
||||
<module>wm-notify</module>
|
||||
<module>wm-job</module>
|
||||
<module>wm-dispatch</module>
|
||||
<module>wm-system</module>
|
||||
<module>wm-mobile-app</module>
|
||||
</modules>
|
||||
|
||||
<dependencyManagement>
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
<?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>
|
||||
<parent>
|
||||
<groupId>com.water</groupId>
|
||||
<artifactId>wm-parent</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>wm-bpm-engine</artifactId>
|
||||
<name>wm-bpm-engine</name>
|
||||
<description>BPM 业务流程引擎模块</description>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.water</groupId>
|
||||
<artifactId>wm-common</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-spring-boot3-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<!-- Test -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.water.bpmengine;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
@SpringBootApplication
|
||||
public class BpmEngineApplication {
|
||||
public static void main(String[] args) { SpringApplication.run(BpmEngineApplication.class, args); }
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.water.bpmengine.controller;
|
||||
import com.water.common.core.result.R;
|
||||
import com.water.bpmengine.entity.*;
|
||||
import com.water.bpmengine.service.BpmEngineService;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import java.util.*;
|
||||
|
||||
@Tag(name = "业务流程引擎")
|
||||
@RestController @RequestMapping("/bpm") @RequiredArgsConstructor
|
||||
public class BpmEngineController {
|
||||
private final BpmEngineService svc;
|
||||
|
||||
@GetMapping("/definition/list")
|
||||
public R<List<ProcessDefinition>> listDefs(
|
||||
@RequestParam(required=false) String category,
|
||||
@RequestParam(required=false) Integer status) {
|
||||
return R.ok(svc.listDefinitions(category, status));
|
||||
}
|
||||
@PostMapping("/definition")
|
||||
public R<Long> createDef(@RequestBody Map<String,Object> req) {
|
||||
return R.ok(svc.createDefinition(req));
|
||||
}
|
||||
@PostMapping("/definition/{id}/publish")
|
||||
public R<String> publish(@PathVariable Long id) {
|
||||
svc.publishDefinition(id); return R.ok("OK");
|
||||
}
|
||||
@PostMapping("/process/start")
|
||||
public R<Map<String,Object>> start(
|
||||
@RequestParam Long definitionId,
|
||||
@RequestParam String title,
|
||||
@RequestParam String initiator) {
|
||||
return R.ok(svc.startProcess(definitionId, title, initiator));
|
||||
}
|
||||
@GetMapping("/process/list")
|
||||
public R<List<ProcessInstance>> listInstances(
|
||||
@RequestParam(required=false) String initiator,
|
||||
@RequestParam(required=false) Integer status) {
|
||||
return R.ok(svc.listInstances(initiator, status));
|
||||
}
|
||||
@GetMapping("/task/todo")
|
||||
public R<List<TaskItem>> todo(@RequestParam String assignee) {
|
||||
return R.ok(svc.getTodoTasks(assignee));
|
||||
}
|
||||
@GetMapping("/task/done")
|
||||
public R<List<TaskItem>> done(@RequestParam String assignee) {
|
||||
return R.ok(svc.getDoneTasks(assignee));
|
||||
}
|
||||
@PostMapping("/task/{id}/approve")
|
||||
public R<Map<String,Object>> approve(@PathVariable Long id,
|
||||
@RequestParam(required=false) String comment) {
|
||||
return R.ok(svc.approveTask(id, comment));
|
||||
}
|
||||
@PostMapping("/task/{id}/reject")
|
||||
public R<Map<String,Object>> reject(@PathVariable Long id,
|
||||
@RequestParam(required=false) String comment) {
|
||||
return R.ok(svc.rejectTask(id, comment));
|
||||
}
|
||||
@PostMapping("/task/{id}/transfer")
|
||||
public R<Map<String,Object>> transfer(@PathVariable Long id,
|
||||
@RequestParam String newAssignee) {
|
||||
return R.ok(svc.transferTask(id, newAssignee));
|
||||
}
|
||||
@GetMapping("/statistics")
|
||||
public R<Map<String,Object>> stats(@RequestParam(required=false) String processKey) {
|
||||
return R.ok(svc.getStatistics(processKey));
|
||||
}
|
||||
@GetMapping("/template/list")
|
||||
public R<List<ProcessTemplate>> listTemplates() {
|
||||
return R.ok(svc.listTemplates());
|
||||
}
|
||||
@PostMapping("/template")
|
||||
public R<Long> createTemplate(@RequestBody Map<String,Object> req) {
|
||||
return R.ok(svc.createTemplate(req));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.water.bpmengine.entity;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data; import java.time.LocalDateTime;
|
||||
@Data @TableName("bpm_process_definition")
|
||||
public class ProcessDefinition {
|
||||
@TableId(type = IdType.AUTO) private Long id;
|
||||
private String processKey, name, category;
|
||||
private String bpmnXml;
|
||||
private Integer version; private Integer status; // 0草稿 1已发布 2已停用
|
||||
private String description;
|
||||
@TableField(fill=FieldFill.INSERT) private LocalDateTime createdTime;
|
||||
@TableField(fill=FieldFill.INSERT_UPDATE) private LocalDateTime updatedTime;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.water.bpmengine.entity;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data; import java.time.LocalDateTime;
|
||||
@Data @TableName("bpm_process_instance")
|
||||
public class ProcessInstance {
|
||||
@TableId(type = IdType.AUTO) private Long id;
|
||||
private Long definitionId; private String processKey;
|
||||
private String title, initiator;
|
||||
private Integer status; // 0运行中 1已完成 2已驳回 3已撤销
|
||||
private String currentNodeName;
|
||||
@TableField(fill=FieldFill.INSERT) private LocalDateTime createdTime;
|
||||
private LocalDateTime completedTime;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.water.bpmengine.entity;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data; import java.time.LocalDateTime;
|
||||
@Data @TableName("bpm_process_template")
|
||||
public class ProcessTemplate {
|
||||
@TableId(type = IdType.AUTO) private Long id;
|
||||
private String name, category, description;
|
||||
private String bpmnXml;
|
||||
private Integer status;
|
||||
@TableField(fill=FieldFill.INSERT) private LocalDateTime createdTime;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.water.bpmengine.entity;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data; import java.time.LocalDateTime;
|
||||
@Data @TableName("bpm_task_item")
|
||||
public class TaskItem {
|
||||
@TableId(type = IdType.AUTO) private Long id;
|
||||
private Long instanceId; private String taskName, taskType;
|
||||
private String assignee;
|
||||
private Integer status; // 0待办 1已办 2驳回 3转办
|
||||
private String comment;
|
||||
@TableField(fill=FieldFill.INSERT) private LocalDateTime createdTime;
|
||||
private LocalDateTime completedTime;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.water.bpmengine.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.bpmengine.entity.ProcessDefinition;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@Mapper public interface ProcessDefinitionMapper extends BaseMapper<ProcessDefinition> {}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.water.bpmengine.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.bpmengine.entity.ProcessInstance;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@Mapper public interface ProcessInstanceMapper extends BaseMapper<ProcessInstance> {}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.water.bpmengine.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.bpmengine.entity.ProcessTemplate;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@Mapper public interface ProcessTemplateMapper extends BaseMapper<ProcessTemplate> {}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.water.bpmengine.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.bpmengine.entity.TaskItem;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@Mapper public interface TaskItemMapper extends BaseMapper<TaskItem> {}
|
||||
@@ -0,0 +1,122 @@
|
||||
package com.water.bpmengine.service;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.water.bpmengine.entity.*;
|
||||
import com.water.bpmengine.mapper.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import java.time.LocalDateTime; import java.util.*;
|
||||
|
||||
@Service @RequiredArgsConstructor
|
||||
public class BpmEngineService {
|
||||
private final ProcessDefinitionMapper defMapper;
|
||||
private final ProcessInstanceMapper instMapper;
|
||||
private final TaskItemMapper taskMapper;
|
||||
private final ProcessTemplateMapper tplMapper;
|
||||
|
||||
// === 流程定义 ===
|
||||
public List<ProcessDefinition> listDefinitions(String category, Integer status) {
|
||||
return defMapper.selectList(new LambdaQueryWrapper<ProcessDefinition>()
|
||||
.eq(category != null, ProcessDefinition::getCategory, category)
|
||||
.eq(status != null, ProcessDefinition::getStatus, status));
|
||||
}
|
||||
public Long createDefinition(Map<String,Object> req) {
|
||||
ProcessDefinition d = new ProcessDefinition();
|
||||
d.setProcessKey((String)req.get("processKey"));
|
||||
d.setName((String)req.get("name"));
|
||||
d.setCategory((String)req.get("category"));
|
||||
d.setBpmnXml((String)req.get("bpmnXml"));
|
||||
d.setDescription((String)req.get("description"));
|
||||
d.setVersion(1); d.setStatus(0);
|
||||
defMapper.insert(d);
|
||||
return d.getId();
|
||||
}
|
||||
public void publishDefinition(Long id) {
|
||||
ProcessDefinition d = defMapper.selectById(id);
|
||||
if (d == null) throw new RuntimeException("流程定义不存在");
|
||||
d.setStatus(1); defMapper.updateById(d);
|
||||
}
|
||||
|
||||
// === 流程实例 ===
|
||||
public Map<String,Object> startProcess(Long definitionId, String title, String initiator) {
|
||||
ProcessDefinition d = defMapper.selectById(definitionId);
|
||||
if (d == null || d.getStatus() != 1) throw new RuntimeException("流程未发布");
|
||||
ProcessInstance inst = new ProcessInstance();
|
||||
inst.setDefinitionId(definitionId); inst.setProcessKey(d.getProcessKey());
|
||||
inst.setTitle(title); inst.setInitiator(initiator);
|
||||
inst.setStatus(0); inst.setCurrentNodeName("开始");
|
||||
instMapper.insert(inst);
|
||||
TaskItem t = new TaskItem();
|
||||
t.setInstanceId(inst.getId()); t.setTaskName("审批节点");
|
||||
t.setTaskType("审批"); t.setAssignee(initiator); t.setStatus(0);
|
||||
taskMapper.insert(t);
|
||||
return Map.of("instanceId", inst.getId(), "processKey", d.getProcessKey());
|
||||
}
|
||||
public List<ProcessInstance> listInstances(String initiator, Integer status) {
|
||||
return instMapper.selectList(new LambdaQueryWrapper<ProcessInstance>()
|
||||
.eq(initiator != null, ProcessInstance::getInitiator, initiator)
|
||||
.eq(status != null, ProcessInstance::getStatus, status));
|
||||
}
|
||||
|
||||
// === 任务处理 ===
|
||||
public List<TaskItem> getTodoTasks(String assignee) {
|
||||
return taskMapper.selectList(new LambdaQueryWrapper<TaskItem>()
|
||||
.eq(TaskItem::getAssignee, assignee).eq(TaskItem::getStatus, 0));
|
||||
}
|
||||
public List<TaskItem> getDoneTasks(String assignee) {
|
||||
return taskMapper.selectList(new LambdaQueryWrapper<TaskItem>()
|
||||
.eq(TaskItem::getAssignee, assignee).in(TaskItem::getStatus, 1, 2));
|
||||
}
|
||||
public Map<String,Object> approveTask(Long taskId, String comment) {
|
||||
TaskItem t = taskMapper.selectById(taskId);
|
||||
if (t == null || t.getStatus() != 0) throw new RuntimeException("任务不可审批");
|
||||
t.setStatus(1); t.setComment(comment); t.setCompletedTime(LocalDateTime.now());
|
||||
taskMapper.updateById(t);
|
||||
ProcessInstance inst = instMapper.selectById(t.getInstanceId());
|
||||
inst.setCurrentNodeName("已完成"); inst.setStatus(1); inst.setCompletedTime(LocalDateTime.now());
|
||||
instMapper.updateById(inst);
|
||||
return Map.of("taskId", taskId, "status", "已审批");
|
||||
}
|
||||
public Map<String,Object> rejectTask(Long taskId, String comment) {
|
||||
TaskItem t = taskMapper.selectById(taskId);
|
||||
if (t == null) throw new RuntimeException("任务不存在");
|
||||
t.setStatus(2); t.setComment(comment); t.setCompletedTime(LocalDateTime.now());
|
||||
taskMapper.updateById(t);
|
||||
ProcessInstance inst = instMapper.selectById(t.getInstanceId());
|
||||
inst.setStatus(2); inst.setCompletedTime(LocalDateTime.now());
|
||||
instMapper.updateById(inst);
|
||||
return Map.of("taskId", taskId, "status", "已驳回");
|
||||
}
|
||||
public Map<String,Object> transferTask(Long taskId, String newAssignee) {
|
||||
TaskItem t = taskMapper.selectById(taskId);
|
||||
if (t == null) throw new RuntimeException("任务不存在");
|
||||
t.setStatus(3); t.setCompletedTime(LocalDateTime.now());
|
||||
taskMapper.updateById(t);
|
||||
TaskItem nt = new TaskItem();
|
||||
nt.setInstanceId(t.getInstanceId()); nt.setTaskName(t.getTaskName());
|
||||
nt.setTaskType(t.getTaskType()); nt.setAssignee(newAssignee); nt.setStatus(0);
|
||||
taskMapper.insert(nt);
|
||||
return Map.of("oldTaskId", taskId, "newTaskId", nt.getId());
|
||||
}
|
||||
|
||||
// === 统计 ===
|
||||
public Map<String,Object> getStatistics(String processKey) {
|
||||
long total = instMapper.selectCount(new LambdaQueryWrapper<ProcessInstance>()
|
||||
.eq(processKey != null, ProcessInstance::getProcessKey, processKey));
|
||||
long completed = instMapper.selectCount(new LambdaQueryWrapper<ProcessInstance>()
|
||||
.eq(processKey != null, ProcessInstance::getProcessKey, processKey)
|
||||
.eq(ProcessInstance::getStatus, 1));
|
||||
return Map.of("total", total, "completed", completed,
|
||||
"running", total - completed,
|
||||
"completionRate", total > 0 ? (double)completed / total : 0);
|
||||
}
|
||||
|
||||
// === 模板 ===
|
||||
public List<ProcessTemplate> listTemplates() { return tplMapper.selectList(null); }
|
||||
public Long createTemplate(Map<String,Object> req) {
|
||||
ProcessTemplate t = new ProcessTemplate();
|
||||
t.setName((String)req.get("name")); t.setCategory((String)req.get("category"));
|
||||
t.setBpmnXml((String)req.get("bpmnXml")); t.setStatus(1);
|
||||
tplMapper.insert(t);
|
||||
return t.getId();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
server:
|
||||
port: 9040
|
||||
spring:
|
||||
application:
|
||||
name: wm-bpm-engine
|
||||
datasource:
|
||||
url: jdbc:postgresql://localhost:5432/water_bpm
|
||||
username: water
|
||||
password: water123
|
||||
mybatis-plus:
|
||||
configuration:
|
||||
map-underscore-to-camel-case: true
|
||||
global-config:
|
||||
db-config:
|
||||
id-type: auto
|
||||
@@ -0,0 +1,23 @@
|
||||
-- BPM Engine DDL
|
||||
CREATE TABLE IF NOT EXISTS bpm_process_definition (
|
||||
id BIGSERIAL PRIMARY KEY, process_key VARCHAR(100), name VARCHAR(200),
|
||||
category VARCHAR(50), bpmn_xml TEXT, version INT DEFAULT 1,
|
||||
status INT DEFAULT 0, description TEXT,
|
||||
created_time TIMESTAMP DEFAULT NOW(), updated_time TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS bpm_process_instance (
|
||||
id BIGSERIAL PRIMARY KEY, definition_id BIGINT, process_key VARCHAR(100),
|
||||
title VARCHAR(200), initiator VARCHAR(50), status INT DEFAULT 0,
|
||||
current_node_name VARCHAR(100),
|
||||
created_time TIMESTAMP DEFAULT NOW(), completed_time TIMESTAMP
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS bpm_task_item (
|
||||
id BIGSERIAL PRIMARY KEY, instance_id BIGINT, task_name VARCHAR(100),
|
||||
task_type VARCHAR(30), assignee VARCHAR(50), status INT DEFAULT 0,
|
||||
comment TEXT, created_time TIMESTAMP DEFAULT NOW(), completed_time TIMESTAMP
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS bpm_process_template (
|
||||
id BIGSERIAL PRIMARY KEY, name VARCHAR(200), category VARCHAR(50),
|
||||
bpmn_xml TEXT, status INT DEFAULT 1,
|
||||
created_time TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
@@ -1,18 +1,63 @@
|
||||
package com.water.bpm.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.water.common.core.entity.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 审批记录实体
|
||||
* BPM-03: 流程处理
|
||||
*/
|
||||
@Data
|
||||
public class BpmApprovalRecord {
|
||||
private Long id;
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("bpm_approval_record")
|
||||
public class BpmApprovalRecord extends BaseEntity {
|
||||
|
||||
/** 流程实例ID */
|
||||
private Long instanceId;
|
||||
|
||||
/** 流程实例UUID */
|
||||
private String instanceUuid;
|
||||
|
||||
/** 节点标识 */
|
||||
private String nodeId;
|
||||
|
||||
/** 节点名称 */
|
||||
private String nodeName;
|
||||
|
||||
/** 审批人ID */
|
||||
private Long approverId;
|
||||
|
||||
/** 审批人姓名 */
|
||||
private String approverName;
|
||||
private String action; // approve/reject/transfer/delegate/back
|
||||
|
||||
/** 审批动作: approve/reject/transfer/delegate/back/countersign */
|
||||
private String action;
|
||||
|
||||
/** 审批意见 */
|
||||
private String comment;
|
||||
private String targetAssignee; // 转办/委派目标
|
||||
|
||||
/** 转办/委派目标人ID */
|
||||
private Long targetAssigneeId;
|
||||
|
||||
/** 转办/委派目标人姓名 */
|
||||
private String targetAssigneeName;
|
||||
|
||||
/** 会签结果: all/pass_one/veto */
|
||||
private String countersignResult;
|
||||
|
||||
/** 会签通过数 */
|
||||
private Integer countersignApproved;
|
||||
|
||||
/** 会签总数 */
|
||||
private Integer countersignTotal;
|
||||
|
||||
/** 审批时间 */
|
||||
private LocalDateTime approvedAt;
|
||||
|
||||
/** 租户ID */
|
||||
private String tenantId;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.water.bpm.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.water.common.core.entity.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 流程表单模板实体
|
||||
* BPM-02: 模板化快速创建
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("bpm_form_template")
|
||||
public class BpmFormTemplate extends BaseEntity {
|
||||
|
||||
/** 模板名称 */
|
||||
private String templateName;
|
||||
|
||||
/** 模板编码 */
|
||||
private String templateCode;
|
||||
|
||||
/** 模板分类 */
|
||||
private String category;
|
||||
|
||||
/** 表单 JSON Schema */
|
||||
private String formSchema;
|
||||
|
||||
/** 流程 BPMN XML 模板 */
|
||||
private String bpmnTemplate;
|
||||
|
||||
/** 模板描述 */
|
||||
private String description;
|
||||
|
||||
/** 模板图标 */
|
||||
private String icon;
|
||||
|
||||
/** 使用次数 */
|
||||
private Integer useCount;
|
||||
|
||||
/** 状态: 0-草稿 1-启用 2-停用 */
|
||||
private Integer status;
|
||||
|
||||
/** 创建人 */
|
||||
private String createdBy;
|
||||
|
||||
/** 租户ID */
|
||||
private String tenantId;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.water.bpm.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.water.common.core.entity.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 流程编排实体
|
||||
* BPM-05: 跨系统流程编排
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("bpm_orchestration")
|
||||
public class BpmOrchestration extends BaseEntity {
|
||||
|
||||
/** 编排名称 */
|
||||
private String orchestrationName;
|
||||
|
||||
/** 编排编码 */
|
||||
private String orchestrationCode;
|
||||
|
||||
/** 编排描述 */
|
||||
private String description;
|
||||
|
||||
/** 包含的流程定义ID列表 JSON */
|
||||
private String processDefinitionIds;
|
||||
|
||||
/** 编排规则 JSON (流程间依赖关系、触发条件) */
|
||||
private String orchestrationRules;
|
||||
|
||||
/** 触发方式: manual/scheduled/event */
|
||||
private String triggerType;
|
||||
|
||||
/** 定时表达式 (cron) */
|
||||
private String cronExpression;
|
||||
|
||||
/** 事件名称 (event触发时) */
|
||||
private String eventName;
|
||||
|
||||
/** 状态: 0-草稿 1-启用 2-停用 */
|
||||
private Integer status;
|
||||
|
||||
/** 创建人 */
|
||||
private String createdBy;
|
||||
|
||||
/** 执行次数 */
|
||||
private Integer executionCount;
|
||||
|
||||
/** 租户ID */
|
||||
private String tenantId;
|
||||
}
|
||||
@@ -1,20 +1,58 @@
|
||||
package com.water.bpm.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.water.common.core.entity.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 流程定义实体
|
||||
* BPM-01: 流程定义管理
|
||||
*/
|
||||
@Data
|
||||
public class BpmProcessDefinition {
|
||||
private Long id;
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("bpm_process_definition")
|
||||
public class BpmProcessDefinition extends BaseEntity {
|
||||
|
||||
/** 流程唯一标识 */
|
||||
private String processKey;
|
||||
|
||||
/** 流程名称 */
|
||||
private String processName;
|
||||
|
||||
/** 流程描述 */
|
||||
private String description;
|
||||
private String bpmnXml; // BPMN 2.0 XML
|
||||
private String formSchema; // 表单 JSON Schema
|
||||
private String category; // revenue/patrol/dispatch/maintenance
|
||||
|
||||
/** BPMN 2.0 XML 定义 */
|
||||
private String bpmnXml;
|
||||
|
||||
/** 表单 JSON Schema */
|
||||
private String formSchema;
|
||||
|
||||
/** 流程分类: revenue/patrol/dispatch/maintenance/inspection */
|
||||
private String category;
|
||||
|
||||
/** 版本号 */
|
||||
@TableField("version")
|
||||
private Integer version;
|
||||
private Integer status; // 0:草稿 1:发布 2:停用
|
||||
|
||||
/** 状态: 0-草稿 1-已发布 2-已停用 */
|
||||
private Integer status;
|
||||
|
||||
/** 创建人 */
|
||||
private String createdBy;
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
/** 流程图标 */
|
||||
private String icon;
|
||||
|
||||
/** 排序号 */
|
||||
private Integer sortOrder;
|
||||
|
||||
/** 发布时间 */
|
||||
private LocalDateTime publishedAt;
|
||||
|
||||
/** 租户ID */
|
||||
private String tenantId;
|
||||
}
|
||||
|
||||
@@ -1,26 +1,84 @@
|
||||
package com.water.bpm.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.water.common.core.entity.BaseEntity;
|
||||
import lombok.Data;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 流程实例实体
|
||||
* BPM-03: 流程处理
|
||||
*/
|
||||
@Data
|
||||
public class BpmProcessInstance {
|
||||
private Long id;
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("bpm_process_instance")
|
||||
public class BpmProcessInstance extends BaseEntity {
|
||||
|
||||
/** 实例唯一ID */
|
||||
private String instanceId;
|
||||
|
||||
/** 关联流程定义ID */
|
||||
private Long definitionId;
|
||||
|
||||
/** 流程标识 */
|
||||
private String processKey;
|
||||
private String businessKey; // 关联业务ID
|
||||
private String businessType; // 业务类型
|
||||
|
||||
/** 流程名称 */
|
||||
private String processName;
|
||||
|
||||
/** 业务主键(关联业务表) */
|
||||
private String businessKey;
|
||||
|
||||
/** 业务类型 */
|
||||
private String businessType;
|
||||
|
||||
/** 流程标题 */
|
||||
private String title;
|
||||
|
||||
/** 发起人ID */
|
||||
private Long initiatorId;
|
||||
|
||||
/** 发起人姓名 */
|
||||
private String initiatorName;
|
||||
private String currentNode; // 当前审批节点
|
||||
private String currentAssignee; // 当前处理人
|
||||
private String status; // running/completed/terminated/rejected
|
||||
private Map<String, Object> variables;
|
||||
private Map<String, Object> formData;
|
||||
|
||||
/** 当前节点标识 */
|
||||
private String currentNodeId;
|
||||
|
||||
/** 当前节点名称 */
|
||||
private String currentNodeName;
|
||||
|
||||
/** 当前处理人ID */
|
||||
private Long currentAssigneeId;
|
||||
|
||||
/** 当前处理人姓名 */
|
||||
private String currentAssigneeName;
|
||||
|
||||
/** 状态: running/completed/terminated/rejected/suspended */
|
||||
private String status;
|
||||
|
||||
/** 优先级: 0-普通 1-紧急 2-特急 */
|
||||
private Integer priority;
|
||||
|
||||
/** 流程变量 JSON */
|
||||
private String variables;
|
||||
|
||||
/** 表单数据 JSON */
|
||||
private String formData;
|
||||
|
||||
/** 开始时间 */
|
||||
private LocalDateTime startedAt;
|
||||
|
||||
/** 结束时间 */
|
||||
private LocalDateTime completedAt;
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
/** 预计完成时间 */
|
||||
private LocalDateTime expectedCompletionAt;
|
||||
|
||||
/** 耗时(秒) */
|
||||
private Long durationSeconds;
|
||||
|
||||
/** 租户ID */
|
||||
private String tenantId;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.water.bpm.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.water.common.core.entity.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 流程节点定义实体
|
||||
* BPM-01: 流程定义
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("bpm_process_node")
|
||||
public class BpmProcessNode extends BaseEntity {
|
||||
|
||||
/** 关联流程定义ID */
|
||||
private Long definitionId;
|
||||
|
||||
/** 节点标识 */
|
||||
private String nodeId;
|
||||
|
||||
/** 节点名称 */
|
||||
private String nodeName;
|
||||
|
||||
/** 节点类型: start/end/userTask/serviceTask/gateway/subprocess/timer */
|
||||
private String nodeType;
|
||||
|
||||
/** 处理人类型: role/user/department/position/initiator */
|
||||
private String assigneeType;
|
||||
|
||||
/** 处理人值(角色ID/用户ID/部门ID等) */
|
||||
private String assigneeValue;
|
||||
|
||||
/** 处理人名称(冗余) */
|
||||
private String assigneeName;
|
||||
|
||||
/** 多人审批方式: sequential(会签)/parallel(或签)/countersign(比例签) */
|
||||
private String multiInstanceType;
|
||||
|
||||
/** 会签通过比例 */
|
||||
private Integer countersignRate;
|
||||
|
||||
/** 超时时间(小时) */
|
||||
private Integer timeoutHours;
|
||||
|
||||
/** 超时处理: remind/transfer/escalate/auto_approve */
|
||||
private String timeoutAction;
|
||||
|
||||
/** 表单权限 JSON */
|
||||
private String formPermission;
|
||||
|
||||
/** 节点条件表达式 */
|
||||
private String conditionExpression;
|
||||
|
||||
/** 排序号 */
|
||||
private Integer sortOrder;
|
||||
|
||||
/** 租户ID */
|
||||
private String tenantId;
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.water.bpm.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.water.common.core.entity.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 流程统计实体
|
||||
* BPM-04: 统计评估
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("bpm_process_stat")
|
||||
public class BpmProcessStat extends BaseEntity {
|
||||
|
||||
/** 流程定义ID */
|
||||
private Long definitionId;
|
||||
|
||||
/** 流程标识 */
|
||||
private String processKey;
|
||||
|
||||
/** 统计周期: day/week/month/quarter/year */
|
||||
private String period;
|
||||
|
||||
/** 统计日期 */
|
||||
private String statDate;
|
||||
|
||||
/** 发起总数 */
|
||||
private Integer startCount;
|
||||
|
||||
/** 完成总数 */
|
||||
private Integer completedCount;
|
||||
|
||||
/** 驳回总数 */
|
||||
private Integer rejectedCount;
|
||||
|
||||
/** 撤回总数 */
|
||||
private Integer terminatedCount;
|
||||
|
||||
/** 平均耗时(秒) */
|
||||
private Long avgDurationSeconds;
|
||||
|
||||
/** 最长耗时(秒) */
|
||||
private Long maxDurationSeconds;
|
||||
|
||||
/** 最短耗时(秒) */
|
||||
private Long minDurationSeconds;
|
||||
|
||||
/** 平均节点耗时(秒) */
|
||||
private Long avgNodeDurationSeconds;
|
||||
|
||||
/** 超时任务数 */
|
||||
private Integer timeoutCount;
|
||||
|
||||
/** 一次通过率(百分比) */
|
||||
private Double firstPassRate;
|
||||
|
||||
/** 租户ID */
|
||||
private String tenantId;
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.water.bpm.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.water.common.core.entity.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 待办任务实体
|
||||
* BPM-06: 待办/已办中心
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("bpm_todo_task")
|
||||
public class BpmTodoTask extends BaseEntity {
|
||||
|
||||
/** 流程实例ID */
|
||||
private Long instanceId;
|
||||
|
||||
/** 流程实例UUID */
|
||||
private String instanceUuid;
|
||||
|
||||
/** 流程标题 */
|
||||
private String title;
|
||||
|
||||
/** 流程标识 */
|
||||
private String processKey;
|
||||
|
||||
/** 流程名称 */
|
||||
private String processName;
|
||||
|
||||
/** 节点标识 */
|
||||
private String nodeId;
|
||||
|
||||
/** 节点名称 */
|
||||
private String nodeName;
|
||||
|
||||
/** 处理人ID */
|
||||
private Long assigneeId;
|
||||
|
||||
/** 处理人姓名 */
|
||||
private String assigneeName;
|
||||
|
||||
/** 发起人ID */
|
||||
private Long initiatorId;
|
||||
|
||||
/** 发起人姓名 */
|
||||
private String initiatorName;
|
||||
|
||||
/** 业务主键 */
|
||||
private String businessKey;
|
||||
|
||||
/** 任务状态: pending/completed/transferred/delegated */
|
||||
private String status;
|
||||
|
||||
/** 优先级: 0-普通 1-紧急 2-特急 */
|
||||
private Integer priority;
|
||||
|
||||
/** 接收时间 */
|
||||
private LocalDateTime receivedAt;
|
||||
|
||||
/** 完成时间 */
|
||||
private LocalDateTime completedAt;
|
||||
|
||||
/** 超时时间 */
|
||||
private LocalDateTime deadlineAt;
|
||||
|
||||
/** 是否已读 */
|
||||
private Boolean isRead;
|
||||
|
||||
/** 租户ID */
|
||||
private String tenantId;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.water.bpm.entity.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 审批请求 DTO
|
||||
*/
|
||||
@Data
|
||||
public class ApprovalRequest {
|
||||
/** 流程实例ID */
|
||||
private Long instanceId;
|
||||
|
||||
/** 流程实例UUID */
|
||||
private String instanceUuid;
|
||||
|
||||
/** 节点标识 */
|
||||
private String nodeId;
|
||||
|
||||
/** 节点名称 */
|
||||
private String nodeName;
|
||||
|
||||
/** 审批动作: approve/reject/transfer/delegate/back/countersign */
|
||||
private String action;
|
||||
|
||||
/** 审批意见 */
|
||||
private String comment;
|
||||
|
||||
/** 转办/委派目标人ID */
|
||||
private Long targetAssigneeId;
|
||||
|
||||
/** 转办/委派目标人姓名 */
|
||||
private String targetAssigneeName;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.water.bpm.entity.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 流程实例查询 DTO
|
||||
*/
|
||||
@Data
|
||||
public class ProcessInstanceQuery {
|
||||
/** 流程标识 */
|
||||
private String processKey;
|
||||
|
||||
/** 流程标题 */
|
||||
private String title;
|
||||
|
||||
/** 状态 */
|
||||
private String status;
|
||||
|
||||
/** 发起人ID */
|
||||
private Long initiatorId;
|
||||
|
||||
/** 业务主键 */
|
||||
private String businessKey;
|
||||
|
||||
/** 业务类型 */
|
||||
private String businessType;
|
||||
|
||||
/** 开始时间(起) */
|
||||
private LocalDateTime startTimeFrom;
|
||||
|
||||
/** 开始时间(止) */
|
||||
private LocalDateTime startTimeTo;
|
||||
|
||||
/** 页码 */
|
||||
private Integer pageNum = 1;
|
||||
|
||||
/** 每页条数 */
|
||||
private Integer pageSize = 10;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.water.bpm.entity.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 流程发起请求 DTO
|
||||
*/
|
||||
@Data
|
||||
public class ProcessStartRequest {
|
||||
/** 流程定义ID */
|
||||
private Long definitionId;
|
||||
|
||||
/** 业务主键 */
|
||||
private String businessKey;
|
||||
|
||||
/** 业务类型 */
|
||||
private String businessType;
|
||||
|
||||
/** 流程标题 */
|
||||
private String title;
|
||||
|
||||
/** 表单数据 */
|
||||
private Map<String, Object> formData;
|
||||
|
||||
/** 流程变量 */
|
||||
private Map<String, Object> variables;
|
||||
|
||||
/** 优先级 */
|
||||
private Integer priority;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.water.bpm.entity.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 流程统计 VO
|
||||
*/
|
||||
@Data
|
||||
public class ProcessStatVO {
|
||||
/** 流程定义ID */
|
||||
private Long definitionId;
|
||||
|
||||
/** 流程名称 */
|
||||
private String processName;
|
||||
|
||||
/** 流程标识 */
|
||||
private String processKey;
|
||||
|
||||
/** 总实例数 */
|
||||
private Integer totalInstances;
|
||||
|
||||
/** 运行中数量 */
|
||||
private Integer runningCount;
|
||||
|
||||
/** 已完成数量 */
|
||||
private Integer completedCount;
|
||||
|
||||
/** 已驳回数量 */
|
||||
private Integer rejectedCount;
|
||||
|
||||
/** 已撤回数量 */
|
||||
private Integer terminatedCount;
|
||||
|
||||
/** 平均耗时(小时) */
|
||||
private Double avgDurationHours;
|
||||
|
||||
/** 最长耗时(小时) */
|
||||
private Double maxDurationHours;
|
||||
|
||||
/** 最短耗时(小时) */
|
||||
private Double minDurationHours;
|
||||
|
||||
/** 一次通过率 */
|
||||
private Double firstPassRate;
|
||||
|
||||
/** 超时率 */
|
||||
private Double timeoutRate;
|
||||
|
||||
/** 各节点平均耗时 */
|
||||
private List<Map<String, Object>> nodeAvgDurations;
|
||||
|
||||
/** 瓶颈节点(耗时最长) */
|
||||
private String bottleneckNode;
|
||||
|
||||
/** 趋势数据 */
|
||||
private List<Map<String, Object>> trendData;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.water.bpm.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.bpm.entity.BpmApprovalRecord;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 审批记录 Mapper
|
||||
*/
|
||||
@Mapper
|
||||
public interface BpmApprovalRecordMapper extends BaseMapper<BpmApprovalRecord> {
|
||||
|
||||
/**
|
||||
* 根据流程实例查询审批记录
|
||||
*/
|
||||
@Select("SELECT * FROM bpm_approval_record WHERE instance_id = #{instanceId} AND deleted = 0 ORDER BY approved_at")
|
||||
List<BpmApprovalRecord> selectByInstanceId(@Param("instanceId") Long instanceId);
|
||||
|
||||
/**
|
||||
* 根据流程实例UUID查询审批记录
|
||||
*/
|
||||
@Select("SELECT * FROM bpm_approval_record WHERE instance_uuid = #{instanceUuid} AND deleted = 0 ORDER BY approved_at")
|
||||
List<BpmApprovalRecord> selectByInstanceUuid(@Param("instanceUuid") String instanceUuid);
|
||||
|
||||
/**
|
||||
* 查询某人的审批统计
|
||||
*/
|
||||
@Select("SELECT approver_id, approver_name, COUNT(*) as total, " +
|
||||
"SUM(CASE WHEN action = 'approve' THEN 1 ELSE 0 END) as approved, " +
|
||||
"SUM(CASE WHEN action = 'reject' THEN 1 ELSE 0 END) as rejected, " +
|
||||
"AVG(EXTRACT(EPOCH FROM (approved_at - created_at))) as avg_handle_seconds " +
|
||||
"FROM bpm_approval_record WHERE deleted = 0 AND approved_at >= #{startDate} " +
|
||||
"GROUP BY approver_id, approver_name")
|
||||
List<java.util.Map<String, Object>> statByApprover(@Param("startDate") java.time.LocalDateTime startDate);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.water.bpm.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.bpm.entity.BpmFormTemplate;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 表单模板 Mapper
|
||||
*/
|
||||
@Mapper
|
||||
public interface BpmFormTemplateMapper extends BaseMapper<BpmFormTemplate> {
|
||||
|
||||
/**
|
||||
* 根据分类查询模板
|
||||
*/
|
||||
@Select("SELECT * FROM bpm_form_template WHERE category = #{category} AND status = 1 AND deleted = 0 ORDER BY use_count DESC")
|
||||
List<BpmFormTemplate> selectByCategory(@Param("category") String category);
|
||||
|
||||
/**
|
||||
* 查询热门模板
|
||||
*/
|
||||
@Select("SELECT * FROM bpm_form_template WHERE status = 1 AND deleted = 0 ORDER BY use_count DESC LIMIT #{limit}")
|
||||
List<BpmFormTemplate> selectHotTemplates(@Param("limit") int limit);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.water.bpm.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.bpm.entity.BpmOrchestration;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 流程编排 Mapper
|
||||
*/
|
||||
@Mapper
|
||||
public interface BpmOrchestrationMapper extends BaseMapper<BpmOrchestration> {
|
||||
|
||||
/**
|
||||
* 查询所有启用的编排
|
||||
*/
|
||||
@Select("SELECT * FROM bpm_orchestration WHERE status = 1 AND deleted = 0 ORDER BY created_at DESC")
|
||||
List<BpmOrchestration> selectEnabled();
|
||||
|
||||
/**
|
||||
* 查询事件触发的编排
|
||||
*/
|
||||
@Select("SELECT * FROM bpm_orchestration WHERE trigger_type = 'event' AND event_name = #{eventName} " +
|
||||
"AND status = 1 AND deleted = 0")
|
||||
List<BpmOrchestration> selectByEvent(String eventName);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.water.bpm.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.bpm.entity.BpmProcessDefinition;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 流程定义 Mapper
|
||||
*/
|
||||
@Mapper
|
||||
public interface BpmProcessDefinitionMapper extends BaseMapper<BpmProcessDefinition> {
|
||||
|
||||
/**
|
||||
* 根据分类查询已发布的流程定义
|
||||
*/
|
||||
@Select("SELECT * FROM bpm_process_definition WHERE category = #{category} AND status = 1 AND deleted = 0 ORDER BY sort_order")
|
||||
List<BpmProcessDefinition> selectByCategory(@Param("category") String category);
|
||||
|
||||
/**
|
||||
* 根据 processKey 查询最新版本
|
||||
*/
|
||||
@Select("SELECT * FROM bpm_process_definition WHERE process_key = #{processKey} AND deleted = 0 ORDER BY version DESC LIMIT 1")
|
||||
BpmProcessDefinition selectByProcessKey(@Param("processKey") String processKey);
|
||||
|
||||
/**
|
||||
* 查询所有分类
|
||||
*/
|
||||
@Select("SELECT DISTINCT category FROM bpm_process_definition WHERE deleted = 0 AND status = 1 ORDER BY category")
|
||||
List<String> selectAllCategories();
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.water.bpm.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.bpm.entity.BpmProcessInstance;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 流程实例 Mapper
|
||||
*/
|
||||
@Mapper
|
||||
public interface BpmProcessInstanceMapper extends BaseMapper<BpmProcessInstance> {
|
||||
|
||||
/**
|
||||
* 统计各状态数量
|
||||
*/
|
||||
@Select("SELECT status, COUNT(*) as count FROM bpm_process_instance WHERE deleted = 0 GROUP BY status")
|
||||
List<Map<String, Object>> countByStatus();
|
||||
|
||||
/**
|
||||
* 根据流程定义统计
|
||||
*/
|
||||
@Select("SELECT definition_id, COUNT(*) as total, " +
|
||||
"SUM(CASE WHEN status = 'running' THEN 1 ELSE 0 END) as running, " +
|
||||
"SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) as completed, " +
|
||||
"SUM(CASE WHEN status = 'rejected' THEN 1 ELSE 0 END) as rejected, " +
|
||||
"SUM(CASE WHEN status = 'terminated' THEN 1 ELSE 0 END) as terminated, " +
|
||||
"AVG(duration_seconds) as avg_duration, " +
|
||||
"MAX(duration_seconds) as max_duration, " +
|
||||
"MIN(duration_seconds) as min_duration " +
|
||||
"FROM bpm_process_instance WHERE deleted = 0 GROUP BY definition_id")
|
||||
List<Map<String, Object>> statByDefinition();
|
||||
|
||||
/**
|
||||
* 查询我发起的流程
|
||||
*/
|
||||
@Select("SELECT * FROM bpm_process_instance WHERE initiator_id = #{userId} AND deleted = 0 ORDER BY created_at DESC")
|
||||
List<BpmProcessInstance> selectMyInitiated(@Param("userId") Long userId);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.water.bpm.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.bpm.entity.BpmProcessNode;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 流程节点 Mapper
|
||||
*/
|
||||
@Mapper
|
||||
public interface BpmProcessNodeMapper extends BaseMapper<BpmProcessNode> {
|
||||
|
||||
/**
|
||||
* 查询流程定义的所有节点
|
||||
*/
|
||||
@Select("SELECT * FROM bpm_process_node WHERE definition_id = #{definitionId} AND deleted = 0 ORDER BY sort_order")
|
||||
List<BpmProcessNode> selectByDefinitionId(@Param("definitionId") Long definitionId);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.water.bpm.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.bpm.entity.BpmProcessStat;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 流程统计 Mapper
|
||||
*/
|
||||
@Mapper
|
||||
public interface BpmProcessStatMapper extends BaseMapper<BpmProcessStat> {
|
||||
|
||||
/**
|
||||
* 查询某流程的统计趋势
|
||||
*/
|
||||
@Select("SELECT * FROM bpm_process_stat WHERE definition_id = #{definitionId} AND period = #{period} " +
|
||||
"AND deleted = 0 ORDER BY stat_date DESC LIMIT #{limit}")
|
||||
List<BpmProcessStat> selectTrend(@Param("definitionId") Long definitionId,
|
||||
@Param("period") String period,
|
||||
@Param("limit") int limit);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.water.bpm.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.bpm.entity.BpmTodoTask;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 待办任务 Mapper
|
||||
*/
|
||||
@Mapper
|
||||
public interface BpmTodoTaskMapper extends BaseMapper<BpmTodoTask> {
|
||||
|
||||
/**
|
||||
* 查询待办列表
|
||||
*/
|
||||
@Select("SELECT * FROM bpm_todo_task WHERE assignee_id = #{userId} AND status = 'pending' AND deleted = 0 " +
|
||||
"ORDER BY priority DESC, received_at")
|
||||
List<BpmTodoTask> selectPendingByUserId(@Param("userId") Long userId);
|
||||
|
||||
/**
|
||||
* 查询已办列表
|
||||
*/
|
||||
@Select("SELECT * FROM bpm_todo_task WHERE assignee_id = #{userId} AND status != 'pending' AND deleted = 0 " +
|
||||
"ORDER BY completed_at DESC")
|
||||
List<BpmTodoTask> selectDoneByUserId(@Param("userId") Long userId);
|
||||
|
||||
/**
|
||||
* 统计待办数量
|
||||
*/
|
||||
@Select("SELECT COUNT(*) FROM bpm_todo_task WHERE assignee_id = #{userId} AND status = 'pending' AND deleted = 0")
|
||||
Integer countPendingByUserId(@Param("userId") Long userId);
|
||||
|
||||
/**
|
||||
* 查询超时的待办
|
||||
*/
|
||||
@Select("SELECT * FROM bpm_todo_task WHERE status = 'pending' AND deadline_at < NOW() AND deleted = 0")
|
||||
List<BpmTodoTask> selectTimeoutTasks();
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?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>
|
||||
<parent>
|
||||
<groupId>com.water</groupId>
|
||||
<artifactId>wm-parent</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>wm-dispatch</artifactId>
|
||||
<name>调度工作台</name>
|
||||
<description>调度工作台与调度业务管理模块</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.water</groupId>
|
||||
<artifactId>wm-common</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-spring-boot3-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.water.dispatch;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class DispatchApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(DispatchApplication.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.water.dispatch.controller;
|
||||
import com.water.common.core.result.R;
|
||||
import com.water.dispatch.entity.*;
|
||||
import com.water.dispatch.service.DispatchBizService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import java.util.*;
|
||||
@Tag(name="调度工作台") @RestController @RequestMapping("/dispatch") @RequiredArgsConstructor
|
||||
public class DispatchController {
|
||||
private final DispatchBizService svc;
|
||||
@GetMapping("/duty/today") public R<List<DutySchedule>> todayDuty() { return R.ok(svc.getTodayDuty()); }
|
||||
@PostMapping("/command") public R<Map<String,Object>> createCommand(@RequestBody Map<String,Object> req) { return R.ok(svc.createCommand(req)); }
|
||||
@PostMapping("/command/{cmdNo}/issue") public R<Map<String,Object>> issue(@PathVariable String cmdNo) { return R.ok(svc.issueCommand(cmdNo)); }
|
||||
@GetMapping("/command/list") public R<List<DispatchCommand>> listCommands(@RequestParam(required=false) Integer status) { return R.ok(svc.listCommands(status)); }
|
||||
@PostMapping("/work-order") public R<Map<String,Object>> createWO(@RequestBody Map<String,Object> req) { return R.ok(svc.createWorkOrder(req)); }
|
||||
@PutMapping("/work-order/{id}/status") public R<Map<String,Object>> updateWOStatus(@PathVariable Long id, @RequestParam int status) { return R.ok(svc.updateWorkOrderStatus(id, status)); }
|
||||
@PostMapping("/duty-log") public R<String> addLog(@RequestParam Long scheduleId, @RequestParam Long userId, @RequestParam String type, @RequestParam String content) { svc.addDutyLog(scheduleId,userId,type,content); return R.ok("OK"); }
|
||||
@GetMapping("/duty-log/{scheduleId}") public R<List<DutyLog>> getLogs(@PathVariable Long scheduleId) { return R.ok(svc.getDutyLogs(scheduleId)); }
|
||||
@GetMapping("/strategy") public R<List<DispatchStrategy>> listStrategies(@RequestParam(required=false) String type) { return R.ok(svc.listStrategies(type)); }
|
||||
@GetMapping("/emergency-plan") public R<List<EmergencyPlan>> listPlans(@RequestParam(required=false) String type) { return R.ok(svc.listPlans(type)); }
|
||||
@PostMapping("/emergency/simulate") public R<Map<String,Object>> simulate(@RequestParam String type, @RequestParam double lng, @RequestParam double lat) { return R.ok(svc.simulateEmergency(type,lng,lat)); }
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package com.water.dispatch.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 调度指令 - 全生命周期: 下发→接收→执行→完成→驳回
|
||||
*/
|
||||
@Data
|
||||
@TableName("disp_dispatch_command")
|
||||
public class DispatchCommand {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/** 指令编号 */
|
||||
private String commandNo;
|
||||
|
||||
/** 指令标题 */
|
||||
private String title;
|
||||
|
||||
/** 指令内容 */
|
||||
private String content;
|
||||
|
||||
/** 指令类型: NORMAL-常规 EMERGENCY-应急 MAINTENANCE-维护 */
|
||||
private String commandType;
|
||||
|
||||
/** 优先级: LOW-低 MEDIUM-中 HIGH-高 URGENT-紧急 */
|
||||
private String priority;
|
||||
|
||||
/** 下发人ID */
|
||||
private Long issuerId;
|
||||
|
||||
/** 下发人姓名 */
|
||||
private String issuerName;
|
||||
|
||||
/** 接收人ID */
|
||||
private Long receiverId;
|
||||
|
||||
/** 接收人姓名 */
|
||||
private String receiverName;
|
||||
|
||||
/** 关联设施ID */
|
||||
private Long facilityId;
|
||||
|
||||
/** 状态: ISSUED-下发 RECEIVED-接收 EXECUTING-执行 COMPLETED-完成 REJECTED-驳回 CANCELLED-取消 */
|
||||
private String status;
|
||||
|
||||
/** 下发时间 */
|
||||
private LocalDateTime issuedAt;
|
||||
|
||||
/** 接收时间 */
|
||||
private LocalDateTime receivedAt;
|
||||
|
||||
/** 执行开始时间 */
|
||||
private LocalDateTime executedAt;
|
||||
|
||||
/** 完成时间 */
|
||||
private LocalDateTime completedAt;
|
||||
|
||||
/** 驳回原因 */
|
||||
private String rejectReason;
|
||||
|
||||
/** 执行结果 */
|
||||
private String executeResult;
|
||||
|
||||
/** 截止时间 */
|
||||
private LocalDateTime deadline;
|
||||
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
private LocalDateTime updatedAt;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.water.dispatch.entity;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data; import java.time.LocalDateTime;
|
||||
@Data @TableName("dispatch_strategy")
|
||||
public class DispatchStrategy {
|
||||
@TableId(type = IdType.AUTO) private Long id;
|
||||
private String name, type, description, ruleConfig;
|
||||
private Integer status;
|
||||
@TableField(fill=FieldFill.INSERT) private LocalDateTime createdTime;
|
||||
@TableField(fill=FieldFill.INSERT_UPDATE) private LocalDateTime updatedTime;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.water.dispatch.entity;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data; import java.time.LocalDateTime;
|
||||
@Data @TableName("dispatch_duty_log")
|
||||
public class DutyLog {
|
||||
@TableId(type = IdType.AUTO) private Long id;
|
||||
private Long scheduleId, userId;
|
||||
private String logType, content, attachments;
|
||||
@TableField(fill=FieldFill.INSERT) private LocalDateTime createdTime;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.water.dispatch.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
|
||||
/**
|
||||
* 值班安排
|
||||
*/
|
||||
@Data
|
||||
@TableName("disp_duty_schedule")
|
||||
public class DutySchedule {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/** 值班人员ID */
|
||||
private Long userId;
|
||||
|
||||
/** 值班人员姓名 */
|
||||
private String userName;
|
||||
|
||||
/** 值班日期 */
|
||||
private LocalDate dutyDate;
|
||||
|
||||
/** 班次类型: DAY-白班 NIGHT-夜班 FULL-全天 */
|
||||
private String shiftType;
|
||||
|
||||
/** 开始时间 */
|
||||
private LocalTime startTime;
|
||||
|
||||
/** 结束时间 */
|
||||
private LocalTime endTime;
|
||||
|
||||
/** 状态: 0-待值班 1-值班中 2-已完成 */
|
||||
private Integer status;
|
||||
|
||||
/** 备注 */
|
||||
private String remark;
|
||||
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
private LocalDateTime updatedAt;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.water.dispatch.entity;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data; import java.time.LocalDateTime;
|
||||
@Data @TableName("dispatch_emergency_plan")
|
||||
public class EmergencyPlan {
|
||||
@TableId(type = IdType.AUTO) private Long id;
|
||||
private String planNo, name, type, content, resourceConfig;
|
||||
private Integer status; private Long creatorId;
|
||||
@TableField(fill=FieldFill.INSERT) private LocalDateTime createdTime;
|
||||
@TableField(fill=FieldFill.INSERT_UPDATE) private LocalDateTime updatedTime;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.water.dispatch.entity;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data; import java.time.LocalDateTime;
|
||||
@Data @TableName("dispatch_work_order")
|
||||
public class WorkOrder {
|
||||
@TableId(type = IdType.AUTO) private Long id;
|
||||
private String orderNo, title, description, type, priority;
|
||||
private Integer status; private Long assigneeId, creatorId;
|
||||
private LocalDateTime deadline, completedAt;
|
||||
@TableField(fill=FieldFill.INSERT) private LocalDateTime createdTime;
|
||||
@TableField(fill=FieldFill.INSERT_UPDATE) private LocalDateTime updatedTime;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.water.dispatch.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.dispatch.entity.DispatchCommand;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@Mapper public interface DispatchCommandMapper extends BaseMapper<DispatchCommand> {}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.water.dispatch.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.dispatch.entity.DispatchStrategy;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@Mapper public interface DispatchStrategyMapper extends BaseMapper<DispatchStrategy> {}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.water.dispatch.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.dispatch.entity.DutyLog;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@Mapper public interface DutyLogMapper extends BaseMapper<DutyLog> {}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.water.dispatch.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.dispatch.entity.DutySchedule;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@Mapper public interface DutyScheduleMapper extends BaseMapper<DutySchedule> {}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.water.dispatch.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.dispatch.entity.EmergencyPlan;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@Mapper public interface EmergencyPlanMapper extends BaseMapper<EmergencyPlan> {}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.water.dispatch.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.dispatch.entity.WorkOrder;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@Mapper public interface WorkOrderMapper extends BaseMapper<WorkOrder> {}
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.water.dispatch.service;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.water.dispatch.entity.*;
|
||||
import com.water.dispatch.mapper.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import java.time.*; import java.util.*;
|
||||
@Service @RequiredArgsConstructor
|
||||
public class DispatchBizService {
|
||||
private final DutyScheduleMapper dutyMapper;
|
||||
private final DispatchCommandMapper cmdMapper;
|
||||
private final WorkOrderMapper woMapper;
|
||||
private final DutyLogMapper logMapper;
|
||||
private final DispatchStrategyMapper stratMapper;
|
||||
private final EmergencyPlanMapper planMapper;
|
||||
|
||||
public List<DutySchedule> getTodayDuty() {
|
||||
return dutyMapper.selectList(new LambdaQueryWrapper<DutySchedule>()
|
||||
.eq(DutySchedule::getDutyDate, LocalDate.now()));
|
||||
}
|
||||
public Map<String,Object> createCommand(Map<String,Object> req) {
|
||||
DispatchCommand c = new DispatchCommand();
|
||||
c.setCmdNo("CMD-" + System.currentTimeMillis());
|
||||
c.setTitle((String)req.get("title")); c.setContent((String)req.get("content"));
|
||||
c.setType((String)req.getOrDefault("type","常规")); c.setStatus(0);
|
||||
cmdMapper.insert(c);
|
||||
return Map.of("id",c.getId(),"cmdNo",c.getCmdNo());
|
||||
}
|
||||
public Map<String,Object> issueCommand(String cmdNo) {
|
||||
DispatchCommand c = cmdMapper.selectOne(new LambdaQueryWrapper<DispatchCommand>()
|
||||
.eq(DispatchCommand::getCmdNo, cmdNo));
|
||||
if(c==null) throw new RuntimeException("指令不存在");
|
||||
c.setStatus(1); c.setIssuedTime(LocalDateTime.now());
|
||||
cmdMapper.updateById(c);
|
||||
return Map.of("cmdNo",cmdNo,"status",1);
|
||||
}
|
||||
public List<DispatchCommand> listCommands(Integer status) {
|
||||
return cmdMapper.selectList(new LambdaQueryWrapper<DispatchCommand>()
|
||||
.eq(status!=null, DispatchCommand::getStatus, status));
|
||||
}
|
||||
public Map<String,Object> createWorkOrder(Map<String,Object> req) {
|
||||
WorkOrder w = new WorkOrder();
|
||||
w.setOrderNo("WO-" + System.currentTimeMillis());
|
||||
w.setTitle((String)req.get("title")); w.setDescription((String)req.get("description"));
|
||||
w.setType((String)req.getOrDefault("type","维修")); w.setStatus(0);
|
||||
w.setPriority((String)req.getOrDefault("priority","中"));
|
||||
woMapper.insert(w);
|
||||
return Map.of("id",w.getId(),"orderNo",w.getOrderNo());
|
||||
}
|
||||
public Map<String,Object> updateWorkOrderStatus(Long id, int status) {
|
||||
WorkOrder w = woMapper.selectById(id);
|
||||
if(w==null) throw new RuntimeException("工单不存在");
|
||||
w.setStatus(status);
|
||||
if(status==2) w.setCompletedAt(LocalDateTime.now());
|
||||
woMapper.updateById(w);
|
||||
return Map.of("id",id,"status",status);
|
||||
}
|
||||
public void addDutyLog(Long scheduleId, Long userId, String type, String content) {
|
||||
DutyLog l = new DutyLog();
|
||||
l.setScheduleId(scheduleId); l.setUserId(userId);
|
||||
l.setLogType(type); l.setContent(content);
|
||||
logMapper.insert(l);
|
||||
}
|
||||
public List<DutyLog> getDutyLogs(Long scheduleId) {
|
||||
return logMapper.selectList(new LambdaQueryWrapper<DutyLog>()
|
||||
.eq(DutyLog::getScheduleId, scheduleId));
|
||||
}
|
||||
public List<DispatchStrategy> listStrategies(String type) {
|
||||
return stratMapper.selectList(new LambdaQueryWrapper<DispatchStrategy>()
|
||||
.eq(type!=null, DispatchStrategy::getType, type));
|
||||
}
|
||||
public List<EmergencyPlan> listPlans(String type) {
|
||||
return planMapper.selectList(new LambdaQueryWrapper<EmergencyPlan>()
|
||||
.eq(type!=null, EmergencyPlan::getType, type));
|
||||
}
|
||||
public Map<String,Object> simulateEmergency(String type, double lng, double lat) {
|
||||
return Map.of("type",type,"lng",lng,"lat",lat,
|
||||
"affectedArea","半径500米","affectedUsers",120,
|
||||
"estimatedDuration","4小时");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
server:
|
||||
port: 9050
|
||||
spring:
|
||||
application:
|
||||
name: wm-dispatch
|
||||
datasource:
|
||||
url: jdbc:postgresql://localhost:5432/water_dispatch
|
||||
username: water
|
||||
password: water123
|
||||
mybatis-plus:
|
||||
configuration:
|
||||
map-underscore-to-camel-case: true
|
||||
global-config:
|
||||
db-config:
|
||||
id-type: auto
|
||||
@@ -0,0 +1,33 @@
|
||||
CREATE TABLE IF NOT EXISTS dispatch_duty_schedule (
|
||||
id BIGSERIAL PRIMARY KEY, user_id BIGINT, user_name VARCHAR(50),
|
||||
duty_date DATE, start_time TIME, end_time TIME, area VARCHAR(100),
|
||||
created_time TIMESTAMP DEFAULT NOW(), updated_time TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS dispatch_command (
|
||||
id BIGSERIAL PRIMARY KEY, cmd_no VARCHAR(50) UNIQUE, title VARCHAR(200),
|
||||
content TEXT, type VARCHAR(20), status INT DEFAULT 0,
|
||||
issued_time TIMESTAMP, completed_time TIMESTAMP,
|
||||
created_time TIMESTAMP DEFAULT NOW(), updated_time TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS dispatch_work_order (
|
||||
id BIGSERIAL PRIMARY KEY, order_no VARCHAR(50) UNIQUE, title VARCHAR(200),
|
||||
description TEXT, type VARCHAR(20), priority VARCHAR(10), status INT DEFAULT 0,
|
||||
assignee_id BIGINT, creator_id BIGINT, deadline TIMESTAMP, completed_at TIMESTAMP,
|
||||
created_time TIMESTAMP DEFAULT NOW(), updated_time TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS dispatch_duty_log (
|
||||
id BIGSERIAL PRIMARY KEY, schedule_id BIGINT, user_id BIGINT,
|
||||
log_type VARCHAR(20), content TEXT, attachments TEXT,
|
||||
created_time TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS dispatch_strategy (
|
||||
id BIGSERIAL PRIMARY KEY, name VARCHAR(100), type VARCHAR(20),
|
||||
description TEXT, rule_config TEXT, status INT DEFAULT 1,
|
||||
created_time TIMESTAMP DEFAULT NOW(), updated_time TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS dispatch_emergency_plan (
|
||||
id BIGSERIAL PRIMARY KEY, plan_no VARCHAR(50) UNIQUE, name VARCHAR(100),
|
||||
type VARCHAR(20), content TEXT, resource_config TEXT,
|
||||
status INT DEFAULT 0, creator_id BIGINT,
|
||||
created_time TIMESTAMP DEFAULT NOW(), updated_time TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
@@ -0,0 +1,45 @@
|
||||
<?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>
|
||||
<parent><groupId>com.water</groupId><artifactId>wm-parent</artifactId><version>1.0.0-SNAPSHOT</version></parent>
|
||||
<artifactId>wm-mobile-app</artifactId>
|
||||
<name>wm-mobile-app</name>
|
||||
<description>移动APP三合一后端服务层 - 供水/巡检/营业收费统一入口</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency><groupId>com.water</groupId><artifactId>wm-common</artifactId></dependency>
|
||||
|
||||
<!-- Web -->
|
||||
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
|
||||
|
||||
<!-- Nacos Discovery -->
|
||||
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency>
|
||||
|
||||
<!-- MyBatis-Plus -->
|
||||
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-spring-boot3-starter</artifactId></dependency>
|
||||
|
||||
<!-- Sa-Token -->
|
||||
<dependency><groupId>cn.dev33</groupId><artifactId>sa-token-spring-boot3-starter</artifactId></dependency>
|
||||
|
||||
<!-- PostgreSQL -->
|
||||
<dependency><groupId>org.postgresql</groupId><artifactId>postgresql</artifactId></dependency>
|
||||
|
||||
<!-- Knife4j Swagger -->
|
||||
<dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId></dependency>
|
||||
|
||||
<!-- Test -->
|
||||
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.water.mobile;
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
|
||||
@SpringBootApplication
|
||||
@ComponentScan(basePackages = {"com.water.mobile", "com.water.common"})
|
||||
@MapperScan("com.water.mobile.mapper")
|
||||
public class MobileApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(MobileApplication.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.water.mobile.controller;
|
||||
import com.water.common.core.result.R;
|
||||
import com.water.mobile.entity.PushNotification;
|
||||
import com.water.mobile.service.MobileApiService;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import java.util.*;
|
||||
@Tag(name="移动APP") @RestController @RequestMapping("/mobile") @RequiredArgsConstructor
|
||||
public class MobileController {
|
||||
private final MobileApiService svc;
|
||||
@PostMapping("/login") public R<Map<String,Object>> login(@RequestParam String username, @RequestParam String password, @RequestParam String appModule) { return R.ok(svc.login(username, password, appModule)); }
|
||||
@GetMapping("/water/overview") public R<Map<String,Object>> waterOverview() { return R.ok(svc.getWaterOverview()); }
|
||||
@GetMapping("/patrol/tasks") public R<List<Map<String,Object>>> patrolTasks(@RequestParam Long userId) { return R.ok(svc.getPatrolTasks(userId)); }
|
||||
@GetMapping("/billing/summary") public R<Map<String,Object>> billingSummary(@RequestParam Long userId) { return R.ok(svc.getBillingSummary(userId)); }
|
||||
@GetMapping("/notifications") public R<List<PushNotification>> notifications(@RequestParam Long userId, @RequestParam(required=false) Boolean unreadOnly) { return R.ok(svc.getNotifications(userId, unreadOnly)); }
|
||||
@PutMapping("/notifications/{id}/read") public R<String> markRead(@PathVariable Long id) { svc.markRead(id); return R.ok("OK"); }
|
||||
@PostMapping("/notifications/send") public R<Long> send(@RequestParam Long userId, @RequestParam String title, @RequestParam String content, @RequestParam String type, @RequestParam String appModule) { return R.ok(svc.sendNotification(userId, title, content, type, appModule)); }
|
||||
@GetMapping("/update/check") public R<Map<String,Object>> checkUpdate(@RequestParam String appModule, @RequestParam String currentVersion) { return R.ok(svc.checkUpdate(appModule, currentVersion)); }
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.water.mobile.entity;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data; import java.time.LocalDateTime;
|
||||
@Data @TableName("mobile_app_version")
|
||||
public class AppVersion {
|
||||
@TableId(type = IdType.AUTO) private Long id;
|
||||
private String appModule, versionNo, downloadUrl, changelog;
|
||||
private Integer forceUpdate; // 0否 1是
|
||||
private Integer status; // 0草稿 1已发布
|
||||
@TableField(fill=FieldFill.INSERT) private LocalDateTime createdTime;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.water.mobile.entity;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data; import java.time.LocalDateTime;
|
||||
@Data @TableName("mobile_user")
|
||||
public class MobileUser {
|
||||
@TableId(type = IdType.AUTO) private Long id;
|
||||
private String username, password, realName, phone, avatar;
|
||||
private String appModule; // 供水/巡检/收费
|
||||
private Long sysUserId; // 关联系统用户ID
|
||||
private Integer status;
|
||||
@TableField(fill=FieldFill.INSERT) private LocalDateTime createdTime;
|
||||
private LocalDateTime lastLoginTime;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.water.mobile.entity;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data; import java.time.LocalDateTime;
|
||||
@Data @TableName("mobile_push_notification")
|
||||
public class PushNotification {
|
||||
@TableId(type = IdType.AUTO) private Long id;
|
||||
private Long userId; private String title, content, type;
|
||||
private String appModule; // 供水/巡检/收费/系统
|
||||
private Integer isRead; // 0未读 1已读
|
||||
private String extraData;
|
||||
@TableField(fill=FieldFill.INSERT) private LocalDateTime createdTime;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.water.mobile.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.mobile.entity.AppVersion;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@Mapper public interface AppVersionMapper extends BaseMapper<AppVersion> {}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.water.mobile.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.mobile.entity.MobileUser;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@Mapper public interface MobileUserMapper extends BaseMapper<MobileUser> {}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.water.mobile.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.mobile.entity.PushNotification;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@Mapper public interface PushNotificationMapper extends BaseMapper<PushNotification> {}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.water.mobile.service;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.water.mobile.entity.*;
|
||||
import com.water.mobile.mapper.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import java.util.*;
|
||||
@Service @RequiredArgsConstructor
|
||||
public class MobileApiService {
|
||||
private final MobileUserMapper userMapper;
|
||||
private final PushNotificationMapper pushMapper;
|
||||
private final AppVersionMapper verMapper;
|
||||
|
||||
public Map<String,Object> login(String username, String password, String appModule) {
|
||||
MobileUser u = userMapper.selectOne(new LambdaQueryWrapper<MobileUser>()
|
||||
.eq(MobileUser::getUsername, username)
|
||||
.eq(MobileUser::getAppModule, appModule));
|
||||
if (u == null || !u.getPassword().equals(password)) throw new RuntimeException("登录失败");
|
||||
return Map.of("userId", u.getId(), "realName", u.getRealName(),
|
||||
"appModule", u.getAppModule(), "token", "mock-token-" + u.getId());
|
||||
}
|
||||
// 供水API聚合
|
||||
public Map<String,Object> getWaterOverview() {
|
||||
return Map.of("todaySupply", 12500.0, "yesterdaySupply", 11800.0,
|
||||
"waterQuality", "合格", "alertCount", 3, "deviceOnlineRate", 0.95);
|
||||
}
|
||||
// 巡检API聚合
|
||||
public List<Map<String,Object>> getPatrolTasks(Long userId) {
|
||||
return List.of(
|
||||
Map.of("id", 1L, "taskName", "主管网巡检A线", "status", "待执行", "deadline", "今日18:00"),
|
||||
Map.of("id", 2L, "taskName", "消防栓检查-区域B", "status", "进行中", "deadline", "今日17:00")
|
||||
);
|
||||
}
|
||||
// 收费API聚合
|
||||
public Map<String,Object> getBillingSummary(Long userId) {
|
||||
return Map.of("unpaidCount", 2, "totalAmount", 156.80,
|
||||
"recentBills", List.of(
|
||||
Map.of("period", "2025-01", "amount", 78.40, "status", "未缴费"),
|
||||
Map.of("period", "2024-12", "amount", 82.50, "status", "已缴费")
|
||||
));
|
||||
}
|
||||
// 消息通知
|
||||
public List<PushNotification> getNotifications(Long userId, Boolean unreadOnly) {
|
||||
LambdaQueryWrapper<PushNotification> w = new LambdaQueryWrapper<PushNotification>()
|
||||
.eq(PushNotification::getUserId, userId);
|
||||
if (Boolean.TRUE.equals(unreadOnly)) w.eq(PushNotification::getIsRead, 0);
|
||||
return pushMapper.selectList(w.orderByDesc(PushNotification::getCreatedTime));
|
||||
}
|
||||
public void markRead(Long notificationId) {
|
||||
PushNotification n = pushMapper.selectById(notificationId);
|
||||
if (n != null) { n.setIsRead(1); pushMapper.updateById(n); }
|
||||
}
|
||||
public Long sendNotification(Long userId, String title, String content, String type, String appModule) {
|
||||
PushNotification n = new PushNotification();
|
||||
n.setUserId(userId); n.setTitle(title); n.setContent(content);
|
||||
n.setType(type); n.setAppModule(appModule); n.setIsRead(0);
|
||||
pushMapper.insert(n);
|
||||
return n.getId();
|
||||
}
|
||||
// 版本检查
|
||||
public Map<String,Object> checkUpdate(String appModule, String currentVersion) {
|
||||
AppVersion v = verMapper.selectOne(new LambdaQueryWrapper<AppVersion>()
|
||||
.eq(AppVersion::getAppModule, appModule)
|
||||
.eq(AppVersion::getStatus, 1)
|
||||
.orderByDesc(AppVersion::getCreatedTime).last("LIMIT 1"));
|
||||
if (v == null || v.getVersionNo().equals(currentVersion))
|
||||
return Map.of("hasUpdate", false);
|
||||
return Map.of("hasUpdate", true, "versionNo", v.getVersionNo(),
|
||||
"downloadUrl", v.getDownloadUrl(), "changelog", v.getChangelog(),
|
||||
"forceUpdate", v.getForceUpdate() == 1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
server:
|
||||
port: 9060
|
||||
spring:
|
||||
application:
|
||||
name: wm-mobile-app
|
||||
datasource:
|
||||
url: jdbc:postgresql://localhost:5432/water_mobile
|
||||
username: water
|
||||
password: water123
|
||||
mybatis-plus:
|
||||
configuration:
|
||||
map-underscore-to-camel-case: true
|
||||
global-config:
|
||||
db-config:
|
||||
id-type: auto
|
||||
@@ -0,0 +1,18 @@
|
||||
CREATE TABLE IF NOT EXISTS mobile_user (
|
||||
id BIGSERIAL PRIMARY KEY, username VARCHAR(50), password VARCHAR(200),
|
||||
real_name VARCHAR(50), phone VARCHAR(20), avatar VARCHAR(500),
|
||||
app_module VARCHAR(20), sys_user_id BIGINT, status INT DEFAULT 1,
|
||||
created_time TIMESTAMP DEFAULT NOW(), last_login_time TIMESTAMP
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS mobile_push_notification (
|
||||
id BIGSERIAL PRIMARY KEY, user_id BIGINT, title VARCHAR(200),
|
||||
content TEXT, type VARCHAR(30), app_module VARCHAR(20),
|
||||
is_read INT DEFAULT 0, extra_data TEXT,
|
||||
created_time TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS mobile_app_version (
|
||||
id BIGSERIAL PRIMARY KEY, app_module VARCHAR(20), version_no VARCHAR(20),
|
||||
download_url VARCHAR(500), changelog TEXT,
|
||||
force_update INT DEFAULT 0, status INT DEFAULT 0,
|
||||
created_time TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.water.production.entity;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data; import java.time.LocalDateTime;
|
||||
@Data @TableName("prod_alert_record")
|
||||
public class AlertRecord {
|
||||
@TableId(type = IdType.AUTO) private Long id;
|
||||
private String deviceId, area, level; // 一般/重要/紧急
|
||||
private String alertType, description;
|
||||
private Integer status; // 0活跃 1已确认 2已处理
|
||||
private Long confirmedBy, handledBy;
|
||||
@TableField(fill=FieldFill.INSERT) private LocalDateTime createdTime;
|
||||
private LocalDateTime confirmedTime, handledTime;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.water.production.entity;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data; import java.time.LocalDateTime;
|
||||
@Data @TableName("prod_device_status")
|
||||
public class DeviceStatus {
|
||||
@TableId(type = IdType.AUTO) private Long id;
|
||||
private String deviceId, deviceName, deviceType;
|
||||
private String area; private Integer status; // 0离线 1在线 2故障
|
||||
private Double lng, lat;
|
||||
private LocalDateTime lastOnlineTime;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.water.production.entity;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data; import java.time.LocalDateTime;
|
||||
@Data @TableName("prod_flow_pressure")
|
||||
public class FlowPressureMonitor {
|
||||
@TableId(type = IdType.AUTO) private Long id;
|
||||
private String deviceId, area, positionType; // 流量/压力/液位
|
||||
private Double value; private String unit;
|
||||
private Double lng, lat;
|
||||
@TableField(fill=FieldFill.INSERT) private LocalDateTime createdTime;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.water.production.entity;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
@Data @TableName("prod_video_camera")
|
||||
public class VideoCamera {
|
||||
@TableId(type = IdType.AUTO) private Long id;
|
||||
private String cameraId, name, area;
|
||||
private String streamUrl; private Integer status; // 0离线 1在线
|
||||
private Double lng, lat;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.water.production.entity;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data; import java.time.LocalDateTime;
|
||||
@Data @TableName("prod_water_quality")
|
||||
public class WaterQualityRecord {
|
||||
@TableId(type = IdType.AUTO) private Long id;
|
||||
private String station, positionType; // 原水/出厂水/末梢水
|
||||
private Double turbidity, ph, residualChlorine, color, odor;
|
||||
private String result; // 合格/不合格
|
||||
@TableField(fill=FieldFill.INSERT) private LocalDateTime createdTime;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.water.production.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.production.entity.AlertRecord;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@Mapper public interface AlertRecordMapper extends BaseMapper<AlertRecord> {}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.water.production.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.production.entity.DeviceStatus;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@Mapper public interface DeviceStatusMapper extends BaseMapper<DeviceStatus> {}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.water.production.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.production.entity.FlowPressureMonitor;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@Mapper public interface FlowPressureMonitorMapper extends BaseMapper<FlowPressureMonitor> {}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.water.production.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.production.entity.VideoCamera;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@Mapper public interface VideoCameraMapper extends BaseMapper<VideoCamera> {}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.water.production.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.production.entity.WaterQualityRecord;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@Mapper public interface WaterQualityRecordMapper extends BaseMapper<WaterQualityRecord> {}
|
||||
@@ -0,0 +1,30 @@
|
||||
CREATE TABLE IF NOT EXISTS prod_water_quality (
|
||||
id BIGSERIAL PRIMARY KEY, station VARCHAR(100), position_type VARCHAR(20),
|
||||
turbidity DOUBLE PRECISION, ph DOUBLE PRECISION,
|
||||
residual_chlorine DOUBLE PRECISION, color DOUBLE PRECISION, odor DOUBLE PRECISION,
|
||||
result VARCHAR(20), created_time TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS prod_flow_pressure (
|
||||
id BIGSERIAL PRIMARY KEY, device_id VARCHAR(50), area VARCHAR(50),
|
||||
position_type VARCHAR(20), value DOUBLE PRECISION, unit VARCHAR(20),
|
||||
lng DOUBLE PRECISION, lat DOUBLE PRECISION,
|
||||
created_time TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS prod_device_status (
|
||||
id BIGSERIAL PRIMARY KEY, device_id VARCHAR(50), device_name VARCHAR(100),
|
||||
device_type VARCHAR(30), area VARCHAR(50), status INT DEFAULT 0,
|
||||
lng DOUBLE PRECISION, lat DOUBLE PRECISION,
|
||||
last_online_time TIMESTAMP
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS prod_alert_record (
|
||||
id BIGSERIAL PRIMARY KEY, device_id VARCHAR(50), area VARCHAR(50),
|
||||
level VARCHAR(10), alert_type VARCHAR(30), description TEXT,
|
||||
status INT DEFAULT 0, confirmed_by BIGINT, handled_by BIGINT,
|
||||
created_time TIMESTAMP DEFAULT NOW(),
|
||||
confirmed_time TIMESTAMP, handled_time TIMESTAMP
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS prod_video_camera (
|
||||
id BIGSERIAL PRIMARY KEY, camera_id VARCHAR(50), name VARCHAR(100),
|
||||
area VARCHAR(50), stream_url VARCHAR(500), status INT DEFAULT 0,
|
||||
lng DOUBLE PRECISION, lat DOUBLE PRECISION
|
||||
);
|
||||
@@ -0,0 +1,50 @@
|
||||
<?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>
|
||||
<parent>
|
||||
<groupId>com.water</groupId>
|
||||
<artifactId>wm-parent</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>wm-system</artifactId>
|
||||
<name>wm-system</name>
|
||||
<description>文档管理与系统管理模块</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.water</groupId>
|
||||
<artifactId>wm-common</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-spring-boot3-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.minio</groupId>
|
||||
<artifactId>minio</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.water.system;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
|
||||
@SpringBootApplication(scanBasePackages = "com.water")
|
||||
@MapperScan("com.water.system.mapper")
|
||||
public class SystemApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SystemApplication.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.water.system.controller;
|
||||
import com.water.common.core.result.R;
|
||||
import com.water.system.entity.*;
|
||||
import com.water.system.service.DocService;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import java.util.*;
|
||||
@Tag(name="文档管理") @RestController @RequestMapping("/system/doc") @RequiredArgsConstructor
|
||||
public class DocController {
|
||||
private final DocService svc;
|
||||
@GetMapping("/list") public R<List<Document>> list(@RequestParam(required=false) String categoryId, @RequestParam(required=false) String keyword) { return R.ok(svc.listDocs(categoryId, keyword)); }
|
||||
@GetMapping("/{id}") public R<Document> get(@PathVariable Long id) { return R.ok(svc.getDoc(id)); }
|
||||
@PostMapping public R<Long> create(@RequestBody Map<String,Object> req) { return R.ok(svc.createDoc(req)); }
|
||||
@PutMapping("/{id}") public R<String> update(@PathVariable Long id, @RequestBody Map<String,Object> req) { svc.updateDoc(id, req); return R.ok("OK"); }
|
||||
@DeleteMapping("/{id}") public R<String> delete(@PathVariable Long id) { svc.deleteDoc(id); return R.ok("OK"); }
|
||||
@GetMapping("/category/list") public R<List<DocumentCategory>> categories() { return R.ok(svc.listCategories()); }
|
||||
@GetMapping("/{docId}/versions") public R<List<DocumentVersion>> versions(@PathVariable Long docId) { return R.ok(svc.getVersions(docId)); }
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.water.system.controller;
|
||||
import com.water.common.core.result.R;
|
||||
import com.water.system.entity.*;
|
||||
import com.water.system.service.SysService;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import java.util.*;
|
||||
@Tag(name="系统管理") @RestController @RequestMapping("/system") @RequiredArgsConstructor
|
||||
public class SysController {
|
||||
private final SysService svc;
|
||||
@GetMapping("/role/list") public R<List<SysRole>> roles() { return R.ok(svc.listRoles()); }
|
||||
@PostMapping("/role") public R<Long> createRole(@RequestBody Map<String,Object> req) { return R.ok(svc.createRole(req)); }
|
||||
@GetMapping("/user/list") public R<List<SysUser>> users(@RequestParam(required=false) Integer status) { return R.ok(svc.listUsers(status)); }
|
||||
@PostMapping("/user") public R<Long> createUser(@RequestBody Map<String,Object> req) { return R.ok(svc.createUser(req)); }
|
||||
@PutMapping("/user/{id}/status") public R<String> updateUserStatus(@PathVariable Long id, @RequestParam int status) { svc.updateUserStatus(id, status); return R.ok("OK"); }
|
||||
@GetMapping("/menu/list") public R<List<SysMenu>> menus() { return R.ok(svc.listMenus()); }
|
||||
@GetMapping("/dept/list") public R<List<SysDepartment>> depts() { return R.ok(svc.listDepts()); }
|
||||
@PostMapping("/dept") public R<Long> createDept(@RequestBody Map<String,Object> req) { return R.ok(svc.createDept(req)); }
|
||||
@GetMapping("/log/list") public R<List<SysLog>> logs(@RequestParam(required=false) String logType, @RequestParam(required=false) String username) { return R.ok(svc.listLogs(logType, username)); }
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.water.system.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 文档实体
|
||||
*/
|
||||
@Data
|
||||
@TableName("doc_document")
|
||||
public class Document {
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/** 文档名称 */
|
||||
private String name;
|
||||
|
||||
/** 文档原始文件名 */
|
||||
private String originalName;
|
||||
|
||||
/** 文档大小(字节) */
|
||||
private Long fileSize;
|
||||
|
||||
/** 文件类型 */
|
||||
private String fileType;
|
||||
|
||||
/** 存储路径 */
|
||||
private String storagePath;
|
||||
|
||||
/** 文档分类ID */
|
||||
private Long categoryId;
|
||||
|
||||
/** 文档描述 */
|
||||
private String description;
|
||||
|
||||
/** 当前版本号 */
|
||||
private Integer currentVersion;
|
||||
|
||||
/** 上传者ID */
|
||||
private Long uploaderId;
|
||||
|
||||
/** 下载次数 */
|
||||
private Integer downloadCount;
|
||||
|
||||
/** 状态: 0-草稿 1-已发布 2-已归档 */
|
||||
private Integer status;
|
||||
|
||||
/** 权限级别: 0-公开 1-内部 2-机密 */
|
||||
private Integer permissionLevel;
|
||||
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.water.system.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 文档分类实体
|
||||
*/
|
||||
@Data
|
||||
@TableName("doc_category")
|
||||
public class DocumentCategory {
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/** 分类名称 */
|
||||
private String name;
|
||||
|
||||
/** 父分类ID */
|
||||
private Long parentId;
|
||||
|
||||
/** 排序号 */
|
||||
private Integer sortOrder;
|
||||
|
||||
/** 分类描述 */
|
||||
private String description;
|
||||
|
||||
@TableLogic
|
||||
private Integer deleted;
|
||||
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.water.system.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 文档版本实体
|
||||
*/
|
||||
@Data
|
||||
@TableName("doc_version")
|
||||
public class DocumentVersion {
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/** 文档ID */
|
||||
private Long documentId;
|
||||
|
||||
/** 版本号 */
|
||||
private Integer version;
|
||||
|
||||
/** 版本描述 */
|
||||
private String description;
|
||||
|
||||
/** 文件存储路径 */
|
||||
private String storagePath;
|
||||
|
||||
/** 文件大小 */
|
||||
private Long fileSize;
|
||||
|
||||
/** 操作人ID */
|
||||
private Long operatorId;
|
||||
|
||||
private LocalDateTime createdAt;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.water.system.entity;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
@Data @TableName("sys_department")
|
||||
public class SysDepartment {
|
||||
@TableId(type = IdType.AUTO) private Long id;
|
||||
private Long parentId; private String deptName, leader, phone;
|
||||
private Integer sort, status;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.water.system.entity;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data; import java.time.LocalDateTime;
|
||||
@Data @TableName("sys_log")
|
||||
public class SysLog {
|
||||
@TableId(type = IdType.AUTO) private Long id;
|
||||
private Long userId; private String username, logType, module, action;
|
||||
private String requestUrl, requestMethod, requestParams, responseResult;
|
||||
private String ip; private Long duration;
|
||||
@TableField(fill=FieldFill.INSERT) private LocalDateTime createdTime;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.water.system.entity;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data;
|
||||
@Data @TableName("sys_menu")
|
||||
public class SysMenu {
|
||||
@TableId(type = IdType.AUTO) private Long id;
|
||||
private Long parentId; private String name, path, icon, component, permission;
|
||||
private Integer type, sort, visible, status;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.water.system.entity;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data; import java.time.LocalDateTime;
|
||||
@Data @TableName("sys_role")
|
||||
public class SysRole {
|
||||
@TableId(type = IdType.AUTO) private Long id;
|
||||
private String roleCode, roleName, description;
|
||||
private Integer status, sort;
|
||||
@TableField(fill=FieldFill.INSERT) private LocalDateTime createdTime;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.water.system.entity;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Data; import java.time.LocalDateTime;
|
||||
@Data @TableName("sys_user")
|
||||
public class SysUser {
|
||||
@TableId(type = IdType.AUTO) private Long id;
|
||||
private String username, password, realName, phone, email;
|
||||
private Long deptId; private String avatar;
|
||||
private Integer status; // 0停用 1正常
|
||||
@TableField(fill=FieldFill.INSERT) private LocalDateTime createdTime;
|
||||
@TableField(fill=FieldFill.INSERT_UPDATE) private LocalDateTime updatedTime;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.water.system.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.system.entity.DocumentCategory;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@Mapper public interface DocumentCategoryMapper extends BaseMapper<DocumentCategory> {}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.water.system.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.system.entity.Document;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@Mapper public interface DocumentMapper extends BaseMapper<Document> {}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.water.system.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.system.entity.DocumentVersion;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@Mapper public interface DocumentVersionMapper extends BaseMapper<DocumentVersion> {}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.water.system.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.system.entity.SysDepartment;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@Mapper public interface SysDepartmentMapper extends BaseMapper<SysDepartment> {}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.water.system.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.system.entity.SysLog;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@Mapper public interface SysLogMapper extends BaseMapper<SysLog> {}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.water.system.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.system.entity.SysMenu;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@Mapper public interface SysMenuMapper extends BaseMapper<SysMenu> {}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.water.system.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.system.entity.SysRole;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@Mapper public interface SysRoleMapper extends BaseMapper<SysRole> {}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.water.system.mapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.water.system.entity.SysUser;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
@Mapper public interface SysUserMapper extends BaseMapper<SysUser> {}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.water.system.service;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.water.system.entity.*;
|
||||
import com.water.system.mapper.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import java.util.*;
|
||||
@Service @RequiredArgsConstructor
|
||||
public class DocService {
|
||||
private final DocumentMapper docMapper;
|
||||
private final DocumentCategoryMapper catMapper;
|
||||
private final DocumentVersionMapper verMapper;
|
||||
|
||||
public List<Document> listDocs(String categoryId, String keyword) {
|
||||
LambdaQueryWrapper<Document> w = new LambdaQueryWrapper<>();
|
||||
if (categoryId != null) w.eq(Document::getCategoryId, categoryId);
|
||||
if (keyword != null) w.like(Document::getName, keyword);
|
||||
return docMapper.selectList(w);
|
||||
}
|
||||
public Document getDoc(Long id) { return docMapper.selectById(id); }
|
||||
public Long createDoc(Map<String,Object> req) {
|
||||
Document d = new Document();
|
||||
d.setName((String)req.get("name"));
|
||||
d.setCategoryId(req.get("categoryId") != null ? ((Number)req.get("categoryId")).longValue() : null);
|
||||
d.setFileType((String)req.get("fileType"));
|
||||
d.setFilePath((String)req.get("filePath"));
|
||||
d.setStatus(1);
|
||||
docMapper.insert(d);
|
||||
return d.getId();
|
||||
}
|
||||
public void updateDoc(Long id, Map<String,Object> req) {
|
||||
Document d = docMapper.selectById(id);
|
||||
if (d == null) throw new RuntimeException("文档不存在");
|
||||
if (req.containsKey("name")) d.setName((String)req.get("name"));
|
||||
if (req.containsKey("categoryId")) d.setCategoryId(((Number)req.get("categoryId")).longValue());
|
||||
docMapper.updateById(d);
|
||||
}
|
||||
public void deleteDoc(Long id) { docMapper.deleteById(id); }
|
||||
public List<DocumentCategory> listCategories() { return catMapper.selectList(null); }
|
||||
public List<DocumentVersion> getVersions(Long docId) {
|
||||
return verMapper.selectList(new LambdaQueryWrapper<DocumentVersion>()
|
||||
.eq(DocumentVersion::getDocId, docId).orderByDesc(DocumentVersion::getVersionNo));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.water.system.service;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.water.system.entity.*;
|
||||
import com.water.system.mapper.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import java.util.*;
|
||||
@Service @RequiredArgsConstructor
|
||||
public class SysService {
|
||||
private final SysRoleMapper roleMapper;
|
||||
private final SysUserMapper userMapper;
|
||||
private final SysMenuMapper menuMapper;
|
||||
private final SysDepartmentMapper deptMapper;
|
||||
private final SysLogMapper logMapper;
|
||||
|
||||
// Roles
|
||||
public List<SysRole> listRoles() { return roleMapper.selectList(null); }
|
||||
public Long createRole(Map<String,Object> req) {
|
||||
SysRole r = new SysRole();
|
||||
r.setRoleCode((String)req.get("roleCode"));
|
||||
r.setRoleName((String)req.get("roleName"));
|
||||
r.setDescription((String)req.get("description"));
|
||||
r.setStatus(1); r.setSort(0);
|
||||
roleMapper.insert(r);
|
||||
return r.getId();
|
||||
}
|
||||
// Users
|
||||
public List<SysUser> listUsers(Integer status) {
|
||||
return userMapper.selectList(new LambdaQueryWrapper<SysUser>()
|
||||
.eq(status != null, SysUser::getStatus, status));
|
||||
}
|
||||
public Long createUser(Map<String,Object> req) {
|
||||
SysUser u = new SysUser();
|
||||
u.setUsername((String)req.get("username"));
|
||||
u.setPassword((String)req.get("password"));
|
||||
u.setRealName((String)req.get("realName"));
|
||||
u.setPhone((String)req.get("phone"));
|
||||
u.setStatus(1);
|
||||
userMapper.insert(u);
|
||||
return u.getId();
|
||||
}
|
||||
public void updateUserStatus(Long id, int status) {
|
||||
SysUser u = userMapper.selectById(id);
|
||||
if (u == null) throw new RuntimeException("用户不存在");
|
||||
u.setStatus(status);
|
||||
userMapper.updateById(u);
|
||||
}
|
||||
// Menus
|
||||
public List<SysMenu> listMenus() { return menuMapper.selectList(null); }
|
||||
// Departments
|
||||
public List<SysDepartment> listDepts() { return deptMapper.selectList(null); }
|
||||
public Long createDept(Map<String,Object> req) {
|
||||
SysDepartment d = new SysDepartment();
|
||||
d.setDeptName((String)req.get("deptName"));
|
||||
d.setLeader((String)req.get("leader"));
|
||||
d.setSort(0); d.setStatus(1);
|
||||
deptMapper.insert(d);
|
||||
return d.getId();
|
||||
}
|
||||
// Logs
|
||||
public List<SysLog> listLogs(String logType, String username) {
|
||||
LambdaQueryWrapper<SysLog> w = new LambdaQueryWrapper<>();
|
||||
if (logType != null) w.eq(SysLog::getLogType, logType);
|
||||
if (username != null) w.like(SysLog::getUsername, username);
|
||||
return logMapper.selectList(w.orderByDesc(SysLog::getCreatedTime).last("LIMIT 100"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
server:
|
||||
port: 8084
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: wm-system
|
||||
datasource:
|
||||
driver-class-name: org.postgresql.Driver
|
||||
url: jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:5432}/${DB_NAME:water_system}?currentSchema=public
|
||||
username: ${DB_USER:postgres}
|
||||
password: ${DB_PASS:postgres}
|
||||
servlet:
|
||||
multipart:
|
||||
max-file-size: 100MB
|
||||
max-request-size: 100MB
|
||||
|
||||
mybatis-plus:
|
||||
configuration:
|
||||
map-underscore-to-camel-case: true
|
||||
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
global-config:
|
||||
db-config:
|
||||
logic-delete-field: deleted
|
||||
logic-delete-value: 1
|
||||
logic-not-delete-value: 0
|
||||
|
||||
minio:
|
||||
endpoint: ${MINIO_ENDPOINT:http://localhost:9000}
|
||||
access-key: ${MINIO_ACCESS_KEY:minioadmin}
|
||||
secret-key: ${MINIO_SECRET_KEY:minioadmin}
|
||||
bucket-name: ${MINIO_BUCKET:water-documents}
|
||||
|
||||
sa-token:
|
||||
token-name: Authorization
|
||||
timeout: 86400
|
||||
active-timeout: 1800
|
||||
|
||||
logging:
|
||||
level:
|
||||
com.water.system: debug
|
||||
@@ -0,0 +1,45 @@
|
||||
CREATE TABLE IF NOT EXISTS sys_document (
|
||||
id BIGSERIAL PRIMARY KEY, name VARCHAR(200), category_id BIGINT,
|
||||
file_type VARCHAR(20), file_size BIGINT, file_path VARCHAR(500),
|
||||
status INT DEFAULT 1, creator_id BIGINT,
|
||||
created_time TIMESTAMP DEFAULT NOW(), updated_time TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS sys_document_category (
|
||||
id BIGSERIAL PRIMARY KEY, name VARCHAR(100), parent_id BIGINT,
|
||||
sort INT DEFAULT 0, status INT DEFAULT 1,
|
||||
created_time TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS sys_document_version (
|
||||
id BIGSERIAL PRIMARY KEY, doc_id BIGINT, version_no INT,
|
||||
file_path VARCHAR(500), remark TEXT,
|
||||
created_time TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS sys_role (
|
||||
id BIGSERIAL PRIMARY KEY, role_code VARCHAR(50) UNIQUE, role_name VARCHAR(50),
|
||||
description VARCHAR(200), status INT DEFAULT 1, sort INT DEFAULT 0,
|
||||
created_time TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS sys_user (
|
||||
id BIGSERIAL PRIMARY KEY, username VARCHAR(50) UNIQUE, password VARCHAR(200),
|
||||
real_name VARCHAR(50), phone VARCHAR(20), email VARCHAR(100),
|
||||
dept_id BIGINT, avatar VARCHAR(500), status INT DEFAULT 1,
|
||||
created_time TIMESTAMP DEFAULT NOW(), updated_time TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS sys_menu (
|
||||
id BIGSERIAL PRIMARY KEY, parent_id BIGINT, name VARCHAR(50),
|
||||
path VARCHAR(200), icon VARCHAR(50), component VARCHAR(200),
|
||||
permission VARCHAR(100), type INT, sort INT DEFAULT 0,
|
||||
visible INT DEFAULT 1, status INT DEFAULT 1
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS sys_department (
|
||||
id BIGSERIAL PRIMARY KEY, parent_id BIGINT, dept_name VARCHAR(100),
|
||||
leader VARCHAR(50), phone VARCHAR(20), sort INT DEFAULT 0, status INT DEFAULT 1
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS sys_log (
|
||||
id BIGSERIAL PRIMARY KEY, user_id BIGINT, username VARCHAR(50),
|
||||
log_type VARCHAR(20), module VARCHAR(50), action VARCHAR(50),
|
||||
request_url VARCHAR(500), request_method VARCHAR(10),
|
||||
request_params TEXT, response_result TEXT,
|
||||
ip VARCHAR(50), duration BIGINT,
|
||||
created_time TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
Reference in New Issue
Block a user