zizi 43fce856d7 feat: Wave2 变现域 ad+trade 后端建成验证 + game-admin 运营台脊柱
后端(主 agent 独立复跑验证,非采信子 agent 自报):
- 新建 game-module-ad(广告引擎)+ game-module-trade(分账/结算/提现),克隆黄金模板 project
- 契约先行已锁:ad.yaml/trade.yaml + Flyway V6/V7;ad 计费 uk_trace 收紧为 (trace_id,event_type,tenant_id) 防 reward 被 impression 静默吞掉
- ad↔trade Feign seam(AdRevenueApi.getUnsettledRevenue/markSettled)+ project-api 归因(getCreatorUserId,game 模块首个跨模块 Feign,仿 yudao DictDataApi)
- AdProvider SPI(mock,留 csj/gdt 注入位);资金安全:金额用分/uk 幂等/状态机 CAS/防超扣/T+1 结算补偿
- pay 不建,复用 yudao-pay 后置(Doc B:收单归 pay、钱包提现归 trade;MVP 钱财闭环 ad→trade 不经收单)
- 验证:mvn -pl yudao-server -am compile 全量 BUILD SUCCESS;ad 15 + trade 24 = 39 单测绿;huijing 残留=0、裸 select*=0

前端 game-admin(运营后台):
- 克隆 yudao-ui-admin-vue3 裁剪(删 crm/erp/mall/mes/iot 等无关业务模块)+ 5 个 MVP 运营页接 admin-api(审核/精选/看板/广告位/提现审核)+ mock 兜底
- 构建验证移至 mini-desktop(本机 5.8G 内存 OOM,见执行 spec)

文档:HJ-PAR-002 review+execution 双 spec + Workflow 编排脚本

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 16:20:17 +00:00

108 lines
2.1 KiB
TypeScript

import { defineConfig, toEscapedSelector as e, presetUno } from 'unocss'
// import transformerVariantGroup from '@unocss/transformer-variant-group'
export default defineConfig({
// ...UnoCSS options
rules: [
[
/^custom-hover$/,
([], { rawSelector }) => {
const selector = e(rawSelector)
return `
${selector} {
display: flex;
height: 100%;
padding: 0 10px;
cursor: pointer;
align-items: center;
transition: background var(--transition-time-02);
}
/* you can have multiple rules */
${selector}:hover {
background-color: var(--top-header-hover-color);
}
.dark ${selector}:hover {
background-color: var(--el-bg-color-overlay);
}
`
}
],
[
/^layout-border__left$/,
([], { rawSelector }) => {
const selector = e(rawSelector)
return `
${selector}:before {
content: "";
position: absolute;
top: 0;
left: 0;
height: 100%;
background-color: var(--el-border-color);
z-index: 3;
}
`
}
],
[
/^layout-border__right$/,
([], { rawSelector }) => {
const selector = e(rawSelector)
return `
${selector}:after {
content: "";
position: absolute;
top: 0;
right: 0;
width: 1px;
height: 100%;
background-color: var(--el-border-color);
z-index: 3;
}
`
}
],
[
/^layout-border__top$/,
([], { rawSelector }) => {
const selector = e(rawSelector)
return `
${selector}:before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 1px;
background-color: var(--el-border-color);
z-index: 3;
}
`
}
],
[
/^layout-border__bottom$/,
([], { rawSelector }) => {
const selector = e(rawSelector)
return `
${selector}:after {
content: "";
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 1px;
background-color: var(--el-border-color);
z-index: 3;
}
`
}
]
],
presets: [presetUno({ dark: 'class', attributify: false })],
// transformers: [transformerVariantGroup()],
shortcuts: {
'wh-full': 'w-full h-full'
}
})