【BUG】日期带时区的字段设置默认值后导致提交失败

* 描述问题

使用日期带时区的字段,设置默认值后,在创建数据时,使用默认值提交时报错:

* 运行环境

  • NocoBase 版本: 1.4.19
  • 数据库种类与版本: MySQL 8.x
  • 操作系统: Windows
    -浏览器及版本 Chrome
  • 部署方式: 源码
  • Docker 镜像版本:
  • NodeJS 版本: v20.18.1

如何重现

使用日期带时区的字段,设置默认值后,在创建数据时,使用默认值提交时报错

预期行为

日期带时区的字段,可以正常使用默认值提交

截图

日志

补充说明

经过排查,在 packages/core/database/src/fields/date-field.ts 代码文件中,如果是 mysql 数据库,初始化字段时会对默认值做转换:

    if (this.options.defaultValue && this.database.isMySQLCompatibleDialect()) {
      if (typeof this.options.defaultValue === 'string' && isIso8601(this.options.defaultValue)) {
        this.options.defaultValue = moment(this.options.defaultValue)
          .utcOffset(this.resolveTimeZone())
          .format('YYYY-MM-DD HH:mm:ss');
      }
    }

在 listmeta 接口拿到的字段信息会是不带时区的格式化时间:

使用该默认值提交时,会在 create 时走到当前文件的 setter 方法中的这段逻辑:

    if (typeof value === 'string' && isValidDatetime(value)) {
      const dateTimezone = this.resolveTimeZone(options?.context);
      const dateString = `${value} ${dateTimezone}`;
      return new Date(dateString);
    }

处理 resolveTimeZone 时,从字段 options 获取到的 timezone 值为 true,返回 true 导致 dateString 为非法的时间字符串。

默认的日期带时区的 options 里 timezone 值就是 true,所以这里的逻辑应该有问题:

    this.resolveTimeZone = (context) => {
      // @ts-ignore
      const serverTimeZone = this.database.options.rawTimezone;
      if (timezone === 'server') {
        return serverTimeZone;
      }

      if (timezone === 'client') {
        return context?.timezone || serverTimeZone;
      }

      if (timezone) {
        return timezone;
      }

      return serverTimeZone;
    };