zerosaturation
|
89d5d12450
|
fix(task): backfill id=1/2 trigger_event + cleanup misleading NULL comments
daily_browse_asset (id=2) / daily_login (id=1) 之前永远不触发,根因:
2026_07_21_004 迁移只 backfill 了 id=3/4 的 trigger_event=task_key,
id=1/2 留 NULL。但 ProcessTaskEvent 引擎按 trigger_event = ? 严格匹配
(spec §4 单一隔离单元),NULL 不会命中,前端 reportEvent 后引擎跑空
循环、daily-tasks 任务永远 pending。
修复:
- 新增 2026_07_27_005 迁移:回填 id=1/2 的 trigger_event=task_key(幂等)
- 修订原 004 迁移的错误注释('trigger_event 留 NULL'误导后人)
- model/task_models.go:删除 'NULL 仍走 def.TaskKey 兜底' 不实承诺
- impl plan §37/39:修订错描述('暂不依赖 trigger_event 列')
- docker/init-db.sql:124668/124671:重建 dev DB 时也带 trigger_event
- daily_task_repo_test.go:补 2 个回归测试
- NullTriggerEvent_NotMatched:trigger_event=NULL 时查不到
- TriggerEventEqualsTaskKey_Matches:trigger_event=task_key 时能命中
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2026-07-27 16:36:40 +08:00 |
|
zerosaturation
|
cc7794e0f4
|
test(task): consumer + daily_task repo/service + like_bet ON CONFLICT 修订
Phase F.6 测试覆盖:
- mq/consumer_test.go: MQ consumer 单元测试,用 fakeDailyTaskService 模拟
ProcessTaskEvent(newHandleTaskEvent 唯一调用点)
- repository/daily_task_repo_test.go: DailyTaskRepository CRUD 单测
(复用 like_bet_repo_test.go 的 TestMain + dev PG 15432 sentinel 模式)
- service/daily_task_service_test.go: DailyTaskService.ProcessTaskEvent 核心
完成判定逻辑单测
- repository/like_bet_repo_test.go: UniqueConstraint 测试语义修订 —
BatchCreate 内部用 clause.OnConflict{DoNothing: true} 实现幂等,
重复 (exhibition_id, like_id) 不再报错,DB 仍保留 1 条记录
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2026-07-27 15:46:29 +08:00 |
|
zerosaturation
|
a9ce281d5e
|
feat(asset): emit task:event on mint success (fix daily_mint 悬空)
assetService 接入 MQ producer:铸造成功时 emit `task:event { event_type: daily_mint }`,
由 taskService consumer 异步调 ProcessTaskEvent 完成判定。
- main.go: 初始化 MQ (Asynq producer-only),沿用 galleryService 模式;
失败仅 Warn 不阻塞主路径
- service/mint_service.go: CreateMintOrder 成功分支 fire-and-forget emit
- mq/producer.go: 新增 EnqueueTaskEvent helper,封装 TaskEventPayload marshal +
adapter.TaskProducer.Enqueue
配套:spec §4 / Phase F.1 / impl plan Phase D。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2026-07-27 15:45:42 +08:00 |
|
zerosaturation
|
1e8a7476e0
|
feat(task): register task:event MQ consumer
- consumer.go: +newHandleTaskEvent(dailySvc) adapter.TaskHandler
- unmarshal TaskEventPayload -> delegate to ProcessTaskEvent
- returns non-nil error on failure -> Asynq MaxRetry=3
- consumer.go: RegisterHandlers signature +dailySvc parameter
- consumer.go: register TaskEvent with QueueDefault, MaxRetry=3
- main.go: pass dailySvc to taskmq.RegisterHandlers
Now task:event MQ messages produced by:
- assetService/mq/producer.go (Phase F.1) for daily_mint
- frontend reportEvent RPC -> gateway (Phase F.2 callers) for daily_login/browse_asset/place_asset
are consumed asynchronously and routed to ProcessTaskEvent.
spec: docs/superpowers/specs/2026-07-21-daily-task-config-driven-design.md §3 F3 + §4.2
plan: docs/superpowers/plans/2026-07-21-daily-task-config-driven-impl.md Phase E
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2026-07-27 15:42:10 +08:00 |
|
zerosaturation
|
e2f1122cc8
|
feat(task): GORM model + repository + ProcessTaskEvent engine
Phase B (model + repository):
- TaskDefinition: +TriggerEvent string, +TargetCount int
- UserDailyTaskProgress: +Progress int
- DailyTaskRepository: ListActiveDailyTaskDefinitions signature -> (starID, eventType string)
- IncrementProgress: atomic UPDATE progress=progress+1 WHERE status='pending'
(returns rows-affected 0 + re-read on race; caller decides completion transition)
- ResetAllDailyTasks: +progress: 0 in Updates map
- InitDailyTasksForUser: pass eventType='' (backward-compat)
Phase D (engine + ReportEvent delegation, spec §4.3):
- TaskEventResult struct (CompletedTaskKeys []string)
- DailyTaskService.ProcessTaskEvent: 5-step engine
1. ListActiveDailyTaskDefinitions(starID, eventType) - filter by trigger_event
2. GetOrCreateDailyProgress; skip if completed/claimed (day idempotency)
3. IncrementProgress (atomic +1)
4. if progress >= target_count -> status='completed'
5. UpdateDailyProgress + accumulate CompletedTaskKeys
- ReportEvent rewired: delegates to ProcessTaskEvent, maps TaskEventResult
to ReportEventResponse (F1: single isolation unit; MQ consumer + RPC both use engine)
- 3 callers (GetDailyTasks / ClaimDailyTask / ClaimAllDailyTasks) pass eventType=''
for backward-compat (preserves daily_login / daily_browse_asset before Phase F)
Note: Phase B and D are bundled because the signature change in B is what enables
D's engine to filter by trigger_event. Splitting would leave the codebase
uncompilable in the interim.
spec: docs/superpowers/specs/2026-07-21-daily-task-config-driven-design.md §4
plan: docs/superpowers/plans/2026-07-21-daily-task-config-driven-impl.md
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2026-07-27 15:41:35 +08:00 |
|
zerosaturation
|
e079a6c2e2
|
feat(asset): restore starbook home More button by Asset.LikeCount ordering
starbook 首页每个 grade/group 按 Asset.LikeCount DESC, Asset.ID ASC 取前三张,超三显示 has_more;
GetAssetsByType 不截断返回全部匹配项。包含:
- proto/asset.proto 声明 GetAssetsByType RPC + 消息,重新生成 .pb.go/.triple.go
- gateway starbook controller 改用标准 AssetService 客户端
- assetService: 三个 build*GroupForAssets 增加 previewLimit 参数
- 新增 sortAndLimitAssetItems 共享助手
- 新增 asset_service_group_test.go DB-free 单测
- 新增 TestStarbookHomePreviewAndMoreUseAssetLikeRanking 端到端回归
- frontend pages/starbook/items.vue 适配嵌套 groups/grades/items 响应,单 grade 竖向展示
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
2026-07-24 19:20:16 +08:00 |
|
zerosaturation
|
812aab2b79
|
fix(moderationService): start health server on port+1000 (follow-up P1)
- moderationService main.go 加 health.NewHandler + Start/Stop, 与其它 9 个 service 一致;
- 启动 health server 监听 21011 (Dubbo 端口 20011 + 1000), /health + /healthz 都注册;
- 补完后 11 个 service 都启了 health server(注: statisticService 用 gin 21009, 不冲突);
- 此前 P1 follow-up 标记的 'Pod never ready' 阻塞解除 (前提: k8s 探针改用 healthPort, 见下个 commit)。
Co-Authored-By: Claude <noreply@anthropic.com>
|
2026-07-24 15:14:31 +08:00 |
|
zerosaturation
|
f46464fdf9
|
chore(backend): remove starbookService + proto (config 4.2 cleanup)
- 删 services/starbookService 目录 (Phase 2 决策, owner 已迁 assetService);
- 删 backend/proto/starbook.proto (proto 源, 不再被任何 service 引用)。
Co-Authored-By: Claude <noreply@anthropic.com>
|
2026-07-24 14:04:37 +08:00 |
|
zerosaturation
|
8a767fb400
|
fix(backend): service stability — batch 3 accumulated (bcrypt off-txn / login anti-enum / MQ stub / aiChat / event reliability / gateway aggregate)
- 3.1 bcrypt 移出事务 (Register): repository.HashPassword 前移到 db.Transaction 之前。
- 3.2 Login 消除用户枚举 + 限流 + timing 抹平: pkg/errors 加 ErrInvalidCredential / ErrTooManyLoginAttempts;
user-not-found 跑 dummy bcrypt 抹平 ~100ms 时序差; mobile 5次/ip 20次 per 15min 限流 (Redis, fail-open 降级)。
- 3.3 MQ streams adapter 停用 → stub: 0 业务调用方, noop EventProducer.Publish; Init 不再装配 streams;
11 处硬编码 'gallery'/'default' 抽常量到 pkg/queue/consts (值不变, 消漂移)。
- 3.5 JWT 密钥治理: pkg/jwt MustInit fail-fast + atomic.Value, 50-goroutine race_test 零告警;
MustInit 调用点 gateway main + auth_provider + loadgen 同步更新。
- 3.6 aiChat 健壮性: SaveContext 用 persona.ID(非 req.PersonaId); Redis/memory 错误 记 WARN 不静默;
Dify err 映射稳定用户文案。
- 3.7 statistic.Client 重构: TrackEvent 改 buffered channel (cap 1024) + dispatchLoop worker。
- 3.8 网关聚合: StarCache (60s TTL, singleflight) 替换 GetFanIdentities 链式调用;
DeleteAccount 改网关直调 userService.DeleteAccount(避免改 hand-written triple.go);
铸造双写改异步 channel+consumer (3 retry)。
- 大量单测: 各子项 TDD (RED→GREEN), 关键并发 race_test (50 goroutine)。
- .env.example JWT_SECRET 改为 ≥32 字节 base64 示例(原为空, 被 MustInit 立即拒)。
Co-Authored-By: Claude <noreply@anthropic.com>
|
2026-07-24 14:03:21 +08:00 |
|
zerosaturation
|
a337f43f86
|
fix(config): port alignment + service test doubles (batch 4.1/4.5)
- gateway/config Dubbo URL 默认端口修正(原 20004/20005 与服务实际 20001/20004 不符);
- userService main.go 硬编码 WithPort(20000) 修死码, -port flag / PORT env 真正生效;
- .env.example 11 个 DUBBO URL 同步(对齐 serviceDefaultPorts map + 实际服务 bind);
- 删除 DUBBO_STARBOOK_SERVICE_URL 死引用(starbookService 已在 batch 4.2 删除);
- .env.example Service Ports 注释块补全 10 行, 与网关 Dubbo URL + port_test 三方一致;
- 10 个 service 各加 port_test.go, 断言 flag 默认与 serviceDefaultPorts map 一致;
- 11 个 port_test 总计 13 测试覆盖(网关 + 10 service);
- .gitignore 加 userService/main.go.bak 排除(临时备份)。
Co-Authored-By: Claude <noreply@anthropic.com>
|
2026-07-24 14:02:14 +08:00 |
|
zerosaturation
|
e1326acaf9
|
fix(backend): service stability — bcrypt off-txn / login anti-enum / MQ stub / aiChat / event reliability / gateway aggregate (batch 3)
- 3.1 bcrypt 移出事务 (Register): repository.HashPassword 前移到 db.Transaction 之前,消除连接池占用。
- 3.2 Login 消除用户枚举 + 限流 + timing 抹平: pkg/errors 加 ErrInvalidCredential
/ErrTooManyLoginAttempts; 用户不存在/密码错/密码空 三路径统一返回同一错误;
mobile 5次/ip 20次 per 15min 限流 (Redis, fail-open 降级); user-not-found 走
dummy bcrypt 抹平 ~100ms 时序差,完全消除枚举侧信道;空密码分支已核实无时序 leak。
- 3.3 MQ streams adapter 停用 → stub: 0 业务调用方, 新 stub EventProducer.Publish no-op;
pkg/mq/mq.go Init 不再装配 streams; 全仓 grep 验证 11 处硬编码
'gallery'/'default' 集中到 pkg/queue/consts (值不变, 仅消漂移)。
- 3.5 JWT 密钥治理: pkg/jwt MustInit fail-fast + atomic.Value (见上一个 commit 293c7b1)。
- 3.6 aiChat 健壮性: SaveContext 用 persona.ID(非 req.PersonaId); Redis/memory 错误
记 WARN 不静默; Dify err 映射稳定用户文案,原始 err 仅服务端日志。
- 3.7 statistic.Client 重构: TrackEvent 改 buffered channel (cap 1024) + dispatchLoop
worker; 失败 ERROR 日志带字段; drop 记 WARN; Close 可重复调用。
- 3.8 网关聚合: StarCache (60s TTL, singleflight) 替换 5+ 处 GetFanIdentities 链式调用;
DeleteAccount 改网关直调 userService.DeleteAccount(避免改 hand-written triple.go
风险,见报告 §5 proto 风险复盘); 铸造双写改异步 channel+consumer (3 retry)。
- 大量单测: 各子项 TDD (RED→GREEN), 关键并发 race_test (50 goroutine)。
Co-Authored-By: Claude <noreply@anthropic.com>
|
2026-07-23 18:50:40 +08:00 |
|
zerosaturation
|
3407e30395
|
refactor(assetService): CreateMintOrder 3-phase txn + orphan reconciliation (P0-2)
- CreateMintOrder 拆三段: txn1(PENDING→PROCESSING,不调RPC/不写asset)
→ 事务外 UpdateCrystalBalance 扣水晶 → txn2(建asset+registry→SUCCESS);
消除 DB 事务内嵌跨服务 gRPC(连接池占用+跨服务事务风险)。
- 任一步失败 markMintOrderFailed 独立事务标 FAILED(不回滚已扣水晶=审计流水,
重试靠 Task1 source_id 幂等 + Task2 入口短路防双扣); nil-cause 防御。
- 孤儿订单对账 ReconcileStuckMintOrders: 扫陈旧 PROCESSING 单,查 mint_cost 流水—
已扣未建→FOR UPDATE 行锁下幂等补完 SUCCESS(串行化并发防双建),未扣→FAILED,绝不退款。
- main.go 接线周期 worker(MINT_RECONCILE_INTERVAL_SEC 默认600s,0关,优雅退出)。
- 测试: RPC失败落FAILED / 对账未扣→FAILED / 已扣未建→补完(含幂等二次跑)。
Co-Authored-By: Claude <noreply@anthropic.com>
|
2026-07-23 12:28:57 +08:00 |
|
zerosaturation
|
b7022d2dc1
|
fix(backend): auth boundary — trusted identity from ctx (batch 2)
- 新增 pkg/authctx: 从 Dubbo attachment/gRPC metadata 提取可信 user_id/star_id,
统一覆盖 req 同名字段, 缺身份返 Unauthenticated。
- 各 provider 接入(堵身份伪造/越权):
* moderation SubmitReport 等 6 RPC(举报人伪造)
* asset CheckAssetLike/GetAssetQrcode/TrackShare(点赞/分享归因伪造)
* social CheckFriendship(修 starID=0 隐私预言机)
* activity PurchaseItem/BatchPurchaseItem(水晶扣费伪造)等 5 RPC
* gallery/aiChat/task/notification 迁移 authctx, 删散落 extractUserInfo*
- social 正确性: GetUserLikedAssets OR 显式分组(防御); GetRandomUsersByStar 真随机(去 rand.Seed)。
- gateway: /auth/validate 移入 AuthMiddleware 保护组(/refresh 保留,依赖注入身份)。
- 删 userService 已迁移死函数; notification 缺身份错误码统一为 Unauthenticated。
- 各 provider 单测(伪造身份被覆盖 + 缺身份拒绝)。
Co-Authored-By: Claude <noreply@anthropic.com>
|
2026-07-23 01:12:35 +08:00 |
|
zerosaturation
|
878bd46399
|
fix(backend): financial correctness — settlement/hours/mint idempotency (batch 1)
- settlement(1.1): exhibition_revenue_records 加 UNIQUE(exhibition_id,cycle_start_time)
+ CreateRevenueRecord ON CONFLICT DO NOTHING; MQ 用 settled_at 替代复用 is_processed;
恢复扫描器过滤改 settled_at IS NULL; created_at 统一毫秒; 删死代码 cleanup_worker.go。
- hours(1.2): 新增 exhibition_hours_log/asset_exhibition_hours_log(source_id 唯一)幂等表;
fan_profile/assetLevel 的 AddExhibitionHours 按 sourceID 幂等(事务包裹); 存量重算脚本。
- mint(1.4/1.5/1.6): crystal_transaction_records (source_id,change_type) 部分唯一索引
+ UpdateCrystalBalance/CreateMintOrder 幂等; 保底改 crypto/rand; 下线伪 tx_hash;
doMint Redis Lua 原子限流。
- migrations 001/002/003; 各服务单测(自包含, 缺 DB t.Skip)。
Co-Authored-By: Claude <noreply@anthropic.com>
|
2026-07-23 01:11:54 +08:00 |
|
zerosaturation
|
d554d7be83
|
feat:修改周边验证
|
2026-07-17 16:53:57 +08:00 |
|
zerosaturation
|
18aff3b682
|
fix:修改bug
|
2026-07-15 13:12:27 +08:00 |
|
zerosaturation
|
c0b577dd40
|
feat:增加邮箱管理功能
|
2026-07-14 21:59:15 +08:00 |
|
zerosaturation
|
d900c0d8b2
|
feat:增加验证真伪访问次数和首次验证
|
2026-07-13 14:24:42 +08:00 |
|
zerosaturation
|
74853800b6
|
feat:增加二维码验证真伪的功能
|
2026-07-13 11:22:56 +08:00 |
|
zerosaturation
|
e5bd0c854c
|
feat:增加忘记密码的功能
|
2026-07-09 19:00:03 +08:00 |
|
zerosaturation
|
958c867309
|
fix:修改举报/反馈的bug
|
2026-07-06 16:22:26 +08:00 |
|
zerosaturation
|
dcb4e451a1
|
fix:修改合并后bug
|
2026-07-06 10:25:06 +08:00 |
|
|
|
66d226948f
|
Merge pull request 'feat/actvity' (#4) from feat/actvity into dev
Reviewed-on: https://git.liantu.tech/xiaoyu/topfans/pulls/4
合并feat/actvity
|
2026-07-03 16:28:30 +00:00 |
|
zerosaturation
|
8376afc5d6
|
feat:修改websocket的性能和相关的问题
|
2026-07-03 22:04:11 +08:00 |
|
zerosaturation
|
1afee2de73
|
feat:修改的欢迎页的冷启动和系统重启的错误触发和一键登录页的路径修改
|
2026-07-03 18:54:03 +08:00 |
|
zerosaturation
|
c07e8e9c19
|
fix:修改数据看板bug
|
2026-07-03 14:57:14 +08:00 |
|
zerosaturation
|
d12a84c1f0
|
feat:增加队列修改收益方面把轮询改为MQ队列,修改数据看板的数据问题出错
|
2026-07-03 12:34:55 +08:00 |
|
zerosaturation
|
355ac4393b
|
feat:修改收益的计算
|
2026-07-03 12:34:55 +08:00 |
|
Lenticular Studio Agent
|
65ce6bba12
|
feat: Dify 部署脚本修复 + AI 搭子 MVP 接入
主要改动:
fix(docker/dify-deploy): 修复脚本核心功能
- heredoc 单引号 bug: 'ENVEOF' 改为 ENVEOF,变量正确展开
- 端口默认值 8083/8084/8085 对齐 .env.prod 生产配置
- 加 dc_cmd() 兼容 docker-compose v1/v2 plugin
- openssl rand 生成强随机密码与 SECRET_KEY(42 字符)
- install 跳过已存在 .env,保护用户配置(管理员密码/SECRET_KEY)
- read -p < /dev/tty 兼容非 tty 环境(CI/CD)
- show-config 改用 DIFY_NGINX_PORT(nginx 入口)而非 APP_WEB_PORT
docs(mvp-design): 修正 §3.2 workflow inputs 描述
- 实际只有 query,删除错误的 user_id input 声明
- 节点序列图同步更新
feat(aiChatService): 新增 Dify 客户端与适配器
- service/dify_client.go: Dify Workflow 调用 + SSE 解析
- service/dify_adapter.go: 与现有 chat_service 桥接
- provider/ai_chat_provider.go: Dubbo 入口简化
- main.go: 装配 ConversationRepository + DifyClient
feat(migrations): 新增 AI 搭子会话表 ai_chat.sql
- ai_conversations / ai_messages 表 + 索引
docs: 新增 Dify 集成设计文档
- 2026-06-29-ai-chat-dify-mvp-design.md (MVP 实施级)
- 2026-06-29-ai-chat-dify-integration-v2-design.md (V2 演进路线图)
- docs/dify/角角.yml (Workflow DSL 导出)
config: 更新 env 模板与 docker 配置
- backend/.env.example: DIFY_* 环境变量声明
- docker/.env.prod: DIFY_API_BASE 对齐 8083
- docker/build.sh: 微调
- CLAUDE.md: 项目规范补充
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
|
2026-07-02 12:32:34 +08:00 |
|
zerosaturation
|
9c3fe6d695
|
feat:修复点赞收益的问题
|
2026-07-01 11:03:50 +08:00 |
|
zerosaturation
|
3cd68acf6d
|
feat:完善计算点赞押注收益
|
2026-06-29 14:47:32 +08:00 |
|
|
|
c02e53fc0e
|
feat:修改h5地址
|
2026-06-26 18:10:51 +08:00 |
|
|
|
946e204573
|
feat:修改canvas合成图
|
2026-06-26 17:58:37 +08:00 |
|
zerosaturation
|
2032246fd0
|
feat:增加分享界面,完善的保存图片功能
|
2026-06-26 16:45:29 +08:00 |
|
zerosaturation
|
0d6b7a9e95
|
feat:增加购买道具的聚合功能
|
2026-06-24 19:51:13 +08:00 |
|
zerosaturation
|
b7e2aee399
|
feat:修改活动 TOP3 + 我的排名
|
2026-06-24 18:10:12 +08:00 |
|
Lenticular Studio Agent
|
fd5e317e05
|
merge: 解决 docker-compose 和 SocketManager 冲突
Co-Authored-By: Claude <noreply@anthropic.com>
|
2026-06-23 23:06:24 +08:00 |
|
Lenticular Studio Agent
|
67cf3d4177
|
chore: 清理 laserCompositor 微服务残留
- 删除已弃用的 compositor_client.go
- 删除激光合成微服务代码
- 添加 gateway 合成控制器和测试文件
- 添加 Dify prompt 补丁脚本
Co-Authored-By: Claude <noreply@anthropic.com>
|
2026-06-23 22:44:03 +08:00 |
|
zerosaturation
|
37a3f292df
|
feat:访问他人展览页面修改
|
2026-06-23 22:29:39 +08:00 |
|
zerosaturation
|
12571eedba
|
feat:修改活动弹窗bug
|
2026-06-23 18:57:50 +08:00 |
|
zerosaturation
|
75ab617c6c
|
feat:增加实时留言功能和修改轮询道具购买记录显示改为websocket显示
|
2026-06-23 18:13:55 +08:00 |
|
zerosaturation
|
7eb6dad434
|
feat:新增举报和反馈功能
|
2026-06-22 17:19:48 +08:00 |
|
zerosaturation
|
ef0a4f6afd
|
feat:修改通知系统的消息
|
2026-06-17 11:59:51 +08:00 |
|
|
|
ddc5b89a6c
|
frat:增加uniPush的配置
|
2026-06-16 23:49:40 +08:00 |
|
zerosaturation
|
7074546959
|
feat:新增通知系统
|
2026-06-16 21:30:58 +08:00 |
|
zerosaturation
|
060e4944fa
|
fix:修改JWTbug
|
2026-06-15 21:12:59 +08:00 |
|
zerosaturation
|
271e0350c7
|
feat:重构code状态码
|
2026-06-15 16:28:35 +08:00 |
|
zerosaturation
|
56fc2f6beb
|
feat:修改密码增加手机号+短信验证
|
2026-06-15 14:15:24 +08:00 |
|
zerosaturation
|
280b4bbee0
|
feat:docker新增统计的微服务
|
2026-06-11 16:35:56 +08:00 |
|
zerosaturation
|
dfb79af4b1
|
feat: 铸造菜单改为动态配置
|
2026-06-09 12:38:12 +08:00 |
|