@yuku123/z-frontend-common 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/z-frontend-common.css +1 -0
- package/dist/z-frontend-common.es.js +6153 -300
- package/dist/z-frontend-common.umd.js +22 -4
- package/package.json +5 -4
- package/src/components/Ctc/Layout.jsx +328 -0
- package/src/components/Ctc/Layout.module.css +145 -0
- package/src/components/Ctc/agentTeam/index.tsx +308 -0
- package/src/components/Ctc/login/AuthPage.module.css +26 -0
- package/src/components/Ctc/login/AuthPage.tsx +235 -0
- package/src/components/Ctc/login/index.less +49 -0
- package/src/components/Ctc/login/index.tsx +142 -0
- package/src/components/Ctc/userPanel/index.tsx +998 -0
- package/src/components/Ctc/webide/index.tsx +272 -0
- package/src/components/LowCode/LowCodeModel.jsx +962 -0
- package/src/components/LowCode/LowCodePage.jsx +31 -0
- package/src/components/LowCode/LowCodeRuntime.jsx +335 -0
- package/src/components/LowCode/MaterializePage.jsx +235 -0
- package/src/components/LowCode/index.js +1 -0
- package/src/components/MockPlatform/CurlImportModal.jsx +362 -0
- package/src/components/MockPlatform/EndpointsTab.jsx +509 -0
- package/src/components/MockPlatform/EnvironmentsTab.jsx +212 -0
- package/src/components/MockPlatform/MockTemplateHelper.jsx +200 -0
- package/src/components/MockPlatform/OpenApiImportModal.jsx +305 -0
- package/src/components/MockPlatform/RecordingsTab.jsx +397 -0
- package/src/components/MockPlatform/RequestLogsTab.jsx +239 -0
- package/src/components/MockPlatform/ScenariosTab.jsx +236 -0
- package/src/components/MockPlatform/TestCasesTab.jsx +462 -0
- package/src/components/MockPlatform/index.jsx +127 -0
- package/src/components/Overview.jsx +74 -0
- package/src/index.js +26 -27
- package/src/services/agentTeam.js +7 -0
- package/src/services/api.js +84 -0
- package/src/services/ctcAc.js +7 -0
- package/src/services/ctcAcDomain.js +7 -0
- package/src/services/ctcAuthorization.js +7 -0
- package/src/services/ctcSurl.js +7 -0
- package/src/services/ctcUser.js +7 -0
- package/src/services/job.js +7 -0
- package/src/services/metaApp.js +7 -0
- package/src/services/privateConfig.js +7 -0
- package/src/services/request.js +6 -0
- package/src/services/webide.js +6 -0
- package/src/services/workspace.js +21 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
(function(
|
|
1
|
+
(function($,t){typeof exports=="object"&&typeof module<"u"?t(exports,require("react"),require("antd"),require("@ant-design/icons"),require("react-router-dom"),require("axios"),require("@ant-design/pro-components")):typeof define=="function"&&define.amd?define(["exports","react","antd","@ant-design/icons","react-router-dom","axios","@ant-design/pro-components"],t):($=typeof globalThis<"u"?globalThis:$||self,t($.ZFrontendCommon={},$.React,$.antd,$.icons,$.ReactRouterDOM,$.axios,$.ProComponents))})(this,(function($,t,s,i,te,Ye,me){"use strict";var _t=Object.defineProperty;var Lt=($,t,s)=>t in $?_t($,t,{enumerable:!0,configurable:!0,writable:!0,value:s}):$[t]=s;var vs=($,t,s)=>Lt($,typeof t!="symbol"?t+"":t,s);var Oe={exports:{}},we={};/**
|
|
2
2
|
* @license React
|
|
3
3
|
* react-jsx-runtime.production.js
|
|
4
4
|
*
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* This source code is licensed under the MIT license found in the
|
|
8
8
|
* LICENSE file in the root directory of this source tree.
|
|
9
|
-
*/var
|
|
9
|
+
*/var Ve;function Es(){if(Ve)return we;Ve=1;var r=Symbol.for("react.transitional.element"),c=Symbol.for("react.fragment");function o(y,k,S){var d=null;if(S!==void 0&&(d=""+S),k.key!==void 0&&(d=""+k.key),"key"in k){S={};for(var g in k)g!=="key"&&(S[g]=k[g])}else S=k;return k=S.ref,{$$typeof:r,type:y,key:d,ref:k!==void 0?k:null,props:S}}return we.Fragment=c,we.jsx=o,we.jsxs=o,we}var Ie={};/**
|
|
10
10
|
* @license React
|
|
11
11
|
* react-jsx-runtime.development.js
|
|
12
12
|
*
|
|
@@ -14,9 +14,27 @@
|
|
|
14
14
|
*
|
|
15
15
|
* This source code is licensed under the MIT license found in the
|
|
16
16
|
* LICENSE file in the root directory of this source tree.
|
|
17
|
-
*/var
|
|
17
|
+
*/var Xe;function Os(){return Xe||(Xe=1,process.env.NODE_ENV!=="production"&&(function(){function r(a){if(a==null)return null;if(typeof a=="function")return a.$$typeof===n?null:a.displayName||a.name||null;if(typeof a=="string")return a;switch(a){case v:return"Fragment";case b:return"Profiler";case N:return"StrictMode";case M:return"Suspense";case U:return"SuspenseList";case l:return"Activity"}if(typeof a=="object")switch(typeof a.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),a.$$typeof){case B:return"Portal";case P:return a.displayName||"Context";case w:return(a._context.displayName||"Context")+".Consumer";case f:var D=a.render;return a=a.displayName,a||(a=D.displayName||D.name||"",a=a!==""?"ForwardRef("+a+")":"ForwardRef"),a;case J:return D=a.displayName||null,D!==null?D:r(a.type)||"Memo";case H:D=a._payload,a=a._init;try{return r(a(D))}catch{}}return null}function c(a){return""+a}function o(a){try{c(a);var D=!1}catch{D=!0}if(D){D=console;var R=D.error,W=typeof Symbol=="function"&&Symbol.toStringTag&&a[Symbol.toStringTag]||a.constructor.name||"Object";return R.call(D,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",W),c(a)}}function y(a){if(a===v)return"<>";if(typeof a=="object"&&a!==null&&a.$$typeof===H)return"<...>";try{var D=r(a);return D?"<"+D+">":"<...>"}catch{return"<...>"}}function k(){var a=_.A;return a===null?null:a.getOwner()}function S(){return Error("react-stack-top-frame")}function d(a){if(T.call(a,"key")){var D=Object.getOwnPropertyDescriptor(a,"key").get;if(D&&D.isReactWarning)return!1}return a.key!==void 0}function g(a,D){function R(){re||(re=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",D))}R.isReactWarning=!0,Object.defineProperty(a,"key",{get:R,configurable:!0})}function E(){var a=r(this.type);return ae[a]||(ae[a]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),a=this.props.ref,a!==void 0?a:null}function C(a,D,R,W,se,ce){var Z=R.ref;return a={$$typeof:j,type:a,key:D,props:R,_owner:W},(Z!==void 0?Z:null)!==null?Object.defineProperty(a,"ref",{enumerable:!1,get:E}):Object.defineProperty(a,"ref",{enumerable:!1,value:null}),a._store={},Object.defineProperty(a._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(a,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(a,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:se}),Object.defineProperty(a,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:ce}),Object.freeze&&(Object.freeze(a.props),Object.freeze(a)),a}function O(a,D,R,W,se,ce){var Z=D.children;if(Z!==void 0)if(W)if(A(Z)){for(W=0;W<Z.length;W++)m(Z[W]);Object.freeze&&Object.freeze(Z)}else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");else m(Z);if(T.call(D,"key")){Z=r(a);var de=Object.keys(D).filter(function(xe){return xe!=="key"});W=0<de.length?"{key: someKey, "+de.join(": ..., ")+": ...}":"{key: someKey}",p[Z+W]||(de=0<de.length?"{"+de.join(": ..., ")+": ...}":"{}",console.error(`A props object containing a "key" prop is being spread into JSX:
|
|
18
18
|
let props = %s;
|
|
19
19
|
<%s {...props} />
|
|
20
20
|
React keys must be passed directly to JSX without using spread:
|
|
21
21
|
let props = %s;
|
|
22
|
-
<%s key={someKey} {...props} />`,f,d,x,d),ee[d+f]=!0)}if(d=null,u!==void 0&&(i(u),d=""+u),h(r)&&(i(r.key),d=""+r.key),"key"in r){u={};for(var M in r)M!=="key"&&(u[M]=r[M])}else u=r;return d&&R(u,typeof e=="function"?e.displayName||e.name||"Unknown":e),b(e,d,u,c(),S,L)}function J(e){V(e)?e._store&&(e._store.validated=1):typeof e=="object"&&e!==null&&e.$$typeof===C&&(e._payload.status==="fulfilled"?V(e._payload.value)&&e._payload.value._store&&(e._payload.value._store.validated=1):e._store&&(e._store.validated=1))}function V(e){return typeof e=="object"&&e!==null&&e.$$typeof===G}var T=p,G=Symbol.for("react.transitional.element"),fe=Symbol.for("react.portal"),P=Symbol.for("react.fragment"),de=Symbol.for("react.strict_mode"),me=Symbol.for("react.profiler"),pe=Symbol.for("react.consumer"),he=Symbol.for("react.context"),ge=Symbol.for("react.forward_ref"),Re=Symbol.for("react.suspense"),ye=Symbol.for("react.suspense_list"),Ee=Symbol.for("react.memo"),C=Symbol.for("react.lazy"),be=Symbol.for("react.activity"),xe=Symbol.for("react.client.reference"),I=T.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,H=Object.prototype.hasOwnProperty,ve=Array.isArray,N=console.createTask?console.createTask:function(){return null};T={react_stack_bottom_frame:function(e){return e()}};var K,X={},Z=T.react_stack_bottom_frame.bind(T,o)(),Q=N(m(o)),ee={};_.Fragment=P,_.jsx=function(e,r,u){var f=1e4>I.recentlyCreatedOwnerStacks++;return g(e,r,u,!1,f?Error("react-stack-top-frame"):Z,f?N(m(e)):Q)},_.jsxs=function(e,r,u){var f=1e4>I.recentlyCreatedOwnerStacks++;return g(e,r,u,!0,f?Error("react-stack-top-frame"):Z,f?N(m(e)):Q)}})()),_}var Y;function se(){return Y||(Y=1,process.env.NODE_ENV==="production"?j.exports=ne():j.exports=oe()),j.exports}var t=se();const{Header:ae,Sider:ie,Content:le}=a.Layout;function z({menuItems:n=[],appTitle:l="One Company",appShort:i="OC",headerExtra:m,loading:c=!1}){const[o,h]=p.useState(!1),R=w.useNavigate(),y=w.useLocation(),b=({key:g})=>{R(g)};return t.jsxs(a.Layout,{style:{minHeight:"100vh"},children:[t.jsxs(ie,{trigger:null,collapsible:!0,collapsed:o,children:[t.jsx("div",{style:{height:64,display:"flex",alignItems:"center",justifyContent:"center",color:"white",fontSize:o?14:18,fontWeight:"bold"},children:o?i:l}),c?t.jsx("div",{style:{padding:16,textAlign:"center"},children:t.jsx(a.Spin,{size:"small"})}):t.jsx(a.Menu,{theme:"dark",mode:"inline",selectedKeys:[y.pathname],items:n,onClick:b})]}),t.jsxs(a.Layout,{children:[t.jsxs(ae,{style:{padding:"0 16px",background:"#fff",display:"flex",alignItems:"center",justifyContent:"space-between"},children:[t.jsx("span",{onClick:()=>h(!o),style:{fontSize:18,cursor:"pointer"},children:o?t.jsx(E.MenuUnfoldOutlined,{}):t.jsx(E.MenuFoldOutlined,{})}),m]}),t.jsx(le,{style:{margin:16,padding:24,background:"#fff",minHeight:280},children:t.jsx(w.Outlet,{})})]})]})}const O={1:{color:"green",text:"正常"},0:{color:"red",text:"禁用"},pending:{color:"orange",text:"待处理"},approved:{color:"blue",text:"已通过"},rejected:{color:"red",text:"已拒绝"}};function D({status:n,map:l}){const i=(l==null?void 0:l[n])||O[n]||{color:"default",text:String(n)};return t.jsx(a.Tag,{color:i.color,children:i.text})}function ue(n){if(n&&typeof n=="object"&&"code"in n&&"data"in n){const l=n;return l.code!==200?Promise.reject(new Error(l.message||"请求失败")):l.data}return n}function U(n,l={}){const{tokenKey:i="token",userInfoKey:m="userInfo",unauthorizedRedirect:c="/login"}=l;n.interceptors.request.use(o=>{const h=localStorage.getItem(i);return h&&(o.headers.Authorization=`Bearer ${h}`),o}),n.interceptors.response.use(o=>ue(o.data),o=>{var h,R,y;return((h=o.response)==null?void 0:h.status)===401?(localStorage.removeItem(i),localStorage.removeItem(m),window.location.href=c):((R=o.response)==null?void 0:R.status)===403?console.error("没有权限访问该资源"):((y=o.response)==null?void 0:y.status)===500&&console.error("服务器内部错误"),Promise.reject(o)})}function k(n={}){const l=te.create({baseURL:n.baseURL??"/api",timeout:n.timeout??1e4});return U(l,{tokenKey:n.tokenKey,userInfoKey:n.userInfoKey,unauthorizedRedirect:n.unauthorizedRedirect}),l}const A=k(),B=k();function W({title:n="统一管理平台",loginApi:l="/auth/login",redirectUrl:i="/",onSuccess:m}){const[c,o]=p.useState(!1),h=async R=>{var y,b;o(!0);try{const g=await A.post(l,R);g.token?(localStorage.setItem("token",g.token),localStorage.setItem("userInfo",JSON.stringify(g.user||g)),a.message.success("登录成功"),m?m(g):window.location.href=i):a.message.error("登录失败:未获取到 token")}catch(g){a.message.error(((b=(y=g.response)==null?void 0:y.data)==null?void 0:b.message)||g.message||"登录失败")}finally{o(!1)}};return t.jsx("div",{style:{height:"100vh",display:"flex",justifyContent:"center",alignItems:"center",background:"#f0f2f5"},children:t.jsx(a.Card,{title:n,style:{width:400},children:t.jsxs(a.Form,{onFinish:h,size:"large",children:[t.jsx(a.Form.Item,{name:"username",rules:[{required:!0,message:"请输入用户名"}],children:t.jsx(a.Input,{prefix:t.jsx(E.UserOutlined,{}),placeholder:"用户名"})}),t.jsx(a.Form.Item,{name:"password",rules:[{required:!0,message:"请输入密码"}],children:t.jsx(a.Input.Password,{prefix:t.jsx(E.LockOutlined,{}),placeholder:"密码"})}),t.jsx(a.Form.Item,{children:t.jsx(a.Button,{type:"primary",htmlType:"submit",loading:c,block:!0,children:"登 录"})})]})})})}class $ extends p.Component{constructor(i){super(i);re(this,"handleReset",()=>{this.setState({hasError:!1,error:null,errorInfo:null}),typeof this.props.onReset=="function"&&this.props.onReset()});this.state={hasError:!1,error:null,errorInfo:null}}static getDerivedStateFromError(i){return{hasError:!0,error:i}}componentDidCatch(i,m){console.error("[ErrorBoundary] caught error:",i,m),this.setState({errorInfo:m})}render(){if(!this.state.hasError)return this.props.children;const{fallbackTitle:i="组件加载失败",fallbackDescription:m,showReload:c=!0}=this.props,o=this.state.error&&(this.state.error.message||String(this.state.error))||"未知错误";return t.jsxs("div",{style:{padding:24,background:"#fff2f0",border:"1px solid #ffccc7",borderRadius:8,minHeight:200},children:[t.jsx(a.Alert,{type:"error",showIcon:!0,icon:t.jsx(E.BugOutlined,{}),message:i,description:t.jsxs("div",{children:[t.jsx("div",{style:{marginBottom:8},children:m||"当前组件发生了异常,已被错误边界捕获。其他功能仍可正常使用。"}),t.jsx("div",{style:{fontFamily:"Menlo, Monaco, Consolas, monospace",fontSize:12,color:"#cf1322",background:"#fff",padding:8,borderRadius:4,border:"1px solid #ffccc7",wordBreak:"break-word",whiteSpace:"pre-wrap"},children:o})]})}),c&&t.jsx(a.Space,{style:{marginTop:16},children:t.jsx(a.Button,{icon:t.jsx(E.ReloadOutlined,{}),onClick:this.handleReset,children:"重试"})})]})}}const ce={AppLayout:z,StatusTag:D,defaultStatusMap:O,LoginPage:W,ErrorBoundary:$,request:A,authRequest:B,createRequest:k};s.AppLayout=z,s.ErrorBoundary=$,s.LoginPage=W,s.StatusTag=D,s.authRequest=B,s.createRequest=k,s.default=ce,s.defaultStatusMap=O,s.request=A,s.setupInterceptors=U,Object.defineProperties(s,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
|
|
22
|
+
<%s key={someKey} {...props} />`,W,Z,de,Z),p[Z+W]=!0)}if(Z=null,R!==void 0&&(o(R),Z=""+R),d(D)&&(o(D.key),Z=""+D.key),"key"in D){R={};for(var fe in D)fe!=="key"&&(R[fe]=D[fe])}else R=D;return Z&&g(R,typeof a=="function"?a.displayName||a.name||"Unknown":a),C(a,Z,R,k(),se,ce)}function m(a){x(a)?a._store&&(a._store.validated=1):typeof a=="object"&&a!==null&&a.$$typeof===H&&(a._payload.status==="fulfilled"?x(a._payload.value)&&a._payload.value._store&&(a._payload.value._store.validated=1):a._store&&(a._store.validated=1))}function x(a){return typeof a=="object"&&a!==null&&a.$$typeof===j}var z=t,j=Symbol.for("react.transitional.element"),B=Symbol.for("react.portal"),v=Symbol.for("react.fragment"),N=Symbol.for("react.strict_mode"),b=Symbol.for("react.profiler"),w=Symbol.for("react.consumer"),P=Symbol.for("react.context"),f=Symbol.for("react.forward_ref"),M=Symbol.for("react.suspense"),U=Symbol.for("react.suspense_list"),J=Symbol.for("react.memo"),H=Symbol.for("react.lazy"),l=Symbol.for("react.activity"),n=Symbol.for("react.client.reference"),_=z.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,T=Object.prototype.hasOwnProperty,A=Array.isArray,V=console.createTask?console.createTask:function(){return null};z={react_stack_bottom_frame:function(a){return a()}};var re,ae={},ne=z.react_stack_bottom_frame.bind(z,S)(),I=V(y(S)),p={};Ie.Fragment=v,Ie.jsx=function(a,D,R){var W=1e4>_.recentlyCreatedOwnerStacks++;return O(a,D,R,!1,W?Error("react-stack-top-frame"):ne,W?V(y(a)):I)},Ie.jsxs=function(a,D,R){var W=1e4>_.recentlyCreatedOwnerStacks++;return O(a,D,R,!0,W?Error("react-stack-top-frame"):ne,W?V(y(a)):I)}})()),Ie}var Ze;function Fs(){return Ze||(Ze=1,process.env.NODE_ENV==="production"?Oe.exports=Es():Oe.exports=Os()),Oe.exports}var e=Fs();const{Header:Ps,Sider:Ns,Content:As}=s.Layout;function Ds({menuItems:r=[],appTitle:c="One Company",appShort:o="OC",headerExtra:y,loading:k=!1}){const[S,d]=t.useState(!1),g=te.useNavigate(),E=te.useLocation(),C=({key:O})=>{g(O)};return e.jsxs(s.Layout,{style:{minHeight:"100vh"},children:[e.jsxs(Ns,{trigger:null,collapsible:!0,collapsed:S,children:[e.jsx("div",{style:{height:64,display:"flex",alignItems:"center",justifyContent:"center",color:"white",fontSize:S?14:18,fontWeight:"bold"},children:S?o:c}),k?e.jsx("div",{style:{padding:16,textAlign:"center"},children:e.jsx(s.Spin,{size:"small"})}):e.jsx(s.Menu,{theme:"dark",mode:"inline",selectedKeys:[E.pathname],items:r,onClick:C})]}),e.jsxs(s.Layout,{children:[e.jsxs(Ps,{style:{padding:"0 16px",background:"#fff",display:"flex",alignItems:"center",justifyContent:"space-between"},children:[e.jsx("span",{onClick:()=>d(!S),style:{fontSize:18,cursor:"pointer"},children:S?e.jsx(i.MenuUnfoldOutlined,{}):e.jsx(i.MenuFoldOutlined,{})}),y]}),e.jsx(As,{style:{margin:16,padding:24,background:"#fff",minHeight:280},children:e.jsx(te.Outlet,{})})]})]})}const Qe={1:{color:"green",text:"正常"},0:{color:"red",text:"禁用"},pending:{color:"orange",text:"待处理"},approved:{color:"blue",text:"已通过"},rejected:{color:"red",text:"已拒绝"}};function zs({status:r,map:c}){const o=(c==null?void 0:c[r])||Qe[r]||{color:"default",text:String(r)};return e.jsx(s.Tag,{color:o.color,children:o.text})}function Ms(r){if(r&&typeof r=="object"&&"code"in r&&"data"in r){const c=r;return c.code!==200?Promise.reject(new Error(c.message||"请求失败")):c.data}return r}function es(r,c={}){const{tokenKey:o="token",userInfoKey:y="userInfo",unauthorizedRedirect:k="/login"}=c;r.interceptors.request.use(S=>{const d=localStorage.getItem(o);return d&&(S.headers.Authorization=`Bearer ${d}`),S}),r.interceptors.response.use(S=>Ms(S.data),S=>{var d,g,E;return((d=S.response)==null?void 0:d.status)===401?(localStorage.removeItem(o),localStorage.removeItem(y),window.location.href=k):((g=S.response)==null?void 0:g.status)===403?console.error("没有权限访问该资源"):((E=S.response)==null?void 0:E.status)===500&&console.error("服务器内部错误"),Promise.reject(S)})}function Re(r={}){const c=Ye.create({baseURL:r.baseURL??"/api",timeout:r.timeout??1e4});return es(c,{tokenKey:r.tokenKey,userInfoKey:r.userInfoKey,unauthorizedRedirect:r.unauthorizedRedirect}),c}const Y=Re(),ss=Re();function _s({title:r="统一管理平台",loginApi:c="/auth/login",redirectUrl:o="/",onSuccess:y}){const[k,S]=t.useState(!1),d=async g=>{var E,C;S(!0);try{const O=await Y.post(c,g);O.token?(localStorage.setItem("token",O.token),localStorage.setItem("userInfo",JSON.stringify(O.user||O)),s.message.success("登录成功"),y?y(O):window.location.href=o):s.message.error("登录失败:未获取到 token")}catch(O){s.message.error(((C=(E=O.response)==null?void 0:E.data)==null?void 0:C.message)||O.message||"登录失败")}finally{S(!1)}};return e.jsx("div",{style:{height:"100vh",display:"flex",justifyContent:"center",alignItems:"center",background:"#f0f2f5"},children:e.jsx(s.Card,{title:r,style:{width:400},children:e.jsxs(s.Form,{onFinish:d,size:"large",children:[e.jsx(s.Form.Item,{name:"username",rules:[{required:!0,message:"请输入用户名"}],children:e.jsx(s.Input,{prefix:e.jsx(i.UserOutlined,{}),placeholder:"用户名"})}),e.jsx(s.Form.Item,{name:"password",rules:[{required:!0,message:"请输入密码"}],children:e.jsx(s.Input.Password,{prefix:e.jsx(i.LockOutlined,{}),placeholder:"密码"})}),e.jsx(s.Form.Item,{children:e.jsx(s.Button,{type:"primary",htmlType:"submit",loading:k,block:!0,children:"登 录"})})]})})})}class Ls extends t.Component{constructor(o){super(o);vs(this,"handleReset",()=>{this.setState({hasError:!1,error:null,errorInfo:null}),typeof this.props.onReset=="function"&&this.props.onReset()});this.state={hasError:!1,error:null,errorInfo:null}}static getDerivedStateFromError(o){return{hasError:!0,error:o}}componentDidCatch(o,y){console.error("[ErrorBoundary] caught error:",o,y),this.setState({errorInfo:y})}render(){if(!this.state.hasError)return this.props.children;const{fallbackTitle:o="组件加载失败",fallbackDescription:y,showReload:k=!0}=this.props,S=this.state.error&&(this.state.error.message||String(this.state.error))||"未知错误";return e.jsxs("div",{style:{padding:24,background:"#fff2f0",border:"1px solid #ffccc7",borderRadius:8,minHeight:200},children:[e.jsx(s.Alert,{type:"error",showIcon:!0,icon:e.jsx(i.BugOutlined,{}),message:o,description:e.jsxs("div",{children:[e.jsx("div",{style:{marginBottom:8},children:y||"当前组件发生了异常,已被错误边界捕获。其他功能仍可正常使用。"}),e.jsx("div",{style:{fontFamily:"Menlo, Monaco, Consolas, monospace",fontSize:12,color:"#cf1322",background:"#fff",padding:8,borderRadius:4,border:"1px solid #ffccc7",wordBreak:"break-word",whiteSpace:"pre-wrap"},children:S})]})}),k&&e.jsx(s.Space,{style:{marginTop:16},children:e.jsx(s.Button,{icon:e.jsx(i.ReloadOutlined,{}),onClick:this.handleReset,children:"重试"})})]})}}const{Title:Bs,Text:$s,Paragraph:ts}=s.Typography,Rs=()=>e.jsxs("div",{style:{padding:"0"},children:[e.jsxs("div",{style:{marginBottom:24},children:[e.jsx(Bs,{level:2,style:{margin:0},children:"Z-One Company 统一管理平台"}),e.jsx($s,{type:"secondary",children:"一站式企业级应用管理平台"})]}),e.jsxs(s.Row,{gutter:16,style:{marginBottom:24},children:[e.jsx(s.Col,{span:6,children:e.jsx(s.Card,{children:e.jsx(s.Statistic,{title:"配置中心",value:0,prefix:e.jsx(i.SettingOutlined,{})})})}),e.jsx(s.Col,{span:6,children:e.jsx(s.Card,{children:e.jsx(s.Statistic,{title:"任务中心",value:0,prefix:e.jsx(i.FileTextOutlined,{})})})}),e.jsx(s.Col,{span:6,children:e.jsx(s.Card,{children:e.jsx(s.Statistic,{title:"工作流",value:0,prefix:e.jsx(i.AuditOutlined,{})})})}),e.jsx(s.Col,{span:6,children:e.jsx(s.Card,{children:e.jsx(s.Statistic,{title:"用户中心",value:0,prefix:e.jsx(i.UserOutlined,{})})})})]}),e.jsxs(s.Card,{title:"关于 Z-One Company",children:[e.jsx(ts,{children:"Z-One Company 是一站式企业级应用管理平台,整合了配置中心、任务中心、工作流、用户中心等多个模块。"}),e.jsx(ts,{children:e.jsx("strong",{children:"核心模块:"})}),e.jsxs("ul",{children:[e.jsx("li",{children:"配置中心 - 集中管理应用配置"}),e.jsx("li",{children:"任务中心 - 任务调度与执行"}),e.jsx("li",{children:"工作流 - 流程审批与管理"}),e.jsx("li",{children:"用户中心 - 统一身份认证与权限管理"}),e.jsx("li",{children:"调度中心 - 定时任务管理"}),e.jsx("li",{children:"Mist - 密钥管理"}),e.jsx("li",{children:"元数据 - API与应用管理"})]})]})]}),oe={layout:"_layout_1puwg_1",header:"_header_1puwg_5",logo:"_logo_1puwg_15",logoText:"_logoText_1puwg_20",headerRight:"_headerRight_1puwg_26",userInfo:"_userInfo_1puwg_31",userName:"_userName_1puwg_38",mainLayout:"_mainLayout_1puwg_43",sider:"_sider_1puwg_48",menu:"_menu_1puwg_53",collapsedBtn:"_collapsedBtn_1puwg_57",content:"_content_1puwg_74"};let Us="/api";function rs(){return Ye.create({baseURL:Us,timeout:15e3})}const he=rs();rs(),he.interceptors.request.use(r=>{const c=localStorage.getItem("token");return c&&(r.headers.Authorization=`Bearer ${c}`),r});const qs=r=>he.post("/ctc/auth/login",r).then(c=>c.data),Gs=()=>{try{const r=localStorage.getItem("userInfo");return Promise.resolve(r?JSON.parse(r):null)}catch{return Promise.resolve(null)}};function Hs(r){return{list:c=>he.get(`/${r}/list`,{params:c}).then(o=>o.data),page:c=>he.get(`/${r}/page`,{params:c}).then(o=>o.data),get:c=>he.get(`/${r}/${c}`).then(o=>o.data),create:c=>he.post(`/${r}`,c).then(o=>o.data),update:(c,o)=>he.put(`/${r}/${c}`,o).then(y=>y.data),delete:c=>he.delete(`/${r}/${c}`).then(o=>o.data)}}const q=Hs("mock"),{Header:Ws,Sider:Js,Content:Ks}=s.Layout,{Text:Ys}=s.Typography,Vs=({compact:r=!1}={})=>{const c=te.useLocation(),o=te.useNavigate(),[y,k]=t.useState(!1),[S,d]=t.useState("管理员"),[g,E]=t.useState(null),[C,O]=t.useState([]),[m,x]=t.useState([]),z=t.useRef(o);z.current=o,t.useEffect(()=>{if(!localStorage.getItem("token")){z.current("/login");return}const b=localStorage.getItem("userInfo");if(b)try{const w=JSON.parse(b);d(w.userName||"管理员"),E(w),w.tenantCode&&x([w.tenantCode])}catch{}Gs().then(w=>{w&&(E(w),d(w.userName||"管理员"),localStorage.setItem("userInfo",JSON.stringify(w)))}).catch(()=>{}),O([{value:"tenant1",label:"租户1",children:[{value:"domain1-1",label:"域1-1"},{value:"domain1-2",label:"域1-2"}]},{value:"tenant2",label:"租户2",children:[{value:"domain2-1",label:"域2-1"},{value:"domain2-2",label:"域2-2"}]}])},[]);const j=()=>{var b;const N=c.pathname;if(N.includes("/user"))return["user"];if(N.includes("/role"))return["role"];if(N.includes("/permission"))return["permission"];if(N.includes("/app"))return["app"];if(N.includes("/dict"))return["dict"];if(N.includes("/audit"))return["audit"];if(N.includes("/tenant"))return["tenant"];if(N.includes("/domain"))return["domain"];if(N.includes("/org"))return["org"];if(N.includes("/dept"))return["dept"];if(N.includes("/group"))return["group"];if(N.includes("/4a/")){const w=((b=N.split("/4a/")[1])==null?void 0:b.split("/"))||[];if(w.length>0)return[`4a/${w[0]}`]}return N.includes("/webide")?["webide"]:N.includes("/agent-team")?["agent-team"]:["4a/account"]},B=[{key:"4a/account",icon:e.jsx(i.TeamOutlined,{}),label:"账号管理"},{key:"4a/role",icon:e.jsx(i.SafetyOutlined,{}),label:"角色管理"},{key:"4a/application",icon:e.jsx(i.AppstoreOutlined,{}),label:"应用管理"},{key:"4a/tenant",icon:e.jsx(i.TeamOutlined,{}),label:"租户管理"},{key:"4a/org",icon:e.jsx(i.ClusterOutlined,{}),label:"组织管理"},{key:"4a/permission",icon:e.jsx(i.SafetyCertificateOutlined,{}),label:"权限管理"},{key:"4a/surl",icon:e.jsx(i.LinkOutlined,{}),label:"短链管理"},{key:"webide",icon:e.jsx(i.CodeOutlined,{}),label:"WebIDE 容器"},{key:"agent-team",icon:e.jsx(i.RobotOutlined,{}),label:"Agent 群组 IM"},{type:"divider"},{key:"settings",icon:e.jsx(i.SettingOutlined,{}),label:"系统设置"}],v=({key:N})=>{o(`/ctc/${N}`)};return e.jsxs(s.Layout,{className:oe.layout,children:[r?null:e.jsx(e.Fragment,{children:e.jsxs(Ws,{className:oe.header,children:[e.jsx("div",{className:oe.logo,children:e.jsx("span",{className:oe.logoText,children:"Z-CTC 统一用户中心"})}),e.jsx("div",{className:oe.headerRight,children:e.jsx(s.Space,{size:24,children:e.jsx(s.Dropdown,{overlay:e.jsxs("div",{style:{background:"#fff",borderRadius:"8px",boxShadow:"0 6px 16px rgba(0, 0, 0, 0.12)",padding:"16px",width:"360px"},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"12px",marginBottom:"12px"},children:[e.jsx("span",{style:{fontSize:"14px",color:"#666"},children:"租户域"}),e.jsx(s.Cascader,{value:m,onChange:N=>x(N),options:C,placeholder:"请选择租户域",style:{flex:1}})]}),e.jsx(s.Divider,{style:{margin:"12px 0"}}),e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"8px"},children:[e.jsxs("div",{style:{display:"flex",fontSize:"14px"},children:[e.jsx("span",{style:{color:"#999",width:"70px"},children:"用户名:"}),e.jsx("span",{children:(g==null?void 0:g.userName)||"-"})]}),e.jsxs("div",{style:{display:"flex",fontSize:"14px"},children:[e.jsx("span",{style:{color:"#999",width:"70px"},children:"真实姓名:"}),e.jsx("span",{children:(g==null?void 0:g.realName)||"-"})]}),e.jsxs("div",{style:{display:"flex",fontSize:"14px"},children:[e.jsx("span",{style:{color:"#999",width:"70px"},children:"邮箱:"}),e.jsx("span",{children:(g==null?void 0:g.email)||"-"})]}),e.jsxs("div",{style:{display:"flex",fontSize:"14px"},children:[e.jsx("span",{style:{color:"#999",width:"70px"},children:"手机号:"}),e.jsx("span",{children:(g==null?void 0:g.phone)||"-"})]}),e.jsxs("div",{style:{display:"flex",fontSize:"14px"},children:[e.jsx("span",{style:{color:"#999",width:"70px"},children:"状态:"}),e.jsx("span",{children:(g==null?void 0:g.status)===1?"正常":"停用"})]})]}),e.jsx(s.Divider,{style:{margin:"12px 0"}}),e.jsxs("div",{style:{display:"flex",flexDirection:"column"},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"8px",padding:"8px 12px",cursor:"pointer",borderRadius:"4px",fontSize:"14px"},onClick:()=>{},children:[e.jsx(i.UserOutlined,{})," 个人中心"]}),e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"8px",padding:"8px 12px",cursor:"pointer",borderRadius:"4px",fontSize:"14px"},onClick:()=>{},children:[e.jsx(i.SettingOutlined,{})," 系统设置"]}),e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"8px",padding:"8px 12px",cursor:"pointer",borderRadius:"4px",fontSize:"14px"},onClick:()=>{localStorage.removeItem("token"),localStorage.removeItem("userInfo"),o("/ctc/login")},children:[e.jsx(i.LogoutOutlined,{})," 退出登录"]})]})]}),placement:"bottomRight",trigger:["click"],children:e.jsxs("div",{className:oe.userInfo,children:[e.jsx(s.Avatar,{icon:e.jsx(i.UserOutlined,{}),size:"small"}),e.jsx(Ys,{className:oe.userName,children:S}),e.jsx(i.DownOutlined,{})]})})})})]})}),e.jsxs(s.Layout,{className:oe.mainLayout,children:[e.jsxs(Js,{trigger:null,collapsible:!0,collapsed:y,className:oe.sider,width:200,children:[e.jsx(s.Menu,{mode:"inline",selectedKeys:j(),defaultOpenKeys:["user","role","permission","audit","tenant","domain","org","dept","group"],className:oe.menu,items:B,onClick:v}),e.jsx("div",{className:oe.collapsedBtn,onClick:()=>k(!y),children:y?e.jsx(i.MenuUnfoldOutlined,{}):e.jsx(i.MenuFoldOutlined,{})})]}),e.jsx(Ks,{className:oe.content,children:e.jsx(te.Outlet,{})})]})]})},Fe={container:"_container_tti32_1",content:"_content_tti32_9",card:"_card_tti32_14",header:"_header_tti32_19"},{Title:Xs,Text:sr}=s.Typography,Zs=r=>ss.post("/ctc/auth/login",r),Qs=()=>Promise.resolve({code:0,message:"功能暂未开放"}),et=()=>{const r=te.useNavigate(),[c,o]=t.useState("login"),[y,k]=t.useState("account"),[S,d]=t.useState(!1),[g,E]=t.useState(0),[C]=s.Form.useForm(),O=async()=>{s.message.info("验证码功能暂未开放")},m=async j=>{try{let B;if(c==="login"&&y==="account"){if(B=await Zs({identifier:j.username,password:j.password}),B&&B.token){s.message.success("登录成功!"),localStorage.setItem("token",B.token);const v=B.account||{};localStorage.setItem("userInfo",JSON.stringify({userId:v.id,userName:v.username,nickname:v.nickname,tenantCode:v.tenantCode})),r("/ctc");return}s.message.error((B==null?void 0:B.message)||"登录失败")}else{await Qs(),s.message.info("该功能暂未开放");return}}catch(B){s.message.error(B.message||"操作失败,请重试")}},x=()=>{const j=[{key:"account",label:"账户密码"}];return c==="register"?(j.push({key:"phone",label:"手机注册"}),j.push({key:"email",label:"邮箱注册"})):j.push({key:"phone",label:"手机验证码"}),j},z=()=>{const j=c==="login";return e.jsxs(e.Fragment,{children:[y==="account"&&e.jsxs(e.Fragment,{children:[e.jsx(s.Form.Item,{name:"username",rules:[{required:!0,message:"请输入用户名!"}],children:e.jsx(s.Input,{size:"large",prefix:e.jsx(i.UserOutlined,{}),placeholder:"用户名"})}),e.jsx(s.Form.Item,{name:"password",rules:[{required:!0,message:"请输入密码!"}],children:e.jsx(s.Input.Password,{size:"large",prefix:e.jsx(i.LockOutlined,{}),placeholder:"密码"})})]}),(y==="phone"||y==="email")&&e.jsxs(e.Fragment,{children:[e.jsx(s.Form.Item,{name:"receiver",rules:[{required:!0,message:y==="phone"?"请输入手机号!":"请输入邮箱!"}],children:e.jsx(s.Input,{size:"large",prefix:y==="phone"?e.jsx(i.MobileOutlined,{}):e.jsx(i.MailOutlined,{}),placeholder:y==="phone"?"手机号":"邮箱",disabled:g>0})}),e.jsx(s.Form.Item,{children:e.jsxs("div",{style:{display:"flex",gap:8},children:[e.jsx(s.Input,{size:"large",prefix:e.jsx(i.LockOutlined,{}),placeholder:"验证码",style:{flex:1}}),e.jsx(s.Button,{type:"primary",onClick:O,loading:S,disabled:g>0,style:{minWidth:100},children:g>0?`${g}秒`:"获取验证码"})]})}),!j&&e.jsx(s.Form.Item,{name:"password",rules:[{required:!0,message:"请输入密码!"}],children:e.jsx(s.Input.Password,{size:"large",prefix:e.jsx(i.LockOutlined,{}),placeholder:"设置密码"})})]})]})};return e.jsx("div",{className:Fe.container,children:e.jsx("div",{className:Fe.content,children:e.jsxs(s.Card,{className:Fe.card,children:[e.jsxs("div",{className:Fe.header,style:{textAlign:"center"},children:[e.jsxs("svg",{width:"48",height:"48",viewBox:"0 0 56 56",fill:"none","aria-label":"logo",style:{marginBottom:8},children:[e.jsx("defs",{children:e.jsxs("linearGradient",{id:"brandGradAuth",x1:"0",y1:"0",x2:"56",y2:"56",gradientUnits:"userSpaceOnUse",children:[e.jsx("stop",{offset:"0%",stopColor:"#1677ff"}),e.jsx("stop",{offset:"100%",stopColor:"#0958d9"})]})}),e.jsx("rect",{x:"2",y:"2",width:"52",height:"52",rx:"14",fill:"url(#brandGradAuth)"}),e.jsx("path",{d:"M18 18 H40 L18 38 H40",stroke:"#ffffff",strokeWidth:"3.5",strokeLinecap:"round",strokeLinejoin:"round",fill:"none"})]}),e.jsx(Xs,{level:4,style:{margin:0},children:c==="register"?"用户注册":"欢迎登录"})]}),e.jsxs(s.Form,{form:C,layout:"vertical",onFinish:m,initialValues:{autoLogin:!0},children:[c!=="forgot"&&e.jsx(s.Tabs,{activeKey:y,onChange:j=>k(j),centered:!0,items:x()}),z(),e.jsx(s.Form.Item,{children:e.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[c==="login"&&e.jsx(s.Form.Item,{name:"autoLogin",valuePropName:"checked",noStyle:!0,children:e.jsx(s.Checkbox,{children:"自动登录"})}),e.jsx("a",{onClick:()=>{o(c==="login"?"register":"login")},children:c==="login"?"没有账号?立即注册":"已有账号?立即登录"})]})}),e.jsx(s.Form.Item,{children:e.jsx(s.Button,{type:"primary",htmlType:"submit",block:!0,size:"large",children:c==="login"?"登录":"注册"})})]})]})})})},st={display:"flex",flexDirection:"column",height:"100vh",overflow:"auto",background:"#f0f2f5",backgroundImage:"url('https://gw.alipayobjects.com/zos/rmsportal/TVYTbAXWheQpRcWDaDMu.svg')",backgroundRepeat:"no-repeat",backgroundPosition:"center 110px",backgroundSize:"100%"},tt={flex:1,padding:"32px 0",maxWidth:400,margin:"0 auto",width:"100%"},rt=()=>{const[r,c]=t.useState({}),[o]=t.useState("account"),[y,k]=t.useState(!1),S=te.useNavigate(),d=async E=>{k(!0);try{const C=await qs({identifier:E.userName,password:E.password});if(C&&C.token){localStorage.setItem("token",C.token);const O=C.account||{};localStorage.setItem("userInfo",JSON.stringify({userId:O.id,userName:O.username,nickname:O.nickname,tenantCode:O.tenantCode})),s.message.success("登录成功!"),S("/");return}c(C)}catch{s.message.error("登录失败,请重试!")}finally{k(!1)}},{status:g}=r;return e.jsx("div",{style:st,children:e.jsxs("div",{style:tt,children:[e.jsx("div",{style:{textAlign:"center",marginBottom:24},children:e.jsxs("svg",{width:"56",height:"56",viewBox:"0 0 56 56",fill:"none","aria-label":"logo",children:[e.jsx("defs",{children:e.jsxs("linearGradient",{id:"brandGrad",x1:"0",y1:"0",x2:"56",y2:"56",gradientUnits:"userSpaceOnUse",children:[e.jsx("stop",{offset:"0%",stopColor:"#1677ff"}),e.jsx("stop",{offset:"100%",stopColor:"#0958d9"})]})}),e.jsx("rect",{x:"2",y:"2",width:"52",height:"52",rx:"14",fill:"url(#brandGrad)"}),e.jsx("path",{d:"M18 18 H40 L18 38 H40",stroke:"#ffffff",strokeWidth:"3.5",strokeLinecap:"round",strokeLinejoin:"round",fill:"none"})]})}),e.jsx(s.Tabs,{activeKey:o,centered:!0,items:[{key:"account",label:"账户密码登录"}]}),g==="error"&&e.jsx(s.Alert,{message:"账户或密码错误",type:"error",showIcon:!0,style:{marginBottom:16}}),e.jsxs(s.Form,{onFinish:d,initialValues:{autoLogin:!0},layout:"vertical",children:[e.jsx(s.Form.Item,{name:"userName",rules:[{required:!0,message:"请输入用户名!"}],children:e.jsx(s.Input,{size:"large",prefix:e.jsx(i.UserOutlined,{}),placeholder:"用户名"})}),e.jsx(s.Form.Item,{name:"password",rules:[{required:!0,message:"请输入密码!"}],children:e.jsx(s.Input.Password,{size:"large",prefix:e.jsx(i.LockOutlined,{}),placeholder:"密码"})}),e.jsx(s.Form.Item,{name:"autoLogin",valuePropName:"checked",children:e.jsx(s.Checkbox,{children:"自动登录"})}),e.jsx(s.Form.Item,{children:e.jsx(s.Button,{type:"primary",htmlType:"submit",size:"large",block:!0,loading:y,children:"登录"})})]}),e.jsxs("div",{style:{textAlign:"center",marginTop:16,color:"#888",fontSize:14},children:[e.jsx(te.Link,{to:"/uc/register",style:{marginRight:16},children:"用户注册"}),e.jsx("span",{style:{margin:"0 8px",color:"#ddd"},children:"|"}),e.jsx(te.Link,{to:"/uc/reset-password",style:{marginRight:16},children:"找回密码"}),e.jsx("span",{style:{margin:"0 8px",color:"#ddd"},children:"|"}),e.jsx(te.Link,{to:"/uc/login",children:"手机验证码登录"})]})]})})},Pe={health:()=>Y.get("/agentTeam/health").then(r=>r.data)},lt={LEADER:"red",WORKER:"blue",OBSERVER:"default"};function nt(){const[r,c]=t.useState([]),[o,y]=t.useState(null),[k,S]=t.useState([]),[d,g]=t.useState(!1),[E,C]=t.useState(!1),[O,m]=t.useState("disconnected"),[x,z]=t.useState([]),[j,B]=t.useState(""),[v,N]=t.useState([]),b=t.useRef(null),w=async()=>{g(!0);try{const l=await Pe.listTeams();c(l||[])}catch(l){s.message.warning("加载团队失败:"+((l==null?void 0:l.message)||"未知错误")),c([])}finally{g(!1)}},P=async l=>{C(!0);try{const n=await Pe.listMembers(l);S(n||[])}catch(n){s.message.warning("加载成员失败:"+((n==null?void 0:n.message)||"未知错误")),S([])}finally{C(!1)}},f=()=>{if(b.current){s.message.warning("已连接");return}const l=Pe.buildWsUrl();m("connecting"),z(n=>[...n,`[${new Date().toLocaleTimeString()}] 连接到 ${l}...`]);try{const n=new WebSocket(l);n.onopen=()=>{m("connected"),z(_=>[..._,`[${new Date().toLocaleTimeString()}] ✅ 连接已建立`])},n.onmessage=_=>{const T=typeof _.data=="string"?_.data:"[binary]";z(V=>[...V,`[${new Date().toLocaleTimeString()}] ← ${T}`]);const A=T.match(/^([^|]+)\|(.+)$/);A&&N(V=>[...V,{from:A[1],text:A[2],time:new Date().toLocaleTimeString()}])},n.onerror=()=>{m("error"),z(_=>[..._,`[${new Date().toLocaleTimeString()}] ❌ 连接错误`])},n.onclose=()=>{m("disconnected"),z(_=>[..._,`[${new Date().toLocaleTimeString()}] 🔌 连接已关闭`]),b.current=null},b.current=n}catch(n){m("error"),s.message.error("WS 连接失败:"+((n==null?void 0:n.message)||"未知错误"))}},M=()=>{b.current&&(b.current.close(),b.current=null)},U=()=>{if(!b.current||b.current.readyState!==WebSocket.OPEN){s.message.error("WebSocket 未连接");return}if(!j.trim())return;const l=`${localStorage.getItem("userInfo")?JSON.parse(localStorage.getItem("userInfo")).userName:"me"}|${j}`;b.current.send(l),z(n=>[...n,`[${new Date().toLocaleTimeString()}] → ${j}`]),N(n=>[...n,{from:"me",text:j,time:new Date().toLocaleTimeString()}]),B("")};t.useEffect(()=>(w(),()=>{M()}),[]),t.useEffect(()=>{o&&P(o.teamCode)},[o]);const J={disconnected:"default",connecting:"processing",connected:"success",error:"error"},H={disconnected:"未连接",connecting:"连接中",connected:"已连接",error:"错误"};return e.jsxs(me.PageContainer,{header:{title:"Agent 群组 IM (z-agent-team)",subTitle:"团队协作 + 实时通讯",breadcrumb:{}},children:[e.jsxs("div",{style:{display:"grid",gridTemplateColumns:"300px 1fr",gap:16},children:[e.jsx(me.ProCard,{title:e.jsxs(s.Space,{children:[e.jsx(i.TeamOutlined,{})," 团队列表"]}),loading:d,headerBordered:!0,children:r.length===0?e.jsx(s.Empty,{image:s.Empty.PRESENTED_IMAGE_SIMPLE,description:"暂无团队",children:e.jsx(s.Button,{type:"primary",size:"small",onClick:w,children:"刷新"})}):e.jsx(s.List,{dataSource:r,renderItem:l=>e.jsx(s.List.Item,{onClick:()=>y(l),style:{cursor:"pointer",padding:"8px 12px",background:(o==null?void 0:o.teamCode)===l.teamCode?"#e6f7ff":void 0,borderRadius:4},children:e.jsx(s.List.Item.Meta,{title:l.teamName,description:e.jsxs(s.Space,{size:4,children:[e.jsx(s.Tag,{children:l.teamCode}),l.status==="ENABLE"?e.jsx(s.Tag,{color:"green",children:"启用"}):e.jsx(s.Tag,{children:"停用"})]})})})})}),e.jsxs(me.ProCard,{title:o?e.jsxs(s.Space,{children:[e.jsx(i.TeamOutlined,{})," ",o.teamName," (",o.teamCode,")"]}):"请选择团队",headerBordered:!0,extra:e.jsxs(s.Space,{children:[O==="connected"?e.jsx(s.Button,{icon:e.jsx(i.PoweroffOutlined,{}),onClick:M,children:"断开"}):e.jsx(s.Button,{type:"primary",icon:e.jsx(i.CheckCircleOutlined,{}),onClick:f,children:"连接"}),e.jsx(s.Tag,{color:J[O],children:H[O]})]}),children:[o?e.jsxs("div",{style:{display:"grid",gridTemplateColumns:"1fr 1fr",gap:16},children:[e.jsx(me.ProCard,{title:"成员",loading:E,size:"small",children:e.jsx(s.List,{dataSource:k,renderItem:l=>e.jsx(s.List.Item,{children:e.jsx(s.List.Item.Meta,{title:e.jsxs(s.Space,{children:[l.appCode,e.jsx(s.Tag,{color:lt[l.role||"WORKER"],children:l.role})]}),description:`优先级: ${l.priority??0} · ${l.enabled===1?"✅ 启用":"❌ 停用"}`})})})}),e.jsxs(me.ProCard,{title:"实时消息",size:"small",styles:{body:{padding:0,display:"flex",flexDirection:"column",height:400}},children:[e.jsx("div",{style:{flex:1,overflow:"auto",padding:12},children:v.length===0?e.jsx(s.Empty,{image:s.Empty.PRESENTED_IMAGE_SIMPLE,description:"暂无消息"}):v.map((l,n)=>e.jsxs("div",{style:{marginBottom:8},children:[e.jsx(s.Tag,{color:l.from==="me"?"blue":"green",children:l.from}),e.jsx("span",{style:{marginLeft:8},children:l.text}),e.jsx("span",{style:{marginLeft:8,color:"#999",fontSize:11},children:l.time})]},n))}),e.jsxs("div",{style:{padding:8,borderTop:"1px solid #f0f0f0",display:"flex",gap:8},children:[e.jsx(s.Input,{value:j,onChange:l=>B(l.target.value),onPressEnter:U,placeholder:O==="connected"?"输入消息...":"请先连接 WebSocket",disabled:O!=="connected"}),e.jsx(s.Button,{type:"primary",icon:e.jsx(i.SendOutlined,{}),onClick:U,disabled:O!=="connected",children:"发送"})]})]})]}):e.jsx(s.Empty,{description:"请从左侧选择一个团队"}),x.length>0&&e.jsx(me.ProCard,{title:"WebSocket 日志",size:"small",style:{marginTop:16},children:e.jsx("pre",{style:{background:"#1e1e1e",color:"#d4d4d4",padding:8,borderRadius:4,fontFamily:"Menlo, monospace",fontSize:11,maxHeight:180,overflow:"auto",margin:0},children:x.join(`
|
|
23
|
+
`)})})]})]}),e.jsx(s.Alert,{style:{marginTop:16},type:"info",showIcon:!0,message:"说明",description:e.jsxs("span",{children:["完整 STOMP 客户端 (含订阅 Topic、ACK、消息历史) 见 ",e.jsx("code",{children:"z-agent/z-agent-team/z-agent-team-frontend"}),"。 本页提供轻量级 WS 连接 + 群组管理 REST 端点示例。"]})})]})}const ke={list:()=>Y.get("/agent/team/workspace/list").then(r=>r.data),create:r=>Y.post("/agent/team/workspace",r).then(c=>c.data),update:(r,c)=>Y.put(`/agent/team/workspace/${r}`,c).then(o=>o.data),delete:r=>Y.delete(`/agent/team/workspace/${r}`).then(c=>c.data),getFileTree:r=>Y.get("/agent/team/workspace/file-tree-by-path",{params:{path:r}}).then(c=>c.data),getFileContent:r=>Y.get("/agent/team/workspace/file-content",{params:{path:r}}).then(c=>c.data)},Ne={list:r=>Y.get(`/agent/team/conversation/${r}/work-items`).then(c=>c.data),create:r=>Y.post("/agent/team/work-item",r).then(c=>c.data),update:(r,c)=>Y.put(`/agent/team/work-item/${r}`,c).then(o=>o.data),delete:r=>Y.delete(`/agent/team/work-item/${r}`).then(c=>c.data)},ls={OPEN:"green",DONE:"blue",ARCHIVED:"default"};function ot(){var Q,ks;const{message:r}=s.App.useApp(),c=localStorage.getItem("userInfo")||"{}";let o={};try{o=JSON.parse(c)}catch{}const y=o!=null&&o.userId?String(o.userId):"anonymous",k=(o==null?void 0:o.userName)||(o==null?void 0:o.name)||"我",[S,d]=t.useState([]),[g,E]=t.useState(!1),[C,O]=t.useState(null),[m,x]=t.useState([]),[z,j]=t.useState(!1),[B,v]=t.useState([]),[N,b]=t.useState(!1),[w,P]=t.useState(null),[f,M]=t.useState(!1),[U,J]=t.useState([]),[H,l]=t.useState(""),[n,_]=t.useState("disconnected"),T=t.useRef(null),A=t.useRef(null),[V,re]=t.useState(""),[ae,ne]=t.useState(""),[I,p]=t.useState(!1),[a,D]=t.useState(!1),[R]=s.Form.useForm(),[W]=s.Form.useForm(),[se,ce]=t.useState(null),[Z,de]=t.useState("z-one-company-default");t.useEffect(()=>{fe(),xe(),Ce()},[]),t.useEffect(()=>{A.current&&A.current.scrollIntoView({behavior:"smooth"})},[U,V]);const fe=async()=>{try{const h=await Pe.listTeams();h&&h.length>0&&de(h[0].teamCode)}catch{}},xe=async()=>{j(!0);try{const h=await ke.list(y);x(h||[])}catch{x([])}finally{j(!1)}},Ce=async()=>{E(!0);try{const h=await Ne.listAllByOwner(y,100);d(h||[])}catch{d([])}finally{E(!1)}},ge=async h=>{if(!h){v([]);return}b(!0);try{const L=await ke.fileTree(h);v(L?[le(L)]:[])}catch(L){r.error("加载文件树失败:"+((L==null?void 0:L.message)||"未知错误")),v([])}finally{b(!1)}},We=async h=>{try{const X=(await Ne.messages(h,200)||[]).map(ee=>({msgCode:ee.msgCode,senderType:ee.senderType,senderCode:ee.senderCode,senderName:ee.senderName,content:ee.content,messageType:ee.messageType,timestamp:ee.gmtCreate?new Date(ee.gmtCreate).getTime():Date.now()}));J(X)}catch{J([])}},Je=h=>{_e();const X=`${window.location.protocol==="https:"?"wss:":"ws:"}//${window.location.host}/api/agent/team/ws?convCode=${encodeURIComponent(h)}&userId=${encodeURIComponent(y)}&userName=${encodeURIComponent(k)}`;_("connecting");try{const ee=new WebSocket(X);ee.onopen=()=>{_("connected")},ee.onmessage=zt=>{try{const Mt=JSON.parse(zt.data);Ke(Mt)}catch{}},ee.onerror=()=>{_("error")},ee.onclose=()=>{_("disconnected"),T.current=null},T.current=ee}catch(ee){_("error"),r.error("WS 连接失败:"+((ee==null?void 0:ee.message)||"未知错误"))}},_e=()=>{if(T.current){try{T.current.close()}catch{}T.current=null,_("disconnected"),re("")}},Ke=h=>{const L=h.type;L==="AGENT_RESPONSE_DELTA"||L==="AGENT_THINKING_DELTA"?(ne(h.senderName||h.senderCode||"Agent"),re(X=>X+(h.content||""))):L==="AGENT_RESPONSE"||L==="AGENT_THINKING"?(J(X=>[...X,{msgCode:h.eventId||`evt-${Date.now()}`,senderType:h.senderType||"AGENT",senderCode:h.senderCode||"",senderName:h.senderName||"Agent",content:h.content||"",messageType:L,timestamp:h.timestamp||Date.now()}]),re(""),ne("")):L==="SYSTEM"||L==="PARTICIPANT_JOIN"||L==="PARTICIPANT_LEAVE"?h.content&&h.content!=="HEARTBEAT_ACK"&&h.content!=="PONG"&&J(X=>[...X,{msgCode:h.eventId||`evt-${Date.now()}`,senderType:"SYSTEM",senderCode:h.senderCode||"system",senderName:"系统",content:h.content,messageType:L,timestamp:h.timestamp||Date.now()}]):L==="ERROR"?(J(X=>[...X,{msgCode:h.eventId||`err-${Date.now()}`,senderType:"SYSTEM",senderCode:"system",senderName:"错误",content:h.content||"未知错误",messageType:L,timestamp:h.timestamp||Date.now()}]),re(""),ne("")):L==="MESSAGE_END"&&(re(""),ne(""))},Le=()=>{const h=H.trim();if(!h)return;if(!T.current||T.current.readyState!==WebSocket.OPEN){r.warning("IM 未连接");return}if(!C){r.warning("请先选择一个工作项");return}const L=JSON.stringify({type:"USER_MESSAGE",content:h});T.current.send(L),J(X=>[...X,{msgCode:`local-${Date.now()}`,senderType:"USER",senderCode:y,senderName:k,content:h,messageType:"TEXT",timestamp:Date.now()}]),l("")},Be=h=>{O(h),We(h.convCode),Je(h.convCode),h.workspaceCode?(ce(h.workspaceCode),ge(h.workspaceCode)):(ce(null),v([]))},$e=async()=>{try{const h=await W.validateFields(),L=await Ne.create({teamCode:Z,userId:y,userName:k,title:h.title,workspaceCode:h.workspaceCode||void 0});r.success("工作项已创建"),D(!1),W.resetFields(),await Ce(),L&&Be(L)}catch(h){r.error("创建失败:"+((h==null?void 0:h.message)||"未知错误"))}},u=async()=>{var h,L;try{const X=await R.validateFields();await ke.create({workspaceName:X.workspaceName,localPath:X.localPath,ownerId:y,ownerName:k,description:X.description}),r.success("工作空间已创建"),p(!1),R.resetFields(),await xe()}catch(X){const ee=((L=(h=X==null?void 0:X.response)==null?void 0:h.data)==null?void 0:L.message)||(X==null?void 0:X.message)||"未知错误";r.error("创建失败:"+ee)}},F=async h=>{M(!0);try{const L=await ke.fileContent(h);P({path:h,content:(L==null?void 0:L.content)||""})}catch(L){r.error("读取文件失败:"+((L==null?void 0:L.message)||"未知错误"))}finally{M(!1)}},G=async h=>{try{await Ne.close(h,"DONE"),r.success("已关闭工作项"),await Ce(),(C==null?void 0:C.convCode)===h&&(O(null),_e(),J([]),v([]))}catch(L){r.error("关闭失败:"+((L==null?void 0:L.message)||"未知错误"))}},K=async h=>{try{await ke.delete(h),r.success("已删除"),await xe(),se===h&&(ce(null),v([]))}catch(L){r.error("删除失败:"+((L==null?void 0:L.message)||"未知错误"))}},le=h=>{var L;return{key:h.absolutePath,title:e.jsxs("span",{children:[h.isDirectory?e.jsx(i.FolderOutlined,{style:{marginRight:4,color:"#faad14"}}):e.jsx(i.FileOutlined,{style:{marginRight:4,color:"#8c8c8c"}}),h.name,h.isDirectory&&h.totalDescendants>0?e.jsxs("span",{style:{color:"#bfbfbf",marginLeft:6,fontSize:11},children:["(",h.totalDescendants,")"]}):null]}),children:((L=h.children)==null?void 0:L.map(le))||[],isLeaf:!h.isDirectory,disabled:!1}};return e.jsxs("div",{style:{display:"grid",gridTemplateColumns:"240px 280px 1fr",height:"calc(100vh - 130px)",background:"#fff",border:"1px solid #f0f0f0",borderRadius:8,overflow:"hidden"},children:[e.jsxs("div",{style:{borderRight:"1px solid #f0f0f0",display:"flex",flexDirection:"column",background:"#fafafa"},children:[e.jsxs("div",{style:{padding:12,borderBottom:"1px solid #f0f0f0",display:"flex",alignItems:"center",justifyContent:"space-between"},children:[e.jsxs(s.Space,{size:4,children:[e.jsx(i.MessageOutlined,{style:{color:"#1677ff"}}),e.jsx("strong",{children:"工作项"})]}),e.jsxs(s.Space,{size:4,children:[e.jsx(s.Tooltip,{title:"刷新",children:e.jsx(s.Button,{size:"small",type:"text",icon:e.jsx(i.ReloadOutlined,{}),onClick:Ce})}),e.jsx(s.Tooltip,{title:"新建工作项",children:e.jsx(s.Button,{size:"small",type:"text",icon:e.jsx(i.PlusOutlined,{}),onClick:()=>D(!0)})})]})]}),e.jsx("div",{style:{flex:1,overflow:"auto"},children:g?e.jsx("div",{style:{padding:24,textAlign:"center"},children:e.jsx(s.Spin,{size:"small"})}):S.length===0?e.jsx(s.Empty,{image:s.Empty.PRESENTED_IMAGE_SIMPLE,description:"暂无工作项",style:{padding:24,marginTop:24},children:e.jsx(s.Button,{size:"small",type:"primary",onClick:()=>D(!0),children:"新建工作项"})}):S.map(h=>e.jsxs("div",{onClick:()=>Be(h),style:{padding:"10px 12px",cursor:"pointer",borderBottom:"1px solid #f5f5f5",background:(C==null?void 0:C.convCode)===h.convCode?"#e6f7ff":"transparent",transition:"background 0.2s"},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:4},children:[e.jsx("strong",{style:{fontSize:13,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",maxWidth:150},children:h.title||"未命名"}),e.jsx(s.Badge,{count:h.unreadCount||0,size:"small"})]}),e.jsx("div",{style:{fontSize:11,color:"#8c8c8c",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:h.lastMsgPreview||"暂无消息"}),e.jsxs("div",{style:{marginTop:4,fontSize:11,color:"#bfbfbf"},children:[e.jsx(s.Tag,{color:ls[h.status||"OPEN"],style:{marginRight:4,fontSize:10,padding:"0 4px"},children:h.status||"OPEN"}),h.workspaceCode?e.jsx(s.Tag,{color:"purple",style:{fontSize:10,padding:"0 4px"},children:"有工作空间"}):null]})]},h.convCode))})]}),e.jsxs("div",{style:{borderRight:"1px solid #f0f0f0",display:"flex",flexDirection:"column",background:"#fff"},children:[e.jsxs("div",{style:{padding:12,borderBottom:"1px solid #f0f0f0",display:"flex",alignItems:"center",justifyContent:"space-between"},children:[e.jsxs(s.Space,{size:4,children:[e.jsx(i.FolderOpenOutlined,{style:{color:"#faad14"}}),e.jsx("strong",{children:"工作空间"})]}),e.jsx(s.Space,{size:4,children:e.jsx(s.Tooltip,{title:"新建工作空间",children:e.jsx(s.Button,{size:"small",type:"text",icon:e.jsx(i.PlusOutlined,{}),onClick:()=>p(!0)})})})]}),C!=null&&C.workspaceCode?e.jsx("div",{style:{padding:"8px 12px",background:"#f0f5ff",borderBottom:"1px solid #f0f0f0",fontSize:12},children:e.jsxs(s.Space,{size:4,children:[e.jsx(s.Tag,{color:"blue",children:"当前工作项"}),e.jsx("span",{style:{color:"#1677ff"},children:((Q=m.find(h=>h.workspaceCode===C.workspaceCode))==null?void 0:Q.workspaceName)||C.workspaceCode}),e.jsx(s.Button,{size:"small",type:"text",icon:e.jsx(i.ReloadOutlined,{}),onClick:()=>ge(C.workspaceCode)})]})}):null,e.jsx("div",{style:{maxHeight:200,overflow:"auto",borderBottom:"1px solid #f0f0f0"},children:z?e.jsx("div",{style:{padding:12,textAlign:"center"},children:e.jsx(s.Spin,{size:"small"})}):m.length===0?e.jsx("div",{style:{padding:12,color:"#8c8c8c",fontSize:12,textAlign:"center"},children:"暂无工作空间"}):m.map(h=>e.jsxs("div",{onClick:()=>{ce(h.workspaceCode),ge(h.workspaceCode)},style:{padding:"6px 12px",cursor:"pointer",fontSize:12,background:se===h.workspaceCode?"#e6f7ff":"transparent",borderLeft:se===h.workspaceCode?"3px solid #1677ff":"3px solid transparent",display:"flex",alignItems:"center",justifyContent:"space-between"},children:[e.jsxs(s.Space,{size:4,style:{overflow:"hidden"},children:[e.jsx(i.FolderOutlined,{style:{color:"#faad14",fontSize:12}}),e.jsx("span",{style:{overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:h.workspaceName})]}),e.jsx(s.Popconfirm,{title:"删除此工作空间?",onConfirm:L=>{L==null||L.stopPropagation(),K(h.workspaceCode)},onCancel:L=>L==null?void 0:L.stopPropagation(),children:e.jsx(s.Button,{size:"small",type:"text",danger:!0,icon:e.jsx(i.DeleteOutlined,{}),onClick:L=>L.stopPropagation()})})]},h.workspaceCode))}),e.jsx("div",{style:{flex:1,overflow:"auto",padding:8},children:N?e.jsx("div",{style:{padding:24,textAlign:"center"},children:e.jsx(s.Spin,{})}):se?B.length===0?e.jsx(s.Empty,{image:s.Empty.PRESENTED_IMAGE_SIMPLE,description:"空目录或无文件",style:{marginTop:40}}):e.jsx(s.Tree,{treeData:B,defaultExpandAll:!1,showLine:!0,showIcon:!1,onSelect:(h,L)=>{const X=L.node;!X.isLeaf&&h.length>0||X.isLeaf&&L.node.key&&F(String(L.node.key))}}):e.jsx(s.Empty,{image:s.Empty.PRESENTED_IMAGE_SIMPLE,description:"请选择工作空间",style:{marginTop:40}})}),w?e.jsxs("div",{style:{borderTop:"1px solid #f0f0f0",maxHeight:240,overflow:"hidden",display:"flex",flexDirection:"column"},children:[e.jsxs("div",{style:{padding:"6px 12px",background:"#fafafa",borderBottom:"1px solid #f0f0f0",display:"flex",alignItems:"center",justifyContent:"space-between",fontSize:11},children:[e.jsxs(s.Space,{size:4,children:[e.jsx(i.FileTextOutlined,{}),e.jsx("span",{style:{overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",maxWidth:180},children:w.path.split("/").pop()})]}),e.jsx(s.Button,{size:"small",type:"text",onClick:()=>P(null),children:"关闭"})]}),e.jsx("pre",{style:{flex:1,margin:0,padding:8,overflow:"auto",fontSize:11,background:"#1e1e1e",color:"#d4d4d4",fontFamily:"Menlo, monospace",whiteSpace:"pre-wrap",wordBreak:"break-all"},children:f?"加载中...":w.content||"(空)"})]}):null]}),e.jsxs("div",{style:{display:"flex",flexDirection:"column",background:"#f5f5f5"},children:[e.jsxs("div",{style:{padding:"12px 16px",background:"#fff",borderBottom:"1px solid #f0f0f0",display:"flex",alignItems:"center",justifyContent:"space-between"},children:[C?e.jsxs(s.Space,{size:8,children:[e.jsx(i.TeamOutlined,{style:{color:"#1677ff"}}),e.jsx("strong",{style:{fontSize:14},children:C.title||"未命名"}),e.jsx(s.Tag,{color:ls[C.status||"OPEN"],style:{marginLeft:4},children:C.status||"OPEN"}),C.workspaceCode?e.jsx(s.Tag,{color:"purple",icon:e.jsx(i.FolderOpenOutlined,{}),children:((ks=m.find(h=>h.workspaceCode===C.workspaceCode))==null?void 0:ks.workspaceName)||"工作空间"}):null,e.jsxs("span",{style:{color:"#8c8c8c",fontSize:12},children:[C.messageCount||0," 条消息"]})]}):e.jsx("span",{style:{color:"#8c8c8c"},children:"请从左侧选择一个工作项"}),C?e.jsxs(s.Space,{size:4,children:[e.jsx(s.Tag,{color:n==="connected"?"green":n==="error"?"red":"default",children:n==="connected"?"已连接":n==="connecting"?"连接中":n==="error"?"错误":"未连接"}),e.jsx(s.Popconfirm,{title:"关闭此工作项?",onConfirm:()=>G(C.convCode),children:e.jsx(s.Button,{size:"small",type:"text",danger:!0,icon:e.jsx(i.CheckCircleOutlined,{}),children:"完成"})})]}):null]}),e.jsx("div",{style:{flex:1,overflow:"auto",padding:16,display:"flex",flexDirection:"column",gap:12},children:C?U.length===0&&!V?e.jsx(s.Empty,{image:s.Empty.PRESENTED_IMAGE_SIMPLE,description:"暂无消息,开始聊吧",style:{marginTop:80}}):e.jsxs(e.Fragment,{children:[U.map(h=>e.jsx(ns,{msg:h,currentUserId:y},h.msgCode)),V?e.jsx(ns,{msg:{msgCode:"streaming",senderType:"AGENT",senderCode:"agent",senderName:ae,content:V,timestamp:Date.now(),messageType:"STREAMING"},currentUserId:y}):null,e.jsx("div",{ref:A})]}):e.jsx(s.Empty,{image:s.Empty.PRESENTED_IMAGE_SIMPLE,description:"从左侧选择工作项开始聊天",style:{marginTop:80}})}),e.jsxs("div",{style:{padding:12,background:"#fff",borderTop:"1px solid #f0f0f0",display:"flex",gap:8},children:[e.jsx(s.Input.TextArea,{value:H,onChange:h=>l(h.target.value),onPressEnter:h=>{h.shiftKey||(h.preventDefault(),Le())},placeholder:C?n==="connected"?"输入消息... (Enter 发送, Shift+Enter 换行)":"正在连接 IM...":"请先选择工作项",autoSize:{minRows:1,maxRows:4},disabled:!C||n!=="connected"}),e.jsx(s.Button,{type:"primary",icon:e.jsx(i.SendOutlined,{}),onClick:Le,disabled:!C||n!=="connected"||!H.trim(),children:"发送"})]})]}),e.jsx(s.Modal,{title:"新建工作空间",open:I,onCancel:()=>p(!1),onOk:u,okText:"创建",cancelText:"取消",children:e.jsxs(s.Form,{form:R,layout:"vertical",children:[e.jsx(s.Form.Item,{label:"名称",name:"workspaceName",rules:[{required:!0,message:"请输入工作空间名称"}],children:e.jsx(s.Input,{placeholder:"例如:z-opc 主项目"})}),e.jsx(s.Form.Item,{label:"本地路径",name:"localPath",rules:[{required:!0,message:"请输入本地路径"}],extra:"服务器侧的文件系统绝对路径 (例: /Users/zifang/workplace)",children:e.jsx(s.Input,{placeholder:"/Users/zifang/workplace"})}),e.jsx(s.Form.Item,{label:"描述",name:"description",children:e.jsx(s.Input.TextArea,{rows:2,placeholder:"可选:工作空间用途说明"})})]})}),e.jsx(s.Modal,{title:"新建工作项",open:a,onCancel:()=>D(!1),onOk:$e,okText:"创建",cancelText:"取消",children:e.jsxs(s.Form,{form:W,layout:"vertical",children:[e.jsx(s.Form.Item,{label:"标题",name:"title",rules:[{required:!0,message:"请输入工作项标题"}],children:e.jsx(s.Input,{placeholder:"例如:完成 z-opc 用户面板"})}),e.jsx(s.Form.Item,{label:"关联工作空间 (可选)",name:"workspaceCode",extra:"绑定后,工作项右侧会显示对应工作空间的文件树",children:e.jsxs("select",{style:{width:"100%",height:32,border:"1px solid #d9d9d9",borderRadius:6,padding:"0 11px"},children:[e.jsx("option",{value:"",children:"无 (仅 IM 群聊)"}),m.map(h=>e.jsxs("option",{value:h.workspaceCode,children:[h.workspaceName," (",h.localPath,")"]},h.workspaceCode))]})})]})})]})}function ns({msg:r,currentUserId:c}){const o=r.senderType==="USER"&&r.senderCode===c;if(r.senderType==="SYSTEM")return e.jsx("div",{style:{textAlign:"center",color:"#8c8c8c",fontSize:11},children:e.jsx(s.Tag,{color:"default",children:r.content})});const k=o?"#1677ff":"#fff",S=o?"#fff":"#333",d=o?"#1677ff":"#87d068";return e.jsxs("div",{style:{display:"flex",flexDirection:o?"row-reverse":"row",alignItems:"flex-start",gap:8},children:[e.jsx(s.Avatar,{style:{background:d,flexShrink:0},children:(r.senderName||"?").charAt(0).toUpperCase()}),e.jsxs("div",{style:{maxWidth:"70%"},children:[e.jsxs("div",{style:{fontSize:11,color:"#8c8c8c",marginBottom:2,textAlign:o?"right":"left"},children:[r.senderName," · ",new Date(r.timestamp).toLocaleTimeString(),r.messageType&&r.messageType!=="TEXT"?e.jsx(s.Tag,{style:{marginLeft:4,fontSize:10},children:r.messageType}):null]}),e.jsx("div",{style:{padding:"8px 12px",background:k,color:S,borderRadius:8,border:o?"none":"1px solid #e8e8e8",wordBreak:"break-word",whiteSpace:"pre-wrap",boxShadow:"0 1px 2px rgba(0,0,0,0.04)"},children:r.content||(r.messageType==="STREAMING"?"...":"")})]})]})}const Se={health:()=>Y.get("/webide/health").then(r=>r.data)},it={CREATING:{text:"创建中",color:"processing"},RUNNING:{text:"运行中",color:"success"},STOPPED:{text:"已停止",color:"default"},ERROR:{text:"错误",color:"error"}},at={GIT:{text:"GIT 模式",color:"blue"},SHARED:{text:"SHARED 模式",color:"purple"}};function ct(){const r=t.useRef(void 0),[c,o]=t.useState(!1),[y,k]=t.useState(!1),[S,d]=t.useState([]),[g,E]=t.useState(null),[C,O]=t.useState(!1),[m]=s.Form.useForm(),x=async()=>{try{const w=await Se.listContainers();return{data:w||[],success:!0,total:(w||[]).length}}catch(w){return s.message.warning("后端未就绪,显示空列表:"+((w==null?void 0:w.message)||"未知错误")),{data:[],success:!1,total:0}}},z=async()=>{var w;try{const P=await m.validateFields();O(!0);const f=await Se.inspect(P);s.message.success(`WebIDE 创建成功:${f.url}`),o(!1),m.resetFields(),(w=r.current)==null||w.reload(),f.url&&window.open(f.url,"_blank")}catch(P){if(P!=null&&P.errorFields)return;s.message.error("创建失败:"+((P==null?void 0:P.message)||"未知错误"))}finally{O(!1)}},j=async w=>{var P;try{await Se.startContainer(w),s.message.success("已启动"),(P=r.current)==null||P.reload()}catch(f){s.message.error("启动失败:"+((f==null?void 0:f.message)||"未知错误"))}},B=async w=>{var P;try{await Se.stopContainer(w),s.message.success("已停止"),(P=r.current)==null||P.reload()}catch(f){s.message.error("停止失败:"+((f==null?void 0:f.message)||"未知错误"))}},v=async w=>{var P;try{await Se.removeContainer(w),s.message.success("已删除"),(P=r.current)==null||P.reload()}catch(f){s.message.error("删除失败:"+((f==null?void 0:f.message)||"未知错误"))}},N=async w=>{E(w),k(!0),d(["加载中..."]);try{const P=await Se.getLogs(w.containerId,200);d((P==null?void 0:P.lines)||[])}catch(P){d([`加载日志失败:${(P==null?void 0:P.message)||"未知错误"}`])}},b=[{title:"容器ID",dataIndex:"containerId",width:200,fixed:"left",ellipsis:!0},{title:"模式",dataIndex:"mode",width:110,render:(w,P)=>{const f=at[P.mode]||{text:P.mode,color:"default"};return e.jsx(s.Tag,{color:f.color,children:f.text})}},{title:"Git URL",dataIndex:"gitUrl",width:200,ellipsis:!0},{title:"分支",dataIndex:"branch",width:100},{title:"状态",dataIndex:"status",width:100,render:(w,P)=>{const f=it[P.status]||{text:P.status,color:"default"};return e.jsx(s.Tag,{color:f.color,children:f.text})}},{title:"URL",dataIndex:"url",width:200,ellipsis:!0,render:(w,P)=>P.url?e.jsx("a",{href:P.url,target:"_blank",rel:"noreferrer",children:P.url}):"-"},{title:"CPU%",dataIndex:"cpuUsage",width:80,render:w=>typeof w=="number"?`${w.toFixed(1)}%`:"-"},{title:"内存%",dataIndex:"memoryUsage",width:80,render:w=>typeof w=="number"?`${w.toFixed(1)}%`:"-"},{title:"创建时间",dataIndex:"createdAt",width:170,valueType:"dateTime"},{title:"操作",valueType:"option",width:240,fixed:"right",render:(w,P)=>[e.jsx(s.Tooltip,{title:"启动",children:e.jsx(s.Button,{type:"text",size:"small",icon:e.jsx(i.PlayCircleOutlined,{}),onClick:()=>j(P.containerId),children:"启动"})},"start"),e.jsx(s.Tooltip,{title:"停止",children:e.jsx(s.Button,{type:"text",size:"small",icon:e.jsx(i.PauseOutlined,{}),onClick:()=>B(P.containerId),children:"停止"})},"stop"),e.jsx(s.Tooltip,{title:"查看日志",children:e.jsx(s.Button,{type:"text",size:"small",icon:e.jsx(i.FileTextOutlined,{}),onClick:()=>N(P),children:"日志"})},"logs"),e.jsx(s.Tooltip,{title:"删除",children:e.jsx(s.Button,{type:"text",danger:!0,size:"small",icon:e.jsx(i.DeleteOutlined,{}),onClick:()=>v(P.containerId),children:"删除"})},"remove")]}];return e.jsxs(me.PageContainer,{header:{title:"WebIDE 容器管理 (z-webide)",subTitle:"基于 code-server 的容器化 WebIDE",breadcrumb:{}},children:[e.jsx(me.ProTable,{actionRef:r,rowKey:"containerId",columns:b,request:x,search:!1,pagination:{pageSize:20},headerTitle:"容器列表",toolBarRender:()=>[e.jsx(s.Button,{type:"primary",icon:e.jsx(i.PlusOutlined,{}),onClick:()=>o(!0),children:"新建 WebIDE"},"add"),e.jsx(s.Button,{icon:e.jsx(i.ReloadOutlined,{}),onClick:()=>{var w;return(w=r.current)==null?void 0:w.reload()},children:"刷新"},"reload")]}),e.jsx(s.Drawer,{title:e.jsxs(s.Space,{children:[e.jsx(i.CodeOutlined,{})," 新建 WebIDE"]}),open:c,onClose:()=>o(!1),width:520,extra:e.jsxs(s.Space,{children:[e.jsx(s.Button,{onClick:()=>o(!1),children:"取消"}),e.jsx(s.Button,{type:"primary",loading:C,onClick:z,children:"创建并打开"})]}),children:e.jsx(dt,{form:m})}),e.jsx(s.Drawer,{title:g?`容器日志 — ${g.containerId}`:"容器日志",open:y,onClose:()=>k(!1),width:720,children:e.jsx("pre",{style:{background:"#1e1e1e",color:"#d4d4d4",padding:12,borderRadius:4,fontFamily:"Menlo, Consolas, monospace",fontSize:12,maxHeight:"70vh",overflow:"auto",whiteSpace:"pre-wrap"},children:S.join(`
|
|
24
|
+
`)})})]})}function dt({form:r}){const{mode:c,setMode:o}=ut();return e.jsxs(s.Form,{form:r,layout:"vertical",style:{marginTop:16},initialValues:{mode:"GIT"},children:[e.jsx(s.Form.Item,{name:"mode",label:"模式",rules:[{required:!0}],children:e.jsx(s.Select,{onChange:y=>o(y),options:[{value:"GIT",label:"GIT 模式 (从仓库克隆)"},{value:"SHARED",label:"SHARED 模式 (共享工作区)"}]})}),c==="GIT"&&e.jsxs(e.Fragment,{children:[e.jsx(s.Form.Item,{name:"gitUrl",label:"Git URL",rules:[{required:!0,type:"url"}],extra:"支持 https://github.com/xxx/yyy.git",children:e.jsx(s.Input,{placeholder:"https://github.com/your/repo.git"})}),e.jsx(s.Form.Item,{name:"branch",label:"分支",children:e.jsx(s.Input,{placeholder:"main (默认)"})})]}),c==="SHARED"&&e.jsx(s.Form.Item,{name:"shareKey",label:"共享 Key",rules:[{required:!0}],children:e.jsx(s.Input,{placeholder:"SHARED-XXXXXX"})}),e.jsx(s.Form.Item,{name:"tenantCode",label:"租户编码 (可选)",children:e.jsx(s.Input,{placeholder:"default"})})]})}function ut(){const[r,c]=t.useState("GIT");return{mode:r,setMode:c}}const{Option:os}=s.Select,{TextArea:is}=s.Input,Ae=[{type:"STRING",label:"字符串",icon:e.jsx(i.FileTextOutlined,{}),color:"#1677ff",desc:"短文本 (默认 VARCHAR 255)"},{type:"TEXT",label:"长文本",icon:e.jsx(i.FileTextOutlined,{}),color:"#13c2c2",desc:"TEXT 类型, 无长度限制"},{type:"INT",label:"整数",icon:"#",color:"#722ed1",desc:"INT 整数"},{type:"LONG",label:"长整数",icon:"#",color:"#722ed1",desc:"BIGINT 长整数"},{type:"DECIMAL",label:"小数",icon:"0.00",color:"#eb2f96",desc:"DECIMAL 精确小数"},{type:"BOOLEAN",label:"布尔",icon:e.jsx(i.CheckCircleOutlined,{}),color:"#52c41a",desc:"TINYINT(1) 是/否"},{type:"DATE",label:"日期",icon:"📅",color:"#fa8c16",desc:"DATE yyyy-MM-dd"},{type:"DATETIME",label:"日期时间",icon:"🕐",color:"#fa8c16",desc:"DATETIME yyyy-MM-dd HH:mm:ss"},{type:"JSON",label:"JSON",icon:"{}",color:"#2f54eb",desc:"JSON 字符串"},{type:"REF",label:"引用",icon:"🔗",color:"#8c8c8c",desc:"外键引用 BIGINT"}],De=Object.fromEntries(Ae.map(r=>[r.type,r])),Ue="application/x-lc-field-type",qe="application/x-lc-field-idx";function as(){const[r]=te.useSearchParams(),[c,o]=t.useState(r.get("appCode")||"demo"),[y,k]=t.useState(r.get("tenant")||localStorage.getItem("z_tenant")||"default"),[S,d]=t.useState([]),[g,E]=t.useState(null),[C,O]=t.useState(!1),[m,x]=t.useState(null),[z,j]=t.useState(!1),[B]=s.Form.useForm(),[v,N]=t.useState(null),[b,w]=t.useState(null),[P,f]=t.useState(null),[M,U]=t.useState([]),[J,H]=t.useState(null),[l,n]=t.useState(!1),[_,T]=t.useState(!1),A=t.useCallback(async()=>{if(c){O(!0);try{const u=await Y.get(`/lc/app/${c}/schema`,{params:{tenantCode:y}});d(Array.isArray(u)?u:[]),E(null)}catch(u){s.message.error("加载 schema 失败: "+((u==null?void 0:u.message)||"未知错误")),d([])}finally{O(!1)}}},[c,y]);t.useEffect(()=>{A()},[A]);const V=async(u,F,G)=>{var K;try{const le={tenantCode:y,entityCode:F,eventType:u,eventData:typeof G=="string"?G:JSON.stringify(G),source:"USER",parentEventId:g},Q=await Y.post(`/lc/app/${c}/event`,le);s.message.success(`事件 ${u} 已提交 (eventId=${(K=Q==null?void 0:Q.eventId)==null?void 0:K.slice(0,8)}…)`),E((Q==null?void 0:Q.eventId)||null),await A()}catch(le){s.message.error("提交事件失败: "+((le==null?void 0:le.message)||"未知错误"))}},re=()=>{x(null),B.resetFields(),B.setFieldsValue({entityCode:"",entityName:"",tableName:"",description:"",fields:[]}),j(!0)},ae=u=>{x(u),B.setFieldsValue({entityCode:u.entityCode,entityName:u.entityName,tableName:u.tableName||u.entityCode,description:u.description,fields:u.fields||[]}),j(!0)},ne=u=>{U((u.fields||[]).map((F,G)=>({...F,sortOrder:F.sortOrder??G}))),H(null),n(!1),T(!0),x(u)},I=u=>{s.Modal.confirm({title:`删除实体 ${u.entityName||u.entityCode}?`,content:"此操作会发出 DELETE 事件, 所有字段一起删除.",okType:"danger",onOk:()=>V("DELETE",u.entityCode,{entityCode:u.entityCode})})},p=async()=>{try{const u=await B.validateFields(),F=m?"UPDATE":"CREATE",G={entityCode:u.entityCode,entityName:u.entityName,tableName:u.tableName||u.entityCode,description:u.description,fields:(u.fields||[]).map(K=>({fieldCode:K.fieldCode,fieldName:K.fieldName,fieldType:K.fieldType||"STRING",required:!!K.required,defaultValue:K.defaultValue||null,dictCode:K.dictCode||null,refEntity:K.refEntity||null,fieldLength:K.fieldLength||null,scale:K.scale||null,sortOrder:K.sortOrder||0}))};j(!1),await V(F,u.entityCode,G)}catch(u){u!=null&&u.errorFields?s.message.error("请补全必填字段"):s.message.error("提交失败: "+((u==null?void 0:u.message)||"未知错误"))}},a=(u,F)=>{u.dataTransfer.setData(Ue,F),u.dataTransfer.setData("text/plain",F),u.dataTransfer.effectAllowed="copy",N(F)},D=()=>{N(null),f(null)},R=(u,F)=>{u.dataTransfer.setData(qe,String(F)),u.dataTransfer.effectAllowed="move",w(F)},W=()=>{w(null),f(null)},se=u=>{u.preventDefault(),u.dataTransfer.dropEffect=v?"copy":"move"},ce=()=>{f(null)},Z=u=>{u.preventDefault();const F=u.dataTransfer.getData(Ue),G=u.dataTransfer.getData(qe);if(F)xe(F,M.length);else if(G){const K=Number(G);Ce(K,M.length)}f(null),N(null),w(null)},de=(u,F)=>{u.preventDefault(),u.stopPropagation(),f(F)},fe=(u,F)=>{u.preventDefault(),u.stopPropagation();const G=u.dataTransfer.getData(Ue),K=u.dataTransfer.getData(qe);G?xe(G,F):K&&Ce(Number(K),F),f(null),N(null),w(null)},xe=(u,F)=>{const G=De[u];if(!G)return;const le={fieldCode:`field_${M.length+1}`,fieldName:`新${G.label}字段`,fieldType:u,required:!1,defaultValue:null,dictCode:null,refEntity:null,fieldLength:u==="STRING"?255:null,scale:u==="DECIMAL"?2:null,sortOrder:F},Q=[...M];Q.splice(F,0,le),ge(Q),U(Q),H(F),n(!0)},Ce=(u,F)=>{if(u===F||u<0||F<0)return;const G=[...M],[K]=G.splice(u,1),le=F>u?F-1:F;G.splice(le,0,K),ge(G),U(G),n(!0)},ge=u=>{u.forEach((F,G)=>{F.sortOrder=G})},We=(u,F)=>{const G=[...M];G[u]={...G[u],...F},U(G),n(!0)},Je=u=>{const F=M.filter((G,K)=>K!==u);ge(F),U(F),H(null),n(!0)},_e=u=>{const F=M[u],G={...F,fieldCode:`${F.fieldCode}_copy`,fieldName:`${F.fieldName} (副本)`},K=[...M];K.splice(u+1,0,G),ge(K),U(K),H(u+1),n(!0)},Ke=async()=>{if(!m)return;const u={entityCode:m.entityCode,entityName:m.entityName,tableName:m.tableName,description:m.description,fields:M.map(F=>({fieldCode:F.fieldCode,fieldName:F.fieldName,fieldType:F.fieldType||"STRING",required:!!F.required,defaultValue:F.defaultValue||null,dictCode:F.dictCode||null,refEntity:F.refEntity||null,fieldLength:F.fieldLength||null,scale:F.scale||null,sortOrder:F.sortOrder??0}))};await V("UPDATE",m.entityCode,u),n(!1)},Le=async()=>{if(m)try{const u=await Y.post(`/lc/admin/entity/${m.id}/provision?tenant=${y}`);s.message.success(`已建表 (${M.length} 字段)`),console.log("DDL:",u)}catch(u){s.message.error("建表失败: "+((u==null?void 0:u.message)||"未知错误"))}},Be=[{title:"编码",dataIndex:"entityCode",key:"entityCode",width:140},{title:"名称",dataIndex:"entityName",key:"entityName",width:140},{title:"物理表",dataIndex:"tableName",key:"tableName",width:160},{title:"字段数",key:"fields",width:80,render:(u,F)=>{var G;return e.jsx(s.Badge,{count:((G=F.fields)==null?void 0:G.length)||0,showZero:!0,color:"blue"})}},{title:"描述",dataIndex:"description",key:"description",ellipsis:!0},{title:"操作",key:"action",width:260,render:(u,F)=>e.jsxs(s.Space,{children:[e.jsx(s.Button,{type:"link",size:"small",icon:e.jsx(i.FormatPainterOutlined,{}),onClick:()=>ne(F),children:"画布编辑"}),e.jsx(s.Button,{type:"link",size:"small",icon:e.jsx(i.EditOutlined,{}),onClick:()=>ae(F),children:"表单编辑"}),e.jsx(s.Popconfirm,{title:"确定删除?",onConfirm:()=>I(F),children:e.jsx(s.Button,{type:"link",size:"small",danger:!0,icon:e.jsx(i.DeleteOutlined,{}),children:"删除"})})]})}],$e=J!=null?M[J]:null;return e.jsxs("div",{children:[e.jsxs(s.Card,{title:e.jsxs(e.Fragment,{children:[e.jsx(i.ThunderboltOutlined,{})," z-lc 模型编辑器 (拖拽版)"]}),extra:e.jsxs(s.Space,{children:[e.jsx(s.Input,{addonBefore:"appCode",value:c,onChange:u=>o(u.target.value.trim()),style:{width:200}}),e.jsx(s.Input,{addonBefore:"tenant",value:y,onChange:u=>k(u.target.value.trim()),style:{width:160}}),e.jsx(s.Button,{icon:e.jsx(i.ReloadOutlined,{}),onClick:A,children:"刷新"}),e.jsx(s.Button,{type:"primary",icon:e.jsx(i.PlusOutlined,{}),onClick:re,children:"新建实体"})]}),children:[e.jsx(s.Alert,{type:"info",showIcon:!0,message:"提示: 点击实体的「画布编辑」进入拖拽式建模: 从左侧面板拖字段类型到中间, 拖拽字段行可重排, 右侧编辑属性。",style:{marginBottom:16}}),e.jsx(s.Spin,{spinning:C,children:S.length===0?e.jsx(s.Empty,{description:"暂无实体, 点击右上角 「新建实体」 开始"}):e.jsx(s.Table,{rowKey:"entityCode",columns:Be,dataSource:S,pagination:!1,size:"small",expandable:{expandedRowRender:u=>e.jsx(pt,{entity:u})}})})]}),e.jsx(s.Modal,{title:m?`编辑实体 ${m.entityCode}`:"新建实体",open:z,onCancel:()=>j(!1),onOk:p,width:760,destroyOnClose:!0,children:e.jsx(mt,{form:B,editing:m})}),e.jsx(s.Drawer,{title:e.jsxs(s.Space,{children:[e.jsx(i.FormatPainterOutlined,{}),m?`画布编辑 - ${m.entityName||m.entityCode}`:"画布编辑",l&&e.jsx(s.Tag,{color:"orange",children:"未保存"})]}),open:_,onClose:()=>{l?s.Modal.confirm({title:"有未保存的修改, 确定关闭?",onOk:()=>{T(!1),n(!1)}}):T(!1)},width:"85%",destroyOnClose:!0,extra:e.jsxs(s.Space,{children:[e.jsx(s.Button,{onClick:Le,icon:e.jsx(i.DatabaseOutlined,{}),children:"自动建表"}),e.jsx(s.Button,{type:"primary",icon:e.jsx(i.ThunderboltOutlined,{}),disabled:!l,onClick:Ke,children:"提交 (UPDATE 事件)"})]}),children:e.jsxs(s.Row,{gutter:16,style:{height:"calc(100vh - 200px)"},children:[e.jsx(s.Col,{span:5,children:e.jsxs(s.Card,{size:"small",title:e.jsxs(e.Fragment,{children:[e.jsx(i.HolderOutlined,{})," 字段类型面板"]}),style:{height:"100%"},bodyStyle:{padding:12,overflowY:"auto",height:"calc(100% - 40px)"},children:[e.jsx("div",{style:{fontSize:12,color:"#999",marginBottom:8},children:"拖拽字段类型到右侧"}),Ae.map(u=>e.jsxs("div",{draggable:!0,onDragStart:F=>a(F,u.type),onDragEnd:D,style:{padding:"8px 12px",marginBottom:8,background:v===u.type?"#e6f4ff":"#fafafa",border:`1px dashed ${u.color}`,borderRadius:6,cursor:"grab",opacity:v===u.type?.5:1,transition:"all 0.2s"},children:[e.jsxs(s.Space,{children:[e.jsx("span",{style:{display:"inline-block",width:22,height:22,borderRadius:4,background:u.color,color:"#fff",textAlign:"center",lineHeight:"22px",fontSize:11,fontWeight:"bold"},children:u.type.slice(0,2)}),e.jsx("span",{style:{fontWeight:500},children:u.label})]}),e.jsx("div",{style:{fontSize:11,color:"#888",marginTop:4},children:u.desc})]},u.type))]})}),e.jsx(s.Col,{span:12,children:e.jsx(s.Card,{size:"small",title:e.jsxs(s.Space,{children:[e.jsx(i.DatabaseOutlined,{}),"字段列表 (",M.length,")"]}),style:{height:"100%"},bodyStyle:{padding:8,overflowY:"auto",height:"calc(100% - 40px)"},children:e.jsx("div",{onDragOver:se,onDragLeave:ce,onDrop:Z,style:{minHeight:"100%",padding:4,border:"2px dashed transparent",borderRadius:6},children:M.length===0?e.jsx(s.Empty,{description:"从左侧拖拽字段类型到这里",style:{marginTop:80}}):e.jsxs(e.Fragment,{children:[M.map((u,F)=>{const G=De[u.fieldType]||De.STRING,K=J===F,le=b===F;return e.jsxs(t.Fragment,{children:[P===F&&e.jsx("div",{style:{height:4,background:"#1677ff",borderRadius:2,margin:"4px 0"}}),e.jsx("div",{draggable:!0,onDragStart:Q=>R(Q,F),onDragEnd:W,onDragOver:Q=>de(Q,F),onDrop:Q=>fe(Q,F),onClick:()=>H(F),style:{padding:"10px 12px",marginBottom:6,background:K?"#e6f4ff":"#fff",border:`1px solid ${K?"#1677ff":"#d9d9d9"}`,borderRadius:6,cursor:"grab",opacity:le?.4:1,transition:"all 0.15s"},children:e.jsxs(s.Space,{style:{width:"100%",justifyContent:"space-between"},children:[e.jsxs(s.Space,{children:[e.jsx(i.HolderOutlined,{style:{color:"#999"}}),e.jsx("span",{style:{display:"inline-block",width:20,height:20,borderRadius:3,background:G.color,color:"#fff",textAlign:"center",lineHeight:"20px",fontSize:10},children:u.fieldType.slice(0,2)}),e.jsx("span",{style:{fontFamily:"monospace",fontWeight:500},children:u.fieldCode}),e.jsx("span",{children:u.fieldName}),u.required&&e.jsx(s.Tag,{color:"red",style:{margin:0},children:"必填"}),u.dictCode&&e.jsxs(s.Tag,{color:"blue",style:{margin:0},children:["dict:",u.dictCode]}),u.refEntity&&e.jsxs(s.Tag,{color:"purple",style:{margin:0},children:["ref:",u.refEntity]})]}),e.jsxs(s.Space,{size:4,onClick:Q=>Q.stopPropagation(),children:[e.jsx(s.Tooltip,{title:"复制",children:e.jsx(s.Button,{type:"text",size:"small",icon:e.jsx(i.CopyOutlined,{}),onClick:()=>_e(F)})}),e.jsx(s.Tooltip,{title:"删除",children:e.jsx(s.Button,{type:"text",size:"small",danger:!0,icon:e.jsx(i.DeleteOutlined,{}),onClick:()=>Je(F)})})]})]})})]},`${u.fieldCode}-${F}`)}),P===M.length&&e.jsx("div",{style:{height:4,background:"#1677ff",borderRadius:2,margin:"4px 0"}})]})})})}),e.jsx(s.Col,{span:7,children:e.jsx(s.Card,{size:"small",title:e.jsxs(e.Fragment,{children:[e.jsx(i.CodeOutlined,{})," 字段属性"]}),style:{height:"100%"},bodyStyle:{padding:12,overflowY:"auto",height:"calc(100% - 40px)"},children:$e?e.jsx(ht,{field:$e,onChange:u=>We(J,u)}):e.jsx(s.Empty,{description:"点击中间列表中的字段以编辑属性",style:{marginTop:80}})})})]})})]})}function pt({entity:r}){const c=r.fields||[];return c.length===0?e.jsx("span",{style:{color:"#999"},children:"无字段"}):e.jsx(s.Space,{wrap:!0,size:[4,4],children:c.map(o=>e.jsxs(s.Tag,{color:(De[o.fieldType]||{}).color||"default",children:[o.fieldCode," : ",o.fieldType,o.required?" *":""]},o.fieldCode))})}function mt({form:r,editing:c}){return e.jsxs(s.Form,{form:r,layout:"vertical",children:[e.jsxs(s.Space,{style:{width:"100%"},size:"middle",children:[e.jsx(s.Form.Item,{name:"entityCode",label:"实体编码",rules:[{required:!0,pattern:/^[A-Za-z][A-Za-z0-9_]*$/,message:"字母数字下划线"}],children:e.jsx(s.Input,{disabled:!!c,placeholder:"如 user"})}),e.jsx(s.Form.Item,{name:"entityName",label:"实体名称",children:e.jsx(s.Input,{placeholder:"如 用户"})}),e.jsx(s.Form.Item,{name:"tableName",label:"物理表名",rules:[{required:!0,pattern:/^[A-Za-z][A-Za-z0-9_]*$/,message:"字母数字下划线"}],children:e.jsx(s.Input,{placeholder:"默认 = entityCode"})})]}),e.jsx(s.Form.Item,{name:"description",label:"描述",children:e.jsx(is,{rows:2})}),e.jsx(s.Form.List,{name:"fields",children:(o,{add:y,remove:k})=>e.jsxs(e.Fragment,{children:[e.jsx("div",{style:{marginBottom:8},children:e.jsx(s.Button,{type:"dashed",onClick:()=>y({fieldType:"STRING",required:!1}),icon:e.jsx(i.PlusOutlined,{}),children:"添加字段"})}),e.jsx(s.Table,{rowKey:S=>S.fieldCode||Math.random(),columns:[{title:"编码",dataIndex:"fieldCode",render:(S,d,g)=>e.jsx(s.Form.Item,{name:[g,"fieldCode"],noStyle:!0,rules:[{required:!0,pattern:/^[A-Za-z][A-Za-z0-9_]*$/,message:"字母数字下划线"}],children:e.jsx(s.Input,{size:"small",placeholder:"userName"})})},{title:"名称",dataIndex:"fieldName",render:(S,d,g)=>e.jsx(s.Form.Item,{name:[g,"fieldName"],noStyle:!0,children:e.jsx(s.Input,{size:"small",placeholder:"用户名"})})},{title:"类型",dataIndex:"fieldType",width:120,render:(S,d,g)=>e.jsx(s.Form.Item,{name:[g,"fieldType"],noStyle:!0,children:e.jsx(s.Select,{size:"small",children:Ae.map(E=>e.jsx(os,{value:E.type,children:E.type},E.type))})})},{title:"必填",dataIndex:"required",width:60,render:(S,d,g)=>e.jsx(s.Form.Item,{name:[g,"required"],noStyle:!0,valuePropName:"checked",children:e.jsx(s.Switch,{size:"small"})})},{title:"字典",dataIndex:"dictCode",width:110,render:(S,d,g)=>e.jsx(s.Form.Item,{name:[g,"dictCode"],noStyle:!0,children:e.jsx(s.Input,{size:"small",placeholder:"可选"})})},{title:"引用",dataIndex:"refEntity",width:110,render:(S,d,g)=>e.jsx(s.Form.Item,{name:[g,"refEntity"],noStyle:!0,children:e.jsx(s.Input,{size:"small",placeholder:"可选"})})},{title:"操作",width:60,render:(S,d,g)=>e.jsx(s.Button,{size:"small",danger:!0,type:"link",onClick:()=>k(g),children:"移除"})}],dataSource:o,pagination:!1,size:"small"})]})})]})}function ht({field:r,onChange:c}){return e.jsx("div",{children:e.jsxs(s.Form,{layout:"vertical",size:"small",children:[e.jsx(s.Form.Item,{label:"字段编码 (物理列名)",required:!0,children:e.jsx(s.Input,{value:r.fieldCode||"",onChange:o=>c({fieldCode:o.target.value}),placeholder:"如 userName"})}),e.jsx(s.Form.Item,{label:"显示名称",children:e.jsx(s.Input,{value:r.fieldName||"",onChange:o=>c({fieldName:o.target.value}),placeholder:"如 用户名"})}),e.jsx(s.Form.Item,{label:"字段类型",children:e.jsx(s.Select,{value:r.fieldType||"STRING",onChange:o=>c({fieldType:o}),style:{width:"100%"},children:Ae.map(o=>e.jsxs(os,{value:o.type,children:[o.label," (",o.type,")"]},o.type))})}),e.jsx(s.Form.Item,{label:"必填",children:e.jsx(s.Switch,{checked:!!r.required,onChange:o=>c({required:o})})}),(r.fieldType==="STRING"||r.fieldType==="TEXT")&&e.jsx(s.Form.Item,{label:"字段长度",children:e.jsx(s.InputNumber,{value:r.fieldLength,onChange:o=>c({fieldLength:o}),min:1,max:65535,style:{width:"100%"}})}),r.fieldType==="DECIMAL"&&e.jsx(s.Form.Item,{label:"小数位数",children:e.jsx(s.InputNumber,{value:r.scale,onChange:o=>c({scale:o}),min:0,max:10,style:{width:"100%"}})}),e.jsx(s.Form.Item,{label:"默认值",children:e.jsx(s.Input,{value:r.defaultValue||"",onChange:o=>c({defaultValue:o.target.value}),placeholder:"可选"})}),e.jsx(s.Form.Item,{label:"字典编码 (dictCode)",children:e.jsx(s.Input,{value:r.dictCode||"",onChange:o=>c({dictCode:o.target.value}),placeholder:"如 user_status"})}),e.jsx(s.Form.Item,{label:"引用实体 (refEntity)",children:e.jsx(s.Input,{value:r.refEntity||"",onChange:o=>c({refEntity:o.target.value}),placeholder:"如 其他 entity 的 entityCode"})}),e.jsx(s.Form.Item,{label:"排序号",children:e.jsx(s.InputNumber,{value:r.sortOrder??0,onChange:o=>c({sortOrder:o}),style:{width:"100%"}})}),e.jsx(s.Form.Item,{label:"备注",children:e.jsx(is,{rows:2,value:r.description||"",onChange:o=>c({description:o.target.value})})})]})})}const{Option:xt}=s.Select,cs={STRING:{component:s.Input,props:{}},TEXT:{component:s.Input.TextArea,props:{rows:3}},INT:{component:s.InputNumber,props:{}},LONG:{component:s.InputNumber,props:{}},DECIMAL:{component:s.InputNumber,props:{step:.01}},BOOLEAN:{component:s.Switch,props:{}},DATE:{component:s.DatePicker,props:{format:"YYYY-MM-DD"}},DATETIME:{component:s.DatePicker,props:{format:"YYYY-MM-DD HH:mm:ss",showTime:!0}},JSON:{component:s.Input.TextArea,props:{rows:3,placeholder:"JSON 字符串"}},REF:{component:s.InputNumber,props:{}}};function ds(){const{entity:r}=te.useParams(),[c]=te.useSearchParams(),o=c.get("appCode")||"demo",y=c.get("tenant")||localStorage.getItem("z_tenant")||"default",[k,S]=t.useState([]),[d,g]=t.useState(null),[E,C]=t.useState([]),[O,m]=t.useState(0),[x,z]=t.useState(1),[j,B]=t.useState(10),[v,N]=t.useState(!1),[b,w]=t.useState(!1),[P,f]=t.useState(null),[M]=s.Form.useForm(),[U,J]=t.useState({}),H=t.useCallback(async()=>{try{const p=await Y.get(`/lc/app/${o}/schema`,{params:{tenantCode:y}});S(Array.isArray(p)?p:[]);const a=(p||[]).find(D=>D.entityCode===r);g(a||null)}catch(p){s.message.error("加载 schema 失败: "+((p==null?void 0:p.message)||"未知错误")),S([]),g(null)}},[o,y,r]),l=t.useCallback(async p=>{if(!p||U[p])return U[p]||[];try{const a=await Y.get("/dict/items/get",{params:{dictCode:p}}),R=(Array.isArray(a)?a:[]).map(W=>({value:W.itemValue??W.itemCode,label:W.itemName??W.itemLabel??W.itemCode}));return J(W=>({...W,[p]:R})),R}catch{return[]}},[U]),n=t.useCallback(async()=>{if(d){N(!0);try{const p=await Y.post(`/lc/runtime/${d.entityCode}/list`,{tenantCode:y,appCode:o,entityCode:d.entityCode,page:x,size:j});C((p==null?void 0:p.records)||[]),m((p==null?void 0:p.total)||0)}catch(p){s.message.error("查询失败: "+((p==null?void 0:p.message)||"未知错误")),C([]),m(0)}finally{N(!1)}}},[d,y,o,x,j]);if(t.useEffect(()=>{H()},[H]),t.useEffect(()=>{n()},[n]),t.useEffect(()=>{!d||!d.fields||d.fields.forEach(p=>{p.dictCode&&l(p.dictCode)})},[d,l]),!r)return e.jsx(s.Empty,{description:"缺少实体编码 (路径变量 :entity)"});if(!d)return e.jsx(s.Card,{title:e.jsxs(e.Fragment,{children:[e.jsx(i.DatabaseOutlined,{})," z-lc 运行时"]}),children:e.jsx(s.Alert,{type:"warning",showIcon:!0,message:`实体 ${r} 未定义`,description:`请先在 模型编辑器 (路径 /form/_model?appCode=${o}) 中定义实体, 然后刷新此页.`})});const _=d.fields||[],T=()=>{f(null),M.resetFields(),w(!0)},A=async p=>{f(p);try{const a=await Y.post(`/lc/runtime/${d.entityCode}/get`,{tenantCode:y,appCode:o,entityCode:d.entityCode,id:p.id});M.resetFields(),M.setFieldsValue(a||p)}catch{M.resetFields(),M.setFieldsValue(p)}w(!0)},V=p=>{s.Modal.confirm({title:"确定删除?",content:`id=${p.id}`,okType:"danger",onOk:async()=>{try{await Y.post(`/lc/runtime/${d.entityCode}/delete`,{tenantCode:y,appCode:o,entityCode:d.entityCode,id:p.id}),s.message.success("删除成功"),n()}catch(a){s.message.error("删除失败: "+((a==null?void 0:a.message)||"未知错误"))}}})},re=async()=>{try{const p=await M.validateFields(),a={tenantCode:y,appCode:o,entityCode:d.entityCode,fieldValues:{...p}};P?(a.fieldValues.id=P.id,await Y.post(`/lc/runtime/${d.entityCode}/update`,a),s.message.success("更新成功")):(await Y.post(`/lc/runtime/${d.entityCode}/create`,a),s.message.success("创建成功")),w(!1),n()}catch(p){p!=null&&p.errorFields?s.message.error("请补全必填字段"):s.message.error("提交失败: "+((p==null?void 0:p.message)||"未知错误"))}},ae=(p,a)=>{const D=a[p.fieldCode],R=p.fieldCode+"_label";if(a[R]!=null)return e.jsx(s.Tag,{children:a[R]});if(D==null)return"-";if(p.fieldType==="BOOLEAN")return D?"是":"否";if(p.fieldType==="DATETIME"||p.fieldType==="DATE")try{return new Date(D).toLocaleString()}catch{return String(D)}return String(D)},ne=[{title:"ID",dataIndex:"id",key:"id",width:80},..._.map(p=>({title:p.fieldName||p.fieldCode,dataIndex:p.fieldCode,key:p.fieldCode,render:(a,D)=>ae(p,D)})),{title:"操作",key:"action",width:180,fixed:"right",render:(p,a)=>e.jsxs(s.Space,{children:[e.jsx(s.Button,{type:"link",icon:e.jsx(i.EditOutlined,{}),onClick:()=>A(a),children:"编辑"}),e.jsx(s.Button,{type:"link",danger:!0,icon:e.jsx(i.DeleteOutlined,{}),onClick:()=>V(a),children:"删除"})]})}],I=p=>{const a=(p.fieldType||"STRING").toUpperCase();if(p.dictCode){const W=U[p.dictCode]||[];return e.jsx(s.Select,{placeholder:`选择 ${p.fieldName||p.fieldCode}`,allowClear:!0,showSearch:!0,optionFilterProp:"label",children:W.map(se=>e.jsx(xt,{value:se.value,label:se.label,children:se.label},se.value))})}const D=cs[a]||cs.STRING,R=D.component;return e.jsx(R,{...D.props,placeholder:p.fieldName||p.fieldCode})};return e.jsxs(s.Card,{title:e.jsxs(e.Fragment,{children:[e.jsx(i.DatabaseOutlined,{})," ",d.entityName||d.entityCode," (运行时 CRUD)"]}),extra:e.jsxs(s.Space,{children:[e.jsx(s.Button,{icon:e.jsx(i.ReloadOutlined,{}),onClick:n,children:"刷新"}),e.jsx(s.Button,{type:"primary",icon:e.jsx(i.PlusOutlined,{}),onClick:T,children:"新增"})]}),children:[e.jsx(s.Alert,{type:"info",showIcon:!0,message:`App=${o} · Tenant=${y} · 字段数=${_.length}`,style:{marginBottom:16}}),e.jsx(s.Spin,{spinning:v,children:e.jsx(s.Table,{rowKey:"id",columns:ne,dataSource:E,pagination:{current:x,pageSize:j,total:O,showSizeChanger:!0,showTotal:p=>`共 ${p} 条`,onChange:(p,a)=>{z(p),B(a)}},scroll:{x:"max-content"},size:"small"})}),e.jsx(s.Modal,{title:P?`编辑 #${P.id}`:"新增记录",open:b,onCancel:()=>w(!1),onOk:re,width:680,destroyOnClose:!0,children:e.jsx(s.Form,{form:M,layout:"vertical",children:_.map(p=>e.jsx(s.Form.Item,{name:p.fieldCode,label:e.jsxs("span",{children:[p.fieldName||p.fieldCode,p.required&&e.jsx("span",{style:{color:"red"},children:" *"}),e.jsx(s.Tag,{style:{marginLeft:8},children:p.fieldType})]}),rules:p.required?[{required:!0,message:"必填"}]:[],children:I(p)},p.fieldCode))})})]})}const gt=()=>{const{entity:r}=te.useParams();return r?r==="_model"?e.jsx(as,{}):e.jsx(ds,{}):e.jsxs("div",{style:{padding:24},children:["缺少实体编码. 请访问 ",e.jsx("code",{children:"/form/_model"})," 编辑模型, 或 ",e.jsx("code",{children:"/form/{entityCode}"})," 运行时 CRUD."]})},{Text:ve,Paragraph:tr}=s.Typography,{TextArea:yt}=s.Input,us={PENDING:"default",GENERATING:"processing",READY:"success",FAILED:"error"},ps={Entity:"blue",Mapper:"cyan",Service:"green",ServiceImpl:"lime",Controller:"orange",ReactPage:"purple",File:"default"};function jt(){const c=new URLSearchParams(window.location.search).get("appCode")||"demo",[o]=t.useState(c),[y,k]=t.useState([]),[S,d]=t.useState(!1),[g,E]=t.useState(!1),[C,O]=t.useState(!1),[m,x]=t.useState([]),[z,j]=t.useState(null),[B,v]=t.useState([]),[N]=s.Form.useForm();t.useEffect(()=>{b(),w()},[o]);const b=async()=>{d(!0);try{const l=await Y.get(`/lc/app/${o}/materialize/list`,{params:{limit:50}});k((l==null?void 0:l.data)||[])}catch{s.message.warning("加载批次列表失败")}finally{d(!1)}},w=async()=>{var l;try{const n=await Y.get(`/lc/app/${o}/schema`),_=((l=n==null?void 0:n.data)==null?void 0:l.entities)||(n==null?void 0:n.data)||[];v(_)}catch{}},P=async()=>{var l;try{const n=await N.validateFields(),_={appCode:o,materializationPath:n.materializationPath,entityCodes:(l=n.entityCodes)!=null&&l.length?n.entityCodes:null,description:n.description,triggerSource:"USER"};await Y.post(`/lc/app/${o}/materialize`,_),s.message.success("物化已触发,请稍后查看状态"),E(!1),N.resetFields(),b()}catch(n){n!=null&&n.errorFields||s.message.error("触发失败:"+((n==null?void 0:n.message)||"未知错误"))}},f=async l=>{try{const n=await Y.get(`/lc/app/${o}/materialize/diff`,{params:{id:l.id}}),_=(n==null?void 0:n.data)||[];x(_),O(!0),j(null)}catch{s.message.error("加载文件清单失败")}},M=l=>{var n;try{(n=navigator.clipboard)==null||n.writeText(l),s.message.success("已复制到剪贴板")}catch{s.message.warning("复制失败")}},U=l=>{const n=new Blob([l.content],{type:"text/plain;charset=utf-8"}),_=URL.createObjectURL(n),T=document.createElement("a");T.href=_,T.download=l.relativePath.split("/").pop(),T.click(),URL.revokeObjectURL(_)},J=[{title:"批次号",dataIndex:"exportVersion",width:180,render:l=>e.jsx(ve,{code:!0,children:l})},{title:"状态",dataIndex:"status",width:100,render:l=>e.jsx(s.Badge,{status:us[l]==="success"?"success":us[l]==="error"?"error":"processing",text:l})},{title:"文件数",dataIndex:"fileCount",width:80,align:"center",render:l=>l||0},{title:"来源",dataIndex:"triggerSource",width:80,render:l=>e.jsx(s.Tag,{children:l})},{title:"路径",dataIndex:"materializationPath",ellipsis:!0,render:l=>e.jsx(ve,{type:"secondary",style:{fontSize:12},children:l})},{title:"创建时间",dataIndex:"createTime",width:170},{title:"操作",key:"action",width:200,fixed:"right",render:(l,n)=>e.jsx(s.Space,{size:"small",children:e.jsx(s.Button,{size:"small",type:"link",icon:e.jsx(i.FileTextOutlined,{}),onClick:()=>f(n),disabled:n.status!=="READY"&&n.status!=="GENERATING",children:"查看文件"})})}],H=[{title:"类型",dataIndex:"type",width:100,render:l=>e.jsx(s.Tag,{color:ps[l]||"default",children:l})},{title:"Entity",dataIndex:"entityCode",width:120,render:l=>l?e.jsx(ve,{code:!0,children:l}):"-"},{title:"相对路径",dataIndex:"relativePath",ellipsis:!0,render:l=>e.jsx(ve,{code:!0,style:{fontSize:12},children:l})},{title:"大小",dataIndex:"sizeBytes",width:90,render:l=>`${(l/1024).toFixed(1)}KB`},{title:"操作",key:"action",width:200,fixed:"right",render:(l,n)=>e.jsxs(s.Space,{size:"small",children:[e.jsx(s.Button,{size:"small",type:"link",onClick:()=>j(n),children:"预览"}),e.jsx(s.Button,{size:"small",type:"link",icon:e.jsx(i.CopyOutlined,{}),onClick:()=>M(n.content),children:"复制"}),e.jsx(s.Button,{size:"small",type:"link",icon:e.jsx(i.DownloadOutlined,{}),onClick:()=>U(n),children:"下载"})]})}];return e.jsxs("div",{style:{padding:16},children:[e.jsxs(s.Card,{children:[e.jsx(s.Alert,{type:"info",showIcon:!0,icon:e.jsx(i.CodeOutlined,{}),style:{marginBottom:16},message:`z-lc 代码物化 (FEATURE006 T1) — App: ${o}`,description:"将低代码定义的 entity/field 渲染为可编译的 Java (Entity/Mapper/Service/Controller) + React 页面代码。导出是异步的, 完成后可在此查看文件清单。"}),e.jsxs(s.Space,{style:{marginBottom:16},children:[e.jsx(s.Button,{icon:e.jsx(i.ReloadOutlined,{}),onClick:b,children:"刷新"}),e.jsx(s.Button,{type:"primary",icon:e.jsx(i.ExportOutlined,{}),onClick:()=>E(!0),children:"导出代码"}),e.jsx(s.Button,{icon:e.jsx(i.HistoryOutlined,{}),onClick:()=>s.message.info(`共 ${y.length} 个历史批次`),children:"历史"})]}),e.jsx(s.Table,{dataSource:y,columns:J,rowKey:"id",loading:S,pagination:{pageSize:10},size:"small",scroll:{x:1e3}})]}),e.jsx(s.Modal,{title:"触发代码物化",open:g,onCancel:()=>E(!1),onOk:P,okText:"开始导出",width:600,children:e.jsxs(s.Form,{form:N,layout:"vertical",style:{marginTop:16},initialValues:{materializationPath:`app-${o}/v1`},children:[e.jsx(s.Form.Item,{name:"materializationPath",label:"导出根路径 (相对沙箱默认根)",rules:[{required:!0,message:"请输入路径"}],extra:"默认根: ${user.home}/z-lc-materialized. 如需写入绝对路径, 服务端需配置 z-lc.materialize.allow-absolute-path=true",children:e.jsx(s.Input,{placeholder:`app-${o}/v1`})}),e.jsx(s.Form.Item,{name:"entityCodes",label:"导出的 entity (留空 = 全量)",children:e.jsx(s.Select,{mode:"multiple",placeholder:"选择 entity",allowClear:!0,options:B.map(l=>({value:l.entityCode,label:`${l.entityCode} (${l.tableName})`}))})}),e.jsx(s.Form.Item,{name:"description",label:"备注",children:e.jsx(yt,{rows:2,placeholder:"本次导出的业务说明"})})]})}),e.jsx(s.Modal,{title:`物化文件清单 (${m.length} 个)`,open:C,onCancel:()=>{O(!1),j(null)},footer:e.jsx(s.Button,{onClick:()=>{O(!1),j(null)},children:"关闭"}),width:z?1100:800,children:z?e.jsxs("div",{children:[e.jsxs(s.Space,{style:{marginBottom:8},children:[e.jsx(s.Button,{onClick:()=>j(null),children:"← 返回清单"}),e.jsx(ve,{strong:!0,children:z.relativePath}),e.jsx(s.Tag,{color:ps[z.type]||"default",children:z.type}),e.jsx(s.Button,{size:"small",icon:e.jsx(i.CopyOutlined,{}),onClick:()=>M(z.content),children:"复制"}),e.jsx(s.Button,{size:"small",icon:e.jsx(i.DownloadOutlined,{}),onClick:()=>U(z),children:"下载"})]}),e.jsx("pre",{style:{background:"#1e1e1e",color:"#d4d4d4",padding:16,borderRadius:8,maxHeight:500,overflow:"auto",fontSize:12,fontFamily:"Menlo, Monaco, monospace"},children:z.content})]}):e.jsx(s.Table,{dataSource:m,columns:H,rowKey:"relativePath",pagination:{pageSize:20},size:"small",scroll:{x:700}})})]})}const{TextArea:ms}=s.Input;function hs({open:r,onClose:c,onSuccess:o,envOptions:y=[]}){const[k,S]=t.useState("paste"),[d,g]=t.useState(""),[E,C]=t.useState(null),[O,m]=t.useState(null),[x,z]=t.useState(!1),[j,B]=t.useState([]),[v,N]=t.useState(!1),[b]=s.Form.useForm(),w=t.useRef(null),P=()=>{g(""),C(null),m(null),B([]),b.resetFields()},f=()=>{P(),c()},M=async()=>{if(!d.trim()){s.message.warning("请先粘贴或上传 API 规约");return}m(null),z(!0);try{const n=await q.openapi.parse(d);n.success?(C(n),B((n.endpoints||[]).map((_,T)=>T)),b.setFieldsValue({envCode:y[0]||"default",projectCode:"default",defaultResponse:`{
|
|
25
|
+
"code": 0,
|
|
26
|
+
"message": "ok",
|
|
27
|
+
"data": {}
|
|
28
|
+
}`,defaultStatus:200,priority:5,tagPrefix:"openapi-import"}),s.message.success(`识别为 ${n.format},共 ${n.count} 个端点`)):m(n.message||"解析失败")}catch(n){m(String((n==null?void 0:n.message)||n))}finally{z(!1)}},U=async n=>{try{const _=await q.openapi.sample(n);_.success&&(g(_.content),s.message.success(`已加载 ${_.format} 示例`))}catch(_){s.message.error("加载示例失败: "+_.message)}},J=n=>{const _=new FileReader;return _.onload=T=>{var A;g(String(((A=T.target)==null?void 0:A.result)||"")),s.message.success(`已读取 ${n.name}(${(n.size/1024).toFixed(1)}KB)`)},_.onerror=()=>s.message.error("文件读取失败"),_.readAsText(n),!1},H=async()=>{if(!E){s.message.warning("请先解析");return}let n;try{n=await b.validateFields()}catch{return}N(!0);try{const _=(E.endpoints||[]).map((A,V)=>({method:A.method,path:A.path})).filter((A,V)=>j.includes(V)),T=await q.openapi.importBatch({content:d,selected:_,envCode:n.envCode,projectCode:n.projectCode,defaultResponse:n.defaultResponse,defaultStatus:n.defaultStatus,priority:n.priority,tagPrefix:n.tagPrefix});T.success?(s.message.success(`已导入 ${T.imported} 个 Mock 端点${T.failed>0?`,失败 ${T.failed}`:""}`),o&&o(T),f()):s.message.error(T.message||"导入失败")}catch(_){s.message.error(String((_==null?void 0:_.message)||_))}finally{N(!1)}},l=[{title:"Method",dataIndex:"method",width:90,render:n=>e.jsx(s.Tag,{color:ft(n),children:n})},{title:"Path",dataIndex:"path",width:240,ellipsis:!0},{title:"Summary",dataIndex:"summary",ellipsis:!0},{title:"Tags",dataIndex:"tags",width:160,render:n=>(n||[]).map(_=>e.jsx(s.Tag,{children:_},_))},{title:"Params",dataIndex:"parameters",width:80,render:n=>(n==null?void 0:n.length)||0,align:"center"},{title:"示例",dataIndex:"responseExample",width:80,render:n=>n?e.jsx(s.Tag,{color:"green",children:"有"}):e.jsx(s.Tag,{children:"无"})}];return e.jsxs(s.Modal,{title:e.jsxs(s.Space,{children:[e.jsx(i.CloudUploadOutlined,{})," 批量导入 API 规约"]}),open:r,onCancel:f,footer:null,width:1100,destroyOnClose:!0,children:[e.jsx(s.Tabs,{activeKey:k,onChange:S,items:[{key:"paste",label:e.jsxs("span",{children:[e.jsx(i.FileTextOutlined,{})," 粘贴 JSON"]}),children:e.jsxs("div",{children:[e.jsx(ms,{value:d,onChange:n=>g(n.target.value),placeholder:"粘贴 OpenAPI 3.x / Swagger 2.0 / Postman v2.1 JSON 内容…",autoSize:{minRows:6,maxRows:16},style:{fontFamily:"Menlo, Monaco, monospace",fontSize:12}}),e.jsxs(s.Space,{style:{marginTop:8},children:[e.jsx(s.Button,{size:"small",onClick:()=>U("openapi3"),children:"加载 OpenAPI 3 示例"}),e.jsx(s.Button,{size:"small",onClick:()=>U("swagger2"),children:"加载 Swagger 2 示例"}),e.jsx(s.Button,{size:"small",onClick:()=>U("postman"),children:"加载 Postman 示例"})]})]})},{key:"upload",label:e.jsxs("span",{children:[e.jsx(i.FileAddOutlined,{})," 上传文件"]}),children:e.jsxs(s.Upload.Dragger,{ref:w,accept:".json,.yaml,.yml,application/json,text/yaml",beforeUpload:J,showUploadList:!1,style:{padding:24},children:[e.jsx("p",{className:"ant-upload-drag-icon",children:e.jsx(i.CloudUploadOutlined,{style:{fontSize:48,color:"#1890ff"}})}),e.jsx("p",{className:"ant-upload-text",children:"点击或拖拽 JSON / YAML 文件到此处"}),e.jsx("p",{className:"ant-upload-hint",children:"支持 OpenAPI 3.x / Swagger 2.0 / Postman v2.1"})]})}]}),e.jsxs(s.Space,{style:{marginTop:12},children:[e.jsx(s.Button,{type:"primary",icon:e.jsx(i.ThunderboltOutlined,{}),onClick:M,loading:x,children:"解析"}),E&&e.jsx(s.Tag,{color:"blue",children:E.format}),E&&e.jsxs(s.Tag,{children:["共 ",E.count," 个端点,已选 ",j.length]})]}),O&&e.jsx(s.Alert,{type:"error",showIcon:!0,style:{marginTop:12},message:"解析失败",description:O}),E&&e.jsx(s.Card,{size:"small",style:{marginTop:16},title:"预览(可勾选要导入的)",children:e.jsx(s.Table,{size:"small",dataSource:E.endpoints||[],columns:l,rowKey:(n,_)=>_,rowSelection:{selectedRowKeys:j,onChange:B},pagination:{pageSize:8},scroll:{y:280}})}),E&&e.jsx(s.Card,{size:"small",style:{marginTop:16},title:"导入配置",children:e.jsxs(s.Form,{form:b,layout:"vertical",children:[e.jsxs(s.Row,{gutter:16,children:[e.jsx(s.Col,{span:6,children:e.jsx(s.Form.Item,{name:"envCode",label:"环境",rules:[{required:!0}],children:y.length>0?e.jsx(s.Select,{options:y.map(n=>({value:n,label:n}))}):e.jsx(s.Input,{})})}),e.jsx(s.Col,{span:6,children:e.jsx(s.Form.Item,{name:"projectCode",label:"项目",children:e.jsx(s.Input,{})})}),e.jsx(s.Col,{span:4,children:e.jsx(s.Form.Item,{name:"defaultStatus",label:"默认状态码",children:e.jsx(s.Input,{type:"number"})})}),e.jsx(s.Col,{span:4,children:e.jsx(s.Form.Item,{name:"priority",label:"优先级",children:e.jsx(s.Input,{type:"number"})})}),e.jsx(s.Col,{span:4,children:e.jsx(s.Form.Item,{name:"tagPrefix",label:"Tag 前缀",children:e.jsx(s.Input,{})})})]}),e.jsx(s.Form.Item,{name:"defaultResponse",label:"默认响应(无 example 时使用)",children:e.jsx(ms,{autoSize:{minRows:3,maxRows:6},style:{fontFamily:"Menlo, Monaco, monospace"}})}),e.jsxs(s.Button,{type:"primary",size:"large",icon:e.jsx(i.ImportOutlined,{}),onClick:H,loading:v,disabled:j.length===0,children:["批量导入 ",j.length," 个端点"]})]})})]})}function ft(r){return{GET:"blue",POST:"green",PUT:"orange",DELETE:"red",PATCH:"purple"}[r]||"default"}const{Text:Ee,Paragraph:rr}=s.Typography,xs=[{group:"基础数据",icon:e.jsx(i.CodeOutlined,{}),items:[{syntax:"@uuid",desc:"随机 UUID",example:"a3f2e1b7-8c4d-4e6f-9a1b-2c3d4e5f6a7b"},{syntax:"@int(1, 100)",desc:"随机整数(含边界)",example:"42"},{syntax:"@int",desc:"随机整数(0-1000)",example:"731"},{syntax:"@boolean",desc:"随机布尔",example:"true"},{syntax:'@pick("a","b","c")',desc:"从列表随机取一项",example:'"b"'}]},{group:"时间相关",icon:e.jsx(i.FunctionOutlined,{}),items:[{syntax:"@datetime",desc:"当前时间 (yyyy-MM-dd HH:mm:ss)",example:"2026-06-17 22:30:15"},{syntax:"@date",desc:"当前日期 (yyyy-MM-dd)",example:"2026-06-17"},{syntax:"@time",desc:"当前时间戳 (毫秒)",example:"1718639415000"},{syntax:"@timestamp",desc:"Unix 秒级时间戳",example:"1718639415"}]},{group:"文本生成",icon:e.jsx(i.FunctionOutlined,{}),items:[{syntax:"@name",desc:"随机中文姓名",example:"张伟"},{syntax:"@firstName",desc:"随机名",example:"伟"},{syntax:"@lastName",desc:"随机姓",example:"张"},{syntax:"@email",desc:"随机邮箱",example:"zhangwei@example.com"},{syntax:"@phone",desc:"随机手机号(中国)",example:"13812345678"},{syntax:"@idCard",desc:"随机身份证号",example:"110101199003078234"},{syntax:"@word",desc:"随机英文单词",example:"horizon"},{syntax:"@sentence(5, 10)",desc:"随机句子 (5-10 词)",example:"The quick brown fox jumps."},{syntax:"@paragraph(3, 5)",desc:"随机段落 (3-5 句)",example:"..."}]},{group:"序列与状态",icon:e.jsx(i.FunctionOutlined,{}),items:[{syntax:"@sequence(1)",desc:"自增序号(每次调用 +1,1 起始)",example:"1, 2, 3, ..."},{syntax:"@sequence(100, 5)",desc:"自增序号(100 起始,步长 5)",example:"100, 105, 110, ..."}]},{group:"请求上下文",icon:e.jsx(i.FunctionOutlined,{}),items:[{syntax:"#path.id",desc:"从 URL 路径取值 /users/123 → 123",example:"123"},{syntax:"#query.page",desc:"从 query string 取值 ?page=2",example:"2"},{syntax:"#header.X-Token",desc:"从请求头取值",example:"abc.def.ghi"},{syntax:"#body.username",desc:"从请求体 JSON 取值",example:'"alice"'}]}];function gs({onInsert:r,form:c,formField:o="responseTemplate"}){const[y,k]=t.useState(""),S=m=>{var x;try{(x=navigator.clipboard)==null||x.writeText(m)}catch{}if(r)r(m);else if(c){const z=c.getFieldValue(o)||"";c.setFieldsValue({[o]:z+(z.endsWith(`
|
|
29
|
+
`)||!z?"":" ")+m})}s.message.success(`已插入: ${m}`)},d=m=>{var x;try{(x=navigator.clipboard)==null||x.writeText(m),s.message.success("已复制到剪贴板")}catch{s.message.warning("复制失败,请手动选择")}},g=y.toLowerCase(),E=xs.map(m=>({...m,items:m.items.filter(x=>!g||x.syntax.toLowerCase().includes(g)||x.desc.toLowerCase().includes(g)||x.example.toLowerCase().includes(g))})).filter(m=>m.items.length>0),C=xs.reduce((m,x)=>m+x.items.length,0),O=E.reduce((m,x)=>m+x.items.length,0);return e.jsxs(s.Card,{size:"small",title:e.jsxs(s.Space,{children:[e.jsx(i.CodeOutlined,{}),e.jsx(Ee,{strong:!0,children:"模板表达式"}),e.jsxs(s.Tag,{color:"blue",children:[O,"/",C]}),e.jsx(s.Tooltip,{title:"点击按钮即可插入到上方响应模板;点击 syntax 文本可复制",children:e.jsx(i.InfoCircleOutlined,{style:{color:"#999"}})})]}),extra:e.jsx(s.Input,{size:"small",placeholder:"搜索 @ 表达式",prefix:e.jsx(i.SearchOutlined,{}),value:y,onChange:m=>k(m.target.value),style:{width:180},allowClear:!0}),style:{marginTop:8,background:"#fafafa"},styles:{body:{padding:12,maxHeight:320,overflow:"auto"}},children:[E.length===0&&e.jsx(Ee,{type:"secondary",style:{display:"block",textAlign:"center",padding:16},children:"没有匹配的表达式"}),E.map(m=>e.jsxs("div",{style:{marginBottom:12},children:[e.jsxs(s.Space,{size:4,style:{marginBottom:6},children:[m.icon,e.jsx(Ee,{strong:!0,style:{fontSize:13},children:m.group}),e.jsx(s.Tag,{children:m.items.length})]}),e.jsx(s.Row,{gutter:[8,8],children:m.items.map(x=>e.jsx(s.Col,{span:24,children:e.jsxs("div",{style:{display:"flex",alignItems:"center",padding:"6px 8px",background:"#fff",border:"1px solid #f0f0f0",borderRadius:4,gap:8},children:[e.jsx(s.Tooltip,{title:"点击复制",children:e.jsx(Ee,{code:!0,style:{cursor:"pointer",minWidth:140,fontSize:12},onClick:()=>d(x.syntax),children:x.syntax})}),e.jsx(Ee,{type:"secondary",style:{fontSize:12,flex:1},children:x.desc}),e.jsx(s.Tag,{color:"default",style:{margin:0,fontFamily:"monospace"},children:x.example}),e.jsx(s.Tooltip,{title:"插入到响应模板",children:e.jsx(s.Button,{size:"small",type:"text",icon:e.jsx(i.CopyOutlined,{}),onClick:()=>S(x.syntax)})})]})},x.syntax))})]},m.group))]})}const{TextArea:ye}=s.Input,{Text:ue,Paragraph:Ct}=s.Typography,St=[{value:"GET",label:"GET"},{value:"POST",label:"POST"},{value:"PUT",label:"PUT"},{value:"DELETE",label:"DELETE"},{value:"PATCH",label:"PATCH"}],ys={GET:"green",POST:"blue",PUT:"orange",DELETE:"red",PATCH:"purple"},Tt=[{value:"NONE",label:"无故障"},{value:"TIMEOUT",label:"超时 (TIMEOUT)"},{value:"EMPTY_RESPONSE",label:"空响应 (EMPTY)"},{value:"RANDOM_DROP",label:"随机丢弃 (RANDOM_DROP)"},{value:"MALFORMED",label:"畸形响应 (MALFORMED)"},{value:"500_ERROR",label:"500 错误"},{value:"RATE_LIMIT",label:"限流 (RATE_LIMIT)"}],bt=[{value:"JSON",label:"JSON"},{value:"JSONPATH",label:"JSONPath"},{value:"REGEX",label:"正则"},{value:"TEXT",label:"纯文本"}];function ze({activeEnvCode:r}){const[c,o]=t.useState([]),[y,k]=t.useState(!1),[S,d]=t.useState(null),[g,E]=t.useState(!1),[C,O]=t.useState(null),[m]=s.Form.useForm(),[x,z]=t.useState(!1),[j,B]=t.useState(null),[v,N]=t.useState(!1);t.useEffect(()=>{b()},[r]);const b=async()=>{k(!0),d(null);try{const l=await q.endpoints.list(r);o(Array.isArray(l)?l:[])}catch(l){d((l==null?void 0:l.message)||"API unavailable"),o([])}finally{k(!1)}},w=()=>{O(null),m.resetFields(),m.setFieldsValue({method:"GET",statusCode:200,delayMs:0,priority:5,envCode:r||"default",matchBodyType:"JSON",faultType:"NONE",status:1}),E(!0)},P=l=>{O(l),m.setFieldsValue(l),E(!0)},f=async()=>{try{const l=await m.validateFields();C?(await q.endpoints.update(C.mockCode,l),s.message.success("更新成功")):(await q.endpoints.create(l),s.message.success("创建成功")),E(!1),b()}catch(l){if(l!=null&&l.errorFields)return;s.message.error("保存失败: "+((l==null?void 0:l.message)||""))}},M=async l=>{try{await q.endpoints.delete(l),s.message.success("删除成功"),b()}catch{s.message.error("删除失败")}},U=async l=>{const n=l.status===1?0:1;try{await q.endpoints.toggle(l.mockCode,n),s.message.success(n===1?"已启用":"已禁用"),b()}catch{s.message.error("操作失败")}},J=l=>`${window.location.origin}/api/mock/${l.envCode||r||"default"}${l.path||""}`,H=[{title:"路径",dataIndex:"path",key:"path",width:280,render:(l,n)=>e.jsxs(s.Space,{children:[e.jsx(s.Tag,{color:ys[n.method]||"default",children:n.method}),e.jsx(ue,{code:!0,copyable:{text:l},children:l})]})},{title:"编码",dataIndex:"mockCode",key:"mockCode",width:160},{title:"优先级",dataIndex:"priority",key:"priority",width:80,align:"center",render:l=>e.jsxs(s.Tag,{color:"blue",children:["P",l||5]})},{title:"状态码",dataIndex:"statusCode",key:"statusCode",width:80,align:"center"},{title:"延迟",dataIndex:"delayMs",key:"delayMs",width:80,align:"center",render:l=>l>0?e.jsxs(ue,{type:"warning",children:[l,"ms"]}):e.jsx(ue,{type:"secondary",children:"-"})},{title:"故障",dataIndex:"faultType",key:"faultType",width:110,render:l=>l&&l!=="NONE"?e.jsx(s.Tag,{color:"red",children:l}):e.jsx(ue,{type:"secondary",children:"-"})},{title:"场景",dataIndex:"scenarioCode",key:"scenarioCode",width:130,render:l=>l?e.jsx(s.Tag,{color:"purple",children:l}):e.jsx(ue,{type:"secondary",children:"-"})},{title:"命中",dataIndex:"hitCount",key:"hitCount",width:80,align:"center",render:l=>e.jsx(ue,{strong:!0,children:l||0})},{title:"状态",key:"status",width:100,align:"center",render:(l,n)=>e.jsx(s.Switch,{checked:n.status===1,onChange:()=>U(n),checkedChildren:"启用",unCheckedChildren:"禁用",size:"small"})},{title:"操作",key:"action",width:220,fixed:"right",render:(l,n)=>e.jsxs(s.Space,{size:"small",children:[e.jsx(s.Tooltip,{title:"预览响应",children:e.jsx(s.Button,{size:"small",type:"link",icon:e.jsx(i.PlayCircleOutlined,{}),onClick:()=>{B(n),z(!0)},children:"预览"})}),e.jsx(s.Tooltip,{title:"复制URL",children:e.jsx(s.Button,{size:"small",type:"link",icon:e.jsx(i.CopyOutlined,{}),onClick:()=>{navigator.clipboard.writeText(J(n)),s.message.success("已复制")}})}),e.jsx(s.Tooltip,{title:"编辑",children:e.jsx(s.Button,{size:"small",type:"link",icon:e.jsx(i.EditOutlined,{}),onClick:()=>P(n)})}),e.jsx(s.Popconfirm,{title:"确认删除?",onConfirm:()=>M(n.mockCode),children:e.jsx(s.Button,{size:"small",type:"link",danger:!0,icon:e.jsx(i.DeleteOutlined,{})})})]})}];return e.jsxs("div",{children:[S&&e.jsx(s.Alert,{type:"warning",showIcon:!0,style:{marginBottom:16},message:"后端 API 暂未连接",description:S}),e.jsxs(s.Row,{gutter:16,style:{marginBottom:16},children:[e.jsx(s.Col,{span:6,children:e.jsxs(s.Card,{children:[e.jsx("strong",{children:"总端点"}),e.jsx("div",{style:{fontSize:22},children:c.length})]})}),e.jsx(s.Col,{span:6,children:e.jsxs(s.Card,{children:[e.jsx("strong",{children:"已启用"}),e.jsx("div",{style:{fontSize:22,color:"#52c41a"},children:c.filter(l=>l.status===1).length})]})}),e.jsx(s.Col,{span:6,children:e.jsxs(s.Card,{children:[e.jsx("strong",{children:"已禁用"}),e.jsx("div",{style:{fontSize:22,color:"#ff4d4f"},children:c.filter(l=>l.status===0).length})]})}),e.jsx(s.Col,{span:6,children:e.jsxs(s.Card,{children:[e.jsx("strong",{children:"总命中"}),e.jsx("div",{style:{fontSize:22,color:"#1890ff"},children:c.reduce((l,n)=>l+(n.hitCount||0),0)})]})})]}),e.jsxs(s.Space,{style:{marginBottom:16},children:[e.jsx(s.Button,{icon:e.jsx(i.PlayCircleOutlined,{}),onClick:b,children:"刷新"}),e.jsx(s.Button,{type:"primary",icon:e.jsx(i.PlusOutlined,{}),onClick:w,children:"新建 Mock 端点"}),e.jsx(s.Button,{icon:e.jsx(i.CloudUploadOutlined,{}),onClick:()=>N(!0),children:"批量导入 (OpenAPI / Swagger / Postman)"})]}),e.jsx(s.Table,{dataSource:c,columns:H,rowKey:"id",loading:y,pagination:{pageSize:10},scroll:{x:1300},size:"small"}),e.jsx(s.Modal,{title:C?`编辑 Mock 端点: ${C.mockCode}`:"新建 Mock 端点",open:g,onCancel:()=>E(!1),onOk:f,width:900,okText:"保存",cancelText:"取消",children:e.jsx(s.Form,{form:m,layout:"vertical",style:{marginTop:16},children:e.jsx(s.Tabs,{items:[{key:"basic",label:"基本信息",children:e.jsxs(e.Fragment,{children:[e.jsxs(s.Row,{gutter:16,children:[e.jsx(s.Col,{span:8,children:e.jsx(s.Form.Item,{name:"mockCode",label:"Mock 编码",rules:[{required:!0}],children:e.jsx(s.Input,{placeholder:"mock-user-list",disabled:!!C})})}),e.jsx(s.Col,{span:8,children:e.jsx(s.Form.Item,{name:"mockName",label:"名称",children:e.jsx(s.Input,{placeholder:"User List Endpoint"})})}),e.jsx(s.Col,{span:8,children:e.jsx(s.Form.Item,{name:"envCode",label:"环境编码",children:e.jsx(s.Input,{placeholder:"default"})})})]}),e.jsxs(s.Row,{gutter:16,children:[e.jsx(s.Col,{span:12,children:e.jsx(s.Form.Item,{name:"path",label:"路径",rules:[{required:!0}],children:e.jsx(s.Input,{placeholder:"/api/user/list"})})}),e.jsx(s.Col,{span:4,children:e.jsx(s.Form.Item,{name:"method",label:"方法",children:e.jsx(s.Select,{options:St})})}),e.jsx(s.Col,{span:4,children:e.jsx(s.Form.Item,{name:"priority",label:"优先级",children:e.jsx(s.InputNumber,{min:0,max:99,style:{width:"100%"}})})}),e.jsx(s.Col,{span:4,children:e.jsx(s.Form.Item,{name:"statusCode",label:"状态码",children:e.jsx(s.InputNumber,{min:100,max:599,style:{width:"100%"}})})})]}),e.jsxs(s.Row,{gutter:16,children:[e.jsx(s.Col,{span:8,children:e.jsx(s.Form.Item,{name:"delayMs",label:"延迟(ms)",children:e.jsx(s.InputNumber,{min:0,max:6e4,style:{width:"100%"}})})}),e.jsx(s.Col,{span:8,children:e.jsx(s.Form.Item,{name:"projectCode",label:"项目",children:e.jsx(s.Input,{placeholder:"default"})})}),e.jsx(s.Col,{span:8,children:e.jsx(s.Form.Item,{name:"moduleCode",label:"模块",children:e.jsx(s.Input,{placeholder:"user"})})})]}),e.jsx(s.Form.Item,{name:"description",label:"描述",children:e.jsx(ye,{rows:2})})]})},{key:"match",label:"请求匹配",children:e.jsxs(e.Fragment,{children:[e.jsx(s.Form.Item,{name:"matchUrlPattern",label:"URL 匹配模式 (Ant风格)",extra:"支持 /api/users/{id} 通配符,留空则按 path 精确匹配",children:e.jsx(s.Input,{placeholder:"/api/users/{id}"})}),e.jsxs(s.Row,{gutter:16,children:[e.jsx(s.Col,{span:12,children:e.jsx(s.Form.Item,{name:"matchHeaders",label:"Header 匹配 (JSON)",extra:'例: {"Authorization": "Bearer *", "Content-Type": "application/json"}',children:e.jsx(ye,{rows:3,placeholder:'{"Authorization": "Bearer *"}'})})}),e.jsx(s.Col,{span:12,children:e.jsx(s.Form.Item,{name:"matchQuery",label:"Query 匹配 (JSON)",extra:'例: {"page": "1", "size": "10"}',children:e.jsx(ye,{rows:3,placeholder:'{"page": "1"}'})})})]}),e.jsx(s.Form.Item,{name:"matchBodyType",label:"Body 匹配类型",children:e.jsx(s.Select,{options:bt})}),e.jsx(s.Form.Item,{name:"matchBody",label:"Body 匹配表达式",extra:"JSON 类型支持 JSONPath,REGEX 类型为正则表达式",children:e.jsx(ye,{rows:3,placeholder:'$.user.id == "100"'})})]})},{key:"scenario",label:"场景状态机",children:e.jsxs(e.Fragment,{children:[e.jsx(s.Form.Item,{name:"scenarioCode",label:"场景编码",extra:"关联场景实现状态机驱动 (如 user-flow, payment-flow)",children:e.jsx(s.Input,{placeholder:"user-flow"})}),e.jsxs(s.Row,{gutter:16,children:[e.jsx(s.Col,{span:12,children:e.jsx(s.Form.Item,{name:"requiredState",label:"匹配所需状态",extra:"仅当实例处于此状态时才匹配 (留空 = 不限制)",children:e.jsx(s.Input,{placeholder:"started"})})}),e.jsx(s.Col,{span:12,children:e.jsx(s.Form.Item,{name:"newState",label:"匹配后新状态",extra:"匹配成功后自动切换",children:e.jsx(s.Input,{placeholder:"logged-in"})})})]})]})},{key:"fault",label:"故障注入",children:e.jsxs(e.Fragment,{children:[e.jsx(s.Form.Item,{name:"faultType",label:"故障类型",extra:"模拟网络异常,验证客户端容错",children:e.jsx(s.Select,{options:Tt})}),e.jsx(s.Form.Item,{name:"faultConfig",label:"故障配置 (JSON)",extra:'例: {"errorRate": 0.5, "rateLimitQps": 10, "timeoutMs": 30000}',children:e.jsx(ye,{rows:4,placeholder:'{"errorRate": 0.5}'})}),e.jsx(s.Form.Item,{name:"proxyTo",label:"代理目标 URL",extra:"未匹配时转发到真实服务 (MockEnvironment 模式)",children:e.jsx(s.Input,{placeholder:"http://real-service:8080"})})]})},{key:"response",label:"响应",children:e.jsxs(e.Fragment,{children:[e.jsx(s.Form.Item,{name:"responseHeaders",label:"响应头 (JSON)",extra:'例: {"Content-Type": "application/json", "X-Trace-Id": "..."}',children:e.jsx(ye,{rows:2,placeholder:'{"Content-Type": "application/json"}'})}),e.jsx(s.Form.Item,{name:"responseTemplate",label:"响应模板 (JSON)",rules:[{required:!0}],extra:e.jsxs("div",{children:[e.jsxs(ue,{type:"secondary",style:{display:"block",marginBottom:4},children:["支持 ",e.jsx("code",{children:"@int(1,100)"})," / ",e.jsx("code",{children:"@uuid"})," / ",e.jsx("code",{children:"@datetime"})," / ",e.jsx("code",{children:"#path.id"})," 等动态表达式"]}),e.jsx(gs,{form:m,formField:"responseTemplate"})]}),children:e.jsx(ye,{rows:14,placeholder:`{
|
|
30
|
+
"success": true,
|
|
31
|
+
"data": [],
|
|
32
|
+
"code": 200
|
|
33
|
+
}`,style:{fontFamily:"monospace",fontSize:13}})})]})}]})})}),e.jsx(s.Drawer,{title:e.jsxs(s.Space,{children:[e.jsx(i.ExperimentOutlined,{}),"端点详情: ",j==null?void 0:j.mockCode]}),open:x,onClose:()=>z(!1),width:650,children:j&&e.jsxs("div",{children:[e.jsxs(s.Descriptions,{column:2,size:"small",bordered:!0,style:{marginBottom:16},children:[e.jsx(s.Descriptions.Item,{label:"编码",children:j.mockCode}),e.jsx(s.Descriptions.Item,{label:"名称",children:j.mockName}),e.jsx(s.Descriptions.Item,{label:"方法",children:e.jsx(s.Tag,{color:ys[j.method],children:j.method})}),e.jsx(s.Descriptions.Item,{label:"环境",children:j.envCode}),e.jsx(s.Descriptions.Item,{label:"路径",span:2,children:j.path}),e.jsx(s.Descriptions.Item,{label:"状态码",children:j.statusCode}),e.jsxs(s.Descriptions.Item,{label:"延迟",children:[j.delayMs,"ms"]}),e.jsxs(s.Descriptions.Item,{label:"优先级",children:["P",j.priority]}),e.jsx(s.Descriptions.Item,{label:"命中",children:j.hitCount||0}),e.jsx(s.Descriptions.Item,{label:"故障",children:j.faultType&&j.faultType!=="NONE"?e.jsx(s.Tag,{color:"red",children:j.faultType}):e.jsx(ue,{type:"secondary",children:"-"})}),e.jsx(s.Descriptions.Item,{label:"场景",children:j.scenarioCode||"-"}),e.jsx(s.Descriptions.Item,{label:"状态",span:2,children:j.status===1?e.jsx(s.Tag,{color:"green",children:"启用"}):e.jsx(s.Tag,{children:"禁用"})}),e.jsx(s.Descriptions.Item,{label:"完整 URL",span:2,children:e.jsx(ue,{copyable:!0,children:J(j)})})]}),e.jsx(Ct,{strong:!0,children:"响应模板:"}),e.jsx("pre",{style:{background:"#f5f5f5",padding:12,borderRadius:4,maxHeight:350,overflow:"auto",fontSize:13,fontFamily:"monospace",whiteSpace:"pre-wrap",wordBreak:"break-all"},children:j.responseTemplate})]})}),e.jsx(hs,{open:v,onClose:()=>N(!1),onSuccess:()=>{s.message.success("已刷新列表"),b()}})]})}const{Text:Ge}=s.Typography,wt=[{value:"MOCK",label:"MOCK (纯 Mock 拦截)",color:"green"},{value:"REAL",label:"REAL (全部代理到真实)",color:"blue"},{value:"MIXED",label:"MIXED (匹配失败时转发)",color:"orange"}],It={MOCK:"green",REAL:"blue",MIXED:"orange"};function Me({onEnvChange:r}){const[c,o]=t.useState([]),[y,k]=t.useState(!1),[S,d]=t.useState(!1),[g,E]=t.useState(null),[C]=s.Form.useForm();t.useEffect(()=>{O()},[]);const O=async()=>{k(!0);try{const v=await q.environments.list();o(Array.isArray(v)?v:[])}catch(v){s.message.warning("加载环境列表失败: "+(v==null?void 0:v.message))}finally{k(!1)}},m=()=>{E(null),C.resetFields(),C.setFieldsValue({envType:"MOCK",isDefault:0,mockPriority:1}),d(!0)},x=v=>{E(v),C.setFieldsValue(v),d(!0)},z=async()=>{try{const v=await C.validateFields();g?(await q.environments.update(g.envCode,v),s.message.success("更新成功")):(await q.environments.create(v),s.message.success("创建成功")),d(!1),O()}catch(v){if(v!=null&&v.errorFields)return;s.message.error("保存失败")}},j=async v=>{try{await q.environments.delete(v),s.message.success("删除成功"),O()}catch(N){s.message.error("删除失败: "+((N==null?void 0:N.message)||""))}},B=[{title:"环境编码",dataIndex:"envCode",key:"envCode",width:140,render:v=>e.jsx(Ge,{code:!0,children:v})},{title:"环境名称",dataIndex:"envName",key:"envName",width:160},{title:"类型",dataIndex:"envType",key:"envType",width:240,render:v=>e.jsx(s.Tag,{color:It[v]||"default",children:v})},{title:"真实服务地址",dataIndex:"baseUrl",key:"baseUrl",render:v=>v?e.jsx(Ge,{copyable:!0,children:v}):e.jsx(Ge,{type:"secondary",children:"-"})},{title:"默认",dataIndex:"isDefault",key:"isDefault",width:90,align:"center",render:v=>v===1?e.jsx(s.Tag,{color:"gold",children:"默认"}):"-"},{title:"描述",dataIndex:"description",key:"description",width:220,render:v=>v||"-"},{title:"操作",key:"action",width:180,render:(v,N)=>e.jsxs(s.Space,{size:"small",children:[e.jsx(s.Button,{size:"small",type:"link",icon:e.jsx(i.GlobalOutlined,{}),onClick:()=>{r&&r(N.envCode)},children:"切换"}),e.jsx(s.Button,{size:"small",type:"link",icon:e.jsx(i.EditOutlined,{}),onClick:()=>x(N)}),N.isDefault!==1&&e.jsx(s.Popconfirm,{title:`确认删除环境 ${N.envCode}?`,onConfirm:()=>j(N.envCode),children:e.jsx(s.Button,{size:"small",type:"link",danger:!0,icon:e.jsx(i.DeleteOutlined,{})})})]})}];return e.jsxs("div",{children:[e.jsx(s.Alert,{type:"info",showIcon:!0,style:{marginBottom:16},message:"环境隔离 - 控制 Mock 与真实服务的切换",description:e.jsxs("div",{children:[e.jsxs("div",{children:[e.jsx(s.Tag,{color:"green",children:"MOCK"})," 完全拦截,仅返回 Mock 数据"]}),e.jsxs("div",{children:[e.jsx(s.Tag,{color:"blue",children:"REAL"})," 全部代理到 baseUrl(适合压测、回归测试)"]}),e.jsxs("div",{children:[e.jsx(s.Tag,{color:"orange",children:"MIXED"})," Mock 优先,未匹配时转发到 baseUrl(开发联调)"]})]})}),e.jsxs(s.Space,{style:{marginBottom:16},children:[e.jsx(s.Button,{icon:e.jsx(i.ReloadOutlined,{}),onClick:O,children:"刷新"}),e.jsx(s.Button,{type:"primary",icon:e.jsx(i.PlusOutlined,{}),onClick:m,children:"新建环境"})]}),e.jsx(s.Table,{dataSource:c,columns:B,rowKey:"id",loading:y,pagination:{pageSize:10},size:"small"}),e.jsx(s.Modal,{title:g?`编辑环境: ${g.envCode}`:"新建环境",open:S,onCancel:()=>d(!1),onOk:z,width:650,children:e.jsxs(s.Form,{form:C,layout:"vertical",style:{marginTop:16},children:[e.jsxs(s.Row,{gutter:16,children:[e.jsx(s.Col,{span:12,children:e.jsx(s.Form.Item,{name:"envCode",label:"环境编码",rules:[{required:!0}],children:e.jsx(s.Input,{placeholder:"dev / staging / prod",disabled:!!g})})}),e.jsx(s.Col,{span:12,children:e.jsx(s.Form.Item,{name:"envName",label:"环境名称",rules:[{required:!0}],children:e.jsx(s.Input,{placeholder:"开发环境"})})})]}),e.jsx(s.Form.Item,{name:"envType",label:"环境类型",rules:[{required:!0}],children:e.jsx(s.Select,{options:wt})}),e.jsx(s.Form.Item,{name:"baseUrl",label:"真实服务地址",extra:"REAL/MIXED 时使用。MIXED 时未匹配的请求会转发到这里",children:e.jsx(s.Input,{placeholder:"https://api.staging.example.com"})}),e.jsxs(s.Row,{gutter:16,children:[e.jsx(s.Col,{span:12,children:e.jsx(s.Form.Item,{name:"mockPriority",label:"Mock 优先级",children:e.jsx(s.InputNumber,{min:0,max:10,style:{width:"100%"}})})}),e.jsx(s.Col,{span:12,children:e.jsx(s.Form.Item,{name:"isDefault",label:"是否默认",valuePropName:"checked",children:e.jsx(s.Switch,{checkedChildren:"是",unCheckedChildren:"否"})})})]}),e.jsx(s.Form.Item,{name:"description",label:"描述",children:e.jsx(s.Input.TextArea,{rows:3,placeholder:"环境的用途说明"})})]})})]})}const{Text:kt}=s.Typography;function js(){const[r,c]=t.useState([]),[o,y]=t.useState(!1),[k,S]=t.useState(!1),[d,g]=t.useState(null),[E,C]=t.useState(!1),[O,m]=t.useState(null),[x]=s.Form.useForm();t.useEffect(()=>{z()},[]);const z=async()=>{y(!0);try{const f=await q.scenarios.list();c(Array.isArray(f)?f:[])}catch{s.message.warning("加载场景列表失败")}finally{y(!1)}},j=()=>{g(null),x.resetFields(),x.setFieldsValue({initialState:"started"}),S(!0)},B=f=>{g(f),x.setFieldsValue(f),S(!0)},v=async()=>{try{const f=await x.validateFields();let M;try{M=f.statesJson?JSON.parse(f.statesJson):null}catch{s.message.error("状态列表 JSON 格式错误");return}const U={...f,states:M};delete U.statesJson,d?(await q.scenarios.update(d.scenarioCode,U),s.message.success("更新成功")):(await q.scenarios.create(U),s.message.success("创建成功")),S(!1),z()}catch(f){f!=null&&f.errorFields||s.message.error("保存失败")}},N=async f=>{try{await q.scenarios.delete(f),s.message.success("删除成功"),z()}catch{s.message.error("删除失败")}},b=async f=>{try{await q.scenarios.reset(f),s.message.success("已重置所有实例状态")}catch{s.message.error("重置失败")}},w=async f=>{try{const M=await q.scenarios.instances(f);m({code:f,list:M}),C(!0)}catch{s.message.error("加载失败")}},P=[{title:"场景编码",dataIndex:"scenarioCode",key:"scenarioCode",width:160,render:f=>e.jsx(kt,{code:!0,children:f})},{title:"场景名称",dataIndex:"scenarioName",key:"scenarioName",width:200},{title:"初始状态",dataIndex:"initialState",key:"initialState",width:140,render:f=>e.jsx(s.Tag,{color:"blue",children:f})},{title:"状态列表",dataIndex:"states",key:"states",render:f=>{if(!f)return"-";try{const M=typeof f=="string"?JSON.parse(f):f;return Array.isArray(M)?M.map(U=>e.jsx(s.Tag,{children:U},U)):"-"}catch{return"-"}}},{title:"描述",dataIndex:"description",key:"description",width:240,render:f=>f||"-"},{title:"操作",key:"action",width:280,fixed:"right",render:(f,M)=>e.jsxs(s.Space,{size:"small",children:[e.jsx(s.Button,{size:"small",type:"link",icon:e.jsx(i.NodeIndexOutlined,{}),onClick:()=>w(M.scenarioCode),children:"实例"}),e.jsx(s.Button,{size:"small",type:"link",icon:e.jsx(i.UndoOutlined,{}),onClick:()=>b(M.scenarioCode),children:"重置"}),e.jsx(s.Button,{size:"small",type:"link",icon:e.jsx(i.EditOutlined,{}),onClick:()=>B(M)}),e.jsx(s.Popconfirm,{title:`删除场景 ${M.scenarioCode}?`,onConfirm:()=>N(M.scenarioCode),children:e.jsx(s.Button,{size:"small",type:"link",danger:!0,icon:e.jsx(i.DeleteOutlined,{})})})]})}];return e.jsxs("div",{children:[e.jsx(s.Alert,{type:"info",showIcon:!0,style:{marginBottom:16},message:"场景状态机 (Scenario)",description:"用状态机驱动 Mock 集合,模拟完整业务流程(如:未登录→登录中→已登录→下单→已支付→完成)。实例通过 X-Session-Id 或 X-Trace-Id 区分,每个实例独立维护当前状态。"}),e.jsxs(s.Space,{style:{marginBottom:16},children:[e.jsx(s.Button,{icon:e.jsx(i.ReloadOutlined,{}),onClick:z,children:"刷新"}),e.jsx(s.Button,{type:"primary",icon:e.jsx(i.PlusOutlined,{}),onClick:j,children:"新建场景"})]}),e.jsx(s.Table,{dataSource:r,columns:P,rowKey:"id",loading:o,pagination:{pageSize:10},scroll:{x:1100},size:"small"}),e.jsx(s.Modal,{title:d?`编辑场景: ${d.scenarioCode}`:"新建场景",open:k,onCancel:()=>S(!1),onOk:v,width:650,children:e.jsxs(s.Form,{form:x,layout:"vertical",style:{marginTop:16},children:[e.jsxs(s.Row,{gutter:16,children:[e.jsx(s.Col,{span:12,children:e.jsx(s.Form.Item,{name:"scenarioCode",label:"场景编码",rules:[{required:!0}],children:e.jsx(s.Input,{placeholder:"user-login-flow",disabled:!!d})})}),e.jsx(s.Col,{span:12,children:e.jsx(s.Form.Item,{name:"scenarioName",label:"场景名称",children:e.jsx(s.Input,{placeholder:"用户登录流程"})})})]}),e.jsx(s.Form.Item,{name:"initialState",label:"初始状态",rules:[{required:!0}],children:e.jsx(s.Input,{placeholder:"started"})}),e.jsx(s.Form.Item,{name:"statesJson",label:"状态列表 (JSON 数组)",extra:'例: ["started", "logged-in", "checkout", "paid", "completed"]',children:e.jsx(s.Input.TextArea,{rows:3,placeholder:'["started", "logged-in", "checkout", "paid"]'})}),e.jsx(s.Form.Item,{name:"description",label:"描述",children:e.jsx(s.Input.TextArea,{rows:3,placeholder:"场景的业务说明"})})]})}),e.jsx(s.Modal,{title:`场景实例: ${O==null?void 0:O.code}`,open:E,onCancel:()=>C(!1),footer:e.jsx(s.Button,{onClick:()=>C(!1),children:"关闭"}),width:700,children:O&&e.jsx(s.Table,{dataSource:Array.isArray(O.list)?O.list:[],columns:[{title:"实例标识",dataIndex:"instanceKey",key:"instanceKey"},{title:"当前状态",dataIndex:"currentState",key:"currentState",render:f=>e.jsx(s.Tag,{color:"blue",children:f})},{title:"最后变更",dataIndex:"lastUpdateTime",key:"lastUpdateTime"}],rowKey:(f,M)=>f.instanceKey||M,pagination:!1,size:"small"})})]})}const{TextArea:fs}=s.Input,{Text:Te,Paragraph:vt}=s.Typography;function Cs({open:r,onClose:c,onSuccess:o,envOptions:y=[]}){const[k,S]=t.useState(""),[d,g]=t.useState(null),[E,C]=t.useState(null),[O,m]=t.useState(!1),[x,z]=t.useState(null),[j,B]=t.useState(!1),[v,N]=t.useState("import"),[b]=s.Form.useForm(),[w]=s.Form.useForm(),P=()=>{S(""),g(null),C(null),z(null),b.resetFields(),w.resetFields()},f=()=>{P(),c()},M=async()=>{var l,n,_,T;if(!k.trim()){s.message.warning("请先粘贴 curl 命令");return}C(null),g(null),z(null);try{const A=await q.curl.parse(k);A.success?(g(A.data),b.setFieldsValue({caseName:`from-curl-${((l=A.data)==null?void 0:l.method)||"GET"}-${(((n=A.data)==null?void 0:n.path)||"").replace(/\W+/g,"-")}`,caseGroup:"imported",envCode:y[0]||"default"}),w.setFieldsValue({mockName:`mock-${((_=A.data)==null?void 0:_.method)||"GET"}-${(((T=A.data)==null?void 0:T.path)||"").replace(/\W+/g,"-")}`,envCode:y[0]||"default",projectCode:"default",responseTemplate:`{
|
|
34
|
+
"code": 0,
|
|
35
|
+
"message": "ok",
|
|
36
|
+
"data": {}
|
|
37
|
+
}`})):C(A.message||"解析失败")}catch(A){C(String((A==null?void 0:A.message)||A))}},U=async()=>{if(!k.trim()){s.message.warning("请先粘贴 curl 命令");return}m(!0),z(null);try{const l=await q.curl.run(k);z(l)}catch(l){z({success:!1,error:String((l==null?void 0:l.message)||l)})}finally{m(!1)}},J=async()=>{if(!d){s.message.warning("请先解析");return}let l;try{l=await b.validateFields()}catch{return}B(!0);try{const n=await q.curl.importAsCase({curl:k,caseName:l.caseName,caseGroup:l.caseGroup,envCode:l.envCode});n.success?(s.message.success(`已导入测试用例: ${n.caseCode}`),o&&o("case",n),f()):s.message.error(n.message||"导入失败")}catch(n){s.message.error(String((n==null?void 0:n.message)||n))}finally{B(!1)}},H=async()=>{if(!d){s.message.warning("请先解析");return}let l;try{l=await w.validateFields()}catch{return}B(!0);try{const n=await q.curl.importAsEndpoint({curl:k,mockName:l.mockName,envCode:l.envCode,projectCode:l.projectCode,responseTemplate:l.responseTemplate});n.success?(s.message.success(`已导入 Mock 端点: ${n.mockCode}`),o&&o("endpoint",n),f()):s.message.error(n.message||"导入失败")}catch(n){s.message.error(String((n==null?void 0:n.message)||n))}finally{B(!1)}};return e.jsxs(s.Modal,{title:e.jsxs(s.Space,{children:[e.jsx(i.CodeOutlined,{})," 粘贴 curl 一键导入"]}),open:r,onCancel:f,footer:null,width:900,destroyOnClose:!0,children:[e.jsx(vt,{type:"secondary",style:{marginBottom:12},children:"从浏览器 DevTools / Postman / 终端复制 curl 命令,粘贴到下方即可解析、试跑、入库。"}),e.jsx(fs,{value:k,onChange:l=>S(l.target.value),placeholder:`curl -X POST 'https://api.example.com/v1/users/login' \\
|
|
38
|
+
-H 'Content-Type: application/json' \\
|
|
39
|
+
-H 'Authorization: Bearer xxx' \\
|
|
40
|
+
-d '{"username":"alice","password":"123456"}'`,autoSize:{minRows:4,maxRows:10},style:{fontFamily:"Menlo, Monaco, monospace",fontSize:12}}),e.jsxs(s.Space,{style:{marginTop:12},children:[e.jsx(s.Button,{icon:e.jsx(i.FileTextOutlined,{}),onClick:M,type:"primary",ghost:!0,children:"解析"}),e.jsx(s.Button,{icon:e.jsx(i.ThunderboltOutlined,{}),onClick:U,loading:O,children:"直接执行(试跑)"})]}),E&&e.jsx(s.Alert,{type:"error",showIcon:!0,style:{marginTop:12},message:"解析失败",description:E}),d&&e.jsx(s.Card,{size:"small",style:{marginTop:16},title:"解析结果",children:e.jsxs(s.Descriptions,{column:1,size:"small",bordered:!0,children:[e.jsx(s.Descriptions.Item,{label:"Method",children:e.jsx(s.Tag,{color:Et(d.method),children:d.method})}),e.jsx(s.Descriptions.Item,{label:"URL",children:e.jsx(Te,{code:!0,copyable:!0,children:d.url})}),e.jsx(s.Descriptions.Item,{label:"Path",children:e.jsx(Te,{code:!0,children:d.path})}),d.query&&e.jsx(s.Descriptions.Item,{label:"Query",children:e.jsx(Te,{code:!0,children:d.query})}),e.jsx(s.Descriptions.Item,{label:"Headers",children:Object.keys(d.headers||{}).length===0?e.jsx(Te,{type:"secondary",children:"(无)"}):e.jsx("div",{children:Object.entries(d.headers).map(([l,n])=>e.jsxs("div",{children:[e.jsxs(Te,{strong:!0,children:[l,":"]})," ",e.jsx(Te,{code:!0,children:n})]},l))})}),d.body&&e.jsx(s.Descriptions.Item,{label:"Body",children:e.jsx("pre",{style:{background:"#f5f5f5",padding:8,margin:0,fontSize:12,maxHeight:200,overflow:"auto"},children:d.body})})]})}),x&&e.jsxs(s.Card,{size:"small",style:{marginTop:16},title:e.jsxs(s.Space,{children:[e.jsx(i.ThunderboltOutlined,{}),e.jsx("span",{children:"试跑结果"}),x.success?e.jsxs(s.Tag,{color:"green",children:[x.status," · ",x.durationMs,"ms · ",x.bodySize,"B"]}):e.jsx(s.Tag,{color:"red",children:"FAILED"})]}),children:[x.error&&e.jsx(s.Alert,{type:"error",showIcon:!0,message:x.error}),x.body!=null&&e.jsx("pre",{style:{background:"#f5f5f5",padding:8,margin:0,fontSize:12,maxHeight:240,overflow:"auto"},children:x.body})]}),d&&e.jsx(s.Tabs,{activeKey:v,onChange:N,style:{marginTop:16},items:[{key:"import",label:e.jsxs("span",{children:[e.jsx(i.ImportOutlined,{})," 导入为测试用例"]}),children:e.jsxs(s.Form,{form:b,layout:"vertical",children:[e.jsxs(s.Row,{gutter:16,children:[e.jsx(s.Col,{span:12,children:e.jsx(s.Form.Item,{name:"caseName",label:"用例名称",rules:[{required:!0}],children:e.jsx(s.Input,{})})}),e.jsx(s.Col,{span:6,children:e.jsx(s.Form.Item,{name:"caseGroup",label:"用例分组",children:e.jsx(s.Input,{})})}),e.jsx(s.Col,{span:6,children:e.jsx(s.Form.Item,{name:"envCode",label:"环境",children:y.length>0?e.jsx(s.Select,{options:y.map(l=>({value:l,label:l}))}):e.jsx(s.Input,{})})})]}),e.jsx(s.Button,{type:"primary",onClick:J,loading:j,icon:e.jsx(i.ImportOutlined,{}),children:"保存为测试用例"})]})},{key:"mock",label:e.jsxs("span",{children:[e.jsx(i.CodeOutlined,{})," 导入为 Mock 端点"]}),children:e.jsxs(s.Form,{form:w,layout:"vertical",children:[e.jsxs(s.Row,{gutter:16,children:[e.jsx(s.Col,{span:12,children:e.jsx(s.Form.Item,{name:"mockName",label:"Mock 名称",rules:[{required:!0}],children:e.jsx(s.Input,{})})}),e.jsx(s.Col,{span:6,children:e.jsx(s.Form.Item,{name:"envCode",label:"环境",children:y.length>0?e.jsx(s.Select,{options:y.map(l=>({value:l,label:l}))}):e.jsx(s.Input,{})})}),e.jsx(s.Col,{span:6,children:e.jsx(s.Form.Item,{name:"projectCode",label:"项目",children:e.jsx(s.Input,{})})})]}),e.jsx(s.Form.Item,{name:"responseTemplate",label:"响应模板 (JSON)",children:e.jsx(fs,{autoSize:{minRows:3,maxRows:8},style:{fontFamily:"Menlo, Monaco, monospace"}})}),e.jsx(s.Button,{type:"primary",onClick:H,loading:j,icon:e.jsx(i.CodeOutlined,{}),children:"保存为 Mock 端点"})]})}]})]})}function Et(r){return{GET:"blue",POST:"green",PUT:"orange",DELETE:"red",PATCH:"purple"}[r]||"default"}const{Text:je}=s.Typography,Ot=[{value:"P0",label:"P0 (最高)"},{value:"P1",label:"P1 (高)"},{value:"P2",label:"P2 (中)"},{value:"P3",label:"P3 (低)"}],Ft={P0:"red",P1:"orange",P2:"blue",P3:"default"},He={PASS:"green",FAIL:"red",SKIP:"default"},Pt=[{value:"EXACT",label:"完全匹配"},{value:"CONTAINS",label:"包含"},{value:"REGEX",label:"正则"},{value:"JSONPATH",label:"JSONPath"}];function Ss(){const[r,c]=t.useState([]),[o,y]=t.useState(!1),[k,S]=t.useState([]),[d,g]=t.useState(!1),[E,C]=t.useState(null),[O,m]=t.useState(!1),[x,z]=t.useState(null),[j,B]=t.useState(null),[v,N]=t.useState(!1),[b,w]=t.useState(!1),[P]=s.Form.useForm();t.useEffect(()=>{f()},[]);const f=async()=>{y(!0);try{const T=await q.cases.list();c(Array.isArray(T)?T:[])}catch{s.message.warning("加载用例列表失败")}finally{y(!1)}},M=()=>{C(null),P.resetFields(),P.setFieldsValue({requestMethod:"GET",expectedStatus:200,priority:"P1",status:1,expectedBodyMatchType:"EXACT"}),g(!0)},U=T=>{C(T),P.setFieldsValue(T),g(!0)},J=async()=>{try{const T=await P.validateFields();let A;try{A=T.assertionsJson?JSON.parse(T.assertionsJson):null}catch{s.message.error("断言 JSON 格式错误");return}const V={...T,assertions:A};delete V.assertionsJson,E?(await q.cases.update(E.caseCode,V),s.message.success("更新成功")):(await q.cases.create(V),s.message.success("创建成功")),g(!1),f()}catch(T){T!=null&&T.errorFields||s.message.error("保存失败")}},H=async T=>{try{await q.cases.delete(T),s.message.success("删除成功"),f()}catch{s.message.error("删除失败")}},l=async T=>{try{const A=await q.cases.run(T.caseCode);z(A),m(!0),(A==null?void 0:A.status)==="PASS"?s.message.success("用例通过"):s.message.error("用例失败: "+((A==null?void 0:A.error)||(A==null?void 0:A.actualStatus))),f()}catch(A){s.message.error("执行失败: "+(A==null?void 0:A.message))}},n=async()=>{if(k.length===0){s.message.warning("请先选择用例");return}try{const T=await q.cases.runBatch(k);B(T),N(!0),s.message.success(`批量执行完成: ${T==null?void 0:T.pass} 通过, ${T==null?void 0:T.fail} 失败`),f()}catch{s.message.error("批量执行失败")}},_=[{title:"用例编码",dataIndex:"caseCode",key:"caseCode",width:180,render:T=>e.jsx(je,{code:!0,children:T})},{title:"名称",dataIndex:"caseName",key:"caseName",width:220},{title:"分组",dataIndex:"caseGroup",key:"caseGroup",width:130,render:T=>T?e.jsx(s.Tag,{children:T}):"-"},{title:"方法",dataIndex:"requestMethod",key:"requestMethod",width:80,render:T=>e.jsx(s.Tag,{color:"blue",children:T})},{title:"路径",dataIndex:"requestUrl",key:"requestUrl",ellipsis:!0,render:T=>e.jsx(je,{code:!0,children:T})},{title:"优先级",dataIndex:"priority",key:"priority",width:80,align:"center",render:T=>e.jsx(s.Tag,{color:Ft[T],children:T||"P1"})},{title:"上次结果",dataIndex:"lastRunResult",key:"lastRunResult",width:100,align:"center",render:T=>T?e.jsx(s.Tag,{color:He[T],children:T}):"-"},{title:"统计",key:"stats",width:130,align:"center",render:(T,A)=>e.jsxs(s.Space,{size:"small",children:[e.jsx(je,{type:"success",children:A.passCount||0}),"/",e.jsx(je,{type:"danger",children:A.failCount||0}),e.jsxs(je,{type:"secondary",children:["(",A.runCount||0,")"]})]})},{title:"操作",key:"action",width:220,fixed:"right",render:(T,A)=>e.jsxs(s.Space,{size:"small",children:[e.jsx(s.Button,{size:"small",type:"link",icon:e.jsx(i.PlayCircleOutlined,{}),onClick:()=>l(A),children:"运行"}),e.jsx(s.Button,{size:"small",type:"link",icon:e.jsx(i.EditOutlined,{}),onClick:()=>U(A)}),e.jsx(s.Popconfirm,{title:`删除用例 ${A.caseCode}?`,onConfirm:()=>H(A.caseCode),children:e.jsx(s.Button,{size:"small",type:"link",danger:!0,icon:e.jsx(i.DeleteOutlined,{})})})]})}];return e.jsxs("div",{children:[e.jsx(s.Alert,{type:"info",showIcon:!0,style:{marginBottom:16},message:"测试用例库",description:"对 Mock 接口进行断言验证。支持 7 种断言类型:STATUS / HEADER / BODY / JSON_PATH / REGEX / SCHEMA / RESPONSE_TIME。支持单条运行与批量运行,自动统计通过/失败次数。"}),e.jsxs(s.Space,{style:{marginBottom:16},children:[e.jsx(s.Button,{icon:e.jsx(i.ReloadOutlined,{}),onClick:f,children:"刷新"}),e.jsx(s.Button,{type:"primary",icon:e.jsx(i.PlusOutlined,{}),onClick:M,children:"新建用例"}),e.jsx(s.Button,{icon:e.jsx(i.CodeOutlined,{}),onClick:()=>w(!0),children:"粘贴 curl 导入"}),e.jsxs(s.Button,{type:"primary",icon:e.jsx(i.PlayCircleOutlined,{}),onClick:n,disabled:k.length===0,children:["批量运行 (",k.length,")"]})]}),e.jsx(s.Table,{dataSource:r,columns:_,rowKey:"id",loading:o,rowSelection:{selectedRowKeys:k,onChange:S},pagination:{pageSize:10},scroll:{x:1300},size:"small"}),e.jsx(s.Modal,{title:E?`编辑用例: ${E.caseCode}`:"新建测试用例",open:d,onCancel:()=>g(!1),onOk:J,width:750,children:e.jsxs(s.Form,{form:P,layout:"vertical",style:{marginTop:16},children:[e.jsxs(s.Row,{gutter:16,children:[e.jsx(s.Col,{span:12,children:e.jsx(s.Form.Item,{name:"caseCode",label:"用例编码",rules:[{required:!0}],children:e.jsx(s.Input,{placeholder:"case-user-login",disabled:!!E})})}),e.jsx(s.Col,{span:12,children:e.jsx(s.Form.Item,{name:"caseName",label:"用例名称",children:e.jsx(s.Input,{placeholder:"用户登录成功用例"})})})]}),e.jsxs(s.Row,{gutter:16,children:[e.jsx(s.Col,{span:8,children:e.jsx(s.Form.Item,{name:"caseGroup",label:"用例分组",children:e.jsx(s.Input,{placeholder:"login"})})}),e.jsx(s.Col,{span:8,children:e.jsx(s.Form.Item,{name:"priority",label:"优先级",children:e.jsx(s.Select,{options:Ot})})}),e.jsx(s.Col,{span:8,children:e.jsx(s.Form.Item,{name:"envCode",label:"环境",children:e.jsx(s.Input,{placeholder:"default"})})})]}),e.jsxs(s.Row,{gutter:16,children:[e.jsx(s.Col,{span:6,children:e.jsx(s.Form.Item,{name:"requestMethod",label:"方法",children:e.jsx(s.Select,{options:[{value:"GET",label:"GET"},{value:"POST",label:"POST"},{value:"PUT",label:"PUT"},{value:"DELETE",label:"DELETE"}]})})}),e.jsx(s.Col,{span:18,children:e.jsx(s.Form.Item,{name:"requestUrl",label:"请求 URL",rules:[{required:!0}],children:e.jsx(s.Input,{placeholder:"/api/mock/default/user/login"})})})]}),e.jsxs(s.Row,{gutter:16,children:[e.jsx(s.Col,{span:12,children:e.jsx(s.Form.Item,{name:"requestQuery",label:"查询参数",children:e.jsx(s.Input,{placeholder:"debug=true"})})}),e.jsx(s.Col,{span:12,children:e.jsx(s.Form.Item,{name:"expectedStatus",label:"期望状态码",children:e.jsx(s.Select,{options:[{value:200,label:"200 OK"},{value:201,label:"201 Created"},{value:400,label:"400 Bad Request"},{value:401,label:"401 Unauthorized"},{value:404,label:"404 Not Found"},{value:500,label:"500 Server Error"}]})})})]}),e.jsx(s.Form.Item,{name:"requestHeaders",label:"请求头 (JSON)",extra:'例: {"Authorization": "Bearer xxx"}',children:e.jsx(s.Input.TextArea,{rows:2,placeholder:'{"X-Trace-Id": "abc"}'})}),e.jsx(s.Form.Item,{name:"requestBody",label:"请求体",children:e.jsx(s.Input.TextArea,{rows:3,placeholder:'{"username":"test","password":"xxx"}'})}),e.jsx(s.Form.Item,{name:"expectedBodyMatchType",label:"Body 匹配方式",children:e.jsx(s.Select,{options:Pt})}),e.jsx(s.Form.Item,{name:"expectedBody",label:"期望 Body",children:e.jsx(s.Input.TextArea,{rows:3,placeholder:'{"code": 200, "success": true}'})}),e.jsx(s.Form.Item,{name:"assertionsJson",label:"断言列表 (JSON 数组)",extra:'例: [{"assertType":"STATUS","expected":200,"comparator":"EQUALS"}]',children:e.jsx(s.Input.TextArea,{rows:4,placeholder:'[{"assertType":"STATUS","expected":200}]'})}),e.jsx(s.Form.Item,{name:"description",label:"描述",children:e.jsx(s.Input.TextArea,{rows:2})})]})}),e.jsx(s.Drawer,{title:e.jsxs(s.Space,{children:[e.jsx(i.FileSearchOutlined,{}),"用例执行结果"]}),open:O,onClose:()=>m(!1),width:650,children:x&&e.jsxs("div",{children:[e.jsxs(s.Row,{gutter:16,style:{marginBottom:16},children:[e.jsx(s.Col,{span:8,children:e.jsx(s.Card,{children:e.jsx(s.Statistic,{title:"结果",value:x.status,valueStyle:{color:He[x.status]==="green"?"#52c41a":"#ff4d4f"}})})}),e.jsx(s.Col,{span:8,children:e.jsx(s.Card,{children:e.jsx(s.Statistic,{title:"实际状态码",value:x.actualStatus||"-"})})}),e.jsx(s.Col,{span:8,children:e.jsx(s.Card,{children:e.jsx(s.Statistic,{title:"耗时(ms)",value:x.durationMs||0})})})]}),e.jsxs(s.Descriptions,{column:1,size:"small",bordered:!0,style:{marginBottom:16},children:[e.jsx(s.Descriptions.Item,{label:"用例编码",children:x.caseCode}),e.jsx(s.Descriptions.Item,{label:"用例名称",children:x.caseName}),e.jsx(s.Descriptions.Item,{label:"错误信息",children:x.error||"-"})]}),x.assertionResults&&e.jsxs(e.Fragment,{children:[e.jsx(je,{strong:!0,children:"断言详情:"}),e.jsx(s.Table,{style:{marginTop:8},dataSource:x.assertionResults,columns:[{title:"断言类型",dataIndex:"assertType",key:"assertType",width:110},{title:"表达式",dataIndex:"expression",key:"expression"},{title:"期望值",dataIndex:"expected",key:"expected"},{title:"实际值",dataIndex:"actual",key:"actual"},{title:"结果",dataIndex:"passed",key:"passed",width:80,render:T=>T?e.jsx(s.Tag,{color:"green",children:"PASS"}):e.jsx(s.Tag,{color:"red",children:"FAIL"})}],pagination:!1,size:"small"})]}),e.jsx(je,{strong:!0,style:{marginTop:16,display:"block"},children:"响应体:"}),e.jsx("pre",{style:{background:"#f5f5f5",padding:12,borderRadius:4,maxHeight:250,overflow:"auto",fontSize:12,fontFamily:"monospace",whiteSpace:"pre-wrap",wordBreak:"break-all"},children:x.responseBody||"(empty)"})]})}),e.jsx(s.Modal,{title:`批量执行结果 (${(j==null?void 0:j.total)||0} 条)`,open:v,onCancel:()=>N(!1),footer:e.jsx(s.Button,{onClick:()=>N(!1),children:"关闭"}),width:800,children:j&&e.jsxs(e.Fragment,{children:[e.jsxs(s.Row,{gutter:16,style:{marginBottom:16},children:[e.jsx(s.Col,{span:6,children:e.jsx(s.Card,{children:e.jsx(s.Statistic,{title:"总数",value:j.total})})}),e.jsx(s.Col,{span:6,children:e.jsx(s.Card,{children:e.jsx(s.Statistic,{title:"通过",value:j.pass,valueStyle:{color:"#52c41a"}})})}),e.jsx(s.Col,{span:6,children:e.jsx(s.Card,{children:e.jsx(s.Statistic,{title:"失败",value:j.fail,valueStyle:{color:"#ff4d4f"}})})}),e.jsx(s.Col,{span:6,children:e.jsx(s.Card,{children:e.jsx(s.Statistic,{title:"通过率",value:`${j.total>0?Math.round(j.pass/j.total*100):0}%`})})})]}),e.jsx(s.Table,{dataSource:j.results||[],columns:[{title:"编码",dataIndex:"caseCode",key:"caseCode",width:180},{title:"名称",dataIndex:"caseName",key:"caseName"},{title:"结果",dataIndex:"status",key:"status",width:80,render:T=>e.jsx(s.Tag,{color:He[T],children:T})},{title:"耗时",dataIndex:"durationMs",key:"durationMs",width:80,align:"center"},{title:"错误",dataIndex:"error",key:"error",ellipsis:!0}],pagination:!1,size:"small",rowKey:"caseCode"})]})}),e.jsx(Cs,{open:b,onClose:()=>w(!1),onSuccess:(T,A)=>{s.message.success(T==="case"?"测试用例已导入,正在刷新列表":"Mock 端点已导入"),f()}})]})}const{Text:pe}=s.Typography,Ts={IDLE:"default",RECORDING:"red",STOPPED:"green",EXPIRED:"gray"};function bs(){const[r,c]=t.useState([]),[o,y]=t.useState(!1),[k,S]=t.useState(!1),[d,g]=t.useState(!1),[E,C]=t.useState(!1),[O,m]=t.useState(!1),[x,z]=t.useState(null),[j,B]=t.useState([]),[v]=s.Form.useForm(),[N]=s.Form.useForm(),[b]=s.Form.useForm(),[w,P]=t.useState([]),[f,M]=t.useState(!1),[U,J]=t.useState([]);t.useEffect(()=>{H()},[]);const H=async()=>{y(!0);try{const I=await q.recordings.list();c(Array.isArray(I)?I:[])}catch{s.message.warning("加载录制列表失败")}finally{y(!1)}},l=async()=>{try{const I=await v.validateFields();await q.recordings.start(I.recordingCode,I.recordingName,I.targetUrl),s.message.success("录制已开启"),S(!1),v.resetFields(),H()}catch(I){I!=null&&I.errorFields||s.message.error("开启失败")}},n=async I=>{try{await q.recordings.stop(I),s.message.success("录制已停止"),H()}catch{s.message.error("停止失败")}},_=async I=>{try{await q.recordings.delete(I),s.message.success("删除成功"),H()}catch{s.message.error("删除失败")}},T=async I=>{try{const p=await q.recordings.requests(I.recordingCode);z(I),B(Array.isArray(p)?p:[]),m(!0)}catch{s.message.error("加载失败")}},A=async I=>{s.Modal.confirm({title:"导入录制为 Mock",content:`将把录制 "${I.recordingCode}" 转换为 Mock endpoints 并入库。`,okText:"确认导入",onOk:async()=>{try{const p=await q.recordings.import(I.recordingCode,"default");s.message.success(`导入成功: ${(p==null?void 0:p.imported)||0} 个 Mock endpoint`)}catch{s.message.error("导入失败")}}})},V=async()=>{var I,p,a;try{const D=await N.validateFields(),R=await q.recordings.playback(x.recordingCode,D.targetUrl);s.Modal.info({title:"回放结果",width:700,content:e.jsxs("div",{children:[e.jsxs(pe,{children:["总数: ",((I=R==null?void 0:R[0])==null?void 0:I.total)||0," 通过: ",((p=R==null?void 0:R[0])==null?void 0:p.pass)||0," 失败: ",((a=R==null?void 0:R[0])==null?void 0:a.fail)||0]}),e.jsx("pre",{style:{marginTop:12,background:"#f5f5f5",padding:12,maxHeight:400,overflow:"auto",fontSize:12},children:JSON.stringify(R,null,2)})]})}),g(!1)}catch(D){D!=null&&D.errorFields||s.message.error("回放失败")}},re=async()=>{try{M(!0);const I=await b.validateFields().catch(()=>({})),p=await q.recordings.export(x.recordingCode,I==null?void 0:I.projectCode),a=Array.isArray(p==null?void 0:p.drafts)?p.drafts:[];P(a),J(a.map(D=>D.mockCode||D.id)),C(!0)}catch(I){I!=null&&I.errorFields||s.message.error("生成草稿失败")}finally{M(!1)}},ae=async()=>{try{const I=await b.validateFields().catch(()=>({})),p=U;if(p.length===0){s.message.warning("请至少选择一个 Mock");return}const a=await q.recordings.import(x.recordingCode,I==null?void 0:I.envCode,I==null?void 0:I.projectCode);s.message.success(`已导入 ${(a==null?void 0:a.imported)||p.length} 个 Mock`),C(!1),H()}catch(I){s.message.error("导入失败:"+((I==null?void 0:I.message)||"未知错误"))}},ne=[{title:"编码",dataIndex:"recordingCode",key:"recordingCode",width:180,render:I=>e.jsx(pe,{code:!0,children:I})},{title:"名称",dataIndex:"recordingName",key:"recordingName",width:200},{title:"状态",dataIndex:"recordStatus",key:"recordStatus",width:110,render:I=>e.jsx(s.Tag,{color:Ts[I],children:I})},{title:"请求数",dataIndex:"totalRequests",key:"totalRequests",width:90,align:"center"},{title:"目标 URL",dataIndex:"targetUrl",key:"targetUrl",ellipsis:!0,render:I=>I?e.jsx(pe,{copyable:{text:I},children:I}):"-"},{title:"开始时间",dataIndex:"startTime",key:"startTime",width:170},{title:"结束时间",dataIndex:"endTime",key:"endTime",width:170},{title:"操作",key:"action",width:280,fixed:"right",render:(I,p)=>e.jsxs(s.Space,{size:"small",children:[e.jsx(s.Button,{size:"small",type:"link",icon:e.jsx(i.VideoCameraOutlined,{}),onClick:()=>T(p),children:"详情"}),p.recordStatus==="RECORDING"&&e.jsx(s.Button,{size:"small",type:"link",danger:!0,icon:e.jsx(i.StopOutlined,{}),onClick:()=>n(p.recordingCode),children:"停止"}),p.recordStatus==="STOPPED"&&e.jsx(s.Button,{size:"small",type:"link",icon:e.jsx(i.ImportOutlined,{}),onClick:()=>A(p),children:"导入为 Mock"}),e.jsx(s.Popconfirm,{title:`删除录制 ${p.recordingCode}?`,onConfirm:()=>_(p.recordingCode),children:e.jsx(s.Button,{size:"small",type:"link",danger:!0,icon:e.jsx(i.DeleteOutlined,{})})})]})}];return e.jsxs("div",{children:[e.jsx(s.Alert,{type:"info",showIcon:!0,style:{marginBottom:16},message:"流量录制与回放",description:e.jsxs("div",{children:[e.jsxs("div",{children:["• 开启录制后,所有 ",e.jsx(pe,{code:!0,children:"/api/mock/{envCode}/**"})," 请求会被捕获到数据库"]}),e.jsx("div",{children:"• 停止录制后,可一键转为 Mock endpoints(用于离线测试)"}),e.jsx("div",{children:"• 支持回放录制到目标服务(验证录制有效 / 跨环境验证)"})]})}),e.jsxs(s.Space,{style:{marginBottom:16},children:[e.jsx(s.Button,{icon:e.jsx(i.ReloadOutlined,{}),onClick:H,children:"刷新"}),e.jsx(s.Button,{type:"primary",icon:e.jsx(i.VideoCameraOutlined,{}),onClick:()=>S(!0),children:"开启录制"})]}),e.jsx(s.Table,{dataSource:r,columns:ne,rowKey:"id",loading:o,pagination:{pageSize:10},scroll:{x:1300},size:"small"}),e.jsx(s.Modal,{title:"开启录制",open:k,onCancel:()=>S(!1),onOk:l,okText:"开启",cancelText:"取消",children:e.jsxs(s.Form,{form:v,layout:"vertical",style:{marginTop:16},children:[e.jsx(s.Form.Item,{name:"recordingCode",label:"录制编码",rules:[{required:!0}],children:e.jsx(s.Input,{placeholder:"prod-trace-2026-06"})}),e.jsx(s.Form.Item,{name:"recordingName",label:"录制名称",rules:[{required:!0}],children:e.jsx(s.Input,{placeholder:"生产环境订单流程"})}),e.jsx(s.Form.Item,{name:"targetUrl",label:"目标服务地址",children:e.jsx(s.Input,{placeholder:"http://prod-api.example.com"})})]})}),e.jsx(s.Drawer,{title:e.jsxs(s.Space,{children:[e.jsx(i.VideoCameraOutlined,{}),"录制详情: ",x==null?void 0:x.recordingCode]}),open:O,onClose:()=>m(!1),width:800,children:x&&e.jsxs("div",{children:[e.jsxs(s.Descriptions,{column:2,size:"small",bordered:!0,style:{marginBottom:16},children:[e.jsx(s.Descriptions.Item,{label:"编码",children:x.recordingCode}),e.jsx(s.Descriptions.Item,{label:"名称",children:x.recordingName}),e.jsx(s.Descriptions.Item,{label:"状态",children:e.jsx(s.Tag,{color:Ts[x.recordStatus],children:x.recordStatus})}),e.jsx(s.Descriptions.Item,{label:"请求数",children:x.totalRequests}),e.jsx(s.Descriptions.Item,{label:"目标 URL",span:2,children:e.jsx(pe,{copyable:!0,children:x.targetUrl})}),e.jsx(s.Descriptions.Item,{label:"开始",children:x.startTime}),e.jsx(s.Descriptions.Item,{label:"结束",children:x.endTime||"(录制中)"})]}),e.jsxs(s.Space,{style:{marginBottom:16},children:[e.jsx(s.Button,{icon:e.jsx(i.PlayCircleOutlined,{}),onClick:()=>g(!0),disabled:x.recordStatus!=="STOPPED",children:"回放"}),e.jsx(s.Button,{icon:e.jsx(i.ExportOutlined,{}),onClick:re,loading:f,disabled:x.recordStatus!=="STOPPED",children:"导出 Mock 草稿"}),e.jsx(s.Button,{type:"primary",icon:e.jsx(i.ImportOutlined,{}),onClick:()=>A(x),disabled:x.recordStatus!=="STOPPED",children:"导入为 Mock"})]}),e.jsxs(pe,{strong:!0,children:["请求列表 (共 ",j.length," 条):"]}),e.jsx(s.Table,{style:{marginTop:8},dataSource:j,columns:[{title:"#",dataIndex:"sequence",key:"sequence",width:50},{title:"方法",dataIndex:"requestMethod",key:"requestMethod",width:80,render:I=>e.jsx(s.Tag,{color:"blue",children:I})},{title:"URL",dataIndex:"requestUrl",key:"requestUrl",ellipsis:!0,render:I=>e.jsx(pe,{code:!0,children:I})},{title:"响应",dataIndex:"responseStatus",key:"responseStatus",width:80,render:I=>e.jsx(s.Tag,{color:I>=400?"red":"green",children:I})},{title:"耗时",dataIndex:"responseTime",key:"responseTime",width:80,render:I=>`${I||0}ms`}],pagination:{pageSize:10},size:"small",rowKey:"id"})]})}),e.jsx(s.Modal,{title:"回放录制",open:d,onCancel:()=>g(!1),onOk:V,children:e.jsx(s.Form,{form:N,layout:"vertical",style:{marginTop:16},children:e.jsx(s.Form.Item,{name:"targetUrl",label:"目标服务地址",rules:[{required:!0}],children:e.jsx(s.Input,{placeholder:"http://staging-api.example.com"})})})}),e.jsxs(s.Modal,{title:"导出 Mock 草稿",open:E,onCancel:()=>C(!1),onOk:ae,okText:`导入 ${U.length} 个`,width:900,children:[e.jsx(s.Form,{form:b,layout:"vertical",style:{marginTop:8},children:e.jsxs(s.Space,{size:16,style:{width:"100%"},children:[e.jsx(s.Form.Item,{name:"projectCode",label:"项目编码",style:{flex:1,marginBottom:8},children:e.jsx(s.Input,{placeholder:"default"})}),e.jsx(s.Form.Item,{name:"envCode",label:"目标环境",style:{flex:1,marginBottom:8},children:e.jsx(s.Input,{placeholder:"default"})})]})}),e.jsx(s.Alert,{type:"info",showIcon:!0,style:{marginBottom:12},message:`从录制中识别出 ${w.length} 个去重后的 Mock endpoint,已默认全选`}),e.jsx(s.Table,{size:"small",dataSource:w,rowKey:I=>I.mockCode||I.id,pagination:{pageSize:8},scroll:{y:300},rowSelection:{selectedRowKeys:U,onChange:I=>J(I)},columns:[{title:"方法",dataIndex:"method",width:80,render:I=>e.jsx(s.Tag,{color:"blue",children:I})},{title:"URL 模式",dataIndex:"urlPattern",ellipsis:!0,render:I=>e.jsx(pe,{code:!0,children:I})},{title:"状态码",dataIndex:"statusCode",width:80},{title:"响应模板",dataIndex:"responseTemplate",ellipsis:!0,render:I=>e.jsx(pe,{type:"secondary",style:{fontSize:11},children:(I||"").slice(0,80)})},{title:"请求数",dataIndex:"requestCount",width:80,align:"center"}]})]})]})}const{Text:be}=s.Typography,Nt={MOCK:"green",PROXY:"blue",404:"red",502:"orange"};function ws(){const[r,c]=t.useState([]),[o,y]=t.useState(null),[k,S]=t.useState(!1),[d,g]=t.useState(null),[E,C]=t.useState(!1),[O,m]=t.useState(""),[x,z]=t.useState();t.useEffect(()=>{j()},[]);const j=async()=>{S(!0);try{const[b,w]=await Promise.all([q.requestLogs.list({path:O||void 0,matched:x,limit:100}),q.requestLogs.stats().catch(()=>null)]);c(Array.isArray(b)?b:[]),y(w)}catch{s.message.warning("加载失败")}finally{S(!1)}},B=b=>{g(b),C(!0)},v=async()=>{try{await q.requestLogs.clear(1e3),s.message.success("已清理"),j()}catch{s.message.error("清理失败")}},N=[{title:"时间",dataIndex:"createTime",key:"createTime",width:170,render:b=>b?new Date(b).toLocaleString():"-"},{title:"环境",dataIndex:"envCode",key:"envCode",width:100,render:b=>e.jsx(s.Tag,{children:b})},{title:"方法",dataIndex:"requestMethod",key:"requestMethod",width:80,render:b=>e.jsx(s.Tag,{color:"blue",children:b})},{title:"路径",dataIndex:"requestPath",key:"requestPath",ellipsis:!0,render:b=>e.jsx(be,{code:!0,children:b})},{title:"状态",dataIndex:"responseStatus",key:"responseStatus",width:90,align:"center",render:b=>b?e.jsx(s.Tag,{color:b>=400?"red":"green",children:b}):"-"},{title:"匹配",dataIndex:"matched",key:"matched",width:90,align:"center",render:b=>b===1?e.jsx(s.Tag,{color:"green",children:"命中"}):e.jsx(s.Tag,{color:"red",children:"未匹配"})},{title:"回退",dataIndex:"fallbackType",key:"fallbackType",width:100,render:b=>b?e.jsx(s.Tag,{color:Nt[b],children:b}):"-"},{title:"耗时",dataIndex:"durationMs",key:"durationMs",width:80,align:"center",render:b=>`${b||0}ms`},{title:"Mock",dataIndex:"mockCode",key:"mockCode",width:160,ellipsis:!0,render:b=>b?e.jsx(be,{code:!0,children:b}):"-"},{title:"操作",key:"action",width:80,render:(b,w)=>e.jsx(s.Button,{size:"small",type:"link",icon:e.jsx(i.EyeOutlined,{}),onClick:()=>B(w),children:"详情"})}];return e.jsxs("div",{children:[e.jsx(s.Alert,{type:"info",showIcon:!0,style:{marginBottom:16},message:"Mock 请求日志 - 排查未匹配请求",description:"每一次请求都会留痕。包括请求/响应体、是否匹配 Mock、回退类型、耗时、场景状态等。便于排查“为什么这个请求没有 Mock 命中”问题。"}),o&&e.jsxs(s.Row,{gutter:16,style:{marginBottom:16},children:[e.jsx(s.Col,{span:6,children:e.jsx(s.Card,{children:e.jsx(s.Statistic,{title:"总请求数",value:o.total||0})})}),e.jsx(s.Col,{span:6,children:e.jsx(s.Card,{children:e.jsx(s.Statistic,{title:"Mock 命中",value:o.matched||0,valueStyle:{color:"#52c41a"}})})}),e.jsx(s.Col,{span:6,children:e.jsx(s.Card,{children:e.jsx(s.Statistic,{title:"未匹配",value:o.unmatched||0,valueStyle:{color:"#ff4d4f"}})})}),e.jsx(s.Col,{span:6,children:e.jsx(s.Card,{children:e.jsx(s.Statistic,{title:"命中率",value:`${o.total>0?Math.round(o.matched/o.total*100):0}%`})})})]}),e.jsxs(s.Space,{style:{marginBottom:16},children:[e.jsx(s.Input,{placeholder:"搜索路径",prefix:e.jsx(i.SearchOutlined,{}),allowClear:!0,style:{width:240},value:O,onChange:b=>m(b.target.value),onPressEnter:j}),e.jsx(s.Select,{placeholder:"匹配状态",allowClear:!0,style:{width:140},value:x,onChange:z,options:[{value:1,label:"已命中"},{value:0,label:"未匹配"}]}),e.jsx(s.Button,{icon:e.jsx(i.ReloadOutlined,{}),onClick:j,children:"查询"}),e.jsx(s.Popconfirm,{title:"确认清理,保留最近 1000 条?",onConfirm:v,children:e.jsx(s.Button,{icon:e.jsx(i.DeleteOutlined,{}),danger:!0,children:"清理"})})]}),e.jsx(s.Table,{dataSource:r,columns:N,rowKey:"id",loading:k,pagination:{pageSize:20},scroll:{x:1300},size:"small"}),e.jsx(s.Drawer,{title:"请求详情",open:E,onClose:()=>C(!1),width:750,children:d&&e.jsxs("div",{children:[e.jsxs(s.Descriptions,{column:2,size:"small",bordered:!0,style:{marginBottom:16},children:[e.jsx(s.Descriptions.Item,{label:"环境",children:d.envCode}),e.jsx(s.Descriptions.Item,{label:"方法",children:e.jsx(s.Tag,{color:"blue",children:d.requestMethod})}),e.jsx(s.Descriptions.Item,{label:"路径",span:2,children:e.jsx(be,{code:!0,children:d.requestPath})}),e.jsx(s.Descriptions.Item,{label:"状态码",children:e.jsx(s.Tag,{color:d.responseStatus>=400?"red":"green",children:d.responseStatus})}),e.jsxs(s.Descriptions.Item,{label:"耗时",children:[d.durationMs,"ms"]}),e.jsx(s.Descriptions.Item,{label:"匹配",children:d.matched===1?e.jsx(s.Tag,{color:"green",children:"命中"}):e.jsx(s.Tag,{color:"red",children:"未匹配"})}),e.jsx(s.Descriptions.Item,{label:"回退",children:d.fallbackType||"-"}),e.jsx(s.Descriptions.Item,{label:"Mock",span:2,children:d.mockCode||"-"}),e.jsx(s.Descriptions.Item,{label:"场景状态",span:2,children:d.scenarioState||"-"}),e.jsx(s.Descriptions.Item,{label:"客户端 IP",children:d.clientIp||"-"}),e.jsx(s.Descriptions.Item,{label:"User-Agent",ellipsis:!0,children:d.userAgent||"-"}),e.jsx(s.Descriptions.Item,{label:"时间",span:2,children:d.createTime?new Date(d.createTime).toLocaleString():"-"})]}),e.jsx(be,{strong:!0,children:"请求头:"}),e.jsx("pre",{style:{background:"#f5f5f5",padding:12,borderRadius:4,maxHeight:150,overflow:"auto",fontSize:12,fontFamily:"monospace",whiteSpace:"pre-wrap"},children:d.requestHeaders||"(无)"}),e.jsx(be,{strong:!0,style:{marginTop:12,display:"block"},children:"请求体:"}),e.jsx("pre",{style:{background:"#f5f5f5",padding:12,borderRadius:4,maxHeight:200,overflow:"auto",fontSize:12,fontFamily:"monospace",whiteSpace:"pre-wrap",wordBreak:"break-all"},children:d.requestBody||"(无)"}),e.jsx(be,{strong:!0,style:{marginTop:12,display:"block"},children:"响应体:"}),e.jsx("pre",{style:{background:"#f5f5f5",padding:12,borderRadius:4,maxHeight:300,overflow:"auto",fontSize:12,fontFamily:"monospace",whiteSpace:"pre-wrap",wordBreak:"break-all"},children:d.responseBody||"(无)"})]})})]})}const{Text:ie}=s.Typography,Is=[{key:"endpoints",label:"Mock 端点",component:ze},{key:"environments",label:"环境 (MOCK/REAL/MIXED)",component:Me},{key:"scenarios",label:"场景状态机",component:js},{key:"cases",label:"测试用例",component:Ss},{key:"recordings",label:"录制回放",component:bs},{key:"request-logs",label:"请求日志",component:ws}];function At(){var O;const[r,c]=t.useState("endpoints"),[o,y]=t.useState([]),[k,S]=t.useState("default"),[d,g]=t.useState(null);t.useEffect(()=>{E(),C()},[]);const E=async()=>{try{const m=await q.environments.list(),x=Array.isArray(m)?m:[];if(y(x),x.length>0&&!x.find(z=>z.envCode===k)){const z=x.find(j=>j.isDefault===1)||x[0];S(z.envCode)}}catch{}},C=async()=>{try{const m=await q.stats();g(m)}catch{}};return(O=Is.find(m=>m.key===r))==null||O.component,e.jsxs("div",{children:[e.jsx(s.Card,{style:{marginBottom:16},bodyStyle:{padding:16},children:e.jsxs(s.Space,{size:"large",wrap:!0,children:[e.jsxs(s.Space,{children:[e.jsx(i.DashboardOutlined,{style:{fontSize:18,color:"#1890ff"}}),e.jsx(ie,{strong:!0,style:{fontSize:16},children:"Mock 平台"}),e.jsx(s.Tag,{color:"blue",children:"WireMock 级"})]}),e.jsxs(s.Space,{children:[e.jsx(i.GlobalOutlined,{}),e.jsx(ie,{children:"当前环境:"}),e.jsx(s.Select,{value:k,onChange:S,style:{width:200},options:o.map(m=>({value:m.envCode,label:`${m.envName||m.envCode} (${m.envType})`}))})]}),d&&e.jsxs(s.Space,{size:"large",children:[e.jsxs(ie,{type:"secondary",children:["端点: ",e.jsx(ie,{strong:!0,children:d.totalEndpoints})]}),e.jsxs(ie,{type:"secondary",children:["启用: ",e.jsx(ie,{strong:!0,style:{color:"#52c41a"},children:d.activeEndpoints})]}),e.jsxs(ie,{type:"secondary",children:["场景: ",e.jsx(ie,{strong:!0,children:d.totalScenarios})]}),e.jsxs(ie,{type:"secondary",children:["用例: ",e.jsx(ie,{strong:!0,children:d.totalCases})]})]}),e.jsx(s.Button,{icon:e.jsx(i.ReloadOutlined,{}),onClick:()=>{E(),C()},children:"刷新"})]})}),e.jsx(s.Tabs,{activeKey:r,onChange:c,type:"card",items:Is.map(m=>({key:m.key,label:m.label,children:m.component===ze?e.jsx(ze,{activeEnvCode:k}):m.component===Me?e.jsx(Me,{onEnvChange:x=>{S(x),s.message.success(`已切换到环境: ${x}`)}}):e.jsx(m.component,{})}))})]})}const Dt=common;$.AgentTeamIM=nt,$.AppLayout=Ds,$.CtcAuthPage=et,$.CtcLayout=Vs,$.CtcLogin=rt,$.CurlImportModal=Cs,$.EndpointsTab=ze,$.EnvironmentsTab=Me,$.ErrorBoundary=Ls,$.LoginPage=_s,$.LowCodeModel=as,$.LowCodePage=gt,$.LowCodeRuntime=ds,$.MaterializePage=jt,$.MockPlatform=At,$.MockTemplateHelper=gs,$.OpenApiImportModal=hs,$.Overview=Rs,$.RecordingsTab=bs,$.RequestLogsTab=ws,$.ScenariosTab=js,$.StatusTag=zs,$.TestCasesTab=Ss,$.UserPanel=ot,$.Webide=ct,$.authRequest=ss,$.createRequest=Re,$.default=Dt,$.defaultStatusMap=Qe,$.request=Y,$.setupInterceptors=es,Object.defineProperties($,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yuku123/z-frontend-common",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"private": false,
|
|
5
|
-
"description": "z-opc
|
|
5
|
+
"description": "z-opc 共享前端组件库 - AppLayout / StatusTag / LoginPage / ErrorBoundary + 统一 createRequest 工厂",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"react",
|
|
8
8
|
"antd",
|
|
@@ -59,5 +59,6 @@
|
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@vitejs/plugin-react": "^4.2.1",
|
|
61
61
|
"vite": "^6.2.0"
|
|
62
|
-
}
|
|
63
|
-
|
|
62
|
+
},
|
|
63
|
+
"style": "./dist/z-frontend-common.css"
|
|
64
|
+
}
|