@usethink/cf-admin-fe 0.2.6 → 0.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/utils/i18n.d.ts +14 -0
- package/dist/utils/index.d.ts +1 -0
- package/docs/001_cf-admin-fe/346/217/220/345/217/226/345/267/256/350/267/235/345/210/206/346/236/220/346/212/245/345/221/212_2026-08-05.md +2 -1
- package/docs/002_cf-admin-fe/344/275/277/347/224/250/350/257/264/346/230/216/344/271/246/344/270/216/346/263/250/346/204/217/344/272/213/351/241/271.md +7 -3
- package/docs/003_cf-admin-fe/346/236/201/350/207/264/345/214/226/346/226/271/346/241/210/344/270/216/345/217/226/350/210/215_2026-08-05.md +332 -0
- package/package.json +7 -2
- package/recipes/README.md +2 -1
- package/src/components/AdminShell.vue +4 -16
- package/src/components/ConfigField.vue +4 -18
- package/src/index.ts +4 -0
- package/src/styles/admin-primitives.css +5 -1
- package/src/utils/i18n.ts +63 -0
- package/src/utils/index.ts +6 -0
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
面向 Cloudflare 产品家族(`cf-shop`、`cf-lottery`、`cf-auth` 以及未来的 CF 管理端应用)的 Vue 3 **管理端基础套件(admin foundation)**。
|
|
4
4
|
|
|
5
|
-
**状态:** **0.2.
|
|
5
|
+
**状态:** **0.2.8** — P0 三件套:`resolveAdminT` / `tKit`、AdminShell/ConfigField/MetadataDetail 契约测、`size-report`。完整用法见 **[`docs/002_cf-admin-fe使用说明书与注意事项.md`](./docs/002_cf-admin-fe使用说明书与注意事项.md)**;起步清单见 `recipes/README.md`;路线图见 **[`docs/003_cf-admin-fe极致化方案与取舍_2026-08-05.md`](./docs/003_cf-admin-fe极致化方案与取舍_2026-08-05.md)**。
|
|
6
6
|
|
|
7
7
|
**核心目标:** 最大化共享 **管理端前端基础套件**,让 CF 产品快速搭建 — **不**通过克隆业务页面实现,也 **不** 强迫每个产品套用 shop 的 Bearer 模式。
|
|
8
8
|
|
|
@@ -287,6 +287,8 @@ npm pack # 触发 prepack→build;入口仍以 src/ 为准
|
|
|
287
287
|
- **0.2.5** — `createAdminFlagSession`、request `onSuccess` / credentials、cookie recipes(cf-auth 验证)
|
|
288
288
|
- **0.2.6** — `toErrorMessage`、批量 toast/数量上限;`formatMetadata` + `AdminMetadataDetail`;`buildAdminOffsetParams` / `applyAdminOffsetParams`;`copyWithToast`;`recipes/list-page.snippet.ts`;封包 clean/prepack/LICENSE;完整说明书 `docs/002_…`
|
|
289
289
|
- **0.2.6 文档收口(无 API 变更)** — README/recipes/001/002 对齐:string vs number offset、batch `limit` 须跟后端 max、shop §5.8 接线对照、MetadataDetail「新页优先」
|
|
290
|
+
- **0.2.7** — `.table-wrap` 去掉 `scrollbar-gutter: stable`,消除无溢出时表格右侧缺口
|
|
291
|
+
- **0.2.8** — `resolveAdminT` / `tKit`;AdminShell / ConfigField / AdminMetadataDetail 契约测;`npm run size-report`(CSS/源码规模 + runtime dep 门禁)
|
|
290
292
|
|
|
291
293
|
## 许可证
|
|
292
294
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type AdminI18nProxy = {
|
|
2
|
+
$t?: (key: string, params?: Record<string, unknown>) => unknown;
|
|
3
|
+
$te?: (key: string) => boolean;
|
|
4
|
+
} | null | undefined;
|
|
5
|
+
/**
|
|
6
|
+
* 纯函数:可在单测中直接注入 proxy,不依赖 setup。
|
|
7
|
+
*/
|
|
8
|
+
export declare function resolveAdminT(proxy: AdminI18nProxy, key: string, fallback: string, params?: Record<string, unknown>): string;
|
|
9
|
+
/**
|
|
10
|
+
* 从当前组件实例的 appContext.globalProperties 读取 `$t` / `$te`。
|
|
11
|
+
* 使用 globalProperties 而非 `proxy.$t`,避免未安装 vue-i18n 时访问实例代理触发 Vue warn。
|
|
12
|
+
* 勿在模块顶层调用。
|
|
13
|
+
*/
|
|
14
|
+
export declare function tKit(key: string, fallback: string, params?: Record<string, unknown>): string;
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -10,3 +10,4 @@ export { hasBatchFailures, resolveBatchToastType, formatBatchCountsMessage, buil
|
|
|
10
10
|
export { DEFAULT_ADMIN_BATCH_LIMIT, checkAdminBatchLimit, type AdminBatchLimitOk, type AdminBatchLimitExceeded, type AdminBatchLimitCheck, type CheckAdminBatchLimitOptions, } from './batch-limit';
|
|
11
11
|
export { formatMetadata, } from './format-metadata';
|
|
12
12
|
export { buildAdminOffsetParams, applyAdminOffsetParams, type AdminOffsetParams, } from './admin-query';
|
|
13
|
+
export { resolveAdminT, tKit, type AdminI18nProxy, } from './i18n';
|
|
@@ -182,7 +182,8 @@
|
|
|
182
182
|
| cursor 分页 helper | 字段命名因产品而异 | ≥2 产品同一 cursor/`hasMore` 约定 |
|
|
183
183
|
| batch 默认 limit「产品 profile」工厂 | 显式 `{ limit: N }` 已够清晰 | 三端都厌倦每次写 limit **且** N 集合稳定 |
|
|
184
184
|
|
|
185
|
-
**维护文档真相源:** 接线细节以 [`002` §5.8](./002_cf-admin-fe使用说明书与注意事项.md) 为准;本文只记决策与结案,**勿把 R5 当立即开工的 backlog**。
|
|
185
|
+
**维护文档真相源:** 接线细节以 [`002` §5.8](./002_cf-admin-fe使用说明书与注意事项.md) 为准;本文只记决策与结案,**勿把 R5 当立即开工的 backlog**。
|
|
186
|
+
**后续取舍与近端路线(含 P0 三件套、脚手架/文档站冻结条件):** 见 [`003` 极致化方案与取舍](./003_cf-admin-fe极致化方案与取舍_2026-08-05.md)。
|
|
186
187
|
|
|
187
188
|
---
|
|
188
189
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# @usethink/cf-admin-fe 使用说明书与注意事项
|
|
2
2
|
|
|
3
|
-
> **版本:** 0.2.
|
|
3
|
+
> **版本:** 0.2.8(以 `package.json` 为准)
|
|
4
4
|
> **读者:** 新建 CF 管理端前端、或把既有 admin 接到本套件的开发者
|
|
5
5
|
> **原则:** 只写仓库里真实存在的 API 与约束;不发明业务能力。
|
|
6
|
-
> **配套:** 根 [`README.md`](../README.md)(API 面速查)· [`recipes/README.md`](../recipes/README.md)(复制清单)· [`docs/001_…差距分析`](./001_cf-admin-fe提取差距分析报告_2026-08-05.md)
|
|
6
|
+
> **配套:** 根 [`README.md`](../README.md)(API 面速查)· [`recipes/README.md`](../recipes/README.md)(复制清单)· [`docs/001_…差距分析`](./001_cf-admin-fe提取差距分析报告_2026-08-05.md)(提取决策背景)· [`docs/003_…极致化取舍`](./003_cf-admin-fe极致化方案与取舍_2026-08-05.md)(路线图与做/不做裁决,非 API 说明书)
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -784,7 +784,8 @@ npm run build # 生成 dist 声明;可选 npm pack 干跑
|
|
|
784
784
|
|
|
785
785
|
### 10.4 明确不进本封版
|
|
786
786
|
|
|
787
|
-
R5 观察项(number offset helper、silent copy 选项、cursor helper、batch profile 工厂)、旧页迁 `AdminMetadataDetail`、领域 CRUD、C 端 storefront。
|
|
787
|
+
R5 观察项(number offset helper、silent copy 选项、cursor helper、batch profile 工厂)、旧页迁 `AdminMetadataDetail`、领域 CRUD、C 端 storefront。
|
|
788
|
+
后续「该不该做、做到什么程度」见 [`003` 极致化方案与取舍](./003_cf-admin-fe极致化方案与取舍_2026-08-05.md)(P0 三件套 / 冻结项与触发条件);**勿把 003 当本说明书的 API 增补**。
|
|
788
789
|
|
|
789
790
|
---
|
|
790
791
|
|
|
@@ -797,5 +798,8 @@ R5 观察项(number offset helper、silent copy 选项、cursor helper、batch
|
|
|
797
798
|
| 2026-08-05 | **P1–P3 文档收口(无 API)**:README/recipes/001/002 对称 string vs number offset、batch limit 跟后端 max、MetadataDetail 新页优先、R5 观察期 |
|
|
798
799
|
| 2026-08-05 | **§10 封版与部署注意**;三端验证全绿后的冻结摘要 |
|
|
799
800
|
| 2026-08-05 | **AdminShell 用户区上移顶栏右上**(省侧栏高度;`#sidebar-footer` 可选;窄屏可藏用户名) |
|
|
801
|
+
| 2026-08-05 | **0.2.7** `.table-wrap` 去掉 `scrollbar-gutter: stable`,消除全站表格右侧缺口 |
|
|
802
|
+
| 2026-08-05 | 配套链增加 [`003` 极致化方案与取舍](./003_cf-admin-fe极致化方案与取舍_2026-08-05.md);§10.4 指向 003 作路线图(非 API) |
|
|
803
|
+
| 2026-08-05 | **0.2.8** P0:`resolveAdminT`/`tKit`、SFC 契约测、`size-report`;版本锚点同步 |
|
|
800
804
|
|
|
801
805
|
**维护约定:** API 变更时同步改本文件、根 README 公开 API 节、`recipes/README.md` 与 `tests/public-api.test.ts`。说明书只描述已实现行为;示例代码须与 `src/` 签名一致。
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
# @usethink/cf-admin-fe 极致化方案与取舍
|
|
2
|
+
|
|
3
|
+
> **版本锚点:** 以 `package.json` 为准(**0.2.8** 已落地 §9.1 P0 三件套;起草基线为 0.2.7)
|
|
4
|
+
> **日期:** 2026-08-05(P0 落地修订同日)
|
|
5
|
+
> **性质:** 路线图与决策备忘(**不是**待办全开的 backlog;**不是**对外 API 说明书)
|
|
6
|
+
> **配套:** [`002` 使用说明书](./002_cf-admin-fe使用说明书与注意事项.md) · [`001` 提取差距结案](./001_cf-admin-fe提取差距分析报告_2026-08-05.md) · 根 [`README.md`](../README.md) · [`recipes/README.md`](../recipes/README.md)
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 0. 文档怎么用
|
|
11
|
+
|
|
12
|
+
| 读者问题 | 读哪里 |
|
|
13
|
+
|----------|--------|
|
|
14
|
+
| 怎么接套件、有哪些 API | **002** + README + recipes |
|
|
15
|
+
| 当初抽了什么、故意不抽什么 | **001**(结案,勿当未完成清单) |
|
|
16
|
+
| **下一步该不该做、做到什么程度** | **本文 003** |
|
|
17
|
+
| 某条观察项(如 number offset)何时可提 API | 本文 §5.2 + 001 **R5** + 002 §5.8 / 不做清单 |
|
|
18
|
+
|
|
19
|
+
**维护约定:**
|
|
20
|
+
|
|
21
|
+
- 实施完成后,把对应条目改成「已落地(版本号)」,**不要**删决策理由。
|
|
22
|
+
- 新想法先对照 §1 定位与 §2 提取纪律;通不过则记入 §7「冻结 / 触发条件」,勿直接开码。
|
|
23
|
+
- 本文可随迭代修订;**破坏性结论变更**须在文末修订表留一行。
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 1. 核心定位(一切极致化的前提)
|
|
28
|
+
|
|
29
|
+
### 1.1 一句话
|
|
30
|
+
|
|
31
|
+
`@usethink/cf-admin-fe` 是 **CF 产品族 Vue 3 管理端「业务模式」基础套件**,不是通用 UI 组件库,不是业务中台,不是 Worker/API 包。
|
|
32
|
+
|
|
33
|
+
### 1.2 已验证边界(0.2.x 守住的)
|
|
34
|
+
|
|
35
|
+
| 是 | 不是 |
|
|
36
|
+
|----|------|
|
|
37
|
+
| 壳(AdminShell / LoginShell)、表格 UX、分页/选择/确认/Toast | Element / Ant 式通用控件集 |
|
|
38
|
+
| 双会话工厂(Bearer token / Cookie+flag)+ request 旋钮 | 产品域 `api/admin.ts` 方法全集 |
|
|
39
|
+
| ConfigField、列表 loader、错误/批量助手、offset **string** 查询助手 | 订单/抽奖/OAuth/RBAC 页面 |
|
|
40
|
+
| i18n **种子** + recipes 复制清单 | 「一条命令生成完整业务后台」的产品本身 |
|
|
41
|
+
| 在 **≥2 真实消费方**(或第 3 路径验证出的通用缺口)后提取 | 为对齐单一产品而抹平特殊性 |
|
|
42
|
+
|
|
43
|
+
**线上验证面(起草时):**
|
|
44
|
+
|
|
45
|
+
| 产品 | 会话 | 在套件中的角色 |
|
|
46
|
+
|------|------|----------------|
|
|
47
|
+
| **cf-shop** | Bearer | 主路径参考 |
|
|
48
|
+
| **cf-lottery** | Bearer + 平台/仿冒胶水 | Bearer 扩展;布局可有产品自有部分 |
|
|
49
|
+
| **cf-auth** | Cookie + flag | **检验 cookie 路径**;禁止把 OAuth/业务页抽进 kit |
|
|
50
|
+
|
|
51
|
+
### 1.3 「极致」在本仓库的定义
|
|
52
|
+
|
|
53
|
+
对 solo / 小团队维护者,**极致 = 减少摩擦 + 提高改动安全感**,**不是**功能表面积最大化。
|
|
54
|
+
|
|
55
|
+
优先序:
|
|
56
|
+
|
|
57
|
+
1. **改组件不踩雷**(契约可测)
|
|
58
|
+
2. **重复逻辑有单一真相**(如 i18n fallback)
|
|
59
|
+
3. **体积与依赖不偷偷膨胀**
|
|
60
|
+
4. **提取纪律可执行**(≥2 同形,写进政策)
|
|
61
|
+
5. 仅在摩擦真实变大时,再上脚手架 / 文档站 / 更深工厂
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## 2. 治理纪律(建议升格为公开政策)
|
|
66
|
+
|
|
67
|
+
以下三条应与 001/002 一致,并在评审新 PR 时当作硬门禁:
|
|
68
|
+
|
|
69
|
+
1. **不进** Element/Ant 式通用组件库路线。
|
|
70
|
+
2. **不抽** 仅单产品出现的页面编排(业务列定义、域 CRUD、产品特有批量语义)。
|
|
71
|
+
3. **提取门槛:**
|
|
72
|
+
- 同形模式出现在 **≥2 个消费方**,或
|
|
73
|
+
- **同一产品 ≥3 处**稳定复制且契约不再摇摆,或
|
|
74
|
+
- **第 3 条路径**(如 cookie)验证出的通用缺口。
|
|
75
|
+
|
|
76
|
+
**禁止:** 为「看起来整齐」而预抽;为「对齐 shop」而抹平 auth。
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## 3. 现状快照(相对极致化议题)
|
|
81
|
+
|
|
82
|
+
| 维度 | 起草时实况 | 含义 |
|
|
83
|
+
|------|------------|------|
|
|
84
|
+
| 测试 | ~27 个测试文件,**composable / utils 为主**;**8 个 `.vue` 几乎无渲染测** | 模板/插槽回归靠手测,套件信任短板 |
|
|
85
|
+
| 交付形态 | `exports` 指向 **`src/`**;`build` 主要产 **`.d.ts`**;CSS 在 `src/styles` | 体积 KPI 不能按「单一 runtime bundle」幻想来设计 |
|
|
86
|
+
| i18n | `AdminShell.tFallback` 与 `ConfigField.tSafe` **同构重复**;部分组件模板直接 `$t` | 收口 ROI 高、对外行为可兼容 |
|
|
87
|
+
| 请求层 | `createAdminRequest` 已有 `resultMode` / `credentials` 等;产品仍自写 `api/*` | 实例级配置已够用;路径级 registry 证据不足 |
|
|
88
|
+
| 分页 | `buildAdminOffsetParams` **仅 string**(URLSearchParams);number body 手写 | 与 001 **R5** / 002 一致,默认不扩 API |
|
|
89
|
+
| 样式 | `.table-wrap` 已在 **0.2.7** 去掉 `scrollbar-gutter: stable`(消除无溢出右侧缺口) | 表格以视觉对齐优先;弹层/卡片列表仍可 stable |
|
|
90
|
+
| 接入 | recipes **清单式复制**,无官方脚手架 | 3 内部消费方阶段可接受 |
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## 4. 分层裁决总表
|
|
95
|
+
|
|
96
|
+
图例:**采纳** = 应排期;**轻量采纳** = 做,但改写目标;**暂缓** = 有条件再开;**冻结** = 默认不做。
|
|
97
|
+
|
|
98
|
+
| 层级 | 议题 | 裁决 | 一句话理由 |
|
|
99
|
+
|------|------|------|------------|
|
|
100
|
+
| **P0** | 组件 SFC 契约测试 | **已落地(0.2.8)** | `tests/AdminShell|ConfigField|AdminMetadataDetail.test.ts` + happy-dom |
|
|
101
|
+
| **P0** | 体积 / 依赖监控 | **已落地(0.2.8)** | `scripts/size-report.mjs` + `size-baseline.json`;`size-report` / `:write` / `:check` |
|
|
102
|
+
| **P0** | 统一 i18n fallback(`tKit` 等) | **已落地(0.2.8)** | `resolveAdminT` / `tKit`;Shell + ConfigField 收口 |
|
|
103
|
+
| **P1** | `createAdminApi` 路径 resultMode 工厂 | **暂缓** | 第二真相源;现主流是一产品一 request 配置 |
|
|
104
|
+
| **P1** | `create-cf-admin` 脚手架 | **后置** | 模板双维护税 > 当前 onboarding 痛 |
|
|
105
|
+
| **P1** | VitePress 组件演示站 | **冻结(现阶段)** | 卖的是模式套件;002 已够内部用 |
|
|
106
|
+
| **P2** | number offset helper | **观察(R5)** | 先审计同形,默认不提 API |
|
|
107
|
+
| **P2** | Light 主题全集 | **冻结** | 产品族暗色;变量可覆盖即可 |
|
|
108
|
+
| **P2** | dist 过期「玄学」强化 | **低优** | prepack clean 对发布已够 |
|
|
109
|
+
| 架构 | AdminShell 注入式侧栏 | **有第二行为再做** | 现硬依赖 `useAdminSidebar` 合理 |
|
|
110
|
+
| 架构 | 源码交付改 dist-only runtime | **需单独 RFC** | 改变调试与消费模型,非默认极致 |
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## 5. P0 — 高影响、值得做(细则)
|
|
115
|
+
|
|
116
|
+
### 5.1 组件级测试(SFC / 契约测试)
|
|
117
|
+
|
|
118
|
+
**问题:** composable 测得再满,**插槽条件、cents 编辑、元数据安全回退**仍可能被「只改模板」弄坏。
|
|
119
|
+
|
|
120
|
+
**目标重写(重要):**
|
|
121
|
+
|
|
122
|
+
- 要的是 **行为契约**(渲染条件、emit、边界 props),不是行覆盖率表演。
|
|
123
|
+
- 与产品仓「读源码 contract」互补:
|
|
124
|
+
- **kit 内 SFC 测** = 套件契约
|
|
125
|
+
- **产品 contract** = 接线/业务约定
|
|
126
|
+
|
|
127
|
+
**建议优先级:**
|
|
128
|
+
|
|
129
|
+
| 优先级 | 组件 | 覆盖要点 |
|
|
130
|
+
|--------|------|----------|
|
|
131
|
+
| 必做 | `AdminShell` | `#sidebar-footer` 有/无才渲染;`showUser` / `showLogout`;`#header-actions` 与用户区相对位置;`navigate` / `logout` emit;窄屏名称可藏(若可稳定断言) |
|
|
132
|
+
| 必做 | `ConfigField` | cents 往返;枚举空校验;sensitive 占位;status 文案(saving/saved/error) |
|
|
133
|
+
| 应做 | `AdminMetadataDetail` | 空、非法结构、循环/过深时的安全回退展示 |
|
|
134
|
+
| 可后做 | `AdminPagination` / `ConfirmDialog` / `ToastContainer` | 逻辑多在 composable 已测则 **薄测** 即可 |
|
|
135
|
+
| 低 | `AdminLoginShell` / `AdminModal` | 结构 + 关键 a11y 点;少绑 class 字符串 |
|
|
136
|
+
|
|
137
|
+
**基建建议:** Vitest + `@vue/test-utils` + **happy-dom**(相对 jsdom 更轻)。
|
|
138
|
+
**反模式:** 为冲 80% 组件行覆盖写脆测试;断言大段 HTML 快照无说明。
|
|
139
|
+
|
|
140
|
+
**预期发版形态:** 行为兼容 → **0.2.x patch**(如与 i18n 收口同发 0.2.8)。
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
### 5.2 构建产物与「体积」监控(轻量版)
|
|
145
|
+
|
|
146
|
+
**问题重定义:**
|
|
147
|
+
本包 **不是**「npm 只下 dist JS、运行全走打包产物」。消费者 Vite 直接编 **`src/*.vue` + CSS`**;`tsc` 的 `dist/` 以声明为主。
|
|
148
|
+
因此「打一个假入口把全部 subpath 打成一个 app 再 gzip」可以做实验,但 **不宜当主 KPI**,否则会优化错对象。
|
|
149
|
+
|
|
150
|
+
**建议监控(按优先级):**
|
|
151
|
+
|
|
152
|
+
1. **`src/styles/*.css` raw / gzip 体积**(`admin-primitives.css` 是大头之一)
|
|
153
|
+
2. **按 exports 子路径的源码规模**(composables / components / utils / i18n:文件数、近似 LOC)——防 utils 黑洞
|
|
154
|
+
3. **依赖门禁:** 除 `peerDependencies`(`vue`;可选 `vue-i18n`)外,**禁止悄悄增加 runtime dependency**(比多 2KB CSS 更致命)
|
|
155
|
+
4. 可选:对 **纯 TS、无 SFC** 的子树做 esbuild metafile 抽样
|
|
156
|
+
|
|
157
|
+
**CI / 脚本形态:**
|
|
158
|
+
|
|
159
|
+
- `scripts/size-report.mjs`(或同等)输出可读报告 + 可提交的 baseline JSON
|
|
160
|
+
- **仅在明显膨胀时失败**(例如 CSS gzip +15% 且无说明),避免每次微改必红
|
|
161
|
+
|
|
162
|
+
**明确不做(现阶段):** 把套件改成「唯一预打包 runtime bundle」作为默认交付——除非另开 RFC 并改所有消费方调试习惯。
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
### 5.3 统一 i18n 辅助(P0 中 ROI 最高、风险最低)
|
|
167
|
+
|
|
168
|
+
**事实:** `AdminShell` 的 `tFallback` 与 `ConfigField` 的 `tSafe` 同为:
|
|
169
|
+
|
|
170
|
+
`getCurrentInstance()` → `proxy.$t` → 失败或 key 原样则 **fallback**(ConfigField 另支持 params)。
|
|
171
|
+
|
|
172
|
+
**建议 API 形态(实现时二选一,文档写死):**
|
|
173
|
+
|
|
174
|
+
| 形态 | 适用 | 注意 |
|
|
175
|
+
|------|------|------|
|
|
176
|
+
| `tKit(key, fallback, params?)` 在 **setup 内** 调用 | 组件 script | 依赖 `getCurrentInstance`,勿在模块顶层调用 |
|
|
177
|
+
| 纯函数 `resolveAdminT(proxy, key, fallback, params?)` | 可单测、可非 setup | 组件内一行薄封装 |
|
|
178
|
+
|
|
179
|
+
**策略必须统一(避免半套):**
|
|
180
|
+
|
|
181
|
+
- **A:** 套件组件展示文案 **全部** 走 `tKit` / `resolveAdminT`(无 vue-i18n 也能跑中文 fallback);或
|
|
182
|
+
- **B:** 文档强制消费方 `mergeAdminKitMessages`,模板可用 `$t`,但 **kit 内仍建议统一走 tKit** 以免漏 merge 时白屏/露 key。
|
|
183
|
+
|
|
184
|
+
推荐 **A 为主**(与「vue-i18n 为 optional peer」一致)。
|
|
185
|
+
|
|
186
|
+
**范围:** 先收 `AdminShell`、`ConfigField`,再扫其他组件是否有第三份拷贝。
|
|
187
|
+
**发版:** 对外行为不变 → **patch**。
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## 6. P1 — 中等影响,看 ROI
|
|
192
|
+
|
|
193
|
+
### 6.1 通信协议:`createAdminApi` 路径级工厂 — **暂缓**
|
|
194
|
+
|
|
195
|
+
**设想:** 按 path 注册 `resultMode` / `errorField`,调用时自动匹配。
|
|
196
|
+
|
|
197
|
+
**暂缓理由(硬):**
|
|
198
|
+
|
|
199
|
+
- 现抽象已在 **`createAdminRequest` 实例级**;shop / auth / lottery 主流是 **一产品一配置**,不是「一 path 一 envelope」为主矛盾。
|
|
200
|
+
- 路径表会成为 **第二份路由真相**,与产品 `api/admin.ts` 双维护。
|
|
201
|
+
- 强类型 path→响应要么弱(近 `any`),要么维护税接近 OpenAPI。
|
|
202
|
+
|
|
203
|
+
**触发条件(同时满足再评估):**
|
|
204
|
+
|
|
205
|
+
- ≥2 产品在 **同一 request 实例内** 出现多 envelope,且手写分支重复;
|
|
206
|
+
- 配置表能明显减少重复,而不是只是搬家。
|
|
207
|
+
|
|
208
|
+
**更贴定位的替代:** 强化 recipes 中「如何组织 `api/admin.ts`」;必要时只加 **小纯函数**(如 envelope 断言),不建 path registry。
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
### 6.2 准入脚手架 `create-cf-admin` — **后置**
|
|
213
|
+
|
|
214
|
+
**痛点真实,但养模板仓库的成本更高:** kit 每个 API 变更要 **双改模板**,solo 最易腐烂。
|
|
215
|
+
|
|
216
|
+
**更极致、更便宜的中间态:**
|
|
217
|
+
|
|
218
|
+
1. recipes 保持权威清单;
|
|
219
|
+
2. 可选 **`examples/minimal`**(可运行的最小壳,仍非业务后台);
|
|
220
|
+
3. 可选 **检查脚本**(是否 import styles、是否 merge i18n 种子)——**验证**优于**生成**。
|
|
221
|
+
|
|
222
|
+
**触发条件:** 第 4 个消费方(尤其外部)或公开 onboarding 压力明显,再开脚手架。
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
### 6.3 VitePress 文档站 — **现阶段冻结**
|
|
227
|
+
|
|
228
|
+
- 对内:002 + recipes 已是高水位。
|
|
229
|
+
- 对外:本包卖 **模式与纪律**,不是组件货架;Playground 维护税高。
|
|
230
|
+
|
|
231
|
+
**例外:** 若只需 ConfigField / AdminShell **静态一页 demo**,可放 recipes 或单页,**不上**完整文档站基建。
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## 7. P2 与架构 — 低优先 / 触发后再做
|
|
236
|
+
|
|
237
|
+
### 7.1 number 版 offset helper(R5)
|
|
238
|
+
|
|
239
|
+
- 说明书已标明:string 给 `URLSearchParams`;**number body 手写**。
|
|
240
|
+
- shop 全仓大量 `limit/offset` **不等于** 前端构造参数「同形」;服务层分页与 admin API 拼装要分开看。
|
|
241
|
+
|
|
242
|
+
**允许动作:** 审计 `cf-shop/frontend`(及 lottery)里 number body 分页构造;若 **稳定同形 ≥2 处跨产品或 ≥3 处单产品**,再提 `buildAdminOffsetBody` 之类。
|
|
243
|
+
**默认:** 不增 API;结论写回 001 R5 / 002。
|
|
244
|
+
|
|
245
|
+
### 7.2 CSS 主题(Light)
|
|
246
|
+
|
|
247
|
+
- 产品族管理端 **暗色**;无第二套视觉 QA 面需求。
|
|
248
|
+
- **保持** CSS 变量可被消费方覆盖即可;kit **不维护**官方 light 主题包。
|
|
249
|
+
|
|
250
|
+
### 7.3 dist 过期防护
|
|
251
|
+
|
|
252
|
+
- `prepack` → clean → build 对 **发布** 足够。
|
|
253
|
+
- IDE 误解析:以 `exports`→`src` 为准;不必为开发体验叠加复杂 outDir 策略。
|
|
254
|
+
|
|
255
|
+
### 7.4 AdminShell ↔ `useAdminSidebar`
|
|
256
|
+
|
|
257
|
+
- 三家断点一致时,**硬依赖是合理默认**,不是缺陷。
|
|
258
|
+
- **注入整棵侧栏状态机** = 有第二套断点/行为时再做。
|
|
259
|
+
- 现阶段扩展优先靠 **已有插槽**(`#nav` / `#nav-extra` / `#sidebar-footer` / `#header-actions` / `#banner`)。
|
|
260
|
+
|
|
261
|
+
### 7.5 模板中的 `$t`
|
|
262
|
+
|
|
263
|
+
- 根因是 **optional `vue-i18n`**,不是缺 DI 容器。
|
|
264
|
+
- 用 **统一 tKit + merge 种子契约** 收敛,优于「注入 i18n 实例」大重构。
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## 8. 摩擦点:愿景 vs 可执行极致
|
|
269
|
+
|
|
270
|
+
| 摩擦点 | 常见「极致」想象 | **本仓库建议的极致** |
|
|
271
|
+
|--------|------------------|----------------------|
|
|
272
|
+
| 新产品接入 | `npx create-cf-admin` | recipes + 可选 minimal example + 可选检查脚本 |
|
|
273
|
+
| 改套件后验证 | 全自动消费方 monorepo CI | **kit SFC 契约测** + 发版前三仓 `vue-tsc`(可先脚本化) |
|
|
274
|
+
| 组件行为确认 | 读源码 / 全量快照 | **高风险 SFC 行为测** |
|
|
275
|
+
| 升级影响 | 类型断崖吓阻 | **0.2 尽量兼容**;破坏性进 0.3;changelog 记行为 |
|
|
276
|
+
| 是否该提取 | 自动模式挖掘工具 | **人工 ≥2 + R 观察列表**(工具 ROI 过低) |
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## 9. 推荐落地路线图
|
|
281
|
+
|
|
282
|
+
### 9.1 近端 — **0.2.8 三件套(已完成)**
|
|
283
|
+
|
|
284
|
+
1. ~~抽取 **`tKit` / `resolveAdminT`**~~ → `src/utils/i18n.ts`;Shell / ConfigField 收口;`tests/i18n-resolve.test.ts`。
|
|
285
|
+
2. ~~SFC 测试基建 + 契约测~~ → vitest `happy-dom`;AdminShell / ConfigField / AdminMetadataDetail。
|
|
286
|
+
3. ~~**轻量 size-report**~~ → `npm run size-report` / `size-report:write` / `size-report:check`。
|
|
287
|
+
|
|
288
|
+
**刻意不碰(仍有效):** path 级 `createAdminApi`、脚手架、VitePress、双主题、注入式侧栏。
|
|
289
|
+
|
|
290
|
+
### 9.2 中端(有余力)
|
|
291
|
+
|
|
292
|
+
4. 发版辅助脚本:`type-check` + `test` + `size-report` + 提示消费方 bump。
|
|
293
|
+
5. number offset **审计笔记** 写入 R5(有同形再 API,无则结案「维持手写」)。
|
|
294
|
+
6. recipes「最小接入」补强(仍非脚手架)。
|
|
295
|
+
|
|
296
|
+
### 9.3 冻结直到触发条件
|
|
297
|
+
|
|
298
|
+
| 项 | 触发条件(示例) |
|
|
299
|
+
|----|------------------|
|
|
300
|
+
| `createAdminApi` 路径表 | §6.1 条件 |
|
|
301
|
+
| `create-cf-admin` | 第 4 消费方或外部 onboarding 压力 |
|
|
302
|
+
| VitePress | 明确对外品牌/演示需求且有维护带宽 |
|
|
303
|
+
| Light 主题 | 真实产品浅色管理端需求 |
|
|
304
|
+
| 注入式侧栏 | 第二套断点/行为无法用插槽解决 |
|
|
305
|
+
| dist-only runtime | 书面 RFC + 消费方迁移窗 |
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
## 10. 与「极致」容易打架的三条钉死原则
|
|
310
|
+
|
|
311
|
+
1. **源码交付是优势**(可跳进 SFC 调试);勿为「像标准组件库」默认改成仅 dist 运行时。
|
|
312
|
+
2. **测试的极致是契约稳定**,不是测试文件数量或行覆盖率。
|
|
313
|
+
3. **每多一个工厂 / 脚手架 / 主题,就多一条要与 shop·lottery·auth 同步的真理之源**;在 3 仓阶段,**少真相源才是极致**。
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
## 11. 总结(给决策者的一页)
|
|
318
|
+
|
|
319
|
+
- **定位与 ≥2 提取纪律:全盘坚持,并当 PR 门禁。**
|
|
320
|
+
- **P0 三件套已在 0.2.8 落地**(契约测 + i18n 收口 + size-report)。
|
|
321
|
+
- **API 路径工厂、脚手架、文档站、双主题:远见可记,默认冻结。**
|
|
322
|
+
- **R5 number offset:可审计,不可默认加 API。**
|
|
323
|
+
- **下一列车:** 中端(发版辅助脚本 / R5 审计笔记 / recipes 最小接入),仍不扩冻结项。
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## 12. 修订记录
|
|
328
|
+
|
|
329
|
+
| 日期 | 说明 |
|
|
330
|
+
|------|------|
|
|
331
|
+
| 2026-08-05 | 初版:基于 0.2.7 现状与消费方(shop / lottery / auth)对照;固化 P0/P1/P2 裁决、触发条件与 0.2.8 三件套路线;明确极致定义=减摩擦+安全感而非扩面 |
|
|
332
|
+
| 2026-08-05 | **0.2.8 P0 落地**:`tKit`/`resolveAdminT`、SFC 契约测、size-report;§4/§9.1/§11 状态同步 |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@usethink/cf-admin-fe",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.8",
|
|
4
4
|
"description": "Vue 3 frontend admin kit for CF product family — composables, shell, ConfigField, list loader, login chrome, request/token/raw factories, error/batch helpers, system-config engine, nav helpers, i18n seeds, recipes (FE only; not cf-core)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -70,6 +70,8 @@
|
|
|
70
70
|
"devDependencies": {
|
|
71
71
|
"@types/node": "^22.10.0",
|
|
72
72
|
"@vitejs/plugin-vue": "^5.2.1",
|
|
73
|
+
"@vue/test-utils": "^2.4.11",
|
|
74
|
+
"happy-dom": "^20.11.1",
|
|
73
75
|
"typescript": "^5.7.2",
|
|
74
76
|
"vite": "^6.0.0",
|
|
75
77
|
"vitest": "^3.0.0",
|
|
@@ -82,7 +84,10 @@
|
|
|
82
84
|
"test:watch": "vitest",
|
|
83
85
|
"build": "npm run clean && tsc -p tsconfig.build.json",
|
|
84
86
|
"prepack": "npm run build",
|
|
85
|
-
"clean": "node scripts/clean-dist.mjs"
|
|
87
|
+
"clean": "node scripts/clean-dist.mjs",
|
|
88
|
+
"size-report": "node scripts/size-report.mjs",
|
|
89
|
+
"size-report:write": "node scripts/size-report.mjs --write",
|
|
90
|
+
"size-report:check": "node scripts/size-report.mjs --check"
|
|
86
91
|
},
|
|
87
92
|
"keywords": [
|
|
88
93
|
"admin",
|
package/recipes/README.md
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
这些文件是**起点模板**,不是运行时导入。将它们复制(或重新导出)到你的产品 `src/` 目录下,然后补齐产品专属部分(菜单、领域 API 方法、登录 UI)。
|
|
4
4
|
|
|
5
|
-
**完整用法、注意事项、能力榨干清单:** 见 [`docs/002_cf-admin-fe使用说明书与注意事项.md`](../docs/002_cf-admin-fe使用说明书与注意事项.md)。
|
|
5
|
+
**完整用法、注意事项、能力榨干清单:** 见 [`docs/002_cf-admin-fe使用说明书与注意事项.md`](../docs/002_cf-admin-fe使用说明书与注意事项.md)。
|
|
6
|
+
**套件下一步该做什么 / 明确不做:** 见 [`docs/003_cf-admin-fe极致化方案与取舍_2026-08-05.md`](../docs/003_cf-admin-fe极致化方案与取舍_2026-08-05.md)(路线图,非本 recipes 步骤替代)。
|
|
6
7
|
|
|
7
8
|
## 推荐复制顺序
|
|
8
9
|
|
|
@@ -83,8 +83,9 @@
|
|
|
83
83
|
</template>
|
|
84
84
|
|
|
85
85
|
<script setup lang="ts">
|
|
86
|
-
import { computed
|
|
86
|
+
import { computed } from 'vue'
|
|
87
87
|
import { useAdminSidebar } from '../composables/useAdminSidebar'
|
|
88
|
+
import { tKit } from '../utils/i18n'
|
|
88
89
|
|
|
89
90
|
export type AdminShellMenuItem = {
|
|
90
91
|
name: string
|
|
@@ -133,24 +134,11 @@ const emit = defineEmits<{
|
|
|
133
134
|
|
|
134
135
|
const { isMobile, sidebarOpen, toggleSidebar, closeSidebar } = useAdminSidebar()
|
|
135
136
|
|
|
136
|
-
function tFallback(key: string, fallback: string): string {
|
|
137
|
-
const proxy = getCurrentInstance()?.proxy as { $t?: (k: string) => string } | undefined
|
|
138
|
-
try {
|
|
139
|
-
if (typeof proxy?.$t === 'function') {
|
|
140
|
-
const out = proxy.$t(key)
|
|
141
|
-
if (typeof out === 'string' && out !== key) return out
|
|
142
|
-
}
|
|
143
|
-
} catch {
|
|
144
|
-
/* 无 i18n */
|
|
145
|
-
}
|
|
146
|
-
return fallback
|
|
147
|
-
}
|
|
148
|
-
|
|
149
137
|
const resolvedLogoutLabel = computed(
|
|
150
|
-
() => props.logoutLabel ||
|
|
138
|
+
() => props.logoutLabel || tKit('adminLayout.logout', '退出'),
|
|
151
139
|
)
|
|
152
140
|
const resolvedToggleLabel = computed(
|
|
153
|
-
() => props.toggleSidebarLabel ||
|
|
141
|
+
() => props.toggleSidebarLabel || tKit('adminLayout.toggleSidebar', '菜单'),
|
|
154
142
|
)
|
|
155
143
|
|
|
156
144
|
const resolvedTitle = computed(() => {
|
|
@@ -86,12 +86,13 @@
|
|
|
86
86
|
</template>
|
|
87
87
|
|
|
88
88
|
<script setup lang="ts">
|
|
89
|
-
import { computed,
|
|
89
|
+
import { computed, ref, watch } from 'vue'
|
|
90
90
|
import type {
|
|
91
91
|
AdminSystemConfigFieldDefinition,
|
|
92
92
|
ConfigFieldStatus,
|
|
93
93
|
} from '../types/system-config'
|
|
94
94
|
import { formatCents, parseYuanToCents } from '../utils/currency-cents'
|
|
95
|
+
import { tKit } from '../utils/i18n'
|
|
95
96
|
|
|
96
97
|
const props = defineProps<{
|
|
97
98
|
item: AdminSystemConfigFieldDefinition
|
|
@@ -107,24 +108,9 @@ const emit = defineEmits<{
|
|
|
107
108
|
|
|
108
109
|
const localError = ref('')
|
|
109
110
|
|
|
110
|
-
/**
|
|
111
|
-
* 可选 i18n:宿主可注入 vue-i18n 全局 `$t` / `$te`。
|
|
112
|
-
* 切勿把后端自由文本作为 defaultMessage 传入(裸 `@` / `{}` 会导致解析失败)。
|
|
113
|
-
*/
|
|
111
|
+
/** 可选 i18n:统一走 tKit(无 vue-i18n 时用中文 fallback) */
|
|
114
112
|
function tSafe(key: string, fallback: string, params?: Record<string, unknown>): string {
|
|
115
|
-
|
|
116
|
-
| { $t?: (k: string, p?: Record<string, unknown>) => string; $te?: (k: string) => boolean }
|
|
117
|
-
| undefined
|
|
118
|
-
try {
|
|
119
|
-
if (proxy?.$te && !proxy.$te(key)) return fallback
|
|
120
|
-
if (typeof proxy?.$t === 'function') {
|
|
121
|
-
const out = params ? proxy.$t(key, params) : proxy.$t(key)
|
|
122
|
-
if (typeof out === 'string' && out !== key) return out
|
|
123
|
-
}
|
|
124
|
-
} catch {
|
|
125
|
-
/* 无 i18n */
|
|
126
|
-
}
|
|
127
|
-
return fallback
|
|
113
|
+
return tKit(key, fallback, params)
|
|
128
114
|
}
|
|
129
115
|
|
|
130
116
|
function translateConfigText(
|
package/src/index.ts
CHANGED
|
@@ -130,8 +130,12 @@ export {
|
|
|
130
130
|
formatMetadata,
|
|
131
131
|
buildAdminOffsetParams,
|
|
132
132
|
applyAdminOffsetParams,
|
|
133
|
+
resolveAdminT,
|
|
134
|
+
tKit,
|
|
133
135
|
} from './utils'
|
|
134
136
|
|
|
137
|
+
export type { AdminI18nProxy } from './utils'
|
|
138
|
+
|
|
135
139
|
export {
|
|
136
140
|
normalizeOtpDigits,
|
|
137
141
|
isOtpComplete,
|
|
@@ -177,6 +177,11 @@
|
|
|
177
177
|
/* ── 表格容器 ──
|
|
178
178
|
* 滚动裁剪发生在这里(overflow: auto)。sticky 表头相对 .table-wrap 吸顶。
|
|
179
179
|
* 禁止在页面 scoped 再写一套 table-wrap / th sticky。
|
|
180
|
+
*
|
|
181
|
+
* 滚动条策略(勿用 scrollbar-gutter: stable):
|
|
182
|
+
* - stable 会在无溢出时也预留纵向槽,表右侧出现「缺口」、最后一列与圆角边框不对齐;
|
|
183
|
+
* - 默认 auto:仅在真正溢出时占位;细滚动条见下方 ::-webkit-scrollbar。
|
|
184
|
+
* 弹层/长卡片列表可另用 stable(防布局跳动);表格以视觉对齐优先。
|
|
180
185
|
*/
|
|
181
186
|
.table-wrap {
|
|
182
187
|
background: var(--tg-secondary-bg, #151b28);
|
|
@@ -184,7 +189,6 @@
|
|
|
184
189
|
border: 1px solid var(--border, rgba(255, 255, 255, 0.1));
|
|
185
190
|
overflow: auto;
|
|
186
191
|
overscroll-behavior: contain;
|
|
187
|
-
scrollbar-gutter: stable;
|
|
188
192
|
flex: 1;
|
|
189
193
|
min-height: 0;
|
|
190
194
|
/* 建立独立层叠上下文,避免表头与外部 sticky toolbar 抢 z-index */
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 套件组件统一 i18n 回退(vue-i18n 为 optional peer)。
|
|
3
|
+
*
|
|
4
|
+
* - 有 `$t` 且返回非 key 本身 → 用翻译
|
|
5
|
+
* - 有 `$te` 且 key 不存在 → 直接 fallback(避免 vue-i18n 警告/返回 key)
|
|
6
|
+
* - 无 i18n 或抛错 → fallback
|
|
7
|
+
*
|
|
8
|
+
* 切勿把后端自由文本当 fallback 里的插值模板(裸 `@` / `{}` 可能被 i18n 解析)。
|
|
9
|
+
*/
|
|
10
|
+
import { getCurrentInstance } from 'vue'
|
|
11
|
+
|
|
12
|
+
export type AdminI18nProxy = {
|
|
13
|
+
$t?: (key: string, params?: Record<string, unknown>) => unknown
|
|
14
|
+
$te?: (key: string) => boolean
|
|
15
|
+
} | null | undefined
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* 纯函数:可在单测中直接注入 proxy,不依赖 setup。
|
|
19
|
+
*/
|
|
20
|
+
export function resolveAdminT(
|
|
21
|
+
proxy: AdminI18nProxy,
|
|
22
|
+
key: string,
|
|
23
|
+
fallback: string,
|
|
24
|
+
params?: Record<string, unknown>,
|
|
25
|
+
): string {
|
|
26
|
+
try {
|
|
27
|
+
if (typeof proxy?.$te === 'function' && !proxy.$te(key)) return fallback
|
|
28
|
+
if (typeof proxy?.$t === 'function') {
|
|
29
|
+
const out = params !== undefined ? proxy.$t(key, params) : proxy.$t(key)
|
|
30
|
+
if (typeof out === 'string' && out !== key) return out
|
|
31
|
+
}
|
|
32
|
+
} catch {
|
|
33
|
+
/* 无 i18n 或运行时错误 */
|
|
34
|
+
}
|
|
35
|
+
return fallback
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* 从当前组件实例的 appContext.globalProperties 读取 `$t` / `$te`。
|
|
40
|
+
* 使用 globalProperties 而非 `proxy.$t`,避免未安装 vue-i18n 时访问实例代理触发 Vue warn。
|
|
41
|
+
* 勿在模块顶层调用。
|
|
42
|
+
*/
|
|
43
|
+
export function tKit(
|
|
44
|
+
key: string,
|
|
45
|
+
fallback: string,
|
|
46
|
+
params?: Record<string, unknown>,
|
|
47
|
+
): string {
|
|
48
|
+
const instance = getCurrentInstance()
|
|
49
|
+
const gp = instance?.appContext.config.globalProperties as
|
|
50
|
+
| Record<string, unknown>
|
|
51
|
+
| undefined
|
|
52
|
+
const proxy: AdminI18nProxy = gp
|
|
53
|
+
? {
|
|
54
|
+
$t: typeof gp.$t === 'function'
|
|
55
|
+
? (gp.$t as (k: string, p?: Record<string, unknown>) => unknown).bind(gp)
|
|
56
|
+
: undefined,
|
|
57
|
+
$te: typeof gp.$te === 'function'
|
|
58
|
+
? (gp.$te as (k: string) => boolean).bind(gp)
|
|
59
|
+
: undefined,
|
|
60
|
+
}
|
|
61
|
+
: undefined
|
|
62
|
+
return resolveAdminT(proxy, key, fallback, params)
|
|
63
|
+
}
|