- 房地产新材料选材管理数据系统
+
+
{{ userInitial }}
{{ user?.username || '用户' }}
-
{{ isAdmin ? '管理员' : '普通账号' }}
+
+
+ {{ isAdmin ? '管理员' : '普通账号' }}
+
-
修改密码
-
退出
+
+
+ 修改密码
+
+
+
+ 退出
+
@@ -62,6 +93,7 @@ import { useRoute, useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import { useAuth } from '@/store/auth'
import { changePassword } from '@/api/auth'
+import BaseIcon from '@/components/BaseIcon.vue'
const route = useRoute()
const router = useRouter()
@@ -69,6 +101,10 @@ const { state, isAdmin, clearAuth } = useAuth()
const active = computed(() => route.path)
const user = computed(() => state.user)
+const userInitial = computed(() => {
+ const name = state.user?.username || ''
+ return name ? name.charAt(0).toUpperCase() : '?'
+})
const passwordVisible = ref(false)
const passwordForm = reactive({
@@ -105,25 +141,49 @@ const onLogout = () => {
display: flex;
flex-direction: column;
height: 100vh;
+ background: var(--bg);
}
.topbar {
- height: 64px;
+ height: 60px;
padding: 0 24px;
display: flex;
align-items: center;
justify-content: space-between;
background: #fff;
- box-shadow: 0 12px 24px rgba(15, 26, 42, 0.08);
+ border-bottom: 1px solid rgba(15, 26, 42, 0.06);
flex-shrink: 0;
z-index: 10;
}
+.brand {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ min-width: 0;
+}
+
+.mark {
+ width: 34px;
+ height: 34px;
+ border-radius: 9px;
+ background: linear-gradient(135deg, var(--brand-500), #6ea7d8);
+ color: #fff;
+ display: grid;
+ place-items: center;
+ font-size: 16px;
+ font-weight: 800;
+ box-shadow: 0 8px 18px rgba(78, 134, 184, 0.3);
+}
+
.logo-title {
- font-size: 18px;
+ font-size: 16px;
font-weight: 600;
color: var(--brand-900, #1b2a41);
+ letter-spacing: 0.4px;
white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
}
.user {
@@ -132,18 +192,58 @@ const onLogout = () => {
gap: 12px;
}
+.avatar {
+ width: 34px;
+ height: 34px;
+ border-radius: 50%;
+ background: linear-gradient(135deg, #4e86b8, #7cb4e3);
+ color: #fff;
+ font-weight: 700;
+ font-size: 14px;
+ display: grid;
+ place-items: center;
+ box-shadow: 0 6px 14px rgba(78, 134, 184, 0.3);
+}
+
.user-info {
text-align: right;
- line-height: 1.2;
+ line-height: 1.25;
+ min-width: 0;
}
.user-info .name {
font-weight: 600;
+ font-size: 13px;
+ color: var(--text-900);
}
.user-info .role {
- font-size: 12px;
- color: #6b7785;
+ font-size: 11px;
+ color: var(--text-600);
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ gap: 4px;
+ margin-top: 2px;
+}
+
+.role-dot {
+ width: 6px;
+ height: 6px;
+ border-radius: 50%;
+ background: #9aa6b2;
+}
+
+.role-dot.admin {
+ background: var(--accent-500);
+ box-shadow: 0 0 0 3px rgba(242, 178, 76, 0.18);
+}
+
+.topbar-btn {
+ display: inline-flex;
+ align-items: center;
+ gap: 6px;
+ border-radius: 8px;
}
.body {
@@ -159,47 +259,73 @@ const onLogout = () => {
color: #fff;
display: flex;
flex-direction: column;
+ position: relative;
+}
+
+.sidebar::before {
+ content: '';
+ position: absolute;
+ inset: 0;
+ background: radial-gradient(circle at top left, rgba(124, 180, 227, 0.12), transparent 60%);
+ pointer-events: none;
}
.menu {
border-right: none;
background: transparent;
color: #fff;
- padding-top: 12px;
+ padding: 16px 10px 0;
+ flex: 1;
+ position: relative;
+ z-index: 1;
}
-:deep(.el-menu-item) {
+:deep(.el-menu-item),
+:deep(.el-sub-menu__title) {
+ color: rgba(255, 255, 255, 0.82);
+ font-size: 14px;
+ height: 46px;
+ line-height: 46px;
+ border-radius: 10px;
+ padding: 0 14px !important;
+ margin-bottom: 4px;
+ transition: background 0.2s, color 0.2s;
+ gap: 10px;
+}
+
+:deep(.el-menu-item:hover),
+:deep(.el-sub-menu__title:hover) {
color: #fff;
- transition: all 0.2s ease;
+ background: rgba(255, 255, 255, 0.08);
}
:deep(.el-menu-item.is-active) {
- color: #7cb4e3;
- background-color: rgba(255, 255, 255, 0.12);
+ color: #fff;
+ background: linear-gradient(135deg, rgba(124, 180, 227, 0.25), rgba(78, 134, 184, 0.18));
box-shadow: inset 3px 0 0 #7cb4e3;
}
-:deep(.el-menu-item:hover) {
- color: #fff;
- background-color: rgba(255, 255, 255, 0.08);
-}
-
-:deep(.el-sub-menu__title) {
- color: #fff;
- transition: all 0.2s ease;
-}
-
-:deep(.el-sub-menu__title:hover) {
- color: #fff;
- background-color: rgba(255, 255, 255, 0.08);
-}
-
:deep(.el-sub-menu.is-active > .el-sub-menu__title) {
- color: #7cb4e3;
+ color: #fff;
}
:deep(.el-sub-menu .el-menu) {
background: transparent;
+ padding-left: 0;
+}
+
+:deep(.el-sub-menu .el-menu-item) {
+ padding-left: 40px !important;
+ font-size: 13px;
+}
+
+.sidebar-footer {
+ padding: 14px 18px;
+ font-size: 11px;
+ color: rgba(255, 255, 255, 0.35);
+ letter-spacing: 0.5px;
+ position: relative;
+ z-index: 1;
}
.main {
diff --git a/frontend/src/styles/base.css b/frontend/src/styles/base.css
index b521dde..6176de6 100644
--- a/frontend/src/styles/base.css
+++ b/frontend/src/styles/base.css
@@ -4,17 +4,25 @@
--brand-800: #203754;
--brand-700: #2f4b6b;
--brand-500: #4e86b8;
+ --brand-400: #6ea7d8;
+ --brand-300: #7cb4e3;
--accent-500: #f2b24c;
--accent-400: #ffd18a;
--bg: #f3f5fb;
--bg-soft: #eef2f9;
+ --border-soft: rgba(15, 26, 42, 0.06);
--text-900: #0f1a2a;
--text-600: #5c6b7a;
+ --text-400: #8b98a7;
--card: #ffffff;
--danger: #d64550;
+ --warning: #e8930f;
--success: #24a26a;
--radius-lg: 14px;
--radius-md: 10px;
+ --radius-sm: 8px;
+ --shadow-card: 0 6px 24px rgba(15, 26, 42, 0.06);
+ --shadow-card-lg: 0 18px 40px rgba(15, 26, 42, 0.08);
}
* {
@@ -54,25 +62,44 @@ a {
height: 100%;
padding: 20px 24px 16px;
min-height: 0;
-}
-
-.list-page .toolbar {
- flex-shrink: 0;
+ gap: 14px;
}
.list-page .page-title {
flex-shrink: 0;
+ margin: 0;
+}
+
+.list-page .toolbar {
+ flex-shrink: 0;
+ margin: 0;
+ padding: 14px 16px;
+ background: var(--card);
+ border: 1px solid var(--border-soft);
+ border-radius: var(--radius-md);
+ box-shadow: var(--shadow-card);
}
.list-page .table-wrap {
flex: 1 1 auto;
min-height: 0;
overflow: hidden;
+ background: var(--card);
+ border: 1px solid var(--border-soft);
+ border-radius: var(--radius-md);
+ box-shadow: var(--shadow-card);
}
.list-page .pagination {
flex-shrink: 0;
- margin-top: 12px;
+ margin: 0;
+ padding: 10px 16px;
+ background: var(--card);
+ border: 1px solid var(--border-soft);
+ border-radius: var(--radius-md);
+ box-shadow: var(--shadow-card);
+ display: flex;
+ justify-content: flex-end;
}
.page-title {
@@ -123,6 +150,12 @@ a {
.el-table {
border-radius: var(--radius-md);
overflow: hidden;
+ --el-table-border-color: var(--border-soft);
+ --el-table-header-bg-color: var(--bg-soft);
+}
+
+.el-table tr:hover > td {
+ background-color: rgba(78, 134, 184, 0.04) !important;
}
.table-maxheight {
@@ -156,13 +189,28 @@ a {
border-radius: var(--radius-md);
}
+.el-button {
+ border-radius: var(--radius-sm);
+ transition: transform 0.15s ease, box-shadow 0.2s ease, background 0.2s ease;
+}
+
+.el-button:active {
+ transform: translateY(1px);
+}
+
.el-button--primary {
- background: linear-gradient(135deg, var(--brand-500), #6ea7d8);
+ background: linear-gradient(135deg, var(--brand-500), var(--brand-400));
border: none;
+ box-shadow: 0 6px 14px rgba(78, 134, 184, 0.25);
}
.el-button--primary:hover {
background: linear-gradient(135deg, #3f7bb1, #7db7e7);
+ box-shadow: 0 8px 18px rgba(78, 134, 184, 0.32);
+}
+
+.el-pagination {
+ --el-pagination-button-bg-color: transparent;
}
.el-dialog {
diff --git a/frontend/src/views/BrandManage.vue b/frontend/src/views/BrandManage.vue
index e807633..f152933 100644
--- a/frontend/src/views/BrandManage.vue
+++ b/frontend/src/views/BrandManage.vue
@@ -194,16 +194,6 @@ onMounted(() => {
diff --git a/frontend/src/views/MaterialManage.vue b/frontend/src/views/MaterialManage.vue
index 040f9fd..8dcd350 100644
--- a/frontend/src/views/MaterialManage.vue
+++ b/frontend/src/views/MaterialManage.vue
@@ -741,12 +741,6 @@ onMounted(() => {
gap: 12px;
}
-.pagination {
- margin-top: 16px;
- display: flex;
- justify-content: flex-end;
-}
-
.dialog-scroll :deep(.el-dialog__body) {
max-height: 60vh;
overflow: auto;
diff --git a/frontend/src/views/UserManage.vue b/frontend/src/views/UserManage.vue
index 84564ef..0b81dc6 100644
--- a/frontend/src/views/UserManage.vue
+++ b/frontend/src/views/UserManage.vue
@@ -213,12 +213,6 @@ onMounted(() => {