@yuku123/z-team-component 0.2.29 → 0.2.31

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 (49) hide show
  1. package/dist/{ChangeLogView-CG-o5YP1.js → ChangeLogView-FLd1wS8H.js} +1 -1
  2. package/dist/ComponentDoc-CUhlRqDo.js +3843 -0
  3. package/dist/DebugPlayground-cxffrMgF.js +15 -0
  4. package/dist/{InvitationManagementPage-ByJuWwA_.js → InvitationManagementPage-DBAAQ3Qq.js} +90 -85
  5. package/dist/{OnboardingPage-D58h1JK_.js → OnboardingPage-zLHkQLok.js} +2 -2
  6. package/dist/SmartWorkbench.module-DzQskKT0.js +85 -0
  7. package/dist/SystemShell-yMCZOMUN.js +635 -0
  8. package/dist/{admin-logs-C2V1ElH9.js → admin-logs-Dv86pFvY.js} +2 -2
  9. package/dist/{api--Fg0hL9Y.js → api-19TXED_O.js} +52 -39
  10. package/dist/api-63lPU5Cs.js +20 -0
  11. package/dist/{createWorkspaceWsHandler-CqGqcTh_.js → createWorkspaceWsHandler-CBk4DqP4.js} +6 -5
  12. package/dist/{index-CDKg_qI5.js → index-B5_xKK08.js} +1140 -1153
  13. package/dist/{index-D2S8FrNc.js → index-BCBBZW4m.js} +358 -347
  14. package/dist/{index-D5u3BjCZ.js → index-BIJnjJd5.js} +2 -2
  15. package/dist/{index-bbwTcNjB.js → index-BTLD5gUt.js} +3 -3
  16. package/dist/{index-CiMxCTOS.js → index-B_EBV24V.js} +1 -1
  17. package/dist/{index-DOVOWiGU.js → index-BbjzrjsP.js} +1134 -1132
  18. package/dist/{index-BafC42Cl.js → index-Bd57t_yF.js} +1 -1
  19. package/dist/{index-C2aPiQSz.js → index-BjqYiZpC.js} +3 -3
  20. package/dist/{index-BaCiSbPR.js → index-BoGVJ0hC.js} +1 -1
  21. package/dist/{index-C01UUprh.js → index-BpuJ9Njb.js} +7016 -6946
  22. package/dist/index-C6vfXs2f.js +1329 -0
  23. package/dist/{index-CcFJEYgr.js → index-C815hPWS.js} +55 -52
  24. package/dist/{index-DvIHX7lZ.js → index-CcpWacSZ.js} +243 -236
  25. package/dist/index-CrC94bvI.js +169 -0
  26. package/dist/{index-Dky6GVc1.js → index-CwIgdJYL.js} +9 -9
  27. package/dist/{index-Da7ls5q6.js → index-DOPkM2W8.js} +6 -6
  28. package/dist/{index-CTD7k9dP.js → index-DYgD6BuB.js} +4 -4
  29. package/dist/{index-Da3doGtf.js → index-JMzBzwiO.js} +57 -54
  30. package/dist/{index-BwFEDHy3.js → index-VHvEmmhf.js} +5 -5
  31. package/dist/{index-CRac8IT2.js → index-icI-ZchA.js} +3 -3
  32. package/dist/{index-Dao4uqQd.js → index-x4-W5ClM.js} +4 -4
  33. package/dist/index.js +7 -6
  34. package/dist/{instance-1QEDBRqA.js → instance-D951fRuD.js} +1 -1
  35. package/dist/pages.js +13 -9
  36. package/dist/{schedule-C89oiqIR.js → schedule-DD50-7cs.js} +1 -1
  37. package/dist/{send-default-agent-team-message-CxkWi3XC.js → send-default-agent-team-message-Bbs2rMNf.js} +1 -1
  38. package/dist/{sso-user-BE1Ell5F.js → sso-user-BEY5ICaR.js} +1 -1
  39. package/dist/{training-o-vSBkqP.js → training-B-9tNFQw.js} +1 -1
  40. package/dist/{useAppStore-wgWaxcyc.js → useAppStore-BQN-26ns.js} +1 -1
  41. package/dist/{webide-BxD6cYe-.js → webide-P867RFZi.js} +4 -4
  42. package/dist/z-team-component.css +1 -1
  43. package/package.json +2 -2
  44. package/dist/ProjectApp-oUbzb0Io.js +0 -3818
  45. package/dist/SmartWorkbench.module-xRRmpTTw.js +0 -85
  46. package/dist/SystemShell-D4mGsT0X.js +0 -604
  47. package/dist/api-3-Ykp2ll.js +0 -19
  48. package/dist/index-B8mNsH88.js +0 -1411
  49. package/dist/index-DYDba1NC.js +0 -187
@@ -1,3818 +0,0 @@
1
- import { jsx as e, jsxs as n, Fragment as Me } from "react/jsx-runtime";
2
- import { lazy as xt, Suspense as wt, useState as g, useEffect as K, useRef as it } from "react";
3
- import { useLocation as It, useNavigate as be, useParams as st, Routes as ot, Route as re, Navigate as ct, useSearchParams as St } from "react-router-dom";
4
- import { Row as Q, Col as M, Typography as le, Alert as J, Card as P, Space as R, Button as _, Table as H, Drawer as xe, Descriptions as z, Tag as x, Tooltip as he, message as b, Modal as pe, Statistic as U, Input as B, Select as W, Tabs as we, Form as E, Upload as kt, Popconfirm as qe, Spin as _e, Radio as ne, InputNumber as ze, Empty as dt } from "antd";
5
- import { SettingOutlined as Ct, ProjectOutlined as Ae, UserOutlined as ut, AuditOutlined as $e, RobotOutlined as Le, ApiOutlined as je, AppstoreOutlined as Tt, ThunderboltOutlined as fe, BarChartOutlined as vt, ScheduleOutlined as _t, FileTextOutlined as Fe, ReloadOutlined as ee, ExperimentOutlined as At, PlayCircleOutlined as Ee, CopyOutlined as ht, GlobalOutlined as pt, NodeIndexOutlined as Et, UndoOutlined as Rt, FileSearchOutlined as zt, VideoCameraOutlined as Ve, SearchOutlined as mt, EyeOutlined as Ot, CodeOutlined as ge, InfoCircleOutlined as Pt, FunctionOutlined as Se, ImportOutlined as Ne, CloudUploadOutlined as Je, FileAddOutlined as Mt, PlusOutlined as yt, EditOutlined as $t, PauseCircleOutlined as Lt, CheckCircleOutlined as Ue, DeleteOutlined as Nt, ExclamationCircleOutlined as Dt, SaveOutlined as gt, ArrowLeftOutlined as ft, SendOutlined as Bt } from "@ant-design/icons";
6
- import "@yuku123/z-frontend-common";
7
- import { PageHeader as me, GradientStatCard as ke, SectionHeader as qt, FeatureCard as jt, DarkBanner as Ft, TableToolbar as Ut, ErrorState as Ht, EmptyState as Kt } from "@yuku123/z-frontend-common/ui";
8
- import He from "axios";
9
- const Y = (t) => {
10
- const i = xt(t);
11
- return (r) => /* @__PURE__ */ e(wt, { fallback: null, children: /* @__PURE__ */ e(i, { ...r }) });
12
- }, se = Y(() => import("./index-DOVOWiGU.js").then((t) => t.H)), Gt = Y(() => import("./index-Da7ls5q6.js")), Vt = Y(() => import("./index-bbwTcNjB.js")), Jt = Y(() => import("./index-CTD7k9dP.js")), Xt = Y(() => import("./index-Dao4uqQd.js")), Wt = Y(() => import("./index-D5u3BjCZ.js"));
13
- Y(() => import("./index-C01UUprh.js"));
14
- const Zt = Y(() => import("./index-CcFJEYgr.js")), Yt = Y(() => import("./index-UsGqMo11.js")), Qt = Y(() => import("./index-BkX0I2aB.js")), en = Y(() => import("./index-CiMxCTOS.js")), tn = Y(() => import("./index-BafC42Cl.js")), nn = Y(() => import("./index-C2aPiQSz.js"));
15
- function Zn({ forcedMode: t }) {
16
- const { pathname: i } = It(), r = i.replace(/\/+$/, "") || "/";
17
- return t === "system" ? /* @__PURE__ */ e(se, { forcedChatMode: "system" }) : t === "rpa" ? /* @__PURE__ */ e(se, { forcedChatMode: "rpa" }) : t === "dev" ? /* @__PURE__ */ e(se, { forcedChatMode: "dev" }) : r === "/workspace" ? /* @__PURE__ */ e(se, {}) : r === "/workspace/phone" ? /* @__PURE__ */ e(Gt, {}) : r === "/workspace/from-ticket" ? /* @__PURE__ */ e(Vt, {}) : r === "/workspace/from-scenario" ? /* @__PURE__ */ e(Jt, {}) : r === "/workspace/build-by-form" ? /* @__PURE__ */ e(Xt, {}) : r === "/scenario" ? /* @__PURE__ */ e(Wt, {}) : r === "/admin" ? /* @__PURE__ */ e(se, {}) : r === "/welcome" ? /* @__PURE__ */ e(Yt, {}) : r === "/portal" ? /* @__PURE__ */ e(Qt, {}) : r === "/chatdemo" ? /* @__PURE__ */ e(Zt, {}) : r === "/embed/chat" || r.startsWith("/embed/chat/") ? /* @__PURE__ */ e(nn, {}) : r === "/change-log" ? /* @__PURE__ */ e(en, {}) : r === "/docs" ? /* @__PURE__ */ e(tn, {}) : /* @__PURE__ */ e(se, {});
18
- }
19
- function rn(t) {
20
- if (!t || typeof t != "string") return null;
21
- const i = t.split(".");
22
- if (i.length !== 3) return null;
23
- try {
24
- let r = i[1].replace(/-/g, "+").replace(/_/g, "/");
25
- const S = r.length % 4;
26
- S && (r += "=".repeat(4 - S));
27
- const l = atob(r), y = Uint8Array.from(l, (w) => w.charCodeAt(0)), s = new TextDecoder().decode(y), f = JSON.parse(s);
28
- return f && typeof f == "object" && !Array.isArray(f) ? f : null;
29
- } catch {
30
- return null;
31
- }
32
- }
33
- function ln(t, i = 30) {
34
- const r = rn(t);
35
- return !r || typeof r.exp != "number" ? !0 : Date.now() / 1e3 > r.exp - i;
36
- }
37
- let Xe = !1;
38
- const an = [
39
- "/ctc/authn/login",
40
- "/ctc/authn/register",
41
- "/ctc/authn/send-code",
42
- "/ctc/authn/register-phone",
43
- "/ctc/authn/reset-password",
44
- "/ctc/authn/phone-login",
45
- "/ctc/authn/verify",
46
- "/ctc/ac/login",
47
- "/auth/login",
48
- "/auth/register",
49
- "/auth/reset-password",
50
- "/uc/login",
51
- "/uc/register",
52
- "/uc/phone-login",
53
- "/sso/login",
54
- "/sso/callback"
55
- ];
56
- function sn(t) {
57
- return an.some((i) => t.includes(i));
58
- }
59
- function We(t) {
60
- if (Xe || typeof window > "u" || window.location.pathname.startsWith("/login")) return;
61
- Xe = !0;
62
- try {
63
- localStorage.removeItem("token"), localStorage.removeItem("userInfo");
64
- } catch {
65
- }
66
- console.warn(`[Auth] ${t}, 跳转到 /login`);
67
- const i = window.location.pathname + window.location.search, r = encodeURIComponent(i);
68
- window.location.href = `/login?redirect=${r}`;
69
- }
70
- function on(t) {
71
- if (t && typeof t == "object" && "code" in t && "data" in t) {
72
- const i = t;
73
- return (typeof i.success == "boolean" ? i.success : typeof i.code == "number" && i.code >= 200 && i.code < 300) ? i.data : Promise.reject(new Error(i.message || "请求失败"));
74
- }
75
- return t;
76
- }
77
- function cn(t, i = {}) {
78
- const { tokenKey: r = "token", userInfoKey: S = "userInfo" } = i;
79
- t.interceptors.request.use((l) => {
80
- const y = localStorage.getItem(r);
81
- if (y && ln(y))
82
- return We(`请求前检测到 token 已过期 (${l.url || ""})`), Promise.reject(new He.CanceledError("token expired"));
83
- try {
84
- const s = localStorage.getItem(S);
85
- if (s) {
86
- const f = JSON.parse(s), w = f.tenantCode || "default", T = f.domainCode || "default", A = f.id ?? f.userId, m = (l.method || "get").toLowerCase();
87
- if (typeof l.url == "string" && l.url.includes("/ctc/ac/") && (l.params = { ...l.params || {} }, l.params.tenantCode || (l.params.tenantCode = w), l.params.domainCode || (l.params.domainCode = T)), A != null && (l.headers["X-User-Id"] = String(A)), m !== "get" && m !== "delete" && l.data && typeof l.data == "object") {
88
- const h = l.data;
89
- h.tenantCode == null && (h.tenantCode = w), h.domainCode == null && (h.domainCode = T);
90
- }
91
- }
92
- } catch {
93
- }
94
- return l;
95
- }), t.interceptors.response.use(
96
- (l) => on(l.data),
97
- (l) => {
98
- var f, w;
99
- const y = (f = l.response) == null ? void 0 : f.status, s = ((w = l.config) == null ? void 0 : w.url) || "";
100
- return y === 401 ? sn(s) ? console.warn(`[401] 公开接口返回 401 (不是 token 问题): ${s}`) : We(`接口 ${s} 返回 401`) : y === 403 ? console.warn("[403] 没有权限访问该资源:", s) : y === 404 ? console.warn("[404] 接口不存在:", s) : y === 500 && console.error("[500] 服务器内部错误:", s), Promise.reject(l);
101
- }
102
- );
103
- }
104
- function Ke(t = {}) {
105
- const i = He.create({
106
- baseURL: t.baseURL ?? "/api",
107
- timeout: t.timeout ?? 1e4,
108
- withCredentials: !0
109
- // Cookie 模式:浏览器自动携带 Cookie
110
- });
111
- return cn(i, {
112
- tokenKey: t.tokenKey,
113
- userInfoKey: t.userInfoKey
114
- }), i;
115
- }
116
- const N = Ke(), Yn = Ke(), Ce = Ke({ baseURL: "/api", timeout: 1e4 }), Te = (t) => t ? typeof t.total == "number" ? t.total : Array.isArray(t) ? t.length : Array.isArray(t.records) ? t.records.length : Array.isArray(t.data) ? t.data.length : 0 : 0, dn = [
117
- {
118
- key: "ai",
119
- color: "violet",
120
- title: "智能中心",
121
- subtitle: "Agent · 模型 · MCP · 技能",
122
- icon: /* @__PURE__ */ e(Le, {}),
123
- href: "/ai/agent/app",
124
- items: [
125
- {
126
- title: "Agent 应用",
127
- description: "创建和管理 AI Agent 应用, 支持多种 LLM 模型",
128
- icon: /* @__PURE__ */ e(Le, {}),
129
- color: "violet",
130
- tags: [{ label: "AI", color: "violet" }, { label: "推荐", color: "orange" }],
131
- meta: "12 个应用"
132
- },
133
- {
134
- title: "多 Agent 实例",
135
- description: "多 Agent 协同执行, 支持 ZBOT / Hermes / Claude Code / OpenCode",
136
- icon: /* @__PURE__ */ e(je, {}),
137
- color: "blue",
138
- tags: [{ label: "AI", color: "blue" }],
139
- meta: "5 种引擎"
140
- },
141
- {
142
- title: "模板市场",
143
- description: "精选 AI 应用模板, 一键复制即可使用",
144
- icon: /* @__PURE__ */ e(Tt, {}),
145
- color: "pink",
146
- tags: [{ label: "模板", color: "pink" }],
147
- meta: "24 个模板"
148
- },
149
- {
150
- title: "技能市场",
151
- description: "为 Agent 装配技能, 拓展能力边界",
152
- icon: /* @__PURE__ */ e(fe, {}),
153
- color: "orange",
154
- tags: [{ label: "扩展", color: "orange" }]
155
- }
156
- ]
157
- },
158
- // 运维中心已迁出独立平台 z-ops (2026-09-24, github.com/z-opc-foundation/z-ops)
159
- {
160
- key: "task",
161
- color: "green",
162
- title: "任务中心",
163
- subtitle: "仪表盘 · 任务 · 项目",
164
- icon: /* @__PURE__ */ e(Ae, {}),
165
- href: "/task/dashboard",
166
- items: [
167
- {
168
- title: "任务仪表盘",
169
- description: "实时任务执行情况, 成功率与时长统计",
170
- icon: /* @__PURE__ */ e(vt, {}),
171
- color: "green",
172
- tags: [{ label: "看板", color: "green" }]
173
- },
174
- {
175
- title: "任务列表",
176
- description: "所有定时/手动任务, 支持 Cron 表达式",
177
- icon: /* @__PURE__ */ e(_t, {}),
178
- color: "blue",
179
- tags: [{ label: "调度", color: "blue" }]
180
- },
181
- {
182
- title: "项目管理",
183
- description: "项目维度组织任务, 支持里程碑",
184
- icon: /* @__PURE__ */ e(Ae, {}),
185
- color: "violet",
186
- tags: [{ label: "项目", color: "violet" }]
187
- }
188
- ]
189
- },
190
- {
191
- key: "workflow",
192
- color: "orange",
193
- title: "流程中心",
194
- subtitle: "审批 · 待办 · 我的",
195
- icon: /* @__PURE__ */ e($e, {}),
196
- href: "/workflow/dashboard",
197
- items: [
198
- {
199
- title: "流程仪表盘",
200
- description: "流程实例统计与效率分析",
201
- icon: /* @__PURE__ */ e($e, {}),
202
- color: "orange",
203
- tags: [{ label: "审批", color: "orange" }]
204
- },
205
- {
206
- title: "待办任务",
207
- description: "我的待审批任务, 实时推送",
208
- icon: /* @__PURE__ */ e(Fe, {}),
209
- color: "red",
210
- tags: [{ label: "待办", color: "red" }]
211
- }
212
- ]
213
- }
214
- ], Qn = () => {
215
- const [t, i] = g({
216
- configCount: null,
217
- projectCount: null,
218
- userCount: null,
219
- roleCount: null
220
- });
221
- return K(() => {
222
- let r = !0;
223
- const S = [
224
- Ce.get("/config/list", { params: { pageSize: 1 } }).then((l) => Te(l)).then((l) => r && i((y) => ({ ...y, configCount: l }))).catch(() => r && i((l) => ({ ...l, configCount: 0 }))),
225
- Ce.get("/project/user/list").then((l) => Te(l)).then((l) => r && i((y) => ({ ...y, projectCount: l }))).catch(() => r && i((l) => ({ ...l, projectCount: 0 }))),
226
- Ce.get("/ctc/ac/accounts", { params: { pageSize: 1 } }).then((l) => Te(l)).then((l) => r && i((y) => ({ ...y, userCount: l }))).catch(() => r && i((l) => ({ ...l, userCount: 0 }))),
227
- Ce.get("/ctc/authz/roles/list").then((l) => Te(l)).then((l) => r && i((y) => ({ ...y, roleCount: l }))).catch(() => r && i((l) => ({ ...l, roleCount: 0 })))
228
- ];
229
- return () => {
230
- r = !1, S.forEach((l) => {
231
- var y;
232
- return (y = l == null ? void 0 : l.catch) == null ? void 0 : y.call(l, () => {
233
- });
234
- });
235
- };
236
- }, []), /* @__PURE__ */ n("div", { children: [
237
- /* @__PURE__ */ e(
238
- me,
239
- {
240
- title: "统一管理平台",
241
- subtitle: "一站式企业级应用管理平台 · 整合配置 / 任务 / 工作流 / 用户 / 调度 等核心模块",
242
- breadcrumb: [{ label: "首页" }]
243
- }
244
- ),
245
- /* @__PURE__ */ n(Q, { gutter: [16, 16], children: [
246
- /* @__PURE__ */ e(M, { xs: 24, sm: 12, md: 12, lg: 6, children: /* @__PURE__ */ e(
247
- ke,
248
- {
249
- icon: /* @__PURE__ */ e(Ct, {}),
250
- label: "配置中心",
251
- value: t.configCount,
252
- suffix: "条",
253
- color: "violet",
254
- trend: 12.5,
255
- href: "/config/list"
256
- }
257
- ) }),
258
- /* @__PURE__ */ e(M, { xs: 24, sm: 12, md: 12, lg: 6, children: /* @__PURE__ */ e(
259
- ke,
260
- {
261
- icon: /* @__PURE__ */ e(Ae, {}),
262
- label: "我的项目",
263
- value: t.projectCount,
264
- suffix: "个",
265
- color: "blue",
266
- trend: 8.3,
267
- href: "/project/list"
268
- }
269
- ) }),
270
- /* @__PURE__ */ e(M, { xs: 24, sm: 12, md: 12, lg: 6, children: /* @__PURE__ */ e(
271
- ke,
272
- {
273
- icon: /* @__PURE__ */ e(ut, {}),
274
- label: "账号数",
275
- value: t.userCount,
276
- suffix: "人",
277
- color: "green",
278
- trend: -2.1,
279
- href: "/ctc/4a/account"
280
- }
281
- ) }),
282
- /* @__PURE__ */ e(M, { xs: 24, sm: 12, md: 12, lg: 6, children: /* @__PURE__ */ e(
283
- ke,
284
- {
285
- icon: /* @__PURE__ */ e($e, {}),
286
- label: "角色数",
287
- value: t.roleCount,
288
- suffix: "个",
289
- color: "orange",
290
- trend: 4.7,
291
- href: "/ctc/4a/role"
292
- }
293
- ) })
294
- ] }),
295
- dn.map((r) => /* @__PURE__ */ n("div", { style: { marginBottom: 32 }, children: [
296
- /* @__PURE__ */ e(
297
- qt,
298
- {
299
- color: r.color,
300
- title: r.title,
301
- subtitle: r.subtitle,
302
- moreHref: r.href
303
- }
304
- ),
305
- /* @__PURE__ */ e(Q, { gutter: [16, 16], children: r.items.map((S, l) => /* @__PURE__ */ e(
306
- M,
307
- {
308
- xs: 24,
309
- sm: 12,
310
- md: 12,
311
- lg: 6,
312
- xl: 6,
313
- xxl: 6,
314
- children: /* @__PURE__ */ e(
315
- jt,
316
- {
317
- title: S.title,
318
- description: S.description,
319
- icon: S.icon,
320
- color: S.color,
321
- tags: S.tags,
322
- meta: S.meta,
323
- href: r.href
324
- }
325
- )
326
- },
327
- l
328
- )) })
329
- ] }, r.key)),
330
- /* @__PURE__ */ e(
331
- Ft,
332
- {
333
- tag: "FOR ENGINEERS",
334
- title: "把 Z-One Company 接入你的工作流",
335
- description: "通过 OpenAPI、Webhook 与 SDK,把统一管理平台的能力嵌入到你的业务系统中。支持配置查询、任务触发、流程审批等 200+ 接口。",
336
- buttonText: "查看开发文档",
337
- buttonHref: "/z-tool/webide"
338
- }
339
- )
340
- ] });
341
- };
342
- let un = "/api";
343
- function bt() {
344
- return He.create({ baseURL: un, timeout: 15e3, withCredentials: !0 });
345
- }
346
- const Ie = bt(), hn = bt();
347
- hn.interceptors.request.use((t) => t);
348
- Ie.interceptors.request.use((t) => t);
349
- const Re = "/mock-platform", V = (t, i) => Ie.get(`${Re}${t}`, { params: i }).then((r) => r.data), F = (t, i, r) => Ie.post(`${Re}${t}`, i, { params: r }).then((S) => S.data), ve = (t, i, r) => Ie.put(`${Re}${t}`, i, { params: r }).then((S) => S.data), oe = (t, i) => Ie.delete(`${Re}${t}`, { params: i }).then((r) => r.data), q = {
350
- stats: () => V("/stats"),
351
- environments: {
352
- list: () => V("/environments/list"),
353
- create: (t) => F("/environments", t),
354
- update: (t, i) => ve("/environments", i, { envCode: t }),
355
- delete: (t) => oe("/environments", { envCode: t })
356
- },
357
- endpoints: {
358
- list: (t, i, r) => V("/endpoints/list", { envCode: t, scenarioCode: i, status: r }),
359
- get: (t) => V("/endpoints/byCode", { mockCode: t }),
360
- create: (t) => F("/endpoints", t),
361
- update: (t, i) => ve("/endpoints", i, { mockCode: t }),
362
- delete: (t) => oe("/endpoints", { mockCode: t }),
363
- toggle: (t, i) => F("/endpoints/toggle", null, { mockCode: t, status: i })
364
- },
365
- scenarios: {
366
- list: () => V("/scenarios/list"),
367
- get: (t) => V("/scenarios/byCode", { scenarioCode: t }),
368
- create: (t) => F("/scenarios", t),
369
- update: (t, i) => ve("/scenarios", i, { scenarioCode: t }),
370
- delete: (t) => oe("/scenarios", { scenarioCode: t }),
371
- reset: (t) => F("/scenarios/reset", null, { scenarioCode: t }),
372
- instances: (t) => V("/scenarios/instances", { scenarioCode: t })
373
- },
374
- cases: {
375
- list: () => V("/cases/list"),
376
- get: (t) => V("/cases/byCode", { caseCode: t }),
377
- create: (t) => F("/cases", t),
378
- update: (t, i) => ve("/cases", i, { caseCode: t }),
379
- delete: (t) => oe("/cases", { caseCode: t }),
380
- run: (t) => F("/cases/run", null, { caseCode: t }),
381
- runBatch: (t) => F("/cases/run-batch", { caseCodes: t })
382
- },
383
- recordings: {
384
- list: () => V("/recordings/list"),
385
- get: (t) => V("/recordings/byCode", { recordingCode: t }),
386
- requests: (t) => V("/recordings/requests", { recordingCode: t }),
387
- start: (t, i, r) => F("/recordings/start", {
388
- recordingCode: t,
389
- recordingName: i,
390
- targetUrl: r
391
- }),
392
- stop: (t) => F("/recordings/stop", null, { recordingCode: t }),
393
- export: (t, i) => F("/recordings/export", { recordingCode: t, projectCode: i }),
394
- import: (t, i) => F("/recordings/import", { recordingCode: t, projectCode: i }),
395
- playback: (t, i) => F("/recordings/playback", { recordingCode: t, targetUrl: i }),
396
- delete: (t) => oe("/recordings", { recordingCode: t })
397
- },
398
- requestLogs: {
399
- list: (t) => V("/request-logs/list", t),
400
- stats: () => V("/request-logs/stats"),
401
- clear: (t) => oe("/request-logs/clear", { limit: t })
402
- },
403
- curl: {
404
- parse: (t) => F("/curl/parse", { curlText: t }),
405
- run: (t) => F("/curl/run", { curlText: t }),
406
- importAsCase: (t) => F("/curl/import-as-case", t),
407
- importAsEndpoint: (t) => F("/curl/import-as-endpoint", t)
408
- },
409
- openapi: {
410
- parse: (t) => F("/openapi/parse", { content: t }),
411
- importBatch: (t) => F("/openapi/import-batch", t),
412
- sample: (t) => V("/openapi/sample", { format: t })
413
- }
414
- }, { Text: ae, Paragraph: pn } = le, Ze = { GET: "green", POST: "blue", PUT: "orange", DELETE: "red", PATCH: "purple" };
415
- function De({ activeEnvCode: t }) {
416
- const [i, r] = g([]), [S, l] = g(!1), [y, s] = g(null), [f, w] = g(!1), [T, A] = g(null);
417
- K(() => {
418
- m();
419
- }, [t]);
420
- const m = async () => {
421
- l(!0), s(null);
422
- try {
423
- const c = await q.endpoints.list(t);
424
- r(Array.isArray(c) ? c : []);
425
- } catch (c) {
426
- s((c == null ? void 0 : c.message) || "API unavailable"), r([]);
427
- } finally {
428
- l(!1);
429
- }
430
- }, h = (c) => `${window.location.origin}/api/mock/${c.env_code || t || "default"}${c.path || ""}`, d = [
431
- {
432
- title: "路径",
433
- dataIndex: "path",
434
- key: "path",
435
- width: 280,
436
- render: (c, v) => /* @__PURE__ */ n(R, { children: [
437
- /* @__PURE__ */ e(x, { color: Ze[v.method] || "default", children: v.method }),
438
- /* @__PURE__ */ e(ae, { code: !0, copyable: { text: c }, children: c })
439
- ] })
440
- },
441
- { title: "编码", dataIndex: "mock_code", key: "mock_code", width: 160 },
442
- {
443
- title: "优先级",
444
- dataIndex: "priority",
445
- key: "priority",
446
- width: 80,
447
- align: "center",
448
- render: (c) => /* @__PURE__ */ n(x, { color: "blue", children: [
449
- "P",
450
- c || 5
451
- ] })
452
- },
453
- { title: "状态码", dataIndex: "status_code", key: "status_code", width: 80, align: "center" },
454
- {
455
- title: "延迟",
456
- dataIndex: "delay_ms",
457
- key: "delay_ms",
458
- width: 80,
459
- align: "center",
460
- render: (c) => c > 0 ? /* @__PURE__ */ n(ae, { type: "warning", children: [
461
- c,
462
- "ms"
463
- ] }) : /* @__PURE__ */ e(ae, { type: "secondary", children: "-" })
464
- },
465
- {
466
- title: "故障",
467
- dataIndex: "fault_type",
468
- key: "fault_type",
469
- width: 110,
470
- render: (c) => c && c !== "NONE" ? /* @__PURE__ */ e(x, { color: "red", children: c }) : /* @__PURE__ */ e(ae, { type: "secondary", children: "-" })
471
- },
472
- {
473
- title: "场景",
474
- dataIndex: "scenario_code",
475
- key: "scenario_code",
476
- width: 130,
477
- render: (c) => c ? /* @__PURE__ */ e(x, { color: "purple", children: c }) : /* @__PURE__ */ e(ae, { type: "secondary", children: "-" })
478
- },
479
- {
480
- title: "命中",
481
- dataIndex: "hit_count",
482
- key: "hit_count",
483
- width: 80,
484
- align: "center",
485
- render: (c) => /* @__PURE__ */ e(ae, { strong: !0, children: c || 0 })
486
- },
487
- {
488
- title: "状态",
489
- dataIndex: "status",
490
- key: "status",
491
- width: 100,
492
- align: "center",
493
- render: (c) => c === 1 ? /* @__PURE__ */ e(x, { color: "green", children: "启用" }) : /* @__PURE__ */ e(x, { children: "禁用" })
494
- },
495
- {
496
- title: "操作",
497
- key: "action",
498
- width: 160,
499
- fixed: "right",
500
- render: (c, v) => /* @__PURE__ */ n(R, { size: "small", children: [
501
- /* @__PURE__ */ e(he, { title: "预览响应", children: /* @__PURE__ */ e(
502
- _,
503
- {
504
- size: "small",
505
- type: "link",
506
- icon: /* @__PURE__ */ e(Ee, {}),
507
- onClick: () => {
508
- A(v), w(!0);
509
- },
510
- children: "预览"
511
- }
512
- ) }),
513
- /* @__PURE__ */ e(he, { title: "复制URL", children: /* @__PURE__ */ e(
514
- _,
515
- {
516
- size: "small",
517
- type: "link",
518
- icon: /* @__PURE__ */ e(ht, {}),
519
- onClick: () => {
520
- navigator.clipboard.writeText(h(v)), b.success("已复制");
521
- }
522
- }
523
- ) })
524
- ] })
525
- }
526
- ];
527
- return /* @__PURE__ */ n("div", { children: [
528
- y && /* @__PURE__ */ e(
529
- J,
530
- {
531
- type: "warning",
532
- showIcon: !0,
533
- style: { marginBottom: 16 },
534
- title: "后端 API 暂未连接",
535
- description: y
536
- }
537
- ),
538
- /* @__PURE__ */ n(Q, { gutter: 16, style: { marginBottom: 16 }, children: [
539
- /* @__PURE__ */ e(M, { span: 6, children: /* @__PURE__ */ n(P, { children: [
540
- /* @__PURE__ */ e("strong", { children: "总端点" }),
541
- /* @__PURE__ */ e("div", { style: { fontSize: 22 }, children: i.length })
542
- ] }) }),
543
- /* @__PURE__ */ e(M, { span: 6, children: /* @__PURE__ */ n(P, { children: [
544
- /* @__PURE__ */ e("strong", { children: "已启用" }),
545
- /* @__PURE__ */ e("div", { style: { fontSize: 22, color: "#52c41a" }, children: i.filter((c) => c.status === 1).length })
546
- ] }) }),
547
- /* @__PURE__ */ e(M, { span: 6, children: /* @__PURE__ */ n(P, { children: [
548
- /* @__PURE__ */ e("strong", { children: "已禁用" }),
549
- /* @__PURE__ */ e("div", { style: { fontSize: 22, color: "#ff4d4f" }, children: i.filter((c) => c.status === 0).length })
550
- ] }) }),
551
- /* @__PURE__ */ e(M, { span: 6, children: /* @__PURE__ */ n(P, { children: [
552
- /* @__PURE__ */ e("strong", { children: "总命中" }),
553
- /* @__PURE__ */ e("div", { style: {
554
- fontSize: 22,
555
- color: "#1890ff"
556
- }, children: i.reduce((c, v) => c + (v.hit_count || 0), 0) })
557
- ] }) })
558
- ] }),
559
- /* @__PURE__ */ e(R, { style: { marginBottom: 16 }, children: /* @__PURE__ */ e(_, { icon: /* @__PURE__ */ e(ee, {}), onClick: m, children: "刷新" }) }),
560
- /* @__PURE__ */ e(
561
- H,
562
- {
563
- dataSource: i,
564
- columns: d,
565
- rowKey: "id",
566
- loading: S,
567
- pagination: { pageSize: 10 },
568
- scroll: { x: 1300 },
569
- size: "small"
570
- }
571
- ),
572
- /* @__PURE__ */ e(
573
- xe,
574
- {
575
- title: /* @__PURE__ */ n(R, { children: [
576
- /* @__PURE__ */ e(At, {}),
577
- "端点详情: ",
578
- T == null ? void 0 : T.mock_code
579
- ] }),
580
- open: f,
581
- onClose: () => w(!1),
582
- size: "large",
583
- children: T && /* @__PURE__ */ n("div", { children: [
584
- /* @__PURE__ */ n(z, { column: 2, size: "small", bordered: !0, style: { marginBottom: 16 }, children: [
585
- /* @__PURE__ */ e(z.Item, { label: "编码", children: T.mock_code }),
586
- /* @__PURE__ */ e(z.Item, { label: "名称", children: T.mock_name }),
587
- /* @__PURE__ */ e(z.Item, { label: "方法", children: /* @__PURE__ */ e(x, { color: Ze[T.method], children: T.method }) }),
588
- /* @__PURE__ */ e(z.Item, { label: "环境", children: T.env_code }),
589
- /* @__PURE__ */ e(z.Item, { label: "路径", span: 2, children: T.path }),
590
- /* @__PURE__ */ e(z.Item, { label: "状态码", children: T.status_code }),
591
- /* @__PURE__ */ n(z.Item, { label: "延迟", children: [
592
- T.delay_ms,
593
- "ms"
594
- ] }),
595
- /* @__PURE__ */ n(z.Item, { label: "优先级", children: [
596
- "P",
597
- T.priority
598
- ] }),
599
- /* @__PURE__ */ e(z.Item, { label: "命中", children: T.hit_count || 0 }),
600
- /* @__PURE__ */ e(z.Item, { label: "故障", children: T.fault_type && T.fault_type !== "NONE" ? /* @__PURE__ */ e(x, { color: "red", children: T.fault_type }) : /* @__PURE__ */ e(ae, { type: "secondary", children: "-" }) }),
601
- /* @__PURE__ */ e(z.Item, { label: "场景", children: T.scenario_code || "-" }),
602
- /* @__PURE__ */ e(z.Item, { label: "状态", span: 2, children: T.status === 1 ? /* @__PURE__ */ e(x, { color: "green", children: "启用" }) : /* @__PURE__ */ e(x, { children: "禁用" }) }),
603
- /* @__PURE__ */ e(z.Item, { label: "完整 URL", span: 2, children: /* @__PURE__ */ e(ae, { copyable: !0, children: h(T) }) })
604
- ] }),
605
- /* @__PURE__ */ e(pn, { strong: !0, children: "响应模板:" }),
606
- /* @__PURE__ */ e("pre", { style: {
607
- background: "#f5f5f5",
608
- padding: 12,
609
- borderRadius: 4,
610
- maxHeight: 350,
611
- overflow: "auto",
612
- fontSize: 13,
613
- fontFamily: "monospace",
614
- whiteSpace: "pre-wrap",
615
- wordBreak: "break-all"
616
- }, children: T.response_template })
617
- ] })
618
- }
619
- )
620
- ] });
621
- }
622
- const { Text: Oe } = le, mn = { MOCK: "green", REAL: "blue", MIXED: "orange" };
623
- function Be({ onEnvChange: t }) {
624
- const [i, r] = g([]), [S, l] = g(!1);
625
- K(() => {
626
- y();
627
- }, []);
628
- const y = async () => {
629
- l(!0);
630
- try {
631
- const f = await q.environments.list();
632
- r(Array.isArray(f) ? f : []);
633
- } catch (f) {
634
- b.warning("加载环境列表失败: " + (f == null ? void 0 : f.message));
635
- } finally {
636
- l(!1);
637
- }
638
- };
639
- return /* @__PURE__ */ n("div", { children: [
640
- /* @__PURE__ */ e(
641
- J,
642
- {
643
- type: "info",
644
- showIcon: !0,
645
- style: { marginBottom: 16 },
646
- message: "环境隔离 - 控制 Mock 与真实服务的切换",
647
- description: /* @__PURE__ */ n("div", { children: [
648
- /* @__PURE__ */ n("div", { children: [
649
- /* @__PURE__ */ e(x, { color: "green", children: "MOCK" }),
650
- " 完全拦截,仅返回 Mock 数据"
651
- ] }),
652
- /* @__PURE__ */ n("div", { children: [
653
- /* @__PURE__ */ e(x, { color: "blue", children: "REAL" }),
654
- " 全部代理到 base_url(适合压测、回归测试)"
655
- ] }),
656
- /* @__PURE__ */ n("div", { children: [
657
- /* @__PURE__ */ e(x, { color: "orange", children: "MIXED" }),
658
- " Mock 优先,未匹配时转发到 base_url(开发联调)"
659
- ] })
660
- ] })
661
- }
662
- ),
663
- /* @__PURE__ */ e(R, { style: { marginBottom: 16 }, children: /* @__PURE__ */ e(_, { icon: /* @__PURE__ */ e(ee, {}), onClick: y, children: "刷新" }) }),
664
- /* @__PURE__ */ e(
665
- H,
666
- {
667
- dataSource: i,
668
- columns: [
669
- {
670
- title: "环境编码",
671
- dataIndex: "env_code",
672
- key: "env_code",
673
- width: 140,
674
- render: (f) => /* @__PURE__ */ e(Oe, { code: !0, children: f })
675
- },
676
- { title: "环境名称", dataIndex: "env_name", key: "env_name", width: 160 },
677
- {
678
- title: "类型",
679
- dataIndex: "env_type",
680
- key: "env_type",
681
- width: 240,
682
- render: (f) => /* @__PURE__ */ e(x, { color: mn[f] || "default", children: f })
683
- },
684
- {
685
- title: "真实服务地址",
686
- dataIndex: "base_url",
687
- key: "base_url",
688
- render: (f) => f ? /* @__PURE__ */ e(Oe, { copyable: !0, children: f }) : /* @__PURE__ */ e(Oe, { type: "secondary", children: "-" })
689
- },
690
- {
691
- title: "默认",
692
- dataIndex: "is_default",
693
- key: "is_default",
694
- width: 90,
695
- align: "center",
696
- render: (f) => f === 1 ? /* @__PURE__ */ e(x, { color: "gold", children: "默认" }) : "-"
697
- },
698
- {
699
- title: "描述",
700
- dataIndex: "description",
701
- key: "description",
702
- width: 220,
703
- render: (f) => f || "-"
704
- },
705
- {
706
- title: "操作",
707
- key: "action",
708
- width: 120,
709
- render: (f, w) => /* @__PURE__ */ e(R, { size: "small", children: /* @__PURE__ */ e(
710
- _,
711
- {
712
- size: "small",
713
- type: "link",
714
- icon: /* @__PURE__ */ e(pt, {}),
715
- onClick: () => {
716
- t && t(w.env_code);
717
- },
718
- children: "切换"
719
- }
720
- ) })
721
- }
722
- ],
723
- rowKey: "id",
724
- loading: S,
725
- pagination: { pageSize: 10 },
726
- size: "small"
727
- }
728
- )
729
- ] });
730
- }
731
- const { Text: yn } = le;
732
- function gn() {
733
- const [t, i] = g([]), [r, S] = g(!1), [l, y] = g(!1), [s, f] = g(null);
734
- K(() => {
735
- w();
736
- }, []);
737
- const w = async () => {
738
- S(!0);
739
- try {
740
- const h = await q.scenarios.list();
741
- i(Array.isArray(h) ? h : []);
742
- } catch {
743
- b.warning("加载场景列表失败");
744
- } finally {
745
- S(!1);
746
- }
747
- }, T = async (h) => {
748
- try {
749
- await q.scenarios.reset(h), b.success("已重置所有实例状态");
750
- } catch {
751
- b.error("重置失败");
752
- }
753
- }, A = async (h) => {
754
- try {
755
- const d = await q.scenarios.instances(h);
756
- f({ code: h, list: d }), y(!0);
757
- } catch {
758
- b.error("加载失败");
759
- }
760
- };
761
- return /* @__PURE__ */ n("div", { children: [
762
- /* @__PURE__ */ e(
763
- J,
764
- {
765
- type: "info",
766
- showIcon: !0,
767
- style: { marginBottom: 16 },
768
- title: "场景状态机 (Scenario)",
769
- description: "用状态机驱动 Mock 集合,模拟完整业务流程(如:未登录→登录中→已登录→下单→已支付→完成)。实例通过 X-Session-Id 或 X-Trace-Id 区分,每个实例独立维护当前状态。"
770
- }
771
- ),
772
- /* @__PURE__ */ e(R, { style: { marginBottom: 16 }, children: /* @__PURE__ */ e(_, { icon: /* @__PURE__ */ e(ee, {}), onClick: w, children: "刷新" }) }),
773
- /* @__PURE__ */ e(
774
- H,
775
- {
776
- dataSource: t,
777
- columns: [
778
- {
779
- title: "场景编码",
780
- dataIndex: "scenario_code",
781
- key: "scenario_code",
782
- width: 160,
783
- render: (h) => /* @__PURE__ */ e(yn, { code: !0, children: h })
784
- },
785
- { title: "场景名称", dataIndex: "scenario_name", key: "scenario_name", width: 200 },
786
- {
787
- title: "初始状态",
788
- dataIndex: "initial_state",
789
- key: "initial_state",
790
- width: 140,
791
- render: (h) => /* @__PURE__ */ e(x, { color: "blue", children: h })
792
- },
793
- {
794
- title: "描述",
795
- dataIndex: "description",
796
- key: "description",
797
- width: 240,
798
- render: (h) => h || "-"
799
- },
800
- {
801
- title: "操作",
802
- key: "action",
803
- width: 200,
804
- fixed: "right",
805
- render: (h, d) => /* @__PURE__ */ n(R, { size: "small", children: [
806
- /* @__PURE__ */ e(
807
- _,
808
- {
809
- size: "small",
810
- type: "link",
811
- icon: /* @__PURE__ */ e(Et, {}),
812
- onClick: () => A(d.scenario_code),
813
- children: "实例"
814
- }
815
- ),
816
- /* @__PURE__ */ e(
817
- _,
818
- {
819
- size: "small",
820
- type: "link",
821
- icon: /* @__PURE__ */ e(Rt, {}),
822
- onClick: () => T(d.scenario_code),
823
- children: "重置"
824
- }
825
- )
826
- ] })
827
- }
828
- ],
829
- rowKey: "id",
830
- loading: r,
831
- pagination: { pageSize: 10 },
832
- scroll: { x: 1100 },
833
- size: "small"
834
- }
835
- ),
836
- /* @__PURE__ */ e(
837
- pe,
838
- {
839
- title: `场景实例: ${s == null ? void 0 : s.code}`,
840
- open: l,
841
- onCancel: () => y(!1),
842
- footer: /* @__PURE__ */ e(_, { onClick: () => y(!1), children: "关闭" }),
843
- size: "large",
844
- children: s && /* @__PURE__ */ e(
845
- H,
846
- {
847
- dataSource: Array.isArray(s.list) ? s.list : [],
848
- columns: [
849
- { title: "实例标识", dataIndex: "instance_key", key: "instance_key" },
850
- {
851
- title: "当前状态",
852
- dataIndex: "current_state",
853
- key: "current_state",
854
- render: (h) => /* @__PURE__ */ e(x, { color: "blue", children: h })
855
- },
856
- { title: "最后变更", dataIndex: "update_time", key: "update_time" }
857
- ],
858
- rowKey: (h, d) => h.instance_key || d,
859
- pagination: !1,
860
- size: "small"
861
- }
862
- )
863
- }
864
- )
865
- ] });
866
- }
867
- const { Text: ie } = le, Pe = { PASS: "green", FAIL: "red", SKIP: "default" }, fn = { P0: "red", P1: "orange", P2: "blue", P3: "default" };
868
- function bn() {
869
- const [t, i] = g([]), [r, S] = g(!1), [l, y] = g([]), [s, f] = g(!1), [w, T] = g(null), [A, m] = g(null), [h, d] = g(!1);
870
- K(() => {
871
- c();
872
- }, []);
873
- const c = async () => {
874
- S(!0);
875
- try {
876
- const u = await q.cases.list();
877
- i(Array.isArray(u) ? u : []);
878
- } catch {
879
- b.warning("加载用例列表失败");
880
- } finally {
881
- S(!1);
882
- }
883
- }, v = async (u) => {
884
- try {
885
- const a = await q.cases.run(u.case_code);
886
- T(a), f(!0), (a == null ? void 0 : a.status) === "PASS" ? b.success("用例通过") : b.error("用例失败: " + ((a == null ? void 0 : a.error) || (a == null ? void 0 : a.actualStatus))), c();
887
- } catch (a) {
888
- b.error("执行失败: " + (a == null ? void 0 : a.message));
889
- }
890
- }, L = async () => {
891
- if (l.length === 0) {
892
- b.warning("请先选择用例");
893
- return;
894
- }
895
- try {
896
- const u = await q.cases.runBatch(l);
897
- m(u), d(!0), b.success(`批量执行完成: ${u == null ? void 0 : u.pass} 通过, ${u == null ? void 0 : u.fail} 失败`), c();
898
- } catch {
899
- b.error("批量执行失败");
900
- }
901
- }, C = [
902
- {
903
- title: "用例编码",
904
- dataIndex: "case_code",
905
- key: "case_code",
906
- width: 180,
907
- render: (u) => /* @__PURE__ */ e(ie, { code: !0, children: u })
908
- },
909
- { title: "名称", dataIndex: "case_name", key: "case_name", width: 220 },
910
- {
911
- title: "分组",
912
- dataIndex: "case_group",
913
- key: "case_group",
914
- width: 130,
915
- render: (u) => u ? /* @__PURE__ */ e(x, { children: u }) : "-"
916
- },
917
- {
918
- title: "方法",
919
- dataIndex: "request_method",
920
- key: "request_method",
921
- width: 80,
922
- render: (u) => /* @__PURE__ */ e(x, { color: "blue", children: u })
923
- },
924
- {
925
- title: "路径",
926
- dataIndex: "request_url",
927
- key: "request_url",
928
- ellipsis: !0,
929
- render: (u) => /* @__PURE__ */ e(ie, { code: !0, children: u })
930
- },
931
- {
932
- title: "优先级",
933
- dataIndex: "priority",
934
- key: "priority",
935
- width: 80,
936
- align: "center",
937
- render: (u) => /* @__PURE__ */ e(x, { color: fn[u], children: u || "P1" })
938
- },
939
- {
940
- title: "上次结果",
941
- dataIndex: "last_run_result",
942
- key: "last_run_result",
943
- width: 100,
944
- align: "center",
945
- render: (u) => u ? /* @__PURE__ */ e(x, { color: Pe[u], children: u }) : "-"
946
- },
947
- {
948
- title: "统计",
949
- key: "stats",
950
- width: 130,
951
- align: "center",
952
- render: (u, a) => /* @__PURE__ */ n(R, { size: "small", children: [
953
- /* @__PURE__ */ e(ie, { type: "success", children: a.pass_count || 0 }),
954
- "/",
955
- /* @__PURE__ */ e(ie, { type: "danger", children: a.fail_count || 0 }),
956
- /* @__PURE__ */ n(ie, { type: "secondary", children: [
957
- "(",
958
- a.run_count || 0,
959
- ")"
960
- ] })
961
- ] })
962
- },
963
- {
964
- title: "操作",
965
- key: "action",
966
- width: 120,
967
- fixed: "right",
968
- render: (u, a) => /* @__PURE__ */ e(R, { size: "small", children: /* @__PURE__ */ e(
969
- _,
970
- {
971
- size: "small",
972
- type: "link",
973
- icon: /* @__PURE__ */ e(Ee, {}),
974
- onClick: () => v(a),
975
- children: "运行"
976
- }
977
- ) })
978
- }
979
- ];
980
- return /* @__PURE__ */ n("div", { children: [
981
- /* @__PURE__ */ e(
982
- J,
983
- {
984
- type: "info",
985
- showIcon: !0,
986
- style: { marginBottom: 16 },
987
- title: "测试用例库",
988
- description: "对 Mock 接口进行断言验证。支持 7 种断言类型:STATUS / HEADER / BODY / JSON_PATH / REGEX / SCHEMA / RESPONSE_TIME。支持单条运行与批量运行,自动统计通过/失败次数。"
989
- }
990
- ),
991
- /* @__PURE__ */ n(R, { style: { marginBottom: 16 }, children: [
992
- /* @__PURE__ */ e(_, { icon: /* @__PURE__ */ e(ee, {}), onClick: c, children: "刷新" }),
993
- /* @__PURE__ */ n(
994
- _,
995
- {
996
- type: "primary",
997
- icon: /* @__PURE__ */ e(Ee, {}),
998
- onClick: L,
999
- disabled: l.length === 0,
1000
- children: [
1001
- "批量运行 (",
1002
- l.length,
1003
- ")"
1004
- ]
1005
- }
1006
- )
1007
- ] }),
1008
- /* @__PURE__ */ e(
1009
- H,
1010
- {
1011
- dataSource: t,
1012
- columns: C,
1013
- rowKey: "id",
1014
- loading: r,
1015
- rowSelection: {
1016
- selectedRowKeys: l,
1017
- // 批量执行收的是 **case_code 列表**(后端按 case_code 查行),
1018
- // 原来这里存的是 rowKey(=id) ⇒ 批量执行永远查不到行。
1019
- onChange: (u, a) => y(a.map((k) => k.case_code))
1020
- },
1021
- pagination: { pageSize: 10 },
1022
- scroll: { x: 1300 },
1023
- size: "small"
1024
- }
1025
- ),
1026
- /* @__PURE__ */ e(
1027
- xe,
1028
- {
1029
- title: /* @__PURE__ */ n(R, { children: [
1030
- /* @__PURE__ */ e(zt, {}),
1031
- "用例执行结果"
1032
- ] }),
1033
- open: s,
1034
- onClose: () => f(!1),
1035
- size: "large",
1036
- children: w && /* @__PURE__ */ n("div", { children: [
1037
- /* @__PURE__ */ n(Q, { gutter: 16, style: { marginBottom: 16 }, children: [
1038
- /* @__PURE__ */ e(M, { span: 8, children: /* @__PURE__ */ e(P, { children: /* @__PURE__ */ e(
1039
- U,
1040
- {
1041
- title: "结果",
1042
- value: w.status,
1043
- styles: { content: { color: Pe[w.status] === "green" ? "#52c41a" : "#ff4d4f" } }
1044
- }
1045
- ) }) }),
1046
- /* @__PURE__ */ e(M, { span: 8, children: /* @__PURE__ */ e(P, { children: /* @__PURE__ */ e(U, { title: "实际状态码", value: w.actualStatus || "-" }) }) }),
1047
- /* @__PURE__ */ e(M, { span: 8, children: /* @__PURE__ */ e(P, { children: /* @__PURE__ */ e(U, { title: "耗时(ms)", value: w.durationMs || 0 }) }) })
1048
- ] }),
1049
- /* @__PURE__ */ n(z, { column: 1, size: "small", bordered: !0, style: { marginBottom: 16 }, children: [
1050
- /* @__PURE__ */ e(z.Item, { label: "用例编码", children: w.caseCode }),
1051
- /* @__PURE__ */ e(z.Item, { label: "用例名称", children: w.caseName }),
1052
- /* @__PURE__ */ e(z.Item, { label: "错误信息", children: w.error || "-" })
1053
- ] }),
1054
- w.assertionResults && /* @__PURE__ */ n(Me, { children: [
1055
- /* @__PURE__ */ e(ie, { strong: !0, children: "断言详情:" }),
1056
- /* @__PURE__ */ e(
1057
- H,
1058
- {
1059
- style: { marginTop: 8 },
1060
- dataSource: w.assertionResults,
1061
- columns: [
1062
- { title: "断言类型", dataIndex: "type", key: "type", width: 110 },
1063
- { title: "表达式", dataIndex: "expression", key: "expression" },
1064
- { title: "期望值", dataIndex: "expected", key: "expected" },
1065
- { title: "实际值", dataIndex: "actual", key: "actual" },
1066
- {
1067
- title: "结果",
1068
- dataIndex: "passed",
1069
- key: "passed",
1070
- width: 80,
1071
- render: (u) => u ? /* @__PURE__ */ e(x, { color: "green", children: "PASS" }) : /* @__PURE__ */ e(x, { color: "red", children: "FAIL" })
1072
- }
1073
- ],
1074
- pagination: !1,
1075
- size: "small"
1076
- }
1077
- )
1078
- ] }),
1079
- /* @__PURE__ */ e(ie, { strong: !0, style: { marginTop: 16, display: "block" }, children: "响应体:" }),
1080
- /* @__PURE__ */ e("pre", { style: {
1081
- background: "#f5f5f5",
1082
- padding: 12,
1083
- borderRadius: 4,
1084
- maxHeight: 250,
1085
- overflow: "auto",
1086
- fontSize: 12,
1087
- fontFamily: "monospace",
1088
- whiteSpace: "pre-wrap",
1089
- wordBreak: "break-all"
1090
- }, children: w.responseBody || "(empty)" })
1091
- ] })
1092
- }
1093
- ),
1094
- /* @__PURE__ */ e(
1095
- pe,
1096
- {
1097
- title: `批量执行结果 (${(A == null ? void 0 : A.total) || 0} 条)`,
1098
- open: h,
1099
- onCancel: () => d(!1),
1100
- footer: /* @__PURE__ */ e(_, { onClick: () => d(!1), children: "关闭" }),
1101
- size: "large",
1102
- children: A && /* @__PURE__ */ n(Me, { children: [
1103
- /* @__PURE__ */ n(Q, { gutter: 16, style: { marginBottom: 16 }, children: [
1104
- /* @__PURE__ */ e(M, { span: 6, children: /* @__PURE__ */ e(P, { children: /* @__PURE__ */ e(U, { title: "总数", value: A.total }) }) }),
1105
- /* @__PURE__ */ e(M, { span: 6, children: /* @__PURE__ */ e(P, { children: /* @__PURE__ */ e(
1106
- U,
1107
- {
1108
- title: "通过",
1109
- value: A.pass,
1110
- styles: { content: { color: "#52c41a" } }
1111
- }
1112
- ) }) }),
1113
- /* @__PURE__ */ e(M, { span: 6, children: /* @__PURE__ */ e(P, { children: /* @__PURE__ */ e(
1114
- U,
1115
- {
1116
- title: "失败",
1117
- value: A.fail,
1118
- styles: { content: { color: "#ff4d4f" } }
1119
- }
1120
- ) }) }),
1121
- /* @__PURE__ */ e(M, { span: 6, children: /* @__PURE__ */ e(P, { children: /* @__PURE__ */ e(
1122
- U,
1123
- {
1124
- title: "通过率",
1125
- value: `${A.total > 0 ? Math.round(A.pass / A.total * 100) : 0}%`
1126
- }
1127
- ) }) })
1128
- ] }),
1129
- /* @__PURE__ */ e(
1130
- H,
1131
- {
1132
- dataSource: A.results || [],
1133
- columns: [
1134
- { title: "编码", dataIndex: "caseCode", key: "caseCode", width: 180 },
1135
- { title: "名称", dataIndex: "caseName", key: "caseName" },
1136
- {
1137
- title: "结果",
1138
- dataIndex: "status",
1139
- key: "status",
1140
- width: 80,
1141
- render: (u) => /* @__PURE__ */ e(x, { color: Pe[u], children: u })
1142
- },
1143
- { title: "耗时", dataIndex: "durationMs", key: "durationMs", width: 80, align: "center" },
1144
- { title: "错误", dataIndex: "error", key: "error", ellipsis: !0 }
1145
- ],
1146
- pagination: !1,
1147
- size: "small",
1148
- rowKey: "caseCode"
1149
- }
1150
- )
1151
- ] })
1152
- }
1153
- )
1154
- ] });
1155
- }
1156
- const { Text: ce } = le, Ye = {
1157
- IDLE: "default",
1158
- RECORDING: "red",
1159
- STOPPED: "green",
1160
- EXPIRED: "gray"
1161
- };
1162
- function xn() {
1163
- const [t, i] = g([]), [r, S] = g(!1), [l, y] = g(!1), [s, f] = g(null), [w, T] = g([]);
1164
- K(() => {
1165
- A();
1166
- }, []);
1167
- const A = async () => {
1168
- S(!0);
1169
- try {
1170
- const d = await q.recordings.list();
1171
- i(Array.isArray(d) ? d : []);
1172
- } catch {
1173
- b.warning("加载录制列表失败");
1174
- } finally {
1175
- S(!1);
1176
- }
1177
- }, m = async (d) => {
1178
- try {
1179
- const c = await q.recordings.requests(d.recording_code);
1180
- f(d), T(Array.isArray(c) ? c : []), y(!0);
1181
- } catch {
1182
- b.error("加载失败");
1183
- }
1184
- };
1185
- return /* @__PURE__ */ n("div", { children: [
1186
- /* @__PURE__ */ e(
1187
- J,
1188
- {
1189
- type: "info",
1190
- showIcon: !0,
1191
- style: { marginBottom: 16 },
1192
- message: "流量录制与回放",
1193
- description: /* @__PURE__ */ n("div", { children: [
1194
- /* @__PURE__ */ n("div", { children: [
1195
- "• 开启录制后,所有 ",
1196
- /* @__PURE__ */ e(ce, { code: !0, children: "/api/mock/{envCode}/**" }),
1197
- " 请求会被捕获到数据库"
1198
- ] }),
1199
- /* @__PURE__ */ e("div", { children: "• 停止录制后,可一键转为 Mock endpoints(用于离线测试)" }),
1200
- /* @__PURE__ */ e("div", { children: "• 支持回放录制到目标服务(验证录制有效 / 跨环境验证)" })
1201
- ] })
1202
- }
1203
- ),
1204
- /* @__PURE__ */ e(R, { style: { marginBottom: 16 }, children: /* @__PURE__ */ e(_, { icon: /* @__PURE__ */ e(ee, {}), onClick: A, children: "刷新" }) }),
1205
- /* @__PURE__ */ e(
1206
- H,
1207
- {
1208
- dataSource: t,
1209
- columns: [
1210
- {
1211
- title: "编码",
1212
- dataIndex: "recording_code",
1213
- key: "recording_code",
1214
- width: 180,
1215
- render: (d) => /* @__PURE__ */ e(ce, { code: !0, children: d })
1216
- },
1217
- { title: "名称", dataIndex: "recording_name", key: "recording_name", width: 200 },
1218
- {
1219
- title: "状态",
1220
- dataIndex: "record_status",
1221
- key: "record_status",
1222
- width: 110,
1223
- render: (d) => /* @__PURE__ */ e(x, { color: Ye[d], children: d })
1224
- },
1225
- {
1226
- title: "请求数",
1227
- dataIndex: "total_requests",
1228
- key: "total_requests",
1229
- width: 90,
1230
- align: "center"
1231
- },
1232
- {
1233
- title: "目标 URL",
1234
- dataIndex: "target_url",
1235
- key: "target_url",
1236
- ellipsis: !0,
1237
- render: (d) => d ? /* @__PURE__ */ e(ce, { copyable: { text: d }, children: d }) : "-"
1238
- },
1239
- { title: "开始时间", dataIndex: "start_time", key: "start_time", width: 170 },
1240
- { title: "结束时间", dataIndex: "end_time", key: "end_time", width: 170 },
1241
- {
1242
- title: "操作",
1243
- key: "action",
1244
- width: 120,
1245
- fixed: "right",
1246
- render: (d, c) => /* @__PURE__ */ e(R, { size: "small", children: /* @__PURE__ */ e(
1247
- _,
1248
- {
1249
- size: "small",
1250
- type: "link",
1251
- icon: /* @__PURE__ */ e(Ve, {}),
1252
- onClick: () => m(c),
1253
- children: "详情"
1254
- }
1255
- ) })
1256
- }
1257
- ],
1258
- rowKey: "id",
1259
- loading: r,
1260
- pagination: { pageSize: 10 },
1261
- scroll: { x: 1300 },
1262
- size: "small"
1263
- }
1264
- ),
1265
- /* @__PURE__ */ e(
1266
- xe,
1267
- {
1268
- title: /* @__PURE__ */ n(R, { children: [
1269
- /* @__PURE__ */ e(Ve, {}),
1270
- "录制详情: ",
1271
- s == null ? void 0 : s.recording_code
1272
- ] }),
1273
- open: l,
1274
- onClose: () => y(!1),
1275
- size: "large",
1276
- children: s && /* @__PURE__ */ n("div", { children: [
1277
- /* @__PURE__ */ n(z, { column: 2, size: "small", bordered: !0, style: { marginBottom: 16 }, children: [
1278
- /* @__PURE__ */ e(z.Item, { label: "编码", children: s.recording_code }),
1279
- /* @__PURE__ */ e(z.Item, { label: "名称", children: s.recording_name }),
1280
- /* @__PURE__ */ e(z.Item, { label: "状态", children: /* @__PURE__ */ e(x, { color: Ye[s.record_status], children: s.record_status }) }),
1281
- /* @__PURE__ */ e(z.Item, { label: "请求数", children: s.total_requests }),
1282
- /* @__PURE__ */ e(z.Item, { label: "目标 URL", span: 2, children: /* @__PURE__ */ e(ce, { copyable: !0, children: s.target_url }) }),
1283
- /* @__PURE__ */ e(z.Item, { label: "开始", children: s.start_time }),
1284
- /* @__PURE__ */ e(z.Item, { label: "结束", children: s.end_time || "(录制中)" })
1285
- ] }),
1286
- /* @__PURE__ */ n(ce, { strong: !0, children: [
1287
- "请求列表 (共 ",
1288
- w.length,
1289
- " 条):"
1290
- ] }),
1291
- /* @__PURE__ */ e(
1292
- H,
1293
- {
1294
- style: { marginTop: 8 },
1295
- dataSource: w,
1296
- columns: [
1297
- { title: "#", dataIndex: "sequence", key: "sequence", width: 50 },
1298
- {
1299
- title: "方法",
1300
- dataIndex: "request_method",
1301
- key: "request_method",
1302
- width: 80,
1303
- render: (d) => /* @__PURE__ */ e(x, { color: "blue", children: d })
1304
- },
1305
- {
1306
- title: "URL",
1307
- dataIndex: "request_url",
1308
- key: "request_url",
1309
- ellipsis: !0,
1310
- render: (d) => /* @__PURE__ */ e(ce, { code: !0, children: d })
1311
- },
1312
- {
1313
- title: "响应",
1314
- dataIndex: "response_status",
1315
- key: "response_status",
1316
- width: 80,
1317
- render: (d) => /* @__PURE__ */ e(x, { color: d >= 400 ? "red" : "green", children: d })
1318
- },
1319
- {
1320
- title: "耗时",
1321
- dataIndex: "response_time",
1322
- key: "response_time",
1323
- width: 80,
1324
- render: (d) => `${d || 0}ms`
1325
- }
1326
- ],
1327
- pagination: { pageSize: 10 },
1328
- size: "small",
1329
- rowKey: "id"
1330
- }
1331
- )
1332
- ] })
1333
- }
1334
- )
1335
- ] });
1336
- }
1337
- const { Text: de } = le, wn = { MOCK: "green", PROXY: "blue", 404: "red", 502: "orange" };
1338
- function In() {
1339
- const [t, i] = g([]), [r, S] = g(null), [l, y] = g(!1), [s, f] = g(null), [w, T] = g(!1), [A, m] = g(""), [h, d] = g();
1340
- K(() => {
1341
- c();
1342
- }, []);
1343
- const c = async () => {
1344
- y(!0);
1345
- try {
1346
- const [C, u] = await Promise.all([
1347
- q.requestLogs.list({
1348
- path: A || void 0,
1349
- matched: h,
1350
- limit: 100
1351
- }),
1352
- q.requestLogs.stats().catch(() => null)
1353
- ]);
1354
- i(Array.isArray(C) ? C : []), S(u);
1355
- } catch {
1356
- b.warning("加载失败");
1357
- } finally {
1358
- y(!1);
1359
- }
1360
- }, v = (C) => {
1361
- f(C), T(!0);
1362
- }, L = [
1363
- {
1364
- title: "时间",
1365
- dataIndex: "create_time",
1366
- key: "create_time",
1367
- width: 170,
1368
- render: (C) => C ? new Date(C).toLocaleString() : "-"
1369
- },
1370
- {
1371
- title: "环境",
1372
- dataIndex: "env_code",
1373
- key: "env_code",
1374
- width: 100,
1375
- render: (C) => /* @__PURE__ */ e(x, { children: C })
1376
- },
1377
- {
1378
- title: "方法",
1379
- dataIndex: "request_method",
1380
- key: "request_method",
1381
- width: 80,
1382
- render: (C) => /* @__PURE__ */ e(x, { color: "blue", children: C })
1383
- },
1384
- {
1385
- title: "路径",
1386
- dataIndex: "request_path",
1387
- key: "request_path",
1388
- ellipsis: !0,
1389
- render: (C) => /* @__PURE__ */ e(de, { code: !0, children: C })
1390
- },
1391
- {
1392
- title: "状态",
1393
- dataIndex: "response_status",
1394
- key: "response_status",
1395
- width: 90,
1396
- align: "center",
1397
- render: (C) => C ? /* @__PURE__ */ e(x, { color: C >= 400 ? "red" : "green", children: C }) : "-"
1398
- },
1399
- {
1400
- title: "匹配",
1401
- dataIndex: "matched",
1402
- key: "matched",
1403
- width: 90,
1404
- align: "center",
1405
- render: (C) => C === 1 ? /* @__PURE__ */ e(x, { color: "green", children: "命中" }) : /* @__PURE__ */ e(x, { color: "red", children: "未匹配" })
1406
- },
1407
- {
1408
- title: "回退",
1409
- dataIndex: "fallback_type",
1410
- key: "fallback_type",
1411
- width: 100,
1412
- render: (C) => C ? /* @__PURE__ */ e(x, { color: wn[C], children: C }) : "-"
1413
- },
1414
- {
1415
- title: "耗时",
1416
- dataIndex: "duration_ms",
1417
- key: "duration_ms",
1418
- width: 80,
1419
- align: "center",
1420
- render: (C) => `${C || 0}ms`
1421
- },
1422
- {
1423
- title: "Mock",
1424
- dataIndex: "mock_code",
1425
- key: "mock_code",
1426
- width: 160,
1427
- ellipsis: !0,
1428
- render: (C) => C ? /* @__PURE__ */ e(de, { code: !0, children: C }) : "-"
1429
- },
1430
- {
1431
- title: "操作",
1432
- key: "action",
1433
- width: 80,
1434
- render: (C, u) => /* @__PURE__ */ e(
1435
- _,
1436
- {
1437
- size: "small",
1438
- type: "link",
1439
- icon: /* @__PURE__ */ e(Ot, {}),
1440
- onClick: () => v(u),
1441
- children: "详情"
1442
- }
1443
- )
1444
- }
1445
- ];
1446
- return /* @__PURE__ */ n("div", { children: [
1447
- /* @__PURE__ */ e(
1448
- J,
1449
- {
1450
- type: "info",
1451
- showIcon: !0,
1452
- style: { marginBottom: 16 },
1453
- title: "Mock 请求日志 - 排查未匹配请求",
1454
- description: "每一次请求都会留痕。包括请求/响应体、是否匹配 Mock、回退类型、耗时、场景状态等。便于排查“为什么这个请求没有 Mock 命中”问题。"
1455
- }
1456
- ),
1457
- r && /* @__PURE__ */ n(Q, { gutter: 16, style: { marginBottom: 16 }, children: [
1458
- /* @__PURE__ */ e(M, { span: 6, children: /* @__PURE__ */ e(P, { children: /* @__PURE__ */ e(U, { title: "总请求数", value: r.total || 0 }) }) }),
1459
- /* @__PURE__ */ e(M, { span: 6, children: /* @__PURE__ */ e(P, { children: /* @__PURE__ */ e(
1460
- U,
1461
- {
1462
- title: "Mock 命中",
1463
- value: r.matched || 0,
1464
- styles: { content: { color: "#52c41a" } }
1465
- }
1466
- ) }) }),
1467
- /* @__PURE__ */ e(M, { span: 6, children: /* @__PURE__ */ e(P, { children: /* @__PURE__ */ e(
1468
- U,
1469
- {
1470
- title: "未匹配",
1471
- value: r.unmatched || 0,
1472
- styles: { content: { color: "#ff4d4f" } }
1473
- }
1474
- ) }) }),
1475
- /* @__PURE__ */ e(M, { span: 6, children: /* @__PURE__ */ e(P, { children: /* @__PURE__ */ e(
1476
- U,
1477
- {
1478
- title: "命中率",
1479
- value: `${r.total > 0 ? Math.round(r.matched / r.total * 100) : 0}%`
1480
- }
1481
- ) }) })
1482
- ] }),
1483
- /* @__PURE__ */ n(R, { style: { marginBottom: 16 }, children: [
1484
- /* @__PURE__ */ e(
1485
- B,
1486
- {
1487
- placeholder: "搜索路径",
1488
- prefix: /* @__PURE__ */ e(mt, {}),
1489
- allowClear: !0,
1490
- style: { width: 240 },
1491
- value: A,
1492
- onChange: (C) => m(C.target.value),
1493
- onPressEnter: c
1494
- }
1495
- ),
1496
- /* @__PURE__ */ e(
1497
- W,
1498
- {
1499
- placeholder: "匹配状态",
1500
- allowClear: !0,
1501
- style: { width: 140 },
1502
- value: h,
1503
- onChange: d,
1504
- options: [
1505
- { value: 1, label: "已命中" },
1506
- { value: 0, label: "未匹配" }
1507
- ]
1508
- }
1509
- ),
1510
- /* @__PURE__ */ e(_, { icon: /* @__PURE__ */ e(ee, {}), onClick: c, children: "查询" })
1511
- ] }),
1512
- /* @__PURE__ */ e(
1513
- H,
1514
- {
1515
- dataSource: t,
1516
- columns: L,
1517
- rowKey: "id",
1518
- loading: l,
1519
- pagination: { pageSize: 20 },
1520
- scroll: { x: 1300 },
1521
- size: "small"
1522
- }
1523
- ),
1524
- /* @__PURE__ */ e(
1525
- xe,
1526
- {
1527
- title: "请求详情",
1528
- open: w,
1529
- onClose: () => T(!1),
1530
- size: "large",
1531
- children: s && /* @__PURE__ */ n("div", { children: [
1532
- /* @__PURE__ */ n(z, { column: 2, size: "small", bordered: !0, style: { marginBottom: 16 }, children: [
1533
- /* @__PURE__ */ e(z.Item, { label: "环境", children: s.env_code }),
1534
- /* @__PURE__ */ e(z.Item, { label: "方法", children: /* @__PURE__ */ e(
1535
- x,
1536
- {
1537
- color: "blue",
1538
- children: s.request_method
1539
- }
1540
- ) }),
1541
- /* @__PURE__ */ e(z.Item, { label: "路径", span: 2, children: /* @__PURE__ */ e(
1542
- de,
1543
- {
1544
- code: !0,
1545
- children: s.request_path
1546
- }
1547
- ) }),
1548
- /* @__PURE__ */ e(z.Item, { label: "状态码", children: /* @__PURE__ */ e(
1549
- x,
1550
- {
1551
- color: s.response_status >= 400 ? "red" : "green",
1552
- children: s.response_status
1553
- }
1554
- ) }),
1555
- /* @__PURE__ */ n(z.Item, { label: "耗时", children: [
1556
- s.duration_ms,
1557
- "ms"
1558
- ] }),
1559
- /* @__PURE__ */ e(z.Item, { label: "匹配", children: s.matched === 1 ? /* @__PURE__ */ e(x, { color: "green", children: "命中" }) : /* @__PURE__ */ e(x, { color: "red", children: "未匹配" }) }),
1560
- /* @__PURE__ */ e(z.Item, { label: "回退", children: s.fallback_type || "-" }),
1561
- /* @__PURE__ */ e(z.Item, { label: "Mock", span: 2, children: s.mock_code || "-" }),
1562
- /* @__PURE__ */ e(
1563
- z.Item,
1564
- {
1565
- label: "场景状态",
1566
- span: 2,
1567
- children: s.scenario_state || "-"
1568
- }
1569
- ),
1570
- /* @__PURE__ */ e(z.Item, { label: "客户端 IP", children: s.client_ip || "-" }),
1571
- /* @__PURE__ */ e(z.Item, { label: "User-Agent", ellipsis: !0, children: s.user_agent || "-" }),
1572
- /* @__PURE__ */ e(z.Item, { label: "时间", span: 2, children: s.create_time ? new Date(s.create_time).toLocaleString() : "-" })
1573
- ] }),
1574
- /* @__PURE__ */ e(de, { strong: !0, children: "请求头:" }),
1575
- /* @__PURE__ */ e("pre", { style: {
1576
- background: "#f5f5f5",
1577
- padding: 12,
1578
- borderRadius: 4,
1579
- maxHeight: 150,
1580
- overflow: "auto",
1581
- fontSize: 12,
1582
- fontFamily: "monospace",
1583
- whiteSpace: "pre-wrap"
1584
- }, children: s.request_headers || "(无)" }),
1585
- /* @__PURE__ */ e(de, { strong: !0, style: { marginTop: 12, display: "block" }, children: "请求体:" }),
1586
- /* @__PURE__ */ e("pre", { style: {
1587
- background: "#f5f5f5",
1588
- padding: 12,
1589
- borderRadius: 4,
1590
- maxHeight: 200,
1591
- overflow: "auto",
1592
- fontSize: 12,
1593
- fontFamily: "monospace",
1594
- whiteSpace: "pre-wrap",
1595
- wordBreak: "break-all"
1596
- }, children: s.request_body || "(无)" }),
1597
- /* @__PURE__ */ e(de, { strong: !0, style: { marginTop: 12, display: "block" }, children: "响应体:" }),
1598
- /* @__PURE__ */ e("pre", { style: {
1599
- background: "#f5f5f5",
1600
- padding: 12,
1601
- borderRadius: 4,
1602
- maxHeight: 300,
1603
- overflow: "auto",
1604
- fontSize: 12,
1605
- fontFamily: "monospace",
1606
- whiteSpace: "pre-wrap",
1607
- wordBreak: "break-all"
1608
- }, children: s.response_body || "(无)" })
1609
- ] })
1610
- }
1611
- )
1612
- ] });
1613
- }
1614
- const { Text: te } = le, Qe = [
1615
- { key: "endpoints", label: "Mock 端点", component: De },
1616
- { key: "environments", label: "环境 (MOCK/REAL/MIXED)", component: Be },
1617
- { key: "scenarios", label: "场景状态机", component: gn },
1618
- { key: "cases", label: "测试用例", component: bn },
1619
- { key: "recordings", label: "录制回放", component: xn },
1620
- { key: "request-logs", label: "请求日志", component: In }
1621
- ];
1622
- function Sn() {
1623
- var A;
1624
- const [t, i] = g("endpoints"), [r, S] = g([]), [l, y] = g("default"), [s, f] = g(null);
1625
- K(() => {
1626
- w(), T();
1627
- }, []);
1628
- const w = async () => {
1629
- try {
1630
- const m = await q.environments.list(), h = Array.isArray(m) ? m : [];
1631
- if (S(h), h.length > 0 && !h.find((d) => d.env_code === l)) {
1632
- const d = h.find((c) => c.is_default === 1) || h[0];
1633
- y(d.env_code);
1634
- }
1635
- } catch {
1636
- }
1637
- }, T = async () => {
1638
- try {
1639
- const m = await q.stats();
1640
- f(m);
1641
- } catch {
1642
- }
1643
- };
1644
- return (A = Qe.find((m) => m.key === t)) == null || A.component, /* @__PURE__ */ n("div", { children: [
1645
- /* @__PURE__ */ e(
1646
- me,
1647
- {
1648
- title: "Mock 平台",
1649
- subtitle: "WireMock 级 · Mock 端点管理、环境隔离、场景状态机、测试用例库、录制回放、请求日志"
1650
- }
1651
- ),
1652
- /* @__PURE__ */ e(
1653
- we,
1654
- {
1655
- activeKey: t,
1656
- onChange: i,
1657
- type: "card",
1658
- tabBarExtraContent: /* @__PURE__ */ n(R, { size: "large", wrap: !0, children: [
1659
- /* @__PURE__ */ n(R, { children: [
1660
- /* @__PURE__ */ e(pt, {}),
1661
- /* @__PURE__ */ e(te, { children: "当前环境:" }),
1662
- /* @__PURE__ */ e(
1663
- W,
1664
- {
1665
- value: l,
1666
- onChange: y,
1667
- style: { width: 200 },
1668
- options: r.map((m) => ({
1669
- value: m.env_code,
1670
- label: `${m.env_name || m.env_code} (${m.env_type})`
1671
- }))
1672
- }
1673
- )
1674
- ] }),
1675
- s && /* @__PURE__ */ n(R, { size: "large", children: [
1676
- /* @__PURE__ */ n(te, { type: "secondary", children: [
1677
- "端点: ",
1678
- /* @__PURE__ */ e(te, { strong: !0, children: s.totalEndpoints })
1679
- ] }),
1680
- /* @__PURE__ */ n(te, { type: "secondary", children: [
1681
- "启用: ",
1682
- /* @__PURE__ */ e(
1683
- te,
1684
- {
1685
- strong: !0,
1686
- style: { color: "#52c41a" },
1687
- children: s.activeEndpoints
1688
- }
1689
- )
1690
- ] }),
1691
- /* @__PURE__ */ n(te, { type: "secondary", children: [
1692
- "场景: ",
1693
- /* @__PURE__ */ e(te, { strong: !0, children: s.totalScenarios })
1694
- ] }),
1695
- /* @__PURE__ */ n(te, { type: "secondary", children: [
1696
- "用例: ",
1697
- /* @__PURE__ */ e(te, { strong: !0, children: s.totalCases })
1698
- ] })
1699
- ] }),
1700
- /* @__PURE__ */ e(_, { icon: /* @__PURE__ */ e(ee, {}), onClick: () => {
1701
- w(), T();
1702
- }, children: "刷新" })
1703
- ] }),
1704
- items: Qe.map((m) => ({
1705
- key: m.key,
1706
- label: m.label,
1707
- children: m.component === De ? /* @__PURE__ */ e(De, { activeEnvCode: l }) : m.component === Be ? /* @__PURE__ */ e(Be, { onEnvChange: (h) => {
1708
- y(h), b.success(`已切换到环境: ${h}`);
1709
- } }) : /* @__PURE__ */ e(m.component, {})
1710
- }))
1711
- }
1712
- )
1713
- ] });
1714
- }
1715
- const er = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
1716
- __proto__: null,
1717
- default: Sn
1718
- }, Symbol.toStringTag, { value: "Module" })), { Text: ye, Paragraph: tr } = le, et = [
1719
- {
1720
- group: "基础数据",
1721
- icon: /* @__PURE__ */ e(ge, {}),
1722
- items: [
1723
- { syntax: "@uuid", desc: "随机 UUID", example: "a3f2e1b7-8c4d-4e6f-9a1b-2c3d4e5f6a7b" },
1724
- { syntax: "@int(1, 100)", desc: "随机整数(含边界)", example: "42" },
1725
- { syntax: "@int", desc: "随机整数(0-1000)", example: "731" },
1726
- { syntax: "@boolean", desc: "随机布尔", example: "true" },
1727
- { syntax: '@pick("a","b","c")', desc: "从列表随机取一项", example: '"b"' }
1728
- ]
1729
- },
1730
- {
1731
- group: "时间相关",
1732
- icon: /* @__PURE__ */ e(Se, {}),
1733
- items: [
1734
- { syntax: "@datetime", desc: "当前时间 (yyyy-MM-dd HH:mm:ss)", example: "2026-06-17 22:30:15" },
1735
- { syntax: "@date", desc: "当前日期 (yyyy-MM-dd)", example: "2026-06-17" },
1736
- { syntax: "@time", desc: "当前时间戳 (毫秒)", example: "1718639415000" },
1737
- { syntax: "@timestamp", desc: "Unix 秒级时间戳", example: "1718639415" }
1738
- ]
1739
- },
1740
- {
1741
- group: "文本生成",
1742
- icon: /* @__PURE__ */ e(Se, {}),
1743
- items: [
1744
- { syntax: "@name", desc: "随机中文姓名", example: "张伟" },
1745
- { syntax: "@firstName", desc: "随机名", example: "伟" },
1746
- { syntax: "@lastName", desc: "随机姓", example: "张" },
1747
- { syntax: "@email", desc: "随机邮箱", example: "zhangwei@example.com" },
1748
- { syntax: "@phone", desc: "随机手机号(中国)", example: "13812345678" },
1749
- { syntax: "@idCard", desc: "随机身份证号", example: "110101199003078234" },
1750
- { syntax: "@word", desc: "随机英文单词", example: "horizon" },
1751
- { syntax: "@sentence(5, 10)", desc: "随机句子 (5-10 词)", example: "The quick brown fox jumps." },
1752
- { syntax: "@paragraph(3, 5)", desc: "随机段落 (3-5 句)", example: "..." }
1753
- ]
1754
- },
1755
- {
1756
- group: "序列与状态",
1757
- icon: /* @__PURE__ */ e(Se, {}),
1758
- items: [
1759
- { syntax: "@sequence(1)", desc: "自增序号(每次调用 +1,1 起始)", example: "1, 2, 3, ..." },
1760
- { syntax: "@sequence(100, 5)", desc: "自增序号(100 起始,步长 5)", example: "100, 105, 110, ..." }
1761
- ]
1762
- },
1763
- {
1764
- group: "请求上下文",
1765
- icon: /* @__PURE__ */ e(Se, {}),
1766
- items: [
1767
- { syntax: "#path.id", desc: "从 URL 路径取值 /users/123 → 123", example: "123" },
1768
- { syntax: "#query.page", desc: "从 query string 取值 ?page=2", example: "2" },
1769
- { syntax: "#header.X-Token", desc: "从请求头取值", example: "abc.def.ghi" },
1770
- { syntax: "#body.username", desc: "从请求体 JSON 取值", example: '"alice"' }
1771
- ]
1772
- }
1773
- ];
1774
- function nr({ onInsert: t, form: i, formField: r = "responseTemplate" }) {
1775
- const [S, l] = g(""), y = (m) => {
1776
- var h;
1777
- try {
1778
- (h = navigator.clipboard) == null || h.writeText(m);
1779
- } catch {
1780
- }
1781
- if (t)
1782
- t(m);
1783
- else if (i) {
1784
- const d = i.getFieldValue(r) || "";
1785
- i.setFieldsValue({ [r]: d + (d.endsWith(`
1786
- `) || !d ? "" : " ") + m });
1787
- }
1788
- b.success(`已插入: ${m}`);
1789
- }, s = (m) => {
1790
- var h;
1791
- try {
1792
- (h = navigator.clipboard) == null || h.writeText(m), b.success("已复制到剪贴板");
1793
- } catch {
1794
- b.warning("复制失败,请手动选择");
1795
- }
1796
- }, f = S.toLowerCase(), w = et.map((m) => ({
1797
- ...m,
1798
- items: m.items.filter(
1799
- (h) => !f || h.syntax.toLowerCase().includes(f) || h.desc.toLowerCase().includes(f) || h.example.toLowerCase().includes(f)
1800
- )
1801
- })).filter((m) => m.items.length > 0), T = et.reduce((m, h) => m + h.items.length, 0), A = w.reduce((m, h) => m + h.items.length, 0);
1802
- return /* @__PURE__ */ n(
1803
- P,
1804
- {
1805
- size: "small",
1806
- title: /* @__PURE__ */ n(R, { children: [
1807
- /* @__PURE__ */ e(ge, {}),
1808
- /* @__PURE__ */ e(ye, { strong: !0, children: "模板表达式" }),
1809
- /* @__PURE__ */ n(x, { color: "blue", children: [
1810
- A,
1811
- "/",
1812
- T
1813
- ] }),
1814
- /* @__PURE__ */ e(he, { title: "点击按钮即可插入到上方响应模板;点击 syntax 文本可复制", children: /* @__PURE__ */ e(Pt, { style: { color: "#999" } }) })
1815
- ] }),
1816
- extra: /* @__PURE__ */ e(
1817
- B,
1818
- {
1819
- size: "small",
1820
- placeholder: "搜索 @ 表达式",
1821
- prefix: /* @__PURE__ */ e(mt, {}),
1822
- value: S,
1823
- onChange: (m) => l(m.target.value),
1824
- style: { width: 180 },
1825
- allowClear: !0
1826
- }
1827
- ),
1828
- style: { marginTop: 8, background: "#fafafa" },
1829
- styles: { body: { padding: 12, maxHeight: 320, overflow: "auto" } },
1830
- children: [
1831
- w.length === 0 && /* @__PURE__ */ e(ye, { type: "secondary", style: { display: "block", textAlign: "center", padding: 16 }, children: "没有匹配的表达式" }),
1832
- w.map((m) => /* @__PURE__ */ n("div", { style: { marginBottom: 12 }, children: [
1833
- /* @__PURE__ */ n(R, { size: 4, style: { marginBottom: 6 }, children: [
1834
- m.icon,
1835
- /* @__PURE__ */ e(ye, { strong: !0, style: { fontSize: 13 }, children: m.group }),
1836
- /* @__PURE__ */ e(x, { children: m.items.length })
1837
- ] }),
1838
- /* @__PURE__ */ e(Q, { gutter: [8, 8], children: m.items.map((h) => /* @__PURE__ */ e(M, { span: 24, children: /* @__PURE__ */ n(
1839
- "div",
1840
- {
1841
- style: {
1842
- display: "flex",
1843
- alignItems: "center",
1844
- padding: "6px 8px",
1845
- background: "#fff",
1846
- border: "1px solid #f0f0f0",
1847
- borderRadius: 4,
1848
- gap: 8
1849
- },
1850
- children: [
1851
- /* @__PURE__ */ e(he, { title: "点击复制", children: /* @__PURE__ */ e(
1852
- ye,
1853
- {
1854
- code: !0,
1855
- style: { cursor: "pointer", minWidth: 140, fontSize: 12 },
1856
- onClick: () => s(h.syntax),
1857
- children: h.syntax
1858
- }
1859
- ) }),
1860
- /* @__PURE__ */ e(ye, { type: "secondary", style: { fontSize: 12, flex: 1 }, children: h.desc }),
1861
- /* @__PURE__ */ e(x, { color: "default", style: { margin: 0, fontFamily: "monospace" }, children: h.example }),
1862
- /* @__PURE__ */ e(he, { title: "插入到响应模板", children: /* @__PURE__ */ e(
1863
- _,
1864
- {
1865
- size: "small",
1866
- type: "text",
1867
- icon: /* @__PURE__ */ e(ht, {}),
1868
- onClick: () => y(h.syntax)
1869
- }
1870
- ) })
1871
- ]
1872
- }
1873
- ) }, h.syntax)) })
1874
- ] }, m.group))
1875
- ]
1876
- }
1877
- );
1878
- }
1879
- const { TextArea: tt } = B, { Text: ue, Paragraph: kn } = le;
1880
- function rr({ open: t, onClose: i, onSuccess: r, envOptions: S = [] }) {
1881
- const [l, y] = g(""), [s, f] = g(null), [w, T] = g(null), [A, m] = g(!1), [h, d] = g(null), [c, v] = g(!1), [L, C] = g("import"), [u] = E.useForm(), [a] = E.useForm(), k = () => {
1882
- y(""), f(null), T(null), d(null), u.resetFields(), a.resetFields();
1883
- }, $ = () => {
1884
- k(), i();
1885
- }, X = async () => {
1886
- var O, I, D, Z;
1887
- if (!l.trim()) {
1888
- b.warning("请先粘贴 curl 命令");
1889
- return;
1890
- }
1891
- T(null), f(null), d(null);
1892
- try {
1893
- const j = await q.curl.parse(l);
1894
- j.success ? (f(j.data), u.setFieldsValue({
1895
- caseName: `from-curl-${((O = j.data) == null ? void 0 : O.method) || "GET"}-${(((I = j.data) == null ? void 0 : I.path) || "").replace(/\W+/g, "-")}`,
1896
- caseGroup: "imported",
1897
- envCode: S[0] || "default"
1898
- }), a.setFieldsValue({
1899
- mockName: `mock-${((D = j.data) == null ? void 0 : D.method) || "GET"}-${(((Z = j.data) == null ? void 0 : Z.path) || "").replace(/\W+/g, "-")}`,
1900
- envCode: S[0] || "default",
1901
- projectCode: "default",
1902
- responseTemplate: `{
1903
- "code": 0,
1904
- "message": "ok",
1905
- "data": {}
1906
- }`
1907
- })) : T(j.message || "解析失败");
1908
- } catch (j) {
1909
- T(String((j == null ? void 0 : j.message) || j));
1910
- }
1911
- }, G = async () => {
1912
- if (!l.trim()) {
1913
- b.warning("请先粘贴 curl 命令");
1914
- return;
1915
- }
1916
- m(!0), d(null);
1917
- try {
1918
- const O = await q.curl.run(l);
1919
- d(O);
1920
- } catch (O) {
1921
- d({ success: !1, error: String((O == null ? void 0 : O.message) || O) });
1922
- } finally {
1923
- m(!1);
1924
- }
1925
- }, p = async () => {
1926
- if (!s) {
1927
- b.warning("请先解析");
1928
- return;
1929
- }
1930
- let O;
1931
- try {
1932
- O = await u.validateFields();
1933
- } catch {
1934
- return;
1935
- }
1936
- v(!0);
1937
- try {
1938
- const I = await q.curl.importAsCase({
1939
- curl: l,
1940
- caseName: O.caseName,
1941
- caseGroup: O.caseGroup,
1942
- envCode: O.envCode
1943
- });
1944
- I.success ? (b.success(`已导入测试用例: ${I.caseCode}`), r && r("case", I), $()) : b.error(I.message || "导入失败");
1945
- } catch (I) {
1946
- b.error(String((I == null ? void 0 : I.message) || I));
1947
- } finally {
1948
- v(!1);
1949
- }
1950
- }, o = async () => {
1951
- if (!s) {
1952
- b.warning("请先解析");
1953
- return;
1954
- }
1955
- let O;
1956
- try {
1957
- O = await a.validateFields();
1958
- } catch {
1959
- return;
1960
- }
1961
- v(!0);
1962
- try {
1963
- const I = await q.curl.importAsEndpoint({
1964
- curl: l,
1965
- mockName: O.mockName,
1966
- envCode: O.envCode,
1967
- projectCode: O.projectCode,
1968
- responseTemplate: O.responseTemplate
1969
- });
1970
- I.success ? (b.success(`已导入 Mock 端点: ${I.mockCode}`), r && r("endpoint", I), $()) : b.error(I.message || "导入失败");
1971
- } catch (I) {
1972
- b.error(String((I == null ? void 0 : I.message) || I));
1973
- } finally {
1974
- v(!1);
1975
- }
1976
- };
1977
- return /* @__PURE__ */ n(
1978
- pe,
1979
- {
1980
- title: /* @__PURE__ */ n(R, { children: [
1981
- /* @__PURE__ */ e(ge, {}),
1982
- " 粘贴 curl 一键导入"
1983
- ] }),
1984
- open: t,
1985
- onCancel: $,
1986
- footer: null,
1987
- size: "large",
1988
- destroyOnHidden: !0,
1989
- children: [
1990
- /* @__PURE__ */ e(kn, { type: "secondary", style: { marginBottom: 12 }, children: "从浏览器 DevTools / Postman / 终端复制 curl 命令,粘贴到下方即可解析、试跑、入库。" }),
1991
- /* @__PURE__ */ e(
1992
- tt,
1993
- {
1994
- value: l,
1995
- onChange: (O) => y(O.target.value),
1996
- placeholder: `curl -X POST 'https://api.example.com/v1/users/login' \\
1997
- -H 'Content-Type: application/json' \\
1998
- -H 'Authorization: Bearer xxx' \\
1999
- -d '{"username":"alice","password":"123456"}'`,
2000
- autoSize: { minRows: 4, maxRows: 10 },
2001
- style: { fontFamily: "Menlo, Monaco, monospace", fontSize: 12 }
2002
- }
2003
- ),
2004
- /* @__PURE__ */ n(R, { style: { marginTop: 12 }, children: [
2005
- /* @__PURE__ */ e(_, { icon: /* @__PURE__ */ e(Fe, {}), onClick: X, type: "primary", ghost: !0, children: "解析" }),
2006
- /* @__PURE__ */ e(_, { icon: /* @__PURE__ */ e(fe, {}), onClick: G, loading: A, children: "直接执行(试跑)" })
2007
- ] }),
2008
- w && /* @__PURE__ */ e(J, { type: "error", showIcon: !0, style: { marginTop: 12 }, title: "解析失败", description: w }),
2009
- s && /* @__PURE__ */ e(P, { size: "small", style: { marginTop: 16 }, title: "解析结果", children: /* @__PURE__ */ n(z, { column: 1, size: "small", bordered: !0, children: [
2010
- /* @__PURE__ */ e(z.Item, { label: "Method", children: /* @__PURE__ */ e(x, { color: Cn(s.method), children: s.method }) }),
2011
- /* @__PURE__ */ e(z.Item, { label: "URL", children: /* @__PURE__ */ e(ue, { code: !0, copyable: !0, children: s.url }) }),
2012
- /* @__PURE__ */ e(z.Item, { label: "Path", children: /* @__PURE__ */ e(ue, { code: !0, children: s.path }) }),
2013
- s.query && /* @__PURE__ */ e(z.Item, { label: "Query", children: /* @__PURE__ */ e(ue, { code: !0, children: s.query }) }),
2014
- /* @__PURE__ */ e(z.Item, { label: "Headers", children: Object.keys(s.headers || {}).length === 0 ? /* @__PURE__ */ e(ue, { type: "secondary", children: "(无)" }) : /* @__PURE__ */ e("div", { children: Object.entries(s.headers).map(([O, I]) => /* @__PURE__ */ n("div", { children: [
2015
- /* @__PURE__ */ n(ue, { strong: !0, children: [
2016
- O,
2017
- ":"
2018
- ] }),
2019
- " ",
2020
- /* @__PURE__ */ e(ue, { code: !0, children: I })
2021
- ] }, O)) }) }),
2022
- s.body && /* @__PURE__ */ e(z.Item, { label: "Body", children: /* @__PURE__ */ e("pre", { style: {
2023
- background: "#f5f5f5",
2024
- padding: 8,
2025
- margin: 0,
2026
- fontSize: 12,
2027
- maxHeight: 200,
2028
- overflow: "auto"
2029
- }, children: s.body }) })
2030
- ] }) }),
2031
- h && /* @__PURE__ */ n(P, { size: "small", style: { marginTop: 16 }, title: /* @__PURE__ */ n(R, { children: [
2032
- /* @__PURE__ */ e(fe, {}),
2033
- /* @__PURE__ */ e("span", { children: "试跑结果" }),
2034
- h.success ? /* @__PURE__ */ n(x, { color: "green", children: [
2035
- h.status,
2036
- " · ",
2037
- h.durationMs,
2038
- "ms · ",
2039
- h.bodySize,
2040
- "B"
2041
- ] }) : /* @__PURE__ */ e(x, { color: "red", children: "FAILED" })
2042
- ] }), children: [
2043
- h.error && /* @__PURE__ */ e(J, { type: "error", showIcon: !0, title: h.error }),
2044
- h.body != null && /* @__PURE__ */ e("pre", { style: {
2045
- background: "#f5f5f5",
2046
- padding: 8,
2047
- margin: 0,
2048
- fontSize: 12,
2049
- maxHeight: 240,
2050
- overflow: "auto"
2051
- }, children: h.body })
2052
- ] }),
2053
- s && /* @__PURE__ */ e(
2054
- we,
2055
- {
2056
- activeKey: L,
2057
- onChange: C,
2058
- style: { marginTop: 16 },
2059
- items: [
2060
- {
2061
- key: "import",
2062
- label: /* @__PURE__ */ n("span", { children: [
2063
- /* @__PURE__ */ e(Ne, {}),
2064
- " 导入为测试用例"
2065
- ] }),
2066
- children: /* @__PURE__ */ n(E, { form: u, layout: "vertical", children: [
2067
- /* @__PURE__ */ n(Q, { gutter: 16, children: [
2068
- /* @__PURE__ */ e(M, { span: 12, children: /* @__PURE__ */ e(E.Item, { name: "caseName", label: "用例名称", rules: [{ required: !0 }], children: /* @__PURE__ */ e(B, {}) }) }),
2069
- /* @__PURE__ */ e(M, { span: 6, children: /* @__PURE__ */ e(E.Item, { name: "caseGroup", label: "用例分组", children: /* @__PURE__ */ e(B, {}) }) }),
2070
- /* @__PURE__ */ e(M, { span: 6, children: /* @__PURE__ */ e(E.Item, { name: "envCode", label: "环境", children: S.length > 0 ? /* @__PURE__ */ e(W, { options: S.map((O) => ({ value: O, label: O })) }) : /* @__PURE__ */ e(B, {}) }) })
2071
- ] }),
2072
- /* @__PURE__ */ e(
2073
- _,
2074
- {
2075
- type: "primary",
2076
- onClick: p,
2077
- loading: c,
2078
- icon: /* @__PURE__ */ e(Ne, {}),
2079
- children: "保存为测试用例"
2080
- }
2081
- )
2082
- ] })
2083
- },
2084
- {
2085
- key: "mock",
2086
- label: /* @__PURE__ */ n("span", { children: [
2087
- /* @__PURE__ */ e(ge, {}),
2088
- " 导入为 Mock 端点"
2089
- ] }),
2090
- children: /* @__PURE__ */ n(E, { form: a, layout: "vertical", children: [
2091
- /* @__PURE__ */ n(Q, { gutter: 16, children: [
2092
- /* @__PURE__ */ e(M, { span: 12, children: /* @__PURE__ */ e(E.Item, { name: "mockName", label: "Mock 名称", rules: [{ required: !0 }], children: /* @__PURE__ */ e(B, {}) }) }),
2093
- /* @__PURE__ */ e(M, { span: 6, children: /* @__PURE__ */ e(E.Item, { name: "envCode", label: "环境", children: S.length > 0 ? /* @__PURE__ */ e(W, { options: S.map((O) => ({ value: O, label: O })) }) : /* @__PURE__ */ e(B, {}) }) }),
2094
- /* @__PURE__ */ e(M, { span: 6, children: /* @__PURE__ */ e(E.Item, { name: "projectCode", label: "项目", children: /* @__PURE__ */ e(B, {}) }) })
2095
- ] }),
2096
- /* @__PURE__ */ e(E.Item, { name: "responseTemplate", label: "响应模板 (JSON)", children: /* @__PURE__ */ e(
2097
- tt,
2098
- {
2099
- autoSize: { minRows: 3, maxRows: 8 },
2100
- style: { fontFamily: "Menlo, Monaco, monospace" }
2101
- }
2102
- ) }),
2103
- /* @__PURE__ */ e(
2104
- _,
2105
- {
2106
- type: "primary",
2107
- onClick: o,
2108
- loading: c,
2109
- icon: /* @__PURE__ */ e(ge, {}),
2110
- children: "保存为 Mock 端点"
2111
- }
2112
- )
2113
- ] })
2114
- }
2115
- ]
2116
- }
2117
- )
2118
- ]
2119
- }
2120
- );
2121
- }
2122
- function Cn(t) {
2123
- return { GET: "blue", POST: "green", PUT: "orange", DELETE: "red", PATCH: "purple" }[t] || "default";
2124
- }
2125
- const { TextArea: nt } = B;
2126
- function lr({ open: t, onClose: i, onSuccess: r, envOptions: S = [] }) {
2127
- const [l, y] = g("paste"), [s, f] = g(""), [w, T] = g(null), [A, m] = g(null), [h, d] = g(!1), [c, v] = g([]), [L, C] = g(!1), [u] = E.useForm(), a = it(null), k = () => {
2128
- f(""), T(null), m(null), v([]), u.resetFields();
2129
- }, $ = () => {
2130
- k(), i();
2131
- }, X = async () => {
2132
- if (!s.trim()) {
2133
- b.warning("请先粘贴或上传 API 规约");
2134
- return;
2135
- }
2136
- m(null), d(!0);
2137
- try {
2138
- const I = await q.openapi.parse(s);
2139
- I.success ? (T(I), v((I.endpoints || []).map((D, Z) => Z)), u.setFieldsValue({
2140
- envCode: S[0] || "default",
2141
- projectCode: "default",
2142
- defaultResponse: `{
2143
- "code": 0,
2144
- "message": "ok",
2145
- "data": {}
2146
- }`,
2147
- defaultStatus: 200,
2148
- priority: 5,
2149
- tagPrefix: "openapi-import"
2150
- }), b.success(`识别为 ${I.format},共 ${I.count} 个端点`)) : m(I.message || "解析失败");
2151
- } catch (I) {
2152
- m(String((I == null ? void 0 : I.message) || I));
2153
- } finally {
2154
- d(!1);
2155
- }
2156
- }, G = async (I) => {
2157
- try {
2158
- const D = await q.openapi.sample(I);
2159
- D.success && (f(D.content), b.success(`已加载 ${D.format} 示例`));
2160
- } catch (D) {
2161
- b.error("加载示例失败: " + D.message);
2162
- }
2163
- }, p = (I) => {
2164
- const D = new FileReader();
2165
- return D.onload = (Z) => {
2166
- var j;
2167
- f(String(((j = Z.target) == null ? void 0 : j.result) || "")), b.success(`已读取 ${I.name}(${(I.size / 1024).toFixed(1)}KB)`);
2168
- }, D.onerror = () => b.error("文件读取失败"), D.readAsText(I), !1;
2169
- }, o = async () => {
2170
- if (!w) {
2171
- b.warning("请先解析");
2172
- return;
2173
- }
2174
- let I;
2175
- try {
2176
- I = await u.validateFields();
2177
- } catch {
2178
- return;
2179
- }
2180
- C(!0);
2181
- try {
2182
- const D = (w.endpoints || []).map((j, Ge) => ({
2183
- method: j.method,
2184
- path: j.path
2185
- })).filter((j, Ge) => c.includes(Ge)), Z = await q.openapi.importBatch({
2186
- content: s,
2187
- selected: D,
2188
- envCode: I.envCode,
2189
- projectCode: I.projectCode,
2190
- defaultResponse: I.defaultResponse,
2191
- defaultStatus: I.defaultStatus,
2192
- priority: I.priority,
2193
- tagPrefix: I.tagPrefix
2194
- });
2195
- Z.success ? (b.success(`已导入 ${Z.imported} 个 Mock 端点${Z.failed > 0 ? `,失败 ${Z.failed}` : ""}`), r && r(Z), $()) : b.error(Z.message || "导入失败");
2196
- } catch (D) {
2197
- b.error(String((D == null ? void 0 : D.message) || D));
2198
- } finally {
2199
- C(!1);
2200
- }
2201
- }, O = [
2202
- {
2203
- title: "Method",
2204
- dataIndex: "method",
2205
- width: 90,
2206
- render: (I) => /* @__PURE__ */ e(x, { color: Tn(I), children: I })
2207
- },
2208
- { title: "Path", dataIndex: "path", width: 240, ellipsis: !0 },
2209
- { title: "Summary", dataIndex: "summary", ellipsis: !0 },
2210
- {
2211
- title: "Tags",
2212
- dataIndex: "tags",
2213
- width: 160,
2214
- render: (I) => (I || []).map((D) => /* @__PURE__ */ e(x, { children: D }, D))
2215
- },
2216
- {
2217
- title: "Params",
2218
- dataIndex: "parameters",
2219
- width: 80,
2220
- render: (I) => (I == null ? void 0 : I.length) || 0,
2221
- align: "center"
2222
- },
2223
- {
2224
- // `ApiSpecParser.ParsedEndpoint` 是 **POJO**(public 字段)⇒ 被全局 SNAKE_CASE 改名
2225
- title: "示例",
2226
- dataIndex: "response_example",
2227
- width: 80,
2228
- render: (I) => I ? /* @__PURE__ */ e(x, { color: "green", children: "有" }) : /* @__PURE__ */ e(x, { children: "无" })
2229
- }
2230
- ];
2231
- return /* @__PURE__ */ n(
2232
- pe,
2233
- {
2234
- title: /* @__PURE__ */ n(R, { children: [
2235
- /* @__PURE__ */ e(Je, {}),
2236
- " 批量导入 API 规约"
2237
- ] }),
2238
- open: t,
2239
- onCancel: $,
2240
- footer: null,
2241
- size: "large",
2242
- destroyOnHidden: !0,
2243
- children: [
2244
- /* @__PURE__ */ e(
2245
- we,
2246
- {
2247
- activeKey: l,
2248
- onChange: y,
2249
- items: [
2250
- {
2251
- key: "paste",
2252
- label: /* @__PURE__ */ n("span", { children: [
2253
- /* @__PURE__ */ e(Fe, {}),
2254
- " 粘贴 JSON"
2255
- ] }),
2256
- children: /* @__PURE__ */ n("div", { children: [
2257
- /* @__PURE__ */ e(
2258
- nt,
2259
- {
2260
- value: s,
2261
- onChange: (I) => f(I.target.value),
2262
- placeholder: "粘贴 OpenAPI 3.x / Swagger 2.0 / Postman v2.1 JSON 内容…",
2263
- autoSize: { minRows: 6, maxRows: 16 },
2264
- style: { fontFamily: "Menlo, Monaco, monospace", fontSize: 12 }
2265
- }
2266
- ),
2267
- /* @__PURE__ */ n(R, { style: { marginTop: 8 }, children: [
2268
- /* @__PURE__ */ e(_, { size: "small", onClick: () => G("openapi3"), children: "加载 OpenAPI 3 示例" }),
2269
- /* @__PURE__ */ e(_, { size: "small", onClick: () => G("swagger2"), children: "加载 Swagger 2 示例" }),
2270
- /* @__PURE__ */ e(_, { size: "small", onClick: () => G("postman"), children: "加载 Postman 示例" })
2271
- ] })
2272
- ] })
2273
- },
2274
- {
2275
- key: "upload",
2276
- label: /* @__PURE__ */ n("span", { children: [
2277
- /* @__PURE__ */ e(Mt, {}),
2278
- " 上传文件"
2279
- ] }),
2280
- children: /* @__PURE__ */ n(
2281
- kt.Dragger,
2282
- {
2283
- ref: a,
2284
- accept: ".json,.yaml,.yml,application/json,text/yaml",
2285
- beforeUpload: p,
2286
- showUploadList: !1,
2287
- style: { padding: 24 },
2288
- children: [
2289
- /* @__PURE__ */ e("p", { className: "ant-upload-drag-icon", children: /* @__PURE__ */ e(Je, { style: { fontSize: 48, color: "#1890ff" } }) }),
2290
- /* @__PURE__ */ e("p", { className: "ant-upload-text", children: "点击或拖拽 JSON / YAML 文件到此处" }),
2291
- /* @__PURE__ */ e("p", { className: "ant-upload-hint", children: "支持 OpenAPI 3.x / Swagger 2.0 / Postman v2.1" })
2292
- ]
2293
- }
2294
- )
2295
- }
2296
- ]
2297
- }
2298
- ),
2299
- /* @__PURE__ */ n(R, { style: { marginTop: 12 }, children: [
2300
- /* @__PURE__ */ e(_, { type: "primary", icon: /* @__PURE__ */ e(fe, {}), onClick: X, loading: h, children: "解析" }),
2301
- w && /* @__PURE__ */ e(x, { color: "blue", children: w.format }),
2302
- w && /* @__PURE__ */ n(x, { children: [
2303
- "共 ",
2304
- w.count,
2305
- " 个端点,已选 ",
2306
- c.length
2307
- ] })
2308
- ] }),
2309
- A && /* @__PURE__ */ e(J, { type: "error", showIcon: !0, style: { marginTop: 12 }, title: "解析失败", description: A }),
2310
- w && /* @__PURE__ */ e(P, { size: "small", style: { marginTop: 16 }, title: "预览(可勾选要导入的)", children: /* @__PURE__ */ e(
2311
- H,
2312
- {
2313
- size: "small",
2314
- dataSource: w.endpoints || [],
2315
- columns: O,
2316
- rowKey: (I, D) => D,
2317
- rowSelection: {
2318
- selectedRowKeys: c,
2319
- onChange: v
2320
- },
2321
- pagination: { pageSize: 8 },
2322
- scroll: { y: 280 }
2323
- }
2324
- ) }),
2325
- w && /* @__PURE__ */ e(P, { size: "small", style: { marginTop: 16 }, title: "导入配置", children: /* @__PURE__ */ n(E, { form: u, layout: "vertical", children: [
2326
- /* @__PURE__ */ n(Q, { gutter: 16, children: [
2327
- /* @__PURE__ */ e(M, { span: 6, children: /* @__PURE__ */ e(E.Item, { name: "envCode", label: "环境", rules: [{ required: !0 }], children: S.length > 0 ? /* @__PURE__ */ e(W, { options: S.map((I) => ({ value: I, label: I })) }) : /* @__PURE__ */ e(B, {}) }) }),
2328
- /* @__PURE__ */ e(M, { span: 6, children: /* @__PURE__ */ e(E.Item, { name: "projectCode", label: "项目", children: /* @__PURE__ */ e(B, {}) }) }),
2329
- /* @__PURE__ */ e(M, { span: 4, children: /* @__PURE__ */ e(E.Item, { name: "defaultStatus", label: "默认状态码", children: /* @__PURE__ */ e(B, { type: "number" }) }) }),
2330
- /* @__PURE__ */ e(M, { span: 4, children: /* @__PURE__ */ e(E.Item, { name: "priority", label: "优先级", children: /* @__PURE__ */ e(B, { type: "number" }) }) }),
2331
- /* @__PURE__ */ e(M, { span: 4, children: /* @__PURE__ */ e(E.Item, { name: "tagPrefix", label: "Tag 前缀", children: /* @__PURE__ */ e(B, {}) }) })
2332
- ] }),
2333
- /* @__PURE__ */ e(E.Item, { name: "defaultResponse", label: "默认响应(无 example 时使用)", children: /* @__PURE__ */ e(
2334
- nt,
2335
- {
2336
- autoSize: { minRows: 3, maxRows: 6 },
2337
- style: { fontFamily: "Menlo, Monaco, monospace" }
2338
- }
2339
- ) }),
2340
- /* @__PURE__ */ n(
2341
- _,
2342
- {
2343
- type: "primary",
2344
- size: "large",
2345
- icon: /* @__PURE__ */ e(Ne, {}),
2346
- onClick: o,
2347
- loading: L,
2348
- disabled: c.length === 0,
2349
- children: [
2350
- "批量导入 ",
2351
- c.length,
2352
- " 个端点"
2353
- ]
2354
- }
2355
- )
2356
- ] }) })
2357
- ]
2358
- }
2359
- );
2360
- }
2361
- function Tn(t) {
2362
- return { GET: "blue", POST: "green", PUT: "orange", DELETE: "red", PATCH: "purple" }[t] || "default";
2363
- }
2364
- const vn = {
2365
- STANDARD_JSON: { label: "标准 JSON", color: "blue" },
2366
- RSS_XML: { label: "RSS 2.0", color: "orange" },
2367
- ATOM_XML: { label: "Atom 1.0", color: "gold" },
2368
- CUSTOM_SCRIPT: { label: "自定义脚本", color: "purple" },
2369
- INTERNAL_BEAN: { label: "内部 Bean", color: "cyan" }
2370
- }, _n = {
2371
- PENDING_VERIFY: { color: "default", text: "待验证" },
2372
- VERIFIED: { color: "green", text: "已验证" },
2373
- INVALID_AUTH: { color: "red", text: "鉴权失败" },
2374
- FATAL: { color: "red", text: "永久失败" },
2375
- DISABLED: { color: "default", text: "已停用" }
2376
- }, rt = {
2377
- PENDING: { color: "default" },
2378
- RUNNING: { color: "processing" },
2379
- SUCCESS: { color: "green" },
2380
- EMPTY: { color: "default" },
2381
- FAILED: { color: "red" },
2382
- FATAL: { color: "red" }
2383
- };
2384
- function An() {
2385
- const t = be(), [i, r] = g([]), [S, l] = g(!1), [y, s] = g(null), [f, w] = g([]), [T, A] = g({}), [m, h] = g(null), [d, c] = g([]), v = async () => {
2386
- l(!0);
2387
- try {
2388
- const p = await N.get("/subscribe/subscription/list");
2389
- p && p.success !== !1 && r(Array.isArray(p.data) ? p.data : Array.isArray(p) ? p : []);
2390
- } catch (p) {
2391
- b.error("获取订阅列表失败: " + ((p == null ? void 0 : p.message) || ""));
2392
- } finally {
2393
- l(!1);
2394
- }
2395
- };
2396
- K(() => {
2397
- v();
2398
- }, []);
2399
- const L = (p) => {
2400
- pe.confirm({
2401
- title: "确认删除",
2402
- icon: /* @__PURE__ */ e(Dt, {}),
2403
- content: `确定要删除订阅 "${p.name}" 吗? 运行历史会保留.`,
2404
- onOk: async () => {
2405
- try {
2406
- const o = await N.delete(`/subscribe/subscription/${p.id}`);
2407
- o && o.success !== !1 ? (b.success("删除成功"), v()) : b.error((o == null ? void 0 : o.message) || "删除失败");
2408
- } catch (o) {
2409
- b.error("删除失败: " + ((o == null ? void 0 : o.message) || ""));
2410
- }
2411
- }
2412
- });
2413
- }, C = async (p) => {
2414
- try {
2415
- const o = await N.post(`/subscribe/subscription/${p}/enable`);
2416
- o && o.success !== !1 ? (b.success("已启用"), v()) : b.error((o == null ? void 0 : o.message) || "启用失败");
2417
- } catch (o) {
2418
- b.error("启用失败: " + ((o == null ? void 0 : o.message) || ""));
2419
- }
2420
- }, u = async (p) => {
2421
- try {
2422
- const o = await N.post(`/subscribe/subscription/${p}/disable`);
2423
- o && o.success !== !1 ? (b.success("已停用"), v()) : b.error((o == null ? void 0 : o.message) || "停用失败");
2424
- } catch (o) {
2425
- b.error("停用失败: " + ((o == null ? void 0 : o.message) || ""));
2426
- }
2427
- }, a = async (p) => {
2428
- pe.confirm({
2429
- title: "手动触发",
2430
- content: `将立即执行一次 "${p.name}" 的抽取, 同步返回 runId.`,
2431
- onOk: async () => {
2432
- try {
2433
- const o = await N.post(`/subscribe/subscription/${p.id}/trigger?triggerBy=ceo`);
2434
- if (o && (o.data !== void 0 || o.success !== !1)) {
2435
- const O = o.data ?? o;
2436
- b.success(`已触发, runId = ${O}`), $(p);
2437
- } else
2438
- b.error((o == null ? void 0 : o.message) || "触发失败");
2439
- } catch (o) {
2440
- b.error("触发失败: " + ((o == null ? void 0 : o.message) || ""));
2441
- }
2442
- }
2443
- });
2444
- }, k = async (p) => {
2445
- try {
2446
- const o = await N.post(`/subscribe/subscription/${p.id}/dry-run`);
2447
- s({ sub: p, result: (o == null ? void 0 : o.data) ?? o });
2448
- } catch (o) {
2449
- s({ sub: p, result: { success: !1, errorMessage: (o == null ? void 0 : o.message) || "请求失败" } });
2450
- }
2451
- }, $ = async (p) => {
2452
- try {
2453
- const o = await N.get(`/subscribe/run/list?subscriptionId=${p.id}&limit=20`), O = (o == null ? void 0 : o.data) ?? o ?? [];
2454
- w(Array.isArray(O) ? O : []), h(null), A({}), c([]), s({ sub: p, tab: "runs" });
2455
- } catch {
2456
- b.error("获取运行历史失败");
2457
- }
2458
- }, X = async (p) => {
2459
- if (T[p]) {
2460
- h(p);
2461
- return;
2462
- }
2463
- try {
2464
- const o = await N.get(`/subscribe/run/${p}/items?limit=200`), O = (o == null ? void 0 : o.data) ?? o ?? [];
2465
- A((I) => ({ ...I, [p]: Array.isArray(O) ? O : [] })), h(p);
2466
- } catch {
2467
- b.error("获取抽取项失败");
2468
- }
2469
- };
2470
- return /* @__PURE__ */ n("div", { children: [
2471
- /* @__PURE__ */ e(
2472
- me,
2473
- {
2474
- title: "订阅中心 - 数据源订阅",
2475
- subtitle: "负责把三方 / 内部 / RSS 等数据源按 Cron 定时抽取, 归一化后落到本地"
2476
- }
2477
- ),
2478
- /* @__PURE__ */ n(P, { extra: /* @__PURE__ */ n(R, { children: [
2479
- /* @__PURE__ */ e(_, { icon: /* @__PURE__ */ e(ee, {}), onClick: v, children: "刷新" }),
2480
- /* @__PURE__ */ e(
2481
- _,
2482
- {
2483
- type: "primary",
2484
- icon: /* @__PURE__ */ e(yt, {}),
2485
- onClick: () => t("/subscribe/new"),
2486
- children: "新建订阅"
2487
- }
2488
- )
2489
- ] }), children: [
2490
- /* @__PURE__ */ e(
2491
- J,
2492
- {
2493
- type: "info",
2494
- showIcon: !0,
2495
- style: { marginBottom: 16 },
2496
- message: "订阅中心负责把三方 / 内部 / RSS 等数据源按 Cron 定时抽取, 归一化后落到本地, 供 CEO 立项和 Agent 协作使用."
2497
- }
2498
- ),
2499
- /* @__PURE__ */ e(
2500
- H,
2501
- {
2502
- rowKey: "id",
2503
- columns: [
2504
- {
2505
- title: "ID",
2506
- dataIndex: "id",
2507
- width: 70
2508
- },
2509
- {
2510
- title: "名称",
2511
- dataIndex: "name",
2512
- render: (p, o) => /* @__PURE__ */ n(R, { orientation: "vertical", size: 0, children: [
2513
- /* @__PURE__ */ e("span", { style: { fontWeight: 500 }, children: p }),
2514
- o.description && /* @__PURE__ */ e("span", { style: { color: "#999", fontSize: 12 }, children: o.description })
2515
- ] })
2516
- },
2517
- {
2518
- title: "数据源",
2519
- dataIndex: "sourceType",
2520
- width: 90,
2521
- render: (p) => /* @__PURE__ */ e(x, { children: p })
2522
- },
2523
- {
2524
- title: "抽取器",
2525
- dataIndex: "extractorType",
2526
- width: 140,
2527
- render: (p) => {
2528
- const o = vn[p] || { label: p, color: "default" };
2529
- return /* @__PURE__ */ e(x, { color: o.color, children: o.label });
2530
- }
2531
- },
2532
- {
2533
- title: "Cron",
2534
- dataIndex: "cronExpr",
2535
- width: 150,
2536
- render: (p) => /* @__PURE__ */ e("code", { style: { fontSize: 12 }, children: p })
2537
- },
2538
- {
2539
- title: "状态",
2540
- dataIndex: "status",
2541
- width: 110,
2542
- render: (p) => {
2543
- const o = _n[p] || { color: "default", text: p };
2544
- return /* @__PURE__ */ e(x, { color: o.color, children: o.text });
2545
- }
2546
- },
2547
- {
2548
- title: "启用",
2549
- dataIndex: "enabled",
2550
- width: 80,
2551
- render: (p, o) => p ? /* @__PURE__ */ e(x, { color: "green", children: "是" }) : /* @__PURE__ */ e(x, { children: "否" })
2552
- },
2553
- {
2554
- title: "最近 run",
2555
- dataIndex: "lastStatus",
2556
- width: 110,
2557
- render: (p, o) => {
2558
- var O;
2559
- return p ? /* @__PURE__ */ e(he, { title: o.lastError || "", children: /* @__PURE__ */ e(x, { color: ((O = rt[p]) == null ? void 0 : O.color) || "default", children: p }) }) : /* @__PURE__ */ e("span", { style: { color: "#ccc" }, children: "-" });
2560
- }
2561
- },
2562
- {
2563
- title: "累计",
2564
- width: 130,
2565
- render: (p, o) => /* @__PURE__ */ n(R, { size: 4, children: [
2566
- /* @__PURE__ */ n(x, { color: "green", children: [
2567
- "✓ ",
2568
- o.successCountTotal || 0
2569
- ] }),
2570
- /* @__PURE__ */ n(x, { color: "red", children: [
2571
- "✗ ",
2572
- o.failCountTotal || 0
2573
- ] })
2574
- ] })
2575
- },
2576
- {
2577
- title: "操作",
2578
- width: 280,
2579
- fixed: "right",
2580
- render: (p, o) => /* @__PURE__ */ n(R, { size: 4, wrap: !0, children: [
2581
- /* @__PURE__ */ e(
2582
- _,
2583
- {
2584
- type: "link",
2585
- size: "small",
2586
- icon: /* @__PURE__ */ e($t, {}),
2587
- onClick: () => t(`/subscribe/edit/${o.id}`),
2588
- children: "编辑"
2589
- }
2590
- ),
2591
- /* @__PURE__ */ e(
2592
- _,
2593
- {
2594
- type: "link",
2595
- size: "small",
2596
- icon: /* @__PURE__ */ e(fe, {}),
2597
- onClick: () => k(o),
2598
- children: "试运行"
2599
- }
2600
- ),
2601
- /* @__PURE__ */ e(
2602
- _,
2603
- {
2604
- type: "link",
2605
- size: "small",
2606
- icon: /* @__PURE__ */ e(Ee, {}),
2607
- onClick: () => a(o),
2608
- children: "触发"
2609
- }
2610
- ),
2611
- /* @__PURE__ */ e(
2612
- _,
2613
- {
2614
- type: "link",
2615
- size: "small",
2616
- onClick: () => $(o),
2617
- children: "历史"
2618
- }
2619
- ),
2620
- o.enabled ? /* @__PURE__ */ e(
2621
- _,
2622
- {
2623
- type: "link",
2624
- size: "small",
2625
- icon: /* @__PURE__ */ e(Lt, {}),
2626
- onClick: () => u(o.id),
2627
- children: "停用"
2628
- }
2629
- ) : /* @__PURE__ */ e(
2630
- _,
2631
- {
2632
- type: "link",
2633
- size: "small",
2634
- icon: /* @__PURE__ */ e(Ue, {}),
2635
- onClick: () => C(o.id),
2636
- children: "启用"
2637
- }
2638
- ),
2639
- /* @__PURE__ */ e(qe, { title: "确认删除?", onConfirm: () => L(o), okText: "删除", cancelText: "取消", children: /* @__PURE__ */ e(_, { type: "link", size: "small", danger: !0, icon: /* @__PURE__ */ e(Nt, {}), children: "删除" }) })
2640
- ] })
2641
- }
2642
- ],
2643
- dataSource: i,
2644
- loading: S,
2645
- scroll: { x: 1400 },
2646
- size: "middle",
2647
- pagination: { pageSize: 20, showSizeChanger: !0, showTotal: (p) => `共 ${p} 条` }
2648
- }
2649
- )
2650
- ] }),
2651
- /* @__PURE__ */ e(
2652
- xe,
2653
- {
2654
- title: y != null && y.sub ? `试运行 - ${y.sub.name}` : "运行历史",
2655
- open: !!y,
2656
- onClose: () => s(null),
2657
- size: "large",
2658
- children: (y == null ? void 0 : y.tab) === "runs" ? /* @__PURE__ */ e(
2659
- we,
2660
- {
2661
- activeKey: m ? "items" : "list",
2662
- onChange: (p) => p === "list" && h(null),
2663
- items: [
2664
- {
2665
- key: "list",
2666
- label: `运行列表 (${f.length})`,
2667
- children: /* @__PURE__ */ e(
2668
- H,
2669
- {
2670
- rowKey: "id",
2671
- size: "small",
2672
- dataSource: f,
2673
- pagination: !1,
2674
- onRow: (p) => ({ onClick: () => X(p.id) }),
2675
- columns: [
2676
- { title: "runId", dataIndex: "id", width: 70 },
2677
- {
2678
- title: "计划",
2679
- dataIndex: "scheduledAt",
2680
- width: 160,
2681
- render: (p) => p ? new Date(p).toLocaleString() : "-"
2682
- },
2683
- { title: "耗时(ms)", dataIndex: "durationMs", width: 90 },
2684
- {
2685
- title: "状态",
2686
- dataIndex: "status",
2687
- width: 90,
2688
- render: (p) => {
2689
- var o;
2690
- return /* @__PURE__ */ e(x, { color: (o = rt[p]) == null ? void 0 : o.color, children: p });
2691
- }
2692
- },
2693
- {
2694
- title: "拉取/成功/重复/死信",
2695
- width: 200,
2696
- render: (p, o) => `${o.fetchedCount} / ${o.successCount} / ${o.duplicateCount || 0} / ${o.deadLetterCount}`
2697
- },
2698
- {
2699
- title: "错误",
2700
- dataIndex: "errorMessage",
2701
- render: (p) => p ? /* @__PURE__ */ e("span", { style: { color: "#cf1322", fontSize: 12 }, children: p }) : "-"
2702
- }
2703
- ]
2704
- }
2705
- )
2706
- },
2707
- {
2708
- key: "items",
2709
- label: m ? `run#${m} 抽取项` : "抽取项",
2710
- disabled: !m,
2711
- children: /* @__PURE__ */ n(R, { orientation: "vertical", style: { width: "100%" }, children: [
2712
- /* @__PURE__ */ n(R, { children: [
2713
- /* @__PURE__ */ n(x, { color: "blue", children: [
2714
- "已选 ",
2715
- d.length,
2716
- " 条"
2717
- ] }),
2718
- /* @__PURE__ */ n(
2719
- _,
2720
- {
2721
- size: "small",
2722
- type: "primary",
2723
- icon: /* @__PURE__ */ e(Ae, {}),
2724
- disabled: d.length === 0,
2725
- onClick: () => {
2726
- const p = d.join(",");
2727
- t(`/project/new?subscriptionId=${y.sub.id}&itemIds=${p}`);
2728
- },
2729
- children: [
2730
- "用所选 ",
2731
- d.length,
2732
- " 条立项"
2733
- ]
2734
- }
2735
- )
2736
- ] }),
2737
- /* @__PURE__ */ e(
2738
- H,
2739
- {
2740
- rowKey: "id",
2741
- size: "small",
2742
- dataSource: T[m] || [],
2743
- pagination: { pageSize: 20 },
2744
- rowSelection: {
2745
- selectedRowKeys: d,
2746
- onChange: c
2747
- },
2748
- columns: [
2749
- { title: "id", dataIndex: "dedupKey", width: 180, ellipsis: !0 },
2750
- {
2751
- title: "title",
2752
- dataIndex: "normalized",
2753
- render: (p) => {
2754
- try {
2755
- return JSON.parse(p).title || "(无标题)";
2756
- } catch {
2757
- return p;
2758
- }
2759
- }
2760
- },
2761
- {
2762
- title: "link",
2763
- dataIndex: "normalized",
2764
- render: (p) => {
2765
- try {
2766
- const o = JSON.parse(p);
2767
- return o.link ? /* @__PURE__ */ e("a", { href: o.link, target: "_blank", children: "↗" }) : "-";
2768
- } catch {
2769
- return "-";
2770
- }
2771
- }
2772
- },
2773
- {
2774
- title: "状态",
2775
- dataIndex: "status",
2776
- width: 110,
2777
- render: (p) => /* @__PURE__ */ e(x, { children: p })
2778
- }
2779
- ]
2780
- }
2781
- )
2782
- ] })
2783
- }
2784
- ]
2785
- }
2786
- ) : /* @__PURE__ */ e(En, { result: y == null ? void 0 : y.result })
2787
- }
2788
- )
2789
- ] });
2790
- }
2791
- function En({ result: t }) {
2792
- return t ? t.success ? /* @__PURE__ */ n(R, { orientation: "vertical", style: { width: "100%" }, size: "middle", children: [
2793
- /* @__PURE__ */ e(P, { size: "small", title: "调用结果", children: /* @__PURE__ */ n(R, { size: "large", wrap: !0, children: [
2794
- /* @__PURE__ */ n("span", { children: [
2795
- /* @__PURE__ */ e("b", { children: "HTTP:" }),
2796
- " ",
2797
- t.httpStatus || "-"
2798
- ] }),
2799
- /* @__PURE__ */ n("span", { children: [
2800
- /* @__PURE__ */ e("b", { children: "耗时:" }),
2801
- " ",
2802
- t.latencyMs,
2803
- "ms"
2804
- ] }),
2805
- /* @__PURE__ */ n("span", { children: [
2806
- /* @__PURE__ */ e("b", { children: "大小:" }),
2807
- " ",
2808
- t.responseSize,
2809
- "B"
2810
- ] }),
2811
- /* @__PURE__ */ n("span", { children: [
2812
- /* @__PURE__ */ e("b", { children: "样本:" }),
2813
- " ",
2814
- t.sampleCount,
2815
- " 条"
2816
- ] })
2817
- ] }) }),
2818
- t.firstItem && /* @__PURE__ */ e(P, { size: "small", title: "第一条样本 (归一化后)", children: /* @__PURE__ */ e(
2819
- "pre",
2820
- {
2821
- style: { background: "#f5f5f5", padding: 12, borderRadius: 4, maxHeight: 300, overflow: "auto" },
2822
- children: JSON.stringify(t.firstItem, null, 2)
2823
- }
2824
- ) }),
2825
- t.responsePreview && /* @__PURE__ */ e(P, { size: "small", title: "响应预览 (前 4KB)", children: /* @__PURE__ */ e("pre", { style: {
2826
- background: "#f5f5f5",
2827
- padding: 12,
2828
- borderRadius: 4,
2829
- maxHeight: 300,
2830
- overflow: "auto",
2831
- fontSize: 12
2832
- }, children: t.responsePreview }) }),
2833
- t.fieldErrors && t.fieldErrors.length > 0 && /* @__PURE__ */ e(J, { type: "warning", showIcon: !0, message: "字段问题", description: /* @__PURE__ */ e("ul", { children: t.fieldErrors.map((i, r) => /* @__PURE__ */ e("li", { children: i }, r)) }) })
2834
- ] }) : /* @__PURE__ */ e(J, { type: "error", showIcon: !0, title: "试运行失败", description: t.errorMessage || "未知错误" }) : null;
2835
- }
2836
- const Rn = [
2837
- { value: "STANDARD_JSON", label: "标准 JSON (按统一契约返回的 JSON)" },
2838
- { value: "RSS_XML", label: "RSS 2.0 (XML feed)" },
2839
- { value: "ATOM_XML", label: "Atom 1.0 (XML feed)" },
2840
- { value: "CUSTOM_SCRIPT", label: "自定义脚本 (z-script 平台)" },
2841
- { value: "INTERNAL_BEAN", label: "内部 Bean (我们自己的模块, 暂未启用)" }
2842
- ], zn = [
2843
- { value: "NONE", label: "无鉴权" },
2844
- { value: "BEARER", label: "Bearer (Authorization: Bearer xxx)" },
2845
- { value: "API_KEY", label: "API Key (Authorization: xxx)" },
2846
- { value: "BASIC", label: "Basic (user:password base64)" }
2847
- ], On = [
2848
- { label: "每 5 分钟", value: "0 */5 * * * ?" },
2849
- { label: "每 15 分钟", value: "0 */15 * * * ?" },
2850
- { label: "每小时", value: "0 0 * * * ?" },
2851
- { label: "每 6 小时", value: "0 0 */6 * * ?" },
2852
- { label: "每天 8 点", value: "0 0 8 * * ?" }
2853
- ];
2854
- function lt() {
2855
- const { id: t } = st(), i = be(), r = !!t, [S] = E.useForm(), [l, y] = g(!1), [s, f] = g(!1), [w, T] = g([]), [A, m] = g([]), h = E.useWatch("sourceType", S), d = E.useWatch("extractorType", S), c = E.useWatch("authType", S);
2856
- K(() => {
2857
- v(), L(), r && C();
2858
- }, [t]);
2859
- const v = async () => {
2860
- try {
2861
- const a = await N.get("/secret/list"), k = (a == null ? void 0 : a.data) ?? a ?? [];
2862
- T(Array.isArray(k) ? k : []);
2863
- } catch {
2864
- }
2865
- }, L = async () => {
2866
- try {
2867
- const a = await N.get("/script/list"), k = (a == null ? void 0 : a.data) ?? a ?? [];
2868
- m(Array.isArray(k) ? k.filter(($) => $.status === 1) : []);
2869
- } catch {
2870
- }
2871
- }, C = async () => {
2872
- y(!0);
2873
- try {
2874
- const a = await N.get(`/subscribe/subscription/${t}`), k = (a == null ? void 0 : a.data) ?? a;
2875
- k && S.setFieldsValue({
2876
- ...k,
2877
- enabled: k.enabled === 1 || k.enabled === !0
2878
- });
2879
- } catch (a) {
2880
- b.error("加载订阅失败: " + ((a == null ? void 0 : a.message) || ""));
2881
- } finally {
2882
- y(!1);
2883
- }
2884
- }, u = async () => {
2885
- try {
2886
- const a = await S.validateFields();
2887
- f(!0);
2888
- const k = {
2889
- ...a,
2890
- enabled: a.enabled ? 1 : 0
2891
- };
2892
- let $;
2893
- if (r ? $ = await N.put("/subscribe/subscription", k) : $ = await N.post("/subscribe/subscription", k), $ && $.success === !1) {
2894
- b.error($.message || "保存失败");
2895
- return;
2896
- }
2897
- b.success(r ? "已更新 (注意: 修改 cron / url / 抽取器后会自动重置为 PENDING_VERIFY)" : "已创建, 已自动验证"), i("/subscribe/list");
2898
- } catch (a) {
2899
- a != null && a.errorFields ? b.warning("请检查表单") : b.error("保存失败: " + ((a == null ? void 0 : a.message) || ""));
2900
- } finally {
2901
- f(!1);
2902
- }
2903
- };
2904
- return /* @__PURE__ */ n("div", { style: { padding: 24 }, children: [
2905
- /* @__PURE__ */ e(
2906
- me,
2907
- {
2908
- title: r ? `编辑订阅 #${t}` : "新建订阅",
2909
- subtitle: "配置数据源、抽取器、鉴权与调度策略",
2910
- back: !0,
2911
- extra: /* @__PURE__ */ n(R, { children: [
2912
- /* @__PURE__ */ e(_, { onClick: () => i("/subscribe/list"), children: "取消" }),
2913
- /* @__PURE__ */ e(_, { type: "primary", icon: /* @__PURE__ */ e(gt, {}), loading: s, onClick: u, children: "保存 (自动验证)" })
2914
- ] })
2915
- }
2916
- ),
2917
- /* @__PURE__ */ e(P, { children: /* @__PURE__ */ e(_e, { spinning: l, children: /* @__PURE__ */ n(
2918
- E,
2919
- {
2920
- form: S,
2921
- layout: "vertical",
2922
- initialValues: {
2923
- sourceType: "HTTP",
2924
- httpMethod: "GET",
2925
- authType: "NONE",
2926
- extractorType: "STANDARD_JSON",
2927
- enabled: !0,
2928
- minIntervalSec: 60,
2929
- maxItemsPerRun: 1e3,
2930
- timeoutMs: 15e3
2931
- },
2932
- children: [
2933
- /* @__PURE__ */ n(P, { type: "inner", title: "基本信息", style: { marginBottom: 16 }, children: [
2934
- /* @__PURE__ */ e(E.Item, { label: "名称", name: "name", rules: [{ required: !0, message: "请输入名称" }], children: /* @__PURE__ */ e(B, { placeholder: "例如: GitHub PR 通知" }) }),
2935
- /* @__PURE__ */ e(E.Item, { label: "说明", name: "description", children: /* @__PURE__ */ e(B.TextArea, { rows: 2, placeholder: "(可选)" }) })
2936
- ] }),
2937
- /* @__PURE__ */ n(P, { type: "inner", title: "数据源", style: { marginBottom: 16 }, children: [
2938
- /* @__PURE__ */ e(E.Item, { label: "数据源形态", name: "sourceType", rules: [{ required: !0 }], children: /* @__PURE__ */ n(ne.Group, { children: [
2939
- /* @__PURE__ */ e(ne.Button, { value: "HTTP", children: "HTTP / HTTPS" }),
2940
- /* @__PURE__ */ e(ne.Button, { value: "INTERNAL", disabled: !0, children: "内部 Bean" })
2941
- ] }) }),
2942
- h === "HTTP" && /* @__PURE__ */ n(Me, { children: [
2943
- /* @__PURE__ */ e(
2944
- E.Item,
2945
- {
2946
- label: "目标 URL",
2947
- name: "targetUrl",
2948
- rules: [{ required: !0, message: "请输入 URL" }],
2949
- children: /* @__PURE__ */ e(B, { placeholder: "https://api.github.com/repos/.../pulls?state=open" })
2950
- }
2951
- ),
2952
- /* @__PURE__ */ n(R, { size: "large", style: { width: "100%" }, children: [
2953
- /* @__PURE__ */ e(E.Item, { label: "HTTP 方法", name: "httpMethod", children: /* @__PURE__ */ e(W, { style: { width: 120 }, options: [
2954
- { value: "GET", label: "GET" },
2955
- { value: "POST", label: "POST" },
2956
- { value: "PUT", label: "PUT" }
2957
- ] }) }),
2958
- /* @__PURE__ */ e(E.Item, { label: "超时 (ms)", name: "timeoutMs", children: /* @__PURE__ */ e(ze, { min: 1e3, max: 12e4, step: 1e3 }) })
2959
- ] }),
2960
- /* @__PURE__ */ e(E.Item, { label: "自定义 HTTP 头 (JSON)", name: "httpHeaders", children: /* @__PURE__ */ e(B.TextArea, { rows: 2, placeholder: '{"X-Trace-Id":"abc"}' }) }),
2961
- /* @__PURE__ */ e(E.Item, { label: "请求体 (POST/PUT)", name: "requestBody", children: /* @__PURE__ */ e(B.TextArea, { rows: 3, placeholder: "(可选)" }) })
2962
- ] })
2963
- ] }),
2964
- /* @__PURE__ */ n(P, { type: "inner", title: "鉴权 (从 z-mist 拉取 secret)", style: { marginBottom: 16 }, children: [
2965
- /* @__PURE__ */ e(E.Item, { label: "鉴权方式", name: "authType", children: /* @__PURE__ */ e(W, { options: zn }) }),
2966
- c && c !== "NONE" && /* @__PURE__ */ e(
2967
- E.Item,
2968
- {
2969
- label: "z-mist 凭据引用",
2970
- name: "authSecretKey",
2971
- extra: "从密钥中心 (z-mist) 选一个 secret; secret 的解密值会作为 secret 注入",
2972
- children: /* @__PURE__ */ e(
2973
- W,
2974
- {
2975
- showSearch: !0,
2976
- allowClear: !0,
2977
- placeholder: "选择 secret (key)",
2978
- options: w.map((a) => ({
2979
- value: a.secretKey,
2980
- label: `${a.secretKey}${a.secretName ? " (" + a.secretName + ")" : ""}`
2981
- }))
2982
- }
2983
- )
2984
- }
2985
- )
2986
- ] }),
2987
- /* @__PURE__ */ n(P, { type: "inner", title: "抽取器", style: { marginBottom: 16 }, children: [
2988
- /* @__PURE__ */ e(
2989
- E.Item,
2990
- {
2991
- label: "抽取器类型",
2992
- name: "extractorType",
2993
- rules: [{ required: !0 }],
2994
- extra: "STANDARD_JSON/RSS_XML/ATOM_XML 直接解析; CUSTOM_SCRIPT 调 z-script 平台",
2995
- children: /* @__PURE__ */ e(W, { options: Rn })
2996
- }
2997
- ),
2998
- d === "CUSTOM_SCRIPT" && /* @__PURE__ */ e(
2999
- E.Item,
3000
- {
3001
- label: "z-script 脚本",
3002
- name: "extractorScriptCode",
3003
- rules: [{ required: !0, message: "请选择脚本" }],
3004
- extra: "在 智能中心 > 脚本中心 维护脚本. 脚本返回 { items: [...], nextCursor: '...' }",
3005
- children: /* @__PURE__ */ e(
3006
- W,
3007
- {
3008
- showSearch: !0,
3009
- placeholder: "选择已启用的脚本",
3010
- options: A.map((a) => ({
3011
- value: a.scriptCode,
3012
- label: `${a.scriptCode} (${a.dslType})${a.scriptName ? " - " + a.scriptName : ""}`
3013
- }))
3014
- }
3015
- )
3016
- }
3017
- )
3018
- ] }),
3019
- /* @__PURE__ */ n(P, { type: "inner", title: "调度", style: { marginBottom: 16 }, children: [
3020
- /* @__PURE__ */ e(
3021
- E.Item,
3022
- {
3023
- label: "Cron 表达式",
3024
- name: "cronExpr",
3025
- rules: [{ required: !0, message: "请输入 Cron" }],
3026
- extra: "Quartz 兼容, 例如 0 */5 * * * ? = 每 5 分钟",
3027
- children: /* @__PURE__ */ e(B, { addonAfter: /* @__PURE__ */ e(
3028
- W,
3029
- {
3030
- style: { width: 140 },
3031
- placeholder: "常用",
3032
- options: On,
3033
- onChange: (a) => S.setFieldValue("cronExpr", a),
3034
- value: null
3035
- }
3036
- ) })
3037
- }
3038
- ),
3039
- /* @__PURE__ */ n(R, { size: "large", children: [
3040
- /* @__PURE__ */ e(E.Item, { label: "启用", name: "enabled", valuePropName: "checked", children: /* @__PURE__ */ n(ne.Group, { children: [
3041
- /* @__PURE__ */ e(ne.Button, { value: !0, children: "启用" }),
3042
- /* @__PURE__ */ e(ne.Button, { value: !1, children: "停用" })
3043
- ] }) }),
3044
- /* @__PURE__ */ e(
3045
- E.Item,
3046
- {
3047
- label: "最小间隔 (秒)",
3048
- name: "minIntervalSec",
3049
- extra: "距上次 run 至少 N 秒",
3050
- children: /* @__PURE__ */ e(ze, { min: 0, max: 3600 })
3051
- }
3052
- ),
3053
- /* @__PURE__ */ e(E.Item, { label: "单次最多条数", name: "maxItemsPerRun", children: /* @__PURE__ */ e(ze, { min: 1, max: 1e4 }) })
3054
- ] })
3055
- ] }),
3056
- /* @__PURE__ */ e(
3057
- J,
3058
- {
3059
- type: "success",
3060
- showIcon: !0,
3061
- title: "保存后会自动 dry-run: 真实 HTTP 一次, 把响应喂给抽取器, 失败时订阅进入 INVALID_AUTH 状态, 不会自动调度."
3062
- }
3063
- )
3064
- ]
3065
- }
3066
- ) }) })
3067
- ] });
3068
- }
3069
- const Pn = {
3070
- PENDING: "default",
3071
- RUNNING: "processing",
3072
- SUCCESS: "green",
3073
- EMPTY: "default",
3074
- FAILED: "red",
3075
- FATAL: "red"
3076
- };
3077
- function Mn() {
3078
- const [t, i] = g([]), [r, S] = g(null), [l, y] = g([]), [s, f] = g([]), [w, T] = g(null), [A, m] = g(!1);
3079
- K(() => {
3080
- h();
3081
- }, []), K(() => {
3082
- r && d(r);
3083
- }, [r]);
3084
- const h = async () => {
3085
- try {
3086
- const u = await N.get("/subscribe/subscription/list"), a = (u == null ? void 0 : u.data) ?? u ?? [];
3087
- i(Array.isArray(a) ? a : []), Array.isArray(a) && a.length > 0 && S(a[0].id);
3088
- } catch {
3089
- b.error("加载订阅列表失败");
3090
- }
3091
- }, d = async (u) => {
3092
- m(!0);
3093
- try {
3094
- const a = await N.get(`/subscribe/run/list?subscriptionId=${u}&limit=50`), k = (a == null ? void 0 : a.data) ?? a ?? [];
3095
- y(Array.isArray(k) ? k : []);
3096
- } catch {
3097
- b.error("加载运行历史失败");
3098
- } finally {
3099
- m(!1);
3100
- }
3101
- }, c = async (u) => {
3102
- T(u);
3103
- try {
3104
- const a = await N.get(`/subscribe/run/${u}/items?limit=200`), k = (a == null ? void 0 : a.data) ?? a ?? [];
3105
- f(Array.isArray(k) ? k : []);
3106
- } catch {
3107
- b.error("加载抽取项失败");
3108
- }
3109
- }, v = l.reduce((u, a) => u + (a.successCount || 0), 0), L = l.reduce((u, a) => u + (a.deadLetterCount || 0), 0), C = l.reduce((u, a) => u + (a.duplicateCount || 0), 0);
3110
- return /* @__PURE__ */ n("div", { children: [
3111
- /* @__PURE__ */ e(
3112
- me,
3113
- {
3114
- title: "订阅中心 - 运行历史",
3115
- subtitle: "查看各订阅的抽取运行记录与统计"
3116
- }
3117
- ),
3118
- /* @__PURE__ */ e(
3119
- Ut,
3120
- {
3121
- left: /* @__PURE__ */ e(
3122
- W,
3123
- {
3124
- style: { width: 280 },
3125
- placeholder: "选择订阅",
3126
- value: r,
3127
- onChange: S,
3128
- options: t.map((u) => ({ value: u.id, label: u.name })),
3129
- showSearch: !0,
3130
- optionFilterProp: "label"
3131
- }
3132
- ),
3133
- right: /* @__PURE__ */ n("a", { onClick: () => r && d(r), children: [
3134
- /* @__PURE__ */ e(ee, {}),
3135
- " 刷新"
3136
- ] })
3137
- }
3138
- ),
3139
- /* @__PURE__ */ n(P, { children: [
3140
- /* @__PURE__ */ n(Q, { gutter: 16, style: { marginBottom: 16 }, children: [
3141
- /* @__PURE__ */ e(M, { span: 6, children: /* @__PURE__ */ e(P, { children: /* @__PURE__ */ e(U, { title: "run 总数", value: l.length }) }) }),
3142
- /* @__PURE__ */ e(M, { span: 6, children: /* @__PURE__ */ e(P, { children: /* @__PURE__ */ e(
3143
- U,
3144
- {
3145
- title: "成功条数",
3146
- value: v,
3147
- styles: { content: { color: "#3f8600" } }
3148
- }
3149
- ) }) }),
3150
- /* @__PURE__ */ e(M, { span: 6, children: /* @__PURE__ */ e(P, { children: /* @__PURE__ */ e(
3151
- U,
3152
- {
3153
- title: "死信条数",
3154
- value: L,
3155
- styles: { content: { color: "#cf1322" } }
3156
- }
3157
- ) }) }),
3158
- /* @__PURE__ */ e(M, { span: 6, children: /* @__PURE__ */ e(P, { children: /* @__PURE__ */ e(U, { title: "重复跳过", value: C }) }) })
3159
- ] }),
3160
- /* @__PURE__ */ n(Q, { gutter: 16, children: [
3161
- /* @__PURE__ */ e(M, { span: 12, children: /* @__PURE__ */ e(P, { type: "inner", title: `运行列表 (${l.length})`, size: "small", children: /* @__PURE__ */ e(
3162
- H,
3163
- {
3164
- rowKey: "id",
3165
- size: "small",
3166
- loading: A,
3167
- dataSource: l,
3168
- pagination: { pageSize: 10 },
3169
- onRow: (u) => ({
3170
- onClick: () => c(u.id),
3171
- style: { cursor: "pointer", background: u.id === w ? "#e6f7ff" : "" }
3172
- }),
3173
- columns: [
3174
- { title: "ID", dataIndex: "id", width: 60 },
3175
- {
3176
- title: "计划",
3177
- dataIndex: "scheduledAt",
3178
- width: 150,
3179
- render: (u) => u ? new Date(u).toLocaleString() : "-"
3180
- },
3181
- { title: "耗时", dataIndex: "durationMs", width: 80 },
3182
- {
3183
- title: "状态",
3184
- dataIndex: "status",
3185
- width: 80,
3186
- render: (u) => /* @__PURE__ */ e(x, { color: Pn[u], children: u })
3187
- },
3188
- {
3189
- title: "拉取/成功/死信",
3190
- width: 150,
3191
- render: (u, a) => `${a.fetchedCount} / ${a.successCount} / ${a.deadLetterCount}`
3192
- }
3193
- ]
3194
- }
3195
- ) }) }),
3196
- /* @__PURE__ */ e(M, { span: 12, children: /* @__PURE__ */ e(
3197
- P,
3198
- {
3199
- type: "inner",
3200
- title: w ? `run#${w} 抽取项 (${s.length})` : "抽取项",
3201
- size: "small",
3202
- children: s.length === 0 ? /* @__PURE__ */ e(dt, { description: w ? "该 run 无抽取项" : "点击左侧 run 查看抽取项" }) : /* @__PURE__ */ e(
3203
- H,
3204
- {
3205
- rowKey: "id",
3206
- size: "small",
3207
- dataSource: s,
3208
- pagination: { pageSize: 10 },
3209
- columns: [
3210
- { title: "id", dataIndex: "dedupKey", width: 160, ellipsis: !0 },
3211
- {
3212
- title: "title",
3213
- dataIndex: "normalized",
3214
- render: (u) => {
3215
- try {
3216
- return JSON.parse(u).title || "(无标题)";
3217
- } catch {
3218
- return u;
3219
- }
3220
- }
3221
- },
3222
- {
3223
- title: "link",
3224
- dataIndex: "normalized",
3225
- width: 60,
3226
- render: (u) => {
3227
- try {
3228
- const a = JSON.parse(u);
3229
- return a.link ? /* @__PURE__ */ e("a", { href: a.link, target: "_blank", children: "↗" }) : "-";
3230
- } catch {
3231
- return "-";
3232
- }
3233
- }
3234
- },
3235
- {
3236
- title: "状态",
3237
- dataIndex: "status",
3238
- width: 100,
3239
- render: (u) => /* @__PURE__ */ e(x, { children: u })
3240
- }
3241
- ]
3242
- }
3243
- )
3244
- }
3245
- ) })
3246
- ] })
3247
- ] })
3248
- ] });
3249
- }
3250
- function $n() {
3251
- return /* @__PURE__ */ n(ot, { children: [
3252
- /* @__PURE__ */ e(re, { index: !0, element: /* @__PURE__ */ e(ct, { to: "list", replace: !0 }) }),
3253
- /* @__PURE__ */ e(re, { path: "list", element: /* @__PURE__ */ e(An, {}) }),
3254
- /* @__PURE__ */ e(re, { path: "new", element: /* @__PURE__ */ e(lt, {}) }),
3255
- /* @__PURE__ */ e(re, { path: "edit/:id", element: /* @__PURE__ */ e(lt, {}) }),
3256
- /* @__PURE__ */ e(re, { path: "runs", element: /* @__PURE__ */ e(Mn, {}) })
3257
- ] });
3258
- }
3259
- const ar = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
3260
- __proto__: null,
3261
- default: $n
3262
- }, Symbol.toStringTag, { value: "Module" })), Ln = {
3263
- OPEN: { color: "blue", text: "待开始" },
3264
- IN_PROGRESS: { color: "green", text: "进行中" },
3265
- COMPLETED: { color: "default", text: "已完成" },
3266
- ARCHIVED: { color: "default", text: "已归档" }
3267
- };
3268
- function Nn() {
3269
- const t = be(), [i, r] = g("mine"), [S, l] = g([]), [y, s] = g(!1), [f, w] = g(null), T = async () => {
3270
- s(!0), w(null);
3271
- try {
3272
- const d = i === "mine" ? "/project/list/mine?limit=100" : `/project/list/by-status?status=${i}&limit=100`, c = await N.get(d), v = (c == null ? void 0 : c.data) ?? c ?? [];
3273
- l(Array.isArray(v) ? v : []);
3274
- } catch (d) {
3275
- w((d == null ? void 0 : d.message) || (d == null ? void 0 : d.msg) || "加载失败");
3276
- } finally {
3277
- s(!1);
3278
- }
3279
- };
3280
- K(() => {
3281
- T();
3282
- }, [i]);
3283
- const A = async (d) => {
3284
- try {
3285
- const c = await N.post(`/project/${d}/status?status=COMPLETED`);
3286
- c && c.success !== !1 && (b.success("已标记完成"), T());
3287
- } catch (c) {
3288
- b.error("操作失败: " + ((c == null ? void 0 : c.message) || ""));
3289
- }
3290
- }, m = [
3291
- { title: "ID", dataIndex: "id", width: 60 },
3292
- {
3293
- title: "名称",
3294
- dataIndex: "name",
3295
- render: (d, c) => /* @__PURE__ */ n(R, { orientation: "vertical", size: 0, children: [
3296
- /* @__PURE__ */ e("a", { onClick: () => t(`/project/${c.id}`), style: { fontWeight: 500 }, children: d }),
3297
- c.description && /* @__PURE__ */ e("span", { style: { color: "#999", fontSize: 12 }, children: c.description })
3298
- ] })
3299
- },
3300
- { title: "来源", dataIndex: "sourceType", width: 100, render: (d) => /* @__PURE__ */ e(x, { children: d }) },
3301
- {
3302
- title: "订阅",
3303
- dataIndex: "sourceSubscriptionId",
3304
- width: 80,
3305
- render: (d) => d ? `#${d}` : /* @__PURE__ */ e("span", { style: { color: "#ccc" }, children: "-" })
3306
- },
3307
- {
3308
- title: "状态",
3309
- dataIndex: "status",
3310
- width: 100,
3311
- render: (d) => {
3312
- const c = Ln[d] || { color: "default", text: d };
3313
- return /* @__PURE__ */ e(x, { color: c.color, children: c.text });
3314
- }
3315
- },
3316
- { title: "消息数", dataIndex: "messageCount", width: 80 },
3317
- {
3318
- title: "上下文",
3319
- width: 130,
3320
- render: (d, c) => /* @__PURE__ */ n(x, { color: "blue", children: [
3321
- c.contextSize || 0,
3322
- "B"
3323
- ] })
3324
- },
3325
- {
3326
- title: "最近活动",
3327
- dataIndex: "lastMessageAt",
3328
- width: 150,
3329
- render: (d) => d ? new Date(d).toLocaleString() : /* @__PURE__ */ e("span", { style: { color: "#ccc" }, children: "-" })
3330
- },
3331
- {
3332
- title: "操作",
3333
- width: 160,
3334
- render: (d, c) => /* @__PURE__ */ n(R, { size: 4, children: [
3335
- /* @__PURE__ */ e(_, { type: "link", size: "small", onClick: () => t(`/project/${c.id}`), children: "对话" }),
3336
- c.status !== "COMPLETED" && c.status !== "ARCHIVED" && /* @__PURE__ */ e(
3337
- qe,
3338
- {
3339
- title: "标记为已完成?",
3340
- onConfirm: () => A(c.id),
3341
- okButtonProps: { danger: !0 },
3342
- children: /* @__PURE__ */ e(_, { type: "link", size: "small", icon: /* @__PURE__ */ e(Ue, {}), children: "完成" })
3343
- }
3344
- )
3345
- ] })
3346
- }
3347
- ], h = !y && !f && S.length === 0;
3348
- return /* @__PURE__ */ n("div", { children: [
3349
- /* @__PURE__ */ e(
3350
- me,
3351
- {
3352
- title: "项目中心",
3353
- subtitle: "管理由 CEO 立项的项目与 Agent 对话上下文",
3354
- breadcrumb: [{ label: "项目中心" }]
3355
- }
3356
- ),
3357
- f && !y && /* @__PURE__ */ e("div", { style: { marginBottom: 16 }, children: /* @__PURE__ */ e(Ht, { error: f, onRetry: T }) }),
3358
- /* @__PURE__ */ n("div", { style: {
3359
- background: "#ffffff",
3360
- borderRadius: 16,
3361
- padding: 20,
3362
- boxShadow: "0 1px 3px rgba(15, 23, 42, 0.04), 0 1px 2px rgba(15, 23, 42, 0.06)"
3363
- }, children: [
3364
- /* @__PURE__ */ e(
3365
- we,
3366
- {
3367
- activeKey: i,
3368
- onChange: r,
3369
- tabBarExtraContent: /* @__PURE__ */ n(R, { children: [
3370
- /* @__PURE__ */ e(_, { icon: /* @__PURE__ */ e(ee, {}), onClick: T, loading: y, children: "刷新" }),
3371
- /* @__PURE__ */ e(
3372
- _,
3373
- {
3374
- type: "primary",
3375
- icon: /* @__PURE__ */ e(yt, {}),
3376
- onClick: () => t("/project/new"),
3377
- children: "新建项目"
3378
- }
3379
- )
3380
- ] }),
3381
- items: [
3382
- { key: "mine", label: "我的进行中" },
3383
- { key: "OPEN", label: "待开始" },
3384
- { key: "IN_PROGRESS", label: "进行中" },
3385
- { key: "COMPLETED", label: "已完成" }
3386
- ]
3387
- }
3388
- ),
3389
- h ? /* @__PURE__ */ e(
3390
- Kt,
3391
- {
3392
- title: "还没有项目",
3393
- description: "立项一个项目, 让 Agent 围绕目标持续推进对话与任务",
3394
- actionText: "新建第一个项目",
3395
- onAction: () => t("/project/new")
3396
- }
3397
- ) : /* @__PURE__ */ e(
3398
- H,
3399
- {
3400
- rowKey: "id",
3401
- columns: m,
3402
- dataSource: S,
3403
- loading: y,
3404
- size: "middle",
3405
- pagination: { pageSize: 20 }
3406
- }
3407
- )
3408
- ] })
3409
- ] });
3410
- }
3411
- const Dn = [
3412
- { value: "general", label: "通用助手" },
3413
- { value: "analyst", label: "分析师" },
3414
- { value: "writer", label: "写手" },
3415
- { value: "pm", label: "产品经理" },
3416
- { value: "ops", label: "运营" }
3417
- ];
3418
- function Bn() {
3419
- const t = be(), [i] = St(), [r] = E.useForm(), [S, l] = g(!1), [y, s] = g("from-subscribe"), [f, w] = g([]), [T, A] = g([]), [m, h] = g(!1), [d, c] = g([]), [v, L] = g(null);
3420
- K(() => {
3421
- const k = i.get("subscriptionId"), $ = i.get("itemIds");
3422
- k && (L(Number(k)), r.setFieldValue("sourceSubscriptionId", Number(k)), u(k)), $ && c($.split(",").map(Number).filter(Boolean));
3423
- }, [i]), K(() => {
3424
- C();
3425
- }, []);
3426
- const C = async () => {
3427
- try {
3428
- const k = await N.get("/subscribe/subscription/list"), $ = (k == null ? void 0 : k.data) ?? k ?? [];
3429
- w(Array.isArray($) ? $.filter((X) => X.status === "VERIFIED") : []);
3430
- } catch {
3431
- }
3432
- }, u = async (k) => {
3433
- h(!0);
3434
- try {
3435
- const $ = await N.get(`/subscribe/run/list?subscriptionId=${k}&limit=1`), X = ($ == null ? void 0 : $.data) ?? $ ?? [];
3436
- if (X.length === 0) {
3437
- A([]);
3438
- return;
3439
- }
3440
- const G = X[0], p = await N.get(`/subscribe/run/${G.id}/items?limit=100`), o = (p == null ? void 0 : p.data) ?? p ?? [];
3441
- A(Array.isArray(o) ? o : []);
3442
- } catch {
3443
- b.error("加载抽取项失败");
3444
- } finally {
3445
- h(!1);
3446
- }
3447
- };
3448
- return /* @__PURE__ */ e("div", { style: { padding: 24 }, children: /* @__PURE__ */ e(
3449
- P,
3450
- {
3451
- title: /* @__PURE__ */ n(R, { children: [
3452
- /* @__PURE__ */ e(_, { type: "text", icon: /* @__PURE__ */ e(ft, {}), onClick: () => t("/project/list") }),
3453
- /* @__PURE__ */ e(je, {}),
3454
- "新建项目 (立项)"
3455
- ] }),
3456
- extra: /* @__PURE__ */ n(R, { children: [
3457
- /* @__PURE__ */ e(_, { onClick: () => t("/project/list"), children: "取消" }),
3458
- /* @__PURE__ */ e(
3459
- _,
3460
- {
3461
- type: "primary",
3462
- icon: /* @__PURE__ */ e(gt, {}),
3463
- loading: S,
3464
- onClick: async () => {
3465
- try {
3466
- const k = await r.validateFields();
3467
- if (y === "from-subscribe" && d.length === 0) {
3468
- b.warning("请至少选 1 个 item");
3469
- return;
3470
- }
3471
- l(!0);
3472
- const $ = {
3473
- ...k,
3474
- sourceItemIds: y === "from-subscribe" ? d.map(String) : null
3475
- }, X = y === "from-subscribe" ? "/project/create-from-items" : "/project/create-manual", G = await N.post(X, $);
3476
- if (G && G.success !== !1) {
3477
- const p = G.data ?? G;
3478
- b.success("立项成功"), t(`/project/${p.id}`);
3479
- } else
3480
- b.error((G == null ? void 0 : G.message) || "立项失败");
3481
- } catch (k) {
3482
- k != null && k.errorFields || b.error("立项失败: " + ((k == null ? void 0 : k.message) || ""));
3483
- } finally {
3484
- l(!1);
3485
- }
3486
- },
3487
- children: "立项"
3488
- }
3489
- )
3490
- ] }),
3491
- children: /* @__PURE__ */ n(E, { form: r, layout: "vertical", initialValues: { agentRole: "general" }, children: [
3492
- /* @__PURE__ */ e(E.Item, { label: "来源", children: /* @__PURE__ */ n(ne.Group, { value: y, onChange: (k) => s(k.target.value), children: [
3493
- /* @__PURE__ */ e(ne.Button, { value: "from-subscribe", children: "从订阅线索立项 (主路径)" }),
3494
- /* @__PURE__ */ e(ne.Button, { value: "manual", children: "手动立项 (无源数据)" })
3495
- ] }) }),
3496
- /* @__PURE__ */ e(E.Item, { label: "项目名称", name: "name", rules: [{ required: !0, message: "请输入名称" }], children: /* @__PURE__ */ e(B, { placeholder: "例如: 跟进 GitHub 高优 Issue" }) }),
3497
- /* @__PURE__ */ e(E.Item, { label: "项目描述", name: "description", children: /* @__PURE__ */ e(B.TextArea, { rows: 2, placeholder: "(可选) 这个项目要解决什么?" }) }),
3498
- y === "from-subscribe" && /* @__PURE__ */ n(P, { type: "inner", title: "源数据", style: { marginBottom: 16 }, children: [
3499
- /* @__PURE__ */ e(
3500
- E.Item,
3501
- {
3502
- label: "选择订阅",
3503
- name: "sourceSubscriptionId",
3504
- rules: [{ required: !0, message: "请选订阅" }],
3505
- children: /* @__PURE__ */ e(
3506
- W,
3507
- {
3508
- placeholder: "选择订阅 (拉取最近一次 run 的 items)",
3509
- options: f.map((k) => ({ value: k.id, label: `#${k.id} ${k.name}` })),
3510
- onChange: (k) => {
3511
- L(k), u(k), c([]);
3512
- }
3513
- }
3514
- )
3515
- }
3516
- ),
3517
- v && /* @__PURE__ */ n(_e, { spinning: m, children: [
3518
- /* @__PURE__ */ n("div", { style: { marginBottom: 8 }, children: [
3519
- /* @__PURE__ */ n(x, { color: "blue", children: [
3520
- "已选 ",
3521
- d.length,
3522
- " / ",
3523
- T.length
3524
- ] }),
3525
- /* @__PURE__ */ e(
3526
- _,
3527
- {
3528
- size: "small",
3529
- onClick: () => c(T.map((k) => k.id)),
3530
- children: "全选"
3531
- }
3532
- ),
3533
- /* @__PURE__ */ e(
3534
- _,
3535
- {
3536
- size: "small",
3537
- onClick: () => c([]),
3538
- style: { marginLeft: 4 },
3539
- children: "清空"
3540
- }
3541
- )
3542
- ] }),
3543
- /* @__PURE__ */ e(
3544
- H,
3545
- {
3546
- rowKey: "id",
3547
- size: "small",
3548
- dataSource: T,
3549
- pagination: { pageSize: 10 },
3550
- rowSelection: {
3551
- selectedRowKeys: d,
3552
- onChange: c
3553
- },
3554
- columns: [
3555
- { title: "id", dataIndex: "dedupKey", width: 160, ellipsis: !0 },
3556
- {
3557
- title: "title",
3558
- dataIndex: "normalized",
3559
- render: (k) => {
3560
- try {
3561
- return JSON.parse(k).title || "(无)";
3562
- } catch {
3563
- return k;
3564
- }
3565
- }
3566
- },
3567
- {
3568
- title: "fetched",
3569
- dataIndex: "fetchedAt",
3570
- width: 150,
3571
- render: (k) => k ? new Date(k).toLocaleString() : "-"
3572
- }
3573
- ]
3574
- }
3575
- )
3576
- ] })
3577
- ] }),
3578
- /* @__PURE__ */ n(P, { type: "inner", title: "Agent 配置", style: { marginBottom: 16 }, children: [
3579
- /* @__PURE__ */ e(E.Item, { label: "Agent 角色", name: "agentRole", extra: "决定 system prompt 的语气 / 视角", children: /* @__PURE__ */ e(W, { options: Dn }) }),
3580
- /* @__PURE__ */ e(
3581
- E.Item,
3582
- {
3583
- label: "模型 (可选)",
3584
- name: "modelCode",
3585
- extra: "留空走默认 (智能中心 LLM 凭证里第一个 enabled)",
3586
- children: /* @__PURE__ */ e(B, { placeholder: "例如: gpt-4 / deepseek-chat" })
3587
- }
3588
- )
3589
- ] }),
3590
- /* @__PURE__ */ e(
3591
- J,
3592
- {
3593
- type: "info",
3594
- showIcon: !0,
3595
- title: "立项后源数据会被快照 (context_snapshot), 后续订阅更新不会影响项目上下文."
3596
- }
3597
- )
3598
- ] })
3599
- }
3600
- ) });
3601
- }
3602
- const at = {
3603
- USER: { color: "blue", icon: /* @__PURE__ */ e(ut, {}), label: "CEO" },
3604
- ASSISTANT: { color: "purple", icon: /* @__PURE__ */ e(Le, {}), label: "Agent" },
3605
- SYSTEM: { color: "default", icon: null, label: "系统" }
3606
- }, qn = {
3607
- OPEN: { color: "blue", text: "待开始" },
3608
- IN_PROGRESS: { color: "green", text: "进行中" },
3609
- COMPLETED: { color: "default", text: "已完成" },
3610
- ARCHIVED: { color: "default", text: "已归档" }
3611
- };
3612
- function jn() {
3613
- const { id: t } = st(), i = be(), [r, S] = g(null), [l, y] = g([]), [s, f] = g(""), [w, T] = g(!1), A = it(null);
3614
- K(() => {
3615
- t && m();
3616
- }, [t]), K(() => {
3617
- A.current && (A.current.scrollTop = A.current.scrollHeight);
3618
- }, [l]);
3619
- const m = async () => {
3620
- try {
3621
- const [v, L] = await Promise.all([
3622
- N.get(`/project/${t}`),
3623
- N.get(`/project/${t}/messages`)
3624
- ]);
3625
- S((v == null ? void 0 : v.data) ?? v), y(Array.isArray((L == null ? void 0 : L.data) ?? L) ? (L == null ? void 0 : L.data) ?? L : []);
3626
- } catch {
3627
- b.error("加载项目失败");
3628
- }
3629
- }, h = async () => {
3630
- if (!s.trim()) return;
3631
- const v = s.trim();
3632
- f(""), T(!0);
3633
- const L = { seq: -1, role: "USER", content: v, createdAt: (/* @__PURE__ */ new Date()).toISOString() };
3634
- y((C) => [...C, L]);
3635
- try {
3636
- const C = await N.post(`/project/${t}/chat`, { message: v });
3637
- if (C && C.success !== !1) {
3638
- const a = (C.data ?? C).message;
3639
- y((k) => [...k.filter((X) => X.seq !== -1), ...a ? [a] : []]), setTimeout(m, 100);
3640
- } else
3641
- b.error((C == null ? void 0 : C.message) || "发送失败");
3642
- } catch (C) {
3643
- b.error("发送失败: " + ((C == null ? void 0 : C.message) || ""));
3644
- } finally {
3645
- T(!1);
3646
- }
3647
- }, d = async () => {
3648
- try {
3649
- const v = await N.post(`/project/${t}/status?status=COMPLETED`);
3650
- v && v.success !== !1 && (b.success("已标记完成"), m());
3651
- } catch {
3652
- b.error("操作失败");
3653
- }
3654
- };
3655
- if (!r) return /* @__PURE__ */ e("div", { style: { padding: 24 }, children: /* @__PURE__ */ e(_e, {}) });
3656
- const c = qn[r.status] || { color: "default", text: r.status };
3657
- return /* @__PURE__ */ n("div", { style: { padding: 24, height: "calc(100vh - 64px)", display: "flex", flexDirection: "column", gap: 16 }, children: [
3658
- /* @__PURE__ */ n(
3659
- P,
3660
- {
3661
- title: /* @__PURE__ */ n(R, { children: [
3662
- /* @__PURE__ */ e(_, { type: "text", icon: /* @__PURE__ */ e(ft, {}), onClick: () => i("/project/list") }),
3663
- /* @__PURE__ */ e(je, {}),
3664
- /* @__PURE__ */ e("span", { style: { fontWeight: 500 }, children: r.name }),
3665
- /* @__PURE__ */ e(x, { color: c.color, children: c.text })
3666
- ] }),
3667
- extra: /* @__PURE__ */ n(R, { children: [
3668
- r.contextSize > 0 && /* @__PURE__ */ n(x, { color: "blue", children: [
3669
- "上下文 ",
3670
- r.contextSize,
3671
- " B"
3672
- ] }),
3673
- /* @__PURE__ */ e(x, { children: r.agentRole }),
3674
- r.modelCode && /* @__PURE__ */ e(x, { color: "purple", children: r.modelCode }),
3675
- r.status !== "COMPLETED" && r.status !== "ARCHIVED" && /* @__PURE__ */ e(qe, { title: "标记完成?", onConfirm: d, children: /* @__PURE__ */ e(_, { icon: /* @__PURE__ */ e(Ue, {}), children: "标记完成" }) })
3676
- ] }),
3677
- children: [
3678
- r.description && /* @__PURE__ */ e("div", { style: { color: "#666", marginBottom: 8 }, children: r.description }),
3679
- /* @__PURE__ */ n(R, { size: "large", children: [
3680
- /* @__PURE__ */ e(U, { title: "消息数", value: r.messageCount || 0 }),
3681
- r.sourceSubscriptionId && /* @__PURE__ */ e(U, { title: "来源订阅", value: `#${r.sourceSubscriptionId}` }),
3682
- /* @__PURE__ */ e(
3683
- U,
3684
- {
3685
- title: "立项",
3686
- value: r.createdAt ? new Date(r.createdAt).toLocaleString() : "-"
3687
- }
3688
- )
3689
- ] })
3690
- ]
3691
- }
3692
- ),
3693
- /* @__PURE__ */ n(
3694
- P,
3695
- {
3696
- style: { flex: 1, display: "flex", flexDirection: "column" },
3697
- styles: { body: { flex: 1, display: "flex", flexDirection: "column", padding: 0 } },
3698
- children: [
3699
- /* @__PURE__ */ e("div", { ref: A, style: { flex: 1, overflow: "auto", padding: 16, background: "#fafafa" }, children: l.length === 0 ? /* @__PURE__ */ e(dt, { description: "还没有消息, 跟 Agent 说点什么?" }) : /* @__PURE__ */ n(R, { orientation: "vertical", style: { width: "100%" }, size: "middle", children: [
3700
- l.map((v) => {
3701
- const L = at[v.role] || at.SYSTEM, C = v.role === "USER";
3702
- return /* @__PURE__ */ e("div", { style: {
3703
- display: "flex",
3704
- justifyContent: C ? "flex-end" : "flex-start"
3705
- }, children: /* @__PURE__ */ n("div", { style: {
3706
- maxWidth: "70%",
3707
- background: C ? "#1677ff" : "#fff",
3708
- color: C ? "#fff" : "#000",
3709
- border: C ? "none" : "1px solid #e8e8e8",
3710
- borderRadius: 8,
3711
- padding: "10px 14px",
3712
- boxShadow: "0 1px 2px rgba(0,0,0,0.04)"
3713
- }, children: [
3714
- /* @__PURE__ */ e("div", { style: { fontSize: 12, opacity: 0.7, marginBottom: 4 }, children: /* @__PURE__ */ n(R, { size: 4, children: [
3715
- L.icon,
3716
- L.label,
3717
- v.seq > 0 && /* @__PURE__ */ n("span", { children: [
3718
- "#",
3719
- v.seq
3720
- ] }),
3721
- v.latencyMs > 0 && /* @__PURE__ */ n("span", { children: [
3722
- "· ",
3723
- v.latencyMs,
3724
- "ms"
3725
- ] }),
3726
- v.modelCode && /* @__PURE__ */ n("span", { children: [
3727
- "· ",
3728
- v.modelCode
3729
- ] })
3730
- ] }) }),
3731
- /* @__PURE__ */ e("div", { style: { whiteSpace: "pre-wrap", wordBreak: "break-word" }, children: v.content })
3732
- ] }) }, v.id || v.seq);
3733
- }),
3734
- w && /* @__PURE__ */ e("div", { style: { display: "flex", justifyContent: "flex-start" }, children: /* @__PURE__ */ n("div", { style: {
3735
- background: "#fff",
3736
- border: "1px solid #e8e8e8",
3737
- borderRadius: 8,
3738
- padding: "10px 14px"
3739
- }, children: [
3740
- /* @__PURE__ */ e(_e, { size: "small" }),
3741
- " 思考中..."
3742
- ] }) })
3743
- ] }) }),
3744
- r.status === "COMPLETED" || r.status === "ARCHIVED" ? /* @__PURE__ */ e(
3745
- J,
3746
- {
3747
- style: { margin: 12, marginBottom: 0 },
3748
- type: "info",
3749
- title: "项目已完成 / 归档, 不再接受新消息",
3750
- showIcon: !0
3751
- }
3752
- ) : /* @__PURE__ */ n("div", { style: { borderTop: "1px solid #f0f0f0", padding: 12, display: "flex", gap: 8 }, children: [
3753
- /* @__PURE__ */ e(
3754
- B.TextArea,
3755
- {
3756
- value: s,
3757
- onChange: (v) => f(v.target.value),
3758
- onPressEnter: (v) => {
3759
- v.shiftKey || (v.preventDefault(), h());
3760
- },
3761
- placeholder: "输入消息, Enter 发送 (Shift+Enter 换行)",
3762
- autoSize: { minRows: 1, maxRows: 6 },
3763
- disabled: w
3764
- }
3765
- ),
3766
- /* @__PURE__ */ e(
3767
- _,
3768
- {
3769
- type: "primary",
3770
- icon: /* @__PURE__ */ e(Bt, {}),
3771
- loading: w,
3772
- onClick: h,
3773
- disabled: !s.trim(),
3774
- children: "发送"
3775
- }
3776
- )
3777
- ] })
3778
- ]
3779
- }
3780
- )
3781
- ] });
3782
- }
3783
- function Fn() {
3784
- return /* @__PURE__ */ n(ot, { children: [
3785
- /* @__PURE__ */ e(re, { index: !0, element: /* @__PURE__ */ e(ct, { to: "list", replace: !0 }) }),
3786
- /* @__PURE__ */ e(re, { path: "list", element: /* @__PURE__ */ e(Nn, {}) }),
3787
- /* @__PURE__ */ e(re, { path: "new", element: /* @__PURE__ */ e(Bn, {}) }),
3788
- /* @__PURE__ */ e(re, { path: ":id", element: /* @__PURE__ */ e(jn, {}) })
3789
- ] });
3790
- }
3791
- const ir = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
3792
- __proto__: null,
3793
- default: Fn
3794
- }, Symbol.toStringTag, { value: "Module" }));
3795
- export {
3796
- rr as C,
3797
- De as E,
3798
- Sn as M,
3799
- lr as O,
3800
- Fn as P,
3801
- xn as R,
3802
- $n as S,
3803
- bn as T,
3804
- Zn as Z,
3805
- Yn as a,
3806
- Be as b,
3807
- nr as c,
3808
- Qn as d,
3809
- In as e,
3810
- gn as f,
3811
- Ke as g,
3812
- er as h,
3813
- ln as i,
3814
- ar as j,
3815
- ir as k,
3816
- N as r,
3817
- cn as s
3818
- };