feat: 添加 flowme-life 功能,包括创建、更新、删除和列表接口,导入 life JSON 数据到数据库
This commit is contained in:
217
.opencode/skills/create-routes/SKILL.md
Normal file
217
.opencode/skills/create-routes/SKILL.md
Normal file
@@ -0,0 +1,217 @@
|
||||
---
|
||||
name: create-routes
|
||||
description: 创建路由例子模板代码
|
||||
---
|
||||
|
||||
# 创建路由例子模板代码
|
||||
|
||||
app是自定义@kevisual/router的一个APP
|
||||
|
||||
1. 一般来说,修改path,和对应的schema表,就可以快速创建对应的增删改查接口。
|
||||
2. 根据需要,每一个功能需要添加对应的描述
|
||||
3. 根据需要,对应schema表的字段进行修改代码
|
||||
|
||||
示例:
|
||||
|
||||
```ts
|
||||
import { desc, eq, count, or, like, and } from 'drizzle-orm';
|
||||
import { schema, app, db } from '@/app.ts';
|
||||
import { z } from 'zod';
|
||||
|
||||
app
|
||||
.route({
|
||||
path: 'prompts',
|
||||
key: 'list',
|
||||
middleware: ['auth'],
|
||||
description: '获取提示词列表',
|
||||
metadata: {
|
||||
args: {
|
||||
page: z.number().optional().default(1).describe('页码'),
|
||||
pageSize: z.number().optional().default(20).describe('每页数量'),
|
||||
search: z.string().optional().describe('搜索关键词'),
|
||||
sort: z.enum(['ASC', 'DESC']).optional().default('DESC').describe('排序方式'),
|
||||
},
|
||||
},
|
||||
})
|
||||
.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.prompts.updatedAt : desc(schema.prompts.updatedAt);
|
||||
|
||||
let whereCondition = eq(schema.prompts.uid, uid);
|
||||
if (search) {
|
||||
whereCondition = and(eq(schema.prompts.uid, uid), or(like(schema.prompts.title, `%${search}%`), like(schema.prompts.summary, `%${search}%`)));
|
||||
}
|
||||
|
||||
const [list, totalCount] = await Promise.all([
|
||||
db.select().from(schema.prompts).where(whereCondition).limit(pageSize).offset(offset).orderBy(orderByField),
|
||||
db.select({ count: count() }).from(schema.prompts).where(whereCondition),
|
||||
]);
|
||||
|
||||
ctx.body = {
|
||||
list,
|
||||
pagination: {
|
||||
page,
|
||||
current: page,
|
||||
pageSize,
|
||||
total: totalCount[0]?.count || 0,
|
||||
},
|
||||
};
|
||||
return ctx;
|
||||
})
|
||||
.addTo(app);
|
||||
app
|
||||
.route({
|
||||
path: 'prompts',
|
||||
key: 'create',
|
||||
middleware: ['auth'],
|
||||
description: '创建提示词',
|
||||
metadata: {
|
||||
args: {
|
||||
data: z
|
||||
.object({
|
||||
title: z.string().describe('提示词标题'),
|
||||
description: z.string().optional().describe('描述'),
|
||||
summary: z.string().optional().describe('摘要'),
|
||||
tags: z.array(z.string()).optional().describe('标签'),
|
||||
link: z.string().optional().describe('链接'),
|
||||
data: z.record(z.string(), z.any()).optional().describe('数据对象'),
|
||||
parents: z.array(z.string()).optional().describe('父级ID数组'),
|
||||
})
|
||||
.describe('提示词对象'),
|
||||
},
|
||||
},
|
||||
})
|
||||
.define(async (ctx) => {
|
||||
const tokenUser = ctx.state.tokenUser;
|
||||
const { title, description, summary, tags, link, data, parents } = ctx.query.data || {};
|
||||
if (!title) {
|
||||
ctx.throw(400, 'title 参数缺失');
|
||||
}
|
||||
const newPrompt = await db
|
||||
.insert(schema.prompts)
|
||||
.values({
|
||||
title,
|
||||
description,
|
||||
summary,
|
||||
tags,
|
||||
link,
|
||||
data,
|
||||
parents,
|
||||
uid: tokenUser.id,
|
||||
})
|
||||
.returning();
|
||||
|
||||
ctx.body = newPrompt;
|
||||
})
|
||||
.addTo(app);
|
||||
app
|
||||
.route({
|
||||
path: 'prompts',
|
||||
key: 'update',
|
||||
middleware: ['auth'],
|
||||
description: '更新提示词',
|
||||
metadata: {
|
||||
args: {
|
||||
data: z
|
||||
.object({
|
||||
id: z.string().optional().describe('提示词ID, 不填表示创建'),
|
||||
title: z.string().describe('提示词标题'),
|
||||
description: z.string().optional().describe('描述'),
|
||||
summary: z.string().optional().describe('摘要'),
|
||||
tags: z.array(z.string()).optional().describe('标签'),
|
||||
link: z.string().optional().describe('链接'),
|
||||
data: z.record(z.string(), z.any()).optional().describe('数据对象'),
|
||||
parents: z.array(z.string()).optional().describe('父级ID数组'),
|
||||
})
|
||||
.describe('提示词对象'),
|
||||
},
|
||||
},
|
||||
})
|
||||
.define(async (ctx) => {
|
||||
const { id, uid, updatedAt, ...rest } = ctx.query.data || {};
|
||||
const tokenUser = ctx.state.tokenUser;
|
||||
let prompt;
|
||||
if (!id) {
|
||||
ctx.throw(400, 'id 参数缺失');
|
||||
}
|
||||
const existing = await db.select().from(schema.prompts).where(eq(schema.prompts.id, id)).limit(1);
|
||||
if (existing.length === 0) {
|
||||
ctx.throw(404, '没有找到对应的提示词');
|
||||
}
|
||||
if (existing[0].uid !== tokenUser.id) {
|
||||
ctx.throw(403, '没有权限更新该提示词');
|
||||
}
|
||||
prompt = await db
|
||||
.update(schema.prompts)
|
||||
.set({
|
||||
...rest,
|
||||
})
|
||||
.where(eq(schema.prompts.id, id))
|
||||
.returning();
|
||||
ctx.body = prompt;
|
||||
})
|
||||
.addTo(app);
|
||||
|
||||
app
|
||||
.route({
|
||||
path: 'prompts',
|
||||
key: 'delete',
|
||||
middleware: ['auth'],
|
||||
description: '删除提示词, 参数: id 提示词ID',
|
||||
metadata: {
|
||||
args: {
|
||||
id: z.string().describe('提示词ID'),
|
||||
},
|
||||
},
|
||||
})
|
||||
.define(async (ctx) => {
|
||||
const tokenUser = ctx.state.tokenUser;
|
||||
const { id } = ctx.query || {};
|
||||
if (!id) {
|
||||
ctx.throw(400, 'id 参数缺失');
|
||||
}
|
||||
const existing = await db.select().from(schema.prompts).where(eq(schema.prompts.id, id)).limit(1);
|
||||
if (existing.length === 0) {
|
||||
ctx.throw(404, '没有找到对应的提示词');
|
||||
}
|
||||
if (existing[0].uid !== tokenUser.id) {
|
||||
ctx.throw(403, '没有权限删除该提示词');
|
||||
}
|
||||
await db.delete(schema.prompts).where(eq(schema.prompts.id, id));
|
||||
ctx.body = { success: true };
|
||||
})
|
||||
.addTo(app);
|
||||
|
||||
app
|
||||
.route({
|
||||
path: 'prompts',
|
||||
key: 'get',
|
||||
middleware: ['auth'],
|
||||
description: '获取单个提示词, 参数: id 提示词ID',
|
||||
metadata: {
|
||||
args: {
|
||||
id: z.string().describe('提示词ID'),
|
||||
},
|
||||
},
|
||||
})
|
||||
.define(async (ctx) => {
|
||||
const tokenUser = ctx.state.tokenUser;
|
||||
const { id } = ctx.query || {};
|
||||
if (!id) {
|
||||
ctx.throw(400, 'id 参数缺失');
|
||||
}
|
||||
const existing = await db.select().from(schema.prompts).where(eq(schema.prompts.id, id)).limit(1);
|
||||
if (existing.length === 0) {
|
||||
ctx.throw(404, '没有找到对应的提示词');
|
||||
}
|
||||
if (existing[0].uid !== tokenUser.id) {
|
||||
ctx.throw(403, '没有权限查看该提示词');
|
||||
}
|
||||
ctx.body = existing[0];
|
||||
})
|
||||
.addTo(app);
|
||||
```
|
||||
Reference in New Issue
Block a user