Compare commits
10 Commits
10874917f2
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
56a55ac5ae | ||
|
|
8184994b2c | ||
|
|
2000b474a0 | ||
|
|
07efc4e468 | ||
|
|
f305a900f4 | ||
|
|
6a92ee7a2d | ||
|
|
6467e6dea8 | ||
|
|
08884b7e4b | ||
|
|
9be5eb00f5 | ||
|
|
2332f05cef |
2
.npmrc
2
.npmrc
@@ -1,2 +0,0 @@
|
||||
@abearxiong:registry=https://npm.pkg.github.com
|
||||
ignore-workspace-root-check=true
|
||||
29
.opencode/skills/pnpm-deploy/SKILL.md
Normal file
29
.opencode/skills/pnpm-deploy/SKILL.md
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
name: pnpm-deploy
|
||||
description: 使用pnpm部署应用到测试或生成环境
|
||||
---
|
||||
|
||||
# pnpm-deploy 部署技能
|
||||
|
||||
部署应用到测试或生成环境。
|
||||
|
||||
## 部署环境
|
||||
|
||||
| 环境 | 命令 |
|
||||
|------|------|
|
||||
| 测试环境 | `pnpm pub:me` |
|
||||
| 生成环境 | `pnpm pub:kevisual` |
|
||||
|
||||
## 使用方法
|
||||
|
||||
在项目目录下执行部署命令:
|
||||
|
||||
### 部署到测试环境
|
||||
```bash
|
||||
pnpm pub:me
|
||||
```
|
||||
|
||||
### 部署到生成环境
|
||||
```bash
|
||||
pnpm pub:kevisual
|
||||
```
|
||||
33
package.json
33
package.json
@@ -41,16 +41,16 @@
|
||||
],
|
||||
"license": "UNLICENSED",
|
||||
"dependencies": {
|
||||
"@kevisual/ai": "^0.0.27",
|
||||
"@kevisual/ai": "^0.0.28",
|
||||
"@kevisual/auth": "^2.0.3",
|
||||
"@kevisual/js-filter": "^0.0.6",
|
||||
"@kevisual/query": "^0.0.53",
|
||||
"@kevisual/query": "^0.0.55",
|
||||
"@types/busboy": "^1.5.4",
|
||||
"@types/send": "^1.2.1",
|
||||
"@types/ws": "^8.18.1",
|
||||
"bullmq": "^5.70.4",
|
||||
"bullmq": "^5.71.0",
|
||||
"busboy": "^1.6.0",
|
||||
"drizzle-kit": "^0.31.9",
|
||||
"drizzle-kit": "^0.31.10",
|
||||
"drizzle-orm": "^0.45.1",
|
||||
"eventemitter3": "^5.0.4",
|
||||
"send": "^1.2.1",
|
||||
@@ -59,38 +59,37 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ai-sdk/openai-compatible": "^2.0.35",
|
||||
"@aws-sdk/client-s3": "^3.1005.0",
|
||||
"@kevisual/api": "^0.0.62",
|
||||
"@kevisual/cnb": "^0.0.42",
|
||||
"@aws-sdk/client-s3": "^3.1013.0",
|
||||
"@kevisual/api": "^0.0.64",
|
||||
"@kevisual/cnb": "^0.0.56",
|
||||
"@kevisual/context": "^0.0.8",
|
||||
"@kevisual/convex": "^0.0.6",
|
||||
"@kevisual/local-app-manager": "0.1.32",
|
||||
"@kevisual/logger": "^0.0.4",
|
||||
"@kevisual/oss": "0.0.20",
|
||||
"@kevisual/permission": "^0.0.4",
|
||||
"@kevisual/router": "0.1.0",
|
||||
"@kevisual/router": "0.1.6",
|
||||
"@kevisual/types": "^0.0.12",
|
||||
"@kevisual/use-config": "^1.0.30",
|
||||
"@types/archiver": "^7.0.0",
|
||||
"@types/bun": "^1.3.10",
|
||||
"@types/bun": "^1.3.11",
|
||||
"@types/crypto-js": "^4.2.2",
|
||||
"@types/jsonwebtoken": "^9.0.10",
|
||||
"@types/node": "^25.4.0",
|
||||
"@types/node": "^25.5.0",
|
||||
"@types/pg": "^8.18.0",
|
||||
"@types/semver": "^7.7.1",
|
||||
"@types/xml2js": "^0.4.14",
|
||||
"ai": "^6.0.116",
|
||||
"archiver": "^7.0.1",
|
||||
"convex": "^1.32.0",
|
||||
"convex": "^1.34.0",
|
||||
"crypto-js": "^4.2.0",
|
||||
"dayjs": "^1.11.19",
|
||||
"dayjs": "^1.11.20",
|
||||
"dotenv": "^17.3.1",
|
||||
"drizzle-zod": "^0.8.3",
|
||||
"es-toolkit": "^1.45.1",
|
||||
"ioredis": "^5.10.0",
|
||||
"ioredis": "^5.10.1",
|
||||
"jsonwebtoken": "^9.0.3",
|
||||
"lunar": "^2.0.0",
|
||||
"nanoid": "^5.1.6",
|
||||
"nanoid": "^5.1.7",
|
||||
"p-queue": "^9.1.0",
|
||||
"pg": "^8.20.0",
|
||||
"pm2": "^6.0.14",
|
||||
@@ -100,9 +99,9 @@
|
||||
"resolutions": {
|
||||
"inflight": "latest",
|
||||
"picomatch": "^4.0.2",
|
||||
"ioredis": "^5.9.3"
|
||||
"ioredis": "^5.10.0"
|
||||
},
|
||||
"packageManager": "pnpm@10.32.0",
|
||||
"packageManager": "pnpm@10.32.1",
|
||||
"workspaces": [
|
||||
"wxmsg"
|
||||
]
|
||||
|
||||
1467
pnpm-lock.yaml
generated
1467
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -61,6 +61,8 @@ type StoreSetOpts = {
|
||||
loginType?: 'default' | 'plugin' | 'month' | 'season' | 'year' | 'week' | 'day'; // 登陆类型 'default' | 'plugin' | 'month' | 'season' | 'year'
|
||||
expire?: number; // 过期时间,单位为秒
|
||||
hasRefreshToken?: boolean;
|
||||
// refreshToken的过期时间比accessToken多多少天,默认是1天
|
||||
expireDay?: number;
|
||||
[key: string]: any;
|
||||
};
|
||||
interface Store<T> {
|
||||
@@ -70,7 +72,7 @@ interface Store<T> {
|
||||
expire: (key: string, ttl?: number) => Promise<void>;
|
||||
delObject: (value?: T) => Promise<void>;
|
||||
keys: (key?: string) => Promise<string[]>;
|
||||
setToken: (value: { accessToken: string; refreshToken: string; value?: T }, opts?: StoreSetOpts) => Promise<TokenData>;
|
||||
setToken: (value: { accessToken: string; refreshToken: string; value?: T, day?: number }, opts?: StoreSetOpts) => Promise<TokenData>;
|
||||
delKeys: (keys: string[]) => Promise<number>;
|
||||
}
|
||||
|
||||
@@ -138,9 +140,11 @@ export class RedisTokenStore implements Store<OauthUser> {
|
||||
await this.del(userPrefix + ':token:' + accessToken);
|
||||
}
|
||||
}
|
||||
async setToken(data: { accessToken: string; refreshToken: string; value?: OauthUser }, opts?: StoreSetOpts): Promise<TokenData> {
|
||||
async setToken(data: { accessToken: string; refreshToken: string; value?: OauthUser, day?: number }, opts?: StoreSetOpts): Promise<TokenData> {
|
||||
const { accessToken, refreshToken, value } = data;
|
||||
let userPrefix = 'user:' + value?.id;
|
||||
const expireDay = data?.day || 1;
|
||||
|
||||
if (value?.orgId) {
|
||||
userPrefix = 'org:' + value?.orgId + ':user:' + value?.id;
|
||||
}
|
||||
@@ -156,28 +160,18 @@ export class RedisTokenStore implements Store<OauthUser> {
|
||||
case 'week':
|
||||
expire = 7 * 24 * 60 * 60;
|
||||
break;
|
||||
case 'month':
|
||||
expire = 30 * 24 * 60 * 60;
|
||||
break;
|
||||
case 'season':
|
||||
expire = 90 * 24 * 60 * 60;
|
||||
break;
|
||||
default:
|
||||
expire = 7 * 24 * 60 * 60; // 默认过期时间为7天
|
||||
}
|
||||
} else {
|
||||
expire = Math.min(expire, 60 * 60 * 24 * 30, 60 * 60 * 24 * 90); // 默认的过期时间最大为90天
|
||||
expire = Math.min(expire, 60 * 60 * 24 * 30); // 默认的过期时间最大为30天
|
||||
}
|
||||
|
||||
await this.set(accessToken, JSON.stringify(value), expire);
|
||||
await this.set(userPrefix + ':token:' + accessToken, accessToken, expire);
|
||||
// refreshToken的过期时间比accessToken多2天,确保在accessToken过期后,refreshToken仍然有效
|
||||
let refreshTokenExpiresIn = expire + 2 * day;
|
||||
// refreshToken的过期时间比accessToken多expireDay天,确保在accessToken过期后,refreshToken仍然有效
|
||||
let refreshTokenExpiresIn = expire + expireDay * day;
|
||||
if (refreshToken) {
|
||||
// 小于7天, 则设置为7天
|
||||
if (refreshTokenExpiresIn < 60 * 60 * 24 * 7) {
|
||||
refreshTokenExpiresIn = 60 * 60 * 24 * 7;
|
||||
}
|
||||
await this.set(refreshToken, JSON.stringify(value), refreshTokenExpiresIn);
|
||||
await this.set(userPrefix + ':refreshToken:' + refreshToken, refreshToken, refreshTokenExpiresIn);
|
||||
}
|
||||
@@ -239,7 +233,7 @@ export class OAuth<T extends OauthUser> {
|
||||
user.oauthExpand.refreshToken = refreshToken;
|
||||
}
|
||||
}
|
||||
const tokenData = await this.store.setToken({ accessToken, refreshToken, value: user }, expandOpts);
|
||||
const tokenData = await this.store.setToken({ accessToken, refreshToken, value: user, day: expandOpts?.day }, expandOpts);
|
||||
|
||||
return tokenData;
|
||||
}
|
||||
@@ -253,7 +247,7 @@ export class OAuth<T extends OauthUser> {
|
||||
createTime: new Date().getTime(), // 创建时间
|
||||
};
|
||||
await this.store.setToken(
|
||||
{ accessToken: secretKey, refreshToken: '', value: oauthUser },
|
||||
{ accessToken: secretKey, refreshToken: '', value: oauthUser, day: opts?.day },
|
||||
{
|
||||
...opts,
|
||||
hasRefreshToken: false,
|
||||
@@ -338,6 +332,7 @@ export class OAuth<T extends OauthUser> {
|
||||
{
|
||||
...user.oauthExpand,
|
||||
hasRefreshToken: true,
|
||||
day: user.oauthExpand?.day,
|
||||
},
|
||||
);
|
||||
console.log('resetToken token', await this.store.keys());
|
||||
@@ -370,6 +365,7 @@ export class OAuth<T extends OauthUser> {
|
||||
{
|
||||
...user.oauthExpand,
|
||||
hasRefreshToken: true,
|
||||
day: user.oauthExpand?.day,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -429,8 +425,8 @@ export class OAuth<T extends OauthUser> {
|
||||
async setJwksToken(token: string, opts: { id: string; expire: number }) {
|
||||
const expire = opts.expire ?? 2 * 3600; // 2 hours
|
||||
const id = opts.id || '-';
|
||||
// jwks token的过期时间比accessToken多3天,确保3天内可以用来refresh token
|
||||
const addExpire = 3 * 24 * 3600;
|
||||
// jwks token的过期时间比accessToken多2天,确保2天内可以用来refresh token
|
||||
const addExpire = 2 * 24 * 3600;
|
||||
await this.store.redis.set('user:jwks:' + token, id, 'EX', expire + addExpire);
|
||||
}
|
||||
async deleteJwksToken(token: string) {
|
||||
|
||||
@@ -330,8 +330,11 @@ export const microAppsUpload = pgTable("micro_apps_upload", {
|
||||
export const microMark = pgTable("micro_mark", {
|
||||
id: uuid().primaryKey().defaultRandom(),
|
||||
title: text().default(''),
|
||||
description: text().default(''),
|
||||
tags: jsonb().default([]),
|
||||
link: text().default(''),
|
||||
summary: text().default(''),
|
||||
description: text().default(''),
|
||||
|
||||
data: jsonb().default({}),
|
||||
uname: varchar({ length: 255 }).default(''),
|
||||
uid: uuid(),
|
||||
@@ -339,8 +342,7 @@ export const microMark = pgTable("micro_mark", {
|
||||
updatedAt: timestamp({ withTimezone: true, mode: 'string' }).notNull().defaultNow(),
|
||||
cover: text().default(''),
|
||||
thumbnail: text().default(''),
|
||||
link: text().default(''),
|
||||
summary: text().default(''),
|
||||
|
||||
markType: text().default('md'),
|
||||
config: jsonb().default({}),
|
||||
puid: uuid(),
|
||||
|
||||
@@ -68,12 +68,20 @@ const getAiProxy = async (req: IncomingMessage, res: ServerResponse, opts: Proxy
|
||||
const password = params.get('p');
|
||||
const hash = params.get('hash');
|
||||
let dir = !!params.get('dir');
|
||||
const edit = !!params.get('edit');
|
||||
const recursive = !!params.get('recursive');
|
||||
const showStat = !!params.get('stat');
|
||||
const { objectName, app, owner, loginUser, isOwner } = await getObjectName(req);
|
||||
if (!dir && _u.pathname.endsWith('/')) {
|
||||
dir = true; // 如果是目录请求,强制设置为true
|
||||
}
|
||||
if (edit) {
|
||||
// 重定向root/codepod/#folder=路径
|
||||
const redirectUrl = `/root/codepod/#folder=${_u.pathname}`;
|
||||
res.writeHead(302, { Location: redirectUrl });
|
||||
res.end();
|
||||
return true;
|
||||
}
|
||||
logger.debug(`proxy request: ${objectName}`, dir);
|
||||
try {
|
||||
if (dir) {
|
||||
|
||||
@@ -48,7 +48,7 @@ export const N5Proxy = async (req: IncomingMessage, res: ServerResponse, opts?:
|
||||
}
|
||||
try {
|
||||
const user = await User.findByPk(userId);
|
||||
const token = await User.createJwksTokenResponse({ id: userId, username: user?.username || '' }, { hasRefreshToken: false });
|
||||
const token = await User.createJwksTokenResponse({ id: userId, username: user?.username || '' }, { hasRefreshToken: true });
|
||||
const urlObj = new URL(link);
|
||||
urlObj.searchParams.set('token', token.accessToken);
|
||||
const resultLink = await fetch(urlObj.toString(), { method: 'GET' }).then(res => res.json())
|
||||
|
||||
@@ -10,11 +10,11 @@ import { getUserConfig } from '@/modules/fm-manager/index.ts';
|
||||
export const rediretHome = async (req: http.IncomingMessage, res: http.ServerResponse) => {
|
||||
const user = await getLoginUser(req);
|
||||
if (!user?.token) {
|
||||
res.writeHead(302, { Location: '/root/home/' });
|
||||
res.writeHead(302, { Location: '/root/center/' });
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
let redirectURL = '/root/home/';
|
||||
let redirectURL = '/root/center/';
|
||||
try {
|
||||
const token = user.token;
|
||||
const resConfig = await getUserConfig(token);
|
||||
|
||||
@@ -28,7 +28,7 @@ export const defaultKeys = [
|
||||
{
|
||||
key: 'user.json',
|
||||
description: '用户配置',
|
||||
data: { key: 'user', version: '1.0.0', redirectURL: '/root/home/' },
|
||||
data: { key: 'user', version: '1.0.0', redirectURL: '/root/center/' },
|
||||
},
|
||||
{
|
||||
key: 'life.json',
|
||||
|
||||
@@ -1,15 +1,23 @@
|
||||
import { eq, desc, and, like, or, count, sql } from 'drizzle-orm';
|
||||
import { app, db, schema } from '../../app.ts';
|
||||
import { MarkServices } from './services/mark.ts';
|
||||
import dayjs from 'dayjs';
|
||||
import { nanoid } from 'nanoid';
|
||||
import z from 'zod';
|
||||
|
||||
app
|
||||
.route({
|
||||
path: 'mark',
|
||||
key: 'list',
|
||||
description: 'mark list.',
|
||||
description: '获取mark列表',
|
||||
middleware: ['auth'],
|
||||
metadata: {
|
||||
args: {
|
||||
page: z.number().optional().describe('页码'),
|
||||
pageSize: z.number().optional().describe('每页数量'),
|
||||
search: z.string().optional().describe('搜索关键词'),
|
||||
markType: z.string().optional().describe('mark类型,simple,wallnote,md,draw等'),
|
||||
sort: z.enum(['DESC', 'ASC']).default('DESC').describe('排序字段'),
|
||||
}
|
||||
}
|
||||
})
|
||||
.define(async (ctx) => {
|
||||
const tokenUser = ctx.state.tokenUser;
|
||||
@@ -25,7 +33,13 @@ app
|
||||
.route({
|
||||
path: 'mark',
|
||||
key: 'getVersion',
|
||||
description: '获取mark版本信息',
|
||||
middleware: ['auth'],
|
||||
metadata: {
|
||||
args: {
|
||||
id: z.string().describe('mark id'),
|
||||
}
|
||||
},
|
||||
})
|
||||
.define(async (ctx) => {
|
||||
const tokenUser = ctx.state.tokenUser;
|
||||
@@ -47,26 +61,6 @@ app
|
||||
};
|
||||
} else {
|
||||
ctx.throw(400, 'id is required');
|
||||
// const [markModel, created] = await MarkModel.findOrCreate({
|
||||
// where: {
|
||||
// uid: tokenUser.id,
|
||||
// puid: tokenUser.uid,
|
||||
// title: dayjs().format('YYYY-MM-DD'),
|
||||
// },
|
||||
// defaults: {
|
||||
// title: dayjs().format('YYYY-MM-DD'),
|
||||
// uid: tokenUser.id,
|
||||
// markType: 'wallnote',
|
||||
// tags: ['daily'],
|
||||
// },
|
||||
// });
|
||||
// ctx.body = {
|
||||
// version: Number(markModel.version),
|
||||
// updatedAt: markModel.updatedAt,
|
||||
// createdAt: markModel.createdAt,
|
||||
// id: markModel.id,
|
||||
// created: created,
|
||||
// };
|
||||
}
|
||||
})
|
||||
.addTo(app);
|
||||
@@ -76,6 +70,13 @@ app
|
||||
path: 'mark',
|
||||
key: 'get',
|
||||
middleware: ['auth'],
|
||||
description: '获取mark详情',
|
||||
metadata: {
|
||||
args: {
|
||||
|
||||
id: z.string().describe('mark id'),
|
||||
}
|
||||
},
|
||||
})
|
||||
.define(async (ctx) => {
|
||||
const tokenUser = ctx.state.tokenUser;
|
||||
@@ -92,24 +93,6 @@ app
|
||||
ctx.body = markModel;
|
||||
} else {
|
||||
ctx.throw(400, 'id is required');
|
||||
// id 不存在,获取当天的title为 日期的一条数据
|
||||
// const [markModel, created] = await MarkModel.findOrCreate({
|
||||
// where: {
|
||||
// uid: tokenUser.id,
|
||||
// puid: tokenUser.uid,
|
||||
// title: dayjs().format('YYYY-MM-DD'),
|
||||
// },
|
||||
// defaults: {
|
||||
// title: dayjs().format('YYYY-MM-DD'),
|
||||
// uid: tokenUser.id,
|
||||
// markType: 'wallnote',
|
||||
// tags: ['daily'],
|
||||
// uname: tokenUser.username,
|
||||
// puid: tokenUser.uid,
|
||||
// version: 1,
|
||||
// },
|
||||
// });
|
||||
// ctx.body = markModel;
|
||||
}
|
||||
})
|
||||
.addTo(app);
|
||||
@@ -119,7 +102,20 @@ app
|
||||
path: 'mark',
|
||||
key: 'update',
|
||||
middleware: ['auth'],
|
||||
description: '更新mark内容',
|
||||
isDebug: true,
|
||||
metadata: {
|
||||
args: {
|
||||
id: z.string().describe('mark id'),
|
||||
data: z.object({
|
||||
title: z.string().default(''),
|
||||
tags: z.any().default([]),
|
||||
link: z.string().default(''),
|
||||
summary: z.string().default(''),
|
||||
description: z.string().default(''),
|
||||
})
|
||||
}
|
||||
},
|
||||
})
|
||||
.define(async (ctx) => {
|
||||
const tokenUser = ctx.state.tokenUser;
|
||||
@@ -161,11 +157,24 @@ app
|
||||
ctx.body = markModel;
|
||||
})
|
||||
.addTo(app);
|
||||
|
||||
|
||||
app
|
||||
.route({
|
||||
path: 'mark',
|
||||
key: 'updateNode',
|
||||
middleware: ['auth'],
|
||||
description: '更新mark节点,支持更新和删除操作',
|
||||
metadata: {
|
||||
args: {
|
||||
id: z.string().describe('mark id'),
|
||||
operate: z.enum(['update', 'delete']).default('update').describe('节点操作类型,update或delete'),
|
||||
data: z.object({
|
||||
id: z.string().describe('节点id'),
|
||||
node: z.any().describe('要更新的节点数据'),
|
||||
}).describe('要更新的节点数据'),
|
||||
}
|
||||
},
|
||||
})
|
||||
.define(async (ctx) => {
|
||||
const tokenUser = ctx.state.tokenUser;
|
||||
@@ -183,7 +192,7 @@ app
|
||||
const currentData = markModel.data as any || {};
|
||||
const nodes = currentData.nodes || [];
|
||||
const nodeIndex = nodes.findIndex((n: any) => n.id === node.id);
|
||||
|
||||
|
||||
let updatedNodes;
|
||||
if (operate === 'delete') {
|
||||
updatedNodes = nodes.filter((n: any) => n.id !== node.id);
|
||||
@@ -193,7 +202,7 @@ app
|
||||
} else {
|
||||
updatedNodes = [...nodes, node];
|
||||
}
|
||||
|
||||
|
||||
const version = Number(markModel.version) + 1;
|
||||
const updated = await db.update(schema.microMark)
|
||||
.set({
|
||||
@@ -211,6 +220,16 @@ app
|
||||
path: 'mark',
|
||||
key: 'updateNodes',
|
||||
middleware: ['auth'],
|
||||
description: '批量更新mark节点,支持更新和删除操作',
|
||||
metadata: {
|
||||
args: {
|
||||
id: z.string().describe('mark id'),
|
||||
nodeOperateList: z.array(z.object({
|
||||
operate: z.enum(['update', 'delete']).default('update').describe('节点操作类型,update或delete'),
|
||||
node: z.any().describe('要更新的节点数据'),
|
||||
})).describe('要更新的节点列表'),
|
||||
}
|
||||
},
|
||||
})
|
||||
.define(async (ctx) => {
|
||||
const tokenUser = ctx.state.tokenUser;
|
||||
@@ -229,15 +248,15 @@ app
|
||||
if (nodeOperateList.some((item: any) => !item.node)) {
|
||||
ctx.throw(400, 'nodeOperateList node is required');
|
||||
}
|
||||
|
||||
|
||||
// Update multiple JSON nodes logic with Drizzle
|
||||
const currentData = markModel.data as any || {};
|
||||
let nodes = currentData.nodes || [];
|
||||
|
||||
|
||||
for (const item of nodeOperateList) {
|
||||
const { node, operate = 'update' } = item;
|
||||
const nodeIndex = nodes.findIndex((n: any) => n.id === node.id);
|
||||
|
||||
|
||||
if (operate === 'delete') {
|
||||
nodes = nodes.filter((n: any) => n.id !== node.id);
|
||||
} else if (nodeIndex >= 0) {
|
||||
@@ -246,7 +265,7 @@ app
|
||||
nodes.push(node);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const version = Number(markModel.version) + 1;
|
||||
const updated = await db.update(schema.microMark)
|
||||
.set({
|
||||
@@ -265,6 +284,11 @@ app
|
||||
path: 'mark',
|
||||
key: 'delete',
|
||||
middleware: ['auth'],
|
||||
metadata: {
|
||||
args: {
|
||||
id: z.string().describe('mark id'),
|
||||
}
|
||||
},
|
||||
})
|
||||
.define(async (ctx) => {
|
||||
const tokenUser = ctx.state.tokenUser;
|
||||
@@ -283,7 +307,51 @@ app
|
||||
.addTo(app);
|
||||
|
||||
app
|
||||
.route({ path: 'mark', key: 'getMenu', description: '获取菜单', middleware: ['auth'] })
|
||||
.route({
|
||||
path: 'mark',
|
||||
key: 'create',
|
||||
description: '创建一个新的mark.',
|
||||
middleware: ['auth'],
|
||||
metadata: {
|
||||
args: {
|
||||
title: z.string().default('').describe('标题'),
|
||||
tags: z.any().default([]).describe('标签'),
|
||||
link: z.string().default('').describe('链接'),
|
||||
summary: z.string().default('').describe('摘要'),
|
||||
description: z.string().default('').describe('描述'),
|
||||
markType: z.string().default('md').describe('mark类型'),
|
||||
config: z.any().default({}).describe('配置'),
|
||||
data: z.any().default({}).describe('数据')
|
||||
}
|
||||
}
|
||||
})
|
||||
.define(async (ctx) => {
|
||||
const tokenUser = ctx.state.tokenUser;
|
||||
const { title, tags, link, summary, description, markType, config, data } = ctx.query;
|
||||
const inserted = await db.insert(schema.microMark).values({
|
||||
title,
|
||||
tags: tags || [],
|
||||
link: link || '',
|
||||
summary: summary || '',
|
||||
description: description || '',
|
||||
markType: markType || 'md',
|
||||
config: config || {},
|
||||
data: data || {},
|
||||
uname: tokenUser.username,
|
||||
uid: tokenUser.id,
|
||||
puid: tokenUser.uid,
|
||||
}).returning();
|
||||
ctx.body = inserted[0];
|
||||
})
|
||||
.addTo(app);
|
||||
|
||||
app
|
||||
.route({
|
||||
path: 'mark',
|
||||
key: 'getMenu',
|
||||
description: '获取mark菜单',
|
||||
middleware: ['auth']
|
||||
})
|
||||
.define(async (ctx) => {
|
||||
const tokenUser = ctx.state.tokenUser;
|
||||
const [rows, totalResult] = await Promise.all([
|
||||
|
||||
@@ -48,7 +48,7 @@ app
|
||||
<script>
|
||||
const redirect = new URL('${reqUrl}', window.location.origin);
|
||||
const encodeRedirect = encodeURIComponent(redirect.toString());
|
||||
const toPage = new URL('/root/home/?user-check=true&redirect='+encodeRedirect, window.location.origin);
|
||||
const toPage = new URL('/root/center/login/?user-check=true&redirect='+encodeRedirect, window.location.origin);
|
||||
setTimeout(() => {
|
||||
window.location.href = toPage.toString();
|
||||
}, 1000);
|
||||
|
||||
@@ -23,16 +23,19 @@
|
||||
],
|
||||
"author": "abearxiong <xiongxiao@xiongxiao.me> (https://www.xiongxiao.me)",
|
||||
"license": "MIT",
|
||||
"packageManager": "pnpm@10.28.2",
|
||||
"packageManager": "pnpm@10.32.1",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@kevisual/context": "^0.0.4",
|
||||
"@kevisual/query": "^0.0.39",
|
||||
"@kevisual/router": "0.0.70",
|
||||
"@types/node": "^25.2.1",
|
||||
"@kevisual/context": "^0.0.8",
|
||||
"@kevisual/query": "^0.0.53",
|
||||
"@kevisual/router": "0.1.4",
|
||||
"@types/node": "^25.5.0",
|
||||
"crypto-js": "^4.2.0",
|
||||
"xml2js": "^0.6.2"
|
||||
},
|
||||
"resolutions": {
|
||||
"ioredis": "^5.10.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/crypto-js": "^4.2.2",
|
||||
"@types/xml2js": "^0.4.14"
|
||||
|
||||
@@ -157,22 +157,23 @@ export class Wx {
|
||||
}
|
||||
const wxMsg = msg as WxMsgText;
|
||||
const question = wxMsg.content;
|
||||
const nocoMsg = {
|
||||
path: 'noco-life',
|
||||
key: "chat",
|
||||
payload: {
|
||||
token: userToken,
|
||||
question,
|
||||
}
|
||||
}
|
||||
const res = await this.query.post(nocoMsg);
|
||||
if (res.code !== 200) {
|
||||
await sendUserText('自动回复失败,请稍后再试:' + res.message);
|
||||
}
|
||||
const content = res.data?.content || ''
|
||||
if (content) {
|
||||
await sendUserText(content);
|
||||
}
|
||||
// const nocoMsg = {
|
||||
// path: 'noco-life',
|
||||
// key: "chat",
|
||||
// payload: {
|
||||
// token: userToken,
|
||||
// question,
|
||||
// }
|
||||
// }
|
||||
// const res = await this.query.post(nocoMsg);
|
||||
// if (res.code !== 200) {
|
||||
// await sendUserText('自动回复失败,请稍后再试:' + res.message);
|
||||
// }
|
||||
// const content = res.data?.content || ''
|
||||
// if (content) {
|
||||
// await sendUserText(content);
|
||||
// }
|
||||
sendUserText('自动回复功能正在开发中,敬请期待!');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user