refactor(frontend): 侧栏层级与表单页版式调整
侧栏层级口径改版(视觉稿 v4.2):组标题与菜单项同字号 13px,层级改由 「折叠箭头 + 组间留白 + 子项缩进」表达,不靠字号/字重压过父级。 - 去掉组标题的靛蓝竖标与激活项左侧 2px 竖条(竖条只能落在侧栏内边缘、 与白底悬空,是重复的第二个信号),激活只留白底浮起 + 靛蓝字 - 子项缩进 30px 收到 22px,图标父子统一 16px - AppMenu 的 .app-menu 提供横向 10px 留白,BasicLayout 的 .app-aside__menu 只写上下内距——两处都用 padding 简写会同权重靠注入顺序决胜,横向留白 会被整条抹掉、条目贴到侧栏边缘 公司信息页字段自适应分列:卡片够宽时两字段并排,窄时折回单列;说明文字 紧贴控件下方,不再顶到卡片最右缘(宽屏下与输入框隔上千像素,视线关联断掉)。 设计稿同步升 v4.2。 Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
1 parent
61965e0b60
commit
a00fca942d
4 files changed
+130
-80
No files matched your search
@@ -10,7 +10,12 @@ const { topLevelMenus, groupedMenus } = useAppMenu()
|
||||
|
||||
<template>
|
||||
<el-menu class="app-menu" :default-active="route.path" router>
|
||||
<el-menu-item v-for="item in topLevelMenus" :key="item.path" :index="item.path">
|
||||
<el-menu-item
|
||||
v-for="item in topLevelMenus"
|
||||
:key="item.path"
|
||||
class="app-menu__top"
|
||||
:index="item.path"
|
||||
>
|
||||
<el-icon v-if="item.icon" class="app-menu__icon" aria-hidden="true">
|
||||
<component :is="item.icon" />
|
||||
</el-icon>
|
||||
@@ -32,69 +37,67 @@ const { topLevelMenus, groupedMenus } = useAppMenu()
|
||||
|
||||
<style scoped>
|
||||
/*
|
||||
* 中性灰侧栏上的菜单:覆盖 Element Plus 的主题变量而非直接写颜色 ——
|
||||
* 后者与组件库规则同权重,受样式注入顺序影响而不稳定。
|
||||
* 激活项 = 白底浮起(微渐变 + 内高光 + 分层阴影)+ 左侧 2px 靛蓝条。
|
||||
* 侧栏菜单:中性灰底 + 靛蓝点缀。
|
||||
* 覆盖 Element Plus 的主题变量而非直接写颜色 —— 后者与组件库规则同权重,
|
||||
* 受样式注入顺序影响而不稳定。
|
||||
*
|
||||
* 层级口径:父子**同字号(13px)**,层级不靠字号/字重刻意压过 ——
|
||||
* 组标题与条目一样大,结构由「组标题带折叠箭头 + 组间留白 + 子项缩进一档」承担。
|
||||
* 前两版各走偏一次:先把组标题压成 11px 弱墨「目录行」,父级弱于子项;
|
||||
* 后改成 14px/600 + 靛蓝竖标,父级刻意压过子项、像一排小标题在喊叫。
|
||||
* 层级是位置关系,不是字号关系 —— 两版都不要。
|
||||
*
|
||||
* 激活态:白底浮起(微渐变 + 内高光 + 分层阴影)+ 靛蓝字,不再叠左侧竖条 ——
|
||||
* 竖条只能落在侧栏内边缘(离白底悬空),是与白底重复的第二个信号。
|
||||
*/
|
||||
.app-menu {
|
||||
--el-menu-bg-color: transparent;
|
||||
--el-menu-text-color: var(--ys-ink-2);
|
||||
--el-menu-active-color: var(--ys-indigo);
|
||||
--el-menu-hover-bg-color: rgba(255, 255, 255, 0.55);
|
||||
--el-menu-item-height: 36px;
|
||||
--el-menu-item-height: 34px;
|
||||
|
||||
padding: 0 10px;
|
||||
padding: 2px 10px 12px;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
/* 菜单项:内距 9px 10px、圆角 7px、13px 字 —— 组内层级靠缩进区分,不加分隔线 */
|
||||
.app-menu :deep(.el-menu-item) {
|
||||
height: 36px;
|
||||
/* 组与组之间留白:分组交给间距,不加分割线 */
|
||||
.app-menu :deep(.el-sub-menu) {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
/*
|
||||
* 顶层叶子项(首页):与组标题同级 —— 13px / 500 / 主墨。
|
||||
* 用 scoped 模板 class 定位(权重高于组件库默认样式),
|
||||
* 不与子项共用 :deep 规则,避免字号被子项规则带走。
|
||||
*/
|
||||
.app-menu__top {
|
||||
height: 34px;
|
||||
padding: 0 10px;
|
||||
margin-bottom: 2px;
|
||||
font-size: 13px;
|
||||
line-height: 36px;
|
||||
font-weight: 500;
|
||||
line-height: 34px;
|
||||
color: var(--ys-ink);
|
||||
border-radius: var(--ys-radius-sm);
|
||||
transition:
|
||||
background-color 150ms var(--ys-ease),
|
||||
color 150ms var(--ys-ease);
|
||||
}
|
||||
|
||||
.app-menu :deep(.el-menu-item:hover) {
|
||||
.app-menu__top:hover {
|
||||
color: var(--ys-ink);
|
||||
background-color: rgba(255, 255, 255, 0.55);
|
||||
}
|
||||
|
||||
/* 子项向右缩进一档,与顶层项形成「树」的暗示而非并列 */
|
||||
.app-menu :deep(.el-sub-menu .el-menu-item) {
|
||||
padding-left: 22px !important;
|
||||
}
|
||||
|
||||
.app-menu :deep(.el-menu-item.is-active) {
|
||||
position: relative;
|
||||
font-weight: 500;
|
||||
background: linear-gradient(180deg, var(--ys-paper), #fbfcfe);
|
||||
box-shadow:
|
||||
inset 0 1px 0 #fff,
|
||||
0 1px 2px rgba(28, 35, 51, 0.06),
|
||||
0 4px 10px rgba(28, 35, 51, 0.06);
|
||||
}
|
||||
|
||||
.app-menu :deep(.el-menu-item.is-active)::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 9px;
|
||||
bottom: 9px;
|
||||
left: -10px;
|
||||
width: 2px;
|
||||
border-radius: 1px;
|
||||
background: var(--ys-indigo);
|
||||
}
|
||||
|
||||
/* 组标题:11px 大字距的「目录行」,不抢子项;展开时转靛蓝并压一层白底 */
|
||||
/* 组标题:与条目同字号,靠折叠箭头表明「可展开」,不靠压重 */
|
||||
.app-menu :deep(.el-sub-menu__title) {
|
||||
height: 32px;
|
||||
height: 34px;
|
||||
padding: 0 10px;
|
||||
line-height: 32px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
line-height: 34px;
|
||||
color: var(--ys-ink);
|
||||
border-radius: var(--ys-radius-sm);
|
||||
transition:
|
||||
background-color 150ms var(--ys-ease),
|
||||
@@ -102,23 +105,47 @@ const { topLevelMenus, groupedMenus } = useAppMenu()
|
||||
}
|
||||
|
||||
.app-menu__group {
|
||||
font-size: 11px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.1em;
|
||||
color: var(--ys-ink-3);
|
||||
transition: color 150ms var(--ys-ease);
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
/*
|
||||
* 子项:13px 次墨 + 缩进一档(12px)。
|
||||
* Element Plus 的 `.el-menu--inline .el-menu-item` 带 !important 的 40px 缩进,
|
||||
* 必须同样用 !important 才能压住,否则缩进档位不受控。
|
||||
*/
|
||||
.app-menu :deep(.el-sub-menu .el-menu-item) {
|
||||
height: 32px;
|
||||
padding-right: 10px !important;
|
||||
padding-left: 22px !important;
|
||||
margin-bottom: 1px;
|
||||
font-size: 13px;
|
||||
line-height: 32px;
|
||||
color: var(--ys-ink-2);
|
||||
border-radius: var(--ys-radius-sm);
|
||||
transition:
|
||||
background-color 150ms var(--ys-ease),
|
||||
color 150ms var(--ys-ease);
|
||||
}
|
||||
|
||||
.app-menu :deep(.el-sub-menu .el-menu-item:hover) {
|
||||
color: var(--ys-ink);
|
||||
}
|
||||
|
||||
/* 激活项:白底浮起 + 靛蓝字(阴影分层与设计稿卡片同口径) */
|
||||
.app-menu :deep(.el-menu-item.is-active) {
|
||||
font-weight: 500;
|
||||
color: var(--ys-indigo);
|
||||
background: linear-gradient(180deg, var(--ys-paper), #fbfcfe);
|
||||
box-shadow:
|
||||
inset 0 1px 0 #fff,
|
||||
0 1px 2px rgba(28, 35, 51, 0.06),
|
||||
0 4px 10px rgba(28, 35, 51, 0.06);
|
||||
}
|
||||
|
||||
.app-menu :deep(.el-sub-menu__title:hover) {
|
||||
background-color: rgba(255, 255, 255, 0.55);
|
||||
}
|
||||
|
||||
.app-menu :deep(.el-sub-menu.is-opened > .el-sub-menu__title) {
|
||||
background-color: rgba(255, 255, 255, 0.45);
|
||||
}
|
||||
|
||||
.app-menu :deep(.el-sub-menu.is-opened > .el-sub-menu__title) .app-menu__group {
|
||||
color: var(--ys-indigo);
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -136,21 +163,21 @@ const { topLevelMenus, groupedMenus } = useAppMenu()
|
||||
}
|
||||
|
||||
.app-menu :deep(.el-sub-menu.is-opened > .el-sub-menu__title .el-sub-menu__icon-arrow) {
|
||||
color: var(--ys-indigo);
|
||||
color: var(--ys-ink-2);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
/*
|
||||
* 菜单图标:设计稿口径为 16px、透明度 0.7(激活项 1)——Element Plus 默认
|
||||
* 给菜单图标 24px 宽 + 5px 间距,直接沿用会让图标比文字更抢眼、字距发散,
|
||||
* 故在此显式覆盖。
|
||||
* 故在此显式覆盖。父子同级,图标尺寸统一,不再按层级分档。
|
||||
*/
|
||||
.app-menu__icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 9px;
|
||||
font-size: 16px;
|
||||
opacity: 0.7;
|
||||
opacity: 0.72;
|
||||
}
|
||||
|
||||
.app-menu :deep(.el-menu-item.is-active) .app-menu__icon {
|
||||
@@ -158,10 +185,10 @@ const { topLevelMenus, groupedMenus } = useAppMenu()
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.app-menu :deep(.el-menu-item),
|
||||
.app-menu__top,
|
||||
.app-menu :deep(.el-sub-menu .el-menu-item),
|
||||
.app-menu :deep(.el-sub-menu__title),
|
||||
.app-menu :deep(.el-sub-menu__icon-arrow),
|
||||
.app-menu__group {
|
||||
.app-menu :deep(.el-sub-menu__icon-arrow) {
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,7 +155,13 @@ async function handleLogout(): Promise<void> {
|
||||
|
||||
.app-aside__menu {
|
||||
flex: 1;
|
||||
padding: 2px 0 12px;
|
||||
/*
|
||||
* 只写上下内距:横向 10px 留白由 AppMenu 自己的 .app-menu 提供。
|
||||
* 这里若用 padding 简写,会与 .app-menu 的 padding 简写同权重、
|
||||
* 靠样式注入顺序决胜 —— 横向留白可能被整条抹掉,条目贴到侧栏边缘。
|
||||
*/
|
||||
padding-top: 2px;
|
||||
padding-bottom: 12px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
|
||||
@@ -118,9 +118,13 @@ const previewName = computed(() => form.company_name.trim() || '衍水集团')
|
||||
label-width="92px"
|
||||
@submit.prevent
|
||||
>
|
||||
<el-form-item label="公司名称" prop="company_name">
|
||||
<!-- 控件与说明并排:说明靠行尾对齐,宽屏下整行铺满卡片而非缩在左上角 -->
|
||||
<div class="field-control">
|
||||
<!--
|
||||
字段自适应分列:卡片够宽时两个字段并排(各占一列),窄时自动折回单列。
|
||||
说明文字紧贴控件下方 —— 早前把它顶到卡片最右缘,宽屏下与输入框隔了
|
||||
上千像素,视线关联直接断掉。
|
||||
-->
|
||||
<div class="field-grid">
|
||||
<el-form-item label="公司名称" prop="company_name">
|
||||
<el-input
|
||||
v-model="form.company_name"
|
||||
class="field-control__main"
|
||||
@@ -129,11 +133,9 @@ const previewName = computed(() => form.company_name.trim() || '衍水集团')
|
||||
clearable
|
||||
/>
|
||||
<p class="field-control__note">最多 64 个字符;保存后对所有在线用户立即生效。</p>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="logo">
|
||||
<div class="field-control">
|
||||
<el-form-item label="logo">
|
||||
<el-upload
|
||||
class="logo-uploader"
|
||||
:show-file-list="false"
|
||||
@@ -149,8 +151,8 @@ const previewName = computed(() => form.company_name.trim() || '衍水集团')
|
||||
<p class="field-control__note">
|
||||
png / jpg,不超过 2MB;仅展示于登录页品牌位,按 ≤56×36 显示。
|
||||
</p>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in new issue
Block a user