feat: improve app ui and project metadata
This commit is contained in:
@@ -18,13 +18,14 @@ export const LANES: readonly ForeshadowStatus[] = [
|
||||
] as const;
|
||||
|
||||
export const LANE_LABELS: Record<ForeshadowStatus, string> = {
|
||||
OPEN: "OPEN",
|
||||
PARTIAL: "PARTIAL",
|
||||
CLOSED: "CLOSED",
|
||||
OVERDUE: "OVERDUE",
|
||||
OPEN: "待推进",
|
||||
PARTIAL: "推进中",
|
||||
CLOSED: "已回收",
|
||||
OVERDUE: "已逾期",
|
||||
};
|
||||
|
||||
export type ForeshadowLanes = Record<ForeshadowStatus, ForeshadowView[]>;
|
||||
export type ForeshadowLaneCounts = Record<ForeshadowStatus, number>;
|
||||
|
||||
function emptyLanes(): ForeshadowLanes {
|
||||
return { OPEN: [], PARTIAL: [], CLOSED: [], OVERDUE: [] };
|
||||
@@ -46,6 +47,18 @@ export function groupByStatus(
|
||||
return lanes;
|
||||
}
|
||||
|
||||
export function countByStatus(
|
||||
items: readonly ForeshadowView[] | undefined,
|
||||
): ForeshadowLaneCounts {
|
||||
const lanes = groupByStatus(items);
|
||||
return {
|
||||
OPEN: lanes.OPEN.length,
|
||||
PARTIAL: lanes.PARTIAL.length,
|
||||
CLOSED: lanes.CLOSED.length,
|
||||
OVERDUE: lanes.OVERDUE.length,
|
||||
};
|
||||
}
|
||||
|
||||
// 接近回收窗口判定:current 在 [from, to] 内,或已超 from 但尚未 CLOSED(提示安排回收)。
|
||||
// 仅对 OPEN/PARTIAL 提示;CLOSED 已回收、OVERDUE 已逾期另有强调。
|
||||
export function isWindowApproaching(
|
||||
@@ -70,6 +83,21 @@ export function suggestForeshadowCode(
|
||||
return `FS-${String(index + 1).padStart(2, "0")}`;
|
||||
}
|
||||
|
||||
// 在已占用代号(taken,区分大小写按原样)中,为预填代号挑一个不冲突的值:
|
||||
// preferred 未被占用就用它;否则从 FS-01 起取首个空闲的 FS-<两位序号>。
|
||||
// 纯函数(可单测)。避免登记时与库里已存代号撞码 → 422 duplicate。
|
||||
export function nextFreeForeshadowCode(
|
||||
preferred: string,
|
||||
taken: ReadonlySet<string>,
|
||||
): string {
|
||||
if (preferred && !taken.has(preferred)) return preferred;
|
||||
for (let n = 1; n < 1000; n++) {
|
||||
const candidate = `FS-${String(n).padStart(2, "0")}`;
|
||||
if (!taken.has(candidate)) return candidate;
|
||||
}
|
||||
return preferred; // 理论不可达:1000 个代号全占用时退回原值
|
||||
}
|
||||
|
||||
export interface RegisterInput {
|
||||
projectId: string;
|
||||
code: string;
|
||||
|
||||
Reference in New Issue
Block a user