@yuku123/z-frontend-common 0.2.9 → 1.0.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.
Files changed (57) hide show
  1. package/LICENSE +25 -0
  2. package/README.md +55 -42
  3. package/dist/index.js +1 -0
  4. package/package.json +49 -44
  5. package/src/components/ErrorBoundary/index.jsx +24 -77
  6. package/src/components/Layout/index.jsx +141 -38
  7. package/src/components/LoginPage/index.jsx +47 -21
  8. package/src/components/StatusTag/index.jsx +14 -12
  9. package/src/index.js +32 -38
  10. package/src/services/request.js +74 -4
  11. package/dist/z-frontend-common.css +0 -1
  12. package/dist/z-frontend-common.es.js +0 -51275
  13. package/dist/z-frontend-common.umd.js +0 -459
  14. package/src/components/Ctc/Layout.jsx +0 -330
  15. package/src/components/Ctc/Layout.module.css +0 -145
  16. package/src/components/Ctc/agentTeam/index.tsx +0 -308
  17. package/src/components/Ctc/login/AuthPage.module.css +0 -26
  18. package/src/components/Ctc/login/AuthPage.tsx +0 -235
  19. package/src/components/Ctc/login/index.less +0 -49
  20. package/src/components/Ctc/login/index.tsx +0 -142
  21. package/src/components/Ctc/uc/UCLogin.tsx +0 -31
  22. package/src/components/Ctc/uc/UCPhoneLogin.tsx +0 -62
  23. package/src/components/Ctc/uc/UCRegister.tsx +0 -37
  24. package/src/components/Ctc/uc/UCResetPassword.tsx +0 -69
  25. package/src/components/Ctc/uc/index.tsx +0 -15
  26. package/src/components/Ctc/userPanel/index.tsx +0 -999
  27. package/src/components/Ctc/webide/index.tsx +0 -272
  28. package/src/components/LowCode/LowCodeModel.jsx +0 -962
  29. package/src/components/LowCode/LowCodePage.jsx +0 -31
  30. package/src/components/LowCode/LowCodeRuntime.jsx +0 -335
  31. package/src/components/LowCode/MaterializePage.jsx +0 -235
  32. package/src/components/LowCode/index.js +0 -1
  33. package/src/components/MockPlatform/CurlImportModal.jsx +0 -362
  34. package/src/components/MockPlatform/EndpointsTab.jsx +0 -509
  35. package/src/components/MockPlatform/EnvironmentsTab.jsx +0 -212
  36. package/src/components/MockPlatform/MockTemplateHelper.jsx +0 -200
  37. package/src/components/MockPlatform/OpenApiImportModal.jsx +0 -305
  38. package/src/components/MockPlatform/RecordingsTab.jsx +0 -397
  39. package/src/components/MockPlatform/RequestLogsTab.jsx +0 -239
  40. package/src/components/MockPlatform/ScenariosTab.jsx +0 -236
  41. package/src/components/MockPlatform/TestCasesTab.jsx +0 -462
  42. package/src/components/MockPlatform/index.jsx +0 -127
  43. package/src/components/Overview.jsx +0 -74
  44. package/src/dev.jsx +0 -28
  45. package/src/services/agentTeam.js +0 -7
  46. package/src/services/api.js +0 -84
  47. package/src/services/ctcAc.js +0 -7
  48. package/src/services/ctcAcDomain.js +0 -7
  49. package/src/services/ctcAuthorization.js +0 -7
  50. package/src/services/ctcSurl.js +0 -7
  51. package/src/services/ctcUser.js +0 -7
  52. package/src/services/job.js +0 -7
  53. package/src/services/metaApp.js +0 -7
  54. package/src/services/privateConfig.js +0 -7
  55. package/src/services/webide.js +0 -6
  56. package/src/services/workspace.js +0 -21
  57. package/src/utils/request.ts +0 -102
@@ -1,212 +0,0 @@
1
- import {useEffect, useState} from 'react'
2
- import {
3
- Alert,
4
- Button,
5
- Col,
6
- Form,
7
- Input,
8
- InputNumber,
9
- message,
10
- Modal,
11
- Popconfirm,
12
- Row,
13
- Select,
14
- Space,
15
- Switch,
16
- Table,
17
- Tag,
18
- Typography
19
- } from 'antd'
20
- import {DeleteOutlined, EditOutlined, GlobalOutlined, PlusOutlined, ReloadOutlined} from '@ant-design/icons'
21
- import {mockPlatformApi} from '@/services/api'
22
-
23
- const {Text} = Typography
24
-
25
- const ENV_TYPES = [
26
- {value: 'MOCK', label: 'MOCK (纯 Mock 拦截)', color: 'green'},
27
- {value: 'REAL', label: 'REAL (全部代理到真实)', color: 'blue'},
28
- {value: 'MIXED', label: 'MIXED (匹配失败时转发)', color: 'orange'},
29
- ]
30
-
31
- const ENV_TYPE_COLORS = {MOCK: 'green', REAL: 'blue', MIXED: 'orange'}
32
-
33
- export default function EnvironmentsTab({onEnvChange}) {
34
- const [envs, setEnvs] = useState([])
35
- const [loading, setLoading] = useState(false)
36
- const [modalOpen, setModalOpen] = useState(false)
37
- const [editing, setEditing] = useState(null)
38
- const [form] = Form.useForm()
39
-
40
- useEffect(() => {
41
- loadEnvs()
42
- }, [])
43
-
44
- const loadEnvs = async () => {
45
- setLoading(true)
46
- try {
47
- const res = await mockPlatformApi.environments.list()
48
- setEnvs(Array.isArray(res) ? res : [])
49
- } catch (e) {
50
- message.warning('加载环境列表失败: ' + e?.message)
51
- } finally {
52
- setLoading(false)
53
- }
54
- }
55
-
56
- const handleCreate = () => {
57
- setEditing(null)
58
- form.resetFields()
59
- form.setFieldsValue({envType: 'MOCK', isDefault: 0, mockPriority: 1})
60
- setModalOpen(true)
61
- }
62
-
63
- const handleEdit = (record) => {
64
- setEditing(record)
65
- form.setFieldsValue(record)
66
- setModalOpen(true)
67
- }
68
-
69
- const handleSave = async () => {
70
- try {
71
- const values = await form.validateFields()
72
- if (editing) {
73
- await mockPlatformApi.environments.update(editing.envCode, values)
74
- message.success('更新成功')
75
- } else {
76
- await mockPlatformApi.environments.create(values)
77
- message.success('创建成功')
78
- }
79
- setModalOpen(false)
80
- loadEnvs()
81
- } catch (e) {
82
- if (e?.errorFields) return
83
- message.error('保存失败')
84
- }
85
- }
86
-
87
- const handleDelete = async (envCode) => {
88
- try {
89
- await mockPlatformApi.environments.delete(envCode)
90
- message.success('删除成功')
91
- loadEnvs()
92
- } catch (e) {
93
- message.error('删除失败: ' + (e?.message || ''))
94
- }
95
- }
96
-
97
- const columns = [
98
- {
99
- title: '环境编码', dataIndex: 'envCode', key: 'envCode', width: 140,
100
- render: (v) => <Text code>{v}</Text>
101
- },
102
- {title: '环境名称', dataIndex: 'envName', key: 'envName', width: 160},
103
- {
104
- title: '类型', dataIndex: 'envType', key: 'envType', width: 240,
105
- render: (v) => <Tag color={ENV_TYPE_COLORS[v] || 'default'}>{v}</Tag>
106
- },
107
- {
108
- title: '真实服务地址', dataIndex: 'baseUrl', key: 'baseUrl',
109
- render: (v) => v ? <Text copyable>{v}</Text> : <Text type="secondary">-</Text>
110
- },
111
- {
112
- title: '默认', dataIndex: 'isDefault', key: 'isDefault', width: 90, align: 'center',
113
- render: (v) => v === 1 ? <Tag color="gold">默认</Tag> : '-'
114
- },
115
- {
116
- title: '描述', dataIndex: 'description', key: 'description', width: 220,
117
- render: (v) => v || '-'
118
- },
119
- {
120
- title: '操作', key: 'action', width: 180,
121
- render: (_, record) => (
122
- <Space size="small">
123
- <Button size="small" type="link" icon={<GlobalOutlined/>}
124
- onClick={() => {
125
- if (onEnvChange) onEnvChange(record.envCode)
126
- }}>切换</Button>
127
- <Button size="small" type="link" icon={<EditOutlined/>} onClick={() => handleEdit(record)}/>
128
- {record.isDefault !== 1 && (
129
- <Popconfirm title={`确认删除环境 ${record.envCode}?`}
130
- onConfirm={() => handleDelete(record.envCode)}>
131
- <Button size="small" type="link" danger icon={<DeleteOutlined/>}/>
132
- </Popconfirm>
133
- )}
134
- </Space>
135
- )
136
- },
137
- ]
138
-
139
- return (
140
- <div>
141
- <Alert type="info" showIcon style={{marginBottom: 16}}
142
- title="环境隔离 - 控制 Mock 与真实服务的切换"
143
- description={
144
- <div>
145
- <div><Tag color="green">MOCK</Tag> 完全拦截,仅返回 Mock 数据</div>
146
- <div><Tag color="blue">REAL</Tag> 全部代理到 baseUrl(适合压测、回归测试)</div>
147
- <div><Tag color="orange">MIXED</Tag> Mock 优先,未匹配时转发到 baseUrl(开发联调)</div>
148
- </div>
149
- }
150
- />
151
-
152
- <Space style={{marginBottom: 16}}>
153
- <Button icon={<ReloadOutlined/>} onClick={loadEnvs}>刷新</Button>
154
- <Button type="primary" icon={<PlusOutlined/>} onClick={handleCreate}>新建环境</Button>
155
- </Space>
156
-
157
- <Table
158
- dataSource={envs}
159
- columns={columns}
160
- rowKey="id"
161
- loading={loading}
162
- pagination={{pageSize: 10}}
163
- size="small"
164
- />
165
-
166
- <Modal
167
- title={editing ? `编辑环境: ${editing.envCode}` : '新建环境'}
168
- open={modalOpen}
169
- onCancel={() => setModalOpen(false)}
170
- onOk={handleSave}
171
- width={650}
172
- >
173
- <Form form={form} layout="vertical" style={{marginTop: 16}}>
174
- <Row gutter={16}>
175
- <Col span={12}>
176
- <Form.Item name="envCode" label="环境编码" rules={[{required: true}]}>
177
- <Input placeholder="dev / staging / prod" disabled={!!editing}/>
178
- </Form.Item>
179
- </Col>
180
- <Col span={12}>
181
- <Form.Item name="envName" label="环境名称" rules={[{required: true}]}>
182
- <Input placeholder="开发环境"/>
183
- </Form.Item>
184
- </Col>
185
- </Row>
186
- <Form.Item name="envType" label="环境类型" rules={[{required: true}]}>
187
- <Select options={ENV_TYPES}/>
188
- </Form.Item>
189
- <Form.Item name="baseUrl" label="真实服务地址"
190
- extra="REAL/MIXED 时使用。MIXED 时未匹配的请求会转发到这里">
191
- <Input placeholder="https://api.staging.example.com"/>
192
- </Form.Item>
193
- <Row gutter={16}>
194
- <Col span={12}>
195
- <Form.Item name="mockPriority" label="Mock 优先级">
196
- <InputNumber min={0} max={10} style={{width: '100%'}}/>
197
- </Form.Item>
198
- </Col>
199
- <Col span={12}>
200
- <Form.Item name="isDefault" label="是否默认" valuePropName="checked">
201
- <Switch checkedChildren="是" unCheckedChildren="否"/>
202
- </Form.Item>
203
- </Col>
204
- </Row>
205
- <Form.Item name="description" label="描述">
206
- <Input.TextArea rows={3} placeholder="环境的用途说明"/>
207
- </Form.Item>
208
- </Form>
209
- </Modal>
210
- </div>
211
- )
212
- }
@@ -1,200 +0,0 @@
1
- import {useState} from 'react'
2
- import {Button, Card, Col, Input, Row, Space, Tag, Tooltip, Typography} from 'antd'
3
- import {
4
- CodeOutlined,
5
- CopyOutlined,
6
- FunctionOutlined,
7
- InfoCircleOutlined,
8
- ReloadOutlined,
9
- SearchOutlined
10
- } from '@ant-design/icons'
11
- import {message} from 'antd'
12
-
13
- const {Text, Paragraph} = Typography
14
-
15
- /**
16
- * Mock 模板表达式目录
17
- * 同步自 MockTemplateEngine (z-mock) 实现的 @xxx 表达式
18
- */
19
- export const TEMPLATE_EXPRESSIONS = [
20
- {
21
- group: '基础数据', icon: <CodeOutlined/>,
22
- items: [
23
- {syntax: '@uuid', desc: '随机 UUID', example: 'a3f2e1b7-8c4d-4e6f-9a1b-2c3d4e5f6a7b'},
24
- {syntax: '@int(1, 100)', desc: '随机整数(含边界)', example: '42'},
25
- {syntax: '@int', desc: '随机整数(0-1000)', example: '731'},
26
- {syntax: '@boolean', desc: '随机布尔', example: 'true'},
27
- {syntax: '@pick("a","b","c")', desc: '从列表随机取一项', example: '"b"'},
28
- ]
29
- },
30
- {
31
- group: '时间相关', icon: <FunctionOutlined/>,
32
- items: [
33
- {syntax: '@datetime', desc: '当前时间 (yyyy-MM-dd HH:mm:ss)', example: '2026-06-17 22:30:15'},
34
- {syntax: '@date', desc: '当前日期 (yyyy-MM-dd)', example: '2026-06-17'},
35
- {syntax: '@time', desc: '当前时间戳 (毫秒)', example: '1718639415000'},
36
- {syntax: '@timestamp', desc: 'Unix 秒级时间戳', example: '1718639415'},
37
- ]
38
- },
39
- {
40
- group: '文本生成', icon: <FunctionOutlined/>,
41
- items: [
42
- {syntax: '@name', desc: '随机中文姓名', example: '张伟'},
43
- {syntax: '@firstName', desc: '随机名', example: '伟'},
44
- {syntax: '@lastName', desc: '随机姓', example: '张'},
45
- {syntax: '@email', desc: '随机邮箱', example: 'zhangwei@example.com'},
46
- {syntax: '@phone', desc: '随机手机号(中国)', example: '13812345678'},
47
- {syntax: '@idCard', desc: '随机身份证号', example: '110101199003078234'},
48
- {syntax: '@word', desc: '随机英文单词', example: 'horizon'},
49
- {syntax: '@sentence(5, 10)', desc: '随机句子 (5-10 词)', example: 'The quick brown fox jumps.'},
50
- {syntax: '@paragraph(3, 5)', desc: '随机段落 (3-5 句)', example: '...'},
51
- ]
52
- },
53
- {
54
- group: '序列与状态', icon: <FunctionOutlined/>,
55
- items: [
56
- {syntax: '@sequence(1)', desc: '自增序号(每次调用 +1,1 起始)', example: '1, 2, 3, ...'},
57
- {syntax: '@sequence(100, 5)', desc: '自增序号(100 起始,步长 5)', example: '100, 105, 110, ...'},
58
- ]
59
- },
60
- {
61
- group: '请求上下文', icon: <FunctionOutlined/>,
62
- items: [
63
- {syntax: '#path.id', desc: '从 URL 路径取值 /users/123 → 123', example: '123'},
64
- {syntax: '#query.page', desc: '从 query string 取值 ?page=2', example: '2'},
65
- {syntax: '#header.X-Token', desc: '从请求头取值', example: 'abc.def.ghi'},
66
- {syntax: '#body.username', desc: '从请求体 JSON 取值', example: '"alice"'},
67
- ]
68
- },
69
- ]
70
-
71
- /**
72
- * MockTemplateHelper — 模板表达式面板
73
- *
74
- * 用法:
75
- * <MockTemplateHelper onInsert={(expr) => form.setFieldsValue({ responseTemplate: prev + expr })} />
76
- *
77
- * @param onInsert 选中表达式后回调(参数为 syntax 字符串)
78
- * @param formField 当前正在编辑的 Form.Item 字段名(用于 getFieldValue 读取当前内容)
79
- * @param form AntD form 实例(可选)
80
- */
81
- export default function MockTemplateHelper({onInsert, form, formField = 'responseTemplate'}) {
82
- const [filter, setFilter] = useState('')
83
-
84
- const handleInsert = (syntax) => {
85
- // 复制到剪贴板
86
- try {
87
- navigator.clipboard?.writeText(syntax)
88
- } catch {
89
- }
90
- if (onInsert) {
91
- onInsert(syntax)
92
- } else if (form) {
93
- const prev = form.getFieldValue(formField) || ''
94
- form.setFieldsValue({[formField]: prev + (prev.endsWith('\n') || !prev ? '' : ' ') + syntax})
95
- }
96
- message.success(`已插入: ${syntax}`)
97
- }
98
-
99
- const handleCopy = (text) => {
100
- try {
101
- navigator.clipboard?.writeText(text)
102
- message.success('已复制到剪贴板')
103
- } catch {
104
- message.warning('复制失败,请手动选择')
105
- }
106
- }
107
-
108
- const lowerFilter = filter.toLowerCase()
109
- const filteredGroups = TEMPLATE_EXPRESSIONS.map(g => ({
110
- ...g,
111
- items: g.items.filter(it =>
112
- !lowerFilter ||
113
- it.syntax.toLowerCase().includes(lowerFilter) ||
114
- it.desc.toLowerCase().includes(lowerFilter) ||
115
- it.example.toLowerCase().includes(lowerFilter)
116
- )
117
- })).filter(g => g.items.length > 0)
118
-
119
- const totalCount = TEMPLATE_EXPRESSIONS.reduce((s, g) => s + g.items.length, 0)
120
- const filteredCount = filteredGroups.reduce((s, g) => s + g.items.length, 0)
121
-
122
- return (
123
- <Card
124
- size="small"
125
- title={
126
- <Space>
127
- <CodeOutlined/>
128
- <Text strong>模板表达式</Text>
129
- <Tag color="blue">{filteredCount}/{totalCount}</Tag>
130
- <Tooltip title="点击按钮即可插入到上方响应模板;点击 syntax 文本可复制">
131
- <InfoCircleOutlined style={{color: '#999'}}/>
132
- </Tooltip>
133
- </Space>
134
- }
135
- extra={
136
- <Input
137
- size="small"
138
- placeholder="搜索 @ 表达式"
139
- prefix={<SearchOutlined/>}
140
- value={filter}
141
- onChange={e => setFilter(e.target.value)}
142
- style={{width: 180}}
143
- allowClear
144
- />
145
- }
146
- style={{marginTop: 8, background: '#fafafa'}}
147
- styles={{body: {padding: 12, maxHeight: 320, overflow: 'auto'}}}
148
- >
149
- {filteredGroups.length === 0 && (
150
- <Text type="secondary" style={{display: 'block', textAlign: 'center', padding: 16}}>
151
- 没有匹配的表达式
152
- </Text>
153
- )}
154
- {filteredGroups.map(group => (
155
- <div key={group.group} style={{marginBottom: 12}}>
156
- <Space size={4} style={{marginBottom: 6}}>
157
- {group.icon}
158
- <Text strong style={{fontSize: 13}}>{group.group}</Text>
159
- <Tag>{group.items.length}</Tag>
160
- </Space>
161
- <Row gutter={[8, 8]}>
162
- {group.items.map(item => (
163
- <Col span={24} key={item.syntax}>
164
- <div
165
- style={{
166
- display: 'flex',
167
- alignItems: 'center',
168
- padding: '6px 8px',
169
- background: '#fff',
170
- border: '1px solid #f0f0f0',
171
- borderRadius: 4,
172
- gap: 8,
173
- }}
174
- >
175
- <Tooltip title="点击复制">
176
- <Text code
177
- style={{cursor: 'pointer', minWidth: 140, fontSize: 12}}
178
- onClick={() => handleCopy(item.syntax)}>
179
- {item.syntax}
180
- </Text>
181
- </Tooltip>
182
- <Text type="secondary" style={{fontSize: 12, flex: 1}}>
183
- {item.desc}
184
- </Text>
185
- <Tag color="default" style={{margin: 0, fontFamily: 'monospace'}}>
186
- {item.example}
187
- </Tag>
188
- <Tooltip title="插入到响应模板">
189
- <Button size="small" type="text" icon={<CopyOutlined/>}
190
- onClick={() => handleInsert(item.syntax)}/>
191
- </Tooltip>
192
- </div>
193
- </Col>
194
- ))}
195
- </Row>
196
- </div>
197
- ))}
198
- </Card>
199
- )
200
- }