Files
yidaima/RuoYi-Vue/docs/superpowers/plans/2026-07-08-ai-usage-cny-cost.md

4.9 KiB

AI Usage CNY Cost Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Make AI usage fees calculated and displayed as Chinese yuan.

Architecture: Keep the existing AI usage ledger API and database compatibility fields. Update AiCostCalculator to use CNY model rates while preserving cache-hit, cache-miss, and completion token calculation. Update the admin Vue page label and formatter to present CNY.

Tech Stack: Java, JUnit 4, Spring/MyBatis, Vue 2, Element UI.


File Structure

  • Modify: ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/AiCostCalculatorTest.java
    • Owns pricing expectations for Flash, Pro, default DeepSeek models, missing usage, and cent rounding.
  • Modify: ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/AiUsageRecorderTest.java
    • Verifies recorded ledger/scope costs reflect the calculator's CNY amount.
  • Modify: ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/AiCostCalculator.java
    • Owns token-to-money calculation and model rate selection.
  • Modify: ruoyi-ui/src/views/generator/aiUsage/index.vue
    • Owns AI usage fee labels and currency formatting.

Task 1: Backend Pricing Tests

  • Step 1: Write failing calculator expectations

Update expected values in AiCostCalculatorTest:

assertEquals(300, calculator.estimateCostCents("deepseek", "deepseek-chat", 1_000_000, 1_000_000));
assertEquals(new BigDecimal("2.90200000"),
        calculator.estimateCostUsd("deepseek", "deepseek-v4-flash", usage));
assertEquals(new BigDecimal("9.02500000"),
        calculator.estimateCostUsd("deepseek", "deepseek-v4-pro", usage));
assertEquals(new BigDecimal("3.00000000"),
        calculator.estimateCostUsd("deepseek", "deepseek-chat", usage));
  • Step 2: Verify tests fail under old USD rates

Run:

mvn -pl ruoyi-generator -Dtest=AiCostCalculatorTest test

Expected: failures show old USD amounts such as 0.40628000 where CNY amounts are expected.

  • Step 3: Update recorder expectation

In AiUsageRecorderTest, replace 0.40628000 expectations with 2.90200000.

  • Step 4: Verify recorder test fails under old USD rates

Run:

mvn -pl ruoyi-generator -Dtest=AiUsageRecorderTest test

Expected: failures show old USD amount 0.40628000 instead of 2.90000000.

Task 2: Backend CNY Implementation

  • Step 1: Replace calculator rate constants

In AiCostCalculator, replace USD constants with CNY constants:

private static final BigDecimal FLASH_CACHE_HIT_CNY_PER_1M = new BigDecimal("0.02");
private static final BigDecimal FLASH_CACHE_MISS_CNY_PER_1M = new BigDecimal("1");
private static final BigDecimal FLASH_OUTPUT_CNY_PER_1M = new BigDecimal("2");
private static final BigDecimal PRO_CACHE_HIT_CNY_PER_1M = new BigDecimal("0.025");
private static final BigDecimal PRO_CACHE_MISS_CNY_PER_1M = new BigDecimal("3");
private static final BigDecimal PRO_OUTPUT_CNY_PER_1M = new BigDecimal("6");

Keep public method names unchanged for compatibility.

  • Step 2: Update internal variable names where local only

Rename local variables and Rate fields from Usd to neutral Amount or Cny inside AiCostCalculator. Do not rename public methods or domain fields in this task.

  • Step 3: Verify backend tests pass

Run:

mvn -pl ruoyi-generator -Dtest=AiCostCalculatorTest,AiUsageRecorderTest test

Expected: both test classes pass.

Task 3: Admin UI CNY Display

  • Step 1: Update label and formatter

In ruoyi-ui/src/views/generator/aiUsage/index.vue:

<div class="metric-label">费用 CNY</div>
<div class="metric-value">{{ formatCny(summary.costUsd) }}</div>

Use formatCny for row values and return a yuan-prefixed string:

formatCny(value, cents) {
  let amount = Number(value || 0)
  if (!amount && cents) {
    amount = Number(cents || 0) / 100
  }
  return ${amount.toFixed(8).replace(/0+$/, '').replace(/\.$/, '') || '0'}`
}
  • Step 2: Verify UI references

Run:

rg -n "formatUsd|费用 USD|\\$[0-9]" ruoyi-ui/src/views/generator/aiUsage/index.vue

Expected: no matches.

Task 4: Final Verification

  • Step 1: Run targeted backend tests

Run:

mvn -pl ruoyi-generator -Dtest=AiCostCalculatorTest,AiUsageRecorderTest test

Expected: exit code 0.

  • Step 2: Check changed file diff

Run:

git diff -- ruoyi-generator/src/main/java/com/ruoyi/generator/service/front/AiCostCalculator.java ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/AiCostCalculatorTest.java ruoyi-generator/src/test/java/com/ruoyi/generator/service/front/AiUsageRecorderTest.java ruoyi-ui/src/views/generator/aiUsage/index.vue

Expected: diff only changes pricing tests, CNY rates, and UI CNY formatter/labels.