@guozhi-fe/oms-trade-workbench 0.1.0-alpha.0
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/LICENSE +21 -0
- package/README.md +85 -0
- package/dist/api/demo.d.ts +28 -0
- package/dist/api/demo.d.ts.map +1 -0
- package/dist/components/TradeWorkbench/index.d.ts +11 -0
- package/dist/components/TradeWorkbench/index.d.ts.map +1 -0
- package/dist/context/TradeWorkbenchProvider.d.ts +16 -0
- package/dist/context/TradeWorkbenchProvider.d.ts.map +1 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +304 -0
- package/dist/index.js.map +1 -0
- package/dist/model/demo.d.ts +48 -0
- package/dist/model/demo.d.ts.map +1 -0
- package/dist/style.css +2 -0
- package/dist/types/component.d.ts +20 -0
- package/dist/types/component.d.ts.map +1 -0
- package/dist/types/runtime.d.ts +16 -0
- package/dist/types/runtime.d.ts.map +1 -0
- package/dist/types/transport.d.ts +14 -0
- package/dist/types/transport.d.ts.map +1 -0
- package/package.json +84 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 GZ
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# @guozhi-fe/oms-trade-workbench
|
|
2
|
+
|
|
3
|
+
国智 OMS 应用共享的交易工作台 React 组件。当前 `0.1.0-alpha.*` 版本用于验证独立发包、
|
|
4
|
+
宿主请求适配、主题继承和受控全屏弹窗;其中的 Demo 数据契约不代表正式交易接口。
|
|
5
|
+
|
|
6
|
+
## 安装
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npm install --save-exact @guozhi-fe/oms-trade-workbench@0.1.0-alpha.0
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
宿主需要提供兼容版本的 `react`、`react-dom`、`antd` 和 `@chenhui996/gg-ui`。具体范围以
|
|
13
|
+
包内 `peerDependencies` 为准。
|
|
14
|
+
|
|
15
|
+
## 接入
|
|
16
|
+
|
|
17
|
+
应用入口只引入一次组件样式,并在宿主现有主题 Provider 内注入请求 Transport:
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
import {
|
|
21
|
+
TradeWorkbenchProvider,
|
|
22
|
+
type TradeWorkbenchTransport,
|
|
23
|
+
} from '@guozhi-fe/oms-trade-workbench';
|
|
24
|
+
import '@guozhi-fe/oms-trade-workbench/style.css';
|
|
25
|
+
|
|
26
|
+
const transport: TradeWorkbenchTransport = {
|
|
27
|
+
request: async (config) => {
|
|
28
|
+
// 将 path、method、query、body、headers 和 signal 适配到宿主请求客户端。
|
|
29
|
+
return hostRequest(config);
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
function Root() {
|
|
34
|
+
return (
|
|
35
|
+
<HostThemeProvider>
|
|
36
|
+
<TradeWorkbenchProvider transport={transport}>
|
|
37
|
+
<App />
|
|
38
|
+
</TradeWorkbenchProvider>
|
|
39
|
+
</HostThemeProvider>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
页面通过受控属性打开弹窗:
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
import { TradeWorkbench } from '@guozhi-fe/oms-trade-workbench';
|
|
48
|
+
|
|
49
|
+
<TradeWorkbench
|
|
50
|
+
open={open}
|
|
51
|
+
entry={{ mode: 'edit', tradeId: 'DEMO-001' }}
|
|
52
|
+
onRequestClose={() => setOpen(false)}
|
|
53
|
+
onSubmitted={({ tradeId }) => {
|
|
54
|
+
console.info('submitted', tradeId);
|
|
55
|
+
}}
|
|
56
|
+
/>;
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
`entry` 支持创建、编辑和只读入口:
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
type TradeWorkbenchEntry =
|
|
63
|
+
| { mode: 'create'; tradeId?: never }
|
|
64
|
+
| { mode: 'edit' | 'view'; tradeId: string };
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## 宿主边界
|
|
68
|
+
|
|
69
|
+
- 包不创建根级主题 Provider,继承宿主的 Locale、组件前缀和 `--gz-*` Token。
|
|
70
|
+
- 包不依赖宿主 Router、Store、Token 或请求库。
|
|
71
|
+
- 宿主应在 Vite 中去重 `react`、`react-dom`、`antd` 和 `@chenhui996/gg-ui`。
|
|
72
|
+
- 只能从包根入口和 `@guozhi-fe/oms-trade-workbench/style.css` 引用,不承诺 `dist/` 深层路径。
|
|
73
|
+
|
|
74
|
+
## 开发验证
|
|
75
|
+
|
|
76
|
+
在 `oms-web` 仓库根目录执行:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
npm run trade-workbench:verify
|
|
80
|
+
npm pack ./packages/trade-workbench --dry-run
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## License
|
|
84
|
+
|
|
85
|
+
MIT
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type TradeWorkbenchDemoData } from '../model/demo';
|
|
2
|
+
import type { TradeWorkbenchSubmitResult } from '../types/component';
|
|
3
|
+
import type { TradeWorkbenchTransport } from '../types/transport';
|
|
4
|
+
/**
|
|
5
|
+
* 通过宿主注入的 Transport 加载交易工作台 MVP 展示数据。
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* 该接口仅用于技术验证,不连接真实交易服务;`signal` 会原样交给宿主请求实现。
|
|
9
|
+
*
|
|
10
|
+
* @param transport - 宿主注入的最小请求能力。
|
|
11
|
+
* @param tradeId - 当前 Demo 交易标识。
|
|
12
|
+
* @param signal - 用于取消当前加载请求的信号。
|
|
13
|
+
* @returns 已完成结构校验的 Demo 数据。
|
|
14
|
+
*/
|
|
15
|
+
export declare const getTradeWorkbenchDemo: (transport: TradeWorkbenchTransport, tradeId: string, signal: AbortSignal) => Promise<TradeWorkbenchDemoData>;
|
|
16
|
+
/**
|
|
17
|
+
* 通过宿主注入的 Transport 提交当前 MVP Demo。
|
|
18
|
+
*
|
|
19
|
+
* @remarks
|
|
20
|
+
* 该请求仅验证提交编排、重复提交保护和宿主回调,不代表正式交易提交契约。
|
|
21
|
+
*
|
|
22
|
+
* @param transport - 宿主注入的最小请求能力。
|
|
23
|
+
* @param tradeId - 当前 Demo 交易标识。
|
|
24
|
+
* @param signal - 用于取消提交请求的信号。
|
|
25
|
+
* @returns 只包含稳定交易标识的提交结果。
|
|
26
|
+
*/
|
|
27
|
+
export declare const submitTradeWorkbenchDemo: (transport: TradeWorkbenchTransport, tradeId: string, signal: AbortSignal) => Promise<TradeWorkbenchSubmitResult>;
|
|
28
|
+
//# sourceMappingURL=demo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demo.d.ts","sourceRoot":"","sources":["../../src/api/demo.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,sBAAsB,EAC5B,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAKlE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,qBAAqB,GAChC,WAAW,uBAAuB,EAClC,SAAS,MAAM,EACf,QAAQ,WAAW,KAClB,OAAO,CAAC,sBAAsB,CAQhC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,wBAAwB,GACnC,WAAW,uBAAuB,EAClC,SAAS,MAAM,EACf,QAAQ,WAAW,KAClB,OAAO,CAAC,0BAA0B,CAQpC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { TradeWorkbenchProps } from '../../types/component';
|
|
3
|
+
/**
|
|
4
|
+
* 渲染由宿主控制开关状态的交易工作台 MVP 全屏弹窗。
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* 组件在打开或入口变化时加载 Demo 数据,并取消上一轮加载或提交请求;旧响应不会覆盖新入口。
|
|
8
|
+
* 创建、编辑和只读入口只验证技术契约,不代表正式交易流程或字段定义。
|
|
9
|
+
*/
|
|
10
|
+
export declare const TradeWorkbench: React.FC<TradeWorkbenchProps>;
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/TradeWorkbench/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAS3D,OAAO,KAAK,EAGV,mBAAmB,EACpB,MAAM,uBAAuB,CAAC;AA8F/B;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAuNxD,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type TradeWorkbenchProviderProps, type TradeWorkbenchRuntime } from '../types/runtime';
|
|
3
|
+
/**
|
|
4
|
+
* 向交易工作台实例注入宿主请求能力与未处理错误回调。
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* Provider 只保存运行环境,不缓存任何交易或表单状态;`transport` 更新后,后续渲染读取新实例。
|
|
8
|
+
*/
|
|
9
|
+
export declare const TradeWorkbenchProvider: React.FC<TradeWorkbenchProviderProps>;
|
|
10
|
+
/**
|
|
11
|
+
* 读取当前交易工作台运行环境。
|
|
12
|
+
*
|
|
13
|
+
* @throws {@link TradeWorkbenchConfigurationError} 当宿主未挂载 `TradeWorkbenchProvider` 时抛出。
|
|
14
|
+
*/
|
|
15
|
+
export declare const useTradeWorkbenchRuntime: () => TradeWorkbenchRuntime;
|
|
16
|
+
//# sourceMappingURL=TradeWorkbenchProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TradeWorkbenchProvider.d.ts","sourceRoot":"","sources":["../../src/context/TradeWorkbenchProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoC,MAAM,OAAO,CAAC;AACzD,OAAO,EAEL,KAAK,2BAA2B,EAChC,KAAK,qBAAqB,EAC3B,MAAM,kBAAkB,CAAC;AAI1B;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,EAAE,KAAK,CAAC,EAAE,CAAC,2BAA2B,CAQxE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,QAAO,qBAQ3C,CAAC"}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));let c=require("@chenhui996/gg-ui"),l=require("react");l=s(l,1);let u=require("react/jsx-runtime");var d=e=>typeof e==`object`&&!!e&&!Array.isArray(e),f=(e,t)=>d(e)&&t.every(t=>typeof e[t]==`string`),p=e=>f(e,[`id`,`label`]),m=e=>f(e,[`label`,`value`]),h=e=>!d(e)||![`basic`,`trade`,`contract`].includes(String(e.key))||typeof e.title!=`string`||!Array.isArray(e.fields)?!1:e.fields.every(m),g=e=>f(e,[`key`,`label`,`value`])&&d(e)&&[`execution`,`risk`,`approval`,`pricing`].includes(String(e.key)),_=e=>d(e)&&typeof e.tradeId==`string`&&typeof e.title==`string`&&typeof e.statusLabel==`string`&&Array.isArray(e.drafts)&&Array.isArray(e.sections)&&Array.isArray(e.statuses)&&e.drafts.every(p)&&e.sections.every(h)&&e.statuses.every(g),v=e=>{if(!_(e))throw Error(`交易工作台 Demo 响应结构无效`);return e},y=e=>{if(!d(e)||typeof e.tradeId!=`string`)throw Error(`交易工作台 Demo 提交响应结构无效`);return{tradeId:e.tradeId}},b=e=>`/__trade-workbench-demo/trades/${encodeURIComponent(e)}`,x=async(e,t,n)=>v(await e.request({method:`GET`,path:b(t),signal:n})),S=async(e,t,n)=>y(await e.request({method:`POST`,path:`${b(t)}/submit`,signal:n})),C=class extends Error{constructor(){super(`[@guozhi-fe/oms-trade-workbench] 缺少 TradeWorkbenchProvider。请在宿主主题 Provider 内挂载 TradeWorkbenchProvider 并注入 transport。`),this.name=`TradeWorkbenchConfigurationError`}},w=(0,l.createContext)(void 0),T=e=>{let{children:t,onUnhandledError:n,transport:r}=e;return(0,u.jsx)(w.Provider,{value:{onUnhandledError:n,transport:r},children:t})},E=()=>{let e=(0,l.useContext)(w);if(!e)throw new C;return e},D={modalRoot:`_modalRoot_4fozy_1`,modalWrapper:`_modalWrapper_4fozy_4`,modalContainer:`_modalContainer_4fozy_8`,modalBody:`_modalBody_4fozy_18`,workbench:`_workbench_4fozy_21`,header:`_header_4fozy_31`,footer:`_footer_4fozy_32`,headingGroup:`_headingGroup_4fozy_45`,title:`_title_4fozy_51`,columnTitle:`_columnTitle_4fozy_52`,sectionTitle:`_sectionTitle_4fozy_53`,meta:`_meta_4fozy_62`,workspaceScroller:`_workspaceScroller_4fozy_69`,workspaceGrid:`_workspaceGrid_4fozy_75`,draftColumn:`_draftColumn_4fozy_83`,detailColumn:`_detailColumn_4fozy_84`,statusColumn:`_statusColumn_4fozy_85`,sectionCard:`_sectionCard_4fozy_91`,draftList:`_draftList_4fozy_102`,statusList:`_statusList_4fozy_103`,draftButton:`_draftButton_4fozy_109`,fieldGrid:`_fieldGrid_4fozy_115`,fieldItem:`_fieldItem_4fozy_121`,statusItem:`_statusItem_4fozy_138`,statePane:`_statePane_4fozy_146`,actionMessage:`_actionMessage_4fozy_161`,actionScroller:`_actionScroller_4fozy_168`,actions:`_actions_4fozy_172`},O=`DEMO-CREATE`,k=e=>{let{drafts:t}=e;return(0,u.jsxs)(`aside`,{className:D.draftColumn,"aria-label":`Demo 草稿列表`,children:[(0,u.jsx)(`h2`,{className:D.columnTitle,children:`草稿列表`}),(0,u.jsx)(`div`,{className:D.draftList,children:t.map((e,t)=>(0,u.jsx)(c.Button,{block:!0,className:D.draftButton,type:t===0?`primary`:`text`,children:e.label},e.id))})]})},A=e=>{let{sections:t}=e;return(0,u.jsx)(`div`,{className:D.detailColumn,"aria-label":`Demo 交易结构区`,children:t.map(e=>(0,u.jsxs)(`section`,{className:D.sectionCard,children:[(0,u.jsx)(`h2`,{className:D.sectionTitle,children:e.title}),(0,u.jsx)(`dl`,{className:D.fieldGrid,children:e.fields.map(t=>(0,u.jsxs)(`div`,{className:D.fieldItem,children:[(0,u.jsx)(`dt`,{children:t.label}),(0,u.jsx)(`dd`,{children:t.value})]},`${e.key}-${t.label}`))})]},e.key))})},j=e=>{let{statuses:t}=e;return(0,u.jsxs)(`aside`,{className:D.statusColumn,"aria-label":`Demo 执行与风控状态`,children:[(0,u.jsx)(`h2`,{className:D.columnTitle,children:`执行与风控`}),(0,u.jsx)(`div`,{className:D.statusList,children:t.map(e=>(0,u.jsxs)(`div`,{className:D.statusItem,children:[(0,u.jsx)(`span`,{children:e.label}),(0,u.jsx)(c.Tag,{children:e.value})]},e.key))})]})},M=e=>e.mode===`create`?`新建交易`:e.mode===`edit`?`编辑交易`:`查看交易`,N=e=>e instanceof Error?e.message:`未知错误`,P=e=>e.type===`keydown`?`escape`:`mask`,F=e=>{let{entry:t,getContainer:n,onRequestClose:r,onSubmitted:i,open:a,zIndex:o}=e,{transport:s}=E(),d=t.mode===`create`?O:t.tradeId,f=t.mode===`view`,[p,m]=(0,l.useState)(),[h,g]=(0,l.useState)(),[_,v]=(0,l.useState)(!1),[y,b]=(0,l.useState)(!1),[C,w]=(0,l.useState)(`等待操作`),[T,F]=(0,l.useState)(0),I=(0,l.useRef)(0),L=(0,l.useRef)(0),R=(0,l.useRef)(void 0);(0,l.useEffect)(()=>{if(!a)return;let e=new AbortController,t=++I.current;return m(void 0),g(void 0),v(!0),w(`正在加载 Demo 数据`),x(s,d,e.signal).then(n=>{e.signal.aborted||t!==I.current||(m(n),w(`Demo 数据已加载`))}).catch(n=>{e.signal.aborted||t!==I.current||(g(N(n)),w(`Demo 数据加载失败`))}).finally(()=>{!e.signal.aborted&&t===I.current&&v(!1)}),()=>{e.abort()}},[d,a,T,s]),(0,l.useEffect)(()=>()=>{L.current+=1,R.current?.abort(),R.current=void 0},[d,a]);let z=e=>{r(P(e))},B=()=>{F(e=>e+1)},V=e=>{w(`${e}仅用于验证交互状态,MVP 未连接真实接口`)};return(0,u.jsx)(c.Modal,{classNames:{body:D.modalBody,container:D.modalContainer,wrapper:D.modalWrapper},closable:!1,destroyOnHidden:!0,footer:null,getContainer:n,keyboard:!0,mask:{closable:!0},onCancel:z,open:a,rootClassName:D.modalRoot,title:null,width:`100%`,zIndex:o,children:(0,u.jsxs)(`div`,{className:D.workbench,children:[(0,u.jsxs)(`header`,{className:D.header,children:[(0,u.jsxs)(`div`,{className:D.headingGroup,children:[(0,u.jsx)(`h1`,{className:D.title,children:M(t)}),(0,u.jsxs)(`span`,{className:D.meta,children:[p?.title??`Demo 数据`,` · 交易 ID:`,p?.tradeId??d]}),(0,u.jsx)(c.Tag,{children:p?.statusLabel??`Demo`})]}),(0,u.jsx)(c.Button,{"aria-label":`关闭交易工作台`,onClick:()=>r(`close-button`),children:`关闭`})]}),(0,u.jsxs)(`main`,{className:D.workspaceScroller,children:[_&&(0,u.jsxs)(`div`,{className:D.statePane,children:[(0,u.jsx)(c.Spin,{size:`large`}),(0,u.jsx)(`span`,{children:`正在加载交易工作台…`})]}),!_&&h&&(0,u.jsxs)(`div`,{className:D.statePane,children:[(0,u.jsx)(c.Alert,{description:h,showIcon:!0,title:`加载失败`,type:`error`}),(0,u.jsx)(c.Button,{"aria-label":`重试`,onClick:B,type:`primary`,children:`重试`})]}),!_&&!h&&p&&(0,u.jsxs)(`div`,{className:D.workspaceGrid,children:[(0,u.jsx)(k,{drafts:p.drafts}),(0,u.jsx)(A,{sections:p.sections}),(0,u.jsx)(j,{statuses:p.statuses})]})]}),(0,u.jsxs)(`footer`,{className:D.footer,children:[(0,u.jsx)(`span`,{className:D.actionMessage,role:`status`,children:C}),(0,u.jsx)(`div`,{className:D.actionScroller,children:(0,u.jsxs)(`div`,{className:D.actions,children:[(0,u.jsx)(c.Button,{"aria-label":`取消`,onClick:()=>r(`cancel-button`),children:`取消`}),(0,u.jsx)(c.Button,{"aria-label":`风控试算`,disabled:f||_||!!h,onClick:()=>V(`风控试算`),children:`风控试算`}),(0,u.jsx)(c.Button,{"aria-label":`试定价`,disabled:f||_||!!h,onClick:()=>V(`试定价`),children:`试定价`}),(0,u.jsx)(c.Button,{"aria-label":`保存草稿`,disabled:f||_||!!h,onClick:()=>V(`保存草稿`),children:`保存草稿`}),(0,u.jsx)(c.Button,{"aria-label":`提交`,disabled:f||_||!!h||!p,loading:y,onClick:async()=>{if(f||y)return;R.current?.abort();let e=new AbortController,t=++L.current;R.current=e,b(!0),w(`正在提交 Demo`);try{let n=await S(s,d,e.signal);if(e.signal.aborted||t!==L.current)return;w(`Demo 提交成功`),i?.(n),r(`submitted`)}catch(n){!e.signal.aborted&&t===L.current&&w(`Demo 提交失败:${N(n)}`)}finally{!e.signal.aborted&&t===L.current&&(b(!1),R.current=void 0)}},type:`primary`,children:`提交`})]})})]})]})})};exports.TradeWorkbench=F,exports.TradeWorkbenchConfigurationError=C,exports.TradeWorkbenchProvider=T;
|
|
2
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":[],"sources":["../src/model/demo.ts","../src/api/demo.ts","../src/types/runtime.ts","../src/context/TradeWorkbenchProvider.tsx","../src/components/TradeWorkbench/index.module.less","../src/components/TradeWorkbench/index.tsx"],"sourcesContent":["export interface TradeWorkbenchDemoDraft {\n id: string;\n label: string;\n}\n\nexport interface TradeWorkbenchDemoField {\n label: string;\n value: string;\n}\n\nexport interface TradeWorkbenchDemoSection {\n key: 'basic' | 'trade' | 'contract';\n title: string;\n fields: readonly TradeWorkbenchDemoField[];\n}\n\nexport interface TradeWorkbenchDemoStatus {\n key: 'execution' | 'risk' | 'approval' | 'pricing';\n label: string;\n value: string;\n}\n\nexport interface TradeWorkbenchDemoData {\n tradeId: string;\n title: string;\n statusLabel: string;\n drafts: readonly TradeWorkbenchDemoDraft[];\n sections: readonly TradeWorkbenchDemoSection[];\n statuses: readonly TradeWorkbenchDemoStatus[];\n}\n\nconst isRecord = (value: unknown): value is Readonly<Record<string, unknown>> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nconst isStringEntry = (value: unknown, keys: readonly string[]): boolean =>\n isRecord(value) && keys.every((key) => typeof value[key] === 'string');\n\nconst isDemoDraft = (value: unknown): value is TradeWorkbenchDemoDraft =>\n isStringEntry(value, ['id', 'label']);\n\nconst isDemoField = (value: unknown): value is TradeWorkbenchDemoField =>\n isStringEntry(value, ['label', 'value']);\n\nconst isDemoSection = (value: unknown): value is TradeWorkbenchDemoSection => {\n if (\n !isRecord(value) ||\n !['basic', 'trade', 'contract'].includes(String(value.key)) ||\n typeof value.title !== 'string' ||\n !Array.isArray(value.fields)\n ) {\n return false;\n }\n\n return value.fields.every(isDemoField);\n};\n\nconst isDemoStatus = (value: unknown): value is TradeWorkbenchDemoStatus =>\n isStringEntry(value, ['key', 'label', 'value']) &&\n isRecord(value) &&\n ['execution', 'risk', 'approval', 'pricing'].includes(String(value.key));\n\nconst isTradeWorkbenchDemoData = (value: unknown): value is TradeWorkbenchDemoData =>\n isRecord(value) &&\n typeof value.tradeId === 'string' &&\n typeof value.title === 'string' &&\n typeof value.statusLabel === 'string' &&\n Array.isArray(value.drafts) &&\n Array.isArray(value.sections) &&\n Array.isArray(value.statuses) &&\n value.drafts.every(isDemoDraft) &&\n value.sections.every(isDemoSection) &&\n value.statuses.every(isDemoStatus);\n\n/**\n * 校验宿主 Transport 返回的交易工作台 Demo 数据。\n *\n * @remarks\n * Demo 响应不属于正式交易契约;结构不完整时立即失败,避免不可信数据直接进入组件渲染。\n *\n * @param value - Transport 返回的未知响应。\n * @returns 可供 MVP 弹窗展示的 Demo 数据。\n * @throws 当响应缺少必需字段或数组项结构不合法时抛出。\n */\nexport const parseTradeWorkbenchDemoData = (value: unknown): TradeWorkbenchDemoData => {\n if (!isTradeWorkbenchDemoData(value)) {\n throw new Error('交易工作台 Demo 响应结构无效');\n }\n\n return value;\n};\n\n/**\n * 校验 Demo 提交结果,仅向宿主返回稳定的交易标识。\n *\n * @param value - Transport 返回的未知提交响应。\n * @returns MVP 提交结果。\n * @throws 当响应不包含字符串 `tradeId` 时抛出。\n */\nexport const parseTradeWorkbenchSubmitResult = (value: unknown): { tradeId: string } => {\n if (!isRecord(value) || typeof value.tradeId !== 'string') {\n throw new Error('交易工作台 Demo 提交响应结构无效');\n }\n\n return { tradeId: value.tradeId };\n};\n","import {\n parseTradeWorkbenchDemoData,\n parseTradeWorkbenchSubmitResult,\n type TradeWorkbenchDemoData,\n} from '../model/demo';\nimport type { TradeWorkbenchSubmitResult } from '../types/component';\nimport type { TradeWorkbenchTransport } from '../types/transport';\n\nconst resolveDemoTradePath = (tradeId: string): string =>\n `/__trade-workbench-demo/trades/${encodeURIComponent(tradeId)}`;\n\n/**\n * 通过宿主注入的 Transport 加载交易工作台 MVP 展示数据。\n *\n * @remarks\n * 该接口仅用于技术验证,不连接真实交易服务;`signal` 会原样交给宿主请求实现。\n *\n * @param transport - 宿主注入的最小请求能力。\n * @param tradeId - 当前 Demo 交易标识。\n * @param signal - 用于取消当前加载请求的信号。\n * @returns 已完成结构校验的 Demo 数据。\n */\nexport const getTradeWorkbenchDemo = async (\n transport: TradeWorkbenchTransport,\n tradeId: string,\n signal: AbortSignal,\n): Promise<TradeWorkbenchDemoData> => {\n const response = await transport.request<unknown>({\n method: 'GET',\n path: resolveDemoTradePath(tradeId),\n signal,\n });\n\n return parseTradeWorkbenchDemoData(response);\n};\n\n/**\n * 通过宿主注入的 Transport 提交当前 MVP Demo。\n *\n * @remarks\n * 该请求仅验证提交编排、重复提交保护和宿主回调,不代表正式交易提交契约。\n *\n * @param transport - 宿主注入的最小请求能力。\n * @param tradeId - 当前 Demo 交易标识。\n * @param signal - 用于取消提交请求的信号。\n * @returns 只包含稳定交易标识的提交结果。\n */\nexport const submitTradeWorkbenchDemo = async (\n transport: TradeWorkbenchTransport,\n tradeId: string,\n signal: AbortSignal,\n): Promise<TradeWorkbenchSubmitResult> => {\n const response = await transport.request<unknown>({\n method: 'POST',\n path: `${resolveDemoTradePath(tradeId)}/submit`,\n signal,\n });\n\n return parseTradeWorkbenchSubmitResult(response);\n};\n","import type React from 'react';\nimport type { TradeWorkbenchTransport } from './transport';\n\nexport interface TradeWorkbenchProviderProps {\n children: React.ReactNode;\n transport: TradeWorkbenchTransport;\n onUnhandledError?: (error: unknown) => void;\n}\n\nexport interface TradeWorkbenchRuntime {\n transport: TradeWorkbenchTransport;\n onUnhandledError?: (error: unknown) => void;\n}\n\n/** 宿主未注入交易工作台运行环境时抛出的配置错误。 */\nexport class TradeWorkbenchConfigurationError extends Error {\n public constructor() {\n super(\n '[@guozhi-fe/oms-trade-workbench] 缺少 TradeWorkbenchProvider。请在宿主主题 Provider 内挂载 TradeWorkbenchProvider 并注入 transport。',\n );\n this.name = 'TradeWorkbenchConfigurationError';\n }\n}\n","import React, { createContext, useContext } from 'react';\nimport {\n TradeWorkbenchConfigurationError,\n type TradeWorkbenchProviderProps,\n type TradeWorkbenchRuntime,\n} from '../types/runtime';\n\nconst TradeWorkbenchRuntimeContext = createContext<TradeWorkbenchRuntime | undefined>(undefined);\n\n/**\n * 向交易工作台实例注入宿主请求能力与未处理错误回调。\n *\n * @remarks\n * Provider 只保存运行环境,不缓存任何交易或表单状态;`transport` 更新后,后续渲染读取新实例。\n */\nexport const TradeWorkbenchProvider: React.FC<TradeWorkbenchProviderProps> = (props) => {\n const { children, onUnhandledError, transport } = props;\n\n return (\n <TradeWorkbenchRuntimeContext.Provider value={{ onUnhandledError, transport }}>\n {children}\n </TradeWorkbenchRuntimeContext.Provider>\n );\n};\n\n/**\n * 读取当前交易工作台运行环境。\n *\n * @throws {@link TradeWorkbenchConfigurationError} 当宿主未挂载 `TradeWorkbenchProvider` 时抛出。\n */\nexport const useTradeWorkbenchRuntime = (): TradeWorkbenchRuntime => {\n const runtime = useContext(TradeWorkbenchRuntimeContext);\n\n if (!runtime) {\n throw new TradeWorkbenchConfigurationError();\n }\n\n return runtime;\n};\n",".modalRoot {\n color: var(--gz-color-text);\n}\n\n.modalWrapper {\n padding: calc(var(--gz-padding, 16) * 1px);\n overflow: hidden;\n}\n\n.modalContainer {\n top: 0;\n max-width: none;\n height: calc(100dvh - calc(var(--gz-padding, 16) * 2px));\n padding: 0;\n overflow: hidden;\n background: var(--gz-color-bg-container);\n border: 1px solid var(--gz-color-border-secondary);\n border-radius: calc(var(--gz-border-radius-lg, 8) * 1px);\n}\n\n.modalBody {\n height: 100%;\n}\n\n.workbench {\n display: flex;\n flex-direction: column;\n width: 100%;\n min-width: 0;\n height: 100%;\n min-height: 0;\n color: var(--gz-color-text);\n background: var(--gz-color-bg-layout);\n}\n\n.header,\n.footer {\n display: flex;\n flex: none;\n align-items: center;\n justify-content: space-between;\n min-width: 0;\n padding: calc(var(--gz-padding-sm, 12) * 1px) calc(var(--gz-padding, 16) * 1px);\n background: var(--gz-color-bg-container);\n}\n\n.header {\n gap: calc(var(--gz-margin-sm, 12) * 1px);\n border-bottom: 1px solid var(--gz-color-border-secondary);\n}\n\n.headingGroup {\n display: flex;\n gap: calc(var(--gz-margin-sm, 12) * 1px);\n align-items: center;\n min-width: 0;\n}\n\n.title,\n.columnTitle,\n.sectionTitle {\n margin: 0;\n font-weight: var(--gz-font-weight-strong, 600);\n color: var(--gz-color-text);\n}\n\n.title {\n font-size: calc(var(--gz-font-size-heading-4, 20) * 1px);\n white-space: nowrap;\n}\n\n.meta {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n color: var(--gz-color-text-secondary);\n white-space: nowrap;\n}\n\n.workspaceScroller {\n flex: 1;\n min-width: 0;\n min-height: 0;\n overflow: auto;\n}\n\n.workspaceGrid {\n display: grid;\n grid-template-columns: minmax(180px, 220px) minmax(520px, 1fr) minmax(240px, 300px);\n gap: calc(var(--gz-margin-sm, 12) * 1px);\n min-width: 1020px;\n min-height: 100%;\n padding: calc(var(--gz-padding-sm, 12) * 1px);\n}\n\n.draftColumn,\n.detailColumn,\n.statusColumn {\n min-width: 0;\n min-height: 0;\n}\n\n.draftColumn,\n.statusColumn,\n.sectionCard {\n padding: calc(var(--gz-padding-sm, 12) * 1px);\n background: var(--gz-color-bg-container);\n border: 1px solid var(--gz-color-border-secondary);\n border-radius: calc(var(--gz-border-radius, 6) * 1px);\n}\n\n.columnTitle,\n.sectionTitle {\n margin-bottom: calc(var(--gz-margin-sm, 12) * 1px);\n font-size: calc(var(--gz-font-size-lg, 16) * 1px);\n}\n\n.draftList,\n.statusList,\n.detailColumn {\n display: flex;\n flex-direction: column;\n gap: calc(var(--gz-margin-sm, 12) * 1px);\n}\n\n.draftButton {\n overflow: hidden;\n text-overflow: ellipsis;\n text-align: left;\n white-space: nowrap;\n}\n\n.fieldGrid {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: calc(var(--gz-margin-sm, 12) * 1px);\n margin: 0;\n}\n\n.fieldItem {\n min-width: 0;\n padding: calc(var(--gz-padding-xs, 8) * 1px);\n background: var(--gz-color-fill-tertiary);\n border-radius: calc(var(--gz-border-radius-sm, 4) * 1px);\n\n dt {\n margin-bottom: calc(var(--gz-margin-xxs, 4) * 1px);\n color: var(--gz-color-text-secondary);\n }\n\n dd {\n margin: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n color: var(--gz-color-text);\n white-space: nowrap;\n }\n}\n\n.statusItem {\n display: flex;\n gap: calc(var(--gz-margin-xs, 8) * 1px);\n align-items: center;\n justify-content: space-between;\n padding-bottom: calc(var(--gz-padding-xs, 8) * 1px);\n border-bottom: 1px solid var(--gz-color-border-secondary);\n}\n\n.statePane {\n display: flex;\n flex-direction: column;\n gap: calc(var(--gz-margin, 16) * 1px);\n align-items: center;\n justify-content: center;\n min-width: 320px;\n min-height: 100%;\n padding: calc(var(--gz-padding-lg, 24) * 1px);\n color: var(--gz-color-text-secondary);\n}\n\n.footer {\n gap: calc(var(--gz-margin-sm, 12) * 1px);\n border-top: 1px solid var(--gz-color-border-secondary);\n}\n\n.actionMessage {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n color: var(--gz-color-text-secondary);\n white-space: nowrap;\n}\n\n.actionScroller {\n min-width: 0;\n overflow-x: auto;\n}\n\n.actions {\n display: flex;\n gap: calc(var(--gz-margin-xs, 8) * 1px);\n width: max-content;\n min-width: max-content;\n}\n\n@media (width <= 720px) {\n .modalWrapper {\n padding: calc(var(--gz-padding-xs, 8) * 1px);\n }\n\n .modalContainer {\n height: calc(100dvh - calc(var(--gz-padding-xs, 8) * 2px));\n }\n\n .headingGroup {\n gap: calc(var(--gz-margin-xs, 8) * 1px);\n }\n\n .meta {\n display: none;\n }\n\n .footer {\n flex-direction: column;\n align-items: stretch;\n }\n}\n","import { Alert, Button, Modal, Spin, Tag } from '@chenhui996/gg-ui';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { getTradeWorkbenchDemo, submitTradeWorkbenchDemo } from '../../api/demo';\nimport { useTradeWorkbenchRuntime } from '../../context/TradeWorkbenchProvider';\nimport type {\n TradeWorkbenchDemoData,\n TradeWorkbenchDemoDraft,\n TradeWorkbenchDemoSection,\n TradeWorkbenchDemoStatus,\n} from '../../model/demo';\nimport type {\n TradeWorkbenchCloseReason,\n TradeWorkbenchEntry,\n TradeWorkbenchProps,\n} from '../../types/component';\nimport styles from './index.module.less';\n\nconst CREATE_DEMO_TRADE_ID = 'DEMO-CREATE';\n\ninterface DraftListProps {\n drafts: readonly TradeWorkbenchDemoDraft[];\n}\n\nconst DraftList: React.FC<DraftListProps> = (props) => {\n const { drafts } = props;\n\n return (\n <aside className={styles.draftColumn} aria-label=\"Demo 草稿列表\">\n <h2 className={styles.columnTitle}>草稿列表</h2>\n <div className={styles.draftList}>\n {drafts.map((draft, index) => (\n <Button\n block\n className={styles.draftButton}\n key={draft.id}\n type={index === 0 ? 'primary' : 'text'}\n >\n {draft.label}\n </Button>\n ))}\n </div>\n </aside>\n );\n};\n\ninterface DetailSectionsProps {\n sections: readonly TradeWorkbenchDemoSection[];\n}\n\nconst DetailSections: React.FC<DetailSectionsProps> = (props) => {\n const { sections } = props;\n\n return (\n <div className={styles.detailColumn} aria-label=\"Demo 交易结构区\">\n {sections.map((section) => (\n <section className={styles.sectionCard} key={section.key}>\n <h2 className={styles.sectionTitle}>{section.title}</h2>\n <dl className={styles.fieldGrid}>\n {section.fields.map((field) => (\n <div className={styles.fieldItem} key={`${section.key}-${field.label}`}>\n <dt>{field.label}</dt>\n <dd>{field.value}</dd>\n </div>\n ))}\n </dl>\n </section>\n ))}\n </div>\n );\n};\n\ninterface StatusSummaryProps {\n statuses: readonly TradeWorkbenchDemoStatus[];\n}\n\nconst StatusSummary: React.FC<StatusSummaryProps> = (props) => {\n const { statuses } = props;\n\n return (\n <aside className={styles.statusColumn} aria-label=\"Demo 执行与风控状态\">\n <h2 className={styles.columnTitle}>执行与风控</h2>\n <div className={styles.statusList}>\n {statuses.map((status) => (\n <div className={styles.statusItem} key={status.key}>\n <span>{status.label}</span>\n <Tag>{status.value}</Tag>\n </div>\n ))}\n </div>\n </aside>\n );\n};\n\nconst getEntryTitle = (entry: TradeWorkbenchEntry): string => {\n if (entry.mode === 'create') {\n return '新建交易';\n }\n\n return entry.mode === 'edit' ? '编辑交易' : '查看交易';\n};\n\nconst getErrorMessage = (error: unknown): string =>\n error instanceof Error ? error.message : '未知错误';\n\nconst getModalCloseReason = (\n event: React.MouseEvent<HTMLButtonElement> | React.KeyboardEvent<HTMLElement>,\n): TradeWorkbenchCloseReason => (event.type === 'keydown' ? 'escape' : 'mask');\n\n/**\n * 渲染由宿主控制开关状态的交易工作台 MVP 全屏弹窗。\n *\n * @remarks\n * 组件在打开或入口变化时加载 Demo 数据,并取消上一轮加载或提交请求;旧响应不会覆盖新入口。\n * 创建、编辑和只读入口只验证技术契约,不代表正式交易流程或字段定义。\n */\nexport const TradeWorkbench: React.FC<TradeWorkbenchProps> = (props) => {\n const { entry, getContainer, onRequestClose, onSubmitted, open, zIndex } = props;\n const { transport } = useTradeWorkbenchRuntime();\n const demoTradeId = entry.mode === 'create' ? CREATE_DEMO_TRADE_ID : entry.tradeId;\n const readOnly = entry.mode === 'view';\n const [data, setData] = useState<TradeWorkbenchDemoData>();\n const [loadError, setLoadError] = useState<string>();\n const [isLoading, setIsLoading] = useState(false);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [actionMessage, setActionMessage] = useState('等待操作');\n const [reloadVersion, setReloadVersion] = useState(0);\n const loadVersionRef = useRef(0);\n const submitVersionRef = useRef(0);\n const submitControllerRef = useRef<AbortController | undefined>(undefined);\n\n useEffect(() => {\n if (!open) {\n return;\n }\n\n const controller = new AbortController();\n const requestVersion = ++loadVersionRef.current;\n setData(undefined);\n setLoadError(undefined);\n setIsLoading(true);\n setActionMessage('正在加载 Demo 数据');\n\n getTradeWorkbenchDemo(transport, demoTradeId, controller.signal)\n .then((response) => {\n if (controller.signal.aborted || requestVersion !== loadVersionRef.current) {\n return;\n }\n\n setData(response);\n setActionMessage('Demo 数据已加载');\n })\n .catch((error: unknown) => {\n if (controller.signal.aborted || requestVersion !== loadVersionRef.current) {\n return;\n }\n\n setLoadError(getErrorMessage(error));\n setActionMessage('Demo 数据加载失败');\n })\n .finally(() => {\n if (!controller.signal.aborted && requestVersion === loadVersionRef.current) {\n setIsLoading(false);\n }\n });\n\n return () => {\n controller.abort();\n };\n }, [demoTradeId, open, reloadVersion, transport]);\n\n useEffect(() => {\n return () => {\n submitVersionRef.current += 1;\n submitControllerRef.current?.abort();\n submitControllerRef.current = undefined;\n };\n }, [demoTradeId, open]);\n\n const handleModalCancel = (\n event: React.MouseEvent<HTMLButtonElement> | React.KeyboardEvent<HTMLElement>,\n ): void => {\n onRequestClose(getModalCloseReason(event));\n };\n\n const handleRetry = (): void => {\n setReloadVersion((version) => version + 1);\n };\n\n const handleDemoAction = (action: string): void => {\n setActionMessage(`${action}仅用于验证交互状态,MVP 未连接真实接口`);\n };\n\n const handleSubmit = async (): Promise<void> => {\n if (readOnly || isSubmitting) {\n return;\n }\n\n submitControllerRef.current?.abort();\n const controller = new AbortController();\n const requestVersion = ++submitVersionRef.current;\n submitControllerRef.current = controller;\n setIsSubmitting(true);\n setActionMessage('正在提交 Demo');\n\n try {\n const result = await submitTradeWorkbenchDemo(transport, demoTradeId, controller.signal);\n if (controller.signal.aborted || requestVersion !== submitVersionRef.current) {\n return;\n }\n\n setActionMessage('Demo 提交成功');\n onSubmitted?.(result);\n onRequestClose('submitted');\n } catch (error: unknown) {\n if (!controller.signal.aborted && requestVersion === submitVersionRef.current) {\n setActionMessage(`Demo 提交失败:${getErrorMessage(error)}`);\n }\n } finally {\n if (!controller.signal.aborted && requestVersion === submitVersionRef.current) {\n setIsSubmitting(false);\n submitControllerRef.current = undefined;\n }\n }\n };\n\n return (\n <Modal\n classNames={{\n body: styles.modalBody,\n container: styles.modalContainer,\n wrapper: styles.modalWrapper,\n }}\n closable={false}\n destroyOnHidden\n footer={null}\n getContainer={getContainer}\n keyboard\n mask={{ closable: true }}\n onCancel={handleModalCancel}\n open={open}\n rootClassName={styles.modalRoot}\n title={null}\n width=\"100%\"\n zIndex={zIndex}\n >\n <div className={styles.workbench}>\n <header className={styles.header}>\n <div className={styles.headingGroup}>\n <h1 className={styles.title}>{getEntryTitle(entry)}</h1>\n <span className={styles.meta}>\n {data?.title ?? 'Demo 数据'} · 交易 ID:{data?.tradeId ?? demoTradeId}\n </span>\n <Tag>{data?.statusLabel ?? 'Demo'}</Tag>\n </div>\n <Button aria-label=\"关闭交易工作台\" onClick={() => onRequestClose('close-button')}>\n 关闭\n </Button>\n </header>\n\n <main className={styles.workspaceScroller}>\n {isLoading && (\n <div className={styles.statePane}>\n <Spin size=\"large\" />\n <span>正在加载交易工作台…</span>\n </div>\n )}\n\n {!isLoading && loadError && (\n <div className={styles.statePane}>\n <Alert description={loadError} showIcon title=\"加载失败\" type=\"error\" />\n <Button aria-label=\"重试\" onClick={handleRetry} type=\"primary\">\n 重试\n </Button>\n </div>\n )}\n\n {!isLoading && !loadError && data && (\n <div className={styles.workspaceGrid}>\n <DraftList drafts={data.drafts} />\n <DetailSections sections={data.sections} />\n <StatusSummary statuses={data.statuses} />\n </div>\n )}\n </main>\n\n <footer className={styles.footer}>\n <span className={styles.actionMessage} role=\"status\">\n {actionMessage}\n </span>\n <div className={styles.actionScroller}>\n <div className={styles.actions}>\n <Button aria-label=\"取消\" onClick={() => onRequestClose('cancel-button')}>\n 取消\n </Button>\n <Button\n aria-label=\"风控试算\"\n disabled={readOnly || isLoading || Boolean(loadError)}\n onClick={() => handleDemoAction('风控试算')}\n >\n 风控试算\n </Button>\n <Button\n aria-label=\"试定价\"\n disabled={readOnly || isLoading || Boolean(loadError)}\n onClick={() => handleDemoAction('试定价')}\n >\n 试定价\n </Button>\n <Button\n aria-label=\"保存草稿\"\n disabled={readOnly || isLoading || Boolean(loadError)}\n onClick={() => handleDemoAction('保存草稿')}\n >\n 保存草稿\n </Button>\n <Button\n aria-label=\"提交\"\n disabled={readOnly || isLoading || Boolean(loadError) || !data}\n loading={isSubmitting}\n onClick={handleSubmit}\n type=\"primary\"\n >\n 提交\n </Button>\n </div>\n </div>\n </footer>\n </div>\n </Modal>\n );\n};\n"],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { TradeWorkbench } from './components/TradeWorkbench';
|
|
2
|
+
export { TradeWorkbenchProvider } from './context/TradeWorkbenchProvider';
|
|
3
|
+
export type { TradeWorkbenchCloseReason, TradeWorkbenchEntry, TradeWorkbenchProps, TradeWorkbenchSubmitResult, } from './types/component';
|
|
4
|
+
export { TradeWorkbenchConfigurationError } from './types/runtime';
|
|
5
|
+
export type { TradeWorkbenchProviderProps } from './types/runtime';
|
|
6
|
+
export type { TradeWorkbenchHttpMethod, TradeWorkbenchQueryValue, TradeWorkbenchRequestConfig, TradeWorkbenchTransport, } from './types/transport';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,YAAY,EACV,yBAAyB,EACzB,mBAAmB,EACnB,mBAAmB,EACnB,0BAA0B,GAC3B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,gCAAgC,EAAE,MAAM,iBAAiB,CAAC;AACnE,YAAY,EAAE,2BAA2B,EAAE,MAAM,iBAAiB,CAAC;AACnE,YAAY,EACV,wBAAwB,EACxB,wBAAwB,EACxB,2BAA2B,EAC3B,uBAAuB,GACxB,MAAM,mBAAmB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
import { Alert as e, Button as t, Modal as n, Spin as r, Tag as i } from "@chenhui996/gg-ui";
|
|
2
|
+
import { createContext as a, useContext as o, useEffect as s, useRef as c, useState as l } from "react";
|
|
3
|
+
import { jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
4
|
+
//#region src/model/demo.ts
|
|
5
|
+
var f = (e) => typeof e == "object" && !!e && !Array.isArray(e), p = (e, t) => f(e) && t.every((t) => typeof e[t] == "string"), m = (e) => p(e, ["id", "label"]), h = (e) => p(e, ["label", "value"]), g = (e) => !f(e) || ![
|
|
6
|
+
"basic",
|
|
7
|
+
"trade",
|
|
8
|
+
"contract"
|
|
9
|
+
].includes(String(e.key)) || typeof e.title != "string" || !Array.isArray(e.fields) ? !1 : e.fields.every(h), _ = (e) => p(e, [
|
|
10
|
+
"key",
|
|
11
|
+
"label",
|
|
12
|
+
"value"
|
|
13
|
+
]) && f(e) && [
|
|
14
|
+
"execution",
|
|
15
|
+
"risk",
|
|
16
|
+
"approval",
|
|
17
|
+
"pricing"
|
|
18
|
+
].includes(String(e.key)), v = (e) => f(e) && typeof e.tradeId == "string" && typeof e.title == "string" && typeof e.statusLabel == "string" && Array.isArray(e.drafts) && Array.isArray(e.sections) && Array.isArray(e.statuses) && e.drafts.every(m) && e.sections.every(g) && e.statuses.every(_), y = (e) => {
|
|
19
|
+
if (!v(e)) throw Error("交易工作台 Demo 响应结构无效");
|
|
20
|
+
return e;
|
|
21
|
+
}, b = (e) => {
|
|
22
|
+
if (!f(e) || typeof e.tradeId != "string") throw Error("交易工作台 Demo 提交响应结构无效");
|
|
23
|
+
return { tradeId: e.tradeId };
|
|
24
|
+
}, x = (e) => `/__trade-workbench-demo/trades/${encodeURIComponent(e)}`, S = async (e, t, n) => y(await e.request({
|
|
25
|
+
method: "GET",
|
|
26
|
+
path: x(t),
|
|
27
|
+
signal: n
|
|
28
|
+
})), C = async (e, t, n) => b(await e.request({
|
|
29
|
+
method: "POST",
|
|
30
|
+
path: `${x(t)}/submit`,
|
|
31
|
+
signal: n
|
|
32
|
+
})), w = class extends Error {
|
|
33
|
+
constructor() {
|
|
34
|
+
super("[@guozhi-fe/oms-trade-workbench] 缺少 TradeWorkbenchProvider。请在宿主主题 Provider 内挂载 TradeWorkbenchProvider 并注入 transport。"), this.name = "TradeWorkbenchConfigurationError";
|
|
35
|
+
}
|
|
36
|
+
}, T = a(void 0), E = (e) => {
|
|
37
|
+
let { children: t, onUnhandledError: n, transport: r } = e;
|
|
38
|
+
return /* @__PURE__ */ u(T.Provider, {
|
|
39
|
+
value: {
|
|
40
|
+
onUnhandledError: n,
|
|
41
|
+
transport: r
|
|
42
|
+
},
|
|
43
|
+
children: t
|
|
44
|
+
});
|
|
45
|
+
}, D = () => {
|
|
46
|
+
let e = o(T);
|
|
47
|
+
if (!e) throw new w();
|
|
48
|
+
return e;
|
|
49
|
+
}, O = {
|
|
50
|
+
modalRoot: "_modalRoot_4fozy_1",
|
|
51
|
+
modalWrapper: "_modalWrapper_4fozy_4",
|
|
52
|
+
modalContainer: "_modalContainer_4fozy_8",
|
|
53
|
+
modalBody: "_modalBody_4fozy_18",
|
|
54
|
+
workbench: "_workbench_4fozy_21",
|
|
55
|
+
header: "_header_4fozy_31",
|
|
56
|
+
footer: "_footer_4fozy_32",
|
|
57
|
+
headingGroup: "_headingGroup_4fozy_45",
|
|
58
|
+
title: "_title_4fozy_51",
|
|
59
|
+
columnTitle: "_columnTitle_4fozy_52",
|
|
60
|
+
sectionTitle: "_sectionTitle_4fozy_53",
|
|
61
|
+
meta: "_meta_4fozy_62",
|
|
62
|
+
workspaceScroller: "_workspaceScroller_4fozy_69",
|
|
63
|
+
workspaceGrid: "_workspaceGrid_4fozy_75",
|
|
64
|
+
draftColumn: "_draftColumn_4fozy_83",
|
|
65
|
+
detailColumn: "_detailColumn_4fozy_84",
|
|
66
|
+
statusColumn: "_statusColumn_4fozy_85",
|
|
67
|
+
sectionCard: "_sectionCard_4fozy_91",
|
|
68
|
+
draftList: "_draftList_4fozy_102",
|
|
69
|
+
statusList: "_statusList_4fozy_103",
|
|
70
|
+
draftButton: "_draftButton_4fozy_109",
|
|
71
|
+
fieldGrid: "_fieldGrid_4fozy_115",
|
|
72
|
+
fieldItem: "_fieldItem_4fozy_121",
|
|
73
|
+
statusItem: "_statusItem_4fozy_138",
|
|
74
|
+
statePane: "_statePane_4fozy_146",
|
|
75
|
+
actionMessage: "_actionMessage_4fozy_161",
|
|
76
|
+
actionScroller: "_actionScroller_4fozy_168",
|
|
77
|
+
actions: "_actions_4fozy_172"
|
|
78
|
+
}, k = "DEMO-CREATE", A = (e) => {
|
|
79
|
+
let { drafts: n } = e;
|
|
80
|
+
return /* @__PURE__ */ d("aside", {
|
|
81
|
+
className: O.draftColumn,
|
|
82
|
+
"aria-label": "Demo 草稿列表",
|
|
83
|
+
children: [/* @__PURE__ */ u("h2", {
|
|
84
|
+
className: O.columnTitle,
|
|
85
|
+
children: "草稿列表"
|
|
86
|
+
}), /* @__PURE__ */ u("div", {
|
|
87
|
+
className: O.draftList,
|
|
88
|
+
children: n.map((e, n) => /* @__PURE__ */ u(t, {
|
|
89
|
+
block: !0,
|
|
90
|
+
className: O.draftButton,
|
|
91
|
+
type: n === 0 ? "primary" : "text",
|
|
92
|
+
children: e.label
|
|
93
|
+
}, e.id))
|
|
94
|
+
})]
|
|
95
|
+
});
|
|
96
|
+
}, j = (e) => {
|
|
97
|
+
let { sections: t } = e;
|
|
98
|
+
return /* @__PURE__ */ u("div", {
|
|
99
|
+
className: O.detailColumn,
|
|
100
|
+
"aria-label": "Demo 交易结构区",
|
|
101
|
+
children: t.map((e) => /* @__PURE__ */ d("section", {
|
|
102
|
+
className: O.sectionCard,
|
|
103
|
+
children: [/* @__PURE__ */ u("h2", {
|
|
104
|
+
className: O.sectionTitle,
|
|
105
|
+
children: e.title
|
|
106
|
+
}), /* @__PURE__ */ u("dl", {
|
|
107
|
+
className: O.fieldGrid,
|
|
108
|
+
children: e.fields.map((t) => /* @__PURE__ */ d("div", {
|
|
109
|
+
className: O.fieldItem,
|
|
110
|
+
children: [/* @__PURE__ */ u("dt", { children: t.label }), /* @__PURE__ */ u("dd", { children: t.value })]
|
|
111
|
+
}, `${e.key}-${t.label}`))
|
|
112
|
+
})]
|
|
113
|
+
}, e.key))
|
|
114
|
+
});
|
|
115
|
+
}, M = (e) => {
|
|
116
|
+
let { statuses: t } = e;
|
|
117
|
+
return /* @__PURE__ */ d("aside", {
|
|
118
|
+
className: O.statusColumn,
|
|
119
|
+
"aria-label": "Demo 执行与风控状态",
|
|
120
|
+
children: [/* @__PURE__ */ u("h2", {
|
|
121
|
+
className: O.columnTitle,
|
|
122
|
+
children: "执行与风控"
|
|
123
|
+
}), /* @__PURE__ */ u("div", {
|
|
124
|
+
className: O.statusList,
|
|
125
|
+
children: t.map((e) => /* @__PURE__ */ d("div", {
|
|
126
|
+
className: O.statusItem,
|
|
127
|
+
children: [/* @__PURE__ */ u("span", { children: e.label }), /* @__PURE__ */ u(i, { children: e.value })]
|
|
128
|
+
}, e.key))
|
|
129
|
+
})]
|
|
130
|
+
});
|
|
131
|
+
}, N = (e) => e.mode === "create" ? "新建交易" : e.mode === "edit" ? "编辑交易" : "查看交易", P = (e) => e instanceof Error ? e.message : "未知错误", F = (e) => e.type === "keydown" ? "escape" : "mask", I = (a) => {
|
|
132
|
+
let { entry: o, getContainer: f, onRequestClose: p, onSubmitted: m, open: h, zIndex: g } = a, { transport: _ } = D(), v = o.mode === "create" ? k : o.tradeId, y = o.mode === "view", [b, x] = l(), [w, T] = l(), [E, I] = l(!1), [L, R] = l(!1), [z, B] = l("等待操作"), [V, H] = l(0), U = c(0), W = c(0), G = c(void 0);
|
|
133
|
+
s(() => {
|
|
134
|
+
if (!h) return;
|
|
135
|
+
let e = new AbortController(), t = ++U.current;
|
|
136
|
+
return x(void 0), T(void 0), I(!0), B("正在加载 Demo 数据"), S(_, v, e.signal).then((n) => {
|
|
137
|
+
e.signal.aborted || t !== U.current || (x(n), B("Demo 数据已加载"));
|
|
138
|
+
}).catch((n) => {
|
|
139
|
+
e.signal.aborted || t !== U.current || (T(P(n)), B("Demo 数据加载失败"));
|
|
140
|
+
}).finally(() => {
|
|
141
|
+
!e.signal.aborted && t === U.current && I(!1);
|
|
142
|
+
}), () => {
|
|
143
|
+
e.abort();
|
|
144
|
+
};
|
|
145
|
+
}, [
|
|
146
|
+
v,
|
|
147
|
+
h,
|
|
148
|
+
V,
|
|
149
|
+
_
|
|
150
|
+
]), s(() => () => {
|
|
151
|
+
W.current += 1, G.current?.abort(), G.current = void 0;
|
|
152
|
+
}, [v, h]);
|
|
153
|
+
let K = (e) => {
|
|
154
|
+
p(F(e));
|
|
155
|
+
}, q = () => {
|
|
156
|
+
H((e) => e + 1);
|
|
157
|
+
}, J = (e) => {
|
|
158
|
+
B(`${e}仅用于验证交互状态,MVP 未连接真实接口`);
|
|
159
|
+
};
|
|
160
|
+
return /* @__PURE__ */ u(n, {
|
|
161
|
+
classNames: {
|
|
162
|
+
body: O.modalBody,
|
|
163
|
+
container: O.modalContainer,
|
|
164
|
+
wrapper: O.modalWrapper
|
|
165
|
+
},
|
|
166
|
+
closable: !1,
|
|
167
|
+
destroyOnHidden: !0,
|
|
168
|
+
footer: null,
|
|
169
|
+
getContainer: f,
|
|
170
|
+
keyboard: !0,
|
|
171
|
+
mask: { closable: !0 },
|
|
172
|
+
onCancel: K,
|
|
173
|
+
open: h,
|
|
174
|
+
rootClassName: O.modalRoot,
|
|
175
|
+
title: null,
|
|
176
|
+
width: "100%",
|
|
177
|
+
zIndex: g,
|
|
178
|
+
children: /* @__PURE__ */ d("div", {
|
|
179
|
+
className: O.workbench,
|
|
180
|
+
children: [
|
|
181
|
+
/* @__PURE__ */ d("header", {
|
|
182
|
+
className: O.header,
|
|
183
|
+
children: [/* @__PURE__ */ d("div", {
|
|
184
|
+
className: O.headingGroup,
|
|
185
|
+
children: [
|
|
186
|
+
/* @__PURE__ */ u("h1", {
|
|
187
|
+
className: O.title,
|
|
188
|
+
children: N(o)
|
|
189
|
+
}),
|
|
190
|
+
/* @__PURE__ */ d("span", {
|
|
191
|
+
className: O.meta,
|
|
192
|
+
children: [
|
|
193
|
+
b?.title ?? "Demo 数据",
|
|
194
|
+
" · 交易 ID:",
|
|
195
|
+
b?.tradeId ?? v
|
|
196
|
+
]
|
|
197
|
+
}),
|
|
198
|
+
/* @__PURE__ */ u(i, { children: b?.statusLabel ?? "Demo" })
|
|
199
|
+
]
|
|
200
|
+
}), /* @__PURE__ */ u(t, {
|
|
201
|
+
"aria-label": "关闭交易工作台",
|
|
202
|
+
onClick: () => p("close-button"),
|
|
203
|
+
children: "关闭"
|
|
204
|
+
})]
|
|
205
|
+
}),
|
|
206
|
+
/* @__PURE__ */ d("main", {
|
|
207
|
+
className: O.workspaceScroller,
|
|
208
|
+
children: [
|
|
209
|
+
E && /* @__PURE__ */ d("div", {
|
|
210
|
+
className: O.statePane,
|
|
211
|
+
children: [/* @__PURE__ */ u(r, { size: "large" }), /* @__PURE__ */ u("span", { children: "正在加载交易工作台…" })]
|
|
212
|
+
}),
|
|
213
|
+
!E && w && /* @__PURE__ */ d("div", {
|
|
214
|
+
className: O.statePane,
|
|
215
|
+
children: [/* @__PURE__ */ u(e, {
|
|
216
|
+
description: w,
|
|
217
|
+
showIcon: !0,
|
|
218
|
+
title: "加载失败",
|
|
219
|
+
type: "error"
|
|
220
|
+
}), /* @__PURE__ */ u(t, {
|
|
221
|
+
"aria-label": "重试",
|
|
222
|
+
onClick: q,
|
|
223
|
+
type: "primary",
|
|
224
|
+
children: "重试"
|
|
225
|
+
})]
|
|
226
|
+
}),
|
|
227
|
+
!E && !w && b && /* @__PURE__ */ d("div", {
|
|
228
|
+
className: O.workspaceGrid,
|
|
229
|
+
children: [
|
|
230
|
+
/* @__PURE__ */ u(A, { drafts: b.drafts }),
|
|
231
|
+
/* @__PURE__ */ u(j, { sections: b.sections }),
|
|
232
|
+
/* @__PURE__ */ u(M, { statuses: b.statuses })
|
|
233
|
+
]
|
|
234
|
+
})
|
|
235
|
+
]
|
|
236
|
+
}),
|
|
237
|
+
/* @__PURE__ */ d("footer", {
|
|
238
|
+
className: O.footer,
|
|
239
|
+
children: [/* @__PURE__ */ u("span", {
|
|
240
|
+
className: O.actionMessage,
|
|
241
|
+
role: "status",
|
|
242
|
+
children: z
|
|
243
|
+
}), /* @__PURE__ */ u("div", {
|
|
244
|
+
className: O.actionScroller,
|
|
245
|
+
children: /* @__PURE__ */ d("div", {
|
|
246
|
+
className: O.actions,
|
|
247
|
+
children: [
|
|
248
|
+
/* @__PURE__ */ u(t, {
|
|
249
|
+
"aria-label": "取消",
|
|
250
|
+
onClick: () => p("cancel-button"),
|
|
251
|
+
children: "取消"
|
|
252
|
+
}),
|
|
253
|
+
/* @__PURE__ */ u(t, {
|
|
254
|
+
"aria-label": "风控试算",
|
|
255
|
+
disabled: y || E || !!w,
|
|
256
|
+
onClick: () => J("风控试算"),
|
|
257
|
+
children: "风控试算"
|
|
258
|
+
}),
|
|
259
|
+
/* @__PURE__ */ u(t, {
|
|
260
|
+
"aria-label": "试定价",
|
|
261
|
+
disabled: y || E || !!w,
|
|
262
|
+
onClick: () => J("试定价"),
|
|
263
|
+
children: "试定价"
|
|
264
|
+
}),
|
|
265
|
+
/* @__PURE__ */ u(t, {
|
|
266
|
+
"aria-label": "保存草稿",
|
|
267
|
+
disabled: y || E || !!w,
|
|
268
|
+
onClick: () => J("保存草稿"),
|
|
269
|
+
children: "保存草稿"
|
|
270
|
+
}),
|
|
271
|
+
/* @__PURE__ */ u(t, {
|
|
272
|
+
"aria-label": "提交",
|
|
273
|
+
disabled: y || E || !!w || !b,
|
|
274
|
+
loading: L,
|
|
275
|
+
onClick: async () => {
|
|
276
|
+
if (y || L) return;
|
|
277
|
+
G.current?.abort();
|
|
278
|
+
let e = new AbortController(), t = ++W.current;
|
|
279
|
+
G.current = e, R(!0), B("正在提交 Demo");
|
|
280
|
+
try {
|
|
281
|
+
let n = await C(_, v, e.signal);
|
|
282
|
+
if (e.signal.aborted || t !== W.current) return;
|
|
283
|
+
B("Demo 提交成功"), m?.(n), p("submitted");
|
|
284
|
+
} catch (n) {
|
|
285
|
+
!e.signal.aborted && t === W.current && B(`Demo 提交失败:${P(n)}`);
|
|
286
|
+
} finally {
|
|
287
|
+
!e.signal.aborted && t === W.current && (R(!1), G.current = void 0);
|
|
288
|
+
}
|
|
289
|
+
},
|
|
290
|
+
type: "primary",
|
|
291
|
+
children: "提交"
|
|
292
|
+
})
|
|
293
|
+
]
|
|
294
|
+
})
|
|
295
|
+
})]
|
|
296
|
+
})
|
|
297
|
+
]
|
|
298
|
+
})
|
|
299
|
+
});
|
|
300
|
+
};
|
|
301
|
+
//#endregion
|
|
302
|
+
export { I as TradeWorkbench, w as TradeWorkbenchConfigurationError, E as TradeWorkbenchProvider };
|
|
303
|
+
|
|
304
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/model/demo.ts","../src/api/demo.ts","../src/types/runtime.ts","../src/context/TradeWorkbenchProvider.tsx","../src/components/TradeWorkbench/index.module.less","../src/components/TradeWorkbench/index.tsx"],"sourcesContent":["export interface TradeWorkbenchDemoDraft {\n id: string;\n label: string;\n}\n\nexport interface TradeWorkbenchDemoField {\n label: string;\n value: string;\n}\n\nexport interface TradeWorkbenchDemoSection {\n key: 'basic' | 'trade' | 'contract';\n title: string;\n fields: readonly TradeWorkbenchDemoField[];\n}\n\nexport interface TradeWorkbenchDemoStatus {\n key: 'execution' | 'risk' | 'approval' | 'pricing';\n label: string;\n value: string;\n}\n\nexport interface TradeWorkbenchDemoData {\n tradeId: string;\n title: string;\n statusLabel: string;\n drafts: readonly TradeWorkbenchDemoDraft[];\n sections: readonly TradeWorkbenchDemoSection[];\n statuses: readonly TradeWorkbenchDemoStatus[];\n}\n\nconst isRecord = (value: unknown): value is Readonly<Record<string, unknown>> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nconst isStringEntry = (value: unknown, keys: readonly string[]): boolean =>\n isRecord(value) && keys.every((key) => typeof value[key] === 'string');\n\nconst isDemoDraft = (value: unknown): value is TradeWorkbenchDemoDraft =>\n isStringEntry(value, ['id', 'label']);\n\nconst isDemoField = (value: unknown): value is TradeWorkbenchDemoField =>\n isStringEntry(value, ['label', 'value']);\n\nconst isDemoSection = (value: unknown): value is TradeWorkbenchDemoSection => {\n if (\n !isRecord(value) ||\n !['basic', 'trade', 'contract'].includes(String(value.key)) ||\n typeof value.title !== 'string' ||\n !Array.isArray(value.fields)\n ) {\n return false;\n }\n\n return value.fields.every(isDemoField);\n};\n\nconst isDemoStatus = (value: unknown): value is TradeWorkbenchDemoStatus =>\n isStringEntry(value, ['key', 'label', 'value']) &&\n isRecord(value) &&\n ['execution', 'risk', 'approval', 'pricing'].includes(String(value.key));\n\nconst isTradeWorkbenchDemoData = (value: unknown): value is TradeWorkbenchDemoData =>\n isRecord(value) &&\n typeof value.tradeId === 'string' &&\n typeof value.title === 'string' &&\n typeof value.statusLabel === 'string' &&\n Array.isArray(value.drafts) &&\n Array.isArray(value.sections) &&\n Array.isArray(value.statuses) &&\n value.drafts.every(isDemoDraft) &&\n value.sections.every(isDemoSection) &&\n value.statuses.every(isDemoStatus);\n\n/**\n * 校验宿主 Transport 返回的交易工作台 Demo 数据。\n *\n * @remarks\n * Demo 响应不属于正式交易契约;结构不完整时立即失败,避免不可信数据直接进入组件渲染。\n *\n * @param value - Transport 返回的未知响应。\n * @returns 可供 MVP 弹窗展示的 Demo 数据。\n * @throws 当响应缺少必需字段或数组项结构不合法时抛出。\n */\nexport const parseTradeWorkbenchDemoData = (value: unknown): TradeWorkbenchDemoData => {\n if (!isTradeWorkbenchDemoData(value)) {\n throw new Error('交易工作台 Demo 响应结构无效');\n }\n\n return value;\n};\n\n/**\n * 校验 Demo 提交结果,仅向宿主返回稳定的交易标识。\n *\n * @param value - Transport 返回的未知提交响应。\n * @returns MVP 提交结果。\n * @throws 当响应不包含字符串 `tradeId` 时抛出。\n */\nexport const parseTradeWorkbenchSubmitResult = (value: unknown): { tradeId: string } => {\n if (!isRecord(value) || typeof value.tradeId !== 'string') {\n throw new Error('交易工作台 Demo 提交响应结构无效');\n }\n\n return { tradeId: value.tradeId };\n};\n","import {\n parseTradeWorkbenchDemoData,\n parseTradeWorkbenchSubmitResult,\n type TradeWorkbenchDemoData,\n} from '../model/demo';\nimport type { TradeWorkbenchSubmitResult } from '../types/component';\nimport type { TradeWorkbenchTransport } from '../types/transport';\n\nconst resolveDemoTradePath = (tradeId: string): string =>\n `/__trade-workbench-demo/trades/${encodeURIComponent(tradeId)}`;\n\n/**\n * 通过宿主注入的 Transport 加载交易工作台 MVP 展示数据。\n *\n * @remarks\n * 该接口仅用于技术验证,不连接真实交易服务;`signal` 会原样交给宿主请求实现。\n *\n * @param transport - 宿主注入的最小请求能力。\n * @param tradeId - 当前 Demo 交易标识。\n * @param signal - 用于取消当前加载请求的信号。\n * @returns 已完成结构校验的 Demo 数据。\n */\nexport const getTradeWorkbenchDemo = async (\n transport: TradeWorkbenchTransport,\n tradeId: string,\n signal: AbortSignal,\n): Promise<TradeWorkbenchDemoData> => {\n const response = await transport.request<unknown>({\n method: 'GET',\n path: resolveDemoTradePath(tradeId),\n signal,\n });\n\n return parseTradeWorkbenchDemoData(response);\n};\n\n/**\n * 通过宿主注入的 Transport 提交当前 MVP Demo。\n *\n * @remarks\n * 该请求仅验证提交编排、重复提交保护和宿主回调,不代表正式交易提交契约。\n *\n * @param transport - 宿主注入的最小请求能力。\n * @param tradeId - 当前 Demo 交易标识。\n * @param signal - 用于取消提交请求的信号。\n * @returns 只包含稳定交易标识的提交结果。\n */\nexport const submitTradeWorkbenchDemo = async (\n transport: TradeWorkbenchTransport,\n tradeId: string,\n signal: AbortSignal,\n): Promise<TradeWorkbenchSubmitResult> => {\n const response = await transport.request<unknown>({\n method: 'POST',\n path: `${resolveDemoTradePath(tradeId)}/submit`,\n signal,\n });\n\n return parseTradeWorkbenchSubmitResult(response);\n};\n","import type React from 'react';\nimport type { TradeWorkbenchTransport } from './transport';\n\nexport interface TradeWorkbenchProviderProps {\n children: React.ReactNode;\n transport: TradeWorkbenchTransport;\n onUnhandledError?: (error: unknown) => void;\n}\n\nexport interface TradeWorkbenchRuntime {\n transport: TradeWorkbenchTransport;\n onUnhandledError?: (error: unknown) => void;\n}\n\n/** 宿主未注入交易工作台运行环境时抛出的配置错误。 */\nexport class TradeWorkbenchConfigurationError extends Error {\n public constructor() {\n super(\n '[@guozhi-fe/oms-trade-workbench] 缺少 TradeWorkbenchProvider。请在宿主主题 Provider 内挂载 TradeWorkbenchProvider 并注入 transport。',\n );\n this.name = 'TradeWorkbenchConfigurationError';\n }\n}\n","import React, { createContext, useContext } from 'react';\nimport {\n TradeWorkbenchConfigurationError,\n type TradeWorkbenchProviderProps,\n type TradeWorkbenchRuntime,\n} from '../types/runtime';\n\nconst TradeWorkbenchRuntimeContext = createContext<TradeWorkbenchRuntime | undefined>(undefined);\n\n/**\n * 向交易工作台实例注入宿主请求能力与未处理错误回调。\n *\n * @remarks\n * Provider 只保存运行环境,不缓存任何交易或表单状态;`transport` 更新后,后续渲染读取新实例。\n */\nexport const TradeWorkbenchProvider: React.FC<TradeWorkbenchProviderProps> = (props) => {\n const { children, onUnhandledError, transport } = props;\n\n return (\n <TradeWorkbenchRuntimeContext.Provider value={{ onUnhandledError, transport }}>\n {children}\n </TradeWorkbenchRuntimeContext.Provider>\n );\n};\n\n/**\n * 读取当前交易工作台运行环境。\n *\n * @throws {@link TradeWorkbenchConfigurationError} 当宿主未挂载 `TradeWorkbenchProvider` 时抛出。\n */\nexport const useTradeWorkbenchRuntime = (): TradeWorkbenchRuntime => {\n const runtime = useContext(TradeWorkbenchRuntimeContext);\n\n if (!runtime) {\n throw new TradeWorkbenchConfigurationError();\n }\n\n return runtime;\n};\n",".modalRoot {\n color: var(--gz-color-text);\n}\n\n.modalWrapper {\n padding: calc(var(--gz-padding, 16) * 1px);\n overflow: hidden;\n}\n\n.modalContainer {\n top: 0;\n max-width: none;\n height: calc(100dvh - calc(var(--gz-padding, 16) * 2px));\n padding: 0;\n overflow: hidden;\n background: var(--gz-color-bg-container);\n border: 1px solid var(--gz-color-border-secondary);\n border-radius: calc(var(--gz-border-radius-lg, 8) * 1px);\n}\n\n.modalBody {\n height: 100%;\n}\n\n.workbench {\n display: flex;\n flex-direction: column;\n width: 100%;\n min-width: 0;\n height: 100%;\n min-height: 0;\n color: var(--gz-color-text);\n background: var(--gz-color-bg-layout);\n}\n\n.header,\n.footer {\n display: flex;\n flex: none;\n align-items: center;\n justify-content: space-between;\n min-width: 0;\n padding: calc(var(--gz-padding-sm, 12) * 1px) calc(var(--gz-padding, 16) * 1px);\n background: var(--gz-color-bg-container);\n}\n\n.header {\n gap: calc(var(--gz-margin-sm, 12) * 1px);\n border-bottom: 1px solid var(--gz-color-border-secondary);\n}\n\n.headingGroup {\n display: flex;\n gap: calc(var(--gz-margin-sm, 12) * 1px);\n align-items: center;\n min-width: 0;\n}\n\n.title,\n.columnTitle,\n.sectionTitle {\n margin: 0;\n font-weight: var(--gz-font-weight-strong, 600);\n color: var(--gz-color-text);\n}\n\n.title {\n font-size: calc(var(--gz-font-size-heading-4, 20) * 1px);\n white-space: nowrap;\n}\n\n.meta {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n color: var(--gz-color-text-secondary);\n white-space: nowrap;\n}\n\n.workspaceScroller {\n flex: 1;\n min-width: 0;\n min-height: 0;\n overflow: auto;\n}\n\n.workspaceGrid {\n display: grid;\n grid-template-columns: minmax(180px, 220px) minmax(520px, 1fr) minmax(240px, 300px);\n gap: calc(var(--gz-margin-sm, 12) * 1px);\n min-width: 1020px;\n min-height: 100%;\n padding: calc(var(--gz-padding-sm, 12) * 1px);\n}\n\n.draftColumn,\n.detailColumn,\n.statusColumn {\n min-width: 0;\n min-height: 0;\n}\n\n.draftColumn,\n.statusColumn,\n.sectionCard {\n padding: calc(var(--gz-padding-sm, 12) * 1px);\n background: var(--gz-color-bg-container);\n border: 1px solid var(--gz-color-border-secondary);\n border-radius: calc(var(--gz-border-radius, 6) * 1px);\n}\n\n.columnTitle,\n.sectionTitle {\n margin-bottom: calc(var(--gz-margin-sm, 12) * 1px);\n font-size: calc(var(--gz-font-size-lg, 16) * 1px);\n}\n\n.draftList,\n.statusList,\n.detailColumn {\n display: flex;\n flex-direction: column;\n gap: calc(var(--gz-margin-sm, 12) * 1px);\n}\n\n.draftButton {\n overflow: hidden;\n text-overflow: ellipsis;\n text-align: left;\n white-space: nowrap;\n}\n\n.fieldGrid {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: calc(var(--gz-margin-sm, 12) * 1px);\n margin: 0;\n}\n\n.fieldItem {\n min-width: 0;\n padding: calc(var(--gz-padding-xs, 8) * 1px);\n background: var(--gz-color-fill-tertiary);\n border-radius: calc(var(--gz-border-radius-sm, 4) * 1px);\n\n dt {\n margin-bottom: calc(var(--gz-margin-xxs, 4) * 1px);\n color: var(--gz-color-text-secondary);\n }\n\n dd {\n margin: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n color: var(--gz-color-text);\n white-space: nowrap;\n }\n}\n\n.statusItem {\n display: flex;\n gap: calc(var(--gz-margin-xs, 8) * 1px);\n align-items: center;\n justify-content: space-between;\n padding-bottom: calc(var(--gz-padding-xs, 8) * 1px);\n border-bottom: 1px solid var(--gz-color-border-secondary);\n}\n\n.statePane {\n display: flex;\n flex-direction: column;\n gap: calc(var(--gz-margin, 16) * 1px);\n align-items: center;\n justify-content: center;\n min-width: 320px;\n min-height: 100%;\n padding: calc(var(--gz-padding-lg, 24) * 1px);\n color: var(--gz-color-text-secondary);\n}\n\n.footer {\n gap: calc(var(--gz-margin-sm, 12) * 1px);\n border-top: 1px solid var(--gz-color-border-secondary);\n}\n\n.actionMessage {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n color: var(--gz-color-text-secondary);\n white-space: nowrap;\n}\n\n.actionScroller {\n min-width: 0;\n overflow-x: auto;\n}\n\n.actions {\n display: flex;\n gap: calc(var(--gz-margin-xs, 8) * 1px);\n width: max-content;\n min-width: max-content;\n}\n\n@media (width <= 720px) {\n .modalWrapper {\n padding: calc(var(--gz-padding-xs, 8) * 1px);\n }\n\n .modalContainer {\n height: calc(100dvh - calc(var(--gz-padding-xs, 8) * 2px));\n }\n\n .headingGroup {\n gap: calc(var(--gz-margin-xs, 8) * 1px);\n }\n\n .meta {\n display: none;\n }\n\n .footer {\n flex-direction: column;\n align-items: stretch;\n }\n}\n","import { Alert, Button, Modal, Spin, Tag } from '@chenhui996/gg-ui';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { getTradeWorkbenchDemo, submitTradeWorkbenchDemo } from '../../api/demo';\nimport { useTradeWorkbenchRuntime } from '../../context/TradeWorkbenchProvider';\nimport type {\n TradeWorkbenchDemoData,\n TradeWorkbenchDemoDraft,\n TradeWorkbenchDemoSection,\n TradeWorkbenchDemoStatus,\n} from '../../model/demo';\nimport type {\n TradeWorkbenchCloseReason,\n TradeWorkbenchEntry,\n TradeWorkbenchProps,\n} from '../../types/component';\nimport styles from './index.module.less';\n\nconst CREATE_DEMO_TRADE_ID = 'DEMO-CREATE';\n\ninterface DraftListProps {\n drafts: readonly TradeWorkbenchDemoDraft[];\n}\n\nconst DraftList: React.FC<DraftListProps> = (props) => {\n const { drafts } = props;\n\n return (\n <aside className={styles.draftColumn} aria-label=\"Demo 草稿列表\">\n <h2 className={styles.columnTitle}>草稿列表</h2>\n <div className={styles.draftList}>\n {drafts.map((draft, index) => (\n <Button\n block\n className={styles.draftButton}\n key={draft.id}\n type={index === 0 ? 'primary' : 'text'}\n >\n {draft.label}\n </Button>\n ))}\n </div>\n </aside>\n );\n};\n\ninterface DetailSectionsProps {\n sections: readonly TradeWorkbenchDemoSection[];\n}\n\nconst DetailSections: React.FC<DetailSectionsProps> = (props) => {\n const { sections } = props;\n\n return (\n <div className={styles.detailColumn} aria-label=\"Demo 交易结构区\">\n {sections.map((section) => (\n <section className={styles.sectionCard} key={section.key}>\n <h2 className={styles.sectionTitle}>{section.title}</h2>\n <dl className={styles.fieldGrid}>\n {section.fields.map((field) => (\n <div className={styles.fieldItem} key={`${section.key}-${field.label}`}>\n <dt>{field.label}</dt>\n <dd>{field.value}</dd>\n </div>\n ))}\n </dl>\n </section>\n ))}\n </div>\n );\n};\n\ninterface StatusSummaryProps {\n statuses: readonly TradeWorkbenchDemoStatus[];\n}\n\nconst StatusSummary: React.FC<StatusSummaryProps> = (props) => {\n const { statuses } = props;\n\n return (\n <aside className={styles.statusColumn} aria-label=\"Demo 执行与风控状态\">\n <h2 className={styles.columnTitle}>执行与风控</h2>\n <div className={styles.statusList}>\n {statuses.map((status) => (\n <div className={styles.statusItem} key={status.key}>\n <span>{status.label}</span>\n <Tag>{status.value}</Tag>\n </div>\n ))}\n </div>\n </aside>\n );\n};\n\nconst getEntryTitle = (entry: TradeWorkbenchEntry): string => {\n if (entry.mode === 'create') {\n return '新建交易';\n }\n\n return entry.mode === 'edit' ? '编辑交易' : '查看交易';\n};\n\nconst getErrorMessage = (error: unknown): string =>\n error instanceof Error ? error.message : '未知错误';\n\nconst getModalCloseReason = (\n event: React.MouseEvent<HTMLButtonElement> | React.KeyboardEvent<HTMLElement>,\n): TradeWorkbenchCloseReason => (event.type === 'keydown' ? 'escape' : 'mask');\n\n/**\n * 渲染由宿主控制开关状态的交易工作台 MVP 全屏弹窗。\n *\n * @remarks\n * 组件在打开或入口变化时加载 Demo 数据,并取消上一轮加载或提交请求;旧响应不会覆盖新入口。\n * 创建、编辑和只读入口只验证技术契约,不代表正式交易流程或字段定义。\n */\nexport const TradeWorkbench: React.FC<TradeWorkbenchProps> = (props) => {\n const { entry, getContainer, onRequestClose, onSubmitted, open, zIndex } = props;\n const { transport } = useTradeWorkbenchRuntime();\n const demoTradeId = entry.mode === 'create' ? CREATE_DEMO_TRADE_ID : entry.tradeId;\n const readOnly = entry.mode === 'view';\n const [data, setData] = useState<TradeWorkbenchDemoData>();\n const [loadError, setLoadError] = useState<string>();\n const [isLoading, setIsLoading] = useState(false);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [actionMessage, setActionMessage] = useState('等待操作');\n const [reloadVersion, setReloadVersion] = useState(0);\n const loadVersionRef = useRef(0);\n const submitVersionRef = useRef(0);\n const submitControllerRef = useRef<AbortController | undefined>(undefined);\n\n useEffect(() => {\n if (!open) {\n return;\n }\n\n const controller = new AbortController();\n const requestVersion = ++loadVersionRef.current;\n setData(undefined);\n setLoadError(undefined);\n setIsLoading(true);\n setActionMessage('正在加载 Demo 数据');\n\n getTradeWorkbenchDemo(transport, demoTradeId, controller.signal)\n .then((response) => {\n if (controller.signal.aborted || requestVersion !== loadVersionRef.current) {\n return;\n }\n\n setData(response);\n setActionMessage('Demo 数据已加载');\n })\n .catch((error: unknown) => {\n if (controller.signal.aborted || requestVersion !== loadVersionRef.current) {\n return;\n }\n\n setLoadError(getErrorMessage(error));\n setActionMessage('Demo 数据加载失败');\n })\n .finally(() => {\n if (!controller.signal.aborted && requestVersion === loadVersionRef.current) {\n setIsLoading(false);\n }\n });\n\n return () => {\n controller.abort();\n };\n }, [demoTradeId, open, reloadVersion, transport]);\n\n useEffect(() => {\n return () => {\n submitVersionRef.current += 1;\n submitControllerRef.current?.abort();\n submitControllerRef.current = undefined;\n };\n }, [demoTradeId, open]);\n\n const handleModalCancel = (\n event: React.MouseEvent<HTMLButtonElement> | React.KeyboardEvent<HTMLElement>,\n ): void => {\n onRequestClose(getModalCloseReason(event));\n };\n\n const handleRetry = (): void => {\n setReloadVersion((version) => version + 1);\n };\n\n const handleDemoAction = (action: string): void => {\n setActionMessage(`${action}仅用于验证交互状态,MVP 未连接真实接口`);\n };\n\n const handleSubmit = async (): Promise<void> => {\n if (readOnly || isSubmitting) {\n return;\n }\n\n submitControllerRef.current?.abort();\n const controller = new AbortController();\n const requestVersion = ++submitVersionRef.current;\n submitControllerRef.current = controller;\n setIsSubmitting(true);\n setActionMessage('正在提交 Demo');\n\n try {\n const result = await submitTradeWorkbenchDemo(transport, demoTradeId, controller.signal);\n if (controller.signal.aborted || requestVersion !== submitVersionRef.current) {\n return;\n }\n\n setActionMessage('Demo 提交成功');\n onSubmitted?.(result);\n onRequestClose('submitted');\n } catch (error: unknown) {\n if (!controller.signal.aborted && requestVersion === submitVersionRef.current) {\n setActionMessage(`Demo 提交失败:${getErrorMessage(error)}`);\n }\n } finally {\n if (!controller.signal.aborted && requestVersion === submitVersionRef.current) {\n setIsSubmitting(false);\n submitControllerRef.current = undefined;\n }\n }\n };\n\n return (\n <Modal\n classNames={{\n body: styles.modalBody,\n container: styles.modalContainer,\n wrapper: styles.modalWrapper,\n }}\n closable={false}\n destroyOnHidden\n footer={null}\n getContainer={getContainer}\n keyboard\n mask={{ closable: true }}\n onCancel={handleModalCancel}\n open={open}\n rootClassName={styles.modalRoot}\n title={null}\n width=\"100%\"\n zIndex={zIndex}\n >\n <div className={styles.workbench}>\n <header className={styles.header}>\n <div className={styles.headingGroup}>\n <h1 className={styles.title}>{getEntryTitle(entry)}</h1>\n <span className={styles.meta}>\n {data?.title ?? 'Demo 数据'} · 交易 ID:{data?.tradeId ?? demoTradeId}\n </span>\n <Tag>{data?.statusLabel ?? 'Demo'}</Tag>\n </div>\n <Button aria-label=\"关闭交易工作台\" onClick={() => onRequestClose('close-button')}>\n 关闭\n </Button>\n </header>\n\n <main className={styles.workspaceScroller}>\n {isLoading && (\n <div className={styles.statePane}>\n <Spin size=\"large\" />\n <span>正在加载交易工作台…</span>\n </div>\n )}\n\n {!isLoading && loadError && (\n <div className={styles.statePane}>\n <Alert description={loadError} showIcon title=\"加载失败\" type=\"error\" />\n <Button aria-label=\"重试\" onClick={handleRetry} type=\"primary\">\n 重试\n </Button>\n </div>\n )}\n\n {!isLoading && !loadError && data && (\n <div className={styles.workspaceGrid}>\n <DraftList drafts={data.drafts} />\n <DetailSections sections={data.sections} />\n <StatusSummary statuses={data.statuses} />\n </div>\n )}\n </main>\n\n <footer className={styles.footer}>\n <span className={styles.actionMessage} role=\"status\">\n {actionMessage}\n </span>\n <div className={styles.actionScroller}>\n <div className={styles.actions}>\n <Button aria-label=\"取消\" onClick={() => onRequestClose('cancel-button')}>\n 取消\n </Button>\n <Button\n aria-label=\"风控试算\"\n disabled={readOnly || isLoading || Boolean(loadError)}\n onClick={() => handleDemoAction('风控试算')}\n >\n 风控试算\n </Button>\n <Button\n aria-label=\"试定价\"\n disabled={readOnly || isLoading || Boolean(loadError)}\n onClick={() => handleDemoAction('试定价')}\n >\n 试定价\n </Button>\n <Button\n aria-label=\"保存草稿\"\n disabled={readOnly || isLoading || Boolean(loadError)}\n onClick={() => handleDemoAction('保存草稿')}\n >\n 保存草稿\n </Button>\n <Button\n aria-label=\"提交\"\n disabled={readOnly || isLoading || Boolean(loadError) || !data}\n loading={isSubmitting}\n onClick={handleSubmit}\n type=\"primary\"\n >\n 提交\n </Button>\n </div>\n </div>\n </footer>\n </div>\n </Modal>\n );\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export interface TradeWorkbenchDemoDraft {
|
|
2
|
+
id: string;
|
|
3
|
+
label: string;
|
|
4
|
+
}
|
|
5
|
+
export interface TradeWorkbenchDemoField {
|
|
6
|
+
label: string;
|
|
7
|
+
value: string;
|
|
8
|
+
}
|
|
9
|
+
export interface TradeWorkbenchDemoSection {
|
|
10
|
+
key: 'basic' | 'trade' | 'contract';
|
|
11
|
+
title: string;
|
|
12
|
+
fields: readonly TradeWorkbenchDemoField[];
|
|
13
|
+
}
|
|
14
|
+
export interface TradeWorkbenchDemoStatus {
|
|
15
|
+
key: 'execution' | 'risk' | 'approval' | 'pricing';
|
|
16
|
+
label: string;
|
|
17
|
+
value: string;
|
|
18
|
+
}
|
|
19
|
+
export interface TradeWorkbenchDemoData {
|
|
20
|
+
tradeId: string;
|
|
21
|
+
title: string;
|
|
22
|
+
statusLabel: string;
|
|
23
|
+
drafts: readonly TradeWorkbenchDemoDraft[];
|
|
24
|
+
sections: readonly TradeWorkbenchDemoSection[];
|
|
25
|
+
statuses: readonly TradeWorkbenchDemoStatus[];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 校验宿主 Transport 返回的交易工作台 Demo 数据。
|
|
29
|
+
*
|
|
30
|
+
* @remarks
|
|
31
|
+
* Demo 响应不属于正式交易契约;结构不完整时立即失败,避免不可信数据直接进入组件渲染。
|
|
32
|
+
*
|
|
33
|
+
* @param value - Transport 返回的未知响应。
|
|
34
|
+
* @returns 可供 MVP 弹窗展示的 Demo 数据。
|
|
35
|
+
* @throws 当响应缺少必需字段或数组项结构不合法时抛出。
|
|
36
|
+
*/
|
|
37
|
+
export declare const parseTradeWorkbenchDemoData: (value: unknown) => TradeWorkbenchDemoData;
|
|
38
|
+
/**
|
|
39
|
+
* 校验 Demo 提交结果,仅向宿主返回稳定的交易标识。
|
|
40
|
+
*
|
|
41
|
+
* @param value - Transport 返回的未知提交响应。
|
|
42
|
+
* @returns MVP 提交结果。
|
|
43
|
+
* @throws 当响应不包含字符串 `tradeId` 时抛出。
|
|
44
|
+
*/
|
|
45
|
+
export declare const parseTradeWorkbenchSubmitResult: (value: unknown) => {
|
|
46
|
+
tradeId: string;
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=demo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demo.d.ts","sourceRoot":"","sources":["../../src/model/demo.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,yBAAyB;IACxC,GAAG,EAAE,OAAO,GAAG,OAAO,GAAG,UAAU,CAAC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,SAAS,uBAAuB,EAAE,CAAC;CAC5C;AAED,MAAM,WAAW,wBAAwB;IACvC,GAAG,EAAE,WAAW,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;IACnD,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,SAAS,uBAAuB,EAAE,CAAC;IAC3C,QAAQ,EAAE,SAAS,yBAAyB,EAAE,CAAC;IAC/C,QAAQ,EAAE,SAAS,wBAAwB,EAAE,CAAC;CAC/C;AA4CD;;;;;;;;;GASG;AACH,eAAO,MAAM,2BAA2B,GAAI,OAAO,OAAO,KAAG,sBAM5D,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,+BAA+B,GAAI,OAAO,OAAO,KAAG;IAAE,OAAO,EAAE,MAAM,CAAA;CAMjF,CAAC"}
|
package/dist/style.css
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
._modalRoot_4fozy_1{color:var(--gz-color-text)}._modalWrapper_4fozy_4{padding:calc(var(--gz-padding,16) * 1px);overflow:hidden}._modalContainer_4fozy_8{max-width:none;height:calc(100dvh - calc(var(--gz-padding,16) * 2px));background:var(--gz-color-bg-container);border:1px solid var(--gz-color-border-secondary);border-radius:calc(var(--gz-border-radius-lg,8) * 1px);padding:0;top:0;overflow:hidden}._modalBody_4fozy_18{height:100%}._workbench_4fozy_21{width:100%;min-width:0;height:100%;min-height:0;color:var(--gz-color-text);background:var(--gz-color-bg-layout);flex-direction:column;display:flex}._header_4fozy_31,._footer_4fozy_32{min-width:0;padding:calc(var(--gz-padding-sm,12) * 1px) calc(var(--gz-padding,16) * 1px);background:var(--gz-color-bg-container);flex:none;justify-content:space-between;align-items:center;display:flex}._header_4fozy_31{gap:calc(var(--gz-margin-sm,12) * 1px);border-bottom:1px solid var(--gz-color-border-secondary)}._headingGroup_4fozy_45{gap:calc(var(--gz-margin-sm,12) * 1px);align-items:center;min-width:0;display:flex}._title_4fozy_51,._columnTitle_4fozy_52,._sectionTitle_4fozy_53{font-weight:var(--gz-font-weight-strong,600);color:var(--gz-color-text);margin:0}._title_4fozy_51{font-size:calc(var(--gz-font-size-heading-4,20) * 1px);white-space:nowrap}._meta_4fozy_62{text-overflow:ellipsis;min-width:0;color:var(--gz-color-text-secondary);white-space:nowrap;overflow:hidden}._workspaceScroller_4fozy_69{flex:1;min-width:0;min-height:0;overflow:auto}._workspaceGrid_4fozy_75{gap:calc(var(--gz-margin-sm,12) * 1px);min-width:1020px;min-height:100%;padding:calc(var(--gz-padding-sm,12) * 1px);grid-template-columns:minmax(180px,220px) minmax(520px,1fr) minmax(240px,300px);display:grid}._draftColumn_4fozy_83,._detailColumn_4fozy_84,._statusColumn_4fozy_85{min-width:0;min-height:0}._draftColumn_4fozy_83,._statusColumn_4fozy_85,._sectionCard_4fozy_91{padding:calc(var(--gz-padding-sm,12) * 1px);background:var(--gz-color-bg-container);border:1px solid var(--gz-color-border-secondary);border-radius:calc(var(--gz-border-radius,6) * 1px)}._columnTitle_4fozy_52,._sectionTitle_4fozy_53{margin-bottom:calc(var(--gz-margin-sm,12) * 1px);font-size:calc(var(--gz-font-size-lg,16) * 1px)}._draftList_4fozy_102,._statusList_4fozy_103,._detailColumn_4fozy_84{gap:calc(var(--gz-margin-sm,12) * 1px);flex-direction:column;display:flex}._draftButton_4fozy_109{text-overflow:ellipsis;text-align:left;white-space:nowrap;overflow:hidden}._fieldGrid_4fozy_115{gap:calc(var(--gz-margin-sm,12) * 1px);grid-template-columns:repeat(2,minmax(0,1fr));margin:0;display:grid}._fieldItem_4fozy_121{min-width:0;padding:calc(var(--gz-padding-xs,8) * 1px);background:var(--gz-color-fill-tertiary);border-radius:calc(var(--gz-border-radius-sm,4) * 1px)}._fieldItem_4fozy_121 dt{margin-bottom:calc(var(--gz-margin-xxs,4) * 1px);color:var(--gz-color-text-secondary)}._fieldItem_4fozy_121 dd{text-overflow:ellipsis;color:var(--gz-color-text);white-space:nowrap;margin:0;overflow:hidden}._statusItem_4fozy_138{gap:calc(var(--gz-margin-xs,8) * 1px);padding-bottom:calc(var(--gz-padding-xs,8) * 1px);border-bottom:1px solid var(--gz-color-border-secondary);justify-content:space-between;align-items:center;display:flex}._statePane_4fozy_146{gap:calc(var(--gz-margin,16) * 1px);min-width:320px;min-height:100%;padding:calc(var(--gz-padding-lg,24) * 1px);color:var(--gz-color-text-secondary);flex-direction:column;justify-content:center;align-items:center;display:flex}._footer_4fozy_32{gap:calc(var(--gz-margin-sm,12) * 1px);border-top:1px solid var(--gz-color-border-secondary)}._actionMessage_4fozy_161{text-overflow:ellipsis;min-width:0;color:var(--gz-color-text-secondary);white-space:nowrap;overflow:hidden}._actionScroller_4fozy_168{min-width:0;overflow-x:auto}._actions_4fozy_172{gap:calc(var(--gz-margin-xs,8) * 1px);width:max-content;min-width:max-content;display:flex}@media (width<=720px){._modalWrapper_4fozy_4{padding:calc(var(--gz-padding-xs,8) * 1px)}._modalContainer_4fozy_8{height:calc(100dvh - calc(var(--gz-padding-xs,8) * 2px))}._headingGroup_4fozy_45{gap:calc(var(--gz-margin-xs,8) * 1px)}._meta_4fozy_62{display:none}._footer_4fozy_32{flex-direction:column;align-items:stretch}}
|
|
2
|
+
/*$vite$:1*/
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type TradeWorkbenchEntry = {
|
|
2
|
+
mode: 'create';
|
|
3
|
+
tradeId?: never;
|
|
4
|
+
} | {
|
|
5
|
+
mode: 'edit' | 'view';
|
|
6
|
+
tradeId: string;
|
|
7
|
+
};
|
|
8
|
+
export type TradeWorkbenchCloseReason = 'close-button' | 'cancel-button' | 'escape' | 'mask' | 'submitted';
|
|
9
|
+
export interface TradeWorkbenchSubmitResult {
|
|
10
|
+
tradeId: string;
|
|
11
|
+
}
|
|
12
|
+
export interface TradeWorkbenchProps {
|
|
13
|
+
open: boolean;
|
|
14
|
+
entry: TradeWorkbenchEntry;
|
|
15
|
+
getContainer?: HTMLElement | (() => HTMLElement) | false;
|
|
16
|
+
zIndex?: number;
|
|
17
|
+
onRequestClose: (reason: TradeWorkbenchCloseReason) => void;
|
|
18
|
+
onSubmitted?: (result: TradeWorkbenchSubmitResult) => void;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=component.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../../src/types/component.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,mBAAmB,GAC3B;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,CAAC,EAAE,KAAK,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/C,MAAM,MAAM,yBAAyB,GACjC,cAAc,GACd,eAAe,GACf,QAAQ,GACR,MAAM,GACN,WAAW,CAAC;AAEhB,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,mBAAmB,CAAC;IAC3B,YAAY,CAAC,EAAE,WAAW,GAAG,CAAC,MAAM,WAAW,CAAC,GAAG,KAAK,CAAC;IACzD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,CAAC,MAAM,EAAE,yBAAyB,KAAK,IAAI,CAAC;IAC5D,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,0BAA0B,KAAK,IAAI,CAAC;CAC5D"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import type { TradeWorkbenchTransport } from './transport';
|
|
3
|
+
export interface TradeWorkbenchProviderProps {
|
|
4
|
+
children: React.ReactNode;
|
|
5
|
+
transport: TradeWorkbenchTransport;
|
|
6
|
+
onUnhandledError?: (error: unknown) => void;
|
|
7
|
+
}
|
|
8
|
+
export interface TradeWorkbenchRuntime {
|
|
9
|
+
transport: TradeWorkbenchTransport;
|
|
10
|
+
onUnhandledError?: (error: unknown) => void;
|
|
11
|
+
}
|
|
12
|
+
/** 宿主未注入交易工作台运行环境时抛出的配置错误。 */
|
|
13
|
+
export declare class TradeWorkbenchConfigurationError extends Error {
|
|
14
|
+
constructor();
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/types/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAE3D,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,SAAS,EAAE,uBAAuB,CAAC;IACnC,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CAC7C;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,uBAAuB,CAAC;IACnC,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CAC7C;AAED,8BAA8B;AAC9B,qBAAa,gCAAiC,SAAQ,KAAK;;CAO1D"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type TradeWorkbenchHttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
|
|
2
|
+
export type TradeWorkbenchQueryValue = string | number | boolean | null | readonly string[] | readonly number[];
|
|
3
|
+
export interface TradeWorkbenchRequestConfig<TBody = unknown> {
|
|
4
|
+
path: string;
|
|
5
|
+
method: TradeWorkbenchHttpMethod;
|
|
6
|
+
query?: Readonly<Record<string, TradeWorkbenchQueryValue>>;
|
|
7
|
+
body?: TBody;
|
|
8
|
+
headers?: Readonly<Record<string, string>>;
|
|
9
|
+
signal?: AbortSignal;
|
|
10
|
+
}
|
|
11
|
+
export interface TradeWorkbenchTransport {
|
|
12
|
+
request<TResponse, TBody = unknown>(config: TradeWorkbenchRequestConfig<TBody>): Promise<TResponse>;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/types/transport.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,wBAAwB,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;AAEzE,MAAM,MAAM,wBAAwB,GAChC,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,SAAS,MAAM,EAAE,GACjB,SAAS,MAAM,EAAE,CAAC;AAEtB,MAAM,WAAW,2BAA2B,CAAC,KAAK,GAAG,OAAO;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,wBAAwB,CAAC;IACjC,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC,CAAC;IAC3D,IAAI,CAAC,EAAE,KAAK,CAAC;IACb,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3C,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,uBAAuB;IACtC,OAAO,CAAC,SAAS,EAAE,KAAK,GAAG,OAAO,EAChC,MAAM,EAAE,2BAA2B,CAAC,KAAK,CAAC,GACzC,OAAO,CAAC,SAAS,CAAC,CAAC;CACvB"}
|
package/package.json
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@guozhi-fe/oms-trade-workbench",
|
|
3
|
+
"version": "0.1.0-alpha.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "Host-integrated React trade workbench modal for GuoZhi OMS applications.",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"trade",
|
|
8
|
+
"workbench",
|
|
9
|
+
"react",
|
|
10
|
+
"modal",
|
|
11
|
+
"oms"
|
|
12
|
+
],
|
|
13
|
+
"homepage": "https://github.com/chenhui996/oms-web/tree/main/packages/trade-workbench#readme",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/chenhui996/oms-web/issues"
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/chenhui996/oms-web.git",
|
|
20
|
+
"directory": "packages/trade-workbench"
|
|
21
|
+
},
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"sideEffects": [
|
|
24
|
+
"**/*.css",
|
|
25
|
+
"**/*.less"
|
|
26
|
+
],
|
|
27
|
+
"type": "module",
|
|
28
|
+
"exports": {
|
|
29
|
+
".": {
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"import": "./dist/index.js",
|
|
32
|
+
"require": "./dist/index.cjs"
|
|
33
|
+
},
|
|
34
|
+
"./style.css": "./dist/style.css"
|
|
35
|
+
},
|
|
36
|
+
"main": "./dist/index.cjs",
|
|
37
|
+
"module": "./dist/index.js",
|
|
38
|
+
"types": "./dist/index.d.ts",
|
|
39
|
+
"files": [
|
|
40
|
+
"dist",
|
|
41
|
+
"README.md",
|
|
42
|
+
"LICENSE"
|
|
43
|
+
],
|
|
44
|
+
"scripts": {
|
|
45
|
+
"build": "vite build && tsc -p tsconfig.build.json",
|
|
46
|
+
"dev": "vite build --watch",
|
|
47
|
+
"lint": "eslint src vite.config.ts",
|
|
48
|
+
"lint:style": "stylelint \"src/**/*.{css,less}\"",
|
|
49
|
+
"prepack": "npm run verify",
|
|
50
|
+
"test": "vitest run",
|
|
51
|
+
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
52
|
+
"verify": "npm run lint && npm run lint:style && npm run typecheck && npm run test && npm run build"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@chenhui996/gg-ui": "0.2.0",
|
|
56
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
57
|
+
"@testing-library/react": "^16.3.2",
|
|
58
|
+
"@types/react": "^19.2.14",
|
|
59
|
+
"@types/react-dom": "^19.2.3",
|
|
60
|
+
"@vitejs/plugin-react": "^6.0.0",
|
|
61
|
+
"antd": "^6.3.3",
|
|
62
|
+
"jsdom": "^29.0.2",
|
|
63
|
+
"less": "^4.6.4",
|
|
64
|
+
"react": "^19.2.4",
|
|
65
|
+
"react-dom": "^19.2.4",
|
|
66
|
+
"stylelint": "^17.14.1",
|
|
67
|
+
"typescript": "~5.9.3",
|
|
68
|
+
"vite": "^8.1.5",
|
|
69
|
+
"vitest": "^4.1.4"
|
|
70
|
+
},
|
|
71
|
+
"peerDependencies": {
|
|
72
|
+
"@chenhui996/gg-ui": "0.2.0",
|
|
73
|
+
"antd": ">=6.3.3 <7",
|
|
74
|
+
"react": ">=19.2.4 <20",
|
|
75
|
+
"react-dom": ">=19.2.4 <20"
|
|
76
|
+
},
|
|
77
|
+
"engines": {
|
|
78
|
+
"node": ">=20.19.0"
|
|
79
|
+
},
|
|
80
|
+
"publishConfig": {
|
|
81
|
+
"access": "public",
|
|
82
|
+
"registry": "https://registry.npmjs.org/"
|
|
83
|
+
}
|
|
84
|
+
}
|