14 KiB
前端样式 / 布局 / UI 修改操作指南
面向二次开发前端,告诉你:改样式 / 改布局 / 改 UI 具体要动哪些文件、怎么改。
项目技术栈:Vite + Vue 3 + TypeScript + Ant Design Vue + Pinia + Vue Router + SCSS
🧭 速查表
- 改全局颜色 / 按钮 / 弹窗风格:看第 1 章「整体样式体系总览」(
src/styles/index.scss+src/styles/variables.scss) - 改管理端整体布局(侧边栏、头部、内容区排版):看 2.1「管理端整体布局」(
src/views/admin_page/index.vue) - 改用户端整体布局(顶部导航 + 内容容器)」:看 2.2「用户端整体布局」(
src/views/user_pages/index.vue) - 改 YOLO 检测排版 / 三种布局 / 卡片样式:看第 3 章「YOLO 检测页面修改指南」(
src/views/user_pages/YoloDetection.vue) - 改 AI 助手聊天布局:看第 4 章「修改 AI 助手页面」(
src/views/user_pages/AiChat.vue)
1. 整体样式体系总览
1.1 全局样式入口
- 入口文件:
src/styles/index.scss - 在
src/main.ts中全局引入:import './styles/index.scss'
- 主要职责:
- 重置 margin / padding / box-sizing
- 全局字体、
html, body, #app基础样式 - 自定义
.btn/.card等通用类 - 全局 Ant Design Vue 主题风格覆盖(如
.ant-modal,.ant-btn等)
如果你要改全局的按钮、弹窗、表单、输入框等基础风格:
- 打开
src/styles/index.scss - 找对应的选择器:
- 按钮:
.ant-btn下的几种状态(&.ant-btn-default/&.ant-btn-primary/&.ant-btn-dangerous等) - 弹窗:
.ant-modal内的.ant-modal-content/.ant-modal-header/.ant-modal-footer - 输入/选择等:
.ant-input,.ant-select-selector,.ant-input-number,.ant-picker等
- 按钮:
- 直接在这里调整颜色、圆角、阴影、间距。
- 样式会作用于所有页面,无需在每个
.vue里重复写。
建议:全局 Design System 统一改在这里,不要在业务页面里到处改 AntD 默认样式。
1.2 变量和混合(主题基础)
- 文件:
src/styles/variables.scss - 主要内容:
- 颜色:
$primary-color、$success-color、$gray-xxx等 - 间距:
$spacing-1 ~ $spacing-20 - 圆角:
$radius-md、$radius-lg等 - 阴影:
$shadow-sm/$shadow-md/$shadow-lg - 常用 mixin:
@mixin card-style、@mixin button-style等
- 颜色:
改全局配色 / 圆角 / 阴影的操作方式:
- 打开
src/styles/variables.scss - 修改对应变量:
- 主色:
$primary-color/$primary-light/$primary-dark - 背景:
$bg-primary/$bg-secondary - 阴影:
$shadow-md/$shadow-lg
- 主色:
- 不需要修改业务页面,使用这些变量的地方会统一生效。
如果要在页面里复用统一卡片/按钮样式,可以直接:
.my-card { @include card-style; } .my-primary-button { @include button-style($primary-color, #fff); }
1.3 主题 store 与 CSS 变量
- 文件:
src/stores/hertz_theme.ts - 作用:
- 定义
ThemeConfig(导航栏背景、页面背景、卡片背景、主色、文字颜色) - 使用
document.documentElement.style.setProperty写入 CSS 变量:--theme-header-bg,--theme-page-bg,--theme-card-bg,--theme-primary,--theme-text-primary等
- 定义
- 使用方式:
- 在页面/组件的 SCSS 中,通过
var(--theme-primary)等变量引用主题色:- 示例:
color: var(--theme-text-primary, #1e293b);
- 示例:
- 在页面/组件的 SCSS 中,通过
修改主题默认值:
- 打开
src/stores/hertz_theme.ts - 修改
defaultTheme对象里的颜色值即可:- 如:
primaryColor: '#FF4D4F'改成你的品牌色
- 如:
- 调用
themeStore.loadTheme()时会自动应用到全局。
页面内如何用这些主题变量?
- 在 SCSS 中使用:
.some-block {
background: var(--theme-card-bg, #fff);
color: var(--theme-text-primary, #1e293b);
border-color: var(--theme-card-border, #e5e7eb);
}
2. 布局结构:管理端 / 用户端
2.1 管理端整体布局
- 入口布局:
src/views/admin_page/index.vue - 结构:
- 外层
.admin-layout - 使用
a-layout+a-layout-sider+a-layout-header+a-layout-content+a-layout-footer - 侧边菜单:
a-layout-sider内的a-menu,使用admin_menu.ts生成菜单项
- 外层
修改管理端整体布局方式(比如侧边栏宽度、顶部高度):
- 打开
src/views/admin_page/index.vue - 找到模板部分:
- 侧边栏:
<a-layout-sider ... class="admin-sider"> - 顶部:
<a-layout-header class="header"> - 内容:
<a-layout-content class="content">
- 侧边栏:
- 在同文件底部的
<style scoped lang="scss">中调整:.admin-layout、.admin-sider、.header、.content的 padding / background / shadow 等。
- 如果要改变菜单布局(比如改成顶部导航):需要同时更新 template 结构和对应的 SCSS。
2.2 用户端整体布局
- 入口布局:
src/views/user_pages/index.vue - 结构:
- 顶部
a-layout-header.user-header:包含 logo + 顶部菜单 + 面包屑 + 布局切换按钮 + 主题按钮 + 用户下拉 - 主体
a-layout.main-layout,内部a-layout-content.user-content作为页面内容容器 - 中间区域通过
currentComponent动态切换不同业务页(YOLO 检测、AI 助手等)
- 顶部
修改用户端整体布局(例如 header 高度、主内容宽度):
- 打开
src/views/user_pages/index.vue - 在 template 里找到:
<a-layout-header class="user-header"><a-layout class="main-layout"><a-layout-content class="user-content">
- 在同文件的
<style scoped lang="scss">中调整:.user-layout、.user-header、.main-layout、.user-content、.content-wrapper
- 你也可以在这里添加全局背景图(比如
.user-layout里加 background),只作用于用户端。
所有用户端的业务页面(
YoloDetection.vue、AiChat.vue等)都是渲染在user-content容器里,尽量保持这里的 padding / 背景一致,具体视觉再在业务页内做细化。
3. YOLO 检测页面修改指南(排版 / 布局 / 样式 / UI)
文件路径:src/views/user_pages/YoloDetection.vue
这个页面已经内置了 三种布局模式,并且使用了大量局部 SCSS + AntD 组件。下面分步骤说明如何操作。
3.1 布局模式(classic / vertical / grid)
关键代码:
- 布局枚举与状态:
const layoutMode = ref<'classic' | 'vertical' | 'grid'>('classic')
const layoutKey = ref(0)
- 模板中的三个布局分支:
<!-- 经典两列布局 -->
<div v-if="layoutMode === 'classic'" class="detection-content classic-layout" :key="`classic-${layoutKey}`">
...
</div>
<!-- 上下布局 -->
<div v-if="layoutMode === 'vertical'" class="detection-content vertical-layout" :key="`vertical-${layoutKey}`">
...
</div>
<!-- 侧边栏详情布局 -->
<div v-if="layoutMode === 'grid'" class="detection-content sidebar-layout" :key="`grid-${layoutKey}`">
...
</div>
layoutMode 的切换来自用户端首页布局弹窗(user_pages/index.vue),会写入 localStorage('yoloDetectionLayout')。
如果你要改某一种布局的排版:
- 在
YoloDetection.vue模板里定位对应的div:- 经典两列:
.classic-layout - 上下布局:
.vertical-layout - 侧边栏布局:
.sidebar-layout
- 经典两列:
- 在同文件的
<style scoped lang="scss">中搜索这些 class(例如搜索.classic-layout):- 调整其中的
a-row/a-col排布、卡片宽度、高度等。
- 调整其中的
- 如果你只想保留一种布局,比如只保留经典两列:
- 可以在 template 中暂时注释掉
vertical和grid这两段。 - 或者在 script 中将
layoutMode的类型改小,只允许'classic'。
- 可以在 template 中暂时注释掉
3.2 修改上传区域(左侧卡片)
上传部分主结构(classic 布局示例):
<a-card title="文件上传" class="upload-card">
<div class="upload-area">
<a-upload-dragger ... class="beautiful-upload">
...
</a-upload-dragger>
<div v-if="fileList.length > 0" class="compact-preview">...
</div>
</div>
<div class="detection-params" v-if="fileList.length > 0">...
</div>
<div class="upload-actions" v-if="fileList.length > 0">...
</div>
</a-card>
对应样式(节选):
.yolo-detection-page {
.upload-card { ... }
.upload-area { ... }
.beautiful-upload { ... }
.compact-preview { ... }
.upload-actions { ... }
}
// 深度作用 AntD Upload
:deep(.ant-upload-dragger) {
border: 2px dashed #d1d5db;
border-radius: 12px;
background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
...
}
具体改法示例:
-
想调整拖拽区域高度 / 圆角 / 背景:
- 在
<style scoped lang="scss">中搜索:deep(.ant-upload-dragger)。 - 修改其中的
border-radius、min-height、background等。
- 在
-
想改变已上传文件的缩略图排列方式:
- 搜索
.compact-preview、.preview-grid、.preview-card等 class。 - 例如,将
display: grid的列数从3改为4:- 修改
grid-template-columns: repeat(3, 1fr);为repeat(4, 1fr);。
- 修改
- 搜索
-
想给“开始检测”按钮加一个 loading 状态颜色:
- 上传按钮使用的是
<a-button type="primary" :loading="detecting">,全局颜色来自.ant-btn-primary。 - 如果想只在该页面定制:
- 上传按钮使用的是
.yolo-detection-page {
.upload-actions {
:deep(.ant-btn-primary) {
background: #22c55e; // 单独改为绿色
}
}
}
3.3 修改检测结果区域排版
经典布局右侧结果卡片结构:
<a-card title="检测结果" class="result-card">
<div v-if="detectionResults.length === 0" class="no-results">...</div>
<div v-else class="results-list">
<div class="results-grid">
<div v-for="result in sortedDetectionResults" class="result-item">
<div class="image-comparison">...
<div class="result-details">...
</div>
</div>
</div>
</a-card>
对应样式关键点:
.results-list:控制滚动区域、高度和滚动条样式.result-item:单个结果卡片的背景、边框、阴影.image-comparison/.image-pair/.image-wrapper:左右对比图/视频布局.result-details/.detection-stats/.detection-tags:文本统计信息
操作示例:
-
改结果区域整体高度 / 是否滚动:
- 在 SCSS 中搜索
.results-list。 - 调整
max-height或移除overflow-y: scroll !important;,就可以变成自适应高度。
- 在 SCSS 中搜索
-
把“原图/检测结果”改成上下叠加而不是左右:
- 找到
.image-pair:
- 找到
.image-pair {
display: flex;
gap: 16px;
}
- 改为列方向:
.image-pair {
display: flex;
flex-direction: column; // 上下排列
gap: 16px;
}
- 调整图片容器比例 / 加圆角阴影:
- 修改
.image-wrapper:height: 160px;改为你想要的高度或使用aspect-ratio。 - 修改
border-radius/box-shadow实现更柔和的卡片效果。
- 修改
3.4 深度选择器 :deep 使用说明
在 YoloDetection.vue 中多次使用了 :deep(...) 来覆盖 AntD 子组件样式,例如:
:deep(.ant-card-body) {
flex: 1;
display: flex;
flex-direction: column;
}
:deep(.ant-upload-list) {
display: none !important;
}
规则:
- 页面级样式修改尽量写在该
.vue的<style scoped>中,用:deep定位到 AntD 的 DOM 结构。 - 全局通用样式统一放在
src/styles/index.scss,不要在页面里频繁写过多全局覆盖。
如何找到 AntD 的 class 名称?
- 浏览器打开页面,F12 查看对应组件 DOM 结构。
- 复制最内层需要修改的 class(如
.ant-card-head)。 - 在该页面样式中写:
.my-custom-card {
:deep(.ant-card-head) {
// 自定义头部样式
}
}
4. 修改 AI 助手页面(整体方法类似)
AI 助手页面:src/views/user_pages/AiChat.vue
- 也有多种布局:
default(左右)、compact(上下)、wide(全屏消息 + 浮动侧边栏)。 - 样式组织方式与 YOLO 检测类似:
- 外层
.ai-chat-page - 内部
.chat-container/.chat-sidebar/.chat-main/.messages-wrapper/.composer等 - 使用
:deep覆盖 AntD 的a-card、a-input-search、a-list等组件
- 外层
如果你已经掌握了上面 YOLO 页面改法:
- 改 AI 助手排版时只需:
- 找到对应布局分支(
currentLayout === 'default' | 'compact' | 'wide') - 在
<style scoped lang="scss">中编辑对应 class 的样式即可。
- 找到对应布局分支(
5. 实战建议:改 UI 的基本步骤
-
先确认层级:
- 是全局都要变?(颜色、按钮、弹窗 ->
styles/index.scss,styles/variables.scss,hertz_theme.ts) - 只改某个模块?(YOLO / AI / 管理端 / 用户端布局 -> 各自
.vue的 scoped 样式)
- 是全局都要变?(颜色、按钮、弹窗 ->
-
用浏览器开发者工具查 DOM 和 class:
- 看清楚 AntD 组件最终渲染出的结构和 class
- 再决定用
:deep(.ant-xxx)还是自定义的.my-block去写样式
-
在对应
.vue文件底部<style scoped lang="scss">中改局部样式:- 保持 class 命名有语义:
.yolo-detection-page、.upload-area、.results-list等
- 保持 class 命名有语义:
-
共用样式尽量抽到全局:
- 例如卡片风格在
variables.scss+index.scss抽成 mixin 或全局 class
- 例如卡片风格在
-
改完后检查响应式:
YoloDetection.vue和 AI 助手都内置了@media段,记得同步修改,以免移动端错位。
6. 如果要新增一个“风格类似 YOLO 的新页面”
- 在
src/views/user_pages/下新建MyFeature.vue - 参考
YoloDetection.vue的结构:- 顶部
.page-header - 中间
a-row+a-col做主布局 - 底部
<style scoped lang="scss">里用.my-feature-page { ... }包裹所有样式
- 顶部
- 使用全局变量和 mixin:
.my-feature-page {
background: var(--theme-page-bg, #f5f5f5);
.my-card {
@include card-style;
}
}
- 在
src/router/user_menu_ai.ts中为用户端菜单新增一项,对应MyFeature.vue。