福建水务营收系统概要设计文档

系统设计团队

2024年12月19日

1 福建水务营收系统概要设计文档

1.1 文档信息

项目信息 详情
项目名称 福建水务营收系统
文档类型 概要设计文档
文档版本 v1.0
编写日期 2024-12-19
文档状态 ✅ 已完成

ewpage

2 第1部分:

2.0.0.0.1 福建水务营收系统架构设计文档
2.0.0.0.2 文档信息
项目信息 详情
项目名称 福建水务营收系统
文档类型 概要设计文档
技术框架 RuoYi-Vue-Pro + yudao-ui-admin-vue3
文档版本 v1.0
编写日期 2024-12-19
文档状态 ✅ 基本完成
2.0.0.0.3 目录
2.0.0.0.4 一、系统架构概述

福建水务营收系统采用多层架构设计,旨在支持集团化的集中管理、统一资源管理的业务需求。系统架构的设计目标是实现”一个业务平台、一网通平台”的建设目标,为集团及下属各分公司提供统一的营业收费系统。

系统架构主要包括以下核心特点: - 多租户架构:支持集团、分公司、营业站点的多层级租户管理模式 - 统一资源服务:统一的数字水务系统运行资源环境 - 统一平台应用:统一业务流程,集中汇集数据 - 统一对外接口:提供标准的接口和能力

2.0.0.0.5 1.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.0.0.0.6 1.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
2.0.0.0.7 二、技术架构

系统采用B/S和M/S相结合的架构模式,具体技术栈如下:

2.0.0.0.8 2.1 技术栈总览图
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.0.0.0.9 2.2 系统数据流向图
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
2.0.0.0.10 2.3 服务端技术架构
2.0.0.0.11 2.3.1 RuoYi-Vue-Pro框架配置示例

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();
    }
}
2.0.0.0.12 2.4 客户端技术架构
2.0.0.0.13 2.4.1 前端项目结构配置

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
2.0.0.0.14 2.5 前端技术架构详细设计
2.0.0.0.15 2.5.1 Web管理端架构 (yudao-ui-admin-vue3)

技术栈组成:

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]'
      }
    }
  }
})
2.0.0.0.16 2.5.2 移动端架构 (uni-app)

技术栈组成:

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           # 页面配置
2.0.0.0.17 2.5.3 客户端小程序架构

微信小程序技术栈: - 开发框架:微信小程序原生框架 - UI组件:WeUI + 自定义组件 - 状态管理:小程序全局数据管理 - 支付集成:微信支付API - 地图服务:腾讯地图API

支付宝小程序技术栈: - 开发框架:支付宝小程序原生框架
- UI组件:mini-antui + 自定义组件 - 状态管理:小程序全局数据管理 - 支付集成:支付宝支付API - 地图服务:高德地图API

2.0.0.0.18 2.5.4 前端工程化配置

代码规范:

// .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

2.0.0.0.19 2.6 技术特性
2.0.0.0.20 三、应用架构
2.0.0.0.21 3.1 微服务应用架构图
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.0.0.0.22 3.2 服务治理架构
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

系统应用架构基于业务域划分,主要包括以下核心应用模块:

2.0.0.0.23 3.3 统一平台
2.0.0.0.24 3.4 营收系统
2.0.0.0.25 3.5 客户服务
2.0.0.0.26 3.6 表务系统
2.0.0.0.27 3.7 报装管理
2.0.0.0.28 3.8 统计分析
2.0.0.0.29 3.9 工程管理
2.0.0.0.30 3.10 抄表APP
2.0.0.0.31 3.11 接口服务
2.0.0.0.32 3.12 系统配置
2.0.0.0.33 四、数据架构

系统数据架构基于客户关系数据库为核心和基础,实现客户全生命周期管理。

2.0.0.0.34 4.1 数据分层
2.0.0.0.35 4.2 OpenGauss数据库架构
2.0.0.0.36 4.2.1 主从高可用架构
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
2.0.0.0.37 4.2.2 分片存储架构
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
2.0.0.0.38 4.2.3 数据安全架构
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
2.0.0.0.39 4.3 数据模型设计
2.0.0.0.40 4.4 数据集成与共享
2.0.0.0.41 4.5 OpenGauss特性应用
2.0.0.0.42 4.5.1 性能优化特性
2.0.0.0.43 4.5.2 企业级特性
2.0.0.0.44 五、安全架构

系统安全架构基于OpenGauss数据库的企业级安全特性,满足等保三级要求和国产化安全标准:

2.0.0.0.45 5.1 网络安全
2.0.0.0.46 5.2 OpenGauss数据安全架构
2.0.0.0.47 5.2.1 数据加密安全
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
2.0.0.0.48 5.2.2 访问控制安全
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
2.0.0.0.49 5.3 数据安全特性
2.0.0.0.50 5.4 多租户安全隔离
2.0.0.0.51 5.5 应用安全
2.0.0.0.52 5.6 接口安全
2.0.0.0.53 六、部署架构

系统采用集中部署的模式,基于集团私有云环境进行部署。

2.0.0.0.54 6.1 物理部署
2.0.0.0.55 6.2 逻辑部署
2.0.0.0.56 6.3 容器部署
2.0.0.0.57 七、接口架构

系统提供标准化的接口,实现与外部系统的集成和数据交换。

2.0.0.0.58 7.1 外部接口
2.0.0.0.59 7.2 内部接口
2.0.0.0.60 7.3 接口标准
2.0.0.0.61 7.4 接口服务管理

ewpage

3 第2部分:

3.0.0.0.1 福建水务营收系统模块功能设计文档
3.0.0.0.2 文档信息
项目信息 详情
项目名称 福建水务营收系统
文档类型 概要设计文档
技术框架 RuoYi-Vue-Pro + yudao-ui-admin-vue3
文档版本 v1.0
编写日期 2024-12-19
文档状态 ✅ 已完成
3.0.0.0.3 目录
3.0.0.0.4 一、系统整体架构

福建水务营收系统采用现代化的分布式微服务架构,基于RuoYi-Vue-Pro后端框架和yudao-ui-admin-vue3前端框架构建,为水务企业提供完整的营收管理解决方案。

3.0.0.0.5 1.1 系统架构图
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
3.0.0.0.6 1.2 技术架构图
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
3.0.0.0.7 1.3 业务架构图
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
3.0.0.0.8 二、统一平台

统一平台是客户服务平台的综合展示平台,基于RuoYi-Vue-Pro和yudao-ui-admin-vue3框架构建,包含日常工作功能和客户全部的信息,是系统的基础功能模块。

3.0.0.0.9 2.1 单点登录

单点登录模块基于Spring Security和JWT实现用户一次登录即可访问系统中所有应用的功能,主要特点包括:

3.0.0.0.10 2.2 系统管理

系统管理模块基于RuoYi-Vue-Pro框架的现成功能,提供对系统基础参数的配置管理功能,主要包括:

3.0.0.0.11 三、营收系统

营收系统是水务业务系统的核心组成部分,负责抄表、收费、账务处理等关键业务功能。

3.0.0.0.12 3.1 系统管理

营收系统的基础管理功能,包括:

3.0.0.0.13 3.2 抄表开账

抄表开账模块负责水表读数的采集和账单生成,是营收系统的核心业务模块。

3.0.0.0.14 3.2.1 业务流程图
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.0.0.0.15 3.2.2 主要功能

册本管理:册本基本信息的维护和管理 - 册本创建与配置 - 抄表路线规划 - 抄表员分配 - 抄表周期设置

抄表录入:支持多种抄表方式 - 手工抄表:现场抄表、批量录入 - 智能抄表:远程数据采集、自动同步 - 自报抄表:客户自主上报、在线提交

抄表数据审核:确保数据质量 - 数据校验:读数合理性检查、用量异常检测 - 异常处理:异常数据标记、人工处理 - 开账处理:数据确认、账单生成

追加抄表:支持非周期性特殊抄表 - 补抄管理:漏抄数据补录 - 特殊抄表:临时抄表需求 - 调整抄表:读数错误修正

3.0.0.0.16 3.2.3 核心接口定义

抄表管理主要接口

@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.0.0.0.17 3.2.4 前端界面设计

抄表管理页面结构

<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.0.0.0.18 3.3 收费管理

收费管理模块负责水费的收取和管理,是营收系统的重要业务模块。

3.0.0.0.19 3.3.1 业务流程图
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.0.0.0.20 3.3.2 主要功能

柜台收费:现场收费服务 - 用户查询:客户信息查询、账单查询 - 收费处理:多种支付方式、找零计算 - 收费打印:收据打印、发票开具 - 预存预付:余额充值、预付费管理

柜台结账:营业网点日常结账 - 日结处理:当日收费汇总、统计分析 - 交款管理:现金上缴、账务核对 - 结账查询:历史结账记录查询

预付款管理:预付费业务处理 - 预付款充值:余额充值、充值记录 - 使用管理:自动扣款、余额提醒 - 退款处理:预付款退款、退款审核

缴费记录查询:缴费历史管理 - 多条件查询:按时间、金额、渠道查询 - 统计分析:缴费趋势、渠道分析 - 导出功能:缴费记录导出

3.0.0.0.21 3.3.3 核心接口定义

缴费管理主要接口

@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.0.0.0.22 3.4 账务处理

账务处理模块负责处理各类特殊账务情况,确保账务数据的准确性和完整性。

3.0.0.0.23 3.4.1 业务流程图
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.0.0.0.24 3.4.2 主要功能

未销调整:处理各类账务调整需求 - 水量调整:调整用水量和相关费用 - 金额调整:直接调整账单金额 - 违约金减免:减免或取消违约金 - 费用追加:补收相关费用

特殊开账:处理特殊情况的账单生成 - 补抄开账:补录抄表数据并生成账单 - 估抄开账:估算用水量生成账单 - 平均开账:基于历史用量平均开账

账务退款:处理各类退款业务 - 多缴退款:退还多缴的水费 - 预付款退款:退还预存余额 - 错误缴费退款:退还错误缴费

3.0.0.0.25 3.4.3 核心接口定义
@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.0.0.0.26 3.5 发票管理

发票管理模块负责水费发票的全生命周期管理,支持纸质发票和电子发票。

3.0.0.0.27 3.5.1 业务流程图
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.0.0.0.28 3.5.2 核心接口定义
@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.0.0.0.29 3.6 代收业务

代收业务模块负责处理各种渠道的水费代收业务,主要功能包括:

3.0.0.0.30 3.7 环卫系统

环卫系统模块负责管理与环卫相关的收费和计费业务,主要功能包括:

3.0.0.0.31 3.8 业务工单

业务工单模块负责管理日常业务工单的流转和处理,主要功能包括:

3.0.0.0.32 四、表务系统

表务系统负责水表的全生命周期管理,包括水表购置、安装、维修、更换等业务。

3.0.0.0.33 4.1 表务工单

表务工单模块负责处理各类表务作业,主要功能包括:

3.0.0.0.34 4.2 表务仓库

表务仓库模块负责水表的仓储管理,主要功能包括:

3.0.0.0.35 4.3 水表参数与基础信息

水表参数与基础信息模块负责维护水表相关的基础数据,主要功能包括:

3.0.0.0.36 4.4 物联网对接与数据同步

物联网对接与数据同步模块负责水表数据的互联互通,主要功能包括:

3.0.0.0.37 五、报装系统

报装系统负责新用户的报装立户管理,主要功能包括:

3.0.0.0.38 5.1 报装流程

报装流程模块负责新用户报装业务的全流程管理,主要功能包括:

3.0.0.0.39 5.2 一户一表管理

一户一表管理模块负责实施”一户一表”改造,主要功能包括:

3.0.0.0.40 六、客户服务

客户服务模块提供多渠道的客户服务功能,主要包括:

3.0.0.0.41 6.1 微信、支付宝服务窗
3.0.0.0.42 6.2 历史账单
3.0.0.0.43 6.3 电子发票
3.0.0.0.44 6.4 营业网点
3.0.0.0.45 6.5 账户流水
3.0.0.0.46 6.6 微网厅
3.0.0.0.47 七、系统配置

系统配置模块提供各类系统参数的配置管理功能,主要包括:

3.0.0.0.48 7.1 水表参数
3.0.0.0.49 7.2 地址参数
3.0.0.0.50 7.3 价格体系
3.0.0.0.51 7.4 基本配置
3.0.0.0.52 7.5 催缴管理
3.0.0.0.53 7.6 用户权限
3.0.0.0.54 7.7 定时任务
3.0.0.0.55 八、系统接口

系统接口模块提供与外部系统的集成和数据交换功能,实现业务数据的互通互联。

3.0.0.0.56 8.1 银行接口

银行接口实现与银行系统的对接,支持代扣、托收等功能,主要包括:

3.0.0.0.57 8.2 支付宝/微信接口

支付宝和微信接口实现与第三方支付平台的对接,支持在线支付功能,主要包括:

3.0.0.0.58 8.3 短信接口

短信接口提供短信通知和验证功能,主要包括:

3.0.0.0.59 8.4 集抄系统接口

集抄系统接口实现与智能水表集中抄表系统的对接,主要包括:

3.0.0.0.60 8.5 政务系统接口

政务系统接口实现与地方政务平台和政务APP的对接,主要包括:

3.0.0.0.61 8.6 消火栓系统接口

消火栓系统接口实现与消火栓系统的对接,主要功能包括:

3.0.0.0.62 8.7 其他系统对接

其他系统对接模块负责与周边系统进行数据交换和业务协同,主要功能包括:

3.0.0.0.63 九、统计分析

统计分析模块提供多维度的数据统计和分析功能,为管理决策提供数据支持。

3.0.0.0.64 9.1 报表查询
3.0.0.0.65 9.2 欠费查询
3.0.0.0.66 9.3 缴费记录
3.0.0.0.67 9.4 用水分析
3.0.0.0.68 十、工程管理

工程管理模块负责处理与供水工程相关的业务,包括工程申请、施工管理和工程验收等。

3.0.0.0.69 10.1 工程申请
3.0.0.0.70 10.2 工程施工
3.0.0.0.71 10.3 工程验收
3.0.0.0.72 10.4 工程查询
3.0.0.0.73 十一、抄表APP

抄表APP是针对移动端开发的抄表工具,支持外勤人员进行现场抄表、问题处理和工单管理等业务操作。

3.0.0.0.74 11.1 首页功能
3.0.0.0.75 11.2 抄表功能
3.0.0.0.76 11.3 工单管理
3.0.0.0.77 十二、接口服务

接口服务模块提供系统对外的API接口管理和服务能力,实现与第三方系统的便捷集成。

3.0.0.0.78 12.1 API市场
3.0.0.0.79 12.2 API管理
3.0.0.0.80 12.3 接口权限管理
3.0.0.0.81 12.4 系统对外接口
3.0.0.0.82 系统集成架构
3.0.0.0.83 前后端集成架构
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
3.0.0.0.84 技术栈整合方案

后端技术整合: - 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提供全文搜索

3.1 这样的架构设计确保了系统的高可用性、可扩展性和维护性,为福建水务营收系统提供了坚实的技术基础。

ewpage

4 第3部分:

4.0.0.0.1 福建水务营收系统数据库设计文档
4.0.0.0.2 文档信息
项目信息 详情
项目名称 福建水务营收系统
文档类型 概要设计文档
技术框架 RuoYi-Vue-Pro + yudao-ui-admin-vue3
文档版本 v1.0
编写日期 2024-12-19
文档状态 ✅ 已完成
4.0.0.0.3 目录
4.0.0.0.4 一、数据库设计概述

福建水务营收系统采用华为OpenGauss 5.0+数据库,基于RuoYi-Vue-Pro框架规范设计。OpenGauss作为国产自主可控的企业级数据库,具有高性能、高可用、高安全的特点,完全满足水务行业对数据安全和国产化的要求。数据库架构支持多租户、高并发、高可用的业务需求,为水务营收业务提供稳定可靠的数据存储服务。

4.0.0.0.5 1.1 设计目标
4.0.0.0.6 1.2 数据库选型优势
4.0.0.0.7 1.3 设计原则
4.0.0.0.8 二、数据库架构
4.0.0.0.9 1. 数据库架构图
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
4.0.0.0.10 2. 多租户架构设计
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
4.0.0.0.11 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 逻辑删除标识
4.0.0.0.12 三、核心数据模型ER图
4.0.0.0.13 1. 客户管理模块ER图
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 : "对应"
4.0.0.0.14 2. 营收管理模块ER图
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 : "对应"
4.0.0.0.15 3. 表务管理模块ER图
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.0.0.0.16 4. 系统管理模块ER图
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 : "包含"
4.0.0.0.17 四、核心数据表设计
4.0.0.0.18 1. 表务管理模块ER图
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 : "关联"
4.0.0.0.19 2. 系统管理模块ER图
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 : "包含"
4.0.0.0.20 五、完整DDL语句
4.0.0.0.21 1. 客户管理相关表DDL
4.0.0.0.22 1.1 客户基本信息表
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='客户基本信息表';
4.0.0.0.23 1.2 水表信息表
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='水表信息表';
4.0.0.0.24 3. 表务工单管理表DDL
4.0.0.0.25 3.1 表务工单表
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='表务工单表';
4.0.0.0.26 3.2 水表库存管理表
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.0.0.0.27 4. 系统管理相关表DDL
4.0.0.0.28 4.1 数据字典类型表
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='数据字典类型表';
4.0.0.0.29 5. 完整DDL语句列表
4.0.0.0.30 5.1 客户基本信息表 (OpenGauss版本)
-- 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();
4.0.0.0.31 1.2 水表信息表
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='水表信息表';
4.0.0.0.32 1.3 客户账户表
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='客户账户信息表';
4.0.0.0.33 2. 营收管理相关表DDL
4.0.0.0.34 2.1 抄表记录表
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='抄表记录表';
4.0.0.0.35 2.2 水费账单表
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='水费账单表';
4.0.0.0.36 2.3 缴费记录表
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='缴费记录表';
4.0.0.0.37 3. 表务管理相关表DDL
4.0.0.0.38 3.1 水表档案表
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.0.0.0.39 4. 系统管理相关表DDL
4.0.0.0.40 4.1 数据字典表
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='数据字典表';
4.0.0.0.41 5. 初始化数据脚本
-- 插入基础字典数据
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, '银行自动代扣');
4.0.0.0.42 六、OpenGauss数据库特性应用
4.0.0.0.43 1. OpenGauss高级特性
4.0.0.0.44 1.1 分区表设计
-- 按月份分区的账单表
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')
  -- 继续按月创建分区...
);
4.0.0.0.45 1.2 列存储表
-- 统计分析用的列存储表
CREATE TABLE water_bill_stats (
  -- 字段定义...
) WITH (ORIENTATION = COLUMN);
4.0.0.0.46 1.3 内存表
-- 配置参数缓存表
CREATE TABLE water_config_cache (
  -- 字段定义...
) WITH (ORIENTATION = ROW, STORAGE_TYPE = USTORE);
4.0.0.0.47 2. 性能优化配置
4.0.0.0.48 2.1 连接池配置
-- 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';
4.0.0.0.49 2.2 并行查询
-- 启用并行查询
ALTER SYSTEM SET max_parallel_workers = 8;
ALTER SYSTEM SET max_parallel_workers_per_gather = 4;
4.0.0.0.50 七、索引设计与优化
4.0.0.0.51 1. 基础索引设计
4.0.0.0.52 1.1 主键索引
4.0.0.0.53 1.2 唯一索引
-- 客户编号唯一索引
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);
4.0.0.0.54 1.3 复合索引
-- 多租户查询优化
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);
4.0.0.0.55 2. OpenGauss特殊索引
4.0.0.0.56 2.1 HASH索引
-- 等值查询优化
CREATE INDEX CONCURRENTLY idx_customer_phone_hash ON water_customer USING HASH (phone);
4.0.0.0.57 2.2 GIN索引
-- 全文检索索引
CREATE INDEX idx_customer_name_gin ON water_customer USING GIN (to_tsvector('simple', customer_name));
4.0.0.0.58 2.3 部分索引
-- 只对有效数据建索引
CREATE INDEX idx_active_customers ON water_customer (customer_code) WHERE deleted = FALSE AND status = 1;
4.0.0.0.59 八、OpenGauss数据安全设计
4.0.0.0.60 1. 内置安全特性
4.0.0.0.61 1.1 透明数据加密 (TDE)
-- 启用表级加密
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;
4.0.0.0.62 1.2 行级安全策略 (RLS)
-- 创建多租户行级安全
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);
4.0.0.0.63 1.3 动态数据脱敏
-- 创建脱敏函数
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;
4.0.0.0.64 2. 权限控制体系
4.0.0.0.65 2.1 角色权限设计
-- 创建业务角色
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;
4.0.0.0.66 2.2 列级权限控制
-- 敏感字段权限控制
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;
4.0.0.0.67 3. 审计与监控
4.0.0.0.68 3.1 审计日志配置
-- 启用审计
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');
4.0.0.0.69 3.2 敏感操作监控
-- 创建敏感操作触发器
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.0.0.0.70 4. 数据备份与灾备
4.0.0.0.71 4.1 OpenGauss备份策略
-- 全量备份
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.0.0.0.72 4.2 主备同步配置
-- 主库配置
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;
4.0.0.0.73 5. 国产化安全合规
4.0.0.0.74 5.1 等保三级要求
4.0.0.0.75 5.2 国产化认证
-- 使用国产SM4算法加密
CREATE TABLE water_customer_sm4 (
  -- 字段定义...
) WITH (ENCRYPTION_TYPE = 'SM4_CTR');

ewpage

5 第4部分:

5.0.0.0.1 福建水务营收系统接口设计文档
5.0.0.0.2 文档信息
项目信息 详情
项目名称 福建水务营收系统
文档类型 概要设计文档
技术框架 RuoYi-Vue-Pro + yudao-ui-admin-vue3
文档版本 v1.0
编写日期 2024-12-19
文档状态 🟡 进行中
5.0.0.0.3 目录
5.0.0.0.4 1. 接口概述

福建水务业务系统提供丰富的接口,用于与外部系统集成以及系统内部各模块间的数据交换。接口设计遵循标准化、安全性、可扩展性的原则,基于RuoYi-Vue-Pro框架采用RESTful风格设计,支持JSON数据格式。

5.0.0.0.5 1.1 接口设计原则
5.0.0.0.6 1.2 RESTful API规范

系统API接口采用RESTful风格设计,主要规范如下:

5.0.0.0.7 1.2.1 资源命名
5.0.0.0.8 1.2.2 HTTP方法
5.0.0.0.9 1.2.3 状态码
5.0.0.0.10 1.2.4 响应格式

系统统一采用以下JSON格式响应:

{
  "code": 0,           // 业务状态码,0表示成功,非0表示失败
  "data": {},          // 响应数据
  "msg": "success"     // 响应消息
}

分页查询响应格式:

{
  "code": 0,
  "data": {
    "list": [],        // 数据列表
    "total": 100,      // 总记录数
    "pageNum": 1,      // 当前页码
    "pageSize": 10     // 每页记录数
  },
  "msg": "success"
}
5.0.0.0.11 1.3 接口文档

系统使用Knife4j(基于Swagger)自动生成API文档,文档地址为:http://{系统地址}/doc.html

主要特点: - 在线接口文档:支持在线查看接口定义 - 接口调试:支持在线调试接口 - 文档导出:支持导出OpenAPI规范文档 - 权限控制:支持对接口文档的访问控制

5.0.0.0.12 2. 外部接口
5.0.0.0.13 2.1 银行接口对接
5.0.0.0.14 2.1.1 银行代扣接口

功能描述:通过银行系统自动从用户账户中扣除水费。

接口详情: - 接口方式:文件交换(FTP/SFTP) - 数据格式:定长文本文件 - 交换频率:每日凌晨2:00 - 文件编码:GBK

代扣文件格式

记录类型(1位) + 客户号(12位) + 户名(30位) + 银行账号(20位) + 扣款金额(12位,含2位小数) + 账期(6位) + 保留字段(19位)

代扣文件示例

1C00000000001张三                          62172511001234567890000009180202412          
1C00000000002李四                          62172511001234567891000015460202412          

回盘文件格式

记录类型(1位) + 客户号(12位) + 银行账号(20位) + 扣款金额(12位) + 处理状态(1位) + 银行流水号(20位) + 处理时间(14位) + 失败原因(20位)

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();
    }
}
5.0.0.0.15 2.1.2 银行实时缴费接口

功能描述:用户在银行柜台、网上银行或手机银行实时缴纳水费。

接口详情: - 接口方式:HTTP POST - 请求URLhttps://bank.api.com/payment/water-fee - 数据格式:JSON - 认证方式:API Key + 签名

请求参数

{
  "merchantId": "WATER001",
  "customerCode": "C001",
  "billCodes": ["B202412190001"],
  "totalAmount": 91.80,
  "bankAccount": "6217251100123456789",
  "customerName": "张三",
  "timestamp": "20241219103000",
  "signature": "ABC123DEF456..."
}

响应参数

{
  "resultCode": "0000",
  "resultMsg": "交易成功",
  "data": {
    "transactionId": "TXN20241219001",
    "paymentTime": "20241219103001",
    "bankSerial": "BNK20241219001234"
  }
}
5.0.0.0.16 2.2 支付宝接口对接

功能描述:用户通过支付宝缴纳水费,支持扫码支付和H5支付。

接口详情: - 接口方式:HTTP POST - 支付方式:统一收单交易预创建(alipay.trade.precreate) - 数据格式:JSON - 认证方式:RSA2签名

预创建支付请求参数

{
  "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"
  }
}

支付宝响应参数

{
  "alipay_trade_precreate_response": {
    "code": "10000",
    "msg": "Success",
    "out_trade_no": "P202412190002",
    "qr_code": "https://qr.alipay.com/bax08945xtdnfwgqmwi200b4"
  },
  "sign": "ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE"
}

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());
        }
    }
}
5.0.0.0.17 2.3 微信支付接口对接

功能描述:用户通过微信支付缴纳水费,支持扫码支付和小程序支付。

接口详情: - 接口方式:HTTP POST - 支付方式:Native支付(扫码)/ JSAPI支付(小程序) - 请求URLhttps://api.mch.weixin.qq.com/v3/pay/transactions/native - 数据格式:JSON - 认证方式:微信支付V3签名

统一下单请求参数

{
  "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"
}

微信支付响应参数

{
  "code_url": "weixin://wxpay/bizpayurl?pr=HuaLcAKwa"
}

支付结果通知参数

{
  "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": "..."
  }
}
5.0.0.0.18 2.4 短信接口

功能描述:向用户发送各类业务通知短信。

接口规范: - 接口方式:HTTP接口 - 数据格式:JSON - 交换频率:实时

5.0.0.0.19 2.5 物联网集抄平台接口

功能描述:与物联网集抄平台交互,获取智能水表数据。

接口规范: - 接口方式:HTTP接口或WebService - 数据格式:JSON或XML - 交换频率:定时或实时

5.0.0.0.20 3. 内部接口
5.0.0.0.21 3.1 客户管理API接口
5.0.0.0.22 3.1.1 客户信息查询接口

功能描述:根据客户ID查询客户详细信息。

接口详情: - 请求方式:GET - 请求路径/admin-api/water/customer/{id} - 请求头Authorization: Bearer {token}

请求参数: | 参数名 | 类型 | 必填 | 说明 | 示例 | |——-|——|——|——|——| | id | Long | 是 | 客户ID | 1 |

响应参数

{
  "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代码示例

@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));
    }
}
5.0.0.0.23 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 |

响应参数

{
  "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
  }
}
5.0.0.0.24 3.1.3 客户创建接口

功能描述:创建新客户记录。

接口详情: - 请求方式:POST - 请求路径/admin-api/water/customer/create

请求参数

{
  "customerCode": "C002",
  "customerName": "李四",
  "customerType": "RESIDENT",
  "idType": "ID_CARD",
  "idNumber": "350103199001011234",
  "phone": "13900139000",
  "address": "福建省福州市鼓楼区XX街道XX号"
}

响应参数

{
  "code": 0,
  "msg": "操作成功",
  "data": 2
}

Service层代码示例

@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);
        }
    }
}
5.0.0.0.25 3.2 水表管理API接口
5.0.0.0.26 3.2.1 水表信息查询接口

功能描述:根据水表ID查询水表详细信息。

接口详情: - 请求方式:GET - 请求路径/admin-api/water/meter/{id} - 请求头Authorization: Bearer {token}

请求参数: | 参数名 | 类型 | 必填 | 说明 | 示例 | |——-|——|——|——|——| | id | Long | 是 | 水表ID | 1 |

响应参数

{
  "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代码示例

@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));
    }
}
5.0.0.0.27 3.2.2 抄表记录创建接口

功能描述:创建新的抄表记录。

接口详情: - 请求方式:POST - 请求路径/admin-api/water/reading/create

请求参数

{
  "meterId": 1,
  "readingDate": "2024-12-19",
  "readingValue": 156.32,
  "readingType": "MANUAL",
  "readerId": "R001",
  "photoUrl": "https://example.com/photos/reading001.jpg",
  "remark": "正常抄表"
}

响应参数

{
  "code": 0,
  "msg": "操作成功", 
  "data": 1
}

Service层实现示例

@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();
    }
}
5.0.0.0.28 3.2.3 抄表数据批量导入接口

功能描述:批量导入抄表数据,支持Excel文件上传。

接口详情: - 请求方式:POST - 请求路径/admin-api/water/reading/import - Content-Typemultipart/form-data

请求参数: | 参数名 | 类型 | 必填 | 说明 | 示例 | |——-|——|——|——|——| | file | MultipartFile | 是 | Excel文件 | reading_data.xlsx | | updateSupport | Boolean | 否 | 是否更新已有数据 | false |

响应参数

{
  "code": 0,
  "msg": "操作成功",
  "data": {
    "successCount": 95,
    "failureCount": 5,
    "failureList": [
      {
        "lineNumber": 3,
        "meterCode": "M003", 
        "errorMsg": "水表不存在"
      }
    ]
  }
}
5.0.0.0.29 3.3 账单管理API接口
5.0.0.0.30 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 |

响应参数

{
  "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
  }
}
5.0.0.0.31 3.3.2 账单生成接口

功能描述:根据抄表记录生成水费账单。

接口详情: - 请求方式:POST - 请求路径/admin-api/water/bill/generate

请求参数

{
  "billMonth": "2024-12",
  "customerIds": [1, 2, 3],
  "readingIds": [1, 2, 3],
  "dueDate": "2025-01-19"
}

响应参数

{
  "code": 0,
  "msg": "操作成功",
  "data": {
    "generateCount": 3,
    "successList": [
      {
        "customerId": 1,
        "billId": 1,
        "totalAmount": 91.80
      }
    ],
    "failureList": []
  }
}

Service层代码示例

@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;
    }
}
5.0.0.0.32 3.4 缴费管理API接口
5.0.0.0.33 3.4.1 缴费处理接口

功能描述:处理客户缴费操作。

接口详情: - 请求方式:POST - 请求路径/admin-api/water/payment/create

请求参数

{
  "customerId": 1,
  "billIds": [1, 2],
  "paymentType": "NORMAL",
  "paymentChannel": "CASH",
  "paymentAmount": 183.60,
  "actualAmount": 200.00,
  "operatorId": "OP001",
  "outletCode": "OUT001",
  "remark": "现金缴费"
}

响应参数

{
  "code": 0,
  "msg": "操作成功",
  "data": {
    "paymentId": 1,
    "paymentCode": "P202412190001",
    "changeAmount": 16.40,
    "invoiceNo": "INV20241219001"
  }
}
5.0.0.0.34 3.4.2 在线支付接口

功能描述:处理在线支付(微信、支付宝等)。

接口详情: - 请求方式:POST - 请求路径/admin-api/water/payment/online-pay

请求参数

{
  "customerId": 1,
  "billIds": [1],
  "paymentChannel": "WECHAT",
  "paymentAmount": 91.80,
  "returnUrl": "https://water.example.com/payment/callback",
  "notifyUrl": "https://water.example.com/api/payment/notify"
}

响应参数

{
  "code": 0,
  "msg": "操作成功",
  "data": {
    "paymentCode": "P202412190002",
    "prepayId": "wx20241219001234567890",
    "payUrl": "weixin://wxpay/bizpayurl?pr=abc123",
    "qrCode": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..."
  }
}
5.0.0.0.35 3.4 工单接口
5.0.0.0.36 3.4.1 工单创建接口

功能描述:创建业务工单。

接口规范: - 请求方式:POST - 请求路径:/api/workorders - 请求/返回格式:JSON

5.0.0.0.37 3.4.2 工单状态更新接口

功能描述:更新工单处理状态。

接口规范: - 请求方式:PUT - 请求路径:/api/workorders/{workorderId}/status - 请求/返回格式:JSON

5.0.0.0.38 4. 接口标准
5.0.0.0.39 4.1 接口协议

系统接口主要采用以下协议:

5.0.0.0.40 4.2 数据格式

接口数据主要采用以下格式:

5.0.0.0.41 4.3 接口安全设计

接口安全采用多层防护机制:

5.0.0.0.42 4.3.1 认证机制

JWT令牌认证

@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认证(外部系统):

@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);
    }
}
5.0.0.0.43 4.3.2 数据加密

敏感数据加密

@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);
    }
}
5.0.0.0.44 4.3.3 访问控制

IP白名单控制

@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);
    }
}
5.0.0.0.45 4.3.4 接口限流

基于Redis的令牌桶限流

@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;
    }
}
5.0.0.0.46 4.4 错误处理机制
5.0.0.0.47 4.4.1 统一异常处理
@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());
    }
}
5.0.0.0.48 4.4.2 错误码定义
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, "缴费渠道不可用");
}
5.0.0.0.49 4.4.3 接口调用示例

成功响应示例

{
  "code": 0,
  "msg": "操作成功",
  "data": {
    "id": 1,
    "customerName": "张三"
  }
}

失败响应示例

{
  "code": 1001000001,
  "msg": "客户不存在",
  "data": null
}
5.0.0.0.50 4.5 前端接口调用示例
5.0.0.0.51 4.5.1 Vue3 + 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}` })
  }
}
5.0.0.0.52 4.5.2 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>

ewpage

6 第5部分:

6.0.0.0.1 福建水务营收系统部署设计文档
6.0.0.0.2 文档信息
项目信息 详情
项目名称 福建水务营收系统
文档类型 概要设计文档
技术框架 RuoYi-Vue-Pro + yudao-ui-admin-vue3
文档版本 v1.0
编写日期 2024-12-19
文档状态 ✅ 已完成
6.0.0.0.3 目录
6.0.0.0.4 1. 部署概述

福建水务业务系统采用集中化部署模式,基于集团私有云环境进行部署,构建高可用、可扩展的系统架构,满足集团及下属各水务公司的业务需求。

6.0.0.0.5 1.1 部署目标
6.0.0.0.6 1.2 部署原则
6.0.0.0.7 2. 部署架构
6.0.0.0.8 2.1 总体部署架构

福建水务业务系统采用三层架构部署:

系统部署采用集群模式,各层均部署多个节点,实现高可用和负载均衡。

6.0.0.0.9 2.2 生产环境部署架构

生产环境采用双机房部署方案,包括主生产环境和灾备环境:

6.0.0.0.10 2.2.1 主生产环境

主生产环境部署在集团主数据中心,包括:

6.0.0.0.11 2.2.2 灾备环境

灾备环境部署在集团备用数据中心,包括:

6.0.0.0.12 2.3 测试环境部署架构

测试环境部署在集团测试中心,用于系统测试和验证,包括:

6.0.0.0.13 2.4 开发环境部署架构

开发环境部署在开发中心,用于系统开发和集成测试,包括:

6.0.0.0.14 3. 服务器配置
6.0.0.0.15 3.1 硬件配置要求
6.0.0.0.16 3.1.1 负载均衡服务器
6.0.0.0.17 3.1.2 Web服务器
6.0.0.0.18 3.1.3 应用服务器
6.0.0.0.19 3.1.4 数据库服务器
6.0.0.0.20 3.1.5 文件服务器
6.0.0.0.21 3.1.6 缓存服务器
6.0.0.0.22 3.2 软件配置要求
6.0.0.0.23 3.2.1 操作系统
6.0.0.0.24 3.2.2 数据库
6.0.0.0.25 3.2.3 应用服务器
6.0.0.0.26 3.2.4 缓存服务器
6.0.0.0.27 3.2.5 中间件
6.0.0.0.28 3.2.6 前端环境
6.0.0.0.29 4. 网络架构
6.0.0.0.30 4.1 网络拓扑

福建水务业务系统网络架构采用三层网络结构:

6.0.0.0.31 4.2 网络安全区域划分

网络安全区域划分为以下几个区域:

6.0.0.0.32 4.3 网络带宽配置
6.0.0.0.33 5. 安全设计
6.0.0.0.34 5.1 网络安全
6.0.0.0.35 5.1.1 边界安全
6.0.0.0.36 5.1.2 内网安全
6.0.0.0.37 5.2 系统安全
6.0.0.0.38 5.2.1 主机安全
6.0.0.0.39 5.2.2 应用安全
6.0.0.0.40 5.3 数据安全
6.0.0.0.41 5.3.1 数据存储安全
6.0.0.0.42 5.3.2 数据备份与恢复
6.0.0.0.43 6. 部署流程
6.0.0.0.44 6.1 部署准备
6.0.0.0.45 6.2 应用部署
6.0.0.0.46 6.2.1 数据库部署
6.0.0.0.47 6.2.2 应用服务部署
6.0.0.0.48 6.2.3 Web服务部署
6.0.0.0.49 6.3 系统联调
6.0.0.0.50 6.4 系统上线
6.0.0.0.51 7. 监控与运维
6.0.0.0.52 7.1 监控系统
6.0.0.0.53 7.1.1 基础设施监控
6.0.0.0.54 7.1.2 应用监控
6.0.0.0.55 7.1.3 数据库监控
6.0.0.0.56 7.2 运维管理
6.0.0.0.57 7.2.1 日常运维
6.0.0.0.58 7.2.2 变更管理
6.0.0.0.59 7.2.3 故障管理
6.0.0.0.60 7.2.4 应急预案
6.0.0.0.61 8. 容器化部署方案
6.0.0.0.62 8.1 Docker Compose部署
6.0.0.0.63 8.1.1 完整部署配置
##### 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:
6.0.0.0.64 8.1.2 后端应用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"]
6.0.0.0.65 8.1.3 前端应用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;"]
6.0.0.0.66 8.2 Docker Compose高级配置
6.0.0.0.67 8.2.1 生产环境配置优化

Docker Compose生产环境配置文件

##### 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
6.0.0.0.68 8.2.2 环境变量配置
##### .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
6.0.0.0.69 8.2.3 监控集成
##### 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:
6.0.0.0.70 8.3 自动化部署脚本
6.0.0.0.71 8.3.1 Docker部署脚本
#!/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"
6.0.0.0.72 8.3.2 生产环境部署脚本
#!/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"
6.0.0.0.73 8.4 持续集成/持续部署 (CI/CD)
6.0.0.0.74 8.4.1 GitHub Actions配置
##### .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流水线:持续集成和持续部署

6.1 这些配置都基于RuoYi-Vue-Pro框架的要求,提供了生产就绪的部署方案。

ewpage

7 第6部分:

7.0.0.0.1 福建水务营收系统安全设计文档
7.0.0.0.2 文档信息
项目信息 详情
项目名称 福建水务营收系统
文档类型 安全设计文档
技术框架 RuoYi-Vue-Pro + OpenGauss
文档版本 v1.0
编写日期 2024-12-19
文档状态 ✅ 已完成
7.0.0.0.3 目录
7.0.0.0.4 一、安全设计概述

福建水务营收系统安全设计严格按照《网络安全等级保护基本要求》第三级标准,结合水务行业特点和国产化要求,构建全方位、多层次的安全防护体系。

7.0.0.0.5 1.1 安全目标
7.0.0.0.6 1.2 安全原则
7.0.0.0.7 1.3 总体安全架构
graph TB
    subgraph "外部威胁"
        THREAT1[网络攻击]
        THREAT2[恶意软件]
        THREAT3[数据泄露]
        THREAT4[内部威胁]
    end
    
    subgraph "安全防护层"
        subgraph "边界安全"
            WAF[Web应用防火墙]
            FW[网络防火墙]
            IPS[入侵防护系统]
            VPN[VPN网关]
        end
        
        subgraph "应用安全"
            AUTH[身份认证]
            AUTHZ[访问控制]
            AUDIT[操作审计]
            ENCRYPT[数据加密]
        end
        
        subgraph "数据安全"
            TDE[透明数据加密]
            RLS[行级安全]
            MASK[数据脱敏]
            BACKUP[安全备份]
        end
        
        subgraph "运维安全"
            MONITOR[安全监控]
            LOG[日志分析]
            ALERT[告警响应]
            PATCH[安全更新]
        end
    end
    
    subgraph "核心资产"
        APP[水务营收系统]
        DB[OpenGauss数据库]
        FILE[文件存储]
        API[接口服务]
    end
    
    THREAT1 --> WAF
    THREAT2 --> FW
    THREAT3 --> IPS
    THREAT4 --> VPN
    
    WAF --> AUTH
    FW --> AUTHZ
    IPS --> AUDIT
    VPN --> ENCRYPT
    
    AUTH --> TDE
    AUTHZ --> RLS
    AUDIT --> MASK
    ENCRYPT --> BACKUP
    
    TDE --> MONITOR
    RLS --> LOG
    MASK --> ALERT
    BACKUP --> PATCH
    
    MONITOR --> APP
    LOG --> DB
    ALERT --> FILE
    PATCH --> API
7.0.0.0.8 二、等级保护三级安全设计
7.0.0.0.9 2.1 技术安全要求
7.0.0.0.10 2.1.1 安全通信网络

网络架构安全

graph TB
    subgraph "安全区域划分"
        DMZ[DMZ区<br/>Web服务器]
        APP_ZONE[应用区<br/>应用服务器]
        DB_ZONE[数据区<br/>数据库服务器]
        MGT_ZONE[管理区<br/>运维管理]
    end
    
    subgraph "边界防护"
        INTERNET[互联网]
        FW1[边界防火墙]
        FW2[内部防火墙]
        IDS[入侵检测系统]
    end
    
    subgraph "访问控制"
        VPN[VPN接入]
        JUMP[跳板机]
        BASTION[堡垒机]
    end
    
    INTERNET --> FW1
    FW1 --> DMZ
    DMZ --> FW2
    FW2 --> APP_ZONE
    APP_ZONE --> DB_ZONE
    
    VPN --> JUMP
    JUMP --> BASTION
    BASTION --> MGT_ZONE
    
    IDS --> DMZ
    IDS --> APP_ZONE

网络安全措施 - 网络边界部署防火墙,实现网络访问控制 - 重要网络设备和服务器前端部署网络入侵检测设备 - 网络分段部署,DMZ区、应用区、数据区物理隔离 - 关键网络设备提供双机热备功能 - 网络设备登录实现身份标识和鉴别

7.0.0.0.11 2.1.2 安全区域边界

区域边界防护 - 在网络边界部署防火墙设备,设置访问控制策略 - 在网络边界部署入侵检测设备,监控网络攻击行为 - 在应用层部署Web应用防火墙,防护Web应用攻击 - 对进出网络的数据流进行过滤和监控 - 建立网络访问控制策略,限制不必要的网络连接

7.0.0.0.12 2.1.3 安全计算环境

身份鉴别

graph LR
    subgraph "多因素认证"
        USER[用户] --> AUTH1[用户名密码]
        AUTH1 --> AUTH2[短信验证码]
        AUTH2 --> AUTH3[邮箱验证]
        AUTH3 --> TOKEN[JWT Token]
    end
    
    subgraph "认证集成"
        LDAP[LDAP认证]
        SSO[单点登录]
        OAUTH[OAuth2.0]
        SAML[SAML认证]
    end
    
    TOKEN --> LDAP
    TOKEN --> SSO
    TOKEN --> OAUTH
    TOKEN --> SAML

访问控制设计 - 实现基于角色的访问控制(RBAC) - 支持基于属性的访问控制(ABAC) - 实现最小权限原则 - 支持权限的动态调整和审批流程

7.0.0.0.13 2.2 管理安全要求
7.0.0.0.14 2.2.1 安全管理中心
7.0.0.0.15 2.2.2 安全管理制度
7.0.0.0.16 三、OpenGauss数据库安全
7.0.0.0.17 3.1 数据库安全架构
graph TB
    subgraph "OpenGauss安全特性"
        subgraph "身份认证"
            PWD[密码认证]
            CERT[证书认证]
            LDAP_AUTH[LDAP认证]
            KERBEROS[Kerberos认证]
        end
        
        subgraph "访问控制"
            RBAC_DB[基于角色的访问控制]
            RLS_DB[行级安全策略]
            CLS_DB[列级访问控制]
            SCHEMA[模式权限控制]
        end
        
        subgraph "数据加密"
            TDE_SM4[TDE透明加密<br/>SM4国密算法]
            SSL_SM[SSL传输加密<br/>SM2/SM3/SM4]
            FIELD_ENC[字段级加密]
            BACKUP_ENC[备份加密]
        end
        
        subgraph "审计监控"
            AUDIT_LOG[操作审计日志]
            LOGIN_LOG[登录审计]
            DDL_LOG[DDL操作记录]
            SECURITY_LOG[安全事件日志]
        end
    end
    
    PWD --> RBAC_DB
    CERT --> RLS_DB
    LDAP_AUTH --> CLS_DB
    KERBEROS --> SCHEMA
    
    RBAC_DB --> TDE_SM4
    RLS_DB --> SSL_SM
    CLS_DB --> FIELD_ENC
    SCHEMA --> BACKUP_ENC
    
    TDE_SM4 --> AUDIT_LOG
    SSL_SM --> LOGIN_LOG
    FIELD_ENC --> DDL_LOG
    BACKUP_ENC --> SECURITY_LOG
7.0.0.0.18 3.2 国产密码算法应用
7.0.0.0.19 3.2.1 传输加密
-- 配置国密SSL连接
ALTER SYSTEM SET ssl = on;
ALTER SYSTEM SET ssl_ciphers = 'SM4-GCM-SM3:SM4-CCM-SM3';
ALTER SYSTEM SET ssl_cert_file = 'server-sm2.crt';
ALTER SYSTEM SET ssl_key_file = 'server-sm2.key';
7.0.0.0.20 3.2.2 透明数据加密
-- 启用TDE透明数据加密,使用SM4算法
CREATE KEY ENCRYPTION KEY water_biz_kek 
WITH ALGORITHM = 'SM4-CTR', KEY_STORE = 'localkms';

-- 为敏感表启用加密
CREATE TABLE water_customer (
    id SERIAL PRIMARY KEY,
    customer_name VARCHAR(100) ENCRYPTED WITH (
        COLUMN_ENCRYPTION_KEY = water_biz_kek,
        ENCRYPTION_TYPE = DETERMINISTIC,
        ALGORITHM = 'SM4-CTR'
    ),
    id_card VARCHAR(18) ENCRYPTED WITH (
        COLUMN_ENCRYPTION_KEY = water_biz_kek,
        ENCRYPTION_TYPE = RANDOMIZED,
        ALGORITHM = 'SM4-CTR'
    )
);
7.0.0.0.21 3.3 行级安全策略
-- 创建多租户行级安全策略
CREATE ROW LEVEL SECURITY POLICY tenant_isolation_policy
ON water_customer
USING (tenant_id = current_setting('app.current_tenant_id')::bigint);

-- 启用行级安全
ALTER TABLE water_customer ENABLE ROW LEVEL SECURITY;

-- 创建数据访问角色
CREATE ROLE water_data_reader;
CREATE ROLE water_data_writer;

-- 配置列级权限
GRANT SELECT (id, customer_name, phone) ON water_customer TO water_data_reader;
GRANT ALL ON water_customer TO water_data_writer;
7.0.0.0.22 3.4 数据脱敏策略
-- 创建数据脱敏函数
CREATE OR REPLACE FUNCTION mask_phone(phone_num TEXT) 
RETURNS TEXT AS $$
BEGIN
    RETURN SUBSTRING(phone_num, 1, 3) || '****' || SUBSTRING(phone_num, 8, 4);
END;
$$ LANGUAGE plpgsql;

-- 创建脱敏视图
CREATE VIEW water_customer_masked AS
SELECT 
    id,
    customer_name,
    mask_phone(phone) as phone,
    LEFT(id_card, 6) || '********' || RIGHT(id_card, 4) as id_card_masked
FROM water_customer;

-- 授权普通用户只能访问脱敏视图
GRANT SELECT ON water_customer_masked TO water_normal_user;
7.0.0.0.23 四、应用系统安全
7.0.0.0.24 4.1 Spring Security安全配置
7.0.0.0.25 4.1.1 认证配置
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(prePostEnabled = true)
public class SecurityConfig {
    
    @Bean
    public PasswordEncoder passwordEncoder() {
        // 使用国密SM3哈希算法
        return new SM3PasswordEncoder();
    }
    
    @Bean
    public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter() {
        return new JwtAuthenticationTokenFilter();
    }
    
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http
            // CSRF防护
            .csrf(csrf -> csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()))
            // 请求授权
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/login", "/api/register").permitAll()
                .requestMatchers("/api/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
            )
            // JWT过滤器
            .addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class)
            // 会话管理
            .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .build();
    }
}
7.0.0.0.26 4.1.2 多因素认证
@Service
public class MFAService {
    
    @Autowired
    private SmsService smsService;
    
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    
    public boolean sendSmsCode(String phone) {
        String code = generateRandomCode();
        String key = "mfa:sms:" + phone;
        
        // 存储验证码,5分钟过期
        redisTemplate.opsForValue().set(key, code, Duration.ofMinutes(5));
        
        // 发送短信
        return smsService.send(phone, "您的验证码是:" + code + ",5分钟内有效。");
    }
    
    public boolean verifySmsCode(String phone, String code) {
        String key = "mfa:sms:" + phone;
        String storedCode = redisTemplate.opsForValue().get(key);
        
        if (storedCode != null && storedCode.equals(code)) {
            redisTemplate.delete(key);
            return true;
        }
        return false;
    }
}
7.0.0.0.27 4.2 数据传输安全
7.0.0.0.28 4.2.1 HTTPS配置
server:
  port: 8443
  ssl:
    enabled: true
    key-store: classpath:keystore/server.p12
    key-store-password: ${SSL_KEYSTORE_PASSWORD}
    key-store-type: PKCS12
    # 支持国密算法
    ciphers: SM4-GCM-SM3,SM4-CCM-SM3,ECDHE-SM2-WITH-SM4-SM3
    protocols: TLSv1.2,TLSv1.3
7.0.0.0.29 4.2.2 敏感数据加密
@Component
public class DataEncryptionService {
    
    private final SM4Cipher sm4Cipher = new SM4Cipher();
    
    public String encryptSensitiveData(String plaintext) {
        try {
            return sm4Cipher.encrypt(plaintext);
        } catch (Exception e) {
            throw new SecurityException("数据加密失败", e);
        }
    }
    
    public String decryptSensitiveData(String ciphertext) {
        try {
            return sm4Cipher.decrypt(ciphertext);
        } catch (Exception e) {
            throw new SecurityException("数据解密失败", e);
        }
    }
}
7.0.0.0.30 4.3 接口安全防护
7.0.0.0.31 4.3.1 接口签名验证
@Component
public class ApiSignatureValidator {
    
    public boolean validateSignature(HttpServletRequest request) {
        String timestamp = request.getHeader("X-Timestamp");
        String nonce = request.getHeader("X-Nonce");
        String signature = request.getHeader("X-Signature");
        String body = getRequestBody(request);
        
        // 检查时间戳,防止重放攻击
        if (isTimestampExpired(timestamp)) {
            return false;
        }
        
        // 生成签名
        String expectedSignature = generateSignature(timestamp, nonce, body);
        
        // 验证签名
        return signature.equals(expectedSignature);
    }
    
    private String generateSignature(String timestamp, String nonce, String body) {
        String message = timestamp + nonce + body;
        return SM3Utils.hash(message);
    }
}
7.0.0.0.32 4.3.2 接口限流防护
@Component
public class RateLimitService {
    
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    
    public boolean isAllowed(String key, int limit, Duration window) {
        String redisKey = "rate_limit:" + key;
        String current = redisTemplate.opsForValue().get(redisKey);
        
        if (current == null) {
            redisTemplate.opsForValue().set(redisKey, "1", window);
            return true;
        }
        
        int count = Integer.parseInt(current);
        if (count < limit) {
            redisTemplate.opsForValue().increment(redisKey);
            return true;
        }
        
        return false;
    }
}
7.0.0.0.33 五、网络安全设计
7.0.0.0.34 5.1 网络拓扑安全
graph TB
    subgraph "外网区域"
        INTERNET[互联网]
        CDN[CDN加速]
        DNS[DNS服务]
    end
    
    subgraph "边界防护"
        WAF[Web应用防火墙<br/>国产WAF产品]
        FW_BORDER[边界防火墙<br/>安全审计]
        IPS[入侵防护系统<br/>威胁检测]
        DPI[深度包检测<br/>流量分析]
    end
    
    subgraph "DMZ区域"
        LB[负载均衡器<br/>SSL卸载]
        WEB1[Web服务器1]
        WEB2[Web服务器2]
        PROXY[反向代理]
    end
    
    subgraph "内网安全"
        FW_INTERNAL[内部防火墙]
        VLAN_APP[应用VLAN]
        VLAN_DB[数据库VLAN]
        VLAN_MGT[管理VLAN]
    end
    
    subgraph "应用层"
        APP1[应用服务器1]
        APP2[应用服务器2]
        APP3[应用服务器3]
    end
    
    subgraph "数据层"
        DB_MASTER[OpenGauss主库]
        DB_SLAVE[OpenGauss从库]
        REDIS[Redis集群]
    end
    
    subgraph "管理层"
        JUMP[跳板机]
        MONITOR[监控服务器]
        LOG[日志服务器]
    end
    
    INTERNET --> CDN
    CDN --> DNS
    DNS --> WAF
    WAF --> FW_BORDER
    FW_BORDER --> IPS
    IPS --> DPI
    DPI --> LB
    
    LB --> WEB1
    LB --> WEB2
    WEB1 --> PROXY
    WEB2 --> PROXY
    
    PROXY --> FW_INTERNAL
    FW_INTERNAL --> VLAN_APP
    FW_INTERNAL --> VLAN_DB
    FW_INTERNAL --> VLAN_MGT
    
    VLAN_APP --> APP1
    VLAN_APP --> APP2
    VLAN_APP --> APP3
    
    VLAN_DB --> DB_MASTER
    VLAN_DB --> DB_SLAVE
    VLAN_DB --> REDIS
    
    VLAN_MGT --> JUMP
    VLAN_MGT --> MONITOR
    VLAN_MGT --> LOG
7.0.0.0.35 5.2 防火墙策略配置
7.0.0.0.36 5.2.1 边界防火墙策略
##### 允许HTTPS访问
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

##### 允许HTTP重定向到HTTPS
iptables -A INPUT -p tcp --dport 80 -j ACCEPT

##### 禁止直接数据库访问
iptables -A INPUT -p tcp --dport 5432 -s ! 192.168.1.0/24 -j DROP

##### 允许内网SSH管理
iptables -A INPUT -p tcp --dport 22 -s 192.168.100.0/24 -j ACCEPT

##### 拒绝其他所有入站连接
iptables -A INPUT -j DROP
7.0.0.0.37 5.2.2 应用层防火墙策略
##### 只允许来自DMZ区的连接
iptables -A INPUT -s 192.168.1.0/24 -j ACCEPT

##### 允许访问数据库
iptables -A OUTPUT -d 192.168.2.0/24 -p tcp --dport 5432 -j ACCEPT

##### 允许访问Redis
iptables -A OUTPUT -d 192.168.2.0/24 -p tcp --dport 6379 -j ACCEPT

##### 允许DNS查询
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT

##### 拒绝其他出站连接
iptables -A OUTPUT -j DROP
7.0.0.0.38 5.3 入侵检测与防护
7.0.0.0.39 5.3.1 IDS/IPS规则配置
##### Suricata规则示例
alert tcp any any -> $HOME_NET 443 (msg:"Suspicious HTTPS traffic"; \
    content:"POST"; http_method; content:"/api/admin"; http_uri; \
    threshold:type limit, track by_src, count 10, seconds 60; \
    sid:10001; rev:1;)

alert tcp any any -> $HOME_NET 5432 (msg:"Direct database access attempt"; \
    content:"SELECT"; content:"FROM"; distance:0; \
    sid:10002; rev:1;)

alert tcp any any -> $HOME_NET any (msg:"Brute force attack detected"; \
    flags:S; threshold:type threshold, track by_src, count 100, seconds 60; \
    sid:10003; rev:1;)
7.0.0.0.40 六、数据安全设计
7.0.0.0.41 6.1 数据分类分级
7.0.0.0.42 6.1.1 数据分类标准
graph TB
    subgraph "数据分类"
        TOP_SECRET[绝密级<br/>核心商业机密]
        SECRET[机密级<br/>重要业务数据]
        INTERNAL[内部级<br/>一般业务数据]
        PUBLIC[公开级<br/>公开业务数据]
    end
    
    subgraph "水务业务数据"
        CUSTOMER[客户身份信息<br/>机密级]
        METER[水表计量数据<br/>内部级]
        BILLING[收费账务数据<br/>机密级]
        REPORT[统计报表数据<br/>内部级]
        CONFIG[系统配置数据<br/>内部级]
        LOG[日志审计数据<br/>内部级]
    end
    
    subgraph "保护措施"
        ENC_HIGH[强加密<br/>SM4+数字签名]
        ENC_MID[加密存储<br/>SM4算法]
        ENC_LOW[访问控制<br/>权限管理]
        ENC_NONE[公开访问<br/>无特殊保护]
    end
    
    TOP_SECRET --> ENC_HIGH
    SECRET --> ENC_MID
    INTERNAL --> ENC_LOW
    PUBLIC --> ENC_NONE
    
    CUSTOMER --> SECRET
    BILLING --> SECRET
    METER --> INTERNAL
    REPORT --> INTERNAL
    CONFIG --> INTERNAL
    LOG --> INTERNAL
7.0.0.0.43 6.1.2 数据保护策略
-- 客户敏感信息表(机密级)
CREATE TABLE water_customer_sensitive (
    id SERIAL PRIMARY KEY,
    customer_id BIGINT NOT NULL,
    -- 身份证号:强加密存储
    id_card_encrypted VARCHAR(200) ENCRYPTED WITH (
        COLUMN_ENCRYPTION_KEY = customer_sensitive_key,
        ENCRYPTION_TYPE = RANDOMIZED,
        ALGORITHM = 'SM4-CTR'
    ),
    -- 银行卡号:强加密存储
    bank_account_encrypted VARCHAR(200) ENCRYPTED WITH (
        COLUMN_ENCRYPTION_KEY = customer_sensitive_key,
        ENCRYPTION_TYPE = RANDOMIZED,
        ALGORITHM = 'SM4-CTR'
    ),
    -- 手机号:确定性加密,支持查询
    phone_encrypted VARCHAR(200) ENCRYPTED WITH (
        COLUMN_ENCRYPTION_KEY = customer_sensitive_key,
        ENCRYPTION_TYPE = DETERMINISTIC,
        ALGORITHM = 'SM4-CTR'
    ),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 创建行级安全策略
CREATE POLICY customer_sensitive_policy ON water_customer_sensitive
FOR ALL TO water_customer_service_role
USING (
    customer_id IN (
        SELECT customer_id FROM water_customer 
        WHERE tenant_id = current_setting('app.current_tenant_id')::bigint
    )
);
7.0.0.0.44 6.2 数据备份与恢复安全
7.0.0.0.45 6.2.1 备份加密策略
#!/bin/bash
##### OpenGauss安全备份脚本

##### 设置备份参数
BACKUP_DIR="/backup/opengauss"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="water_biz_backup_${DATE}.tar.gz"
ENCRYPT_KEY="/etc/opengauss/backup_key.key"

##### 创建加密备份
gs_backup -D $GAUSSDATA -U gaussdb \
    --encrypt --encrypt-key-file=$ENCRYPT_KEY \
    --backup-format=tar \
    --backup-path=$BACKUP_DIR/$BACKUP_FILE

##### 验证备份完整性
openssl dgst -sm3 $BACKUP_DIR/$BACKUP_FILE > $BACKUP_DIR/$BACKUP_FILE.sm3

##### 安全传输到异地备份中心
rsync -avz --delete $BACKUP_DIR/ backup-server:/backup/remote/
7.0.0.0.46 6.2.2 数据恢复流程
-- 恢复前验证备份完整性
-- 1. 验证SM3摘要
-- 2. 解密备份文件
-- 3. 验证数据库结构
-- 4. 执行恢复操作

-- 创建恢复测试环境
CREATE DATABASE water_biz_recovery_test;

-- 恢复数据到测试环境
\c water_biz_recovery_test;
-- 执行恢复SQL脚本
\i /backup/water_biz_recovery.sql;

-- 验证数据完整性
SELECT COUNT(*) FROM water_customer;
SELECT COUNT(*) FROM water_meter_reading;
SELECT COUNT(*) FROM water_billing;

-- 验证加密数据
SELECT id, 
       pgp_sym_decrypt(id_card_encrypted, 'encryption_key') as id_card
FROM water_customer_sensitive LIMIT 1;
7.0.0.0.47 6.3 数据销毁与清理
7.0.0.0.48 6.3.1 安全数据销毁
-- 创建安全数据销毁函数
CREATE OR REPLACE FUNCTION secure_data_destroy(table_name TEXT, where_clause TEXT)
RETURNS BOOLEAN AS $$
DECLARE
    sql_cmd TEXT;
    affected_rows INTEGER;
BEGIN
    -- 构建删除SQL
    sql_cmd := 'DELETE FROM ' || table_name || ' WHERE ' || where_clause;
    
    -- 执行删除
    EXECUTE sql_cmd;
    GET DIAGNOSTICS affected_rows = ROW_COUNT;
    
    -- 记录审计日志
    INSERT INTO data_destroy_audit (
        table_name, where_clause, affected_rows, 
        operator, operation_time
    ) VALUES (
        table_name, where_clause, affected_rows,
        current_user, current_timestamp
    );
    
    -- 执行VACUUM清理物理空间
    EXECUTE 'VACUUM FULL ' || table_name;
    
    RETURN TRUE;
EXCEPTION
    WHEN OTHERS THEN
        RAISE EXCEPTION '数据销毁失败: %', SQLERRM;
        RETURN FALSE;
END;
$$ LANGUAGE plpgsql;

-- 示例:销毁3年前的历史数据
SELECT secure_data_destroy(
    'water_meter_reading_history',
    'reading_date < CURRENT_DATE - INTERVAL ''3 years'''
);
7.0.0.0.49 七、运维安全设计
7.0.0.0.50 7.1 安全监控体系
7.0.0.0.51 7.1.1 安全监控架构
graph TB
    subgraph "数据采集层"
        AGENT1[系统日志采集]
        AGENT2[应用日志采集]
        AGENT3[数据库日志采集]
        AGENT4[网络流量采集]
    end
    
    subgraph "数据处理层"
        KAFKA[消息队列<br/>Kafka集群]
        STREAM[流处理<br/>Flink/Storm]
        ETL[数据清洗<br/>Logstash]
    end
    
    subgraph "存储分析层"
        ES[Elasticsearch<br/>日志存储]
        SIEM[安全信息事件管理<br/>SIEM平台]
        AI[智能分析<br/>机器学习]
    end
    
    subgraph "可视化层"
        DASHBOARD[监控仪表盘<br/>Grafana]
        ALERT[告警系统<br/>AlertManager]
        REPORT[安全报告<br/>自动生成]
    end
    
    AGENT1 --> KAFKA
    AGENT2 --> KAFKA
    AGENT3 --> KAFKA
    AGENT4 --> KAFKA
    
    KAFKA --> STREAM
    STREAM --> ETL
    ETL --> ES
    
    ES --> SIEM
    SIEM --> AI
    AI --> DASHBOARD
    
    DASHBOARD --> ALERT
    ALERT --> REPORT
7.0.0.0.52 7.1.2 安全事件检测规则
##### 安全事件检测规则配置
security_rules:
  - name: "暴力破解检测"
    type: "authentication"
    condition: "failed_login_count > 5 in 5 minutes"
    severity: "high"
    action: ["block_ip", "send_alert"]
    
  - name: "异常数据访问"
    type: "data_access"
    condition: "query_count > 1000 in 1 minute"
    severity: "medium"
    action: ["rate_limit", "send_alert"]
    
  - name: "权限提升检测"
    type: "privilege_escalation"
    condition: "role_change to admin"
    severity: "critical"
    action: ["block_user", "send_alert", "create_incident"]
    
  - name: "异常时间访问"
    type: "abnormal_access"
    condition: "access_time between 22:00 and 06:00"
    severity: "medium"
    action: ["log_event", "send_alert"]
7.0.0.0.53 7.2 漏洞管理
7.0.0.0.54 7.2.1 漏洞扫描策略
#!/bin/bash
##### 系统漏洞扫描脚本

##### 扫描操作系统漏洞
nmap -sV --script vulners localhost

##### 扫描Web应用漏洞
nikto -h https://water.example.com -ssl

##### 扫描数据库漏洞
nmap -p 5432 --script pgsql-brute,pgsql-databases localhost

##### 生成漏洞报告
cat > vulnerability_report.html << EOF
<!DOCTYPE html>
<html>
<head>
    <title>安全漏洞扫描报告</title>
</head>
<body>
    <h1>福建水务营收系统漏洞扫描报告</h1>
    <p>扫描时间:$(date)</p>
    <h2>高危漏洞</h2>
    <pre>$(grep -i "high\|critical" scan_results.txt)</pre>
    <h2>中危漏洞</h2>
    <pre>$(grep -i "medium" scan_results.txt)</pre>
</body>
</html>
EOF
7.0.0.0.55 7.2.2 补丁管理流程
graph LR
    DISCOVER[漏洞发现] --> ASSESS[风险评估]
    ASSESS --> PLAN[补丁计划]
    PLAN --> TEST[测试验证]
    TEST --> DEPLOY[生产部署]
    DEPLOY --> VERIFY[部署验证]
    VERIFY --> DOCUMENT[文档记录]
    
    subgraph "评估标准"
        HIGH[高危<br/>24小时内]
        MEDIUM[中危<br/>7天内]
        LOW[低危<br/>30天内]
    end
    
    ASSESS --> HIGH
    ASSESS --> MEDIUM
    ASSESS --> LOW
7.0.0.0.56 7.3 应急响应预案
7.0.0.0.57 7.3.1 安全事件分级
级别 描述 响应时间 处理措施
P0 系统完全不可用,数据泄露 15分钟 立即启动应急预案,通知管理层
P1 核心功能受影响,安全风险高 30分钟 启动应急预案,组建应急小组
P2 部分功能受影响,安全风险中等 2小时 安排专人处理,定期汇报
P3 轻微影响,安全风险较低 8小时 正常工作时间处理
7.0.0.0.58 7.3.2 应急响应流程
graph TB
    INCIDENT[安全事件发生] --> DETECT[事件检测]
    DETECT --> REPORT[事件上报]
    REPORT --> ASSESS[影响评估]
    ASSESS --> RESPONSE[应急响应]
    
    subgraph "应急响应措施"
        ISOLATE[系统隔离]
        PRESERVE[证据保全]
        RECOVER[系统恢复]
        INVESTIGATE[调查分析]
    end
    
    subgraph "后续处理"
        LESSON[经验总结]
        IMPROVE[流程改进]
        TRAIN[培训加强]
        DOC[文档更新]
    end
    
    RESPONSE --> ISOLATE
    RESPONSE --> PRESERVE
    RESPONSE --> RECOVER
    RESPONSE --> INVESTIGATE
    
    INVESTIGATE --> LESSON
    LESSON --> IMPROVE
    IMPROVE --> TRAIN
    TRAIN --> DOC
7.0.0.0.59 八、安全管理制度
7.0.0.0.60 8.1 安全组织架构
7.0.0.0.61 8.1.1 安全管理组织
graph TB
    CEO[总经理<br/>安全最高责任人]
    CISO[信息安全负责人<br/>CISO]
    
    subgraph "安全管理委员会"
        IT_DIR[IT总监]
        SECURITY_DIR[安全总监]
        COMPLIANCE[合规负责人]
        LEGAL[法务负责人]
    end
    
    subgraph "安全执行团队"
        SEC_ADMIN[安全管理员]
        SYS_ADMIN[系统管理员]
        DBA[数据库管理员]
        NET_ADMIN[网络管理员]
    end
    
    subgraph "业务安全责任人"
        BUS_OWNER[业务负责人]
        DATA_OWNER[数据负责人]
        USER_ADMIN[用户管理员]
    end
    
    CEO --> CISO
    CISO --> IT_DIR
    CISO --> SECURITY_DIR
    CISO --> COMPLIANCE
    CISO --> LEGAL
    
    IT_DIR --> SEC_ADMIN
    IT_DIR --> SYS_ADMIN
    IT_DIR --> DBA
    IT_DIR --> NET_ADMIN
    
    SECURITY_DIR --> BUS_OWNER
    SECURITY_DIR --> DATA_OWNER
    SECURITY_DIR --> USER_ADMIN
7.0.0.0.62 8.2 安全管理制度
7.0.0.0.63 8.2.1 人员安全管理
7.0.0.0.64 8.2.2 系统建设安全管理
7.0.0.0.65 8.2.3 系统运维安全管理
7.0.0.0.66 8.3 合规管理
7.0.0.0.67 8.3.1 法律法规合规
7.0.0.0.68 8.3.2 行业标准合规
7.0.0.0.69 8.3.3 合规检查清单

7.0.0.0.70 总结

福建水务营收系统安全设计严格按照等级保护三级要求,结合OpenGauss数据库的安全特性,建立了全方位、多层次的安全防护体系。通过技术防护、管理制度、人员培训等多重措施,确保系统安全稳定运行,满足水务行业的安全合规要求。

本安全设计方案的核心特点: 1. 国产化安全:采用OpenGauss数据库和国密算法 2. 纵深防御:网络、应用、数据多层安全防护 3. 合规导向:严格按照等保三级标准设计 4. 持续改进:建立安全监控和应急响应机制 5. 管理规范:完善的安全管理制度和流程 —