# 页面视图开发 :::tip 说明 页面视图位于 `src/views/` 目录,每个业务模块遵循 `index.vue`(列表页)+ `edit.vue`(编辑弹窗)+ `detail.vue`(详情弹窗)的标准模式,辅以 `columns.ts`(列定义)和 `querySchemas.ts`(搜索表单)配置文件。 ::: ## 目录结构 ``` src/views/ ├── tool/ │ ├── example/ │ │ ├── index.vue # 案例列表页 │ │ ├── edit.vue # 案例编辑弹窗 │ │ ├── detail.vue # 案例详情弹窗 │ │ ├── columns.ts # 表格列定义 │ │ └── querySchemas.ts # 搜索表单定义 │ └── ... └── ... ``` ## 文件职责 | 文件 | 职责 | 说明 | |------|------|------| | `index.vue` | 列表页 | 搜索表单 + 工具栏 + BasicTable + 编辑弹窗引用 | | `edit.vue` | 编辑弹窗 | el-dialog + el-form,懒加载 | | `detail.vue` | 详情弹窗 | el-dialog 展示详情,懒加载 | | `columns.ts` | 表格列定义 | 定义列 prop、label、render 函数等 | | `querySchemas.ts` | 搜索表单定义 | FormSchema 数组,定义搜索字段 | ## index.vue 列表页 以案例管理为例,完整结构如下: ```vue ``` ## columns.ts ```typescript import { h } from 'vue'; import { ElAvatar, ElTag } from 'element-plus'; export const columns = [ { type: 'selection' }, { label: 'ID', prop: 'id', fixed: 'left', width: 50 }, { label: '案例名称', prop: 'name', minWidth: 120 }, { label: '案例图片', prop: 'avatar', minWidth: 120, render(record) { return h(ElAvatar, { size: 48, src: record.row.avatar, shape: 'square', fit: 'fill' }); }, }, { label: '案例类型', prop: 'type', minWidth: 100, render(record) { const statusMap = { 1: { text: '类型1', type: 'success' }, 2: { text: '类型2', type: 'danger' } }; const status = statusMap[record.row.type]; return h(ElTag, { type: status?.type || 'info' }, { default: () => status?.text || record.row.type }); }, }, { label: '案例状态', prop: 'status', minWidth: 100, render(record) { const statusMap = { 1: { text: '正常', type: 'success' }, 2: { text: '禁用', type: 'danger' } }; const status = statusMap[record.row.status]; return h(ElTag, { type: status?.type || 'info' }, { default: () => status?.text || record.row.status }); }, }, { label: '排序', prop: 'sort', minWidth: 100 }, { label: '创建人', prop: 'createUser', minWidth: 100 }, { label: '创建时间', prop: 'createTime', width: 180 }, ]; ``` ## querySchemas.ts ```typescript import { FormSchema } from '@/components/Form/index'; export const schemas: FormSchema[] = [ { field: 'name', component: 'Input', label: '案例名称', componentProps: { placeholder: '请输入案例名称', clearable: true }, }, { field: 'type', component: 'Select', label: '案例类型', componentProps: { placeholder: '请输入案例类型', clearable: true, options: [ { label: '类型1', value: 1 }, { label: '类型2', value: 2 }, ], }, }, { field: 'status', component: 'Select', label: '案例状态', componentProps: { placeholder: '请输入案例状态', clearable: true, options: [ { label: '正常', value: 1 }, { label: '禁用', value: 2 }, ], }, }, ]; ``` ## 数据流 ``` 页面加载 → BasicForm 注册 → BasicTable request 触发 → loadDataTable → API → 渲染表格 用户搜索 → handleSubmit → 更新 formParams → reloadTable → 重新请求 用户新增 → handleAdd → currentId=0 → editVisible=true → edit.vue 加载 → 表单填写 → 提交 用户编辑 → handleEdit → currentId=id → editVisible=true → edit.vue 加载详情 → 修改 → 提交 用户删除 → confirm → API → reloadTable ``` :::tip 温馨提示 `columns.ts` 和 `querySchemas.ts` 独立为配置文件,便于维护和复用。`columns` 中的 `render` 函数使用 Vue 的 `h()` 创建虚拟 DOM,可实现任意复杂的自定义渲染。`querySchemas` 中的 `options` 硬编码或通过字典 API 动态获取。 ::: ## 总结 页面视图遵循 `index.vue` + `edit.vue` + `detail.vue` + `columns.ts` + `querySchemas.ts` 标准模式。列表页使用 `BasicForm` 搜索 + `BasicTable` 展示数据 + `TableAction` 操作按钮,编辑弹窗使用 `defineAsyncComponent` 懒加载 + `useLockFn` 防重复提交。