diff --git a/src/modules/html/studio-app-list/index.ts b/src/modules/html/studio-app-list/index.ts
deleted file mode 100644
index 042b4bf..0000000
--- a/src/modules/html/studio-app-list/index.ts
+++ /dev/null
@@ -1,354 +0,0 @@
-type StudioOpts = {
- user: string,
- userAppKey?: string;
- appIds: string[]
- infoList?: {
- user: string;
- id: string;
- status: 'waiting' | 'connected' | 'closed';
- }[]
-}
-export const createStudioAppListHtml = (opts: StudioOpts) => {
- const user = opts.user!;
- const userAppKey = opts?.userAppKey;
- let showUserAppKey = userAppKey;
- const infos = opts.infoList || [];
- if (showUserAppKey && showUserAppKey.startsWith(user + '--')) {
- showUserAppKey = showUserAppKey.replace(user + '--', '');
- }
- const pathApps = opts?.appIds?.map(appId => {
- const shortAppId = appId.replace(opts!.user + '--', '')
- return {
- appId,
- shortAppId,
- pathname: `/${user}/v1/${shortAppId}`
- };
- }) || []
-
- // 应用列表内容
- const appListContent = `
-
-
-
-
- ${pathApps.length === 0 ? `
-
- ` : ''}
- `
-
- return `
-
-
-
-
-
- Studio - ${user} 的应用
-
-
-
-
- ${showUserAppKey ? `
-
-
-
应用不存在
-
抱歉,您访问的应用 ${showUserAppKey || ''} 不存在。
-
请检查应用 Key 是否正确,或联系管理员。
-
← 返回应用列表
-
- ` : ''}
- ${appListContent}
-
${JSON.stringify(infos, null, 2)}
-
-
-
-
- `;
-};
diff --git a/src/modules/v1-ws-proxy/proxy.ts b/src/modules/v1-ws-proxy/proxy.ts
index fdba8e0..83cde89 100644
--- a/src/modules/v1-ws-proxy/proxy.ts
+++ b/src/modules/v1-ws-proxy/proxy.ts
@@ -4,7 +4,6 @@ import { wsProxyManager } from './index.ts';
import { App } from '@kevisual/router';
import { logger } from '../logger.ts';
import { getLoginUser } from '@/modules/auth.ts';
-import { createStudioAppListHtml } from '../html/studio-app-list/index.ts';
import { omit } from 'es-toolkit';
import { baseProxyUrl, proxyDomain } from '../domain.ts';
import { renderServerHtml } from '../html/render-server-html.ts';
diff --git a/src/routes/flowme/list.ts b/src/routes/flowme/list.ts
index 4ffb491..bfc3d02 100644
--- a/src/routes/flowme/list.ts
+++ b/src/routes/flowme/list.ts
@@ -1,5 +1,6 @@
import { desc, eq, count, or, like, and } from 'drizzle-orm';
import { schema, app, db } from '@/app.ts'
+import z from 'zod';
// 获取 flowme 列表
app.route({
@@ -7,6 +8,15 @@ app.route({
key: 'list',
middleware: ['auth'],
description: '获取 flowme 列表',
+ metadata: {
+ args: {
+ page: z.number().describe('页码, 默认为 1').optional(),
+ pageSize: z.number().describe('每页数量, 默认为 20').optional(),
+ search: z.string().describe('搜索关键词').optional(),
+ channelId: z.string().describe('频道ID').optional(),
+ sort: z.enum(['ASC', 'DESC']).describe('排序方式,ASC 或 DESC,默认为 DESC').optional(),
+ }
+ }
}).define(async (ctx) => {
const tokenUser = ctx.state.tokenUser;
const uid = tokenUser.id;
@@ -56,61 +66,93 @@ app.route({
return ctx;
}).addTo(app);
-// 创建或更新 flowme
-const flowmeUpdate = `创建或更新一个 flowme, 参数定义:
-title: 标题, 必填
-description: 描述, 选填
-tags: 标签, 数组, 选填
-link: 链接, 选填
-data: 数据, 对象, 选填
-channelId: 频道ID, 选填
-type: 类型, 选填
-source: 来源, 选填
-importance: 重要性等级, 数字, 选填
-`;
+// 创建 flowme
+app.route({
+ path: 'flowme',
+ key: 'create',
+ middleware: ['auth'],
+ description: '创建一个 flowme',
+ metadata: {
+ args: {
+ data: z.object({
+ title: 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(),
+ channelId: z.string().describe('频道ID').optional(),
+ type: z.string().describe('类型').optional(),
+ source: z.string().describe('来源').optional(),
+ importance: z.number().describe('重要性等级').optional(),
+ isArchived: z.boolean().describe('是否归档').optional(),
+ })
+ }
+ }
+}).define(async (ctx) => {
+ const { uid, updatedAt, createdAt, ...rest } = ctx.query.data || {};
+ const tokenUser = ctx.state.tokenUser;
+ const flowmeItem = await db.insert(schema.flowme).values({
+ title: rest.title || '',
+ description: rest.description || '',
+ tags: rest.tags || [],
+ link: rest.link || '',
+ data: rest.data || {},
+ channelId: rest.channelId || null,
+ type: rest.type || '',
+ source: rest.source || '',
+ importance: rest.importance || 0,
+ uid: tokenUser.id,
+ }).returning();
+ ctx.body = flowmeItem;
+}).addTo(app);
+
app.route({
path: 'flowme',
key: 'update',
middleware: ['auth'],
- description: flowmeUpdate,
+ description: '更新一个 flowme',
+ metadata: {
+ args: {
+ data: z.object({
+ id: z.string().describe('ID'),
+ title: 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(),
+ channelId: z.string().describe('频道ID').optional(),
+ type: z.string().describe('类型').optional(),
+ source: z.string().describe('来源').optional(),
+ importance: z.number().describe('重要性等级').optional(),
+ isArchived: z.boolean().describe('是否归档').optional(),
+ })
+ }
+ }
}).define(async (ctx) => {
const { id, uid, updatedAt, createdAt, ...rest } = ctx.query.data || {};
const tokenUser = ctx.state.tokenUser;
- let flowmeItem;
if (!id) {
- flowmeItem = await db.insert(schema.flowme).values({
- title: rest.title || '',
- description: rest.description || '',
- tags: rest.tags || [],
- link: rest.link || '',
- data: rest.data || {},
- channelId: rest.channelId || null,
- type: rest.type || '',
- source: rest.source || '',
- importance: rest.importance || 0,
- uid: tokenUser.id,
- }).returning();
- } else {
- const existing = await db.select().from(schema.flowme).where(eq(schema.flowme.id, id)).limit(1);
- if (existing.length === 0) {
- ctx.throw(404, '没有找到对应的 flowme');
- }
- if (existing[0].uid !== tokenUser.id) {
- ctx.throw(403, '没有权限更新该 flowme');
- }
- flowmeItem = await db.update(schema.flowme).set({
- title: rest.title,
- description: rest.description,
- tags: rest.tags,
- link: rest.link,
- data: rest.data,
- channelId: rest.channelId,
- type: rest.type,
- source: rest.source,
- importance: rest.importance,
- isArchived: rest.isArchived,
- }).where(eq(schema.flowme.id, id)).returning();
+ ctx.throw(400, 'id 参数缺失');
}
+ const existing = await db.select().from(schema.flowme).where(eq(schema.flowme.id, id)).limit(1);
+ if (existing.length === 0) {
+ ctx.throw(404, '没有找到对应的 flowme');
+ }
+ if (existing[0].uid !== tokenUser.id) {
+ ctx.throw(403, '没有权限更新该 flowme');
+ }
+ const flowmeItem = await db.update(schema.flowme).set({
+ title: rest.title,
+ description: rest.description,
+ tags: rest.tags,
+ link: rest.link,
+ data: rest.data,
+ channelId: rest.channelId,
+ type: rest.type,
+ source: rest.source,
+ importance: rest.importance,
+ isArchived: rest.isArchived,
+ }).where(eq(schema.flowme.id, id)).returning();
ctx.body = flowmeItem;
}).addTo(app);
@@ -119,7 +161,14 @@ app.route({
path: 'flowme',
key: 'delete',
middleware: ['auth'],
- description: '删除 flowme, 参数: data.id 必填',
+ description: '删除 flowme ',
+ metadata: {
+ args: {
+ data: z.object({
+ id: z.string().describe('ID'),
+ })
+ }
+ }
}).define(async (ctx) => {
const tokenUser = ctx.state.tokenUser;
const { id } = ctx.query.data || {};