fix(价格展示): 修复模板渲染时极小价格被折叠为 0.00 的问题

Motivation:
此前的修复仅覆盖直接拼接文案的场景,跟单等基于模板渲染的推送场景中,%.2f 格式化仍会把 PEPE 等 Meme 币的极小价格(如 0.00000059)折叠为 0.00,导致交易通知丢失真实价格、误导用户。

Changes:

* 抽取共享的价格显示逻辑到统一显示层,两个订阅者改为复用,移除重复实现
* 新增 Decimal 类型,渲染时以副本方式包装模板数据,使模板内 printf 风格格式化保留极小价格精度且不出现科学计数法,同时不修改调用方原始数据
* 渲染引擎空值判断改用反射实现,覆盖全部整型、无符号整型与浮点类型
* 补充转换到渲染的端到端回归测试,覆盖极小价格精度、科学计数法与数据不可变性
This commit is contained in:
2026-08-23 00:12:41 +08:00
parent c7e154d7cc
commit 6f5aaa9f85
6 changed files with 135 additions and 60 deletions
+15 -12
View File
@@ -3,8 +3,11 @@ package engine
import (
"bytes"
"fmt"
"reflect"
"strings"
"text/template"
"aiaa-notification-service/internal/display"
)
type Renderer struct{}
@@ -26,7 +29,7 @@ func (r *Renderer) Render(tmplContent string, data map[string]interface{}) (stri
return "", fmt.Errorf("parse template: %w", err)
}
var buf bytes.Buffer
if err := tmpl.Execute(&buf, data); err != nil {
if err := tmpl.Execute(&buf, display.WrapMap(data)); err != nil {
return "", fmt.Errorf("execute template: %w", err)
}
return buf.String(), nil
@@ -82,17 +85,17 @@ func isEmptyValue(v any) bool {
return strings.TrimSpace(t) == ""
case bool:
return !t
case int:
return t == 0
case int32:
return t == 0
case int64:
return t == 0
case float32:
return t == 0
case float64:
return t == 0
default:
return false
rv := reflect.ValueOf(v)
switch rv.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return rv.Int() == 0
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return rv.Uint() == 0
case reflect.Float32, reflect.Float64:
return rv.Float() == 0
default:
return false
}
}
}