| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063 |
- import { Hono } from "hono";
- import debug from "debug";
- import type {
- FileLibrary,
- FileCategory,
- KnowInfo,
- ThemeSettings,
- SystemSetting,
- SystemSettingGroupData,
- } from "../client/share/types.ts";
- import {
- EnableStatus,
- DeleteStatus,
- ThemeMode,
- FontSize,
- CompactMode,
- } from "../client/share/types.ts";
- import type { Variables, WithAuth } from "./app.tsx";
- const log = {
- api: debug("api:sys"),
- };
- // 创建知识库管理路由
- export function createKnowInfoRoutes(withAuth: WithAuth) {
- const knowInfoRoutes = new Hono<{ Variables: Variables }>();
- // 获取知识库文章列表
- knowInfoRoutes.get("/", withAuth, async (c) => {
- try {
- const apiClient = c.get('apiClient');
- // 获取分页参数
- const page = Number(c.req.query("page")) || 1;
- const limit = Number(c.req.query("limit")) || 10;
- const offset = (page - 1) * limit;
- // 获取筛选参数
- const title = c.req.query("title");
- const category = c.req.query("category");
- const tags = c.req.query("tags");
- // 构建查询
- let query = apiClient.database
- .table("know_info")
- .where("is_deleted", 0)
- .orderBy("id", "desc");
- // 应用筛选条件
- if (title) {
- query = query.where("title", "like", `%${title}%`);
- }
- if (category) {
- query = query.where("category", category);
- }
- if (tags) {
- query = query.where("tags", "like", `%${tags}%`);
- }
- // 克隆查询以获取总数
- const countQuery = query.clone();
- // 执行分页查询
- const articles = await query.limit(limit).offset(offset);
- // 获取总数
- const count = await countQuery.count();
- return c.json({
- data: articles,
- pagination: {
- total: Number(count),
- current: page,
- pageSize: limit,
- totalPages: Math.ceil(Number(count) / limit),
- },
- });
- } catch (error) {
- log.api("获取知识库文章列表失败:", error);
- return c.json({ error: "获取知识库文章列表失败" }, 500);
- }
- });
- // 获取单个知识库文章
- knowInfoRoutes.get("/:id", withAuth, async (c) => {
- try {
- const id = Number(c.req.param("id"));
- if (!id || isNaN(id)) {
- return c.json({ error: "无效的文章ID" }, 400);
- }
- const apiClient = c.get('apiClient');
- const [article] = await apiClient.database
- .table("know_info")
- .where({ id, is_deleted: 0 });
- if (!article) {
- return c.json({ error: "文章不存在" }, 404);
- }
- return c.json({message: '获取知识库文章详情成功', data: article});
- } catch (error) {
- log.api("获取知识库文章详情失败:", error);
- return c.json({ error: "获取知识库文章详情失败" }, 500);
- }
- });
- // 创建知识库文章
- knowInfoRoutes.post("/", withAuth, async (c) => {
- try {
- const articleData = (await c.req.json()) as Partial<KnowInfo>;
- // 验证必填字段
- if (!articleData.title) {
- return c.json({ error: "文章标题不能为空" }, 400);
- }
- // 如果作者为空,则使用当前用户的用户名
- if (!articleData.author) {
- const user = c.get("user");
- articleData.author = user ? user.username : "unknown";
- }
- const apiClient = c.get('apiClient');
- const [id] = await apiClient.database
- .table("know_info")
- .insert(articleData);
- // 获取创建的文章
- const [createdArticle] = await apiClient.database
- .table("know_info")
- .where("id", id);
- return c.json({
- message: "知识库文章创建成功",
- data: createdArticle,
- });
- } catch (error) {
- log.api("创建知识库文章失败:", error);
- return c.json({ error: "创建知识库文章失败" }, 500);
- }
- });
- // 更新知识库文章
- knowInfoRoutes.put("/:id", withAuth, async (c) => {
- try {
- const id = Number(c.req.param("id"));
- if (!id || isNaN(id)) {
- return c.json({ error: "无效的文章ID" }, 400);
- }
- const articleData = (await c.req.json()) as Partial<KnowInfo>;
- // 验证必填字段
- if (!articleData.title) {
- return c.json({ error: "文章标题不能为空" }, 400);
- }
- const apiClient = c.get('apiClient');
- // 检查文章是否存在
- const [existingArticle] = await apiClient.database
- .table("know_info")
- .where({ id, is_deleted: 0 });
- if (!existingArticle) {
- return c.json({ error: "文章不存在" }, 404);
- }
- // 更新文章
- await apiClient.database
- .table("know_info")
- .where("id", id)
- .update({
- ...articleData,
- updated_at: apiClient.database.fn.now(),
- });
- // 获取更新后的文章
- const [updatedArticle] = await apiClient.database
- .table("know_info")
- .where("id", id);
- return c.json({
- message: "知识库文章更新成功",
- data: updatedArticle,
- });
- } catch (error) {
- log.api("更新知识库文章失败:", error);
- return c.json({ error: "更新知识库文章失败" }, 500);
- }
- });
- // 删除知识库文章(软删除)
- knowInfoRoutes.delete("/:id", withAuth, async (c) => {
- try {
- const id = Number(c.req.param("id"));
- if (!id || isNaN(id)) {
- return c.json({ error: "无效的文章ID" }, 400);
- }
- const apiClient = c.get('apiClient');
- // 检查文章是否存在
- const [existingArticle] = await apiClient.database
- .table("know_info")
- .where({ id, is_deleted: 0 });
- if (!existingArticle) {
- return c.json({ error: "文章不存在" }, 404);
- }
- // 软删除文章
- await apiClient.database.table("know_info").where("id", id).update({
- is_deleted: 1,
- updated_at: apiClient.database.fn.now(),
- });
- return c.json({
- message: "知识库文章删除成功",
- });
- } catch (error) {
- log.api("删除知识库文章失败:", error);
- return c.json({ error: "删除知识库文章失败" }, 500);
- }
- });
-
- return knowInfoRoutes;
- }
- // 创建文件分类路由
- export function createFileCategoryRoutes(withAuth: WithAuth) {
- const fileCategoryRoutes = new Hono<{ Variables: Variables }>();
- // 获取文件分类列表
- fileCategoryRoutes.get("/", withAuth, async (c) => {
- try {
- const apiClient = c.get('apiClient');
- const page = Number(c.req.query("page")) || 1;
- const pageSize = Number(c.req.query("pageSize")) || 10;
- const offset = (page - 1) * pageSize;
- const search = c.req.query("search") || "";
- let query = apiClient.database.table("file_category").orderBy("id", "desc");
- if (search) {
- query = query.where("name", "like", `%${search}%`);
- }
- const total = await query.clone().count();
- const categories = await query
- .select("id", "name", "code", "description")
- .limit(pageSize)
- .offset(offset);
- return c.json({
- data: categories,
- total: Number(total),
- page,
- pageSize,
- });
- } catch (error) {
- log.api("获取文件分类列表失败:", error);
- return c.json({ error: "获取文件分类列表失败" }, 500);
- }
- });
- // 创建文件分类
- fileCategoryRoutes.post("/", withAuth, async (c) => {
- try {
- const apiClient = c.get('apiClient');
- const data = (await c.req.json()) as Partial<FileCategory>;
- // 验证必填字段
- if (!data.name) {
- return c.json({ error: "分类名称不能为空" }, 400);
- }
- // 插入文件分类
- const [id] = await apiClient.database.table("file_category").insert({
- ...data,
- created_at: apiClient.database.fn.now(),
- updated_at: apiClient.database.fn.now(),
- });
- return c.json({
- message: "文件分类创建成功",
- data: {
- id,
- ...data,
- },
- });
- } catch (error) {
- log.api("创建文件分类失败:", error);
- return c.json({ error: "创建文件分类失败" }, 500);
- }
- });
- // 更新文件分类
- fileCategoryRoutes.put("/:id", withAuth, async (c) => {
- try {
- const apiClient = c.get('apiClient');
- const id = Number(c.req.param("id"));
- if (!id || isNaN(id)) {
- return c.json({ error: "无效的分类ID" }, 400);
- }
- const data = (await c.req.json()) as Partial<FileCategory>;
- // 更新文件分类
- await apiClient.database
- .table("file_category")
- .where("id", id)
- .update({
- ...data,
- updated_at: apiClient.database.fn.now(),
- });
- return c.json({
- message: "文件分类更新成功",
- data: {
- id,
- ...data,
- },
- });
- } catch (error) {
- log.api("更新文件分类失败:", error);
- return c.json({ error: "更新文件分类失败" }, 500);
- }
- });
- // 删除文件分类
- fileCategoryRoutes.delete("/:id", withAuth, async (c) => {
- try {
- const apiClient = c.get('apiClient');
- const id = Number(c.req.param("id"));
- if (!id || isNaN(id)) {
- return c.json({ error: "无效的分类ID" }, 400);
- }
- await apiClient.database.table("file_category").where("id", id).update({
- is_deleted: DeleteStatus.DELETED,
- updated_at: apiClient.database.fn.now(),
- });
- return c.json({
- message: "文件分类删除成功",
- });
- } catch (error) {
- log.api("删除文件分类失败:", error);
- return c.json({ error: "删除文件分类失败" }, 500);
- }
- });
-
- return fileCategoryRoutes;
- }
- // 创建文件上传路由
- export function createFileUploadRoutes(withAuth: WithAuth) {
- const fileUploadRoutes = new Hono<{ Variables: Variables }>();
- // 获取 MinIO 上传策略
- fileUploadRoutes.get("/policy", withAuth, async (c) => {
- try {
- const prefix = c.req.query("prefix") || "uploads/";
- const filename = c.req.query("filename");
- const maxSize = Number(c.req.query("maxSize")) || 10 * 1024 * 1024; // 默认10MB
- if (!filename) {
- return c.json({ error: "文件名不能为空" }, 400);
- }
- const apiClient = c.get('apiClient');
- const policy = await apiClient.storage.getUploadPolicy(
- prefix,
- filename,
- maxSize
- );
- return c.json({
- message: "获取上传策略成功",
- data: policy,
- });
- } catch (error) {
- log.api("获取上传策略失败:", error);
- return c.json({ error: "获取上传策略失败" }, 500);
- }
- });
- // 保存文件信息到文件库
- fileUploadRoutes.post("/save", withAuth, async (c) => {
- try {
- const fileData = (await c.req.json()) as Partial<FileLibrary>;
- const user = c.get("user");
- // 验证必填字段
- if (!fileData.file_name || !fileData.file_path || !fileData.file_type) {
- return c.json({ error: "文件名、路径和类型不能为空" }, 400);
- }
- const apiClient = c.get('apiClient');
- // 设置上传者信息
- if (user) {
- fileData.uploader_id = user.id;
- fileData.uploader_name = user.nickname || user.username;
- }
- // 插入文件库记录
- const [id] = await apiClient.database.table("file_library").insert({
- ...fileData,
- download_count: 0,
- is_disabled: EnableStatus.ENABLED,
- is_deleted: DeleteStatus.NOT_DELETED,
- created_at: apiClient.database.fn.now(),
- updated_at: apiClient.database.fn.now(),
- });
- // 获取插入的数据
- const [insertedFile] = await apiClient.database
- .table("file_library")
- .where("id", id);
- return c.json({
- message: "文件信息保存成功",
- data: insertedFile,
- });
- } catch (error) {
- log.api("保存文件信息失败:", error);
- return c.json({ error: "保存文件信息失败" }, 500);
- }
- });
- // 获取文件列表
- fileUploadRoutes.get("/list", withAuth, async (c) => {
- try {
- const page = Number(c.req.query("page")) || 1;
- const pageSize = Number(c.req.query("pageSize")) || 10;
- const category_id = c.req.query("category_id");
- const fileType = c.req.query("fileType");
- const keyword = c.req.query("keyword");
- const apiClient = c.get('apiClient');
- let query = apiClient.database
- .table("file_library")
- .where("is_deleted", DeleteStatus.NOT_DELETED)
- .orderBy("created_at", "desc");
- // 应用过滤条件
- if (category_id) {
- query = query.where("category_id", category_id);
- }
- if (fileType) {
- query = query.where("file_type", fileType);
- }
- if (keyword) {
- query = query.where((builder) => {
- builder
- .where("file_name", "like", `%${keyword}%`)
- .orWhere("description", "like", `%${keyword}%`)
- .orWhere("tags", "like", `%${keyword}%`);
- });
- }
- // 获取总数
- const total = await query.clone().count();
- // 分页查询
- const files = await query.limit(pageSize).offset((page - 1) * pageSize);
- return c.json({
- message: "获取文件列表成功",
- data: {
- list: files,
- pagination: {
- current: page,
- pageSize,
- total: Number(total),
- },
- },
- });
- } catch (error) {
- log.api("获取文件列表失败:", error);
- return c.json({ error: "获取文件列表失败" }, 500);
- }
- });
- // 获取单个文件信息
- fileUploadRoutes.get("/:id", withAuth, async (c) => {
- try {
- const id = Number(c.req.param("id"));
- if (!id || isNaN(id)) {
- return c.json({ error: "无效的文件ID" }, 400);
- }
- const apiClient = c.get('apiClient');
- const file = await apiClient.database
- .table("file_library")
- .where("id", id)
- .where("is_deleted", DeleteStatus.NOT_DELETED)
- .first();
- if (!file) {
- return c.json({ error: "文件不存在" }, 404);
- }
- return c.json({
- message: "获取文件信息成功",
- data: file,
- });
- } catch (error) {
- log.api("获取文件信息失败:", error);
- return c.json({ error: "获取文件信息失败" }, 500);
- }
- });
- // 增加文件下载计数
- fileUploadRoutes.post("/:id/download", withAuth, async (c) => {
- try {
- const id = Number(c.req.param("id"));
- if (!id || isNaN(id)) {
- return c.json({ error: "无效的文件ID" }, 400);
- }
- const apiClient = c.get('apiClient');
- // 查询文件是否存在
- const file = await apiClient.database
- .table("file_library")
- .where("id", id)
- .where("is_deleted", DeleteStatus.NOT_DELETED)
- .first();
- if (!file) {
- return c.json({ error: "文件不存在" }, 404);
- }
- // 增加下载计数
- await apiClient.database
- .table("file_library")
- .where("id", id)
- .update({
- download_count: apiClient.database.raw("download_count + 1"),
- updated_at: apiClient.database.fn.now(),
- });
- return c.json({
- message: "更新下载计数成功",
- });
- } catch (error) {
- log.api("更新下载计数失败:", error);
- return c.json({ error: "更新下载计数失败" }, 500);
- }
- });
- // 删除文件
- fileUploadRoutes.delete("/:id", withAuth, async (c) => {
- try {
- const id = Number(c.req.param("id"));
- if (!id || isNaN(id)) {
- return c.json({ error: "无效的文件ID" }, 400);
- }
- const apiClient = c.get('apiClient');
- // 查询文件是否存在
- const file = await apiClient.database
- .table("file_library")
- .where("id", id)
- .where("is_deleted", DeleteStatus.NOT_DELETED)
- .first();
- if (!file) {
- return c.json({ error: "文件不存在" }, 404);
- }
- // 软删除文件
- await apiClient.database.table("file_library").where("id", id).update({
- is_deleted: DeleteStatus.DELETED,
- updated_at: apiClient.database.fn.now(),
- });
- return c.json({
- message: "文件删除成功",
- });
- } catch (error) {
- log.api("删除文件失败:", error);
- return c.json({ error: "删除文件失败" }, 500);
- }
- });
-
- return fileUploadRoutes;
- }
- // 创建主题设置路由
- export function createThemeRoutes(withAuth: WithAuth) {
- const themeRoutes = new Hono<{ Variables: Variables }>();
- // 获取当前主题设置
- themeRoutes.get("/", withAuth, async (c) => {
- try {
- const apiClient = c.get('apiClient');
- const user = c.get('user');
- if (!user) {
- return c.json({ error: "未授权访问" }, 401);
- }
- // 获取用户的主题设置
- let themeSettings = await apiClient.database
- .table("theme_settings")
- .where("user_id", user.id)
- .first();
- // 如果用户没有主题设置,则创建默认设置
- if (!themeSettings) {
- const defaultSettings = {
- theme_mode: ThemeMode.LIGHT,
- primary_color: '#1890ff',
- font_size: FontSize.MEDIUM,
- is_compact: CompactMode.NORMAL
- };
- const [id] = await apiClient.database.table("theme_settings").insert({
- user_id: user.id,
- settings: defaultSettings,
- created_at: apiClient.database.fn.now(),
- updated_at: apiClient.database.fn.now(),
- });
- themeSettings = await apiClient.database
- .table("theme_settings")
- .where("id", id)
- .first();
- }
- return c.json({
- message: "获取主题设置成功",
- data: themeSettings?.settings,
- });
- } catch (error) {
- log.api("获取主题设置失败:", error);
- return c.json({ error: "获取主题设置失败" }, 500);
- }
- });
- // 更新主题设置
- themeRoutes.put("/", withAuth, async (c) => {
- try {
- const user = c.get('user');
- const apiClient = c.get('apiClient');
- if (!user) {
- return c.json({ error: "未授权访问" }, 401);
- }
- const themeData = (await c.req.json()) as Partial<ThemeSettings>;
- // 检查用户是否已有主题设置
- const existingTheme = await apiClient.database
- .table("theme_settings")
- .where("user_id", user.id)
- .first();
- if (existingTheme) {
- // 更新现有设置
- const currentSettings = existingTheme.settings || {};
- const updatedSettings = {
- ...currentSettings,
- ...themeData
- };
- await apiClient.database
- .table("theme_settings")
- .where("user_id", user.id)
- .update({
- settings: JSON.stringify(updatedSettings),
- updated_at: apiClient.database.fn.now(),
- });
- } else {
- // 创建新设置
- const defaultSettings = {
- theme_mode: ThemeMode.LIGHT,
- primary_color: '#1890ff',
- font_size: FontSize.MEDIUM,
- is_compact: CompactMode.NORMAL
- };
- const updatedSettings = {
- ...defaultSettings,
- ...themeData
- };
- await apiClient.database.table("theme_settings").insert({
- user_id: user.id,
- settings: updatedSettings,
- created_at: apiClient.database.fn.now(),
- updated_at: apiClient.database.fn.now(),
- });
- }
- // 获取更新后的主题设置
- const updatedTheme = await apiClient.database
- .table("theme_settings")
- .where("user_id", user.id)
- .first();
- return c.json({
- message: "主题设置更新成功",
- data: updatedTheme,
- });
- } catch (error) {
- log.api("更新主题设置失败:", error);
- return c.json({ error: "更新主题设置失败" }, 500);
- }
- });
- // 重置主题设置为默认值
- themeRoutes.post("/reset", withAuth, async (c) => {
- try {
- const user = c.get('user');
- const apiClient = c.get('apiClient');
- if (!user) {
- return c.json({ error: "未授权访问" }, 401);
- }
- // 默认主题设置
- const defaultSettings = {
- theme_mode: ThemeMode.LIGHT,
- primary_color: '#1890ff',
- font_size: FontSize.MEDIUM,
- is_compact: CompactMode.NORMAL
- };
- // 更新用户的主题设置
- await apiClient.database
- .table("theme_settings")
- .where("user_id", user.id)
- .update({
- settings: JSON.stringify(defaultSettings),
- updated_at: apiClient.database.fn.now(),
- });
- // 获取更新后的主题设置
- const updatedTheme = await apiClient.database
- .table("theme_settings")
- .where("user_id", user.id)
- .first();
- return c.json({
- message: "主题设置已重置为默认值",
- data: updatedTheme,
- });
- } catch (error) {
- log.api("重置主题设置失败:", error);
- return c.json({ error: "重置主题设置失败" }, 500);
- }
- });
- return themeRoutes;
- }
- // 创建系统设置路由
- export function createSystemSettingsRoutes(withAuth: WithAuth) {
- const settingsRoutes = new Hono<{ Variables: Variables }>();
- // 获取所有系统设置(按分组)
- settingsRoutes.get('/', withAuth, async (c) => {
- try {
- const apiClient = c.get('apiClient');
- const settings = await apiClient.database
- .table('system_settings')
- .select('*');
- // 按分组整理数据
- const groupedSettings = settings.reduce((acc: SystemSettingGroupData[], setting) => {
- const groupIndex = acc.findIndex((g: SystemSettingGroupData) => g.name === setting.group);
- if (groupIndex === -1) {
- acc.push({
- name: setting.group,
- description: `${setting.group}组设置`,
- settings: [{
- id: setting.id,
- key: setting.key,
- value: setting.value,
- description: setting.description,
- group: setting.group
- }]
- });
- } else {
- acc[groupIndex].settings.push({
- id: setting.id,
- key: setting.key,
- value: setting.value,
- description: setting.description,
- group: setting.group
- });
- }
- return acc;
- }, []);
- return c.json({
- message: '获取系统设置成功',
- data: groupedSettings
- });
- } catch (error) {
- log.api('获取系统设置失败:', error);
- return c.json({ error: '获取系统设置失败' }, 500);
- }
- });
- // 获取指定分组的系统设置
- settingsRoutes.get('/group/:group', withAuth, async (c) => {
- try {
- const apiClient = c.get('apiClient');
- const group = c.req.param('group');
-
- const settings = await apiClient.database
- .table('system_settings')
- .where('group', group)
- .select('*');
- return c.json({
- message: '获取分组设置成功',
- data: settings
- });
- } catch (error) {
- log.api('获取分组设置失败:', error);
- return c.json({ error: '获取分组设置失败' }, 500);
- }
- });
- // 更新系统设置
- settingsRoutes.put('/:key', withAuth, async (c) => {
- try {
- const apiClient = c.get('apiClient');
- const key = c.req.param('key');
- const settingData = await c.req.json();
- // 验证设置是否存在
- const existingSetting = await apiClient.database
- .table('system_settings')
- .where('key', key)
- .first();
- if (!existingSetting) {
- return c.json({ error: '设置项不存在' }, 404);
- }
- // 更新设置
- await apiClient.database
- .table('system_settings')
- .where('key', key)
- .update({
- value: settingData.value,
- updated_at: apiClient.database.fn.now()
- });
- // 获取更新后的设置
- const updatedSetting = await apiClient.database
- .table('system_settings')
- .where('key', key)
- .first();
- return c.json({
- message: '系统设置已更新',
- data: updatedSetting
- });
- } catch (error) {
- log.api('更新系统设置失败:', error);
- return c.json({ error: '更新系统设置失败' }, 500);
- }
- });
- // 批量更新系统设置
- settingsRoutes.put('/', withAuth, async (c) => {
- try {
- const apiClient = c.get('apiClient');
- const settingsData = await c.req.json();
- // 验证数据格式
- if (!Array.isArray(settingsData)) {
- return c.json({ error: '无效的请求数据格式,应为数组' }, 400);
- }
- const trxProvider = apiClient.database.transactionProvider();
- const trx = await trxProvider();
- for (const setting of settingsData) {
- if (!setting.key) continue;
- // 验证设置是否存在
- const existingSetting = await trx.table('system_settings')
- .where('key', setting.key)
- .first();
- if (!existingSetting) {
- throw new Error(`设置项 ${setting.key} 不存在`);
- }
- // 更新设置
- await trx.table('system_settings')
- .where('key', setting.key)
- .update({
- value: setting.value,
- updated_at: trx.fn.now()
- });
- }
- await trx.commit();
- // 获取所有更新后的设置
- const updatedSettings = await apiClient.database
- .table('system_settings')
- .whereIn('key', settingsData.map(s => s.key))
- .select('*');
- return c.json({
- message: '系统设置已批量更新',
- data: updatedSettings
- });
- } catch (error) {
- log.api('批量更新系统设置失败:', error);
- return c.json({ error: '批量更新系统设置失败' }, 500);
- }
- });
- // 重置系统设置
- settingsRoutes.post('/reset', withAuth, async (c) => {
- try {
- const apiClient = c.get('apiClient');
- // 重置为迁移文件中定义的初始值
- const trxProvider = apiClient.database.transactionProvider();
- const trx = await trxProvider();
- // 清空现有设置
- await trx.table('system_settings').delete();
-
- // 插入默认设置
- await trx.table('system_settings').insert([
- // 基础设置组
- {
- key: 'SITE_NAME',
- value: '应用管理系统',
- description: '站点名称',
- group: 'basic',
- created_at: apiClient.database.fn.now(),
- updated_at: apiClient.database.fn.now()
- },
- {
- key: 'SITE_DESCRIPTION',
- value: '一个强大的应用管理系统',
- description: '站点描述',
- group: 'basic',
- created_at: apiClient.database.fn.now(),
- updated_at: apiClient.database.fn.now()
- },
- {
- key: 'SITE_KEYWORDS',
- value: '应用管理,系统管理,后台管理',
- description: '站点关键词',
- group: 'basic',
- created_at: apiClient.database.fn.now(),
- updated_at: apiClient.database.fn.now()
- },
- // 功能设置组
- {
- key: 'ENABLE_REGISTER',
- value: 'true',
- description: '是否开启注册',
- group: 'feature',
- created_at: apiClient.database.fn.now(),
- updated_at: apiClient.database.fn.now()
- },
- {
- key: 'ENABLE_CAPTCHA',
- value: 'true',
- description: '是否开启验证码',
- group: 'feature',
- created_at: apiClient.database.fn.now(),
- updated_at: apiClient.database.fn.now()
- },
- {
- key: 'LOGIN_ATTEMPTS',
- value: '5',
- description: '登录尝试次数',
- group: 'feature',
- created_at: apiClient.database.fn.now(),
- updated_at: apiClient.database.fn.now()
- },
- // 上传设置组
- {
- key: 'UPLOAD_MAX_SIZE',
- value: '10',
- description: '最大上传大小(MB)',
- group: 'upload',
- created_at: apiClient.database.fn.now(),
- updated_at: apiClient.database.fn.now()
- },
- {
- key: 'ALLOWED_FILE_TYPES',
- value: 'jpg,jpeg,png,gif,doc,docx,xls,xlsx,pdf',
- description: '允许的文件类型',
- group: 'upload',
- created_at: apiClient.database.fn.now(),
- updated_at: apiClient.database.fn.now()
- },
- // 通知设置组
- {
- key: 'NOTIFY_ON_LOGIN',
- value: 'true',
- description: '登录通知',
- group: 'notify',
- created_at: apiClient.database.fn.now(),
- updated_at: apiClient.database.fn.now()
- },
- {
- key: 'NOTIFY_ON_ERROR',
- value: 'true',
- description: '错误通知',
- group: 'notify',
- created_at: apiClient.database.fn.now(),
- updated_at: apiClient.database.fn.now()
- }
- ]);
- await trx.commit();
- const resetSettings = await apiClient.database
- .table('system_settings')
- .select('*');
- return c.json({
- message: '系统设置已重置',
- data: resetSettings
- });
- } catch (error) {
- log.api('重置系统设置失败:', error);
- return c.json({ error: '重置系统设置失败' }, 500);
- }
- });
- return settingsRoutes;
- }
|