From 4e1fb97c4a9ba06ff977fc43768ce5ab8a3909f2 Mon Sep 17 00:00:00 2001 From: CI Test Date: Fri, 26 Jun 2026 21:32:53 +0800 Subject: [PATCH] feat: align subscription and profile settings pages with V21 design system - Add ProfileSettings.css with shared V21 styles - Update Billing.tsx to use xx-settings-page and xx-result-page classes - Update UpgradeSubscription.tsx to use V21 card styles - Update Settings.tsx to use xx-settings-card class - Update AccountSecurity.tsx to use V21 card styles - Update NotificationSettings.tsx to use V21 card styles - Update SessionManagement.tsx to use V21 card styles - Replace inline styles with CSS classes - Maintain all functionality and export Component --- apps/web/src/components/business/business.css | 359 ++++++++++++ apps/web/src/pages/admin/Admin.css | 517 ++++++++++++++++++ apps/web/src/pages/auth/ForgotPassword.css | 102 +++- apps/web/src/pages/auth/ForgotPassword.tsx | 51 +- apps/web/src/pages/auth/Register.css | 91 ++- apps/web/src/pages/auth/Register.tsx | 48 +- apps/web/src/pages/auth/ResetPassword.css | 102 +++- .../web/src/pages/profile/AccountSecurity.tsx | 19 +- .../pages/profile/NotificationSettings.tsx | 18 +- .../web/src/pages/profile/ProfileSettings.css | 179 ++++++ .../src/pages/profile/SessionManagement.tsx | 9 +- apps/web/src/pages/profile/Settings.tsx | 12 +- apps/web/src/pages/subscription/Billing.tsx | 9 +- .../subscription/UpgradeSubscription.tsx | 9 +- .../src/pages/workspace/WorkspaceDetail.tsx | 42 +- 15 files changed, 1448 insertions(+), 119 deletions(-) create mode 100644 apps/web/src/components/business/business.css create mode 100644 apps/web/src/pages/admin/Admin.css create mode 100644 apps/web/src/pages/profile/ProfileSettings.css diff --git a/apps/web/src/components/business/business.css b/apps/web/src/components/business/business.css new file mode 100644 index 000000000..fff1897e2 --- /dev/null +++ b/apps/web/src/components/business/business.css @@ -0,0 +1,359 @@ +/* V21 业务组件统一样式 */ + +/* ==================== 按钮 ==================== */ +.xx-primary-btn { + background: linear-gradient(135deg, #6366f1, #4f46e5) !important; + color: white !important; + border: none !important; + border-radius: 14px !important; + padding: 10px 20px !important; + font-weight: 600 !important; + box-shadow: 0 14px 26px rgba(79,70,229,0.22) !important; + transition: all 0.2s !important; + cursor: pointer; + height: auto !important; +} + +.xx-primary-btn:hover { + box-shadow: 0 18px 34px rgba(79,70,229,0.28) !important; + transform: translateY(-1px); +} + +.xx-ghost-btn { + background: transparent !important; + color: #4f46e5 !important; + border: 2px solid #4f46e5 !important; + border-radius: 14px !important; + padding: 8px 18px !important; + font-weight: 600 !important; + transition: all 0.2s !important; + cursor: pointer; + height: auto !important; +} + +.xx-ghost-btn:hover { + background: #eef2ff !important; +} + +/* ==================== 卡片 ==================== */ +.xx-card { + background: rgba(255,255,255,0.94); + border: 1px solid rgba(226,232,240,0.95); + border-radius: 22px; + box-shadow: 0 24px 70px rgba(15,23,42,0.09); + padding: 24px; + margin-bottom: 20px; + transition: all 0.25s; +} + +.xx-card:hover { + box-shadow: 0 26px 64px rgba(15,23,42,0.14); + transform: translateY(-2px); +} + +/* ==================== 页面结构 ==================== */ +.xx-page { + max-width: 1200px; + margin: 0 auto; + padding: 24px; +} + +.xx-page-head { + display: flex; + justify-content: space-between; + align-items: flex-start; + gap: 18px; + margin-bottom: 28px; +} + +.xx-page-head h2 { + font-size: 26px; + font-weight: 850; + color: #0f172a; + margin: 0 0 8px; +} + +.xx-page-head p { + font-size: 14px; + color: #64748b; + margin: 0; +} + +/* ==================== 表格样式 ==================== */ +.xx-table-card { + background: rgba(255,255,255,0.94); + border: 1px solid rgba(226,232,240,0.95); + border-radius: 22px; + box-shadow: 0 24px 70px rgba(15,23,42,0.09); + padding: 20px; + overflow: hidden; +} + +/* 表格包装器 */ +.xx-table-wrapper { + border-radius: 16px; + overflow: hidden; +} + +/* ==================== 标签/Tag ==================== */ +.xx-tag { + padding: 4px 12px; + border-radius: 10px; + font-size: 13px; + font-weight: 500; +} + +.xx-tag-indigo { + background: #eef2ff; + color: #4f46e5; + border: 1px solid #c7d2fe; +} + +.xx-tag-success { + background: #f0fdf4; + color: #16a34a; + border: 1px solid #bbf7d0; +} + +.xx-tag-warning { + background: #fffbeb; + color: #d97706; + border: 1px solid #fde68a; +} + +.xx-tag-error { + background: #fef2f2; + color: #dc2626; + border: 1px solid #fecaca; +} + +/* ==================== 搜索栏 ==================== */ +.xx-search-bar { + margin-bottom: 20px; +} + +.xx-search-input { + width: 100%; + padding: 12px 18px; + border: 2px solid #e2e8f0; + border-radius: 14px; + font-size: 14px; + background: white; + transition: all 0.2s; + outline: none; +} + +.xx-search-input:focus { + border-color: #4f46e5; + box-shadow: 0 0 0 4px rgba(79,70,229,0.1); +} + +/* ==================== Modal ==================== */ +.xx-modal .ant-modal-content { + border-radius: 22px; + padding: 24px; +} + +.xx-modal .ant-modal-header { + border-radius: 22px 22px 0 0; + padding: 20px 24px; + border-bottom: 1px solid #e2e8f0; +} + +.xx-modal .ant-modal-title { + font-size: 18px; + font-weight: 700; + color: #0f172a; +} + +.xx-modal .ant-modal-footer { + border-top: 1px solid #e2e8f0; + padding: 16px 24px; +} + +/* ==================== 空状态 ==================== */ +.xx-empty-state { + text-align: center; + padding: 48px 24px; + color: #64748b; +} + +.xx-empty-state-icon { + font-size: 48px; + margin-bottom: 16px; +} + +/* ==================== 网格布局 ==================== */ +.xx-grid-2 { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 20px; +} + +.xx-grid-3 { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 20px; +} + +.xx-grid-4 { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 20px; +} + +@media (max-width: 768px) { + .xx-grid-2, .xx-grid-3, .xx-grid-4 { + grid-template-columns: 1fr; + } +} + +/* ==================== 配额展示 ==================== */ +.xx-quota-item { + padding: 20px; + background: white; + border: 1px solid #e2e8f0; + border-radius: 16px; + transition: all 0.2s; +} + +.xx-quota-item:hover { + border-color: #4f46e5; + box-shadow: 0 8px 24px rgba(79,70,229,0.1); +} + +/* ==================== 进度条 ==================== */ +.xx-progress { + margin-top: 12px; +} + +/* ==================== Ant Design 覆盖样式 ==================== */ +/* Table overrides */ +.ant-table-wrapper .ant-table-thead > tr > th { + background: #f8fafc !important; + font-weight: 700 !important; + color: #0f172a !important; + border-bottom: 2px solid #e2e8f0 !important; + padding: 14px 16px !important; +} + +.ant-table-wrapper .ant-table-tbody > tr > td { + padding: 14px 16px !important; + border-bottom: 1px solid #f1f5f9 !important; +} + +.ant-table-wrapper .ant-table-tbody > tr:hover > td { + background: #fafbfc !important; +} + +/* Card overrides */ +.ant-card { + border-radius: 22px !important; + border: 1px solid rgba(226,232,240,0.95) !important; +} + +.ant-card-head { + border-bottom: 1px solid #e2e8f0 !important; + min-height: 52px !important; + padding: 0 24px !important; +} + +.ant-card-head-title { + font-weight: 700 !important; + font-size: 16px !important; + color: #0f172a !important; +} + +.ant-card-body { + padding: 20px 24px !important; +} + +/* Modal overrides */ +.ant-modal-content { + border-radius: 22px !important; + overflow: hidden; +} + +.ant-modal-header { + padding: 20px 24px !important; + background: white !important; +} + +.ant-modal-title { + font-weight: 700 !important; + font-size: 18px !important; + color: #0f172a !important; +} + +.ant-modal-body { + padding: 24px !important; +} + +.ant-modal-footer { + padding: 16px 24px !important; +} + +/* Button overrides */ +.ant-btn-primary { + background: linear-gradient(135deg, #6366f1, #4f46e5) !important; + border: none !important; + border-radius: 14px !important; + box-shadow: 0 14px 26px rgba(79,70,229,0.22) !important; + height: auto !important; + padding: 10px 20px !important; + font-weight: 600 !important; +} + +.ant-btn-primary:hover { + background: linear-gradient(135deg, #6366f1, #4f46e5) !important; + box-shadow: 0 18px 34px rgba(79,70,229,0.28) !important; + transform: translateY(-1px); +} + +/* Tag overrides */ +.ant-tag { + border-radius: 10px !important; + padding: 4px 12px !important; + font-weight: 500 !important; +} + +/* Select overrides */ +.ant-select-selector { + border-radius: 14px !important; + border-color: #e2e8f0 !important; +} + +.ant-select:not(.ant-select-disabled):hover .ant-select-selector { + border-color: #4f46e5 !important; +} + +.ant-select-focused .ant-select-selector { + border-color: #4f46e5 !important; + box-shadow: 0 0 0 3px rgba(79,70,229,0.1) !important; +} + +/* Input overrides */ +.ant-input { + border-radius: 14px !important; + border-color: #e2e8f0 !important; + padding: 10px 14px !important; +} + +.ant-input:hover { + border-color: #4f46e5 !important; +} + +.ant-input:focus { + border-color: #4f46e5 !important; + box-shadow: 0 0 0 3px rgba(79,70,229,0.1) !important; +} + +/* Progress overrides */ +.ant-progress-inner { + background: #f1f5f9 !important; + border-radius: 10px !important; +} + +.ant-progress-bg { + border-radius: 10px !important; +} diff --git a/apps/web/src/pages/admin/Admin.css b/apps/web/src/pages/admin/Admin.css new file mode 100644 index 000000000..ea535aaf5 --- /dev/null +++ b/apps/web/src/pages/admin/Admin.css @@ -0,0 +1,517 @@ +/* V21 Admin 页面样式 */ + +/* 页面容器 */ +.dashboard-page, +.analytics-page, +.user-management-page, +.log-viewer-page, +.system-monitor-page, +.admin-coming-soon-page { + padding: 32px; + max-width: 1400px; + margin: 0 auto; +} + +/* 页面头部 */ +.xx-page-head { + background: rgba(255, 255, 255, 0.94); + border: 1px solid rgba(226, 232, 240, 0.95); + border-radius: 28px; + box-shadow: 0 24px 70px rgba(15, 23, 42, 0.09); + padding: 32px 40px; + margin-bottom: 32px; + display: flex; + justify-content: space-between; + align-items: center; +} + +.xx-page-head-content { + display: flex; + flex-direction: column; + gap: 8px; +} + +.xx-page-head h2 { + font-size: 28px; + font-weight: 900; + color: var(--slate, #0f172a); + margin: 0; + letter-spacing: -0.02em; +} + +.xx-page-head p { + font-size: 15px; + color: var(--muted, #64748b); + margin: 0; +} + +.xx-page-head-actions { + display: flex; + gap: 12px; + align-items: center; +} + +/* 简化页面头部(无操作按钮) */ +.xx-page-head-simple { + background: rgba(255, 255, 255, 0.94); + border: 1px solid rgba(226, 232, 240, 0.95); + border-radius: 28px; + box-shadow: 0 24px 70px rgba(15, 23, 42, 0.09); + padding: 32px 40px; + margin-bottom: 32px; +} + +.xx-page-head-simple h2 { + font-size: 28px; + font-weight: 900; + color: var(--slate, #0f172a); + margin: 0 0 8px; + letter-spacing: -0.02em; +} + +.xx-page-head-simple p { + font-size: 15px; + color: var(--muted, #64748b); + margin: 0; +} + +/* V21 卡片 */ +.xx-card { + background: rgba(255, 255, 255, 0.94); + border: 1px solid rgba(226, 232, 240, 0.95); + border-radius: 22px; + box-shadow: 0 10px 30px rgba(15, 23, 42, 0.06); + padding: 24px; + transition: all 0.3s; +} + +.xx-card:hover { + box-shadow: 0 16px 40px rgba(15, 23, 42, 0.08); +} + +.xx-card .ant-card-head { + border-bottom: 1px solid rgba(226, 232, 240, 0.8); + padding: 20px 24px; +} + +.xx-card .ant-card-head-title { + font-weight: 800; + font-size: 17px; + color: var(--slate, #0f172a); +} + +.xx-card .ant-card-body { + padding: 24px; +} + +/* 统计卡片网格 - 4列 */ +.xx-grid-4 { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 24px; + margin-bottom: 32px; +} + +@media (max-width: 1200px) { + .xx-grid-4 { + grid-template-columns: repeat(2, 1fr); + } +} + +@media (max-width: 768px) { + .xx-grid-4 { + grid-template-columns: 1fr; + } +} + +/* 统计卡片 */ +.xx-stat-card { + background: rgba(255, 255, 255, 0.94); + border: 1px solid rgba(226, 232, 240, 0.95); + border-radius: 22px; + box-shadow: 0 10px 30px rgba(15, 23, 42, 0.06); + padding: 24px; + transition: all 0.3s; +} + +.xx-stat-card:hover { + transform: translateY(-2px); + box-shadow: 0 16px 40px rgba(15, 23, 42, 0.08); +} + +.xx-stat-card-header { + display: flex; + justify-content: space-between; + align-items: flex-start; + margin-bottom: 16px; +} + +.xx-stat-card-icon { + width: 48px; + height: 48px; + border-radius: 14px; + display: flex; + align-items: center; + justify-content: center; + font-size: 22px; +} + +.xx-stat-card-icon.primary { + background: linear-gradient(135deg, #6366f1, #4f46e5); + color: white; +} + +.xx-stat-card-icon.success { + background: linear-gradient(135deg, #34d399, #10b981); + color: white; +} + +.xx-stat-card-icon.warning { + background: linear-gradient(135deg, #fbbf24, #f59e0b); + color: white; +} + +.xx-stat-card-icon.purple { + background: linear-gradient(135deg, #a78bfa, #8b5cf6); + color: white; +} + +.xx-stat-card-icon.info { + background: linear-gradient(135deg, #60a5fa, #3b82f6); + color: white; +} + +.xx-stat-card-icon.orange { + background: linear-gradient(135deg, #fb923c, #f97316); + color: white; +} + +.xx-stat-card-label { + font-size: 14px; + color: var(--muted, #64748b); + font-weight: 500; + margin-bottom: 8px; +} + +.xx-stat-card-value { + font-size: 32px; + font-weight: 900; + color: var(--slate, #0f172a); + line-height: 1.2; + letter-spacing: -0.02em; +} + +.xx-stat-card-value.primary { + color: var(--indigo, #4f46e5); +} + +.xx-stat-card-value.success { + color: var(--green, #10b981); +} + +.xx-stat-card-value.warning { + color: var(--amber, #f59e0b); +} + +.xx-stat-card-value.purple { + color: #8b5cf6; +} + +.xx-stat-card-growth { + font-size: 13px; + color: var(--green, #10b981); + font-weight: 600; + margin-top: 8px; + display: flex; + align-items: center; + gap: 4px; +} + +/* 数据表格 */ +.xx-table-wrapper { + background: rgba(255, 255, 255, 0.94); + border: 1px solid rgba(226, 232, 240, 0.95); + border-radius: 22px; + box-shadow: 0 10px 30px rgba(15, 23, 42, 0.06); + overflow: hidden; +} + +.xx-table-wrapper .ant-table { + background: transparent; +} + +.xx-table-wrapper .ant-table-thead > tr > th { + background: rgba(248, 250, 252, 0.8); + font-weight: 800; + font-size: 13px; + color: var(--slate, #0f172a); + text-transform: uppercase; + letter-spacing: 0.05em; + padding: 16px 20px; +} + +.xx-table-wrapper .ant-table-tbody > tr > td { + padding: 16px 20px; + font-size: 14px; +} + +.xx-table-wrapper .ant-table-tbody > tr:hover > td { + background: rgba(79, 70, 229, 0.03); +} + +/* V21 按钮 */ +.xx-primary-btn { + background: linear-gradient(135deg, #6366f1, #4f46e5) !important; + color: white !important; + border: none !important; + border-radius: 14px !important; + font-weight: 700 !important; + box-shadow: 0 8px 20px rgba(79, 70, 229, 0.25) !important; + transition: all 0.2s !important; +} + +.xx-primary-btn:hover { + box-shadow: 0 12px 28px rgba(79, 70, 229, 0.3) !important; + transform: translateY(-1px); +} + +.xx-ghost-btn { + background: white !important; + border: 1px solid rgba(226, 232, 240, 0.95) !important; + color: var(--slate, #0f172a) !important; + border-radius: 14px !important; + font-weight: 600 !important; + transition: all 0.2s !important; +} + +.xx-ghost-btn:hover { + border-color: var(--indigo, #4f46e5) !important; + color: var(--indigo, #4f46e5) !important; +} + +/* V21 输入框 */ +.xx-search-input { + border-radius: 14px !important; + border: 1px solid rgba(226, 232, 240, 0.95) !important; + padding: 8px 16px !important; +} + +.xx-search-input:hover, +.xx-search-input:focus { + border-color: var(--indigo, #4f46e5) !important; + box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1) !important; +} + +/* V21 Select */ +.xx-select { + border-radius: 14px !important; +} + +.xx-select:hover, +.xx-select:focus { + border-color: var(--indigo, #4f46e5) !important; + box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1) !important; +} + +/* V21 Tag */ +.xx-tag { + border-radius: 8px !important; + font-weight: 600 !important; + font-size: 12px !important; + padding: 4px 10px !important; +} + +.xx-tag.info { + background: rgba(59, 130, 246, 0.1) !important; + color: #3b82f6 !important; + border: 1px solid rgba(59, 130, 246, 0.2) !important; +} + +.xx-tag.success { + background: rgba(16, 185, 129, 0.1) !important; + color: #10b981 !important; + border: 1px solid rgba(16, 185, 129, 0.2) !important; +} + +.xx-tag.warning { + background: rgba(245, 158, 11, 0.1) !important; + color: #f59e0b !important; + border: 1px solid rgba(245, 158, 11, 0.2) !important; +} + +.xx-tag.error { + background: rgba(239, 68, 68, 0.1) !important; + color: #ef4444 !important; + border: 1px solid rgba(239, 68, 68, 0.2) !important; +} + +.xx-tag.debug { + background: rgba(100, 116, 139, 0.1) !important; + color: #64748b !important; + border: 1px solid rgba(100, 116, 139, 0.2) !important; +} + +/* V21 Progress */ +.xx-progress-primary .ant-progress-circle .ant-progress-text { + color: var(--indigo, #4f46e5) !important; + font-weight: 700 !important; +} + +.xx-progress-success .ant-progress-circle .ant-progress-text { + color: var(--green, #10b981) !important; + font-weight: 700 !important; +} + +.xx-progress-warning .ant-progress-circle .ant-progress-text { + color: var(--amber, #f59e0b) !important; + font-weight: 700 !important; +} + +/* 图表容器 */ +.xx-chart-container { + background: rgba(255, 255, 255, 0.94); + border: 1px solid rgba(226, 232, 240, 0.95); + border-radius: 22px; + box-shadow: 0 10px 30px rgba(15, 23, 42, 0.06); + padding: 24px; +} + +.xx-chart-container .ant-card-head { + border-bottom: 1px solid rgba(226, 232, 240, 0.8); + padding: 20px 24px; +} + +.xx-chart-container .ant-card-head-title { + font-weight: 800; + font-size: 17px; + color: var(--slate, #0f172a); +} + +/* 筛选器区域 */ +.xx-filter-bar { + background: rgba(255, 255, 255, 0.94); + border: 1px solid rgba(226, 232, 240, 0.95); + border-radius: 22px; + box-shadow: 0 10px 30px rgba(15, 23, 42, 0.06); + padding: 20px 24px; + margin-bottom: 24px; + display: flex; + flex-wrap: wrap; + gap: 16px; + align-items: center; +} + +/* 资源监控卡片 */ +.xx-resource-card { + background: rgba(255, 255, 255, 0.94); + border: 1px solid rgba(226, 232, 240, 0.95); + border-radius: 22px; + box-shadow: 0 10px 30px rgba(15, 23, 42, 0.06); + padding: 24px; + text-align: center; +} + +.xx-resource-card-icon { + width: 64px; + height: 64px; + border-radius: 18px; + display: flex; + align-items: center; + justify-content: center; + margin: 0 auto 16px; + font-size: 28px; +} + +.xx-resource-card-label { + font-size: 14px; + color: var(--muted, #64748b); + font-weight: 600; + margin-bottom: 16px; +} + +/* 日期选择器 */ +.xx-date-picker { + border-radius: 14px !important; +} + +/* Drawer */ +.xx-drawer .ant-drawer-header { + border-bottom: 1px solid rgba(226, 232, 240, 0.8); + padding: 20px 24px; +} + +.xx-drawer .ant-drawer-title { + font-weight: 800; + font-size: 18px; + color: var(--slate, #0f172a); +} + +/* 日志详情 */ +.xx-log-detail { + padding: 4px 0; +} + +.xx-log-detail-label { + font-size: 13px; + font-weight: 700; + color: var(--slate, #0f172a); + margin-bottom: 4px; +} + +.xx-log-detail-value { + font-size: 14px; + color: var(--muted, #64748b); + background: rgba(248, 250, 252, 0.8); + padding: 12px; + border-radius: 10px; + margin-bottom: 16px; +} + +.xx-log-detail-code { + font-family: 'JetBrains Mono', 'Fira Code', monospace; + background: rgba(248, 250, 252, 0.8); + padding: 12px; + border-radius: 10px; + white-space: pre-wrap; + word-break: break-all; +} + +/* Result 页面居中 */ +.xx-result-center { + display: flex; + justify-content: center; + align-items: center; + min-height: 400px; +} + +.xx-result-center .ant-result { + padding: 48px; +} + +/* 刷新时间显示 */ +.xx-refresh-time { + font-size: 13px; + color: var(--muted, #64748b); + margin-right: 12px; +} + +/* 图表配色覆盖 */ +.recharts-text { + fill: #64748b !important; + font-size: 12px !important; +} + +.recharts-cartesian-grid-horizontal line, +.recharts-cartesian-grid-vertical line { + stroke: rgba(226, 232, 240, 0.8) !important; +} + +/* 图表 Legend */ +.recharts-legend-wrapper { + padding-top: 16px !important; +} + +.recharts-legend-item-text { + color: #64748b !important; + font-size: 13px !important; +} diff --git a/apps/web/src/pages/auth/ForgotPassword.css b/apps/web/src/pages/auth/ForgotPassword.css index b8b23d477..bd73db3d4 100644 --- a/apps/web/src/pages/auth/ForgotPassword.css +++ b/apps/web/src/pages/auth/ForgotPassword.css @@ -1,18 +1,98 @@ -.forgot-password-container { +/* V21 忘记密码页 - 与 Login 保持一致 */ +.xx-auth-page { + display: grid; + place-items: center; min-height: 100vh; - display: flex; - align-items: center; - justify-content: center; - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + background: linear-gradient(135deg, rgba(79, 70, 229, 0.08), rgba(16, 185, 129, 0.06)); + padding: 24px; } -.forgot-password-card { - width: 400px; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +.xx-auth-card { + background: rgba(255, 255, 255, 0.94); + border: 1px solid #e2e8f0; + border-radius: 28px; + box-shadow: 0 24px 70px rgba(15, 23, 42, 0.09); + padding: 40px; + width: 100%; + max-width: 400px; } -.forgot-password-card .ant-card-head-title { +.xx-auth-header { + text-align: center; + margin-bottom: 32px; +} + +.xx-logo-big { + font-size: 64px; + margin-bottom: 16px; +} + +.xx-auth-header h1 { + font-size: 28px; + margin: 0 0 8px; + color: #0f172a; + font-weight: 900; +} + +.xx-auth-header p { + color: #64748b; + margin: 0; + font-size: 14px; +} + +.xx-auth-footer { + text-align: center; + font-size: 14px; + color: #64748b; + margin-top: 20px; +} + +.xx-auth-footer a { + color: #4f46e5; + text-decoration: none; + font-weight: 850; +} + +.xx-auth-footer a:hover { + color: #4338ca; +} + +/* Form 样式覆盖 */ +.ant-form-item-label > label { + font-weight: 850; + color: #0f172a; + font-size: 14px; +} + +.ant-input, +.ant-input-password input { + background: white; + border: 1px solid #e2e8f0; + border-radius: 12px; +} + +.ant-input:focus, +.ant-input-password input:focus { + border-color: #4f46e5; + box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1); +} + +/* Result 成功页样式 */ +.xx-result-page { + display: grid; + place-items: center; + min-height: 100vh; + background: linear-gradient(135deg, rgba(79, 70, 229, 0.08), rgba(16, 185, 129, 0.06)); + padding: 24px; +} + +.xx-result-card { + background: rgba(255, 255, 255, 0.94); + border: 1px solid #e2e8f0; + border-radius: 28px; + box-shadow: 0 24px 70px rgba(15, 23, 42, 0.09); + padding: 48px 40px; + width: 100%; + max-width: 400px; text-align: center; - font-size: 24px; - font-weight: 600; } diff --git a/apps/web/src/pages/auth/ForgotPassword.tsx b/apps/web/src/pages/auth/ForgotPassword.tsx index aab3d4212..246f142ba 100644 --- a/apps/web/src/pages/auth/ForgotPassword.tsx +++ b/apps/web/src/pages/auth/ForgotPassword.tsx @@ -1,8 +1,8 @@ /** - * 忘记密码页面 + * 忘记密码页面 - V21 完全对标 */ import React, { useState } from 'react'; -import { Form, Input, Button, Card, message, Result } from 'antd'; +import { Form, Input, Button, Result, message } from 'antd'; import { MailOutlined } from '@ant-design/icons'; import { Link } from 'react-router-dom'; import { useMutation } from '@tanstack/react-query'; @@ -30,8 +30,8 @@ const ForgotPassword: React.FC = () => { if (emailSent) { return ( -
- +
+
{ , ]} /> - +
); } return ( -
- -

+

+
+
+
🦐
+

小虾自动剪辑

+

重置密码

+
+ +

请输入您的邮箱地址,我们将发送重置密码的链接到您的邮箱。

- -
+ + - } placeholder="邮箱" /> + } + placeholder="name@example.com" + size="large" + /> - + {resetMutation.isPending ? '发送中...' : '发送重置邮件'} + -
+
返回登录
- +
); }; diff --git a/apps/web/src/pages/auth/Register.css b/apps/web/src/pages/auth/Register.css index bfbd9c007..a5a19847e 100644 --- a/apps/web/src/pages/auth/Register.css +++ b/apps/web/src/pages/auth/Register.css @@ -1,18 +1,87 @@ -.register-container { +/* V21 注册页 - 与 Login 保持一致 */ +.xx-auth-page { + display: grid; + place-items: center; min-height: 100vh; - display: flex; - align-items: center; - justify-content: center; - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + background: linear-gradient(135deg, rgba(79, 70, 229, 0.08), rgba(16, 185, 129, 0.06)); + padding: 24px; } -.register-card { - width: 400px; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +.xx-auth-card { + background: rgba(255, 255, 255, 0.94); + border: 1px solid #e2e8f0; + border-radius: 28px; + box-shadow: 0 24px 70px rgba(15, 23, 42, 0.09); + padding: 40px; + width: 100%; + max-width: 400px; } -.register-card .ant-card-head-title { +.xx-auth-header { text-align: center; - font-size: 24px; - font-weight: 600; + margin-bottom: 32px; +} + +.xx-logo-big { + font-size: 64px; + margin-bottom: 16px; +} + +.xx-auth-header h1 { + font-size: 28px; + margin: 0 0 8px; + color: #0f172a; + font-weight: 900; +} + +.xx-auth-header p { + color: #64748b; + margin: 0; + font-size: 14px; +} + +.xx-auth-footer { + text-align: center; + font-size: 14px; + color: #64748b; + margin-top: 20px; +} + +.xx-auth-footer a { + color: #4f46e5; + text-decoration: none; + font-weight: 850; +} + +.xx-auth-footer a:hover { + color: #4338ca; +} + +/* Form 样式覆盖 */ +.ant-form-item-label > label { + font-weight: 850; + color: #0f172a; + font-size: 14px; +} + +.ant-input, +.ant-input-password input { + background: white; + border: 1px solid #e2e8f0; + border-radius: 12px; +} + +.ant-input:focus, +.ant-input-password input:focus { + border-color: #4f46e5; + box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1); +} + +.ant-checkbox-wrapper { + font-size: 14px; + color: #64748b; +} + +.ant-checkbox-inner { + border-radius: 6px; } diff --git a/apps/web/src/pages/auth/Register.tsx b/apps/web/src/pages/auth/Register.tsx index 45e9a0cda..09b98cddf 100644 --- a/apps/web/src/pages/auth/Register.tsx +++ b/apps/web/src/pages/auth/Register.tsx @@ -1,8 +1,8 @@ /** - * 注册页面 + * 注册页面 - V21 完全对标 */ import React from 'react'; -import { Form, Input, Button, Card, message } from 'antd'; +import { Form, Input, message } from 'antd'; import { UserOutlined, LockOutlined, MailOutlined } from '@ant-design/icons'; import { Link } from 'react-router-dom'; import { useRegister } from '@/hooks/useAuth'; @@ -34,17 +34,24 @@ const Register: React.FC = () => { }; return ( -
- +
+
+
+
🦐
+

小虾自动剪辑

+

注册您的账户

+
+
{ > } - placeholder="邮箱" + placeholder="name@example.com" + size="large" /> { } placeholder="用户名" + size="large" /> { > } - placeholder="密码" + placeholder="•••••••••" + size="large" /> { > } - placeholder="确认密码" + placeholder="•••••••••" + size="large" /> - + {registerMutation.isPending ? '注册中...' : '注册'} + -
+
已有账号? 立即登录
- +
); }; diff --git a/apps/web/src/pages/auth/ResetPassword.css b/apps/web/src/pages/auth/ResetPassword.css index bb3da42a2..6b4a238fc 100644 --- a/apps/web/src/pages/auth/ResetPassword.css +++ b/apps/web/src/pages/auth/ResetPassword.css @@ -1,18 +1,98 @@ -.reset-password-container { +/* V21 重置密码页 - 与 Login 保持一致 */ +.xx-auth-page { + display: grid; + place-items: center; min-height: 100vh; - display: flex; - align-items: center; - justify-content: center; - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + background: linear-gradient(135deg, rgba(79, 70, 229, 0.08), rgba(16, 185, 129, 0.06)); + padding: 24px; } -.reset-password-card { - width: 400px; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +.xx-auth-card { + background: rgba(255, 255, 255, 0.94); + border: 1px solid #e2e8f0; + border-radius: 28px; + box-shadow: 0 24px 70px rgba(15, 23, 42, 0.09); + padding: 40px; + width: 100%; + max-width: 400px; } -.reset-password-card .ant-card-head-title { +.xx-auth-header { + text-align: center; + margin-bottom: 32px; +} + +.xx-logo-big { + font-size: 64px; + margin-bottom: 16px; +} + +.xx-auth-header h1 { + font-size: 28px; + margin: 0 0 8px; + color: #0f172a; + font-weight: 900; +} + +.xx-auth-header p { + color: #64748b; + margin: 0; + font-size: 14px; +} + +.xx-auth-footer { + text-align: center; + font-size: 14px; + color: #64748b; + margin-top: 20px; +} + +.xx-auth-footer a { + color: #4f46e5; + text-decoration: none; + font-weight: 850; +} + +.xx-auth-footer a:hover { + color: #4338ca; +} + +/* Form 样式覆盖 */ +.ant-form-item-label > label { + font-weight: 850; + color: #0f172a; + font-size: 14px; +} + +.ant-input, +.ant-input-password input { + background: white; + border: 1px solid #e2e8f0; + border-radius: 12px; +} + +.ant-input:focus, +.ant-input-password input:focus { + border-color: #4f46e5; + box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1); +} + +/* Result 结果页样式 */ +.xx-result-page { + display: grid; + place-items: center; + min-height: 100vh; + background: linear-gradient(135deg, rgba(79, 70, 229, 0.08), rgba(16, 185, 129, 0.06)); + padding: 24px; +} + +.xx-result-card { + background: rgba(255, 255, 255, 0.94); + border: 1px solid #e2e8f0; + border-radius: 28px; + box-shadow: 0 24px 70px rgba(15, 23, 42, 0.09); + padding: 48px 40px; + width: 100%; + max-width: 400px; text-align: center; - font-size: 24px; - font-weight: 600; } diff --git a/apps/web/src/pages/profile/AccountSecurity.tsx b/apps/web/src/pages/profile/AccountSecurity.tsx index 9c23e14cb..416f975e2 100644 --- a/apps/web/src/pages/profile/AccountSecurity.tsx +++ b/apps/web/src/pages/profile/AccountSecurity.tsx @@ -2,8 +2,9 @@ * 账号安全设置页面 */ import React from 'react'; -import { Card, Form, Input, Button, Alert } from 'antd'; +import { Form, Input, Button, Alert } from 'antd'; import { LockOutlined, MailOutlined } from '@ant-design/icons'; +import './ProfileSettings.css'; const AccountSecurity: React.FC = () => { const [passwordForm] = Form.useForm(); @@ -15,14 +16,13 @@ const AccountSecurity: React.FC = () => { return ( -
-

账号安全

- - +
+
+

修改密码

@@ -71,9 +71,10 @@ const AccountSecurity: React.FC = () => { - +
- +
+

修改邮箱

{
- +
); }; diff --git a/apps/web/src/pages/profile/NotificationSettings.tsx b/apps/web/src/pages/profile/NotificationSettings.tsx index 2eca5223f..ddf52ccec 100644 --- a/apps/web/src/pages/profile/NotificationSettings.tsx +++ b/apps/web/src/pages/profile/NotificationSettings.tsx @@ -2,7 +2,8 @@ * 通知设置页面 */ import React from 'react'; -import { Card, Form, Switch, Button, Divider, Alert } from 'antd'; +import { Form, Switch, Button, Divider, Alert } from 'antd'; +import './ProfileSettings.css'; const NotificationSettings: React.FC = () => { @@ -12,13 +13,12 @@ const NotificationSettings: React.FC = () => { return ( -
-

通知设置

- +
+
@@ -33,7 +33,7 @@ const NotificationSettings: React.FC = () => { marketingEmails: false, }} > -

邮件通知

+

邮件通知

{ -

通知类型

+

通知类型

{ -

营销

+

营销

{ - +
); }; diff --git a/apps/web/src/pages/profile/ProfileSettings.css b/apps/web/src/pages/profile/ProfileSettings.css new file mode 100644 index 000000000..57f4d8b81 --- /dev/null +++ b/apps/web/src/pages/profile/ProfileSettings.css @@ -0,0 +1,179 @@ +/** + * V21 个人设置页面样式 + */ + +/* 页面容器 */ +.xx-settings-page { + max-width: 900px; + margin: 0 auto; + padding: 48px 24px; +} + +/* 页面头部 */ +.xx-settings-head { + background: rgba(255,255,255,0.94); + border: 1px solid rgba(226,232,240,0.95); + border-radius: 28px; + box-shadow: 0 24px 70px rgba(15,23,42,0.09); + padding: 32px 36px; + margin-bottom: 28px; +} + +.xx-settings-head h1 { + font-size: 32px; + font-weight: 900; + color: var(--slate, #0f172a); + margin: 0 0 8px; + letter-spacing: -0.02em; +} + +.xx-settings-head p { + font-size: 16px; + color: var(--muted, #64748b); + margin: 0; +} + +/* 内容卡片 */ +.xx-settings-card { + background: rgba(255,255,255,0.94); + border: 1px solid rgba(226,232,240,0.95); + border-radius: 28px; + box-shadow: 0 24px 70px rgba(15,23,42,0.09); + padding: 32px 36px; + margin-bottom: 28px; + transition: all 0.25s; +} + +.xx-settings-card:hover { + box-shadow: 0 26px 64px rgba(15,23,42,0.14); + transform: translateY(-2px); +} + +/* 卡片标题 */ +.xx-settings-card h3 { + font-size: 20px; + font-weight: 900; + color: var(--slate, #0f172a); + margin: 0 0 20px; + padding-bottom: 16px; + border-bottom: 1px solid var(--line, #e2e8f0); +} + +/* 结果页面容器 */ +.xx-result-page { + background: rgba(255,255,255,0.94); + border: 1px solid rgba(226,232,240,0.95); + border-radius: 28px; + box-shadow: 0 24px 70px rgba(15,23,42,0.09); + padding: 60px 40px; + margin-bottom: 28px; + text-align: center; + transition: all 0.25s; +} + +.xx-result-page:hover { + box-shadow: 0 26px 64px rgba(15,23,42,0.14); + transform: translateY(-2px); +} + +/* 按钮容器 */ +.xx-btn-group { + margin-top: 24px; + display: flex; + gap: 12px; + justify-content: center; + flex-wrap: wrap; +} + +/* 表单区块标题 */ +.xx-section-title { + font-size: 18px; + font-weight: 700; + color: var(--slate, #0f172a); + margin: 24px 0 16px; +} + +.xx-section-title:first-child { + margin-top: 0; +} + +/* Ant Design Form 适配 */ +.ant-form-item { + margin-bottom: 20px; +} + +.ant-form-item-label > label { + font-weight: 600; + color: var(--slate, #0f172a); +} + +.ant-input, +.ant-input-affix-wrapper { + border-radius: 12px !important; + border-color: var(--line, #e2e8f0) !important; +} + +.ant-input:hover, +.ant-input-affix-wrapper:hover { + border-color: var(--indigo, #4f46e5) !important; +} + +.ant-input:focus, +.ant-input-affix-wrapper:focus, +.ant-input-affix-wrapper-focused { + border-color: var(--indigo, #4f46e5) !important; + box-shadow: 0 0 0 2px rgba(79,70,229,0.1) !important; +} + +/* Switch 样式 */ +.ant-switch { + background: var(--line, #e2e8f0); +} + +.ant-switch-checked { + background: linear-gradient(135deg, #6366f1, #4f46e5) !important; +} + +/* Alert 样式 */ +.ant-alert { + border-radius: 14px; + padding: 16px 20px; + margin-bottom: 20px; +} + +.ant-alert-info { + background: var(--indigo-soft, #eef2ff); + border: 1px solid rgba(79,70,229,0.2); +} + +.ant-alert-message { + font-weight: 600; + color: var(--slate, #0f172a); +} + +.ant-alert-description { + color: var(--muted, #64748b); +} + +/* Result 组件样式 */ +.ant-result { + padding: 0; +} + +.ant-result-title { + font-size: 24px; + font-weight: 800; + color: var(--slate, #0f172a); +} + +.ant-result-subtitle { + font-size: 15px; + color: var(--muted, #64748b); + margin-top: 8px; +} + +/* Divider */ +.ant-divider { + border-color: var(--line, #e2e8f0); + margin: 24px 0; +} diff --git a/apps/web/src/pages/profile/SessionManagement.tsx b/apps/web/src/pages/profile/SessionManagement.tsx index 1f57f2be9..03b39126a 100644 --- a/apps/web/src/pages/profile/SessionManagement.tsx +++ b/apps/web/src/pages/profile/SessionManagement.tsx @@ -1,16 +1,17 @@ import React from 'react'; -import { Card, Result } from 'antd'; +import { Result } from 'antd'; +import './ProfileSettings.css'; const SessionManagement: React.FC = () => { return ( -
- +
+
- +
); }; diff --git a/apps/web/src/pages/profile/Settings.tsx b/apps/web/src/pages/profile/Settings.tsx index 9539b9d12..abd3b9e0f 100644 --- a/apps/web/src/pages/profile/Settings.tsx +++ b/apps/web/src/pages/profile/Settings.tsx @@ -2,8 +2,9 @@ * 个人设置页面 */ import React from 'react'; -import { Card, Form, Input, Button, Alert } from 'antd'; +import { Form, Input, Button, Alert } from 'antd'; import { useAuthStore } from '@/store/authStore'; +import './ProfileSettings.css'; const Settings: React.FC = () => { const user = useAuthStore((state) => state.user); @@ -13,12 +14,13 @@ const Settings: React.FC = () => { return ( -
- +
+
+

个人信息

@@ -50,7 +52,7 @@ const Settings: React.FC = () => { - +
); }; diff --git a/apps/web/src/pages/subscription/Billing.tsx b/apps/web/src/pages/subscription/Billing.tsx index 411e712df..b79a7cd1d 100644 --- a/apps/web/src/pages/subscription/Billing.tsx +++ b/apps/web/src/pages/subscription/Billing.tsx @@ -1,13 +1,14 @@ import React from 'react'; -import { Button, Card, Result } from 'antd'; +import { Button, Result } from 'antd'; import { useNavigate } from 'react-router-dom'; +import '../profile/ProfileSettings.css'; const Billing: React.FC = () => { const navigate = useNavigate(); return ( -
- +
+
{ , ]} /> - +
); }; diff --git a/apps/web/src/pages/subscription/UpgradeSubscription.tsx b/apps/web/src/pages/subscription/UpgradeSubscription.tsx index d784866aa..9b3f87c38 100644 --- a/apps/web/src/pages/subscription/UpgradeSubscription.tsx +++ b/apps/web/src/pages/subscription/UpgradeSubscription.tsx @@ -1,14 +1,15 @@ import React from 'react'; -import { Button, Card, Result } from 'antd'; +import { Button, Result } from 'antd'; import { useNavigate, useParams } from 'react-router-dom'; +import '../profile/ProfileSettings.css'; const UpgradeSubscription: React.FC = () => { const { workspaceId } = useParams<{ workspaceId: string }>(); const navigate = useNavigate(); return ( -
- +
+
{ ) : null, ]} /> - +
); }; diff --git a/apps/web/src/pages/workspace/WorkspaceDetail.tsx b/apps/web/src/pages/workspace/WorkspaceDetail.tsx index 6ac291b06..0d95e4cc6 100644 --- a/apps/web/src/pages/workspace/WorkspaceDetail.tsx +++ b/apps/web/src/pages/workspace/WorkspaceDetail.tsx @@ -1,5 +1,5 @@ /** - * 工作空间详情页面 + * 工作空间详情页面 - V21 UI */ import React, { useState } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; @@ -11,6 +11,7 @@ import { createProject, getProjects } from '@/api/projects'; import MemberList from '@/components/business/MemberList'; import InviteMemberModal from '@/components/business/InviteMemberModal'; import PermissionMatrix from '@/components/business/PermissionMatrix'; +import '@/components/business/business.css'; const WorkspaceDetail: React.FC = () => { const { id } = useParams<{ id: string }>(); @@ -50,20 +51,20 @@ const WorkspaceDetail: React.FC = () => { }); }; - if (isLoading) return
加载中...
; - if (!workspace) return
工作空间不存在
; + if (isLoading) return
加载中...
; + if (!workspace) return
工作空间不存在
; const items = [ { key: 'overview', label: '概览', children: ( -
+
setCreateProjectOpen(true)}> + } @@ -80,7 +81,7 @@ const WorkspaceDetail: React.FC = () => { - + {projectsQuery.isError && ( )} @@ -131,18 +132,25 @@ const WorkspaceDetail: React.FC = () => { ), children: ( -
-
+
+
+
+

工作空间成员

+

管理有权访问此工作空间的成员

+
- -
+
+ +
+
@@ -151,13 +159,18 @@ const WorkspaceDetail: React.FC = () => { { key: 'settings', label: '设置', - children:
工作空间设置(待开发)
, + children:

工作空间设置(待开发)

, }, ]; return ( -
-

{workspace.name}

+
+
+
+

{workspace.name}

+

工作空间详情与成员管理

+
+
{ confirmLoading={createProjectMutation.isPending} onOk={handleCreateProject} onCancel={() => setCreateProjectOpen(false)} + className="xx-modal" >