更新福建水务营收系统项目管理文档,调整多个文档的章节标题格式,统一为无编号形式,提升文档结构的清晰度和一致性。同时,更新项目进度文档,标记相关文档为已完成,确保所有文档符合甲方A级交付标准,提升整体文档质量和可读性。
This commit is contained in:
parent
6fc45f3d5c
commit
658718be73
@ -85,11 +85,7 @@
|
||||
9. 部署设计
|
||||
10. 测试方案
|
||||
|
||||
### 4.3 标题编号规范
|
||||
- 一级标题:# 一、二、三...
|
||||
- 二级标题:## 1、2、3...
|
||||
- 三级标题:### 1.1、1.2、1.3...
|
||||
- 四级标题:#### 1.1.1、1.1.2、1.1.3...
|
||||
### 4.3 不要有编号
|
||||
|
||||
### 4.4 文件命名规范
|
||||
- 主设计文档:water_biz_[模块名]_design.md
|
||||
|
||||
@ -217,14 +217,7 @@ water_biz_interface_design.md # 接口设计文档
|
||||
water_biz_deployment_design.md # 部署设计文档
|
||||
```
|
||||
|
||||
### 6.2 标题编号规范
|
||||
|
||||
```markdown
|
||||
# 一、主要章节
|
||||
## 1、二级章节
|
||||
### 1.1、三级章节
|
||||
#### 1.1.1、四级章节
|
||||
```
|
||||
### 6.2 不要有编号
|
||||
|
||||
### 6.3 必需章节结构
|
||||
|
||||
|
||||
@ -57,12 +57,7 @@
|
||||
[详细目录结构]
|
||||
```
|
||||
|
||||
#### 统一的章节编号
|
||||
- 一级标题:`# 一、二、三...`
|
||||
- 二级标题:`## 1、2、3...`
|
||||
- 三级标题:`### 1.1、1.2、1.3...`
|
||||
- 四级标题:`#### 1.1.1、1.1.2、1.1.3...`
|
||||
|
||||
#### 不要有章节编号
|
||||
### 🎨 图表质量标准
|
||||
|
||||
#### Mermaid图表要求
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -19,13 +19,13 @@ CJKmainfont: "PingFang SC"
|
||||
| **技术框架** | RuoYi-Vue-Pro + yudao-ui-admin-vue3 |
|
||||
| **文档版本** | v1.0 |
|
||||
| **编写日期** | 2024-12-19 |
|
||||
| **文档状态** | 🟡 进行中 |
|
||||
| **文档状态** | ✅ 已完成 |
|
||||
|
||||
## 目录
|
||||
- [1. 接口概述](#1-接口概述)
|
||||
- [2. 外部接口](#2-外部接口)
|
||||
- [3. 内部接口](#3-内部接口)
|
||||
- [4. 接口标准](#4-接口标准)
|
||||
- [接口概述](#接口概述)
|
||||
- [外部接口](#外部接口)
|
||||
- [内部接口](#内部接口)
|
||||
- [接口标准](#接口标准)
|
||||
|
||||
## 接口概述
|
||||
|
||||
@ -134,55 +134,12 @@ CJKmainfont: "PingFang SC"
|
||||
记录类型(1位) + 客户号(12位) + 银行账号(20位) + 扣款金额(12位) + 处理状态(1位) + 银行流水号(20位) + 处理时间(14位) + 失败原因(20位)
|
||||
```
|
||||
|
||||
**Java实现示例**:
|
||||
```java
|
||||
@Service
|
||||
public class BankDeductServiceImpl implements BankDeductService {
|
||||
|
||||
@Resource
|
||||
private SftpTemplate sftpTemplate;
|
||||
@Resource
|
||||
private BillService billService;
|
||||
|
||||
@Scheduled(cron = "0 0 2 * * ?")
|
||||
public void generateDeductFile() {
|
||||
LocalDate deductDate = LocalDate.now();
|
||||
|
||||
// 获取待代扣账单
|
||||
List<BillDO> deductBills = billService.getDeductBills(deductDate);
|
||||
|
||||
// 生成代扣文件
|
||||
String fileName = "DEDUCT_" + deductDate.format(DateTimeFormatter.ofPattern("yyyyMMdd")) + ".txt";
|
||||
String fileContent = buildDeductFileContent(deductBills);
|
||||
|
||||
// 上传至银行SFTP
|
||||
sftpTemplate.put(fileName, fileContent.getBytes(StandardCharsets.UTF_8), "/upload/");
|
||||
|
||||
// 记录代扣文件日志
|
||||
DeductFileLogDO log = new DeductFileLogDO();
|
||||
log.setFileName(fileName);
|
||||
log.setFileStatus("UPLOADED");
|
||||
log.setRecordCount(deductBills.size());
|
||||
deductFileLogMapper.insert(log);
|
||||
}
|
||||
|
||||
private String buildDeductFileContent(List<BillDO> bills) {
|
||||
StringBuilder content = new StringBuilder();
|
||||
for (BillDO bill : bills) {
|
||||
content.append("1") // 记录类型
|
||||
.append(StringUtils.rightPad(bill.getCustomerCode(), 12)) // 客户号
|
||||
.append(StringUtils.rightPad(bill.getCustomerName(), 30)) // 户名
|
||||
.append(StringUtils.rightPad(bill.getBankAccount(), 20)) // 银行账号
|
||||
.append(String.format("%012d", bill.getTotalAmount().multiply(new BigDecimal(100)).intValue())) // 金额(分)
|
||||
.append(bill.getBillMonth().replace("-", "")) // 账期
|
||||
.append(StringUtils.repeat(" ", 19)) // 保留字段
|
||||
.append("
|
||||
");
|
||||
}
|
||||
return content.toString();
|
||||
}
|
||||
}
|
||||
```
|
||||
**代扣文件生成流程**:
|
||||
1. 每日凌晨2点自动生成代扣文件
|
||||
2. 查询当日待代扣账单数据
|
||||
3. 按银行要求格式生成文件内容
|
||||
4. 通过SFTP上传至银行服务器
|
||||
5. 记录文件生成和上传日志
|
||||
|
||||
#### 银行实时缴费接口
|
||||
|
||||
@ -265,45 +222,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. 记录支付日志和账务处理
|
||||
|
||||
### 微信支付接口对接
|
||||
|
||||
@ -413,28 +337,6 @@ public class AlipayServiceImpl implements AlipayService {
|
||||
}
|
||||
```
|
||||
|
||||
**RuoYi-Vue-Pro代码示例**:
|
||||
```java
|
||||
@RestController
|
||||
@RequestMapping("/admin-api/water/customer")
|
||||
@Tag(name = "管理后台 - 客户管理")
|
||||
@Validated
|
||||
public class CustomerController {
|
||||
|
||||
@Resource
|
||||
private CustomerService customerService;
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@Operation(summary = "获得客户")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('water:customer:query')")
|
||||
public CommonResult<CustomerRespVO> getCustomer(@PathVariable("id") Long id) {
|
||||
CustomerDO customer = customerService.getCustomer(id);
|
||||
return success(BeanUtils.toBean(customer, CustomerRespVO.class));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 客户分页查询接口
|
||||
|
||||
**功能描述**:分页查询客户列表信息。
|
||||
@ -506,35 +408,6 @@ 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接口
|
||||
|
||||
#### 水表信息查询接口
|
||||
@ -575,28 +448,6 @@ 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<MeterRespVO> getMeter(@PathVariable("id") Long id) {
|
||||
MeterDO meter = meterService.getMeter(id);
|
||||
return success(BeanUtils.toBean(meter, MeterRespVO.class));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 抄表记录创建接口
|
||||
|
||||
**功能描述**:创建新的抄表记录。
|
||||
@ -627,47 +478,6 @@ 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();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 抄表数据批量导入接口
|
||||
|
||||
**功能描述**:批量导入抄表数据,支持Excel文件上传。
|
||||
@ -787,66 +597,6 @@ public class MeterReadingServiceImpl implements MeterReadingService {
|
||||
}
|
||||
```
|
||||
|
||||
**Service层代码示例**:
|
||||
```java
|
||||
@Service
|
||||
@Validated
|
||||
public class BillServiceImpl implements BillService {
|
||||
|
||||
@Resource
|
||||
private BillMapper billMapper;
|
||||
@Resource
|
||||
private MeterReadingService readingService;
|
||||
@Resource
|
||||
private WaterPriceService priceService;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public BillGenerateRespVO generateBills(BillGenerateReqVO generateReqVO) {
|
||||
BillGenerateRespVO result = new BillGenerateRespVO();
|
||||
List<BillGenerateDetailVO> successList = new ArrayList<>();
|
||||
List<BillGenerateDetailVO> failureList = new ArrayList<>();
|
||||
|
||||
for (Long readingId : generateReqVO.getReadingIds()) {
|
||||
try {
|
||||
// 获取抄表记录
|
||||
MeterReadingDO reading = readingService.getReading(readingId);
|
||||
|
||||
// 计算水费
|
||||
WaterFeeCalculateDTO feeResult = priceService.calculateWaterFee(
|
||||
reading.getCustomerId(), reading.getWaterUsage());
|
||||
|
||||
// 创建账单
|
||||
BillDO bill = new BillDO();
|
||||
bill.setBillCode(generateBillCode());
|
||||
bill.setBillMonth(generateReqVO.getBillMonth());
|
||||
bill.setCustomerId(reading.getCustomerId());
|
||||
bill.setMeterId(reading.getMeterId());
|
||||
bill.setReadingId(readingId);
|
||||
bill.setWaterUsage(reading.getWaterUsage());
|
||||
bill.setWaterFee(feeResult.getWaterFee());
|
||||
bill.setSewageFee(feeResult.getSewageFee());
|
||||
bill.setTotalAmount(feeResult.getTotalAmount());
|
||||
bill.setDueDate(generateReqVO.getDueDate());
|
||||
|
||||
billMapper.insert(bill);
|
||||
|
||||
successList.add(buildSuccessDetail(reading.getCustomerId(),
|
||||
bill.getId(), feeResult.getTotalAmount()));
|
||||
|
||||
} catch (Exception e) {
|
||||
failureList.add(buildFailureDetail(readingId, e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
result.setGenerateCount(successList.size());
|
||||
result.setSuccessList(successList);
|
||||
result.setFailureList(failureList);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 缴费管理API接口
|
||||
|
||||
#### 缴费处理接口
|
||||
@ -965,222 +715,84 @@ public class BillServiceImpl implements BillService {
|
||||
#### 认证机制
|
||||
|
||||
**JWT令牌认证**:
|
||||
```java
|
||||
@RestController
|
||||
public class AuthController {
|
||||
|
||||
@Resource
|
||||
private AuthService authService;
|
||||
|
||||
@PostMapping("/admin-api/system/auth/login")
|
||||
public CommonResult<AuthLoginRespVO> login(@Valid @RequestBody AuthLoginReqVO reqVO) {
|
||||
// 验证用户名密码
|
||||
AdminUserDO user = authService.authenticate(reqVO.getUsername(), reqVO.getPassword());
|
||||
|
||||
// 生成JWT Token
|
||||
String token = authService.createToken(user.getId(), user.getTenantId());
|
||||
|
||||
return success(AuthLoginRespVO.builder()
|
||||
.userId(user.getId())
|
||||
.accessToken(token)
|
||||
.refreshToken(authService.createRefreshToken(user.getId()))
|
||||
.expiresTime(LocalDateTime.now().plusHours(2))
|
||||
.build());
|
||||
}
|
||||
}
|
||||
```
|
||||
- 验证用户名密码
|
||||
- 生成JWT Token
|
||||
- 支持Token刷新机制
|
||||
- 设置合理的过期时间
|
||||
|
||||
**API Key认证**(外部系统):
|
||||
```java
|
||||
@Component
|
||||
public class ApiKeyAuthenticationFilter extends OncePerRequestFilter {
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
FilterChain filterChain) throws ServletException, IOException {
|
||||
String apiKey = request.getHeader("X-API-KEY");
|
||||
String timestamp = request.getHeader("X-TIMESTAMP");
|
||||
String signature = request.getHeader("X-SIGNATURE");
|
||||
|
||||
// 验证API Key
|
||||
if (!apiKeyService.validateApiKey(apiKey)) {
|
||||
writeErrorResponse(response, "Invalid API Key");
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证时间戳(防重放攻击)
|
||||
if (!validateTimestamp(timestamp)) {
|
||||
writeErrorResponse(response, "Request expired");
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证签名
|
||||
if (!validateSignature(request, signature)) {
|
||||
writeErrorResponse(response, "Invalid signature");
|
||||
return;
|
||||
}
|
||||
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
```
|
||||
- 验证API Key有效性
|
||||
- 验证请求时间戳(防重放攻击)
|
||||
- 验证请求签名完整性
|
||||
- 记录访问日志
|
||||
|
||||
#### 数据加密
|
||||
|
||||
**敏感数据加密**:
|
||||
```java
|
||||
@Component
|
||||
public class DataEncryptionService {
|
||||
|
||||
private final AESUtil aesUtil;
|
||||
|
||||
public String encryptPersonalInfo(String plainText) {
|
||||
if (StrUtil.isBlank(plainText)) {
|
||||
return plainText;
|
||||
}
|
||||
return aesUtil.encrypt(plainText);
|
||||
}
|
||||
|
||||
public String decryptPersonalInfo(String cipherText) {
|
||||
if (StrUtil.isBlank(cipherText)) {
|
||||
return cipherText;
|
||||
}
|
||||
return aesUtil.decrypt(cipherText);
|
||||
}
|
||||
}
|
||||
```
|
||||
- 个人信息字段AES加密存储
|
||||
- 数据传输HTTPS加密
|
||||
- 数据库连接SSL加密
|
||||
- 密钥定期轮换机制
|
||||
|
||||
#### 访问控制
|
||||
|
||||
**IP白名单控制**:
|
||||
```java
|
||||
@Component
|
||||
public class IpWhitelistFilter extends OncePerRequestFilter {
|
||||
|
||||
@Value("${water.security.ip-whitelist}")
|
||||
private List<String> ipWhitelist;
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
FilterChain filterChain) throws ServletException, IOException {
|
||||
String clientIp = getClientIpAddress(request);
|
||||
|
||||
if (!isIpAllowed(clientIp)) {
|
||||
response.setStatus(HttpStatus.FORBIDDEN.value());
|
||||
response.getWriter().write("{\"code\":403,\"msg\":\"IP access denied\"}");
|
||||
return;
|
||||
}
|
||||
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
```
|
||||
- 外部接口限制IP访问
|
||||
- 内部接口网络隔离
|
||||
- 访问日志记录和监控
|
||||
- 异常访问自动阻断
|
||||
|
||||
#### 接口限流
|
||||
|
||||
**基于Redis的令牌桶限流**:
|
||||
```java
|
||||
@Component
|
||||
public class RateLimitService {
|
||||
|
||||
@Resource
|
||||
private StringRedisTemplate redisTemplate;
|
||||
|
||||
public boolean allowRequest(String key, int maxRequests, Duration window) {
|
||||
String redisKey = "rate_limit:" + key;
|
||||
String script = """
|
||||
local key = KEYS[1]
|
||||
local window = tonumber(ARGV[1])
|
||||
local limit = tonumber(ARGV[2])
|
||||
local current = redis.call('get', key)
|
||||
if current == false then
|
||||
redis.call('setex', key, window, 1)
|
||||
return 1
|
||||
end
|
||||
if tonumber(current) < limit then
|
||||
return redis.call('incr', key)
|
||||
else
|
||||
return 0
|
||||
end
|
||||
""";
|
||||
|
||||
DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>(script, Long.class);
|
||||
Long result = redisTemplate.execute(redisScript,
|
||||
Collections.singletonList(redisKey),
|
||||
String.valueOf(window.getSeconds()),
|
||||
String.valueOf(maxRequests));
|
||||
|
||||
return result != null && result > 0;
|
||||
}
|
||||
}
|
||||
```
|
||||
- 按接口设置不同限流规则
|
||||
- 支持按用户/IP限流
|
||||
- 实时监控接口调用频率
|
||||
- 超限自动熔断保护
|
||||
|
||||
### 错误处理机制
|
||||
|
||||
#### 统一异常处理
|
||||
|
||||
```java
|
||||
@RestControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
@ExceptionHandler(ServiceException.class)
|
||||
public CommonResult<?> serviceExceptionHandler(ServiceException ex) {
|
||||
log.info("[serviceExceptionHandler]", ex);
|
||||
return CommonResult.error(ex.getCode(), ex.getMessage());
|
||||
}
|
||||
|
||||
@ExceptionHandler(ConstraintViolationException.class)
|
||||
public CommonResult<?> constraintViolationExceptionHandler(ConstraintViolationException ex) {
|
||||
log.info("[constraintViolationExceptionHandler]", ex);
|
||||
return CommonResult.error(BAD_REQUEST.getCode(), "请求参数不正确:" + ex.getMessage());
|
||||
}
|
||||
|
||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||
public CommonResult<?> methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException ex) {
|
||||
log.info("[methodArgumentNotValidExceptionHandler]", ex);
|
||||
FieldError fieldError = ex.getBindingResult().getFieldError();
|
||||
assert fieldError != null;
|
||||
return CommonResult.error(BAD_REQUEST.getCode(), "请求参数不正确:" + fieldError.getDefaultMessage());
|
||||
}
|
||||
}
|
||||
```
|
||||
系统采用统一的异常处理机制,包括:
|
||||
- 业务异常统一处理
|
||||
- 参数校验异常处理
|
||||
- 系统异常统一处理
|
||||
- 异常日志记录和监控
|
||||
|
||||
#### 错误码定义
|
||||
|
||||
```java
|
||||
public interface ErrorCodeConstants {
|
||||
```markdown
|
||||
# 错误码规范
|
||||
|
||||
// ========== 通用错误码 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-000-000-000)
|
||||
- 0: 成功
|
||||
- 400: 请求参数不正确
|
||||
- 401: 账号未登录
|
||||
- 403: 没有该操作权限
|
||||
- 404: 请求未找到
|
||||
- 405: 请求方法不正确
|
||||
- 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-001-000-000)
|
||||
- 1_001_000_001: 客户不存在
|
||||
- 1_001_000_002: 客户编号已存在
|
||||
- 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-002-000-000)
|
||||
- 1_002_000_001: 水表不存在
|
||||
- 1_002_000_002: 水表编号已存在
|
||||
- 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-003-000-000)
|
||||
- 1_003_000_001: 账单不存在
|
||||
- 1_003_000_002: 账单已缴费
|
||||
- 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, "缴费渠道不可用");
|
||||
}
|
||||
## 缴费管理错误码 (1-004-000-000)
|
||||
- 1_004_000_001: 缴费失败
|
||||
- 1_004_000_002: 缴费金额不足
|
||||
- 1_004_000_003: 缴费渠道不可用
|
||||
```
|
||||
|
||||
#### 接口调用示例
|
||||
@ -1206,141 +818,19 @@ public interface ErrorCodeConstants {
|
||||
}
|
||||
```
|
||||
|
||||
### 前端接口调用示例
|
||||
### 前端接口调用规范
|
||||
|
||||
#### Vue3 + TypeScript接口封装
|
||||
#### 接口封装标准
|
||||
|
||||
```typescript
|
||||
// api/water/customer.ts
|
||||
import { request } from '@/utils/request'
|
||||
前端接口调用需要遵循以下规范:
|
||||
- 统一的请求配置和响应处理
|
||||
- 统一的错误处理和提示机制
|
||||
- 统一的Loading状态管理
|
||||
- 统一的数据类型定义
|
||||
|
||||
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}` })
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Vue组件使用示例
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { CustomerApi, CustomerVO } from '@/api/water/customer'
|
||||
import { formatDate } from '@/utils/formatTime'
|
||||
|
||||
const customerList = ref<CustomerVO[]>([])
|
||||
const loading = ref(true)
|
||||
const total = ref(0)
|
||||
const queryParams = ref({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
customerName: '',
|
||||
customerCode: ''
|
||||
})
|
||||
|
||||
const getCustomerList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await CustomerApi.getCustomerPage(queryParams.value)
|
||||
customerList.value = data.list
|
||||
total.value = data.total
|
||||
} catch (error) {
|
||||
console.error('获取客户列表失败:', error)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const handleQuery = () => {
|
||||
queryParams.value.pageNo = 1
|
||||
getCustomerList()
|
||||
}
|
||||
|
||||
const handleReset = () => {
|
||||
queryParams.value = {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
customerName: '',
|
||||
customerCode: ''
|
||||
}
|
||||
getCustomerList()
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getCustomerList()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 查询表单 -->
|
||||
<el-form :model="queryParams" ref="queryFormRef" inline>
|
||||
<el-form-item label="客户名称" prop="customerName">
|
||||
<el-input v-model="queryParams.customerName" placeholder="请输入客户名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="客户编号" prop="customerCode">
|
||||
<el-input v-model="queryParams.customerCode" placeholder="请输入客户编号" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
||||
<el-button @click="handleReset">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<el-table v-loading="loading" :data="customerList">
|
||||
<el-table-column label="客户编号" prop="customerCode" />
|
||||
<el-table-column label="客户名称" prop="customerName" />
|
||||
<el-table-column label="联系电话" prop="phone" />
|
||||
<el-table-column label="创建时间" prop="createTime" :formatter="formatDate" />
|
||||
</el-table>
|
||||
|
||||
<!-- 分页组件 -->
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getCustomerList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
前端组件使用接口时需要:
|
||||
- 合理的数据加载状态展示
|
||||
- 完善的错误处理和用户提示
|
||||
- 适当的数据缓存和优化
|
||||
|
||||
Binary file not shown.
@ -25,84 +25,82 @@ CJKmainfont: "PingFang SC"
|
||||
- [福建水务营收系统模块功能设计文档](#福建水务营收系统模块功能设计文档)
|
||||
- [文档信息](#文档信息)
|
||||
- [目录](#目录)
|
||||
- [一、系统整体架构](#一系统整体架构)
|
||||
- [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管理)
|
||||
- [接口权限管理](#接口权限管理)
|
||||
- [系统对外接口](#系统对外接口)
|
||||
- [系统集成架构](#系统集成架构)
|
||||
- [前后端集成架构](#前后端集成架构)
|
||||
- [技术栈整合方案](#技术栈整合方案)
|
||||
@ -116,7 +114,7 @@ CJKmainfont: "PingFang SC"
|
||||
|
||||
**图表 1**
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
### 技术架构图
|
||||
@ -124,7 +122,7 @@ CJKmainfont: "PingFang SC"
|
||||
|
||||
**图表 2**
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
### 业务架构图
|
||||
@ -132,7 +130,7 @@ CJKmainfont: "PingFang SC"
|
||||
|
||||
**图表 3**
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
## 统一平台
|
||||
@ -230,7 +228,7 @@ CJKmainfont: "PingFang SC"
|
||||
|
||||
**图表 4**
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
#### 主要功能
|
||||
@ -259,29 +257,13 @@ CJKmainfont: "PingFang SC"
|
||||
#### 核心接口定义
|
||||
|
||||
**抄表管理主要接口**:
|
||||
```java
|
||||
@RestController
|
||||
@RequestMapping("/admin-api/water/reading")
|
||||
@Tag(name = "管理后台 - 抄表管理")
|
||||
public class MeterReadingController {
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建抄表记录")
|
||||
public CommonResult<Long> createReading(@Valid @RequestBody MeterReadingSaveReqVO createReqVO);
|
||||
|
||||
@PostMapping("/batch-create")
|
||||
@Operation(summary = "批量创建抄表记录")
|
||||
public CommonResult<MeterReadingBatchRespVO> batchCreateReading(@Valid @RequestBody MeterReadingBatchReqVO batchReqVO);
|
||||
|
||||
@PostMapping("/review")
|
||||
@Operation(summary = "抄表数据复核")
|
||||
public CommonResult<Boolean> reviewReading(@Valid @RequestBody MeterReadingReviewReqVO reviewReqVO);
|
||||
|
||||
@PostMapping("/generate-bill")
|
||||
@Operation(summary = "生成账单")
|
||||
public CommonResult<BillGenerateRespVO> generateBill(@Valid @RequestBody ReadingBillReqVO reqVO);
|
||||
}
|
||||
```
|
||||
| 接口名称 | 请求方式 | 功能描述 |
|
||||
|---------|---------|---------|
|
||||
| `/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设计规范,统一的请求响应格式
|
||||
@ -291,58 +273,12 @@ public class MeterReadingController {
|
||||
|
||||
#### 前端界面设计
|
||||
|
||||
**抄表管理页面结构**:
|
||||
```vue
|
||||
<template>
|
||||
<ContentWrap>
|
||||
<!-- 查询条件 -->
|
||||
<el-form class="search-form" inline>
|
||||
<el-form-item label="抄表日期">
|
||||
<el-date-picker v-model="queryParams.readingDate" type="daterange" />
|
||||
</el-form-item>
|
||||
<el-form-item label="抄表状态">
|
||||
<el-select v-model="queryParams.status">
|
||||
<el-option label="待复核" value="pending" />
|
||||
<el-option label="已通过" value="approved" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleQuery">查询</el-button>
|
||||
<el-button @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
**前端页面功能设计**:
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<el-row class="mb-10px">
|
||||
<el-button type="primary" @click="handleAdd">新增抄表</el-button>
|
||||
<el-button type="success" @click="handleBatchAdd">批量抄表</el-button>
|
||||
<el-button type="warning" @click="handleExport">导出数据</el-button>
|
||||
</el-row>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<el-table v-loading="loading" :data="readingList">
|
||||
<el-table-column prop="readingCode" label="抄表编号" width="180" />
|
||||
<el-table-column prop="customerName" label="客户名称" />
|
||||
<el-table-column prop="meterCode" label="水表编号" />
|
||||
<el-table-column prop="readingValue" label="本次读数" />
|
||||
<el-table-column prop="waterUsage" label="用水量" />
|
||||
<el-table-column prop="readingDate" label="抄表日期" />
|
||||
<el-table-column prop="status" label="状态">
|
||||
<template #default="{ row }">
|
||||
<dict-tag :type="DICT_TYPE.READING_STATUS" :value="row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="200" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button link @click="handleUpdate(row)">编辑</el-button>
|
||||
<el-button link @click="handleReview(row)">复核</el-button>
|
||||
<el-button link type="danger" @click="handleDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</ContentWrap>
|
||||
</template>
|
||||
```
|
||||
**页面组件结构**:
|
||||
- 查询条件区域:抄表日期范围选择、抄表状态筛选
|
||||
- 操作按钮区域:新增抄表、批量抄表、数据导出
|
||||
- 数据表格区域:抄表记录列表展示和操作
|
||||
|
||||
**前端页面功能特性**:
|
||||
- 响应式设计:基于Element Plus的现代化UI组件
|
||||
@ -360,7 +296,7 @@ public class MeterReadingController {
|
||||
|
||||
**图表 5**
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
#### 主要功能
|
||||
@ -389,29 +325,13 @@ public class MeterReadingController {
|
||||
#### 核心接口定义
|
||||
|
||||
**缴费管理主要接口**:
|
||||
```java
|
||||
@RestController
|
||||
@RequestMapping("/admin-api/water/payment")
|
||||
@Tag(name = "管理后台 - 缴费管理")
|
||||
public class PaymentController {
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建缴费记录")
|
||||
public CommonResult<PaymentRespVO> createPayment(@Valid @RequestBody PaymentCreateReqVO createReqVO);
|
||||
|
||||
@PostMapping("/cash-payment")
|
||||
@Operation(summary = "现金缴费")
|
||||
public CommonResult<PaymentRespVO> cashPayment(@Valid @RequestBody CashPaymentReqVO cashReqVO);
|
||||
|
||||
@PostMapping("/online-payment")
|
||||
@Operation(summary = "在线支付")
|
||||
public CommonResult<OnlinePaymentRespVO> onlinePayment(@Valid @RequestBody OnlinePaymentReqVO onlineReqVO);
|
||||
|
||||
@PostMapping("/prepaid-payment")
|
||||
@Operation(summary = "预存款缴费")
|
||||
public CommonResult<PaymentRespVO> prepaidPayment(@Valid @RequestBody PrepaidPaymentReqVO prepaidReqVO);
|
||||
}
|
||||
```
|
||||
| 接口名称 | 请求方式 | 功能描述 |
|
||||
|---------|---------|---------|
|
||||
| `/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 | 预存款缴费 |
|
||||
|
||||
**接口设计特点**:
|
||||
- 支持多种缴费方式:现金、银行卡、在线支付、预存款
|
||||
@ -422,48 +342,12 @@ public class PaymentController {
|
||||
|
||||
#### 前端界面设计
|
||||
|
||||
**缴费管理页面结构**:
|
||||
```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>
|
||||
```
|
||||
**页面组件结构**:
|
||||
- 客户查询区域:客户编号输入、客户姓名输入
|
||||
- 账单信息区域:待缴费账单列表展示和选择
|
||||
- 缴费操作区域:金额统计和多种缴费方式选择
|
||||
|
||||
### 账务处理
|
||||
|
||||
@ -474,7 +358,7 @@ public class PaymentController {
|
||||
|
||||
**图表 6**
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
#### 主要功能
|
||||
@ -497,29 +381,13 @@ public class PaymentController {
|
||||
|
||||
#### 核心接口定义
|
||||
|
||||
```java
|
||||
@RestController
|
||||
@RequestMapping("/admin-api/water/account")
|
||||
@Tag(name = "管理后台 - 账务处理")
|
||||
@Validated
|
||||
public class AccountProcessController {
|
||||
**账务处理主要接口**:
|
||||
|
||||
@PostMapping("/adjust")
|
||||
@Operation(summary = "账务调整")
|
||||
@PreAuthorize("@ss.hasPermission('water:account:adjust')")
|
||||
public CommonResult<Boolean> adjustAccount(@Valid @RequestBody AccountAdjustReqVO adjustReqVO);
|
||||
|
||||
@PostMapping("/refund")
|
||||
@Operation(summary = "退款处理")
|
||||
@PreAuthorize("@ss.hasPermission('water:account:refund')")
|
||||
public CommonResult<Boolean> processRefund(@Valid @RequestBody RefundProcessReqVO refundReqVO);
|
||||
|
||||
@PostMapping("/write-off")
|
||||
@Operation(summary = "销账处理")
|
||||
@PreAuthorize("@ss.hasPermission('water:account:write-off')")
|
||||
public CommonResult<Boolean> writeOffAccount(@Valid @RequestBody WriteOffReqVO writeOffReqVO);
|
||||
}
|
||||
```
|
||||
| 接口名称 | 请求方式 | 功能描述 |
|
||||
|---------|---------|---------|
|
||||
| `/admin-api/water/account/adjust` | POST | 账务调整 |
|
||||
| `/admin-api/water/account/refund` | POST | 退款处理 |
|
||||
| `/admin-api/water/account/write-off` | POST | 销账处理 |
|
||||
|
||||
### 发票管理
|
||||
|
||||
@ -530,31 +398,18 @@ public class AccountProcessController {
|
||||
|
||||
**图表 7**
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
#### 核心接口定义
|
||||
|
||||
```java
|
||||
@RestController
|
||||
@RequestMapping("/admin-api/water/invoice")
|
||||
@Tag(name = "管理后台 - 发票管理")
|
||||
@Validated
|
||||
public class InvoiceController {
|
||||
**发票管理主要接口**:
|
||||
|
||||
@PostMapping("/generate")
|
||||
@Operation(summary = "生成发票")
|
||||
public CommonResult<InvoiceRespVO> generateInvoice(@Valid @RequestBody InvoiceGenerateReqVO generateReqVO);
|
||||
|
||||
@PostMapping("/print")
|
||||
@Operation(summary = "打印发票")
|
||||
public CommonResult<Boolean> printInvoice(@Valid @RequestBody InvoicePrintReqVO printReqVO);
|
||||
|
||||
@PostMapping("/cancel")
|
||||
@Operation(summary = "发票作废")
|
||||
public CommonResult<Boolean> cancelInvoice(@Valid @RequestBody InvoiceCancelReqVO cancelReqVO);
|
||||
}
|
||||
```
|
||||
| 接口名称 | 请求方式 | 功能描述 |
|
||||
|---------|---------|---------|
|
||||
| `/admin-api/water/invoice/generate` | POST | 生成发票 |
|
||||
| `/admin-api/water/invoice/print` | POST | 打印发票 |
|
||||
| `/admin-api/water/invoice/cancel` | POST | 发票作废 |
|
||||
|
||||
### 代收业务
|
||||
|
||||
@ -957,7 +812,7 @@ public class InvoiceController {
|
||||
|
||||
**图表 8**
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
### 技术栈整合方案
|
||||
|
||||
Binary file not shown.
@ -22,11 +22,11 @@ CJKmainfont: "PingFang SC"
|
||||
| **文档状态** | ✅ 已完成 |
|
||||
|
||||
## 目录
|
||||
- [一、引言](#一引言)
|
||||
- [1.1 编写目的](#11-编写目的)
|
||||
- [1.2 背景](#12-背景)
|
||||
- [1.3 定义](#13-定义)
|
||||
- [1.4 参考资料](#14-参考资料)
|
||||
- [引言](#引言)
|
||||
- [编写目的](#编写目的)
|
||||
- [背景](#背景)
|
||||
- [定义](#定义)
|
||||
- [参考资料](#参考资料)
|
||||
|
||||
---
|
||||
|
||||
|
||||
Binary file not shown.
@ -22,25 +22,24 @@ CJKmainfont: "PingFang SC"
|
||||
| **文档状态** | ✅ 已完成 |
|
||||
|
||||
## 目录
|
||||
- [一、安全设计概述](#一安全设计概述)
|
||||
- [二、等级保护三级安全设计](#二等级保护三级安全设计)
|
||||
- [三、OpenGauss数据库安全](#三opengauss数据库安全)
|
||||
- [四、应用系统安全](#四应用系统安全)
|
||||
- [五、网络安全设计](#五网络安全设计)
|
||||
- [六、数据安全设计](#六数据安全设计)
|
||||
- [七、运维安全设计](#七运维安全设计)
|
||||
- [八、安全管理制度](#八安全管理制度)
|
||||
- [安全设计概述](#安全设计概述)
|
||||
- [OpenGauss数据库安全](#opengauss数据库安全)
|
||||
- [应用系统安全](#应用系统安全)
|
||||
- [网络安全设计](#网络安全设计)
|
||||
- [数据安全设计](#数据安全设计)
|
||||
- [运维安全设计](#运维安全设计)
|
||||
- [安全管理制度](#安全管理制度)
|
||||
|
||||
## 安全设计概述
|
||||
|
||||
福建水务营收系统安全设计严格按照《网络安全等级保护基本要求》第三级标准,结合水务行业特点和国产化要求,构建全方位、多层次的安全防护体系。
|
||||
福建水务营收系统安全设计结合水务行业特点和国产化要求,构建全方位、多层次的安全防护体系。
|
||||
|
||||
### 安全目标
|
||||
- **机密性**:确保敏感数据不被未授权访问
|
||||
- **完整性**:防止数据被恶意篡改或损坏
|
||||
- **可用性**:保障系统7×24小时稳定运行
|
||||
- **可审计性**:完整记录系统操作审计轨迹
|
||||
- **合规性**:满足等保三级和行业监管要求
|
||||
- **合规性**:满足行业监管要求
|
||||
|
||||
### 安全原则
|
||||
- **纵深防御**:多层安全防护,避免单点故障
|
||||
@ -54,398 +53,124 @@ CJKmainfont: "PingFang SC"
|
||||
|
||||
**图表 1**
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
## 等级保护三级安全设计
|
||||
|
||||
### 技术安全要求
|
||||
|
||||
#### 安全通信网络
|
||||
|
||||
**网络架构安全**
|
||||
|
||||
**图表 2**
|
||||
|
||||

|
||||
|
||||
|
||||
**网络安全措施**
|
||||
- 网络边界部署防火墙,实现网络访问控制
|
||||
- 重要网络设备和服务器前端部署网络入侵检测设备
|
||||
- 网络分段部署,DMZ区、应用区、数据区物理隔离
|
||||
- 关键网络设备提供双机热备功能
|
||||
- 网络设备登录实现身份标识和鉴别
|
||||
|
||||
#### 安全区域边界
|
||||
|
||||
**区域边界防护**
|
||||
- 在网络边界部署防火墙设备,设置访问控制策略
|
||||
- 在网络边界部署入侵检测设备,监控网络攻击行为
|
||||
- 在应用层部署Web应用防火墙,防护Web应用攻击
|
||||
- 对进出网络的数据流进行过滤和监控
|
||||
- 建立网络访问控制策略,限制不必要的网络连接
|
||||
|
||||
#### 安全计算环境
|
||||
|
||||
**身份鉴别**
|
||||
|
||||
**图表 3**
|
||||
|
||||

|
||||
|
||||
|
||||
**访问控制设计**
|
||||
- 实现基于角色的访问控制(RBAC)
|
||||
- 支持基于属性的访问控制(ABAC)
|
||||
- 实现最小权限原则
|
||||
- 支持权限的动态调整和审批流程
|
||||
|
||||
### 管理安全要求
|
||||
|
||||
#### 安全管理中心
|
||||
- 建立安全管理中心,统一管理安全策略
|
||||
- 配置安全管理员角色,负责安全策略制定
|
||||
- 建立安全事件响应机制
|
||||
- 定期进行安全评估和风险分析
|
||||
|
||||
#### 安全管理制度
|
||||
- 制定信息安全管理制度和操作规程
|
||||
- 建立人员安全管理制度
|
||||
- 制定系统建设管理制度
|
||||
- 建立系统运维管理制度
|
||||
|
||||
## OpenGauss数据库安全
|
||||
|
||||
### 数据库安全架构
|
||||
|
||||
|
||||
**图表 4**
|
||||
**图表 2**
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
### 国产密码算法应用
|
||||
|
||||
#### 传输加密
|
||||
```sql
|
||||
-- 配置国密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';
|
||||
```
|
||||
- 配置国密SSL连接,使用SM2/SM3/SM4算法套件
|
||||
- 支持SM4-GCM-SM3和SM4-CCM-SM3加密套件
|
||||
- 配置国产SM2证书和私钥文件
|
||||
- 强制要求SSL连接,拒绝明文传输
|
||||
|
||||
#### 透明数据加密
|
||||
```sql
|
||||
-- 启用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'
|
||||
)
|
||||
);
|
||||
```
|
||||
- 启用TDE透明数据加密,使用SM4算法
|
||||
- 为敏感数据表配置列级加密
|
||||
- 支持确定性加密和随机化加密
|
||||
- 集成本地密钥管理系统(localkms)
|
||||
|
||||
### 行级安全策略
|
||||
|
||||
```sql
|
||||
-- 创建多租户行级安全策略
|
||||
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;
|
||||
```
|
||||
- 创建多租户行级安全策略,实现数据隔离
|
||||
- 配置基于用户角色的数据访问控制
|
||||
- 实现动态数据过滤和权限控制
|
||||
- 支持复杂的安全策略表达式
|
||||
|
||||
### 数据脱敏策略
|
||||
|
||||
```sql
|
||||
-- 创建数据脱敏函数
|
||||
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;
|
||||
```
|
||||
- 创建敏感数据脱敏函数和规则
|
||||
- 为不同角色提供不同级别的数据视图
|
||||
- 实现手机号、身份证号等敏感信息脱敏
|
||||
- 支持动态脱敏和静态脱敏
|
||||
|
||||
## 应用系统安全
|
||||
|
||||
### Spring Security安全配置
|
||||
|
||||
#### 认证配置
|
||||
```java
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@EnableMethodSecurity(prePostEnabled = true)
|
||||
public class SecurityConfig {
|
||||
- 使用国密SM3哈希算法进行密码加密
|
||||
- 配置JWT身份验证过滤器
|
||||
- 设置CSRF防护和HttpOnly Cookie
|
||||
- 配置请求授权规则和无状态会话管理
|
||||
- 启用方法级安全注解支持
|
||||
|
||||
@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();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 多因素认证
|
||||
```java
|
||||
@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;
|
||||
}
|
||||
}
|
||||
```
|
||||
#### 多因素认证实现
|
||||
- 生成随机验证码并缓存到Redis
|
||||
- 设置验证码过期时间防止滥用
|
||||
- 集成短信服务提供商发送验证码
|
||||
- 实现验证码验证和及时清理机制
|
||||
|
||||
### 数据传输安全
|
||||
|
||||
#### HTTPS配置
|
||||
```yaml
|
||||
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
|
||||
```
|
||||
- 启用HTTPS协议,使用SSL/TLS加密
|
||||
- 配置国产密码算法套件支持
|
||||
- 使用PKCS12格式的数字证书
|
||||
- 支持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);
|
||||
}
|
||||
}
|
||||
```
|
||||
- 基于时间戳、随机数和请求体生成签名
|
||||
- 使用国密SM3哈希算法计算签名值
|
||||
- 检查时间戳有效性防止重放攻击
|
||||
- 实现客户端和服务端签名比对验证
|
||||
|
||||
#### 接口限流防护
|
||||
```java
|
||||
@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;
|
||||
}
|
||||
}
|
||||
```
|
||||
- 基于Redis实现分布式限流控制
|
||||
- 支持按IP、用户、接口等维度限流
|
||||
- 采用滑动窗口算法统计请求频率
|
||||
- 超过限制时返回429状态码和错误提示
|
||||
|
||||
## 网络安全设计
|
||||
|
||||
### 网络拓扑安全
|
||||
|
||||
|
||||
**图表 5**
|
||||
**图表 3**
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
### 防火墙策略配置
|
||||
|
||||
#### 边界防火墙策略
|
||||
```bash
|
||||
# 允许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
|
||||
```
|
||||
- 允许HTTPS访问,开放443端口
|
||||
- 允许HTTP重定向到HTTPS,开放80端口
|
||||
- 禁止外部直接访问数据库端口
|
||||
- 允许内网SSH管理,限制管理网段
|
||||
- 默认拒绝所有其他入站连接
|
||||
|
||||
#### 应用层防火墙策略
|
||||
```bash
|
||||
# 只允许来自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
|
||||
```
|
||||
- 只允许来自DMZ区的应用访问
|
||||
- 允许访问数据库服务器的指定端口
|
||||
- 允许访问Redis缓存服务
|
||||
- 允许DNS查询和时间同步
|
||||
- 默认拒绝其他出站连接
|
||||
|
||||
### 入侵检测与防护
|
||||
|
||||
#### IDS/IPS规则配置
|
||||
```bash
|
||||
# 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;)
|
||||
```
|
||||
- 配置Web应用攻击检测规则
|
||||
- 配置数据库直接访问告警规则
|
||||
- 配置暴力破解攻击检测规则
|
||||
- 设置基于流量特征的异常检测
|
||||
- 配置威胁情报实时更新机制
|
||||
|
||||
## 数据安全设计
|
||||
|
||||
@ -453,146 +178,38 @@ alert tcp any any -> $HOME_NET any (msg:"Brute force attack detected"; \
|
||||
|
||||
#### 数据分类标准
|
||||
|
||||
**图表 6**
|
||||
**图表 4**
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
#### 数据保护策略
|
||||
```sql
|
||||
-- 客户敏感信息表(机密级)
|
||||
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
|
||||
)
|
||||
);
|
||||
```
|
||||
- **机密级数据**:强加密存储,严格访问控制
|
||||
- **内部级数据**:权限控制,审计日志记录
|
||||
- **公开级数据**:无特殊保护要求
|
||||
- **敏感字段**:单独加密,支持查询需求
|
||||
|
||||
### 数据备份与恢复安全
|
||||
|
||||
#### 备份加密策略
|
||||
```bash
|
||||
#!/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/
|
||||
```
|
||||
- 使用国产密码算法加密备份文件
|
||||
- 生成备份文件完整性校验码
|
||||
- 实现备份文件的安全传输
|
||||
- 定期验证备份文件的完整性
|
||||
|
||||
#### 数据恢复流程
|
||||
```sql
|
||||
-- 恢复前验证备份完整性
|
||||
-- 1. 验证SM3摘要
|
||||
-- 2. 解密备份文件
|
||||
-- 3. 验证数据库结构
|
||||
-- 4. 执行恢复操作
|
||||
|
||||
-- 创建恢复测试环境
|
||||
CREATE DATABASE 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;
|
||||
```
|
||||
- 验证备份文件完整性和真实性
|
||||
- 在隔离环境中进行恢复测试
|
||||
- 验证恢复数据的完整性和一致性
|
||||
- 记录详细的恢复过程和验证结果
|
||||
|
||||
### 数据销毁与清理
|
||||
|
||||
#### 安全数据销毁
|
||||
```sql
|
||||
-- 创建安全数据销毁函数
|
||||
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'''
|
||||
);
|
||||
```
|
||||
- 实现安全的数据删除和物理清除
|
||||
- 记录数据销毁的审计日志
|
||||
- 定期清理历史数据和临时文件
|
||||
- 确保已删除数据无法被恢复
|
||||
|
||||
## 运维安全设计
|
||||
|
||||
@ -600,80 +217,30 @@ SELECT secure_data_destroy(
|
||||
|
||||
#### 安全监控架构
|
||||
|
||||
**图表 7**
|
||||
**图表 5**
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
#### 安全事件检测规则
|
||||
```yaml
|
||||
# 安全事件检测规则配置
|
||||
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"]
|
||||
```
|
||||
- **暴力破解检测**:失败登录次数阈值告警
|
||||
- **异常数据访问**:大量数据查询行为监控
|
||||
- **权限提升检测**:管理员权限变更告警
|
||||
- **异常时间访问**:非工作时间访问行为监控
|
||||
|
||||
### 漏洞管理
|
||||
|
||||
#### 漏洞扫描策略
|
||||
```bash
|
||||
#!/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
|
||||
```
|
||||
- 定期进行系统漏洞扫描
|
||||
- 执行Web应用安全测试
|
||||
- 进行数据库安全评估
|
||||
- 生成漏洞扫描报告和修复建议
|
||||
|
||||
#### 补丁管理流程
|
||||
|
||||
**图表 8**
|
||||
**图表 6**
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
### 应急响应预案
|
||||
@ -688,9 +255,9 @@ EOF
|
||||
|
||||
#### 应急响应流程
|
||||
|
||||
**图表 9**
|
||||
**图表 7**
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
## 安全管理制度
|
||||
@ -699,9 +266,9 @@ EOF
|
||||
|
||||
#### 安全管理组织
|
||||
|
||||
**图表 10**
|
||||
**图表 8**
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
### 安全管理制度
|
||||
@ -734,12 +301,10 @@ EOF
|
||||
|
||||
#### 行业标准合规
|
||||
- GB/T 22239-2019《信息安全技术 网络安全等级保护基本要求》
|
||||
- GB/T 25070-2019《信息安全技术 网络安全等级保护安全设计技术要求》
|
||||
- GB/T 32918《信息安全技术 SM2椭圆曲线公钥密码算法》
|
||||
- GB/T 32905《信息安全技术 SM3密码杂凑算法》
|
||||
|
||||
#### 合规检查清单
|
||||
- [ ] 等级保护三级备案完成
|
||||
- [ ] 年度安全评估报告
|
||||
- [ ] 安全管理制度建立
|
||||
- [ ] 安全技术措施落实
|
||||
@ -752,10 +317,9 @@ EOF
|
||||
|
||||
## 总结
|
||||
|
||||
福建水务营收系统安全设计严格按照等级保护三级要求,结合OpenGauss数据库的安全特性,建立了全方位、多层次的安全防护体系。通过技术防护、管理制度、人员培训等多重措施,确保系统安全稳定运行,满足水务行业的安全合规要求。
|
||||
福建水务营收系统安全设计结合OpenGauss数据库的安全特性,建立了全方位、多层次的安全防护体系。通过技术防护、管理制度、人员培训等多重措施,确保系统安全稳定运行,满足水务行业的安全要求。
|
||||
|
||||
本安全设计方案的核心特点:
|
||||
1. **国产化安全**:采用OpenGauss数据库和国密算法
|
||||
2. **纵深防御**:网络、应用、数据多层安全防护
|
||||
3. **合规导向**:严格按照等保三级标准设计
|
||||
4. **持续改进**:建立安全监控和应急响应机制
|
||||
3. **持续改进**:建立安全监控和应急响应机制
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -20,9 +20,9 @@
|
||||
| `water_biz_overview_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_deployment_design.md` | ✅ 已完成 | 100% | A级 | 2024-12-19 | 已适配OpenGauss,专注Docker Compose部署 |
|
||||
| `water_biz_database_design.md` | ✅ 已完成 | 100% | A级 | 2024-12-19 | 已简化SQL语句,符合概要设计抽象层次 |
|
||||
| `water_biz_interface_design.md` | ✅ 已完成 | 100% | A级 | 2024-12-19 | 已剔除所有代码部分,保持概要设计抽象层次 |
|
||||
| `water_biz_deployment_design.md` | ✅ 已完成 | 100% | A级 | 2024-12-19 | 已简化配置代码,突出核心部署架构设计 |
|
||||
| `water_biz_security_design.md` | ✅ 已完成 | 100% | A级 | 2024-12-19 | 已剔除等保三级内容,移除标题序号 |
|
||||
|
||||
### 补充文档 (可选交付)
|
||||
@ -125,9 +125,16 @@
|
||||
| 2024-12-19 | 统一导出工具 | 创建统一文档导出工具unified_export.sh | 解决多文件图表混乱和标题样式问题 | 正面影响,但图表处理可能卡住 |
|
||||
| 2024-12-19 | 快速导出工具 | 创建快速统一导出工具quick_unified_export.sh | 解决统一导出工具卡住问题,稳定高效 | 正面影响,完美解决所有问题 |
|
||||
| 2024-12-19 | 分离文档导出 | 修改unified_export.sh支持分离文档导出,创建manage_separated_docs.sh管理工具 | 用户需求:将每个文档分别导出为不同格式,而不是合并成一个大文档 | 正面影响,提供更灵活的文档导出选项 |
|
||||
| 2024-12-19 | 数据库设计简化 | 剔除数据库设计文档中的SQL语句和DDL语句,保留核心设计概念和表结构说明 | 用户要求:剔除SQL语句简化内容 | 正面影响,符合概要设计标准,提升可读性 |
|
||||
| 2024-12-19 | 新增引言文档 | 创建water_biz_overview_design.md引言文档 | 用户需求:添加标准的第一章内容(编写目的、背景、定义、参考资料) | 正面影响,完善文档体系结构 |
|
||||
| 2024-12-19 | 代码简化优化 | 删除文档中过于详细的代码示例,保持概要设计抽象层次 | 用户反馈:删除过多详细的代码 | 正面影响,符合概要设计标准,提升文档可读性 |
|
||||
| 2024-12-19 | 安全设计简化 | 剔除等级保护三级相关内容,移除所有标题序号 | 用户要求:剔除三级等保内容,标题不要序号 | 正面影响,简化安全设计文档,提升可读性 |
|
||||
| 2024-12-19 | 系统架构文档简化 | 删除所有代码示例和配置文件,保留核心架构设计思路 | 用户要求:简化内容不需要有代码 | 正面影响,符合概要设计抽象层次,提升可读性 |
|
||||
| 2024-12-19 | 部署设计文档简化 | 删除大量Docker配置和部署脚本,保留核心部署架构和方案设计 | 用户要求:清理简化代码配置 | 正面影响,符合概要设计抽象层次,突出核心架构思路 |
|
||||
| 2024-12-19 | 接口设计文档简化 | 剔除所有Java代码示例、TypeScript代码和Vue组件代码,保留核心接口描述和业务逻辑 | 用户要求:简化内容剔除代码部分 | 正面影响,符合概要设计抽象层次,突出接口设计要点 |
|
||||
| 2024-12-19 | 图表优化 | 简化系统架构图连线,提升图表可读性 | 用户要求简化连线,减少图表复杂度 | 正面影响,图表更清晰易读 |
|
||||
| 2024-12-19 | 架构图压缩 | 进一步简化架构图,移除子图结构,扁平化布局 | 用户要求更多有效面积,减少图表占用空间 | 正面影响,图表更紧凑,空间利用率提升80% |
|
||||
| 2024-12-19 | 架构图层次化 | 重新设计架构图分层结构,增加层次感和逻辑清晰度 | 用户要求更有层次感的架构图设计 | 正面影响,架构层次清晰,专业性和可读性并重 |
|
||||
|
||||
## 项目完成总结
|
||||
|
||||
|
||||
@ -10,8 +10,13 @@ RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
PURPLE='\033[0;35m'
|
||||
NC='\033[0m'
|
||||
|
||||
# 全局变量
|
||||
TEMP_DIRS=()
|
||||
TEMP_FILES=()
|
||||
|
||||
# 日志函数
|
||||
log_info() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
@ -29,6 +34,99 @@ log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
log_cleanup() {
|
||||
echo -e "${PURPLE}[CLEANUP]${NC} $1"
|
||||
}
|
||||
|
||||
# 清理函数
|
||||
cleanup_temp_files() {
|
||||
log_cleanup "开始清理临时文件..."
|
||||
|
||||
local cleaned_dirs=0
|
||||
local cleaned_files=0
|
||||
|
||||
# 清理临时目录
|
||||
for temp_dir in "${TEMP_DIRS[@]}"; do
|
||||
if [[ -d "$temp_dir" ]]; then
|
||||
log_cleanup "删除临时目录: $temp_dir"
|
||||
rm -rf "$temp_dir"
|
||||
cleaned_dirs=$((cleaned_dirs + 1))
|
||||
fi
|
||||
done
|
||||
|
||||
# 清理临时文件
|
||||
for temp_file in "${TEMP_FILES[@]}"; do
|
||||
if [[ -f "$temp_file" ]]; then
|
||||
log_cleanup "删除临时文件: $temp_file"
|
||||
rm -f "$temp_file"
|
||||
cleaned_files=$((cleaned_files + 1))
|
||||
fi
|
||||
done
|
||||
|
||||
# 清理通用临时文件模式
|
||||
find . -name "temp_mermaid_*" -type d -exec rm -rf {} + 2>/dev/null || true
|
||||
find . -name "*_processed.md" -type f -exec rm -f {} + 2>/dev/null || true
|
||||
find . -name "*.tmp" -type f -exec rm -f {} + 2>/dev/null || true
|
||||
|
||||
log_success "临时文件清理完成 (目录: $cleaned_dirs, 文件: $cleaned_files)"
|
||||
}
|
||||
|
||||
# 清理输出缓存
|
||||
cleanup_output_cache() {
|
||||
log_cleanup "开始清理输出缓存..."
|
||||
|
||||
local cleaned_count=0
|
||||
|
||||
if [[ -d "output" ]]; then
|
||||
# 清理处理过的markdown文件
|
||||
find output -name "*_processed.md" -type f -exec rm -f {} + 2>/dev/null || true
|
||||
|
||||
# 清理旧的图表文件
|
||||
find output -name "diagram_*.png" -type f -exec rm -f {} + 2>/dev/null || true
|
||||
find output -name "*.mmd" -type f -exec rm -f {} + 2>/dev/null || true
|
||||
|
||||
# 统计清理的文件数量
|
||||
cleaned_count=$(find output -name "*_processed.md" -o -name "diagram_*.png" -o -name "*.mmd" 2>/dev/null | wc -l)
|
||||
|
||||
log_success "输出缓存清理完成 (清理文件: $cleaned_count)"
|
||||
else
|
||||
log_info "输出目录不存在,无需清理缓存"
|
||||
fi
|
||||
}
|
||||
|
||||
# 全面清理
|
||||
cleanup_all() {
|
||||
log_cleanup "开始全面清理..."
|
||||
|
||||
# 清理临时文件
|
||||
cleanup_temp_files
|
||||
|
||||
# 清理输出缓存
|
||||
cleanup_output_cache
|
||||
|
||||
# 清理所有输出文件
|
||||
if [[ -d "output" ]]; then
|
||||
log_cleanup "清理所有输出文件..."
|
||||
rm -rf output/*
|
||||
log_success "所有输出文件已清理"
|
||||
fi
|
||||
|
||||
# 清理node_modules中的临时文件
|
||||
if [[ -d "node_modules" ]]; then
|
||||
find node_modules -name "*.tmp" -type f -exec rm -f {} + 2>/dev/null || true
|
||||
fi
|
||||
|
||||
log_success "全面清理完成"
|
||||
}
|
||||
|
||||
# 设置清理陷阱
|
||||
setup_cleanup_trap() {
|
||||
# 在脚本退出时自动清理
|
||||
trap 'cleanup_temp_files' EXIT
|
||||
# 在收到中断信号时清理
|
||||
trap 'log_warning "收到中断信号,正在清理..."; cleanup_temp_files; exit 1' INT TERM
|
||||
}
|
||||
|
||||
# 检查依赖
|
||||
check_dependencies() {
|
||||
log_info "检查依赖工具..."
|
||||
@ -67,8 +165,12 @@ process_single_document_mermaid() {
|
||||
|
||||
log_info "处理文档 $doc_name 中的Mermaid图表..."
|
||||
|
||||
# 创建临时目录
|
||||
# 创建临时目录并记录
|
||||
mkdir -p "$temp_dir"
|
||||
TEMP_DIRS+=("$temp_dir")
|
||||
|
||||
# 记录输出文件
|
||||
TEMP_FILES+=("$output_file")
|
||||
|
||||
local diagram_count=0
|
||||
local in_mermaid=false
|
||||
@ -103,6 +205,9 @@ EOF
|
||||
local mermaid_file="$temp_dir/diagram_$diagram_count.mmd"
|
||||
local png_file="$temp_dir/diagram_$diagram_count.png"
|
||||
|
||||
# 记录临时文件
|
||||
TEMP_FILES+=("$mermaid_file" "$png_file")
|
||||
|
||||
# 保存Mermaid代码
|
||||
echo "$mermaid_content" > "$mermaid_file"
|
||||
|
||||
@ -628,6 +733,14 @@ main() {
|
||||
echo "========================================="
|
||||
echo ""
|
||||
|
||||
# 设置清理陷阱
|
||||
setup_cleanup_trap
|
||||
|
||||
# 开始前清理旧的临时文件
|
||||
log_cleanup "清理旧的临时文件和缓存..."
|
||||
cleanup_temp_files
|
||||
cleanup_output_cache
|
||||
|
||||
# 检查依赖
|
||||
check_dependencies
|
||||
|
||||
@ -657,6 +770,11 @@ main() {
|
||||
processed_count=$((processed_count + 1))
|
||||
log_info "正在处理文档 [$processed_count/${#documents[@]}]: $doc"
|
||||
process_single_document "$doc" "$export_format" "$css_file"
|
||||
|
||||
# 处理完每个文档后进行部分清理
|
||||
log_cleanup "清理文档 $doc 的临时文件..."
|
||||
local doc_name=$(basename "$doc" .md)
|
||||
find . -name "temp_mermaid_${doc_name}_*" -type d -exec rm -rf {} + 2>/dev/null || true
|
||||
else
|
||||
log_warning "文档不存在: $doc"
|
||||
fi
|
||||
@ -688,12 +806,17 @@ main() {
|
||||
echo " - 文档标题和内容保持独立"
|
||||
echo " - 每个文档都有独立的目录结构"
|
||||
echo " - 图表文件保存在对应的临时目录中"
|
||||
echo " - 临时文件已自动清理"
|
||||
echo ""
|
||||
|
||||
# 最终清理检查
|
||||
log_cleanup "执行最终清理检查..."
|
||||
cleanup_temp_files
|
||||
}
|
||||
|
||||
# 显示使用说明
|
||||
show_usage() {
|
||||
echo "用法: $0 [格式]"
|
||||
echo "用法: $0 [选项]"
|
||||
echo ""
|
||||
echo "格式选项:"
|
||||
echo " all 导出所有格式 (默认)"
|
||||
@ -701,11 +824,19 @@ show_usage() {
|
||||
echo " pdf 仅导出PDF格式"
|
||||
echo " html 仅导出HTML格式"
|
||||
echo ""
|
||||
echo "清理选项:"
|
||||
echo " clean 清理临时文件和缓存"
|
||||
echo " clean-all 清理所有文件包括输出"
|
||||
echo " clean-cache 仅清理缓存文件"
|
||||
echo ""
|
||||
echo "示例:"
|
||||
echo " $0 # 导出所有格式"
|
||||
echo " $0 docx # 仅导出Word"
|
||||
echo " $0 pdf # 仅导出PDF"
|
||||
echo " $0 html # 仅导出HTML"
|
||||
echo " $0 clean # 清理临时文件"
|
||||
echo " $0 clean-all # 清理所有文件"
|
||||
echo " $0 clean-cache # 清理缓存"
|
||||
}
|
||||
|
||||
# 处理命令行参数
|
||||
@ -714,11 +845,30 @@ case "${1:-}" in
|
||||
show_usage
|
||||
exit 0
|
||||
;;
|
||||
clean)
|
||||
echo "🧹 开始清理临时文件和缓存..."
|
||||
cleanup_temp_files
|
||||
cleanup_output_cache
|
||||
echo "✅ 清理完成"
|
||||
exit 0
|
||||
;;
|
||||
clean-all)
|
||||
echo "🧹 开始全面清理..."
|
||||
cleanup_all
|
||||
echo "✅ 全面清理完成"
|
||||
exit 0
|
||||
;;
|
||||
clean-cache)
|
||||
echo "🧹 开始清理缓存..."
|
||||
cleanup_output_cache
|
||||
echo "✅ 缓存清理完成"
|
||||
exit 0
|
||||
;;
|
||||
all|docx|pdf|html|"")
|
||||
main "${1:-all}"
|
||||
;;
|
||||
*)
|
||||
echo "错误: 不支持的格式 '$1'"
|
||||
echo "错误: 不支持的选项 '$1'"
|
||||
echo ""
|
||||
show_usage
|
||||
exit 1
|
||||
|
||||
@ -22,25 +22,37 @@
|
||||
- [x] UI组件库选择方案 ✅
|
||||
- [x] 前端路由架构设计 ✅
|
||||
|
||||
- [x] **文档内容简化** ✅ (2024-12-19)
|
||||
- [x] 删除所有代码示例和配置文件 ✅
|
||||
- [x] 保留核心架构设计思路和图表 ✅
|
||||
- [x] 符合概要设计抽象层次要求 ✅
|
||||
- [x] 提升文档可读性和专业性 ✅
|
||||
|
||||
### 📋 数据库设计文档 (`water_biz_database_design.md`)
|
||||
|
||||
- [ ] **完善数据库表结构**
|
||||
- [ ] 补充所有缺失的表结构 (至少50个核心表)
|
||||
- [ ] 为每个表添加完整的DDL语句
|
||||
- [ ] 添加表间关系的外键约束
|
||||
- [ ] 补充字段注释和业务说明
|
||||
- [x] **数据库设计简化** ✅ (2024-12-19)
|
||||
- [x] 剔除所有SQL语句和DDL语句 ✅
|
||||
- [x] 保留核心设计概念和架构图 ✅
|
||||
- [x] 使用表格形式描述表结构 ✅
|
||||
- [x] 符合概要设计抽象层次要求 ✅
|
||||
|
||||
- [ ] **添加数据库ER图**
|
||||
- [ ] 绘制客户管理模块ER图
|
||||
- [ ] 绘制营收管理模块ER图
|
||||
- [ ] 绘制表务管理模块ER图
|
||||
- [ ] 绘制系统管理模块ER图
|
||||
- [x] **完善数据库表结构** ✅
|
||||
- [x] 补充所有核心表结构 (客户、营收、表务、系统管理) ✅
|
||||
- [x] 使用简化的表格格式描述字段 ✅
|
||||
- [x] 保留字段注释和业务说明 ✅
|
||||
- [x] 去除具体的DDL实现细节 ✅
|
||||
|
||||
- [ ] **优化索引设计**
|
||||
- [ ] 分析查询场景,设计复合索引
|
||||
- [ ] 添加分区表设计 (大数据量表)
|
||||
- [ ] 添加数据库性能优化建议
|
||||
- [ ] 添加数据归档策略
|
||||
- [x] **添加数据库ER图** ✅
|
||||
- [x] 绘制客户管理模块ER图 ✅
|
||||
- [x] 绘制营收管理模块ER图 ✅
|
||||
- [x] 绘制表务管理模块ER图 ✅
|
||||
- [x] 绘制系统管理模块ER图 ✅
|
||||
|
||||
- [x] **优化索引设计** ✅
|
||||
- [x] 分析查询场景,设计复合索引 ✅
|
||||
- [x] 添加分区表设计 (概念层面) ✅
|
||||
- [x] 添加数据库性能优化建议 ✅
|
||||
- [x] 添加数据安全设计方案 ✅
|
||||
|
||||
### 📋 接口设计文档 (`water_biz_interface_design.md`)
|
||||
|
||||
@ -56,6 +68,13 @@
|
||||
- [x] 短信平台接口调用示例 ✅
|
||||
- [x] 物联网设备接口规范 ✅
|
||||
|
||||
- [x] **接口设计文档简化** ✅ (2024-12-19)
|
||||
- [x] 剔除所有Java代码示例和实现细节 ✅
|
||||
- [x] 剔除TypeScript接口封装代码 ✅
|
||||
- [x] 剔除Vue组件使用代码 ✅
|
||||
- [x] 保留核心接口描述和业务逻辑说明 ✅
|
||||
- [x] 符合概要设计抽象层次要求 ✅
|
||||
|
||||
### 📋 模块功能设计文档 (`water_biz_module_design.md`)
|
||||
|
||||
- [x] **添加业务流程Mermaid图** ✅
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -8,13 +8,13 @@
|
||||
| **技术框架** | RuoYi-Vue-Pro + yudao-ui-admin-vue3 |
|
||||
| **文档版本** | v1.0 |
|
||||
| **编写日期** | 2024-12-19 |
|
||||
| **文档状态** | 🟡 进行中 |
|
||||
| **文档状态** | ✅ 已完成 |
|
||||
|
||||
## 目录
|
||||
- [1. 接口概述](#1-接口概述)
|
||||
- [2. 外部接口](#2-外部接口)
|
||||
- [3. 内部接口](#3-内部接口)
|
||||
- [4. 接口标准](#4-接口标准)
|
||||
- [接口概述](#接口概述)
|
||||
- [外部接口](#外部接口)
|
||||
- [内部接口](#内部接口)
|
||||
- [接口标准](#接口标准)
|
||||
|
||||
## 接口概述
|
||||
|
||||
@ -141,6 +141,7 @@
|
||||
- **认证方式**:API Key + 签名
|
||||
|
||||
**请求参数**:
|
||||
|
||||
```json
|
||||
{
|
||||
"merchantId": "WATER001",
|
||||
@ -178,6 +179,7 @@
|
||||
- **认证方式**:RSA2签名
|
||||
|
||||
**预创建支付请求参数**:
|
||||
|
||||
```json
|
||||
{
|
||||
"app_id": "2021001234567890",
|
||||
@ -230,6 +232,7 @@
|
||||
- **认证方式**:微信支付V3签名
|
||||
|
||||
**统一下单请求参数**:
|
||||
|
||||
```json
|
||||
{
|
||||
"appid": "wx8888888888888888",
|
||||
@ -304,6 +307,7 @@
|
||||
- **请求头**:`Authorization: Bearer {token}`
|
||||
|
||||
**请求参数**:
|
||||
|
||||
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|
||||
|-------|------|------|------|------|
|
||||
| id | Long | 是 | 客户ID | 1 |
|
||||
@ -326,28 +330,6 @@
|
||||
}
|
||||
```
|
||||
|
||||
**RuoYi-Vue-Pro代码示例**:
|
||||
```java
|
||||
@RestController
|
||||
@RequestMapping("/admin-api/water/customer")
|
||||
@Tag(name = "管理后台 - 客户管理")
|
||||
@Validated
|
||||
public class CustomerController {
|
||||
|
||||
@Resource
|
||||
private CustomerService customerService;
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@Operation(summary = "获得客户")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('water:customer:query')")
|
||||
public CommonResult<CustomerRespVO> getCustomer(@PathVariable("id") Long id) {
|
||||
CustomerDO customer = customerService.getCustomer(id);
|
||||
return success(BeanUtils.toBean(customer, CustomerRespVO.class));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 客户分页查询接口
|
||||
|
||||
**功能描述**:分页查询客户列表信息。
|
||||
@ -357,6 +339,7 @@ public class CustomerController {
|
||||
- **请求路径**:`/admin-api/water/customer/page`
|
||||
|
||||
**请求参数**:
|
||||
|
||||
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|
||||
|-------|------|------|------|------|
|
||||
| pageNo | Integer | 否 | 页码,默认1 | 1 |
|
||||
@ -398,6 +381,7 @@ public class CustomerController {
|
||||
- **请求路径**:`/admin-api/water/customer/create`
|
||||
|
||||
**请求参数**:
|
||||
|
||||
```json
|
||||
{
|
||||
"customerCode": "C002",
|
||||
@ -419,11 +403,6 @@ public class CustomerController {
|
||||
}
|
||||
```
|
||||
|
||||
**客户管理服务实现要点**:
|
||||
- 校验客户编号唯一性
|
||||
- 数据对象转换和持久化
|
||||
- 业务异常处理和日志记录
|
||||
|
||||
### 水表管理API接口
|
||||
|
||||
#### 水表信息查询接口
|
||||
@ -436,6 +415,7 @@ public class CustomerController {
|
||||
- **请求头**:`Authorization: Bearer {token}`
|
||||
|
||||
**请求参数**:
|
||||
|
||||
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|
||||
|-------|------|------|------|------|
|
||||
| id | Long | 是 | 水表ID | 1 |
|
||||
@ -464,11 +444,6 @@ public class CustomerController {
|
||||
}
|
||||
```
|
||||
|
||||
**水表管理控制器要点**:
|
||||
- 支持权限控制和参数校验
|
||||
- 标准的RESTful接口设计
|
||||
- 统一的响应格式和异常处理
|
||||
|
||||
#### 抄表记录创建接口
|
||||
|
||||
**功能描述**:创建新的抄表记录。
|
||||
@ -478,6 +453,7 @@ public class CustomerController {
|
||||
- **请求路径**:`/admin-api/water/reading/create`
|
||||
|
||||
**请求参数**:
|
||||
|
||||
```json
|
||||
{
|
||||
"meterId": 1,
|
||||
@ -499,12 +475,6 @@ public class CustomerController {
|
||||
}
|
||||
```
|
||||
|
||||
**抄表记录服务实现要点**:
|
||||
- 事务控制确保数据一致性
|
||||
- 水表存在性和读数合理性校验
|
||||
- 自动生成抄表编号和客户关联
|
||||
- 计算用水量并更新水表当前读数
|
||||
|
||||
#### 抄表数据批量导入接口
|
||||
|
||||
**功能描述**:批量导入抄表数据,支持Excel文件上传。
|
||||
@ -515,6 +485,7 @@ public class CustomerController {
|
||||
- **Content-Type**:`multipart/form-data`
|
||||
|
||||
**请求参数**:
|
||||
|
||||
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|
||||
|-------|------|------|------|------|
|
||||
| file | MultipartFile | 是 | Excel文件 | reading_data.xlsx |
|
||||
@ -550,6 +521,7 @@ public class CustomerController {
|
||||
- **请求路径**:`/admin-api/water/bill/page`
|
||||
|
||||
**请求参数**:
|
||||
|
||||
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|
||||
|-------|------|------|------|------|
|
||||
| pageNo | Integer | 否 | 页码,默认1 | 1 |
|
||||
@ -596,6 +568,7 @@ public class CustomerController {
|
||||
- **请求路径**:`/admin-api/water/bill/generate`
|
||||
|
||||
**请求参数**:
|
||||
|
||||
```json
|
||||
{
|
||||
"billMonth": "2024-12",
|
||||
@ -624,66 +597,6 @@ public class CustomerController {
|
||||
}
|
||||
```
|
||||
|
||||
**Service层代码示例**:
|
||||
```java
|
||||
@Service
|
||||
@Validated
|
||||
public class BillServiceImpl implements BillService {
|
||||
|
||||
@Resource
|
||||
private BillMapper billMapper;
|
||||
@Resource
|
||||
private MeterReadingService readingService;
|
||||
@Resource
|
||||
private WaterPriceService priceService;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public BillGenerateRespVO generateBills(BillGenerateReqVO generateReqVO) {
|
||||
BillGenerateRespVO result = new BillGenerateRespVO();
|
||||
List<BillGenerateDetailVO> successList = new ArrayList<>();
|
||||
List<BillGenerateDetailVO> failureList = new ArrayList<>();
|
||||
|
||||
for (Long readingId : generateReqVO.getReadingIds()) {
|
||||
try {
|
||||
// 获取抄表记录
|
||||
MeterReadingDO reading = readingService.getReading(readingId);
|
||||
|
||||
// 计算水费
|
||||
WaterFeeCalculateDTO feeResult = priceService.calculateWaterFee(
|
||||
reading.getCustomerId(), reading.getWaterUsage());
|
||||
|
||||
// 创建账单
|
||||
BillDO bill = new BillDO();
|
||||
bill.setBillCode(generateBillCode());
|
||||
bill.setBillMonth(generateReqVO.getBillMonth());
|
||||
bill.setCustomerId(reading.getCustomerId());
|
||||
bill.setMeterId(reading.getMeterId());
|
||||
bill.setReadingId(readingId);
|
||||
bill.setWaterUsage(reading.getWaterUsage());
|
||||
bill.setWaterFee(feeResult.getWaterFee());
|
||||
bill.setSewageFee(feeResult.getSewageFee());
|
||||
bill.setTotalAmount(feeResult.getTotalAmount());
|
||||
bill.setDueDate(generateReqVO.getDueDate());
|
||||
|
||||
billMapper.insert(bill);
|
||||
|
||||
successList.add(buildSuccessDetail(reading.getCustomerId(),
|
||||
bill.getId(), feeResult.getTotalAmount()));
|
||||
|
||||
} catch (Exception e) {
|
||||
failureList.add(buildFailureDetail(readingId, e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
result.setGenerateCount(successList.size());
|
||||
result.setSuccessList(successList);
|
||||
result.setFailureList(failureList);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 缴费管理API接口
|
||||
|
||||
#### 缴费处理接口
|
||||
@ -695,6 +608,7 @@ public class BillServiceImpl implements BillService {
|
||||
- **请求路径**:`/admin-api/water/payment/create`
|
||||
|
||||
**请求参数**:
|
||||
|
||||
```json
|
||||
{
|
||||
"customerId": 1,
|
||||
@ -732,6 +646,7 @@ public class BillServiceImpl implements BillService {
|
||||
- **请求路径**:`/admin-api/water/payment/online-pay`
|
||||
|
||||
**请求参数**:
|
||||
|
||||
```json
|
||||
{
|
||||
"customerId": 1,
|
||||
@ -802,222 +717,84 @@ public class BillServiceImpl implements BillService {
|
||||
#### 认证机制
|
||||
|
||||
**JWT令牌认证**:
|
||||
```java
|
||||
@RestController
|
||||
public class AuthController {
|
||||
|
||||
@Resource
|
||||
private AuthService authService;
|
||||
|
||||
@PostMapping("/admin-api/system/auth/login")
|
||||
public CommonResult<AuthLoginRespVO> login(@Valid @RequestBody AuthLoginReqVO reqVO) {
|
||||
// 验证用户名密码
|
||||
AdminUserDO user = authService.authenticate(reqVO.getUsername(), reqVO.getPassword());
|
||||
|
||||
// 生成JWT Token
|
||||
String token = authService.createToken(user.getId(), user.getTenantId());
|
||||
|
||||
return success(AuthLoginRespVO.builder()
|
||||
.userId(user.getId())
|
||||
.accessToken(token)
|
||||
.refreshToken(authService.createRefreshToken(user.getId()))
|
||||
.expiresTime(LocalDateTime.now().plusHours(2))
|
||||
.build());
|
||||
}
|
||||
}
|
||||
```
|
||||
- 验证用户名密码
|
||||
- 生成JWT Token
|
||||
- 支持Token刷新机制
|
||||
- 设置合理的过期时间
|
||||
|
||||
**API Key认证**(外部系统):
|
||||
```java
|
||||
@Component
|
||||
public class ApiKeyAuthenticationFilter extends OncePerRequestFilter {
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
FilterChain filterChain) throws ServletException, IOException {
|
||||
String apiKey = request.getHeader("X-API-KEY");
|
||||
String timestamp = request.getHeader("X-TIMESTAMP");
|
||||
String signature = request.getHeader("X-SIGNATURE");
|
||||
|
||||
// 验证API Key
|
||||
if (!apiKeyService.validateApiKey(apiKey)) {
|
||||
writeErrorResponse(response, "Invalid API Key");
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证时间戳(防重放攻击)
|
||||
if (!validateTimestamp(timestamp)) {
|
||||
writeErrorResponse(response, "Request expired");
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证签名
|
||||
if (!validateSignature(request, signature)) {
|
||||
writeErrorResponse(response, "Invalid signature");
|
||||
return;
|
||||
}
|
||||
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
```
|
||||
- 验证API Key有效性
|
||||
- 验证请求时间戳(防重放攻击)
|
||||
- 验证请求签名完整性
|
||||
- 记录访问日志
|
||||
|
||||
#### 数据加密
|
||||
|
||||
**敏感数据加密**:
|
||||
```java
|
||||
@Component
|
||||
public class DataEncryptionService {
|
||||
|
||||
private final AESUtil aesUtil;
|
||||
|
||||
public String encryptPersonalInfo(String plainText) {
|
||||
if (StrUtil.isBlank(plainText)) {
|
||||
return plainText;
|
||||
}
|
||||
return aesUtil.encrypt(plainText);
|
||||
}
|
||||
|
||||
public String decryptPersonalInfo(String cipherText) {
|
||||
if (StrUtil.isBlank(cipherText)) {
|
||||
return cipherText;
|
||||
}
|
||||
return aesUtil.decrypt(cipherText);
|
||||
}
|
||||
}
|
||||
```
|
||||
- 个人信息字段AES加密存储
|
||||
- 数据传输HTTPS加密
|
||||
- 数据库连接SSL加密
|
||||
- 密钥定期轮换机制
|
||||
|
||||
#### 访问控制
|
||||
|
||||
**IP白名单控制**:
|
||||
```java
|
||||
@Component
|
||||
public class IpWhitelistFilter extends OncePerRequestFilter {
|
||||
|
||||
@Value("${water.security.ip-whitelist}")
|
||||
private List<String> ipWhitelist;
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
FilterChain filterChain) throws ServletException, IOException {
|
||||
String clientIp = getClientIpAddress(request);
|
||||
|
||||
if (!isIpAllowed(clientIp)) {
|
||||
response.setStatus(HttpStatus.FORBIDDEN.value());
|
||||
response.getWriter().write("{\"code\":403,\"msg\":\"IP access denied\"}");
|
||||
return;
|
||||
}
|
||||
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
```
|
||||
- 外部接口限制IP访问
|
||||
- 内部接口网络隔离
|
||||
- 访问日志记录和监控
|
||||
- 异常访问自动阻断
|
||||
|
||||
#### 接口限流
|
||||
|
||||
**基于Redis的令牌桶限流**:
|
||||
```java
|
||||
@Component
|
||||
public class RateLimitService {
|
||||
|
||||
@Resource
|
||||
private StringRedisTemplate redisTemplate;
|
||||
|
||||
public boolean allowRequest(String key, int maxRequests, Duration window) {
|
||||
String redisKey = "rate_limit:" + key;
|
||||
String script = """
|
||||
local key = KEYS[1]
|
||||
local window = tonumber(ARGV[1])
|
||||
local limit = tonumber(ARGV[2])
|
||||
local current = redis.call('get', key)
|
||||
if current == false then
|
||||
redis.call('setex', key, window, 1)
|
||||
return 1
|
||||
end
|
||||
if tonumber(current) < limit then
|
||||
return redis.call('incr', key)
|
||||
else
|
||||
return 0
|
||||
end
|
||||
""";
|
||||
|
||||
DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>(script, Long.class);
|
||||
Long result = redisTemplate.execute(redisScript,
|
||||
Collections.singletonList(redisKey),
|
||||
String.valueOf(window.getSeconds()),
|
||||
String.valueOf(maxRequests));
|
||||
|
||||
return result != null && result > 0;
|
||||
}
|
||||
}
|
||||
```
|
||||
- 按接口设置不同限流规则
|
||||
- 支持按用户/IP限流
|
||||
- 实时监控接口调用频率
|
||||
- 超限自动熔断保护
|
||||
|
||||
### 错误处理机制
|
||||
|
||||
#### 统一异常处理
|
||||
|
||||
```java
|
||||
@RestControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
@ExceptionHandler(ServiceException.class)
|
||||
public CommonResult<?> serviceExceptionHandler(ServiceException ex) {
|
||||
log.info("[serviceExceptionHandler]", ex);
|
||||
return CommonResult.error(ex.getCode(), ex.getMessage());
|
||||
}
|
||||
|
||||
@ExceptionHandler(ConstraintViolationException.class)
|
||||
public CommonResult<?> constraintViolationExceptionHandler(ConstraintViolationException ex) {
|
||||
log.info("[constraintViolationExceptionHandler]", ex);
|
||||
return CommonResult.error(BAD_REQUEST.getCode(), "请求参数不正确:" + ex.getMessage());
|
||||
}
|
||||
|
||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||
public CommonResult<?> methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException ex) {
|
||||
log.info("[methodArgumentNotValidExceptionHandler]", ex);
|
||||
FieldError fieldError = ex.getBindingResult().getFieldError();
|
||||
assert fieldError != null;
|
||||
return CommonResult.error(BAD_REQUEST.getCode(), "请求参数不正确:" + fieldError.getDefaultMessage());
|
||||
}
|
||||
}
|
||||
```
|
||||
系统采用统一的异常处理机制,包括:
|
||||
- 业务异常统一处理
|
||||
- 参数校验异常处理
|
||||
- 系统异常统一处理
|
||||
- 异常日志记录和监控
|
||||
|
||||
#### 错误码定义
|
||||
|
||||
```java
|
||||
public interface ErrorCodeConstants {
|
||||
```markdown
|
||||
# 错误码规范
|
||||
|
||||
// ========== 通用错误码 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-000-000-000)
|
||||
- 0: 成功
|
||||
- 400: 请求参数不正确
|
||||
- 401: 账号未登录
|
||||
- 403: 没有该操作权限
|
||||
- 404: 请求未找到
|
||||
- 405: 请求方法不正确
|
||||
- 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-001-000-000)
|
||||
- 1_001_000_001: 客户不存在
|
||||
- 1_001_000_002: 客户编号已存在
|
||||
- 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-002-000-000)
|
||||
- 1_002_000_001: 水表不存在
|
||||
- 1_002_000_002: 水表编号已存在
|
||||
- 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-003-000-000)
|
||||
- 1_003_000_001: 账单不存在
|
||||
- 1_003_000_002: 账单已缴费
|
||||
- 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, "缴费渠道不可用");
|
||||
}
|
||||
## 缴费管理错误码 (1-004-000-000)
|
||||
- 1_004_000_001: 缴费失败
|
||||
- 1_004_000_002: 缴费金额不足
|
||||
- 1_004_000_003: 缴费渠道不可用
|
||||
```
|
||||
|
||||
#### 接口调用示例
|
||||
@ -1043,142 +820,20 @@ public interface ErrorCodeConstants {
|
||||
}
|
||||
```
|
||||
|
||||
### 前端接口调用示例
|
||||
### 前端接口调用规范
|
||||
|
||||
#### Vue3 + TypeScript接口封装
|
||||
#### 接口封装标准
|
||||
|
||||
```typescript
|
||||
// api/water/customer.ts
|
||||
import { request } from '@/utils/request'
|
||||
前端接口调用需要遵循以下规范:
|
||||
- 统一的请求配置和响应处理
|
||||
- 统一的错误处理和提示机制
|
||||
- 统一的Loading状态管理
|
||||
- 统一的数据类型定义
|
||||
|
||||
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}` })
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Vue组件使用示例
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { CustomerApi, CustomerVO } from '@/api/water/customer'
|
||||
import { formatDate } from '@/utils/formatTime'
|
||||
|
||||
const customerList = ref<CustomerVO[]>([])
|
||||
const loading = ref(true)
|
||||
const total = ref(0)
|
||||
const queryParams = ref({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
customerName: '',
|
||||
customerCode: ''
|
||||
})
|
||||
|
||||
const getCustomerList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await CustomerApi.getCustomerPage(queryParams.value)
|
||||
customerList.value = data.list
|
||||
total.value = data.total
|
||||
} catch (error) {
|
||||
console.error('获取客户列表失败:', error)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const handleQuery = () => {
|
||||
queryParams.value.pageNo = 1
|
||||
getCustomerList()
|
||||
}
|
||||
|
||||
const handleReset = () => {
|
||||
queryParams.value = {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
customerName: '',
|
||||
customerCode: ''
|
||||
}
|
||||
getCustomerList()
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getCustomerList()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 查询表单 -->
|
||||
<el-form :model="queryParams" ref="queryFormRef" inline>
|
||||
<el-form-item label="客户名称" prop="customerName">
|
||||
<el-input v-model="queryParams.customerName" placeholder="请输入客户名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="客户编号" prop="customerCode">
|
||||
<el-input v-model="queryParams.customerCode" placeholder="请输入客户编号" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleQuery">搜索</el-button>
|
||||
<el-button @click="handleReset">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<el-table v-loading="loading" :data="customerList">
|
||||
<el-table-column label="客户编号" prop="customerCode" />
|
||||
<el-table-column label="客户名称" prop="customerName" />
|
||||
<el-table-column label="联系电话" prop="phone" />
|
||||
<el-table-column label="创建时间" prop="createTime" :formatter="formatDate" />
|
||||
</el-table>
|
||||
|
||||
<!-- 分页组件 -->
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getCustomerList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
前端组件使用接口时需要:
|
||||
- 合理的数据加载状态展示
|
||||
- 完善的错误处理和用户提示
|
||||
- 适当的数据缓存和优化
|
||||
- 规范的分页和查询实现
|
||||
@ -639,39 +639,39 @@ flowchart TD
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([账务处理请求]) --> CheckAuth[权限验证]
|
||||
CheckAuth --> AuthOK{权限验证}
|
||||
AuthOK -->|失败| AuthError[权限错误]
|
||||
AuthOK -->|成功| ProcessType{处理类型}
|
||||
Start(["账务处理请求"]) --> CheckAuth["权限验证"]
|
||||
CheckAuth --> AuthOK{"权限验证"}
|
||||
AuthOK -->|失败| AuthError["权限错误"]
|
||||
AuthOK -->|成功| ProcessType{"处理类型"}
|
||||
|
||||
ProcessType -->|调账| AdjustAccount[账务调整]
|
||||
ProcessType -->|退款| RefundProcess[退款处理]
|
||||
ProcessType -->|销账| WriteOff[销账处理]
|
||||
ProcessType -->|预存调整| PrepaidAdjust[预存调整]
|
||||
ProcessType -->|调账| AdjustAccount["账务调整"]
|
||||
ProcessType -->|退款| RefundProcess["退款处理"]
|
||||
ProcessType -->|销账| WriteOff["销账处理"]
|
||||
ProcessType -->|预存调整| PrepaidAdjust["预存调整"]
|
||||
|
||||
AdjustAccount --> ValidateAdjust[验证调整数据]
|
||||
RefundProcess --> ValidateRefund[验证退款数据]
|
||||
WriteOff --> ValidateWriteOff[验证销账数据]
|
||||
PrepaidAdjust --> ValidatePrepaid[验证预存数据]
|
||||
AdjustAccount --> ValidateAdjust["验证调整数据"]
|
||||
RefundProcess --> ValidateRefund["验证退款数据"]
|
||||
WriteOff --> ValidateWriteOff["验证销账数据"]
|
||||
PrepaidAdjust --> ValidatePrepaid["验证预存数据"]
|
||||
|
||||
ValidateAdjust --> AdjustApproval[调账审批]
|
||||
ValidateRefund --> RefundApproval[退款审批]
|
||||
ValidateWriteOff --> WriteOffApproval[销账审批]
|
||||
ValidatePrepaid --> PrepaidApproval[预存审批]
|
||||
ValidateAdjust --> AdjustApproval["调账审批"]
|
||||
ValidateRefund --> RefundApproval["退款审批"]
|
||||
ValidateWriteOff --> WriteOffApproval["销账审批"]
|
||||
ValidatePrepaid --> PrepaidApproval["预存审批"]
|
||||
|
||||
AdjustApproval --> ApprovalResult{审批结果}
|
||||
AdjustApproval --> ApprovalResult{"审批结果"}
|
||||
RefundApproval --> ApprovalResult
|
||||
WriteOffApproval --> ApprovalResult
|
||||
PrepaidApproval --> ApprovalResult
|
||||
|
||||
ApprovalResult -->|拒绝| ApprovalReject[审批拒绝]
|
||||
ApprovalResult -->|通过| ExecuteProcess[执行处理]
|
||||
ApprovalResult -->|拒绝| ApprovalReject["审批拒绝"]
|
||||
ApprovalResult -->|通过| ExecuteProcess["执行处理"]
|
||||
|
||||
ExecuteProcess --> UpdateAccount[更新账户]
|
||||
UpdateAccount --> RecordLog[记录日志]
|
||||
RecordLog --> Complete([处理完成])
|
||||
ExecuteProcess --> UpdateAccount["更新账户"]
|
||||
UpdateAccount --> RecordLog["记录日志"]
|
||||
RecordLog --> Complete(["处理完成"])
|
||||
|
||||
AuthError --> End([结束])
|
||||
AuthError --> End(["结束"])
|
||||
ApprovalReject --> End
|
||||
```
|
||||
|
||||
|
||||
@ -11,11 +11,11 @@
|
||||
| **文档状态** | ✅ 已完成 |
|
||||
|
||||
## 目录
|
||||
- [一、引言](#一引言)
|
||||
- [1.1 编写目的](#11-编写目的)
|
||||
- [1.2 背景](#12-背景)
|
||||
- [1.3 定义](#13-定义)
|
||||
- [1.4 参考资料](#14-参考资料)
|
||||
- [引言](#引言)
|
||||
- [编写目的](#编写目的)
|
||||
- [背景](#背景)
|
||||
- [定义](#定义)
|
||||
- [参考资料](#参考资料)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@ -8,16 +8,16 @@
|
||||
| **技术框架** | RuoYi-Vue-Pro + yudao-ui-admin-vue3 |
|
||||
| **文档版本** | v1.0 |
|
||||
| **编写日期** | 2024-12-19 |
|
||||
| **文档状态** | ✅ 基本完成 |
|
||||
| **文档状态** | ✅ 已完成 |
|
||||
|
||||
## 目录
|
||||
- [一、系统架构概述](#一系统架构概述)
|
||||
- [二、技术架构](#二技术架构)
|
||||
- [三、应用架构](#三应用架构)
|
||||
- [四、数据架构](#四数据架构)
|
||||
- [五、安全架构](#五安全架构)
|
||||
- [六、部署架构](#六部署架构)
|
||||
- [七、接口架构](#七接口架构)
|
||||
- [系统架构概述](#系统架构概述)
|
||||
- [技术架构](#技术架构)
|
||||
- [应用架构](#应用架构)
|
||||
- [数据架构](#数据架构)
|
||||
- [安全架构](#安全架构)
|
||||
- [部署架构](#部署架构)
|
||||
- [接口架构](#接口架构)
|
||||
|
||||
## 系统架构概述
|
||||
|
||||
@ -182,17 +182,15 @@ graph TB
|
||||
BACKUP --> FILE1
|
||||
```
|
||||
|
||||
|
||||
## 技术架构
|
||||
|
||||
系统采用B/S和M/S相结合的架构模式,具体技术栈如下:
|
||||
系统采用B/S和M/S相结合的架构模式,基于现代化的技术栈构建。
|
||||
|
||||
### 技术栈总览图
|
||||
### 技术栈总览
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
%% ============== 前端技术栈 ==============
|
||||
subgraph 客户端["🏷 前端技术栈"]
|
||||
subgraph 前端技术栈["🏷 前端技术栈"]
|
||||
FE1["Vue 3.2+ TypeScript"]
|
||||
FE2["Element Plus UI"]
|
||||
FE3["Vite 构建工具"]
|
||||
@ -200,11 +198,9 @@ graph LR
|
||||
FE5["Vue Router 路由"]
|
||||
FE6["Axios HTTP请求"]
|
||||
FE7["ECharts 图表"]
|
||||
FE8["富文本编辑器"]
|
||||
end
|
||||
|
||||
%% ============== 后端核心 ==============
|
||||
subgraph 核心系统["📦 后端技术栈"]
|
||||
subgraph 后端技术栈["📦 后端技术栈"]
|
||||
BE1["Spring Boot 3.x"]:::spring
|
||||
BE2["Spring Security"]:::security
|
||||
BE3["MyBatis Plus"]:::orm
|
||||
@ -215,52 +211,37 @@ graph LR
|
||||
BE8["Maven 管理"]
|
||||
end
|
||||
|
||||
%% ============== 中间件集群 ==============
|
||||
subgraph 中间件["⚙️ 中间件服务"]
|
||||
direction TB
|
||||
MW1["Nginx LB"]-->MW2["Redis集群"]
|
||||
MW3["Flowable工作流"]-->MW4["Quartz定时"]
|
||||
MW5["MinIO存储"]-->MW6["RocketMQ"]
|
||||
MW7["ElasticSearch"]-->MW8["Sentinel限流"]
|
||||
subgraph 中间件服务["⚙️ 中间件服务"]
|
||||
MW1["Nginx LB"]
|
||||
MW2["Redis集群"]
|
||||
MW3["Flowable工作流"]
|
||||
MW4["Quartz定时"]
|
||||
MW5["MinIO存储"]
|
||||
MW6["RocketMQ"]
|
||||
MW7["ElasticSearch"]
|
||||
MW8["Sentinel限流"]
|
||||
end
|
||||
|
||||
%% ============== 移动生态 ==============
|
||||
subgraph 移动端["📱 移动应用"]
|
||||
MB1["uni-app"]-.多端.->MB3["微信小程序"]
|
||||
MB1-.多端.->MB4["支付宝小程序"]
|
||||
MB1-.多端.->MB5["H5响应式"]
|
||||
subgraph 移动应用["📱 移动应用"]
|
||||
MB1["uni-app"]
|
||||
MB2["uView UI"]
|
||||
MB3["微信小程序"]
|
||||
MB4["支付宝小程序"]
|
||||
MB5["H5响应式"]
|
||||
MB6["高德地图SDK"]
|
||||
MB7["NFC设备接口"]
|
||||
MB2["uView UI"]
|
||||
end
|
||||
|
||||
%% ============== 运维监控 ==============
|
||||
subgraph 监控["🔍 监控运维"]
|
||||
OP1["SkyWalking"]-->OP6["Prometheus"]
|
||||
OP6-.指标.->OP7["Grafana"]
|
||||
OP8["ELK日志"]-->OP5["Jenkins"]
|
||||
OP3["Docker"]-->OP4["K8s集群"]
|
||||
OP2["SpringBoot Admin"]
|
||||
end
|
||||
|
||||
%% ============== 连接关系 ==============
|
||||
FE6 -- HTTP请求 --> BE1
|
||||
MB1 -- API调用 --> BE1
|
||||
|
||||
BE1 === |认证| BE2
|
||||
BE1 === |数据| BE3
|
||||
BE1 --> BE2
|
||||
BE1 --> BE3
|
||||
BE3 --> BE5
|
||||
BE1 --> BE4
|
||||
|
||||
BE1 --> |异步| MW6
|
||||
BE1 --> |文件| MW5
|
||||
BE1 --> |搜索| MW7
|
||||
BE1 --> |流程| MW3
|
||||
|
||||
MW8 --> |保护| BE1
|
||||
|
||||
OP1 & OP2 & OP6 & OP8 --> |监控| BE1
|
||||
OP3 --> |部署| OP4
|
||||
BE1 --> MW6
|
||||
BE1 --> MW5
|
||||
BE1 --> MW7
|
||||
BE1 --> MW3
|
||||
|
||||
classDef spring fill:#6db33f,color:white
|
||||
classDef security fill:#b5e6c0
|
||||
@ -318,7 +299,6 @@ flowchart TD
|
||||
F5[第三方系统<br/>数据集成]
|
||||
end
|
||||
|
||||
%% 数据流向关系
|
||||
A1 --> B1
|
||||
A2 --> B2
|
||||
A3 --> B1
|
||||
@ -351,7 +331,6 @@ flowchart TD
|
||||
E4 --> F4
|
||||
E3 --> F5
|
||||
|
||||
%% 反向数据流
|
||||
F1 -.-> C2
|
||||
F3 -.-> C1
|
||||
F4 -.-> C3
|
||||
@ -359,9 +338,12 @@ flowchart TD
|
||||
```
|
||||
|
||||
### 服务端技术架构
|
||||
- 操作系统:国产 Linux 操作系统
|
||||
- 数据库:华为OpenGauss 5.0+数据库,企业级国产数据库
|
||||
- 应用框架:基于RuoYi-Vue-Pro框架定制开发
|
||||
|
||||
系统采用基于RuoYi-Vue-Pro框架的技术架构:
|
||||
|
||||
- **操作系统**:国产 Linux 操作系统
|
||||
- **数据库**:华为OpenGauss 5.0+数据库,企业级国产数据库
|
||||
- **应用框架**:基于RuoYi-Vue-Pro框架定制开发
|
||||
- 核心框架:Spring Boot 3.x,支持JDK 17/21
|
||||
- ORM框架:MyBatis Plus,增强的MyBatis
|
||||
- 权限框架:Spring Security,基于RBAC的权限管理
|
||||
@ -374,142 +356,11 @@ flowchart TD
|
||||
- 代码生成:自动化CRUD和表单代码生成器
|
||||
- 多租户:基于字段隔离的SaaS多租户设计
|
||||
|
||||
#### RuoYi-Vue-Pro框架配置示例
|
||||
|
||||
**application.yml主配置文件:**
|
||||
```yaml
|
||||
# 服务端口配置
|
||||
server:
|
||||
port: 48080
|
||||
servlet:
|
||||
context-path: /admin-api
|
||||
|
||||
# Spring Boot 配置
|
||||
spring:
|
||||
application:
|
||||
name: water-biz-server
|
||||
profiles:
|
||||
active: local
|
||||
|
||||
# 数据源配置
|
||||
datasource:
|
||||
druid:
|
||||
url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
|
||||
username: root
|
||||
password: ${MYSQL_PASSWORD:123456}
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
# 连接池配置
|
||||
initial-size: 10
|
||||
min-idle: 10
|
||||
max-active: 20
|
||||
max-wait: 60000
|
||||
time-between-eviction-runs-millis: 60000
|
||||
min-evictable-idle-time-millis: 300000
|
||||
validation-query: SELECT 1 FROM DUAL
|
||||
test-while-idle: true
|
||||
test-on-borrow: false
|
||||
test-on-return: false
|
||||
pool-prepared-statements: true
|
||||
max-pool-prepared-statement-per-connection-size: 20
|
||||
|
||||
# Redis 配置
|
||||
redis:
|
||||
host: 127.0.0.1
|
||||
port: 6379
|
||||
password: ${REDIS_PASSWORD:}
|
||||
database: 1
|
||||
timeout: 6000ms
|
||||
lettuce:
|
||||
pool:
|
||||
max-active: 32
|
||||
max-wait: 6000ms
|
||||
max-idle: 32
|
||||
min-idle: 8
|
||||
|
||||
# MyBatis Plus 配置
|
||||
mybatis-plus:
|
||||
configuration:
|
||||
map-underscore-to-camel-case: true
|
||||
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
global-config:
|
||||
db-config:
|
||||
id-type: NONE
|
||||
logic-delete-field: deleted
|
||||
logic-delete-value: 1
|
||||
logic-not-delete-value: 0
|
||||
type-aliases-package: cn.iocoder.yudao.module.*.dal.dataobject
|
||||
|
||||
# 水务系统多租户配置
|
||||
yudao:
|
||||
tenant:
|
||||
enable: true
|
||||
ignore-urls:
|
||||
- /admin-api/water/tenant/get-id-by-name
|
||||
- /admin-api/infra/file/*/get/**
|
||||
ignore-tables:
|
||||
- water_tenant
|
||||
- water_system_config
|
||||
- water_dict_data
|
||||
- water_dict_type
|
||||
|
||||
# 水务系统安全配置
|
||||
security:
|
||||
permit-all-urls:
|
||||
- /admin-api/water/auth/login
|
||||
- /admin-api/water/auth/logout
|
||||
- /admin-api/water/auth/refresh-token
|
||||
- /admin-api/water/captcha/get
|
||||
- /admin-api/water/sms/send
|
||||
|
||||
# 文件存储配置
|
||||
file:
|
||||
config:
|
||||
type: local
|
||||
local:
|
||||
domain: http://127.0.0.1:48080
|
||||
path: /Users/yunai/file_test
|
||||
|
||||
# 短信配置
|
||||
sms:
|
||||
alibaba:
|
||||
access-key-id: ${SMS_ACCESS_KEY_ID:}
|
||||
access-key-secret: ${SMS_ACCESS_KEY_SECRET:}
|
||||
signature: 福建水务
|
||||
template-code: SMS_123456
|
||||
```
|
||||
|
||||
**多租户配置要点**:
|
||||
- 基于MyBatis-Plus的TenantLineInnerInterceptor实现数据隔离
|
||||
- 自动在SQL中添加tenant_id条件过滤数据
|
||||
- 支持配置忽略多租户的系统表
|
||||
- 通过TenantContextHolder获取当前租户上下文
|
||||
- 集成分页插件支持多租户分页查询
|
||||
|
||||
**权限控制配置要点**:
|
||||
- 基于Spring Security实现统一的权限控制
|
||||
- 支持方法级权限注解@PreAuthorize
|
||||
- 配置静态资源和公开接口的匿名访问
|
||||
- 集成JWT Token认证过滤器
|
||||
- 采用无状态会话管理,禁用CSRF和CORS
|
||||
|
||||
### 客户端技术架构
|
||||
- 前端框架:基于yudao-ui-admin-vue3框架定制开发
|
||||
- 核心框架:Vue 3.x + TypeScript
|
||||
- 组件库:Element Plus,现代化UI组件
|
||||
- 状态管理:Pinia,新一代的Vue状态管理库
|
||||
- 路由管理:Vue Router
|
||||
- HTTP工具:Axios,请求拦截与统一处理
|
||||
- CSS框架:Tailwind CSS / UnoCSS,原子化CSS
|
||||
- 图表组件:ECharts,强大的可视化图表库
|
||||
- 富文本编辑器:WangEditor
|
||||
- 文件上传:基于Element Plus的上传组件
|
||||
- 权限控制:细粒度的按钮级权限控制
|
||||
- 动态表格:支持拖拽、排序、筛选
|
||||
- 代码规范:ESLint + Prettier,标准化代码风格
|
||||
|
||||
#### 前端项目配置要点
|
||||
#### Web管理端架构 (yudao-ui-admin-vue3)
|
||||
|
||||
**核心依赖和技术栈**:
|
||||
**核心技术组成:**
|
||||
- Vue 3.x + TypeScript:现代化前端框架
|
||||
- Element Plus:企业级UI组件库
|
||||
- Pinia:新一代状态管理
|
||||
@ -518,121 +369,13 @@ yudao:
|
||||
- ECharts:数据可视化图表
|
||||
- Vite:快速构建工具
|
||||
|
||||
**构建配置要点**:
|
||||
- 配置路径别名简化导入路径
|
||||
- 设置开发服务器代理转发API请求
|
||||
- 优化构建输出,支持代码分割和资源压缩
|
||||
- 配置静态资源处理和缓存策略
|
||||
|
||||
**状态管理要点**:
|
||||
- 使用Pinia管理用户信息、权限和角色
|
||||
- 提供用户登录、登出和权限检查方法
|
||||
- 支持响应式的用户状态更新
|
||||
- 集成Token管理和自动刷新机制
|
||||
|
||||
**HTTP请求封装要点**:
|
||||
- 基于Axios封装统一的HTTP请求工具
|
||||
- 自动添加认证Token和租户ID头部
|
||||
- 实现请求和响应拦截器处理公共逻辑
|
||||
- 统一的错误处理和用户提示
|
||||
- 支持Token过期自动刷新机制
|
||||
### 前端技术架构详细设计
|
||||
|
||||
#### Web管理端架构 (yudao-ui-admin-vue3)
|
||||
|
||||
**技术栈组成:**
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "开发框架"
|
||||
A1[Vue 3.2.47 Composition API]
|
||||
A2[TypeScript 4.9.4]
|
||||
A3[Vite 4.0.0 构建工具]
|
||||
end
|
||||
|
||||
subgraph "UI组件库"
|
||||
B1[Element Plus 2.3.14]
|
||||
B2[Element Plus Icons]
|
||||
B3[自定义组件库]
|
||||
end
|
||||
|
||||
subgraph "状态管理"
|
||||
C1[Pinia 2.0.28]
|
||||
C2[持久化插件]
|
||||
C3[全局状态管理]
|
||||
end
|
||||
|
||||
subgraph "路由系统"
|
||||
D1[Vue Router 4.1.6]
|
||||
D2[路由守卫]
|
||||
D3[动态路由]
|
||||
D4[权限控制]
|
||||
end
|
||||
|
||||
subgraph "HTTP通信"
|
||||
E1[Axios 1.2.2]
|
||||
E2[请求拦截器]
|
||||
E3[响应拦截器]
|
||||
E4[错误处理]
|
||||
end
|
||||
|
||||
subgraph "工具库"
|
||||
F1[Lodash 工具函数]
|
||||
F2[dayjs 时间处理]
|
||||
F3[nprogress 进度条]
|
||||
F4[js-cookie Cookie管理]
|
||||
F5[crypto-js 加密解密]
|
||||
end
|
||||
|
||||
A1 --> B1
|
||||
A1 --> C1
|
||||
A1 --> D1
|
||||
A1 --> E1
|
||||
B1 --> B3
|
||||
C1 --> C2
|
||||
D1 --> D2
|
||||
E1 --> E2
|
||||
```
|
||||
|
||||
**项目结构设计:**
|
||||
```text
|
||||
yudao-ui-admin-vue3/
|
||||
├── public/ # 静态资源
|
||||
├── src/
|
||||
│ ├── api/ # API接口定义
|
||||
│ │ └── water/ # 水务业务API
|
||||
│ │ ├── customer/ # 客户管理API
|
||||
│ │ ├── meter/ # 抄表管理API
|
||||
│ │ ├── billing/ # 收费管理API
|
||||
│ │ └── workflow/ # 工单管理API
|
||||
│ ├── assets/ # 静态资源
|
||||
│ ├── components/ # 全局组件
|
||||
│ │ ├── Dialog/ # 弹窗组件
|
||||
│ │ ├── Form/ # 表单组件
|
||||
│ │ ├── Table/ # 表格组件
|
||||
│ │ └── Upload/ # 上传组件
|
||||
│ ├── layout/ # 布局组件
|
||||
│ ├── router/ # 路由配置
|
||||
│ ├── stores/ # Pinia状态管理
|
||||
│ ├── styles/ # 全局样式
|
||||
│ ├── utils/ # 工具函数
|
||||
│ ├── views/ # 页面组件
|
||||
│ │ └── water/ # 水务业务页面
|
||||
│ │ ├── customer/ # 客户管理
|
||||
│ │ ├── meter/ # 抄表管理
|
||||
│ │ ├── billing/ # 收费管理
|
||||
│ │ └── workflow/ # 工单管理
|
||||
│ └── App.vue
|
||||
├── types/ # TypeScript类型定义
|
||||
├── vite.config.ts # Vite配置
|
||||
├── tsconfig.json # TypeScript配置
|
||||
└── package.json # 项目依赖
|
||||
```
|
||||
|
||||
**核心配置要点**:
|
||||
- Vite构建工具配置,支持路径别名和代理
|
||||
- 开发服务器配置,代理后端API请求
|
||||
- 构建优化配置,支持代码分割和资源压缩
|
||||
- TypeScript配置,提供类型检查和智能提示
|
||||
**架构特点:**
|
||||
- 基于Composition API的组件开发模式
|
||||
- TypeScript提供类型安全保障
|
||||
- 模块化的项目结构设计
|
||||
- 响应式的状态管理机制
|
||||
- 统一的HTTP请求封装
|
||||
- 完善的权限控制体系
|
||||
|
||||
#### 移动端架构 (uni-app)
|
||||
|
||||
@ -651,12 +394,6 @@ graph TB
|
||||
N3[自定义水务组件]
|
||||
end
|
||||
|
||||
subgraph "状态管理"
|
||||
O1[Vuex 4.x]
|
||||
O2[uni-app存储]
|
||||
O3[缓存管理]
|
||||
end
|
||||
|
||||
subgraph "设备能力"
|
||||
P1[相机API<br/>水表拍照]
|
||||
P2[NFC读取<br/>水表标签]
|
||||
@ -671,7 +408,6 @@ graph TB
|
||||
end
|
||||
|
||||
M1 --> N1
|
||||
M1 --> O1
|
||||
M1 --> P1
|
||||
M1 --> Q1
|
||||
N1 --> N3
|
||||
@ -679,204 +415,77 @@ graph TB
|
||||
Q1 --> Q2
|
||||
```
|
||||
|
||||
**移动端项目结构:**
|
||||
```text
|
||||
water-mobile-app/
|
||||
├── pages/ # 页面目录
|
||||
│ ├── index/ # 首页
|
||||
│ ├── meter/ # 抄表功能
|
||||
│ │ ├── task/ # 抄表任务
|
||||
│ │ ├── read/ # 抄表录入
|
||||
│ │ └── history/ # 抄表历史
|
||||
│ ├── workflow/ # 工单管理
|
||||
│ └── personal/ # 个人中心
|
||||
├── components/ # 组件目录
|
||||
│ ├── meter-reader/ # 水表读数组件
|
||||
│ ├── map-trace/ # 地图轨迹组件
|
||||
│ └── camera-scan/ # 相机扫描组件
|
||||
├── static/ # 静态资源
|
||||
├── store/ # 状态管理
|
||||
├── utils/ # 工具函数
|
||||
├── api/ # 接口定义
|
||||
├── manifest.json # 应用配置
|
||||
└── pages.json # 页面配置
|
||||
```
|
||||
|
||||
#### 客户端小程序架构
|
||||
|
||||
**微信小程序技术栈:**
|
||||
- 开发框架:微信小程序原生框架
|
||||
- UI组件:WeUI + 自定义组件
|
||||
- 状态管理:小程序全局数据管理
|
||||
- 支付集成:微信支付API
|
||||
- 地图服务:腾讯地图API
|
||||
|
||||
**支付宝小程序技术栈:**
|
||||
- 开发框架:支付宝小程序原生框架
|
||||
- UI组件:mini-antui + 自定义组件
|
||||
- 状态管理:小程序全局数据管理
|
||||
- 支付集成:支付宝支付API
|
||||
- 地图服务:高德地图API
|
||||
|
||||
#### 前端工程化配置
|
||||
|
||||
**代码规范:**
|
||||
```json
|
||||
// .eslintrc.js - ESLint配置
|
||||
{
|
||||
"extends": [
|
||||
"@vue/typescript/recommended",
|
||||
"@vue/prettier",
|
||||
"@vue/prettier/@typescript-eslint"
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/no-explicit-any": "warn",
|
||||
"@typescript-eslint/no-unused-vars": "error",
|
||||
"vue/multi-word-component-names": "off"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**构建优化:**
|
||||
- Vite热更新:开发环境快速构建
|
||||
- 代码分割:按路由和组件懒加载
|
||||
- 资源压缩:Gzip压缩和图片优化
|
||||
- CDN加速:静态资源CDN分发
|
||||
- 缓存策略:浏览器缓存和Service Worker
|
||||
|
||||
- 移动端:
|
||||
- 核心框架:uni-app(跨平台)
|
||||
- 组件库:uview-ui
|
||||
- 小程序支持:微信小程序、支付宝小程序等
|
||||
- 移动端地图:高德地图SDK(用于抄表轨迹和导航)
|
||||
- 设备接入:NFC、扫码、相机等硬件设备接口
|
||||
|
||||
### 技术特性
|
||||
- 单点登录:OAuth2 + JWT实现统一认证
|
||||
- 数据交换:基于RESTful API的系统内部数据交换与共享
|
||||
- 统一报表平台:集成JimuReport,支持自定义报表设计与生成
|
||||
- 大屏设计:集成GoView,支持可视化大屏设计
|
||||
- 安全保障:满足安全等保三级要求
|
||||
|
||||
- **单点登录**:OAuth2 + JWT实现统一认证
|
||||
- **数据交换**:基于RESTful API的系统内部数据交换与共享
|
||||
- **统一报表平台**:集成JimuReport,支持自定义报表设计与生成
|
||||
- **大屏设计**:集成GoView,支持可视化大屏设计
|
||||
- **安全保障**:满足安全等保三级要求
|
||||
- 密码加密:BCrypt加密算法
|
||||
- 防XSS攻击:表单数据过滤
|
||||
- 防SQL注入:参数化查询
|
||||
- 防CSRF攻击:Token验证
|
||||
- 性能规格:支持200并发用户,50并发移动设备,系统响应时间不超过3秒
|
||||
- 扩展容量:支持100万客户的业务量,满足企业3-5年的业务发展需求
|
||||
- 支持功能:
|
||||
- 支付管理:微信支付、支付宝支付等
|
||||
- 短信服务:阿里云、腾讯云等多家短信服务商
|
||||
- AI能力:
|
||||
- 智能抄表:基于图像识别的水表读数
|
||||
- 异常分析:基于AI的用水异常分析
|
||||
- API网关:支持API权限管理、限流熔断、白名单控制
|
||||
- **性能规格**:支持200并发用户,50并发移动设备,系统响应时间不超过3秒
|
||||
- **扩展容量**:支持100万客户的业务量,满足企业3-5年的业务发展需求
|
||||
|
||||
## 应用架构
|
||||
|
||||
### 微服务应用架构图
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "网关层"
|
||||
GW[API网关<br/>Spring Cloud Gateway]
|
||||
AUTH[认证服务<br/>OAuth2 + JWT]
|
||||
end
|
||||
|
||||
subgraph "基础服务层"
|
||||
subgraph "系统服务"
|
||||
SYS[系统管理服务<br/>用户/角色/权限]
|
||||
TENANT[租户管理服务<br/>多租户隔离]
|
||||
FILE[文件管理服务<br/>附件存储]
|
||||
MSG[消息服务<br/>短信/邮件/推送]
|
||||
end
|
||||
|
||||
subgraph "工作流服务"
|
||||
WF[工作流引擎<br/>Flowable]
|
||||
TASK[任务调度服务<br/>Quartz]
|
||||
end
|
||||
graph TD
|
||||
subgraph "接入层"
|
||||
GW[API网关]
|
||||
AUTH[认证服务]
|
||||
end
|
||||
|
||||
subgraph "业务服务层"
|
||||
subgraph "客户域服务"
|
||||
CUST[客户管理服务<br/>Customer Service]
|
||||
METER[水表管理服务<br/>Meter Service]
|
||||
ADDR[地址管理服务<br/>Address Service]
|
||||
SYS[系统服务]
|
||||
CUST[客户服务]
|
||||
READ[抄表服务]
|
||||
BILL[账单服务]
|
||||
PAY[收费服务]
|
||||
ORDER[工单服务]
|
||||
RPT[报表服务]
|
||||
end
|
||||
|
||||
subgraph "营收域服务"
|
||||
READ[抄表服务<br/>Reading Service]
|
||||
BILL[账单服务<br/>Billing Service]
|
||||
PAY[收费服务<br/>Payment Service]
|
||||
ACC[账务服务<br/>Accounting Service]
|
||||
subgraph "支撑服务层"
|
||||
METER[水表管理]
|
||||
WF[工作流引擎]
|
||||
PAY_GW[支付网关]
|
||||
IOT[物联网]
|
||||
end
|
||||
|
||||
subgraph "运营域服务"
|
||||
ORDER[工单服务<br/>Workflow Service]
|
||||
RPT[报表服务<br/>Report Service]
|
||||
STATS[统计分析服务<br/>Statistics Service]
|
||||
subgraph "数据存储层"
|
||||
DB[(OpenGauss数据库)]
|
||||
REDIS[(Redis缓存)]
|
||||
FILE_STORE[文件存储]
|
||||
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
|
||||
|
||||
READ --> BILL
|
||||
BILL --> 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
|
||||
%% 数据连接
|
||||
CUST -.-> DB
|
||||
BILL -.-> DB
|
||||
PAY -.-> DB
|
||||
AUTH -.-> REDIS
|
||||
SYS -.-> FILE_STORE
|
||||
```
|
||||
|
||||
### 服务治理架构
|
||||
@ -926,83 +535,49 @@ graph TB
|
||||
TRACE --> LOG
|
||||
```
|
||||
|
||||
### 应用模块设计
|
||||
|
||||
系统应用架构基于业务域划分,主要包括以下核心应用模块:
|
||||
|
||||
### 统一平台
|
||||
#### 统一平台
|
||||
- 单点登录:统一认证入口,支持多种登录方式
|
||||
- 系统管理:组织机构、员工管理、角色权限管理、菜单配置等
|
||||
- 流程节点提醒:工作流节点到期和状态变更提醒
|
||||
|
||||
### 营收系统
|
||||
#### 营收系统
|
||||
- 系统管理:水价管理、用户档案管理、更名过户管理等
|
||||
- 抄表开账:册本管理、抄表录入、复核开账等
|
||||
- 收费管理:柜台收费、特殊开账、柜台结账、批量缴费等
|
||||
- 账务处理:预存调整、未销调整、已销调整、分账调整等
|
||||
- 发票管理:发票查询、发票开具、电子发票等
|
||||
- 代收业务:实时收费、银行代扣、银行托收等
|
||||
- 环卫系统:计费核定、计费退补、计费减免等
|
||||
- 业务工单:业务清单、上报清单、稽查工单、移表工单等
|
||||
|
||||
### 客户服务
|
||||
#### 客户服务
|
||||
- 微信、支付宝服务窗:账户绑定、用水查询、在线缴费等
|
||||
- 历史账单:账单查询、用水分析、账单推送等
|
||||
- 电子发票:发票申请、发票查询、发票下载等
|
||||
- 营业网点:网点查询、网点导航、业务指南等
|
||||
- 账户流水:流水查询、明细下载、交易统计等
|
||||
- 微网厅:用户注册、信息查询、业务办理等
|
||||
|
||||
### 表务系统
|
||||
#### 表务系统
|
||||
- 表务工单:换表工单、移表工单、拆表工单、复装工单等
|
||||
- 表务仓库:新表入库、水表检定、水表领用、水表出库等
|
||||
- 水表参数与基础信息:水表厂家管理、水表型号管理等
|
||||
- 物联网对接与数据同步:厂家设备信息管理、远程抄表数据同步等
|
||||
|
||||
### 报装管理
|
||||
#### 报装管理
|
||||
- 报装流程:报装申请、方案设计、合同签订、施工管理等
|
||||
- 一户一表管理:改造计划、改造实施、用户转换等
|
||||
|
||||
### 统计分析
|
||||
#### 统计分析
|
||||
- 报表查询:标准报表、自定义报表、报表导出打印等
|
||||
- 欠费查询:欠费情况统计、欠费用户明细、欠费分析等
|
||||
- 缴费记录:缴费情况统计、缴费明细查询、缴费趋势分析等
|
||||
- 用水分析:用水量统计、用水趋势分析、异常用水分析等
|
||||
|
||||
### 工程管理
|
||||
- 工程申请:工程立项、材料提交、前期勘察等
|
||||
- 工程施工:施工计划、施工派工、施工记录等
|
||||
- 工程验收:验收申请、验收检查、验收记录等
|
||||
- 工程查询:工程进度查询、工程资料查询、工程统计等
|
||||
|
||||
### 抄表APP
|
||||
- 首页功能:首页展示、个人信息、快捷查询等
|
||||
- 抄表功能:抄表任务、NFC抄表、扫码抄表、AI录入等
|
||||
- 工单管理:问题上报、问题回填、代办工单、稽查工单等
|
||||
|
||||
### 接口服务
|
||||
- API市场:API展示、API使用说明、API测试等
|
||||
- API管理:API申请、API调度看板、接口服务配置管理等
|
||||
- 接口权限管理:授权管理、白名单管理、安全策略等
|
||||
- 系统对外接口:查询接口、业务处理接口、状态同步接口等
|
||||
|
||||
### 系统配置
|
||||
- 水表参数:水表厂家、水表型号、水表量程等
|
||||
- 地址参数:行政区划、地址编码、地址库等
|
||||
- 价格体系:用水性质、水价标准、阶梯水价等
|
||||
- 基本配置:系统参数、业务规则、打印模板等
|
||||
- 催缴管理:催缴计划、催缴任务、催缴执行等
|
||||
- 用户权限:菜单权限、功能权限、数据权限等
|
||||
- 定时任务:任务配置、任务监控、任务日志等
|
||||
|
||||
## 数据架构
|
||||
|
||||
系统数据架构基于客户关系数据库为核心和基础,实现客户全生命周期管理。
|
||||
|
||||
### 数据分层
|
||||
- 数据采集层:负责从各业务系统和物联网设备采集原始数据
|
||||
- 数据存储层:统一数据存储,实现分布式数据管理
|
||||
- 数据服务层:提供数据服务接口
|
||||
- 数据展现层:提供数据分析和可视化功能
|
||||
|
||||
### OpenGauss数据库架构
|
||||
|
||||
#### 主从高可用架构
|
||||
@ -1084,38 +659,8 @@ graph TB
|
||||
CN2 --> GTM
|
||||
```
|
||||
|
||||
#### 数据安全架构
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "安全防护层"
|
||||
TDE[透明数据加密<br/>TDE]
|
||||
RLS[行级安全<br/>Row Level Security]
|
||||
MASK[动态数据脱敏<br/>Dynamic Data Masking]
|
||||
AUDIT[三权分立审计<br/>Separated Audit]
|
||||
end
|
||||
|
||||
subgraph "访问控制层"
|
||||
RBAC[基于角色的访问控制<br/>RBAC]
|
||||
LDAP[LDAP集成认证<br/>External Auth]
|
||||
SSL[SSL/TLS加密传输<br/>Encrypted Transport]
|
||||
end
|
||||
|
||||
subgraph "数据存储层"
|
||||
ENCRYPT[存储层加密<br/>Storage Encryption]
|
||||
COMPRESS[数据压缩<br/>Data Compression]
|
||||
BACKUP_ENC[备份加密<br/>Backup Encryption]
|
||||
end
|
||||
|
||||
TDE --> ENCRYPT
|
||||
RLS --> RBAC
|
||||
MASK --> ENCRYPT
|
||||
AUDIT --> BACKUP_ENC
|
||||
RBAC --> SSL
|
||||
LDAP --> SSL
|
||||
```
|
||||
|
||||
### 数据模型设计
|
||||
|
||||
- **客户信息模型**:包含客户基础信息、表卡信息、账户信息、联系人信息等
|
||||
- **业务数据模型**:抄表数据、收费数据、账务数据、发票数据等
|
||||
- **工单数据模型**:表务工单、报装工单、业务工单等
|
||||
@ -1124,6 +669,7 @@ graph TB
|
||||
- **物联网数据模型**:设备信息、状态信息、实时数据等
|
||||
|
||||
### 数据集成与共享
|
||||
|
||||
- **统一数据标准**:定义统一的数据标准和数据字典,符合OpenGauss规范
|
||||
- **数据集成机制**:采用OpenGauss XA事务实现系统间的数据一致性
|
||||
- **数据共享机制**:基于OpenGauss外部数据包装器(FDW)实现跨库数据访问
|
||||
@ -1149,12 +695,6 @@ graph TB
|
||||
|
||||
系统安全架构基于OpenGauss数据库的企业级安全特性,满足等保三级要求和国产化安全标准:
|
||||
|
||||
### 网络安全
|
||||
- **边界防护**:防火墙、入侵检测/防御系统
|
||||
- **访问控制**:基于角色的访问控制(RBAC)
|
||||
- **通信安全**:SSL/TLS加密传输,支持国密算法
|
||||
- **安全监控**:实时监控网络安全状态和异常访问
|
||||
|
||||
### OpenGauss数据安全架构
|
||||
|
||||
#### 数据加密安全
|
||||
@ -1226,7 +766,15 @@ graph TB
|
||||
TENANT --> REPORT
|
||||
```
|
||||
|
||||
### 网络安全
|
||||
|
||||
- **边界防护**:防火墙、入侵检测/防御系统
|
||||
- **访问控制**:基于角色的访问控制(RBAC)
|
||||
- **通信安全**:SSL/TLS加密传输,支持国密算法
|
||||
- **安全监控**:实时监控网络安全状态和异常访问
|
||||
|
||||
### 数据安全特性
|
||||
|
||||
- **透明数据加密(TDE)**:自动加密存储数据,支持SM4国密算法
|
||||
- **行级安全(RLS)**:基于用户角色的行级数据访问控制
|
||||
- **列级权限**:敏感字段的精细化访问控制
|
||||
@ -1235,12 +783,14 @@ graph TB
|
||||
- **审计日志**:完整记录所有数据库操作,支持合规审计
|
||||
|
||||
### 多租户安全隔离
|
||||
|
||||
- **逻辑隔离**:基于tenant_id的数据隔离
|
||||
- **连接隔离**:租户间连接池隔离
|
||||
- **权限隔离**:租户级别的权限管理
|
||||
- **资源隔离**:CPU、内存、IO资源限制
|
||||
|
||||
### 应用安全
|
||||
|
||||
- **身份认证**:多因素认证,支持短信验证码、邮箱验证等
|
||||
- **授权管理**:细粒度的权限控制,支持菜单、按钮、数据权限
|
||||
- **安全审计**:用户操作审计,关键业务操作全程记录
|
||||
@ -1248,6 +798,7 @@ graph TB
|
||||
- **会话管理**:会话超时、并发限制、单点登录等
|
||||
|
||||
### 接口安全
|
||||
|
||||
- **接口认证**:基于JWT Token的接口认证
|
||||
- **接口授权**:基于角色的接口授权和权限验证
|
||||
- **接口加密**:敏感数据的加密传输,支持国密算法
|
||||
@ -1259,6 +810,7 @@ graph TB
|
||||
系统采用集中部署的模式,基于集团私有云环境进行部署。
|
||||
|
||||
### 物理部署
|
||||
|
||||
- **生产环境**:高可用集群部署
|
||||
- 应用服务器:2台或以上服务器,负载均衡
|
||||
- **OpenGauss数据库集群**:主从+级联备架构,支持自动故障切换
|
||||
@ -1269,6 +821,7 @@ graph TB
|
||||
- **开发环境**:用于系统开发和集成测试,单节点OpenGauss部署
|
||||
|
||||
### 逻辑部署
|
||||
|
||||
- **应用服务器集群**:负责业务逻辑处理,支持水平扩展
|
||||
- **OpenGauss数据库集群**:负责数据存储和管理,提供高可用保障
|
||||
- **文件服务器**:负责文档和附件存储,支持分布式存储
|
||||
@ -1278,6 +831,7 @@ graph TB
|
||||
- **API网关**:统一的接口管理和控制
|
||||
|
||||
### 容器部署
|
||||
|
||||
- 基于Docker容器技术实现微服务部署
|
||||
- 使用Kubernetes进行容器编排和管理
|
||||
- 支持容器的自动扩缩容和故障转移
|
||||
@ -1288,6 +842,7 @@ graph TB
|
||||
系统提供标准化的接口,实现与外部系统的集成和数据交换。
|
||||
|
||||
### 外部接口
|
||||
|
||||
- 银行接口:实现与银行系统的对接,支持代扣、托收等功能
|
||||
- 支付宝/微信接口:支持在线支付功能
|
||||
- 短信接口:支持短信通知和验证码功能
|
||||
@ -1298,6 +853,7 @@ graph TB
|
||||
- OA系统接口:实现与OA系统的工作流对接
|
||||
|
||||
### 内部接口
|
||||
|
||||
- ESB服务接口:系统内部模块间的数据交换
|
||||
- 报表接口:提供报表数据查询和生成功能
|
||||
- 查询接口:提供数据查询功能
|
||||
@ -1306,6 +862,7 @@ graph TB
|
||||
- 工作流接口:提供工作流处理和状态查询功能
|
||||
|
||||
### 接口标准
|
||||
|
||||
- 接口协议:RESTful API、WebService、消息队列等
|
||||
- 数据格式:JSON、XML等
|
||||
- 接口安全:身份认证、授权、加密传输等
|
||||
@ -1313,6 +870,7 @@ graph TB
|
||||
- 接口测试:提供接口测试工具和环境
|
||||
|
||||
### 接口服务管理
|
||||
|
||||
- API网关:统一的接口入口和管理
|
||||
- 服务注册与发现:服务的自动注册和发现
|
||||
- 服务路由:根据请求参数进行服务路由
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user