# 9.12 新增页面开发步骤
:::tip 概述
以 example 模块为例,演示从 API 到视图的完整开发步骤(代码来自项目实际的 `tool/example` 模块)。一个完整模块涉及 6 个文件:API 接口、表格列配置、查询表单配置、列表页、编辑弹窗、详情弹窗。
:::
## 开发流程
```text
1. 创建 API 接口 src/api/{module}/{name}.ts
2. 创建表格列配置 src/views/{module}/{name}/columns.ts
3. 创建查询表单配置 src/views/{module}/{name}/querySchemas.ts
4. 创建列表页 src/views/{module}/{name}/index.vue
5. 创建编辑弹窗 src/views/{module}/{name}/edit.vue
6. 创建详情弹窗 src/views/{module}/{name}/detail.vue
7. 配置菜单 后端菜单管理中设置组件路径
8. 测试 刷新前端页面,点击菜单测试
```
## 完整文件结构
```text
ui/src/
├── api/
│ └── tool/
│ └── example.ts # API 接口
└── views/
└── tool/
└── example/
├── index.vue # 列表页(主页面)
├── columns.ts # 表格列配置
├── querySchemas.ts # 查询表单配置
├── edit.vue # 编辑弹窗(新增/修改)
└── detail.vue # 详情弹窗
```
## 步骤一:创建 API 接口
```typescript
// ui/src/api/tool/example.ts
import { http } from '@/utils/http/axios';
// 分页查询
export function getExamplePage(params?) {
return http.request({ url: '/example/page', method: 'GET', params });
}
// 全量列表(下拉框数据源)
export function getExampleList(params?) {
return http.request({ url: '/example/list', method: 'GET', params });
}
// 详情
export function getExampleDetail(id) {
return http.request({ url: '/example/detail/' + id, method: 'GET' });
}
// 新增
export function exampleAdd(data: any) {
return http.request({ url: '/example/add', method: 'POST', data });
}
// 修改
export function exampleUpdate(data: any) {
return http.request({ url: '/example/update', method: 'PUT', data });
}
// 删除
export function exampleDelete(id) {
return http.request({ url: '/example/delete/' + id, method: 'DELETE' });
}
// 批量删除
export function exampleBatchDelete(data: any) {
return http.request({ url: '/example/batchDelete', method: 'DELETE', data });
}
```
### API 命名规范
| 操作 | 函数名 | HTTP 方法 |
|------|--------|----------|
| 分页查询 | `get{Module}Page` | GET |
| 全量列表 | `get{Module}List` | GET |
| 详情 | `get{Module}Detail` | GET |
| 新增 | `{module}Add` | POST |
| 修改 | `{module}Update` | PUT |
| 删除 | `{module}Delete` | DELETE |
| 批量删除 | `{module}BatchDelete` | DELETE |
## 步骤二:创建表格列配置
表格列使用 `title` / `key` 字段声明表头与数据字段,`render` 函数参数为当前行对象:
```typescript
// ui/src/views/tool/example/columns.ts(来自项目实际代码)
import { h } from 'vue';
import { NTag, NAvatar } from 'naive-ui';
export const columns = [
{
title: '案例名称',
key: 'name',
width: 120,
// 普通文本渲染(默认按 key 取值)
},
{
title: '案例图片',
key: 'avatar',
width: 120,
// 图片渲染:以方形头像形式展示
render(record) {
return h(NAvatar, {
size: 48,
src: record.avatar,
round: false,
objectFit: 'fill',
});
},
},
{
title: '案例状态',
key: 'status',
width: 100,
// 选项标签渲染:按选项值映射文字与标签颜色
render(record) {
const statusMap = {
1: { text: '在用', type: 'success' },
2: { text: '停用', type: 'error' },
};
const status = statusMap[record.status];
return h(
NTag,
{ bordered: false, type: status?.type || 'info' },
{ default: () => status?.text || record.status },
);
},
},
{
title: '创建人',
key: 'createUser',
width: 100,
},
{
title: '创建时间',
key: 'createTime',
width: 180,
},
];
```
### 列配置字段说明
| 字段 | 类型 | 说明 |
|------|------|------|
| `type` | string | 列类型:`selection`(多选框)/ `index`(序号) |
| `title` | string | 表头标题 |
| `key` | string | 数据字段名(camelCase) |
| `fixed` | string | 固定列:`left` / `right` |
| `width` | number | 固定宽度 |
| `minWidth` | number | 最小宽度(自适应) |
| `render` | function | 自定义渲染函数,参数为当前行对象 |
| `auth` | string[] | 按权限控制列显示(可选) |
## 步骤三:创建查询表单配置
`component` 取值为对应的组件名(`NInput`/`NSelect`/`NInputNumber`/`NDatePicker` 等):
```typescript
// ui/src/views/tool/example/querySchemas.ts(来自项目实际代码)
import { FormSchema } from '@/components/Form/index';
export const schemas: FormSchema[] = [
{
field: 'name',
component: 'NInput',
label: '案例名称',
componentProps: {
placeholder: '请输入案例名称',
clearable: true,
},
},
{
field: 'status',
component: 'NSelect',
label: '案例状态',
componentProps: {
placeholder: '请选择案例状态',
clearable: true,
options: [
{ label: '在用', value: 1 },
{ label: '停用', value: 2 },
],
},
},
];
```
### 表单组件类型
| component | 适用场景 | 说明 |
|-----------|---------|------|
| `NInput` | 字符串字段 | 文本输入框 |
| `NSelect` | 枚举/选项字段 | 下拉选择框(选项通过 `componentProps.options` 传入) |
| `NInputNumber` | 数字字段 | 数字输入框 |
| `NDatePicker` | 日期字段 | 日期选择器 |
| `NRadioGroup` | 少量选项(≤3 个) | 单选组 |
## 步骤四:创建列表页
列表页使用 `BasicForm`(搜索)+ `BasicTable`(表格,内置分页与操作列)组合:
```vue
新增
批量删除
```
## 步骤五:创建编辑弹窗
使用项目封装的 `basicModal`(`useModal`)+ `n-form`:
```vue
在用
停用
```
## 步骤六:创建详情弹窗
详情弹窗使用 `n-modal`(preset="card")+ `n-descriptions`:
```vue
{{ formData.name || '-' }}
-
{{ formData.status === 1 ? '在用' : '停用' }}
{{ formData.sort || '-' }}
关闭
```
## 步骤七:配置菜单
在后端菜单管理中添加菜单项:
| 字段 | 值 |
|------|-----|
| 菜单名称 | 案例管理 |
| 组件路径 | `tool/example/index` |
| 路由路径 | `/tool/example` |
| 权限标识 | `sys:example:page` |
添加按钮权限:
| 按钮名称 | 权限标识 |
|---------|---------|
| 新增 | `sys:example:add` |
| 修改 | `sys:example:update` |
| 删除 | `sys:example:delete` |
| 批量删除 | `sys:example:batchDelete` |
| 详情 | `sys:example:detail` |
## 步骤八:测试
1. 刷新前端页面
2. 点击菜单"案例管理"
3. 测试搜索、新增、编辑、详情、删除、批量删除功能
## 代码生成器(快速创建)
如果模块结构简单,可使用代码生成器一键生成前后端代码:
1. 建好数据库表
2. 访问 `/api/generator/page` 查看可生成的表
3. `POST /api/generator/preview` 预览代码
4. `POST /api/generator/generate` 生成代码
5. 在菜单管理中配置菜单
详见[代码生成器](/zh/generator/overview.html)。