修复提交
This commit is contained in:
1 parent
d8786eb28a
commit
5fe7f5d476
4 files changed
+68
-13
No files matched your search
@@ -0,0 +1,41 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { RESOURCES } from './resource-registry';
|
||||
|
||||
/**
|
||||
* 日期字段的转换护栏。
|
||||
*
|
||||
* 起因:后台加「首页新课」填发布日期,报 PrismaClientValidationError——
|
||||
* 表单传的是 'YYYY-MM-DD',而 Prisma 的 DateTime 要完整时间,原样透传就被拒。
|
||||
*/
|
||||
describe('资源注册表的日期字段', () => {
|
||||
const schema = RESOURCES['home-courses']!.create;
|
||||
|
||||
it('纯日期串会转成 Date(UTC 零点),不再原样透传给 Prisma', () => {
|
||||
const parsed = schema.parse({ course_name: 'x', published_at: '2026-09-30' });
|
||||
expect(parsed.published_at).toBeInstanceOf(Date);
|
||||
expect((parsed.published_at as Date).toISOString()).toBe('2026-09-30T00:00:00.000Z');
|
||||
});
|
||||
|
||||
it('转出来的日期能原样回填,不会串一天', () => {
|
||||
const parsed = schema.parse({ course_name: 'x', published_at: '2026-09-30' });
|
||||
// 后台显示/回填用的是 ISO 串前 10 位
|
||||
expect((parsed.published_at as Date).toISOString().slice(0, 10)).toBe('2026-09-30');
|
||||
});
|
||||
|
||||
it('完整时间串照样接受', () => {
|
||||
const parsed = schema.parse({ course_name: 'x', published_at: '2026-09-30T12:34:56.000Z' });
|
||||
expect((parsed.published_at as Date).toISOString()).toBe('2026-09-30T12:34:56.000Z');
|
||||
});
|
||||
|
||||
it('空值按「不填」处理,不报错', () => {
|
||||
expect(schema.parse({ course_name: 'x', published_at: '' }).published_at).toBeNull();
|
||||
expect(schema.parse({ course_name: 'x', published_at: null }).published_at).toBeNull();
|
||||
expect(schema.parse({ course_name: 'x' }).published_at).toBeUndefined();
|
||||
});
|
||||
|
||||
it('乱填会被挡下,并给出可读的原因', () => {
|
||||
const result = schema.safeParse({ course_name: 'x', published_at: '九月三十号' });
|
||||
expect(result.success).toBe(false);
|
||||
expect(JSON.stringify(result.error?.issues)).toContain('日期格式不正确');
|
||||
});
|
||||
});
|
||||
@@ -9,7 +9,29 @@ import { z } from 'zod';
|
||||
* 一个通用控制器 + 这张表覆盖了管理后台的绝大部分内容管理功能。
|
||||
*/
|
||||
|
||||
const dateish = z.union([z.string(), z.date(), z.null()]);
|
||||
/**
|
||||
* 日期字段。后台表单传的是 'YYYY-MM-DD' 纯日期串,而 Prisma 的 DateTime 需要完整时间,
|
||||
* 原样透传会抛 PrismaClientValidationError(首页新课加日期就报过这个)。
|
||||
*
|
||||
* 补成 **UTC 零点**,是为了跟后台的显示/回填对齐:那边是拿 ISO 串切前 10 位,
|
||||
* 若按北京时间补,就会出现「显示 09-30 → 保存 → 回填成 09-29」串一天。
|
||||
*/
|
||||
const dateish = z
|
||||
.union([z.string(), z.date(), z.null()])
|
||||
.transform((value, ctx) => {
|
||||
if (value === null) return null;
|
||||
if (value instanceof Date) return value;
|
||||
|
||||
const text = value.trim();
|
||||
if (!text) return null;
|
||||
|
||||
const parsed = new Date(/^\d{4}-\d{2}-\d{2}$/.test(text) ? `${text}T00:00:00.000Z` : text);
|
||||
if (Number.isNaN(parsed.getTime())) {
|
||||
ctx.addIssue({ code: z.ZodIssueCode.custom, message: `日期格式不正确:${value}` });
|
||||
return z.NEVER;
|
||||
}
|
||||
return parsed;
|
||||
});
|
||||
const optionalDate = dateish.optional();
|
||||
|
||||
export interface ResourceDef {
|
||||
@@ -136,4 +158,3 @@ export const RESOURCES: Record<string, ResourceDef> = {
|
||||
export const READONLY_RESOURCES: Record<string, { delegate: string; orderBy: Record<string, 'asc' | 'desc'>[] }> = {
|
||||
'free-lessons': { delegate: 'freeLesson', orderBy: [{ series_no: 'asc' }, { sort_order: 'asc' }] },
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user