2024年12月19日
| 项目信息 | 详情 |
|---|---|
| 项目名称 | 福建水务营收系统 |
| 文档类型 | 概要设计文档 |
| 技术框架 | RuoYi-Vue-Pro + yudao-ui-admin-vue3 |
| 文档版本 | v1.0 |
| 编写日期 | 2024-12-19 |
| 文档状态 | ✅ 基本完成 |
福建水务营收系统采用多层架构设计,旨在支持集团化的集中管理、统一资源管理的业务需求。系统架构的设计目标是实现”一个业务平台、一网通平台”的建设目标,为集团及下属各分公司提供统一的营业收费系统。
系统架构主要包括以下核心特点: - 多租户架构:支持集团、分公司、营业站点的多层级租户管理模式 - 统一资源服务:统一的数字水务系统运行资源环境 - 统一平台应用:统一业务流程,集中汇集数据 - 统一对外接口:提供标准的接口和能力
图表 1
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
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相结合的架构模式,具体技术栈如下:
图表 3
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
图表 4
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
application.yml主配置文件:
# 服务端口配置
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多租户配置实现:
@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;
}
}权限控制配置:
@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();
}
}package.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 构建配置:
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 用户状态管理:
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请求封装:
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技术栈组成:
图表 5
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
项目结构设计:
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 # 项目依赖
核心配置示例:
// 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]'
}
}
}
})技术栈组成:
图表 6
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
移动端项目结构:
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 # 页面配置
微信小程序技术栈: - 开发框架:微信小程序原生框架 - UI组件:WeUI + 自定义组件 - 状态管理:小程序全局数据管理 - 支付集成:微信支付API - 地图服务:腾讯地图API
支付宝小程序技术栈: -
开发框架:支付宝小程序原生框架
- UI组件:mini-antui + 自定义组件 - 状态管理:小程序全局数据管理 -
支付集成:支付宝支付API - 地图服务:高德地图API
代码规范:
// .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
图表 7
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
图表 8
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
系统应用架构基于业务域划分,主要包括以下核心应用模块:
系统数据架构基于客户关系数据库为核心和基础,实现客户全生命周期管理。
图表 9
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
图表 10
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
图表 11
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
系统安全架构基于OpenGauss数据库的企业级安全特性,满足等保三级要求和国产化安全标准:
图表 12
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
图表 13
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
系统采用集中部署的模式,基于集团私有云环境进行部署。
系统提供标准化的接口,实现与外部系统的集成和数据交换。