diff --git a/CHANGELOG.md b/CHANGELOG.md index 8376b2c..fb44a92 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,21 @@ # AirPower4T 版本发布日志 +## v2.3.4 + +### 🎉 Features: + +- feat(Keys): 支持了一个键盘值枚举 +- feat(Constant): 支持了一个AirConstant静态常量类 + +### 🐞 Bug fixes: + +- fix(Constant): 使用常量替换树结构中的硬编码字符串 +- fix(Validator): 优化了验证器的类型和生成逻辑 +- fix(DateTime): 修复AirDateTime对象类型检查错误 +- fix(Table): 更新AirTable字段配置中的默认图像大小 +- fix(Entity): 简化AirEntity中的copyExposeId方法 + ## v2.3.3 ### 🎉 Features: diff --git a/base/AirEntity.ts b/base/AirEntity.ts index b8d39c4..6763320 100644 --- a/base/AirEntity.ts +++ b/base/AirEntity.ts @@ -2,6 +2,7 @@ import { Dictionary, Field, Type } from '../decorator/Custom' import { AirModel } from './AirModel' import { Table } from '../decorator/TableField' import { AirDisableDictionary } from '../model/AirDisableDictionary' +import { AirConstant } from '../config/AirConstant' /** * # 实体超类 @@ -39,28 +40,26 @@ export class AirEntity extends AirModel { } } - private static readonly ID = 'id' - /** * ## 复制一个只包含 `ID` 的实体 * @returns 仅包含ID的实体 */ copyExposeId() { return this.copy() - .expose(AirEntity.ID) + .exposeId() } /** * ## 只暴露 `ID` */ exposeId() { - return this.expose(AirEntity.ID) + return this.expose(AirConstant.ID) } /** * ## 排除 `ID` */ excludeId() { - return this.exclude(AirEntity.ID) + return this.exclude(AirConstant.ID) } } diff --git a/base/AirEnum.ts b/base/AirEnum.ts index d3d27dd..5cff617 100644 --- a/base/AirEnum.ts +++ b/base/AirEnum.ts @@ -1,3 +1,4 @@ +import { AirConstant } from '../config/AirConstant' import { AirColor } from '../enum/AirColor' import { IDictionary } from '../interface/IDictionary' import { AirDictionaryArray } from '../model/extend/AirDictionaryArray' @@ -66,7 +67,7 @@ export class AirEnum implements IDictionary { * @param key `Key` * @param defaultLabel `可选` 默认 `Label` */ - static getLabel(key: AirEnumKey, defaultLabel = '-'): string { + static getLabel(key: AirEnumKey, defaultLabel = AirConstant.HYPHEN): string { return this.get(key)?.label || defaultLabel } diff --git a/base/AirModel.ts b/base/AirModel.ts index 1d0bbdc..693499e 100644 --- a/base/AirModel.ts +++ b/base/AirModel.ts @@ -1,4 +1,5 @@ /* eslint-disable no-continue */ +import { AirConstant } from '../config/AirConstant' import { AirFormFieldConfig } from '../config/AirFormFieldConfig' import { AirSearchFieldConfig } from '../config/AirSearchFieldConfig' import { AirTableFieldConfig } from '../config/AirTableFieldConfig' @@ -105,7 +106,7 @@ export class AirModel { let fieldData = json[ (!getNoPrefix(instance, fieldKey) ? getFieldPrefix(instance) - : '' + : AirConstant.EMPTY_STRING ) + (fieldAliasName || fieldKey)] if (fieldData === undefined) { @@ -139,7 +140,7 @@ export class AirModel { (instance as IJson)[fieldKey] = fieldValueList continue } - if (defaultValue !== undefined && (fieldData === undefined || fieldData === null || fieldData === '')) { + if (defaultValue !== undefined && (fieldData === undefined || fieldData === null || fieldData === AirConstant.EMPTY_STRING)) { // 如果有默认值 则先给上默认值 (instance as IJson)[fieldKey] = defaultValue } diff --git a/config/AirApi.ts b/config/AirApi.ts index ed3f845..24f4f57 100644 --- a/config/AirApi.ts +++ b/config/AirApi.ts @@ -1,3 +1,5 @@ +import { AirConstant } from './AirConstant' + /** * # `API` 兼容类 * @author Hamm.cn @@ -10,7 +12,7 @@ export class AirApi { */ public static getStorage(key: string): string { const value = localStorage.getItem(key) - return value ? value.toString() : '' + return value ? value.toString() : AirConstant.EMPTY_STRING } /** diff --git a/config/AirConfig.ts b/config/AirConfig.ts index 0f48182..63a4d84 100644 --- a/config/AirConfig.ts +++ b/config/AirConfig.ts @@ -12,6 +12,7 @@ import { AirUserEntity } from '../model/entity/AirUserEntity' import { ClassConstructor } from '../type/ClassConstructor' import { AirCodeNumber, AirMoneyDirection } from '../type/AirType' import { AirApi } from './AirApi' +import { AirConstant } from './AirConstant' /** * # `AirPower` 全局配置 @@ -22,7 +23,7 @@ export class AirConfig { /** * ## `AirPower` 版本号 */ - static readonly version = 'v2.3.3' + static readonly version = 'v2.3.4' /** * ## `AppKey` @@ -39,7 +40,7 @@ export class AirConfig { * ## 项目名称 * 会显示在浏览器标题上 */ - static product = '' + static product = AirConstant.EMPTY_STRING /** * ## 接口根地址 @@ -309,7 +310,7 @@ export class AirConfig { * ## 默认树结构配置数据 */ static treeProps: INormalTreeProps = { - children: 'children', + children: AirConstant.CHILDREN, label: 'name', } @@ -333,7 +334,7 @@ export class AirConfig { * ## 默认的表格空数据兜底字符串 * `@Table` 装饰器中可以单独配置 `emptyValue`, */ - static tableEmptyValue = '-' + static tableEmptyValue = AirConstant.HYPHEN /** * ## 表格是否默认开启禁用和启用按钮 @@ -344,7 +345,7 @@ export class AirConfig { * ## 默认的表格数组显示分割字符 * `@Table` 装饰器中可以单独配置 `arraySplitor` */ - static arraySplitor = ',' + static arraySplitor = AirConstant.COMMA /** * ## 隐藏表格序号列 diff --git a/config/AirConstant.ts b/config/AirConstant.ts new file mode 100644 index 0000000..9aed552 --- /dev/null +++ b/config/AirConstant.ts @@ -0,0 +1,137 @@ +/** + * # `AirPower` 内置常量 + * + * @author Hamm.cn + */ +export class AirConstant { + /** + * ## `id` + */ + static readonly ID = 'id' + + /** + * ## `http://` + */ + static readonly PREFIX_HTTP = 'http://' + + /** + * ## `https://` + */ + static readonly PREFIX_HTTPS = 'https://' + + /** + * ## 空字符串 + */ + static readonly EMPTY_STRING = '' + + /** + * ## `Content-Type` + */ + static readonly CONTENT_TYPE = 'Content-Type' + + /** + * ## 半角问号 `?` + */ + static readonly QUESTION_MARK = '?' + + /** + * ## 连接符号 `&` + */ + static readonly AND_MARK = '&' + + /** + * ## `AirModel` + */ + static readonly AIR_MODEL = 'AirModel' + + /** + * ## 下划线 `_` + */ + static readonly UNDER_LINE = '_' + + /** + * ## 默认进制 + */ + static readonly DEFAULT_RADIX = 10 + + /** + * ## `.` 点 + */ + static readonly DOT = '.' + + /** + * ## `children` + */ + static readonly CHILDREN = 'children' + + /** + * ## `'0'` + */ + static readonly ZERO_STRING = '0' + + /** + * ## 半角逗号 `,` + */ + static readonly COMMA = ',' + + /** + * ## 横线 `-` + */ + static readonly HYPHEN = '-' + + /** + * ## 时间进制 + */ + static readonly TIME_RADIX = 60 + + /** + * ## 千 + */ + static readonly THOUSAND = 1000 + + /** + * ## 1024 + * 😄 + */ + static readonly ONE_ZERO_TWO_FOUR = 1024 + + /** + * ## 每月最大天数 + */ + static readonly DAY_OF_MONTH = 31 + + /** + * ## 每年月份 + */ + static readonly MONTH_OF_YEAR = 12 + + /** + * ## 每年天数 + */ + static readonly DAY_OF_YEAR = 365 + + /** + * ## 每周天数 + */ + static readonly DAY_OF_WEEK = 7 + + /** + * ## 每年平均周 + */ + static readonly WEEK_OF_YEAR = 52 + + /** + * ## 每月平均周 + */ + static readonly WEEK_OF_MONTH = 4 + + /** + * ## 每天秒数 + */ + static readonly SECONDS_OF_DAY = 86400 + + /** + * ## 一世纪年数 + */ + static readonly YEARS_OF_CENTURY = 100 +} diff --git a/config/AirGlobal.ts b/config/AirGlobal.ts index f44bdf0..7023ca4 100644 --- a/config/AirGlobal.ts +++ b/config/AirGlobal.ts @@ -1,6 +1,7 @@ import { AirConfig } from './AirConfig' import { IJson } from '../interface/IJson' import { AirStore } from '../store/AirStore' +import { AirKeys } from '../enum/AirKeys' /** * # 一些全局使用的扩展方法 @@ -22,26 +23,29 @@ Window.prototype.airConfig = () => { // eslint-disable-next-line no-console console.log(airConfig) } + +const CONTROL_KEYS: string[] = [AirKeys.META, AirKeys.ALT] + let controlKeyDownTimer: number document.onkeydown = (e: KeyboardEvent) => { - if (e.key === 'Meta' || e.key === 'Alt') { + if (CONTROL_KEYS.includes(e.key)) { clearTimeout(controlKeyDownTimer) AirStore().controlKeyDown = true controlKeyDownTimer = setTimeout(() => { AirStore().controlKeyDown = false }, 5000) } - if (e.key === 'Escape') { + if (e.key === AirKeys.ESC) { AirStore().escKeyDown = true } } document.onkeyup = (e: KeyboardEvent) => { - if (e.key === 'Meta' || e.key === 'Alt') { + if (CONTROL_KEYS.includes(e.key)) { AirStore().controlKeyDown = false clearTimeout(controlKeyDownTimer) } - if (e.key === 'Escape') { + if (e.key === AirKeys.ESC) { AirStore().escKeyDown = false } } diff --git a/config/AirTableFieldConfig.ts b/config/AirTableFieldConfig.ts index 32cceac..5f74a3c 100644 --- a/config/AirTableFieldConfig.ts +++ b/config/AirTableFieldConfig.ts @@ -46,9 +46,9 @@ export class AirTableFieldConfig extends AirFieldConfig implements ITableFieldCo image = false - imageWidth = 60 + imageWidth = 30 - imageHeight = 60 + imageHeight = 30 imageRadius = '10px' diff --git a/decorator/Custom.ts b/decorator/Custom.ts index 4a56254..9f3b41a 100644 --- a/decorator/Custom.ts +++ b/decorator/Custom.ts @@ -4,6 +4,7 @@ */ import { AirEnum } from '../base/AirEnum' import { AirModel } from '../base/AirModel' +import { AirConstant } from '../config/AirConstant' import { AirDecorator } from '../helper/AirDecorator' import { IJson } from '../interface/IJson' import { AirDictionaryArray } from '../model/extend/AirDictionaryArray' @@ -247,7 +248,7 @@ export function FieldPrefix(prefix: string) { * @param target 目标类 */ export function getFieldPrefix(target: AirDecoratorTarget): string { - return AirDecorator.getClassConfig(target, FIELD_PREFIX_KEY) || '' + return AirDecorator.getClassConfig(target, FIELD_PREFIX_KEY) || AirConstant.EMPTY_STRING } /** @@ -269,5 +270,5 @@ export function Alias(alias: string) { * @param key 属性名 */ export function getAlias(target: AirDecoratorTarget, key: string): string { - return AirDecorator.getFieldConfig(target, key, ALIAS_KEY) || '' + return AirDecorator.getFieldConfig(target, key, ALIAS_KEY) || AirConstant.EMPTY_STRING } diff --git a/enum/AirKeys.ts b/enum/AirKeys.ts new file mode 100644 index 0000000..502de16 --- /dev/null +++ b/enum/AirKeys.ts @@ -0,0 +1,10 @@ +/* eslint-disable no-unused-vars */ +/** + * # 常见键盘值 + * @author Hamm.cn + */ +export enum AirKeys { + META = 'Meta', + ALT = 'Alt', + ESC = 'Escape' +} diff --git a/feedback/AirAlert.ts b/feedback/AirAlert.ts index 44cb917..6dcbc00 100644 --- a/feedback/AirAlert.ts +++ b/feedback/AirAlert.ts @@ -2,6 +2,7 @@ import { ElMessageBox, ElMessageBoxOptions } from 'element-plus' import { CSSProperties } from 'vue' import { AirFeedbackType } from '../enum/AirFeedbackType' import { AirI18n } from '../helper/AirI18n' +import { AirConstant } from '../config/AirConstant' /** * # 消息弹窗类 @@ -53,17 +54,17 @@ export class AirAlert { /** * ## 弹窗宽度 */ - protected width = '' + protected width = AirConstant.EMPTY_STRING /** * ## 弹窗高度 */ - protected height = '' + protected height = AirConstant.EMPTY_STRING /** * ## 确认按钮样式类名 */ - protected confirmButtonClass = '' + protected confirmButtonClass = AirConstant.EMPTY_STRING /** * ## 设置确认按钮文字 @@ -282,7 +283,7 @@ export class AirAlert { type: this.confirmButtonClass ? AirFeedbackType.NONE : this.icon, draggable: true, dangerouslyUseHTMLString: this.isHtmlEnabled, - customClass: this.isHtmlEnabled ? 'rich-text' : '', + customClass: this.isHtmlEnabled ? 'rich-text' : AirConstant.EMPTY_STRING, customStyle, showClose: this.isCloseButtonShow, closeOnClickModal: this.isCloseByCover, diff --git a/helper/AirDateTime.ts b/helper/AirDateTime.ts index 38467e8..93f799b 100644 --- a/helper/AirDateTime.ts +++ b/helper/AirDateTime.ts @@ -1,4 +1,5 @@ import { AirConfig } from '../config/AirConfig' +import { AirConstant } from '../config/AirConstant' import { AirDateTimeFormatter } from '../enum/AirDateTimeFormatter' import { IJson } from '../interface/IJson' @@ -25,7 +26,7 @@ export class AirDateTime { * @param date `可选` Date对象/时间字符串 (默认当前时间) */ static getUnixTimeStamps(date?: Date | string): number { - return Math.round(this.getMilliTimeStamps(date) / 1000) + return Math.round(this.getMilliTimeStamps(date) / AirConstant.THOUSAND) } /** @@ -36,7 +37,7 @@ export class AirDateTime { if (!date) { return new Date().valueOf() } - if (typeof data === 'object') { + if (typeof date === 'object') { return date.valueOf() } return new Date(date).valueOf() @@ -48,7 +49,7 @@ export class AirDateTime { * @param formatString `可选` 格式化模板 默认为`AirConfig.dateTimeFormatter` */ static formatFromSecond(timeStamp: number, formatString?: AirDateTimeFormatter | string): string { - return this.formatFromDate(new Date(timeStamp * 1000), formatString) + return this.formatFromDate(new Date(timeStamp * AirConstant.THOUSAND), formatString) } /** @@ -96,59 +97,57 @@ export class AirDateTime { const nowTimeStamps: number = this.getUnixTimeStamps(new Date()) let oldTimeStamp: number if (typeof date === 'number') { - oldTimeStamp = parseInt((date / 1000).toString(), 10) + oldTimeStamp = parseInt((date / AirConstant.THOUSAND).toString(), 10) } else { oldTimeStamp = this.getUnixTimeStamps(date) } const diffTimeStamp = Math.abs(nowTimeStamps - oldTimeStamp) + const secondOfYear = AirConstant.SECONDS_OF_DAY * AirConstant.DAY_OF_YEAR + const secondOfMonth = AirConstant.SECONDS_OF_DAY * AirConstant.DAY_OF_MONTH + const secondOfWeek = AirConstant.SECONDS_OF_DAY * AirConstant.DAY_OF_WEEK + const secondOfHour = AirConstant.TIME_RADIX * AirConstant.TIME_RADIX if (oldTimeStamp > nowTimeStamps) { // after - if (diffTimeStamp > 86400 * 36500) { - return `${Math.floor(diffTimeStamp / 86400 / 100 / 31)}世纪后` + if (diffTimeStamp > secondOfYear) { + return `${Math.floor(diffTimeStamp / secondOfYear)}年后` } - if (diffTimeStamp > 86400 * 365) { - return `${Math.floor(diffTimeStamp / 86400 / 365)}年后` + if (diffTimeStamp > secondOfMonth) { + return `${Math.floor(diffTimeStamp / secondOfMonth)}月后` } - if (diffTimeStamp > 86400 * 31) { - return `${Math.floor(diffTimeStamp / 86400 / 31)}月后` + if (diffTimeStamp > secondOfWeek) { + return `${Math.floor(diffTimeStamp / secondOfWeek)}周后` } - if (diffTimeStamp > 86400 * 7) { - return `${Math.floor(diffTimeStamp / 86400 / 7)}周后` + if (diffTimeStamp > AirConstant.SECONDS_OF_DAY) { + return `${Math.floor(diffTimeStamp / AirConstant.SECONDS_OF_DAY)}天后` } - if (diffTimeStamp > 86400) { - return `${Math.floor(diffTimeStamp / 86400)}天后` + if (diffTimeStamp > secondOfHour) { + return `${Math.floor(diffTimeStamp / secondOfHour)}小时后` } - if (diffTimeStamp > 3600) { - return `${Math.floor(diffTimeStamp / 3600)}小时后` - } - if (diffTimeStamp > 60) { - return `${Math.floor(diffTimeStamp / 60)}分钟后` + if (diffTimeStamp > AirConstant.TIME_RADIX) { + return `${Math.floor(diffTimeStamp / AirConstant.TIME_RADIX)}分钟后` } if (diffTimeStamp > 0) { return `${diffTimeStamp}秒后` } } else { // before - if (diffTimeStamp > 86400 * 36500) { - return `${Math.floor(diffTimeStamp / 86400 / 100 / 365)}世纪前` - } - if (diffTimeStamp > 86400 * 365) { - return `${Math.floor(diffTimeStamp / 86400 / 365)}年前` + if (diffTimeStamp > secondOfYear) { + return `${Math.floor(diffTimeStamp / secondOfYear)}年前` } - if (diffTimeStamp > 86400 * 30) { - return `${Math.floor(diffTimeStamp / 86400 / 30)}月前` + if (diffTimeStamp > secondOfMonth) { + return `${Math.floor(diffTimeStamp / secondOfMonth)}月前` } - if (diffTimeStamp > 86400 * 7) { - return `${Math.floor(diffTimeStamp / 86400 / 7)}周前` + if (diffTimeStamp > secondOfWeek) { + return `${Math.floor(diffTimeStamp / secondOfWeek)}周前` } - if (diffTimeStamp > 86400) { - return `${Math.floor(diffTimeStamp / 86400)}天前` + if (diffTimeStamp > AirConstant.SECONDS_OF_DAY) { + return `${Math.floor(diffTimeStamp / AirConstant.SECONDS_OF_DAY)}天前` } - if (diffTimeStamp > 3600) { - return `${Math.floor(diffTimeStamp / 3600)}小时前` + if (diffTimeStamp > secondOfHour) { + return `${Math.floor(diffTimeStamp / secondOfHour)}小时前` } - if (diffTimeStamp > 60) { - return `${Math.floor(diffTimeStamp / 60)}分钟前` + if (diffTimeStamp > AirConstant.TIME_RADIX) { + return `${Math.floor(diffTimeStamp / AirConstant.TIME_RADIX)}分钟前` } if (diffTimeStamp >= 0) { return '刚刚' diff --git a/helper/AirDecorator.ts b/helper/AirDecorator.ts index 3bcef9b..dceadc7 100644 --- a/helper/AirDecorator.ts +++ b/helper/AirDecorator.ts @@ -5,6 +5,7 @@ import { AirClassTransformer } from './AirClassTransformer' import { AirDictionaryArray } from '../model/extend/AirDictionaryArray' import { AirDecoratorData, AirDecoratorTarget, AirEnumKey } from '../type/AirType' import { AirEnum } from '../base/AirEnum' +import { AirConstant } from '../config/AirConstant' /** * # 装饰器助手类 @@ -65,7 +66,7 @@ export class AirDecorator { return classConfig } const superClass = Reflect.getPrototypeOf(target) - if (!superClass || superClass.constructor.name === 'AirModel') { + if (!superClass || superClass.constructor.name === AirConstant.AIR_MODEL) { return undefined } return this.getClassConfig(superClass, classConfigKey) @@ -74,7 +75,7 @@ export class AirDecorator { classConfig = classConfig || {} // 对象配置 const superClass = Reflect.getPrototypeOf(target) - if (!superClass || superClass.constructor.name === 'AirModel') { + if (!superClass || superClass.constructor.name === AirConstant.AIR_MODEL) { return defaultValue } @@ -127,7 +128,7 @@ export class AirDecorator { } // 没有查询到配置 const superClass = Reflect.getPrototypeOf(target) - if (!superClass || superClass.constructor.name === 'AirModel') { + if (!superClass || superClass.constructor.name === AirConstant.AIR_MODEL) { return undefined } return this.getFieldConfig(superClass, key, fieldConfigKey) @@ -137,7 +138,7 @@ export class AirDecorator { fieldConfig = fieldConfig || {} // 没有查询到配置 const superClass = Reflect.getPrototypeOf(target) - if (!superClass || superClass.constructor.name === 'AirModel') { + if (!superClass || superClass.constructor.name === AirConstant.AIR_MODEL) { return {} } return { ...this.getFieldConfig(superClass, key, fieldConfigKey, true), ...fieldConfig } @@ -153,7 +154,7 @@ export class AirDecorator { const fieldList: string[] = Reflect.get(target, fieldConfigKey) || [] fieldList.forEach((item) => list.includes(item) || list.push(item)) const superClass = Reflect.getPrototypeOf(target) - if (!superClass || superClass.constructor.name === 'AirModel') { + if (!superClass || superClass.constructor.name === AirConstant.AIR_MODEL) { return list } return this.getFieldList(superClass, fieldConfigKey, list) @@ -215,7 +216,7 @@ export class AirDecorator { return fieldConfig[configKey] } const superClass = Object.getPrototypeOf(target) - if (!superClass || superClass.constructor.name === 'AirModel') { + if (!superClass || superClass.constructor.name === AirConstant.AIR_MODEL) { return undefined } return this.getFieldConfigValue(superClass, fieldConfigKey, key, configKey) diff --git a/helper/AirDialog.ts b/helper/AirDialog.ts index 7584e38..e242fd8 100644 --- a/helper/AirDialog.ts +++ b/helper/AirDialog.ts @@ -10,6 +10,7 @@ import { IFile } from '../interface/IFile' import { AirEntity } from '../base/AirEntity' import { IJson } from '../interface/IJson' import { AirStore } from '../store/AirStore' +import { AirConstant } from '../config/AirConstant' /** * # 弹窗助手类 @@ -34,7 +35,7 @@ export class AirDialog { static async build(view: Component, param: IJson): Promise { const parentNode = document.createElement('div') const domId = `dialog_${Math.random()}` - parentNode.setAttribute('id', domId) + parentNode.setAttribute(AirConstant.ID, domId) let app: App | undefined // 卸载dom的方法 diff --git a/helper/AirFile.ts b/helper/AirFile.ts index 57a6ad1..dba66ce 100644 --- a/helper/AirFile.ts +++ b/helper/AirFile.ts @@ -1,4 +1,5 @@ import { AirConfig } from '../config/AirConfig' +import { AirConstant } from '../config/AirConstant' import { AirI18n } from './AirI18n' /** @@ -6,11 +7,6 @@ import { AirI18n } from './AirI18n' * @author Hamm.cn */ export class AirFile { - /** - * ## 文件大小计算常量 - */ - static readonly FILE_SIZE_CALCULATION_CONSTANT = 1024 - /** * ## 文件单位列表 */ @@ -26,8 +22,8 @@ export class AirFile { return AirI18n.get().FileUnknownSize || '未知大小' } for (let i = 0; i < this.FILE_UNIT_LIST.length; i += 1) { - if (size < this.FILE_SIZE_CALCULATION_CONSTANT ** (i + 1)) { - return `${(size / (this.FILE_SIZE_CALCULATION_CONSTANT ** i)).toFixed(fractionDigits)}${this.FILE_UNIT_LIST[i]}` + if (size < AirConstant.ONE_ZERO_TWO_FOUR ** (i + 1)) { + return `${(size / (AirConstant.ONE_ZERO_TWO_FOUR ** i)).toFixed(fractionDigits)}${this.FILE_UNIT_LIST[i]}` } } return AirI18n.get().FileTooLarge || '文件过大' @@ -41,7 +37,7 @@ export class AirFile { if (!url) { return '' } - if (url.includes('https://') || url.includes('http://')) { + if (url.includes(AirConstant.PREFIX_HTTP) || url.includes(AirConstant.PREFIX_HTTPS)) { return url } return AirConfig.staticUrl + url diff --git a/helper/AirHttp.ts b/helper/AirHttp.ts index 5a62230..76abc83 100644 --- a/helper/AirHttp.ts +++ b/helper/AirHttp.ts @@ -9,6 +9,7 @@ import { IJson } from '../interface/IJson' import { AirAlert } from '../feedback/AirAlert' import { AirI18n } from './AirI18n' import { AirAny } from '../type/AirType' +import { AirConstant } from '../config/AirConstant' /** * # 网络请求类 @@ -18,7 +19,7 @@ export class AirHttp { /** * ## 访问的接口 `URL` */ - private url = '' + private url = AirConstant.EMPTY_STRING /** * ## `Loading` @@ -72,11 +73,10 @@ export class AirHttp { } // 初始化一些默认值 this.axiosRequestConfig.method = AirHttpMethod.POST - this.axiosRequestConfig.baseURL = this.url.indexOf('http://') === 0 || this.url.indexOf('https://') === 0 ? '' : AirConfig.apiUrl + this.axiosRequestConfig.baseURL = this.url.indexOf(AirConstant.PREFIX_HTTP) === 0 || this.url.indexOf(AirConstant.PREFIX_HTTPS) === 0 ? AirConstant.EMPTY_STRING : AirConfig.apiUrl this.axiosRequestConfig.timeout = this.timeout - this.axiosRequestConfig.headers = { - 'content-type': AirHttpContentType.JSON, - } + this.axiosRequestConfig.headers = {} + this.axiosRequestConfig.headers[AirConstant.CONTENT_TYPE] = AirHttpContentType.JSON const accessToken = AirConfig.getAccessToken() if (accessToken) { this.axiosRequestConfig.headers[AirConfig.authorizationHeaderKey] = accessToken @@ -147,7 +147,7 @@ export class AirHttp { * @param contentType `content-type` */ setContentType(contentType: AirHttpContentType): this { - return this.addHttpHeader('Content-Type', contentType) + return this.addHttpHeader(AirConstant.CONTENT_TYPE, contentType) } /** @@ -302,10 +302,10 @@ export class AirHttp { for (const key in params) { queryArray.push(`${key}=${encodeURIComponent(params[key])}`) } - if (this.url.includes('?')) { - this.url += `&${queryArray.join('&')}` + if (this.url.includes(AirConstant.QUESTION_MARK)) { + this.url += `&${queryArray.join(AirConstant.AND_MARK)}` } else { - this.url += `?${queryArray.join('&')}` + this.url += `?${queryArray.join(AirConstant.AND_MARK)}` } } this.setHttpMethod(AirHttpMethod.GET) diff --git a/helper/AirPermission.ts b/helper/AirPermission.ts index 6ee3318..f9f3b72 100644 --- a/helper/AirPermission.ts +++ b/helper/AirPermission.ts @@ -3,17 +3,13 @@ import { getEntityConfig } from '../decorator/EntityConfig' import { AirConfig } from '../config/AirConfig' import { AirEntity } from '../base/AirEntity' import { ClassConstructor } from '../type/ClassConstructor' +import { AirConstant } from '../config/AirConstant' /** * # 权限标识处理类 * @author Hamm.cn */ export class AirPermission { - /** - * ## 下划线 - */ - private static readonly UNDER_LINE = '_' - /** * ## 获取指定实体类在某个场景的权限标识字符串 * @param EntityClass 实体类 @@ -21,25 +17,25 @@ export class AirPermission { */ static getPermission(EntityClass: ClassConstructor | null | undefined, action: AirPermissionAction): string { if (!EntityClass) { - return '' + return AirConstant.EMPTY_STRING } const entityConfig = getEntityConfig(new EntityClass()) if (!entityConfig) { - return '' + return AirConstant.EMPTY_STRING } if (AirConfig.autoPermission) { // 自动处理权限 if (!entityConfig.permissionPrefix) { // 没有配置前缀 从类中获取权限前缀 - const entityName = EntityClass.name.replace('Entity', '') + const entityName = EntityClass.name.replace('Entity', AirConstant.EMPTY_STRING) .toString() entityConfig.permissionPrefix = entityName.slice(0, 1) + entityName.slice(1) } } else { // 如不自动配置权限, 则将权限前缀清空 - entityConfig.permissionPrefix = '' + entityConfig.permissionPrefix = AirConstant.EMPTY_STRING } - const permissionPrefix = entityConfig.permissionPrefix + this.UNDER_LINE + const permissionPrefix = entityConfig.permissionPrefix + AirConstant.UNDER_LINE switch (action) { case AirPermissionAction.ADD: @@ -58,7 +54,7 @@ export class AirPermission { return permissionPrefix + this.getAutoPermissionFlag(entityConfig.importPermission, action) default: } - return '' + return AirConstant.EMPTY_STRING } /** @@ -71,6 +67,6 @@ export class AirPermission { if (AirConfig.autoPermission) { return permission || action } - return permission || '' + return permission || AirConstant.EMPTY_STRING } } diff --git a/helper/AirRand.ts b/helper/AirRand.ts index cd5d325..7355994 100644 --- a/helper/AirRand.ts +++ b/helper/AirRand.ts @@ -1,3 +1,5 @@ +import { AirConstant } from '../config/AirConstant' + /** * # 随机生成数据助手 * @author Hamm.cn @@ -18,18 +20,13 @@ export class AirRand { */ private static readonly STRING_OF_UPPER_CHAR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' - /** - * ## 默认的进制 - */ - private static readonly DEFAULT_RADIX = 10 - /** * ## 指定范围内获取随机整数 * @param min 最小 * @param max 最大 */ static getRandNumber(min: number, max: number): number { - return parseInt((min + Math.random() * (max - min)).toString(), this.DEFAULT_RADIX) + return parseInt((min + Math.random() * (max - min)).toString(), AirConstant.DEFAULT_RADIX) } /** @@ -37,9 +34,9 @@ export class AirRand { * @param length `可选` 长度 `默认6位` */ static getRandNumberString(length = 6): string { - let str = '' + let str = AirConstant.EMPTY_STRING for (let i = 0; i < length; i += 1) { - str += this.STRING_OF_NUMBER[parseInt((Math.random() * this.STRING_OF_NUMBER.length).toString(), this.DEFAULT_RADIX)] + str += this.STRING_OF_NUMBER[parseInt((Math.random() * this.STRING_OF_NUMBER.length).toString(), AirConstant.DEFAULT_RADIX)] } return str } @@ -50,9 +47,9 @@ export class AirRand { * @param isUpper `可选` 是否大写 `默认小写` */ static getRandCharString(length = 32, isUpper = false): string { - let str = '' + let str = AirConstant.EMPTY_STRING for (let i = 0; i < length; i += 1) { - str += this.STRING_OF_LOWER_CHAR[parseInt((Math.random() * this.STRING_OF_LOWER_CHAR.length).toString(), this.DEFAULT_RADIX)] + str += this.STRING_OF_LOWER_CHAR[parseInt((Math.random() * this.STRING_OF_LOWER_CHAR.length).toString(), AirConstant.DEFAULT_RADIX)] } return isUpper ? str.toLocaleUpperCase() : str } @@ -62,10 +59,10 @@ export class AirRand { * @param length `可选` 长度 `默认32位` */ static getRandMixedCharString(length = 32): string { - let str = '' + let str = AirConstant.EMPTY_STRING const strStorage = this.STRING_OF_LOWER_CHAR + this.STRING_OF_UPPER_CHAR for (let i = 0; i < length; i += 1) { - str += strStorage[parseInt((Math.random() * strStorage.length).toString(), this.DEFAULT_RADIX)] + str += strStorage[parseInt((Math.random() * strStorage.length).toString(), AirConstant.DEFAULT_RADIX)] } return str } @@ -76,10 +73,10 @@ export class AirRand { * @param isUpper `可选` 是否大写 `默认false` */ static getRandNumberAndCharString(length = 32, isUpper = false): string { - let str = '' + let str = AirConstant.EMPTY_STRING const strStorage = this.STRING_OF_LOWER_CHAR + this.STRING_OF_NUMBER for (let i = 0; i < length; i += 1) { - str += strStorage[parseInt((Math.random() * strStorage.length).toString(), this.DEFAULT_RADIX)] + str += strStorage[parseInt((Math.random() * strStorage.length).toString(), AirConstant.DEFAULT_RADIX)] } return isUpper ? str.toLocaleUpperCase() : str } @@ -89,10 +86,10 @@ export class AirRand { * @param length `可选` 长度 `默认32位` */ static getRandNumberAndMixedCharString(length = 32): string { - let str = '' + let str = AirConstant.EMPTY_STRING const strStorage = this.STRING_OF_LOWER_CHAR + this.STRING_OF_NUMBER + this.STRING_OF_UPPER_CHAR for (let i = 0; i < length; i += 1) { - str += strStorage[parseInt((Math.random() * strStorage.length).toString(), this.DEFAULT_RADIX)] + str += strStorage[parseInt((Math.random() * strStorage.length).toString(), AirConstant.DEFAULT_RADIX)] } return str } @@ -104,7 +101,7 @@ export class AirRand { static getRandColor() { return `#${Math.random() .toString(16) - .padEnd(6, '0') + .padEnd(6, AirConstant.ZERO_STRING) .slice(2, 8)}` } } diff --git a/helper/AirString.ts b/helper/AirString.ts index 1ffe410..f4169a7 100644 --- a/helper/AirString.ts +++ b/helper/AirString.ts @@ -1,3 +1,5 @@ +import { AirConstant } from '../config/AirConstant' + /** * # 字符串处理工具类 * @author Hamm.cn @@ -50,7 +52,7 @@ export class AirString { * @param to 截取结束位置 */ static slice(str: string, from = 0, to = this.getLength(str) - 1): string { - let s = '' + let s = AirConstant.EMPTY_STRING if (from < 0) { throw new Error('AirString.get() Error: from error') } diff --git a/helper/AirTree.ts b/helper/AirTree.ts index f97eea3..ba73e1b 100644 --- a/helper/AirTree.ts +++ b/helper/AirTree.ts @@ -1,4 +1,5 @@ -import { ITree } from '@/airpower/interface/ITree' +import { AirConstant } from '../config/AirConstant' +import { ITree } from '../interface/ITree' /** * # 树结构工具类 @@ -27,7 +28,7 @@ export class AirTree { static treeList2List(treeList: E[]): E[] { const list: E[] = [] treeList.forEach((item) => { - const i = item.copy().exclude('children') + const i = item.copy().exclude(AirConstant.CHILDREN) list.push(i) if (item.children && item.children.length > 0) { list.push(...this.treeList2List(item.children)) diff --git a/helper/AirValidator.ts b/helper/AirValidator.ts index 6bc8d22..51032d3 100644 --- a/helper/AirValidator.ts +++ b/helper/AirValidator.ts @@ -6,18 +6,16 @@ import { AirEntity } from '../base/AirEntity' import { AirAbstractEntityService } from '../base/AirAbstractEntityService' import { AirI18n } from './AirI18n' import { IJson } from '../interface/IJson' -import { AirAny, AirValidatorCallback, AirValidatorRule } from '../type/AirType' +import { + AirAny, AirValidatorCallback, AirValidatorRule, AirValidatorTrigger, AirValidatorType, +} from '../type/AirType' +import { AirConstant } from '../config/AirConstant' /** * # 表单验证工具 * @author Hamm.cn * */ export class AirValidator { - /** - * ## 默认的进制 - */ - private static readonly DEFAULT_RADIX = 10 - /** * ## 错误提醒 * 请通过 `.show()` 传入 @@ -28,13 +26,13 @@ export class AirValidator { * ## 类型 * 可通过 `toString` `toNumber` `toArray` 设置 (默认`string`) */ - private type!: string + private type!: AirValidatorType /** * ## 触发方式 * 不建议直接设置哦~ (默认blur) */ - private trigger: 'blur' | 'change' = 'change' + private trigger: AirValidatorTrigger = 'change' /** * ## 是否必填 @@ -165,21 +163,21 @@ export class AirValidator { return false } - const year = parseInt(str.substring(6), this.DEFAULT_RADIX) + const year = parseInt(str.substring(6), AirConstant.DEFAULT_RADIX) if (year > new Date().getFullYear() || year < 1900) { return false } - const month = parseInt(str.substring(10, 12), this.DEFAULT_RADIX) + const month = parseInt(str.substring(10, 12), AirConstant.DEFAULT_RADIX) if (month > 12 || month < 1) { return false } - const day = parseInt(str.substring(12, 14), this.DEFAULT_RADIX) + const day = parseInt(str.substring(12, 14), AirConstant.DEFAULT_RADIX) if (day > 31 || month < 1) { return false } let sum = 0 for (let i = 0; i < 17; i += 1) { - sum += parseInt(str[i], this.DEFAULT_RADIX) * (validArray[0][i] as number) + sum += parseInt(str[i], AirConstant.DEFAULT_RADIX) * (validArray[0][i] as number) } // eslint-disable-next-line eqeqeq return validArray[1][(sum % 11)] == str[17] @@ -191,7 +189,7 @@ export class AirValidator { * @param list 验证器 */ static validate(str: string, ...list: AirInputType[]) { - let regString = '' + let regString = AirConstant.EMPTY_STRING for (let i = 0; i < list.length; i += 1) { regString += list[i] } @@ -212,6 +210,15 @@ export class AirValidator { return rule } + /** + * ## 获取一个验证器 + * @param configValue 验证器配置的值 + * @returns + */ + private static getValidator(configValue: string | boolean): AirValidator { + return AirValidator.show(typeof configValue === 'string' ? configValue : AirConstant.EMPTY_STRING) + } + /** * ## 创建验证器 * @param form 表单对象 @@ -229,21 +236,16 @@ export class AirValidator { formRules[fieldKey] = [] } if (config.requiredString) { - (formRules[fieldKey]).push(AirValidator.show(typeof config.requiredString === 'string' ? config.requiredString : '') - .ifEmpty()) + (formRules[fieldKey]).push(this.getValidator(config.requiredString).ifEmpty()) } if (config.requiredNumber) { - (formRules[fieldKey]).push(AirValidator.show(typeof config.requiredNumber === 'string' ? config.requiredNumber : '') - .toNumber() - .ifEmpty()) + (formRules[fieldKey]).push(this.getValidator(config.requiredNumber).toNumber().ifEmpty()) } if (config.requiredPayload) { - (formRules[fieldKey]).push(AirValidator.show(typeof config.requiredPayload === 'string' ? config.requiredPayload : '') - .ifPayloadEmpty()) + (formRules[fieldKey]).push(this.getValidator(config.requiredPayload).ifPayloadEmpty()) } if (config.minLength) { - (formRules[fieldKey]).push(AirValidator.show() - .ifLengthLessThan(config.minLength)) + (formRules[fieldKey]).push(AirValidator.show().ifLengthLessThan(config.minLength)) } if (config.number) { if (config.min) { @@ -256,27 +258,22 @@ export class AirValidator { } } if (config.chinese) { - (formRules[fieldKey]).push(AirValidator.show(typeof config.chinese === 'string' ? config.chinese : '') - .ifNotChinese()) + (formRules[fieldKey]).push(this.getValidator(config.chinese).ifNotChinese()) } if (config.telPhone) { - (formRules[fieldKey]).push(AirValidator.show(typeof config.telPhone === 'string' ? config.telPhone : '') - .ifNotTelPhone()) + (formRules[fieldKey]).push(this.getValidator(config.telPhone).ifNotTelPhone()) } if (config.mobilePhone) { - (formRules[fieldKey]).push(AirValidator.show(typeof config.mobilePhone === 'string' ? config.mobilePhone : '') - .ifNotMobilePhone()) + (formRules[fieldKey]).push(this.getValidator(config.mobilePhone).ifNotMobilePhone()) } if (config.phone) { - (formRules[fieldKey]).push(AirValidator.show(typeof config.phone === 'string' ? config.phone : '') - .ifNotPhone()) + (formRules[fieldKey]).push(this.getValidator(config.phone).ifNotPhone()) } if (config.email) { - (formRules[fieldKey]).push(AirValidator.show(typeof config.email === 'string' ? config.email : '') - .ifNotEmail()) + (formRules[fieldKey]).push(this.getValidator(config.email).ifNotEmail()) } if (config.regExp) { - (formRules[fieldKey]).push(AirValidator.show('') + (formRules[fieldKey]).push(AirValidator.show(AirConstant.EMPTY_STRING) .ifNotTest(config.regExp)) } } @@ -494,20 +491,20 @@ export class AirValidator { * @param whats 字符串数组 */ ifContain(...whats: string[]): this { - let error = '' + let error = AirConstant.EMPTY_STRING this.validator = (_: AirValidatorRule, value: string, callback: AirValidatorCallback) => { if (!value) { callback() return } for (const what of whats) { - error = '' + error = AirConstant.EMPTY_STRING if (value.indexOf(what) >= 0) { error = what break } } - if (error !== '') { + if (error !== AirConstant.EMPTY_STRING) { callback(this.message || `不允许输入中包含 ${error} `) } else { callback() diff --git a/helper/AirVersion.ts b/helper/AirVersion.ts index 794ff44..edb64ec 100644 --- a/helper/AirVersion.ts +++ b/helper/AirVersion.ts @@ -1,6 +1,7 @@ /* eslint-disable no-console */ import ElementPlus from 'element-plus' import { AirAlert } from '../feedback/AirAlert' +import { AirConstant } from '../config/AirConstant' /** * # 版本工具类 @@ -12,6 +13,11 @@ export class AirVersion { */ private static readonly elementPlusRequired = '2.8.0' + /** + * ## 版本号长度 + */ + private static readonly VERSION_LENGTH = 2 + /** * ## 检查 `Element Plus` */ @@ -40,10 +46,10 @@ export class AirVersion { * @param padding `可选` 填充位数 默认 `2` * @returns 版本号数字 */ - static parseVersion(version: string, splitor = '.', padding = 2): number { + static parseVersion(version: string, splitor = AirConstant.DOT, padding = this.VERSION_LENGTH): number { return parseInt(version.split(splitor) - .map((item) => item.padStart(padding, '0')) - .join(''), 10) + .map((item) => item.padStart(padding, AirConstant.ZERO_STRING)) + .join(AirConstant.EMPTY_STRING), 10) } /** @@ -53,7 +59,7 @@ export class AirVersion { * @param padding `可选` 填充位数 默认 `2` * @returns 版本号字符串 */ - static formatVersion(version: number, splitor = '.', padding = 2): string { + static formatVersion(version: number, splitor = AirConstant.DOT, padding = this.VERSION_LENGTH): string { const major = Math.floor(version / (10 ** padding ** padding)) const minor = Math.floor(version % (10 ** padding ** padding)) / (10 ** padding) return [major, minor].join(splitor) diff --git a/index.ts b/index.ts index 0c91b54..135866d 100644 --- a/index.ts +++ b/index.ts @@ -49,8 +49,8 @@ console.clear() console.log( `%c©%cAirPower%c4T%c${AirConfig.version}%c\n已支持: Web、微信小程序、uniapp\n\n%c🔥🔥🔥AirPower系列开源项目推荐\n -%c基础脚手架: https://github.com/HammCn/AirPower -%c后端(Java): https://github.com/HammCn/AirPower4J +%c前端: https://github.com/HammCn/AirPower4T +%c后端: https://github.com/HammCn/AirPower4J `, `padding:20px 0px 0px 0px; font-size:24px;font-weight:bold; diff --git a/model/extend/AirDictionaryArray.ts b/model/extend/AirDictionaryArray.ts index c668c5a..e9af516 100644 --- a/model/extend/AirDictionaryArray.ts +++ b/model/extend/AirDictionaryArray.ts @@ -2,6 +2,7 @@ import { AirColorString, AirEnumKey } from '../../type/AirType' import { AirColor } from '../../enum/AirColor' import { IDictionary } from '../../interface/IDictionary' import { AirDictionary } from '../AirDictionary' +import { AirConstant } from '@/airpower/config/AirConstant' /** * # 字典数组 @@ -34,7 +35,7 @@ export class AirDictionaryArray extends Arr * @param key Key * @param defaultLabel 默认Label */ - getLabel(key: AirEnumKey, defaultLabel = '-'): string { + getLabel(key: AirEnumKey, defaultLabel = AirConstant.HYPHEN): string { return this.get(key).label || defaultLabel } diff --git a/type/AirType.ts b/type/AirType.ts index d420441..2f9f202 100644 --- a/type/AirType.ts +++ b/type/AirType.ts @@ -92,6 +92,16 @@ export type AirValidatorCallback = (error?: string) => void */ export type AirValidatorRule = AirAny +/** + * ## 验证器数据类型 + */ +export type AirValidatorType = 'string' | 'number' | 'date' | 'array' + +/** + * ## 验证器触发类型 + */ +export type AirValidatorTrigger = 'blur' | 'change' + /** * ## 图标类型字符串类型 */