修改样式
This commit is contained in:
parent
b002e3ca1c
commit
8411df8ad6
@ -17,15 +17,15 @@ description: "比赛管理系统设计规范。当用户提出页面开发需求
|
|||||||
// ==========================================
|
// ==========================================
|
||||||
// 项目统一设计变量 - 必须复制
|
// 项目统一设计变量 - 必须复制
|
||||||
// ==========================================
|
// ==========================================
|
||||||
$primary: #0958d9;
|
$primary: #1890ff;
|
||||||
$primary-light: #1677ff;
|
$primary-dark: #0958d9;
|
||||||
$primary-dark: #003eb3;
|
$primary-light: #40a9ff;
|
||||||
$secondary: #4096ff;
|
$secondary: #4096ff;
|
||||||
$success: #52c41a;
|
$success: #52c41a;
|
||||||
$warning: #faad14;
|
$warning: #faad14;
|
||||||
$error: #ff4d4f;
|
$error: #ff4d4f;
|
||||||
|
|
||||||
$background: #f5f5f5;
|
$background: #f5f7fa;
|
||||||
$surface: #ffffff;
|
$surface: #ffffff;
|
||||||
|
|
||||||
$text: rgba(0, 0, 0, 0.85);
|
$text: rgba(0, 0, 0, 0.85);
|
||||||
@ -35,7 +35,7 @@ $text-muted: rgba(0, 0, 0, 0.45);
|
|||||||
$border: #d9d9d9;
|
$border: #d9d9d9;
|
||||||
$border-light: #e8e8e8;
|
$border-light: #e8e8e8;
|
||||||
|
|
||||||
$gradient-primary: linear-gradient(135deg, $primary 0%, $primary-light 100%);
|
$gradient-primary: linear-gradient(135deg, $primary 0%, $primary-dark 100%);
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -46,9 +46,9 @@ $gradient-primary: linear-gradient(135deg, $primary 0%, $primary-light 100%);
|
|||||||
|
|
||||||
| 变量 | 色值 | 用途 |
|
| 变量 | 色值 | 用途 |
|
||||||
|------|------|------|
|
|------|------|------|
|
||||||
| `$primary` | `#0958d9` | 主色、按钮、链接 |
|
| `$primary` | `#1890ff` | 主色、按钮、链接 |
|
||||||
| `$primary-light` | `#1677ff` | 悬停态 |
|
| `$primary-dark` | `#0958d9` | 渐变深色、激活态 |
|
||||||
| `$primary-dark` | `#003eb3` | 激活态 |
|
| `$primary-light` | `#40a9ff` | 悬停态、浅色 |
|
||||||
| `$secondary` | `#4096ff` | 辅助蓝 |
|
| `$secondary` | `#4096ff` | 辅助蓝 |
|
||||||
|
|
||||||
### 功能色
|
### 功能色
|
||||||
@ -156,20 +156,45 @@ $gradient-primary: linear-gradient(135deg, $primary 0%, $primary-light 100%);
|
|||||||
</a-button>
|
</a-button>
|
||||||
```
|
```
|
||||||
|
|
||||||
### 主按钮
|
### 主按钮(渐变样式)
|
||||||
|
|
||||||
```scss
|
```scss
|
||||||
.primary-btn {
|
.primary-btn,
|
||||||
background: $gradient-primary !important;
|
.gradient-btn {
|
||||||
|
background: linear-gradient(135deg, $primary 0%, $primary-dark 100%) !important;
|
||||||
border: none !important;
|
border: none !important;
|
||||||
color: #fff !important;
|
color: #fff !important;
|
||||||
font-weight: 500 !important;
|
font-weight: 500 !important;
|
||||||
|
border-radius: 20px !important;
|
||||||
|
padding: 6px 16px !important;
|
||||||
transition: all 0.3s ease !important;
|
transition: all 0.3s ease !important;
|
||||||
|
box-shadow: 0 2px 8px rgba($primary, 0.3);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
filter: brightness(1.1);
|
|
||||||
transform: translateY(-2px);
|
transform: translateY(-2px);
|
||||||
box-shadow: 0 12px 24px rgba($primary, 0.2);
|
box-shadow: 0 6px 20px rgba($primary, 0.4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用于 hero 区域的大按钮
|
||||||
|
.action-btn.primary {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 12px 28px;
|
||||||
|
border-radius: 24px;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 600;
|
||||||
|
background: linear-gradient(135deg, $primary 0%, $primary-dark 100%);
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
box-shadow: 0 4px 15px rgba($primary, 0.4);
|
||||||
|
transition: all 0.3s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 6px 20px rgba($primary, 0.5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@ -211,26 +211,25 @@ const handleLogout = async () => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
$primary: #1890ff;
|
||||||
|
$primary-dark: #0958d9;
|
||||||
|
$primary-light: #40a9ff;
|
||||||
|
|
||||||
.layout {
|
.layout {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 自定义侧边栏样式 - 参考图片中的浅灰色背景
|
// 渐变主题风格侧边栏
|
||||||
.custom-sider {
|
.custom-sider {
|
||||||
background: var(--sidebar-bg, #f5f5f5) !important; // 浅灰色背景,参考图片
|
background: #fff !important;
|
||||||
border-right: none !important; // 去掉右侧边框线
|
border-right: none !important;
|
||||||
|
box-shadow: 2px 0 12px rgba(0, 0, 0, 0.05);
|
||||||
|
|
||||||
:deep(.ant-layout-sider-children) {
|
:deep(.ant-layout-sider-children) {
|
||||||
background: var(--sidebar-bg, #f5f5f5);
|
background: #fff;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 确保 Ant Design Vue 的默认边框被移除
|
|
||||||
:deep(.ant-layout-sider) {
|
|
||||||
border-right: none !important;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,10 +243,37 @@ const handleLogout = async () => {
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
|
padding: 0 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Logo 区域 - 简洁风格
|
||||||
|
.logo {
|
||||||
|
height: 64px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 16px 12px;
|
||||||
|
border-bottom: 1px solid rgba(0, 0, 0, 0.06);
|
||||||
|
margin-bottom: 8px;
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 32px;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-text {
|
||||||
|
color: $primary;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 700;
|
||||||
|
margin: 0;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 底部用户区域
|
||||||
.sider-bottom {
|
.sider-bottom {
|
||||||
padding: 12px;
|
padding: 12px 16px;
|
||||||
border-top: 1px solid rgba(0, 0, 0, 0.06);
|
border-top: 1px solid rgba(0, 0, 0, 0.06);
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -258,7 +284,7 @@ const handleLogout = async () => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
padding: 8px;
|
padding: 6px 10px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.3s;
|
transition: all 0.3s;
|
||||||
@ -266,12 +292,17 @@ const handleLogout = async () => {
|
|||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: var(--sidebar-menu-item-selected-bg, #e2f0ed);
|
background: rgba($primary, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-avatar) {
|
||||||
|
border: 2px solid rgba($primary, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.username {
|
.username {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: var(--sidebar-menu-text, rgba(0, 0, 0, 0.85));
|
font-weight: 500;
|
||||||
|
color: rgba(0, 0, 0, 0.85);
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
@ -280,7 +311,7 @@ const handleLogout = async () => {
|
|||||||
|
|
||||||
.user-info-collapsed {
|
.user-info-collapsed {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 8px;
|
padding: 6px;
|
||||||
flex: unset;
|
flex: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,15 +321,15 @@ const handleLogout = async () => {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
border-radius: 6px;
|
border-radius: 8px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.3s;
|
transition: all 0.3s;
|
||||||
color: var(--sidebar-menu-text, rgba(0, 0, 0, 0.65));
|
color: rgba(0, 0, 0, 0.45);
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: var(--sidebar-menu-item-selected-bg, #e2f0ed);
|
background: rgba($primary, 0.08);
|
||||||
color: var(--sidebar-menu-text-selected, #01412b);
|
color: $primary;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -306,7 +337,7 @@ const handleLogout = async () => {
|
|||||||
.sider-bottom-collapsed {
|
.sider-bottom-collapsed {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 12px;
|
gap: 10px;
|
||||||
padding: 12px 8px;
|
padding: 12px 8px;
|
||||||
|
|
||||||
.collapse-trigger {
|
.collapse-trigger {
|
||||||
@ -314,59 +345,51 @@ const handleLogout = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo {
|
// 覆盖 Ant Design 默认边框
|
||||||
height: 64px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
background: transparent; // 透明背景,与侧边栏一致
|
|
||||||
color: var(--sidebar-menu-text-selected, #01412b); // Logo 文字使用主题色
|
|
||||||
margin-bottom: 8px;
|
|
||||||
border-radius: 0; // 保持直角,与图片一致
|
|
||||||
padding: 20px 12px;
|
|
||||||
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
max-height: 30px;
|
|
||||||
object-fit: contain;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo-text {
|
|
||||||
color: var(--sidebar-menu-text-selected, #01412b); // Logo 文字使用主题色
|
|
||||||
font-size: 18px;
|
|
||||||
font-weight: bold;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 覆盖 Ant Design 默认的右侧边框(使用全局选择器)
|
|
||||||
:deep(.ant-menu-light.ant-menu-root.ant-menu-inline),
|
:deep(.ant-menu-light.ant-menu-root.ant-menu-inline),
|
||||||
:deep(.ant-menu-light.ant-menu-root.ant-menu-vertical) {
|
:deep(.ant-menu-light.ant-menu-root.ant-menu-vertical) {
|
||||||
border-inline-end: none !important;
|
border-inline-end: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 自定义菜单样式
|
// 菜单样式 - 渐变主题
|
||||||
.custom-menu {
|
.custom-menu {
|
||||||
background: transparent !important;
|
background: transparent !important;
|
||||||
border-right: none !important;
|
border-right: none !important;
|
||||||
border-inline-end: none !important;
|
border-inline-end: none !important;
|
||||||
|
padding: 4px 0;
|
||||||
|
|
||||||
:deep(.ant-menu-item) {
|
:deep(.ant-menu-item) {
|
||||||
color: var(--sidebar-menu-text, rgba(0, 0, 0, 0.85));
|
color: rgba(0, 0, 0, 0.75);
|
||||||
margin: 4px 8px;
|
margin: 4px 0;
|
||||||
border-radius: 6px;
|
border-radius: 10px;
|
||||||
transition: all 0.3s;
|
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
background: transparent !important;
|
background: transparent !important;
|
||||||
|
height: 44px;
|
||||||
|
line-height: 44px;
|
||||||
|
|
||||||
|
.anticon {
|
||||||
|
font-size: 16px;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: var(--sidebar-menu-item-selected-bg, #e2f0ed) !important;
|
color: $primary !important;
|
||||||
color: var(--sidebar-menu-text-selected, #01412b) !important;
|
background: rgba($primary, 0.08) !important;
|
||||||
|
|
||||||
|
.anticon {
|
||||||
|
color: $primary;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.ant-menu-item-selected {
|
&.ant-menu-item-selected {
|
||||||
background: var(--sidebar-menu-item-selected-bg, #e2f0ed) !important;
|
color: #fff !important;
|
||||||
color: var(--sidebar-menu-text-selected, #01412b) !important;
|
background: linear-gradient(135deg, $primary 0%, $primary-dark 100%) !important;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
box-shadow: 0 2px 8px rgba($primary, 0.3);
|
||||||
|
|
||||||
|
.anticon {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
display: none;
|
display: none;
|
||||||
@ -376,34 +399,41 @@ const handleLogout = async () => {
|
|||||||
|
|
||||||
:deep(.ant-menu-submenu) {
|
:deep(.ant-menu-submenu) {
|
||||||
.ant-menu-submenu-title {
|
.ant-menu-submenu-title {
|
||||||
color: var(--sidebar-menu-text, rgba(0, 0, 0, 0.85));
|
color: rgba(0, 0, 0, 0.75);
|
||||||
margin: 4px 8px;
|
margin: 4px 0;
|
||||||
border-radius: 6px;
|
border-radius: 10px;
|
||||||
transition: all 0.3s;
|
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
background: transparent !important;
|
background: transparent !important;
|
||||||
|
height: 44px;
|
||||||
|
line-height: 44px;
|
||||||
|
|
||||||
|
.anticon {
|
||||||
|
font-size: 16px;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: var(--sidebar-menu-item-selected-bg, #e2f0ed) !important;
|
color: $primary !important;
|
||||||
color: var(--sidebar-menu-text-selected, #01412b) !important;
|
background: rgba($primary, 0.08) !important;
|
||||||
|
|
||||||
|
.anticon {
|
||||||
|
color: $primary;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.ant-menu-submenu-open > .ant-menu-submenu-title {
|
&.ant-menu-submenu-open > .ant-menu-submenu-title {
|
||||||
color: var(--sidebar-menu-text-selected, #01412b);
|
color: $primary;
|
||||||
background: var(--sidebar-menu-item-selected-bg, #e2f0ed) !important;
|
background: rgba($primary, 0.08) !important;
|
||||||
|
|
||||||
|
.anticon {
|
||||||
|
color: $primary;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.ant-menu-submenu-selected > .ant-menu-submenu-title {
|
&.ant-menu-submenu-selected > .ant-menu-submenu-title {
|
||||||
color: var(--sidebar-menu-text-selected, #01412b);
|
color: $primary;
|
||||||
background: var(--sidebar-menu-item-selected-bg, #e2f0ed) !important;
|
font-weight: 500;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.ant-menu-submenu-inner) {
|
|
||||||
.ant-menu-submenu-title {
|
|
||||||
&:hover {
|
|
||||||
background: var(--sidebar-menu-item-selected-bg, #e2f0ed) !important;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -412,20 +442,27 @@ const handleLogout = async () => {
|
|||||||
|
|
||||||
.ant-menu-item {
|
.ant-menu-item {
|
||||||
padding-left: 48px !important;
|
padding-left: 48px !important;
|
||||||
background: transparent !important;
|
height: 40px;
|
||||||
|
line-height: 40px;
|
||||||
&:hover {
|
margin: 2px 0;
|
||||||
background: var(--sidebar-menu-item-selected-bg, #e2f0ed) !important;
|
|
||||||
color: var(--sidebar-menu-text-selected, #01412b) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.ant-menu-item-selected {
|
&.ant-menu-item-selected {
|
||||||
background: var(--sidebar-menu-item-selected-bg, #e2f0ed) !important;
|
background: linear-gradient(135deg, $primary 0%, $primary-dark 100%) !important;
|
||||||
color: var(--sidebar-menu-text-selected, #01412b) !important;
|
box-shadow: 0 2px 8px rgba($primary, 0.3);
|
||||||
font-weight: 500;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 展开箭头样式
|
||||||
|
:deep(.ant-menu-submenu-arrow) {
|
||||||
|
color: rgba(0, 0, 0, 0.45);
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-menu-submenu-open > .ant-menu-submenu-title > .ant-menu-submenu-arrow),
|
||||||
|
:deep(.ant-menu-submenu:hover > .ant-menu-submenu-title > .ant-menu-submenu-arrow) {
|
||||||
|
color: $primary;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-layout {
|
.main-layout {
|
||||||
@ -435,7 +472,7 @@ const handleLogout = async () => {
|
|||||||
|
|
||||||
.content {
|
.content {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
background: #fff;
|
background: #f5f7fa;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
|
|||||||
@ -523,9 +523,10 @@ onMounted(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
// 主题色
|
// 主题色 - 统一色系
|
||||||
$primary: #0958d9;
|
$primary: #1890ff;
|
||||||
$primary-light: #1677ff;
|
$primary-dark: #0958d9;
|
||||||
|
$primary-light: #40a9ff;
|
||||||
|
|
||||||
.contests-activities-page {
|
.contests-activities-page {
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
@ -582,7 +583,7 @@ $primary-light: #1677ff;
|
|||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background: linear-gradient(135deg, $primary-light 0%, $primary 100%);
|
background: linear-gradient(135deg, $primary 0%, $primary-dark 100%);
|
||||||
box-shadow: 0 4px 12px rgba($primary, 0.35);
|
box-shadow: 0 4px 12px rgba($primary, 0.35);
|
||||||
|
|
||||||
.anticon {
|
.anticon {
|
||||||
@ -834,19 +835,19 @@ $primary-light: #1677ff;
|
|||||||
padding: 6px 16px;
|
padding: 6px 16px;
|
||||||
height: auto;
|
height: auto;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
background: linear-gradient(135deg, #1890ff 0%, #0050b3 100%);
|
background: linear-gradient(135deg, $primary 0%, $primary-dark 100%);
|
||||||
box-shadow: 0 4px 12px rgba(24, 144, 255, 0.4);
|
box-shadow: 0 2px 8px rgba($primary, 0.3);
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: linear-gradient(135deg, #40a9ff 0%, #1890ff 100%);
|
background: linear-gradient(135deg, $primary-light 0%, $primary 100%);
|
||||||
box-shadow: 0 6px 16px rgba(24, 144, 255, 0.5);
|
box-shadow: 0 4px 12px rgba($primary, 0.4);
|
||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:active {
|
&:active {
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
box-shadow: 0 2px 8px rgba(24, 144, 255, 0.4);
|
box-shadow: 0 2px 6px rgba($primary, 0.3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -864,7 +865,7 @@ $primary-light: #1677ff;
|
|||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: linear-gradient(135deg, #e8ecf0 0%, #dce1e6 100%);
|
background: linear-gradient(135deg, #e8ecf0 0%, #dce1e6 100%);
|
||||||
color: #1890ff;
|
color: $primary;
|
||||||
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
|
||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,7 +30,9 @@
|
|||||||
<!-- 状态标签 -->
|
<!-- 状态标签 -->
|
||||||
<div class="status-tags">
|
<div class="status-tags">
|
||||||
<span class="tag tag-type">
|
<span class="tag tag-type">
|
||||||
{{ contest?.contestType === "individual" ? "个人赛" : "团队赛" }}
|
{{
|
||||||
|
contest?.contestType === "individual" ? "个人赛" : "团队赛"
|
||||||
|
}}
|
||||||
</span>
|
</span>
|
||||||
<span v-if="getStageText()" class="tag" :class="getStageClass()">
|
<span v-if="getStageText()" class="tag" :class="getStageClass()">
|
||||||
{{ getStageText() }}
|
{{ getStageText() }}
|
||||||
@ -44,11 +46,17 @@
|
|||||||
<div class="hero-meta">
|
<div class="hero-meta">
|
||||||
<div class="meta-item">
|
<div class="meta-item">
|
||||||
<CalendarOutlined />
|
<CalendarOutlined />
|
||||||
<span>比赛时间:{{ formatDate(contest?.startTime) }} ~ {{ formatDate(contest?.endTime) }}</span>
|
<span
|
||||||
|
>比赛时间:{{ formatDate(contest?.startTime) }} ~
|
||||||
|
{{ formatDate(contest?.endTime) }}</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="meta-item">
|
<div class="meta-item">
|
||||||
<ClockCircleOutlined />
|
<ClockCircleOutlined />
|
||||||
<span>报名时间:{{ formatDate(contest?.registerStartTime) }} ~ {{ formatDate(contest?.registerEndTime) }}</span>
|
<span
|
||||||
|
>报名时间:{{ formatDate(contest?.registerStartTime) }} ~
|
||||||
|
{{ formatDate(contest?.registerEndTime) }}</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -76,7 +84,7 @@
|
|||||||
disabled
|
disabled
|
||||||
>
|
>
|
||||||
<FormOutlined />
|
<FormOutlined />
|
||||||
{{ isRegistering ? '立即报名' : '报名已截止' }}
|
{{ isRegistering ? "立即报名" : "报名已截止" }}
|
||||||
</button>
|
</button>
|
||||||
<span v-if="isRegistering" class="countdown">
|
<span v-if="isRegistering" class="countdown">
|
||||||
距离报名截止还有 <strong>{{ daysRemaining }}</strong> 天
|
距离报名截止还有 <strong>{{ daysRemaining }}</strong> 天
|
||||||
@ -105,7 +113,9 @@
|
|||||||
>
|
>
|
||||||
<BellOutlined />
|
<BellOutlined />
|
||||||
<span>通知公告</span>
|
<span>通知公告</span>
|
||||||
<span v-if="notices.length > 0" class="badge">{{ notices.length }}</span>
|
<span v-if="notices.length > 0" class="badge">{{
|
||||||
|
notices.length
|
||||||
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="tab-item"
|
class="tab-item"
|
||||||
@ -134,7 +144,11 @@
|
|||||||
<h2>竞赛详情</h2>
|
<h2>竞赛详情</h2>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div v-if="contest.content" class="rich-content" v-html="contest.content"></div>
|
<div
|
||||||
|
v-if="contest.content"
|
||||||
|
class="rich-content"
|
||||||
|
v-html="contest.content"
|
||||||
|
></div>
|
||||||
<a-empty v-else description="暂无详情内容" />
|
<a-empty v-else description="暂无详情内容" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -151,11 +165,18 @@
|
|||||||
<div v-if="noticesLoading" class="loading-placeholder">
|
<div v-if="noticesLoading" class="loading-placeholder">
|
||||||
<a-spin />
|
<a-spin />
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="notices.length === 0" class="empty-placeholder">
|
<div
|
||||||
|
v-else-if="notices.length === 0"
|
||||||
|
class="empty-placeholder"
|
||||||
|
>
|
||||||
<a-empty description="暂无公告" />
|
<a-empty description="暂无公告" />
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="notice-list">
|
<div v-else class="notice-list">
|
||||||
<div v-for="item in notices" :key="item.id" class="notice-item">
|
<div
|
||||||
|
v-for="item in notices"
|
||||||
|
:key="item.id"
|
||||||
|
class="notice-item"
|
||||||
|
>
|
||||||
<div class="notice-header">
|
<div class="notice-header">
|
||||||
<span class="notice-title">{{ item.title }}</span>
|
<span class="notice-title">{{ item.title }}</span>
|
||||||
<span class="notice-type" :class="item.noticeType">
|
<span class="notice-type" :class="item.noticeType">
|
||||||
@ -192,15 +213,26 @@
|
|||||||
>
|
>
|
||||||
<template #bodyCell="{ column, record }">
|
<template #bodyCell="{ column, record }">
|
||||||
<template v-if="column.key === 'rank'">
|
<template v-if="column.key === 'rank'">
|
||||||
<div class="rank-badge" :class="getRankClass(record.rank)">
|
<div
|
||||||
|
class="rank-badge"
|
||||||
|
:class="getRankClass(record.rank)"
|
||||||
|
>
|
||||||
{{ record.rank || "-" }}
|
{{ record.rank || "-" }}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="column.key === 'author'">
|
<template v-else-if="column.key === 'author'">
|
||||||
{{ record.registration?.user?.nickname || record.registration?.team?.teamName || "-" }}
|
{{
|
||||||
|
record.registration?.user?.nickname ||
|
||||||
|
record.registration?.team?.teamName ||
|
||||||
|
"-"
|
||||||
|
}}
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="column.key === 'award'">
|
<template v-else-if="column.key === 'award'">
|
||||||
<span v-if="record.awardName" class="award-tag" :class="getAwardClass(record.awardName)">
|
<span
|
||||||
|
v-if="record.awardName"
|
||||||
|
class="award-tag"
|
||||||
|
:class="getAwardClass(record.awardName)"
|
||||||
|
>
|
||||||
{{ record.awardName }}
|
{{ record.awardName }}
|
||||||
</span>
|
</span>
|
||||||
<span v-else>-</span>
|
<span v-else>-</span>
|
||||||
@ -230,8 +262,16 @@
|
|||||||
主办单位
|
主办单位
|
||||||
</div>
|
</div>
|
||||||
<div class="item-value">
|
<div class="item-value">
|
||||||
<template v-if="contest.organizers && contest.organizers.length">
|
<template
|
||||||
<div v-for="org in contest.organizers" :key="org" class="org-name">{{ org }}</div>
|
v-if="contest.organizers && contest.organizers.length"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="org in contest.organizers"
|
||||||
|
:key="org"
|
||||||
|
class="org-name"
|
||||||
|
>
|
||||||
|
{{ org }}
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<span v-else class="empty-text">暂无</span>
|
<span v-else class="empty-text">暂无</span>
|
||||||
</div>
|
</div>
|
||||||
@ -243,8 +283,18 @@
|
|||||||
协办单位
|
协办单位
|
||||||
</div>
|
</div>
|
||||||
<div class="item-value">
|
<div class="item-value">
|
||||||
<template v-if="contest.coOrganizers && contest.coOrganizers.length">
|
<template
|
||||||
<div v-for="org in contest.coOrganizers" :key="org" class="org-name">{{ org }}</div>
|
v-if="
|
||||||
|
contest.coOrganizers && contest.coOrganizers.length
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="org in contest.coOrganizers"
|
||||||
|
:key="org"
|
||||||
|
class="org-name"
|
||||||
|
>
|
||||||
|
{{ org }}
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<span v-else class="empty-text">暂无</span>
|
<span v-else class="empty-text">暂无</span>
|
||||||
</div>
|
</div>
|
||||||
@ -256,8 +306,16 @@
|
|||||||
赞助单位
|
赞助单位
|
||||||
</div>
|
</div>
|
||||||
<div class="item-value">
|
<div class="item-value">
|
||||||
<template v-if="contest.sponsors && contest.sponsors.length">
|
<template
|
||||||
<div v-for="sp in contest.sponsors" :key="sp" class="org-name">{{ sp }}</div>
|
v-if="contest.sponsors && contest.sponsors.length"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="sp in contest.sponsors"
|
||||||
|
:key="sp"
|
||||||
|
class="org-name"
|
||||||
|
>
|
||||||
|
{{ sp }}
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<span v-else class="empty-text">暂无</span>
|
<span v-else class="empty-text">暂无</span>
|
||||||
</div>
|
</div>
|
||||||
@ -266,7 +324,10 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 联系方式 -->
|
<!-- 联系方式 -->
|
||||||
<div v-if="contest.contactName || contest.contactPhone" class="sidebar-card">
|
<div
|
||||||
|
v-if="contest.contactName || contest.contactPhone"
|
||||||
|
class="sidebar-card"
|
||||||
|
>
|
||||||
<div class="sidebar-header">
|
<div class="sidebar-header">
|
||||||
<PhoneOutlined />
|
<PhoneOutlined />
|
||||||
<span>联系方式</span>
|
<span>联系方式</span>
|
||||||
@ -293,7 +354,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a-empty v-else-if="!loading" description="比赛不存在" style="padding: 100px 0" />
|
<a-empty
|
||||||
|
v-else-if="!loading"
|
||||||
|
description="比赛不存在"
|
||||||
|
style="padding: 100px 0"
|
||||||
|
/>
|
||||||
</a-spin>
|
</a-spin>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -347,7 +412,10 @@ const myRegistration = ref<any>(null)
|
|||||||
|
|
||||||
const canViewRegistration = computed(() => {
|
const canViewRegistration = computed(() => {
|
||||||
const permissions = authStore.user?.permissions || []
|
const permissions = authStore.user?.permissions || []
|
||||||
return permissions.includes("registration:read") || permissions.includes("registration:create")
|
return (
|
||||||
|
permissions.includes("registration:read") ||
|
||||||
|
permissions.includes("registration:create")
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
const isTeacher = computed(() => authStore.hasRole("teacher"))
|
const isTeacher = computed(() => authStore.hasRole("teacher"))
|
||||||
@ -364,7 +432,13 @@ const resultColumns = [
|
|||||||
{ title: "排名", key: "rank", dataIndex: "rank", width: 80 },
|
{ title: "排名", key: "rank", dataIndex: "rank", width: 80 },
|
||||||
{ title: "作品名称", key: "title", dataIndex: "title", width: 200 },
|
{ title: "作品名称", key: "title", dataIndex: "title", width: 200 },
|
||||||
{ title: "作者", key: "author", width: 150 },
|
{ title: "作者", key: "author", width: 150 },
|
||||||
{ title: "最终得分", key: "finalScore", dataIndex: "finalScore", width: 120, sorter: true },
|
{
|
||||||
|
title: "最终得分",
|
||||||
|
key: "finalScore",
|
||||||
|
dataIndex: "finalScore",
|
||||||
|
width: 120,
|
||||||
|
sorter: true,
|
||||||
|
},
|
||||||
{ title: "奖项", key: "award", width: 120 },
|
{ title: "奖项", key: "award", width: 120 },
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -387,15 +461,23 @@ const isRegistering = computed(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const isSubmitting = computed(() => {
|
const isSubmitting = computed(() => {
|
||||||
if (!contest.value?.submitStartTime || !contest.value?.submitEndTime) return false
|
if (!contest.value?.submitStartTime || !contest.value?.submitEndTime)
|
||||||
|
return false
|
||||||
const now = dayjs()
|
const now = dayjs()
|
||||||
return now.isAfter(dayjs(contest.value.submitStartTime)) && now.isBefore(dayjs(contest.value.submitEndTime))
|
return (
|
||||||
|
now.isAfter(dayjs(contest.value.submitStartTime)) &&
|
||||||
|
now.isBefore(dayjs(contest.value.submitEndTime))
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
const isReviewing = computed(() => {
|
const isReviewing = computed(() => {
|
||||||
if (!contest.value?.reviewStartTime || !contest.value?.reviewEndTime) return false
|
if (!contest.value?.reviewStartTime || !contest.value?.reviewEndTime)
|
||||||
|
return false
|
||||||
const now = dayjs()
|
const now = dayjs()
|
||||||
return now.isAfter(dayjs(contest.value.reviewStartTime)) && now.isBefore(dayjs(contest.value.reviewEndTime))
|
return (
|
||||||
|
now.isAfter(dayjs(contest.value.reviewStartTime)) &&
|
||||||
|
now.isBefore(dayjs(contest.value.reviewEndTime))
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
const daysRemaining = computed(() => {
|
const daysRemaining = computed(() => {
|
||||||
@ -422,9 +504,12 @@ const getStageClass = () => {
|
|||||||
|
|
||||||
const getNoticeTypeText = (type?: string) => {
|
const getNoticeTypeText = (type?: string) => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "urgent": return "紧急"
|
case "urgent":
|
||||||
case "system": return "系统"
|
return "紧急"
|
||||||
default: return "公告"
|
case "system":
|
||||||
|
return "系统"
|
||||||
|
default:
|
||||||
|
return "公告"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -488,7 +573,11 @@ const fetchResults = async () => {
|
|||||||
if (!contest.value || contest.value.resultState !== "published") return
|
if (!contest.value || contest.value.resultState !== "published") return
|
||||||
resultsLoading.value = true
|
resultsLoading.value = true
|
||||||
try {
|
try {
|
||||||
const response = await resultsApi.getResults(contestId, resultsPagination.value.current, resultsPagination.value.pageSize)
|
const response = await resultsApi.getResults(
|
||||||
|
contestId,
|
||||||
|
resultsPagination.value.current,
|
||||||
|
resultsPagination.value.pageSize
|
||||||
|
)
|
||||||
results.value = response.list || []
|
results.value = response.list || []
|
||||||
resultsPagination.value.total = response.total || 0
|
resultsPagination.value.total = response.total || 0
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
@ -566,7 +655,11 @@ $primary-dark: #0958d9;
|
|||||||
.hero-overlay {
|
.hero-overlay {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
background: linear-gradient(180deg, rgba(0,0,0,0.3) 0%, rgba(0,0,0,0.6) 100%);
|
background: linear-gradient(
|
||||||
|
180deg,
|
||||||
|
rgba(0, 0, 0, 0.3) 0%,
|
||||||
|
rgba(0, 0, 0, 0.6) 100%
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-nav {
|
.hero-nav {
|
||||||
@ -628,10 +721,18 @@ $primary-dark: #0958d9;
|
|||||||
border: 1px solid rgba(255, 255, 255, 0.3);
|
border: 1px solid rgba(255, 255, 255, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tag-registering { background: linear-gradient(135deg, #52c41a, #73d13d); }
|
.tag-registering {
|
||||||
.tag-submitting { background: linear-gradient(135deg, #1890ff, #40a9ff); }
|
background: linear-gradient(135deg, #52c41a, #73d13d);
|
||||||
.tag-reviewing { background: linear-gradient(135deg, #faad14, #ffc53d); }
|
}
|
||||||
.tag-finished { background: linear-gradient(135deg, #8c8c8c, #bfbfbf); }
|
.tag-submitting {
|
||||||
|
background: linear-gradient(135deg, #1890ff, #40a9ff);
|
||||||
|
}
|
||||||
|
.tag-reviewing {
|
||||||
|
background: linear-gradient(135deg, #faad14, #ffc53d);
|
||||||
|
}
|
||||||
|
.tag-finished {
|
||||||
|
background: linear-gradient(135deg, #8c8c8c, #bfbfbf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-title {
|
.hero-title {
|
||||||
@ -656,7 +757,9 @@ $primary-dark: #0958d9;
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: rgba(255, 255, 255, 0.9);
|
color: rgba(255, 255, 255, 0.9);
|
||||||
|
|
||||||
.anticon { font-size: 16px; }
|
.anticon {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -721,7 +824,7 @@ $primary-dark: #0958d9;
|
|||||||
background: #fff;
|
background: #fff;
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
top: -20px;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
|
|
||||||
.tab-container {
|
.tab-container {
|
||||||
@ -782,7 +885,7 @@ $primary-dark: #0958d9;
|
|||||||
padding: 24px 0 48px;
|
padding: 24px 0 48px;
|
||||||
|
|
||||||
.main-container {
|
.main-container {
|
||||||
padding: 0 24px;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-grid {
|
.content-grid {
|
||||||
@ -839,15 +942,24 @@ $primary-dark: #0958d9;
|
|||||||
|
|
||||||
:deep(p) {
|
:deep(p) {
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
&:last-child { margin-bottom: 0; }
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(h1), :deep(h2), :deep(h3), :deep(h4), :deep(h5), :deep(h6) {
|
:deep(h1),
|
||||||
|
:deep(h2),
|
||||||
|
:deep(h3),
|
||||||
|
:deep(h4),
|
||||||
|
:deep(h5),
|
||||||
|
:deep(h6) {
|
||||||
color: rgba(0, 0, 0, 0.85);
|
color: rgba(0, 0, 0, 0.85);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
margin-top: 24px;
|
margin-top: 24px;
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
&:first-child { margin-top: 0; }
|
&:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(img) {
|
:deep(img) {
|
||||||
@ -856,7 +968,8 @@ $primary-dark: #0958d9;
|
|||||||
margin: 16px 0;
|
margin: 16px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(ul), :deep(ol) {
|
:deep(ul),
|
||||||
|
:deep(ol) {
|
||||||
padding-left: 24px;
|
padding-left: 24px;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
}
|
}
|
||||||
@ -870,7 +983,8 @@ $primary-dark: #0958d9;
|
|||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
margin: 16px 0;
|
margin: 16px 0;
|
||||||
|
|
||||||
th, td {
|
th,
|
||||||
|
td {
|
||||||
border: 1px solid #e8e8e8;
|
border: 1px solid #e8e8e8;
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
@ -893,7 +1007,9 @@ $primary-dark: #0958d9;
|
|||||||
:deep(a) {
|
:deep(a) {
|
||||||
color: $primary;
|
color: $primary;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
&:hover { text-decoration: underline; }
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -905,7 +1021,9 @@ $primary-dark: #0958d9;
|
|||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
|
|
||||||
&:last-child { margin-bottom: 0; }
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.notice-header {
|
.notice-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -925,8 +1043,14 @@ $primary-dark: #0958d9;
|
|||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
|
||||||
&.urgent { background: #fff2f0; color: #ff4d4f; }
|
&.urgent {
|
||||||
&.system { background: #e6f7ff; color: #1890ff; }
|
background: #fff2f0;
|
||||||
|
color: #ff4d4f;
|
||||||
|
}
|
||||||
|
&.system {
|
||||||
|
background: #e6f7ff;
|
||||||
|
color: #1890ff;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -960,9 +1084,18 @@ $primary-dark: #0958d9;
|
|||||||
background: #f0f0f0;
|
background: #f0f0f0;
|
||||||
color: rgba(0, 0, 0, 0.65);
|
color: rgba(0, 0, 0, 0.65);
|
||||||
|
|
||||||
&.rank-1 { background: linear-gradient(135deg, #ffd700, #ffb800); color: #fff; }
|
&.rank-1 {
|
||||||
&.rank-2 { background: linear-gradient(135deg, #c0c0c0, #a0a0a0); color: #fff; }
|
background: linear-gradient(135deg, #ffd700, #ffb800);
|
||||||
&.rank-3 { background: linear-gradient(135deg, #cd7f32, #b8860b); color: #fff; }
|
color: #fff;
|
||||||
|
}
|
||||||
|
&.rank-2 {
|
||||||
|
background: linear-gradient(135deg, #c0c0c0, #a0a0a0);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
&.rank-3 {
|
||||||
|
background: linear-gradient(135deg, #cd7f32, #b8860b);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 奖项标签
|
// 奖项标签
|
||||||
@ -972,9 +1105,18 @@ $primary-dark: #0958d9;
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
|
||||||
&.award-gold { background: #fffbe6; color: #d48806; }
|
&.award-gold {
|
||||||
&.award-silver { background: #f5f5f5; color: #595959; }
|
background: #fffbe6;
|
||||||
&.award-bronze { background: #fff7e6; color: #d46b08; }
|
color: #d48806;
|
||||||
|
}
|
||||||
|
&.award-silver {
|
||||||
|
background: #f5f5f5;
|
||||||
|
color: #595959;
|
||||||
|
}
|
||||||
|
&.award-bronze {
|
||||||
|
background: #fff7e6;
|
||||||
|
color: #d46b08;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 侧边栏卡片
|
// 侧边栏卡片
|
||||||
@ -985,20 +1127,29 @@ $primary-dark: #0958d9;
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
|
|
||||||
&:last-child { margin-bottom: 0; }
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.sidebar-header {
|
.sidebar-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
padding: 16px 20px;
|
padding: 16px 20px;
|
||||||
background: linear-gradient(135deg, rgba($primary, 0.05), rgba($primary-dark, 0.08));
|
background: linear-gradient(
|
||||||
|
135deg,
|
||||||
|
rgba($primary, 0.05),
|
||||||
|
rgba($primary-dark, 0.08)
|
||||||
|
);
|
||||||
border-bottom: 1px solid #f0f0f0;
|
border-bottom: 1px solid #f0f0f0;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: rgba(0, 0, 0, 0.85);
|
color: rgba(0, 0, 0, 0.85);
|
||||||
|
|
||||||
.anticon { color: $primary; font-size: 16px; }
|
.anticon {
|
||||||
|
color: $primary;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-body {
|
.sidebar-body {
|
||||||
@ -1008,7 +1159,9 @@ $primary-dark: #0958d9;
|
|||||||
.sidebar-item {
|
.sidebar-item {
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
|
|
||||||
&:last-child { margin-bottom: 0; }
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.item-label {
|
.item-label {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -1018,7 +1171,9 @@ $primary-dark: #0958d9;
|
|||||||
color: rgba(0, 0, 0, 0.45);
|
color: rgba(0, 0, 0, 0.45);
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
|
|
||||||
.anticon { font-size: 14px; }
|
.anticon {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-value {
|
.item-value {
|
||||||
@ -1030,10 +1185,14 @@ $primary-dark: #0958d9;
|
|||||||
padding: 4px 0;
|
padding: 4px 0;
|
||||||
border-bottom: 1px dashed #f0f0f0;
|
border-bottom: 1px dashed #f0f0f0;
|
||||||
|
|
||||||
&:last-child { border-bottom: none; }
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.empty-text { color: rgba(0,0,0,0.25); }
|
.empty-text {
|
||||||
|
color: rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1061,9 +1220,16 @@ $primary-dark: #0958d9;
|
|||||||
height: auto;
|
height: auto;
|
||||||
min-height: 360px;
|
min-height: 360px;
|
||||||
|
|
||||||
.hero-title { font-size: 24px; }
|
.hero-title {
|
||||||
.hero-meta { flex-direction: column; gap: 12px; }
|
font-size: 24px;
|
||||||
.hero-actions { flex-wrap: wrap; }
|
}
|
||||||
|
.hero-meta {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
.hero-actions {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-section .custom-tabs {
|
.tab-section .custom-tabs {
|
||||||
|
|||||||
@ -361,17 +361,22 @@ const handlePreview3DModel = (fileUrl: string, index: number) => {
|
|||||||
|
|
||||||
// 收集所有模型URL用于多模型切换
|
// 收集所有模型URL用于多模型切换
|
||||||
const allModelUrls = modelItems.value.map((m) => m.fileUrl)
|
const allModelUrls = modelItems.value.map((m) => m.fileUrl)
|
||||||
|
|
||||||
|
// 存储到 sessionStorage(避免URL过长)
|
||||||
if (allModelUrls.length > 1) {
|
if (allModelUrls.length > 1) {
|
||||||
sessionStorage.setItem("model-viewer-urls", JSON.stringify(allModelUrls))
|
sessionStorage.setItem("model-viewer-urls", JSON.stringify(allModelUrls))
|
||||||
sessionStorage.setItem("model-viewer-index", String(index))
|
sessionStorage.setItem("model-viewer-index", String(index))
|
||||||
|
// 清除单URL存储
|
||||||
|
sessionStorage.removeItem("model-viewer-url")
|
||||||
} else {
|
} else {
|
||||||
|
sessionStorage.setItem("model-viewer-url", fileUrl)
|
||||||
sessionStorage.removeItem("model-viewer-urls")
|
sessionStorage.removeItem("model-viewer-urls")
|
||||||
sessionStorage.removeItem("model-viewer-index")
|
sessionStorage.removeItem("model-viewer-index")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 不在URL上携带参数
|
||||||
router.push({
|
router.push({
|
||||||
path: `/${tenantCode}/workbench/model-viewer`,
|
path: `/${tenantCode}/workbench/model-viewer`,
|
||||||
query: { url: fileUrl },
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1489,13 +1489,13 @@ onUnmounted(() => {
|
|||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
// ==========================================
|
// ==========================================
|
||||||
// 蓝色主题色彩方案 - 与系统统一
|
// 蓝色主题色彩方案 - 统一色系
|
||||||
// ==========================================
|
// ==========================================
|
||||||
$primary: #0958d9;
|
$primary: #1890ff;
|
||||||
$primary-light: #1677ff;
|
$primary-dark: #0958d9;
|
||||||
$primary-dark: #003eb3;
|
$primary-light: #40a9ff;
|
||||||
$secondary: #4096ff;
|
$secondary: #4096ff;
|
||||||
$accent: #1677ff;
|
$accent: #40a9ff;
|
||||||
$success: #52c41a;
|
$success: #52c41a;
|
||||||
$warning: #faad14;
|
$warning: #faad14;
|
||||||
$error: #ff4d4f;
|
$error: #ff4d4f;
|
||||||
@ -1509,8 +1509,8 @@ $text-secondary: rgba(0, 0, 0, 0.65);
|
|||||||
$text-muted: rgba(0, 0, 0, 0.45);
|
$text-muted: rgba(0, 0, 0, 0.45);
|
||||||
$text-light: #ffffff;
|
$text-light: #ffffff;
|
||||||
|
|
||||||
// 渐变
|
// 渐变 - 与导航栏选中按钮一致
|
||||||
$gradient-primary: linear-gradient(135deg, $primary 0%, $primary-light 100%);
|
$gradient-primary: linear-gradient(135deg, $primary 0%, $primary-dark 100%);
|
||||||
|
|
||||||
.model-viewer-page {
|
.model-viewer-page {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
|||||||
@ -355,13 +355,13 @@ onUnmounted(() => {
|
|||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
// ==========================================
|
// ==========================================
|
||||||
// 蓝色主题色彩方案 - 与 Index.vue 统一
|
// 蓝色主题色彩方案 - 统一色系
|
||||||
// ==========================================
|
// ==========================================
|
||||||
$primary: #0958d9;
|
$primary: #1890ff;
|
||||||
$primary-light: #1677ff;
|
$primary-dark: #0958d9;
|
||||||
$primary-dark: #003eb3;
|
$primary-light: #40a9ff;
|
||||||
$secondary: #4096ff;
|
$secondary: #4096ff;
|
||||||
$accent: #1677ff;
|
$accent: #40a9ff;
|
||||||
$success: #52c41a;
|
$success: #52c41a;
|
||||||
$warning: #faad14;
|
$warning: #faad14;
|
||||||
$error: #ff4d4f;
|
$error: #ff4d4f;
|
||||||
@ -376,8 +376,8 @@ $text: rgba(0, 0, 0, 0.85);
|
|||||||
$text-secondary: rgba(0, 0, 0, 0.65);
|
$text-secondary: rgba(0, 0, 0, 0.65);
|
||||||
$text-muted: rgba(0, 0, 0, 0.45);
|
$text-muted: rgba(0, 0, 0, 0.45);
|
||||||
|
|
||||||
// 渐变
|
// 渐变 - 与导航栏选中按钮一致
|
||||||
$gradient-primary: linear-gradient(135deg, $primary 0%, $primary-light 100%);
|
$gradient-primary: linear-gradient(135deg, $primary 0%, $primary-dark 100%);
|
||||||
$gradient-card: linear-gradient(
|
$gradient-card: linear-gradient(
|
||||||
145deg,
|
145deg,
|
||||||
rgba($primary, 0.05) 0%,
|
rgba($primary, 0.05) 0%,
|
||||||
|
|||||||
@ -391,11 +391,11 @@ onUnmounted(() => {
|
|||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
// ==========================================
|
// ==========================================
|
||||||
// 项目统一设计变量
|
// 项目统一设计变量 - 统一色系
|
||||||
// ==========================================
|
// ==========================================
|
||||||
$primary: #0958d9;
|
$primary: #1890ff;
|
||||||
$primary-light: #1677ff;
|
$primary-dark: #0958d9;
|
||||||
$primary-dark: #003eb3;
|
$primary-light: #40a9ff;
|
||||||
$secondary: #4096ff;
|
$secondary: #4096ff;
|
||||||
$success: #52c41a;
|
$success: #52c41a;
|
||||||
$warning: #faad14;
|
$warning: #faad14;
|
||||||
@ -412,7 +412,8 @@ $text-muted: rgba(0, 0, 0, 0.45);
|
|||||||
$border: #d9d9d9;
|
$border: #d9d9d9;
|
||||||
$border-light: #e8e8e8;
|
$border-light: #e8e8e8;
|
||||||
|
|
||||||
$gradient-primary: linear-gradient(135deg, $primary 0%, $primary-light 100%);
|
// 渐变 - 与导航栏选中按钮一致
|
||||||
|
$gradient-primary: linear-gradient(135deg, $primary 0%, $primary-dark 100%);
|
||||||
|
|
||||||
.history-page {
|
.history-page {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
|
|||||||
@ -773,14 +773,14 @@ onUnmounted(() => {
|
|||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
// ==========================================
|
// ==========================================
|
||||||
// 蓝色主题色彩方案 - 简洁统一
|
// 蓝色主题色彩方案 - 统一色系
|
||||||
// ==========================================
|
// ==========================================
|
||||||
// 主色调 - 蓝色系
|
// 主色调 - 蓝色系
|
||||||
$primary: #0958d9; // 主题蓝色(与系统统一)
|
$primary: #1890ff;
|
||||||
$primary-light: #1677ff;
|
$primary-dark: #0958d9;
|
||||||
$primary-dark: #003eb3;
|
$primary-light: #40a9ff;
|
||||||
$secondary: #4096ff; // 浅蓝色作为辅助色
|
$secondary: #4096ff;
|
||||||
$accent: #1677ff; // 蓝色强调
|
$accent: #40a9ff;
|
||||||
$success: #52c41a;
|
$success: #52c41a;
|
||||||
$warning: #faad14;
|
$warning: #faad14;
|
||||||
$error: #ff4d4f;
|
$error: #ff4d4f;
|
||||||
@ -796,9 +796,9 @@ $text-secondary: rgba(0, 0, 0, 0.65);
|
|||||||
$text-muted: rgba(0, 0, 0, 0.45);
|
$text-muted: rgba(0, 0, 0, 0.45);
|
||||||
$text-light: #ffffff; // 深色区域的白色文字
|
$text-light: #ffffff; // 深色区域的白色文字
|
||||||
|
|
||||||
// 渐变 - 蓝色渐变
|
// 渐变 - 与导航栏选中按钮一致
|
||||||
$gradient-primary: linear-gradient(135deg, $primary 0%, $primary-light 100%);
|
$gradient-primary: linear-gradient(135deg, $primary 0%, $primary-dark 100%);
|
||||||
$gradient-secondary: linear-gradient(135deg, $accent 0%, $primary 100%);
|
$gradient-secondary: linear-gradient(135deg, $primary-light 0%, $primary 100%);
|
||||||
|
|
||||||
.ai-3d-container {
|
.ai-3d-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -1335,8 +1335,8 @@ $gradient-secondary: linear-gradient(135deg, $accent 0%, $primary 100%);
|
|||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
background: linear-gradient(
|
background: linear-gradient(
|
||||||
135deg,
|
135deg,
|
||||||
$primary 0%,
|
$primary-dark 0%,
|
||||||
$primary-light 40%,
|
$primary 35%,
|
||||||
#8b5cf6 70%,
|
#8b5cf6 70%,
|
||||||
#a855f7 100%
|
#a855f7 100%
|
||||||
);
|
);
|
||||||
@ -1391,16 +1391,16 @@ $gradient-secondary: linear-gradient(135deg, $accent 0%, $primary 100%);
|
|||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
|
||||||
&.gradient-1 {
|
&.gradient-1 {
|
||||||
background: linear-gradient(135deg, $primary 0%, $primary-light 100%);
|
background: linear-gradient(135deg, $primary 0%, $primary-dark 100%);
|
||||||
}
|
}
|
||||||
&.gradient-2 {
|
&.gradient-2 {
|
||||||
background: linear-gradient(135deg, $primary-light 0%, $accent 100%);
|
background: linear-gradient(135deg, $primary-dark 0%, darken($primary-dark, 10%) 100%);
|
||||||
}
|
}
|
||||||
&.gradient-3 {
|
&.gradient-3 {
|
||||||
background: linear-gradient(135deg, $accent 0%, $primary 100%);
|
background: linear-gradient(135deg, $primary 0%, $primary-dark 100%);
|
||||||
}
|
}
|
||||||
&.gradient-4 {
|
&.gradient-4 {
|
||||||
background: linear-gradient(135deg, $primary 0%, $primary-dark 100%);
|
background: linear-gradient(135deg, $primary-dark 0%, $primary 100%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user