@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,37 +1,57 @@
1
- import {useState} from 'react'
2
- import {Button, Card, Form, Input, message} from 'antd'
3
- import {LockOutlined, UserOutlined} from '@ant-design/icons'
4
- import request from '../../utils/request'
1
+ import { useState } from 'react'
2
+ import { Alert, Button, Card, Form, Input, message } from 'antd'
3
+ import { LockOutlined, UserOutlined } from '@ant-design/icons'
4
+ import { request } from '../../services/request'
5
5
 
6
6
  /**
7
- * 统一登录页面组件
8
- * @param {Object} props
9
- * @param {string} props.title - 页面标题
10
- * @param {string} props.loginApi - 登录 API 路径,默认 /auth/login
11
- * @param {string} props.redirectUrl - 登录成功后跳转地址,默认 /
12
- * @param {Function} props.onSuccess - 登录成功回调,覆盖 redirectUrl
7
+ * 统一登录页(lead 008 §16)—— mockAuth / 真实 API 双模式:
8
+ * <ul>
9
+ * <li>{@code mockAuth} 传入 → 纯前端校验(admin/123456 硬编码顶替,CTC/SSO 接入前短期形态),
10
+ * 登录成功写 localStorage.token + userInfo 并跳 redirectUrl</li>
11
+ * <li>{@code mockAuth} 缺省 → POST {@code loginApi}(CTC 中央认证),后端签发 token</li>
12
+ * </ul>
13
+ *
14
+ * @param {string} [title='统一管理平台'] 卡片标题
15
+ * @param {Object} [mockAuth] {username, password, user:{name, role}} 本地 mock 校验配置
16
+ * @param {string} [loginApi='/auth/login'] 真实登录端点(mockAuth 缺省时生效)
17
+ * @param {string} [redirectUrl='/'] 登录成功跳转
18
+ * @param {Function} [onSuccess] 登录成功回调(覆盖 redirectUrl 跳转)
13
19
  */
14
20
  export default function LoginPage({
15
21
  title = '统一管理平台',
22
+ mockAuth,
16
23
  loginApi = '/auth/login',
17
24
  redirectUrl = '/',
18
25
  onSuccess,
19
26
  }) {
20
27
  const [loading, setLoading] = useState(false)
21
28
 
29
+ const persistAndRedirect = (user) => {
30
+ localStorage.setItem('token', mockAuth ? 'mock-' + mockAuth.username : user?.token || 'token')
31
+ localStorage.setItem('userInfo', JSON.stringify(user || {}))
32
+ message.success('登录成功' + (mockAuth ? '(mock 模式,待 CTC/SSO 接入)' : ''))
33
+ if (onSuccess) onSuccess(user)
34
+ else window.location.href = redirectUrl
35
+ }
36
+
22
37
  const handleSubmit = async (values) => {
23
38
  setLoading(true)
24
39
  try {
40
+ if (mockAuth) {
41
+ if (values.username === mockAuth.username && values.password === mockAuth.password) {
42
+ persistAndRedirect(mockAuth.user)
43
+ } else {
44
+ message.error('用户名或密码错误')
45
+ }
46
+ return
47
+ }
25
48
  const res = await request.post(loginApi, values)
26
- if (res.token) {
49
+ if (res?.token) {
27
50
  localStorage.setItem('token', res.token)
28
51
  localStorage.setItem('userInfo', JSON.stringify(res.user || res))
29
52
  message.success('登录成功')
30
- if (onSuccess) {
31
- onSuccess(res)
32
- } else {
33
- window.location.href = redirectUrl
34
- }
53
+ if (onSuccess) onSuccess(res)
54
+ else window.location.href = redirectUrl
35
55
  } else {
36
56
  message.error('登录失败:未获取到 token')
37
57
  }
@@ -47,13 +67,19 @@ export default function LoginPage({
47
67
  height: '100vh', display: 'flex', justifyContent: 'center', alignItems: 'center',
48
68
  background: '#f0f2f5',
49
69
  }}>
50
- <Card title={title} style={{width: 400}}>
70
+ <Card title={title} style={{ width: 400 }}>
71
+ {mockAuth && (
72
+ <Alert
73
+ type="info" showIcon style={{ marginBottom: 16 }}
74
+ message={`Mock 模式:用户名 ${mockAuth.username} / 密码 ${mockAuth.password}`}
75
+ />
76
+ )}
51
77
  <Form onFinish={handleSubmit} size="large">
52
- <Form.Item name="username" rules={[{required: true, message: '请输入用户名'}]}>
53
- <Input prefix={<UserOutlined/>} placeholder="用户名"/>
78
+ <Form.Item name="username" rules={[{ required: true, message: '请输入用户名' }]}>
79
+ <Input prefix={<UserOutlined />} placeholder="用户名" />
54
80
  </Form.Item>
55
- <Form.Item name="password" rules={[{required: true, message: '请输入密码'}]}>
56
- <Input.Password prefix={<LockOutlined/>} placeholder="密码"/>
81
+ <Form.Item name="password" rules={[{ required: true, message: '请输入密码' }]}>
82
+ <Input.Password prefix={<LockOutlined />} placeholder="密码" />
57
83
  </Form.Item>
58
84
  <Form.Item>
59
85
  <Button type="primary" htmlType="submit" loading={loading} block>
@@ -1,16 +1,18 @@
1
- import {Tag} from 'antd'
1
+ import { Tag } from 'antd'
2
2
 
3
- const defaultStatusMap = {
4
- 1: {color: 'green', text: '正常'},
5
- 0: {color: 'red', text: '禁用'},
6
- pending: {color: 'orange', text: '待处理'},
7
- approved: {color: 'blue', text: '已通过'},
8
- rejected: {color: 'red', text: '已拒绝'},
3
+ /** 0.1.1 契约保留:数值/枚举 → 语义色 Tag 的默认映射。 */
4
+ export const defaultStatusMap = {
5
+ 1: { color: 'green', text: '正常' },
6
+ 0: { color: 'red', text: '禁用' },
7
+ pending: { color: 'orange', text: '待处理' },
8
+ approved: { color: 'blue', text: '已通过' },
9
+ rejected: { color: 'red', text: '已拒绝' },
9
10
  }
10
11
 
11
- export default function StatusTag({status, map}) {
12
- const config = map?.[status] || defaultStatusMap[status] || {color: 'default', text: String(status)}
13
- return <Tag color={config.color}>{config.text}</Tag>
12
+ /**
13
+ * 状态标签。props 与 0.1.1 一致:status + 可选 map(覆盖/追加 defaultStatusMap)。
14
+ */
15
+ export default function StatusTag({ status, map }) {
16
+ const conf = map?.[status] || defaultStatusMap[status] || { color: 'default', text: String(status) }
17
+ return <Tag color={conf.color}>{conf.text}</Tag>
14
18
  }
15
-
16
- export {defaultStatusMap}
package/src/index.js CHANGED
@@ -1,42 +1,36 @@
1
- export {default as AppLayout} from './components/Layout'
2
- export {default as StatusTag, defaultStatusMap} from './components/StatusTag'
3
- export {default as LoginPage} from './components/LoginPage'
4
- export {default as ErrorBoundary} from './components/ErrorBoundary'
5
- export {default as Overview} from './components/Overview'
6
- export {default as request} from './utils/request'
7
- export {authRequest, createRequest, setupInterceptors} from './utils/request'
8
- export {ctcRequest} from './services/request'
1
+ /**
2
+ * z-frontend-common 桶导出 —— lead 008 前端开发规范唯一承载仓。
3
+ *
4
+ * 40+ 仓 suit 的 AppLayout / LoginPage 唯一来源;21 个 <repo>-component 的
5
+ * services 层消费 createRequest / request / authRequest。
6
+ *
7
+ * API 契约与 0.1.1 完全兼容(ErrorBoundary / LoginPage / StatusTag /
8
+ * authRequest / createRequest / defaultStatusMap / request /
9
+ * setupInterceptors + default 桶),AppLayout 升级为 §1/§11/§12/§15/§16
10
+ * 规范版,LoginPage 扩展 mockAuth 双模式(§16)。
11
+ */
9
12
 
10
- // 4A 中心 Layout + 登录
11
- export {default as CtcLayout} from './components/Ctc/Layout'
12
- export {default as CtcAuthPage} from './components/Ctc/login/AuthPage'
13
- export {default as CtcLogin} from './components/Ctc/login/index'
14
- export {default as AgentTeamIM} from './components/Ctc/agentTeam'
15
- export {default as UserPanel} from './components/Ctc/userPanel'
16
- export {default as Webide} from './components/Ctc/webide'
13
+ export { AppLayout } from './components/Layout/index.jsx'
14
+ export { default as LoginPage } from './components/LoginPage/index.jsx'
15
+ export { default as StatusTag, defaultStatusMap } from './components/StatusTag/index.jsx'
16
+ export { default as ErrorBoundary } from './components/ErrorBoundary/index.jsx'
17
17
 
18
- // UC 用户中心 (FEATURE011)
19
- export {default as UCLayout} from './components/Ctc/uc'
20
- export {default as UCLogin} from './components/Ctc/uc/UCLogin'
21
- export {default as UCPhoneLogin} from './components/Ctc/uc/UCPhoneLogin'
22
- export {default as UCRegister} from './components/Ctc/uc/UCRegister'
23
- export {default as UCResetPassword} from './components/Ctc/uc/UCResetPassword'
18
+ import { AppLayout } from './components/Layout/index.jsx'
19
+ import StatusTag, { defaultStatusMap } from './components/StatusTag/index.jsx'
20
+ import LoginPage from './components/LoginPage/index.jsx'
21
+ import ErrorBoundary from './components/ErrorBoundary/index.jsx'
22
+ import { createRequest, setupInterceptors, unwrapResponse, request, authRequest } from './services/request.js'
24
23
 
25
- // 低代码建模
26
- export {default as LowCodePage} from './components/LowCode/LowCodePage'
27
- export {default as LowCodeRuntime} from './components/LowCode/LowCodeRuntime'
28
- export {default as LowCodeModel} from './components/LowCode/LowCodeModel'
29
- export {default as MaterializePage} from './components/LowCode/MaterializePage'
30
-
31
- // Mock 平台 (工具平台)
32
- export {default as MockPlatform} from './components/MockPlatform/index'
33
- export {default as EndpointsTab} from './components/MockPlatform/EndpointsTab'
34
- export {default as ScenariosTab} from './components/MockPlatform/ScenariosTab'
35
- export {default as TestCasesTab} from './components/MockPlatform/TestCasesTab'
36
- export {default as RequestLogsTab} from './components/MockPlatform/RequestLogsTab'
37
- export {default as RecordingsTab} from './components/MockPlatform/RecordingsTab'
38
- export {default as EnvironmentsTab} from './components/MockPlatform/EnvironmentsTab'
39
- export {default as MockTemplateHelper} from './components/MockPlatform/MockTemplateHelper'
40
- export {default as CurlImportModal} from './components/MockPlatform/CurlImportModal'
41
- export {default as OpenApiImportModal} from './components/MockPlatform/OpenApiImportModal'
24
+ export { createRequest, setupInterceptors, unwrapResponse, request, authRequest }
42
25
 
26
+ // 0.1.1 default 桶契约原样保留(Ge 对象),老调用方 `import zfc from '@yuku123/z-frontend-common'` 不断
27
+ export default {
28
+ AppLayout,
29
+ StatusTag,
30
+ defaultStatusMap,
31
+ LoginPage,
32
+ ErrorBoundary,
33
+ request,
34
+ authRequest,
35
+ createRequest,
36
+ }
@@ -1,6 +1,76 @@
1
+ import axios from 'axios'
2
+ import { message } from 'antd'
3
+
1
4
  /**
2
- * 兼容垫片: 之前在 z-opc-main-starter-frontend/services/request.ts 里的 axios 实例.
5
+ * 统一响应解包:z-opc 后端走 {code, data, message} 包装(Spring MVC 统一返回体),
6
+ * 独立 standalone 后端可能返回裸数据。有 code+data 双键就按包装解,否则原样透传。
7
+ * (z-vector standalone 实测坑:不解包全站拿 undefined —— 见 z-vector 仓 2026-10-11 修痕。)
3
8
  */
4
- import request, {authRequest, createRequest, setupInterceptors} from '../utils/request'
5
- export {request as default, authRequest, createRequest, setupInterceptors}
6
- export const ctcRequest = authRequest
9
+ export function unwrapResponse(body) {
10
+ if (body && typeof body === 'object' && 'code' in body && 'data' in body) {
11
+ return body.code !== 200
12
+ ? Promise.reject(new Error(body.message || '请求失败'))
13
+ : body.data
14
+ }
15
+ return body
16
+ }
17
+
18
+ /**
19
+ * axios 拦截器装配(request / authRequest 预建实例与 createRequest 工厂共用)。
20
+ * 与 0.1.1 的 API 契约逐字段一致,21 个 component 仓的 services 层在消费,不能改签名。
21
+ */
22
+ export function setupInterceptors(instance, options = {}) {
23
+ const {
24
+ tokenKey = 'token',
25
+ userInfoKey = 'userInfo',
26
+ unauthorizedRedirect = '/login',
27
+ } = options
28
+
29
+ instance.interceptors.request.use((config) => {
30
+ const token = localStorage.getItem(tokenKey)
31
+ if (token) config.headers.Authorization = `Bearer ${token}`
32
+ return config
33
+ })
34
+
35
+ instance.interceptors.response.use(
36
+ (response) => unwrapResponse(response.data),
37
+ (error) => {
38
+ const status = error.response?.status
39
+ if (status === 401) {
40
+ localStorage.removeItem(tokenKey)
41
+ localStorage.removeItem(userInfoKey)
42
+ window.location.href = unauthorizedRedirect
43
+ } else if (status === 403) {
44
+ console.error('没有权限访问该资源')
45
+ } else if (status === 500) {
46
+ console.error('服务器内部错误')
47
+ }
48
+ return Promise.reject(error)
49
+ },
50
+ )
51
+ return instance
52
+ }
53
+
54
+ /**
55
+ * axios 实例工厂 —— 21 个 <repo>-component 的 services/api.js 用它建各自的请求实例。
56
+ * @param {Object} options
57
+ * @param {string} [options.baseURL='/api']
58
+ * @param {number} [options.timeout=10000]
59
+ * @param {string} [options.tokenKey='token']
60
+ * @param {string} [options.userInfoKey='userInfo']
61
+ * @param {string} [options.unauthorizedRedirect='/login']
62
+ */
63
+ export function createRequest(options = {}) {
64
+ const instance = axios.create({
65
+ baseURL: options.baseURL ?? '/api',
66
+ timeout: options.timeout ?? 10000,
67
+ })
68
+ return setupInterceptors(instance, {
69
+ tokenKey: options.tokenKey,
70
+ userInfoKey: options.userInfoKey,
71
+ unauthorizedRedirect: options.unauthorizedRedirect,
72
+ })
73
+ }
74
+
75
+ export const request = createRequest()
76
+ export const authRequest = createRequest()
@@ -1 +0,0 @@
1
- ._layout_1puwg_1{min-height:100vh}._header_1puwg_5{display:flex;justify-content:space-between;align-items:center;padding:0 24px;background:#001529;height:48px;line-height:48px}._logo_1puwg_15{display:flex;align-items:center}._logoText_1puwg_20{color:#fff;font-size:16px;font-weight:600}._headerRight_1puwg_26{display:flex;align-items:center}._userInfo_1puwg_31{display:flex;align-items:center;cursor:pointer;color:#fff}._userName_1puwg_38{margin-left:8px;color:#fff}._mainLayout_1puwg_43{margin-top:0;min-height:calc(100vh - 48px)}._sider_1puwg_48{background:#fff;min-height:calc(100vh - 48px)}._menu_1puwg_53{border-right:none}._collapsedBtn_1puwg_57{position:absolute;bottom:16px;left:50%;transform:translate(-50%);cursor:pointer;padding:8px 16px;background:#f5f5f5;border-radius:4px;color:#666}._collapsedBtn_1puwg_57:hover{background:#e6f7ff;color:#1890ff}._content_1puwg_74{padding:24px;background:#f5f5f5;min-height:calc(100vh - 48px);overflow:auto}._userDropdownPanel_1puwg_81{background:#fff;border-radius:8px;box-shadow:0 6px 16px #0000001f;padding:16px;width:360px}._tenantSection_1puwg_89{display:flex;align-items:center;gap:12px}._tenantLabel_1puwg_95{font-size:14px;color:#666;white-space:nowrap}._tenantCascader_1puwg_101{flex:1}._panelDivider_1puwg_105{margin:12px 0}._userSection_1puwg_109{display:flex;flex-direction:column;gap:8px}._userInfoRow_1puwg_115{display:flex;font-size:14px;line-height:1.6}._userInfoLabel_1puwg_121{color:#999;width:70px;flex-shrink:0}._menuSection_1puwg_127{display:flex;flex-direction:column}._menuItem_1puwg_132{display:flex;align-items:center;gap:8px;padding:8px 12px;cursor:pointer;border-radius:4px;font-size:14px;color:#333}._menuItem_1puwg_132:hover{background:#f5f5f5}._container_tti32_1{min-height:100vh;display:flex;align-items:center;justify-content:center;background:linear-gradient(135deg,#667eea,#764ba2)}._content_tti32_9{width:400px;padding:20px}._card_tti32_14{border-radius:8px;box-shadow:0 4px 20px #0000001a}._header_tti32_19{text-align:center;margin-bottom:24px}._header_tti32_19 h3{margin-bottom:8px}