Align console UI with school-iot-admin and wire login to serverschool

UI / layout
- rebuild left mode: full-width blue header (60px) + white sidebar below + card-style tags view
- introduce design tokens in variables.css (brand #347df9, sidebar 240px, menu item 49px)
  and theme overrides for dark / dark-blue themes
- restyle navigation bar (logo + platform name / top nav / tools + user), logo, sidebar
  (selected state: light blue bg + blue bar + bold), tags view, app main
- global styles: .app-container white card, .head-title, .btn-blue/.btn-white,
  el-table / el-dialog look, brand color injected into --el-color-primary
- add favorites store (localStorage) wired to sidebar star and header top nav
- disable template watermark / footer / promo notifications by default

Login (serverschool)
- port school-iot-admin login page (background art, right side card, keep-login)
- OAuth2 password mode: GET /oauth/token (raw axios) + GET /uc/account/current
- port phone lookup (/wx/getAccoutList) and forget-password flow
  (/sms/sendCode + /sms/verifyCode) as components/login/Forget.vue
- user store exposes accountInfo / accountType / teamId / roleId and strips password

Infra
- move all devServer proxies and env vars from school-iot-admin/vue.config.js
  (default targets point to production)
- fix empty sidebar: guard short-circuit skipped setRoutes when login page already
  fetched user info
This commit is contained in:
2026-10-27 09:13:39 +08:00
parent 80b8218b23
commit 47dd605067
38 changed files with 1719 additions and 464 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

@@ -1,4 +1,16 @@
// 自定义 Element Plus 样式
// 视觉规范对齐 school-iot-admin(品牌色 #347df9)
// 品牌主色(对齐 school-iot-admin 的 #347df9,让按钮/链接/开关等统一品牌色)
:root {
--el-color-primary: #347df9;
--el-color-primary-light-3: #71a4fb;
--el-color-primary-light-5: #9abefc;
--el-color-primary-light-7: #c2d8fd;
--el-color-primary-light-8: #d6e5fe;
--el-color-primary-light-9: #ebf2fe;
--el-color-primary-dark-2: #2e68cb;
}
// 分页
.el-pagination {
@@ -13,3 +25,61 @@
}
}
}
// 表格
.el-table {
--el-table-header-bg-color: #eaf1fe;
--el-table-header-text-color: #3d3e40;
--el-table-text-color: #373535;
--el-table-border-color: #ebeef5;
--el-table-row-hover-bg-color: #f2f6fc;
th.el-table__cell {
font-size: 15px;
font-weight: 500;
}
td.el-table__cell {
font-size: 14px;
}
// 斑马纹
&.el-table--striped .el-table__body tr.el-table__row--striped td.el-table__cell {
background-color: #f7faff;
}
}
// 弹窗(标题栏为品牌蓝底白字)
.el-dialog {
border-radius: 10px;
overflow: hidden;
.el-dialog__header {
margin: 0;
padding: 0 20px;
height: 48px;
display: flex;
align-items: center;
background-color: #347df9;
.el-dialog__title {
color: #ffffff;
font-size: 16px;
font-weight: 500;
}
.el-dialog__headerbtn {
top: 50%;
right: 12px;
transform: translateY(-50%);
.el-dialog__close {
color: #ffffff;
}
}
}
.el-dialog__body {
padding: 20px;
}
}
// 表单
.el-form-item__label {
font-weight: 500;
}
+51 -1
View File
@@ -16,8 +16,58 @@
@import "./view-transition.scss";
// 业务页面几乎都应该在根元素上挂载 class="app-container",以保持页面美观
// 视觉规范对齐 school-iot-admin:白卡片 + 10px 圆角 + 淡蓝阴影
.app-container {
padding: 20px;
padding: 16px 20px 20px;
background-color: var(--el-bg-color);
border-radius: 10px;
box-shadow: 0 0 10px rgba(32, 76, 131, 0.12);
}
// 页面标题(对齐 school-iot-admin 的 .head-title:左侧 6px 蓝色竖条)
.head-title {
position: relative;
display: flex;
align-items: center;
margin: 4px 0 16px;
padding-left: 14px;
font-size: 20px;
font-weight: 500;
color: var(--el-text-color-primary);
&::before {
content: "";
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
width: 6px;
height: 17px;
border-radius: 10px;
background-color: #347df9;
}
.tle {
margin: 0 5px;
}
}
// 主按钮(对齐 school-iot-admin 的 .btn-blue)
.btn-blue {
min-width: 68px;
border-radius: 2px;
font-weight: 500;
color: #ffffff;
background-color: #347df9;
border-color: #347df9;
}
// 次按钮(对齐 school-iot-admin 的 .btn-white)
.btn-white {
min-width: 68px;
border-radius: 2px;
font-weight: 500;
color: #347df9;
background-color: #ffffff;
border: 1px solid #347df9;
}
html {
@@ -4,3 +4,30 @@
$theme-name: "dark-blue";
// 主题背景颜色
$theme-bg-color: #001b44;
// dark-blue 主题下的布局变量覆盖
html.#{ $theme-name } {
// Element Plus 品牌主色(与亮色主题保持一致)
--el-color-primary: #347df9;
--el-color-primary-light-3: #2460c3;
--el-color-primary-light-5: #1a4c9e;
--el-color-primary-light-7: #10387a;
--el-color-primary-light-8: #0a2f68;
--el-color-primary-light-9: #052556;
--el-color-primary-dark-2: #5d97fa;
// Body
--v3-body-bg-color: #{$theme-bg-color};
// Sidebar 组件(深色背景下需要浅色文字)
--v3-sidebar-menu-bg-color: var(--el-bg-color);
--v3-sidebar-menu-hover-bg-color: var(--el-fill-color);
--v3-sidebar-menu-active-bg-color: var(--el-fill-color);
--v3-sidebar-menu-text-color: #cfd3dc;
--v3-sidebar-menu-active-text-color: #ffffff;
// TagsView 组件
--v3-tagsview-text-color: var(--el-text-color-regular);
--v3-tagsview-tag-bg-color: var(--el-bg-color);
--v3-tagsview-tag-bg: var(--el-bg-color);
--v3-tagsview-tag-active-bg: var(--el-color-primary);
--v3-tagsview-tag-border-color: var(--el-border-color-lighter);
}
@@ -4,3 +4,30 @@
$theme-name: "dark";
// 主题背景颜色
$theme-bg-color: #141414;
// dark 主题下的布局变量覆盖
html.#{ $theme-name } {
// Element Plus 品牌主色(与亮色主题保持一致)
--el-color-primary: #347df9;
--el-color-primary-light-3: #2a5eb4;
--el-color-primary-light-5: #244886;
--el-color-primary-light-7: #1e3459;
--el-color-primary-light-8: #1a2942;
--el-color-primary-light-9: #171e2b;
--el-color-primary-dark-2: #5d97fa;
// Body
--v3-body-bg-color: #{$theme-bg-color};
// Sidebar 组件(深色背景下需要浅色文字)
--v3-sidebar-menu-bg-color: var(--el-bg-color);
--v3-sidebar-menu-hover-bg-color: var(--el-fill-color);
--v3-sidebar-menu-active-bg-color: var(--el-fill-color);
--v3-sidebar-menu-text-color: #cfd3dc;
--v3-sidebar-menu-active-text-color: #ffffff;
// TagsView 组件
--v3-tagsview-text-color: var(--el-text-color-regular);
--v3-tagsview-tag-bg-color: var(--el-bg-color);
--v3-tagsview-tag-bg: var(--el-bg-color);
--v3-tagsview-tag-active-bg: var(--el-color-primary);
--v3-tagsview-tag-border-color: var(--el-border-color-lighter);
}
+29 -28
View File
@@ -3,37 +3,38 @@
:root {
/* Body */
--v3-body-text-color: var(--el-text-color-primary);
--v3-body-bg-color: var(--el-bg-color-page);
--v3-body-bg-color: #f5f7fa;
/* Header 区域 = NavigationBar 组件 + TagsView 组件 */
--v3-header-height: calc(
var(--v3-navigationbar-height) + var(--v3-tagsview-height) + var(--v3-header-border-bottom-width)
);
--v3-header-bg-color: var(--el-bg-color);
--v3-header-box-shadow: var(--el-box-shadow-lighter);
--v3-header-border-bottom-width: 1px;
--v3-header-border-bottom: var(--v3-header-border-bottom-width) solid var(--el-fill-color);
--v3-header-height: calc(var(--v3-navigationbar-height) + var(--v3-tagsview-height));
--v3-header-bg-color: #347df9;
--v3-header-box-shadow: none;
--v3-header-border-bottom-width: 0px;
--v3-header-border-bottom: none;
/* NavigationBar 组件 */
--v3-navigationbar-height: 50px;
--v3-navigationbar-text-color: var(--el-text-color-regular);
--v3-navigationbar-height: 60px;
--v3-navigationbar-text-color: #ffffff;
/* Sidebar 组件(左侧模式全部生效、顶部模式全部不生效、混合模式非颜色部分生效) */
--v3-sidebar-width: 220px;
--v3-sidebar-hide-width: 58px;
--v3-sidebar-border-right: 1px solid var(--el-fill-color);
--v3-sidebar-menu-item-height: 60px;
--v3-sidebar-menu-tip-line-bg-color: var(--el-color-primary);
--v3-sidebar-menu-bg-color: #001428;
--v3-sidebar-menu-hover-bg-color: #409eff10;
--v3-sidebar-menu-text-color: #cfd3dc;
--v3-sidebar-menu-active-text-color: #ffffff;
--v3-sidebar-width: 240px;
--v3-sidebar-hide-width: 64px;
--v3-sidebar-border-right: none;
--v3-sidebar-menu-item-height: 49px;
--v3-sidebar-menu-tip-line-bg-color: #347df9;
--v3-sidebar-menu-bg-color: #ffffff;
--v3-sidebar-menu-hover-bg-color: #f2f6fc;
--v3-sidebar-menu-active-bg-color: #ebf5ff;
--v3-sidebar-menu-text-color: #303133;
--v3-sidebar-menu-active-text-color: #347df9;
/* TagsView 组件 */
--v3-tagsview-height: 34px;
--v3-tagsview-text-color: var(--el-text-color-regular);
--v3-tagsview-height: 36px;
--v3-tagsview-text-color: #303133;
--v3-tagsview-tag-active-text-color: #ffffff;
--v3-tagsview-tag-bg-color: var(--el-bg-color);
--v3-tagsview-tag-active-bg-color: var(--el-color-primary);
--v3-tagsview-tag-border-radius: 2px;
--v3-tagsview-tag-border-color: var(--el-border-color-lighter);
--v3-tagsview-tag-active-border-color: var(--el-color-primary);
--v3-tagsview-tag-bg-color: #ffffff;
--v3-tagsview-tag-bg: linear-gradient(to bottom, #ffffff 20%, #90c8f7);
--v3-tagsview-tag-active-bg-color: #347df9;
--v3-tagsview-tag-active-bg: linear-gradient(to bottom, #56bafb, #0577fa);
--v3-tagsview-tag-border-radius: 4px 4px 0 0;
--v3-tagsview-tag-border-color: #d3d4d6;
--v3-tagsview-tag-active-border-color: #347df9;
--v3-tagsview-tag-icon-hover-bg-color: #00000030;
--v3-tagsview-tag-icon-hover-color: #ffffff;
--v3-tagsview-contextmenu-text-color: var(--el-text-color-regular);
@@ -42,9 +43,9 @@
--v3-tagsview-contextmenu-hover-bg-color: var(--el-fill-color);
--v3-tagsview-contextmenu-box-shadow: var(--el-box-shadow);
/* Hamburger 组件 */
--v3-hamburger-text-color: var(--el-text-color-primary);
--v3-hamburger-text-color: #ffffff;
/* RightPanel 组件 */
--v3-rightpanel-button-bg-color: #001428;
--v3-rightpanel-button-bg-color: #347df9;
}
/* 内容区放大时,将不需要的组件隐藏 */