@yuku123/z-frontend-common 0.2.9 → 1.1.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 (75) hide show
  1. package/LICENSE +25 -0
  2. package/README.md +55 -42
  3. package/dist/PagedTable-DyjNokXN.js +1211 -0
  4. package/dist/index.js +310 -0
  5. package/dist/ui.js +27 -0
  6. package/package.json +52 -44
  7. package/src/components/ErrorBoundary/index.jsx +24 -77
  8. package/src/components/Layout/index.jsx +141 -38
  9. package/src/components/LoginPage/index.jsx +47 -21
  10. package/src/components/StatusTag/index.jsx +14 -12
  11. package/src/components/ui/CategoryDot.jsx +38 -0
  12. package/src/components/ui/DarkBanner.jsx +142 -0
  13. package/src/components/ui/EChartsChart.jsx +82 -0
  14. package/src/components/ui/EmptyState.jsx +94 -0
  15. package/src/components/ui/ErrorState.jsx +114 -0
  16. package/src/components/ui/FeatureCard.jsx +205 -0
  17. package/src/components/ui/GradientStatCard.jsx +196 -0
  18. package/src/components/ui/LoadingState.jsx +116 -0
  19. package/src/components/ui/PageHeader.jsx +143 -0
  20. package/src/components/ui/PagedTable.jsx +83 -0
  21. package/src/components/ui/SearchInput.jsx +111 -0
  22. package/src/components/ui/SectionHeader.jsx +76 -0
  23. package/src/components/ui/StatusBadge.jsx +66 -0
  24. package/src/components/ui/TableToolbar.jsx +58 -0
  25. package/src/components/ui/index.js +36 -0
  26. package/src/components/ui/tokens.js +224 -0
  27. package/src/index.js +33 -37
  28. package/src/services/request.js +74 -4
  29. package/dist/z-frontend-common.css +0 -1
  30. package/dist/z-frontend-common.es.js +0 -51275
  31. package/dist/z-frontend-common.umd.js +0 -459
  32. package/src/components/Ctc/Layout.jsx +0 -330
  33. package/src/components/Ctc/Layout.module.css +0 -145
  34. package/src/components/Ctc/agentTeam/index.tsx +0 -308
  35. package/src/components/Ctc/login/AuthPage.module.css +0 -26
  36. package/src/components/Ctc/login/AuthPage.tsx +0 -235
  37. package/src/components/Ctc/login/index.less +0 -49
  38. package/src/components/Ctc/login/index.tsx +0 -142
  39. package/src/components/Ctc/uc/UCLogin.tsx +0 -31
  40. package/src/components/Ctc/uc/UCPhoneLogin.tsx +0 -62
  41. package/src/components/Ctc/uc/UCRegister.tsx +0 -37
  42. package/src/components/Ctc/uc/UCResetPassword.tsx +0 -69
  43. package/src/components/Ctc/uc/index.tsx +0 -15
  44. package/src/components/Ctc/userPanel/index.tsx +0 -999
  45. package/src/components/Ctc/webide/index.tsx +0 -272
  46. package/src/components/LowCode/LowCodeModel.jsx +0 -962
  47. package/src/components/LowCode/LowCodePage.jsx +0 -31
  48. package/src/components/LowCode/LowCodeRuntime.jsx +0 -335
  49. package/src/components/LowCode/MaterializePage.jsx +0 -235
  50. package/src/components/LowCode/index.js +0 -1
  51. package/src/components/MockPlatform/CurlImportModal.jsx +0 -362
  52. package/src/components/MockPlatform/EndpointsTab.jsx +0 -509
  53. package/src/components/MockPlatform/EnvironmentsTab.jsx +0 -212
  54. package/src/components/MockPlatform/MockTemplateHelper.jsx +0 -200
  55. package/src/components/MockPlatform/OpenApiImportModal.jsx +0 -305
  56. package/src/components/MockPlatform/RecordingsTab.jsx +0 -397
  57. package/src/components/MockPlatform/RequestLogsTab.jsx +0 -239
  58. package/src/components/MockPlatform/ScenariosTab.jsx +0 -236
  59. package/src/components/MockPlatform/TestCasesTab.jsx +0 -462
  60. package/src/components/MockPlatform/index.jsx +0 -127
  61. package/src/components/Overview.jsx +0 -74
  62. package/src/dev.jsx +0 -28
  63. package/src/services/agentTeam.js +0 -7
  64. package/src/services/api.js +0 -84
  65. package/src/services/ctcAc.js +0 -7
  66. package/src/services/ctcAcDomain.js +0 -7
  67. package/src/services/ctcAuthorization.js +0 -7
  68. package/src/services/ctcSurl.js +0 -7
  69. package/src/services/ctcUser.js +0 -7
  70. package/src/services/job.js +0 -7
  71. package/src/services/metaApp.js +0 -7
  72. package/src/services/privateConfig.js +0 -7
  73. package/src/services/webide.js +0 -6
  74. package/src/services/workspace.js +0 -21
  75. package/src/utils/request.ts +0 -102
@@ -0,0 +1,36 @@
1
+ /**
2
+ * UI 通用组件库 - 借鉴 wenming7/marketplace 视觉语言 + GitHub/awesome-copilot 交互原则
3
+ *
4
+ * 视觉类 (借鉴 wenming7/marketplace):
5
+ * - GradientStatCard 渐变数据卡 (替代 antd Statistic)
6
+ * - CategoryDot 分类圆点
7
+ * - SectionHeader 段落标题 (圆点 + 标题 + 全部>)
8
+ * - FeatureCard 功能卡 (16:9 封面 + 多 chip + 元信息)
9
+ * - DarkBanner 深色 CTA 横幅
10
+ *
11
+ * 交互类 (借鉴 ui-ux-pro-max + frontend-ui-engineering):
12
+ * - EmptyState 统一空状态 (图标 + 文案 + 行动)
13
+ * - ErrorState 错误状态 (原因 + 重试)
14
+ * - LoadingState 骨架屏 (cards/table/list/detail)
15
+ * - SearchInput Debounced 搜索 (300ms, Enter 立即, Esc 清空)
16
+ * - EChartsChart 安全 echarts 包装 (自动 dispose/resize)
17
+ * - PageHeader 页面标题 (面包屑 + 返回 + 操作区)
18
+ */
19
+
20
+ export {default as GradientStatCard} from './GradientStatCard'
21
+ export {default as CategoryDot} from './CategoryDot'
22
+ export {default as SectionHeader} from './SectionHeader'
23
+ export {default as FeatureCard} from './FeatureCard'
24
+ export {default as DarkBanner} from './DarkBanner'
25
+
26
+ export {default as EmptyState} from './EmptyState'
27
+ export {default as ErrorState} from './ErrorState'
28
+ export {default as LoadingState} from './LoadingState'
29
+ export {default as SearchInput} from './SearchInput'
30
+ export {default as EChartsChart} from './EChartsChart'
31
+ export {default as PageHeader} from './PageHeader'
32
+ export {default as TableToolbar, RefreshButton} from './TableToolbar'
33
+ export {default as StatusBadge} from './StatusBadge'
34
+ export {default as PagedTable} from './PagedTable'
35
+
36
+ export {brand, palette, neutral, radius, shadow, lift, space, fontSize, antdTheme} from './tokens'
@@ -0,0 +1,224 @@
1
+ /**
2
+ * 设计 token - 借鉴 wenming7/marketplace 视觉语言
3
+ *
4
+ * 设计原则:
5
+ * - 主色蓝紫, OKLCH 感知均匀
6
+ * - 多种分类色 (粉/蓝/绿/橙/紫) 用于模块/分类标识
7
+ * - 统一圆角 8/12/16, 统一阴影 (柔和多层)
8
+ * - 紧凑间距 4/8/12/16/24/32
9
+ *
10
+ * 这些 token 既被 antd ConfigProvider 消费, 也被 UI 组件内部引用,
11
+ * 保持单一来源, 改一处全局生效.
12
+ */
13
+
14
+ // ============ 品牌主色 ============
15
+ export const brand = {
16
+ // 主色 (蓝紫) - 顶导/重点按钮/链接
17
+ primary: '#7c3aed', // violet-600
18
+ primaryHover: '#8b5cf6', // violet-500
19
+ primaryActive: '#6d28d9', // violet-700
20
+ primarySoft: '#ede9fe', // violet-100 (淡背景)
21
+ }
22
+
23
+ // ============ 分类色 (借鉴 wenming7 多色分类) ============
24
+ // 用于分类圆点 / 数据卡 / 状态 chip
25
+ // 每个色 = { bg, fg, soft, gradient }
26
+ export const palette = {
27
+ pink: {
28
+ bg: '#ec4899',
29
+ fg: '#ffffff',
30
+ soft: '#fce7f3',
31
+ gradient: 'linear-gradient(135deg, #ec4899 0%, #be185d 100%)',
32
+ },
33
+ blue: {
34
+ bg: '#3b82f6',
35
+ fg: '#ffffff',
36
+ soft: '#dbeafe',
37
+ gradient: 'linear-gradient(135deg, #3b82f6 0%, #1e40af 100%)',
38
+ },
39
+ green: {
40
+ bg: '#10b981',
41
+ fg: '#ffffff',
42
+ soft: '#d1fae5',
43
+ gradient: 'linear-gradient(135deg, #10b981 0%, #047857 100%)',
44
+ },
45
+ orange: {
46
+ bg: '#f97316',
47
+ fg: '#ffffff',
48
+ soft: '#ffedd5',
49
+ gradient: 'linear-gradient(135deg, #f97316 0%, #c2410c 100%)',
50
+ },
51
+ violet: {
52
+ bg: '#8b5cf6',
53
+ fg: '#ffffff',
54
+ soft: '#ede9fe',
55
+ gradient: 'linear-gradient(135deg, #8b5cf6 0%, #6d28d9 100%)',
56
+ },
57
+ cyan: {
58
+ bg: '#06b6d4',
59
+ fg: '#ffffff',
60
+ soft: '#cffafe',
61
+ gradient: 'linear-gradient(135deg, #06b6d4 0%, #0e7490 100%)',
62
+ },
63
+ red: {
64
+ bg: '#ef4444',
65
+ fg: '#ffffff',
66
+ soft: '#fee2e2',
67
+ gradient: 'linear-gradient(135deg, #ef4444 0%, #b91c1c 100%)',
68
+ },
69
+ yellow: {
70
+ bg: '#eab308',
71
+ fg: '#1f2937',
72
+ soft: '#fef3c7',
73
+ gradient: 'linear-gradient(135deg, #eab308 0%, #a16207 100%)',
74
+ },
75
+ }
76
+
77
+ // ============ 中性色 ============
78
+ export const neutral = {
79
+ bg: '#f8fafc', // 页面底色 (比 antd 默认 #f5f5f5 更冷一点, 更现代)
80
+ surface: '#ffffff', // 卡片表面
81
+ surfaceAlt: '#fafbfc', // 次级表面 (表格 hover 等)
82
+ border: '#e5e7eb', // 默认边框 (比 antd 默认淡, 更现代)
83
+ borderStrong: '#d1d5db',
84
+ text: '#111827', // 主文本
85
+ textMuted: '#6b7280', // 次文本
86
+ textDisabled: '#9ca3af',
87
+ }
88
+
89
+ // ============ 圆角 ============
90
+ export const radius = {
91
+ sm: 8,
92
+ md: 12,
93
+ lg: 16,
94
+ xl: 20,
95
+ pill: 999,
96
+ }
97
+
98
+ // ============ 阴影 (柔和多层, 借鉴 wenming7) ============
99
+ export const shadow = {
100
+ sm: '0 1px 2px 0 rgba(15, 23, 42, 0.04), 0 1px 3px 0 rgba(15, 23, 42, 0.06)',
101
+ md: '0 2px 4px -1px rgba(15, 23, 42, 0.04), 0 4px 8px -1px rgba(15, 23, 42, 0.08)',
102
+ lg: '0 4px 6px -2px rgba(15, 23, 42, 0.05), 0 12px 16px -4px rgba(15, 23, 42, 0.10)',
103
+ xl: '0 8px 24px -6px rgba(15, 23, 42, 0.10), 0 24px 48px -12px rgba(15, 23, 42, 0.18)',
104
+ }
105
+
106
+ // 悬浮抬升 (卡片 hover 时)
107
+ export const lift = {
108
+ rest: shadow.md,
109
+ hover: '0 8px 16px -4px rgba(15, 23, 42, 0.08), 0 20px 32px -8px rgba(15, 23, 42, 0.14)',
110
+ }
111
+
112
+ // ============ 间距 ============
113
+ export const space = {
114
+ 1: 4,
115
+ 2: 8,
116
+ 3: 12,
117
+ 4: 16,
118
+ 5: 20,
119
+ 6: 24,
120
+ 8: 32,
121
+ 10: 40,
122
+ 12: 48,
123
+ 16: 64,
124
+ }
125
+
126
+ // ============ 字号梯度 ============
127
+ export const fontSize = {
128
+ xs: 11,
129
+ sm: 12,
130
+ base: 14,
131
+ md: 16,
132
+ lg: 18,
133
+ xl: 20,
134
+ '2xl': 24,
135
+ '3xl': 30,
136
+ '4xl': 36,
137
+ }
138
+
139
+ // ============ antd theme token (给 ConfigProvider 消费) ============
140
+ export const antdTheme = {
141
+ token: {
142
+ // 主色
143
+ colorPrimary: brand.primary,
144
+ colorInfo: brand.primary,
145
+ colorSuccess: palette.green.bg,
146
+ colorWarning: palette.orange.bg,
147
+ colorError: palette.red.bg,
148
+
149
+ // 链接
150
+ colorLink: brand.primary,
151
+ colorLinkHover: brand.primaryHover,
152
+ colorLinkActive: brand.primaryActive,
153
+
154
+ // 文本
155
+ colorText: neutral.text,
156
+ colorTextSecondary: neutral.textMuted,
157
+ colorTextTertiary: neutral.textDisabled,
158
+
159
+ // 背景
160
+ colorBgBase: neutral.surface,
161
+ colorBgLayout: neutral.bg,
162
+ colorBgContainer: neutral.surface,
163
+ colorBgElevated: neutral.surface,
164
+
165
+ // 边框
166
+ colorBorder: neutral.border,
167
+ colorBorderSecondary: neutral.surfaceAlt,
168
+
169
+ // 圆角
170
+ borderRadius: radius.md,
171
+ borderRadiusLG: radius.lg,
172
+ borderRadiusSM: radius.sm,
173
+
174
+ // 字体
175
+ fontSize: fontSize.base,
176
+ fontFamily:
177
+ "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', " +
178
+ "'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif",
179
+
180
+ // 阴影
181
+ boxShadow: shadow.md,
182
+ boxShadowSecondary: shadow.lg,
183
+ },
184
+ components: {
185
+ // Layout: 顶导白底更现代
186
+ Layout: {
187
+ headerBg: neutral.surface,
188
+ headerHeight: 64,
189
+ headerPadding: '0 24px',
190
+ siderBg: '#0f172a', // 深色侧栏 (slate-900), 比纯黑更有质感
191
+ },
192
+ // Menu: 深色侧栏菜单
193
+ Menu: {
194
+ darkItemBg: 'transparent',
195
+ darkSubMenuItemBg: 'transparent',
196
+ darkItemSelectedBg: brand.primary,
197
+ darkItemHoverBg: 'rgba(255, 255, 255, 0.06)',
198
+ darkItemColor: 'rgba(255, 255, 255, 0.75)',
199
+ itemBorderRadius: 8,
200
+ itemMarginInline: 8,
201
+ },
202
+ // Card: 更柔和
203
+ Card: {
204
+ borderRadiusLG: radius.lg,
205
+ boxShadowTertiary: shadow.sm,
206
+ },
207
+ // Button: 主按钮圆角统一
208
+ Button: {
209
+ borderRadius: radius.md,
210
+ borderRadiusLG: radius.lg,
211
+ fontWeight: 500,
212
+ },
213
+ // Tabs: 现代化下划线
214
+ Tabs: {
215
+ itemSelectedColor: brand.primary,
216
+ inkBarColor: brand.primary,
217
+ titleFontSize: fontSize.base,
218
+ },
219
+ // Tag: 更小巧
220
+ Tag: {
221
+ borderRadiusSM: 6,
222
+ },
223
+ },
224
+ }
package/src/index.js CHANGED
@@ -1,42 +1,38 @@
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 * from './components/ui/index.js'
17
14
 
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'
15
+ export { AppLayout } from './components/Layout/index.jsx'
16
+ export { default as LoginPage } from './components/LoginPage/index.jsx'
17
+ export { default as StatusTag, defaultStatusMap } from './components/StatusTag/index.jsx'
18
+ export { default as ErrorBoundary } from './components/ErrorBoundary/index.jsx'
24
19
 
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'
20
+ import { AppLayout } from './components/Layout/index.jsx'
21
+ import StatusTag, { defaultStatusMap } from './components/StatusTag/index.jsx'
22
+ import LoginPage from './components/LoginPage/index.jsx'
23
+ import ErrorBoundary from './components/ErrorBoundary/index.jsx'
24
+ import { createRequest, setupInterceptors, unwrapResponse, request, authRequest } from './services/request.js'
30
25
 
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'
26
+ export { createRequest, setupInterceptors, unwrapResponse, request, authRequest }
42
27
 
28
+ // 0.1.1 default 桶契约原样保留(Ge 对象),老调用方 `import zfc from '@yuku123/z-frontend-common'` 不断
29
+ export default {
30
+ AppLayout,
31
+ StatusTag,
32
+ defaultStatusMap,
33
+ LoginPage,
34
+ ErrorBoundary,
35
+ request,
36
+ authRequest,
37
+ createRequest,
38
+ }
@@ -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}