front/docs/前端页面设计规范.md
2026-03-23 10:00:44 +08:00

521 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 中后台前端页面设计规范
> 基于 itfx-front 项目现有技术栈与实现,整理的一套通用、可直接落地的前端设计规范。
> 后续开发须遵循本规范,确保视觉与交互一致性。
---
## 一、技术栈约定
| 类别 | 技术选型 | 版本/说明 |
|------|----------|-----------|
| 框架 | Vue 3 | 使用 Composition API、`<script setup>` |
| UI 库 | Arco Design Vue | 主 UI 框架,优先使用 |
| 辅助 UI | Element Plus | 仅在特殊场景使用 |
| 表格 | vxe-table / Handsontable | 见「表格」章节 |
| 构建 | Vite | 6.x |
| 状态 | Pinia | |
| 国际化 | vue-i18n | |
| 样式 | Less + UnoCSS + 全局 CSS 变量 | |
| 路由 | vue-router | 4.x |
---
## 二、布局规范
### 2.1 整体结构
```
a-layout (垂直)
├── TopNav(顶部导航,fixed)
├── a-layout-content
│ ├── paddingTop: 顶部导航高度 + Tab 栏高度(可选)
│ └── PageLayout(router-view + keep-alive)
└── Footer(可选)
```
**约定:**
- 主内容背景色:`#f0f3f4`
- 页面容器使用 `[class$='-container']`,统一 `padding: 16px`
- 内容区域使用 `overflow: hidden`、`height: 100%` 保证高度正确
### 2.2 页面内容结构
单页内容推荐结构:
```html
<div class="xxx-container" style="background-color: #fff;">
<!-- 1. 页面头部操作区(可选) -->
<div class="page-header">
<a-space>...</a-space>
<a-space>...</a-space>
</div>
<!-- 2. 表格工具栏 -->
<div class="table-toolbar">
<div class="toolbar-left">主操作、批量操作</div>
<div class="toolbar-right">分页控制等</div>
</div>
<!-- 3. 表格/表单内容 -->
...
</div>
```
### 2.3 工具栏布局
- 使用 `table-toolbar` 作为表格上方工具栏
- 左侧 `toolbar-left`:新增、删除、导出等主操作
- 右侧 `toolbar-right`:分页、筛选等
- 使用 `a-space :size="8"` 或 `display: flex; gap: 8px` 控制按钮间距
### 2.4 响应式断点(Less)
```less
@screen-xs: 480px; // 手机
@screen-sm: 576px; // 平板
@screen-md: 768px; // 小屏
@screen-lg: 992px; // 桌面
@screen-xl: 1200px; // 大屏
@screen-xxl: 1600px; // 超大屏
```
---
## 三、色彩规范
### 3.1 主题色(CSS 变量)
通过 `:root` 统一管理,运行时由 `themeColor` 工具更新:
```css
:root {
--app-primary-color: #2D8C8C;
--app-primary-color-hover: #2A7F7F;
--app-primary-color-light: #e6f7f7;
--app-navbar-bg: #2D8C8C;
--app-sidebar-bg: #2D8C8C;
--app-button-gap: 8px; /* 相邻按钮间距 */
}
```
**约定:**
- 主色:`var(--app-primary-color)` 或 `#2D8C8C`
- Hover 色:`var(--app-primary-color-hover)`
- 浅底(选中背景):`var(--app-primary-color-light)`
- 页面背景:`var(--color-bg-1)`(Arco)
- 内容区背景:`#fff` 或 `#f0f3f4`
### 3.2 组件配色
- 主按钮、Switch、Tabs 指示线、菜单选中:使用主题色
- 日期选择器、Input focus:`border-color: var(--app-primary-color)`
- 链接激活态:`color: var(--app-primary-color)`
---
## 四、字体规范
### 4.1 字体栈
```css
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
"Microsoft YaHei", Inter, Roboto, "Helvetica Neue", Arial, sans-serif;
```
代码字体:
```css
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
"Courier New", monospace;
```
### 4.2 字号与行高
- 全局基准字号:`14px`
- 表单、按钮、输入框:`14px`
- 日期选择器、部分紧凑区域:`12px`(如 `.notice` 内)
- 菜单文字:`12px`,`font-weight: bold`
---
## 五、组件规范
### 5.1 按钮
- 高度:`32px`,`border-radius: 4px`
- 图标按钮:`32px × 32px` 正方形
- **相邻按钮间距**:统一 `8px`
- 使用 `a-space :size="8"` 或 `gap: 8px` / `gap: var(--app-button-gap)`
- 适用于工具栏、表格操作列、弹窗底部按钮组
- 主操作使用 `type="primary"`
### 5.2 输入类(Input / Select / Picker)
- 统一高度:`32px`(Input)、`28px`(Picker)
- `border-radius: 4px`
- Focus / Hover 使用主题色 border 与 shadow
### 5.3 卡片 / 弹窗 / 下拉
- `border-radius: 8px`(Card、Modal、Popover、Dropdown、Drawer、Table、Tag、Alert、Message、Notification)
### 5.4 Pro 系列组件
| 组件 | 用途 |
|------|------|
| FormPro | 配置驱动表单,itemList + comp + compProps |
| TablePro | VxeGrid 封装,tableConfig + api + formConfig |
| CustomList | 自定义列 + TablePro,支持列管理 |
| HandsontablePro | 类 Excel 表格 |
| ModalPro | 弹窗,配合 useModal |
| DrawerPro | 抽屉 |
| SelectPro | 增强选择器 |
| JsonEditorPro / JsonDiffPro | JSON 编辑与对比 |
| CodeMirror | 代码编辑 |
**约定:**
- 增强型封装统一使用 `Pro` 后缀
- 优先使用 Pro 组件,减少重复造轮子
### 5.5 消息与确认
- 使用 `$baseMessage`、`$baseConfirm`(如有)
- 或 Arco 的 `Message`、`Modal.confirm`、`a-popconfirm`
---
## 六、表单规范
### 6.1 布局
- 表单类型:`horizontal`、`vertical`、`inline`
- 标签列:`label-col-props="{ span: 6 }"`(或 5)
- 内容列:`wrapper-col-props="{ span: 16 }"`(或 19)
- FormPro:`labelColProps: { span: 5 }`、`wrapperColProps: { span: 19 }`、`rowGutter: 20`、`defaultSpan: 6`
### 6.2 FormPro 配置示例
```ts
itemList: [
{
comp: 'AInput',
field: 'name',
label: '名称',
required: true,
span: 6,
rules: [{ required: true, message: '请输入名称' }],
compProps: { placeholder: '请输入' },
},
{
comp: 'ASelect',
field: 'status',
label: '状态',
compProps: { options: [...], placeholder: '请选择' },
},
]
```
### 6.3 校验
- 使用 Arco Form 的 `rules`
- 提交前调用 `formRef.validate()` 统一校验
- 必填项使用 `required: true` 并配置 `message`
---
## 七、表格规范
### 7.1 组件选择
| 场景 | 组件 | 说明 |
|------|------|------|
| 常规 CRUD 列表 | TablePro | 带搜索表单、分页、API 集成 |
| 自定义列 + 列管理 | CustomList | 包裹 TablePro |
| 类 Excel 编辑 | HandsontablePro | 单元格编辑、复制粘贴 |
| 简单列表(角色、菜单等) | a-table | Arco 原生 |
### 7.2 TablePro 配置
- `tableConfig`:columns、toolbarConfig 等
- `api`:分页接口,参数含 `pageIndex`、`pageSize`、表单值
- `formConfig`:搜索区域
- `columnConfig.useKey: true`、`resizable: true`
- `showOverflow: 'tooltip'`
### 7.3 分页
- 可选 pageSize:`10 / 30 / 50 / 100`(按需裁剪)
- 默认 pageSize:`30`
- 接口参数:`pageIndex`、`pageSize`;返回:`totalCount`、`items` 或 `data.list`
### 7.4 操作列
- 编辑、删除、分配等使用 `a-button type="text" size="small"`
- 删除使用 `a-popconfirm`
- 操作按钮需权限控制(见「权限」)
---
## 八、交互规范
### 8.1 弹窗 / 抽屉
- 使用 `ModalPro` + `useModal()` 管理显隐与数据
- 标准流程:`openModal(true, data)` → 编辑 → `setLoading(true)` → 提交 → 成功 → `closeModal()`、刷新列表
- 弹窗宽度:常规 `600px`,复杂表单 `800px` 或更高
### 8.2 加载与空态
- 表格:`loading` 状态
- 弹窗提交:`confirm-loading`
- 空数据:使用 Arco `Empty` 或统一空态组件
### 8.3 按钮顺序
- 主操作(确定、保存)在右侧
- 取消 / 重置在左侧
- destructive 操作(删除)单独放置,并加确认
---
## 九、权限规范
### 9.1 权限格式
`Module.Resource.Action`,如:
- `Rbac.Roles.Create`
- `Rbac.Users.Update`
- `Api.Interfaces.Query`
- `Track.Orders.Query`
### 9.2 使用方式
**模板:**
```vue
<a-button
v-if="hasPermission('Rbac.Roles.Create')"
type="primary"
@click="handleAdd"
>
新增
</a-button>
```
**路由:**
```ts
{
path: '/system/roles',
meta: { permission: 'Rbac.Roles.Query' },
}
```
**工具函数:**
```ts
import { hasPermission, hasAnyPermission, hasAllPermissions, hasRole } from '@/utils/rbac-permission';
```
### 9.3 菜单
- 菜单基于 RBAC `menus` 与 `userMenuIdSet` 过滤
- 无权限的菜单项不展示
---
## 十、命名规范
### 10.1 文件与目录
| 类型 | 规范 | 示例 |
|------|------|------|
| 页面组件 | `index.vue` 置于功能目录下 | `views/api/upstreamInterface/index.vue` |
| 子组件 | PascalCase 或 kebab-case | `ServiceProviderInterfaceModal.vue`、`AccountList.vue` |
| 布局组件 | kebab-case | `top-nav`、`tab-bar`、`page-layout` |
| 共享组件 | PascalCase | `FormPro`、`TablePro`、`CustomList` |
| API 模块 | camelCase 或 PascalCase | `interface-serviceProvider`、`TrackOrder` |
| Store 模块 | kebab-case | `rbac-user`、`tab-bar`、`app` |
| 国际化 | `zh-CN.ts`、`en-US.ts` | `locale/zh-CN.ts` |
### 10.2 代码命名
| 类型 | 规范 |
|------|------|
| 变量 / 方法 | camelCase |
| 常量 | UPPER_SNAKE_CASE 或 camelCase |
| 类型 / 接口 | PascalCase |
| 组件名 | PascalCase |
### 10.3 路由
- path:camelCase,如 `/api/upstreamInterface`、`/track/kpiEarlyWarningConfig`
- name:PascalCase,如 `InterfaceDetailTest`
### 10.4 国际化 Key
- 格式:`模块.资源.键` 或 `common.xxx`
- 示例:`system.role.actions.add`、`common.search`、`common.reset`
---
## 十一、国际化规范
### 11.1 结构
- 根:`src/locale/zh-CN.ts`、`en-US.ts`
- 按页面拆分:`views/xxx/locale/zh-CN.ts`,在根 locale 中合并
### 11.2 使用
```vue
<template>{{ t('common.search') }}</template>
<script setup>
const { t } = useI18n();
</script>
```
### 11.3 必备 Key
- `common.search`、`common.reset`、`common.add`、`common.delete`、`common.editSuccess`、`common.addSuccess`、`common.saveSuccess`
- `common.selectPlaceholder`、`common.actions`、`common.viewDetail`
---
## 十二、API 与请求规范
### 12.1 分页接口
**请求:**
```ts
{
pageIndex: number;
pageSize: number;
// 其它搜索参数
}
```
**响应:**
```ts
{
totalCount: number;
items: T[]; // 或 data.list
}
```
### 12.2 错误处理
- 使用统一的 axios 拦截器(如 `rbac-error-handler`)
- 401 自动跳转登录;其它错误统一提示
---
## 十三、样式约定
### 13.1 作用域
- 组件内使用 `scoped`
- 覆盖第三方样式时使用 `:deep()` 或全局类
### 13.2 容器类
- 页面根容器:`xxx-container`(如 `role-page`、业务相关命名),保证 `padding: 16px`
- 表格工具栏:`table-toolbar`、`toolbar-left`、`toolbar-right`
### 13.3 按钮间距
- 相邻 `arco-btn` 之间:`margin-left: 8px`(全局已统一)
- 使用 `a-space :size="8"` 包裹一组按钮
---
## 十四、检查清单(新页面开发)
- [ ] 使用 `xxx-container` 或等效布局结构
- [ ] 工具栏使用 `table-toolbar`、`toolbar-left`、`toolbar-right`
- [ ] 按钮、输入框符合全局样式(高度、圆角)
- [ ] 使用主题色变量,不硬编码 `#2D8C8C`
- [ ] 弹窗 / 抽屉使用 ModalPro / DrawerPro + useModal
- [ ] 表单使用 FormPro 或统一 label/span
- [ ] 表格优先 TablePro / CustomList / HandsontablePro
- [ ] 分页 10/30/50/100,默认 30
- [ ] 操作按钮按权限使用 `hasPermission`
- [ ] 路由 meta 配置 `permission`
- [ ] 文案通过 i18n,不写死中文
- [ ] 命名符合本规范(文件、路由、变量、i18n key)
---
## 附录:常用代码片段
### 页面头部 + 权限按钮
```vue
<div class="page-header">
<a-space>
<a-button
v-if="hasPermission('Module.Resource.Create')"
type="primary"
@click="handleAdd"
>
<template #icon><icon-plus /></template>
{{ t('common.add') }}
</a-button>
</a-space>
<a-space>
<a-button @click="loadData">
<template #icon><icon-refresh /></template>
</a-button>
</a-space>
</div>
```
### 表格操作列(编辑 / 删除)
```vue
<template #action="{ record }">
<div class="action-buttons">
<a-button
v-if="hasPermission('Module.Resource.Update')"
type="text"
size="small"
@click="handleEdit(record)"
>
<IconEdit />
</a-button>
<a-popconfirm
v-if="hasPermission('Module.Resource.Delete')"
:content="t('common.deleteConfirm')"
@ok="handleDelete(record.id)"
>
<a-button type="text" size="small">
<IconDelete />
</a-button>
</a-popconfirm>
</div>
</template>
```
### FormPro 查询表单
```vue
<FormPro
ref="formProRef"
:item-list="formItemList"
:button-config="{ showBtn: true }"
@submit="handleSearch"
@reset="handleReset"
/>
```
---
*文档版本:1.0 | 更新日期:2025-03-21*