From 67db982cfa99c75ef79ed1115db4f8d52b6d8f4b Mon Sep 17 00:00:00 2001 From: tangweijie <877588133@qq.com> Date: Tue, 10 Jun 2025 15:34:35 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=A6=8F=E5=BB=BA=E6=B0=B4?= =?UTF-8?q?=E5=8A=A1=E8=90=A5=E6=94=B6=E7=B3=BB=E7=BB=9F=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E6=96=87=E6=A1=A3=EF=BC=8C=E7=AE=80=E5=8C=96?= =?UTF-8?q?=E5=A4=9A=E4=B8=AA=E6=96=87=E6=A1=A3=E4=B8=AD=E7=9A=84=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E7=A4=BA=E4=BE=8B=EF=BC=8C=E4=BF=9D=E6=8C=81=E6=A6=82?= =?UTF-8?q?=E8=A6=81=E8=AE=BE=E8=AE=A1=E7=9A=84=E6=8A=BD=E8=B1=A1=E5=B1=82?= =?UTF-8?q?=E6=AC=A1=EF=BC=8C=E6=8F=90=E5=8D=87=E6=96=87=E6=A1=A3=E5=8F=AF?= =?UTF-8?q?=E8=AF=BB=E6=80=A7=E5=92=8C=E4=B8=80=E8=87=B4=E6=80=A7=E3=80=82?= =?UTF-8?q?=E5=90=8C=E6=97=B6=EF=BC=8C=E6=9B=B4=E6=96=B0=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=E8=BF=9B=E5=BA=A6=E6=96=87=E6=A1=A3=EF=BC=8C=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E6=96=87=E6=A1=A3=E4=BC=98=E5=8C=96=E5=92=8C=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E7=AE=80=E5=8C=96=E7=9A=84=E8=BF=9B=E5=B1=95=EF=BC=8C=E7=A1=AE?= =?UTF-8?q?=E4=BF=9D=E6=89=80=E6=9C=89=E6=96=87=E6=A1=A3=E7=AC=A6=E5=90=88?= =?UTF-8?q?=E7=94=B2=E6=96=B9A=E7=BA=A7=E4=BA=A4=E4=BB=98=E6=A0=87?= =?UTF-8?q?=E5=87=86=E3=80=82=E8=B0=83=E6=95=B4=E6=A8=A1=E5=9D=97=E8=AE=BE?= =?UTF-8?q?=E8=AE=A1=E6=96=87=E6=A1=A3=E5=92=8C=E6=8E=A5=E5=8F=A3=E8=AE=BE?= =?UTF-8?q?=E8=AE=A1=E6=96=87=E6=A1=A3=E7=9A=84=E7=8A=B6=E6=80=81=E4=B8=BA?= =?UTF-8?q?=E5=B7=B2=E5=AE=8C=E6=88=90=EF=BC=8C=E5=AE=8C=E6=88=90=E5=BA=A6?= =?UTF-8?q?=E6=8F=90=E5=8D=87=E8=87=B3100%=EF=BC=8C=E8=B4=A8=E9=87=8F?= =?UTF-8?q?=E8=AF=84=E7=BA=A7=E8=B0=83=E6=95=B4=E4=B8=BAA=E7=BA=A7?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- project_progress.md | 9 +- water_biz_interface_design.md | 201 ++------------- water_biz_module_design.md | 373 +++++++++------------------- water_biz_security_design.md | 182 +++----------- water_biz_system_architecture.md | 404 ++++--------------------------- 5 files changed, 217 insertions(+), 952 deletions(-) diff --git a/project_progress.md b/project_progress.md index 563463f..cf06e05 100644 --- a/project_progress.md +++ b/project_progress.md @@ -18,12 +18,12 @@ | 文档名称 | 状态 | 完成度 | 质量评级 | 最后更新 | 备注 | |---------|------|--------|----------|----------|------| | `water_biz_overview_design.md` | ✅ 已完成 | 100% | A级 | 2024-12-19 | 新增引言文档,包含编写目的、背景、定义等 | -| `water_biz_system_architecture.md` | ✅ 已完成 | 100% | A级 | 2024-12-19 | 已全面适配OpenGauss,架构图完整 | -| `water_biz_module_design.md` | ✅ 已完成 | 100% | A级 | 2024-12-19 | 已完成代码示例优化,符合概要设计标准 | +| `water_biz_system_architecture.md` | ✅ 已完成 | 100% | A级 | 2024-12-19 | 已简化配置代码,突出架构设计要点 | +| `water_biz_module_design.md` | ✅ 已完成 | 100% | A级 | 2024-12-19 | 已简化代码示例,符合概要设计抽象层次 | | `water_biz_database_design.md` | ✅ 已完成 | 100% | A+级 | 2024-12-19 | 已适配OpenGauss,完整DDL和安全设计 | -| `water_biz_interface_design.md` | ✅ 已完成 | 100% | A级 | 2024-12-19 | 已补充详细接口参数、代码示例和安全设计 | +| `water_biz_interface_design.md` | ✅ 已完成 | 100% | A级 | 2024-12-19 | 已简化代码示例,保持接口设计抽象层次 | | `water_biz_deployment_design.md` | ✅ 已完成 | 100% | A级 | 2024-12-19 | 已适配OpenGauss,专注Docker Compose部署 | -| `water_biz_security_design.md` | ✅ 已完成 | 100% | A级 | 2024-12-19 | 等保三级安全设计,基于OpenGauss | +| `water_biz_security_design.md` | ✅ 已完成 | 100% | A级 | 2024-12-19 | 已简化代码示例,突出安全设计要点 | ### 补充文档 (可选交付) @@ -126,6 +126,7 @@ | 2024-12-19 | 快速导出工具 | 创建快速统一导出工具quick_unified_export.sh | 解决统一导出工具卡住问题,稳定高效 | 正面影响,完美解决所有问题 | | 2024-12-19 | 分离文档导出 | 修改unified_export.sh支持分离文档导出,创建manage_separated_docs.sh管理工具 | 用户需求:将每个文档分别导出为不同格式,而不是合并成一个大文档 | 正面影响,提供更灵活的文档导出选项 | | 2024-12-19 | 新增引言文档 | 创建water_biz_overview_design.md引言文档 | 用户需求:添加标准的第一章内容(编写目的、背景、定义、参考资料) | 正面影响,完善文档体系结构 | +| 2024-12-19 | 代码简化优化 | 删除文档中过于详细的代码示例,保持概要设计抽象层次 | 用户反馈:删除过多详细的代码 | 正面影响,符合概要设计标准,提升文档可读性 | ## 项目完成总结 diff --git a/water_biz_interface_design.md b/water_biz_interface_design.md index c75f639..b7c527e 100644 --- a/water_biz_interface_design.md +++ b/water_biz_interface_design.md @@ -123,54 +123,12 @@ 记录类型(1位) + 客户号(12位) + 银行账号(20位) + 扣款金额(12位) + 处理状态(1位) + 银行流水号(20位) + 处理时间(14位) + 失败原因(20位) ``` -**Java实现示例**: -```java -@Service -public class BankDeductServiceImpl implements BankDeductService { - - @Resource - private SftpTemplate sftpTemplate; - @Resource - private BillService billService; - - @Scheduled(cron = "0 0 2 * * ?") - public void generateDeductFile() { - LocalDate deductDate = LocalDate.now(); - - // 获取待代扣账单 - List 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 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(); - } -} -``` +**代扣文件生成流程**: +1. 每日凌晨2点自动生成代扣文件 +2. 查询当日待代扣账单数据 +3. 按银行要求格式生成文件内容 +4. 通过SFTP上传至银行服务器 +5. 记录文件生成和上传日志 #### 银行实时缴费接口 @@ -253,45 +211,12 @@ public class BankDeductServiceImpl implements BankDeductService { } ``` -**Java实现示例**: -```java -@Service -public class AlipayServiceImpl implements AlipayService { - - @Resource - private AlipayClient alipayClient; - - @Override - public AlipayPaymentRespVO createPayment(AlipayPaymentReqVO request) { - AlipayTradePrecreateRequest alipayRequest = new AlipayTradePrecreateRequest(); - alipayRequest.setNotifyUrl("https://water.example.com/api/payment/alipay/notify"); - - AlipayTradePrecreateModel model = new AlipayTradePrecreateModel(); - model.setOutTradeNo(request.getPaymentCode()); - model.setTotalAmount(request.getTotalAmount().toString()); - model.setSubject("水费缴费"); - model.setBody("账单号:" + String.join(",", request.getBillCodes())); - model.setTimeoutExpress("30m"); - - alipayRequest.setBizModel(model); - - try { - AlipayTradePrecreateResponse response = alipayClient.execute(alipayRequest); - if (response.isSuccess()) { - return AlipayPaymentRespVO.builder() - .paymentCode(request.getPaymentCode()) - .qrCode(response.getQrCode()) - .outTradeNo(response.getOutTradeNo()) - .build(); - } else { - throw new BizException(ALIPAY_PAY_FAILED, response.getSubMsg()); - } - } catch (AlipayApiException e) { - throw new BizException(ALIPAY_PAY_ERROR, e.getErrMsg()); - } - } -} -``` +**支付宝支付集成流程**: +1. 调用支付宝预创建接口生成支付二维码 +2. 前端展示二维码供用户扫码支付 +3. 支付完成后支付宝发送异步通知 +4. 系统验证通知签名并更新订单状态 +5. 记录支付日志和账务处理 ### 微信支付接口对接 @@ -494,34 +419,10 @@ public class CustomerController { } ``` -**Service层代码示例**: -```java -@Service -@Validated -public class CustomerServiceImpl implements CustomerService { - - @Resource - private CustomerMapper customerMapper; - - @Override - public Long createCustomer(CustomerSaveReqVO createReqVO) { - // 校验客户编号唯一性 - validateCustomerCodeUnique(createReqVO.getCustomerCode()); - - // 创建客户 - CustomerDO customer = BeanUtils.toBean(createReqVO, CustomerDO.class); - customerMapper.insert(customer); - return customer.getId(); - } - - private void validateCustomerCodeUnique(String customerCode) { - CustomerDO existCustomer = customerMapper.selectByCustomerCode(customerCode); - if (existCustomer != null) { - throw exception(CUSTOMER_CODE_DUPLICATE); - } - } -} -``` +**客户管理服务实现要点**: +- 校验客户编号唯一性 +- 数据对象转换和持久化 +- 业务异常处理和日志记录 ### 水表管理API接口 @@ -563,27 +464,10 @@ public class CustomerServiceImpl implements CustomerService { } ``` -**Controller代码示例**: -```java -@RestController -@RequestMapping("/admin-api/water/meter") -@Tag(name = "管理后台 - 水表管理") -@Validated -public class MeterController { - - @Resource - private MeterService meterService; - - @GetMapping("/{id}") - @Operation(summary = "获得水表") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('water:meter:query')") - public CommonResult getMeter(@PathVariable("id") Long id) { - MeterDO meter = meterService.getMeter(id); - return success(BeanUtils.toBean(meter, MeterRespVO.class)); - } -} -``` +**水表管理控制器要点**: +- 支持权限控制和参数校验 +- 标准的RESTful接口设计 +- 统一的响应格式和异常处理 #### 抄表记录创建接口 @@ -615,46 +499,11 @@ public class MeterController { } ``` -**Service层实现示例**: -```java -@Service -@Validated -public class MeterReadingServiceImpl implements MeterReadingService { - - @Resource - private MeterReadingMapper readingMapper; - @Resource - private MeterService meterService; - - @Override - @Transactional(rollbackFor = Exception.class) - public Long createReading(MeterReadingSaveReqVO createReqVO) { - // 校验水表存在性 - MeterDO meter = meterService.validateMeterExists(createReqVO.getMeterId()); - - // 校验读数合理性 - validateReadingValue(createReqVO.getMeterId(), createReqVO.getReadingValue()); - - // 创建抄表记录 - MeterReadingDO reading = BeanUtils.toBean(createReqVO, MeterReadingDO.class); - reading.setReadingCode(generateReadingCode()); - reading.setCustomerId(meter.getCustomerId()); - - // 计算用水量 - BigDecimal waterUsage = calculateWaterUsage(meter.getCurrentReading(), - createReqVO.getReadingValue()); - reading.setWaterUsage(waterUsage); - - readingMapper.insert(reading); - - // 更新水表当前读数 - meterService.updateCurrentReading(createReqVO.getMeterId(), - createReqVO.getReadingValue()); - - return reading.getId(); - } -} -``` +**抄表记录服务实现要点**: +- 事务控制确保数据一致性 +- 水表存在性和读数合理性校验 +- 自动生成抄表编号和客户关联 +- 计算用水量并更新水表当前读数 #### 抄表数据批量导入接口 diff --git a/water_biz_module_design.md b/water_biz_module_design.md index 40d8a08..6592021 100644 --- a/water_biz_module_design.md +++ b/water_biz_module_design.md @@ -14,84 +14,82 @@ - [福建水务营收系统模块功能设计文档](#福建水务营收系统模块功能设计文档) - [文档信息](#文档信息) - [目录](#目录) - - [一、系统整体架构](#一系统整体架构) - - [1.1 系统架构图](#11-系统架构图) - - [1.2 技术架构图](#12-技术架构图) - - [1.3 业务架构图](#13-业务架构图) - - [二、统一平台](#二统一平台) - - [2.1 单点登录](#21-单点登录) - - [2.2 系统管理](#22-系统管理) - - [三、营收系统](#三营收系统) - - [3.1 系统管理](#31-系统管理) - - [3.2 抄表开账](#32-抄表开账) - - [3.2.1 业务流程图](#321-业务流程图) - - [3.2.2 主要功能](#322-主要功能) - - [3.2.3 核心接口定义](#323-核心接口定义) - - [3.2.4 前端界面设计](#324-前端界面设计) - - [3.3 收费管理](#33-收费管理) - - [3.3.1 业务流程图](#331-业务流程图) - - [3.3.2 主要功能](#332-主要功能) - - [3.3.3 核心接口定义](#333-核心接口定义) - - [3.4 账务处理](#34-账务处理) - - [3.4.1 业务流程图](#341-业务流程图) - - [3.4.2 主要功能](#342-主要功能) - - [3.4.3 核心接口定义](#343-核心接口定义) - - [3.5 发票管理](#35-发票管理) - - [3.5.1 业务流程图](#351-业务流程图) - - [3.5.2 核心接口定义](#352-核心接口定义) - - [3.6 代收业务](#36-代收业务) - - [3.7 环卫系统](#37-环卫系统) - - [3.8 业务工单](#38-业务工单) - - [四、表务系统](#四表务系统) - - [4.1 表务工单](#41-表务工单) - - [4.2 表务仓库](#42-表务仓库) - - [4.3 水表参数与基础信息](#43-水表参数与基础信息) - - [4.4 物联网对接与数据同步](#44-物联网对接与数据同步) - - [五、报装系统](#五报装系统) - - [5.1 报装流程](#51-报装流程) - - [5.2 一户一表管理](#52-一户一表管理) - - [六、客户服务](#六客户服务) - - [6.1 微信、支付宝服务窗](#61-微信支付宝服务窗) - - [6.2 历史账单](#62-历史账单) - - [6.3 电子发票](#63-电子发票) - - [6.4 营业网点](#64-营业网点) - - [6.5 账户流水](#65-账户流水) - - [6.6 微网厅](#66-微网厅) - - [七、系统配置](#七系统配置) - - [7.1 水表参数](#71-水表参数) - - [7.2 地址参数](#72-地址参数) - - [7.3 价格体系](#73-价格体系) - - [7.4 基本配置](#74-基本配置) - - [7.5 催缴管理](#75-催缴管理) - - [7.6 用户权限](#76-用户权限) - - [7.7 定时任务](#77-定时任务) - - [八、系统接口](#八系统接口) - - [8.1 银行接口](#81-银行接口) - - [8.2 支付宝/微信接口](#82-支付宝微信接口) - - [8.3 短信接口](#83-短信接口) - - [8.4 集抄系统接口](#84-集抄系统接口) - - [8.5 政务系统接口](#85-政务系统接口) - - [8.6 消火栓系统接口](#86-消火栓系统接口) - - [8.7 其他系统对接](#87-其他系统对接) - - [九、统计分析](#九统计分析) - - [9.1 报表查询](#91-报表查询) - - [9.2 欠费查询](#92-欠费查询) - - [9.3 缴费记录](#93-缴费记录) - - [9.4 用水分析](#94-用水分析) - - [十、工程管理](#十工程管理) - - [10.1 工程申请](#101-工程申请) - - [10.2 工程施工](#102-工程施工) - - [10.3 工程验收](#103-工程验收) - - [10.4 工程查询](#104-工程查询) - - [十一、抄表APP](#十一抄表app) - - [11.1 首页功能](#111-首页功能) - - [11.2 抄表功能](#112-抄表功能) - - [11.3 工单管理](#113-工单管理) - - [十二、接口服务](#十二接口服务) - - [12.1 API市场](#121-api市场) - - [12.2 API管理](#122-api管理) - - [12.3 接口权限管理](#123-接口权限管理) - - [12.4 系统对外接口](#124-系统对外接口) + - [系统整体架构](#系统整体架构) + - [系统架构图](#系统架构图) + - [技术架构图](#技术架构图) + - [业务架构图](#业务架构图) + - [统一平台](#统一平台) + - [单点登录](#单点登录) + - [系统管理](#系统管理) + - [营收系统](#营收系统) + - [系统管理](#系统管理-1) + - [抄表开账](#抄表开账) + - [业务流程图](#业务流程图) + - [主要功能](#主要功能) + - [核心接口定义](#核心接口定义) + - [前端界面设计](#前端界面设计) + - [收费管理](#收费管理) + - [业务流程图](#业务流程图-1) + - [主要功能](#主要功能-1) + - [核心接口定义](#核心接口定义-1) + - [主要功能](#主要功能-2) + - [核心接口定义](#核心接口定义-2) + - [发票管理](#发票管理) + - [业务流程图](#业务流程图-2) + - [核心接口定义](#核心接口定义-3) + - [代收业务](#代收业务) + - [环卫系统](#环卫系统) + - [业务工单](#业务工单) + - [表务系统](#表务系统) + - [表务工单](#表务工单) + - [表务仓库](#表务仓库) + - [水表参数与基础信息](#水表参数与基础信息) + - [物联网对接与数据同步](#物联网对接与数据同步) + - [报装系统](#报装系统) + - [报装流程](#报装流程) + - [一户一表管理](#一户一表管理) + - [客户服务](#客户服务) + - [微信、支付宝服务窗](#微信支付宝服务窗) + - [历史账单](#历史账单) + - [电子发票](#电子发票) + - [营业网点](#营业网点) + - [账户流水](#账户流水) + - [微网厅](#微网厅) + - [系统配置](#系统配置) + - [水表参数](#水表参数) + - [地址参数](#地址参数) + - [价格体系](#价格体系) + - [基本配置](#基本配置) + - [催缴管理](#催缴管理) + - [用户权限](#用户权限) + - [定时任务](#定时任务) + - [系统接口](#系统接口) + - [银行接口](#银行接口) + - [支付宝/微信接口](#支付宝微信接口) + - [短信接口](#短信接口) + - [集抄系统接口](#集抄系统接口) + - [政务系统接口](#政务系统接口) + - [消火栓系统接口](#消火栓系统接口) + - [其他系统对接](#其他系统对接) + - [统计分析](#统计分析) + - [报表查询](#报表查询) + - [欠费查询](#欠费查询) + - [缴费记录](#缴费记录) + - [用水分析](#用水分析) + - [工程管理](#工程管理) + - [工程申请](#工程申请) + - [工程施工](#工程施工) + - [工程验收](#工程验收) + - [工程查询](#工程查询) + - [抄表APP](#抄表app) + - [首页功能](#首页功能) + - [抄表功能](#抄表功能) + - [工单管理](#工单管理) + - [接口服务](#接口服务) + - [API市场](#api市场) + - [API管理](#api管理) + - [接口权限管理](#接口权限管理) + - [系统对外接口](#系统对外接口) - [系统集成架构](#系统集成架构) - [前后端集成架构](#前后端集成架构) - [技术栈整合方案](#技术栈整合方案) @@ -498,29 +496,13 @@ flowchart TD #### 核心接口定义 **抄表管理主要接口**: -```java -@RestController -@RequestMapping("/admin-api/water/reading") -@Tag(name = "管理后台 - 抄表管理") -public class MeterReadingController { - - @PostMapping("/create") - @Operation(summary = "创建抄表记录") - public CommonResult createReading(@Valid @RequestBody MeterReadingSaveReqVO createReqVO); - - @PostMapping("/batch-create") - @Operation(summary = "批量创建抄表记录") - public CommonResult batchCreateReading(@Valid @RequestBody MeterReadingBatchReqVO batchReqVO); - - @PostMapping("/review") - @Operation(summary = "抄表数据复核") - public CommonResult reviewReading(@Valid @RequestBody MeterReadingReviewReqVO reviewReqVO); - - @PostMapping("/generate-bill") - @Operation(summary = "生成账单") - public CommonResult generateBill(@Valid @RequestBody ReadingBillReqVO reqVO); -} -``` + +| 接口名称 | 请求方式 | 功能描述 | +|---------|---------|---------| +| `/admin-api/water/reading/create` | POST | 创建抄表记录 | +| `/admin-api/water/reading/batch-create` | POST | 批量创建抄表记录 | +| `/admin-api/water/reading/review` | POST | 抄表数据复核 | +| `/admin-api/water/reading/generate-bill` | POST | 生成账单 | **接口设计要点**: - 遵循RESTful设计规范,统一的请求响应格式 @@ -530,58 +512,12 @@ public class MeterReadingController { #### 前端界面设计 -**抄表管理页面结构**: -```vue - -``` +**页面组件结构**: +- 查询条件区域:抄表日期范围选择、抄表状态筛选 +- 操作按钮区域:新增抄表、批量抄表、数据导出 +- 数据表格区域:抄表记录列表展示和操作 **前端页面功能特性**: - 响应式设计:基于Element Plus的现代化UI组件 @@ -671,29 +607,13 @@ flowchart TD #### 核心接口定义 **缴费管理主要接口**: -```java -@RestController -@RequestMapping("/admin-api/water/payment") -@Tag(name = "管理后台 - 缴费管理") -public class PaymentController { - - @PostMapping("/create") - @Operation(summary = "创建缴费记录") - public CommonResult createPayment(@Valid @RequestBody PaymentCreateReqVO createReqVO); - - @PostMapping("/cash-payment") - @Operation(summary = "现金缴费") - public CommonResult cashPayment(@Valid @RequestBody CashPaymentReqVO cashReqVO); - - @PostMapping("/online-payment") - @Operation(summary = "在线支付") - public CommonResult onlinePayment(@Valid @RequestBody OnlinePaymentReqVO onlineReqVO); - - @PostMapping("/prepaid-payment") - @Operation(summary = "预存款缴费") - public CommonResult prepaidPayment(@Valid @RequestBody PrepaidPaymentReqVO prepaidReqVO); -} -``` + +| 接口名称 | 请求方式 | 功能描述 | +|---------|---------|---------| +| `/admin-api/water/payment/create` | POST | 创建缴费记录 | +| `/admin-api/water/payment/cash-payment` | POST | 现金缴费 | +| `/admin-api/water/payment/online-payment` | POST | 在线支付 | +| `/admin-api/water/payment/prepaid-payment` | POST | 预存款缴费 | **接口设计特点**: - 支持多种缴费方式:现金、银行卡、在线支付、预存款 @@ -704,48 +624,12 @@ public class PaymentController { #### 前端界面设计 -**缴费管理页面结构**: -```vue - -``` +**页面组件结构**: +- 客户查询区域:客户编号输入、客户姓名输入 +- 账单信息区域:待缴费账单列表展示和选择 +- 缴费操作区域:金额统计和多种缴费方式选择 ### 账务处理 @@ -811,29 +695,13 @@ flowchart TD #### 核心接口定义 -```java -@RestController -@RequestMapping("/admin-api/water/account") -@Tag(name = "管理后台 - 账务处理") -@Validated -public class AccountProcessController { - - @PostMapping("/adjust") - @Operation(summary = "账务调整") - @PreAuthorize("@ss.hasPermission('water:account:adjust')") - public CommonResult adjustAccount(@Valid @RequestBody AccountAdjustReqVO adjustReqVO); - - @PostMapping("/refund") - @Operation(summary = "退款处理") - @PreAuthorize("@ss.hasPermission('water:account:refund')") - public CommonResult processRefund(@Valid @RequestBody RefundProcessReqVO refundReqVO); - - @PostMapping("/write-off") - @Operation(summary = "销账处理") - @PreAuthorize("@ss.hasPermission('water:account:write-off')") - public CommonResult writeOffAccount(@Valid @RequestBody WriteOffReqVO writeOffReqVO); -} -``` +**账务处理主要接口**: + +| 接口名称 | 请求方式 | 功能描述 | +|---------|---------|---------| +| `/admin-api/water/account/adjust` | POST | 账务调整 | +| `/admin-api/water/account/refund` | POST | 退款处理 | +| `/admin-api/water/account/write-off` | POST | 销账处理 | ### 发票管理 @@ -869,26 +737,13 @@ flowchart TD #### 核心接口定义 -```java -@RestController -@RequestMapping("/admin-api/water/invoice") -@Tag(name = "管理后台 - 发票管理") -@Validated -public class InvoiceController { - - @PostMapping("/generate") - @Operation(summary = "生成发票") - public CommonResult generateInvoice(@Valid @RequestBody InvoiceGenerateReqVO generateReqVO); - - @PostMapping("/print") - @Operation(summary = "打印发票") - public CommonResult printInvoice(@Valid @RequestBody InvoicePrintReqVO printReqVO); - - @PostMapping("/cancel") - @Operation(summary = "发票作废") - public CommonResult cancelInvoice(@Valid @RequestBody InvoiceCancelReqVO cancelReqVO); -} -``` +**发票管理主要接口**: + +| 接口名称 | 请求方式 | 功能描述 | +|---------|---------|---------| +| `/admin-api/water/invoice/generate` | POST | 生成发票 | +| `/admin-api/water/invoice/print` | POST | 打印发票 | +| `/admin-api/water/invoice/cancel` | POST | 发票作废 | ### 代收业务 diff --git a/water_biz_security_design.md b/water_biz_security_design.md index 3a6df23..d3621ef 100644 --- a/water_biz_security_design.md +++ b/water_biz_security_design.md @@ -349,78 +349,20 @@ GRANT SELECT ON water_customer_masked TO water_normal_user; ### Spring Security安全配置 -#### 认证配置 -```java -@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(); - } -} -``` +#### 认证配置要点 +**Spring Security核心配置**: +- 使用国密SM3哈希算法进行密码加密 +- 配置JWT身份验证过滤器 +- 设置CSRF防护和HttpOnly Cookie +- 配置请求授权规则和无状态会话管理 +- 启用方法级安全注解支持 -#### 多因素认证 -```java -@Service -public class MFAService { - - @Autowired - private SmsService smsService; - - @Autowired - private RedisTemplate 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; - } -} -``` +#### 多因素认证实现 +**短信验证码服务要点**: +- 生成6位随机验证码并缓存到Redis +- 设置5分钟过期时间防止验证码滥用 +- 集成短信服务提供商发送验证码 +- 验证时比对缓存验证码并及时清理 ### 数据传输安全 @@ -438,90 +380,28 @@ server: protocols: TLSv1.2,TLSv1.3 ``` -#### 敏感数据加密 -```java -@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); - } - } -} -``` +#### 敏感数据加密实现 +**数据加密服务要点**: +- 采用国密SM4对称加密算法 +- 实现敏感数据的加密和解密方法 +- 统一的异常处理和错误提示 +- 支持身份证号、手机号等敏感信息加密 ### 接口安全防护 -#### 接口签名验证 -```java -@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); - } -} -``` +#### 接口签名验证实现 +**API签名验证要点**: +- 基于时间戳、随机数和请求体生成签名 +- 使用国密SM3哈希算法计算签名值 +- 检查时间戳有效性防止重放攻击 +- 比对客户端签名和服务端计算签名 -#### 接口限流防护 -```java -@Component -public class RateLimitService { - - @Autowired - private RedisTemplate 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; - } -} -``` +#### 接口限流防护实现 +**限流服务要点**: +- 基于Redis实现分布式限流控制 +- 支持按IP、用户、接口等维度限流 +- 采用滑动窗口算法统计请求频率 +- 超过限制时返回429状态码 ## 网络安全设计 diff --git a/water_biz_system_architecture.md b/water_biz_system_architecture.md index 81e6be9..644684a 100644 --- a/water_biz_system_architecture.md +++ b/water_biz_system_architecture.md @@ -478,100 +478,19 @@ yudao: template-code: SMS_123456 ``` -**多租户配置实现:** -```java -@Component -@Slf4j -public class WaterTenantConfiguration { - - @Resource - private TenantProperties tenantProperties; - - /** - * 多租户字段处理器 - */ - @Bean - public TenantLineHandler tenantLineHandler() { - return new TenantLineHandler() { - - @Override - public Expression getTenantId() { - // 从当前登录用户上下文获取租户ID - Long tenantId = TenantContextHolder.getTenantId(); - if (tenantId == null) { - return null; - } - return new LongValue(tenantId); - } - - @Override - public String getTenantIdColumn() { - return "tenant_id"; - } - - @Override - public boolean ignoreTable(String tableName) { - // 忽略的表不进行多租户处理 - return tenantProperties.getIgnoreTables().contains(tableName); - } - }; - } - - /** - * 多租户拦截器 - */ - @Bean - public MybatisPlusInterceptor mybatisPlusInterceptor() { - MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); - // 多租户插件 - TenantLineInnerInterceptor tenantInterceptor = new TenantLineInnerInterceptor(); - tenantInterceptor.setTenantLineHandler(tenantLineHandler()); - interceptor.addInnerInterceptor(tenantInterceptor); - // 分页插件 - interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); - return interceptor; - } -} -``` +**多租户配置要点**: +- 基于MyBatis-Plus的TenantLineInnerInterceptor实现数据隔离 +- 自动在SQL中添加tenant_id条件过滤数据 +- 支持配置忽略多租户的系统表 +- 通过TenantContextHolder获取当前租户上下文 +- 集成分页插件支持多租户分页查询 -**权限控制配置:** -```java -@EnableWebSecurity -@EnableMethodSecurity(prePostEnabled = true, securedEnabled = true) -@Configuration -public class WaterSecurityConfiguration { - - @Resource - private SecurityProperties securityProperties; - - @Bean - public SecurityFilterChain filterChain(HttpSecurity httpSecurity, - @Lazy TokenAuthenticationFilter tokenAuthenticationFilter) throws Exception { - return httpSecurity - // 设置 URL 安全权限 - .authorizeHttpRequests(c -> c - // 1. 静态资源,可匿名访问 - .requestMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll() - // 2. 设置 @PermitAll 无需认证 - .requestMatchers(securityProperties.getPermitAllUrls().toArray(new String[0])).permitAll() - // 3. 兜底规则,必须认证 - .anyRequest().authenticated() - ) - // 设置处理器 - .exceptionHandling(c -> c.authenticationEntryPoint(authenticationEntryPoint) - .accessDeniedHandler(accessDeniedHandler)) - // 添加 Token Filter - .addFilterBefore(tokenAuthenticationFilter, UsernamePasswordAuthenticationFilter.class) - // 不创建 SecurityContext - .sessionManagement(c -> c.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) - // 禁用 CSRF,因为使用 token 机制 - .csrf(AbstractHttpConfigurer::disable) - // 禁用 cors - .cors(AbstractHttpConfigurer::disable) - .build(); - } -} -``` +**权限控制配置要点**: +- 基于Spring Security实现统一的权限控制 +- 支持方法级权限注解@PreAuthorize +- 配置静态资源和公开接口的匿名访问 +- 集成JWT Token认证过滤器 +- 采用无状态会话管理,禁用CSRF和CORS ### 客户端技术架构 - 前端框架:基于yudao-ui-admin-vue3框架定制开发 @@ -588,239 +507,35 @@ public class WaterSecurityConfiguration { - 动态表格:支持拖拽、排序、筛选 - 代码规范:ESLint + Prettier,标准化代码风格 -#### 前端项目结构配置 +#### 前端项目配置要点 -**package.json 依赖配置:** -```json -{ - "name": "water-biz-ui-admin", - "version": "1.0.0", - "description": "福建水务营收系统管理后台", - "dependencies": { - "@element-plus/icons-vue": "^2.1.0", - "@vueuse/core": "^10.5.0", - "axios": "^1.6.0", - "echarts": "^5.4.3", - "element-plus": "^2.4.2", - "pinia": "^2.1.7", - "vue": "^3.3.8", - "vue-router": "^4.2.5", - "@wangeditor/editor": "^5.1.23", - "@wangeditor/editor-for-vue": "^5.1.12" - }, - "devDependencies": { - "@types/node": "^20.8.7", - "@typescript-eslint/eslint-plugin": "^6.9.1", - "@typescript-eslint/parser": "^6.9.1", - "@vitejs/plugin-vue": "^4.4.1", - "eslint": "^8.52.0", - "eslint-plugin-vue": "^9.17.0", - "prettier": "^3.0.3", - "typescript": "^5.2.2", - "vite": "^4.5.0", - "vue-tsc": "^1.8.22" - } -} -``` +**核心依赖和技术栈**: +- Vue 3.x + TypeScript:现代化前端框架 +- Element Plus:企业级UI组件库 +- Pinia:新一代状态管理 +- Vue Router:路由管理 +- Axios:HTTP请求库 +- ECharts:数据可视化图表 +- Vite:快速构建工具 -**vite.config.ts 构建配置:** -```typescript -import { defineConfig } from 'vite' -import vue from '@vitejs/plugin-vue' -import { resolve } from 'path' +**构建配置要点**: +- 配置路径别名简化导入路径 +- 设置开发服务器代理转发API请求 +- 优化构建输出,支持代码分割和资源压缩 +- 配置静态资源处理和缓存策略 -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]' - } - } - } -}) -``` +**状态管理要点**: +- 使用Pinia管理用户信息、权限和角色 +- 提供用户登录、登出和权限检查方法 +- 支持响应式的用户状态更新 +- 集成Token管理和自动刷新机制 -**src/stores/user.ts 用户状态管理:** -```typescript -import { defineStore } from 'pinia' -import { ref, computed } from 'vue' -import { UserApi, UserVO } from '@/api/system/user' -import { getAccessToken, removeToken } from '@/utils/auth' - -export const useUserStore = defineStore('user', () => { - const userInfo = ref() - const permissions = ref([]) - const roles = ref([]) - - const nickname = computed(() => userInfo.value?.nickname ?? '') - const avatar = computed(() => userInfo.value?.avatar ?? '') - const email = computed(() => userInfo.value?.email ?? '') - - // 获取用户信息 - const getUserInfo = async () => { - const res = await UserApi.getUserProfile() - userInfo.value = res - permissions.value = res.permissions - roles.value = res.roles - } - - // 用户登出 - const logout = async () => { - try { - await UserApi.logout() - } finally { - await resetToken() - } - } - - // 重置令牌 - const resetToken = async () => { - userInfo.value = undefined - permissions.value = [] - roles.value = [] - removeToken() - } - - // 检查权限 - const hasPermission = (permission: string) => { - return permissions.value.includes(permission) - } - - // 检查角色 - const hasRole = (role: string) => { - return roles.value.includes(role) - } - - return { - userInfo, - permissions, - roles, - nickname, - avatar, - email, - getUserInfo, - logout, - resetToken, - hasPermission, - hasRole - } -}) -``` - -**src/utils/request.ts HTTP请求封装:** -```typescript -import axios, { AxiosResponse, InternalAxiosRequestConfig } from 'axios' -import { ElMessage, ElMessageBox } from 'element-plus' -import { getAccessToken, getRefreshToken, removeToken } from '@/utils/auth' -import { useUserStore } from '@/stores/user' - -// 创建 axios 实例 -const service = axios.create({ - baseURL: import.meta.env.VITE_BASE_URL, - timeout: 50000, - withCredentials: false -}) - -// 请求拦截器 -service.interceptors.request.use( - (config: InternalAxiosRequestConfig) => { - // 添加 token - const accessToken = getAccessToken() - if (accessToken && config.headers) { - config.headers.Authorization = `Bearer ${accessToken}` - } - - // 添加租户ID - const tenantId = localStorage.getItem('tenantId') - if (tenantId && config.headers) { - config.headers['tenant-id'] = tenantId - } - - return config - }, - error => { - console.log(error) - return Promise.reject(error) - } -) - -// 响应拦截器 -service.interceptors.response.use( - (response: AxiosResponse) => { - const { data } = response - const { code, msg } = data - - // 业务请求成功 - if (code === 0) { - return data - } - - // token 过期,尝试刷新 - if (code === 401) { - return handleTokenExpired() - } - - // 业务请求失败 - ElMessage.error(msg || '系统未知错误,请反馈给管理员') - return Promise.reject(new Error(msg || 'Error')) - }, - error => { - console.log('err' + error) - let { message } = error - if (message === 'Network Error') { - message = '后端接口连接异常' - } else if (message.includes('timeout')) { - message = '系统接口请求超时' - } else if (message.includes('Request failed with status code')) { - message = '系统接口' + message.substr(message.length - 3) + '异常' - } - ElMessage.error(message) - return Promise.reject(error) - } -) - -// 处理 token 过期 -const handleTokenExpired = async () => { - const userStore = useUserStore() - ElMessageBox.alert('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { - confirmButtonText: '重新登录', - type: 'warning' - }).then(() => { - userStore.resetToken().then(() => { - location.reload() - }) - }) -} - -export default service -``` +**HTTP请求封装要点**: +- 基于Axios封装统一的HTTP请求工具 +- 自动添加认证Token和租户ID头部 +- 实现请求和响应拦截器处理公共逻辑 +- 统一的错误处理和用户提示 +- 支持Token过期自动刷新机制 ### 前端技术架构详细设计 #### Web管理端架构 (yudao-ui-admin-vue3) @@ -913,46 +628,11 @@ yudao-ui-admin-vue3/ └── package.json # 项目依赖 ``` -**核心配置示例:** -```typescript -// vite.config.ts - Vite构建配置 -import { defineConfig } from 'vite' -import vue from '@vitejs/plugin-vue' -import { resolve } from 'path' - -export default defineConfig({ - plugins: [vue()], - resolve: { - alias: { - '@': resolve(__dirname, 'src'), - '@/api': resolve(__dirname, 'src/api'), - '@/components': resolve(__dirname, 'src/components'), - '@/utils': resolve(__dirname, 'src/utils') - } - }, - server: { - port: 80, - proxy: { - '/admin-api': { - target: 'http://127.0.0.1:48080', - changeOrigin: true, - rewrite: (path) => path.replace(/^\/admin-api/, '/admin-api') - } - } - }, - build: { - outDir: 'dist', - sourcemap: false, - rollupOptions: { - output: { - chunkFileNames: 'js/[name]-[hash].js', - entryFileNames: 'js/[name]-[hash].js', - assetFileNames: '[ext]/[name]-[hash].[ext]' - } - } - } -}) -``` +**核心配置要点**: +- Vite构建工具配置,支持路径别名和代理 +- 开发服务器配置,代理后端API请求 +- 构建优化配置,支持代码分割和资源压缩 +- TypeScript配置,提供类型检查和智能提示 #### 移动端架构 (uni-app)