@yuku123/z-team-component 0.2.26 → 0.2.29

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.
@@ -0,0 +1,3818 @@
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
+ };