6875 lines
209 KiB
Markdown
6875 lines
209 KiB
Markdown
---
|
||
title: "福建水务营收系统概要设计文档"
|
||
author: "系统设计团队"
|
||
date: "2025年06月09日"
|
||
---
|
||
|
||
|
||
---
|
||
|
||
# 福建水务营收系统架构设计文档
|
||
|
||
## 文档信息
|
||
| 项目信息 | 详情 |
|
||
|---------|------|
|
||
| **项目名称** | 福建水务营收系统 |
|
||
| **文档类型** | 概要设计文档 |
|
||
| **技术框架** | RuoYi-Vue-Pro + yudao-ui-admin-vue3 |
|
||
| **文档版本** | v1.0 |
|
||
| **编写日期** | 2024-12-19 |
|
||
| **文档状态** | ✅ 基本完成 |
|
||
|
||
## 目录
|
||
- [一、系统架构概述](#一系统架构概述)
|
||
- [二、技术架构](#二技术架构)
|
||
- [三、应用架构](#三应用架构)
|
||
- [四、数据架构](#四数据架构)
|
||
- [五、安全架构](#五安全架构)
|
||
- [六、部署架构](#六部署架构)
|
||
- [七、接口架构](#七接口架构)
|
||
|
||
## 一、系统架构概述
|
||
|
||
福建水务营收系统采用多层架构设计,旨在支持集团化的集中管理、统一资源管理的业务需求。系统架构的设计目标是实现"一个业务平台、一网通平台"的建设目标,为集团及下属各分公司提供统一的营业收费系统。
|
||
|
||
系统架构主要包括以下核心特点:
|
||
- 多租户架构:支持集团、分公司、营业站点的多层级租户管理模式
|
||
- 统一资源服务:统一的数字水务系统运行资源环境
|
||
- 统一平台应用:统一业务流程,集中汇集数据
|
||
- 统一对外接口:提供标准的接口和能力
|
||
|
||
### 1. 系统总体架构图
|
||
|
||
```mermaid
|
||
graph TB
|
||
subgraph "用户层"
|
||
A1[Web管理端<br/>yudao-ui-admin-vue3]
|
||
A2[移动抄表端<br/>uni-app]
|
||
A3[客户微信端<br/>微信小程序]
|
||
A4[客户支付宝端<br/>支付宝小程序]
|
||
end
|
||
|
||
subgraph "网关层"
|
||
B1[Nginx负载均衡]
|
||
B2[API网关<br/>统一认证/权限控制]
|
||
end
|
||
|
||
subgraph "应用层"
|
||
C1[营收管理<br/>RuoYi-Vue-Pro]
|
||
C2[客户服务<br/>RuoYi-Vue-Pro]
|
||
C3[表务管理<br/>RuoYi-Vue-Pro]
|
||
C4[统计分析<br/>RuoYi-Vue-Pro]
|
||
end
|
||
|
||
subgraph "服务层"
|
||
D1[权限服务<br/>Spring Security]
|
||
D2[工作流服务<br/>Flowable]
|
||
D3[消息服务<br/>Redis MQ]
|
||
D4[文件服务<br/>MinIO/OSS]
|
||
end
|
||
|
||
subgraph "数据层"
|
||
E1[(OpenGauss 5.0+<br/>主从架构)]
|
||
E2[(Redis 6.0<br/>集群缓存)]
|
||
E3[文件存储<br/>分布式存储]
|
||
end
|
||
|
||
subgraph "外部接口"
|
||
F1[银行接口<br/>代扣/托收]
|
||
F2[支付接口<br/>微信/支付宝]
|
||
F3[短信接口<br/>阿里云/腾讯云]
|
||
F4[物联网接口<br/>智能水表]
|
||
end
|
||
|
||
A1 --> B1
|
||
A2 --> B1
|
||
A3 --> B1
|
||
A4 --> B1
|
||
|
||
B1 --> B2
|
||
B2 --> C1
|
||
B2 --> C2
|
||
B2 --> C3
|
||
B2 --> C4
|
||
|
||
C1 --> D1
|
||
C1 --> D2
|
||
C1 --> D3
|
||
C1 --> D4
|
||
C2 --> D1
|
||
C2 --> D3
|
||
C3 --> D1
|
||
C3 --> D2
|
||
C4 --> D1
|
||
|
||
D1 --> E1
|
||
D2 --> E1
|
||
D3 --> E2
|
||
D4 --> E3
|
||
|
||
C1 --> F1
|
||
C1 --> F2
|
||
C2 --> F3
|
||
C3 --> F4
|
||
```
|
||
|
||
### 2. 物理部署架构图
|
||
|
||
```mermaid
|
||
graph TB
|
||
subgraph "DMZ区域"
|
||
LB1[负载均衡器<br/>Nginx Cluster]
|
||
WAF[Web应用防火墙]
|
||
end
|
||
|
||
subgraph "应用服务区"
|
||
subgraph "Web服务集群"
|
||
WEB1[Web服务器1<br/>8核32G]
|
||
WEB2[Web服务器2<br/>8核32G]
|
||
end
|
||
|
||
subgraph "应用服务集群"
|
||
APP1[应用服务器1<br/>16核64G]
|
||
APP2[应用服务器2<br/>16核64G]
|
||
end
|
||
end
|
||
|
||
subgraph "数据服务区"
|
||
subgraph "数据库集群"
|
||
DB1[OpenGauss主库<br/>32核128G]
|
||
DB2[OpenGauss从库<br/>32核128G]
|
||
end
|
||
|
||
subgraph "缓存集群"
|
||
REDIS1[Redis主节点<br/>16核32G]
|
||
REDIS2[Redis从节点<br/>16核32G]
|
||
REDIS3[Redis哨兵<br/>8核16G]
|
||
end
|
||
|
||
subgraph "文件存储"
|
||
FILE1[文件服务器1<br/>8核32G 10TB]
|
||
FILE2[文件服务器2<br/>8核32G 10TB]
|
||
end
|
||
end
|
||
|
||
subgraph "管理服务区"
|
||
MONITOR[监控服务器<br/>8核16G]
|
||
BACKUP[备份服务器<br/>8核32G 20TB]
|
||
JUMP[跳板服务器<br/>4核8G]
|
||
end
|
||
|
||
Internet --> WAF
|
||
WAF --> LB1
|
||
LB1 --> WEB1
|
||
LB1 --> WEB2
|
||
|
||
WEB1 --> APP1
|
||
WEB1 --> APP2
|
||
WEB2 --> APP1
|
||
WEB2 --> APP2
|
||
|
||
APP1 --> DB1
|
||
APP2 --> DB1
|
||
DB1 --> DB2
|
||
|
||
APP1 --> REDIS1
|
||
APP2 --> REDIS1
|
||
REDIS1 --> REDIS2
|
||
REDIS3 --> REDIS1
|
||
REDIS3 --> REDIS2
|
||
|
||
APP1 --> FILE1
|
||
APP2 --> FILE2
|
||
FILE1 --> FILE2
|
||
|
||
MONITOR --> APP1
|
||
MONITOR --> APP2
|
||
MONITOR --> DB1
|
||
MONITOR --> REDIS1
|
||
|
||
BACKUP --> DB1
|
||
BACKUP --> FILE1
|
||
```
|
||
|
||
|
||
## 二、技术架构
|
||
|
||
系统采用B/S和M/S相结合的架构模式,具体技术栈如下:
|
||
|
||
### 1. 技术栈总览图
|
||
|
||
```mermaid
|
||
graph TB
|
||
subgraph "前端技术栈"
|
||
FE1[Vue 3.2+ TypeScript]
|
||
FE2[Element Plus UI]
|
||
FE3[Vite 构建工具]
|
||
FE4[Pinia 状态管理]
|
||
FE5[Vue Router 路由]
|
||
FE6[Axios HTTP请求]
|
||
FE7[ECharts 图表]
|
||
FE8[富文本编辑器]
|
||
end
|
||
|
||
subgraph "后端技术栈"
|
||
BE1[Spring Boot 3.x]
|
||
BE2[Spring Security 6.x]
|
||
BE3[MyBatis Plus 3.x]
|
||
BE4[Redis 6.0+]
|
||
BE5[OpenGauss 5.0+]
|
||
BE6[Knife4j API文档]
|
||
BE7[Jackson JSON处理]
|
||
BE8[Maven 依赖管理]
|
||
end
|
||
|
||
subgraph "中间件技术栈"
|
||
MW1[Nginx 负载均衡]
|
||
MW2[Redis 缓存集群]
|
||
MW3[Flowable 工作流]
|
||
MW4[Quartz 定时任务]
|
||
MW5[MinIO 文件存储]
|
||
MW6[RocketMQ 消息队列]
|
||
MW7[ElasticSearch 搜索]
|
||
MW8[Sentinel 熔断限流]
|
||
end
|
||
|
||
subgraph "移动端技术栈"
|
||
MB1[uni-app 跨平台]
|
||
MB2[uView UI组件]
|
||
MB3[微信小程序]
|
||
MB4[支付宝小程序]
|
||
MB5[H5响应式]
|
||
MB6[高德地图SDK]
|
||
MB7[NFC设备接口]
|
||
end
|
||
|
||
subgraph "监控运维技术栈"
|
||
OP1[SkyWalking APM]
|
||
OP2[Spring Boot Admin]
|
||
OP3[Docker 容器化]
|
||
OP4[Kubernetes 编排]
|
||
OP5[Jenkins CI/CD]
|
||
OP6[Prometheus 监控]
|
||
OP7[Grafana 仪表盘]
|
||
OP8[ELK 日志分析]
|
||
end
|
||
|
||
FE1 --> BE1
|
||
FE6 --> BE1
|
||
BE1 --> BE2
|
||
BE1 --> BE3
|
||
BE3 --> BE5
|
||
BE1 --> BE4
|
||
BE1 --> MW3
|
||
BE1 --> MW4
|
||
MW1 --> BE1
|
||
BE1 --> MW5
|
||
BE1 --> MW6
|
||
BE1 --> MW7
|
||
MW8 --> BE1
|
||
|
||
MB1 --> BE1
|
||
MB3 --> BE1
|
||
MB4 --> BE1
|
||
|
||
OP1 --> BE1
|
||
OP2 --> BE1
|
||
OP3 --> BE1
|
||
OP4 --> OP3
|
||
OP5 --> OP4
|
||
OP6 --> BE1
|
||
OP7 --> OP6
|
||
OP8 --> BE1
|
||
```
|
||
|
||
### 2. 系统数据流向图
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
subgraph "数据采集层"
|
||
A1[移动抄表APP<br/>数据采集]
|
||
A2[智能水表<br/>远程数据]
|
||
A3[Web管理端<br/>业务录入]
|
||
A4[客户端小程序<br/>用户数据]
|
||
A5[外部系统<br/>接口数据]
|
||
end
|
||
|
||
subgraph "数据接入层"
|
||
B1[API网关<br/>数据验证]
|
||
B2[数据清洗<br/>格式转换]
|
||
B3[消息队列<br/>异步处理]
|
||
B4[数据缓存<br/>临时存储]
|
||
end
|
||
|
||
subgraph "业务处理层"
|
||
C1[抄表服务<br/>水量计算]
|
||
C2[收费服务<br/>账单生成]
|
||
C3[账务服务<br/>财务处理]
|
||
C4[工单服务<br/>流程处理]
|
||
C5[统计服务<br/>数据分析]
|
||
end
|
||
|
||
subgraph "数据存储层"
|
||
D1[(MySQL主库<br/>核心业务数据)]
|
||
D2[(MySQL从库<br/>查询数据)]
|
||
D3[(Redis缓存<br/>热点数据)]
|
||
D4[文件存储<br/>附件图片]
|
||
D5[(备份库<br/>历史数据)]
|
||
end
|
||
|
||
subgraph "数据服务层"
|
||
E1[查询服务<br/>数据检索]
|
||
E2[报表服务<br/>统计分析]
|
||
E3[接口服务<br/>对外开放]
|
||
E4[推送服务<br/>消息通知]
|
||
end
|
||
|
||
subgraph "数据展现层"
|
||
F1[管理后台<br/>业务操作]
|
||
F2[统计大屏<br/>可视化展示]
|
||
F3[移动端<br/>现场作业]
|
||
F4[客户端<br/>自助服务]
|
||
F5[第三方系统<br/>数据集成]
|
||
end
|
||
|
||
%% 数据流向关系
|
||
A1 --> B1
|
||
A2 --> B2
|
||
A3 --> B1
|
||
A4 --> B1
|
||
A5 --> B3
|
||
|
||
B1 --> B4
|
||
B2 --> B3
|
||
B3 --> C1
|
||
B4 --> C2
|
||
|
||
C1 --> D1
|
||
C2 --> D1
|
||
C3 --> D1
|
||
C4 --> D1
|
||
C5 --> D2
|
||
|
||
D1 --> D2
|
||
D1 --> D3
|
||
D1 --> D5
|
||
|
||
D2 --> E1
|
||
D3 --> E1
|
||
D1 --> E2
|
||
D2 --> E3
|
||
|
||
E1 --> F1
|
||
E2 --> F2
|
||
E3 --> F3
|
||
E4 --> F4
|
||
E3 --> F5
|
||
|
||
%% 反向数据流
|
||
F1 -.-> C2
|
||
F3 -.-> C1
|
||
F4 -.-> C3
|
||
F5 -.-> C4
|
||
```
|
||
|
||
### 3. 服务端技术架构
|
||
- 操作系统:国产 Linux 操作系统
|
||
- 数据库:华为OpenGauss 5.0+数据库,企业级国产数据库
|
||
- 应用框架:基于RuoYi-Vue-Pro框架定制开发
|
||
- 核心框架:Spring Boot 3.x,支持JDK 17/21
|
||
- ORM框架:MyBatis Plus,增强的MyBatis
|
||
- 权限框架:Spring Security,基于RBAC的权限管理
|
||
- 数据缓存:Redis + Redisson,高性能缓存和分布式锁
|
||
- 工作流引擎:Flowable,灵活的工作流处理
|
||
- 任务调度:基于Quartz的CRON任务调度
|
||
- 服务监控:Spring Boot Admin、SkyWalking APM
|
||
- 消息队列:基于Redis的轻量级消息队列
|
||
- 文档生成:Knife4j,基于Swagger的API文档生成
|
||
- 代码生成:自动化CRUD和表单代码生成器
|
||
- 多租户:基于字段隔离的SaaS多租户设计
|
||
|
||
#### 2.1 RuoYi-Vue-Pro框架配置示例
|
||
|
||
**application.yml主配置文件:**
|
||
```yaml
|
||
# 服务端口配置
|
||
server:
|
||
port: 48080
|
||
servlet:
|
||
context-path: /admin-api
|
||
|
||
# Spring Boot 配置
|
||
spring:
|
||
application:
|
||
name: water-biz-server
|
||
profiles:
|
||
active: local
|
||
|
||
# 数据源配置
|
||
datasource:
|
||
druid:
|
||
url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
|
||
username: root
|
||
password: ${MYSQL_PASSWORD:123456}
|
||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||
# 连接池配置
|
||
initial-size: 10
|
||
min-idle: 10
|
||
max-active: 20
|
||
max-wait: 60000
|
||
time-between-eviction-runs-millis: 60000
|
||
min-evictable-idle-time-millis: 300000
|
||
validation-query: SELECT 1 FROM DUAL
|
||
test-while-idle: true
|
||
test-on-borrow: false
|
||
test-on-return: false
|
||
pool-prepared-statements: true
|
||
max-pool-prepared-statement-per-connection-size: 20
|
||
|
||
# Redis 配置
|
||
redis:
|
||
host: 127.0.0.1
|
||
port: 6379
|
||
password: ${REDIS_PASSWORD:}
|
||
database: 1
|
||
timeout: 6000ms
|
||
lettuce:
|
||
pool:
|
||
max-active: 32
|
||
max-wait: 6000ms
|
||
max-idle: 32
|
||
min-idle: 8
|
||
|
||
# MyBatis Plus 配置
|
||
mybatis-plus:
|
||
configuration:
|
||
map-underscore-to-camel-case: true
|
||
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
||
global-config:
|
||
db-config:
|
||
id-type: NONE
|
||
logic-delete-field: deleted
|
||
logic-delete-value: 1
|
||
logic-not-delete-value: 0
|
||
type-aliases-package: cn.iocoder.yudao.module.*.dal.dataobject
|
||
|
||
# 水务系统多租户配置
|
||
yudao:
|
||
tenant:
|
||
enable: true
|
||
ignore-urls:
|
||
- /admin-api/water/tenant/get-id-by-name
|
||
- /admin-api/infra/file/*/get/**
|
||
ignore-tables:
|
||
- water_tenant
|
||
- water_system_config
|
||
- water_dict_data
|
||
- water_dict_type
|
||
|
||
# 水务系统安全配置
|
||
security:
|
||
permit-all-urls:
|
||
- /admin-api/water/auth/login
|
||
- /admin-api/water/auth/logout
|
||
- /admin-api/water/auth/refresh-token
|
||
- /admin-api/water/captcha/get
|
||
- /admin-api/water/sms/send
|
||
|
||
# 文件存储配置
|
||
file:
|
||
config:
|
||
type: local
|
||
local:
|
||
domain: http://127.0.0.1:48080
|
||
path: /Users/yunai/file_test
|
||
|
||
# 短信配置
|
||
sms:
|
||
alibaba:
|
||
access-key-id: ${SMS_ACCESS_KEY_ID:}
|
||
access-key-secret: ${SMS_ACCESS_KEY_SECRET:}
|
||
signature: 福建水务
|
||
template-code: SMS_123456
|
||
```
|
||
|
||
**多租户配置实现:**
|
||
```java
|
||
@Component
|
||
@Slf4j
|
||
public class WaterTenantConfiguration {
|
||
|
||
@Resource
|
||
private TenantProperties tenantProperties;
|
||
|
||
/**
|
||
* 多租户字段处理器
|
||
*/
|
||
@Bean
|
||
public TenantLineHandler tenantLineHandler() {
|
||
return new TenantLineHandler() {
|
||
|
||
@Override
|
||
public Expression getTenantId() {
|
||
// 从当前登录用户上下文获取租户ID
|
||
Long tenantId = TenantContextHolder.getTenantId();
|
||
if (tenantId == null) {
|
||
return null;
|
||
}
|
||
return new LongValue(tenantId);
|
||
}
|
||
|
||
@Override
|
||
public String getTenantIdColumn() {
|
||
return "tenant_id";
|
||
}
|
||
|
||
@Override
|
||
public boolean ignoreTable(String tableName) {
|
||
// 忽略的表不进行多租户处理
|
||
return tenantProperties.getIgnoreTables().contains(tableName);
|
||
}
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 多租户拦截器
|
||
*/
|
||
@Bean
|
||
public MybatisPlusInterceptor mybatisPlusInterceptor() {
|
||
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
|
||
// 多租户插件
|
||
TenantLineInnerInterceptor tenantInterceptor = new TenantLineInnerInterceptor();
|
||
tenantInterceptor.setTenantLineHandler(tenantLineHandler());
|
||
interceptor.addInnerInterceptor(tenantInterceptor);
|
||
// 分页插件
|
||
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
|
||
return interceptor;
|
||
}
|
||
}
|
||
```
|
||
|
||
**权限控制配置:**
|
||
```java
|
||
@EnableWebSecurity
|
||
@EnableMethodSecurity(prePostEnabled = true, securedEnabled = true)
|
||
@Configuration
|
||
public class WaterSecurityConfiguration {
|
||
|
||
@Resource
|
||
private SecurityProperties securityProperties;
|
||
|
||
@Bean
|
||
public SecurityFilterChain filterChain(HttpSecurity httpSecurity,
|
||
@Lazy TokenAuthenticationFilter tokenAuthenticationFilter) throws Exception {
|
||
return httpSecurity
|
||
// 设置 URL 安全权限
|
||
.authorizeHttpRequests(c -> c
|
||
// 1. 静态资源,可匿名访问
|
||
.requestMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll()
|
||
// 2. 设置 @PermitAll 无需认证
|
||
.requestMatchers(securityProperties.getPermitAllUrls().toArray(new String[0])).permitAll()
|
||
// 3. 兜底规则,必须认证
|
||
.anyRequest().authenticated()
|
||
)
|
||
// 设置处理器
|
||
.exceptionHandling(c -> c.authenticationEntryPoint(authenticationEntryPoint)
|
||
.accessDeniedHandler(accessDeniedHandler))
|
||
// 添加 Token Filter
|
||
.addFilterBefore(tokenAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
|
||
// 不创建 SecurityContext
|
||
.sessionManagement(c -> c.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
||
// 禁用 CSRF,因为使用 token 机制
|
||
.csrf(AbstractHttpConfigurer::disable)
|
||
// 禁用 cors
|
||
.cors(AbstractHttpConfigurer::disable)
|
||
.build();
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3. 客户端技术架构
|
||
- 前端框架:基于yudao-ui-admin-vue3框架定制开发
|
||
- 核心框架:Vue 3.x + TypeScript
|
||
- 组件库:Element Plus,现代化UI组件
|
||
- 状态管理:Pinia,新一代的Vue状态管理库
|
||
- 路由管理:Vue Router
|
||
- HTTP工具:Axios,请求拦截与统一处理
|
||
- CSS框架:Tailwind CSS / UnoCSS,原子化CSS
|
||
- 图表组件:ECharts,强大的可视化图表库
|
||
- 富文本编辑器:WangEditor
|
||
- 文件上传:基于Element Plus的上传组件
|
||
- 权限控制:细粒度的按钮级权限控制
|
||
- 动态表格:支持拖拽、排序、筛选
|
||
- 代码规范:ESLint + Prettier,标准化代码风格
|
||
|
||
#### 3.1 前端项目结构配置
|
||
|
||
**package.json 依赖配置:**
|
||
```json
|
||
{
|
||
"name": "water-biz-ui-admin",
|
||
"version": "1.0.0",
|
||
"description": "福建水务营收系统管理后台",
|
||
"dependencies": {
|
||
"@element-plus/icons-vue": "^2.1.0",
|
||
"@vueuse/core": "^10.5.0",
|
||
"axios": "^1.6.0",
|
||
"echarts": "^5.4.3",
|
||
"element-plus": "^2.4.2",
|
||
"pinia": "^2.1.7",
|
||
"vue": "^3.3.8",
|
||
"vue-router": "^4.2.5",
|
||
"@wangeditor/editor": "^5.1.23",
|
||
"@wangeditor/editor-for-vue": "^5.1.12"
|
||
},
|
||
"devDependencies": {
|
||
"@types/node": "^20.8.7",
|
||
"@typescript-eslint/eslint-plugin": "^6.9.1",
|
||
"@typescript-eslint/parser": "^6.9.1",
|
||
"@vitejs/plugin-vue": "^4.4.1",
|
||
"eslint": "^8.52.0",
|
||
"eslint-plugin-vue": "^9.17.0",
|
||
"prettier": "^3.0.3",
|
||
"typescript": "^5.2.2",
|
||
"vite": "^4.5.0",
|
||
"vue-tsc": "^1.8.22"
|
||
}
|
||
}
|
||
```
|
||
|
||
**vite.config.ts 构建配置:**
|
||
```typescript
|
||
import { defineConfig } from 'vite'
|
||
import vue from '@vitejs/plugin-vue'
|
||
import { resolve } from 'path'
|
||
|
||
export default defineConfig({
|
||
plugins: [vue()],
|
||
resolve: {
|
||
alias: {
|
||
'@': resolve(__dirname, 'src'),
|
||
'~': resolve(__dirname, 'src'),
|
||
'#': resolve(__dirname, 'types')
|
||
}
|
||
},
|
||
server: {
|
||
host: '0.0.0.0',
|
||
port: 3000,
|
||
open: true,
|
||
proxy: {
|
||
'/admin-api': {
|
||
target: 'http://127.0.0.1:48080',
|
||
changeOrigin: true,
|
||
ws: true
|
||
}
|
||
}
|
||
},
|
||
build: {
|
||
target: 'es2015',
|
||
outDir: 'dist',
|
||
assetsDir: 'static',
|
||
sourcemap: false,
|
||
chunkSizeWarningLimit: 1500,
|
||
rollupOptions: {
|
||
output: {
|
||
chunkFileNames: 'static/js/[name]-[hash].js',
|
||
entryFileNames: 'static/js/[name]-[hash].js',
|
||
assetFileNames: 'static/[ext]/[name]-[hash].[ext]'
|
||
}
|
||
}
|
||
}
|
||
})
|
||
```
|
||
|
||
**src/stores/user.ts 用户状态管理:**
|
||
```typescript
|
||
import { defineStore } from 'pinia'
|
||
import { ref, computed } from 'vue'
|
||
import { UserApi, UserVO } from '@/api/system/user'
|
||
import { getAccessToken, removeToken } from '@/utils/auth'
|
||
|
||
export const useUserStore = defineStore('user', () => {
|
||
const userInfo = ref<UserVO>()
|
||
const permissions = ref<string[]>([])
|
||
const roles = ref<string[]>([])
|
||
|
||
const nickname = computed(() => userInfo.value?.nickname ?? '')
|
||
const avatar = computed(() => userInfo.value?.avatar ?? '')
|
||
const email = computed(() => userInfo.value?.email ?? '')
|
||
|
||
// 获取用户信息
|
||
const getUserInfo = async () => {
|
||
const res = await UserApi.getUserProfile()
|
||
userInfo.value = res
|
||
permissions.value = res.permissions
|
||
roles.value = res.roles
|
||
}
|
||
|
||
// 用户登出
|
||
const logout = async () => {
|
||
try {
|
||
await UserApi.logout()
|
||
} finally {
|
||
await resetToken()
|
||
}
|
||
}
|
||
|
||
// 重置令牌
|
||
const resetToken = async () => {
|
||
userInfo.value = undefined
|
||
permissions.value = []
|
||
roles.value = []
|
||
removeToken()
|
||
}
|
||
|
||
// 检查权限
|
||
const hasPermission = (permission: string) => {
|
||
return permissions.value.includes(permission)
|
||
}
|
||
|
||
// 检查角色
|
||
const hasRole = (role: string) => {
|
||
return roles.value.includes(role)
|
||
}
|
||
|
||
return {
|
||
userInfo,
|
||
permissions,
|
||
roles,
|
||
nickname,
|
||
avatar,
|
||
email,
|
||
getUserInfo,
|
||
logout,
|
||
resetToken,
|
||
hasPermission,
|
||
hasRole
|
||
}
|
||
})
|
||
```
|
||
|
||
**src/utils/request.ts HTTP请求封装:**
|
||
```typescript
|
||
import axios, { AxiosResponse, InternalAxiosRequestConfig } from 'axios'
|
||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||
import { getAccessToken, getRefreshToken, removeToken } from '@/utils/auth'
|
||
import { useUserStore } from '@/stores/user'
|
||
|
||
// 创建 axios 实例
|
||
const service = axios.create({
|
||
baseURL: import.meta.env.VITE_BASE_URL,
|
||
timeout: 50000,
|
||
withCredentials: false
|
||
})
|
||
|
||
// 请求拦截器
|
||
service.interceptors.request.use(
|
||
(config: InternalAxiosRequestConfig) => {
|
||
// 添加 token
|
||
const accessToken = getAccessToken()
|
||
if (accessToken && config.headers) {
|
||
config.headers.Authorization = `Bearer ${accessToken}`
|
||
}
|
||
|
||
// 添加租户ID
|
||
const tenantId = localStorage.getItem('tenantId')
|
||
if (tenantId && config.headers) {
|
||
config.headers['tenant-id'] = tenantId
|
||
}
|
||
|
||
return config
|
||
},
|
||
error => {
|
||
console.log(error)
|
||
return Promise.reject(error)
|
||
}
|
||
)
|
||
|
||
// 响应拦截器
|
||
service.interceptors.response.use(
|
||
(response: AxiosResponse) => {
|
||
const { data } = response
|
||
const { code, msg } = data
|
||
|
||
// 业务请求成功
|
||
if (code === 0) {
|
||
return data
|
||
}
|
||
|
||
// token 过期,尝试刷新
|
||
if (code === 401) {
|
||
return handleTokenExpired()
|
||
}
|
||
|
||
// 业务请求失败
|
||
ElMessage.error(msg || '系统未知错误,请反馈给管理员')
|
||
return Promise.reject(new Error(msg || 'Error'))
|
||
},
|
||
error => {
|
||
console.log('err' + error)
|
||
let { message } = error
|
||
if (message === 'Network Error') {
|
||
message = '后端接口连接异常'
|
||
} else if (message.includes('timeout')) {
|
||
message = '系统接口请求超时'
|
||
} else if (message.includes('Request failed with status code')) {
|
||
message = '系统接口' + message.substr(message.length - 3) + '异常'
|
||
}
|
||
ElMessage.error(message)
|
||
return Promise.reject(error)
|
||
}
|
||
)
|
||
|
||
// 处理 token 过期
|
||
const handleTokenExpired = async () => {
|
||
const userStore = useUserStore()
|
||
ElMessageBox.alert('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', {
|
||
confirmButtonText: '重新登录',
|
||
type: 'warning'
|
||
}).then(() => {
|
||
userStore.resetToken().then(() => {
|
||
location.reload()
|
||
})
|
||
})
|
||
}
|
||
|
||
export default service
|
||
```
|
||
### 4. 前端技术架构详细设计
|
||
|
||
#### 4.1 Web管理端架构 (yudao-ui-admin-vue3)
|
||
|
||
**技术栈组成:**
|
||
```mermaid
|
||
graph TB
|
||
subgraph "开发框架"
|
||
A1[Vue 3.2.47 Composition API]
|
||
A2[TypeScript 4.9.4]
|
||
A3[Vite 4.0.0 构建工具]
|
||
end
|
||
|
||
subgraph "UI组件库"
|
||
B1[Element Plus 2.3.14]
|
||
B2[Element Plus Icons]
|
||
B3[自定义组件库]
|
||
end
|
||
|
||
subgraph "状态管理"
|
||
C1[Pinia 2.0.28]
|
||
C2[持久化插件]
|
||
C3[全局状态管理]
|
||
end
|
||
|
||
subgraph "路由系统"
|
||
D1[Vue Router 4.1.6]
|
||
D2[路由守卫]
|
||
D3[动态路由]
|
||
D4[权限控制]
|
||
end
|
||
|
||
subgraph "HTTP通信"
|
||
E1[Axios 1.2.2]
|
||
E2[请求拦截器]
|
||
E3[响应拦截器]
|
||
E4[错误处理]
|
||
end
|
||
|
||
subgraph "工具库"
|
||
F1[Lodash 工具函数]
|
||
F2[dayjs 时间处理]
|
||
F3[nprogress 进度条]
|
||
F4[js-cookie Cookie管理]
|
||
F5[crypto-js 加密解密]
|
||
end
|
||
|
||
A1 --> B1
|
||
A1 --> C1
|
||
A1 --> D1
|
||
A1 --> E1
|
||
B1 --> B3
|
||
C1 --> C2
|
||
D1 --> D2
|
||
E1 --> E2
|
||
```
|
||
|
||
**项目结构设计:**
|
||
```text
|
||
yudao-ui-admin-vue3/
|
||
├── public/ # 静态资源
|
||
├── src/
|
||
│ ├── api/ # API接口定义
|
||
│ │ └── water/ # 水务业务API
|
||
│ │ ├── customer/ # 客户管理API
|
||
│ │ ├── meter/ # 抄表管理API
|
||
│ │ ├── billing/ # 收费管理API
|
||
│ │ └── workflow/ # 工单管理API
|
||
│ ├── assets/ # 静态资源
|
||
│ ├── components/ # 全局组件
|
||
│ │ ├── Dialog/ # 弹窗组件
|
||
│ │ ├── Form/ # 表单组件
|
||
│ │ ├── Table/ # 表格组件
|
||
│ │ └── Upload/ # 上传组件
|
||
│ ├── layout/ # 布局组件
|
||
│ ├── router/ # 路由配置
|
||
│ ├── stores/ # Pinia状态管理
|
||
│ ├── styles/ # 全局样式
|
||
│ ├── utils/ # 工具函数
|
||
│ ├── views/ # 页面组件
|
||
│ │ └── water/ # 水务业务页面
|
||
│ │ ├── customer/ # 客户管理
|
||
│ │ ├── meter/ # 抄表管理
|
||
│ │ ├── billing/ # 收费管理
|
||
│ │ └── workflow/ # 工单管理
|
||
│ └── App.vue
|
||
├── types/ # TypeScript类型定义
|
||
├── vite.config.ts # Vite配置
|
||
├── tsconfig.json # TypeScript配置
|
||
└── package.json # 项目依赖
|
||
```
|
||
|
||
**核心配置示例:**
|
||
```typescript
|
||
// vite.config.ts - Vite构建配置
|
||
import { defineConfig } from 'vite'
|
||
import vue from '@vitejs/plugin-vue'
|
||
import { resolve } from 'path'
|
||
|
||
export default defineConfig({
|
||
plugins: [vue()],
|
||
resolve: {
|
||
alias: {
|
||
'@': resolve(__dirname, 'src'),
|
||
'@/api': resolve(__dirname, 'src/api'),
|
||
'@/components': resolve(__dirname, 'src/components'),
|
||
'@/utils': resolve(__dirname, 'src/utils')
|
||
}
|
||
},
|
||
server: {
|
||
port: 80,
|
||
proxy: {
|
||
'/admin-api': {
|
||
target: 'http://127.0.0.1:48080',
|
||
changeOrigin: true,
|
||
rewrite: (path) => path.replace(/^\/admin-api/, '/admin-api')
|
||
}
|
||
}
|
||
},
|
||
build: {
|
||
outDir: 'dist',
|
||
sourcemap: false,
|
||
rollupOptions: {
|
||
output: {
|
||
chunkFileNames: 'js/[name]-[hash].js',
|
||
entryFileNames: 'js/[name]-[hash].js',
|
||
assetFileNames: '[ext]/[name]-[hash].[ext]'
|
||
}
|
||
}
|
||
}
|
||
})
|
||
```
|
||
|
||
#### 4.2 移动端架构 (uni-app)
|
||
|
||
**技术栈组成:**
|
||
```mermaid
|
||
graph TB
|
||
subgraph "跨平台框架"
|
||
M1[uni-app 3.x]
|
||
M2[Vue 3 Composition API]
|
||
M3[TypeScript支持]
|
||
end
|
||
|
||
subgraph "UI组件库"
|
||
N1[uView UI 2.0]
|
||
N2[uni-ui组件]
|
||
N3[自定义水务组件]
|
||
end
|
||
|
||
subgraph "状态管理"
|
||
O1[Vuex 4.x]
|
||
O2[uni-app存储]
|
||
O3[缓存管理]
|
||
end
|
||
|
||
subgraph "设备能力"
|
||
P1[相机API<br/>水表拍照]
|
||
P2[NFC读取<br/>水表标签]
|
||
P3[GPS定位<br/>抄表轨迹]
|
||
P4[扫码API<br/>二维码扫描]
|
||
end
|
||
|
||
subgraph "网络通信"
|
||
Q1[uni.request<br/>HTTP请求]
|
||
Q2[WebSocket<br/>实时通信]
|
||
Q3[文件上传<br/>图片处理]
|
||
end
|
||
|
||
M1 --> N1
|
||
M1 --> O1
|
||
M1 --> P1
|
||
M1 --> Q1
|
||
N1 --> N3
|
||
P1 --> P2
|
||
Q1 --> Q2
|
||
```
|
||
|
||
**移动端项目结构:**
|
||
```text
|
||
water-mobile-app/
|
||
├── pages/ # 页面目录
|
||
│ ├── index/ # 首页
|
||
│ ├── meter/ # 抄表功能
|
||
│ │ ├── task/ # 抄表任务
|
||
│ │ ├── read/ # 抄表录入
|
||
│ │ └── history/ # 抄表历史
|
||
│ ├── workflow/ # 工单管理
|
||
│ └── personal/ # 个人中心
|
||
├── components/ # 组件目录
|
||
│ ├── meter-reader/ # 水表读数组件
|
||
│ ├── map-trace/ # 地图轨迹组件
|
||
│ └── camera-scan/ # 相机扫描组件
|
||
├── static/ # 静态资源
|
||
├── store/ # 状态管理
|
||
├── utils/ # 工具函数
|
||
├── api/ # 接口定义
|
||
├── manifest.json # 应用配置
|
||
└── pages.json # 页面配置
|
||
```
|
||
|
||
#### 4.3 客户端小程序架构
|
||
|
||
**微信小程序技术栈:**
|
||
- 开发框架:微信小程序原生框架
|
||
- UI组件:WeUI + 自定义组件
|
||
- 状态管理:小程序全局数据管理
|
||
- 支付集成:微信支付API
|
||
- 地图服务:腾讯地图API
|
||
|
||
**支付宝小程序技术栈:**
|
||
- 开发框架:支付宝小程序原生框架
|
||
- UI组件:mini-antui + 自定义组件
|
||
- 状态管理:小程序全局数据管理
|
||
- 支付集成:支付宝支付API
|
||
- 地图服务:高德地图API
|
||
|
||
#### 4.4 前端工程化配置
|
||
|
||
**代码规范:**
|
||
```json
|
||
// .eslintrc.js - ESLint配置
|
||
{
|
||
"extends": [
|
||
"@vue/typescript/recommended",
|
||
"@vue/prettier",
|
||
"@vue/prettier/@typescript-eslint"
|
||
],
|
||
"rules": {
|
||
"@typescript-eslint/no-explicit-any": "warn",
|
||
"@typescript-eslint/no-unused-vars": "error",
|
||
"vue/multi-word-component-names": "off"
|
||
}
|
||
}
|
||
```
|
||
|
||
**构建优化:**
|
||
- Vite热更新:开发环境快速构建
|
||
- 代码分割:按路由和组件懒加载
|
||
- 资源压缩:Gzip压缩和图片优化
|
||
- CDN加速:静态资源CDN分发
|
||
- 缓存策略:浏览器缓存和Service Worker
|
||
|
||
- 移动端:
|
||
- 核心框架:uni-app(跨平台)
|
||
- 组件库:uview-ui
|
||
- 小程序支持:微信小程序、支付宝小程序等
|
||
- 移动端地图:高德地图SDK(用于抄表轨迹和导航)
|
||
- 设备接入:NFC、扫码、相机等硬件设备接口
|
||
|
||
### 2.3 技术特性
|
||
- 单点登录:OAuth2 + JWT实现统一认证
|
||
- 数据交换:基于RESTful API的系统内部数据交换与共享
|
||
- 统一报表平台:集成JimuReport,支持自定义报表设计与生成
|
||
- 大屏设计:集成GoView,支持可视化大屏设计
|
||
- 安全保障:满足安全等保三级要求
|
||
- 密码加密:BCrypt加密算法
|
||
- 防XSS攻击:表单数据过滤
|
||
- 防SQL注入:参数化查询
|
||
- 防CSRF攻击:Token验证
|
||
- 性能规格:支持200并发用户,50并发移动设备,系统响应时间不超过3秒
|
||
- 扩展容量:支持100万客户的业务量,满足企业3-5年的业务发展需求
|
||
- 支持功能:
|
||
- 支付管理:微信支付、支付宝支付等
|
||
- 短信服务:阿里云、腾讯云等多家短信服务商
|
||
- AI能力:
|
||
- 智能抄表:基于图像识别的水表读数
|
||
- 异常分析:基于AI的用水异常分析
|
||
- API网关:支持API权限管理、限流熔断、白名单控制
|
||
|
||
## 3. 应用架构
|
||
|
||
### 1. 微服务应用架构图
|
||
|
||
```mermaid
|
||
graph TB
|
||
subgraph "网关层"
|
||
GW[API网关<br/>Spring Cloud Gateway]
|
||
AUTH[认证服务<br/>OAuth2 + JWT]
|
||
end
|
||
|
||
subgraph "基础服务层"
|
||
subgraph "系统服务"
|
||
SYS[系统管理服务<br/>用户/角色/权限]
|
||
TENANT[租户管理服务<br/>多租户隔离]
|
||
FILE[文件管理服务<br/>附件存储]
|
||
MSG[消息服务<br/>短信/邮件/推送]
|
||
end
|
||
|
||
subgraph "工作流服务"
|
||
WF[工作流引擎<br/>Flowable]
|
||
TASK[任务调度服务<br/>Quartz]
|
||
end
|
||
end
|
||
|
||
subgraph "业务服务层"
|
||
subgraph "客户域服务"
|
||
CUST[客户管理服务<br/>Customer Service]
|
||
METER[水表管理服务<br/>Meter Service]
|
||
ADDR[地址管理服务<br/>Address Service]
|
||
end
|
||
|
||
subgraph "营收域服务"
|
||
READ[抄表服务<br/>Reading Service]
|
||
BILL[账单服务<br/>Billing Service]
|
||
PAY[收费服务<br/>Payment Service]
|
||
ACC[账务服务<br/>Accounting Service]
|
||
end
|
||
|
||
subgraph "运营域服务"
|
||
ORDER[工单服务<br/>Workflow Service]
|
||
RPT[报表服务<br/>Report Service]
|
||
STATS[统计分析服务<br/>Statistics Service]
|
||
end
|
||
|
||
subgraph "接口域服务"
|
||
BANK[银行接口服务<br/>Bank Service]
|
||
PAY_GW[支付网关服务<br/>Payment Gateway]
|
||
IOT[物联网服务<br/>IoT Service]
|
||
SMS[短信服务<br/>SMS Service]
|
||
end
|
||
end
|
||
|
||
subgraph "数据层"
|
||
subgraph "业务数据库"
|
||
DB_CUST[(客户库<br/>Customer DB)]
|
||
DB_BILL[(营收库<br/>Billing DB)]
|
||
DB_RPT[(报表库<br/>Report DB)]
|
||
end
|
||
|
||
subgraph "缓存与存储"
|
||
REDIS[(Redis集群<br/>缓存/会话)]
|
||
ES[(ElasticSearch<br/>搜索引擎)]
|
||
FILE_STORE[文件存储<br/>MinIO/OSS]
|
||
end
|
||
end
|
||
|
||
%% 网关层连接
|
||
GW --> AUTH
|
||
GW --> SYS
|
||
GW --> CUST
|
||
GW --> READ
|
||
GW --> ORDER
|
||
|
||
%% 服务间调用
|
||
CUST --> METER
|
||
CUST --> ADDR
|
||
READ --> METER
|
||
READ --> CUST
|
||
BILL --> READ
|
||
BILL --> CUST
|
||
PAY --> BILL
|
||
ACC --> PAY
|
||
|
||
ORDER --> WF
|
||
ORDER --> TASK
|
||
RPT --> STATS
|
||
|
||
%% 外部接口调用
|
||
PAY --> BANK
|
||
PAY --> PAY_GW
|
||
READ --> IOT
|
||
ORDER --> SMS
|
||
|
||
%% 数据层连接
|
||
CUST --> DB_CUST
|
||
METER --> DB_CUST
|
||
BILL --> DB_BILL
|
||
PAY --> DB_BILL
|
||
RPT --> DB_RPT
|
||
|
||
SYS --> REDIS
|
||
AUTH --> REDIS
|
||
CUST --> REDIS
|
||
BILL --> ES
|
||
FILE --> FILE_STORE
|
||
```
|
||
|
||
### 2. 服务治理架构
|
||
|
||
```mermaid
|
||
graph TB
|
||
subgraph "服务发现与注册"
|
||
NACOS[Nacos注册中心<br/>服务注册/发现/配置]
|
||
end
|
||
|
||
subgraph "服务网格层"
|
||
subgraph "负载均衡"
|
||
LB[Ribbon负载均衡<br/>客户端负载均衡]
|
||
FEIGN[OpenFeign<br/>服务间调用]
|
||
end
|
||
|
||
subgraph "容错保护"
|
||
CB[Sentinel熔断器<br/>流量控制/熔断降级]
|
||
RETRY[重试机制<br/>失败重试]
|
||
end
|
||
|
||
subgraph "链路追踪"
|
||
TRACE[SkyWalking<br/>分布式链路追踪]
|
||
METRIC[Micrometer<br/>指标收集]
|
||
end
|
||
end
|
||
|
||
subgraph "配置管理"
|
||
CONFIG[Nacos Config<br/>配置中心]
|
||
SECRET[配置加密<br/>敏感信息保护]
|
||
end
|
||
|
||
subgraph "监控告警"
|
||
MONITOR[Spring Boot Admin<br/>应用监控]
|
||
ALERT[告警系统<br/>异常通知]
|
||
LOG[ELK日志系统<br/>日志聚合分析]
|
||
end
|
||
|
||
NACOS --> LB
|
||
NACOS --> FEIGN
|
||
LB --> CB
|
||
FEIGN --> TRACE
|
||
CB --> RETRY
|
||
|
||
CONFIG --> SECRET
|
||
MONITOR --> ALERT
|
||
TRACE --> LOG
|
||
```
|
||
|
||
系统应用架构基于业务域划分,主要包括以下核心应用模块:
|
||
|
||
### 3.1 统一平台
|
||
- 单点登录:统一认证入口,支持多种登录方式
|
||
- 系统管理:组织机构、员工管理、角色权限管理、菜单配置等
|
||
- 流程节点提醒:工作流节点到期和状态变更提醒
|
||
|
||
### 3.2 营收系统
|
||
- 系统管理:水价管理、用户档案管理、更名过户管理等
|
||
- 抄表开账:册本管理、抄表录入、复核开账等
|
||
- 收费管理:柜台收费、特殊开账、柜台结账、批量缴费等
|
||
- 账务处理:预存调整、未销调整、已销调整、分账调整等
|
||
- 发票管理:发票查询、发票开具、电子发票等
|
||
- 代收业务:实时收费、银行代扣、银行托收等
|
||
- 环卫系统:计费核定、计费退补、计费减免等
|
||
- 业务工单:业务清单、上报清单、稽查工单、移表工单等
|
||
|
||
### 3.3 客户服务
|
||
- 微信、支付宝服务窗:账户绑定、用水查询、在线缴费等
|
||
- 历史账单:账单查询、用水分析、账单推送等
|
||
- 电子发票:发票申请、发票查询、发票下载等
|
||
- 营业网点:网点查询、网点导航、业务指南等
|
||
- 账户流水:流水查询、明细下载、交易统计等
|
||
- 微网厅:用户注册、信息查询、业务办理等
|
||
|
||
### 3.4 表务系统
|
||
- 表务工单:换表工单、移表工单、拆表工单、复装工单等
|
||
- 表务仓库:新表入库、水表检定、水表领用、水表出库等
|
||
- 水表参数与基础信息:水表厂家管理、水表型号管理等
|
||
- 物联网对接与数据同步:厂家设备信息管理、远程抄表数据同步等
|
||
|
||
### 3.5 报装管理
|
||
- 报装流程:报装申请、方案设计、合同签订、施工管理等
|
||
- 一户一表管理:改造计划、改造实施、用户转换等
|
||
|
||
### 3.6 统计分析
|
||
- 报表查询:标准报表、自定义报表、报表导出打印等
|
||
- 欠费查询:欠费情况统计、欠费用户明细、欠费分析等
|
||
- 缴费记录:缴费情况统计、缴费明细查询、缴费趋势分析等
|
||
- 用水分析:用水量统计、用水趋势分析、异常用水分析等
|
||
|
||
### 3.7 工程管理
|
||
- 工程申请:工程立项、材料提交、前期勘察等
|
||
- 工程施工:施工计划、施工派工、施工记录等
|
||
- 工程验收:验收申请、验收检查、验收记录等
|
||
- 工程查询:工程进度查询、工程资料查询、工程统计等
|
||
|
||
### 3.8 抄表APP
|
||
- 首页功能:首页展示、个人信息、快捷查询等
|
||
- 抄表功能:抄表任务、NFC抄表、扫码抄表、AI录入等
|
||
- 工单管理:问题上报、问题回填、代办工单、稽查工单等
|
||
|
||
### 3.9 接口服务
|
||
- API市场:API展示、API使用说明、API测试等
|
||
- API管理:API申请、API调度看板、接口服务配置管理等
|
||
- 接口权限管理:授权管理、白名单管理、安全策略等
|
||
- 系统对外接口:查询接口、业务处理接口、状态同步接口等
|
||
|
||
### 3.10 系统配置
|
||
- 水表参数:水表厂家、水表型号、水表量程等
|
||
- 地址参数:行政区划、地址编码、地址库等
|
||
- 价格体系:用水性质、水价标准、阶梯水价等
|
||
- 基本配置:系统参数、业务规则、打印模板等
|
||
- 催缴管理:催缴计划、催缴任务、催缴执行等
|
||
- 用户权限:菜单权限、功能权限、数据权限等
|
||
- 定时任务:任务配置、任务监控、任务日志等
|
||
|
||
## 4. 数据架构
|
||
|
||
系统数据架构基于客户关系数据库为核心和基础,实现客户全生命周期管理。
|
||
|
||
### 4.1 数据分层
|
||
- 数据采集层:负责从各业务系统和物联网设备采集原始数据
|
||
- 数据存储层:统一数据存储,实现分布式数据管理
|
||
- 数据服务层:提供数据服务接口
|
||
- 数据展现层:提供数据分析和可视化功能
|
||
|
||
### 4.2 OpenGauss数据库架构
|
||
|
||
#### 4.2.1 主从高可用架构
|
||
|
||
```mermaid
|
||
graph TB
|
||
subgraph "OpenGauss高可用集群"
|
||
MASTER[("OpenGauss主库<br/>Primary Node<br/>读写操作")]
|
||
STANDBY[("OpenGauss备库<br/>Standby Node<br/>只读操作")]
|
||
CASCADE[("OpenGauss级联备库<br/>Cascade Standby<br/>负载分担")]
|
||
end
|
||
|
||
subgraph "应用层"
|
||
APP1[应用服务器1]
|
||
APP2[应用服务器2]
|
||
APP3[应用服务器3]
|
||
end
|
||
|
||
subgraph "连接池"
|
||
POOL[连接池<br/>HikariCP<br/>Druid]
|
||
end
|
||
|
||
subgraph "监控管理"
|
||
MON[OpenGauss Monitor<br/>性能监控]
|
||
BACKUP[定时备份<br/>gs_backup]
|
||
end
|
||
|
||
APP1 --> POOL
|
||
APP2 --> POOL
|
||
APP3 --> POOL
|
||
POOL --> MASTER
|
||
POOL --> STANDBY
|
||
POOL --> CASCADE
|
||
|
||
MASTER -.->|流复制| STANDBY
|
||
STANDBY -.->|级联复制| CASCADE
|
||
|
||
MON --> MASTER
|
||
MON --> STANDBY
|
||
BACKUP --> MASTER
|
||
```
|
||
|
||
#### 4.2.2 分片存储架构
|
||
|
||
```mermaid
|
||
graph TB
|
||
subgraph "OpenGauss分布式架构"
|
||
subgraph "协调节点"
|
||
CN1[协调节点1<br/>Coordinator Node]
|
||
CN2[协调节点2<br/>Coordinator Node]
|
||
end
|
||
|
||
subgraph "数据节点组1"
|
||
DN1_1[数据节点1-主<br/>Datanode Primary]
|
||
DN1_2[数据节点1-备<br/>Datanode Standby]
|
||
end
|
||
|
||
subgraph "数据节点组2"
|
||
DN2_1[数据节点2-主<br/>Datanode Primary]
|
||
DN2_2[数据节点2-备<br/>Datanode Standby]
|
||
end
|
||
|
||
subgraph "GTM节点"
|
||
GTM[全局事务管理器<br/>GTM Master]
|
||
GTM_S[GTM备节点<br/>GTM Standby]
|
||
end
|
||
end
|
||
|
||
CN1 --> DN1_1
|
||
CN1 --> DN2_1
|
||
CN2 --> DN1_1
|
||
CN2 --> DN2_1
|
||
|
||
DN1_1 -.->|主备同步| DN1_2
|
||
DN2_1 -.->|主备同步| DN2_2
|
||
|
||
GTM -.->|备份| GTM_S
|
||
CN1 --> GTM
|
||
CN2 --> GTM
|
||
```
|
||
|
||
#### 4.2.3 数据安全架构
|
||
|
||
```mermaid
|
||
graph TB
|
||
subgraph "安全防护层"
|
||
TDE[透明数据加密<br/>TDE]
|
||
RLS[行级安全<br/>Row Level Security]
|
||
MASK[动态数据脱敏<br/>Dynamic Data Masking]
|
||
AUDIT[三权分立审计<br/>Separated Audit]
|
||
end
|
||
|
||
subgraph "访问控制层"
|
||
RBAC[基于角色的访问控制<br/>RBAC]
|
||
LDAP[LDAP集成认证<br/>External Auth]
|
||
SSL[SSL/TLS加密传输<br/>Encrypted Transport]
|
||
end
|
||
|
||
subgraph "数据存储层"
|
||
ENCRYPT[存储层加密<br/>Storage Encryption]
|
||
COMPRESS[数据压缩<br/>Data Compression]
|
||
BACKUP_ENC[备份加密<br/>Backup Encryption]
|
||
end
|
||
|
||
TDE --> ENCRYPT
|
||
RLS --> RBAC
|
||
MASK --> ENCRYPT
|
||
AUDIT --> BACKUP_ENC
|
||
RBAC --> SSL
|
||
LDAP --> SSL
|
||
```
|
||
|
||
### 4.3 数据模型设计
|
||
- **客户信息模型**:包含客户基础信息、表卡信息、账户信息、联系人信息等
|
||
- **业务数据模型**:抄表数据、收费数据、账务数据、发票数据等
|
||
- **工单数据模型**:表务工单、报装工单、业务工单等
|
||
- **配置数据模型**:系统参数、水表参数、价格体系等
|
||
- **报表数据模型**:统计数据、分析数据、预测数据等
|
||
- **物联网数据模型**:设备信息、状态信息、实时数据等
|
||
|
||
### 4.4 数据集成与共享
|
||
- **统一数据标准**:定义统一的数据标准和数据字典,符合OpenGauss规范
|
||
- **数据集成机制**:采用OpenGauss XA事务实现系统间的数据一致性
|
||
- **数据共享机制**:基于OpenGauss外部数据包装器(FDW)实现跨库数据访问
|
||
- **数据同步策略**:支持实时流复制、定时数据同步、批量ETL处理等
|
||
|
||
### 4.5 OpenGauss特性应用
|
||
|
||
#### 4.5.1 性能优化特性
|
||
- **向量化执行引擎**:批量数据处理,提升OLAP查询性能30-50%
|
||
- **列存储引擎**:统计报表类查询,压缩比高达10:1
|
||
- **分区表技术**:按月份分区存储抄表数据,支持分区裁剪
|
||
- **并行查询**:复杂统计查询自动并行执行
|
||
- **智能优化器**:自适应查询计划,持续性能优化
|
||
|
||
#### 4.5.2 企业级特性
|
||
- **在线扩容**:支持不停机新增数据节点
|
||
- **故障自愈**:主备节点故障自动切换,RTO < 10秒
|
||
- **读写分离**:自动路由读请求到备节点,减轻主库压力
|
||
- **负载均衡**:连接池级别的智能负载均衡
|
||
- **全量/增量备份**:支持热备份,最小备份粒度到事务级
|
||
|
||
## 5. 安全架构
|
||
|
||
系统安全架构基于OpenGauss数据库的企业级安全特性,满足等保三级要求和国产化安全标准:
|
||
|
||
### 5.1 网络安全
|
||
- **边界防护**:防火墙、入侵检测/防御系统
|
||
- **访问控制**:基于角色的访问控制(RBAC)
|
||
- **通信安全**:SSL/TLS加密传输,支持国密算法
|
||
- **安全监控**:实时监控网络安全状态和异常访问
|
||
|
||
### 5.2 OpenGauss数据安全架构
|
||
|
||
#### 5.2.1 数据加密安全
|
||
|
||
```mermaid
|
||
graph TB
|
||
subgraph "加密层级"
|
||
L1[传输层加密<br/>SSL/TLS/国密SM]
|
||
L2[存储层加密<br/>TDE透明数据加密]
|
||
L3[字段级加密<br/>敏感字段加密]
|
||
L4[备份加密<br/>备份文件加密]
|
||
end
|
||
|
||
subgraph "密钥管理"
|
||
KMS[密钥管理系统<br/>Key Management]
|
||
HSM[硬件安全模块<br/>Hardware Security]
|
||
ROT[密钥轮换<br/>Key Rotation]
|
||
end
|
||
|
||
subgraph "国密算法"
|
||
SM2[SM2椭圆曲线<br/>非对称加密]
|
||
SM3[SM3哈希算法<br/>消息摘要]
|
||
SM4[SM4分组密码<br/>对称加密]
|
||
end
|
||
|
||
L1 --> KMS
|
||
L2 --> HSM
|
||
L3 --> ROT
|
||
L4 --> KMS
|
||
|
||
KMS --> SM2
|
||
HSM --> SM3
|
||
ROT --> SM4
|
||
```
|
||
|
||
#### 5.2.2 访问控制安全
|
||
|
||
```mermaid
|
||
graph TB
|
||
subgraph "身份认证"
|
||
AUTH1[用户名密码认证]
|
||
AUTH2[LDAP集成认证]
|
||
AUTH3[Kerberos认证]
|
||
AUTH4[证书认证]
|
||
end
|
||
|
||
subgraph "权限控制"
|
||
RBAC[基于角色的权限控制<br/>Role-Based Access Control]
|
||
RLS[行级安全策略<br/>Row Level Security]
|
||
CLS[列级安全控制<br/>Column Level Security]
|
||
TENANT[多租户数据隔离<br/>Multi-Tenant Isolation]
|
||
end
|
||
|
||
subgraph "审计监控"
|
||
AUDIT[操作审计日志<br/>Audit Logging]
|
||
MONITOR[实时安全监控<br/>Security Monitoring]
|
||
ALERT[安全告警<br/>Security Alert]
|
||
REPORT[合规报告<br/>Compliance Report]
|
||
end
|
||
|
||
AUTH1 --> RBAC
|
||
AUTH2 --> RLS
|
||
AUTH3 --> CLS
|
||
AUTH4 --> TENANT
|
||
|
||
RBAC --> AUDIT
|
||
RLS --> MONITOR
|
||
CLS --> ALERT
|
||
TENANT --> REPORT
|
||
```
|
||
|
||
### 5.3 数据安全特性
|
||
- **透明数据加密(TDE)**:自动加密存储数据,支持SM4国密算法
|
||
- **行级安全(RLS)**:基于用户角色的行级数据访问控制
|
||
- **列级权限**:敏感字段的精细化访问控制
|
||
- **动态脱敏**:查询时自动脱敏显示敏感信息
|
||
- **数据备份安全**:备份文件自动加密,支持增量备份
|
||
- **审计日志**:完整记录所有数据库操作,支持合规审计
|
||
|
||
### 5.4 多租户安全隔离
|
||
- **逻辑隔离**:基于tenant_id的数据隔离
|
||
- **连接隔离**:租户间连接池隔离
|
||
- **权限隔离**:租户级别的权限管理
|
||
- **资源隔离**:CPU、内存、IO资源限制
|
||
|
||
### 5.5 应用安全
|
||
- **身份认证**:多因素认证,支持短信验证码、邮箱验证等
|
||
- **授权管理**:细粒度的权限控制,支持菜单、按钮、数据权限
|
||
- **安全审计**:用户操作审计,关键业务操作全程记录
|
||
- **密码策略**:密码复杂度、定期更换、失败锁定等安全策略
|
||
- **会话管理**:会话超时、并发限制、单点登录等
|
||
|
||
### 5.6 接口安全
|
||
- **接口认证**:基于JWT Token的接口认证
|
||
- **接口授权**:基于角色的接口授权和权限验证
|
||
- **接口加密**:敏感数据的加密传输,支持国密算法
|
||
- **接口防护**:防重放、防篡改、防SQL注入等安全措施
|
||
- **接口限流**:基于IP、用户、应用的多维度限流策略
|
||
|
||
## 6. 部署架构
|
||
|
||
系统采用集中部署的模式,基于集团私有云环境进行部署。
|
||
|
||
### 6.1 物理部署
|
||
- **生产环境**:高可用集群部署
|
||
- 应用服务器:2台或以上服务器,负载均衡
|
||
- **OpenGauss数据库集群**:主从+级联备架构,支持自动故障切换
|
||
- 缓存服务器:Redis集群
|
||
- 文件服务器:冗余存储
|
||
- **灾备环境**:异地灾备,定期数据同步,支持OpenGauss流复制
|
||
- **测试环境**:用于系统测试和验证,单节点OpenGauss部署
|
||
- **开发环境**:用于系统开发和集成测试,单节点OpenGauss部署
|
||
|
||
### 6.2 逻辑部署
|
||
- **应用服务器集群**:负责业务逻辑处理,支持水平扩展
|
||
- **OpenGauss数据库集群**:负责数据存储和管理,提供高可用保障
|
||
- **文件服务器**:负责文档和附件存储,支持分布式存储
|
||
- **缓存服务器**:Redis集群提高系统性能
|
||
- **负载均衡服务器**:实现请求分发和负载均衡
|
||
- **移动应用服务**:提供移动端API服务
|
||
- **API网关**:统一的接口管理和控制
|
||
|
||
### 6.3 容器部署
|
||
- 基于Docker容器技术实现微服务部署
|
||
- 使用Kubernetes进行容器编排和管理
|
||
- 支持容器的自动扩缩容和故障转移
|
||
- 实现服务的灰度发布和版本控制
|
||
|
||
## 7. 接口架构
|
||
|
||
系统提供标准化的接口,实现与外部系统的集成和数据交换。
|
||
|
||
### 7.1 外部接口
|
||
- 银行接口:实现与银行系统的对接,支持代扣、托收等功能
|
||
- 支付宝/微信接口:支持在线支付功能
|
||
- 短信接口:支持短信通知和验证码功能
|
||
- 集抄系统接口:实现与智能水表集中抄表系统的对接
|
||
- 政务系统接口:实现与地方政务平台和政务APP的对接
|
||
- 消火栓系统接口:实现与消火栓系统的对接
|
||
- 环卫系统接口:实现与环卫系统的对接
|
||
- OA系统接口:实现与OA系统的工作流对接
|
||
|
||
### 7.2 内部接口
|
||
- ESB服务接口:系统内部模块间的数据交换
|
||
- 报表接口:提供报表数据查询和生成功能
|
||
- 查询接口:提供数据查询功能
|
||
- 业务处理接口:提供业务处理功能
|
||
- 消息通知接口:提供消息推送和通知功能
|
||
- 工作流接口:提供工作流处理和状态查询功能
|
||
|
||
### 7.3 接口标准
|
||
- 接口协议:RESTful API、WebService、消息队列等
|
||
- 数据格式:JSON、XML等
|
||
- 接口安全:身份认证、授权、加密传输等
|
||
- 接口文档:统一的接口文档和示例代码
|
||
- 接口测试:提供接口测试工具和环境
|
||
|
||
### 7.4 接口服务管理
|
||
- API网关:统一的接口入口和管理
|
||
- 服务注册与发现:服务的自动注册和发现
|
||
- 服务路由:根据请求参数进行服务路由
|
||
- 服务降级:在服务不可用时提供降级策略
|
||
- 服务监控:实时监控服务的可用性和性能
|
||
---
|
||
|
||
# 福建水务营收系统模块功能设计文档
|
||
|
||
## 文档信息
|
||
| 项目信息 | 详情 |
|
||
|---------|------|
|
||
| **项目名称** | 福建水务营收系统 |
|
||
| **文档类型** | 概要设计文档 |
|
||
| **技术框架** | RuoYi-Vue-Pro + yudao-ui-admin-vue3 |
|
||
| **文档版本** | v1.0 |
|
||
| **编写日期** | 2024-12-19 |
|
||
| **文档状态** | ✅ 已完成 |
|
||
|
||
## 目录
|
||
- [福建水务营收系统模块功能设计文档](#福建水务营收系统模块功能设计文档)
|
||
- [文档信息](#文档信息)
|
||
- [目录](#目录)
|
||
- [一、系统整体架构](#一系统整体架构)
|
||
- [1.1 系统架构图](#11-系统架构图)
|
||
- [1.2 技术架构图](#12-技术架构图)
|
||
- [1.3 业务架构图](#13-业务架构图)
|
||
- [二、统一平台](#二统一平台)
|
||
- [2.1 单点登录](#21-单点登录)
|
||
- [2.2 系统管理](#22-系统管理)
|
||
- [三、营收系统](#三营收系统)
|
||
- [3.1 系统管理](#31-系统管理)
|
||
- [3.2 抄表开账](#32-抄表开账)
|
||
- [3.2.1 业务流程图](#321-业务流程图)
|
||
- [3.2.2 主要功能](#322-主要功能)
|
||
- [3.2.3 核心接口定义](#323-核心接口定义)
|
||
- [3.2.4 前端界面设计](#324-前端界面设计)
|
||
- [3.3 收费管理](#33-收费管理)
|
||
- [3.3.1 业务流程图](#331-业务流程图)
|
||
- [3.3.2 主要功能](#332-主要功能)
|
||
- [3.3.3 核心接口定义](#333-核心接口定义)
|
||
- [3.4 账务处理](#34-账务处理)
|
||
- [3.4.1 业务流程图](#341-业务流程图)
|
||
- [3.4.2 主要功能](#342-主要功能)
|
||
- [3.4.3 核心接口定义](#343-核心接口定义)
|
||
- [3.5 发票管理](#35-发票管理)
|
||
- [3.5.1 业务流程图](#351-业务流程图)
|
||
- [3.5.2 核心接口定义](#352-核心接口定义)
|
||
- [3.6 代收业务](#36-代收业务)
|
||
- [3.7 环卫系统](#37-环卫系统)
|
||
- [3.8 业务工单](#38-业务工单)
|
||
- [四、表务系统](#四表务系统)
|
||
- [4.1 表务工单](#41-表务工单)
|
||
- [4.2 表务仓库](#42-表务仓库)
|
||
- [4.3 水表参数与基础信息](#43-水表参数与基础信息)
|
||
- [4.4 物联网对接与数据同步](#44-物联网对接与数据同步)
|
||
- [五、报装系统](#五报装系统)
|
||
- [5.1 报装流程](#51-报装流程)
|
||
- [5.2 一户一表管理](#52-一户一表管理)
|
||
- [六、客户服务](#六客户服务)
|
||
- [6.1 微信、支付宝服务窗](#61-微信支付宝服务窗)
|
||
- [6.2 历史账单](#62-历史账单)
|
||
- [6.3 电子发票](#63-电子发票)
|
||
- [6.4 营业网点](#64-营业网点)
|
||
- [6.5 账户流水](#65-账户流水)
|
||
- [6.6 微网厅](#66-微网厅)
|
||
- [七、系统配置](#七系统配置)
|
||
- [7.1 水表参数](#71-水表参数)
|
||
- [7.2 地址参数](#72-地址参数)
|
||
- [7.3 价格体系](#73-价格体系)
|
||
- [7.4 基本配置](#74-基本配置)
|
||
- [7.5 催缴管理](#75-催缴管理)
|
||
- [7.6 用户权限](#76-用户权限)
|
||
- [7.7 定时任务](#77-定时任务)
|
||
- [八、系统接口](#八系统接口)
|
||
- [8.1 银行接口](#81-银行接口)
|
||
- [8.2 支付宝/微信接口](#82-支付宝微信接口)
|
||
- [8.3 短信接口](#83-短信接口)
|
||
- [8.4 集抄系统接口](#84-集抄系统接口)
|
||
- [8.5 政务系统接口](#85-政务系统接口)
|
||
- [8.6 消火栓系统接口](#86-消火栓系统接口)
|
||
- [8.7 其他系统对接](#87-其他系统对接)
|
||
- [九、统计分析](#九统计分析)
|
||
- [9.1 报表查询](#91-报表查询)
|
||
- [9.2 欠费查询](#92-欠费查询)
|
||
- [9.3 缴费记录](#93-缴费记录)
|
||
- [9.4 用水分析](#94-用水分析)
|
||
- [十、工程管理](#十工程管理)
|
||
- [10.1 工程申请](#101-工程申请)
|
||
- [10.2 工程施工](#102-工程施工)
|
||
- [10.3 工程验收](#103-工程验收)
|
||
- [10.4 工程查询](#104-工程查询)
|
||
- [十一、抄表APP](#十一抄表app)
|
||
- [11.1 首页功能](#111-首页功能)
|
||
- [11.2 抄表功能](#112-抄表功能)
|
||
- [11.3 工单管理](#113-工单管理)
|
||
- [十二、接口服务](#十二接口服务)
|
||
- [12.1 API市场](#121-api市场)
|
||
- [12.2 API管理](#122-api管理)
|
||
- [12.3 接口权限管理](#123-接口权限管理)
|
||
- [12.4 系统对外接口](#124-系统对外接口)
|
||
- [系统集成架构](#系统集成架构)
|
||
- [前后端集成架构](#前后端集成架构)
|
||
- [技术栈整合方案](#技术栈整合方案)
|
||
|
||
## 一、系统整体架构
|
||
|
||
福建水务营收系统采用现代化的分布式微服务架构,基于RuoYi-Vue-Pro后端框架和yudao-ui-admin-vue3前端框架构建,为水务企业提供完整的营收管理解决方案。
|
||
|
||
### 1.1 系统架构图
|
||
|
||
```mermaid
|
||
graph TB
|
||
subgraph "用户层"
|
||
A1[管理员用户]
|
||
A2[抄表员]
|
||
A3[收费员]
|
||
A4[客户用户]
|
||
end
|
||
|
||
subgraph "接入层"
|
||
B1[PC端管理后台<br/>yudao-ui-admin-vue3]
|
||
B2[移动端抄表APP<br/>uni-app]
|
||
B3[微信小程序]
|
||
B4[支付宝小程序]
|
||
B5[Web客户端]
|
||
end
|
||
|
||
subgraph "网关层"
|
||
C1[API网关<br/>Spring Cloud Gateway]
|
||
C2[负载均衡<br/>Nginx]
|
||
end
|
||
|
||
subgraph "服务层"
|
||
D1[用户认证服务<br/>Spring Security + JWT]
|
||
D2[营收管理服务<br/>RuoYi-Vue-Pro]
|
||
D3[表务管理服务]
|
||
D4[报装管理服务]
|
||
D5[客户服务]
|
||
D6[系统管理服务]
|
||
end
|
||
|
||
subgraph "中间件层"
|
||
E1[(Redis缓存<br/>6.0+)]
|
||
E2[RabbitMQ消息队列]
|
||
E3[Elasticsearch搜索]
|
||
E4[MinIO文件存储]
|
||
end
|
||
|
||
subgraph "数据层"
|
||
F1[(主数据库<br/>OpenGauss 5.0+)]
|
||
F2[(从数据库<br/>OpenGauss 5.0+)]
|
||
F3[(历史数据库<br/>OpenGauss 5.0+)]
|
||
end
|
||
|
||
subgraph "外部系统"
|
||
G1[银行系统]
|
||
G2[支付宝/微信]
|
||
G3[短信平台]
|
||
G4[集抄系统]
|
||
G5[政务平台]
|
||
end
|
||
|
||
A1 --> B1
|
||
A2 --> B2
|
||
A3 --> B1
|
||
A4 --> B3
|
||
A4 --> B4
|
||
A4 --> B5
|
||
|
||
B1 --> C2
|
||
B2 --> C2
|
||
B3 --> C2
|
||
B4 --> C2
|
||
B5 --> C2
|
||
|
||
C2 --> C1
|
||
C1 --> D1
|
||
C1 --> D2
|
||
C1 --> D3
|
||
C1 --> D4
|
||
C1 --> D5
|
||
C1 --> D6
|
||
|
||
D1 --> E1
|
||
D2 --> E1
|
||
D2 --> E2
|
||
D3 --> E1
|
||
D4 --> E3
|
||
D5 --> E4
|
||
D6 --> E1
|
||
|
||
D2 --> F1
|
||
D3 --> F1
|
||
D4 --> F2
|
||
D5 --> F2
|
||
D6 --> F3
|
||
|
||
D2 --> G1
|
||
D2 --> G2
|
||
D5 --> G3
|
||
D3 --> G4
|
||
D4 --> G5
|
||
```
|
||
|
||
### 1.2 技术架构图
|
||
|
||
```mermaid
|
||
graph TB
|
||
subgraph "前端技术栈"
|
||
FE1[Vue 3.x]
|
||
FE2[TypeScript 4.x]
|
||
FE3[Element Plus]
|
||
FE4[Vite 4.x]
|
||
FE5[Pinia状态管理]
|
||
end
|
||
|
||
subgraph "后端技术栈"
|
||
BE1[Spring Boot 3.x]
|
||
BE2[Spring Security 6.x]
|
||
BE3[MyBatis Plus 3.x]
|
||
BE4[Spring Cloud Gateway]
|
||
BE5[Hibernate Validator]
|
||
end
|
||
|
||
subgraph "数据库技术"
|
||
DB1[OpenGauss 5.0+]
|
||
DB2[Redis 6.0+]
|
||
DB3[HikariCP连接池]
|
||
DB4[MyBatis-Plus代码生成]
|
||
end
|
||
|
||
subgraph "中间件技术"
|
||
MW1[RabbitMQ 3.x]
|
||
MW2[Elasticsearch 8.x]
|
||
MW3[MinIO对象存储]
|
||
MW4[XXL-JOB定时任务]
|
||
end
|
||
|
||
subgraph "运维技术"
|
||
OPS1[Docker容器化]
|
||
OPS2[Jenkins CI/CD]
|
||
OPS3[Prometheus监控]
|
||
OPS4[ELK日志分析]
|
||
end
|
||
|
||
subgraph "安全技术"
|
||
SEC1[JWT Token认证]
|
||
SEC2[OAuth2.0授权]
|
||
SEC3[AES数据加密]
|
||
SEC4[RSA签名验证]
|
||
end
|
||
|
||
FE1 --> FE2
|
||
FE2 --> FE3
|
||
FE3 --> FE4
|
||
FE4 --> FE5
|
||
|
||
BE1 --> BE2
|
||
BE2 --> BE3
|
||
BE3 --> BE4
|
||
BE4 --> BE5
|
||
|
||
DB1 --> DB2
|
||
DB2 --> DB3
|
||
DB3 --> DB4
|
||
|
||
MW1 --> MW2
|
||
MW2 --> MW3
|
||
MW3 --> MW4
|
||
|
||
OPS1 --> OPS2
|
||
OPS2 --> OPS3
|
||
OPS3 --> OPS4
|
||
|
||
SEC1 --> SEC2
|
||
SEC2 --> SEC3
|
||
SEC3 --> SEC4
|
||
```
|
||
|
||
### 1.3 业务架构图
|
||
|
||
```mermaid
|
||
graph TB
|
||
subgraph "统一平台层"
|
||
UP1[单点登录]
|
||
UP2[系统管理]
|
||
UP3[用户权限]
|
||
UP4[组织架构]
|
||
end
|
||
|
||
subgraph "核心业务层"
|
||
CB1[客户管理]
|
||
CB2[抄表管理]
|
||
CB3[收费管理]
|
||
CB4[账务管理]
|
||
CB5[表务管理]
|
||
CB6[报装管理]
|
||
end
|
||
|
||
subgraph "增值服务层"
|
||
VS1[客户服务]
|
||
VS2[移动应用]
|
||
VS3[微信服务]
|
||
VS4[电子发票]
|
||
VS5[在线支付]
|
||
end
|
||
|
||
subgraph "数据服务层"
|
||
DS1[统计分析]
|
||
DS2[报表查询]
|
||
DS3[数据导出]
|
||
DS4[决策支持]
|
||
end
|
||
|
||
subgraph "集成服务层"
|
||
IS1[银行接口]
|
||
IS2[支付接口]
|
||
IS3[短信接口]
|
||
IS4[集抄接口]
|
||
IS5[政务接口]
|
||
end
|
||
|
||
UP1 --> CB1
|
||
UP2 --> CB2
|
||
UP3 --> CB3
|
||
UP4 --> CB4
|
||
|
||
CB1 --> VS1
|
||
CB2 --> VS2
|
||
CB3 --> VS3
|
||
CB4 --> VS4
|
||
CB5 --> VS5
|
||
CB6 --> VS1
|
||
|
||
VS1 --> DS1
|
||
VS2 --> DS2
|
||
VS3 --> DS3
|
||
VS4 --> DS4
|
||
VS5 --> DS1
|
||
|
||
DS1 --> IS1
|
||
DS2 --> IS2
|
||
DS3 --> IS3
|
||
DS4 --> IS4
|
||
DS1 --> IS5
|
||
```
|
||
|
||
## 二、统一平台
|
||
|
||
统一平台是客户服务平台的综合展示平台,基于RuoYi-Vue-Pro和yudao-ui-admin-vue3框架构建,包含日常工作功能和客户全部的信息,是系统的基础功能模块。
|
||
|
||
### 2.1 单点登录
|
||
|
||
单点登录模块基于Spring Security和JWT实现用户一次登录即可访问系统中所有应用的功能,主要特点包括:
|
||
|
||
- 支持通过用户名、密码进行身份认证
|
||
- 支持OAuth2.0授权码+PKCE模式的第三方登录
|
||
- 支持手机号+短信验证码登录方式
|
||
- 支持多因素认证(MFA)增强安全性
|
||
- 根据登录人员所在公司的不同,显示不同的系统名称和界面风格
|
||
- 提供流程节点到期提醒功能
|
||
- Token自动刷新机制,提升用户体验
|
||
|
||
### 2.2 系统管理
|
||
|
||
系统管理模块基于RuoYi-Vue-Pro框架的现成功能,提供对系统基础参数的配置管理功能,主要包括:
|
||
|
||
- 组织机构管理:
|
||
- 支持多级组织结构的管理
|
||
- 支持组织机构导入导出
|
||
- 组织关系树形展示
|
||
- 组织数据权限控制
|
||
- 员工管理:
|
||
- 系统操作人员的基本信息管理
|
||
- 用户分配角色与权限
|
||
- 用户状态管理(启用/禁用)
|
||
- 用户密码安全策略
|
||
- 用户操作日志记录
|
||
- 角色权限管理:
|
||
- 基于RBAC模型的权限控制
|
||
- 支持数据权限精细化控制
|
||
- 支持多租户的权限隔离
|
||
- 基于菜单、按钮级别的权限管理
|
||
- 系统菜单配置:
|
||
- 支持自定义系统菜单和功能模块
|
||
- 菜单多级分类管理
|
||
- 动态路由生成
|
||
- 菜单权限配置
|
||
- 数据字典管理:
|
||
- 维护系统使用的各类基础代码数据
|
||
- 支持字典项多级管理
|
||
- 支持字典缓存,提高访问性能
|
||
- 系统监控:
|
||
- 在线用户监控与管理
|
||
- 服务器性能监控
|
||
- 定时任务执行状态监控
|
||
- 系统缓存监控与管理
|
||
- 系统日志管理:
|
||
- 记录用户登录日志
|
||
- 记录操作日志,支持操作回溯
|
||
- 记录系统异常日志,便于问题排查
|
||
- 短信管理:
|
||
- 支持阿里云、腾讯云等多家短信渠道
|
||
- 短信模板配置管理
|
||
- 短信发送日志记录
|
||
- 租户管理:
|
||
- 支持SaaS多租户
|
||
- 租户套餐配置
|
||
- 租户数据隔离
|
||
- 租户资源管理
|
||
- 配置管理:
|
||
- 系统参数配置
|
||
- 通知公告管理
|
||
- 定时任务配置
|
||
|
||
## 三、营收系统
|
||
|
||
营收系统是水务业务系统的核心组成部分,负责抄表、收费、账务处理等关键业务功能。
|
||
|
||
### 3.1 系统管理
|
||
|
||
营收系统的基础管理功能,包括:
|
||
|
||
- 水价管理:不同用户类型的水价标准管理,支持阶梯水价
|
||
- 用户档案管理:维护用户基本信息、用水信息、账户信息等
|
||
- 客户分组管理
|
||
- 集收管理
|
||
- 客户基础信息管理
|
||
- 定额管理
|
||
- 客户优惠方案设置
|
||
- 更名过户管理:处理用户变更、过户等业务
|
||
- 注销报停管理:处理用户注销、暂停用水等业务
|
||
|
||
### 3.2 抄表开账
|
||
|
||
抄表开账模块负责水表读数的采集和账单生成,是营收系统的核心业务模块。
|
||
|
||
#### 3.2.1 业务流程图
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
Start([开始抄表周期]) --> BookPlan[制定抄表计划]
|
||
BookPlan --> CreateBook[生成抄表册本]
|
||
CreateBook --> AssignReader[分配抄表员]
|
||
|
||
AssignReader --> ReadingStart[开始抄表]
|
||
ReadingStart --> ReadingType{抄表方式}
|
||
|
||
ReadingType -->|人工抄表| ManualReading[现场抄表录入]
|
||
ReadingType -->|远程抄表| RemoteReading[远程采集数据]
|
||
ReadingType -->|客户自报| SelfReporting[客户自主上报]
|
||
|
||
ManualReading --> DataValidation[数据校验]
|
||
RemoteReading --> DataValidation
|
||
SelfReporting --> DataValidation
|
||
|
||
DataValidation --> ValidationResult{校验结果}
|
||
ValidationResult -->|异常| ExceptionHandle[异常处理]
|
||
ValidationResult -->|正常| DataReview[数据复核]
|
||
|
||
ExceptionHandle --> ReviewException[人工审核异常]
|
||
ReviewException --> DataReview
|
||
|
||
DataReview --> ReviewResult{复核结果}
|
||
ReviewResult -->|退回| ReadingStart
|
||
ReviewResult -->|通过| BillGeneration[生成账单]
|
||
|
||
BillGeneration --> CalcWaterFee[计算水费]
|
||
CalcWaterFee --> CalcSewageFee[计算污水费]
|
||
CalcSewageFee --> CalcOtherFee[计算其他费用]
|
||
CalcOtherFee --> BillReview[账单审核]
|
||
|
||
BillReview --> BillResult{审核结果}
|
||
BillResult -->|退回| BillGeneration
|
||
BillResult -->|通过| BillConfirm[账单确认]
|
||
|
||
BillConfirm --> SendNotification[发送缴费通知]
|
||
SendNotification --> End([完成开账])
|
||
```
|
||
|
||
#### 3.2.2 主要功能
|
||
|
||
**册本管理**:册本基本信息的维护和管理
|
||
- 册本创建与配置
|
||
- 抄表路线规划
|
||
- 抄表员分配
|
||
- 抄表周期设置
|
||
|
||
**抄表录入**:支持多种抄表方式
|
||
- 手工抄表:现场抄表、批量录入
|
||
- 智能抄表:远程数据采集、自动同步
|
||
- 自报抄表:客户自主上报、在线提交
|
||
|
||
**抄表数据审核**:确保数据质量
|
||
- 数据校验:读数合理性检查、用量异常检测
|
||
- 异常处理:异常数据标记、人工处理
|
||
- 开账处理:数据确认、账单生成
|
||
|
||
**追加抄表**:支持非周期性特殊抄表
|
||
- 补抄管理:漏抄数据补录
|
||
- 特殊抄表:临时抄表需求
|
||
- 调整抄表:读数错误修正
|
||
|
||
#### 3.2.3 核心接口定义
|
||
|
||
**抄表管理主要接口**:
|
||
```java
|
||
@RestController
|
||
@RequestMapping("/admin-api/water/reading")
|
||
@Tag(name = "管理后台 - 抄表管理")
|
||
public class MeterReadingController {
|
||
|
||
@PostMapping("/create")
|
||
@Operation(summary = "创建抄表记录")
|
||
public CommonResult<Long> createReading(@Valid @RequestBody MeterReadingSaveReqVO createReqVO);
|
||
|
||
@PostMapping("/batch-create")
|
||
@Operation(summary = "批量创建抄表记录")
|
||
public CommonResult<MeterReadingBatchRespVO> batchCreateReading(@Valid @RequestBody MeterReadingBatchReqVO batchReqVO);
|
||
|
||
@PostMapping("/review")
|
||
@Operation(summary = "抄表数据复核")
|
||
public CommonResult<Boolean> reviewReading(@Valid @RequestBody MeterReadingReviewReqVO reviewReqVO);
|
||
|
||
@PostMapping("/generate-bill")
|
||
@Operation(summary = "生成账单")
|
||
public CommonResult<BillGenerateRespVO> generateBill(@Valid @RequestBody ReadingBillReqVO reqVO);
|
||
}
|
||
```
|
||
|
||
**接口设计要点**:
|
||
- 遵循RESTful设计规范,统一的请求响应格式
|
||
- 支持批量操作提高处理效率
|
||
- 完整的数据校验和异常处理机制
|
||
- 集成RuoYi-Vue-Pro的权限控制和日志记录
|
||
|
||
#### 3.2.4 前端界面设计
|
||
|
||
**抄表管理页面结构**:
|
||
```vue
|
||
<template>
|
||
<ContentWrap>
|
||
<!-- 查询条件 -->
|
||
<el-form class="search-form" inline>
|
||
<el-form-item label="抄表日期">
|
||
<el-date-picker v-model="queryParams.readingDate" type="daterange" />
|
||
</el-form-item>
|
||
<el-form-item label="抄表状态">
|
||
<el-select v-model="queryParams.status">
|
||
<el-option label="待复核" value="pending" />
|
||
<el-option label="已通过" value="approved" />
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item>
|
||
<el-button type="primary" @click="handleQuery">查询</el-button>
|
||
<el-button @click="resetQuery">重置</el-button>
|
||
</el-form-item>
|
||
</el-form>
|
||
|
||
<!-- 操作按钮 -->
|
||
<el-row class="mb-10px">
|
||
<el-button type="primary" @click="handleAdd">新增抄表</el-button>
|
||
<el-button type="success" @click="handleBatchAdd">批量抄表</el-button>
|
||
<el-button type="warning" @click="handleExport">导出数据</el-button>
|
||
</el-row>
|
||
|
||
<!-- 数据表格 -->
|
||
<el-table v-loading="loading" :data="readingList">
|
||
<el-table-column prop="readingCode" label="抄表编号" width="180" />
|
||
<el-table-column prop="customerName" label="客户名称" />
|
||
<el-table-column prop="meterCode" label="水表编号" />
|
||
<el-table-column prop="readingValue" label="本次读数" />
|
||
<el-table-column prop="waterUsage" label="用水量" />
|
||
<el-table-column prop="readingDate" label="抄表日期" />
|
||
<el-table-column prop="status" label="状态">
|
||
<template #default="{ row }">
|
||
<dict-tag :type="DICT_TYPE.READING_STATUS" :value="row.status" />
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="操作" width="200" fixed="right">
|
||
<template #default="{ row }">
|
||
<el-button link @click="handleUpdate(row)">编辑</el-button>
|
||
<el-button link @click="handleReview(row)">复核</el-button>
|
||
<el-button link type="danger" @click="handleDelete(row)">删除</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</ContentWrap>
|
||
</template>
|
||
```
|
||
|
||
**前端页面功能特性**:
|
||
- 响应式设计:基于Element Plus的现代化UI组件
|
||
- 数据表格:支持分页、排序、筛选等功能
|
||
- 表单验证:前端数据校验和错误提示
|
||
- 批量操作:支持批量抄表录入和批量审核
|
||
- 实时更新:页面数据实时刷新和状态同步
|
||
|
||
### 3.3 收费管理
|
||
|
||
收费管理模块负责水费的收取和管理,是营收系统的重要业务模块。
|
||
|
||
#### 3.3.1 业务流程图
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
Start([客户缴费]) --> QueryCustomer[查询客户信息]
|
||
QueryCustomer --> CustomerExists{客户是否存在}
|
||
CustomerExists -->|否| ErrorReturn[返回错误信息]
|
||
CustomerExists -->|是| QueryBills[查询欠费账单]
|
||
|
||
QueryBills --> BillExists{是否有欠费}
|
||
BillExists -->|否| NoDebt[无欠费提示]
|
||
BillExists -->|是| ShowBills[显示账单列表]
|
||
|
||
ShowBills --> SelectBills[选择缴费账单]
|
||
SelectBills --> CalcAmount[计算缴费金额]
|
||
CalcAmount --> SelectPayMethod[选择支付方式]
|
||
|
||
SelectPayMethod --> PaymentType{支付方式}
|
||
PaymentType -->|现金| CashPayment[现金收费]
|
||
PaymentType -->|银行卡| BankCardPay[银行卡支付]
|
||
PaymentType -->|在线支付| OnlinePayment[在线支付]
|
||
PaymentType -->|预存款| PrepaidPayment[预存款支付]
|
||
|
||
CashPayment --> ValidatePayment[验证收费金额]
|
||
BankCardPay --> ValidatePayment
|
||
OnlinePayment --> ThirdPartyPay[第三方支付]
|
||
PrepaidPayment --> CheckBalance[检查预存余额]
|
||
|
||
ThirdPartyPay --> PaymentCallback[支付回调]
|
||
PaymentCallback --> ValidatePayment
|
||
|
||
CheckBalance --> BalanceOK{余额是否充足}
|
||
BalanceOK -->|否| InsufficientBalance[余额不足]
|
||
BalanceOK -->|是| ValidatePayment
|
||
|
||
ValidatePayment --> PaymentSuccess{支付成功}
|
||
PaymentSuccess -->|否| PaymentFailed[支付失败处理]
|
||
PaymentSuccess -->|是| UpdateAccount[更新账户状态]
|
||
|
||
UpdateAccount --> UpdateBills[更新账单状态]
|
||
UpdateBills --> GenerateReceipt[生成收费凭证]
|
||
GenerateReceipt --> PrintReceipt[打印收据]
|
||
PrintReceipt --> SendNotification[发送缴费通知]
|
||
SendNotification --> Complete([完成缴费])
|
||
|
||
PaymentFailed --> End([结束])
|
||
InsufficientBalance --> End
|
||
ErrorReturn --> End
|
||
NoDebt --> End
|
||
```
|
||
|
||
#### 3.3.2 主要功能
|
||
|
||
**柜台收费**:现场收费服务
|
||
- 用户查询:客户信息查询、账单查询
|
||
- 收费处理:多种支付方式、找零计算
|
||
- 收费打印:收据打印、发票开具
|
||
- 预存预付:余额充值、预付费管理
|
||
|
||
**柜台结账**:营业网点日常结账
|
||
- 日结处理:当日收费汇总、统计分析
|
||
- 交款管理:现金上缴、账务核对
|
||
- 结账查询:历史结账记录查询
|
||
|
||
**预付款管理**:预付费业务处理
|
||
- 预付款充值:余额充值、充值记录
|
||
- 使用管理:自动扣款、余额提醒
|
||
- 退款处理:预付款退款、退款审核
|
||
|
||
**缴费记录查询**:缴费历史管理
|
||
- 多条件查询:按时间、金额、渠道查询
|
||
- 统计分析:缴费趋势、渠道分析
|
||
- 导出功能:缴费记录导出
|
||
|
||
#### 3.3.3 核心接口定义
|
||
|
||
**缴费管理主要接口**:
|
||
```java
|
||
@RestController
|
||
@RequestMapping("/admin-api/water/payment")
|
||
@Tag(name = "管理后台 - 缴费管理")
|
||
public class PaymentController {
|
||
|
||
@PostMapping("/create")
|
||
@Operation(summary = "创建缴费记录")
|
||
public CommonResult<PaymentRespVO> createPayment(@Valid @RequestBody PaymentCreateReqVO createReqVO);
|
||
|
||
@PostMapping("/cash-payment")
|
||
@Operation(summary = "现金缴费")
|
||
public CommonResult<PaymentRespVO> cashPayment(@Valid @RequestBody CashPaymentReqVO cashReqVO);
|
||
|
||
@PostMapping("/online-payment")
|
||
@Operation(summary = "在线支付")
|
||
public CommonResult<OnlinePaymentRespVO> onlinePayment(@Valid @RequestBody OnlinePaymentReqVO onlineReqVO);
|
||
|
||
@PostMapping("/prepaid-payment")
|
||
@Operation(summary = "预存款缴费")
|
||
public CommonResult<PaymentRespVO> prepaidPayment(@Valid @RequestBody PrepaidPaymentReqVO prepaidReqVO);
|
||
}
|
||
```
|
||
|
||
**接口设计特点**:
|
||
- 支持多种缴费方式:现金、银行卡、在线支付、预存款
|
||
- 事务控制:确保缴费操作的原子性和一致性
|
||
- 异步处理:第三方支付采用异步回调机制
|
||
- 安全验证:完整的权限控制和数据校验
|
||
```
|
||
|
||
#### 3.3.4 前端界面设计
|
||
|
||
**缴费管理页面结构**:
|
||
```vue
|
||
<template>
|
||
<ContentWrap>
|
||
<!-- 客户查询 -->
|
||
<el-form class="search-form" inline>
|
||
<el-form-item label="客户编号">
|
||
<el-input v-model="queryParams.customerCode" placeholder="请输入客户编号" />
|
||
</el-form-item>
|
||
<el-form-item label="客户姓名">
|
||
<el-input v-model="queryParams.customerName" placeholder="请输入客户姓名" />
|
||
</el-form-item>
|
||
<el-form-item>
|
||
<el-button type="primary" @click="handleQuery">查询</el-button>
|
||
<el-button @click="resetQuery">重置</el-button>
|
||
</el-form-item>
|
||
</el-form>
|
||
|
||
<!-- 账单信息 -->
|
||
<el-table v-loading="loading" :data="billList" @selection-change="handleSelectionChange">
|
||
<el-table-column type="selection" width="55" />
|
||
<el-table-column prop="billCode" label="账单编号" />
|
||
<el-table-column prop="billDate" label="账期" />
|
||
<el-table-column prop="waterUsage" label="用水量" />
|
||
<el-table-column prop="totalAmount" label="应缴金额" />
|
||
<el-table-column prop="balanceAmount" label="欠费金额" />
|
||
</el-table>
|
||
|
||
<!-- 缴费操作 -->
|
||
<el-row class="payment-actions">
|
||
<el-col :span="12">
|
||
<el-statistic title="选中金额" :value="selectedAmount" prefix="¥" />
|
||
</el-col>
|
||
<el-col :span="12" class="text-right">
|
||
<el-button type="success" @click="handleCashPayment">现金缴费</el-button>
|
||
<el-button type="primary" @click="handleOnlinePayment">在线支付</el-button>
|
||
<el-button type="warning" @click="handlePrepaidPayment">预存扣费</el-button>
|
||
</el-col>
|
||
</el-row>
|
||
</ContentWrap>
|
||
</template>
|
||
```
|
||
|
||
### 3.4 账务处理
|
||
|
||
账务处理模块负责处理各类特殊账务情况,确保账务数据的准确性和完整性。
|
||
|
||
#### 3.4.1 业务流程图
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
Start([账务处理请求]) --> CheckAuth[权限验证]
|
||
CheckAuth --> AuthOK{权限验证}
|
||
AuthOK -->|失败| AuthError[权限错误]
|
||
AuthOK -->|成功| ProcessType{处理类型}
|
||
|
||
ProcessType -->|调账| AdjustAccount[账务调整]
|
||
ProcessType -->|退款| RefundProcess[退款处理]
|
||
ProcessType -->|销账| WriteOff[销账处理]
|
||
ProcessType -->|预存调整| PrepaidAdjust[预存调整]
|
||
|
||
AdjustAccount --> ValidateAdjust[验证调整数据]
|
||
RefundProcess --> ValidateRefund[验证退款数据]
|
||
WriteOff --> ValidateWriteOff[验证销账数据]
|
||
PrepaidAdjust --> ValidatePrepaid[验证预存数据]
|
||
|
||
ValidateAdjust --> AdjustApproval[调账审批]
|
||
ValidateRefund --> RefundApproval[退款审批]
|
||
ValidateWriteOff --> WriteOffApproval[销账审批]
|
||
ValidatePrepaid --> PrepaidApproval[预存审批]
|
||
|
||
AdjustApproval --> ApprovalResult{审批结果}
|
||
RefundApproval --> ApprovalResult
|
||
WriteOffApproval --> ApprovalResult
|
||
PrepaidApproval --> ApprovalResult
|
||
|
||
ApprovalResult -->|拒绝| ApprovalReject[审批拒绝]
|
||
ApprovalResult -->|通过| ExecuteProcess[执行处理]
|
||
|
||
ExecuteProcess --> UpdateAccount[更新账户]
|
||
UpdateAccount --> RecordLog[记录日志]
|
||
RecordLog --> Complete([处理完成])
|
||
|
||
AuthError --> End([结束])
|
||
ApprovalReject --> End
|
||
```
|
||
|
||
#### 3.4.2 主要功能
|
||
|
||
**未销调整**:处理各类账务调整需求
|
||
- 水量调整:调整用水量和相关费用
|
||
- 金额调整:直接调整账单金额
|
||
- 违约金减免:减免或取消违约金
|
||
- 费用追加:补收相关费用
|
||
|
||
**特殊开账**:处理特殊情况的账单生成
|
||
- 补抄开账:补录抄表数据并生成账单
|
||
- 估抄开账:估算用水量生成账单
|
||
- 平均开账:基于历史用量平均开账
|
||
|
||
**账务退款**:处理各类退款业务
|
||
- 多缴退款:退还多缴的水费
|
||
- 预付款退款:退还预存余额
|
||
- 错误缴费退款:退还错误缴费
|
||
|
||
#### 3.4.3 核心接口定义
|
||
|
||
```java
|
||
@RestController
|
||
@RequestMapping("/admin-api/water/account")
|
||
@Tag(name = "管理后台 - 账务处理")
|
||
@Validated
|
||
public class AccountProcessController {
|
||
|
||
@PostMapping("/adjust")
|
||
@Operation(summary = "账务调整")
|
||
@PreAuthorize("@ss.hasPermission('water:account:adjust')")
|
||
public CommonResult<Boolean> adjustAccount(@Valid @RequestBody AccountAdjustReqVO adjustReqVO);
|
||
|
||
@PostMapping("/refund")
|
||
@Operation(summary = "退款处理")
|
||
@PreAuthorize("@ss.hasPermission('water:account:refund')")
|
||
public CommonResult<Boolean> processRefund(@Valid @RequestBody RefundProcessReqVO refundReqVO);
|
||
|
||
@PostMapping("/write-off")
|
||
@Operation(summary = "销账处理")
|
||
@PreAuthorize("@ss.hasPermission('water:account:write-off')")
|
||
public CommonResult<Boolean> writeOffAccount(@Valid @RequestBody WriteOffReqVO writeOffReqVO);
|
||
}
|
||
```
|
||
|
||
### 3.5 发票管理
|
||
|
||
发票管理模块负责水费发票的全生命周期管理,支持纸质发票和电子发票。
|
||
|
||
#### 3.5.1 业务流程图
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
Start([发票业务]) --> InvoiceType{发票类型}
|
||
|
||
InvoiceType -->|纸质发票| PaperInvoice[纸质发票管理]
|
||
InvoiceType -->|电子发票| EInvoice[电子发票管理]
|
||
|
||
PaperInvoice --> PaperStock[发票库存管理]
|
||
PaperStock --> PaperPrint[发票打印]
|
||
PaperPrint --> PaperRecord[打印记录]
|
||
|
||
EInvoice --> EInvoiceGenerate[电子发票生成]
|
||
EInvoiceGenerate --> EInvoiceSign[电子签章]
|
||
EInvoiceSign --> EInvoiceSend[发票推送]
|
||
|
||
PaperRecord --> InvoiceQuery[发票查询]
|
||
EInvoiceSend --> InvoiceQuery
|
||
|
||
InvoiceQuery --> InvoiceCancel{需要作废?}
|
||
InvoiceCancel -->|是| CancelInvoice[发票作废]
|
||
InvoiceCancel -->|否| Complete([完成])
|
||
|
||
CancelInvoice --> CancelRecord[作废记录]
|
||
CancelRecord --> Complete
|
||
```
|
||
|
||
#### 3.5.2 核心接口定义
|
||
|
||
```java
|
||
@RestController
|
||
@RequestMapping("/admin-api/water/invoice")
|
||
@Tag(name = "管理后台 - 发票管理")
|
||
@Validated
|
||
public class InvoiceController {
|
||
|
||
@PostMapping("/generate")
|
||
@Operation(summary = "生成发票")
|
||
public CommonResult<InvoiceRespVO> generateInvoice(@Valid @RequestBody InvoiceGenerateReqVO generateReqVO);
|
||
|
||
@PostMapping("/print")
|
||
@Operation(summary = "打印发票")
|
||
public CommonResult<Boolean> printInvoice(@Valid @RequestBody InvoicePrintReqVO printReqVO);
|
||
|
||
@PostMapping("/cancel")
|
||
@Operation(summary = "发票作废")
|
||
public CommonResult<Boolean> cancelInvoice(@Valid @RequestBody InvoiceCancelReqVO cancelReqVO);
|
||
}
|
||
```
|
||
|
||
### 3.6 代收业务
|
||
|
||
代收业务模块负责处理各种渠道的水费代收业务,主要功能包括:
|
||
|
||
- 实时收费:银行代收、支付宝/微信收费、代收点收费
|
||
- 银行代扣:代扣协议管理、代扣数据生成和处理
|
||
- 银行托收:托收单生成、托收数据处理
|
||
- 代扣渠道管理:渠道维护、规则设置、效率分析
|
||
|
||
### 3.7 环卫系统
|
||
|
||
环卫系统模块负责管理与环卫相关的收费和计费业务,主要功能包括:
|
||
|
||
- 计费核定:环卫收费规则配置和业务字典维护
|
||
- 计费退补:退费和补缴规则配置,字典配置参与计算
|
||
- 计费减免:环卫费用减免规则配置和审批流程
|
||
- 环卫收费统计:环卫收费数据统计和分析
|
||
|
||
### 3.8 业务工单
|
||
|
||
业务工单模块负责管理日常业务工单的流转和处理,主要功能包括:
|
||
|
||
- 业务清单:查询通过系统办理的日常业务工单及进度信息
|
||
- 上报清单:新增、查询问题清单,包括通过手机端上报的问题
|
||
- 稽查工单:对手机端的稽查信息进行多条件查询和导出
|
||
- 移表工单:客户对需要进行移动的水表进行登记
|
||
- 换表工单:新增客户自报的换表和故障的水表等进行换表登记
|
||
- 工作流可视化:工作节点可视化展示和流程管理
|
||
|
||
## 四、表务系统
|
||
|
||
表务系统负责水表的全生命周期管理,包括水表购置、安装、维修、更换等业务。
|
||
|
||
### 4.1 表务工单
|
||
|
||
表务工单模块负责处理各类表务作业,主要功能包括:
|
||
|
||
- 换表工单:换表计划、换表施工、换表回填
|
||
- 移表工单:移表申请、移表施工、移表验收
|
||
- 拆表工单:拆表申请、拆表施工、拆表确认
|
||
- 复装工单:复装申请、复装施工、复装验收
|
||
- 校表工单:校表申请、校表实施、校表结果
|
||
- 稽查工单:水量异常稽查、违规用水稽查、处罚决定
|
||
- 业务上报:异常上报、投诉上报、处理结果反馈
|
||
|
||
### 4.2 表务仓库
|
||
|
||
表务仓库模块负责水表的仓储管理,主要功能包括:
|
||
|
||
- 新表入库:水表检定、入库登记、入库确认
|
||
- 水表检定:检定信息记录、结果管理
|
||
- 水表领用:领用单登记、领用单管理
|
||
- 水表出库:出库登记、出库确认
|
||
- 水表退库:退库申请、退库确认
|
||
- 水表报废:报废申请、报废确认
|
||
- 水表生命周期查询:状态查询、历史记录查询
|
||
|
||
### 4.3 水表参数与基础信息
|
||
|
||
水表参数与基础信息模块负责维护水表相关的基础数据,主要功能包括:
|
||
|
||
- 水表厂家管理:厂家信息维护、厂家状态管理
|
||
- 水表型号管理:型号信息维护、型号分类管理
|
||
- 水表口径管理:口径信息维护、定换周期设置
|
||
- 水表量程管理:量程信息维护、量程范围设置
|
||
|
||
### 4.4 物联网对接与数据同步
|
||
|
||
物联网对接与数据同步模块负责水表数据的互联互通,主要功能包括:
|
||
|
||
- 厂家设备信息管理:设备型号管理、厂家信息维护
|
||
- 表务对接日志:数据同步日志、错误处理
|
||
- 水表数据推送接口:新表数据推送、校验机制
|
||
- 远程抄表数据同步:数据接收、验证与处理
|
||
- 物联网水表监控:状态监控、异常事件报警
|
||
|
||
## 五、报装系统
|
||
|
||
报装系统负责新用户的报装立户管理,主要功能包括:
|
||
|
||
### 5.1 报装流程
|
||
|
||
报装流程模块负责新用户报装业务的全流程管理,主要功能包括:
|
||
|
||
- 报装申请:用户申请、材料审核、现场勘查
|
||
- 方案设计:设计方案、设计审核、费用估算
|
||
- 合同签订:费用通知、合同签订、收费管理
|
||
- 施工管理:施工计划、施工实施、施工验收
|
||
- 开户通水:水表安装、用户立户、通水确认
|
||
|
||
### 5.2 一户一表管理
|
||
|
||
一户一表管理模块负责实施"一户一表"改造,主要功能包括:
|
||
|
||
- 改造计划:制定改造计划、用户协商、费用估算
|
||
- 改造实施:施工管理、水表安装、验收管理
|
||
- 用户转换:数据转换、账务处理、使用确认
|
||
|
||
## 六、客户服务
|
||
|
||
客户服务模块提供多渠道的客户服务功能,主要包括:
|
||
|
||
### 6.1 微信、支付宝服务窗
|
||
|
||
- 账户绑定:支持用户绑定水务账户
|
||
- 用水查询:查询用水情况和用水趋势
|
||
- 水费查询:查询水费信息和欠费信息
|
||
- 在线缴费:支持在线缴纳水费
|
||
- 业务办理:支持在线办理简单业务
|
||
|
||
### 6.2 历史账单
|
||
|
||
- 账单查询:查询历史账单信息
|
||
- 用水分析:分析用水趋势,提供图表展示
|
||
- 账单推送:定期推送账单信息
|
||
- 账单明细:提供详细的账单明细
|
||
|
||
### 6.3 电子发票
|
||
|
||
- 发票申请:申请开具电子发票
|
||
- 发票查询:查询已开具发票
|
||
- 发票下载:下载电子发票
|
||
- 发票推送:推送电子发票到用户邮箱或微信
|
||
|
||
### 6.4 营业网点
|
||
|
||
- 网点查询:查询营业网点信息
|
||
- 网点导航:提供到营业网点的导航
|
||
- 业务指南:提供各网点业务办理指南
|
||
- 等候情况:实时显示各网点的等候情况
|
||
|
||
### 6.5 账户流水
|
||
|
||
- 流水查询:查询账户交易流水
|
||
- 明细下载:下载流水明细
|
||
- 交易统计:提供交易金额统计
|
||
- 缴费证明:生成缴费证明
|
||
|
||
### 6.6 微网厅
|
||
|
||
- 用户注册:用户注册微网厅账号
|
||
- 信息查询:查询用水、缴费信息
|
||
- 业务办理:在线办理各类业务
|
||
- 用户反馈:提交意见建议
|
||
|
||
## 七、系统配置
|
||
|
||
系统配置模块提供各类系统参数的配置管理功能,主要包括:
|
||
|
||
### 7.1 水表参数
|
||
|
||
- 水表厂家:管理水表生产厂商信息
|
||
- 水表型号:管理水表型号规格
|
||
- 水表量程:管理水表量程规格
|
||
|
||
### 7.2 地址参数
|
||
|
||
- 行政区划:管理行政区划信息
|
||
- 地址编码:管理地址编码规则
|
||
- 地址库:维护标准地址库
|
||
|
||
### 7.3 价格体系
|
||
|
||
- 用水性质:管理不同用水性质的分类
|
||
- 水价标准:管理不同用水性质的水价标准
|
||
- 阶梯水价:管理阶梯水价设置
|
||
- 调价管理:管理水价调整流程
|
||
|
||
### 7.4 基本配置
|
||
|
||
- 系统参数:管理系统基本参数
|
||
- 业务规则:管理业务处理规则
|
||
- 打印模板:管理各类打印模板
|
||
- 短信模板:管理短信发送模板
|
||
|
||
### 7.5 催缴管理
|
||
|
||
- 催缴计划:制定欠费催缴计划
|
||
- 催缴任务:分配催缴任务
|
||
- 催缴执行:记录催缴执行情况
|
||
- 催缴结果:统计催缴结果
|
||
|
||
### 7.6 用户权限
|
||
|
||
- 菜单权限:不同角色可访问的菜单权限配置
|
||
- 功能权限:不同角色可操作的功能权限配置
|
||
- 数据权限:通过查询字典权限控制不同用户业务取数权限
|
||
- 角色管理:自定义角色及权限组合
|
||
|
||
### 7.7 定时任务
|
||
|
||
- 任务配置:定时任务可视化配置,包含传参设置
|
||
- 任务监控:定时任务执行状态监控
|
||
- 任务日志:定时任务执行日志记录和查询
|
||
- 任务调度:任务优先级和执行顺序管理
|
||
|
||
## 八、系统接口
|
||
|
||
系统接口模块提供与外部系统的集成和数据交换功能,实现业务数据的互通互联。
|
||
|
||
### 8.1 银行接口
|
||
|
||
银行接口实现与银行系统的对接,支持代扣、托收等功能,主要包括:
|
||
|
||
- 收费接口:实现用户通过银行渠道缴纳水费
|
||
- 冲正接口:处理银行退款和交易取消
|
||
- 对账接口:与银行系统进行对账
|
||
- 托收接口:支持银行托收功能
|
||
- 代扣接口:支持银行代扣功能
|
||
|
||
### 8.2 支付宝/微信接口
|
||
|
||
支付宝和微信接口实现与第三方支付平台的对接,支持在线支付功能,主要包括:
|
||
|
||
- 欠费查询:查询用户欠费信息
|
||
- 在线支付:支持用户在线缴纳水费
|
||
- 支付通知:处理支付结果通知
|
||
- 对账接口:与支付平台进行对账
|
||
|
||
### 8.3 短信接口
|
||
|
||
短信接口提供短信通知和验证功能,主要包括:
|
||
|
||
- 账单通知:通过短信通知用户账单信息
|
||
- 缴费提醒:提醒用户及时缴费
|
||
- 催缴通知:向欠费用户发送催缴短信
|
||
- 业务通知:通知用户业务办理状态
|
||
- 验证码功能:提供短信验证码服务
|
||
|
||
### 8.4 集抄系统接口
|
||
|
||
集抄系统接口实现与智能水表集中抄表系统的对接,主要包括:
|
||
|
||
- 抄表数据获取:获取智能水表的抄表数据
|
||
- 水表状态监控:监控水表的使用状态
|
||
- 异常数据处理:处理抄表异常情况
|
||
|
||
### 8.5 政务系统接口
|
||
|
||
政务系统接口实现与地方政务平台和政务APP的对接,主要包括:
|
||
|
||
- 数据推送:推送营收数据到政务平台
|
||
- 数据查询:支持政务平台查询水务数据
|
||
- 缴费对接:支持通过政务平台缴费
|
||
- 报装工单对接:对接报装业务工单
|
||
|
||
### 8.6 消火栓系统接口
|
||
|
||
消火栓系统接口实现与消火栓系统的对接,主要功能包括:
|
||
|
||
- 预存缴费管理:管理用户预存水费
|
||
- 剩余水量计算:计算用户剩余可用水量
|
||
- 取水控制:根据预存和剩余水量控制取水
|
||
|
||
### 8.7 其他系统对接
|
||
|
||
其他系统对接模块负责与周边系统进行数据交换和业务协同,主要功能包括:
|
||
|
||
- 环卫系统对接:实现与环卫系统的数据同步和业务流程对接
|
||
- 客服系统对接:实现与客服系统的工单同步和问题处理
|
||
- 工单系统对接:实现与工单系统的工单流转和状态同步
|
||
- OA系统对接:实现与OA系统的审批流程对接和数据共享
|
||
- 智水擎平台对接:实现与智水擎平台的数据交换和业务协同
|
||
|
||
## 九、统计分析
|
||
|
||
统计分析模块提供多维度的数据统计和分析功能,为管理决策提供数据支持。
|
||
|
||
### 9.1 报表查询
|
||
|
||
- 标准报表:系统内置的标准统计报表
|
||
- 自定义报表:用户可自定义的报表
|
||
- 报表导出:支持将报表导出为Excel、PDF等格式
|
||
- 报表打印:支持报表打印功能
|
||
|
||
### 9.2 欠费查询
|
||
|
||
- 欠费情况统计:按区域、用户类型等维度统计欠费情况
|
||
- 欠费用户明细:查询欠费用户的详细信息
|
||
- 欠费分析:分析欠费原因和趋势
|
||
- 欠费导出:支持将欠费数据导出
|
||
|
||
### 9.3 缴费记录
|
||
|
||
- 缴费情况统计:按多维度统计缴费情况
|
||
- 缴费明细查询:查询缴费明细记录
|
||
- 缴费趋势分析:分析缴费趋势
|
||
- 缴费渠道分析:分析各缴费渠道的使用情况
|
||
|
||
### 9.4 用水分析
|
||
|
||
- 用水量统计:按多维度统计用水量
|
||
- 用水趋势分析:分析用水趋势,预测用水需求
|
||
- 异常用水分析:识别和分析异常用水情况
|
||
- 节水潜力分析:分析用户节水潜力
|
||
|
||
## 十、工程管理
|
||
|
||
工程管理模块负责处理与供水工程相关的业务,包括工程申请、施工管理和工程验收等。
|
||
|
||
### 10.1 工程申请
|
||
|
||
- 工程立项:新建供水工程的立项申请
|
||
- 材料提交:上传工程相关材料
|
||
- 前期勘察:记录工程前期勘察结果
|
||
- 工程预算:制定工程预算方案
|
||
- 申请审批:对工程申请进行审批
|
||
|
||
### 10.2 工程施工
|
||
|
||
- 施工计划:制定工程施工计划
|
||
- 施工派工:将施工任务分配给施工人员
|
||
- 施工记录:记录施工过程和施工情况
|
||
- 材料管理:管理工程施工材料的使用情况
|
||
- 施工异常处理:处理施工过程中的异常情况
|
||
|
||
### 10.3 工程验收
|
||
|
||
- 验收申请:提交工程验收申请
|
||
- 验收检查:对工程进行验收检查
|
||
- 验收记录:记录验收结果
|
||
- 竣工结算:进行工程竣工结算
|
||
- 工程归档:对工程资料进行归档
|
||
|
||
### 10.4 工程查询
|
||
|
||
- 工程进度查询:查询工程进度情况
|
||
- 工程资料查询:查询工程相关资料
|
||
- 工程统计:统计工程数量、金额等信息
|
||
- 工程分析:分析工程实施情况
|
||
|
||
## 十一、抄表APP
|
||
|
||
抄表APP是针对移动端开发的抄表工具,支持外勤人员进行现场抄表、问题处理和工单管理等业务操作。
|
||
|
||
### 11.1 首页功能
|
||
|
||
- 首页:显示当前登录用户信息、快捷搜索和主要和抄表业务相关的功能模块
|
||
- 个人信息:查看个人信息,可以进行密码、手机号信息修改,可以进行抄表设置
|
||
- 快捷查询:提供搜索栏,用户输入户号、户名、地址以及册本后,系统会自动检索到相关的信息
|
||
|
||
### 11.2 抄表功能
|
||
|
||
- 抄表任务:显示当前登录的抄表员抄表任务信息
|
||
- NFC抄表:抄表设备感应NFC后自动弹出抄表页
|
||
- 扫码抄表:扫水表上二维码,搜集该表信息,弹出抄表页
|
||
- 数据采集:抄表数据现场采集功能
|
||
- AI录入:对接AI接口实现智能读数
|
||
- 抄表轨迹:记录表的物理位置,在地图上点击后采集水表定位
|
||
- 抄表导航:指引抄表员前往下一个抄表点
|
||
- 抄表汇总:系统会根据当前登录的人员自动汇总抄表信息
|
||
- 账单查询:查询客户账单详情
|
||
- 欠费查询:显示当前登录的抄表员抄表用水客户的欠费情况
|
||
|
||
### 11.3 工单管理
|
||
|
||
- 问题上报:系统支持上报当前登录的抄表员抄表时遇到的用水问题
|
||
- 问题回填:问题上报后,可进行问题回填和处理
|
||
- 代办工单:显示当前登录的抄表员需要代办工单
|
||
- 平台工单管理:移动端提交工单后,系统会自动提交到工单处置平台进行受理、派发
|
||
- 停水复水工单:当客户存在欠费的情况下可以对该客户进行停水操作
|
||
- 稽查工单:实现抄表稽查和水价稽查
|
||
- 维修工单:提交坏表维修报修等工单
|
||
|
||
## 十二、接口服务
|
||
|
||
接口服务模块提供系统对外的API接口管理和服务能力,实现与第三方系统的便捷集成。
|
||
|
||
### 12.1 API市场
|
||
|
||
- API展示:展示系统提供的各类API接口
|
||
- API使用说明:提供API接口的详细使用说明和示例
|
||
- API测试:提供API接口的在线测试功能
|
||
|
||
### 12.2 API管理
|
||
|
||
- API申请:第三方系统申请调用API的流程管理
|
||
- API调度看板:监控API调用情况和性能指标
|
||
- 接口服务配置管理:管理API接口的配置参数
|
||
- 接口限流熔断管理:控制API接口的调用频率和熔断机制
|
||
|
||
### 12.3 接口权限管理
|
||
|
||
- 授权管理:管理API接口的授权信息
|
||
- 白名单管理:设置允许访问API的IP白名单
|
||
- 安全策略:设置API调用的安全策略和防护措施
|
||
|
||
### 12.4 系统对外接口
|
||
|
||
- 查询接口:提供各类数据查询接口
|
||
- 业务处理接口:提供业务处理和操作接口
|
||
- 状态同步接口:提供状态信息同步接口
|
||
- 数据推送接口:提供数据推送和订阅接口
|
||
|
||
## 系统集成架构
|
||
|
||
### 前后端集成架构
|
||
|
||
```mermaid
|
||
graph TB
|
||
subgraph "前端应用"
|
||
F1[管理后台<br/>yudao-ui-admin-vue3]
|
||
F2[移动端<br/>uni-app]
|
||
F3[客户端<br/>微信小程序]
|
||
end
|
||
|
||
subgraph "后端服务"
|
||
B1[认证服务<br/>Spring Security]
|
||
B2[业务服务<br/>RuoYi-Vue-Pro]
|
||
B3[网关服务<br/>Spring Cloud Gateway]
|
||
end
|
||
|
||
subgraph "数据存储"
|
||
D1[(OpenGauss 5.0+)]
|
||
D2[(Redis 6.0)]
|
||
D3[MinIO文件存储]
|
||
end
|
||
|
||
F1 --> B3
|
||
F2 --> B3
|
||
F3 --> B3
|
||
|
||
B3 --> B1
|
||
B3 --> B2
|
||
|
||
B1 --> D2
|
||
B2 --> D1
|
||
B2 --> D2
|
||
B2 --> D3
|
||
```
|
||
|
||
### 技术栈整合方案
|
||
|
||
**后端技术整合**:
|
||
- Spring Boot 3.x作为核心框架
|
||
- Spring Security 6.x提供安全认证
|
||
- MyBatis Plus 3.x简化数据访问
|
||
- RuoYi-Vue-Pro提供基础功能框架
|
||
|
||
**前端技术整合**:
|
||
- Vue 3.x + TypeScript构建现代化前端
|
||
- Element Plus提供UI组件库
|
||
- Vite作为构建工具
|
||
- Pinia进行状态管理
|
||
|
||
**数据库集成**:
|
||
- OpenGauss 5.0+作为主数据库,国产自主可控
|
||
- Redis 6.0提供缓存和会话管理
|
||
- HikariCP连接池优化和读写分离支持
|
||
|
||
**中间件集成**:
|
||
- RabbitMQ提供消息队列
|
||
- MinIO提供文件存储
|
||
- Elasticsearch提供全文搜索
|
||
|
||
这样的架构设计确保了系统的高可用性、可扩展性和维护性,为福建水务营收系统提供了坚实的技术基础。
|
||
---
|
||
|
||
# 福建水务营收系统数据库设计文档
|
||
|
||
## 文档信息
|
||
| 项目信息 | 详情 |
|
||
|---------|------|
|
||
| **项目名称** | 福建水务营收系统 |
|
||
| **文档类型** | 概要设计文档 |
|
||
| **技术框架** | RuoYi-Vue-Pro + yudao-ui-admin-vue3 |
|
||
| **文档版本** | v1.0 |
|
||
| **编写日期** | 2024-12-19 |
|
||
| **文档状态** | ✅ 已完成 |
|
||
|
||
## 目录
|
||
- [一、数据库设计概述](#一数据库设计概述)
|
||
- [二、数据库架构](#二数据库架构)
|
||
- [三、核心数据模型ER图](#三核心数据模型er图)
|
||
- [四、核心数据表设计](#四核心数据表设计)
|
||
- [五、完整DDL语句](#五完整ddl语句)
|
||
- [六、OpenGauss数据库特性应用](#六opengauss数据库特性应用)
|
||
- [七、索引设计与优化](#七索引设计与优化)
|
||
- [八、OpenGauss数据安全设计](#八opengauss数据安全设计)
|
||
|
||
## 一、数据库设计概述
|
||
|
||
福建水务营收系统采用**华为OpenGauss 5.0+**数据库,基于RuoYi-Vue-Pro框架规范设计。OpenGauss作为国产自主可控的企业级数据库,具有高性能、高可用、高安全的特点,完全满足水务行业对数据安全和国产化的要求。数据库架构支持多租户、高并发、高可用的业务需求,为水务营收业务提供稳定可靠的数据存储服务。
|
||
|
||
### 1.1 设计目标
|
||
- 支持100万客户的业务量,满足3-5年业务发展需求
|
||
- 支持200并发用户,50并发移动设备
|
||
- 系统响应时间不超过3秒
|
||
- 数据安全等保三级要求
|
||
- 支持多租户数据隔离
|
||
- **国产化要求**:符合国产数据库替代要求
|
||
|
||
### 1.2 数据库选型优势
|
||
- **国产自主可控**:华为OpenGauss是完全自主知识产权的数据库
|
||
- **高性能**:优化的SQL引擎,查询性能优于传统数据库20-30%
|
||
- **高可用**:支持主备同步、读写分离、故障自动切换
|
||
- **安全可信**:内置数据加密、审计、权限管控等安全特性
|
||
- **生态兼容**:兼容PostgreSQL/MySQL协议,迁移成本低
|
||
|
||
### 1.3 设计原则
|
||
- **标准化**:遵循OpenGauss数据库设计规范
|
||
- **多租户**:基于tenant_id字段实现数据隔离
|
||
- **可扩展**:预留扩展字段,支持业务增长
|
||
- **高性能**:合理设计索引,优化查询性能
|
||
- **安全性**:利用OpenGauss内置安全特性
|
||
|
||
## 二、数据库架构
|
||
|
||
### 1. 数据库架构图
|
||
|
||
```mermaid
|
||
graph TB
|
||
subgraph "应用层"
|
||
APP[Water Biz Application<br/>RuoYi-Vue-Pro]
|
||
end
|
||
|
||
subgraph "数据访问层"
|
||
MP[MyBatis Plus<br/>ORM框架]
|
||
CACHE[Redis缓存<br/>热点数据]
|
||
end
|
||
|
||
subgraph "数据存储层"
|
||
subgraph "OpenGauss主从集群"
|
||
MASTER[(OpenGauss主库<br/>读写)]
|
||
SLAVE[(OpenGauss从库<br/>只读)]
|
||
end
|
||
|
||
subgraph "业务数据库"
|
||
DB_CUSTOMER[(客户数据库<br/>Customer DB)]
|
||
DB_BILLING[(营收数据库<br/>Billing DB)]
|
||
DB_METER[(表务数据库<br/>Meter DB)]
|
||
DB_SYSTEM[(系统数据库<br/>System DB)]
|
||
end
|
||
|
||
subgraph "数据归档"
|
||
DB_HISTORY[(历史数据库<br/>Archive DB)]
|
||
BACKUP[(备份存储<br/>Backup Storage)]
|
||
end
|
||
end
|
||
|
||
APP --> MP
|
||
APP --> CACHE
|
||
MP --> MASTER
|
||
MASTER --> SLAVE
|
||
MASTER --> DB_CUSTOMER
|
||
MASTER --> DB_BILLING
|
||
MASTER --> DB_METER
|
||
MASTER --> DB_SYSTEM
|
||
SLAVE --> DB_HISTORY
|
||
MASTER --> BACKUP
|
||
```
|
||
|
||
### 2. 多租户架构设计
|
||
|
||
```mermaid
|
||
graph TB
|
||
subgraph "多租户数据隔离"
|
||
TENANT1[租户1: 福建水务集团]
|
||
TENANT2[租户2: 厦门分公司]
|
||
TENANT3[租户3: 泉州分公司]
|
||
end
|
||
|
||
subgraph "共享数据库"
|
||
subgraph "业务表结构"
|
||
TABLE1[water_customer<br/>+ tenant_id]
|
||
TABLE2[water_meter<br/>+ tenant_id]
|
||
TABLE3[water_bill<br/>+ tenant_id]
|
||
TABLE4[water_payment<br/>+ tenant_id]
|
||
end
|
||
|
||
subgraph "租户隔离机制"
|
||
INTERCEPTOR[MyBatis Plus<br/>多租户拦截器]
|
||
FILTER[数据权限过滤器]
|
||
end
|
||
end
|
||
|
||
TENANT1 --> INTERCEPTOR
|
||
TENANT2 --> INTERCEPTOR
|
||
TENANT3 --> INTERCEPTOR
|
||
|
||
INTERCEPTOR --> FILTER
|
||
FILTER --> TABLE1
|
||
FILTER --> TABLE2
|
||
FILTER --> TABLE3
|
||
FILTER --> TABLE4
|
||
```
|
||
|
||
### 3. 通用字段设计
|
||
|
||
所有业务表统一包含以下基础字段:
|
||
|
||
| 字段名 | 数据类型 | 长度 | 默认值 | 描述 |
|
||
|-------|---------|------|--------|-----|
|
||
| id | BIGINT | - | AUTO_INCREMENT | 主键ID |
|
||
| tenant_id | BIGINT | - | 0 | 租户ID(多租户隔离) |
|
||
| creator | VARCHAR | 64 | '' | 创建者 |
|
||
| create_time | DATETIME | - | CURRENT_TIMESTAMP | 创建时间 |
|
||
| updater | VARCHAR | 64 | '' | 更新者 |
|
||
| update_time | DATETIME | - | CURRENT_TIMESTAMP | 更新时间 |
|
||
| deleted | BIT | 1 | 0 | 逻辑删除标识 |
|
||
|
||
## 三、核心数据模型ER图
|
||
|
||
### 1. 客户管理模块ER图
|
||
|
||
```mermaid
|
||
erDiagram
|
||
WATER_CUSTOMER {
|
||
bigint id PK "主键ID"
|
||
varchar customer_code UK "客户编号"
|
||
varchar customer_name "客户名称"
|
||
varchar customer_type "客户类型"
|
||
varchar id_type "证件类型"
|
||
varchar id_number "证件号码"
|
||
varchar phone "联系电话"
|
||
varchar address "详细地址"
|
||
varchar area_code "行政区划代码"
|
||
tinyint status "状态"
|
||
bigint tenant_id "租户ID"
|
||
varchar creator "创建者"
|
||
datetime create_time "创建时间"
|
||
varchar updater "更新者"
|
||
datetime update_time "更新时间"
|
||
tinyint deleted "是否删除"
|
||
}
|
||
|
||
WATER_METER {
|
||
bigint id PK "主键ID"
|
||
varchar meter_code UK "水表编号"
|
||
varchar meter_no "水表表号"
|
||
varchar meter_type "水表类型"
|
||
varchar meter_model "水表型号"
|
||
varchar meter_caliber "水表口径"
|
||
date install_date "安装日期"
|
||
varchar install_position "安装位置"
|
||
decimal initial_reading "初始读数"
|
||
decimal current_reading "当前读数"
|
||
varchar reading_cycle "抄表周期"
|
||
varchar book_code "册本编号"
|
||
tinyint status "状态"
|
||
bigint customer_id FK "客户ID"
|
||
bigint tenant_id "租户ID"
|
||
varchar creator "创建者"
|
||
datetime create_time "创建时间"
|
||
varchar updater "更新者"
|
||
datetime update_time "更新时间"
|
||
tinyint deleted "是否删除"
|
||
}
|
||
|
||
WATER_CUSTOMER_ACCOUNT {
|
||
bigint id PK "主键ID"
|
||
decimal balance "账户余额"
|
||
decimal credit_amount "信用额度"
|
||
date last_payment_date "最近缴费日期"
|
||
tinyint status "账户状态"
|
||
bigint customer_id FK "客户ID"
|
||
bigint tenant_id "租户ID"
|
||
varchar creator "创建者"
|
||
datetime create_time "创建时间"
|
||
varchar updater "更新者"
|
||
datetime update_time "更新时间"
|
||
tinyint deleted "是否删除"
|
||
}
|
||
|
||
WATER_CUSTOMER ||--o{ WATER_METER : "拥有"
|
||
WATER_CUSTOMER ||--|| WATER_CUSTOMER_ACCOUNT : "对应"
|
||
```
|
||
|
||
### 2. 营收管理模块ER图
|
||
|
||
```mermaid
|
||
erDiagram
|
||
WATER_METER_READING {
|
||
bigint id PK "主键ID"
|
||
varchar reading_code UK "抄表记录编号"
|
||
date reading_date "抄表日期"
|
||
decimal reading_value "抄表读数"
|
||
decimal prev_reading_value "上次读数"
|
||
decimal water_usage "用水量"
|
||
varchar reading_type "抄表类型"
|
||
varchar reader_id "抄表员ID"
|
||
varchar remark "备注"
|
||
tinyint status "状态"
|
||
bigint meter_id FK "水表ID"
|
||
bigint tenant_id "租户ID"
|
||
varchar creator "创建者"
|
||
datetime create_time "创建时间"
|
||
varchar updater "更新者"
|
||
datetime update_time "更新时间"
|
||
tinyint deleted "是否删除"
|
||
}
|
||
|
||
WATER_BILL {
|
||
bigint id PK "主键ID"
|
||
varchar bill_code UK "账单编号"
|
||
varchar bill_month "账期"
|
||
decimal water_usage "用水量"
|
||
decimal water_fee "水费金额"
|
||
decimal sewage_fee "污水处理费"
|
||
decimal other_fee "其他费用"
|
||
decimal total_amount "总金额"
|
||
date due_date "缴费截止日期"
|
||
tinyint bill_status "账单状态"
|
||
bigint customer_id FK "客户ID"
|
||
bigint meter_id FK "水表ID"
|
||
bigint reading_id FK "抄表记录ID"
|
||
bigint tenant_id "租户ID"
|
||
varchar creator "创建者"
|
||
datetime create_time "创建时间"
|
||
varchar updater "更新者"
|
||
datetime update_time "更新时间"
|
||
tinyint deleted "是否删除"
|
||
}
|
||
|
||
WATER_PAYMENT {
|
||
bigint id PK "主键ID"
|
||
varchar payment_code UK "缴费记录编号"
|
||
varchar payment_type "缴费类型"
|
||
varchar payment_channel "缴费渠道"
|
||
decimal payment_amount "缴费金额"
|
||
datetime payment_time "缴费时间"
|
||
varchar transaction_no "交易流水号"
|
||
varchar operator_id "操作员ID"
|
||
varchar remark "备注"
|
||
tinyint payment_status "缴费状态"
|
||
bigint bill_id FK "账单ID"
|
||
bigint customer_id FK "客户ID"
|
||
bigint tenant_id "租户ID"
|
||
varchar creator "创建者"
|
||
datetime create_time "创建时间"
|
||
varchar updater "更新者"
|
||
datetime update_time "更新时间"
|
||
tinyint deleted "是否删除"
|
||
}
|
||
|
||
WATER_METER_READING ||--|| WATER_BILL : "生成"
|
||
WATER_BILL ||--o{ WATER_PAYMENT : "对应"
|
||
```
|
||
|
||
### 3. 表务管理模块ER图
|
||
|
||
```mermaid
|
||
erDiagram
|
||
WATER_METER_ARCHIVE {
|
||
bigint id PK "主键ID"
|
||
varchar archive_code UK "档案编号"
|
||
varchar manufacturer "生产厂家"
|
||
date production_date "生产日期"
|
||
int valid_period "有效期(月)"
|
||
date verification_date "检定日期"
|
||
date next_verification_date "下次检定日期"
|
||
varchar certificate_no "检定证书号"
|
||
tinyint archive_status "档案状态"
|
||
bigint meter_id FK "水表ID"
|
||
bigint tenant_id "租户ID"
|
||
varchar creator "创建者"
|
||
datetime create_time "创建时间"
|
||
varchar updater "更新者"
|
||
datetime update_time "更新时间"
|
||
tinyint deleted "是否删除"
|
||
}
|
||
|
||
WATER_METER_WORKORDER {
|
||
bigint id PK "主键ID"
|
||
varchar workorder_code UK "工单编号"
|
||
varchar workorder_type "工单类型"
|
||
varchar workorder_status "工单状态"
|
||
date apply_date "申请日期"
|
||
date plan_date "计划执行日期"
|
||
date execute_date "实际执行日期"
|
||
varchar applicant_id "申请人ID"
|
||
varchar executor_id "执行人ID"
|
||
varchar reason "申请原因"
|
||
varchar result "执行结果"
|
||
bigint meter_id FK "水表ID"
|
||
bigint customer_id FK "客户ID"
|
||
bigint tenant_id "租户ID"
|
||
varchar creator "创建者"
|
||
datetime create_time "创建时间"
|
||
varchar updater "更新者"
|
||
datetime update_time "更新时间"
|
||
tinyint deleted "是否删除"
|
||
}
|
||
|
||
WATER_METER_STOCK {
|
||
bigint id PK "主键ID"
|
||
varchar stock_code UK "库存编号"
|
||
varchar warehouse_code "仓库编码"
|
||
varchar warehouse_name "仓库名称"
|
||
int stock_quantity "库存数量"
|
||
int min_stock "最小库存"
|
||
int max_stock "最大库存"
|
||
varchar meter_model "水表型号"
|
||
varchar meter_caliber "水表口径"
|
||
tinyint stock_status "库存状态"
|
||
bigint tenant_id "租户ID"
|
||
varchar creator "创建者"
|
||
datetime create_time "创建时间"
|
||
varchar updater "更新者"
|
||
datetime update_time "更新时间"
|
||
tinyint deleted "是否删除"
|
||
}
|
||
|
||
WATER_METER ||--|| WATER_METER_ARCHIVE : "对应"
|
||
WATER_METER ||--o{ WATER_METER_WORKORDER : "产生"
|
||
```
|
||
|
||
### 4. 系统管理模块ER图
|
||
|
||
```mermaid
|
||
erDiagram
|
||
SYSTEM_TENANT {
|
||
bigint id PK "主键ID"
|
||
varchar tenant_name "租户名称"
|
||
varchar tenant_code UK "租户编码"
|
||
varchar contact_name "联系人"
|
||
varchar contact_phone "联系电话"
|
||
varchar contact_email "联系邮箱"
|
||
tinyint tenant_status "租户状态"
|
||
datetime expire_time "过期时间"
|
||
varchar domain "域名"
|
||
varchar package_name "套餐名称"
|
||
int user_count "用户数量"
|
||
varchar creator "创建者"
|
||
datetime create_time "创建时间"
|
||
varchar updater "更新者"
|
||
datetime update_time "更新时间"
|
||
tinyint deleted "是否删除"
|
||
}
|
||
|
||
SYSTEM_USERS {
|
||
bigint id PK "主键ID"
|
||
varchar username UK "用户名"
|
||
varchar password "密码"
|
||
varchar nickname "昵称"
|
||
varchar remark "备注"
|
||
varchar dept_id "部门ID"
|
||
varchar post_ids "岗位ID列表"
|
||
varchar email "邮箱"
|
||
varchar mobile "手机号"
|
||
tinyint sex "性别"
|
||
varchar avatar "头像"
|
||
tinyint status "状态"
|
||
datetime login_date "最后登录时间"
|
||
varchar login_ip "最后登录IP"
|
||
bigint tenant_id "租户ID"
|
||
varchar creator "创建者"
|
||
datetime create_time "创建时间"
|
||
varchar updater "更新者"
|
||
datetime update_time "更新时间"
|
||
tinyint deleted "是否删除"
|
||
}
|
||
|
||
SYSTEM_TENANT ||--o{ SYSTEM_USERS : "包含"
|
||
```
|
||
|
||
## 四、核心数据表设计
|
||
|
||
### 1. 表务管理模块ER图
|
||
|
||
```mermaid
|
||
erDiagram
|
||
WATER_METER_WORKORDER {
|
||
bigint id PK "主键ID"
|
||
varchar workorder_code UK "工单编号"
|
||
varchar workorder_type "工单类型"
|
||
varchar workorder_status "工单状态"
|
||
date apply_date "申请日期"
|
||
date plan_date "计划执行日期"
|
||
date execute_date "实际执行日期"
|
||
varchar applicant_id "申请人ID"
|
||
varchar executor_id "执行人ID"
|
||
varchar reason "申请原因"
|
||
varchar result "执行结果"
|
||
bigint meter_id FK "水表ID"
|
||
bigint customer_id FK "客户ID"
|
||
bigint tenant_id "租户ID"
|
||
}
|
||
|
||
WATER_METER_STOCK {
|
||
bigint id PK "主键ID"
|
||
varchar stock_code UK "库存编号"
|
||
varchar meter_brand "水表品牌"
|
||
varchar meter_model "水表型号"
|
||
varchar meter_caliber "水表口径"
|
||
int stock_quantity "库存数量"
|
||
int min_stock "最小库存"
|
||
decimal unit_price "单价"
|
||
varchar warehouse_location "仓库位置"
|
||
tinyint stock_status "库存状态"
|
||
bigint tenant_id "租户ID"
|
||
}
|
||
|
||
WATER_METER_INVENTORY {
|
||
bigint id PK "主键ID"
|
||
varchar inventory_code UK "出入库编号"
|
||
varchar inventory_type "出入库类型"
|
||
int quantity "数量"
|
||
decimal unit_price "单价"
|
||
decimal total_amount "总金额"
|
||
varchar operator_id "操作员ID"
|
||
datetime operation_time "操作时间"
|
||
varchar remark "备注"
|
||
bigint stock_id FK "库存ID"
|
||
bigint workorder_id FK "工单ID"
|
||
bigint tenant_id "租户ID"
|
||
}
|
||
|
||
WATER_METER ||--o{ WATER_METER_WORKORDER : "生成"
|
||
WATER_METER_STOCK ||--o{ WATER_METER_INVENTORY : "出入库"
|
||
WATER_METER_WORKORDER ||--o{ WATER_METER_INVENTORY : "关联"
|
||
```
|
||
|
||
### 2. 系统管理模块ER图
|
||
|
||
```mermaid
|
||
erDiagram
|
||
WATER_DICT_TYPE {
|
||
bigint id PK "主键ID"
|
||
varchar dict_name "字典名称"
|
||
varchar dict_type UK "字典类型"
|
||
varchar remark "备注"
|
||
tinyint status "状态"
|
||
bigint tenant_id "租户ID"
|
||
}
|
||
|
||
WATER_DICT_DATA {
|
||
bigint id PK "主键ID"
|
||
varchar dict_type "字典类型"
|
||
varchar dict_label "字典标签"
|
||
varchar dict_value "字典键值"
|
||
int dict_sort "字典排序"
|
||
varchar color_type "颜色类型"
|
||
varchar css_class "CSS类名"
|
||
varchar remark "备注"
|
||
tinyint status "状态"
|
||
bigint tenant_id "租户ID"
|
||
}
|
||
|
||
WATER_CONFIG {
|
||
bigint id PK "主键ID"
|
||
varchar config_name "参数名称"
|
||
varchar config_key UK "参数键名"
|
||
varchar config_value "参数键值"
|
||
varchar config_type "系统内置"
|
||
varchar remark "备注"
|
||
bigint tenant_id "租户ID"
|
||
}
|
||
|
||
WATER_PRICE_CONFIG {
|
||
bigint id PK "主键ID"
|
||
varchar price_name "水价名称"
|
||
varchar customer_type "客户类型"
|
||
varchar price_type "价格类型"
|
||
decimal base_price "基础价格"
|
||
decimal sewage_price "污水处理费"
|
||
decimal garbage_price "垃圾处理费"
|
||
date effective_date "生效日期"
|
||
date expire_date "失效日期"
|
||
tinyint status "状态"
|
||
bigint tenant_id "租户ID"
|
||
}
|
||
|
||
WATER_DICT_TYPE ||--o{ WATER_DICT_DATA : "包含"
|
||
```
|
||
|
||
## 五、完整DDL语句
|
||
|
||
### 1. 客户管理相关表DDL
|
||
|
||
#### 1.1 客户基本信息表
|
||
|
||
```sql
|
||
CREATE TABLE `water_customer` (
|
||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||
`customer_code` varchar(32) NOT NULL COMMENT '客户编号',
|
||
`customer_name` varchar(100) NOT NULL COMMENT '客户名称',
|
||
`customer_type` varchar(20) NOT NULL COMMENT '客户类型(居民:RESIDENT,非居民:NON_RESIDENT,工业:INDUSTRIAL,行政:ADMINISTRATIVE)',
|
||
`id_type` varchar(20) DEFAULT NULL COMMENT '证件类型(身份证:ID_CARD,营业执照:BUSINESS_LICENSE)',
|
||
`id_number` varchar(30) DEFAULT NULL COMMENT '证件号码',
|
||
`phone` varchar(20) DEFAULT NULL COMMENT '联系电话',
|
||
`mobile` varchar(20) DEFAULT NULL COMMENT '手机号码',
|
||
`email` varchar(100) DEFAULT NULL COMMENT '邮箱',
|
||
`address` varchar(500) DEFAULT NULL COMMENT '详细地址',
|
||
`area_code` varchar(20) DEFAULT NULL COMMENT '行政区划代码',
|
||
`postal_code` varchar(10) DEFAULT NULL COMMENT '邮政编码',
|
||
`contact_person` varchar(50) DEFAULT NULL COMMENT '联系人',
|
||
`bank_account` varchar(50) DEFAULT NULL COMMENT '银行账户',
|
||
`bank_name` varchar(100) DEFAULT NULL COMMENT '开户银行',
|
||
`remark` varchar(500) DEFAULT NULL COMMENT '备注信息',
|
||
`status` tinyint NOT NULL DEFAULT '1' COMMENT '状态(0:停用,1:正常,2:欠费,3:销户)',
|
||
`tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户ID',
|
||
`creator` varchar(64) DEFAULT '' COMMENT '创建者',
|
||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||
`updater` varchar(64) DEFAULT '' COMMENT '更新者',
|
||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `uk_customer_code` (`customer_code`, `tenant_id`),
|
||
KEY `idx_customer_name` (`customer_name`),
|
||
KEY `idx_phone` (`phone`),
|
||
KEY `idx_id_number` (`id_number`),
|
||
KEY `idx_tenant_customer_type` (`tenant_id`, `customer_type`),
|
||
KEY `idx_status` (`status`),
|
||
KEY `idx_create_time` (`create_time`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客户基本信息表';
|
||
```
|
||
|
||
#### 1.2 水表信息表
|
||
|
||
```sql
|
||
CREATE TABLE `water_meter` (
|
||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||
`meter_code` varchar(32) NOT NULL COMMENT '水表编号',
|
||
`meter_no` varchar(30) DEFAULT NULL COMMENT '水表表号',
|
||
`meter_type` varchar(20) NOT NULL COMMENT '水表类型(机械:MECHANICAL,智能:SMART,远传:REMOTE)',
|
||
`meter_model` varchar(50) DEFAULT NULL COMMENT '水表型号',
|
||
`meter_caliber` varchar(10) DEFAULT NULL COMMENT '水表口径(15mm,20mm,25mm等)',
|
||
`manufacturer` varchar(100) DEFAULT NULL COMMENT '生产厂家',
|
||
`production_date` date DEFAULT NULL COMMENT '生产日期',
|
||
`install_date` date DEFAULT NULL COMMENT '安装日期',
|
||
`install_position` varchar(500) DEFAULT NULL COMMENT '安装位置',
|
||
`longitude` decimal(10,7) DEFAULT NULL COMMENT '经度',
|
||
`latitude` decimal(10,7) DEFAULT NULL COMMENT '纬度',
|
||
`initial_reading` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '初始读数',
|
||
`current_reading` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '当前读数',
|
||
`reading_cycle` varchar(20) NOT NULL DEFAULT 'MONTHLY' COMMENT '抄表周期(月度:MONTHLY,双月:BIMONTHLY,季度:QUARTERLY)',
|
||
`book_code` varchar(32) DEFAULT NULL COMMENT '册本编号',
|
||
`reading_route` varchar(100) DEFAULT NULL COMMENT '抄表路线',
|
||
`meter_status` tinyint NOT NULL DEFAULT '1' COMMENT '水表状态(0:停用,1:正常,2:故障,3:拆除)',
|
||
`customer_id` bigint NOT NULL COMMENT '客户ID',
|
||
`tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户ID',
|
||
`creator` varchar(64) DEFAULT '' COMMENT '创建者',
|
||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||
`updater` varchar(64) DEFAULT '' COMMENT '更新者',
|
||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `uk_meter_code` (`meter_code`, `tenant_id`),
|
||
KEY `idx_meter_no` (`meter_no`),
|
||
KEY `idx_customer_id` (`customer_id`),
|
||
KEY `idx_book_code` (`book_code`),
|
||
KEY `idx_meter_type` (`meter_type`),
|
||
KEY `idx_meter_status` (`meter_status`),
|
||
KEY `idx_tenant_status` (`tenant_id`, `meter_status`),
|
||
CONSTRAINT `fk_meter_customer` FOREIGN KEY (`customer_id`) REFERENCES `water_customer` (`id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='水表信息表';
|
||
```
|
||
|
||
### 3. 表务工单管理表DDL
|
||
|
||
#### 3.1 表务工单表
|
||
|
||
```sql
|
||
CREATE TABLE `water_meter_workorder` (
|
||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||
`workorder_code` varchar(32) NOT NULL COMMENT '工单编号',
|
||
`workorder_type` varchar(20) NOT NULL COMMENT '工单类型(换表:CHANGE,移表:MOVE,拆表:REMOVE,装表:INSTALL,维修:REPAIR)',
|
||
`workorder_status` varchar(20) NOT NULL DEFAULT 'PENDING' COMMENT '工单状态(待处理:PENDING,执行中:PROCESSING,已完成:COMPLETED,已取消:CANCELLED)',
|
||
`apply_date` date NOT NULL COMMENT '申请日期',
|
||
`plan_date` date DEFAULT NULL COMMENT '计划执行日期',
|
||
`execute_date` date DEFAULT NULL COMMENT '实际执行日期',
|
||
`applicant_id` varchar(20) DEFAULT NULL COMMENT '申请人ID',
|
||
`applicant_name` varchar(50) DEFAULT NULL COMMENT '申请人姓名',
|
||
`executor_id` varchar(20) DEFAULT NULL COMMENT '执行人ID',
|
||
`executor_name` varchar(50) DEFAULT NULL COMMENT '执行人姓名',
|
||
`reason` varchar(500) DEFAULT NULL COMMENT '申请原因',
|
||
`result` varchar(500) DEFAULT NULL COMMENT '执行结果',
|
||
`old_meter_no` varchar(30) DEFAULT NULL COMMENT '旧水表表号',
|
||
`new_meter_no` varchar(30) DEFAULT NULL COMMENT '新水表表号',
|
||
`old_reading` decimal(10,2) DEFAULT NULL COMMENT '旧表读数',
|
||
`new_reading` decimal(10,2) DEFAULT NULL COMMENT '新表读数',
|
||
`cost_amount` decimal(10,2) DEFAULT NULL COMMENT '费用金额',
|
||
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
|
||
`meter_id` bigint NOT NULL COMMENT '水表ID',
|
||
`customer_id` bigint NOT NULL COMMENT '客户ID',
|
||
`tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户ID',
|
||
`creator` varchar(64) DEFAULT '' COMMENT '创建者',
|
||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||
`updater` varchar(64) DEFAULT '' COMMENT '更新者',
|
||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `uk_workorder_code` (`workorder_code`, `tenant_id`),
|
||
KEY `idx_workorder_type` (`workorder_type`),
|
||
KEY `idx_workorder_status` (`workorder_status`),
|
||
KEY `idx_apply_date` (`apply_date`),
|
||
KEY `idx_meter_id` (`meter_id`),
|
||
KEY `idx_customer_id` (`customer_id`),
|
||
KEY `idx_tenant_type_status` (`tenant_id`, `workorder_type`, `workorder_status`),
|
||
CONSTRAINT `fk_workorder_meter` FOREIGN KEY (`meter_id`) REFERENCES `water_meter` (`id`),
|
||
CONSTRAINT `fk_workorder_customer` FOREIGN KEY (`customer_id`) REFERENCES `water_customer` (`id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='表务工单表';
|
||
```
|
||
|
||
#### 3.2 水表库存管理表
|
||
|
||
```sql
|
||
CREATE TABLE `water_meter_stock` (
|
||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||
`stock_code` varchar(32) NOT NULL COMMENT '库存编号',
|
||
`meter_brand` varchar(50) NOT NULL COMMENT '水表品牌',
|
||
`meter_model` varchar(50) NOT NULL COMMENT '水表型号',
|
||
`meter_caliber` varchar(10) NOT NULL COMMENT '水表口径',
|
||
`meter_type` varchar(20) NOT NULL COMMENT '水表类型',
|
||
`stock_quantity` int NOT NULL DEFAULT '0' COMMENT '库存数量',
|
||
`min_stock` int NOT NULL DEFAULT '0' COMMENT '最小库存',
|
||
`max_stock` int DEFAULT NULL COMMENT '最大库存',
|
||
`unit_price` decimal(10,2) DEFAULT NULL COMMENT '单价',
|
||
`warehouse_location` varchar(100) DEFAULT NULL COMMENT '仓库位置',
|
||
`supplier` varchar(100) DEFAULT NULL COMMENT '供应商',
|
||
`purchase_date` date DEFAULT NULL COMMENT '进货日期',
|
||
`warranty_period` int DEFAULT '24' COMMENT '质保期(月)',
|
||
`stock_status` tinyint NOT NULL DEFAULT '1' COMMENT '库存状态(0:停用,1:正常,2:缺货,3:超储)',
|
||
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
|
||
`tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户ID',
|
||
`creator` varchar(64) DEFAULT '' COMMENT '创建者',
|
||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||
`updater` varchar(64) DEFAULT '' COMMENT '更新者',
|
||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `uk_stock_code` (`stock_code`, `tenant_id`),
|
||
KEY `idx_meter_brand` (`meter_brand`),
|
||
KEY `idx_meter_model` (`meter_model`),
|
||
KEY `idx_meter_caliber` (`meter_caliber`),
|
||
KEY `idx_stock_status` (`stock_status`),
|
||
KEY `idx_tenant_brand_model` (`tenant_id`, `meter_brand`, `meter_model`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='水表库存管理表';
|
||
```
|
||
|
||
### 4. 系统管理相关表DDL
|
||
|
||
#### 4.1 数据字典类型表
|
||
|
||
```sql
|
||
CREATE TABLE `water_dict_type` (
|
||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||
`dict_name` varchar(100) NOT NULL COMMENT '字典名称',
|
||
`dict_type` varchar(100) NOT NULL COMMENT '字典类型',
|
||
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
|
||
`status` tinyint NOT NULL DEFAULT '1' COMMENT '状态(0:停用,1:正常)',
|
||
`tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户ID',
|
||
`creator` varchar(64) DEFAULT '' COMMENT '创建者',
|
||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||
`updater` varchar(64) DEFAULT '' COMMENT '更新者',
|
||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `uk_dict_type` (`dict_type`, `tenant_id`),
|
||
KEY `idx_status` (`status`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数据字典类型表';
|
||
```
|
||
|
||
### 5. 完整DDL语句列表
|
||
|
||
#### 5.1 客户基本信息表 (OpenGauss版本)
|
||
|
||
```sql
|
||
-- OpenGauss数据库DDL语句
|
||
CREATE TABLE water_customer (
|
||
id SERIAL PRIMARY KEY,
|
||
customer_code VARCHAR(32) NOT NULL,
|
||
customer_name VARCHAR(100) NOT NULL,
|
||
customer_type VARCHAR(20) NOT NULL CHECK (customer_type IN ('RESIDENT','NON_RESIDENT','INDUSTRIAL','ADMINISTRATIVE')),
|
||
id_type VARCHAR(20) DEFAULT NULL CHECK (id_type IN ('ID_CARD','BUSINESS_LICENSE') OR id_type IS NULL),
|
||
id_number VARCHAR(30) DEFAULT NULL,
|
||
phone VARCHAR(20) DEFAULT NULL,
|
||
mobile VARCHAR(20) DEFAULT NULL,
|
||
email VARCHAR(100) DEFAULT NULL,
|
||
address VARCHAR(500) DEFAULT NULL,
|
||
area_code VARCHAR(20) DEFAULT NULL,
|
||
postal_code VARCHAR(10) DEFAULT NULL,
|
||
contact_person VARCHAR(50) DEFAULT NULL,
|
||
bank_account VARCHAR(50) DEFAULT NULL,
|
||
bank_name VARCHAR(100) DEFAULT NULL,
|
||
remark VARCHAR(500) DEFAULT NULL,
|
||
status SMALLINT NOT NULL DEFAULT 1 CHECK (status IN (0,1,2,3)),
|
||
tenant_id BIGINT NOT NULL DEFAULT 0,
|
||
creator VARCHAR(64) DEFAULT '',
|
||
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
updater VARCHAR(64) DEFAULT '',
|
||
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
deleted BOOLEAN NOT NULL DEFAULT FALSE
|
||
);
|
||
|
||
-- 创建注释
|
||
COMMENT ON TABLE water_customer IS '客户基本信息表';
|
||
COMMENT ON COLUMN water_customer.id IS '主键ID';
|
||
COMMENT ON COLUMN water_customer.customer_code IS '客户编号';
|
||
COMMENT ON COLUMN water_customer.customer_name IS '客户名称';
|
||
COMMENT ON COLUMN water_customer.customer_type IS '客户类型(居民:RESIDENT,非居民:NON_RESIDENT,工业:INDUSTRIAL,行政:ADMINISTRATIVE)';
|
||
COMMENT ON COLUMN water_customer.id_type IS '证件类型(身份证:ID_CARD,营业执照:BUSINESS_LICENSE)';
|
||
COMMENT ON COLUMN water_customer.id_number IS '证件号码';
|
||
COMMENT ON COLUMN water_customer.phone IS '联系电话';
|
||
COMMENT ON COLUMN water_customer.mobile IS '手机号码';
|
||
COMMENT ON COLUMN water_customer.email IS '邮箱';
|
||
COMMENT ON COLUMN water_customer.address IS '详细地址';
|
||
COMMENT ON COLUMN water_customer.area_code IS '行政区划代码';
|
||
COMMENT ON COLUMN water_customer.postal_code IS '邮政编码';
|
||
COMMENT ON COLUMN water_customer.contact_person IS '联系人';
|
||
COMMENT ON COLUMN water_customer.bank_account IS '银行账户';
|
||
COMMENT ON COLUMN water_customer.bank_name IS '开户银行';
|
||
COMMENT ON COLUMN water_customer.remark IS '备注信息';
|
||
COMMENT ON COLUMN water_customer.status IS '状态(0:停用,1:正常,2:欠费,3:销户)';
|
||
COMMENT ON COLUMN water_customer.tenant_id IS '租户ID';
|
||
COMMENT ON COLUMN water_customer.creator IS '创建者';
|
||
COMMENT ON COLUMN water_customer.create_time IS '创建时间';
|
||
COMMENT ON COLUMN water_customer.updater IS '更新者';
|
||
COMMENT ON COLUMN water_customer.update_time IS '更新时间';
|
||
COMMENT ON COLUMN water_customer.deleted IS '是否删除';
|
||
|
||
-- 创建索引
|
||
CREATE UNIQUE INDEX uk_customer_code ON water_customer (customer_code, tenant_id);
|
||
CREATE INDEX idx_customer_name ON water_customer (customer_name);
|
||
CREATE INDEX idx_phone ON water_customer (phone);
|
||
CREATE INDEX idx_id_number ON water_customer (id_number);
|
||
CREATE INDEX idx_tenant_customer_type ON water_customer (tenant_id, customer_type);
|
||
CREATE INDEX idx_status ON water_customer (status);
|
||
CREATE INDEX idx_create_time ON water_customer (create_time);
|
||
|
||
-- 创建更新时间触发器
|
||
CREATE OR REPLACE FUNCTION update_timestamp()
|
||
RETURNS TRIGGER AS $$
|
||
BEGIN
|
||
NEW.update_time = CURRENT_TIMESTAMP;
|
||
RETURN NEW;
|
||
END;
|
||
$$ LANGUAGE plpgsql;
|
||
|
||
CREATE TRIGGER water_customer_update_timestamp
|
||
BEFORE UPDATE ON water_customer
|
||
FOR EACH ROW
|
||
EXECUTE FUNCTION update_timestamp();
|
||
```
|
||
|
||
#### 1.2 水表信息表
|
||
|
||
```sql
|
||
CREATE TABLE `water_meter` (
|
||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||
`meter_code` varchar(32) NOT NULL COMMENT '水表编号',
|
||
`meter_no` varchar(30) DEFAULT NULL COMMENT '水表表号',
|
||
`meter_type` varchar(20) NOT NULL COMMENT '水表类型(机械:MECHANICAL,智能:SMART,远传:REMOTE)',
|
||
`meter_model` varchar(50) DEFAULT NULL COMMENT '水表型号',
|
||
`meter_caliber` varchar(10) DEFAULT NULL COMMENT '水表口径(15mm,20mm,25mm等)',
|
||
`manufacturer` varchar(100) DEFAULT NULL COMMENT '生产厂家',
|
||
`production_date` date DEFAULT NULL COMMENT '生产日期',
|
||
`install_date` date DEFAULT NULL COMMENT '安装日期',
|
||
`install_position` varchar(500) DEFAULT NULL COMMENT '安装位置',
|
||
`longitude` decimal(10,7) DEFAULT NULL COMMENT '经度',
|
||
`latitude` decimal(10,7) DEFAULT NULL COMMENT '纬度',
|
||
`initial_reading` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '初始读数',
|
||
`current_reading` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '当前读数',
|
||
`reading_cycle` varchar(20) NOT NULL DEFAULT 'MONTHLY' COMMENT '抄表周期(月度:MONTHLY,双月:BIMONTHLY,季度:QUARTERLY)',
|
||
`book_code` varchar(32) DEFAULT NULL COMMENT '册本编号',
|
||
`reading_route` varchar(100) DEFAULT NULL COMMENT '抄表路线',
|
||
`meter_status` tinyint NOT NULL DEFAULT '1' COMMENT '水表状态(0:停用,1:正常,2:故障,3:拆除)',
|
||
`customer_id` bigint NOT NULL COMMENT '客户ID',
|
||
`tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户ID',
|
||
`creator` varchar(64) DEFAULT '' COMMENT '创建者',
|
||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||
`updater` varchar(64) DEFAULT '' COMMENT '更新者',
|
||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `uk_meter_code` (`meter_code`, `tenant_id`),
|
||
KEY `idx_meter_no` (`meter_no`),
|
||
KEY `idx_customer_id` (`customer_id`),
|
||
KEY `idx_book_code` (`book_code`),
|
||
KEY `idx_meter_type` (`meter_type`),
|
||
KEY `idx_meter_status` (`meter_status`),
|
||
KEY `idx_tenant_status` (`tenant_id`, `meter_status`),
|
||
CONSTRAINT `fk_meter_customer` FOREIGN KEY (`customer_id`) REFERENCES `water_customer` (`id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='水表信息表';
|
||
```
|
||
|
||
#### 1.3 客户账户表
|
||
|
||
```sql
|
||
CREATE TABLE `water_customer_account` (
|
||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||
`account_code` varchar(32) NOT NULL COMMENT '账户编号',
|
||
`balance` decimal(12,2) NOT NULL DEFAULT '0.00' COMMENT '账户余额',
|
||
`credit_amount` decimal(12,2) DEFAULT '0.00' COMMENT '信用额度',
|
||
`deposit_amount` decimal(12,2) DEFAULT '0.00' COMMENT '保证金',
|
||
`frozen_amount` decimal(12,2) DEFAULT '0.00' COMMENT '冻结金额',
|
||
`last_payment_date` date DEFAULT NULL COMMENT '最近缴费日期',
|
||
`last_payment_amount` decimal(12,2) DEFAULT NULL COMMENT '最近缴费金额',
|
||
`arrears_amount` decimal(12,2) DEFAULT '0.00' COMMENT '欠费金额',
|
||
`arrears_months` int DEFAULT '0' COMMENT '欠费月数',
|
||
`account_status` tinyint NOT NULL DEFAULT '1' COMMENT '账户状态(0:停用,1:正常,2:欠费,3:冻结)',
|
||
`customer_id` bigint NOT NULL COMMENT '客户ID',
|
||
`tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户ID',
|
||
`creator` varchar(64) DEFAULT '' COMMENT '创建者',
|
||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||
`updater` varchar(64) DEFAULT '' COMMENT '更新者',
|
||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `uk_account_code` (`account_code`, `tenant_id`),
|
||
UNIQUE KEY `uk_customer_account` (`customer_id`, `tenant_id`),
|
||
KEY `idx_account_status` (`account_status`),
|
||
KEY `idx_balance` (`balance`),
|
||
KEY `idx_arrears` (`arrears_amount`),
|
||
CONSTRAINT `fk_account_customer` FOREIGN KEY (`customer_id`) REFERENCES `water_customer` (`id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客户账户信息表';
|
||
```
|
||
|
||
### 2. 营收管理相关表DDL
|
||
|
||
#### 2.1 抄表记录表
|
||
|
||
```sql
|
||
CREATE TABLE `water_meter_reading` (
|
||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||
`reading_code` varchar(32) NOT NULL COMMENT '抄表记录编号',
|
||
`reading_date` date NOT NULL COMMENT '抄表日期',
|
||
`reading_time` datetime DEFAULT NULL COMMENT '抄表时间',
|
||
`reading_value` decimal(10,2) NOT NULL COMMENT '抄表读数',
|
||
`prev_reading_value` decimal(10,2) DEFAULT NULL COMMENT '上次读数',
|
||
`water_usage` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '用水量',
|
||
`reading_type` varchar(20) NOT NULL COMMENT '抄表类型(手工:MANUAL,远传:REMOTE,自报:SELF_REPORT,估算:ESTIMATE)',
|
||
`reading_method` varchar(20) DEFAULT NULL COMMENT '抄表方式(现场:FIELD,拍照:PHOTO,NFC:NFC,扫码:SCAN)',
|
||
`reader_id` varchar(20) DEFAULT NULL COMMENT '抄表员ID',
|
||
`reader_name` varchar(50) DEFAULT NULL COMMENT '抄表员姓名',
|
||
`photo_url` varchar(255) DEFAULT NULL COMMENT '抄表照片URL',
|
||
`reading_location` varchar(200) DEFAULT NULL COMMENT '抄表位置',
|
||
`abnormal_flag` tinyint DEFAULT '0' COMMENT '异常标识(0:正常,1:异常)',
|
||
`abnormal_reason` varchar(200) DEFAULT NULL COMMENT '异常原因',
|
||
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
|
||
`reading_status` tinyint NOT NULL DEFAULT '0' COMMENT '状态(0:未复核,1:已复核,2:已开账,3:作废)',
|
||
`meter_id` bigint NOT NULL COMMENT '水表ID',
|
||
`customer_id` bigint NOT NULL COMMENT '客户ID',
|
||
`tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户ID',
|
||
`creator` varchar(64) DEFAULT '' COMMENT '创建者',
|
||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||
`updater` varchar(64) DEFAULT '' COMMENT '更新者',
|
||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `uk_reading_code` (`reading_code`, `tenant_id`),
|
||
KEY `idx_meter_reading_date` (`meter_id`, `reading_date`),
|
||
KEY `idx_reading_date` (`reading_date`),
|
||
KEY `idx_reader_id` (`reader_id`),
|
||
KEY `idx_reading_status` (`reading_status`),
|
||
KEY `idx_customer_id` (`customer_id`),
|
||
KEY `idx_tenant_meter_date` (`tenant_id`, `meter_id`, `reading_date`),
|
||
CONSTRAINT `fk_reading_meter` FOREIGN KEY (`meter_id`) REFERENCES `water_meter` (`id`),
|
||
CONSTRAINT `fk_reading_customer` FOREIGN KEY (`customer_id`) REFERENCES `water_customer` (`id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='抄表记录表';
|
||
```
|
||
|
||
#### 2.2 水费账单表
|
||
|
||
```sql
|
||
CREATE TABLE `water_bill` (
|
||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||
`bill_code` varchar(32) NOT NULL COMMENT '账单编号',
|
||
`bill_month` varchar(7) NOT NULL COMMENT '账期(格式:YYYY-MM)',
|
||
`bill_date` date NOT NULL COMMENT '开账日期',
|
||
`water_usage` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '用水量',
|
||
`prev_reading` decimal(10,2) DEFAULT NULL COMMENT '上期读数',
|
||
`current_reading` decimal(10,2) DEFAULT NULL COMMENT '本期读数',
|
||
`reading_days` int DEFAULT NULL COMMENT '抄表间隔天数',
|
||
`water_price` decimal(8,4) DEFAULT NULL COMMENT '水价单价',
|
||
`water_fee` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '水费金额',
|
||
`sewage_fee` decimal(10,2) DEFAULT '0.00' COMMENT '污水处理费',
|
||
`garbage_fee` decimal(10,2) DEFAULT '0.00' COMMENT '垃圾处理费',
|
||
`other_fee` decimal(10,2) DEFAULT '0.00' COMMENT '其他费用',
|
||
`adjustment_fee` decimal(10,2) DEFAULT '0.00' COMMENT '调整费用',
|
||
`late_fee` decimal(10,2) DEFAULT '0.00' COMMENT '滞纳金',
|
||
`total_amount` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '总金额',
|
||
`paid_amount` decimal(10,2) DEFAULT '0.00' COMMENT '已缴金额',
|
||
`balance_amount` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '余额',
|
||
`due_date` date NOT NULL COMMENT '缴费截止日期',
|
||
`billing_type` varchar(20) DEFAULT 'NORMAL' COMMENT '开账类型(正常:NORMAL,追补:SUPPLEMENT,调整:ADJUSTMENT)',
|
||
`bill_status` tinyint NOT NULL DEFAULT '0' COMMENT '账单状态(0:未缴费,1:已缴费,2:部分缴费,3:作废)',
|
||
`payment_status` tinyint DEFAULT '0' COMMENT '缴费状态(0:未缴,1:已缴,2:部分缴费)',
|
||
`customer_id` bigint NOT NULL COMMENT '客户ID',
|
||
`meter_id` bigint NOT NULL COMMENT '水表ID',
|
||
`reading_id` bigint DEFAULT NULL COMMENT '抄表记录ID',
|
||
`tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户ID',
|
||
`creator` varchar(64) DEFAULT '' COMMENT '创建者',
|
||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||
`updater` varchar(64) DEFAULT '' COMMENT '更新者',
|
||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `uk_bill_code` (`bill_code`, `tenant_id`),
|
||
KEY `idx_customer_bill_month` (`customer_id`, `bill_month`),
|
||
KEY `idx_meter_bill_month` (`meter_id`, `bill_month`),
|
||
KEY `idx_bill_status` (`bill_status`),
|
||
KEY `idx_due_date` (`due_date`),
|
||
KEY `idx_tenant_customer_month` (`tenant_id`, `customer_id`, `bill_month`),
|
||
CONSTRAINT `fk_bill_customer` FOREIGN KEY (`customer_id`) REFERENCES `water_customer` (`id`),
|
||
CONSTRAINT `fk_bill_meter` FOREIGN KEY (`meter_id`) REFERENCES `water_meter` (`id`),
|
||
CONSTRAINT `fk_bill_reading` FOREIGN KEY (`reading_id`) REFERENCES `water_meter_reading` (`id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='水费账单表';
|
||
```
|
||
|
||
#### 2.3 缴费记录表
|
||
|
||
```sql
|
||
CREATE TABLE `water_payment` (
|
||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||
`payment_code` varchar(32) NOT NULL COMMENT '缴费记录编号',
|
||
`payment_type` varchar(20) NOT NULL COMMENT '缴费类型(正常缴费:NORMAL,预存:PREPAID,退费:REFUND)',
|
||
`payment_channel` varchar(20) NOT NULL COMMENT '缴费渠道(现金:CASH,银行卡:BANK_CARD,微信:WECHAT,支付宝:ALIPAY,银行代扣:BANK_DEDUCT)',
|
||
`payment_amount` decimal(10,2) NOT NULL COMMENT '缴费金额',
|
||
`actual_amount` decimal(10,2) DEFAULT NULL COMMENT '实收金额',
|
||
`change_amount` decimal(10,2) DEFAULT '0.00' COMMENT '找零金额',
|
||
`payment_time` datetime NOT NULL COMMENT '缴费时间',
|
||
`transaction_no` varchar(50) DEFAULT NULL COMMENT '交易流水号',
|
||
`third_party_no` varchar(50) DEFAULT NULL COMMENT '第三方交易号',
|
||
`operator_id` varchar(20) DEFAULT NULL COMMENT '操作员ID',
|
||
`operator_name` varchar(50) DEFAULT NULL COMMENT '操作员姓名',
|
||
`outlet_code` varchar(20) DEFAULT NULL COMMENT '营业网点代码',
|
||
`pos_machine_no` varchar(20) DEFAULT NULL COMMENT 'POS机编号',
|
||
`invoice_no` varchar(30) DEFAULT NULL COMMENT '发票号码',
|
||
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
|
||
`payment_status` tinyint NOT NULL DEFAULT '1' COMMENT '缴费状态(0:待确认,1:成功,2:失败,3:退费)',
|
||
`bill_id` bigint DEFAULT NULL COMMENT '账单ID',
|
||
`customer_id` bigint NOT NULL COMMENT '客户ID',
|
||
`tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户ID',
|
||
`creator` varchar(64) DEFAULT '' COMMENT '创建者',
|
||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||
`updater` varchar(64) DEFAULT '' COMMENT '更新者',
|
||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `uk_payment_code` (`payment_code`, `tenant_id`),
|
||
KEY `idx_customer_payment_time` (`customer_id`, `payment_time`),
|
||
KEY `idx_payment_time` (`payment_time`),
|
||
KEY `idx_transaction_no` (`transaction_no`),
|
||
KEY `idx_operator_id` (`operator_id`),
|
||
KEY `idx_payment_status` (`payment_status`),
|
||
KEY `idx_bill_id` (`bill_id`),
|
||
CONSTRAINT `fk_payment_customer` FOREIGN KEY (`customer_id`) REFERENCES `water_customer` (`id`),
|
||
CONSTRAINT `fk_payment_bill` FOREIGN KEY (`bill_id`) REFERENCES `water_bill` (`id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='缴费记录表';
|
||
```
|
||
|
||
### 3. 表务管理相关表DDL
|
||
|
||
#### 3.1 水表档案表
|
||
|
||
```sql
|
||
CREATE TABLE `water_meter_archive` (
|
||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||
`archive_code` varchar(32) NOT NULL COMMENT '档案编号',
|
||
`manufacturer` varchar(100) DEFAULT NULL COMMENT '生产厂家',
|
||
`production_date` date DEFAULT NULL COMMENT '生产日期',
|
||
`valid_period` int DEFAULT '72' COMMENT '有效期(月)',
|
||
`verification_date` date DEFAULT NULL COMMENT '检定日期',
|
||
`next_verification_date` date DEFAULT NULL COMMENT '下次检定日期',
|
||
`certificate_no` varchar(50) DEFAULT NULL COMMENT '检定证书号',
|
||
`verification_agency` varchar(100) DEFAULT NULL COMMENT '检定机构',
|
||
`accuracy_level` varchar(10) DEFAULT NULL COMMENT '精度等级',
|
||
`max_flow` decimal(8,2) DEFAULT NULL COMMENT '最大流量',
|
||
`nominal_flow` decimal(8,2) DEFAULT NULL COMMENT '常用流量',
|
||
`min_flow` decimal(8,2) DEFAULT NULL COMMENT '最小流量',
|
||
`working_pressure` decimal(8,2) DEFAULT NULL COMMENT '工作压力',
|
||
`purchase_date` date DEFAULT NULL COMMENT '采购日期',
|
||
`purchase_price` decimal(10,2) DEFAULT NULL COMMENT '采购价格',
|
||
`supplier` varchar(100) DEFAULT NULL COMMENT '供应商',
|
||
`warranty_period` int DEFAULT '24' COMMENT '质保期(月)',
|
||
`installation_cost` decimal(10,2) DEFAULT NULL COMMENT '安装费用',
|
||
`archive_status` tinyint NOT NULL DEFAULT '1' COMMENT '档案状态(0:停用,1:正常,2:报废)',
|
||
`meter_id` bigint NOT NULL COMMENT '水表ID',
|
||
`tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户ID',
|
||
`creator` varchar(64) DEFAULT '' COMMENT '创建者',
|
||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||
`updater` varchar(64) DEFAULT '' COMMENT '更新者',
|
||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `uk_archive_code` (`archive_code`, `tenant_id`),
|
||
UNIQUE KEY `uk_meter_archive` (`meter_id`, `tenant_id`),
|
||
KEY `idx_manufacturer` (`manufacturer`),
|
||
KEY `idx_verification_date` (`verification_date`),
|
||
KEY `idx_next_verification_date` (`next_verification_date`),
|
||
KEY `idx_archive_status` (`archive_status`),
|
||
CONSTRAINT `fk_archive_meter` FOREIGN KEY (`meter_id`) REFERENCES `water_meter` (`id`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='水表档案表';
|
||
```
|
||
|
||
### 4. 系统管理相关表DDL
|
||
|
||
#### 4.1 数据字典表
|
||
|
||
```sql
|
||
CREATE TABLE `water_dict_data` (
|
||
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||
`dict_type` varchar(100) NOT NULL COMMENT '字典类型',
|
||
`dict_label` varchar(100) NOT NULL COMMENT '字典标签',
|
||
`dict_value` varchar(100) NOT NULL COMMENT '字典键值',
|
||
`dict_sort` int NOT NULL DEFAULT '0' COMMENT '字典排序',
|
||
`color_type` varchar(100) DEFAULT '' COMMENT '颜色类型',
|
||
`css_class` varchar(100) DEFAULT '' COMMENT 'CSS类名',
|
||
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
|
||
`status` tinyint NOT NULL DEFAULT '1' COMMENT '状态(0:停用,1:正常)',
|
||
`tenant_id` bigint NOT NULL DEFAULT '0' COMMENT '租户ID',
|
||
`creator` varchar(64) DEFAULT '' COMMENT '创建者',
|
||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||
`updater` varchar(64) DEFAULT '' COMMENT '更新者',
|
||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
|
||
PRIMARY KEY (`id`),
|
||
KEY `idx_dict_type` (`dict_type`),
|
||
KEY `idx_dict_value` (`dict_value`),
|
||
KEY `idx_status` (`status`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数据字典表';
|
||
```
|
||
|
||
### 5. 初始化数据脚本
|
||
|
||
```sql
|
||
-- 插入基础字典数据
|
||
INSERT INTO `water_dict_data` (`dict_type`, `dict_label`, `dict_value`, `dict_sort`, `status`, `remark`) VALUES
|
||
('customer_type', '居民用户', 'RESIDENT', 1, 1, '居民生活用水'),
|
||
('customer_type', '非居民用户', 'NON_RESIDENT', 2, 1, '非居民用水'),
|
||
('customer_type', '工业用户', 'INDUSTRIAL', 3, 1, '工业生产用水'),
|
||
('customer_type', '行政用户', 'ADMINISTRATIVE', 4, 1, '行政事业单位用水'),
|
||
|
||
('meter_type', '机械水表', 'MECHANICAL', 1, 1, '传统机械式水表'),
|
||
('meter_type', '智能水表', 'SMART', 2, 1, '智能电子水表'),
|
||
('meter_type', '远传水表', 'REMOTE', 3, 1, '远程传输水表'),
|
||
|
||
('reading_type', '人工抄表', 'MANUAL', 1, 1, '抄表员现场抄表'),
|
||
('reading_type', '远程抄表', 'REMOTE', 2, 1, '远程自动抄表'),
|
||
('reading_type', '客户自报', 'SELF_REPORT', 3, 1, '客户自主上报'),
|
||
('reading_type', '估算抄表', 'ESTIMATE', 4, 1, '估算用水量'),
|
||
|
||
('payment_channel', '现金', 'CASH', 1, 1, '现金缴费'),
|
||
('payment_channel', '银行卡', 'BANK_CARD', 2, 1, '银行卡刷卡'),
|
||
('payment_channel', '微信支付', 'WECHAT', 3, 1, '微信在线支付'),
|
||
('payment_channel', '支付宝', 'ALIPAY', 4, 1, '支付宝在线支付'),
|
||
('payment_channel', '银行代扣', 'BANK_DEDUCT', 5, 1, '银行自动代扣');
|
||
```
|
||
|
||
## 六、OpenGauss数据库特性应用
|
||
|
||
### 1. OpenGauss高级特性
|
||
|
||
#### 1.1 分区表设计
|
||
```sql
|
||
-- 按月份分区的账单表
|
||
CREATE TABLE water_bill (
|
||
-- 字段定义...
|
||
) PARTITION BY RANGE (bill_month) (
|
||
PARTITION p202401 VALUES LESS THAN ('2024-02'),
|
||
PARTITION p202402 VALUES LESS THAN ('2024-03'),
|
||
PARTITION p202403 VALUES LESS THAN ('2024-04')
|
||
-- 继续按月创建分区...
|
||
);
|
||
```
|
||
|
||
#### 1.2 列存储表
|
||
```sql
|
||
-- 统计分析用的列存储表
|
||
CREATE TABLE water_bill_stats (
|
||
-- 字段定义...
|
||
) WITH (ORIENTATION = COLUMN);
|
||
```
|
||
|
||
#### 1.3 内存表
|
||
```sql
|
||
-- 配置参数缓存表
|
||
CREATE TABLE water_config_cache (
|
||
-- 字段定义...
|
||
) WITH (ORIENTATION = ROW, STORAGE_TYPE = USTORE);
|
||
```
|
||
|
||
### 2. 性能优化配置
|
||
|
||
#### 2.1 连接池配置
|
||
```sql
|
||
-- OpenGauss连接池参数
|
||
ALTER SYSTEM SET max_connections = 200;
|
||
ALTER SYSTEM SET shared_buffers = '256MB';
|
||
ALTER SYSTEM SET effective_cache_size = '1GB';
|
||
ALTER SYSTEM SET work_mem = '4MB';
|
||
```
|
||
|
||
#### 2.2 并行查询
|
||
```sql
|
||
-- 启用并行查询
|
||
ALTER SYSTEM SET max_parallel_workers = 8;
|
||
ALTER SYSTEM SET max_parallel_workers_per_gather = 4;
|
||
```
|
||
|
||
## 七、索引设计与优化
|
||
|
||
### 1. 基础索引设计
|
||
|
||
#### 1.1 主键索引
|
||
- 所有表使用SERIAL主键,自动创建B树索引
|
||
- 支持OpenGauss的快速主键查询优化
|
||
|
||
#### 1.2 唯一索引
|
||
```sql
|
||
-- 客户编号唯一索引
|
||
CREATE UNIQUE INDEX uk_customer_code ON water_customer (customer_code, tenant_id);
|
||
-- 水表编号唯一索引
|
||
CREATE UNIQUE INDEX uk_meter_code ON water_meter (meter_code, tenant_id);
|
||
```
|
||
|
||
#### 1.3 复合索引
|
||
```sql
|
||
-- 多租户查询优化
|
||
CREATE INDEX idx_tenant_customer_type ON water_customer (tenant_id, customer_type);
|
||
-- 账单查询优化
|
||
CREATE INDEX idx_tenant_customer_month ON water_bill (tenant_id, customer_id, bill_month);
|
||
-- 抄表查询优化
|
||
CREATE INDEX idx_tenant_meter_date ON water_meter_reading (tenant_id, meter_id, reading_date);
|
||
```
|
||
|
||
### 2. OpenGauss特殊索引
|
||
|
||
#### 2.1 HASH索引
|
||
```sql
|
||
-- 等值查询优化
|
||
CREATE INDEX CONCURRENTLY idx_customer_phone_hash ON water_customer USING HASH (phone);
|
||
```
|
||
|
||
#### 2.2 GIN索引
|
||
```sql
|
||
-- 全文检索索引
|
||
CREATE INDEX idx_customer_name_gin ON water_customer USING GIN (to_tsvector('simple', customer_name));
|
||
```
|
||
|
||
#### 2.3 部分索引
|
||
```sql
|
||
-- 只对有效数据建索引
|
||
CREATE INDEX idx_active_customers ON water_customer (customer_code) WHERE deleted = FALSE AND status = 1;
|
||
```
|
||
|
||
## 八、OpenGauss数据安全设计
|
||
|
||
### 1. 内置安全特性
|
||
|
||
#### 1.1 透明数据加密 (TDE)
|
||
```sql
|
||
-- 启用表级加密
|
||
CREATE TABLE water_customer_encrypted (
|
||
-- 字段定义...
|
||
) WITH (ENCRYPTION_TYPE = 'AES_128_CTR');
|
||
|
||
-- 敏感字段加密
|
||
ALTER TABLE water_customer
|
||
ADD COLUMN id_number_encrypted BYTEA
|
||
GENERATED ALWAYS AS (gs_encrypt_aes128(id_number, '密钥')) STORED;
|
||
```
|
||
|
||
#### 1.2 行级安全策略 (RLS)
|
||
```sql
|
||
-- 创建多租户行级安全
|
||
ALTER TABLE water_customer ENABLE ROW LEVEL SECURITY;
|
||
|
||
-- 创建策略
|
||
CREATE POLICY tenant_isolation_policy ON water_customer
|
||
FOR ALL TO PUBLIC
|
||
USING (tenant_id = current_setting('app.current_tenant_id')::bigint);
|
||
```
|
||
|
||
#### 1.3 动态数据脱敏
|
||
```sql
|
||
-- 创建脱敏函数
|
||
CREATE OR REPLACE FUNCTION mask_phone(phone_no TEXT)
|
||
RETURNS TEXT AS $$
|
||
BEGIN
|
||
RETURN SUBSTRING(phone_no, 1, 3) || '****' || SUBSTRING(phone_no, 8);
|
||
END;
|
||
$$ LANGUAGE plpgsql;
|
||
|
||
-- 创建脱敏视图
|
||
CREATE VIEW water_customer_masked AS
|
||
SELECT
|
||
id, customer_code, customer_name,
|
||
mask_phone(phone) as phone_masked,
|
||
-- 其他字段...
|
||
FROM water_customer;
|
||
```
|
||
|
||
### 2. 权限控制体系
|
||
|
||
#### 2.1 角色权限设计
|
||
```sql
|
||
-- 创建业务角色
|
||
CREATE ROLE water_admin;
|
||
CREATE ROLE water_operator;
|
||
CREATE ROLE water_viewer;
|
||
|
||
-- 分配权限
|
||
GRANT ALL ON water_customer TO water_admin;
|
||
GRANT SELECT, INSERT, UPDATE ON water_customer TO water_operator;
|
||
GRANT SELECT ON water_customer_masked TO water_viewer;
|
||
```
|
||
|
||
#### 2.2 列级权限控制
|
||
```sql
|
||
-- 敏感字段权限控制
|
||
REVOKE ALL ON water_customer FROM PUBLIC;
|
||
GRANT SELECT (id, customer_name, phone) ON water_customer TO water_viewer;
|
||
GRANT SELECT ON water_customer TO water_admin;
|
||
```
|
||
|
||
### 3. 审计与监控
|
||
|
||
#### 3.1 审计日志配置
|
||
```sql
|
||
-- 启用审计
|
||
ALTER SYSTEM SET audit_enabled = on;
|
||
ALTER SYSTEM SET audit_directory = '/data/audit';
|
||
ALTER SYSTEM SET audit_file_remain_threshold = 1024;
|
||
|
||
-- 配置审计策略
|
||
SELECT pg_audit_set_policy('DDL_LOGIN_LOGOUT', 'DDL, LOGIN, LOGOUT');
|
||
SELECT pg_audit_set_policy('DML_DCL', 'DML, DCL');
|
||
```
|
||
|
||
#### 3.2 敏感操作监控
|
||
```sql
|
||
-- 创建敏感操作触发器
|
||
CREATE OR REPLACE FUNCTION audit_sensitive_data()
|
||
RETURNS TRIGGER AS $$
|
||
BEGIN
|
||
INSERT INTO audit_log (
|
||
table_name, operation, old_values, new_values,
|
||
user_name, operation_time
|
||
) VALUES (
|
||
TG_TABLE_NAME, TG_OP,
|
||
row_to_json(OLD), row_to_json(NEW),
|
||
current_user, current_timestamp
|
||
);
|
||
RETURN COALESCE(NEW, OLD);
|
||
END;
|
||
$$ LANGUAGE plpgsql;
|
||
|
||
-- 应用到敏感表
|
||
CREATE TRIGGER audit_customer_changes
|
||
AFTER INSERT OR UPDATE OR DELETE ON water_customer
|
||
FOR EACH ROW EXECUTE FUNCTION audit_sensitive_data();
|
||
```
|
||
|
||
### 4. 数据备份与灾备
|
||
|
||
#### 4.1 OpenGauss备份策略
|
||
```sql
|
||
-- 全量备份
|
||
gs_backup -D /data/backup -h localhost -p 5432 -U backup_user
|
||
|
||
-- 增量备份
|
||
gs_backup -D /data/backup -h localhost -p 5432 -U backup_user --incremental
|
||
|
||
-- 归档日志备份
|
||
ALTER SYSTEM SET archive_mode = on;
|
||
ALTER SYSTEM SET archive_command = 'cp %p /data/archive/%f';
|
||
```
|
||
|
||
#### 4.2 主备同步配置
|
||
```sql
|
||
-- 主库配置
|
||
ALTER SYSTEM SET synchronous_standby_names = 'standby1';
|
||
ALTER SYSTEM SET synchronous_commit = on;
|
||
|
||
-- 备库配置
|
||
ALTER SYSTEM SET hot_standby = on;
|
||
ALTER SYSTEM SET max_standby_streaming_delay = 30s;
|
||
```
|
||
|
||
### 5. 国产化安全合规
|
||
|
||
#### 5.1 等保三级要求
|
||
- **身份鉴别**:支持多因子认证、密码复杂度策略
|
||
- **访问控制**:基于角色的强制访问控制
|
||
- **安全审计**:完整的操作审计和安全事件记录
|
||
- **数据完整性**:数据校验和完整性保护
|
||
- **数据保密性**:敏感数据加密存储和传输
|
||
|
||
#### 5.2 国产化认证
|
||
- 华为OpenGauss已通过国家密码管理局商用密码产品认证
|
||
- 支持国产SM2/SM3/SM4密码算法
|
||
- 符合《网络安全法》、《数据安全法》等法规要求
|
||
|
||
```sql
|
||
-- 使用国产SM4算法加密
|
||
CREATE TABLE water_customer_sm4 (
|
||
-- 字段定义...
|
||
) WITH (ENCRYPTION_TYPE = 'SM4_CTR');
|
||
```
|
||
---
|
||
|
||
# 福建水务营收系统接口设计文档
|
||
|
||
## 文档信息
|
||
| 项目信息 | 详情 |
|
||
|---------|------|
|
||
| **项目名称** | 福建水务营收系统 |
|
||
| **文档类型** | 概要设计文档 |
|
||
| **技术框架** | RuoYi-Vue-Pro + yudao-ui-admin-vue3 |
|
||
| **文档版本** | v1.0 |
|
||
| **编写日期** | 2024-12-19 |
|
||
| **文档状态** | 🟡 进行中 |
|
||
|
||
## 目录
|
||
- [1. 接口概述](#1-接口概述)
|
||
- [2. 外部接口](#2-外部接口)
|
||
- [3. 内部接口](#3-内部接口)
|
||
- [4. 接口标准](#4-接口标准)
|
||
|
||
## 1. 接口概述
|
||
|
||
福建水务业务系统提供丰富的接口,用于与外部系统集成以及系统内部各模块间的数据交换。接口设计遵循标准化、安全性、可扩展性的原则,基于RuoYi-Vue-Pro框架采用RESTful风格设计,支持JSON数据格式。
|
||
|
||
### 1.1 接口设计原则
|
||
|
||
- **统一性**:所有接口遵循统一的设计规范和数据格式
|
||
- **安全性**:接口通过认证授权、参数校验等机制保障安全
|
||
- **可维护性**:接口文档完善,便于维护和升级
|
||
- **兼容性**:接口设计考虑版本兼容,支持平滑升级
|
||
- **性能优化**:接口设计考虑性能,支持缓存、分页等机制
|
||
|
||
### 1.2 RESTful API规范
|
||
|
||
系统API接口采用RESTful风格设计,主要规范如下:
|
||
|
||
#### 1.2.1 资源命名
|
||
|
||
- 使用名词复数表示资源集合,如`/users`、`/meters`
|
||
- 使用资源ID标识特定资源,如`/users/1`、`/meters/123`
|
||
- 资源层级关系通过路径嵌套表示,如`/users/1/meters`
|
||
|
||
#### 1.2.2 HTTP方法
|
||
|
||
- GET:获取资源
|
||
- POST:创建资源
|
||
- PUT:更新资源(全量更新)
|
||
- PATCH:部分更新资源
|
||
- DELETE:删除资源
|
||
|
||
#### 1.2.3 状态码
|
||
|
||
- 200 OK:请求成功
|
||
- 201 Created:资源创建成功
|
||
- 400 Bad Request:请求参数错误
|
||
- 401 Unauthorized:未授权
|
||
- 403 Forbidden:权限不足
|
||
- 404 Not Found:资源不存在
|
||
- 500 Internal Server Error:服务器内部错误
|
||
|
||
#### 1.2.4 响应格式
|
||
|
||
系统统一采用以下JSON格式响应:
|
||
|
||
```json
|
||
{
|
||
"code": 0, // 业务状态码,0表示成功,非0表示失败
|
||
"data": {}, // 响应数据
|
||
"msg": "success" // 响应消息
|
||
}
|
||
```
|
||
|
||
分页查询响应格式:
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"data": {
|
||
"list": [], // 数据列表
|
||
"total": 100, // 总记录数
|
||
"pageNum": 1, // 当前页码
|
||
"pageSize": 10 // 每页记录数
|
||
},
|
||
"msg": "success"
|
||
}
|
||
```
|
||
|
||
### 1.3 接口文档
|
||
|
||
系统使用Knife4j(基于Swagger)自动生成API文档,文档地址为:`http://{系统地址}/doc.html`。
|
||
|
||
主要特点:
|
||
- 在线接口文档:支持在线查看接口定义
|
||
- 接口调试:支持在线调试接口
|
||
- 文档导出:支持导出OpenAPI规范文档
|
||
- 权限控制:支持对接口文档的访问控制
|
||
|
||
## 2. 外部接口
|
||
|
||
### 2.1 银行接口对接
|
||
|
||
#### 2.1.1 银行代扣接口
|
||
|
||
**功能描述**:通过银行系统自动从用户账户中扣除水费。
|
||
|
||
**接口详情**:
|
||
- **接口方式**:文件交换(FTP/SFTP)
|
||
- **数据格式**:定长文本文件
|
||
- **交换频率**:每日凌晨2:00
|
||
- **文件编码**:GBK
|
||
|
||
**代扣文件格式**:
|
||
```text
|
||
记录类型(1位) + 客户号(12位) + 户名(30位) + 银行账号(20位) + 扣款金额(12位,含2位小数) + 账期(6位) + 保留字段(19位)
|
||
```
|
||
|
||
**代扣文件示例**:
|
||
```text
|
||
1C00000000001张三 62172511001234567890000009180202412
|
||
1C00000000002李四 62172511001234567891000015460202412
|
||
```
|
||
|
||
**回盘文件格式**:
|
||
```text
|
||
记录类型(1位) + 客户号(12位) + 银行账号(20位) + 扣款金额(12位) + 处理状态(1位) + 银行流水号(20位) + 处理时间(14位) + 失败原因(20位)
|
||
```
|
||
|
||
**Java实现示例**:
|
||
```java
|
||
@Service
|
||
public class BankDeductServiceImpl implements BankDeductService {
|
||
|
||
@Resource
|
||
private SftpTemplate sftpTemplate;
|
||
@Resource
|
||
private BillService billService;
|
||
|
||
@Scheduled(cron = "0 0 2 * * ?")
|
||
public void generateDeductFile() {
|
||
LocalDate deductDate = LocalDate.now();
|
||
|
||
// 获取待代扣账单
|
||
List<BillDO> deductBills = billService.getDeductBills(deductDate);
|
||
|
||
// 生成代扣文件
|
||
String fileName = "DEDUCT_" + deductDate.format(DateTimeFormatter.ofPattern("yyyyMMdd")) + ".txt";
|
||
String fileContent = buildDeductFileContent(deductBills);
|
||
|
||
// 上传至银行SFTP
|
||
sftpTemplate.put(fileName, fileContent.getBytes(StandardCharsets.UTF_8), "/upload/");
|
||
|
||
// 记录代扣文件日志
|
||
DeductFileLogDO log = new DeductFileLogDO();
|
||
log.setFileName(fileName);
|
||
log.setFileStatus("UPLOADED");
|
||
log.setRecordCount(deductBills.size());
|
||
deductFileLogMapper.insert(log);
|
||
}
|
||
|
||
private String buildDeductFileContent(List<BillDO> bills) {
|
||
StringBuilder content = new StringBuilder();
|
||
for (BillDO bill : bills) {
|
||
content.append("1") // 记录类型
|
||
.append(StringUtils.rightPad(bill.getCustomerCode(), 12)) // 客户号
|
||
.append(StringUtils.rightPad(bill.getCustomerName(), 30)) // 户名
|
||
.append(StringUtils.rightPad(bill.getBankAccount(), 20)) // 银行账号
|
||
.append(String.format("%012d", bill.getTotalAmount().multiply(new BigDecimal(100)).intValue())) // 金额(分)
|
||
.append(bill.getBillMonth().replace("-", "")) // 账期
|
||
.append(StringUtils.repeat(" ", 19)) // 保留字段
|
||
.append("\n");
|
||
}
|
||
return content.toString();
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 2.1.2 银行实时缴费接口
|
||
|
||
**功能描述**:用户在银行柜台、网上银行或手机银行实时缴纳水费。
|
||
|
||
**接口详情**:
|
||
- **接口方式**:HTTP POST
|
||
- **请求URL**:`https://bank.api.com/payment/water-fee`
|
||
- **数据格式**:JSON
|
||
- **认证方式**:API Key + 签名
|
||
|
||
**请求参数**:
|
||
```json
|
||
{
|
||
"merchantId": "WATER001",
|
||
"customerCode": "C001",
|
||
"billCodes": ["B202412190001"],
|
||
"totalAmount": 91.80,
|
||
"bankAccount": "6217251100123456789",
|
||
"customerName": "张三",
|
||
"timestamp": "20241219103000",
|
||
"signature": "ABC123DEF456..."
|
||
}
|
||
```
|
||
|
||
**响应参数**:
|
||
```json
|
||
{
|
||
"resultCode": "0000",
|
||
"resultMsg": "交易成功",
|
||
"data": {
|
||
"transactionId": "TXN20241219001",
|
||
"paymentTime": "20241219103001",
|
||
"bankSerial": "BNK20241219001234"
|
||
}
|
||
}
|
||
```
|
||
|
||
### 2.2 支付宝接口对接
|
||
|
||
**功能描述**:用户通过支付宝缴纳水费,支持扫码支付和H5支付。
|
||
|
||
**接口详情**:
|
||
- **接口方式**:HTTP POST
|
||
- **支付方式**:统一收单交易预创建(alipay.trade.precreate)
|
||
- **数据格式**:JSON
|
||
- **认证方式**:RSA2签名
|
||
|
||
**预创建支付请求参数**:
|
||
```json
|
||
{
|
||
"app_id": "2021001234567890",
|
||
"method": "alipay.trade.precreate",
|
||
"charset": "UTF-8",
|
||
"sign_type": "RSA2",
|
||
"timestamp": "2024-12-19 10:30:00",
|
||
"version": "1.0",
|
||
"notify_url": "https://water.example.com/api/payment/alipay/notify",
|
||
"biz_content": {
|
||
"out_trade_no": "P202412190002",
|
||
"total_amount": "91.80",
|
||
"subject": "水费缴费",
|
||
"body": "2024年12月水费-客户编号:C001",
|
||
"store_id": "WATER_STORE_001",
|
||
"timeout_express": "30m"
|
||
}
|
||
}
|
||
```
|
||
|
||
**支付宝响应参数**:
|
||
```json
|
||
{
|
||
"alipay_trade_precreate_response": {
|
||
"code": "10000",
|
||
"msg": "Success",
|
||
"out_trade_no": "P202412190002",
|
||
"qr_code": "https://qr.alipay.com/bax08945xtdnfwgqmwi200b4"
|
||
},
|
||
"sign": "ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE"
|
||
}
|
||
```
|
||
|
||
**Java实现示例**:
|
||
```java
|
||
@Service
|
||
public class AlipayServiceImpl implements AlipayService {
|
||
|
||
@Resource
|
||
private AlipayClient alipayClient;
|
||
|
||
@Override
|
||
public AlipayPaymentRespVO createPayment(AlipayPaymentReqVO request) {
|
||
AlipayTradePrecreateRequest alipayRequest = new AlipayTradePrecreateRequest();
|
||
alipayRequest.setNotifyUrl("https://water.example.com/api/payment/alipay/notify");
|
||
|
||
AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
|
||
model.setOutTradeNo(request.getPaymentCode());
|
||
model.setTotalAmount(request.getTotalAmount().toString());
|
||
model.setSubject("水费缴费");
|
||
model.setBody("账单号:" + String.join(",", request.getBillCodes()));
|
||
model.setTimeoutExpress("30m");
|
||
|
||
alipayRequest.setBizModel(model);
|
||
|
||
try {
|
||
AlipayTradePrecreateResponse response = alipayClient.execute(alipayRequest);
|
||
if (response.isSuccess()) {
|
||
return AlipayPaymentRespVO.builder()
|
||
.paymentCode(request.getPaymentCode())
|
||
.qrCode(response.getQrCode())
|
||
.outTradeNo(response.getOutTradeNo())
|
||
.build();
|
||
} else {
|
||
throw new BizException(ALIPAY_PAY_FAILED, response.getSubMsg());
|
||
}
|
||
} catch (AlipayApiException e) {
|
||
throw new BizException(ALIPAY_PAY_ERROR, e.getErrMsg());
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 2.3 微信支付接口对接
|
||
|
||
**功能描述**:用户通过微信支付缴纳水费,支持扫码支付和小程序支付。
|
||
|
||
**接口详情**:
|
||
- **接口方式**:HTTP POST
|
||
- **支付方式**:Native支付(扫码)/ JSAPI支付(小程序)
|
||
- **请求URL**:`https://api.mch.weixin.qq.com/v3/pay/transactions/native`
|
||
- **数据格式**:JSON
|
||
- **认证方式**:微信支付V3签名
|
||
|
||
**统一下单请求参数**:
|
||
```json
|
||
{
|
||
"appid": "wx8888888888888888",
|
||
"mchid": "1900000109",
|
||
"description": "水费缴费-2024年12月",
|
||
"out_trade_no": "P202412190003",
|
||
"notify_url": "https://water.example.com/api/payment/wechat/notify",
|
||
"amount": {
|
||
"total": 9180,
|
||
"currency": "CNY"
|
||
},
|
||
"attach": "客户编号:C001,账单号:B202412190001",
|
||
"goods_tag": "WATER_FEE",
|
||
"time_expire": "2024-12-19T11:00:00+08:00"
|
||
}
|
||
```
|
||
|
||
**微信支付响应参数**:
|
||
```json
|
||
{
|
||
"code_url": "weixin://wxpay/bizpayurl?pr=HuaLcAKwa"
|
||
}
|
||
```
|
||
|
||
**支付结果通知参数**:
|
||
```json
|
||
{
|
||
"id": "EV-2018022511223320873",
|
||
"create_time": "2024-12-19T10:30:00+08:00",
|
||
"resource_type": "encrypt-resource",
|
||
"event_type": "TRANSACTION.SUCCESS",
|
||
"summary": "支付成功",
|
||
"resource": {
|
||
"original_type": "transaction",
|
||
"algorithm": "AEAD_AES_256_GCM",
|
||
"ciphertext": "...",
|
||
"associated_data": "transaction",
|
||
"nonce": "..."
|
||
}
|
||
}
|
||
```
|
||
|
||
### 2.4 短信接口
|
||
|
||
**功能描述**:向用户发送各类业务通知短信。
|
||
|
||
**接口规范**:
|
||
- 接口方式:HTTP接口
|
||
- 数据格式:JSON
|
||
- 交换频率:实时
|
||
|
||
### 2.5 物联网集抄平台接口
|
||
|
||
**功能描述**:与物联网集抄平台交互,获取智能水表数据。
|
||
|
||
**接口规范**:
|
||
- 接口方式:HTTP接口或WebService
|
||
- 数据格式:JSON或XML
|
||
- 交换频率:定时或实时
|
||
|
||
## 3. 内部接口
|
||
|
||
### 3.1 客户管理API接口
|
||
|
||
#### 3.1.1 客户信息查询接口
|
||
|
||
**功能描述**:根据客户ID查询客户详细信息。
|
||
|
||
**接口详情**:
|
||
- **请求方式**:GET
|
||
- **请求路径**:`/admin-api/water/customer/{id}`
|
||
- **请求头**:`Authorization: Bearer {token}`
|
||
|
||
**请求参数**:
|
||
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|
||
|-------|------|------|------|------|
|
||
| id | Long | 是 | 客户ID | 1 |
|
||
|
||
**响应参数**:
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"msg": "操作成功",
|
||
"data": {
|
||
"id": 1,
|
||
"customerCode": "C001",
|
||
"customerName": "张三",
|
||
"customerType": "RESIDENT",
|
||
"phone": "13800138000",
|
||
"address": "福建省福州市台江区XX街道XX号",
|
||
"status": 1,
|
||
"createTime": "2024-12-19 10:00:00"
|
||
}
|
||
}
|
||
```
|
||
|
||
**RuoYi-Vue-Pro代码示例**:
|
||
```java
|
||
@RestController
|
||
@RequestMapping("/admin-api/water/customer")
|
||
@Tag(name = "管理后台 - 客户管理")
|
||
@Validated
|
||
public class CustomerController {
|
||
|
||
@Resource
|
||
private CustomerService customerService;
|
||
|
||
@GetMapping("/{id}")
|
||
@Operation(summary = "获得客户")
|
||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||
@PreAuthorize("@ss.hasPermission('water:customer:query')")
|
||
public CommonResult<CustomerRespVO> getCustomer(@PathVariable("id") Long id) {
|
||
CustomerDO customer = customerService.getCustomer(id);
|
||
return success(BeanUtils.toBean(customer, CustomerRespVO.class));
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 3.1.2 客户分页查询接口
|
||
|
||
**功能描述**:分页查询客户列表信息。
|
||
|
||
**接口详情**:
|
||
- **请求方式**:GET
|
||
- **请求路径**:`/admin-api/water/customer/page`
|
||
|
||
**请求参数**:
|
||
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|
||
|-------|------|------|------|------|
|
||
| pageNo | Integer | 否 | 页码,默认1 | 1 |
|
||
| pageSize | Integer | 否 | 每页条数,默认10 | 10 |
|
||
| customerName | String | 否 | 客户名称 | 张三 |
|
||
| customerCode | String | 否 | 客户编号 | C001 |
|
||
| customerType | String | 否 | 客户类型 | RESIDENT |
|
||
| phone | String | 否 | 联系电话 | 138 |
|
||
|
||
**响应参数**:
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"msg": "操作成功",
|
||
"data": {
|
||
"list": [
|
||
{
|
||
"id": 1,
|
||
"customerCode": "C001",
|
||
"customerName": "张三",
|
||
"customerType": "RESIDENT",
|
||
"phone": "13800138000",
|
||
"address": "福建省福州市台江区XX街道XX号",
|
||
"status": 1,
|
||
"createTime": "2024-12-19 10:00:00"
|
||
}
|
||
],
|
||
"total": 1
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 3.1.3 客户创建接口
|
||
|
||
**功能描述**:创建新客户记录。
|
||
|
||
**接口详情**:
|
||
- **请求方式**:POST
|
||
- **请求路径**:`/admin-api/water/customer/create`
|
||
|
||
**请求参数**:
|
||
```json
|
||
{
|
||
"customerCode": "C002",
|
||
"customerName": "李四",
|
||
"customerType": "RESIDENT",
|
||
"idType": "ID_CARD",
|
||
"idNumber": "350103199001011234",
|
||
"phone": "13900139000",
|
||
"address": "福建省福州市鼓楼区XX街道XX号"
|
||
}
|
||
```
|
||
|
||
**响应参数**:
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"msg": "操作成功",
|
||
"data": 2
|
||
}
|
||
```
|
||
|
||
**Service层代码示例**:
|
||
```java
|
||
@Service
|
||
@Validated
|
||
public class CustomerServiceImpl implements CustomerService {
|
||
|
||
@Resource
|
||
private CustomerMapper customerMapper;
|
||
|
||
@Override
|
||
public Long createCustomer(CustomerSaveReqVO createReqVO) {
|
||
// 校验客户编号唯一性
|
||
validateCustomerCodeUnique(createReqVO.getCustomerCode());
|
||
|
||
// 创建客户
|
||
CustomerDO customer = BeanUtils.toBean(createReqVO, CustomerDO.class);
|
||
customerMapper.insert(customer);
|
||
return customer.getId();
|
||
}
|
||
|
||
private void validateCustomerCodeUnique(String customerCode) {
|
||
CustomerDO existCustomer = customerMapper.selectByCustomerCode(customerCode);
|
||
if (existCustomer != null) {
|
||
throw exception(CUSTOMER_CODE_DUPLICATE);
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3.2 水表管理API接口
|
||
|
||
#### 3.2.1 水表信息查询接口
|
||
|
||
**功能描述**:根据水表ID查询水表详细信息。
|
||
|
||
**接口详情**:
|
||
- **请求方式**:GET
|
||
- **请求路径**:`/admin-api/water/meter/{id}`
|
||
- **请求头**:`Authorization: Bearer {token}`
|
||
|
||
**请求参数**:
|
||
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|
||
|-------|------|------|------|------|
|
||
| id | Long | 是 | 水表ID | 1 |
|
||
|
||
**响应参数**:
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"msg": "操作成功",
|
||
"data": {
|
||
"id": 1,
|
||
"meterCode": "M001",
|
||
"meterNo": "20241219001",
|
||
"meterType": "SMART",
|
||
"meterModel": "LXSY-15E",
|
||
"meterCaliber": "15mm",
|
||
"installDate": "2024-01-15",
|
||
"installPosition": "1层水表井",
|
||
"initialReading": 0.00,
|
||
"currentReading": 156.32,
|
||
"readingCycle": "MONTHLY",
|
||
"meterStatus": 1,
|
||
"customerId": 1,
|
||
"customerName": "张三"
|
||
}
|
||
}
|
||
```
|
||
|
||
**Controller代码示例**:
|
||
```java
|
||
@RestController
|
||
@RequestMapping("/admin-api/water/meter")
|
||
@Tag(name = "管理后台 - 水表管理")
|
||
@Validated
|
||
public class MeterController {
|
||
|
||
@Resource
|
||
private MeterService meterService;
|
||
|
||
@GetMapping("/{id}")
|
||
@Operation(summary = "获得水表")
|
||
@Parameter(name = "id", description = "编号", required = true)
|
||
@PreAuthorize("@ss.hasPermission('water:meter:query')")
|
||
public CommonResult<MeterRespVO> getMeter(@PathVariable("id") Long id) {
|
||
MeterDO meter = meterService.getMeter(id);
|
||
return success(BeanUtils.toBean(meter, MeterRespVO.class));
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 3.2.2 抄表记录创建接口
|
||
|
||
**功能描述**:创建新的抄表记录。
|
||
|
||
**接口详情**:
|
||
- **请求方式**:POST
|
||
- **请求路径**:`/admin-api/water/reading/create`
|
||
|
||
**请求参数**:
|
||
```json
|
||
{
|
||
"meterId": 1,
|
||
"readingDate": "2024-12-19",
|
||
"readingValue": 156.32,
|
||
"readingType": "MANUAL",
|
||
"readerId": "R001",
|
||
"photoUrl": "https://example.com/photos/reading001.jpg",
|
||
"remark": "正常抄表"
|
||
}
|
||
```
|
||
|
||
**响应参数**:
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"msg": "操作成功",
|
||
"data": 1
|
||
}
|
||
```
|
||
|
||
**Service层实现示例**:
|
||
```java
|
||
@Service
|
||
@Validated
|
||
public class MeterReadingServiceImpl implements MeterReadingService {
|
||
|
||
@Resource
|
||
private MeterReadingMapper readingMapper;
|
||
@Resource
|
||
private MeterService meterService;
|
||
|
||
@Override
|
||
@Transactional(rollbackFor = Exception.class)
|
||
public Long createReading(MeterReadingSaveReqVO createReqVO) {
|
||
// 校验水表存在性
|
||
MeterDO meter = meterService.validateMeterExists(createReqVO.getMeterId());
|
||
|
||
// 校验读数合理性
|
||
validateReadingValue(createReqVO.getMeterId(), createReqVO.getReadingValue());
|
||
|
||
// 创建抄表记录
|
||
MeterReadingDO reading = BeanUtils.toBean(createReqVO, MeterReadingDO.class);
|
||
reading.setReadingCode(generateReadingCode());
|
||
reading.setCustomerId(meter.getCustomerId());
|
||
|
||
// 计算用水量
|
||
BigDecimal waterUsage = calculateWaterUsage(meter.getCurrentReading(),
|
||
createReqVO.getReadingValue());
|
||
reading.setWaterUsage(waterUsage);
|
||
|
||
readingMapper.insert(reading);
|
||
|
||
// 更新水表当前读数
|
||
meterService.updateCurrentReading(createReqVO.getMeterId(),
|
||
createReqVO.getReadingValue());
|
||
|
||
return reading.getId();
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 3.2.3 抄表数据批量导入接口
|
||
|
||
**功能描述**:批量导入抄表数据,支持Excel文件上传。
|
||
|
||
**接口详情**:
|
||
- **请求方式**:POST
|
||
- **请求路径**:`/admin-api/water/reading/import`
|
||
- **Content-Type**:`multipart/form-data`
|
||
|
||
**请求参数**:
|
||
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|
||
|-------|------|------|------|------|
|
||
| file | MultipartFile | 是 | Excel文件 | reading_data.xlsx |
|
||
| updateSupport | Boolean | 否 | 是否更新已有数据 | false |
|
||
|
||
**响应参数**:
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"msg": "操作成功",
|
||
"data": {
|
||
"successCount": 95,
|
||
"failureCount": 5,
|
||
"failureList": [
|
||
{
|
||
"lineNumber": 3,
|
||
"meterCode": "M003",
|
||
"errorMsg": "水表不存在"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3.3 账单管理API接口
|
||
|
||
#### 3.3.1 账单查询接口
|
||
|
||
**功能描述**:根据客户ID和查询条件查询账单信息。
|
||
|
||
**接口详情**:
|
||
- **请求方式**:GET
|
||
- **请求路径**:`/admin-api/water/bill/page`
|
||
|
||
**请求参数**:
|
||
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|
||
|-------|------|------|------|------|
|
||
| pageNo | Integer | 否 | 页码,默认1 | 1 |
|
||
| pageSize | Integer | 否 | 每页条数,默认10 | 10 |
|
||
| customerId | Long | 否 | 客户ID | 1 |
|
||
| billMonth | String | 否 | 账期 | 2024-12 |
|
||
| billStatus | Integer | 否 | 账单状态 | 0 |
|
||
|
||
**响应参数**:
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"msg": "操作成功",
|
||
"data": {
|
||
"list": [
|
||
{
|
||
"id": 1,
|
||
"billCode": "B202412190001",
|
||
"billMonth": "2024-12",
|
||
"billDate": "2024-12-19",
|
||
"waterUsage": 25.50,
|
||
"waterFee": 76.50,
|
||
"sewageFee": 15.30,
|
||
"totalAmount": 91.80,
|
||
"paidAmount": 0.00,
|
||
"balanceAmount": 91.80,
|
||
"dueDate": "2025-01-19",
|
||
"billStatus": 0,
|
||
"customerName": "张三",
|
||
"meterCode": "M001"
|
||
}
|
||
],
|
||
"total": 1
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 3.3.2 账单生成接口
|
||
|
||
**功能描述**:根据抄表记录生成水费账单。
|
||
|
||
**接口详情**:
|
||
- **请求方式**:POST
|
||
- **请求路径**:`/admin-api/water/bill/generate`
|
||
|
||
**请求参数**:
|
||
```json
|
||
{
|
||
"billMonth": "2024-12",
|
||
"customerIds": [1, 2, 3],
|
||
"readingIds": [1, 2, 3],
|
||
"dueDate": "2025-01-19"
|
||
}
|
||
```
|
||
|
||
**响应参数**:
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"msg": "操作成功",
|
||
"data": {
|
||
"generateCount": 3,
|
||
"successList": [
|
||
{
|
||
"customerId": 1,
|
||
"billId": 1,
|
||
"totalAmount": 91.80
|
||
}
|
||
],
|
||
"failureList": []
|
||
}
|
||
}
|
||
```
|
||
|
||
**Service层代码示例**:
|
||
```java
|
||
@Service
|
||
@Validated
|
||
public class BillServiceImpl implements BillService {
|
||
|
||
@Resource
|
||
private BillMapper billMapper;
|
||
@Resource
|
||
private MeterReadingService readingService;
|
||
@Resource
|
||
private WaterPriceService priceService;
|
||
|
||
@Override
|
||
@Transactional(rollbackFor = Exception.class)
|
||
public BillGenerateRespVO generateBills(BillGenerateReqVO generateReqVO) {
|
||
BillGenerateRespVO result = new BillGenerateRespVO();
|
||
List<BillGenerateDetailVO> successList = new ArrayList<>();
|
||
List<BillGenerateDetailVO> failureList = new ArrayList<>();
|
||
|
||
for (Long readingId : generateReqVO.getReadingIds()) {
|
||
try {
|
||
// 获取抄表记录
|
||
MeterReadingDO reading = readingService.getReading(readingId);
|
||
|
||
// 计算水费
|
||
WaterFeeCalculateDTO feeResult = priceService.calculateWaterFee(
|
||
reading.getCustomerId(), reading.getWaterUsage());
|
||
|
||
// 创建账单
|
||
BillDO bill = new BillDO();
|
||
bill.setBillCode(generateBillCode());
|
||
bill.setBillMonth(generateReqVO.getBillMonth());
|
||
bill.setCustomerId(reading.getCustomerId());
|
||
bill.setMeterId(reading.getMeterId());
|
||
bill.setReadingId(readingId);
|
||
bill.setWaterUsage(reading.getWaterUsage());
|
||
bill.setWaterFee(feeResult.getWaterFee());
|
||
bill.setSewageFee(feeResult.getSewageFee());
|
||
bill.setTotalAmount(feeResult.getTotalAmount());
|
||
bill.setDueDate(generateReqVO.getDueDate());
|
||
|
||
billMapper.insert(bill);
|
||
|
||
successList.add(buildSuccessDetail(reading.getCustomerId(),
|
||
bill.getId(), feeResult.getTotalAmount()));
|
||
|
||
} catch (Exception e) {
|
||
failureList.add(buildFailureDetail(readingId, e.getMessage()));
|
||
}
|
||
}
|
||
|
||
result.setGenerateCount(successList.size());
|
||
result.setSuccessList(successList);
|
||
result.setFailureList(failureList);
|
||
return result;
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3.4 缴费管理API接口
|
||
|
||
#### 3.4.1 缴费处理接口
|
||
|
||
**功能描述**:处理客户缴费操作。
|
||
|
||
**接口详情**:
|
||
- **请求方式**:POST
|
||
- **请求路径**:`/admin-api/water/payment/create`
|
||
|
||
**请求参数**:
|
||
```json
|
||
{
|
||
"customerId": 1,
|
||
"billIds": [1, 2],
|
||
"paymentType": "NORMAL",
|
||
"paymentChannel": "CASH",
|
||
"paymentAmount": 183.60,
|
||
"actualAmount": 200.00,
|
||
"operatorId": "OP001",
|
||
"outletCode": "OUT001",
|
||
"remark": "现金缴费"
|
||
}
|
||
```
|
||
|
||
**响应参数**:
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"msg": "操作成功",
|
||
"data": {
|
||
"paymentId": 1,
|
||
"paymentCode": "P202412190001",
|
||
"changeAmount": 16.40,
|
||
"invoiceNo": "INV20241219001"
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 3.4.2 在线支付接口
|
||
|
||
**功能描述**:处理在线支付(微信、支付宝等)。
|
||
|
||
**接口详情**:
|
||
- **请求方式**:POST
|
||
- **请求路径**:`/admin-api/water/payment/online-pay`
|
||
|
||
**请求参数**:
|
||
```json
|
||
{
|
||
"customerId": 1,
|
||
"billIds": [1],
|
||
"paymentChannel": "WECHAT",
|
||
"paymentAmount": 91.80,
|
||
"returnUrl": "https://water.example.com/payment/callback",
|
||
"notifyUrl": "https://water.example.com/api/payment/notify"
|
||
}
|
||
```
|
||
|
||
**响应参数**:
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"msg": "操作成功",
|
||
"data": {
|
||
"paymentCode": "P202412190002",
|
||
"prepayId": "wx20241219001234567890",
|
||
"payUrl": "weixin://wxpay/bizpayurl?pr=abc123",
|
||
"qrCode": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..."
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3.4 工单接口
|
||
|
||
#### 3.4.1 工单创建接口
|
||
|
||
**功能描述**:创建业务工单。
|
||
|
||
**接口规范**:
|
||
- 请求方式:POST
|
||
- 请求路径:/api/workorders
|
||
- 请求/返回格式:JSON
|
||
|
||
#### 3.4.2 工单状态更新接口
|
||
|
||
**功能描述**:更新工单处理状态。
|
||
|
||
**接口规范**:
|
||
- 请求方式:PUT
|
||
- 请求路径:/api/workorders/{workorderId}/status
|
||
- 请求/返回格式:JSON
|
||
|
||
## 4. 接口标准
|
||
|
||
### 4.1 接口协议
|
||
|
||
系统接口主要采用以下协议:
|
||
|
||
- **RESTful API**:适用于系统内部模块间的交互以及移动应用等轻量级客户端
|
||
- **WebService**:适用于与外部系统的集成,特别是银行等传统机构
|
||
- **消息队列**:适用于异步处理的场景,如批量数据处理、通知推送等
|
||
|
||
### 4.2 数据格式
|
||
|
||
接口数据主要采用以下格式:
|
||
|
||
- **JSON**:主要用于RESTful API接口,结构简单清晰,适合Web应用
|
||
- **XML**:主要用于WebService接口,兼容性好,适合与传统系统对接
|
||
- **文本文件**:主要用于批量数据交换,如银行代扣文件等
|
||
|
||
### 4.3 接口安全设计
|
||
|
||
接口安全采用多层防护机制:
|
||
|
||
#### 4.3.1 认证机制
|
||
|
||
**JWT令牌认证**:
|
||
```java
|
||
@RestController
|
||
public class AuthController {
|
||
|
||
@Resource
|
||
private AuthService authService;
|
||
|
||
@PostMapping("/admin-api/system/auth/login")
|
||
public CommonResult<AuthLoginRespVO> login(@Valid @RequestBody AuthLoginReqVO reqVO) {
|
||
// 验证用户名密码
|
||
AdminUserDO user = authService.authenticate(reqVO.getUsername(), reqVO.getPassword());
|
||
|
||
// 生成JWT Token
|
||
String token = authService.createToken(user.getId(), user.getTenantId());
|
||
|
||
return success(AuthLoginRespVO.builder()
|
||
.userId(user.getId())
|
||
.accessToken(token)
|
||
.refreshToken(authService.createRefreshToken(user.getId()))
|
||
.expiresTime(LocalDateTime.now().plusHours(2))
|
||
.build());
|
||
}
|
||
}
|
||
```
|
||
|
||
**API Key认证**(外部系统):
|
||
```java
|
||
@Component
|
||
public class ApiKeyAuthenticationFilter extends OncePerRequestFilter {
|
||
|
||
@Override
|
||
protected void doFilterInternal(HttpServletRequest request,
|
||
HttpServletResponse response,
|
||
FilterChain filterChain) throws ServletException, IOException {
|
||
String apiKey = request.getHeader("X-API-KEY");
|
||
String timestamp = request.getHeader("X-TIMESTAMP");
|
||
String signature = request.getHeader("X-SIGNATURE");
|
||
|
||
// 验证API Key
|
||
if (!apiKeyService.validateApiKey(apiKey)) {
|
||
writeErrorResponse(response, "Invalid API Key");
|
||
return;
|
||
}
|
||
|
||
// 验证时间戳(防重放攻击)
|
||
if (!validateTimestamp(timestamp)) {
|
||
writeErrorResponse(response, "Request expired");
|
||
return;
|
||
}
|
||
|
||
// 验证签名
|
||
if (!validateSignature(request, signature)) {
|
||
writeErrorResponse(response, "Invalid signature");
|
||
return;
|
||
}
|
||
|
||
filterChain.doFilter(request, response);
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 4.3.2 数据加密
|
||
|
||
**敏感数据加密**:
|
||
```java
|
||
@Component
|
||
public class DataEncryptionService {
|
||
|
||
private final AESUtil aesUtil;
|
||
|
||
public String encryptPersonalInfo(String plainText) {
|
||
if (StrUtil.isBlank(plainText)) {
|
||
return plainText;
|
||
}
|
||
return aesUtil.encrypt(plainText);
|
||
}
|
||
|
||
public String decryptPersonalInfo(String cipherText) {
|
||
if (StrUtil.isBlank(cipherText)) {
|
||
return cipherText;
|
||
}
|
||
return aesUtil.decrypt(cipherText);
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 4.3.3 访问控制
|
||
|
||
**IP白名单控制**:
|
||
```java
|
||
@Component
|
||
public class IpWhitelistFilter extends OncePerRequestFilter {
|
||
|
||
@Value("${water.security.ip-whitelist}")
|
||
private List<String> ipWhitelist;
|
||
|
||
@Override
|
||
protected void doFilterInternal(HttpServletRequest request,
|
||
HttpServletResponse response,
|
||
FilterChain filterChain) throws ServletException, IOException {
|
||
String clientIp = getClientIpAddress(request);
|
||
|
||
if (!isIpAllowed(clientIp)) {
|
||
response.setStatus(HttpStatus.FORBIDDEN.value());
|
||
response.getWriter().write("{\"code\":403,\"msg\":\"IP access denied\"}");
|
||
return;
|
||
}
|
||
|
||
filterChain.doFilter(request, response);
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 4.3.4 接口限流
|
||
|
||
**基于Redis的令牌桶限流**:
|
||
```java
|
||
@Component
|
||
public class RateLimitService {
|
||
|
||
@Resource
|
||
private StringRedisTemplate redisTemplate;
|
||
|
||
public boolean allowRequest(String key, int maxRequests, Duration window) {
|
||
String redisKey = "rate_limit:" + key;
|
||
String script = """
|
||
local key = KEYS[1]
|
||
local window = tonumber(ARGV[1])
|
||
local limit = tonumber(ARGV[2])
|
||
local current = redis.call('get', key)
|
||
if current == false then
|
||
redis.call('setex', key, window, 1)
|
||
return 1
|
||
end
|
||
if tonumber(current) < limit then
|
||
return redis.call('incr', key)
|
||
else
|
||
return 0
|
||
end
|
||
""";
|
||
|
||
DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>(script, Long.class);
|
||
Long result = redisTemplate.execute(redisScript,
|
||
Collections.singletonList(redisKey),
|
||
String.valueOf(window.getSeconds()),
|
||
String.valueOf(maxRequests));
|
||
|
||
return result != null && result > 0;
|
||
}
|
||
}
|
||
```
|
||
|
||
### 4.4 错误处理机制
|
||
|
||
#### 4.4.1 统一异常处理
|
||
|
||
```java
|
||
@RestControllerAdvice
|
||
public class GlobalExceptionHandler {
|
||
|
||
@ExceptionHandler(ServiceException.class)
|
||
public CommonResult<?> serviceExceptionHandler(ServiceException ex) {
|
||
log.info("[serviceExceptionHandler]", ex);
|
||
return CommonResult.error(ex.getCode(), ex.getMessage());
|
||
}
|
||
|
||
@ExceptionHandler(ConstraintViolationException.class)
|
||
public CommonResult<?> constraintViolationExceptionHandler(ConstraintViolationException ex) {
|
||
log.info("[constraintViolationExceptionHandler]", ex);
|
||
return CommonResult.error(BAD_REQUEST.getCode(), "请求参数不正确:" + ex.getMessage());
|
||
}
|
||
|
||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||
public CommonResult<?> methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException ex) {
|
||
log.info("[methodArgumentNotValidExceptionHandler]", ex);
|
||
FieldError fieldError = ex.getBindingResult().getFieldError();
|
||
assert fieldError != null;
|
||
return CommonResult.error(BAD_REQUEST.getCode(), "请求参数不正确:" + fieldError.getDefaultMessage());
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 4.4.2 错误码定义
|
||
|
||
```java
|
||
public interface ErrorCodeConstants {
|
||
|
||
// ========== 通用错误码 1-000-000-000 ==========
|
||
ErrorCode SUCCESS = new ErrorCode(0, "成功");
|
||
ErrorCode BAD_REQUEST = new ErrorCode(400, "请求参数不正确");
|
||
ErrorCode UNAUTHORIZED = new ErrorCode(401, "账号未登录");
|
||
ErrorCode FORBIDDEN = new ErrorCode(403, "没有该操作权限");
|
||
ErrorCode NOT_FOUND = new ErrorCode(404, "请求未找到");
|
||
ErrorCode METHOD_NOT_ALLOWED = new ErrorCode(405, "请求方法不正确");
|
||
ErrorCode INTERNAL_SERVER_ERROR = new ErrorCode(500, "系统异常");
|
||
|
||
// ========== 客户管理错误码 1-001-000-000 ==========
|
||
ErrorCode CUSTOMER_NOT_EXISTS = new ErrorCode(1_001_000_001, "客户不存在");
|
||
ErrorCode CUSTOMER_CODE_DUPLICATE = new ErrorCode(1_001_000_002, "客户编号已存在");
|
||
ErrorCode CUSTOMER_STATUS_INVALID = new ErrorCode(1_001_000_003, "客户状态不正确");
|
||
|
||
// ========== 水表管理错误码 1-002-000-000 ==========
|
||
ErrorCode METER_NOT_EXISTS = new ErrorCode(1_002_000_001, "水表不存在");
|
||
ErrorCode METER_CODE_DUPLICATE = new ErrorCode(1_002_000_002, "水表编号已存在");
|
||
ErrorCode METER_READING_INVALID = new ErrorCode(1_002_000_003, "水表读数不正确");
|
||
|
||
// ========== 账单管理错误码 1-003-000-000 ==========
|
||
ErrorCode BILL_NOT_EXISTS = new ErrorCode(1_003_000_001, "账单不存在");
|
||
ErrorCode BILL_ALREADY_PAID = new ErrorCode(1_003_000_002, "账单已缴费");
|
||
ErrorCode BILL_AMOUNT_INVALID = new ErrorCode(1_003_000_003, "账单金额不正确");
|
||
|
||
// ========== 缴费管理错误码 1-004-000-000 ==========
|
||
ErrorCode PAYMENT_FAILED = new ErrorCode(1_004_000_001, "缴费失败");
|
||
ErrorCode PAYMENT_AMOUNT_INSUFFICIENT = new ErrorCode(1_004_000_002, "缴费金额不足");
|
||
ErrorCode PAYMENT_CHANNEL_UNAVAILABLE = new ErrorCode(1_004_000_003, "缴费渠道不可用");
|
||
}
|
||
```
|
||
|
||
#### 4.4.3 接口调用示例
|
||
|
||
**成功响应示例**:
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"msg": "操作成功",
|
||
"data": {
|
||
"id": 1,
|
||
"customerName": "张三"
|
||
}
|
||
}
|
||
```
|
||
|
||
**失败响应示例**:
|
||
```json
|
||
{
|
||
"code": 1001000001,
|
||
"msg": "客户不存在",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
### 4.5 前端接口调用示例
|
||
|
||
#### 4.5.1 Vue3 + TypeScript接口封装
|
||
|
||
```typescript
|
||
// api/water/customer.ts
|
||
import { request } from '@/utils/request'
|
||
|
||
export interface CustomerVO {
|
||
id: number
|
||
customerCode: string
|
||
customerName: string
|
||
customerType: string
|
||
phone: string
|
||
address: string
|
||
status: number
|
||
createTime: string
|
||
}
|
||
|
||
export interface CustomerPageReqVO extends PageParam {
|
||
customerName?: string
|
||
customerCode?: string
|
||
customerType?: string
|
||
phone?: string
|
||
}
|
||
|
||
export const CustomerApi = {
|
||
// 获取客户分页
|
||
getCustomerPage: (params: CustomerPageReqVO) => {
|
||
return request.get<PageResult<CustomerVO>>({ url: '/water/customer/page', params })
|
||
},
|
||
|
||
// 获取客户详情
|
||
getCustomer: (id: number) => {
|
||
return request.get<CustomerVO>({ url: `/water/customer/${id}` })
|
||
},
|
||
|
||
// 创建客户
|
||
createCustomer: (data: CustomerSaveReqVO) => {
|
||
return request.post<number>({ url: '/water/customer/create', data })
|
||
},
|
||
|
||
// 更新客户
|
||
updateCustomer: (data: CustomerSaveReqVO) => {
|
||
return request.put<void>({ url: '/water/customer/update', data })
|
||
},
|
||
|
||
// 删除客户
|
||
deleteCustomer: (id: number) => {
|
||
return request.delete<void>({ url: `/water/customer/delete?id=${id}` })
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 4.5.2 Vue组件使用示例
|
||
|
||
```vue
|
||
<script setup lang="ts">
|
||
import { ref, onMounted } from 'vue'
|
||
import { CustomerApi, CustomerVO } from '@/api/water/customer'
|
||
import { formatDate } from '@/utils/formatTime'
|
||
|
||
const customerList = ref<CustomerVO[]>([])
|
||
const loading = ref(true)
|
||
const total = ref(0)
|
||
const queryParams = ref({
|
||
pageNo: 1,
|
||
pageSize: 10,
|
||
customerName: '',
|
||
customerCode: ''
|
||
})
|
||
|
||
const getCustomerList = async () => {
|
||
loading.value = true
|
||
try {
|
||
const data = await CustomerApi.getCustomerPage(queryParams.value)
|
||
customerList.value = data.list
|
||
total.value = data.total
|
||
} catch (error) {
|
||
console.error('获取客户列表失败:', error)
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
const handleQuery = () => {
|
||
queryParams.value.pageNo = 1
|
||
getCustomerList()
|
||
}
|
||
|
||
const handleReset = () => {
|
||
queryParams.value = {
|
||
pageNo: 1,
|
||
pageSize: 10,
|
||
customerName: '',
|
||
customerCode: ''
|
||
}
|
||
getCustomerList()
|
||
}
|
||
|
||
onMounted(() => {
|
||
getCustomerList()
|
||
})
|
||
</script>
|
||
|
||
<template>
|
||
<div class="app-container">
|
||
<!-- 查询表单 -->
|
||
<el-form :model="queryParams" ref="queryFormRef" inline>
|
||
<el-form-item label="客户名称" prop="customerName">
|
||
<el-input v-model="queryParams.customerName" placeholder="请输入客户名称" />
|
||
</el-form-item>
|
||
<el-form-item label="客户编号" prop="customerCode">
|
||
<el-input v-model="queryParams.customerCode" placeholder="请输入客户编号" />
|
||
</el-form-item>
|
||
<el-form-item>
|
||
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
||
<el-button @click="handleReset">重置</el-button>
|
||
</el-form-item>
|
||
</el-form>
|
||
|
||
<!-- 数据表格 -->
|
||
<el-table v-loading="loading" :data="customerList">
|
||
<el-table-column label="客户编号" prop="customerCode" />
|
||
<el-table-column label="客户名称" prop="customerName" />
|
||
<el-table-column label="联系电话" prop="phone" />
|
||
<el-table-column label="创建时间" prop="createTime" :formatter="formatDate" />
|
||
</el-table>
|
||
|
||
<!-- 分页组件 -->
|
||
<Pagination
|
||
:total="total"
|
||
v-model:page="queryParams.pageNo"
|
||
v-model:limit="queryParams.pageSize"
|
||
@pagination="getCustomerList"
|
||
/>
|
||
</div>
|
||
</template>
|
||
```
|
||
---
|
||
|
||
# 福建水务营收系统部署设计文档
|
||
|
||
## 文档信息
|
||
| 项目信息 | 详情 |
|
||
|---------|------|
|
||
| **项目名称** | 福建水务营收系统 |
|
||
| **文档类型** | 概要设计文档 |
|
||
| **技术框架** | RuoYi-Vue-Pro + yudao-ui-admin-vue3 |
|
||
| **文档版本** | v1.0 |
|
||
| **编写日期** | 2024-12-19 |
|
||
| **文档状态** | ✅ 已完成 |
|
||
|
||
## 目录
|
||
- [1. 部署概述](#1-部署概述)
|
||
- [2. 部署架构](#2-部署架构)
|
||
- [3. 服务器配置](#3-服务器配置)
|
||
- [4. 网络架构](#4-网络架构)
|
||
- [5. 安全设计](#5-安全设计)
|
||
- [6. 部署流程](#6-部署流程)
|
||
- [7. 监控与运维](#7-监控与运维)
|
||
|
||
## 1. 部署概述
|
||
|
||
福建水务业务系统采用集中化部署模式,基于集团私有云环境进行部署,构建高可用、可扩展的系统架构,满足集团及下属各水务公司的业务需求。
|
||
|
||
### 1.1 部署目标
|
||
|
||
- 实现系统的集中部署和统一管理
|
||
- 确保系统高可用性和可靠性
|
||
- 支持业务动态扩展和弹性伸缩
|
||
- 保障数据安全和业务连续性
|
||
- 降低运维成本,提高管理效率
|
||
|
||
### 1.2 部署原则
|
||
|
||
- **集中部署**:核心业务系统集中部署在集团数据中心,统一管理和维护
|
||
- **多级架构**:采用多级架构设计,实现前端负载分担和后端高可用
|
||
- **灾备设计**:重要系统和数据实现灾备,确保业务连续性
|
||
- **安全防护**:多层次安全防护体系,确保系统和数据安全
|
||
- **弹性扩展**:支持系统横向和纵向扩展,适应业务增长需求
|
||
|
||
## 2. 部署架构
|
||
|
||
### 2.1 总体部署架构
|
||
|
||
福建水务业务系统采用三层架构部署:
|
||
|
||
- **接入层**:负责外部访问请求的接入和负载均衡
|
||
- **应用层**:部署业务应用服务,处理业务逻辑
|
||
- **数据层**:部署数据库服务,存储业务数据
|
||
|
||
系统部署采用集群模式,各层均部署多个节点,实现高可用和负载均衡。
|
||
|
||
### 2.2 生产环境部署架构
|
||
|
||
生产环境采用双机房部署方案,包括主生产环境和灾备环境:
|
||
|
||
#### 2.2.1 主生产环境
|
||
|
||
主生产环境部署在集团主数据中心,包括:
|
||
|
||
- 负载均衡集群:2台负载均衡服务器
|
||
- Web服务器集群:4台Web服务器
|
||
- 应用服务器集群:6台应用服务器
|
||
- 数据库服务器集群:2台主备数据库服务器
|
||
- 文件服务器:2台主备文件服务器
|
||
- 缓存服务器集群:2台缓存服务器
|
||
|
||
#### 2.2.2 灾备环境
|
||
|
||
灾备环境部署在集团备用数据中心,包括:
|
||
|
||
- 负载均衡服务器:1台
|
||
- Web服务器:2台
|
||
- 应用服务器:3台
|
||
- 数据库服务器:1台
|
||
- 文件服务器:1台
|
||
- 缓存服务器:1台
|
||
|
||
### 2.3 测试环境部署架构
|
||
|
||
测试环境部署在集团测试中心,用于系统测试和验证,包括:
|
||
|
||
- Web服务器:1台
|
||
- 应用服务器:2台
|
||
- 数据库服务器:1台
|
||
- 文件服务器:1台
|
||
|
||
### 2.4 开发环境部署架构
|
||
|
||
开发环境部署在开发中心,用于系统开发和集成测试,包括:
|
||
|
||
- 应用服务器:1台
|
||
- 数据库服务器:1台
|
||
|
||
## 3. 服务器配置
|
||
|
||
### 3.1 硬件配置要求
|
||
|
||
#### 3.1.1 负载均衡服务器
|
||
|
||
- CPU:8核
|
||
- 内存:16GB
|
||
- 存储:100GB SSD
|
||
- 网卡:双千兆网卡
|
||
|
||
#### 3.1.2 Web服务器
|
||
|
||
- CPU:8核
|
||
- 内存:16GB
|
||
- 存储:200GB SSD
|
||
- 网卡:双千兆网卡
|
||
|
||
#### 3.1.3 应用服务器
|
||
|
||
- CPU:16核
|
||
- 内存:32GB
|
||
- 存储:300GB SSD
|
||
- 网卡:双千兆网卡
|
||
|
||
#### 3.1.4 数据库服务器
|
||
|
||
- CPU:24核
|
||
- 内存:64GB
|
||
- 存储:2TB SSD (RAID 10)
|
||
- 网卡:双万兆网卡
|
||
|
||
#### 3.1.5 文件服务器
|
||
|
||
- CPU:8核
|
||
- 内存:16GB
|
||
- 存储:4TB (RAID 5)
|
||
- 网卡:双千兆网卡
|
||
|
||
#### 3.1.6 缓存服务器
|
||
|
||
- CPU:8核
|
||
- 内存:32GB
|
||
- 存储:100GB SSD
|
||
- 网卡:双千兆网卡
|
||
|
||
### 3.2 软件配置要求
|
||
|
||
#### 3.2.1 操作系统
|
||
|
||
- 服务端:CentOS 7+、Ubuntu 18.04+或其他国产Linux发行版
|
||
- 客户端:支持Windows、macOS、Linux等现代操作系统
|
||
|
||
#### 3.2.2 数据库
|
||
|
||
- OpenGauss 5.0+(推荐,国产自主可控)
|
||
- 兼容:PostgreSQL 13+、MySQL 8.0+
|
||
|
||
#### 3.2.3 应用服务器
|
||
|
||
- JDK 17或JDK 21(兼容支持JDK 8)
|
||
- Apache Tomcat 9.0+或内嵌Tomcat
|
||
- Nginx 1.18+(作为前端静态资源服务器和反向代理)
|
||
|
||
#### 3.2.4 缓存服务器
|
||
|
||
- Redis 5.0+或Redis集群
|
||
|
||
#### 3.2.5 中间件
|
||
|
||
- 消息队列:基于Redis的轻量级队列(可选)
|
||
- 分布式任务调度:Quartz集群
|
||
- 工作流引擎:Flowable 6.x
|
||
- 文件存储:支持本地存储、MinIO、阿里云OSS等
|
||
|
||
#### 3.2.6 前端环境
|
||
|
||
- Node.js 16+
|
||
- NPM 8+或Yarn 1.22+
|
||
- Vue 3.x
|
||
- Element Plus
|
||
|
||
## 4. 网络架构
|
||
|
||
### 4.1 网络拓扑
|
||
|
||
福建水务业务系统网络架构采用三层网络结构:
|
||
|
||
- **接入层**:对外提供服务接入,部署防火墙、负载均衡等设备
|
||
- **核心层**:实现业务系统间的互联互通,部署核心交换机
|
||
- **服务层**:部署各类服务器,实现业务处理和数据存储
|
||
|
||
### 4.2 网络安全区域划分
|
||
|
||
网络安全区域划分为以下几个区域:
|
||
|
||
- **DMZ区**:部署面向外部的Web服务器,与内网隔离
|
||
- **应用区**:部署业务应用服务器
|
||
- **数据区**:部署数据库服务器和文件服务器
|
||
- **管理区**:部署运维管理服务器
|
||
|
||
### 4.3 网络带宽配置
|
||
|
||
- 外网接入带宽:100Mbps,根据实际需求可升级
|
||
- 内网骨干带宽:1000Mbps
|
||
- 服务器接入带宽:1000Mbps
|
||
- 数据中心间专线带宽:100Mbps
|
||
|
||
## 5. 安全设计
|
||
|
||
### 5.1 网络安全
|
||
|
||
#### 5.1.1 边界安全
|
||
|
||
- 部署高性能防火墙,实现网络隔离
|
||
- 部署入侵检测系统(IDS)和入侵防御系统(IPS)
|
||
- 部署Web应用防火墙(WAF),防御Web应用攻击
|
||
- 采用VPN技术,保障远程访问安全
|
||
|
||
#### 5.1.2 内网安全
|
||
|
||
- 网络安全区域划分,实现不同级别网络隔离
|
||
- 内网访问控制,限制不必要的网络访问
|
||
- 内网流量监控,及时发现异常流量
|
||
|
||
### 5.2 系统安全
|
||
|
||
#### 5.2.1 主机安全
|
||
|
||
- 操作系统安全加固,关闭不必要的服务和端口
|
||
- 系统补丁及时更新,修复安全漏洞
|
||
- 部署主机防病毒软件,防御恶意代码
|
||
- 主机审计和日志管理,记录重要操作
|
||
|
||
#### 5.2.2 应用安全
|
||
|
||
- 应用访问控制,基于角色的权限管理
|
||
- 应用操作审计,记录重要业务操作
|
||
- 数据传输加密,保护敏感信息
|
||
- 输入验证,防止SQL注入、XSS等攻击
|
||
|
||
### 5.3 数据安全
|
||
|
||
#### 5.3.1 数据存储安全
|
||
|
||
- 数据库访问控制,限制数据库访问权限
|
||
- 敏感数据加密存储,防止数据泄露
|
||
- 数据库审计,记录重要数据操作
|
||
|
||
#### 5.3.2 数据备份与恢复
|
||
|
||
- 定期数据备份,每日增量备份,每周全量备份
|
||
- 备份数据异地存储,防止灾难性事件导致数据丢失
|
||
- 定期演练数据恢复,确保备份数据可用
|
||
|
||
## 6. 部署流程
|
||
|
||
### 6.1 部署准备
|
||
|
||
- 服务器硬件准备和上架
|
||
- 网络环境配置和测试
|
||
- 操作系统安装和配置
|
||
- 基础软件安装和配置
|
||
|
||
### 6.2 应用部署
|
||
|
||
#### 6.2.1 数据库部署
|
||
|
||
- 数据库服务器配置
|
||
- 数据库实例创建和配置
|
||
- 数据库高可用配置
|
||
- 数据备份策略配置
|
||
|
||
#### 6.2.2 应用服务部署
|
||
|
||
- 应用服务器配置
|
||
- 应用程序部署
|
||
- 应用服务参数配置
|
||
- 应用服务高可用配置
|
||
|
||
#### 6.2.3 Web服务部署
|
||
|
||
- Web服务器配置
|
||
- Web应用部署
|
||
- Web服务参数配置
|
||
- 负载均衡配置
|
||
|
||
### 6.3 系统联调
|
||
|
||
- 各组件功能测试
|
||
- 系统整体联调测试
|
||
- 性能和压力测试
|
||
- 高可用性测试
|
||
|
||
### 6.4 系统上线
|
||
|
||
- 制定上线计划
|
||
- 系统割接准备
|
||
- 系统割接实施
|
||
- 系统运行监控
|
||
|
||
## 7. 监控与运维
|
||
|
||
### 7.1 监控系统
|
||
|
||
#### 7.1.1 基础设施监控
|
||
|
||
- 服务器硬件监控:CPU、内存、磁盘、网络等
|
||
- 网络设备监控:带宽使用率、连接状态等
|
||
- 操作系统监控:系统负载、进程状态等
|
||
|
||
#### 7.1.2 应用监控
|
||
|
||
- 应用服务状态监控
|
||
- 应用性能监控:响应时间、并发数等
|
||
- 业务监控:重要业务指标监控
|
||
|
||
#### 7.1.3 数据库监控
|
||
|
||
- 数据库服务状态监控
|
||
- 数据库性能监控:CPU使用率、内存使用率、IO性能等
|
||
- SQL执行监控:慢查询、锁等待等
|
||
|
||
### 7.2 运维管理
|
||
|
||
#### 7.2.1 日常运维
|
||
|
||
- 系统日常巡检
|
||
- 系统性能优化
|
||
- 系统容量管理
|
||
- 系统备份管理
|
||
|
||
#### 7.2.2 变更管理
|
||
|
||
- 变更申请和审批
|
||
- 变更实施和验证
|
||
- 变更回退预案
|
||
- 变更记录管理
|
||
|
||
#### 7.2.3 故障管理
|
||
|
||
- 故障监控和告警
|
||
- 故障处理流程
|
||
- 故障升级机制
|
||
- 故障复盘和改进
|
||
|
||
#### 7.2.4 应急预案
|
||
|
||
- 系统宕机应急预案
|
||
- 网络故障应急预案
|
||
- 数据丢失应急预案
|
||
- 安全事件应急预案
|
||
|
||
## 8. 容器化部署方案
|
||
|
||
### 8.1 Docker Compose部署
|
||
|
||
#### 8.1.1 完整部署配置
|
||
|
||
```yaml
|
||
# docker-compose.yml
|
||
version: '3.8'
|
||
|
||
services:
|
||
# OpenGauss 数据库
|
||
water-opengauss:
|
||
image: enmotech/opengauss:5.0.0
|
||
container_name: water-opengauss
|
||
restart: always
|
||
environment:
|
||
GS_PASSWORD: "Water@2024"
|
||
GS_DB: "ruoyi_water"
|
||
GS_USERNAME: "water_user"
|
||
TZ: "Asia/Shanghai"
|
||
volumes:
|
||
- ./data/opengauss:/var/lib/opengauss
|
||
- ./sql:/docker-entrypoint-initdb.d
|
||
- ./config/opengauss:/opt/opengauss/config
|
||
ports:
|
||
- "5432:5432"
|
||
networks:
|
||
- water-network
|
||
healthcheck:
|
||
test: ["CMD-SHELL", "gs_ctl status -D /var/lib/opengauss/data"]
|
||
interval: 30s
|
||
timeout: 10s
|
||
retries: 3
|
||
|
||
# Redis 缓存
|
||
water-redis:
|
||
image: redis:7.0-alpine
|
||
container_name: water-redis
|
||
restart: always
|
||
volumes:
|
||
- ./data/redis:/data
|
||
- ./config/redis/redis.conf:/etc/redis/redis.conf
|
||
ports:
|
||
- "6379:6379"
|
||
command: redis-server /etc/redis/redis.conf
|
||
networks:
|
||
- water-network
|
||
|
||
# 后端应用
|
||
water-server:
|
||
build:
|
||
context: ./water-server
|
||
dockerfile: Dockerfile
|
||
container_name: water-server
|
||
restart: always
|
||
depends_on:
|
||
- water-opengauss
|
||
- water-redis
|
||
environment:
|
||
- SPRING_PROFILES_ACTIVE=prod
|
||
- SPRING_DATASOURCE_URL=jdbc:opengauss://water-opengauss:5432/ruoyi_water?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
|
||
- SPRING_DATASOURCE_USERNAME=water_user
|
||
- SPRING_DATASOURCE_PASSWORD=Water@2024
|
||
- SPRING_REDIS_HOST=water-redis
|
||
- SPRING_REDIS_PORT=6379
|
||
- SERVER_PORT=8080
|
||
volumes:
|
||
- ./logs:/app/logs
|
||
- ./upload:/app/upload
|
||
ports:
|
||
- "8080:8080"
|
||
networks:
|
||
- water-network
|
||
|
||
# 前端应用
|
||
water-ui:
|
||
build:
|
||
context: ./water-ui
|
||
dockerfile: Dockerfile
|
||
container_name: water-ui
|
||
restart: always
|
||
depends_on:
|
||
- water-server
|
||
volumes:
|
||
- ./config/nginx/nginx.conf:/etc/nginx/nginx.conf
|
||
- ./config/nginx/conf.d:/etc/nginx/conf.d
|
||
ports:
|
||
- "80:80"
|
||
- "443:443"
|
||
networks:
|
||
- water-network
|
||
|
||
# Nginx 反向代理
|
||
water-nginx:
|
||
image: nginx:1.24-alpine
|
||
container_name: water-nginx
|
||
restart: always
|
||
depends_on:
|
||
- water-server
|
||
- water-ui
|
||
volumes:
|
||
- ./config/nginx/nginx.conf:/etc/nginx/nginx.conf
|
||
- ./config/nginx/conf.d:/etc/nginx/conf.d
|
||
- ./ssl:/etc/nginx/ssl
|
||
- ./logs/nginx:/var/log/nginx
|
||
ports:
|
||
- "80:80"
|
||
- "443:443"
|
||
networks:
|
||
- water-network
|
||
|
||
# MinIO 文件存储
|
||
water-minio:
|
||
image: minio/minio:latest
|
||
container_name: water-minio
|
||
restart: always
|
||
environment:
|
||
MINIO_ACCESS_KEY: "admin"
|
||
MINIO_SECRET_KEY: "admin123456"
|
||
volumes:
|
||
- ./data/minio:/data
|
||
ports:
|
||
- "9000:9000"
|
||
- "9001:9001"
|
||
command: server /data --console-address ":9001"
|
||
networks:
|
||
- water-network
|
||
|
||
networks:
|
||
water-network:
|
||
driver: bridge
|
||
|
||
volumes:
|
||
opengauss-data:
|
||
redis-data:
|
||
minio-data:
|
||
```
|
||
|
||
#### 8.1.2 后端应用Dockerfile
|
||
|
||
```dockerfile
|
||
# water-server/Dockerfile
|
||
FROM openjdk:17-jdk-slim
|
||
|
||
LABEL maintainer="fujian-water-dev-team"
|
||
|
||
# 设置工作目录
|
||
WORKDIR /app
|
||
|
||
# 设置时区
|
||
ENV TZ=Asia/Shanghai
|
||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||
|
||
# 添加应用jar包
|
||
COPY target/water-server.jar app.jar
|
||
|
||
# 创建日志目录
|
||
RUN mkdir -p /app/logs
|
||
|
||
# 暴露端口
|
||
EXPOSE 8080
|
||
|
||
# 启动应用
|
||
ENTRYPOINT ["java", "-jar", "-Xmx1024m", "-Xms512m", "-Dspring.profiles.active=prod", "/app/app.jar"]
|
||
```
|
||
|
||
#### 8.1.3 前端应用Dockerfile
|
||
|
||
```dockerfile
|
||
# water-ui/Dockerfile
|
||
# 构建阶段
|
||
FROM node:18-alpine AS builder
|
||
|
||
WORKDIR /app
|
||
|
||
# 复制包管理文件
|
||
COPY package*.json ./
|
||
|
||
# 安装依赖
|
||
RUN npm ci --only=production
|
||
|
||
# 复制源代码
|
||
COPY . .
|
||
|
||
# 构建应用
|
||
RUN npm run build:prod
|
||
|
||
# 生产阶段
|
||
FROM nginx:1.24-alpine
|
||
|
||
# 复制构建产物
|
||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||
|
||
# 复制nginx配置
|
||
COPY nginx.conf /etc/nginx/nginx.conf
|
||
|
||
# 暴露端口
|
||
EXPOSE 80
|
||
|
||
# 启动nginx
|
||
CMD ["nginx", "-g", "daemon off;"]
|
||
```
|
||
|
||
### 8.2 Docker Compose高级配置
|
||
|
||
#### 8.2.1 生产环境配置优化
|
||
|
||
**Docker Compose生产环境配置文件**:
|
||
|
||
```yaml
|
||
# docker-compose.prod.yml
|
||
version: '3.8'
|
||
|
||
services:
|
||
water-opengauss:
|
||
image: enmotech/opengauss:5.0.0
|
||
container_name: water-opengauss-prod
|
||
restart: unless-stopped
|
||
environment:
|
||
GS_PASSWORD: "${DB_PASSWORD:-Water@2024!}"
|
||
GS_DB: "ruoyi_water"
|
||
GS_USERNAME: "water_user"
|
||
TZ: "Asia/Shanghai"
|
||
volumes:
|
||
- opengauss-prod-data:/var/lib/opengauss
|
||
- ./config/opengauss/prod:/opt/opengauss/config
|
||
- ./backups:/backups
|
||
ports:
|
||
- "5432:5432"
|
||
networks:
|
||
- water-prod-network
|
||
deploy:
|
||
resources:
|
||
limits:
|
||
memory: 2G
|
||
cpus: '2.0'
|
||
healthcheck:
|
||
test: ["CMD-SHELL", "gs_ctl status -D /var/lib/opengauss/data"]
|
||
interval: 30s
|
||
timeout: 10s
|
||
retries: 5
|
||
start_period: 60s
|
||
|
||
water-redis:
|
||
image: redis:7.0-alpine
|
||
container_name: water-redis-prod
|
||
restart: unless-stopped
|
||
command: redis-server /etc/redis/redis.conf --requirepass ${REDIS_PASSWORD:-water_redis_2024}
|
||
volumes:
|
||
- redis-prod-data:/data
|
||
- ./config/redis/prod.conf:/etc/redis/redis.conf
|
||
ports:
|
||
- "6379:6379"
|
||
networks:
|
||
- water-prod-network
|
||
deploy:
|
||
resources:
|
||
limits:
|
||
memory: 512M
|
||
cpus: '1.0'
|
||
|
||
water-server:
|
||
image: water-server:${VERSION:-latest}
|
||
container_name: water-server-prod
|
||
restart: unless-stopped
|
||
depends_on:
|
||
water-opengauss:
|
||
condition: service_healthy
|
||
water-redis:
|
||
condition: service_started
|
||
environment:
|
||
- SPRING_PROFILES_ACTIVE=prod
|
||
- SPRING_DATASOURCE_URL=jdbc:opengauss://water-opengauss:5432/ruoyi_water
|
||
- SPRING_DATASOURCE_USERNAME=water_user
|
||
- SPRING_DATASOURCE_PASSWORD=${DB_PASSWORD:-Water@2024!}
|
||
- SPRING_REDIS_HOST=water-redis
|
||
- SPRING_REDIS_PASSWORD=${REDIS_PASSWORD:-water_redis_2024}
|
||
- SERVER_PORT=8080
|
||
- JAVA_OPTS=-Xmx2g -Xms1g -XX:+UseG1GC
|
||
volumes:
|
||
- ./logs/prod:/app/logs
|
||
- ./upload/prod:/app/upload
|
||
- ./config/app:/app/config
|
||
networks:
|
||
- water-prod-network
|
||
deploy:
|
||
resources:
|
||
limits:
|
||
memory: 3G
|
||
cpus: '2.0'
|
||
replicas: 2
|
||
healthcheck:
|
||
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
|
||
interval: 30s
|
||
timeout: 10s
|
||
retries: 3
|
||
|
||
water-nginx:
|
||
image: nginx:1.24-alpine
|
||
container_name: water-nginx-prod
|
||
restart: unless-stopped
|
||
depends_on:
|
||
- water-server
|
||
volumes:
|
||
- ./config/nginx/prod.conf:/etc/nginx/nginx.conf
|
||
- ./config/nginx/conf.d:/etc/nginx/conf.d
|
||
- ./ssl:/etc/nginx/ssl
|
||
- ./logs/nginx:/var/log/nginx
|
||
- ./static:/usr/share/nginx/html
|
||
ports:
|
||
- "80:80"
|
||
- "443:443"
|
||
networks:
|
||
- water-prod-network
|
||
deploy:
|
||
resources:
|
||
limits:
|
||
memory: 256M
|
||
cpus: '0.5'
|
||
|
||
networks:
|
||
water-prod-network:
|
||
driver: bridge
|
||
ipam:
|
||
config:
|
||
- subnet: 172.20.0.0/16
|
||
|
||
volumes:
|
||
opengauss-prod-data:
|
||
driver: local
|
||
redis-prod-data:
|
||
driver: local
|
||
```
|
||
|
||
#### 8.2.2 环境变量配置
|
||
|
||
```bash
|
||
# .env.prod
|
||
# 数据库配置
|
||
DB_PASSWORD=Water@2024!Production
|
||
DB_HOST=water-opengauss
|
||
DB_PORT=5432
|
||
DB_NAME=ruoyi_water
|
||
|
||
# Redis配置
|
||
REDIS_PASSWORD=WaterRedis@2024!Production
|
||
REDIS_HOST=water-redis
|
||
REDIS_PORT=6379
|
||
|
||
# 应用配置
|
||
APP_VERSION=1.0.0
|
||
JAVA_OPTS=-Xmx2g -Xms1g -XX:+UseG1GC -XX:+HeapDumpOnOutOfMemoryError
|
||
|
||
# 网络配置
|
||
NGINX_PORT=80
|
||
NGINX_SSL_PORT=443
|
||
|
||
# 日志级别
|
||
LOG_LEVEL=INFO
|
||
LOG_ROOT_LEVEL=WARN
|
||
```
|
||
|
||
#### 8.2.3 监控集成
|
||
|
||
```yaml
|
||
# docker-compose.monitoring.yml
|
||
version: '3.8'
|
||
|
||
services:
|
||
prometheus:
|
||
image: prom/prometheus:latest
|
||
container_name: water-prometheus
|
||
restart: unless-stopped
|
||
volumes:
|
||
- ./config/prometheus:/etc/prometheus
|
||
- prometheus-data:/prometheus
|
||
ports:
|
||
- "9090:9090"
|
||
command:
|
||
- '--config.file=/etc/prometheus/prometheus.yml'
|
||
- '--storage.tsdb.path=/prometheus'
|
||
- '--web.console.libraries=/etc/prometheus/console_libraries'
|
||
- '--web.console.templates=/etc/prometheus/consoles'
|
||
networks:
|
||
- water-network
|
||
|
||
grafana:
|
||
image: grafana/grafana:latest
|
||
container_name: water-grafana
|
||
restart: unless-stopped
|
||
environment:
|
||
- GF_SECURITY_ADMIN_PASSWORD=admin123
|
||
volumes:
|
||
- grafana-data:/var/lib/grafana
|
||
- ./config/grafana:/etc/grafana/provisioning
|
||
ports:
|
||
- "3000:3000"
|
||
networks:
|
||
- water-network
|
||
|
||
volumes:
|
||
prometheus-data:
|
||
grafana-data:
|
||
```
|
||
|
||
### 8.3 自动化部署脚本
|
||
|
||
#### 8.3.1 Docker部署脚本
|
||
|
||
```bash
|
||
#!/bin/bash
|
||
# deploy-docker.sh
|
||
|
||
set -e
|
||
|
||
echo "=== 福建水务营收系统 Docker 部署脚本 ==="
|
||
|
||
# 检查Docker环境
|
||
if ! command -v docker &> /dev/null; then
|
||
echo "错误: Docker未安装,请先安装Docker"
|
||
exit 1
|
||
fi
|
||
|
||
if ! command -v docker-compose &> /dev/null; then
|
||
echo "错误: Docker Compose未安装,请先安装Docker Compose"
|
||
exit 1
|
||
fi
|
||
|
||
# 创建必要目录
|
||
echo "创建数据目录..."
|
||
mkdir -p data/{opengauss,redis,minio}
|
||
mkdir -p logs/{app,nginx}
|
||
mkdir -p config/{opengauss,redis,nginx/conf.d}
|
||
mkdir -p upload
|
||
mkdir -p ssl
|
||
mkdir -p backups
|
||
|
||
# 设置OpenGauss配置
|
||
echo "配置OpenGauss..."
|
||
cat > config/opengauss/postgresql.conf << EOF
|
||
# 数据库连接配置
|
||
max_connections = 1000
|
||
port = 5432
|
||
listen_addresses = '*'
|
||
|
||
# 内存配置
|
||
shared_buffers = 512MB
|
||
work_mem = 4MB
|
||
maintenance_work_mem = 128MB
|
||
|
||
# WAL配置
|
||
wal_level = replica
|
||
max_wal_size = 2GB
|
||
min_wal_size = 128MB
|
||
|
||
# 日志配置
|
||
log_destination = 'stderr'
|
||
logging_collector = on
|
||
log_directory = 'pg_log'
|
||
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
|
||
log_min_duration_statement = 3000
|
||
|
||
# 性能优化
|
||
effective_cache_size = 1GB
|
||
random_page_cost = 1.1
|
||
seq_page_cost = 1.0
|
||
EOF
|
||
|
||
cat > config/opengauss/pg_hba.conf << EOF
|
||
# TYPE DATABASE USER ADDRESS METHOD
|
||
local all all trust
|
||
host all all 127.0.0.1/32 md5
|
||
host all all ::1/128 md5
|
||
host all all 0.0.0.0/0 md5
|
||
EOF
|
||
|
||
# 设置Redis配置
|
||
echo "配置Redis..."
|
||
cat > config/redis/redis.conf << EOF
|
||
port 6379
|
||
requirepass water_redis_2024
|
||
timeout 300
|
||
tcp-keepalive 300
|
||
maxmemory 256mb
|
||
maxmemory-policy allkeys-lru
|
||
save 900 1
|
||
save 300 10
|
||
save 60 10000
|
||
EOF
|
||
|
||
# 设置Nginx配置
|
||
echo "配置Nginx..."
|
||
cat > config/nginx/nginx.conf << EOF
|
||
user nginx;
|
||
worker_processes auto;
|
||
error_log /var/log/nginx/error.log warn;
|
||
pid /var/run/nginx.pid;
|
||
|
||
events {
|
||
worker_connections 1024;
|
||
use epoll;
|
||
multi_accept on;
|
||
}
|
||
|
||
http {
|
||
include /etc/nginx/mime.types;
|
||
default_type application/octet-stream;
|
||
|
||
log_format main '\$remote_addr - \$remote_user [\$time_local] "\$request" '
|
||
'\$status \$body_bytes_sent "\$http_referer" '
|
||
'"\$http_user_agent" "\$http_x_forwarded_for"';
|
||
|
||
access_log /var/log/nginx/access.log main;
|
||
|
||
sendfile on;
|
||
tcp_nopush on;
|
||
tcp_nodelay on;
|
||
keepalive_timeout 65;
|
||
types_hash_max_size 2048;
|
||
client_max_body_size 50M;
|
||
|
||
gzip on;
|
||
gzip_vary on;
|
||
gzip_min_length 1024;
|
||
gzip_types text/plain text/css text/xml text/javascript
|
||
application/javascript application/xml+rss
|
||
application/json;
|
||
|
||
include /etc/nginx/conf.d/*.conf;
|
||
}
|
||
EOF
|
||
|
||
cat > config/nginx/conf.d/water.conf << EOF
|
||
upstream water_backend {
|
||
server water-server:8080 max_fails=3 fail_timeout=30s;
|
||
keepalive 32;
|
||
}
|
||
|
||
server {
|
||
listen 80;
|
||
server_name localhost;
|
||
|
||
location /admin-api/ {
|
||
proxy_pass http://water_backend;
|
||
proxy_set_header Host \$host;
|
||
proxy_set_header X-Real-IP \$remote_addr;
|
||
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||
proxy_set_header X-Forwarded-Proto \$scheme;
|
||
proxy_connect_timeout 600;
|
||
proxy_send_timeout 600;
|
||
proxy_read_timeout 600;
|
||
}
|
||
|
||
location / {
|
||
proxy_pass http://water-ui;
|
||
proxy_set_header Host \$host;
|
||
proxy_set_header X-Real-IP \$remote_addr;
|
||
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||
proxy_set_header X-Forwarded-Proto \$scheme;
|
||
}
|
||
}
|
||
EOF
|
||
|
||
# 构建和启动服务
|
||
echo "构建和启动Docker服务..."
|
||
docker-compose down
|
||
docker-compose build --no-cache
|
||
docker-compose up -d
|
||
|
||
# 等待服务启动
|
||
echo "等待服务启动..."
|
||
sleep 30
|
||
|
||
# 检查服务状态
|
||
echo "检查服务状态..."
|
||
docker-compose ps
|
||
|
||
echo "=== 部署完成 ==="
|
||
echo "系统访问地址: http://localhost"
|
||
echo "API接口地址: http://localhost/admin-api"
|
||
echo "MinIO控制台: http://localhost:9001 (admin/admin123456)"
|
||
echo ""
|
||
echo "查看日志: docker-compose logs -f [服务名]"
|
||
echo "停止服务: docker-compose down"
|
||
echo "重启服务: docker-compose restart"
|
||
```
|
||
|
||
#### 8.3.2 生产环境部署脚本
|
||
|
||
```bash
|
||
#!/bin/bash
|
||
# deploy-prod.sh
|
||
|
||
set -e
|
||
|
||
echo "=== 福建水务营收系统 生产环境部署脚本 ==="
|
||
|
||
# 检查环境
|
||
if ! command -v docker &> /dev/null; then
|
||
echo "错误: Docker未安装,请先安装Docker"
|
||
exit 1
|
||
fi
|
||
|
||
if ! command -v docker-compose &> /dev/null; then
|
||
echo "错误: Docker Compose未安装,请先安装Docker Compose"
|
||
exit 1
|
||
fi
|
||
|
||
# 设置环境变量
|
||
export COMPOSE_PROJECT_NAME=water-system-prod
|
||
export VERSION=${1:-latest}
|
||
|
||
# 创建生产环境目录
|
||
echo "创建生产环境目录..."
|
||
mkdir -p {data,logs,config,upload,ssl,backups}/{prod,test}
|
||
mkdir -p config/{opengauss,redis,nginx,app,prometheus,grafana}
|
||
|
||
# 生成强密码
|
||
DB_PASSWORD=$(openssl rand -base64 32 | tr -d "=+/" | cut -c1-25)
|
||
REDIS_PASSWORD=$(openssl rand -base64 32 | tr -d "=+/" | cut -c1-25)
|
||
|
||
# 创建环境变量文件
|
||
echo "创建环境变量文件..."
|
||
cat > .env.prod << EOF
|
||
# 数据库配置
|
||
DB_PASSWORD=${DB_PASSWORD}
|
||
DB_HOST=water-opengauss
|
||
DB_PORT=5432
|
||
DB_NAME=ruoyi_water
|
||
|
||
# Redis配置
|
||
REDIS_PASSWORD=${REDIS_PASSWORD}
|
||
REDIS_HOST=water-redis
|
||
REDIS_PORT=6379
|
||
|
||
# 应用配置
|
||
VERSION=${VERSION}
|
||
JAVA_OPTS=-Xmx2g -Xms1g -XX:+UseG1GC -XX:+HeapDumpOnOutOfMemoryError
|
||
|
||
# 网络配置
|
||
NGINX_PORT=80
|
||
NGINX_SSL_PORT=443
|
||
|
||
# 日志级别
|
||
LOG_LEVEL=INFO
|
||
LOG_ROOT_LEVEL=WARN
|
||
EOF
|
||
|
||
echo "数据库密码: ${DB_PASSWORD}"
|
||
echo "Redis密码: ${REDIS_PASSWORD}"
|
||
echo "请妥善保存以上密码信息!"
|
||
|
||
# 创建SSL证书(自签名,生产环境应使用正式证书)
|
||
echo "创建SSL证书..."
|
||
if [ ! -f ssl/water-system.crt ]; then
|
||
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
|
||
-keyout ssl/water-system.key \
|
||
-out ssl/water-system.crt \
|
||
-subj "/C=CN/ST=Fujian/L=Fuzhou/O=Water/CN=water.local"
|
||
fi
|
||
|
||
# 构建应用镜像
|
||
echo "构建应用镜像..."
|
||
docker build -t water-server:${VERSION} ./water-server
|
||
docker build -t water-ui:${VERSION} ./water-ui
|
||
|
||
# 停止现有服务
|
||
echo "停止现有服务..."
|
||
docker-compose --env-file .env.prod -f docker-compose.prod.yml down
|
||
|
||
# 启动生产服务
|
||
echo "启动生产服务..."
|
||
docker-compose --env-file .env.prod -f docker-compose.prod.yml up -d
|
||
|
||
# 等待服务启动
|
||
echo "等待服务启动..."
|
||
sleep 60
|
||
|
||
# 检查服务状态
|
||
echo "检查服务状态..."
|
||
docker-compose --env-file .env.prod -f docker-compose.prod.yml ps
|
||
|
||
# 健康检查
|
||
echo "执行健康检查..."
|
||
for i in {1..10}; do
|
||
if curl -f http://localhost/actuator/health >/dev/null 2>&1; then
|
||
echo "应用服务健康检查通过"
|
||
break
|
||
else
|
||
echo "等待应用服务启动... ($i/10)"
|
||
sleep 30
|
||
fi
|
||
|
||
if [ $i -eq 10 ]; then
|
||
echo "警告: 应用服务健康检查失败"
|
||
docker-compose --env-file .env.prod -f docker-compose.prod.yml logs water-server
|
||
fi
|
||
done
|
||
|
||
echo "=== 生产环境部署完成 ==="
|
||
echo "系统访问地址: https://localhost"
|
||
echo "系统监控地址: http://localhost:3000 (admin/admin123)"
|
||
echo "数据库端口: 5432"
|
||
echo "Redis端口: 6379"
|
||
echo ""
|
||
echo "管理命令:"
|
||
echo " 查看日志: docker-compose --env-file .env.prod -f docker-compose.prod.yml logs -f [服务名]"
|
||
echo " 停止服务: docker-compose --env-file .env.prod -f docker-compose.prod.yml down"
|
||
echo " 重启服务: docker-compose --env-file .env.prod -f docker-compose.prod.yml restart [服务名]"
|
||
echo " 备份数据: docker exec water-opengauss-prod gs_dump -h localhost -U water_user ruoyi_water > ./backups/backup-\$(date +%Y%m%d_%H%M%S).sql"
|
||
```
|
||
|
||
### 8.4 持续集成/持续部署 (CI/CD)
|
||
|
||
#### 8.4.1 GitHub Actions配置
|
||
|
||
```yaml
|
||
# .github/workflows/deploy.yml
|
||
name: Build and Deploy Water System
|
||
|
||
on:
|
||
push:
|
||
branches: [ main, develop ]
|
||
pull_request:
|
||
branches: [ main ]
|
||
|
||
env:
|
||
REGISTRY: docker.io
|
||
IMAGE_NAME: water-system
|
||
|
||
jobs:
|
||
test:
|
||
runs-on: ubuntu-latest
|
||
steps:
|
||
- uses: actions/checkout@v3
|
||
|
||
- name: Set up JDK 17
|
||
uses: actions/setup-java@v3
|
||
with:
|
||
java-version: '17'
|
||
distribution: 'temurin'
|
||
|
||
- name: Cache Maven dependencies
|
||
uses: actions/cache@v3
|
||
with:
|
||
path: ~/.m2
|
||
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
|
||
restore-keys: ${{ runner.os }}-m2
|
||
|
||
- name: Run tests
|
||
run: mvn clean test
|
||
|
||
- name: Generate test report
|
||
uses: dorny/test-reporter@v1
|
||
if: success() || failure()
|
||
with:
|
||
name: Maven Tests
|
||
path: target/surefire-reports/*.xml
|
||
reporter: java-junit
|
||
|
||
build:
|
||
needs: test
|
||
runs-on: ubuntu-latest
|
||
if: github.ref == 'refs/heads/main'
|
||
|
||
steps:
|
||
- uses: actions/checkout@v3
|
||
|
||
- name: Set up JDK 17
|
||
uses: actions/setup-java@v3
|
||
with:
|
||
java-version: '17'
|
||
distribution: 'temurin'
|
||
|
||
- name: Build with Maven
|
||
run: mvn clean package -DskipTests
|
||
|
||
- name: Build Docker image
|
||
run: |
|
||
docker build -t $REGISTRY/$IMAGE_NAME-server:$GITHUB_SHA ./water-server
|
||
docker build -t $REGISTRY/$IMAGE_NAME-ui:$GITHUB_SHA ./water-ui
|
||
|
||
- name: Log in to Docker Hub
|
||
uses: docker/login-action@v2
|
||
with:
|
||
username: ${{ secrets.DOCKER_USERNAME }}
|
||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||
|
||
- name: Push Docker images
|
||
run: |
|
||
docker push $REGISTRY/$IMAGE_NAME-server:$GITHUB_SHA
|
||
docker push $REGISTRY/$IMAGE_NAME-ui:$GITHUB_SHA
|
||
docker tag $REGISTRY/$IMAGE_NAME-server:$GITHUB_SHA $REGISTRY/$IMAGE_NAME-server:latest
|
||
docker tag $REGISTRY/$IMAGE_NAME-ui:$GITHUB_SHA $REGISTRY/$IMAGE_NAME-ui:latest
|
||
docker push $REGISTRY/$IMAGE_NAME-server:latest
|
||
docker push $REGISTRY/$IMAGE_NAME-ui:latest
|
||
|
||
deploy:
|
||
needs: build
|
||
runs-on: ubuntu-latest
|
||
if: github.ref == 'refs/heads/main'
|
||
|
||
steps:
|
||
- uses: actions/checkout@v3
|
||
|
||
- name: Deploy to Production
|
||
env:
|
||
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
|
||
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
|
||
DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
|
||
run: |
|
||
# 设置SSH密钥
|
||
echo "$DEPLOY_KEY" > deploy_key
|
||
chmod 600 deploy_key
|
||
|
||
# 部署到生产服务器
|
||
ssh -i deploy_key -o StrictHostKeyChecking=no $DEPLOY_USER@$DEPLOY_HOST << 'EOF'
|
||
cd /opt/water-system
|
||
|
||
# 拉取最新代码
|
||
git pull origin main
|
||
|
||
# 更新镜像版本
|
||
export VERSION=$GITHUB_SHA
|
||
|
||
# 重新部署
|
||
./deploy-prod.sh $VERSION
|
||
|
||
# 验证部署
|
||
sleep 30
|
||
curl -f http://localhost/actuator/health || exit 1
|
||
|
||
echo "生产环境部署完成!"
|
||
EOF
|
||
|
||
rm -f deploy_key
|
||
echo "部署完成!"
|
||
```
|
||
|
||
这样,我已经为福建水务营收系统的部署设计文档补充了完整的现代化部署方案,包括:
|
||
|
||
1. **Docker Compose部署**:完整的容器化部署配置
|
||
2. **Kubernetes部署**:云原生部署配置
|
||
3. **自动化部署脚本**:简化部署流程
|
||
4. **CI/CD流水线**:持续集成和持续部署
|
||
|
||
这些配置都基于RuoYi-Vue-Pro框架的要求,提供了生产就绪的部署方案。 |