datai/docs/archive/sessions/2026-01-25-002-05-session.md

16 KiB
Raw Blame History

会话记录:货币格式化功能

元数据

  • 需求编号2026-01-21-002-05
  • 创建时间2026-01-25
  • 创建人SSOT 架构师
  • 状态:进行中
  • 父需求2026-01-21-002-项目国际化需求

执行阶段

阶段 1需求定义

  • 状态:已完成
  • 生成文档需求文档
  • 关键决策
    • 扩展 sys_user 表,添加 currency_code 字段
    • 支持用户级别的货币偏好覆盖系统默认设置
    • 在配置文件中设置系统默认货币
    • 在后端返回数据时进行格式化,通过 AOP 在 Service 层统一处理
    • 需要支持多货币显示
    • 需要实时汇率转换
    • 后端使用 java.text.DecimalFormat
    • 不考虑性能、安全性等问题

阶段 2方案设计

  • 状态:已完成
  • 生成文档设计文档
  • 关键设计决策
    • 使用 Java DecimalFormat 进行货币格式化
    • 使用 Redis 缓存汇率数据,提高性能
    • 货币格式化在 Service 层进行,使用 AOP 切面拦截响应
    • 货币优先级:用户 > 系统
    • 汇率数据存储在数据库中,支持手动更新和 API 自动更新
    • 所有金额字段使用 BigDecimal 类型
    • 缓存策略汇率缓存TTL = 60 分钟、货币列表缓存TTL = 24 小时、默认货币缓存TTL = 24 小时)

阶段 3方案决策

  • 状态:已完成
  • 生成文档决策记录
  • 关键决策
    • 决策 1货币格式化技术选择 - Java DecimalFormat
      • 理由Java 内置、无需额外依赖、功能完整、性能优秀、成熟稳定、与框架兼容
      • 放弃方案Joda-Money 库(需要额外依赖)、自定义格式化实现(维护成本高)
    • 决策 2缓存策略选择 - Redis 缓存
      • 理由:已集成、性能优秀、分布式支持、自动过期、数据结构丰富、支持持久化
      • 缓存策略汇率缓存TTL = 60 分钟、货币列表缓存TTL = 24 小时、默认货币缓存TTL = 24 小时)
      • 放弃方案Caffeine 本地缓存(无法在分布式环境下共享)、数据库缓存(性能较差、无法自动过期)
    • 决策 3货币格式化层选择 - Service 层格式化 + AOP 切面拦截
      • 理由统一处理、AOP 切面自动格式化、业务逻辑分离、易于维护、性能优化
      • 实现方案:使用 @Around 切面拦截 Service 方法返回值,提供 @CurrencyFormat 注解
      • 放弃方案Controller 层格式化(职责过重、代码重复)、数据库层格式化(违反分层架构、兼容性差)
    • 决策 4货币优先级策略选择 - 双级优先级策略(用户 > 系统)
      • 理由:灵活性高、用户体验好、系统默认、易于扩展
      • 优先级规则:用户货币 > 系统货币 > 硬编码默认CNY
      • 放弃方案:单级优先级(仅用户货币/仅系统货币)- 灵活性不足

阶段 4数据库结构

  • 状态:已完成
  • 生成文档SQL 脚本
  • 数据库变更
    • 创建新表sys_exchange_rate汇率表
      • 字段id、from_currency、to_currency、rate、source、create_by、create_time、update_by、update_time、remark
      • 索引主键索引id、唯一索引from_currency, to_currency、普通索引source
    • 修改现有表sys_user用户表
      • 新增字段currency_code货币代码默认值为 CNY
      • 新增索引idx_currency_codecurrency_code 字段)
    • 插入初始数据
      • 插入常用货币配置CNY、USD、EUR、GBP、JPY

阶段 5提示词生成

  • 状态:已完成
  • 生成文档提示词文档
  • 提示词内容摘要
    • 引用真源需求文档、设计文档、决策记录、SQL 脚本
    • 需求描述:货币格式化功能、汇率管理功能、货币优先级策略、缓存管理、自动货币格式化
    • 设计方案Java DecimalFormat、Redis、MySQL 8.3.0、Spring Boot 3.5.7 + 若依框架、分层架构
    • 输出格式要求
      • Entity 层SysExchangeRate.java
      • 修改现有文件SysUser.java添加 currency_code 字段)
      • Utils 层CurrencyUtils.java
      • 注解:@CurrencyFormat.java
      • Aspect 层CurrencyFormatAspect.java拦截 Service 方法返回值)
      • Mapper 层SysExchangeRateMapper.java、SysExchangeRateMapper.xml
      • Service 层ISysExchangeRateService.java、SysExchangeRateServiceImpl.java
      • Controller 层SysExchangeRateController.java
      • 单元测试CurrencyUtilsTest.java、SysExchangeRateServiceTest.java
    • 代码规范要求:命名规范、注释规范、代码格式、导入规范
    • 测试要求:单元测试覆盖率 ≥ 80%、测试用例场景、测试框架、测试用例命名规范、测试数据
    • 注意事项货币格式化、缓存、权限控制、日志记录、异常处理、性能优化、安全、AOP 切面

阶段 6代码生成

  • 状态:已完成
  • 生成文档代码文档实施方案
  • 代码生成情况
    • 代码生成器生成
      • SysExchangeRate.java实体类
      • SysExchangeRateMapper.javaMapper 接口)
      • SysExchangeRateMapper.xmlMapper XML
      • SysExchangeRateService.javaService 接口基础方法)
      • SysExchangeRateServiceImpl.javaService 实现类基础方法)
      • SysExchangeRateController.javaController 类基础接口)
    • 手动生成/扩展
      • ISysExchangeRateService.java扩展方法getExchangeRate、convert、batchConvert、updateExchangeRate、updateExchangeRateFromApi、getAvailableCurrencies、getDefaultCurrency
      • SysExchangeRateServiceImpl.java实现扩展方法包含 Redis 缓存逻辑
      • CurrencyUtils.java货币格式化工具类format、convert、isValidCurrencyCode、getPattern、getSymbol
      • CurrencyConstants.java货币常量类货币代码、货币符号、货币格式化模式
      • @CurrencyFormat.java货币格式化注解
      • CurrencyFormatAspect.java货币格式化切面拦截 Service 方法返回值)
      • SysUser.java添加 currency_code 字段
      • SysUserController.java添加用户货币偏好管理接口
      • SysExchangeRateDto.java添加汇率转换相关字段
      • CacheConstants.java添加汇率相关缓存常量
  • 关键实现
    • 使用 AOP 切面拦截 Service 方法返回值进行货币格式化
    • Redis 缓存策略:汇率缓存 60 分钟,货币列表缓存 24 小时,默认货币缓存 24 小时
    • 递归格式化复杂对象中的 BigDecimal 字段
    • 支持多货币显示,自动转换并显示多种货币
    • 异常处理无效货币使用默认货币null 值安全处理
  • 修复的问题
    • CurrencyFormatAspect.java 中的 SYS_CONFIG 常量引用错误(修改为 SYS_CONFIG_KEY
  • 补充的接口
    • GET /system/user/currency获取当前用户货币偏好
    • POST /system/user/switchCurrency切换用户货币偏好已添加 @Log 注解记录审计日志)
    • POST /system/exchangeRate/convert汇率转换
    • POST /system/exchangeRate/batchConvert批量汇率转换
    • POST /system/exchangeRate/update更新汇率手动
    • POST /system/exchangeRate/updateFromApi更新汇率API
  • 需求实现情况
    • 功能 1货币符号支持 - 已实现
    • 功能 2小数格式化 - 已实现
    • 功能 3千分位分隔符 - 已实现(逗号分隔符)
    • ⚠️ 功能 4自动格式选择 - 已实现(部分)
    • ⚠️ 功能 5自定义格式 - 已实现(部分)
    • 功能 6多货币显示 - 已实现
    • 功能 7AOP 自动格式化 - 已实现
    • 功能 8用户货币偏好 - 已实现
    • 功能 9系统默认货币 - 已实现
    • 功能 10汇率管理 - 已实现
    • 功能 11汇率转换 - 已实现
    • 功能 12汇率缓存 - 已实现
    • ⚠️ 功能 13货币优先级 - 已实现(部分,缺少租户货币支持)
  • 未实现的需求
    • 空格分隔符支持(功能 3 的部分需求)
    • 自定义千分位分隔符(功能 5 的部分需求)
    • 自定义货币符号(功能 5 的部分需求)
    • 租户货币支持(功能 13 的部分需求)
    • 单元测试
    • 性能测试

阶段 7会话记录

  • 状态:已完成
  • 生成文档当前文档2026-01-25-002-05-session.md
  • 更新内容
    • 更新阶段 6 的代码生成情况
    • 记录补充的接口信息
    • 记录需求实现情况
    • 记录未实现的需求

阶段 8变更日志

  • 状态:待开始
  • 生成文档:待生成

阶段 9复盘与接口

  • 状态:待开始
  • 生成文档:待生成

阶段 10代码提交

  • 状态:待开始
  • 生成文档:待生成

关键设计决策

技术选型

  1. 货币格式化技术Java DecimalFormat

    • 理由Java 内置,无需引入额外依赖;支持自定义格式化模式;性能优秀,格式化时间 < 10ms成熟稳定社区支持良好
  2. 缓存技术Redis

    • 理由:项目已集成 Redis无需额外配置性能优秀响应时间 < 1ms支持分布式部署支持自动过期机制丰富的数据结构支持
  3. 数据库技术MySQL 8.3.0

    • 理由:项目现有数据库;支持 BigDecimal 类型;性能优秀,支持高并发;事务支持完善
  4. 框架技术Spring Boot 3.5.7 + 若依框架

    • 理由项目现有框架Spring Boot 3.5.7 支持 Java 21若依框架提供完善的权限、缓存、日志等功能社区活跃文档完善

架构设计

  1. 系统架构前端层Vue 3→ Controller 层 → Service 层 → Mapper 层 → 数据库层MySQL 8.3.0)→ 缓存层Redis
  2. 模块架构
    • datai-admin启动模块Controller 层
    • datai-system系统模块Service 层、Mapper 层、实体类
    • datai-common公共模块工具类、切面、常量
    • datai-plugins插件模块Redis 缓存工具类

数据流设计

  1. 用户登录流程:用户输入用户名密码 → Controller 接收登录请求 → Service 验证用户信息 → 从数据库读取用户货币偏好 → 从 Redis 缓存读取货币配置 → 将用户货币信息存储到 LoginUser → 生成 Token 并返回 → 前端存储 Token 和货币信息
  2. 数据查询流程:前端发起数据查询请求 → Controller 接收请求 → Service 层从数据库读取金额数据 → AOP 切面拦截响应 → 根据用户货币格式化金额 → 返回格式化后的金额 → 前端显示格式化后的金额
  3. 汇率转换流程:前端发起汇率转换请求 → Controller 接收请求 → Service 层从 Redis 缓存读取汇率 → 如果缓存未命中,从数据库读取汇率 → 返回转换后的金额 → 前端显示转换后的金额
  4. 货币切换流程:用户选择新货币 → Controller 接收货币切换请求 → Service 验证货币代码有效性 → 更新用户货币偏好到数据库 → 清除 Redis 缓存 → 刷新 Token → 前端刷新页面,重新加载金额数据

数据模型设计

  1. 汇率表sys_exchange_rate
    • 字段id、from_currency、to_currency、rate、source、create_by、create_time、update_by、update_time、remark
    • 索引主键索引id、唯一索引from_currency, to_currency、普通索引source
  2. 用户表修改sys_user
    • 新增字段currency_code货币代码
    • 默认值CNY人民币
    • 位置:在 lang_code 字段之后

接口设计

  1. 获取汇率列表GET /system/exchangeRate/list
    • 权限要求:@PreAuthorize("@ss.hasPermi('system:exchangeRate:list')")
    • 响应数据:汇率列表(包含 id、fromCurrency、toCurrency、rate、source
  2. 获取当前用户货币偏好GET /system/user/currency
    • 权限要求:需要登录
    • 响应数据货币代码CNY
  3. 切换货币偏好POST /system/user/switchCurrency
    • 权限要求:需要登录
    • 请求参数currencyCode货币代码
    • 响应数据:成功/失败消息
  4. 汇率转换POST /system/exchangeRate/convert
    • 权限要求:需要登录
    • 请求参数amount金额、fromCurrency源货币、toCurrency目标货币
    • 响应数据:转换后的金额
  5. 批量汇率转换POST /system/exchangeRate/batchConvert
    • 权限要求:需要登录
    • 请求参数amounts金额列表、fromCurrency源货币、toCurrency目标货币
    • 响应数据:转换后的金额列表
  6. 更新汇率(手动)POST /system/exchangeRate/update
    • 权限要求:@PreAuthorize("@ss.hasPermi('system:exchangeRate:edit')")
    • 请求参数fromCurrency源货币、toCurrency目标货币、rate汇率
    • 响应数据:成功/失败消息
  7. 更新汇率APIPOST /system/exchangeRate/updateFromApi
    • 权限要求:@PreAuthorize("@ss.hasPermi('system:exchangeRate:edit')")
    • 响应数据:成功更新的汇率数量

实现要点

  1. 关键实现逻辑
    • 货币格式化在 Service 层进行,使用 AOP 切面拦截响应
    • 使用 CurrencyUtils 工具类进行货币格式化和转换
    • 处理 null 值,避免空指针异常
    • 处理无效货币代码,使用默认货币
    • 支持多货币显示,自动转换并显示多种货币
  2. 异常处理设计
    • 货币格式化异常:捕获异常,记录日志,返回原始金额,提示用户货币格式化失败
    • 货币代码无效异常:捕获异常,记录日志,返回错误响应,提示用户货币代码无效
    • 缓存读取异常:捕获异常,记录日志,从数据库重新加载数据,提示用户缓存读取失败
    • 汇率转换异常:捕获异常,记录日志,返回原始金额,提示用户汇率转换失败
  3. 性能优化设计
    • 缓存优化:使用 Redis 缓存汇率数据,汇率缓存 60 分钟,货币列表缓存 24 小时,默认货币缓存 24 小时
    • 索引优化:为常用查询字段创建索引,提高查询性能
    • 批量转换优化:批量转换时使用并行处理,合理设置线程池大小
  4. 安全设计
    • 数据验证:验证货币代码有效性、格式、白名单
    • 权限控制:使用 @PreAuthorize 注解控制接口权限,使用数据权限控制数据访问范围
    • 审计日志:使用 @Log 注解记录操作日志,记录操作人、操作时间、操作内容

相关文档