build / build (push) Successful in 44s
三级重构(S1-S6,方案见 docs/设置中心三级重构-执行方案-20261008.md): - Settings.vue 三层化主体:curLayer=my/school/platform 单 pane 分层,主题/头像/壁纸/桌面/LOGO 按身份只渲染本级 - 桌面应用三级默认 pane(used_app SCHOOL/BASE 读写 + 角色分段 + ≤8 上限)+ 统计设置真身迁入(StatsBarModal 退役) - SysSetting.vue 去基础设置/机构树;ThemePreview 预览壳套 .layout-wrap; UsedAppApi 新增 审计缺陷修复(设置中心三级重构与消息搜索-审计报告-20261008): - 【P0】DESKTOP_ROLE_TYPES 角色 1/2 标签对齐 SysRoleEnum(1教师/2校领导/3学生),桌面默认不再张冠李戴 - 命令面板:Enter/↑↓ 加 isComposing 守卫防中文输入法误触;过滤后高亮索引归零;stagger 延迟 --i 封顶 20 - WS 通知标题移除 frame.appKey 死消费;BaseApi summary todos 类型同步去 appKey
516 lines
12 KiB
SCSS
516 lines
12 KiB
SCSS
@use "sass:color";
|
||
.default-header {
|
||
width: 100%;
|
||
height: var(--headerH);
|
||
display: flex;
|
||
padding: 0 32px;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
position: relative;
|
||
z-index: 10;
|
||
background-image: linear-gradient(
|
||
180deg,
|
||
rgba(255, 255, 255, 0.65) 0%,
|
||
rgba(255, 255, 255, 0.6) 0.02%,
|
||
rgba(255, 255, 255, 0) 101.19%
|
||
);
|
||
&.base-mask {
|
||
background-image: linear-gradient(
|
||
180deg,
|
||
rgba(255, 255, 255, 0.65) 0%,
|
||
rgba(255, 255, 255, 0.6) 0.02%,
|
||
rgba(255, 255, 255, 0) 101.19%
|
||
);
|
||
box-shadow: 0px 4px 10px 0px rgba(0, 0, 0, 0.08);
|
||
}
|
||
|
||
& .logo-box {
|
||
height: 36px;
|
||
}
|
||
|
||
& .operate-container {
|
||
flex-shrink: 1;
|
||
& > li {
|
||
float: left;
|
||
.icon-box {
|
||
width: 36px;
|
||
height: 36px;
|
||
text-align: center;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
line-height: 36px;
|
||
border-radius: 50%;
|
||
overflow: hidden;
|
||
margin: 0 4px;
|
||
transition: all 0.2s;
|
||
cursor: pointer;
|
||
}
|
||
.icon-box:hover {
|
||
background: #d0e0eb;
|
||
}
|
||
&.active .icon-box {
|
||
background-color: #d0e0eb;
|
||
}
|
||
}
|
||
svg {
|
||
width: 20px;
|
||
height: 20px;
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
/* ===== Header 搜索命令面板(2026-10-08 定稿 B 方案)=====
|
||
⚠️ 必须放在顶层(不可嵌进 .default-header 内):面板由 <Teleport to="body"> 渲染到 body 下,
|
||
若嵌在 .default-header 内会生成 `.default-header .app-cmdk-layer`,匹配不到 body 下的元素。
|
||
类名统一 app-cmdk- 前缀(本文件是全局样式,非 scoped)。 */
|
||
.app-cmdk-layer {
|
||
position: fixed;
|
||
inset: 0;
|
||
z-index: 2000;
|
||
opacity: 0;
|
||
pointer-events: none;
|
||
transition: opacity 0.3s linear;
|
||
|
||
&.is-open {
|
||
opacity: 1;
|
||
pointer-events: auto;
|
||
}
|
||
}
|
||
.app-cmdk-mask {
|
||
position: absolute;
|
||
inset: 0;
|
||
background: rgba(18, 26, 40, 0.34);
|
||
backdrop-filter: blur(10px) saturate(125%);
|
||
-webkit-backdrop-filter: blur(10px) saturate(125%);
|
||
}
|
||
.app-cmdk-panel {
|
||
position: absolute;
|
||
left: 50%;
|
||
top: 78px;
|
||
width: min(620px, calc(100% - 48px));
|
||
background: #fff;
|
||
border-radius: 16px;
|
||
overflow: hidden;
|
||
box-shadow: 0 26px 68px rgba(18, 30, 54, 0.3), 0 2px 8px rgba(18, 30, 54, 0.1);
|
||
opacity: 0;
|
||
transform: translate(-50%, -14px) scale(0.965);
|
||
transition: opacity 0.26s linear, transform 0.48s cubic-bezier(0.2, 0.9, 0.24, 1);
|
||
|
||
.app-cmdk-layer.is-open & {
|
||
opacity: 1;
|
||
transform: translate(-50%, 0) scale(1);
|
||
}
|
||
}
|
||
.app-cmdk-hd {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12px;
|
||
padding: 0 18px;
|
||
height: 56px;
|
||
border-bottom: 1px solid #f0f3f8;
|
||
color: #98a2b0;
|
||
|
||
input {
|
||
flex: 1;
|
||
min-width: 0;
|
||
outline: none;
|
||
border: 0;
|
||
color: #252b35;
|
||
font-size: 15px;
|
||
background: none;
|
||
&::placeholder {
|
||
color: #aab3c0;
|
||
}
|
||
}
|
||
}
|
||
.app-cmdk-kbd {
|
||
font-size: 11px;
|
||
color: #8b95a3;
|
||
background: #f2f5fa;
|
||
border: 1px solid #e4e9f2;
|
||
border-radius: 5px;
|
||
padding: 2px 6px;
|
||
font-family: ui-monospace, Menlo, monospace;
|
||
}
|
||
.app-cmdk-list {
|
||
padding: 8px;
|
||
max-height: min(58vh, 440px);
|
||
overflow: auto;
|
||
}
|
||
.app-cmdk-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12px;
|
||
padding: 9px 12px;
|
||
border-radius: 10px;
|
||
cursor: pointer;
|
||
opacity: 0;
|
||
transform: translateY(9px);
|
||
transition: opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
||
transform 0.42s cubic-bezier(0.4, 0, 0.2, 1), background 0.16s;
|
||
|
||
.app-cmdk-layer.is-open & {
|
||
opacity: 1;
|
||
transform: none;
|
||
/* --i 封顶 20:应用多时(100+)末尾条目延迟不再线性膨胀到数秒,滚动空白窗上限 ≈0.84s */
|
||
transition-delay: calc(0.14s + min(var(--i), 20) * 0.035s),
|
||
calc(0.14s + min(var(--i), 20) * 0.035s), 0s;
|
||
}
|
||
&.is-hl,
|
||
&:hover {
|
||
background: #f3f6fc;
|
||
}
|
||
}
|
||
.app-cmdk-list.is-instant .app-cmdk-item {
|
||
transition-duration: 0.15s;
|
||
transition-delay: 0s;
|
||
}
|
||
.app-cmdk-img {
|
||
width: 34px;
|
||
height: 34px;
|
||
border-radius: 9px;
|
||
flex-shrink: 0;
|
||
}
|
||
.app-cmdk-name {
|
||
flex: 1;
|
||
min-width: 0;
|
||
font-size: 13.5px;
|
||
color: #252b35;
|
||
font-weight: 600;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
/* 应用类型:右侧灰字(来源 BoaAppType.name,与 /apps 分组标题同源) */
|
||
.app-cmdk-type {
|
||
flex-shrink: 0;
|
||
font-size: 11.5px;
|
||
color: #98a2b0;
|
||
font-weight: 400;
|
||
white-space: nowrap;
|
||
}
|
||
.app-cmdk-empty {
|
||
display: none;
|
||
padding: 28px 18px 32px;
|
||
text-align: center;
|
||
color: #a8b1be;
|
||
font-size: 13px;
|
||
&.is-show {
|
||
display: block;
|
||
}
|
||
}
|
||
.app-cmdk-ft {
|
||
display: flex;
|
||
gap: 16px;
|
||
padding: 10px 18px;
|
||
border-top: 1px solid #f0f3f8;
|
||
font-size: 11.5px;
|
||
color: #98a2b0;
|
||
background: #fbfcfe;
|
||
}
|
||
|
||
.role-info {
|
||
height: 22px;
|
||
color: #6b8cf4 !important;
|
||
border-radius: 20px;
|
||
padding: 0 12px;
|
||
font-size: 13px;
|
||
line-height: 21px;
|
||
display: inline-block;
|
||
border: 1px solid #6b8cf4;
|
||
border-radius: 18px;
|
||
}
|
||
|
||
.userinfo-ul {
|
||
display: flex;
|
||
justify-content: center;
|
||
flex-direction: column;
|
||
li {
|
||
height: 42px;
|
||
display: flex;
|
||
cursor: pointer;
|
||
align-items: center;
|
||
justify-content: flex-start;
|
||
user-select: none;
|
||
padding: 0 20px;
|
||
img {
|
||
width: 20px;
|
||
height: 20px;
|
||
margin-right: 8px;
|
||
}
|
||
.backend-manage-icon {
|
||
width: 20px;
|
||
height: 20px;
|
||
margin-right: 8px;
|
||
}
|
||
span {
|
||
color: #323233;
|
||
font-size: 14px;
|
||
font-style: normal;
|
||
font-weight: 400;
|
||
}
|
||
}
|
||
li:hover {
|
||
background-color: #f9f9f9;
|
||
}
|
||
li.border {
|
||
border-bottom: 1px solid #e9e9e9;
|
||
}
|
||
li.header {
|
||
height: 50px;
|
||
padding-right: 10px;
|
||
justify-content: space-between;
|
||
&:hover {
|
||
background-color: #fff;
|
||
}
|
||
.name {
|
||
color: #333;
|
||
font-size: 16px;
|
||
font-style: normal;
|
||
font-weight: 500;
|
||
letter-spacing: 0.8px;
|
||
|
||
flex: 0 1 90px;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
//规定段落中的文本不进行换行
|
||
white-space: nowrap;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* ===== 用户卡片(人像图标唯一入口,2026-10-08)=====
|
||
规格来源:design/05-Header用户卡片整合-切换身份+个人信息+后台管理+退出登录.html
|
||
全部复用既有变量,仅新增卡片骨架与滚动条 */
|
||
.user-card {
|
||
width: 260px;
|
||
background: #fff;
|
||
|
||
/* 原 .roleinfo-wrap 顶层同款:圆点与标题图标统一 20px */
|
||
svg {
|
||
width: 20px;
|
||
height: 20px;
|
||
}
|
||
|
||
.user-card-hd {
|
||
height: 50px;
|
||
padding: 0 16px;
|
||
display: flex;
|
||
align-items: center;
|
||
border-bottom: 1px solid #e8eaec;
|
||
|
||
svg {
|
||
margin-right: 8px;
|
||
}
|
||
.ttl {
|
||
font-size: 16px;
|
||
font-weight: 600;
|
||
color: #272829;
|
||
}
|
||
.close {
|
||
margin-left: auto;
|
||
width: 22px;
|
||
height: 22px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
border-radius: 4px;
|
||
color: #9aa0a8;
|
||
font-size: 14px;
|
||
line-height: 1;
|
||
cursor: pointer;
|
||
transition: all 0.2s;
|
||
|
||
&:hover {
|
||
background: #f2f3f5;
|
||
color: #5a5f68;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 身份列表:完全沿用原 .roleinfo-wrap 的灰卡片形态,不加任何额外 padding/margin/圆角 */
|
||
.user-card-roles {
|
||
max-height: 310px;
|
||
overflow-y: scroll;
|
||
overscroll-behavior: contain;
|
||
|
||
&::-webkit-scrollbar {
|
||
width: 6px;
|
||
}
|
||
&::-webkit-scrollbar-track {
|
||
background: transparent;
|
||
}
|
||
&::-webkit-scrollbar-thumb {
|
||
background: #d4d7dd;
|
||
border-radius: 3px;
|
||
}
|
||
&::-webkit-scrollbar-thumb:hover {
|
||
background: #b9bec7;
|
||
}
|
||
}
|
||
|
||
.u-role {
|
||
background-color: #f9f9f9;
|
||
display: flex;
|
||
align-items: center;
|
||
height: 62px;
|
||
cursor: pointer;
|
||
user-select: none;
|
||
|
||
&:hover {
|
||
background-color: color.adjust($color: #f9f9f9, $lightness: -5%);
|
||
}
|
||
&.active {
|
||
cursor: default;
|
||
background-color: #f9f9f9;
|
||
}
|
||
|
||
svg {
|
||
margin: 0 16px;
|
||
}
|
||
|
||
.who {
|
||
padding: 9px 0;
|
||
border-bottom: 1px solid #e9e9e9;
|
||
flex: auto;
|
||
|
||
.nm {
|
||
font-size: 15px;
|
||
color: #323233;
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.t {
|
||
margin-right: 10px;
|
||
}
|
||
}
|
||
.sch {
|
||
margin-top: 2px;
|
||
font-size: 12px;
|
||
color: #656667;
|
||
}
|
||
}
|
||
|
||
&:last-child .who {
|
||
border-bottom: none;
|
||
}
|
||
}
|
||
|
||
.user-card-menu {
|
||
border-top: 1px solid #e9e9e9;
|
||
|
||
.arw {
|
||
width: 16px;
|
||
height: 16px;
|
||
margin-left: auto;
|
||
}
|
||
}
|
||
|
||
.user-card-logout {
|
||
padding: 10px 20px 16px;
|
||
|
||
.logout-btn {
|
||
width: 100%;
|
||
height: 38px;
|
||
border-radius: 19px;
|
||
background: #fff;
|
||
border: 1px solid #e2e5ea;
|
||
color: #323233;
|
||
font-size: 14px;
|
||
font-family: inherit;
|
||
cursor: pointer;
|
||
transition: all 0.18s;
|
||
|
||
&:hover {
|
||
border-color: #577afb;
|
||
background: #f7f9ff;
|
||
color: #577afb;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.wallpaper-wrap {
|
||
min-height: 500px;
|
||
max-height: 500px;
|
||
padding: 16px;
|
||
}
|
||
.wallpaper-ul {
|
||
display: flex;
|
||
flex-flow: row wrap;
|
||
justify-content: flex-start;
|
||
|
||
li {
|
||
width: 140px;
|
||
height: 104px;
|
||
flex-shrink: 0;
|
||
border-radius: 4px;
|
||
position: relative;
|
||
margin-bottom: 16px;
|
||
overflow: hidden;
|
||
user-select: none;
|
||
box-shadow: 2px 2px 8px 0px rgba(0, 0, 0, 0.25);
|
||
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
img {
|
||
width: 100%;
|
||
height: 100%;
|
||
background: cover no-repeat;
|
||
}
|
||
.context-container {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
|
||
.check-box {
|
||
position: absolute;
|
||
top: 8px;
|
||
right: 8px;
|
||
}
|
||
label {
|
||
font-size: 12px;
|
||
// width: 30px;
|
||
padding: 0 10px;
|
||
text-align: center;
|
||
border-bottom-right-radius: 4px;
|
||
background-color: #14ae5c;
|
||
color: #fff;
|
||
position: absolute;
|
||
left: 0;
|
||
top: 0;
|
||
}
|
||
}
|
||
li .add-wrap {
|
||
width: 140px;
|
||
height: 104px;
|
||
cursor: pointer;
|
||
}
|
||
li .add-box {
|
||
width: 140px;
|
||
height: 50px;
|
||
padding: 27px 0;
|
||
box-sizing: content-box;
|
||
p {
|
||
color: #939393;
|
||
}
|
||
}
|
||
li .mask-box {
|
||
width: 100%;
|
||
height: 26px;
|
||
line-height: 26px;
|
||
color: #fff;
|
||
border-radius: 0px 0px 4px 4px;
|
||
background: rgba(0, 0, 0, 0.5);
|
||
position: absolute;
|
||
text-align: center;
|
||
left: 0;
|
||
bottom: 0;
|
||
}
|
||
}
|
||
.menuwapper-modal {
|
||
}
|