扩展开发指南
本章给出一条完整的二次开发路径。目标不是限制业务设计,而是保证新增模块继续使用项目已有的数据、权限、表格、主题和工程基础设施,避免项目维护半年后出现多套互不兼容的写法。
开始前先做四个决定
新增模块前确认:
- 业务边界:模块负责什么,不负责什么。
- 数据来源:先使用预置数据评审,还是直接连接后端。
- 权限模型:哪些角色可见,包含哪些按钮权限,是否存在数据范围。
- 路由结构:一级菜单、列表、详情和隐藏页面如何组织。
如果这些问题尚未明确,不要先复制大量页面。页面结构一旦扩散,后续统一字段、权限和路由成本会更高。
推荐目录
以客户管理为例:
src/
├── views/customer/
│ ├── list/
│ │ ├── index.vue
│ │ └── modules/
│ │ ├── customer-search.vue
│ │ └── customer-dialog.vue
│ └── detail/
│ └── index.vue
├── api/customer.ts # 已接真实接口时使用
├── mock/customer/ # 评审阶段需要预置数据时使用
├── types/api/customer.d.ts
├── router/modules/customer.ts
└── locales/ # 增加中英文菜单与页面文案不必同时创建 api 和 mock 两套完整实现。根据当前阶段选择需要的目录,迁移时保持函数契约即可。
第一步:定义类型
先定义页面真正需要的类型:
declare namespace Api {
namespace Customer {
interface SearchParams extends Api.Common.PaginationParams {
keyword?: string
status?: 'active' | 'disabled'
}
interface ListItem {
id: number
name: string
status: 'active' | 'disabled'
createdAt: string
}
interface SaveParams {
name: string
status: 'active' | 'disabled'
}
}
}类型应描述前端使用的稳定契约,不要把数据库表结构原样复制到浏览器。敏感字段和页面不使用的内部字段不应进入响应。
第二步:准备数据函数
直接接后端
// src/api/customer.ts
import request from '@/utils/http'
export function fetchCustomerList(params: Api.Customer.SearchParams) {
return request.get<Api.Common.PaginatedResponse<Api.Customer.ListItem>>({
url: '/api/v1/customers',
params
})
}
export function createCustomer(data: Api.Customer.SaveParams) {
return request.post<Api.Customer.ListItem>({
url: '/api/v1/customers',
data,
showSuccessMessage: true
})
}先使用预置数据
在 src/mock/customer 中只实现页面需要的查询和筛选,返回深拷贝分页结果。写操作继续使用 showDemoActionNotice,不要模拟生产保存。
第三步:创建列表页
优先参考 src/views/system/user:
- 页面根节点使用
art-full-height。 - 搜索组件放在页面
modules。 - 表格内容使用
ElCard.art-table-card。 - 使用
ArtTableHeader、ArtTable和useTable。 - 新增和编辑表单放在独立弹窗组件。
const table = useTable({
core: {
apiFn: fetchCustomerList,
apiParams: {
current: 1,
size: 20
},
columnsFactory: () => [
{ type: 'index', width: 60, label: '序号' },
{ prop: 'name', label: '客户名称' },
{ prop: 'status', label: '状态' },
{ prop: 'operation', label: '操作', width: 120, fixed: 'right' }
]
}
})第四步:注册路由
// src/router/modules/customer.ts
const customerRoutes: AppRouteRecord = {
path: '/customer',
name: 'Customer',
component: '/index/index',
meta: {
title: 'menus.customer.title',
icon: 'ri:customer-service-2-line',
roles: ['R_ADMIN', 'R_SALES']
},
children: [
{
path: 'list',
name: 'CustomerList',
component: '/customer/list',
meta: {
title: 'menus.customer.list',
permissionPrefix: 'customer:list',
authList: [
{ title: '新增客户', authMark: 'add' },
{ title: '编辑客户', authMark: 'edit' },
{ title: '删除客户', authMark: 'delete' }
]
}
},
{
path: 'detail/:id',
name: 'CustomerDetail',
component: '/customer/detail',
meta: {
title: 'menus.customer.detail',
isHide: true
}
}
]
}远程菜单模式下,需要把同样的结构同步到菜单接口。隐藏详情页也必须返回,否则动态路由无法注册。
第五步:接入按钮权限
模板中:
<ElButton v-auth="'add'" type="primary">新增客户</ElButton>脚本中:
const { hasAuth } = useAuth()
const canEdit = computed(() => hasAuth('edit'))后端用户接口返回完整权限码:
{
"buttons": [
"customer:list:add",
"customer:list:edit"
]
}业务 API 仍要在服务端重新判断权限和资源归属。
第六步:国际化与品牌文案
新增:
- 中文菜单 key。
- 英文菜单 key。
- 页面固定文案。
- 空状态、校验和错误提示。
客户可在后台修改的名称、Logo 和欢迎语应进入站点配置,不要写死在语言包或页面组件中。
第七步:处理完整页面状态
专业页面不能只验证“有数据且接口成功”。至少覆盖:
- 首次加载。
- 空列表。
- 搜索无结果。
- 慢请求。
- 网络失败和服务端错误。
- 无权限。
- 表单校验失败。
- 重复提交。
- 删除确认和取消。
- 超长文本。
- 移动端与窄屏。
- 亮色与暗色。
接入已有后端的适配原则
在 API 层适配字段
后端字段与页面模型不一致时,优先在对应 API 模块中转换:
export async function fetchCustomerList(params: Api.Customer.SearchParams) {
const result = await request.get<BackendCustomerPage>({
url: '/legacy/customer/query',
params: {
pageNum: params.current,
pageSize: params.size,
keyword: params.keyword
}
})
return {
records: result.rows.map(mapBackendCustomer),
total: result.total,
current: params.current,
size: params.size
}
}不要让页面到处判断后端字段或业务码。
只在必要时修改全局请求层
只有所有接口都共享同一种响应结构、Token 规则或错误格式时,才修改 src/utils/http。单个业务域的特殊行为应保留在该域 API 中,不要为此把接口移动到 Service。
代码质量与提交
开发中建议:
pnpm fix
pnpm build提交前至少执行与改动范围匹配的检查。准备交付时执行:
pnpm release:check新增动态 HTML 时使用 ArtSafeHtml;新增本地存储时使用项目存储工具和命名空间;不要调用 localStorage.clear()。
完成检查清单
- 目录、命名和类型与现有业务域一致。
- 查询、分页、搜索和重置行为正确。
- 写操作不会重复提交,失败时保留输入。
- 权限账号和无权限账号都已验证。
- URL 直达详情页与刷新正常。
- local 与 remote 菜单模式符合项目需求。
- 中英文、亮暗主题和移动端正常。
- 不含密钥、真实客户数据和伪持久化逻辑。
pnpm release:check通过。
开发过程中应同时遵循Hooks 与组合式能力、通用组件和代码规范。完成开发后,按构建部署准备生产交付。
