企业项目管理、ORK、研发管理与敏捷开发工具平台

网站首页 > 精选文章 正文

用装饰器和ElementPlus

wudianyun 2025-08-03 08:52:46 精选文章 4 ℃

前言

如果你恰好也在使用 「TypeScript」 「Vue3」 「ElementPlus」 ,那么这个组件包你可以看看。

之前我们在一些文章里提到过如何使用 「装饰器」 来配置表格,也开源了一个 「AirPower4T」 的开源项目,但后来很多人反馈说,用子仓库的方式使用有些不太方便?

于是我们将 「AirPower4T」 这个项目做了拆分,分别独立成了下面的几个包:

我们今天主要讲的是 「AirPower-Web」 这个库,这个库提供了 「AirPower-Web」 的核心功能,并且还封装了 「ElementPlus」 的一些组件,这样, 「AirPower-Web」 就可以作为替代 「AirPower4T」 的一个库使用。

我们今天要实现的表格是下面这个图:

快速开始

初始化项目我们就不再提了,这里我们从安装包开始:

安装 @airpower/web

可以选择你喜欢的方式安装:

npm install @airpower/web
# or
yarn add @airpower/web
# or
cnpm install @airpower/web
# or ...

声明表格使用的实体类

我们要实现的是一个物料的表格,按后端接口文档,我们知道表格有这么几个列:

而枚举值,我们使用 「AirPower-Enum」 这个库来封装:

import { WebColor, WebEnum } from'@airpower/web'

/**
* # 物料类型枚举
*/

exportclass MaterialTypeEnum extends WebEnum {
/** 自产品 */
static readonly PRODUCT = new MaterialTypeEnum(1, '自产品')
// 设置图中的灯,后面装饰器会用到
.setColor(WebColor.SUCCESS)

/** 外购品 */
static readonly PURCHASE = new MaterialTypeEnum(2, '外购品')
.setColor(WebColor.WARNING)
}

于是我们可以很轻易的声明出这个物料的实体类,

请注意仔细看下面的一些注释:

@Model({
// 标记这个东西叫做 物料。。。
label: '物料',
})
exportclass MaterialEntity extends BaseEntity {
// 标记为表格列
@Table({
// 这个列是可以复制的
copy: true,
// 这个列在列选择器中必须展示,无法取消
force: true,
})
// 标记这个列可以搜索
@Search()
@Field({
// 标记这个列的名字
label: '物料编码',
})
code!: string

@Table()
@Search()
@Field({
label: '物料名称',
})
name!: string

@Table({
// 标记这个列要显示一个枚举的颜色灯
color: true,
// 列的宽度
width: 100,
})
@Search()
@Field({
label: '物料类型',
// 这个列要显示一个枚举字典
dictionary: MaterialTypeEnum,
})
materialType!: number

@Table({
copy: true,
})
@Field({
label: '规格型号',
})
spc!: string
}

实现实体对应的服务

有了这个实体的声明,那么我们可以使用这个物料的类来作为前后端对接数据的标准了。

当然,如果你的后端在你写完后要改,那可以继续标注一些装饰器来解决这些问题,可以参考 @airpower-transformer 这个库。

接下来,我们还要为这个实体类绑定一个服务:

export class MaterialService extends AbstractBaseService {
// 表示这个服务绑定的是 物料 这个实体类
entityClass = MaterialEntity
// 表示这个服务请求后端的 /material/xxxx
baseUrl = 'material'
}

好了,都准备好了,让我们开始写页面了

实现页面

好,接下来可以写页面 list.vue 了:

<template>
<APanel>

<ATable
v-loading="isLoading" // 绑定一个 Loading
:data-list="response.list" // 绑定一个数据列表
:entity="MaterialEntity" // 绑定一个实体类
:service="MaterialService" // 绑定一个服务

@xxx="onXxx" // 如果你需要各种方法,可以继续加
/>

<template #footerLeft>
<APage
:response="response"
@changed="onPageChanged"
/>

template>
APanel>
template>

<script lang="ts" setup>
// 从Hooks中拿出这些属性和方法
const {
isLoading,
response,
// 更多你需要的属性
onPageChanged,
onXxx // 更多你需要的事件
} = useTable(MaterialService)
script>

「这就搞定了。」

我们通过这种方式实现了:

如果你的表格需要各种事件的处理,比如 添加、修改、删除、详情、排序、分页、选择等等等各种方法,都可以为 「ATable」 绑定各种 @xxx="onXxx" ,基本上很多的事件都可以从 useTable 这个 Hook 中拿到。

更多的自定义

你可能会说,我们家后端的标准和你不太一样,比如:接口名字的不同,数据结构的不同,状态码的不同等等,我们来一个个解决:

接口访问的名字不同

你可以通过 baseUrl 属性来配置公共的部分,也可以通过重写 urlForXXX 属性来覆盖我们的默认的访问路径:

export class MaterialService extends AbstractBaseService {
entityClass = MaterialEntity

baseUrl = 'material'

// 则你们的接口地址是 /material/paaaaaaaaage
protected urlGetPage: string = 'paaaaaaaaage'
}

如果连 baseUrl 都需要自定义,你可以直接重写对应的方法:

export class MaterialService extends AbstractBaseService {
entityClass = MaterialEntity

baseUrl = 'material'

getPage(request: QueryRequest, apiUrl?: string): Promise> {
// 等于 /wuliao/getPage
const responsePage: QueryResponsePage = await this.api("getPage","物料").post(request, QueryResponsePage)
responsePage.list = responsePage.list.map(json => Transformer.parse(json, this.entityClass))
return responsePage
}
}

数据结构的不同

和上面一样,你可以通过重写这部分不一样的方法来解决:

export class MaterialService extends AbstractBaseService {
entityClass = MaterialEntity

baseUrl = 'material'

getPage(request: QueryRequest, apiUrl?: string): Promise> {
// 等于 /wuliao/getPage
const responsePage: YourTypeClass = awaitthis.api(apiUrl).post(request, YourTypeClass)
}

// 如果请求的数据类型也不同,那就直接写个新方法?

// getMyPage.....
}

状态码的不同

AirPower-Web 这个包的 Http 服务也是提供了大量灵活的方案来解决这些问题:

通过 WebConfig

你可以通过 WebConfig 来配置全局的 HTTP 服务状态码:

//main.ts
WebConfig.successCode = 200000
// 更多的配置

通过重写 Service 调用你自己的方法

你可以和上面重写 getPage 方法一样,重新调用一个自己的其他方法即可。

还有太多太多

我们本意是不太建议大家各种重写来解决问题的,因为 @airpower/web 这个包本身是和 AirPower4J 这个后端标准后端服务来做兼容的全栈项目的,我们建议如果使用的话,可以考虑和 AirPower4J 这个项目的数据结构做一些兼容处理 :)

还提供了些什么

我们在 「SPMS_Web」 这个项目里,也使用了 AirPower-Web 这个包,具体可以参考这个开源项目。

当然,你也可以看看我们的设计图。

今天就这样啦,再见了各位。

附上设计图:

AI编程资讯AI Coding专区指南:

https://aicoding.juejin.cn/aicoding

" " ~

最近发表
标签列表