2026-01-18 05:13:53 +08:00
|
|
|
|
import { query } from "./_generated/server";
|
2026-01-22 18:53:20 +08:00
|
|
|
|
import { mutation } from "./_generated/server";
|
|
|
|
|
|
import { v } from "convex/values";
|
2026-01-18 05:13:53 +08:00
|
|
|
|
import { getAuthUserId } from "@convex-dev/auth/server";
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取当前登录用户
|
|
|
|
|
|
*/
|
|
|
|
|
|
export const currentUser = query({
|
|
|
|
|
|
args: {},
|
|
|
|
|
|
handler: async (ctx) => {
|
|
|
|
|
|
const userId = await getAuthUserId(ctx);
|
|
|
|
|
|
if (userId === null) {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return await ctx.db.get(userId);
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|
2026-01-22 18:53:20 +08:00
|
|
|
|
|
|
|
|
|
|
function normalizeUsername(raw: string): string {
|
|
|
|
|
|
const username = String(raw ?? "").trim();
|
|
|
|
|
|
if (!username) throw new Error("用户名不能为空");
|
|
|
|
|
|
if (username.length < 2 || username.length > 32) throw new Error("用户名长度需为 2-32 个字符");
|
|
|
|
|
|
if (/\s/.test(username)) throw new Error("用户名不能包含空格");
|
|
|
|
|
|
return username;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 设置当前用户的唯一用户名(写入 users.name)
|
|
|
|
|
|
*/
|
|
|
|
|
|
export const setMyUsername = mutation({
|
|
|
|
|
|
args: { username: v.string() },
|
|
|
|
|
|
handler: async (ctx, args) => {
|
|
|
|
|
|
const userId = await getAuthUserId(ctx);
|
|
|
|
|
|
if (userId === null) throw new Error("未登录");
|
|
|
|
|
|
|
|
|
|
|
|
const username = normalizeUsername(args.username);
|
|
|
|
|
|
|
|
|
|
|
|
// 说明:authTables 的 users 表目前没有为 name 建索引,这里用 filter 做一次全表扫描。
|
|
|
|
|
|
// 用户量较小的桌面场景可接受;后续如需优化可增加独立 username 索引表。
|
|
|
|
|
|
const existing = await ctx.db
|
|
|
|
|
|
.query("users")
|
|
|
|
|
|
.filter((q) => q.eq(q.field("name"), username))
|
|
|
|
|
|
.first();
|
|
|
|
|
|
|
|
|
|
|
|
if (existing && String(existing._id) !== String(userId)) {
|
|
|
|
|
|
throw new Error("用户名已被占用");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
await ctx.db.patch(userId, { name: username });
|
|
|
|
|
|
return { ok: true, username };
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|