# 前端页面视图 前端页面视图是用户直接交互的界面。项目使用 Vue3 + NaiveUI + Vite 构建。一个完整的 CRUD 页面由 4 个文件组成: ``` ui/src/views/system/position/ ├── index.vue # 主页面:搜索 + 表格 + 操作 ├── edit.vue # 编辑弹窗:新增/编辑表单 ├── columns.ts # 表格列定义 └── querySchemas.ts # 搜索表单 Schema ``` ## 1. 主页面 `index.vue` 主页面是模块的入口页面,包含搜索表单、数据表格和操作按钮。 ### 完整代码 ```vue ``` ### 代码解析 **页面结构**:`div` 包裹两个 `n-card`,上方是搜索表单,下方是数据表格。 **搜索表单**:通过 `useForm` 注册,Schema 从 `querySchemas.ts` 导入。`gridProps` 控制响应式列数。 **数据表格**:通过 `BasicTable` 组件渲染,`request` 属性绑定数据加载函数,`columns` 从 `columns.ts` 导入。 **操作栏**:通过 `actionColumn` 的 `render` 函数使用 `h()` 渲染 `TableAction`,支持权限控制(`auth`)。图标通过 `renderIcon` 工具函数包装。 **编辑弹窗**:使用 `editDialog` 组件,通过 `v-model:visible` 控制显示,`positionId` 传入编辑记录 ID(0 表示新增)。通过 `ref` 调用 `openModal()` 打开弹窗。 **删除逻辑**:使用 NaiveUI 的 `useDialog` 弹出确认对话框,单条删除传入 `record`,批量删除从 `rowKeys` 取已选 ID。 **消息提示**:使用 NaiveUI 的 `useMessage` 组件,调用 `message.success()` 显示成功提示。 ## 2. 编辑弹窗 `edit.vue` 编辑弹窗是独立组件,负责新增和编辑操作的表单展示与提交。 ### 完整代码 ```vue ``` ### 代码解析 **弹窗组件**:使用项目封装的 `basicModal` 组件,通过 `useModal` hook 管理弹窗状态。 **Props 接收**: - `visible`:控制弹窗显示/隐藏,通过 `v-model:visible` 双向绑定 - `positionId`:编辑记录的 ID,为 0 时表示新增模式 **表单组件**:使用 NaiveUI 的 `n-form`、`n-form-item`、`n-input`、`n-radio-group`、`n-radio`、`n-input-number` 组件。 **表单配置**: - `label-placement="left"`:标签在左侧显示 - `label-width="85px"`:标签宽度 - `path`:表单字段路径,用于校验 - `:rule`:校验规则 **新增/编辑判断**:`props.positionId ? positionUpdate : positionAdd`,通过 ID 是否为 0 区分。 **防重复提交**:`useModal` 的 `setSubLoading` 方法控制提交按钮 loading 状态。 **数据回填**:`onMounted` 时判断如果是编辑模式,调用 `getPositionDetail` 获取数据并填充表单。 **事件通信**: - `emit('update:visible', false)`:关闭弹窗 - `emit('success')`:通知父页面刷新表格 **弹窗调用方式**:父页面通过 `ref` 调用 `openModal()` 打开弹窗。 ## 3. 表格列定义 `columns.ts` 定义表格的列配置,包括列名、字段名、宽度和自定义渲染。 ### 完整代码 ```typescript import { h } from 'vue'; import { NTag } from 'naive-ui'; export const columns = [ { type: 'selection', width: 50, fixed: 'left', }, { title: 'ID', key: 'id', fixed: 'left', width: 50, }, { title: '岗位名称', key: 'name', width: 100, }, { title: '岗位状态', key: 'status', width: 100, render(record) { return h( NTag, { style: { marginRight: '6px', }, bordered: false, type: record.status == 1 ? 'success' : 'error', }, { default: () => (record.status == 1 ? '正常' : '停用'), }, ); }, }, { title: '排序', key: 'sort', width: 100, }, { title: '创建人', key: 'createUser', width: 100, }, { title: '创建时间', key: 'createTime', width: 180, }, ]; ``` ### 代码解析 **列配置字段**:NaiveUI 表格使用 `title`(列标题)和 `key`(字段名)。 **选择列**:`type: 'selection'` 自动添加复选框列,配合 `@update:checked-row-keys` 事件实现批量选择。 **固定列**:`fixed: 'left'` 固定在左侧,`fixed: 'right'` 固定在右侧(操作列)。 **自定义渲染**:`render(record)` 使用 Vue 的 `h()` 函数创建虚拟 DOM。注意 NaiveUI 的 `render` 回调直接接收 `record` 对象,无需通过 `record.row` 访问。 **标签组件**:使用 NaiveUI 的 `NTag` 组件,`type` 属性支持 `'success'`、`'error'`、`'warning'`、`'info'` 等类型。`bordered: false` 去除边框。 **宽度设置**: - `width`:固定宽度 ## 4. 搜索表单 `querySchemas.ts` 定义搜索表单的字段配置,使用项目封装的 `FormSchema` 类型。 ### 完整代码 ```typescript import { FormSchema } from '@/components/Form/index'; export const schemas: FormSchema[] = [ { field: 'name', component: 'NInput', label: '岗位名称', componentProps: { placeholder: '请输入岗位名称', }, }, { field: 'status', component: 'NSelect', label: '状态', componentProps: { placeholder: '请选择状态', clearable: true, options: [ { label: '正常', value: '1', }, { label: '停用', value: '2', }, ], }, }, ]; ``` ### 代码解析 **FormSchema 字段**: | 字段 | 说明 | |:----|:----| | `field` | 字段名,与后端查询参数对应 | | `component` | 表单组件类型:`NInput` / `NSelect` / `NDatePicker` 等(NaiveUI 组件名) | | `label` | 标签文本 | | `componentProps` | 组件属性,透传给 NaiveUI 组件 | **Select 组件**:`options` 定义下拉选项,`clearable: true` 允许清空选择。 ## 文件关系图 ``` index.vue(主页面) ├── import schemas from './querySchemas' ← 搜索表单配置 ├── import columns from './columns' ← 表格列配置 ├── import editDialog from './edit.vue' ← 编辑弹窗组件 └── import API from '@/api/system/position' ← 接口请求 edit.vue(编辑弹窗) └── import API from '@/api/system/position' ← 接口请求 ``` ## 开发要点 1. **一个模块一个目录**:放在 `ui/src/views/{group}/{module}/` 下 2. **4 个文件各司其职**:主页面、编辑弹窗、列定义、搜索 Schema 3. **编辑弹窗是独立组件**:通过 Props 接收 ID,通过 Emit 通知父页面,通过 `useModal` 管理弹窗状态 4. **列定义使用 `h()` 渲染复杂内容**:如状态标签、操作按钮 5. **搜索 Schema 使用 `FormSchema` 类型**:配置化定义表单字段,组件名使用 NaiveUI 组件名(`NInput`、`NSelect`) 6. **新增/编辑通过 `positionId` 区分**:0 为新增,非 0 为编辑 7. **消息提示使用 `useMessage()`**:调用 `message.success()` / `message.error()` 等 8. **确认对话框使用 `useDialog()`**:调用 `dialog.warning()` 等,通过 `onPositiveClick` 回调处理确认 9. **表格行选择使用 `@update:checked-row-keys`**:获取选中行的 key 数组 10. **列配置使用 `title` 和 `key`**:定义表格列标题和字段名 ## 总结 前端页面统一使用 `n-card` + `BasicForm` + `BasicTable` + `TableAction` 组件组合,分页由 `BasicTable` 内置处理。每个模块包含 `index.vue`(列表页)、`edit.vue`(编辑弹窗)、`columns.ts`(列定义)、`querySchemas.ts`(搜索配置)四个文件。编辑弹窗使用项目封装的 `basicModal` 组件,通过 `useModal` hook 管理弹窗状态和提交按钮 loading。