Files

96 lines
2.3 KiB
TypeScript

export const NOTICE_STATUS_VALUES = ["draft", "published", "retracted"] as const;
export type NoticeStatus = (typeof NOTICE_STATUS_VALUES)[number];
export const NOTICE_STATUS_LABELS: Record<NoticeStatus, string> = {
draft: "草稿",
published: "已发布",
retracted: "已撤回",
};
export type Notice = {
id: string;
organizationId: string;
title: string;
content: string;
audience: string;
status: NoticeStatus;
publishedAt?: string;
createdByAccountId?: string;
createdByName?: string;
updatedByAccountId?: string;
updatedByName?: string;
readCount: number;
hasRead: boolean;
createdAt: string;
updatedAt: string;
};
export type NoticeCenterData = {
metrics: {
published: number;
drafts: number;
unread: number;
retracted: number;
};
notices: Notice[];
};
export type NoticeInput = {
title: string;
content: string;
audience: string;
status: NoticeStatus;
};
type ValidationSuccess<T> = {
success: true;
data: T;
};
type ValidationFailure = {
success: false;
reason: string;
};
export type ValidationResult<T> = ValidationSuccess<T> | ValidationFailure;
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null && !Array.isArray(value);
}
function readString(source: Record<string, unknown>, key: string): string {
const value = source[key];
return typeof value === "string" ? value.trim() : "";
}
function readEnum<T extends string>(value: unknown, values: readonly T[]): T | null {
return typeof value === "string" ? values.find((item) => item === value) ?? null : null;
}
export function validateNoticeInput(value: unknown): ValidationResult<NoticeInput> {
if (!isRecord(value)) {
return { success: false, reason: "请求数据格式无效" };
}
const title = readString(value, "title");
const content = readString(value, "content");
if (!title || !content) {
return { success: false, reason: "公告标题和内容不能为空" };
}
const status = readEnum(value.status, NOTICE_STATUS_VALUES);
if (!status) {
return { success: false, reason: "公告状态无效" };
}
return {
success: true,
data: {
title,
content,
audience: readString(value, "audience") || "全体员工",
status,
},
};
}