model-action 2.0.12 → 2.2.1

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 (82) hide show
  1. package/dist/index.d.ts +6 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +3 -0
  4. package/dist/index.js.map +1 -1
  5. package/dist/modules/Action.d.ts +29 -3
  6. package/dist/modules/Action.d.ts.map +1 -1
  7. package/dist/modules/Action.js +138 -11
  8. package/dist/modules/Action.js.map +1 -1
  9. package/dist/modules/Animation.d.ts +6 -6
  10. package/dist/modules/Animation.js +6 -6
  11. package/dist/modules/Animation.js.map +1 -1
  12. package/dist/modules/Building.d.ts +4 -4
  13. package/dist/modules/Building.js +4 -4
  14. package/dist/modules/Building.js.map +1 -1
  15. package/dist/modules/CameraView.d.ts +5 -5
  16. package/dist/modules/CameraView.js +5 -5
  17. package/dist/modules/CameraView.js.map +1 -1
  18. package/dist/modules/Effect.d.ts +3 -3
  19. package/dist/modules/Effect.js +3 -3
  20. package/dist/modules/Effect.js.map +1 -1
  21. package/dist/modules/Environment.d.ts +3 -3
  22. package/dist/modules/Environment.js +3 -3
  23. package/dist/modules/Environment.js.map +1 -1
  24. package/dist/modules/Focus.d.ts +1 -1
  25. package/dist/modules/Focus.js +1 -1
  26. package/dist/modules/Focus.js.map +1 -1
  27. package/dist/modules/GameMode.d.ts +2 -2
  28. package/dist/modules/GameMode.js +2 -2
  29. package/dist/modules/GameMode.js.map +1 -1
  30. package/dist/modules/Init.d.ts.map +1 -1
  31. package/dist/modules/Init.js +9 -17
  32. package/dist/modules/Init.js.map +1 -1
  33. package/dist/modules/Path.d.ts +5 -5
  34. package/dist/modules/Path.js +6 -6
  35. package/dist/modules/Path.js.map +1 -1
  36. package/dist/modules/Poi.d.ts +8 -8
  37. package/dist/modules/Poi.js +8 -8
  38. package/dist/modules/Poi.js.map +1 -1
  39. package/dist/modules/Routing.d.ts +4 -4
  40. package/dist/modules/Routing.js +4 -4
  41. package/dist/modules/Routing.js.map +1 -1
  42. package/dist/modules/Scene.d.ts +2 -2
  43. package/dist/modules/Scene.js +2 -2
  44. package/dist/modules/Scene.js.map +1 -1
  45. package/dist/modules/SceneAsset.d.ts +115 -0
  46. package/dist/modules/SceneAsset.d.ts.map +1 -0
  47. package/dist/modules/SceneAsset.js +97 -0
  48. package/dist/modules/SceneAsset.js.map +1 -0
  49. package/dist/modules/SingleMesh.d.ts +54 -0
  50. package/dist/modules/SingleMesh.d.ts.map +1 -0
  51. package/dist/modules/SingleMesh.js +33 -0
  52. package/dist/modules/SingleMesh.js.map +1 -0
  53. package/dist/modules/Status.d.ts +1 -1
  54. package/dist/modules/Status.js +1 -1
  55. package/dist/modules/Status.js.map +1 -1
  56. package/dist/modules/VideoFusion.d.ts +9 -9
  57. package/dist/modules/VideoFusion.js +9 -9
  58. package/dist/modules/VideoFusion.js.map +1 -1
  59. package/dist/modules/Window.d.ts +63 -10
  60. package/dist/modules/Window.d.ts.map +1 -1
  61. package/dist/modules/Window.js +30 -27
  62. package/dist/modules/Window.js.map +1 -1
  63. package/package.json +1 -1
  64. package/src/index.ts +33 -0
  65. package/src/modules/Action.ts +173 -10
  66. package/src/modules/Animation.ts +6 -6
  67. package/src/modules/Building.ts +4 -4
  68. package/src/modules/CameraView.ts +5 -5
  69. package/src/modules/Effect.ts +3 -3
  70. package/src/modules/Environment.ts +3 -3
  71. package/src/modules/Focus.ts +1 -1
  72. package/src/modules/GameMode.ts +2 -2
  73. package/src/modules/Init.ts +8 -19
  74. package/src/modules/Path.ts +6 -6
  75. package/src/modules/Poi.ts +8 -8
  76. package/src/modules/Routing.ts +4 -4
  77. package/src/modules/Scene.ts +2 -2
  78. package/src/modules/SceneAsset.ts +242 -0
  79. package/src/modules/SingleMesh.ts +89 -0
  80. package/src/modules/Status.ts +1 -1
  81. package/src/modules/VideoFusion.ts +9 -9
  82. package/src/modules/Window.ts +128 -0
@@ -0,0 +1,242 @@
1
+ /**
2
+ * 场景资产操作方法(上图、房间/资产与三维场景绑定等)
3
+ */
4
+ import { Action, SendParam } from "./Action";
5
+
6
+ /** 前端发往三维的 action */
7
+ export type SceneAssetActionType =
8
+ | "mapLocation"
9
+ | "editSave"
10
+ | "editCancel"
11
+ | "disableSceneEdit";
12
+
13
+ /** 资产大类:房间、POI 等 */
14
+ export type SceneAssetType = "Room" | "POI" | string;
15
+
16
+ /** 地图定位 — 房间在单层下的条目 */
17
+ export interface RoomMapLocationParam {
18
+ /** 房间等业务唯一标识,必须 */
19
+ id: string;
20
+ /** 三维场景内唯一 id,初始可空,上图后由三维回写 */
21
+ sceneId?: string;
22
+ /** 展示名称,必须 */
23
+ name: string;
24
+ /** 如 `X=0.0,Y=0.0,Z=0.0`;空或省略则使用楼层分层默认定位 */
25
+ location?: string;
26
+ description?: string;
27
+ /** 是否已上图;也可由后台根据坐标是否为空推断 */
28
+ alreadyMap?: boolean;
29
+ }
30
+
31
+ /** POI 打点 — 单条参数(与 Room 的 params 结构不同) */
32
+ export interface PoiMapLocationParam {
33
+ /** POI 子类型,用于区分展示样式,如 Camera */
34
+ type: string;
35
+ /** 非必须;前端有唯一值可传给三维,否则由三维生成并回传 */
36
+ sceneId?: string;
37
+ /** 业务关联 ID,必须 */
38
+ linkId: string;
39
+ /** 有则建议传入 */
40
+ name?: string;
41
+ /** 非必须;不传时三维可取当前鼠标在场景中的坐标 */
42
+ location?: string;
43
+ }
44
+
45
+ export type SceneAssetMapLocationPayload =
46
+ | {
47
+ action: "mapLocation";
48
+ type: "Room";
49
+ buildingId: string;
50
+ floor: string;
51
+ params: RoomMapLocationParam[];
52
+ }
53
+ | {
54
+ action: "mapLocation";
55
+ type: "POI";
56
+ /** 不传或空:室外打点;传入时三维会与当前分层校验 */
57
+ buildingId?: string;
58
+ floor?: string;
59
+ params: PoiMapLocationParam[];
60
+ };
61
+
62
+ export type SceneAssetPayload =
63
+ | SceneAssetMapLocationPayload
64
+ | {
65
+ action: "editSave";
66
+ type: SceneAssetType;
67
+ /** 三维返回的 sceneId */
68
+ id: string;
69
+ }
70
+ | {
71
+ action: "editCancel";
72
+ type: SceneAssetType;
73
+ id: string;
74
+ }
75
+ | {
76
+ action: "disableSceneEdit";
77
+ };
78
+
79
+ /** 三维推送:编辑模式下选中资产,前端可据此弹出编辑框 */
80
+ export interface SceneAssetOnAssetSelectedData {
81
+ action: "OnAssetSelected";
82
+ type: SceneAssetType;
83
+ /** POI 场景下为前端下发的 linkId */
84
+ id: string;
85
+ /** 三维生成的唯一 id,需入库 */
86
+ sceneId: string;
87
+ /** POI 所在位置描述,需入库与三维一致 */
88
+ place?: string;
89
+ location: string;
90
+ }
91
+
92
+ /** 三维推送:单个资产修改后的结果 */
93
+ export interface SceneAssetOnEditAssetData {
94
+ action: "OnEditAsset";
95
+ type: SceneAssetType;
96
+ id: string;
97
+ sceneId: string;
98
+ location: string;
99
+ }
100
+
101
+ export type SceneAssetPushData =
102
+ | SceneAssetOnAssetSelectedData
103
+ | SceneAssetOnEditAssetData;
104
+
105
+ /** 三维经 sceneAsset 推送的通用消息壳(无 requestId) */
106
+ export interface SceneAssetPushMessage<
107
+ T extends SceneAssetPushData = SceneAssetPushData
108
+ > {
109
+ code: string;
110
+ message: string;
111
+ cmd: "sceneAsset";
112
+ data: T;
113
+ }
114
+
115
+ type SceneAssetParamType = SendParam & {
116
+ cmd: "sceneAsset";
117
+ data: SceneAssetPayload;
118
+ };
119
+
120
+ function appendPoiBuildingFloor(
121
+ data: Extract<SceneAssetMapLocationPayload, { type: "POI" }>,
122
+ buildingId?: string,
123
+ floor?: string
124
+ ) {
125
+ const b = buildingId?.trim();
126
+ const f = floor?.trim();
127
+ if (b) data.buildingId = b;
128
+ if (f) data.floor = f;
129
+ }
130
+
131
+ export class SceneAssetAction extends Action {
132
+ /**
133
+ * 房间等在指定建筑、楼层上地图定位(上图)
134
+ * @param buildingId 建筑唯一 ID
135
+ * @param floor 楼层,如 1F、B1
136
+ */
137
+ static mapRoomLocation(
138
+ buildingId: string,
139
+ floor: string,
140
+ params: RoomMapLocationParam[]
141
+ ) {
142
+ const data: Extract<SceneAssetMapLocationPayload, { type: "Room" }> = {
143
+ action: "mapLocation",
144
+ type: "Room",
145
+ buildingId,
146
+ floor,
147
+ params
148
+ };
149
+
150
+ const sendParam: SceneAssetParamType = {
151
+ cmd: "sceneAsset",
152
+ data
153
+ };
154
+ return this.sendParam(
155
+ sendParam,
156
+ `场景资产房间上图 - buildingId: ${buildingId} floor: ${floor}`
157
+ );
158
+ }
159
+
160
+ /**
161
+ * POI 打点上图。不传 `buildingId`、`floor`(或仅空白)视为室外;
162
+ * 传入时三维会与当前分层匹配,不匹配则打点失败,前端需提示先分层到目标楼层。
163
+ */
164
+ static mapPoiLocation(
165
+ params: PoiMapLocationParam[],
166
+ buildingId?: string,
167
+ floor?: string
168
+ ) {
169
+ const data: Extract<SceneAssetMapLocationPayload, { type: "POI" }> = {
170
+ action: "mapLocation",
171
+ type: "POI",
172
+ params
173
+ };
174
+ appendPoiBuildingFloor(data, buildingId, floor);
175
+
176
+ const sendParam: SceneAssetParamType = {
177
+ cmd: "sceneAsset",
178
+ data
179
+ };
180
+ const scope =
181
+ buildingId?.trim() && floor?.trim()
182
+ ? `buildingId: ${buildingId} floor: ${floor}`
183
+ : "室外";
184
+ return this.sendParam(sendParam, `场景资产 POI 上图 - ${scope}`);
185
+ }
186
+
187
+ /**
188
+ * 前端编辑框「保存」后通知三维
189
+ * @param id 三维返回的 sceneId
190
+ */
191
+ static editSave(id: string, type: SceneAssetType = "Room") {
192
+ const data: Extract<SceneAssetPayload, { action: "editSave" }> = {
193
+ action: "editSave",
194
+ type,
195
+ id
196
+ };
197
+
198
+ const sendParam: SceneAssetParamType = {
199
+ cmd: "sceneAsset",
200
+ data
201
+ };
202
+ return this.sendParam(
203
+ sendParam,
204
+ `场景资产编辑保存 - ${type} sceneId: ${id}`
205
+ );
206
+ }
207
+
208
+ /**
209
+ * 前端编辑框「取消」后通知三维
210
+ * @param id 三维返回的 sceneId
211
+ */
212
+ static editCancel(id: string, type: SceneAssetType = "Room") {
213
+ const data: Extract<SceneAssetPayload, { action: "editCancel" }> = {
214
+ action: "editCancel",
215
+ type,
216
+ id
217
+ };
218
+
219
+ const sendParam: SceneAssetParamType = {
220
+ cmd: "sceneAsset",
221
+ data
222
+ };
223
+ return this.sendParam(
224
+ sendParam,
225
+ `场景资产编辑取消 - ${type} sceneId: ${id}`
226
+ );
227
+ }
228
+
229
+ /** 退出整个资产管理编辑模块 */
230
+ static disableSceneEdit() {
231
+ const data: Extract<SceneAssetPayload, { action: "disableSceneEdit" }> =
232
+ {
233
+ action: "disableSceneEdit"
234
+ };
235
+
236
+ const sendParam: SceneAssetParamType = {
237
+ cmd: "sceneAsset",
238
+ data
239
+ };
240
+ return this.sendParam(sendParam, "退出场景资产编辑模块");
241
+ }
242
+ }
@@ -0,0 +1,89 @@
1
+ /**
2
+ * 模型单体化:将指定模型转为可操作实例,支持 init / add / remove。
3
+ * POI 替代方案请走 POI 接口;本接口生成的是场景内模型实例。
4
+ */
5
+ import { Action, SendParam } from "./Action";
6
+
7
+ export type SingleMeshOp = "init" | "add" | "remove";
8
+
9
+ /**
10
+ * 接口使用场景区分:Normal 通用;JF 等由项目约定。
11
+ * 无特殊场景可不传,三维按通用处理。
12
+ */
13
+ export type SingleMeshSceneType = "Normal" | "JF" | string;
14
+
15
+ /** 设备模型类型,如服务器、交换机,项目约定 */
16
+ export type SingleMeshDeviceModelType = "Service" | "Switch" | string;
17
+
18
+ /** 设备类别:机柜 | 机柜内设备 等 */
19
+ export type SingleMeshDeviceCategory = "Cabinet" | "CDevice" | string;
20
+
21
+ export interface SingleMeshDevice {
22
+ id: string;
23
+ name: string;
24
+ type: SingleMeshDeviceModelType;
25
+ /** 非必须,内置可补全 */
26
+ category?: SingleMeshDeviceCategory;
27
+ /** 如机柜内设备填所属机柜 id */
28
+ parentId?: string;
29
+ parentCategory?: SingleMeshDeviceCategory;
30
+ /** 在父设备上的槽口,机柜内设备按项目必传 */
31
+ socketOnParent?: string;
32
+ }
33
+
34
+ export interface SingleMeshScene {
35
+ /** 场景/机房编码,项目约定;不传则当前场景 */
36
+ sceneCode?: string;
37
+ sceneName?: string;
38
+ devices: SingleMeshDevice[];
39
+ }
40
+
41
+ export type SingleMeshPayload =
42
+ | {
43
+ action: "add";
44
+ scenes: SingleMeshScene[];
45
+ sceneType?: SingleMeshSceneType;
46
+ }
47
+ | {
48
+ action: "init" | "remove";
49
+ scenes: SingleMeshScene[];
50
+ };
51
+
52
+ type SingleMeshParamType = SendParam & {
53
+ cmd: "singleMesh";
54
+ data: SingleMeshPayload;
55
+ };
56
+
57
+ export class SingleMeshAction extends Action {
58
+ private static emit(data: SingleMeshPayload, log: string) {
59
+ return this.sendParam(
60
+ { cmd: "singleMesh", data } as SingleMeshParamType,
61
+ log
62
+ );
63
+ }
64
+
65
+ /** 初始化场景内单体化数据 */
66
+ static init(scenes: SingleMeshScene[]) {
67
+ return this.emit({ action: "init", scenes }, "单体化 init");
68
+ }
69
+
70
+ /**
71
+ * 增加单体化设备/模型
72
+ * @param sceneType 非必须;机房等特殊场景传如 JF,默认不传为通用 Normal
73
+ */
74
+ static add(scenes: SingleMeshScene[], sceneType?: SingleMeshSceneType) {
75
+ const data: Extract<SingleMeshPayload, { action: "add" }> = {
76
+ action: "add",
77
+ scenes
78
+ };
79
+ if (sceneType != null && sceneType !== "") {
80
+ data.sceneType = sceneType;
81
+ }
82
+ return this.emit(data, `单体化 add${sceneType ? ` (${sceneType})` : ""}`);
83
+ }
84
+
85
+ /** 移除单体化实例 */
86
+ static remove(scenes: SingleMeshScene[]) {
87
+ return this.emit({ action: "remove", scenes }, "单体化 remove");
88
+ }
89
+ }
@@ -69,7 +69,7 @@ export class StatusAction extends Action {
69
69
  }
70
70
 
71
71
  // 使用类型断言调用sendParam,因为StatusType不严格符合SendParam(缺少action字段)
72
- this.sendParam(param as any, msg);
72
+ return this.sendParam(param as any, msg);
73
73
  }
74
74
 
75
75
  /**
@@ -97,7 +97,7 @@ export class VideoFusionAction extends Action {
97
97
  data
98
98
  };
99
99
 
100
- this.sendParam(param, '初始化视频融合');
100
+ return this.sendParam(param, '初始化视频融合');
101
101
  }
102
102
 
103
103
  /**
@@ -118,7 +118,7 @@ export class VideoFusionAction extends Action {
118
118
  data
119
119
  };
120
120
 
121
- this.sendParam(param, '刷新token');
121
+ return this.sendParam(param, '刷新token');
122
122
  }
123
123
 
124
124
  /**
@@ -166,7 +166,7 @@ export class VideoFusionAction extends Action {
166
166
  data
167
167
  };
168
168
 
169
- this.sendParam(param, '播放视频');
169
+ return this.sendParam(param, '播放视频');
170
170
  }
171
171
 
172
172
  /**
@@ -190,7 +190,7 @@ export class VideoFusionAction extends Action {
190
190
  data
191
191
  };
192
192
 
193
- this.sendParam(param, '停止视频');
193
+ return this.sendParam(param, '停止视频');
194
194
  }
195
195
 
196
196
  /**
@@ -214,7 +214,7 @@ export class VideoFusionAction extends Action {
214
214
  data
215
215
  };
216
216
 
217
- this.sendParam(param, '暂停录像播放');
217
+ return this.sendParam(param, '暂停录像播放');
218
218
  }
219
219
 
220
220
  /**
@@ -238,7 +238,7 @@ export class VideoFusionAction extends Action {
238
238
  data
239
239
  };
240
240
 
241
- this.sendParam(param, '恢复录像播放');
241
+ return this.sendParam(param, '恢复录像播放');
242
242
  }
243
243
 
244
244
  /**
@@ -261,7 +261,7 @@ export class VideoFusionAction extends Action {
261
261
  data
262
262
  };
263
263
 
264
- this.sendParam(param, `飞到融合点位 - id: ${options.id}`);
264
+ return this.sendParam(param, `飞到融合点位 - id: ${options.id}`);
265
265
  }
266
266
 
267
267
  /**
@@ -279,7 +279,7 @@ export class VideoFusionAction extends Action {
279
279
  data
280
280
  };
281
281
 
282
- this.sendParam(param, '获取当前所有的融合点位ID');
282
+ return this.sendParam(param, '获取当前所有的融合点位ID');
283
283
  }
284
284
 
285
285
  /**
@@ -311,6 +311,6 @@ export class VideoFusionAction extends Action {
311
311
  data
312
312
  };
313
313
 
314
- this.sendParam(param, '设置隐藏融合视频的阈值');
314
+ return this.sendParam(param, '设置隐藏融合视频的阈值');
315
315
  }
316
316
  }
@@ -0,0 +1,128 @@
1
+ /**
2
+ * 弹框:三维内置弹框或外部弹框(返回屏幕坐标比例供前端自绘,可随锚点移动)。
3
+ * 内置样式需按项目单独开发,本包只负责协议与发送。
4
+ */
5
+ import { Action, SendParam } from "./Action";
6
+
7
+ /** create / remove / update / move */
8
+ export type WindowCrudAction = "create" | "remove" | "update" | "move";
9
+
10
+ export type WindowActionType = WindowCrudAction | "getWindowDetails";
11
+
12
+ /** buildIn:三维内弹框;buildOut:前端弹框(接收屏幕坐标比例) */
13
+ export type WindowPopType = "buildIn" | "buildOut";
14
+
15
+ /** 弹框详情行:属性 / 事件 / 服务 */
16
+ export type WindowDetailRowType = "attr" | "event" | "service";
17
+
18
+ /** windowInfo.params 单项 */
19
+ export interface WindowDetailParam {
20
+ /** 默认 attr;为空时三维会按 attr 处理 */
21
+ type?: WindowDetailRowType;
22
+ id?: string;
23
+ value?: string;
24
+ name?: string;
25
+ unit?: string;
26
+ textColor?: string;
27
+ textSize?: number;
28
+ /** 文本是否有背景(协议字段名如此) */
29
+ hasBlackground?: boolean;
30
+ alertIs?: boolean;
31
+ alertTime?: string;
32
+ }
33
+
34
+ /** 弹框主体配置 */
35
+ export interface WindowInfo {
36
+ /** 设备所在场景编码,按项目约定,非必须 */
37
+ sceneCode?: string;
38
+ /** 弹框唯一 id,不传由三维生成 */
39
+ id?: string;
40
+ /** 绑定的三维资产模型 id */
41
+ linkAssetId?: string;
42
+ /** 标题 */
43
+ name?: string;
44
+ /** 设备/弹框类型 */
45
+ type?: string;
46
+ /** 世界坐标;不传则可用 linkAssetId 对应资产坐标 */
47
+ position?: string;
48
+ /** 相对锚点偏移,用于微调 */
49
+ localPosition?: string;
50
+ /** 详情内容;列表时每项一行 */
51
+ params?: WindowDetailParam[];
52
+ }
53
+
54
+ export type WindowPayload =
55
+ | {
56
+ action: WindowCrudAction;
57
+ popType: WindowPopType;
58
+ windowInfo: WindowInfo;
59
+ }
60
+ | {
61
+ action: "getWindowDetails";
62
+ /** 如机柜、机柜设备 */
63
+ type: string;
64
+ id: string;
65
+ /** 注意:与 windowInfo.sceneCode 不同,此处协议字段名为 senceCode */
66
+ senceCode: string;
67
+ };
68
+
69
+ type WindowParamType = SendParam & {
70
+ cmd: "window";
71
+ data: WindowPayload;
72
+ };
73
+
74
+ export class WindowAction extends Action {
75
+ private static crud(
76
+ action: WindowCrudAction,
77
+ popType: WindowPopType,
78
+ windowInfo: WindowInfo,
79
+ log: string
80
+ ) {
81
+ const data: Extract<WindowPayload, { action: WindowCrudAction }> = {
82
+ action,
83
+ popType,
84
+ windowInfo
85
+ };
86
+ return this.sendParam(
87
+ { cmd: "window", data } as WindowParamType,
88
+ log
89
+ );
90
+ }
91
+
92
+ static createWindow(popType: WindowPopType, windowInfo: WindowInfo) {
93
+ return this.crud("create", popType, windowInfo, `弹框创建 - ${popType}`);
94
+ }
95
+
96
+ static removeWindow(popType: WindowPopType, windowInfo: WindowInfo) {
97
+ return this.crud("remove", popType, windowInfo, `弹框移除 - ${popType}`);
98
+ }
99
+
100
+ static updateWindow(popType: WindowPopType, windowInfo: WindowInfo) {
101
+ return this.crud("update", popType, windowInfo, `弹框更新 - ${popType}`);
102
+ }
103
+
104
+ static moveWindow(popType: WindowPopType, windowInfo: WindowInfo) {
105
+ return this.crud("move", popType, windowInfo, `弹框移动 - ${popType}`);
106
+ }
107
+
108
+ /**
109
+ * 查询弹框详情(按设备类型、设备 id、场景)
110
+ * @param senceCode 协议字段名与 sceneCode 拼写不一致,与三维约定保持一致
111
+ */
112
+ static getWindowDetails(
113
+ type: string,
114
+ id: string,
115
+ senceCode: string
116
+ ) {
117
+ const data: Extract<WindowPayload, { action: "getWindowDetails" }> = {
118
+ action: "getWindowDetails",
119
+ type,
120
+ id,
121
+ senceCode
122
+ };
123
+ return this.sendParam(
124
+ { cmd: "window", data } as WindowParamType,
125
+ `获取弹框详情 - type: ${type} id: ${id}`
126
+ );
127
+ }
128
+ }