create-yoya-ui 0.6.2 → 0.7.5

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.
Files changed (43) hide show
  1. package/package.json +1 -1
  2. package/templates/admin/README.md +1 -1
  3. package/templates/admin/RULES.md +3 -2
  4. package/templates/admin/package.json +9 -1
  5. package/templates/admin/src/api/domain.api.d.ts +1 -1
  6. package/templates/admin/src/api/domain.api.js +1 -1
  7. package/templates/admin/src/api/fetch.api.d.ts +1 -1
  8. package/templates/admin/src/features/dashboard/overview/components/dashboard-chart.js +40 -40
  9. package/templates/admin/src/features/dashboard/overview/pages/dashboard-overview-page.js +178 -181
  10. package/templates/admin/src/features/system/dicts/api/dict.mgr.d.ts +1 -1
  11. package/templates/admin/src/features/system/dicts/api/dict.mgr.js +1 -1
  12. package/templates/admin/src/features/system/dicts/api/dict.state.d.ts +1 -1
  13. package/templates/admin/src/features/system/dicts/components/dict-editor-dialog.js +13 -9
  14. package/templates/admin/src/features/system/dicts/components/dict-item-form-dialog.js +13 -9
  15. package/templates/admin/src/features/system/dicts/pages/dict-list-page.js +37 -43
  16. package/templates/admin/src/features/system/members/api/member.mgr.d.ts +1 -1
  17. package/templates/admin/src/features/system/members/api/member.mgr.js +1 -1
  18. package/templates/admin/src/features/system/members/api/member.req.d.ts +1 -1
  19. package/templates/admin/src/features/system/members/api/member.req.js +1 -1
  20. package/templates/admin/src/features/system/members/api/member.state.d.ts +1 -1
  21. package/templates/admin/src/features/system/members/components/member-form-dialog.js +13 -9
  22. package/templates/admin/src/features/system/members/components/member-toolbar.js +34 -40
  23. package/templates/admin/src/features/system/members/pages/member-list-page.js +13 -20
  24. package/templates/admin/src/features/system/permissions/api/permission.mgr.d.ts +1 -1
  25. package/templates/admin/src/features/system/permissions/api/permission.mgr.js +1 -1
  26. package/templates/admin/src/features/system/permissions/api/permission.state.d.ts +1 -1
  27. package/templates/admin/src/features/system/permissions/components/permission-form-dialog.js +13 -9
  28. package/templates/admin/src/features/system/permissions/pages/permission-list-page.js +16 -22
  29. package/templates/admin/src/features/system/roles/api/role.mgr.d.ts +1 -1
  30. package/templates/admin/src/features/system/roles/api/role.mgr.js +1 -1
  31. package/templates/admin/src/features/system/roles/api/role.state.d.ts +1 -1
  32. package/templates/admin/src/features/system/roles/components/role-form-dialog.js +13 -9
  33. package/templates/admin/src/features/system/roles/components/role-toolbar.js +33 -39
  34. package/templates/admin/src/features/system/roles/pages/role-list-page.js +13 -19
  35. package/templates/admin/src/main.js +1 -1
  36. package/templates/admin/src/shell/api/shell.req.js +1 -1
  37. package/templates/admin/src/shell/components/admin-shell.js +18 -21
  38. package/templates/admin/vite.config.js +7 -5
  39. package/templates/basic/package.json +2 -1
  40. package/templates/ssr/package.json +2 -1
  41. package/templates/ssr/src/home-page.js +3 -2
  42. package/templates/ssr/src/server.mjs +3 -0
  43. package/templates/ssr/vite.config.js +17 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-yoya-ui",
3
- "version": "0.6.2",
3
+ "version": "0.7.5",
4
4
  "description": "Scaffold a new yoya-ui project with Vite: basic template (SPA) or SSR template (renderPage + hydrateOrMount).",
5
5
  "type": "module",
6
6
  "bin": {
@@ -56,7 +56,7 @@ src/
56
56
  dashboard/ 工作台
57
57
  overview/ 数据概览
58
58
  pages/dashboard-overview-page.js 页面编排:核心指标看板 + 趋势卡 + 图表 + 资源使用
59
- components/dashboard-chart.js vChart 内置 SVG 适配器(柱状图 / 折线图)
59
+ components/dashboard-chart.js DashboardChart 图表卡片 + 模板自带的 SVG 适配器(柱状图 / 折线图)
60
60
  todos/ 待办审批(简单页示例)
61
61
  pages/todo-approval-page.js
62
62
  ops/ 运维
@@ -72,8 +72,9 @@ export default {
72
72
  - 导航字段(`menus` / `activeModuleKey` / `activePath`)是 `ref`:`router.subscribe → state.syncFromPath(path)` 只把路径写回信号
73
73
  - 顶栏 / 侧栏从状态**派生高亮**:菜单区先 `rebuildable()` 再读信号(模块 / 路径变化自动重建),组件不持有自己的激活状态
74
74
  - `AdminShell` 只做装配:布局组装,不直接操作 router,也不需要订阅回调转发
75
- - 组件统一写法:节点在 `render()` 内声明式构建,不保留 `applyState()` 这类手动同步入口;没有额外行为要定义(无内部状态、无对外命令方法)的组件直接返回 ViewNode 即可,不必包一层 `render()`
76
- - 组件需要对外命令方法时用 `vNode((api) => 视图)`:命令收到 `api` 上(`api.reload = () => { …; return api }`),工厂挂到返回的节点并校验重名;自带边界写 `api.whenFailed`,其余节点级能力(`mountable()` / `rebuildable()`)链在节点上
75
+ - **组件只有两种形态**:没有额外行为要定义(无内部状态、无对外命令方法)的组件**直接返回 ViewNode**(形态 A 薄工厂,不必包一层 `render()`);需要对外命令方法时用 **`vNode((api) => 视图)`**(形态 B)。`{ render(), … }` 对象组件已退场,新组件不要写
76
+ - 形态 B 的命令写在 `api` 上:`api.reload = () => { …; return api }`(`return api` 等价于返回节点,链式两端都通);命令名撞节点 API(`child` / `destroy` / `renderDom` …)引擎直接报错,不静默覆盖;自带错误边界写 `api.whenFailed`,其余节点级能力(`mountable()` / `rebuildable()`)链在节点上
77
+ - **页面与外壳**:页面文件(`pages/*-page.js`)与外壳(`AdminShell`)同样是组件——没有命令方法就返回 ViewNode;页面需要对外方法(如 `refresh()`)时按形态 B 写
77
78
 
78
79
  ## 7. 页面规则
79
80
 
@@ -3,6 +3,13 @@
3
3
  "version": "0.1.0",
4
4
  "private": true,
5
5
  "type": "module",
6
+ "browserslist": [
7
+ "chrome >= 123",
8
+ "edge >= 123",
9
+ "firefox >= 120",
10
+ "safari >= 17.5",
11
+ "ios_saf >= 17.5"
12
+ ],
6
13
  "scripts": {
7
14
  "dev": "vite",
8
15
  "build": "vite build",
@@ -10,7 +17,8 @@
10
17
  "typecheck": "tsc --noEmit"
11
18
  },
12
19
  "dependencies": {
13
- "@yoyaflow/yoya-ui": "^0.6.2"
20
+ "@yoyaflow/yoya-core": "0.7.5",
21
+ "@yoyaflow/yoya-ui": "0.7.5"
14
22
  },
15
23
  "devDependencies": {
16
24
  "typescript": "^7.0.2",
@@ -1,5 +1,5 @@
1
1
  /** 领域请求入口类型声明(对应 domain.api.js)。 */
2
- import type { RequestCommand } from '@yoyaflow/yoya-ui/api';
2
+ import type { RequestCommand } from '@yoyaflow/yoya-core/api';
3
3
 
4
4
  export function mockRequest(
5
5
  method: string,
@@ -1,5 +1,5 @@
1
1
  // 领域请求入口:统一 Result 解析 + mock / 真实传输切换。
2
- import { configureRequest, Result } from '@yoyaflow/yoya-ui/api';
2
+ import { configureRequest, Result } from '@yoyaflow/yoya-core/api';
3
3
  import { fetchSubmit } from './fetch.api.js';
4
4
 
5
5
  const mockHandlers = new Map();
@@ -1,4 +1,4 @@
1
1
  /** 原始传输层类型声明(对应 fetch.api.js)。 */
2
- import type { RequestCommand } from '@yoyaflow/yoya-ui/api';
2
+ import type { RequestCommand } from '@yoyaflow/yoya-core/api';
3
3
 
4
4
  export function fetchSubmit(req: RequestCommand): Promise<unknown>;
@@ -4,7 +4,16 @@ const VIEW_BOX = { height: 260, width: 640 };
4
4
  const PAD = { bottom: 34, left: 44, right: 16, top: 14 };
5
5
  const SERIES_COLORS = ['#2563eb', '#16a34a', '#f59e0b', '#dc2626', '#8b5cf6'];
6
6
 
7
- // vChart 内置 SVG 适配器:bar 柱状图 / line 折线图,零外部依赖。
7
+ /**
8
+ * 图表卡片(形态 A 薄工厂):vCard 外壳 + vChart 宿主,没有对外命令方法。
9
+ *
10
+ * `vChart` 只提供宿主与**适配器契约**(`init` / `update` / `resize` / `destroy`),自身不带图表库实现
11
+ * (ECharts / Three.js 另有官方适配器组件 `vEchart` / `vThree`);
12
+ * 下面这份 SVG 适配器是本模板自带的零依赖实现(bar 柱状图 / line 折线图)。
13
+ * 适配器画出来的内容交给引擎落位:`context.chart.replaceChildren(节点…)`——`chart` 是组件节点,
14
+ * `replaceChildren` 收的是**视图节点**(DOM 落盘与清理由引擎负责),不要自己调 `renderDom()`。
15
+ * 数据要跟着状态变时,把句柄放进 `data` 即可(`vChart` 的 `data` 收句柄)。
16
+ */
8
17
  export function DashboardChart({
9
18
  labels = [],
10
19
  series = [],
@@ -12,51 +21,42 @@ export function DashboardChart({
12
21
  type = 'bar',
13
22
  height = 280
14
23
  } = {}) {
15
- const chart = vChart({
16
- adapter: createSvgAdapter(),
17
- data: { labels, series },
18
- height,
19
- options: { type }
20
- });
21
-
22
- return {
23
- render() {
24
- return vCard((card) => {
25
- card.vCardHeader(title);
26
- card.vCardBody((body) => {
27
- body.div((host) => {
28
- host.style({ minWidth: '0', width: '100%' });
29
- host.child(chart);
30
- });
31
- });
24
+ return vCard((card) => {
25
+ card.vCardHeader(title);
26
+ card.vCardBody((body) => {
27
+ body.div((host) => {
28
+ host.style({ minWidth: '0', width: '100%' });
29
+ host.child(
30
+ vChart({
31
+ adapter: svgChartAdapter,
32
+ data: { labels, series },
33
+ height,
34
+ options: { type }
35
+ })
36
+ );
32
37
  });
33
- },
34
- update(next) {
35
- chart.data(next);
36
- return this;
37
- }
38
- };
38
+ });
39
+ });
39
40
  }
40
41
 
41
- function createSvgAdapter() {
42
- return {
43
- init(host, context) {
44
- const instance = { host };
45
- renderChart(instance, context);
46
- return instance;
47
- },
48
- update(instance, context) {
49
- renderChart(instance, context);
50
- },
51
- resize() {},
52
- destroy() {}
53
- };
54
- }
42
+ /** 无状态适配器:整份图表由 renderChart 按 context 重画,可以所有实例共用一份。 */
43
+ const svgChartAdapter = {
44
+ init(_host, context) {
45
+ renderChart(context);
46
+ return {};
47
+ },
48
+ update(_instance, context) {
49
+ renderChart(context);
50
+ },
51
+ resize() {},
52
+ destroy() {}
53
+ };
55
54
 
56
- function renderChart(instance, context) {
55
+ function renderChart(context) {
57
56
  const root = buildChartSvg(context.data, context.options);
58
57
  const legend = buildLegend(context.data?.series ?? []);
59
- instance.host.replaceChildren(legend.renderDom(), root.renderDom());
58
+ // 换子节点走引擎口子:组件节点写的是它根元素的孩子们(旧内容连带销毁,不用自己碰 DOM)
59
+ context.chart.replaceChildren(legend, root);
60
60
  }
61
61
 
62
62
  function buildLegend(series) {
@@ -4,198 +4,195 @@ import { DashboardChart } from '../components/dashboard-chart.js';
4
4
  const weekLabels = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'];
5
5
 
6
6
  export function DashboardOverviewPage() {
7
- return {
8
- render() {
9
- return vstack({ gap: '16px' }, (stack) => {
10
- stack.h2('数据概览');
7
+ // 页面也是组件:没有对外命令方法 → 形态 A 薄工厂,直接返回视图节点
8
+ return vstack({ gap: '16px' }, (stack) => {
9
+ stack.h2('数据概览');
11
10
 
12
- stack.vCard((card) => {
13
- card.vCardHeader('核心指标');
14
- card.vCardBody((body) => {
15
- body.vDigitalBoard((board) => {
16
- board.columns(4);
17
- board.vDigitalBoardItem((item) => {
18
- item.label('服务总数');
19
- item.value('128');
20
- item.unit('个');
21
- item.trend('+12 本月');
22
- item.trendUp(true);
23
- item.icon('🖥️');
24
- });
25
- board.vDigitalBoardItem((item) => {
26
- item.label('运行中');
27
- item.value('96');
28
- item.unit('个');
29
- item.trend('+8 本周');
30
- item.trendUp(true);
31
- item.tone('success');
32
- item.icon('✅');
33
- });
34
- board.vDigitalBoardItem((item) => {
35
- item.label('异常告警');
36
- item.value('5');
37
- item.unit('个');
38
- item.trend('-2 今日');
39
- item.trendUp(false);
40
- item.tone('danger');
41
- item.icon('⚠️');
42
- });
43
- board.vDigitalBoardItem((item) => {
44
- item.label('平均响应');
45
- item.value('243');
46
- item.unit('ms');
47
- item.trend('-18 今日');
48
- item.trendUp(true);
49
- item.tone('warning');
50
- item.icon('⏱️');
51
- });
52
- });
11
+ stack.vCard((card) => {
12
+ card.vCardHeader('核心指标');
13
+ card.vCardBody((body) => {
14
+ body.vDigitalBoard((board) => {
15
+ board.columns(4);
16
+ board.vDigitalBoardItem((item) => {
17
+ item.label('服务总数');
18
+ item.value('128');
19
+ item.unit('个');
20
+ item.trend('+12 本月');
21
+ item.trendUp(true);
22
+ item.icon('🖥️');
53
23
  });
54
- });
55
-
56
- stack.div((trends) => {
57
- trends.style({
58
- display: 'grid',
59
- gap: '12px',
60
- gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))'
24
+ board.vDigitalBoardItem((item) => {
25
+ item.label('运行中');
26
+ item.value('96');
27
+ item.unit('个');
28
+ item.trend('+8 本周');
29
+ item.trendUp(true);
30
+ item.tone('success');
31
+ item.icon('✅');
61
32
  });
62
- trends.child(
63
- vTrendCard({
64
- data: [12, 15, 11, 18, 16, 21, 24],
65
- delta: '+6.4%',
66
- title: '今日请求',
67
- tone: 'primary',
68
- unit: 'k',
69
- up: true,
70
- value: '84.2'
71
- })
72
- );
73
- trends.child(
74
- vTrendCard({
75
- data: [320, 290, 310, 270, 260, 248, 243],
76
- delta: '-18 今日',
77
- title: '平均响应',
78
- tone: 'success',
79
- unit: 'ms',
80
- up: true,
81
- value: '243'
82
- })
83
- );
84
- trends.child(
85
- vTrendCard({
86
- data: [6, 7, 4, 3, 5, 2, 2],
87
- delta: '-5 较昨日',
88
- title: '故障次数',
89
- tone: 'danger',
90
- unit: '次',
91
- up: false,
92
- value: '2'
93
- })
94
- );
95
- });
96
-
97
- stack.div((charts) => {
98
- charts.style({
99
- display: 'grid',
100
- gap: '12px',
101
- gridTemplateColumns: 'repeat(auto-fit, minmax(320px, 1fr))'
33
+ board.vDigitalBoardItem((item) => {
34
+ item.label('异常告警');
35
+ item.value('5');
36
+ item.unit('个');
37
+ item.trend('-2 今日');
38
+ item.trendUp(false);
39
+ item.tone('danger');
40
+ item.icon('⚠️');
41
+ });
42
+ board.vDigitalBoardItem((item) => {
43
+ item.label('平均响应');
44
+ item.value('243');
45
+ item.unit('ms');
46
+ item.trend('-18 今日');
47
+ item.trendUp(true);
48
+ item.tone('warning');
49
+ item.icon('⏱️');
102
50
  });
103
- charts.child(
104
- DashboardChart({
105
- labels: weekLabels,
106
- series: [{ name: '请求量', data: [62, 71, 58, 84, 92, 76, 88] }],
107
- title: '近 7 日请求量',
108
- type: 'bar'
109
- })
110
- );
111
- charts.child(
112
- DashboardChart({
113
- labels: weekLabels,
114
- series: [
115
- { name: '错误数', data: [8, 12, 7, 15, 10, 6, 9], color: '#dc2626' },
116
- { name: '恢复数', data: [6, 10, 5, 12, 8, 5, 8], color: '#16a34a' }
117
- ],
118
- title: '近 7 日错误与恢复',
119
- type: 'line'
120
- })
121
- );
122
51
  });
52
+ });
53
+ });
123
54
 
124
- stack.div((bottom) => {
125
- bottom.style({
126
- display: 'grid',
127
- gap: '12px',
128
- gridTemplateColumns: 'repeat(auto-fit, minmax(320px, 1fr))'
129
- });
130
- bottom.vCard((card) => {
131
- card.vCardHeader('资源使用');
132
- card.vCardBody((body) => {
133
- body.hstack((row) => {
134
- row.style({ flexWrap: 'wrap', gap: '20px' });
135
- row.child(vRingStat({ label: '成功率', percent: 99, tone: 'success' }));
136
- row.child(
137
- vRingStat({ label: '容量使用', percent: 68, tone: 'primary', value: '680 GB' })
138
- );
139
- row.div((box) => {
140
- box.style({ textAlign: 'center' });
141
- box.child(vGauge({ unit: '%', value: 72, tone: 'warning' }));
142
- box.p((text) => {
143
- text.style({
144
- color: 'var(--yoya-color-text-muted, #64748b)',
145
- fontSize: '12px'
146
- });
147
- text.child('CPU 使用率');
148
- });
149
- });
150
- row.div((box) => {
151
- box.style({ textAlign: 'center' });
152
- box.child(vGauge({ unit: '%', value: 58, tone: 'primary' }));
153
- box.p((text) => {
154
- text.style({
155
- color: 'var(--yoya-color-text-muted, #64748b)',
156
- fontSize: '12px'
157
- });
158
- text.child('内存使用率');
159
- });
55
+ stack.div((trends) => {
56
+ trends.style({
57
+ display: 'grid',
58
+ gap: '12px',
59
+ gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))'
60
+ });
61
+ trends.child(
62
+ vTrendCard({
63
+ data: [12, 15, 11, 18, 16, 21, 24],
64
+ delta: '+6.4%',
65
+ title: '今日请求',
66
+ tone: 'primary',
67
+ unit: 'k',
68
+ up: true,
69
+ value: '84.2'
70
+ })
71
+ );
72
+ trends.child(
73
+ vTrendCard({
74
+ data: [320, 290, 310, 270, 260, 248, 243],
75
+ delta: '-18 今日',
76
+ title: '平均响应',
77
+ tone: 'success',
78
+ unit: 'ms',
79
+ up: true,
80
+ value: '243'
81
+ })
82
+ );
83
+ trends.child(
84
+ vTrendCard({
85
+ data: [6, 7, 4, 3, 5, 2, 2],
86
+ delta: '-5 较昨日',
87
+ title: '故障次数',
88
+ tone: 'danger',
89
+ unit: '次',
90
+ up: false,
91
+ value: '2'
92
+ })
93
+ );
94
+ });
95
+
96
+ stack.div((charts) => {
97
+ charts.style({
98
+ display: 'grid',
99
+ gap: '12px',
100
+ gridTemplateColumns: 'repeat(auto-fit, minmax(320px, 1fr))'
101
+ });
102
+ charts.child(
103
+ DashboardChart({
104
+ labels: weekLabels,
105
+ series: [{ name: '请求量', data: [62, 71, 58, 84, 92, 76, 88] }],
106
+ title: '近 7 日请求量',
107
+ type: 'bar'
108
+ })
109
+ );
110
+ charts.child(
111
+ DashboardChart({
112
+ labels: weekLabels,
113
+ series: [
114
+ { name: '错误数', data: [8, 12, 7, 15, 10, 6, 9], color: '#dc2626' },
115
+ { name: '恢复数', data: [6, 10, 5, 12, 8, 5, 8], color: '#16a34a' }
116
+ ],
117
+ title: '近 7 日错误与恢复',
118
+ type: 'line'
119
+ })
120
+ );
121
+ });
122
+
123
+ stack.div((bottom) => {
124
+ bottom.style({
125
+ display: 'grid',
126
+ gap: '12px',
127
+ gridTemplateColumns: 'repeat(auto-fit, minmax(320px, 1fr))'
128
+ });
129
+ bottom.vCard((card) => {
130
+ card.vCardHeader('资源使用');
131
+ card.vCardBody((body) => {
132
+ body.hstack((row) => {
133
+ row.style({ flexWrap: 'wrap', gap: '20px' });
134
+ row.child(vRingStat({ label: '成功率', percent: 99, tone: 'success' }));
135
+ row.child(
136
+ vRingStat({ label: '容量使用', percent: 68, tone: 'primary', value: '680 GB' })
137
+ );
138
+ row.div((box) => {
139
+ box.style({ textAlign: 'center' });
140
+ box.child(vGauge({ unit: '%', value: 72, tone: 'warning' }));
141
+ box.p((text) => {
142
+ text.style({
143
+ color: 'var(--yoya-color-text-muted, #64748b)',
144
+ fontSize: '12px'
160
145
  });
146
+ text.child('CPU 使用率');
161
147
  });
162
148
  });
163
- });
164
- bottom.vCard((card) => {
165
- card.vCardHeader('最近动态');
166
- card.vCardBody((body) => {
167
- body.child(
168
- vTimeline((timeline) => {
169
- timeline.vTimelineItem((item) => {
170
- item.status('success');
171
- item.title('服务发布成功');
172
- item.time('09:32 · 2026-09-01');
173
- item.content((box) => box.p('api-gateway v2.4.1 已上线,金丝雀批次全部通过。'));
174
- });
175
- timeline.vTimelineItem((item) => {
176
- item.status('processing');
177
- item.title('滚动发布中');
178
- item.time('09:20 · 2026-09-01');
179
- item.content('web-console 正在按 5% 批次滚动。');
180
- });
181
- timeline.vTimelineItem((item) => {
182
- item.status('warning');
183
- item.title('容量预警');
184
- item.time('08:47 · 2026-09-01');
185
- item.content('redis 内存使用率接近 80%。');
186
- });
187
- timeline.vTimelineItem((item) => {
188
- item.status('danger');
189
- item.title('告警已恢复');
190
- item.time('08:15 · 2026-09-01');
191
- item.content('数据库连接池告警自动恢复。');
192
- });
193
- })
194
- );
149
+ row.div((box) => {
150
+ box.style({ textAlign: 'center' });
151
+ box.child(vGauge({ unit: '%', value: 58, tone: 'primary' }));
152
+ box.p((text) => {
153
+ text.style({
154
+ color: 'var(--yoya-color-text-muted, #64748b)',
155
+ fontSize: '12px'
156
+ });
157
+ text.child('内存使用率');
158
+ });
195
159
  });
196
160
  });
197
161
  });
198
162
  });
199
- }
200
- };
163
+ bottom.vCard((card) => {
164
+ card.vCardHeader('最近动态');
165
+ card.vCardBody((body) => {
166
+ body.child(
167
+ vTimeline((timeline) => {
168
+ timeline.vTimelineItem((item) => {
169
+ item.status('success');
170
+ item.title('服务发布成功');
171
+ item.time('09:32 · 2026-09-01');
172
+ item.content((box) => box.p('api-gateway v2.4.1 已上线,金丝雀批次全部通过。'));
173
+ });
174
+ timeline.vTimelineItem((item) => {
175
+ item.status('processing');
176
+ item.title('滚动发布中');
177
+ item.time('09:20 · 2026-09-01');
178
+ item.content('web-console 正在按 5% 批次滚动。');
179
+ });
180
+ timeline.vTimelineItem((item) => {
181
+ item.status('warning');
182
+ item.title('容量预警');
183
+ item.time('08:47 · 2026-09-01');
184
+ item.content('redis 内存使用率接近 80%。');
185
+ });
186
+ timeline.vTimelineItem((item) => {
187
+ item.status('danger');
188
+ item.title('告警已恢复');
189
+ item.time('08:15 · 2026-09-01');
190
+ item.content('数据库连接池告警自动恢复。');
191
+ });
192
+ })
193
+ );
194
+ });
195
+ });
196
+ });
197
+ });
201
198
  }
@@ -1,5 +1,5 @@
1
1
  /** 字典管理请求命令类型声明(对应 dict.mgr.js)。 */
2
- import { RequestBase } from '@yoyaflow/yoya-ui/api';
2
+ import { RequestBase } from '@yoyaflow/yoya-core/api';
3
3
  import Dicts, { DictStatus } from './dict.views.js';
4
4
 
5
5
  type DictTypeInstance = InstanceType<typeof Dicts.DictTypeItem>;
@@ -1,5 +1,5 @@
1
1
  // 字典管理请求命令:字典类型与字典项。
2
- import { RequestBase } from '@yoyaflow/yoya-ui/api';
2
+ import { RequestBase } from '@yoyaflow/yoya-core/api';
3
3
  import Dicts from './dict.views.js';
4
4
 
5
5
  class QueryTypes extends RequestBase {
@@ -1,6 +1,6 @@
1
1
  /** 字典页状态类类型声明(对应 dict.state.js)。 */
2
2
  import type { SignalHandle } from '@yoyaflow/yoya-ui';
3
- import type { Result } from '@yoyaflow/yoya-ui/api';
3
+ import type { Result } from '@yoyaflow/yoya-core/api';
4
4
  import Dicts from './dict.views.js';
5
5
 
6
6
  type DictTypeInstance = InstanceType<typeof Dicts.DictTypeItem>;
@@ -1,4 +1,4 @@
1
- import { computed, toast, vConfirm, vDialog, vText, vTr } from '@yoyaflow/yoya-ui';
1
+ import { computed, toast, vConfirm, vDialog, vNode, vText, vTr } from '@yoyaflow/yoya-ui';
2
2
  import { fieldValue } from '../../../../shared/state.rows.js';
3
3
  import { RowActionButton } from '../../../../shared/ui.buttons.js';
4
4
  import { DictItemFormDialog } from './dict-item-form-dialog.js';
@@ -179,13 +179,17 @@ export function DictEditorDialog({ state, onSubmit }) {
179
179
  onSubmit(editingId, form.values()).then(() => dialog.close());
180
180
  }
181
181
 
182
- return {
183
- render() {
184
- return dialog;
185
- },
186
- open,
187
- close() {
182
+ // 有对外命令方法(open / close)→ 形态 B:命令写在 api 上,视图就是自己的弹窗节点
183
+ return vNode((api) => {
184
+ api.open = (type = null) => {
185
+ open(type);
186
+ return api;
187
+ };
188
+ api.close = () => {
188
189
  dialog.close();
189
- }
190
- };
190
+ return api;
191
+ };
192
+
193
+ return dialog;
194
+ });
191
195
  }
@@ -1,4 +1,4 @@
1
- import { vDialog } from '@yoyaflow/yoya-ui';
1
+ import { vDialog, vNode } from '@yoyaflow/yoya-ui';
2
2
  import { fieldValue } from '../../../../shared/state.rows.js';
3
3
  import { statusOptions } from '../utils/options.js';
4
4
 
@@ -74,13 +74,17 @@ export function DictItemFormDialog({ onSubmit }) {
74
74
  dialog.close();
75
75
  }
76
76
 
77
- return {
78
- render() {
79
- return dialog;
80
- },
81
- open,
82
- close() {
77
+ // 有对外命令方法(open / close)→ 形态 B:命令写在 api 上,视图就是自己的弹窗节点
78
+ return vNode((api) => {
79
+ api.open = (item = null) => {
80
+ open(item);
81
+ return api;
82
+ };
83
+ api.close = () => {
83
84
  dialog.close();
84
- }
85
- };
85
+ return api;
86
+ };
87
+
88
+ return dialog;
89
+ });
86
90
  }