6 Star 42 Fork 6

AirPower / AirPower

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
MIT


Gitee / Github / CHANGELOG / NPM

🎉 这是个什么项目

AirPower, 一个基于TypeScript的开发工具包, 内置了数据转换、装饰器、时间日期处理、加解密与散列、文件处理、常用枚举和字典、常见数据结构处理等工具。

此项目是独立的 工具包 ,如需体验我们开源的 Vue3+TypeScript+ElementPlus+ViteWeb开发工具包, 请查看 AirPower4T

💻 如何使用(初始化)?

npm install airpower
# or
yarn add airpower
# or
cnpm install airpower
# or ...

⏰ Enjoy it

如有疑问,可以通过本仓库的 Issues 与我们联系,如果你有一些代码贡献,可以通过 Pull Request 将代码贡献,为这个项目添砖加瓦。

高司令:“嗯?Java? 什么Java?”

📖 食用文档

一、 装饰器

AirPower 提供了一些湿滑的装饰器,对数据转换、类和属性的扩展配置等提供了一些便捷的开发帮助。

  • @Alias 字段别名

    在数据转换时提供别名服务。如后端返回的JSON提供的是 username, 而前端期望为 nickname, 可使用下面的别名方式, 前端其他代码中均可直接使用期望的 nickname, 如后端再次修改, 则前端只需要修改 @Alias() 的参数即可。

    class User extends AirModel{
      @Alias("username") nickname!: string
    }

    此时,下面的JSON就可以直接转为目标类的实例了:

    JSON {
      "username": "Hamm"
    }

    转换后:

    User {
      nickname: "Hamm"
    }
  • @ClassName 类的文案

    日常开发中,我们一般会声明一个 Account 类作为账号信息的数据结构载体,使用 账号 作为文案在系统里显示,所以我们使用下面的方式来声明:

    @ClassName('账号')
    class Account extends AirModel{
        username!: string
        password!: string
        // more...
    }
    
    // 返回 “账号”
    const className = Account.getClassName()
    const className = getClassName(Account)

    然后通过 getClassName() 方法来获取配置的名称。

    但可能因为需求原因,需要将系统里显示的 账号 全局修改为 账户。传统方式我们会全局的搜索替换,但很容易造成过度替换后的其他问题。于是我们只需要修改为 @ClassName("账户") 即可。

  • @FieldName 属性的文案

    与上面的 @ClassName 类似的需求,我们将 username 作为 用户名 的字段:

    @ClassName('账号')
    class Account extends AirModel{
        @FieldName('用户名') 
        username!: string
    
        @FieldName('密码') 
        password!: string
        // more...
    }
    // 返回 “用户名”
    const fieldName = Account.getFieldName('username')
    const fieldName = getFieldName(Account, 'username')

    当需要将 密码 修改为 口令 时,我们也只需要去修改为 @FieldName('口令') 即可。

  • @Default 属性默认值

    当我们通过发起请求获取到后端数据后,我们期望后端部分数据缺失时,我们能提供一些默认值:

    class User extends AirModel{
      nickname!: string
    
      @Default("这个人很懒,一句话也没留下")
      bio!: string
      // more...
    }
    
    const defaultBio = getDefault(User, "bio")

    后端传递来的用户JSON格式如下:

    const json = {
      "nickname": "Hamm",
    }
    
    const user = User.fromJson(json)
    
    console.log(user.bio) // 打印 这个人很懒,一句话也没留下
  • @Dictionary

    前端可以通过 AirDictionaryArray.create() 创建一个字典,然后将字典传入到 @Dictionary 的参数中,其他地方则可获取此属性配置的字典,然后做一些其他的操作(如渲染)。

    enum UserStatus {
      ENABLED = 1,
      DISABLED = 2,
      UNVALID = 3
    }
    const UserStatusDictionary = AirDictionaryArray.create([
      {key: UserStatus.ENABLED, label: "已启用"},
      {key: UserStatus.DISABLED, label: "已禁用"},
      {key: UserStatus.UNVALID, label: "待验证"},
    ])
    
    class User extends AirModel{
      nickname!: string
    
      @Dictionary(UserStatusDictionary)
      status!: UserStatus
    }
    
    // 在其他的组件中,即可通过下面的方式来获取指定属性配置的字典
    
    const dict = getDictionary(User, "status")
    const dict = User.getDictionary("status")
  • @FieldPrefix 标记类所有属性的前缀

    如果后端在某些规范下,习惯给字段加上统一的前缀,如 用户信息 都带上了 user_ 的前缀:

    const userJson = {
      user_name: "Hamm",
      user_age: 18,
      user_bio: "这个人很懒,一句话也没留下",
    }
    
    // 为了接收后端来的数据,我们声明了 User 类,使用 @FieldPrefix("user_") 标记前缀
    @FieldPrefix("user_")
    class User extends AirModel{
      name!: string
      age!: number
      bio!: string
    }
    
    // 然后进行数据转换
    const user = User.fromJson(userJson)
    
    console.log(user.name) // 打印 Hamm
    console.log(user.user_name) // 报错,没有这个属性

    于是我们的代码中就不会出现大量的 user_ 前缀了(不因为后端的规范,让前端代码看着拉垮)

  • @IgnorePrefix 属性忽略类配置的前缀

    在上面的示例中,后端某一天不按照规范加了个新的字段 registerIp:

    const userJson = {
      user_name: "Hamm",
      user_age: 18,
      user_bio: "这个人很懒,一句话也没留下",
      registerIp: "127.0.0.1"
    }
    
    // 此时前端声明属性会获取不到数据,于是我们声明一个同样的属性,忽略掉前缀即可
    @FieldPrefix("user_")
    class User extends AirModel{
      name!: string
      age!: number
      bio!: string
    
      @IgnorePrefix() // 忽略前缀
      registerIp!: string
    }
    
    // 然后进行数据转换
    const user = User.fromJson(userJson)
    
    console.log(user.registerIp) // 打印 127.0.0.1
  • @ToModel fromJson自定义转换

    某些场景下,我们使用上面的装饰器都已经无法满足需求了,或者我们有一些自定义的转换规则(如后端给的时间戳,前端需要直接显示), 此时 @ToModel@ToJson 就派上了用场:

    const userJson = {
      nickname: "Hamm",
      lastLoginTime: 124564654465465 // 毫秒时间戳
    }
    
    
    class User extends AirModel{
      @ToModel((json: IJson)=>{ // 参数为原始对象
        return AirDateTime.formatFromMilSecond(json.lastLoginTime)
      })
      lastLoginTime!: number
    }
    
    const user = User.fromJson(userJson)
    
    console.log(user.lastLoginTime) // 打印上面转换后的 "2022-02-02 23:59:59"
  • @ToJson toJson自定义转换

    与上面的 @ToModel 相反,当我们将 类的实例对象 转为后端需要的 JSON 时,可以这么使用:

    
    class User extends AirModel{
     @ToJson((user: User)=>{ // 参数为类的实例对象
       return AirDateTime.getMilTimeStamp(user.lastLoginTime)
     })
     lastLoginTime!: number
    }
    
    const user = new User()
    user.lastLoginTime = "2022-02-02 23:59:59"
    
    const userJson = user.toJson() // 调用内置的 tojson方法
    
    console.log(userJson.lastLoginTime) // 打印毫秒时间戳 1231824291746591
  • @Type 强制转换类型

    后端可能在某些情况下将包含错误数据类型的JSON进行返回,如将 金额 的数字类型转换为了 string:

    const userJson{
        nickname: "Hamm",
        money: "123.02"
    }
    
    // 上面的数据直接进行运算会得到错误的数据,于是我们使用 `@Type` 强制标记为 `Number`:
    class User extends AirModel{
      nickname!: string
    
      @Type(Number)
      money!: number
    }
    
    const user = User.fromJson(userJson)
    
    console.log(user.money + 1) // 打印 124.02 可以安心计算
    console.log(userJson.money + 1) // 打印 123.021 错误的字符串拼接

二、 工具类

  • AirAssert 断言

    断言类是用于一些异常判断拦截,可传入一些断言条件后,断言类的方法将自动判断并抛出异常,然后可自行通过全局处理异常来实现一些异常提示:

    AirAssert.when(a !== 1, "a不允许为1")
    AirAssert.whenNull(user, "用户信息不能为空")
    AirAssert.whenUndefined(user.role, "用户角色不能是undefined")
  • AirClassTransformer 数据转换

    AirClassTransformer 是一个类似 Java BeanUtils 的数据转换类,提供了转换、复制等一系列方法:

    // 简单深拷贝JSON数据
    AirClassTransformer.copyJson(json) 
    
    // 树结构的数组转为普通数组
    const list = AirClassTransformer.treeList2List(treeList)
    
    // 转换JSON数据到指定类的对象
    const userModel = AirClassTransformer.parse(userJson, UserModel)
    
    // 转换JSON数组数据到指定类的对象数组
    const userModelArray = AirClassTransformer.parseArray(userJsonArray, UserModel)
    
    // 复制一个实例
    const userModel = new UserModel()
    const userNewModel = AirClassTransformer.copy(userModel, UserModel)
    
    // 初始化一个指定类型的实例
    const userModel = AirClassTransformer.newInstance(UserModel)

    当然,UserModel 需要继承自 AirModel,也可以直接使用 AirModel 提供的系列静态方法,参考下文关于 AirModel 的文档:)

  • AirCrypto 加解密与编解码

    (有争议,可能会移除)

    内置了 AES加解密SHA1MD5Base64 等前端常用算法,可直接使用。

    AirCrypto.aesEncrypt()
    AirCrypto.aesDecrypt()
    AirCrypto.sha1()
    AirCrypto.md5()
    AirCrypto.base64Encode()
    AirCrypto.base64Decode()
  • AirDateTime 时间与日期

    提供了日期时间在前端常用的一些转换方法:

    // 休眠
    await AirDateTime.sleep(3000)
    
    // 格式化到Unix秒时间戳(默认当前时间)
    AirDateTime.getUnixTimeStamps("2022-02-02 23:59:59")
    
    // 格式化到毫秒时间戳(默认当前时间)
    AirDateTime.getMilliTimeStamps("2022-02-02 23:59:59")
    
    // 从秒时间戳格式化时间
    AirDateTime.formatFromSecond(12312314, AirDateTimeFormatter.YYYY_MM_DD_HH_mm_ss)
    
    // 从毫秒时间戳格式化时间
    AirDateTime.formatFromMilliSecond(12312311234, AirDateTimeFormatter.YYYY_MM_DD_HH_mm_ss)
    
    // 从字符串或对象格式化时间
    AirDateTime.formatFromDate("2022-02-02 23:59:59", AirDateTimeFormatter.YYYY_MM_DD_HH_mm_ss)
    
    // 格式化到友好字符串显示
    AirDateTime.getFriendlyDateTime("2022-02-02 23:59:59") // 三天前
    
  • AirDecorator 装饰器

    装饰器助手类提供了一些设置和读取配置项的方法:

    // 反射添加属性
    AirDecorator.setProperty()
    
    // 设置一个类配置项
    AirDecorator.setClassConfig()
    
    // 递归获取指定类的配置项
    AirDecorator.getClassConfig()
    
    // 设置一个字段配置项
    AirDecorator.setFieldConfig()
    
    // 获取类指定字段的指定类型的配置
    AirDecorator.getFieldConfig()
    
    // 获取类标记了装饰器的字段列表
    AirDecorator.getFieldList()
    
    // 获取目标类指定字段列表的配置项列表
    AirDecorator.getFieldConfigList()
    
    // 获取目标类上指定字段的某个配置的值
    AirDecorator.getFieldConfigValue()
  • AirFile 文件

    提供了一些常用文件处理方法

    // 字节数转可读文件大小
    AirFile.getFileSizeFriendly()
    
    // 获取静态文件的绝对地址
    AirFile.getAbsoluteFileUrl()
  • AirRand 随机生成

    提供了一些常用随机生成方法

    // 指定范围内获取随机整数
    AirRand.getRandNumber()
    
    // 获取随机数字字符串
    AirRand.getRandNumberString()
    
    // 获取随机字母字符串
    AirRand.getRandCharString()
    
    // 获取大小写混合随机字母字符串
    AirRand.getRandMixedCharString()
    
    // 获取字母加数字随机字符串
    AirRand.getRandNumberAndCharString()
    
    // 获取大小写字母加数字随机字符串
    AirRand.getRandNumberAndMixedCharString()
  • AirString 字符串常见处理

    提供了一些字符串处理的常见方法

    // 获取字符串可视化长度
    AirString.getLength()
    
    // 获取字符串可视化位置的内容
    AirString.get()
    
    // 字符串可视化截取
    AirString.slice()

三、 内置接口

  • IDictionary.ts

    定义了字典的接口标准,可通过下面的 AirDictionaryArray 提供的一些方法来创建字典并使用,可参阅 AirDictionaryArray 的部分文档

  • IEntity.ts

    定义实体标准,必须包含实体操作的唯一ID。

  • IFieldConfig.ts

    定义可扩展字段配置的接口,可自行继承后扩展。扩展方法正在开发中:)

  • IJson.ts

    提供标准JSON数据的结构,可替代 Record<string,any> 使用

  • ITree.ts

    提供了标准树结构的要素,如 parentId,children 等。如需自定义名称,可自行实现后使用别名。

四、 内置模型

  • AirModel

    AirModel 为全局模型的超类,所有模型应继承自 AirModel, 继承后默认拥有所有超类模型提供的下列方法。

    如声明了一个用户模型 UserModel

    @ClassName("用户")
    class UserModel extends AirModel{
        @FieldName("昵称")
        nickname!: string
    }
    

    UserModel 可直接调用下列静态方法

    
    // 从json强制转换到模型创建一个实例
    UserModel.fromJson(json)
    
    // 从json强制转换到模型创建一个实例的数组
    UserModel.fromJsonArray(jsonArray)
    
    // 创建一个当前类的实例 可选参数为JSON
    UserModel.newInstance() 
    
    // 创建一个当前类的实例 可选参数为JSON
    UserModel.newInstance() 
    
    // 获取类的可阅读名字
    UserModel.getClassName() // 用户
    
    // 获取属性的可阅读名字
    UserModel.getFieldName("nickname") // 昵称
    

    UserModel 创建的实例也会自带一些继承的方法:

    const user = new UserModel()
    
    // 用指定的数据对当前实例进行覆盖
    user.recoverBy(obj)
    
    // 将当前实例复制到一个新实例上
    user.copy()
    
    // 暴露部分类的字段
    user.expose()
    
    // 排除部分类的字段
    user.exclude()
    
    // 转换到JSON
    user.toJson()
  • AirDictionary

    内置的 IDictionary 实现类,如需扩展自定义字典,可分别继承 IDictionaryAirDictionary 即可。

  • AirDictionaryArray

    提供了创建和查询字典的一些方法:

    // 创建字典
    const dict = AirDictionaryArray.create([
      // ...
    ])
    
    // 创建自定义
    const dict = AirDictionaryArray.createCustom<ICustomDictionary>([
      // ...
    ])
    
    // 获取字典指定Key的Label 
    dict.getLabel()
    
    // 获取一个字典选项 
    dict.get()
    
    // 查找一个字典选项 可能找不到 
    dict.findByKey()
    
    // 查找一个字典选项 可能找不到 
    dict.findByKey()

五、 写在后面

如果有更多的需求和建议,欢迎通过本仓库的 Issues 提出,也欢迎加入 QQ群 555156313 与我们及时反馈。


ATTENTION: Contributor list is just for fun!!!

MIT License Copyright (c) 2024 Hamm.cn Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

简介

🔥🔥🔥AirPower, 一个基于TypeScript的开发工具包, 内置了数据转换、装饰器、时间日期处理、加解密与散列、文件处理、常用枚举和字典、常见数据结构处理等工具。 展开 收起
TypeScript 等 2 种语言
MIT
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
TypeScript
1
https://gitee.com/air-power/AirPower.git
git@gitee.com:air-power/AirPower.git
air-power
AirPower
AirPower
main

搜索帮助