Files
easygoadmin-wiki/EasyGoAdmin_GoFrame_Layui/zh/guide/frontend-integration.md
T
2026-10-20 21:19:44 +08:00

275 lines
7.1 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.
# 3.9 前端联调指引
:::tip 概述
后端接口开发完成后,需要在前端创建对应的 API 模块和页面组件。本节以 example 模块为例,提供简要指引,详细内容参考[第 9 章](/zh/frontend/overview.html)。
:::
## 联调流程
```text
1. 创建 API 模块 → ui/src/api/tool/example.ts
2. 创建页面组件 → ui/src/views/tool/example/index.vue
3. 配置菜单组件路径 → 后端菜单管理中设置 component
4. 测试联调
```
## 步骤一:创建 API 模块
在 `ui/src/api/tool/` 下创建 `example.ts`(来自项目实际代码):
```typescript
// ui/src/api/tool/example.ts
import { http } from '@/utils/http/axios';
/**
* 案例演示模块接口
*
* 提供案例演示的增删改查及导入导出接口调用。
*/
/**
* 获取案例演示分页列表
*
* @param params 查询参数,包含 pageNo、pageSize 及业务筛选条件
* @returns 分页结果,含 records、total、size、current、pages
*/
export function getExamplePage(params?: Record<string, any>) {
return http.request({
url: '/example/page',
method: 'GET',
params,
});
}
/**
* 获取全部案例演示列表
*
* @param params 查询参数
* @returns 案例演示列表
*/
export function getExampleList(params?: Record<string, any>) {
return http.request({
url: '/example/list',
method: 'GET',
params,
});
}
/**
* 根据 ID 获取案例演示详情
*
* @param id 案例演示ID
* @returns 案例演示详情数据
*/
export function getExampleDetail(id) {
return http.request({
url: '/example/detail/' + id,
method: 'get',
});
}
/**
* 添加案例演示
*
* @param data 案例演示数据
* @returns 新记录的 ID
*/
export function exampleAdd(data: any) {
return http.request({
url: '/example/add',
method: 'POST',
data,
});
}
/**
* 更新案例演示
*
* @param data 案例演示数据,需包含主键 id
* @returns 操作结果
*/
export function exampleUpdate(data: any) {
return http.request({
url: '/example/update',
method: 'PUT',
data,
});
}
/**
* 删除案例演示
*
* @param id 案例演示ID
* @returns 操作结果
*/
export function exampleDelete(id) {
return http.request({
url: '/example/delete/' + id,
method: 'DELETE',
});
}
/**
* 批量删除案例演示
*
* @param data 含 ids 数组的对象,形如 { ids: [1, 2, 3] }
* @returns 操作结果
*/
export function exampleBatchDelete(data: any) {
return http.request({
url: '/example/batchDelete',
method: 'DELETE',
data,
});
}
/**
* 导入案例演示
*
* @param data 文件数据(FormData)
* @returns 导入结果,含成功数量与失败明细
*/
export function exampleImport(data) {
return http.request({
url: '/example/import',
method: 'POST',
data,
});
}
/**
* 导出案例演示
*
* @param params 查询参数
* @returns 导出文件的 URL
*/
export function exampleExport(params) {
return http.request({
url: '/example/export',
method: 'GET',
params,
});
}
```
## 步骤二:创建页面组件
在 `ui/src/views/tool/example/` 下创建以下 5 个文件:
| 文件 | 说明 |
|------|------|
| `index.vue` | 列表页(表格 + 搜索 + 分页) |
| `edit.vue` | 新增/编辑弹窗表单 |
| `detail.vue` | 详情查看页 |
| `columns.ts` | 表格列定义 |
| `querySchemas.ts` | 搜索表单字段定义 |
:::tip 关于以下示例
以下代码使用原生 `el-table` / `el-form` 简化展示核心逻辑。实际项目中应使用封装好的 `BasicTable` + `useForm` 等组合式组件,详见[第 9 章组件文档](/zh/frontend/overview.html)。
:::
`index.vue`(列表页)示例:
```vue
<!-- ui/src/views/tool/example/index.vue -->
<template>
<div>
<!-- 搜索表单 -->
<el-form :model="searchForm" inline>
<el-form-item label="名称">
<el-input v-model="searchForm.name" placeholder="请输入名称" />
</el-form-item>
<el-form-item label="状态">
<el-select v-model="searchForm.status" placeholder="请选择" clearable>
<el-option label="启用" :value="1" />
<el-option label="禁用" :value="0" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSearch">搜索</el-button>
<el-button @click="handleReset">重置</el-button>
</el-form-item>
</el-form>
<!-- 操作按钮 -->
<el-button type="primary" @click="handleAdd">新增</el-button>
<el-button type="danger" :disabled="!selectedIds.length" @click="handleBatchDelete">
批量删除
</el-button>
<!-- 数据表格 -->
<el-table :data="tableData" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" />
<el-table-column prop="id" label="ID" width="80" />
<el-table-column prop="name" label="名称" />
<el-table-column prop="typeText" label="类型" width="100" />
<el-table-column prop="statusText" label="状态" width="100" />
<el-table-column prop="sort" label="排序" width="80" />
<el-table-column prop="createTime" label="创建时间" width="180" />
<el-table-column label="操作" width="200">
<template #default="{ row }">
<el-button size="small" @click="handleEdit(row)">编辑</el-button>
<el-button size="small" type="danger" @click="handleDelete(row.id)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<el-pagination
v-model:current-page="pageNo"
v-model:page-size="pageSize"
:total="total"
@current-change="fetchData"
/>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { getExamplePage, exampleDelete, exampleBatchDelete } from '@/api/tool/example';
const searchForm = ref({ name: '', status: '' });
const tableData = ref([]);
const pageNo = ref(1);
const pageSize = ref(20);
const total = ref(0);
const selectedIds = ref([]);
const fetchData = async () => {
const res = await getExamplePage({
pageNo: pageNo.value,
pageSize: pageSize.value,
...searchForm.value,
});
tableData.value = res.records;
total.value = res.total;
};
const handleSearch = () => { pageNo.value = 1; fetchData(); };
const handleReset = () => { searchForm.value = { name: '', status: '' }; handleSearch(); };
const handleDelete = async (id: number) => { await exampleDelete(id); fetchData(); };
const handleBatchDelete = async () => { await exampleBatchDelete({ ids: selectedIds.value }); fetchData(); };
const handleSelectionChange = (rows: any[]) => { selectedIds.value = rows.map((r) => r.id); };
onMounted(() => fetchData());
</script>
```
## 步骤三:配置菜单
在后端菜单管理中,将组件路径设置为:
```text
tool/example/index
```
前端路由系统会自动将此路径映射到 `ui/src/views/tool/example/index.vue`。
## 步骤四:测试联调
1. 确保后端服务运行:`php think run`
2. 确保前端服务运行:`pnpm dev`
3. 刷新前端页面,侧边栏应出现"案例演示"菜单
4. 点击菜单,测试增删改查功能
详细前端开发内容请参考[第 9 章](/zh/frontend/overview.html)。