HarmonyOS鸿蒙Next中怎样实现公共数据校验工具类?

HarmonyOS鸿蒙Next中怎样实现公共数据校验工具类? 开发中需要校验用户输入:

  • 表单字段验证
  • 数据格式检查
  • 业务规则校验
  • 统一错误提示
5 回复

支持一下~~~

更多关于HarmonyOS鸿蒙Next中怎样实现公共数据校验工具类?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


如何查看Linux系统版本信息

1. 使用 lsb_release 命令

lsb_release 命令用于显示LSB(Linux标准基础)和特定版本信息。

lsb_release -a

输出示例:

No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.3 LTS
Release:        20.04
Codename:       focal

常用选项:

  • -a:显示所有信息
  • -d:显示描述信息
  • -r:显示版本号
  • -c:显示代号

2. 查看 /etc/os-release 文件

该文件包含操作系统标识数据。

cat /etc/os-release

输出示例:

NAME="Ubuntu"
VERSION="20.04.3 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.3 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal

3. 查看 /etc/issue 文件

该文件包含系统登录前的标识信息。

cat /etc/issue

输出示例:

Ubuntu 20.04.3 LTS \n \l

4. 使用 hostnamectl 命令

hostnamectl 命令用于查询和更改系统主机名及相关设置。

hostnamectl

输出示例:

   Static hostname: ubuntu-server
         Icon name: computer-server
           Chassis: server
        Machine ID: 1234567890abcdef1234567890abcdef
           Boot ID: abcdef1234567890abcdef1234567890
  Operating System: Ubuntu 20.04.3 LTS
            Kernel: Linux 5.4.0-91-generic
      Architecture: x86-64

5. 查看 /proc/version 文件

该文件显示内核版本信息。

cat /proc/version

输出示例:

Linux version 5.4.0-91-generic (buildd@lgw01-amd64-039) (gcc version 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04)) #102-Ubuntu SMP Fri Nov 5 16:31:28 UTC 2021

6. 使用 uname 命令

uname 命令用于显示系统信息。

uname -a

输出示例:

Linux ubuntu-server 5.4.0-91-generic #102-Ubuntu SMP Fri Nov 5 16:31:28 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

常用选项:

  • -a:显示所有信息
  • -s:显示内核名称
  • -r:显示内核版本
  • -v:显示内核发布时间
  • -m:显示机器硬件名称
  • -p:显示处理器类型
  • -o:显示操作系统

7. 查看发行版特定文件

不同发行版可能有特定的版本文件:

  • Red Hat/CentOS/Fedora

    cat /etc/redhat-release
    cat /etc/centos-release
    cat /etc/fedora-release
    
  • Debian

    cat /etc/debian_version
    
  • Arch Linux

    cat /etc/arch-release
    

总结

以上方法可以帮助您获取Linux系统的详细版本信息。根据您的具体需求,选择合适的方法来查看系统版本、内核版本和发行版信息。

解决方案

完整校验工具类

/**
 * 数据校验工具类
 */
export class Validator {
  /**
   * 是否为空
   */
  static isEmpty(value: string | null | undefined): boolean {
    return value === null || value === undefined || value.trim() === '';
  }

  /**
   * 必填校验
   */
  static required(value: string, fieldName: string = '此项'): string | null {
    if (this.isEmpty(value)) {
      return `${fieldName}不能为空`;
    }
    return null;
  }

  /**
   * 长度校验
   */
  static length(value: string, min: number, max: number, fieldName: string = '此项'): string | null {
    if (this.isEmpty(value)) {
      return null; // 空值由required校验
    }

    const len = value.trim().length;
    if (len < min) {
      return `${fieldName}不能少于${min}个字符`;
    }
    if (len > max) {
      return `${fieldName}不能超过${max}个字符`;
    }
    return null;
  }

  /**
   * 数字范围校验
   */
  static range(value: number, min: number, max: number, fieldName: string = '数值'): string | null {
    if (value < min || value > max) {
      return `${fieldName}必须在${min}-${max}之间`;
    }
    return null;
  }

  /**
   * 手机号校验
   */
  static phone(value: string): string | null {
    const pattern = /^1[3-9]\d{9}$/;
    if (!pattern.test(value)) {
      return '手机号格式不正确';
    }
    return null;
  }

  /**
   * 邮箱校验
   */
  static email(value: string): string | null {
    const pattern = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/;
    if (!pattern.test(value)) {
      return '邮箱格式不正确';
    }
    return null;
  }

  /**
   * 身份证校验
   */
  static idCard(value: string): string | null {
    const pattern = /^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/;
    if (!pattern.test(value)) {
      return '身份证号格式不正确';
    }
    return null;
  }

  /**
   * 日期校验(不能晚于今天)
   */
  static dateNotFuture(timestamp: number): string | null {
    if (timestamp > Date.now()) {
      return '日期不能晚于今天';
    }
    return null;
  }

  /**
   * 日期范围校验
   */
  static dateRange(startTime: number, endTime: number): string | null {
    if (startTime >= endTime) {
      return '开始时间必须早于结束时间';
    }
    return null;
  }

  /**
   * 组合校验
   */
  static validate(value: string, rules: ValidationRule[]): string | null {
    for (const rule of rules) {
      const error = rule(value);
      if (error) {
        return error;
      }
    }
    return null;
  }
}

// 校验规则类型
type ValidationRule = (value: string) => string | null;

使用示例

/**
 * 物品编辑页面
 */
@Component
struct ItemEditPage {
  @State itemName: string = '';
  @State itemDesc: string = '';
  @State expiryDays: number = 30;

  @State nameError: string = '';
  @State descError: string = '';
  @State daysError: string = '';

  /**
   * 实时校验名称
   */
  onNameChange(value: string): void {
    this.itemName = value;

    // ✅ 组合校验
    this.nameError = Validator.validate(value, [
      (v) => Validator.required(v, '物品名称'),
      (v) => Validator.length(v, 1, 50, '物品名称')
    ]) || '';
  }

  /**
   * 失焦校验描述
   */
  onDescBlur(): void {
    this.descError = Validator.length(this.itemDesc, 0, 200, '描述') || '';
  }

  /**
   * 校验天数
   */
  onDaysChange(value: number): void {
    this.expiryDays = value;
    this.daysError = Validator.range(value, 1, 3650, '有效天数') || '';
  }

  /**
   * 提交前完整校验
   */
  async onSubmit(): Promise<void> {
    // ✅ 校验所有字段
    const errors: string[] = [];

    const nameErr = Validator.validate(this.itemName, [
      (v) => Validator.required(v, '物品名称'),
      (v) => Validator.length(v, 1, 50, '物品名称')
    ]);
    if (nameErr) errors.push(nameErr);

    const descErr = Validator.length(this.itemDesc, 0, 200, '描述');
    if (descErr) errors.push(descErr);

    const daysErr = Validator.range(this.expiryDays, 1, 3650, '有效天数');
    if (daysErr) errors.push(daysErr);

    // ✅ 有错误则提示
    if (errors.length > 0) {
      promptAction.showToast({
        message: errors[0] // 显示第一个错误
      });
      return;
    }

    // ✅ 校验通过,保存数据
    await this.saveData();
  }

  build() {
    Column({ space: 16 }) {
      // 物品名称
      Column({ space: 4 }) {
        TextInput({ placeholder: '请输入物品名称' })
          .onChange((value) => {
            this.onNameChange(value);
          });

        if (this.nameError) {
          Text(this.nameError)
            .fontSize(12)
            .fontColor(Color.Red);
        }
      }
      .alignItems(HorizontalAlign.Start)

      // 描述
      Column({ space: 4 }) {
        TextArea({ placeholder: '请输入描述(可选)' })
          .onChange((value) => {
            this.itemDesc = value;
          })
          .onBlur(() => {
            this.onDescBlur();
          });

        if (this.descError) {
          Text(this.descError)
            .fontSize(12)
            .fontColor(Color.Red);
        }
      }
      .alignItems(HorizontalAlign.Start)

      // 提交按钮
      Button('保存')
        .onClick(() => {
          this.onSubmit();
        });
    }
    .padding(16)
  }
}

高级校验器

/**
 * 高级校验器
 */
export class AdvancedValidator {
  /**
   * 自定义正则校验
   */
  static pattern(value: string, regex: RegExp, message: string): string | null {
    if (!regex.test(value)) {
      return message;
    }
    return null;
  }

  /**
   * 唯一性校验(异步)
   */
  static async unique(value: string, checkFn: (v: string) => Promise<boolean>, fieldName: string): Promise<string | null> {
    const exists = await checkFn(value);
    if (exists) {
      return `${fieldName}已存在`;
    }
    return null;
  }

  /**
   * 密码强度校验
   */
  static passwordStrength(password: string): string | null {
    if (password.length < 8) {
      return '密码长度不能少于8位';
    }

    const hasNumber = /\d/.test(password);
    const hasLetter = /[a-zA-Z]/.test(password);
    const hasSpecial = /[!@#$%^&*()]/.test(password);

    if (!hasNumber || !hasLetter) {
      return '密码必须包含字母和数字';
    }

    return null;
  }

  /**
   * 两次密码一致性校验
   */
  static passwordMatch(password: string, confirmPassword: string): string | null {
    if (password !== confirmPassword) {
      return '两次密码不一致';
    }
    return null;
  }
}

// 使用唯一性校验
async function checkNameUnique(): Promise<void> {
  const error = await AdvancedValidator.unique(
    this.itemName,
    async (name) => {
      const count = await ItemDao.countByName(name);
      return count > 0;
    },
    '物品名称'
  );

  if (error) {
    this.nameError = error;
  }
}

关键要点

1. 校验时机

// ✅ 实时校验(输入时)
.onChange((value) => {
  this.validate(value);
})

// ✅ 失焦校验(离开输入框时)
.onBlur(() => {
  this.validate();
})

// ✅ 提交校验(点击按钮时)
.onClick(() => {
  if (this.validateAll()) {
    this.submit();
  }
})

2. 错误显示

// ✅ 推荐:字段下方显示错误
Column() {
  TextInput();
  if (this.error) {
    Text(this.error).fontColor(Color.Red);
  }
}

// ✅ 推荐:Toast提示
promptAction.showToast({ message: error });

3. 校验规则复用

// ✅ 定义常用规则
const NameRules: ValidationRule[] = [
  (v) => Validator.required(v, '名称'),
  (v) => Validator.length(v, 1, 50, '名称')
];

const PhoneRules: ValidationRule[] = [
  (v) => Validator.required(v, '手机号'),
  (v) => Validator.phone(v)
];

// 复用
Validator.validate(name, NameRules);
Validator.validate(phone, PhoneRules);

最佳实践

✅ 提供友好的错误提示 ✅ 实时反馈校验结果 ✅ 组合多个校验规则 ✅ 封装常用校验方法 ✅ 异步校验用户体验

在HarmonyOS Next中,可通过@ohos.data.preferences创建Preferences实例存储校验规则,使用@ohos.utilLruBuffer缓存校验结果。数据校验逻辑推荐使用ArkTS的装饰器@Watch监听数据变化,结合正则表达式进行格式验证。可封装独立工具类,通过export导出validateData函数供调用。

在HarmonyOS Next中,实现一个公共数据校验工具类,可以遵循以下核心思路,利用ArkTS的类型系统和能力来构建:

1. 核心设计:单一职责与链式调用 建议将校验器(Validator)与校验规则(Rule)分离。每个Rule只负责一种校验逻辑,Validator则管理规则链并执行校验。这支持灵活的规则组合与复用。

2. 基础实现步骤

  • 定义校验规则接口:

    interface ValidationRule {
      validate(value: any): boolean;
      getErrorMessage(): string;
    }
    
  • 实现具体规则类: 针对不同的校验类型(如非空、邮箱格式、手机号、数字范围等)创建类并实现ValidationRule接口。

    class RequiredRule implements ValidationRule {
      validate(value: any): boolean {
        return value !== null && value !== undefined && value.toString().trim() !== '';
      }
      getErrorMessage(): string {
        return '该字段为必填项';
      }
    }
    
    class EmailFormatRule implements ValidationRule {
      validate(value: string): boolean {
        const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
        return emailRegex.test(value);
      }
      getErrorMessage(): string {
        return '邮箱格式不正确';
      }
    }
    
  • 构建校验工具类 (Validator): 这个类负责接收待校验的值和规则列表,按顺序执行校验,并收集错误信息。

    class Validator {
      private rules: ValidationRule[] = [];
      private value: any;
    
      constructor(value: any) {
        this.value = value;
      }
    
      addRule(rule: ValidationRule): Validator {
        this.rules.push(rule);
        return this; // 支持链式调用
      }
    
      validate(): { isValid: boolean; errors: string[] } {
        const errors: string[] = [];
        for (const rule of this.rules) {
          if (!rule.validate(this.value)) {
            errors.push(rule.getErrorMessage());
          }
        }
        return {
          isValid: errors.length === 0,
          errors: errors
        };
      }
    }
    

3. 使用示例

// 在业务逻辑中调用
const userEmail = 'user@example.com';
const result = new Validator(userEmail)
  .addRule(new RequiredRule())
  .addRule(new EmailFormatRule())
  .validate();

if (!result.isValid) {
  // 统一处理错误提示,例如使用UI弹窗
  console.error('校验失败:', result.errors);
  // 此处可将errors传递给UI组件进行展示
}

4. 高级扩展建议

  • 异步校验: 对于需要网络请求的校验(如用户名重复性检查),可以设计支持Promise的异步规则接口。
  • 与ArkUI状态绑定: 可以将校验结果与@State装饰的变量绑定,实现校验错误信息在UI上的实时响应式显示。
  • 规则工厂: 对于常用规则组合,可以创建一个“规则工厂”来快速生成预设的规则集,提升代码简洁性。

通过以上方式,你可以构建一个职责清晰、可扩展性强的公共数据校验工具,满足表单验证、数据格式检查等需求,并统一错误处理逻辑。

回到顶部