稀土掘金技术社区 07月21日 09:47
用装饰器和ElementPlus,我们在NPM发布了这个好用的表格组件包
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

AirPower-Web是一个基于TypeScript、Vue3和ElementPlus的组件包,提供了强大的表格功能。它拆分自AirPower4T项目,包含数据转换、枚举封装、国际化和工具封装等核心库。本文详细介绍了如何使用AirPower-Web创建表格,包括实体类声明、服务绑定、页面实现以及接口自定义等。

🔹 AirPower-Web是AirPower4T项目拆分出的库,提供数据转换、枚举封装、国际化和工具封装等功能,可与ElementPlus组件结合使用。

🔹 使用AirPower-Web创建表格,首先需声明实体类,通过装饰器标记列属性,如名称、类型、搜索、颜色等。

🔹 实体类需绑定服务,通过服务与后端进行数据交互,服务类继承AbstractBaseService并指定实体类和服务基址。

🔹 页面实现使用ATable组件,绑定数据列表、实体类和服务,可通过事件处理添加、修改、删除等操作。

🔹 对于接口名称、数据结构或状态码的差异,可通过重写服务方法或配置WebConfig进行自定义,以适应不同后端标准。

原创 Hamm 2025-07-20 09:02 重庆

点击关注公众号,技术干货及时达!

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

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

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

「AirPower-Transformer」 核心的数据转换库,类似 

class-transformer

 的封装。
「AirPower-Enum」 核心的枚举封装库,这个也在之前的文章中提到过。

「AirPower-i18n」 核心的国际化封装库,在我们关于 I18n 的文章中也提到过。

「AirPower-Util」 核心的工具封装库。

「AirPower-Web」「AirPower4T」 的下一个库,做了解耦设计。

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

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

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

安装 @airpower/web可以选择你喜欢的方式安装:

npm install @airpower/web# oryarn add @airpower/web# orcnpm install @airpower/web# or ...

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

「name」: 物料名称 字符串

「materialType」: 物料类型 枚举值

「spc」: 规格型号 字符串

「code」: 物料编码 字符串

而枚举值,我们使用 「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<MaterialEntity> {  // 表示这个服务绑定的是 物料 这个实体类  entityClass = MaterialEntity  // 表示这个服务请求后端的 /material/xxxx   baseUrl = 'material'}

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

实现页面好,接下来可以写页面 

list.vue

 了:

<template>  <APanel>    <!-- 开始使用 ATable 这个我们提供的组件 -->    <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<MaterialEntity> {  entityClass = MaterialEntity  baseUrl = 'material'  // 则你们的接口地址是 /material/paaaaaaaaage  protected urlGetPage: string = 'paaaaaaaaage'}

如果连 

baseUrl

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

export class MaterialService extends AbstractBaseService<MaterialEntity> {  entityClass = MaterialEntity  baseUrl = 'material'  getPage(request: QueryRequest<MaterialEntity>, apiUrl?: string): Promise<QueryResponsePage<MaterialEntity>> {    // 等于 /wuliao/getPage    const responsePage: QueryResponsePage<E> = await this.api("getPage","物料").post(request, QueryResponsePage<E>)    responsePage.list = responsePage.list.map(json => Transformer.parse(json, this.entityClass))    return responsePage  }}

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

export class MaterialService extends AbstractBaseService<MaterialEntity> {  entityClass = MaterialEntity  baseUrl = 'material'  getPage(request: QueryRequest<MaterialEntity>, apiUrl?: string): Promise<QueryResponsePage<MaterialEntity>> {    // 等于 /wuliao/getPage    const responsePage: YourTypeClass = awaitthis.api(apiUrl).post(request, YourTypeClass)  }// 如果请求的数据类型也不同,那就直接写个新方法?// getMyPage.....}

状态码的不同

AirPower-Web

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

WebConfig

你可以通过 

WebConfig

 来配置全局的 HTTP 服务状态码:

//main.tsWebConfig.successCode = 200000// 更多的配置

通过重写 Service 调用你自己的方法你可以和上面重写 

getPage

 方法一样,重新调用一个自己的其他方法即可。还有太多太多我们本意是不太建议大家各种重写来解决问题的,因为 

@airpower/web

 这个包本身是和 

AirPower4J

 这个后端标准后端服务来做兼容的全栈项目的,我们建议如果使用的话,可以考虑和 

AirPower4J

 这个项目的数据结构做一些兼容处理 :)还提供了些什么我们在 「SPMS_Web」 这个项目里,也使用了 

AirPower-Web

 这个包,具体可以参考这个开源项目。当然,你也可以看看我们的设计图。

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

附上设计图:

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

https://aicoding.juejin.cn/aicoding

""~

阅读原文

跳转微信打开

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

AirPower-Web TypeScript Vue3 ElementPlus 表格组件
相关文章