feat: 添加 flowme-life 功能,包括创建、更新、删除和列表接口,导入 life JSON 数据到数据库

This commit is contained in:
2026-03-10 20:17:49 +08:00
parent 48425c6120
commit 027cbecab6
11 changed files with 588 additions and 202 deletions

View File

@@ -0,0 +1 @@
import './list.ts'

View File

@@ -0,0 +1,202 @@
import { desc, eq, count, or, like, and } from 'drizzle-orm';
import { schema, app, db } from '@/app.ts'
import z from 'zod';
app.route({
path: 'flowme-life',
key: 'list',
middleware: ['auth'],
description: '获取 flowme-life 列表',
metadata: {
args: {
page: z.number().describe('页码, 默认为 1').optional(),
pageSize: z.number().describe('每页数量, 默认为 20').optional(),
search: z.string().describe('搜索关键词').optional(),
sort: z.enum(['ASC', 'DESC']).describe('排序方式ASC 或 DESC默认为 DESC').optional(),
}
}
}).define(async (ctx) => {
const tokenUser = ctx.state.tokenUser;
const uid = tokenUser.id;
const { page = 1, pageSize = 20, search, sort = 'DESC' } = ctx.query || {};
const offset = (page - 1) * pageSize;
const orderByField = sort === 'ASC' ? schema.life.updatedAt : desc(schema.life.updatedAt);
let whereCondition = eq(schema.life.uid, uid);
if (search) {
whereCondition = and(
eq(schema.life.uid, uid),
or(
like(schema.life.title, `%${search}%`),
like(schema.life.summary, `%${search}%`)
)
);
}
const [list, totalCount] = await Promise.all([
db.select()
.from(schema.life)
.where(whereCondition)
.limit(pageSize)
.offset(offset)
.orderBy(orderByField),
db.select({ count: count() })
.from(schema.life)
.where(whereCondition)
]);
ctx.body = {
list,
pagination: {
page,
current: page,
pageSize,
total: totalCount[0]?.count || 0,
},
};
return ctx;
}).addTo(app);
app.route({
path: 'flowme-life',
key: 'create',
middleware: ['auth'],
description: '创建一个 flowme-life',
metadata: {
args: {
data: z.object({
title: z.string().describe('标题').optional(),
summary: z.string().describe('摘要').optional(),
description: z.string().describe('描述').optional(),
tags: z.array(z.string()).describe('标签').optional(),
link: z.string().describe('链接').optional(),
data: z.record(z.string(), z.any()).describe('数据').optional(),
effectiveAt: z.string().describe('生效日期').optional(),
type: z.string().describe('类型').optional(),
prompt: z.string().describe('提示词').optional(),
taskType: z.string().describe('任务类型').optional(),
taskResult: z.record(z.string(), z.any()).describe('任务结果').optional(),
})
}
}
}).define(async (ctx) => {
const { uid, updatedAt, createdAt, ...rest } = ctx.query.data || {};
const tokenUser = ctx.state.tokenUser;
const lifeItem = await db.insert(schema.life).values({
title: rest.title || '',
summary: rest.summary || '',
description: rest.description || '',
tags: rest.tags || [],
link: rest.link || '',
data: rest.data || {},
effectiveAt: rest.effectiveAt || '',
type: rest.type || '',
prompt: rest.prompt || '',
taskType: rest.taskType || '',
taskResult: rest.taskResult || {},
uid: tokenUser.id,
}).returning();
ctx.body = lifeItem;
}).addTo(app);
app.route({
path: 'flowme-life',
key: 'update',
middleware: ['auth'],
description: '更新一个 flowme-life',
metadata: {
args: {
data: z.object({
id: z.string().describe('ID'),
title: z.string().describe('标题').optional(),
summary: z.string().describe('摘要').optional(),
description: z.string().describe('描述').optional(),
tags: z.array(z.string()).describe('标签').optional(),
link: z.string().describe('链接').optional(),
data: z.record(z.string(), z.any()).describe('数据').optional(),
effectiveAt: z.string().describe('生效日期').optional(),
type: z.string().describe('类型').optional(),
prompt: z.string().describe('提示词').optional(),
taskType: z.string().describe('任务类型').optional(),
taskResult: z.record(z.string(), z.any()).describe('任务结果').optional(),
})
}
}
}).define(async (ctx) => {
const { id, uid, updatedAt, createdAt, ...rest } = ctx.query.data || {};
const tokenUser = ctx.state.tokenUser;
if (!id) {
ctx.throw(400, 'id 参数缺失');
}
const existing = await db.select().from(schema.life).where(eq(schema.life.id, id)).limit(1);
if (existing.length === 0) {
ctx.throw(404, '没有找到对应的 flowme-life');
}
if (existing[0].uid !== tokenUser.id) {
ctx.throw(403, '没有权限更新该 flowme-life');
}
const lifeItem = await db.update(schema.life).set({
title: rest.title,
summary: rest.summary,
description: rest.description,
tags: rest.tags,
link: rest.link,
data: rest.data,
effectiveAt: rest.effectiveAt,
type: rest.type,
prompt: rest.prompt,
taskType: rest.taskType,
taskResult: rest.taskResult,
}).where(eq(schema.life.id, id)).returning();
ctx.body = lifeItem;
}).addTo(app);
app.route({
path: 'flowme-life',
key: 'delete',
middleware: ['auth'],
description: '删除 flowme-life',
metadata: {
args: {
data: z.object({
id: z.string().describe('ID'),
})
}
}
}).define(async (ctx) => {
const tokenUser = ctx.state.tokenUser;
const { id } = ctx.query.data || {};
if (!id) {
ctx.throw(400, 'id 参数缺失');
}
const existing = await db.select().from(schema.life).where(eq(schema.life.id, id)).limit(1);
if (existing.length === 0) {
ctx.throw(404, '没有找到对应的 flowme-life');
}
if (existing[0].uid !== tokenUser.id) {
ctx.throw(403, '没有权限删除该 flowme-life');
}
await db.delete(schema.life).where(eq(schema.life.id, id));
ctx.body = { success: true };
}).addTo(app);
app.route({
path: 'flowme-life',
key: 'get',
middleware: ['auth'],
description: '获取单个 flowme-life, 参数: data.id 必填',
}).define(async (ctx) => {
const tokenUser = ctx.state.tokenUser;
const { id } = ctx.query.data || {};
if (!id) {
ctx.throw(400, 'id 参数缺失');
}
const existing = await db.select().from(schema.life).where(eq(schema.life.id, id)).limit(1);
if (existing.length === 0) {
ctx.throw(404, '没有找到对应的 flowme-life');
}
if (existing[0].uid !== tokenUser.id) {
ctx.throw(403, '没有权限查看该 flowme-life');
}
ctx.body = existing[0];
}).addTo(app);