feat(organize): 整理记录按整理方式、媒体库目录、分类筛选,统计给出维度计数
列表与统计新增 action / libraryRootId / category 参数(分类取冻结计划的 classification.category); 统计 facets 按其余条件给出三个维度的可选值与条数(只列非零项),供整理记录的维度按钮列选项。 Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
This commit is contained in:
1 parent
ad3bf8926b
commit
eb294b0ffa
3 files changed
+86
-1
No files matched your search
@@ -57,7 +57,31 @@ export function registerOrganizationRoutes(app: ModuleApp, d: AoDeps) {
|
||||
.select((eb) => eb.fn.countAll<string>().as("n")),
|
||||
{ ...query, attention: true },
|
||||
).executeTakeFirst();
|
||||
const facet = async (dim: "action" | "libraryRootId" | "category") => {
|
||||
const col =
|
||||
dim === "action"
|
||||
? sql<string>`action::text`
|
||||
: dim === "libraryRootId"
|
||||
? sql<string>`target_library_root_id::text`
|
||||
: CATEGORY_SQL;
|
||||
const rows = await recordFilters(
|
||||
db()
|
||||
.selectFrom("organization_record")
|
||||
.select([col.as("value"), (eb) => eb.fn.countAll<string>().as("n")])
|
||||
.groupBy(col)
|
||||
.orderBy(sql`count(*)`, "desc"),
|
||||
{ ...query, [dim]: undefined },
|
||||
).execute();
|
||||
return rows
|
||||
.filter((r: { value: string | null }) => r.value)
|
||||
.map((r: { value: string; n: string }) => ({ value: r.value, n: Number(r.n) }));
|
||||
};
|
||||
return {
|
||||
facets: {
|
||||
action: await facet("action"),
|
||||
libraryRootId: await facet("libraryRootId"),
|
||||
category: await facet("category"),
|
||||
},
|
||||
attention: Number(att?.n ?? 0),
|
||||
total: rows.reduce((a, r) => a + Number(r.n), 0),
|
||||
succeeded: n("succeeded"),
|
||||
@@ -339,6 +363,9 @@ export function likePattern(input: string): string {
|
||||
return /[*?]/.test(input) ? esc.replace(/\*/g, "%").replace(/\?/g, "_") : `%${esc}%`;
|
||||
}
|
||||
|
||||
/** 冻结计划里的二级分类 */
|
||||
const CATEGORY_SQL = sql<string>`plan->'classification'->>'category'`;
|
||||
|
||||
/** 列表 / 统计共用筛选(不含状态) */
|
||||
// biome-ignore lint/suspicious/noExplicitAny: 同一张表的 select 与 groupBy 查询共用
|
||||
function recordFilters<Q extends SelectQueryBuilder<DB, "organization_record", any>>(
|
||||
@@ -355,6 +382,9 @@ function recordFilters<Q extends SelectQueryBuilder<DB, "organization_record", a
|
||||
if (query.since) q = q.where("created_at", ">=", new Date(query.since));
|
||||
if (query.organizeOnly) q = q.where("action", "in", ["copy", "move", "in_place", "hardlink"]);
|
||||
if (query.attention) q = q.where(attentionSql());
|
||||
if (query.action) q = q.where("action", "=", query.action);
|
||||
if (query.libraryRootId) q = q.where("target_library_root_id", "=", query.libraryRootId);
|
||||
if (query.category) q = q.where(sql<boolean>`${CATEGORY_SQL} = ${query.category}`);
|
||||
if (query.kind === "none") q = q.where("media_entity_id", "is", null);
|
||||
else if (query.kind)
|
||||
q = q.where("media_entity_id", "in", (eb: ExpressionBuilder<DB, "organization_record">) =>
|
||||
|
||||
Reference in new issue
Block a user