2
0

routes_system_settings.ts 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. import { Hono } from "hono";
  2. import debug from "debug";
  3. import type {
  4. SystemSetting,
  5. SystemSettingGroupData,
  6. } from "../client/share/types.ts";
  7. import type { Variables, WithAuth } from "./middlewares.ts";
  8. const log = {
  9. api: debug("api:sys"),
  10. };
  11. // 创建系统设置路由
  12. export function createSystemSettingsRoutes(withAuth: WithAuth) {
  13. const settingsRoutes = new Hono<{ Variables: Variables }>();
  14. // 获取所有系统设置(按分组)
  15. settingsRoutes.get('/', withAuth, async (c) => {
  16. try {
  17. const apiClient = c.get('apiClient');
  18. const settings = await apiClient.database
  19. .table('system_settings')
  20. .select('*');
  21. // 按分组整理数据
  22. const groupedSettings = settings.reduce((acc: SystemSettingGroupData[], setting) => {
  23. const groupIndex = acc.findIndex((g: SystemSettingGroupData) => g.name === setting.group);
  24. if (groupIndex === -1) {
  25. acc.push({
  26. name: setting.group,
  27. description: `${setting.group}组设置`,
  28. settings: [{
  29. id: setting.id,
  30. key: setting.key,
  31. value: setting.value,
  32. description: setting.description,
  33. group: setting.group
  34. }]
  35. });
  36. } else {
  37. acc[groupIndex].settings.push({
  38. id: setting.id,
  39. key: setting.key,
  40. value: setting.value,
  41. description: setting.description,
  42. group: setting.group
  43. });
  44. }
  45. return acc;
  46. }, []);
  47. return c.json({
  48. message: '获取系统设置成功',
  49. data: groupedSettings
  50. });
  51. } catch (error) {
  52. log.api('获取系统设置失败:', error);
  53. return c.json({ error: '获取系统设置失败' }, 500);
  54. }
  55. });
  56. // 获取指定分组的系统设置
  57. settingsRoutes.get('/group/:group', withAuth, async (c) => {
  58. try {
  59. const apiClient = c.get('apiClient');
  60. const group = c.req.param('group');
  61. const settings = await apiClient.database
  62. .table('system_settings')
  63. .where('group', group)
  64. .select('*');
  65. return c.json({
  66. message: '获取分组设置成功',
  67. data: settings
  68. });
  69. } catch (error) {
  70. log.api('获取分组设置失败:', error);
  71. return c.json({ error: '获取分组设置失败' }, 500);
  72. }
  73. });
  74. // 更新系统设置
  75. settingsRoutes.put('/:key', withAuth, async (c) => {
  76. try {
  77. const apiClient = c.get('apiClient');
  78. const key = c.req.param('key');
  79. const settingData = await c.req.json();
  80. // 验证设置是否存在
  81. const existingSetting = await apiClient.database
  82. .table('system_settings')
  83. .where('key', key)
  84. .first();
  85. if (!existingSetting) {
  86. return c.json({ error: '设置项不存在' }, 404);
  87. }
  88. // 更新设置
  89. await apiClient.database
  90. .table('system_settings')
  91. .where('key', key)
  92. .update({
  93. value: settingData.value,
  94. updated_at: apiClient.database.fn.now()
  95. });
  96. // 获取更新后的设置
  97. const updatedSetting = await apiClient.database
  98. .table('system_settings')
  99. .where('key', key)
  100. .first();
  101. return c.json({
  102. message: '系统设置已更新',
  103. data: updatedSetting
  104. });
  105. } catch (error) {
  106. log.api('更新系统设置失败:', error);
  107. return c.json({ error: '更新系统设置失败' }, 500);
  108. }
  109. });
  110. // 批量更新系统设置
  111. settingsRoutes.put('/', withAuth, async (c) => {
  112. try {
  113. const apiClient = c.get('apiClient');
  114. const settingsData = await c.req.json();
  115. // 验证数据格式
  116. if (!Array.isArray(settingsData)) {
  117. return c.json({ error: '无效的请求数据格式,应为数组' }, 400);
  118. }
  119. const trxProvider = apiClient.database.transactionProvider();
  120. const trx = await trxProvider();
  121. for (const setting of settingsData) {
  122. if (!setting.key) continue;
  123. // 验证设置是否存在
  124. const existingSetting = await trx.table('system_settings')
  125. .where('key', setting.key)
  126. .first();
  127. if (!existingSetting) {
  128. throw new Error(`设置项 ${setting.key} 不存在`);
  129. }
  130. // 更新设置
  131. await trx.table('system_settings')
  132. .where('key', setting.key)
  133. .update({
  134. value: setting.value,
  135. updated_at: trx.fn.now()
  136. });
  137. }
  138. await trx.commit();
  139. // 获取所有更新后的设置
  140. const updatedSettings = await apiClient.database
  141. .table('system_settings')
  142. .whereIn('key', settingsData.map(s => s.key))
  143. .select('*');
  144. return c.json({
  145. message: '系统设置已批量更新',
  146. data: updatedSettings
  147. });
  148. } catch (error) {
  149. log.api('批量更新系统设置失败:', error);
  150. return c.json({ error: '批量更新系统设置失败' }, 500);
  151. }
  152. });
  153. // 重置系统设置
  154. settingsRoutes.post('/reset', withAuth, async (c) => {
  155. try {
  156. const apiClient = c.get('apiClient');
  157. // 重置为迁移文件中定义的初始值
  158. const trxProvider = apiClient.database.transactionProvider();
  159. const trx = await trxProvider();
  160. // 清空现有设置
  161. await trx.table('system_settings').delete();
  162. // 插入默认设置
  163. await trx.table('system_settings').insert([
  164. // 基础设置组
  165. {
  166. key: 'SITE_NAME',
  167. value: '应用管理系统',
  168. description: '站点名称',
  169. group: 'basic',
  170. created_at: apiClient.database.fn.now(),
  171. updated_at: apiClient.database.fn.now()
  172. },
  173. {
  174. key: 'SITE_DESCRIPTION',
  175. value: '一个强大的应用管理系统',
  176. description: '站点描述',
  177. group: 'basic',
  178. created_at: apiClient.database.fn.now(),
  179. updated_at: apiClient.database.fn.now()
  180. },
  181. {
  182. key: 'SITE_KEYWORDS',
  183. value: '应用管理,系统管理,后台管理',
  184. description: '站点关键词',
  185. group: 'basic',
  186. created_at: apiClient.database.fn.now(),
  187. updated_at: apiClient.database.fn.now()
  188. },
  189. // 功能设置组
  190. {
  191. key: 'ENABLE_REGISTER',
  192. value: 'true',
  193. description: '是否开启注册',
  194. group: 'feature',
  195. created_at: apiClient.database.fn.now(),
  196. updated_at: apiClient.database.fn.now()
  197. },
  198. {
  199. key: 'ENABLE_CAPTCHA',
  200. value: 'true',
  201. description: '是否开启验证码',
  202. group: 'feature',
  203. created_at: apiClient.database.fn.now(),
  204. updated_at: apiClient.database.fn.now()
  205. },
  206. {
  207. key: 'LOGIN_ATTEMPTS',
  208. value: '5',
  209. description: '登录尝试次数',
  210. group: 'feature',
  211. created_at: apiClient.database.fn.now(),
  212. updated_at: apiClient.database.fn.now()
  213. },
  214. // 上传设置组
  215. {
  216. key: 'UPLOAD_MAX_SIZE',
  217. value: '10',
  218. description: '最大上传大小(MB)',
  219. group: 'upload',
  220. created_at: apiClient.database.fn.now(),
  221. updated_at: apiClient.database.fn.now()
  222. },
  223. {
  224. key: 'ALLOWED_FILE_TYPES',
  225. value: 'jpg,jpeg,png,gif,doc,docx,xls,xlsx,pdf',
  226. description: '允许的文件类型',
  227. group: 'upload',
  228. created_at: apiClient.database.fn.now(),
  229. updated_at: apiClient.database.fn.now()
  230. },
  231. // 通知设置组
  232. {
  233. key: 'NOTIFY_ON_LOGIN',
  234. value: 'true',
  235. description: '登录通知',
  236. group: 'notify',
  237. created_at: apiClient.database.fn.now(),
  238. updated_at: apiClient.database.fn.now()
  239. },
  240. {
  241. key: 'NOTIFY_ON_ERROR',
  242. value: 'true',
  243. description: '错误通知',
  244. group: 'notify',
  245. created_at: apiClient.database.fn.now(),
  246. updated_at: apiClient.database.fn.now()
  247. }
  248. ]);
  249. await trx.commit();
  250. const resetSettings = await apiClient.database
  251. .table('system_settings')
  252. .select('*');
  253. return c.json({
  254. message: '系统设置已重置',
  255. data: resetSettings
  256. });
  257. } catch (error) {
  258. log.api('重置系统设置失败:', error);
  259. return c.json({ error: '重置系统设置失败' }, 500);
  260. }
  261. });
  262. return settingsRoutes;
  263. }