From 743549600ab7009ae1b00a020e0d3d61edbf7d04 Mon Sep 17 00:00:00 2001 From: ZhuRui Date: Tue, 28 Jul 2026 10:54:36 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20less=E8=A7=84=E8=8C=83=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../styles}/pageLayout.module.less | 0 src/components/ChangePasswordModal/index.tsx | 1 + .../ChangePasswordModal/style.module.less | 61 +- src/components/HelloWorld.module.less | 20 +- src/components/HelloWorld.tsx | 2 +- src/components/index.ts | 2 +- src/components/page/PageTabs.module.less | 185 --- src/components/pageTabs/PageTabs.module.less | 164 +++ .../{page => pageTabs}/PageTabs.tsx | 2 +- src/layouts/BasicLayout.module.less | 223 ++-- src/layouts/BasicLayout.tsx | 2 +- src/pages/about/index.module.less | 32 +- src/pages/about/index.tsx | 2 +- src/pages/dashboard/index.module.less | 44 +- src/pages/dashboard/index.tsx | 2 +- .../components/BannerFormModal.module.less | 237 ++-- .../banner/components/BannerFormModal.tsx | 1 + src/pages/events/banner/index.module.less | 23 +- src/pages/events/banner/index.tsx | 68 +- .../components/EventAuditModal.module.less | 98 +- .../list/components/EventAuditModal.tsx | 1 + .../components/EventDetailModal.module.less | 113 +- .../list/components/EventDetailModal.tsx | 1 + .../EventRegulationModal.module.less | 90 +- .../list/components/EventRegulationModal.tsx | 1 + src/pages/events/list/index.module.less | 27 +- src/pages/events/list/index.tsx | 64 +- .../components/OrderDetailModal.module.less | 358 +++-- .../orders/components/OrderDetailModal.tsx | 254 ++-- src/pages/events/orders/index.module.less | 61 +- src/pages/events/orders/index.tsx | 92 +- src/pages/events/users/index.module.less | 27 +- src/pages/events/users/index.tsx | 60 +- src/pages/login/index.module.less | 1184 ++++++++--------- src/pages/login/index.tsx | 2 +- .../components/RoleFormModal.module.less | 56 +- .../system/roles/components/RoleFormModal.tsx | 1 + .../components/UserListModal.module.less | 40 +- .../system/roles/components/UserListModal.tsx | 1 + src/pages/system/roles/index.module.less | 66 +- src/pages/system/roles/index.tsx | 78 +- .../components/UserFormModal.module.less | 85 +- .../system/users/components/UserFormModal.tsx | 1 + src/pages/system/users/index.module.less | 60 +- src/pages/system/users/index.tsx | 72 +- 45 files changed, 1953 insertions(+), 2011 deletions(-) rename src/{components/page => assets/styles}/pageLayout.module.less (100%) delete mode 100644 src/components/page/PageTabs.module.less create mode 100644 src/components/pageTabs/PageTabs.module.less rename src/components/{page => pageTabs}/PageTabs.tsx (98%) diff --git a/src/components/page/pageLayout.module.less b/src/assets/styles/pageLayout.module.less similarity index 100% rename from src/components/page/pageLayout.module.less rename to src/assets/styles/pageLayout.module.less diff --git a/src/components/ChangePasswordModal/index.tsx b/src/components/ChangePasswordModal/index.tsx index 4c61711..115a973 100644 --- a/src/components/ChangePasswordModal/index.tsx +++ b/src/components/ChangePasswordModal/index.tsx @@ -61,6 +61,7 @@ export default defineComponent({ destroyOnClose footer={null} centered + wrapClassName={styles.changePasswordModalMain} class={styles.modal} >
diff --git a/src/components/ChangePasswordModal/style.module.less b/src/components/ChangePasswordModal/style.module.less index 4d622b2..4606684 100644 --- a/src/components/ChangePasswordModal/style.module.less +++ b/src/components/ChangePasswordModal/style.module.less @@ -1,37 +1,36 @@ -.form { - :global { - .ant-form-item { - margin-bottom: 16px; - } - .ant-form-item-explain-error { - font-size: 12px; +.changePasswordModalMain { + .modal { + :global { + .ant-modal-body { + padding: 16px 24px 0; + } } } -} -/* 底部提示文案 */ -.tip { - margin-top: -4px; - margin-bottom: 24px; - color: rgba(0, 0, 0, 0.45); - font-size: 12px; - line-height: 1.5; -} - -/* 底部按钮 */ -.footer { - display: flex; - justify-content: flex-end; - gap: 8px; - padding-top: 16px; - border-top: 1px solid #f0f0f0; -} - -/* 微调 Modal 内部样式 */ -.modal { - :global { - .ant-modal-body { - padding: 16px 24px 0; + .form { + :global { + .ant-form-item { + margin-bottom: 16px; + } + .ant-form-item-explain-error { + font-size: 12px; + } } } + + .tip { + margin-top: -4px; + margin-bottom: 24px; + color: rgba(0, 0, 0, 0.45); + font-size: 12px; + line-height: 1.5; + } + + .footer { + display: flex; + justify-content: flex-end; + gap: 8px; + padding-top: 16px; + border-top: 1px solid #f0f0f0; + } } diff --git a/src/components/HelloWorld.module.less b/src/components/HelloWorld.module.less index eaab200..32d823a 100644 --- a/src/components/HelloWorld.module.less +++ b/src/components/HelloWorld.module.less @@ -1,16 +1,16 @@ -.container { +.helloWorldMain { text-align: center; padding: 16px; -} -.title { - color: #1677ff; -} + .title { + color: #1677ff; + } -.desc { - code { - background: #f5f5f5; - padding: 2px 6px; - border-radius: 4px; + .desc { + code { + background: #f5f5f5; + padding: 2px 6px; + border-radius: 4px; + } } } diff --git a/src/components/HelloWorld.tsx b/src/components/HelloWorld.tsx index 1b59629..b7fd3bb 100644 --- a/src/components/HelloWorld.tsx +++ b/src/components/HelloWorld.tsx @@ -14,7 +14,7 @@ export default defineComponent({ }, setup(props) { return () => ( -
+

{props.msg}

这是一个公共组件示例,采用 TSX 写法。你可以在 diff --git a/src/components/index.ts b/src/components/index.ts index 1915fb5..cfe65a6 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -4,4 +4,4 @@ */ export { default as HelloWorld } from './HelloWorld'; export { default as ChangePasswordModal } from './ChangePasswordModal'; -export { default as PageTabs } from './page/PageTabs'; +export { default as PageTabs } from './pageTabs/PageTabs'; diff --git a/src/components/page/PageTabs.module.less b/src/components/page/PageTabs.module.less deleted file mode 100644 index 3a48c49..0000000 --- a/src/components/page/PageTabs.module.less +++ /dev/null @@ -1,185 +0,0 @@ -/** - * PageTabs — Chrome 风格标签栏样式 - * - * 参考 VBEN tabs-chrome 的视觉设计: - * - 标签间通过负 margin 重叠 - * - 激活态使用 SVG 绘制左下/右下曲线填充,形成 Chrome tab 效果 - * - hover 态浅灰背景 - * - 分隔线在相邻非激活标签之间 - */ - -// 主色调(antd 默认蓝) -@primary: #1677ff; - -.tabsWrap { - display: flex; - align-items: center; - width: 100%; - height: 100%; - overflow-x: auto; - overflow-y: hidden; - // 隐藏横向滚动条 - &::-webkit-scrollbar { - height: 0; - } -} - -.tabItem { - position: relative; - display: flex; - align-items: center; - height: 100%; - user-select: none; - transition: all 0.15s ease; - padding: 0 8px 0 14px; - - &:global(:not(.dragging)) { - cursor: pointer; - } - - // ── hover 态(非激活) ── - &:not(.tabItemActive) { - &:hover { - // 自身分隔线消失 - > .divider { - opacity: 0; - } - // 右侧邻居的分隔线也消失 - & + .tabItem { - > .divider { - opacity: 0; - } - } - } - } - - // ── 激活态 ── - &.tabItemActive { - z-index: 2; - // 右侧邻居的分隔线消失 - & + .tabItem { - > .divider { - opacity: 0 !important; - } - } - // 文字激活色 - .tabTitle { - color: @primary; - font-weight: 500; - } - // 背景蓝色 - .tabBg { - &.tabBgActive { - .tabBgInner { - background-color: fade(@primary, 8%); - } - .tabBgCurveBefore, - .tabBgCurveAfter { - fill: fade(@primary, 8%); - } - } - } - } -} - -// ── 分隔线 ── -.divider { - position: absolute; - left: 7px; - top: 50%; - z-index: 0; - width: 1px; - height: 16px; - background-color: #e8e8e8; - transform: translateY(-50%); - transition: opacity 0.15s; -} - -// ── Chrome 风格背景层(激活态可见,hover 态可见但偏浅) ── -.tabBg { - position: absolute; - top: 0; - left: 0; - z-index: -1; - width: 100%; - height: 100%; - padding: 0 calc(7px - 1px); - transition: opacity 0.15s; -} - -// 背景主体:顶部圆角 -.tabBgInner { - height: 100%; - border-radius: 7px 7px 0 0; - transition: - background-color 0.15s, - margin 0.15s, - border-radius 0.15s; -} - -// 左下 SVG 曲线 -.tabBgCurveBefore { - position: absolute; - left: -1px; - bottom: 0; - fill: transparent; - transition: fill 0.15s; -} - -// 右下 SVG 曲线 -.tabBgCurveAfter { - position: absolute; - right: -1px; - bottom: 0; - fill: transparent; - transition: fill 0.15s; -} - -// ── 关闭按钮(flex 子元素,文字同行自然居中) ── -.tabClose { - flex-shrink: 0; - width: 16px; - height: 16px; - line-height: 16px; - font-size: 10px; - text-align: center; - margin-right: 12px; - color: rgba(0, 0, 0, 0.45); - border-radius: 50%; - cursor: pointer; - transition: all 0.15s; - - &:hover { - color: rgba(0, 0, 0, 0.85); - background-color: rgba(0, 0, 0, 0.06); - } -} - -.tabTitleCon { - height: 28px; - display: flex; - justify-content: center; - align-items: center; - border-radius: 4px; -} - -// hover 只在非激活标签时生效 -.tabItem:not(.tabItemActive) { - .tabTitleCon:hover { - background-color: rgba(0, 0, 0, 0.06); - } -} - -// ── 标签文字(flex 子元素,可收缩) ── -.tabTitle { - position: relative; - z-index: 2; - flex: 1; - min-width: 0; - padding: 2px 8px; - font-size: 13px; - color: rgba(0, 0, 0, 0.65); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} diff --git a/src/components/pageTabs/PageTabs.module.less b/src/components/pageTabs/PageTabs.module.less new file mode 100644 index 0000000..fe8a93d --- /dev/null +++ b/src/components/pageTabs/PageTabs.module.less @@ -0,0 +1,164 @@ +@primary: #1677ff; + +.pageTabsMain { + display: flex; + align-items: center; + width: 100%; + height: 100%; + overflow-x: auto; + overflow-y: hidden; + + &::-webkit-scrollbar { + height: 0; + } + + .tabItem { + position: relative; + display: flex; + align-items: center; + height: 100%; + user-select: none; + transition: all 0.15s ease; + padding: 0 8px 0 14px; + + &:global(:not(.dragging)) { + cursor: pointer; + } + + &:not(.tabItemActive) { + &:hover { + > .divider { + opacity: 0; + } + + & + .tabItem { + > .divider { + opacity: 0; + } + } + } + } + + &.tabItemActive { + z-index: 2; + + & + .tabItem { + > .divider { + opacity: 0 !important; + } + } + + .tabTitle { + color: @primary; + font-weight: 500; + } + + .tabBg { + &.tabBgActive { + .tabBgInner { + background-color: fade(@primary, 8%); + } + + .tabBgCurveBefore, + .tabBgCurveAfter { + fill: fade(@primary, 8%); + } + } + } + } + + &:not(.tabItemActive) { + .tabTitleCon:hover { + background-color: rgba(0, 0, 0, 0.06); + } + } + } + + .divider { + position: absolute; + left: 7px; + top: 50%; + z-index: 0; + width: 1px; + height: 16px; + background-color: #e8e8e8; + transform: translateY(-50%); + transition: opacity 0.15s; + } + + .tabBg { + position: absolute; + top: 0; + left: 0; + z-index: -1; + width: 100%; + height: 100%; + padding: 0 calc(7px - 1px); + transition: opacity 0.15s; + } + + .tabBgInner { + height: 100%; + border-radius: 7px 7px 0 0; + transition: + background-color 0.15s, + margin 0.15s, + border-radius 0.15s; + } + + .tabBgCurveBefore { + position: absolute; + left: -1px; + bottom: 0; + fill: transparent; + transition: fill 0.15s; + } + + .tabBgCurveAfter { + position: absolute; + right: -1px; + bottom: 0; + fill: transparent; + transition: fill 0.15s; + } + + .tabClose { + flex-shrink: 0; + width: 16px; + height: 16px; + line-height: 16px; + font-size: 10px; + text-align: center; + margin-right: 12px; + color: rgba(0, 0, 0, 0.45); + border-radius: 50%; + cursor: pointer; + transition: all 0.15s; + + &:hover { + color: rgba(0, 0, 0, 0.85); + background-color: rgba(0, 0, 0, 0.06); + } + } + + .tabTitleCon { + height: 28px; + display: flex; + justify-content: center; + align-items: center; + border-radius: 4px; + } + + .tabTitle { + position: relative; + z-index: 2; + flex: 1; + min-width: 0; + padding: 2px 8px; + font-size: 13px; + color: rgba(0, 0, 0, 0.65); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } +} diff --git a/src/components/page/PageTabs.tsx b/src/components/pageTabs/PageTabs.tsx similarity index 98% rename from src/components/page/PageTabs.tsx rename to src/components/pageTabs/PageTabs.tsx index 6ea3cd3..fa0d8df 100644 --- a/src/components/page/PageTabs.tsx +++ b/src/components/pageTabs/PageTabs.tsx @@ -43,7 +43,7 @@ const PageTabs = defineComponent({ }; return () => ( -

+
{props.tabs.map((tab, i) => { const isActive = tab.path === props.activeKey; return ( diff --git a/src/layouts/BasicLayout.module.less b/src/layouts/BasicLayout.module.less index 02d1ac5..910da44 100644 --- a/src/layouts/BasicLayout.module.less +++ b/src/layouts/BasicLayout.module.less @@ -1,133 +1,128 @@ -.container { +.basicLayoutMain { min-height: 100vh; height: 100vh; -} -.logo { - height: 56px; - display: flex; - align-items: center; - justify-content: center; - overflow: hidden; - color: #1a1a1a; - background: #fff; -} - -.logoText { - font-size: 16px; - font-weight: 600; - white-space: nowrap; -} - -.trigger { - font-size: 18px; - cursor: pointer; - transition: color 0.3s; - padding: 0 12px; - display: inline-flex; - align-items: center; - - &:hover { - color: #1677ff; + .logo { + height: 56px; + display: flex; + align-items: center; + justify-content: center; + overflow: hidden; + color: #1a1a1a; + background: #fff; } -} -// 面包屑 -.breadcrumb { - flex: 1; - margin-left: 8px; - font-size: 14px; + .logoText { + font-size: 16px; + font-weight: 600; + white-space: nowrap; + } - :global { - .ant-breadcrumb-link, - .ant-breadcrumb-separator, - .ant-breadcrumb-item a { - color: rgba(0, 0, 0, 0.65); + .trigger { + font-size: 18px; + cursor: pointer; + transition: color 0.3s; + padding: 0 12px; + display: inline-flex; + align-items: center; + + &:hover { + color: #1677ff; } + } - .ant-breadcrumb-item:last-child { + .breadcrumb { + flex: 1; + margin-left: 8px; + font-size: 14px; + + :global { .ant-breadcrumb-link, .ant-breadcrumb-separator, - a { - color: rgba(0, 0, 0, 0.88); - font-weight: 500; - cursor: default; + .ant-breadcrumb-item a { + color: rgba(0, 0, 0, 0.65); + } + + .ant-breadcrumb-item:last-child { + .ant-breadcrumb-link, + .ant-breadcrumb-separator, + a { + color: rgba(0, 0, 0, 0.88); + font-weight: 500; + cursor: default; + } } } } -} -// Header 右侧:账号信息 + 退出图标 -.headerRight { - margin-left: auto; - display: flex; - gap: 10px; - align-items: center; -} - -.userPhone { - font-size: 14px; - color: rgba(0, 0, 0, 0.65); -} - -.logoutIcon { - width: 18px; - height: 18px; - opacity: 0.45; - cursor: pointer; - transition: opacity 0.3s; - - &:hover { - opacity: 1; + .headerRight { + margin-left: auto; + display: flex; + gap: 10px; + align-items: center; } -} -// 下拉菜单项:图标 + 文字 -.menuItem { - display: inline-flex; - align-items: center; - gap: 8px; - - :global(.anticon) { + .userPhone { font-size: 14px; + color: rgba(0, 0, 0, 0.65); + } + + .logoutIcon { + width: 18px; + height: 18px; + opacity: 0.45; + cursor: pointer; + transition: opacity 0.3s; + + &:hover { + opacity: 1; + } + } + + .menuItem { + display: inline-flex; + align-items: center; + gap: 8px; + + :global(.anticon) { + font-size: 14px; + } + } + + .menuItemDanger { + color: #ff4d4f; + } + + .content { + margin: 16px; + border-radius: 8px; + flex: 1; + min-height: 0; + display: flex; + flex-direction: column; + overflow: hidden; + } + + .main { + flex: 1; + min-height: 0; + display: flex; + flex-direction: column; + } + + .headerRow { + padding: 0 16px; + width: 100%; + height: 48px; + display: flex; + align-items: center; + } + + .pageTabs { + width: 100%; + padding: 4px 16px 0 16px; + height: 42px; + background: #fff; + border-top: 1px solid #f0f0f0; } } - -.menuItemDanger { - color: #ff4d4f; -} - -.content { - margin: 16px; - border-radius: 8px; - flex: 1; - min-height: 0; - display: flex; - flex-direction: column; - overflow: hidden; -} - -.main { - flex: 1; - min-height: 0; - display: flex; - flex-direction: column; -} - -// ── 顶部行:原 Header 中的三个区域(折叠按钮 / 面包屑 / 右侧账号信息)整体包成一个 row ── -.headerRow { - padding: 0 16px; - width: 100%; - height: 48px; - display: flex; - align-items: center; -} - -// ── 页面标签栏容器(Chrome 风格 PageTabs 的外壳) ── -.pageTabs { - width: 100%; - padding: 4px 16px 0 16px; - height: 42px; - background: #fff; - border-top: 1px solid #f0f0f0; -} diff --git a/src/layouts/BasicLayout.tsx b/src/layouts/BasicLayout.tsx index dbbddf3..d9d59cf 100644 --- a/src/layouts/BasicLayout.tsx +++ b/src/layouts/BasicLayout.tsx @@ -173,7 +173,7 @@ export default defineComponent({ }; return () => ( - +
{collapsed.value ? '6羽' : '六羽赛事运营平台'} diff --git a/src/pages/about/index.module.less b/src/pages/about/index.module.less index c52f57c..14af90d 100644 --- a/src/pages/about/index.module.less +++ b/src/pages/about/index.module.less @@ -1,20 +1,18 @@ -.container { - // 容器 -} +.aboutMain { + .title { + margin-top: 0; + margin-bottom: 24px; + font-size: 20px; + font-weight: 600; + } -.title { - margin-top: 0; - margin-bottom: 24px; - font-size: 20px; - font-weight: 600; -} + .subtitle { + margin: 16px 0 8px; + } -.subtitle { - margin: 16px 0 8px; -} - -.list { - margin: 0; - padding-left: 20px; - line-height: 2; + .list { + margin: 0; + padding-left: 20px; + line-height: 2; + } } diff --git a/src/pages/about/index.tsx b/src/pages/about/index.tsx index b4e7084..be3e1e1 100644 --- a/src/pages/about/index.tsx +++ b/src/pages/about/index.tsx @@ -23,7 +23,7 @@ export default defineComponent({ ]; return () => ( -
+

关于

CPMS 运营平台前端 PC 端。

diff --git a/src/pages/dashboard/index.module.less b/src/pages/dashboard/index.module.less index e816330..3ebc662 100644 --- a/src/pages/dashboard/index.module.less +++ b/src/pages/dashboard/index.module.less @@ -1,27 +1,25 @@ -.container { - // 容器 -} - -.title { - margin-top: 0; - margin-bottom: 24px; - font-size: 20px; - font-weight: 600; -} - -.panel { - margin-top: 16px; - - ul { - margin: 12px 0 0; - padding-left: 20px; - line-height: 2; +.dashboardMain { + .title { + margin-top: 0; + margin-bottom: 24px; + font-size: 20px; + font-weight: 600; } - code { - padding: 2px 8px; - background: #f5f5f5; - border-radius: 4px; - font-size: 13px; + .panel { + margin-top: 16px; + + ul { + margin: 12px 0 0; + padding-left: 20px; + line-height: 2; + } + + code { + padding: 2px 8px; + background: #f5f5f5; + border-radius: 4px; + font-size: 13px; + } } } diff --git a/src/pages/dashboard/index.tsx b/src/pages/dashboard/index.tsx index 489e275..4a93e13 100644 --- a/src/pages/dashboard/index.tsx +++ b/src/pages/dashboard/index.tsx @@ -23,7 +23,7 @@ export default defineComponent({ ]; return () => ( -
+

工作台

diff --git a/src/pages/events/banner/components/BannerFormModal.module.less b/src/pages/events/banner/components/BannerFormModal.module.less index 8d3a844..5259e15 100644 --- a/src/pages/events/banner/components/BannerFormModal.module.less +++ b/src/pages/events/banner/components/BannerFormModal.module.less @@ -1,133 +1,130 @@ -.form { - :global { - .ant-form-item { - margin-bottom: 16px; - } - .ant-form-item-explain-error { - font-size: 12px; +.bannerFormModalMain { + .form { + :global { + .ant-form-item { + margin-bottom: 16px; + } + .ant-form-item-explain-error { + font-size: 12px; + } } } -} -/* ===== 上传 ===== */ -.uploader { - position: relative; -} - -.uploadCard { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - width: 100%; - height: 140px; - border: 1px dashed #d9d9d9; - border-radius: 6px; - background-color: #fafafa; - cursor: pointer; - transition: border-color 0.2s; - gap: 4px; - - &:hover { - border-color: #1677ff; + .uploader { + position: relative; } -} -.uploadCardError { - border-color: #ff4d4f; -} + .uploadCard { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + width: 100%; + height: 140px; + border: 1px dashed #d9d9d9; + border-radius: 6px; + background-color: #fafafa; + cursor: pointer; + transition: border-color 0.2s; + gap: 4px; -.uploadIcon { - font-size: 32px; - color: #999; - font-weight: 300; - line-height: 1; -} - -.uploadHint { - color: #666; - font-size: 14px; -} - -.uploadTip { - color: #999; - font-size: 12px; - text-align: center; - line-height: 1.6; -} - -/* ===== 预览 ===== */ -.previewWrapper { - position: relative; - width: 100%; - height: 140px; - border: 1px solid #d9d9d9; - border-radius: 6px; - overflow: hidden; - background-color: #f5f5f5; - - :global { - .ant-spin-nested-loading, - .ant-spin-container { - width: 100%; - height: 100%; + &:hover { + border-color: #1677ff; } } -} -.previewImg { - width: 100%; - height: 100%; - object-fit: cover; - display: block; -} + .uploadCardError { + border-color: #ff4d4f; + } -.uploadAgainBtn { - position: absolute; - bottom: 0; - left: 0; - right: 0; - background: rgba(0, 0, 0, 0.5); - color: #fff; - text-align: center; - padding: 4px 0; - cursor: pointer; - font-size: 12px; - user-select: none; - transition: background 0.2s; + .uploadIcon { + font-size: 32px; + color: #999; + font-weight: 300; + line-height: 1; + } - &:hover { - background: rgba(0, 0, 0, 0.65); + .uploadHint { + color: #666; + font-size: 14px; + } + + .uploadTip { + color: #999; + font-size: 12px; + text-align: center; + line-height: 1.6; + } + + .previewWrapper { + position: relative; + width: 100%; + height: 140px; + border: 1px solid #d9d9d9; + border-radius: 6px; + overflow: hidden; + background-color: #f5f5f5; + + :global { + .ant-spin-nested-loading, + .ant-spin-container { + width: 100%; + height: 100%; + } + } + } + + .previewImg { + width: 100%; + height: 100%; + object-fit: cover; + display: block; + } + + .uploadAgainBtn { + position: absolute; + bottom: 0; + left: 0; + right: 0; + background: rgba(0, 0, 0, 0.5); + color: #fff; + text-align: center; + padding: 4px 0; + cursor: pointer; + font-size: 12px; + user-select: none; + transition: background 0.2s; + + &:hover { + background: rgba(0, 0, 0, 0.65); + } + } + + .tip { + padding: 8px 12px; + margin-bottom: 16px; + background-color: #f0f5ff; + border: 1px solid #d6e4ff; + border-radius: 4px; + color: #1677ff; + font-size: 13px; + } + + .timeRow { + display: flex; + gap: 16px; + + .timeItem { + flex: 1; + } + } + + .footer { + display: flex; + justify-content: flex-end; + gap: 8px; + padding-top: 16px; + border-top: 1px solid #f0f0f0; + margin-top: 8px; } } - -/* ===== 提示 ===== */ -.tip { - padding: 8px 12px; - margin-bottom: 16px; - background-color: #f0f5ff; - border: 1px solid #d6e4ff; - border-radius: 4px; - color: #1677ff; - font-size: 13px; -} - -/* ===== 时间行(双列)===== */ -.timeRow { - display: flex; - gap: 16px; - - .timeItem { - flex: 1; - } -} - -/* ===== 底部按钮 ===== */ -.footer { - display: flex; - justify-content: flex-end; - gap: 8px; - padding-top: 16px; - border-top: 1px solid #f0f0f0; - margin-top: 8px; -} diff --git a/src/pages/events/banner/components/BannerFormModal.tsx b/src/pages/events/banner/components/BannerFormModal.tsx index d4f3feb..7630878 100644 --- a/src/pages/events/banner/components/BannerFormModal.tsx +++ b/src/pages/events/banner/components/BannerFormModal.tsx @@ -266,6 +266,7 @@ export default defineComponent({ destroyOnClose footer={null} centered + wrapClassName={styles.bannerFormModalMain} > {/* ===== Banner 标题 ===== */} diff --git a/src/pages/events/banner/index.module.less b/src/pages/events/banner/index.module.less index 822b766..d7c3c7d 100644 --- a/src/pages/events/banner/index.module.less +++ b/src/pages/events/banner/index.module.less @@ -1,14 +1,21 @@ -.tableBody { +.eventBannerMain { flex: 1; min-height: 0; - overflow: hidden; + display: flex; + flex-direction: column; - :global { - .ant-spin-nested-loading, - .ant-spin-container, - .ant-table, - .ant-table-container { - height: 100%; + .tableBody { + flex: 1; + min-height: 0; + overflow: hidden; + + :global { + .ant-spin-nested-loading, + .ant-spin-container, + .ant-table, + .ant-table-container { + height: 100%; + } } } } diff --git a/src/pages/events/banner/index.tsx b/src/pages/events/banner/index.tsx index c8751bc..e54c205 100644 --- a/src/pages/events/banner/index.tsx +++ b/src/pages/events/banner/index.tsx @@ -15,7 +15,7 @@ import { useBannerModel, BANNER_STATUS_OPTIONS } from './model/useBannerModel'; import { useContainerSize } from '@/hooks'; import BannerFormModal from './components/BannerFormModal'; import styles from './index.module.less'; -import pageStyles from '@/components/page/pageLayout.module.less'; +import pageStyles from '@/assets/styles/pageLayout.module.less'; /** * bodyCell 渲染函数 @@ -231,39 +231,41 @@ export default defineComponent({ {/* ===== 表格区 ===== */}
-
- - {{ - bodyCell: (args: any) => - renderBodyCell({ - ...args, - renderJumpType, - renderStatus, - onEdit: handleEdit, - onToggleStatus: confirmToggleStatus, - onDelete: confirmDelete, - }), - }} -
-
+
+
+ + {{ + bodyCell: (args: any) => + renderBodyCell({ + ...args, + renderJumpType, + renderStatus, + onEdit: handleEdit, + onToggleStatus: confirmToggleStatus, + onDelete: confirmDelete, + }), + }} +
+
- {/* 独立分页,右下方 */} -
- `共 ${total} 条`} - onChange={handlePageChange} - onShowSizeChange={handlePageChange} - /> + {/* 独立分页,右下方 */} +
+ `共 ${total} 条`} + onChange={handlePageChange} + onShowSizeChange={handlePageChange} + /> +
diff --git a/src/pages/events/list/components/EventAuditModal.module.less b/src/pages/events/list/components/EventAuditModal.module.less index 466a126..cc88632 100644 --- a/src/pages/events/list/components/EventAuditModal.module.less +++ b/src/pages/events/list/components/EventAuditModal.module.less @@ -1,59 +1,61 @@ -.section { - margin-bottom: 24px; -} +.eventAuditModalMain { + .section { + margin-bottom: 24px; -.section:last-child { - margin-bottom: 0; -} + &:last-child { + margin-bottom: 0; + } + } -.sectionTitle { - font-size: 14px; - font-weight: 600; - color: rgba(0, 0, 0, 0.85); - margin-bottom: 12px; - padding-left: 8px; - border-left: 3px solid #1677ff; -} + .sectionTitle { + font-size: 14px; + font-weight: 600; + color: rgba(0, 0, 0, 0.85); + margin-bottom: 12px; + padding-left: 8px; + border-left: 3px solid #1677ff; + } -.desc :global(.ant-descriptions-item-label) { - width: 110px; - color: rgba(0, 0, 0, 0.65); -} + .desc { + :global(.ant-descriptions-item-label) { + width: 110px; + color: rgba(0, 0, 0, 0.65); + } + } -// ── 审核操作区域 ── -.auditSection { - margin-top: 24px; -} + .auditSection { + margin-top: 24px; + } -.auditHeader { - display: flex; - align-items: center; - margin-bottom: 16px; -} + .auditHeader { + display: flex; + align-items: center; + margin-bottom: 16px; + } -.auditTitle { - font-size: 14px; - font-weight: 600; - color: rgba(0, 0, 0, 0.85); - padding-left: 8px; - border-left: 3px solid #1677ff; -} + .auditTitle { + font-size: 14px; + font-weight: 600; + color: rgba(0, 0, 0, 0.85); + padding-left: 8px; + border-left: 3px solid #1677ff; + } -.auditForm { - // 横线分隔标题与表单 - border-top: 1px solid #f0f0f0; - padding-top: 16px; -} + .auditForm { + border-top: 1px solid #f0f0f0; + padding-top: 16px; + } -.auditField { - margin-bottom: 16px; + .auditField { + margin-bottom: 16px; - :global(.ant-form-item-label) { - font-weight: 500; - color: rgba(0, 0, 0, 0.65); + &:last-child { + margin-bottom: 0; + } + + :global(.ant-form-item-label) { + font-weight: 500; + color: rgba(0, 0, 0, 0.65); + } } } - -.auditField:last-child { - margin-bottom: 0; -} diff --git a/src/pages/events/list/components/EventAuditModal.tsx b/src/pages/events/list/components/EventAuditModal.tsx index 33c20c6..0803e0e 100644 --- a/src/pages/events/list/components/EventAuditModal.tsx +++ b/src/pages/events/list/components/EventAuditModal.tsx @@ -80,6 +80,7 @@ export default defineComponent({ cancelText="取消" centered destroyOnClose + wrapClassName={styles.eventAuditModalMain} > {/* ===== 基础信息 ===== */}
diff --git a/src/pages/events/list/components/EventDetailModal.module.less b/src/pages/events/list/components/EventDetailModal.module.less index d5e26b7..7d4652f 100644 --- a/src/pages/events/list/components/EventDetailModal.module.less +++ b/src/pages/events/list/components/EventDetailModal.module.less @@ -1,67 +1,68 @@ -.section { - margin-bottom: 24px; -} +.eventDetailModalMain { + .section { + margin-bottom: 24px; -.section:last-child { - margin-bottom: 0; -} + &:last-child { + margin-bottom: 0; + } + } -.sectionTitle { - font-size: 14px; - font-weight: 600; - color: rgba(0, 0, 0, 0.85); - margin-bottom: 12px; - padding-left: 8px; - border-left: 3px solid #1677ff; -} + .sectionTitle { + font-size: 14px; + font-weight: 600; + color: rgba(0, 0, 0, 0.85); + margin-bottom: 12px; + padding-left: 8px; + border-left: 3px solid #1677ff; + } -.textBlock { - font-size: 13px; - line-height: 1.8; - color: rgba(0, 0, 0, 0.65); - white-space: pre-wrap; - background: #fafafa; - padding: 12px 16px; - border-radius: 4px; - border: 1px solid #f0f0f0; -} + .textBlock { + font-size: 13px; + line-height: 1.8; + color: rgba(0, 0, 0, 0.65); + white-space: pre-wrap; + background: #fafafa; + padding: 12px 16px; + border-radius: 4px; + border: 1px solid #f0f0f0; + } -// Descriptions 列宽稍微压缩一些,避免单标签被挤 -.desc :global(.ant-descriptions-item-label) { - width: 110px; - color: rgba(0, 0, 0, 0.65); -} + .desc { + :global(.ant-descriptions-item-label) { + width: 110px; + color: rgba(0, 0, 0, 0.65); + } + } -// 组别信息下的子表格 -.group { - margin-bottom: 16px; -} + .group { + margin-bottom: 16px; -.group:last-child { - margin-bottom: 0; -} + &:last-child { + margin-bottom: 0; + } + } -.groupTitle { - font-size: 13px; - color: rgba(0, 0, 0, 0.85); - margin-bottom: 8px; - font-weight: 500; -} + .groupTitle { + font-size: 13px; + color: rgba(0, 0, 0, 0.85); + margin-bottom: 8px; + font-weight: 500; + } -.paginationRow { - display: flex; - justify-content: flex-end; - margin-top: 8px; -} + .paginationRow { + display: flex; + justify-content: flex-end; + margin-top: 8px; + } -// 分组信息列表 -.divisionList { - display: flex; - flex-direction: column; - gap: 6px; -} + .divisionList { + display: flex; + flex-direction: column; + gap: 6px; + } -.divisionItem { - font-size: 13px; - color: rgba(0, 0, 0, 0.65); + .divisionItem { + font-size: 13px; + color: rgba(0, 0, 0, 0.65); + } } diff --git a/src/pages/events/list/components/EventDetailModal.tsx b/src/pages/events/list/components/EventDetailModal.tsx index 279a8a6..0644989 100644 --- a/src/pages/events/list/components/EventDetailModal.tsx +++ b/src/pages/events/list/components/EventDetailModal.tsx @@ -110,6 +110,7 @@ export default defineComponent({ footer={null} centered destroyOnClose + wrapClassName={styles.eventDetailModalMain} > {/* ===== 基础信息 ===== */}
diff --git a/src/pages/events/list/components/EventRegulationModal.module.less b/src/pages/events/list/components/EventRegulationModal.module.less index c86aad7..e8b5048 100644 --- a/src/pages/events/list/components/EventRegulationModal.module.less +++ b/src/pages/events/list/components/EventRegulationModal.module.less @@ -1,51 +1,53 @@ -.section { - margin-bottom: 20px; -} +.eventRegulationModalMain { + .section { + margin-bottom: 20px; -.section:last-child { - margin-bottom: 0; -} + &:last-child { + margin-bottom: 0; + } + } -.sectionTitle { - font-size: 14px; - font-weight: 600; - color: rgba(0, 0, 0, 0.85); - margin-bottom: 10px; - padding-left: 8px; - border-left: 3px solid #1677ff; -} + .sectionTitle { + font-size: 14px; + font-weight: 600; + color: rgba(0, 0, 0, 0.85); + margin-bottom: 10px; + padding-left: 8px; + border-left: 3px solid #1677ff; + } -.textBlock { - font-size: 13px; - line-height: 1.5; - color: rgba(0, 0, 0, 0.65); - white-space: pre-wrap; - background: #fafafa; - padding: 12px 16px; - border-radius: 4px; - border: 1px solid #f0f0f0; -} + .textBlock { + font-size: 13px; + line-height: 1.5; + color: rgba(0, 0, 0, 0.65); + white-space: pre-wrap; + background: #fafafa; + padding: 12px 16px; + border-radius: 4px; + border: 1px solid #f0f0f0; + } -.imageGrid { - display: grid; - grid-template-columns: repeat(4, 1fr); - gap: 12px; -} + .imageGrid { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 12px; + } -.imageCell { - width: 100%; - aspect-ratio: 3 / 2; - background: #f5f5f5; - border-radius: 4px; - overflow: hidden; - border: 1px solid #f0f0f0; - display: flex; - align-items: center; - justify-content: center; -} + .imageCell { + width: 100%; + aspect-ratio: 3 / 2; + background: #f5f5f5; + border-radius: 4px; + overflow: hidden; + border: 1px solid #f0f0f0; + display: flex; + align-items: center; + justify-content: center; -.imageCell :global(.ant-image) { - width: 100%; - height: 100%; - object-fit: cover; + :global(.ant-image) { + width: 100%; + height: 100%; + object-fit: cover; + } + } } diff --git a/src/pages/events/list/components/EventRegulationModal.tsx b/src/pages/events/list/components/EventRegulationModal.tsx index aa15084..304bc76 100644 --- a/src/pages/events/list/components/EventRegulationModal.tsx +++ b/src/pages/events/list/components/EventRegulationModal.tsx @@ -40,6 +40,7 @@ export default defineComponent({ footer={null} centered destroyOnClose + wrapClassName={styles.eventRegulationModalMain} > {/* 规程文字 */}
diff --git a/src/pages/events/list/index.module.less b/src/pages/events/list/index.module.less index 9974dc5..a5eb239 100644 --- a/src/pages/events/list/index.module.less +++ b/src/pages/events/list/index.module.less @@ -1,18 +1,21 @@ -/** - * 表格 body 容器:占满 flex 剩余空间,并确保 antd 嵌套 div 逐层传递 height: 100%, - * 使得 Table scroll.y = 'calc(100% - 55px)' 中的 100% 能正确解析。 - */ -.tableBody { +.eventListMain { flex: 1; min-height: 0; - overflow: hidden; + display: flex; + flex-direction: column; - :global { - .ant-spin-nested-loading, - .ant-spin-container, - .ant-table, - .ant-table-container { - height: 100%; + .tableBody { + flex: 1; + min-height: 0; + overflow: hidden; + + :global { + .ant-spin-nested-loading, + .ant-spin-container, + .ant-table, + .ant-table-container { + height: 100%; + } } } } diff --git a/src/pages/events/list/index.tsx b/src/pages/events/list/index.tsx index 7afab43..4142944 100644 --- a/src/pages/events/list/index.tsx +++ b/src/pages/events/list/index.tsx @@ -26,7 +26,7 @@ import EventRegulationModal from './components/EventRegulationModal'; import EventDetailModal from './components/EventDetailModal'; import EventAuditModal from './components/EventAuditModal'; import styles from './index.module.less'; -import pageStyles from '@/components/page/pageLayout.module.less'; +import pageStyles from '@/assets/styles/pageLayout.module.less'; const { RangePicker } = DatePicker; @@ -309,37 +309,39 @@ export default defineComponent({ {/* ===== 表格区 ===== */}
-
- - {{ - bodyCell: (args: any) => - renderBodyCell({ - ...args, - onView: handleView, - onAudit: handleAudit, - onToggleShelf: handleToggleShelf, - }), - }} -
-
+
+
+ + {{ + bodyCell: (args: any) => + renderBodyCell({ + ...args, + onView: handleView, + onAudit: handleAudit, + onToggleShelf: handleToggleShelf, + }), + }} +
+
- {/* 独立分页,右下方 */} -
- `共 ${total} 条`} - onChange={handlePageChange} - onShowSizeChange={handlePageChange} - /> + {/* 独立分页,右下方 */} +
+ `共 ${total} 条`} + onChange={handlePageChange} + onShowSizeChange={handlePageChange} + /> +
diff --git a/src/pages/events/orders/components/OrderDetailModal.module.less b/src/pages/events/orders/components/OrderDetailModal.module.less index 02e1d7f..0746a27 100644 --- a/src/pages/events/orders/components/OrderDetailModal.module.less +++ b/src/pages/events/orders/components/OrderDetailModal.module.less @@ -1,194 +1,186 @@ -// ===== 自定义标题栏 ===== -.modalHeader { - display: flex; - justify-content: space-between; - align-items: center; - padding: 0 0 16px; - margin-bottom: 16px; - border-bottom: 1px solid #f0f0f0; -} +.orderDetailModalMain { + .modalHeader { + display: flex; + justify-content: space-between; + align-items: center; + padding: 0 0 16px; + margin-bottom: 16px; + border-bottom: 1px solid #f0f0f0; + } -.modalTitle { - font-size: 16px; - font-weight: 600; - color: rgba(0, 0, 0, 0.85); -} - -.closeBtn { - width: 28px; - height: 28px; - border: none; - background: transparent; - font-size: 22px; - line-height: 1; - color: rgba(0, 0, 0, 0.45); - cursor: pointer; - border-radius: 4px; - transition: all 0.2s; - - &:hover { - background: rgba(0, 0, 0, 0.04); + .modalTitle { + font-size: 16px; + font-weight: 600; color: rgba(0, 0, 0, 0.85); } -} -// ===== 内容区 ===== -.modalBody { - padding-top: 0; -} - -// ===== 订单信息 grid ===== -.infoGrid { - display: grid; - grid-template-columns: repeat(3, 1fr); - row-gap: 12px; - column-gap: 24px; - font-size: 13px; - margin-bottom: 24px; - padding-bottom: 16px; - border-bottom: 1px solid #f0f0f0; -} - -.infoItem { - display: flex; - align-items: baseline; - min-width: 0; -} - -.infoLabel { - color: rgba(0, 0, 0, 0.65); - flex-shrink: 0; -} - -// ===== 通用 section ===== -.section { - margin-bottom: 24px; -} - -.section:last-child { - margin-bottom: 0; -} - -.sectionTitle { - font-size: 14px; - font-weight: 600; - color: rgba(0, 0, 0, 0.85); - margin-bottom: 12px; - padding-left: 8px; - border-left: 3px solid #1677ff; -} - -// ===== 退款记录 ===== -.refundHeader { - margin-bottom: 12px; -} - -.refundSummary { - display: flex; - gap: 32px; - font-size: 13px; - color: rgba(0, 0, 0, 0.85); - margin-bottom: 12px; -} - -/** 固定高度 + 滚动 */ -.refundList { - max-height: 320px; - overflow-y: auto; - padding-right: 4px; - - // 自定义滚动条样式 - &::-webkit-scrollbar { - width: 6px; - } - &::-webkit-scrollbar-thumb { - background: #d9d9d9; - border-radius: 3px; - } - &::-webkit-scrollbar-track { + .closeBtn { + width: 28px; + height: 28px; + border: none; background: transparent; + font-size: 22px; + line-height: 1; + color: rgba(0, 0, 0, 0.45); + cursor: pointer; + border-radius: 4px; + transition: all 0.2s; + + &:hover { + background: rgba(0, 0, 0, 0.04); + color: rgba(0, 0, 0, 0.85); + } + } + + .modalBody { + padding-top: 0; + } + + .infoGrid { + display: grid; + grid-template-columns: repeat(3, 1fr); + row-gap: 12px; + column-gap: 24px; + font-size: 13px; + margin-bottom: 24px; + padding-bottom: 16px; + border-bottom: 1px solid #f0f0f0; + } + + .infoItem { + display: flex; + align-items: baseline; + min-width: 0; + } + + .infoLabel { + color: rgba(0, 0, 0, 0.65); + flex-shrink: 0; + } + + .section { + margin-bottom: 24px; + + &:last-child { + margin-bottom: 0; + } + } + + .sectionTitle { + font-size: 14px; + font-weight: 600; + color: rgba(0, 0, 0, 0.85); + margin-bottom: 12px; + padding-left: 8px; + border-left: 3px solid #1677ff; + } + + .refundHeader { + margin-bottom: 12px; + } + + .refundSummary { + display: flex; + gap: 32px; + font-size: 13px; + color: rgba(0, 0, 0, 0.85); + margin-bottom: 12px; + } + + .refundList { + max-height: 320px; + overflow-y: auto; + padding-right: 4px; + + &::-webkit-scrollbar { + width: 6px; + } + &::-webkit-scrollbar-thumb { + background: #d9d9d9; + border-radius: 3px; + } + &::-webkit-scrollbar-track { + background: transparent; + } + } + + .refundCard { + padding: 14px 16px; + margin-bottom: 12px; + background: #fafafa; + border: 1px solid #f0f0f0; + border-radius: 6px; + + &:last-child { + margin-bottom: 0; + } + } + + .refundCardHeader { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 12px; + padding-bottom: 10px; + border-bottom: 1px dashed #e0e0e0; + } + + .refundIndex { + font-size: 13px; + font-weight: 500; + color: rgba(0, 0, 0, 0.85); + } + + .refundCardBody { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 6px 24px; + font-size: 13px; + color: rgba(0, 0, 0, 0.65); + line-height: 1.8; + } + + .refundCol { + min-width: 0; + } + + .refundAmount { + color: rgba(0, 0, 0, 0.85); + font-weight: 500; + } + + .partialMark { + margin-left: 4px; + color: #fa8c16; + font-size: 12px; + } + + .refundEmpty { + padding: 32px 0; + text-align: center; + font-size: 13px; + color: rgba(0, 0, 0, 0.45); + background: #fafafa; + border-radius: 6px; + border: 1px dashed #e0e0e0; + } + + .refundPagination { + display: flex; + justify-content: flex-end; + margin-top: 12px; + } + + .modalFooter { + display: flex; + justify-content: flex-end; + gap: 12px; + padding-top: 16px; + margin-top: 8px; + border-top: 1px solid #f0f0f0; } } -.refundCard { - padding: 14px 16px; - margin-bottom: 12px; - background: #fafafa; - border: 1px solid #f0f0f0; - border-radius: 6px; -} - -.refundCard:last-child { - margin-bottom: 0; -} - -.refundCardHeader { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 12px; - padding-bottom: 10px; - border-bottom: 1px dashed #e0e0e0; -} - -.refundIndex { - font-size: 13px; - font-weight: 500; - color: rgba(0, 0, 0, 0.85); -} - -.refundCardBody { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 6px 24px; - font-size: 13px; - color: rgba(0, 0, 0, 0.65); - line-height: 1.8; -} - -.refundCol { - min-width: 0; -} - -.refundAmount { - color: rgba(0, 0, 0, 0.85); - font-weight: 500; -} - -.partialMark { - margin-left: 4px; - color: #fa8c16; - font-size: 12px; -} - -.refundEmpty { - padding: 32px 0; - text-align: center; - font-size: 13px; - color: rgba(0, 0, 0, 0.45); - background: #fafafa; - border-radius: 6px; - border: 1px dashed #e0e0e0; -} - -// 分页:右下角 -.refundPagination { - display: flex; - justify-content: flex-end; - margin-top: 12px; -} - -// ===== 底部按钮区 ===== -.modalFooter { - display: flex; - justify-content: flex-end; - gap: 12px; - padding-top: 16px; - margin-top: 8px; - border-top: 1px solid #f0f0f0; -} - -// ===== Modal 外层包裹:去除 antd 默认内边距,让自定义标题贴合 ===== .orderModalWrap { :global(.ant-modal-body) { padding-top: 16px; diff --git a/src/pages/events/orders/components/OrderDetailModal.tsx b/src/pages/events/orders/components/OrderDetailModal.tsx index 40df2ae..426c0fe 100644 --- a/src/pages/events/orders/components/OrderDetailModal.tsx +++ b/src/pages/events/orders/components/OrderDetailModal.tsx @@ -128,142 +128,144 @@ export default defineComponent({ closable={false} wrapClassName={styles.orderModalWrap} > - {/* ===== 自定义标题栏 ===== */} -
- 订单信息 - -
- -
- {/* ===== 订单信息 ===== */} -
-
- 赛事名称: - {props.record?.eventName} -
-
- 订单编号: - {props.record?.orderId} -
-
- 订单时间: - {props.record?.orderTime} -
-
- 支付时间: - {props.record?.payTime} -
-
- 订单金额: - {props.record?.totalAmount?.toFixed(2)}元 -
-
- 优惠金额: - {(props.record?.discountAmount || 0).toFixed(2)}元 -
-
- 实付金额: - {props.record?.paidAmount?.toFixed(2)}元 -
-
- 退款金额: - {props.record?.refundAmount?.toFixed(2)}元 -
+
+ {/* ===== 自定义标题栏 ===== */} +
+ 订单信息 +
- {/* ===== 选手信息 ===== */} -
-
选手信息
- - - - {/* ===== 退款记录 ===== */} -
-
- 退款记录 +
+ {/* ===== 订单信息 ===== */} +
+
+ 赛事名称: + {props.record?.eventName} +
+
+ 订单编号: + {props.record?.orderId} +
+
+ 订单时间: + {props.record?.orderTime} +
+
+ 支付时间: + {props.record?.payTime} +
+
+ 订单金额: + {props.record?.totalAmount?.toFixed(2)}元 +
+
+ 优惠金额: + {(props.record?.discountAmount || 0).toFixed(2)}元 +
+
+ 实付金额: + {props.record?.paidAmount?.toFixed(2)}元 +
+
+ 退款金额: + {props.record?.refundAmount?.toFixed(2)}元 +
- {hasRefund.value ? ( - <> -
- 已退金额:{totalRefunded.value.toFixed(2)}元 - 退款次数:{refundRecords.value.length}次 -
- {/* 固定高度 + 内部滚动 */} -
- {pagedRefunds.value.map((r, idx) => { - const statusInfo = REFUND_STATUS_MAP[r.status] || { - label: '-', - color: 'default', - }; - const realIdx = (refundPage.value - 1) * refundPageSize.value + idx + 1; - return ( -
-
- 第{realIdx}次退款 - {statusInfo.label} -
-
-
-
- 退款金额: - - ¥{r.amount.toFixed(2)} - {r.isPartial && ( - (部分退款) - )} - + + {/* ===== 选手信息 ===== */} +
+
选手信息
+
+ + + {/* ===== 退款记录 ===== */} +
+
+ 退款记录 +
+ {hasRefund.value ? ( + <> +
+ 已退金额:{totalRefunded.value.toFixed(2)}元 + 退款次数:{refundRecords.value.length}次 +
+ {/* 固定高度 + 内部滚动 */} +
+ {pagedRefunds.value.map((r, idx) => { + const statusInfo = REFUND_STATUS_MAP[r.status] || { + label: '-', + color: 'default', + }; + const realIdx = (refundPage.value - 1) * refundPageSize.value + idx + 1; + return ( +
+
+ 第{realIdx}次退款 + {statusInfo.label} +
+
+
+
+ 退款金额: + + ¥{r.amount.toFixed(2)} + {r.isPartial && ( + (部分退款) + )} + +
+
申请时间:{r.applyTime}
+
完款时间:{r.completeTime || '-'}
+
+
+
退款方式:{r.method}
+
第三方退款单号:{r.thirdPartyNo || '-'}
-
申请时间:{r.applyTime}
-
完款时间:{r.completeTime || '-'}
-
-
-
退款方式:{r.method}
-
第三方退款单号:{r.thirdPartyNo || '-'}
-
- ); - })} -
-
- -
- + ); + })} + +
+ +
+ + ) : ( +
暂无退款记录
+ )} + + + + {/* ===== 底部按钮 ===== */} +
+ + {hasRefund.value ? ( + ) : ( -
暂无退款记录
+ )}
- - {/* ===== 底部按钮 ===== */} -
- - {hasRefund.value ? ( - - ) : ( - - )} -
); }, diff --git a/src/pages/events/orders/index.module.less b/src/pages/events/orders/index.module.less index 4c665ac..6a6bc01 100644 --- a/src/pages/events/orders/index.module.less +++ b/src/pages/events/orders/index.module.less @@ -1,37 +1,40 @@ -/** - * 表格 body 容器:占满 flex 剩余空间,并确保 antd 嵌套 div 逐层传递 height: 100%, - * 使得 Table scroll.y = 'calc(100% - 55px)' 中的 100% 能正确解析。 - */ -.tableBody { +.eventOrdersMain { flex: 1; min-height: 0; - overflow: hidden; - - :global { - .ant-spin-nested-loading, - .ant-spin-container, - .ant-table, - .ant-table-container { - height: 100%; - } - } -} - -.summaryBar { - flex-shrink: 0; display: flex; - align-items: center; - gap: 20px; - padding: 12px 16px; - font-size: 14px; - color: #1a1a1a; + flex-direction: column; - .summaryItem { - font-weight: 500; + .summaryBar { + flex-shrink: 0; + display: flex; + align-items: center; + gap: 20px; + padding: 12px 16px; + font-size: 14px; + color: #1a1a1a; - .summaryLabel { - color: #666; - font-weight: 400; + .summaryItem { + font-weight: 500; + + .summaryLabel { + color: #666; + font-weight: 400; + } + } + } + + .tableBody { + flex: 1; + min-height: 0; + overflow: hidden; + + :global { + .ant-spin-nested-loading, + .ant-spin-container, + .ant-table, + .ant-table-container { + height: 100%; + } } } } diff --git a/src/pages/events/orders/index.tsx b/src/pages/events/orders/index.tsx index f48e57f..b58a37f 100644 --- a/src/pages/events/orders/index.tsx +++ b/src/pages/events/orders/index.tsx @@ -15,7 +15,7 @@ import { useOrderModel, ORDER_STATUS_OPTIONS, REFUND_STATUS_OPTIONS } from './mo import { useContainerSize, useState } from '@/hooks'; import OrderDetailModal from './components/OrderDetailModal'; import styles from './index.module.less'; -import pageStyles from '@/components/page/pageLayout.module.less'; +import pageStyles from '@/assets/styles/pageLayout.module.less'; const { RangePicker } = DatePicker; @@ -203,52 +203,54 @@ export default defineComponent({ {/* ===== 表格区 ===== */}
- {/* 金额汇总 */} -
- - 总订单金额(已支付): - {summary.value.totalOrderAmount.toFixed(2)}元 - - - 总实付金额: - {summary.value.totalPaidAmount.toFixed(2)}元 - - - 总退款金额: - {summary.value.totalRefundAmount.toFixed(2)}元 - -
+
+ {/* 金额汇总 */} +
+ + 总订单金额(已支付): + {summary.value.totalOrderAmount.toFixed(2)}元 + + + 总实付金额: + {summary.value.totalPaidAmount.toFixed(2)}元 + + + 总退款金额: + {summary.value.totalRefundAmount.toFixed(2)}元 + +
-
-
- {{ - bodyCell: (args: any) => - renderBodyCell({ - ...args, - onView: handleView, - onReRefund: handleReRefund, - }), - }} -
-
+
+ + {{ + bodyCell: (args: any) => + renderBodyCell({ + ...args, + onView: handleView, + onReRefund: handleReRefund, + }), + }} +
+
- {/* 独立分页,右下方 */} -
- `共 ${total} 条`} - onChange={handlePageChange} - onShowSizeChange={handlePageChange} - /> + {/* 独立分页,右下方 */} +
+ `共 ${total} 条`} + onChange={handlePageChange} + onShowSizeChange={handlePageChange} + /> +
diff --git a/src/pages/events/users/index.module.less b/src/pages/events/users/index.module.less index 9974dc5..db8fd98 100644 --- a/src/pages/events/users/index.module.less +++ b/src/pages/events/users/index.module.less @@ -1,18 +1,21 @@ -/** - * 表格 body 容器:占满 flex 剩余空间,并确保 antd 嵌套 div 逐层传递 height: 100%, - * 使得 Table scroll.y = 'calc(100% - 55px)' 中的 100% 能正确解析。 - */ -.tableBody { +.eventUsersMain { flex: 1; min-height: 0; - overflow: hidden; + display: flex; + flex-direction: column; - :global { - .ant-spin-nested-loading, - .ant-spin-container, - .ant-table, - .ant-table-container { - height: 100%; + .tableBody { + flex: 1; + min-height: 0; + overflow: hidden; + + :global { + .ant-spin-nested-loading, + .ant-spin-container, + .ant-table, + .ant-table-container { + height: 100%; + } } } } diff --git a/src/pages/events/users/index.tsx b/src/pages/events/users/index.tsx index 904db56..ae8f63f 100644 --- a/src/pages/events/users/index.tsx +++ b/src/pages/events/users/index.tsx @@ -13,7 +13,7 @@ import { import { useUserModel, USER_STATUS_OPTIONS } from './model/useUserModel'; import { useContainerSize } from '@/hooks'; import styles from './index.module.less'; -import pageStyles from '@/components/page/pageLayout.module.less'; +import pageStyles from '@/assets/styles/pageLayout.module.less'; /** * bodyCell 渲染函数 @@ -145,35 +145,37 @@ export default defineComponent({ {/* ===== 表格区 ===== */}
-
- - {{ - bodyCell: (args: any) => - renderBodyCell({ - ...args, - onToggleStatus: handleToggleStatus, - }), - }} -
-
+
+
+ + {{ + bodyCell: (args: any) => + renderBodyCell({ + ...args, + onToggleStatus: handleToggleStatus, + }), + }} +
+
- {/* 独立分页,右下方 */} -
- `共 ${total} 条`} - onChange={handlePageChange} - onShowSizeChange={handlePageChange} - /> + {/* 独立分页,右下方 */} +
+ `共 ${total} 条`} + onChange={handlePageChange} + onShowSizeChange={handlePageChange} + /> +
diff --git a/src/pages/login/index.module.less b/src/pages/login/index.module.less index cae8ec8..41077ca 100644 --- a/src/pages/login/index.module.less +++ b/src/pages/login/index.module.less @@ -2,169 +2,578 @@ // 左侧:深色品牌展示区,含浮动光球、网格呼吸、脉冲涟漪、粒子点阵等多层动画 // 右侧:白色登录表单区,入场渐显动画 -.container { +.loginMain { min-height: 100vh; display: flex; overflow: hidden; -} - -// ━━━━ 左侧品牌展示区 ━━━━ -.brand { - flex: 1; - display: flex; - flex-direction: column; - position: relative; - background: linear-gradient(160deg, #0c1e3a 0%, #132744 50%, #0a1628 100%); - color: #fff; - overflow: hidden; - padding: 40px 56px 40px 64px; -} - -// ── 动画层1: 浮动光球 ── -.orb1 { - position: absolute; - width: 460px; - height: 460px; - border-radius: 50%; - background: radial-gradient( - circle, - rgba(22, 119, 255, 0.14) 0%, - rgba(22, 119, 255, 0.04) 40%, - transparent 70% - ); - top: -100px; - right: 20%; - z-index: 0; - animation: orbFloat1 12s ease-in-out infinite; - filter: blur(2px); -} - -.orb2 { - position: absolute; - width: 360px; - height: 360px; - border-radius: 50%; - background: radial-gradient( - circle, - rgba(82, 196, 26, 0.1) 0%, - rgba(82, 196, 26, 0.03) 40%, - transparent 70% - ); - bottom: 40px; - left: 10%; - z-index: 0; - animation: orbFloat2 15s ease-in-out infinite; - filter: blur(2px); -} - -.orb3 { - position: absolute; - width: 280px; - height: 280px; - border-radius: 50%; - background: radial-gradient( - circle, - rgba(250, 173, 20, 0.08) 0%, - rgba(250, 173, 20, 0.02) 40%, - transparent 70% - ); - top: 50%; - left: 55%; - z-index: 0; - animation: orbFloat3 18s ease-in-out infinite; - filter: blur(3px); -} - -// ── 动画层2: 脉冲涟漪 ── -.pulse { - position: absolute; - width: 200px; - height: 200px; - border-radius: 50%; - border: 1px solid rgba(22, 119, 255, 0.15); - top: 30%; - right: 15%; - z-index: 0; - animation: pulseExpand 4s ease-out infinite; - - &::before { - content: ''; - position: absolute; - inset: 30px; - border-radius: 50%; - border: 1px solid rgba(22, 119, 255, 0.08); - animation: pulseExpand 4s ease-out infinite 1s; + .brand { + flex: 1; + display: flex; + flex-direction: column; + position: relative; + background: linear-gradient(160deg, #0c1e3a 0%, #132744 50%, #0a1628 100%); + color: #fff; + overflow: hidden; + padding: 40px 56px 40px 64px; } - - &::after { - content: ''; + .orb1 { position: absolute; - inset: 60px; + width: 460px; + height: 460px; border-radius: 50%; - border: 1px solid rgba(22, 119, 255, 0.04); - animation: pulseExpand 4s ease-out infinite 2s; + background: radial-gradient( + circle, + rgba(22, 119, 255, 0.14) 0%, + rgba(22, 119, 255, 0.04) 40%, + transparent 70% + ); + top: -100px; + right: 20%; + z-index: 0; + animation: orbFloat1 12s ease-in-out infinite; + filter: blur(2px); } -} - -// ── 动画层3: 网格呼吸 ── -.brandGrid { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - z-index: 1; - background-image: - linear-gradient(rgba(255, 255, 255, 0.03) 1px, transparent 1px), - linear-gradient(90deg, rgba(255, 255, 255, 0.03) 1px, transparent 1px); - background-size: 50px 50px; - animation: gridBreathe 6s ease-in-out infinite; -} - -// ── 动画层4: 粒子点阵 ── -.particles { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - z-index: 1; -} - -.particle { - position: absolute; - width: 3px; - height: 3px; - border-radius: 50%; - background: rgba(22, 119, 255, 0.5); - animation: particleFloat 8s ease-in-out infinite; - - &::before { - content: ''; + .orb2 { position: absolute; - width: 2px; + width: 360px; + height: 360px; + border-radius: 50%; + background: radial-gradient( + circle, + rgba(82, 196, 26, 0.1) 0%, + rgba(82, 196, 26, 0.03) 40%, + transparent 70% + ); + bottom: 40px; + left: 10%; + z-index: 0; + animation: orbFloat2 15s ease-in-out infinite; + filter: blur(2px); + } + .orb3 { + position: absolute; + width: 280px; + height: 280px; + border-radius: 50%; + background: radial-gradient( + circle, + rgba(250, 173, 20, 0.08) 0%, + rgba(250, 173, 20, 0.02) 40%, + transparent 70% + ); + top: 50%; + left: 55%; + z-index: 0; + animation: orbFloat3 18s ease-in-out infinite; + filter: blur(3px); + } + .pulse { + position: absolute; + width: 200px; + height: 200px; + border-radius: 50%; + border: 1px solid rgba(22, 119, 255, 0.15); + top: 30%; + right: 15%; + z-index: 0; + animation: pulseExpand 4s ease-out infinite; + + &::before { + content: ''; + position: absolute; + inset: 30px; + border-radius: 50%; + border: 1px solid rgba(22, 119, 255, 0.08); + animation: pulseExpand 4s ease-out infinite 1s; + } + + &::after { + content: ''; + position: absolute; + inset: 60px; + border-radius: 50%; + border: 1px solid rgba(22, 119, 255, 0.04); + animation: pulseExpand 4s ease-out infinite 2s; + } + } + .brandGrid { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 1; + background-image: + linear-gradient(rgba(255, 255, 255, 0.03) 1px, transparent 1px), + linear-gradient(90deg, rgba(255, 255, 255, 0.03) 1px, transparent 1px); + background-size: 50px 50px; + animation: gridBreathe 6s ease-in-out infinite; + } + .particles { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 1; + } + .particle { + position: absolute; + width: 3px; + height: 3px; + border-radius: 50%; + background: rgba(22, 119, 255, 0.5); + animation: particleFloat 8s ease-in-out infinite; + + &::before { + content: ''; + position: absolute; + width: 2px; + height: 2px; + border-radius: 50%; + background: rgba(105, 177, 255, 0.3); + top: -8px; + left: 3px; + animation: particleFloat 6s ease-in-out infinite reverse; + } + } + .scanLine { + position: absolute; + top: 0; + left: 0; + right: 0; height: 2px; - border-radius: 50%; - background: rgba(105, 177, 255, 0.3); - top: -8px; - left: 3px; - animation: particleFloat 6s ease-in-out infinite reverse; + background: linear-gradient(90deg, transparent, rgba(22, 119, 255, 0.3), transparent); + z-index: 1; + animation: scanDown 8s linear infinite; + } + .brandInner { + position: relative; + z-index: 2; + display: flex; + flex-direction: column; + flex: 1; + animation: fadeInUp 0.8s ease-out both; + } + .logoRow { + display: flex; + align-items: center; + gap: 14px; + margin-bottom: 48px; + } + .logoMark { + width: 48px; + height: 48px; + border-radius: 14px; + background: linear-gradient(135deg, #1677ff, #69b1ff); + display: flex; + align-items: center; + justify-content: center; + font-size: 24px; + font-weight: 800; + color: #fff; + box-shadow: 0 4px 20px rgba(22, 119, 255, 0.45); + animation: logoPulse 3s ease-in-out infinite; + position: relative; + + &::after { + content: ''; + position: absolute; + top: 4px; + left: 4px; + width: 18px; + height: 7px; + border-radius: 4px; + background: rgba(255, 255, 255, 0.3); + } + } + .logoText { + font-size: 18px; + font-weight: 600; + letter-spacing: 2px; + color: rgba(255, 255, 255, 0.9); + } + .brandTitle { + font-size: 32px; + font-weight: 700; + line-height: 1.35; + letter-spacing: 1px; + margin-bottom: 12px; + animation: fadeInUp 0.8s ease-out 0.1s both; + } + .brandSubtitle { + font-size: 15px; + line-height: 1.7; + color: rgba(255, 255, 255, 0.55); + margin-bottom: 40px; + max-width: 400px; + animation: fadeInUp 0.8s ease-out 0.2s both; + } + .statsRow { + display: flex; + gap: 36px; + margin-bottom: 44px; + animation: fadeInUp 0.8s ease-out 0.3s both; + } + .statItem { + display: flex; + flex-direction: column; + gap: 4px; + } + .statValue { + font-size: 28px; + font-weight: 700; + color: #fff; + letter-spacing: 1px; + } + .statLabel { + font-size: 12px; + color: rgba(255, 255, 255, 0.45); + letter-spacing: 1px; + } + .statHighlight { + color: #69b1ff; + } + .eventCards { + display: flex; + gap: 16px; + margin-bottom: 44px; + animation: fadeInUp 0.8s ease-out 0.4s both; + } + .eventCard { + flex: 1; + padding: 20px; + background: rgba(255, 255, 255, 0.06); + border: 1px solid rgba(255, 255, 255, 0.08); + border-radius: 14px; + backdrop-filter: blur(8px); + transition: all 0.3s ease; + position: relative; + overflow: hidden; + + // 内部光效装饰 + &::before { + content: ''; + position: absolute; + top: -50%; + left: -50%; + width: 200%; + height: 200%; + background: radial-gradient(circle at 30% 30%, rgba(22, 119, 255, 0.06) 0%, transparent 50%); + animation: cardShimmer 5s linear infinite; + pointer-events: none; + } + + &:hover { + background: rgba(255, 255, 255, 0.1); + border-color: rgba(22, 119, 255, 0.3); + transform: translateY(-3px); + box-shadow: 0 8px 24px rgba(22, 119, 255, 0.15); + } + } + .eventIcon { + width: 36px; + height: 36px; + border-radius: 10px; + display: flex; + align-items: center; + justify-content: center; + font-size: 18px; + font-weight: 700; + color: #fff; + margin-bottom: 12px; + position: relative; + z-index: 1; + + &.blue { + background: linear-gradient(135deg, #1677ff, #4096ff); + box-shadow: 0 2px 12px rgba(22, 119, 255, 0.3); + } + + &.green { + background: linear-gradient(135deg, #52c41a, #73d13d); + box-shadow: 0 2px 12px rgba(82, 196, 26, 0.3); + } + + &.orange { + background: linear-gradient(135deg, #fa8c16, #ffa940); + box-shadow: 0 2px 12px rgba(250, 140, 22, 0.3); + } + } + .eventTitle { + font-size: 15px; + font-weight: 600; + color: rgba(255, 255, 255, 0.9); + margin-bottom: 6px; + position: relative; + z-index: 1; + } + .eventDesc { + font-size: 12px; + color: rgba(255, 255, 255, 0.45); + line-height: 1.5; + position: relative; + z-index: 1; + } + .flowSteps { + display: flex; + align-items: center; + gap: 0; + animation: fadeInUp 0.8s ease-out 0.5s both; + } + .step { + display: flex; + flex-direction: column; + align-items: center; + flex: 1; + position: relative; + } + .stepDot { + position: relative; + width: 20px; + height: 20px; + margin-bottom: 12px; + + // 中心核心圆点 + &::before { + content: ''; + position: absolute; + top: 50%; + left: 50%; + width: 6px; + height: 6px; + border-radius: 50%; + background: #fff; + box-shadow: + 0 0 4px 2px rgba(22, 119, 255, 0.8), + 0 0 12px 4px rgba(22, 119, 255, 0.5), + 0 0 24px 8px rgba(22, 119, 255, 0.2); + transform: translate(-50%, -50%); + animation: starCorePulse 2s ease-in-out infinite; + } + + // 十字光芒线(横+纵) + &::after { + content: ''; + position: absolute; + top: 50%; + left: 50%; + width: 20px; + height: 20px; + transform: translate(-50%, -50%) rotate(45deg); + animation: + starSpin 6s linear infinite, + starGlowPulse 2s ease-in-out infinite; + // 横向光芒 + background: + linear-gradient( + 0deg, + transparent 45%, + rgba(22, 119, 255, 0.9) 48%, + #fff 50%, + rgba(22, 119, 255, 0.9) 52%, + transparent 55% + ), + linear-gradient( + 90deg, + transparent 45%, + rgba(22, 119, 255, 0.9) 48%, + #fff 50%, + rgba(22, 119, 255, 0.9) 52%, + transparent 55% + ); + } + } + .stepLine { + flex: 1; + height: 1px; + min-width: 20px; + background: linear-gradient(90deg, rgba(22, 119, 255, 0.5), rgba(22, 119, 255, 0.15)); + align-self: center; + margin-top: -6px; // 微调与星点中心对齐(因为label占空间) + } + .stepLabel { + font-size: 13px; + color: rgba(255, 255, 255, 0.7); + font-weight: 500; + text-align: center; + } + .brandFooter { + margin-top: auto; + font-size: 12px; + color: rgba(255, 255, 255, 0.2); + letter-spacing: 1px; + } + .loginSide { + width: 460px; + min-width: 380px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 40px 48px; + background: #fff; + position: relative; + } + .loginWrapper { + width: 100%; + max-width: 340px; + animation: fadeInRight 0.6s ease-out 0.3s both; + } + .loginTitle { + font-size: 24px; + font-weight: 700; + color: rgba(0, 0, 0, 0.88); + margin-bottom: 6px; + } + .loginDesc { + font-size: 14px; + color: rgba(0, 0, 0, 0.45); + margin-bottom: 36px; + } + .loginForm { + :global(.ant-input-affix-wrapper) { + padding: 10px 14px; + border-radius: 10px; + border-color: #d9d9d9; + transition: all 0.3s; + + &:hover { + border-color: #1677ff; + } + + &:focus-within { + border-color: #1677ff; + box-shadow: 0 0 0 3px rgba(22, 119, 255, 0.08); + } + } + + :global(.ant-input-prefix) { + color: rgba(0, 0, 0, 0.3); + margin-right: 8px; + } + + :global(.ant-form-item) { + margin-bottom: 22px; + } + } + .loginBtn { + height: 46px; + border-radius: 10px; + font-size: 15px; + font-weight: 600; + letter-spacing: 3px; + transition: all 0.3s; + + &:hover { + transform: translateY(-1px); + box-shadow: 0 4px 16px rgba(22, 119, 255, 0.35); + } + } + .rememberRow { + margin-bottom: 8px; + + :global(.ant-checkbox-wrapper) { + color: rgba(0, 0, 0, 0.55); + font-size: 13px; + } + + :global(.ant-checkbox-checked .ant-checkbox-inner) { + background-color: #1677ff; + border-color: #1677ff; + } + } + .loginFooter { + margin-top: 28px; + text-align: center; + font-size: 12px; + color: rgba(0, 0, 0, 0.25); + } + @media screen and (max-width: 1200px) { + .brand { + padding: 32px 36px 32px 40px; + } + + .brandTitle { + font-size: 28px; + } + + .brandSubtitle { + font-size: 14px; + margin-bottom: 32px; + } + + .statsRow { + gap: 24px; + margin-bottom: 32px; + } + + .statValue { + font-size: 24px; + } + + .eventCards { + gap: 12px; + margin-bottom: 32px; + } + + .eventCard { + padding: 16px; + } + + .eventIcon { + width: 32px; + height: 32px; + margin-bottom: 10px; + } + + .eventTitle { + font-size: 14px; + } + + .eventDesc { + font-size: 11px; + } + + .orb1 { + width: 360px; + height: 360px; + } + + .orb2 { + width: 280px; + height: 280px; + } + + .orb3 { + width: 200px; + height: 200px; + } + + .loginSide { + width: 400px; + min-width: 340px; + padding: 36px 40px; + } + + .loginWrapper { + max-width: 320px; + } + + .loginTitle { + font-size: 22px; + } + + .loginDesc { + font-size: 13px; + } + + .stepLabel { + font-size: 12px; + } } } -// ── 动画层5: 扫描线 ── -.scanLine { - position: absolute; - top: 0; - left: 0; - right: 0; - height: 2px; - background: linear-gradient(90deg, transparent, rgba(22, 119, 255, 0.3), transparent); - z-index: 1; - animation: scanDown 8s linear infinite; -} - -// ━━━━ 动画定义 ━━━━ @keyframes orbFloat1 { 0%, 100% { @@ -254,16 +663,6 @@ } } -// ━━━━ 内容层 ━━━━ -.brandInner { - position: relative; - z-index: 2; - display: flex; - flex-direction: column; - flex: 1; - animation: fadeInUp 0.8s ease-out both; -} - @keyframes fadeInUp { from { opacity: 0; @@ -275,41 +674,6 @@ } } -// ── Logo ── -.logoRow { - display: flex; - align-items: center; - gap: 14px; - margin-bottom: 48px; -} - -.logoMark { - width: 48px; - height: 48px; - border-radius: 14px; - background: linear-gradient(135deg, #1677ff, #69b1ff); - display: flex; - align-items: center; - justify-content: center; - font-size: 24px; - font-weight: 800; - color: #fff; - box-shadow: 0 4px 20px rgba(22, 119, 255, 0.45); - animation: logoPulse 3s ease-in-out infinite; - position: relative; - - &::after { - content: ''; - position: absolute; - top: 4px; - left: 4px; - width: 18px; - height: 7px; - border-radius: 4px; - background: rgba(255, 255, 255, 0.3); - } -} - @keyframes logoPulse { 0%, 100% { @@ -322,103 +686,6 @@ } } -.logoText { - font-size: 18px; - font-weight: 600; - letter-spacing: 2px; - color: rgba(255, 255, 255, 0.9); -} - -// ── 大标题 ── -.brandTitle { - font-size: 32px; - font-weight: 700; - line-height: 1.35; - letter-spacing: 1px; - margin-bottom: 12px; - animation: fadeInUp 0.8s ease-out 0.1s both; -} - -.brandSubtitle { - font-size: 15px; - line-height: 1.7; - color: rgba(255, 255, 255, 0.55); - margin-bottom: 40px; - max-width: 400px; - animation: fadeInUp 0.8s ease-out 0.2s both; -} - -// ── 数据统计条 ── -.statsRow { - display: flex; - gap: 36px; - margin-bottom: 44px; - animation: fadeInUp 0.8s ease-out 0.3s both; -} - -.statItem { - display: flex; - flex-direction: column; - gap: 4px; -} - -.statValue { - font-size: 28px; - font-weight: 700; - color: #fff; - letter-spacing: 1px; -} - -.statLabel { - font-size: 12px; - color: rgba(255, 255, 255, 0.45); - letter-spacing: 1px; -} - -.statHighlight { - color: #69b1ff; -} - -// ── 赛事模拟卡片 ── -.eventCards { - display: flex; - gap: 16px; - margin-bottom: 44px; - animation: fadeInUp 0.8s ease-out 0.4s both; -} - -.eventCard { - flex: 1; - padding: 20px; - background: rgba(255, 255, 255, 0.06); - border: 1px solid rgba(255, 255, 255, 0.08); - border-radius: 14px; - backdrop-filter: blur(8px); - transition: all 0.3s ease; - position: relative; - overflow: hidden; - - // 内部光效装饰 - &::before { - content: ''; - position: absolute; - top: -50%; - left: -50%; - width: 200%; - height: 200%; - background: radial-gradient(circle at 30% 30%, rgba(22, 119, 255, 0.06) 0%, transparent 50%); - animation: cardShimmer 5s linear infinite; - pointer-events: none; - } - - &:hover { - background: rgba(255, 255, 255, 0.1); - border-color: rgba(22, 119, 255, 0.3); - transform: translateY(-3px); - box-shadow: 0 8px 24px rgba(22, 119, 255, 0.15); - } -} - @keyframes cardShimmer { 0% { transform: rotate(0deg); @@ -428,138 +695,6 @@ } } -.eventIcon { - width: 36px; - height: 36px; - border-radius: 10px; - display: flex; - align-items: center; - justify-content: center; - font-size: 18px; - font-weight: 700; - color: #fff; - margin-bottom: 12px; - position: relative; - z-index: 1; - - &.blue { - background: linear-gradient(135deg, #1677ff, #4096ff); - box-shadow: 0 2px 12px rgba(22, 119, 255, 0.3); - } - - &.green { - background: linear-gradient(135deg, #52c41a, #73d13d); - box-shadow: 0 2px 12px rgba(82, 196, 26, 0.3); - } - - &.orange { - background: linear-gradient(135deg, #fa8c16, #ffa940); - box-shadow: 0 2px 12px rgba(250, 140, 22, 0.3); - } -} - -.eventTitle { - font-size: 15px; - font-weight: 600; - color: rgba(255, 255, 255, 0.9); - margin-bottom: 6px; - position: relative; - z-index: 1; -} - -.eventDesc { - font-size: 12px; - color: rgba(255, 255, 255, 0.45); - line-height: 1.5; - position: relative; - z-index: 1; -} - -// ── 步骤流程 ── -.flowSteps { - display: flex; - align-items: center; - gap: 0; - animation: fadeInUp 0.8s ease-out 0.5s both; -} - -.step { - display: flex; - flex-direction: column; - align-items: center; - flex: 1; - position: relative; -} - -// ── 星点效果 ── -// 中心发光点 + 四条十字光芒 + 缓慢旋转 + 闪烁呼吸 -.stepDot { - position: relative; - width: 20px; - height: 20px; - margin-bottom: 12px; - - // 中心核心圆点 - &::before { - content: ''; - position: absolute; - top: 50%; - left: 50%; - width: 6px; - height: 6px; - border-radius: 50%; - background: #fff; - box-shadow: - 0 0 4px 2px rgba(22, 119, 255, 0.8), - 0 0 12px 4px rgba(22, 119, 255, 0.5), - 0 0 24px 8px rgba(22, 119, 255, 0.2); - transform: translate(-50%, -50%); - animation: starCorePulse 2s ease-in-out infinite; - } - - // 十字光芒线(横+纵) - &::after { - content: ''; - position: absolute; - top: 50%; - left: 50%; - width: 20px; - height: 20px; - transform: translate(-50%, -50%) rotate(45deg); - animation: - starSpin 6s linear infinite, - starGlowPulse 2s ease-in-out infinite; - // 横向光芒 - background: - linear-gradient( - 0deg, - transparent 45%, - rgba(22, 119, 255, 0.9) 48%, - #fff 50%, - rgba(22, 119, 255, 0.9) 52%, - transparent 55% - ), - linear-gradient( - 90deg, - transparent 45%, - rgba(22, 119, 255, 0.9) 48%, - #fff 50%, - rgba(22, 119, 255, 0.9) 52%, - transparent 55% - ); - } -} - -// 步骤之间的连线 -.stepLine { - flex: 1; - height: 1px; - min-width: 20px; - background: linear-gradient(90deg, rgba(22, 119, 255, 0.5), rgba(22, 119, 255, 0.15)); - align-self: center; - margin-top: -6px; // 微调与星点中心对齐(因为label占空间) -} - @keyframes starCorePulse { 0%, 100% { @@ -595,40 +730,6 @@ } } -.stepLabel { - font-size: 13px; - color: rgba(255, 255, 255, 0.7); - font-weight: 500; - text-align: center; -} - -// ── 左侧底部版权 ── -.brandFooter { - margin-top: auto; - font-size: 12px; - color: rgba(255, 255, 255, 0.2); - letter-spacing: 1px; -} - -// ━━━━ 右侧登录区 ━━━━ -.loginSide { - width: 460px; - min-width: 380px; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - padding: 40px 48px; - background: #fff; - position: relative; -} - -.loginWrapper { - width: 100%; - max-width: 340px; - animation: fadeInRight 0.6s ease-out 0.3s both; -} - @keyframes fadeInRight { from { opacity: 0; @@ -639,168 +740,3 @@ transform: translateX(0); } } - -.loginTitle { - font-size: 24px; - font-weight: 700; - color: rgba(0, 0, 0, 0.88); - margin-bottom: 6px; -} - -.loginDesc { - font-size: 14px; - color: rgba(0, 0, 0, 0.45); - margin-bottom: 36px; -} - -.loginForm { - :global(.ant-input-affix-wrapper) { - padding: 10px 14px; - border-radius: 10px; - border-color: #d9d9d9; - transition: all 0.3s; - - &:hover { - border-color: #1677ff; - } - - &:focus-within { - border-color: #1677ff; - box-shadow: 0 0 0 3px rgba(22, 119, 255, 0.08); - } - } - - :global(.ant-input-prefix) { - color: rgba(0, 0, 0, 0.3); - margin-right: 8px; - } - - :global(.ant-form-item) { - margin-bottom: 22px; - } -} - -.loginBtn { - height: 46px; - border-radius: 10px; - font-size: 15px; - font-weight: 600; - letter-spacing: 3px; - transition: all 0.3s; - - &:hover { - transform: translateY(-1px); - box-shadow: 0 4px 16px rgba(22, 119, 255, 0.35); - } -} - -// ── 记住密码行 ── -.rememberRow { - margin-bottom: 8px; - - :global(.ant-checkbox-wrapper) { - color: rgba(0, 0, 0, 0.55); - font-size: 13px; - } - - :global(.ant-checkbox-checked .ant-checkbox-inner) { - background-color: #1677ff; - border-color: #1677ff; - } -} - -.loginFooter { - margin-top: 28px; - text-align: center; - font-size: 12px; - color: rgba(0, 0, 0, 0.25); -} - -// ━━━━ 响应式 — PC 端自适应 ━━━━ - -// ── 大屏 (>1200px): 默认样式,无需额外处理 ── - -// ── 中屏 (≤1200px): 缩减间距、光球尺寸、字号 ── -@media screen and (max-width: 1200px) { - .brand { - padding: 32px 36px 32px 40px; - } - - .brandTitle { - font-size: 28px; - } - - .brandSubtitle { - font-size: 14px; - margin-bottom: 32px; - } - - .statsRow { - gap: 24px; - margin-bottom: 32px; - } - - .statValue { - font-size: 24px; - } - - .eventCards { - gap: 12px; - margin-bottom: 32px; - } - - .eventCard { - padding: 16px; - } - - .eventIcon { - width: 32px; - height: 32px; - margin-bottom: 10px; - } - - .eventTitle { - font-size: 14px; - } - - .eventDesc { - font-size: 11px; - } - - .orb1 { - width: 360px; - height: 360px; - } - - .orb2 { - width: 280px; - height: 280px; - } - - .orb3 { - width: 200px; - height: 200px; - } - - .loginSide { - width: 400px; - min-width: 340px; - padding: 36px 40px; - } - - .loginWrapper { - max-width: 320px; - } - - .loginTitle { - font-size: 22px; - } - - .loginDesc { - font-size: 13px; - } - - .stepLabel { - font-size: 12px; - } -} diff --git a/src/pages/login/index.tsx b/src/pages/login/index.tsx index a3d710b..590deae 100644 --- a/src/pages/login/index.tsx +++ b/src/pages/login/index.tsx @@ -92,7 +92,7 @@ export default defineComponent({ ]; return () => ( -
+
diff --git a/src/pages/system/roles/components/RoleFormModal.module.less b/src/pages/system/roles/components/RoleFormModal.module.less index 2958fed..a0c05a0 100644 --- a/src/pages/system/roles/components/RoleFormModal.module.less +++ b/src/pages/system/roles/components/RoleFormModal.module.less @@ -1,33 +1,35 @@ -.form { - :global { - .ant-form-item { - margin-bottom: 16px; +.roleFormModalMain { + .modal { + :global { + .ant-modal-body { + padding: 16px 24px 0; + } } } -} -.treeWrapper { - max-height: 380px; - overflow: auto; - padding: 8px 12px; - border: 1px solid #f0f0f0; - border-radius: 4px; - background: #fafafa; -} - -.footer { - display: flex; - justify-content: flex-end; - gap: 8px; - padding-top: 16px; - border-top: 1px solid #f0f0f0; - margin-top: 8px; -} - -.modal { - :global { - .ant-modal-body { - padding: 16px 24px 0; + .form { + :global { + .ant-form-item { + margin-bottom: 16px; + } } } + + .treeWrapper { + max-height: 380px; + overflow: auto; + padding: 8px 12px; + border: 1px solid #f0f0f0; + border-radius: 4px; + background: #fafafa; + } + + .footer { + display: flex; + justify-content: flex-end; + gap: 8px; + padding-top: 16px; + border-top: 1px solid #f0f0f0; + margin-top: 8px; + } } diff --git a/src/pages/system/roles/components/RoleFormModal.tsx b/src/pages/system/roles/components/RoleFormModal.tsx index 86296d7..15c1caf 100644 --- a/src/pages/system/roles/components/RoleFormModal.tsx +++ b/src/pages/system/roles/components/RoleFormModal.tsx @@ -100,6 +100,7 @@ export default defineComponent({ destroyOnClose footer={null} centered + wrapClassName={styles.roleFormModalMain} class={styles.modal} > diff --git a/src/pages/system/roles/components/UserListModal.module.less b/src/pages/system/roles/components/UserListModal.module.less index 47bf537..2486ab0 100644 --- a/src/pages/system/roles/components/UserListModal.module.less +++ b/src/pages/system/roles/components/UserListModal.module.less @@ -1,23 +1,25 @@ -.filter { - margin-bottom: 16px; -} +.userListModalMain { + .filter { + margin-bottom: 16px; + } -.bottom { - display: flex; - justify-content: space-between; - align-items: center; - margin-top: 16px; - padding-top: 12px; - border-top: 1px solid #f0f0f0; -} + .bottom { + display: flex; + justify-content: space-between; + align-items: center; + margin-top: 16px; + padding-top: 12px; + border-top: 1px solid #f0f0f0; + } -.total { - color: rgba(0, 0, 0, 0.65); - font-size: 13px; -} + .total { + color: rgba(0, 0, 0, 0.65); + font-size: 13px; + } -.paginationRow { - display: flex; - justify-content: flex-end; - margin-top: 12px; + .paginationRow { + display: flex; + justify-content: flex-end; + margin-top: 12px; + } } diff --git a/src/pages/system/roles/components/UserListModal.tsx b/src/pages/system/roles/components/UserListModal.tsx index 7f5af7e..f75b542 100644 --- a/src/pages/system/roles/components/UserListModal.tsx +++ b/src/pages/system/roles/components/UserListModal.tsx @@ -78,6 +78,7 @@ export default defineComponent({ footer={null} centered destroyOnClose + wrapClassName={styles.userListModalMain} > {/* 筛选 */}
diff --git a/src/pages/system/roles/index.module.less b/src/pages/system/roles/index.module.less index e693719..f266da0 100644 --- a/src/pages/system/roles/index.module.less +++ b/src/pages/system/roles/index.module.less @@ -1,43 +1,45 @@ -/** - * 表格 body 容器:占满 flex 剩余空间 - */ -.tableBody { +.systemRolesMain { flex: 1; min-height: 0; - overflow: hidden; + display: flex; + flex-direction: column; - :global { - .ant-spin-nested-loading, - .ant-spin-container, - .ant-table, - .ant-table-container { - height: 100%; + .tableBody { + flex: 1; + min-height: 0; + overflow: hidden; + + :global { + .ant-spin-nested-loading, + .ant-spin-container, + .ant-table, + .ant-table-container { + height: 100%; + } } } -} -/* 用户数链接 */ -.userCountLink { - font-variant-numeric: tabular-nums; -} - -/* ===== 删除确认弹窗 ===== */ -.confirmContent { - padding: 4px 24px; - font-size: 14px; - color: rgba(0, 0, 0, 0.85); - - strong { - margin: 0 4px; - font-weight: 600; + .userCountLink { + font-variant-numeric: tabular-nums; } -} -.confirmTip { - margin-top: 8px; - font-size: 12px; - color: rgba(0, 0, 0, 0.45); - line-height: 1.5; + .confirmContent { + padding: 4px 24px; + font-size: 14px; + color: rgba(0, 0, 0, 0.85); + + strong { + margin: 0 4px; + font-weight: 600; + } + } + + .confirmTip { + margin-top: 8px; + font-size: 12px; + color: rgba(0, 0, 0, 0.45); + line-height: 1.5; + } } :global(.deleteConfirmModal) { diff --git a/src/pages/system/roles/index.tsx b/src/pages/system/roles/index.tsx index 8280b42..4eca898 100644 --- a/src/pages/system/roles/index.tsx +++ b/src/pages/system/roles/index.tsx @@ -6,7 +6,7 @@ import { useContainerSize } from '@/hooks'; import RoleFormModal from './components/RoleFormModal'; import UserListModal from './components/UserListModal'; import styles from './index.module.less'; -import pageStyles from '@/components/page/pageLayout.module.less'; +import pageStyles from '@/assets/styles/pageLayout.module.less'; /** * bodyCell 渲染 @@ -57,13 +57,15 @@ function confirmDelete({ record, onOk }: { record: any; onOk: (record: any) => v icon: null, class: styles.deleteConfirmModal, content: ( -
-
- 确定要删除角色 - {record.roleName} - 吗? +
+
+
+ 确定要删除角色 + {record.roleName} + 吗? +
+
删除后该角色下的用户将失去对应的权限,请谨慎操作。
-
删除后该角色下的用户将失去对应的权限,请谨慎操作。
), okText: '确认', @@ -148,37 +150,39 @@ export default defineComponent({ {/* ===== 表格区 ===== */}
-
- - {{ - bodyCell: (args: any) => - renderBodyCell({ - ...args, - onViewUsers: handleViewUsers, - onEdit: handleEdit, - onDelete: triggerDelete, - }), - }} -
-
+
+
+ + {{ + bodyCell: (args: any) => + renderBodyCell({ + ...args, + onViewUsers: handleViewUsers, + onEdit: handleEdit, + onDelete: triggerDelete, + }), + }} +
+
- {/* 分页 */} -
- `共 ${total} 条`} - onChange={handlePageChange} - onShowSizeChange={handlePageChange} - /> + {/* 分页 */} +
+ `共 ${total} 条`} + onChange={handlePageChange} + onShowSizeChange={handlePageChange} + /> +
diff --git a/src/pages/system/users/components/UserFormModal.module.less b/src/pages/system/users/components/UserFormModal.module.less index 3791736..7d2e6ed 100644 --- a/src/pages/system/users/components/UserFormModal.module.less +++ b/src/pages/system/users/components/UserFormModal.module.less @@ -1,52 +1,49 @@ -/* ===== 表单行/列布局 ===== */ -.row { - display: flex; - gap: 16px; - flex-wrap: wrap; -} +.userFormModalMain { + .row { + display: flex; + gap: 16px; + flex-wrap: wrap; + } -.col { - flex: 1; - min-width: 0; -} + .col { + flex: 1; + min-width: 0; + } -/* 让 antd Form.Item 在 col 里能正确控制宽度 */ -.form { - :global { - .ant-form-item { - flex: 1; - min-width: 0; + .form { + :global { + .ant-form-item { + flex: 1; + min-width: 0; + } } } -} -/* ===== 密码区重置链接 ===== */ -.resetLink { - font-size: 14px; - color: #1677ff; - cursor: pointer; - user-select: none; + .resetLink { + font-size: 14px; + color: #1677ff; + cursor: pointer; + user-select: none; - &:hover { - color: #4096ff; + &:hover { + color: #4096ff; + } + } + + .cancelRow { + display: flex; + justify-content: flex-end; + margin-top: -8px; + margin-bottom: 16px; + font-size: 12px; + } + + .footer { + display: flex; + justify-content: flex-end; + gap: 8px; + padding-top: 16px; + border-top: 1px solid #f0f0f0; + margin-top: 8px; } } - -/* ===== 取消重置行 ===== */ -.cancelRow { - display: flex; - justify-content: flex-end; - margin-top: -8px; - margin-bottom: 16px; - font-size: 12px; -} - -/* ===== 底部按钮 ===== */ -.footer { - display: flex; - justify-content: flex-end; - gap: 8px; - padding-top: 16px; - border-top: 1px solid #f0f0f0; - margin-top: 8px; -} diff --git a/src/pages/system/users/components/UserFormModal.tsx b/src/pages/system/users/components/UserFormModal.tsx index 5ca74fa..5146f24 100644 --- a/src/pages/system/users/components/UserFormModal.tsx +++ b/src/pages/system/users/components/UserFormModal.tsx @@ -121,6 +121,7 @@ export default defineComponent({ destroyOnClose footer={null} centered + wrapClassName={styles.userFormModalMain} > {/* 姓名 / 手机号:同一行 */} diff --git a/src/pages/system/users/index.module.less b/src/pages/system/users/index.module.less index d411680..d2999bb 100644 --- a/src/pages/system/users/index.module.less +++ b/src/pages/system/users/index.module.less @@ -1,41 +1,39 @@ -/** - * 表格 body 容器:占满 flex 剩余空间, - * 确保 antd 嵌套 div 逐层传递 height: 100%, - * 使得 Table scroll.y 能正确解析。 - */ -.tableBody { +.systemUsersMain { flex: 1; min-height: 0; - overflow: hidden; + display: flex; + flex-direction: column; - :global { - .ant-spin-nested-loading, - .ant-spin-container, - .ant-table, - .ant-table-container { - height: 100%; + .tableBody { + flex: 1; + min-height: 0; + overflow: hidden; + + :global { + .ant-spin-nested-loading, + .ant-spin-container, + .ant-table, + .ant-table-container { + height: 100%; + } + } + } + + .confirmContent { + display: flex; + align-items: center; + flex-wrap: wrap; + padding: 4px 0; + font-size: 14px; + color: rgba(0, 0, 0, 0.85); + + strong { + margin: 0 4px; + font-weight: 600; } } } -/* ===== 禁用/启用 二次确认弹窗 ===== */ - -/* 内容块:左右加 padding,按用户要求 */ -.confirmContent { - display: flex; - align-items: center; - flex-wrap: wrap; - padding: 4px 0; - font-size: 14px; - color: rgba(0, 0, 0, 0.85); - - strong { - margin: 0 4px; - font-weight: 600; - } -} - -/* antd Modal.confirm 默认 body 已经有 padding,这里额外覆盖一下确保一致 */ :global(.toggleConfirmModal) { .ant-modal-confirm-body { padding: 24px !important; diff --git a/src/pages/system/users/index.tsx b/src/pages/system/users/index.tsx index eac879c..5d84db7 100644 --- a/src/pages/system/users/index.tsx +++ b/src/pages/system/users/index.tsx @@ -4,7 +4,7 @@ import { useUserModel, USER_ROLE_OPTIONS, USER_STATUS_OPTIONS } from './model/us import { useContainerSize } from '@/hooks'; import UserFormModal from './components/UserFormModal'; import styles from './index.module.less'; -import pageStyles from '@/components/page/pageLayout.module.less'; +import pageStyles from '@/assets/styles/pageLayout.module.less'; /** * bodyCell 渲染函数 @@ -54,10 +54,12 @@ function confirmToggleStatus({ record, onOk }: { record: any; onOk: (record: any title: `确认${actionText}`, class: styles.toggleConfirmModal, content: ( -
- 确定要{actionText}用户 - {record.realName} - 吗? +
+
+ 确定要{actionText}用户 + {record.realName} + 吗? +
), okText: '确认', @@ -164,36 +166,38 @@ export default defineComponent({ {/* ===== 表格区 ===== */}
-
- - {{ - bodyCell: (args: any) => - renderBodyCell({ - ...args, - onEdit: triggerEdit, - onToggleStatus: triggerToggle, - }), - }} -
-
+
+
+ + {{ + bodyCell: (args: any) => + renderBodyCell({ + ...args, + onEdit: triggerEdit, + onToggleStatus: triggerToggle, + }), + }} +
+
- {/* 独立分页 */} -
- `共 ${total} 条`} - onChange={handlePageChange} - onShowSizeChange={handlePageChange} - /> + {/* 独立分页 */} +
+ `共 ${total} 条`} + onChange={handlePageChange} + onShowSizeChange={handlePageChange} + /> +