admin.html 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  1. {% extends "base.html" %}
  2. {% set title = "后台" %}
  3. {% set page = "admin" %}
  4. {% block content %}
  5. <div class="admin-layout">
  6. <aside class="sider">
  7. <div class="sider-title">控制台</div>
  8. <nav class="menu" id="adminMenu">
  9. <a href="#" class="menu-item active" data-section="overview">概览</a>
  10. <a href="#" class="menu-item" data-section="plans">会员方案</a>
  11. <a href="#" class="menu-item" data-section="resources">资源管理</a>
  12. <a href="#" class="menu-item" data-section="uploads">上传管理</a>
  13. <a href="#" class="menu-item" data-section="orders">订单管理</a>
  14. <a href="#" class="menu-item" data-section="users">用户管理</a>
  15. <a href="#" class="menu-item" data-section="download-logs">下载记录</a>
  16. <a href="#" class="menu-item" data-section="messages">消息管理</a>
  17. <a href="#" class="menu-item" data-section="settings">第三方配置</a>
  18. </nav>
  19. <div class="sider-footer">
  20. <button id="adminLogoutBtn" type="button" class="btn btn-block">退出登录</button>
  21. </div>
  22. </aside>
  23. <section class="content">
  24. <div class="content-header">
  25. <h1 id="contentTitle">概览</h1>
  26. </div>
  27. <section id="sec-overview" class="content-section">
  28. <div class="toolbar">
  29. <button id="overviewRefreshBtn" type="button" class="btn">刷新</button>
  30. <span id="overviewUpdatedAt" class="muted"></span>
  31. </div>
  32. <div class="grid" style="margin-top: 12px">
  33. <div class="card metric-card">
  34. <div class="muted metric-label">用户</div>
  35. <div class="metric-value" id="ovUsersTotal">-</div>
  36. <div class="muted metric-sub" id="ovUsersSub">-</div>
  37. </div>
  38. <div class="card metric-card">
  39. <div class="muted metric-label">资源</div>
  40. <div class="metric-value" id="ovResourcesTotal">-</div>
  41. <div class="muted metric-sub" id="ovResourcesSub">-</div>
  42. </div>
  43. <div class="card metric-card">
  44. <div class="muted metric-label">订单</div>
  45. <div class="metric-value" id="ovOrdersTotal">-</div>
  46. <div class="muted metric-sub" id="ovOrdersSub">-</div>
  47. </div>
  48. <div class="card metric-card">
  49. <div class="muted metric-label">收入</div>
  50. <div class="metric-value" id="ovRevenueTotal">-</div>
  51. <div class="muted metric-sub" id="ovRevenueSub">-</div>
  52. </div>
  53. <div class="card metric-card">
  54. <div class="muted metric-label">下载</div>
  55. <div class="metric-value" id="ovDownloadsTotal">-</div>
  56. <div class="muted metric-sub" id="ovDownloadsSub">-</div>
  57. </div>
  58. <div class="card metric-card">
  59. <div class="muted metric-label">消息</div>
  60. <div class="metric-value" id="ovMessagesTotal">-</div>
  61. <div class="muted metric-sub" id="ovMessagesSub">-</div>
  62. </div>
  63. </div>
  64. <div class="card" style="margin-top: 16px">
  65. <h3 style="margin:0">系统</h3>
  66. <div class="muted" style="margin-top: 10px" id="ovSystemInfo">-</div>
  67. </div>
  68. </section>
  69. <section id="sec-plans" class="content-section" style="display:none">
  70. <div class="toolbar">
  71. <button id="createPlanOpenBtn" type="button" class="btn btn-primary">新增方案</button>
  72. </div>
  73. <div class="table-wrap">
  74. <table class="table" id="planTable">
  75. <colgroup>
  76. <col style="width:6%" />
  77. <col style="width:28%" />
  78. <col style="width:12%" />
  79. <col style="width:12%" />
  80. <col style="width:10%" />
  81. <col style="width:10%" />
  82. <col style="width:22%" />
  83. </colgroup>
  84. <thead>
  85. <tr>
  86. <th>ID</th><th>名称</th><th>时长(天)</th><th>价格</th><th>启用</th><th>排序</th><th>操作</th>
  87. </tr>
  88. </thead>
  89. <tbody></tbody>
  90. </table>
  91. </div>
  92. </section>
  93. <section id="sec-resources" class="content-section" style="display:none">
  94. <div class="toolbar">
  95. <input id="resQ" class="input" placeholder="搜索标题/简介/仓库" />
  96. <select id="resTypeFilter" class="input">
  97. <option value="">全部类型</option>
  98. <option value="FREE">免费</option>
  99. <option value="VIP">VIP</option>
  100. </select>
  101. <select id="resStatusFilter" class="input">
  102. <option value="">全部状态</option>
  103. <option value="ONLINE">上架</option>
  104. <option value="OFFLINE">下架</option>
  105. <option value="DRAFT">草稿</option>
  106. </select>
  107. <button id="resSearchBtn" type="button" class="btn">搜索</button>
  108. <button id="createResOpenBtn" type="button" class="btn btn-primary">新增资源</button>
  109. </div>
  110. <div class="table-wrap">
  111. <table class="table" id="resourceTable">
  112. <colgroup>
  113. <col style="width:6%" />
  114. <col style="width:24%" />
  115. <col style="width:6%" />
  116. <col style="width:6%" />
  117. <col style="width:18%" />
  118. <col style="width:15%" />
  119. <col style="width:6%" />
  120. <col style="width:19%" />
  121. </colgroup>
  122. <thead>
  123. <tr>
  124. <th>ID</th><th>标题</th><th>类型</th><th>状态</th><th>仓库 / 分支</th><th>更新</th><th>缓存</th><th>操作</th>
  125. </tr>
  126. </thead>
  127. <tbody></tbody>
  128. </table>
  129. </div>
  130. <div class="pager">
  131. <button id="resPrevPage" class="btn">上一页</button>
  132. <span id="resPageInfo" class="muted"></span>
  133. <button id="resNextPage" class="btn">下一页</button>
  134. </div>
  135. </section>
  136. <section id="sec-uploads" class="content-section" style="display:none">
  137. <div class="toolbar">
  138. <input id="uploadsQ" class="input" placeholder="搜索文件名" />
  139. <div class="btn-group">
  140. <button id="uploadsFilterAll" type="button" class="btn btn-toggle active">全部</button>
  141. <button id="uploadsFilterUnused" type="button" class="btn btn-toggle">未引用</button>
  142. <button id="uploadsFilterUsed" type="button" class="btn btn-toggle">已引用</button>
  143. </div>
  144. <button id="uploadsRefreshBtn" type="button" class="btn">刷新</button>
  145. <button id="uploadsUploadBtn" type="button" class="btn btn-primary">上传文件</button>
  146. <input id="uploadsFile" type="file" style="display:none" multiple />
  147. <button id="uploadsCleanupBtn" type="button" class="btn btn-danger">一键清理未使用</button>
  148. </div>
  149. <div id="uploadsStats" class="muted" style="margin: 8px 0;"></div>
  150. <div class="table-wrap">
  151. <table class="table" id="uploadTable">
  152. <colgroup>
  153. <col style="width:10%" />
  154. <col style="width:38%" />
  155. <col style="width:10%" />
  156. <col style="width:14%" />
  157. <col style="width:8%" />
  158. <col style="width:20%" />
  159. </colgroup>
  160. <thead>
  161. <tr>
  162. <th>预览</th><th>文件</th><th>大小</th><th>修改</th><th>引用</th><th>操作</th>
  163. </tr>
  164. </thead>
  165. <tbody></tbody>
  166. </table>
  167. </div>
  168. </section>
  169. <section id="sec-orders" class="content-section" style="display:none">
  170. <div class="toolbar">
  171. <input id="orderQ" class="input" placeholder="搜索订单号/手机号" />
  172. <select id="orderStatusFilter" class="input">
  173. <option value="">全部状态</option>
  174. <option value="PENDING">待支付</option>
  175. <option value="PAID">已支付</option>
  176. <option value="CLOSED">已关闭</option>
  177. <option value="FAILED">失败</option>
  178. </select>
  179. <button id="orderCreateBtn" type="button" class="btn btn-primary">新建订单</button>
  180. <button id="orderRefreshBtn" type="button" class="btn">刷新</button>
  181. </div>
  182. <div class="table-wrap">
  183. <table class="table" id="orderTable">
  184. <colgroup>
  185. <col style="width:21%" />
  186. <col style="width:6%" />
  187. <col style="width:7%" />
  188. <col style="width:16%" />
  189. <col style="width:6%" />
  190. <col style="width:14%" />
  191. <col style="width:14%" />
  192. <col style="width:12%" />
  193. </colgroup>
  194. <thead>
  195. <tr>
  196. <th>ID</th><th>状态</th><th>金额</th><th>用户</th><th>方案</th><th>创建</th><th>支付</th><th>操作</th>
  197. </tr>
  198. </thead>
  199. <tbody></tbody>
  200. </table>
  201. </div>
  202. <div class="pager">
  203. <button id="orderPrevPage" class="btn">上一页</button>
  204. <span id="orderPageInfo" class="muted"></span>
  205. <button id="orderNextPage" class="btn">下一页</button>
  206. </div>
  207. </section>
  208. <section id="sec-users" class="content-section" style="display:none">
  209. <div class="toolbar">
  210. <input id="userQ" class="input" placeholder="搜索手机号" />
  211. <select id="userStatusFilter" class="input">
  212. <option value="">全部状态</option>
  213. <option value="ACTIVE">启用</option>
  214. <option value="DISABLED">禁用</option>
  215. </select>
  216. <select id="userVipFilter" class="input">
  217. <option value="">全部会员</option>
  218. <option value="VIP">仅 VIP</option>
  219. <option value="NONVIP">仅非 VIP</option>
  220. </select>
  221. <button id="userSearchBtn" type="button" class="btn">搜索</button>
  222. </div>
  223. <div class="table-wrap">
  224. <table class="table" id="userTable">
  225. <colgroup>
  226. <col style="width:6%" />
  227. <col style="width:16%" />
  228. <col style="width:10%" />
  229. <col style="width:14%" />
  230. <col style="width:18%" />
  231. <col style="width:18%" />
  232. <col style="width:16%" />
  233. </colgroup>
  234. <thead>
  235. <tr>
  236. <th>ID</th><th>手机号</th><th>状态</th><th>会员</th><th>会员到期</th><th>注册时间</th><th>操作</th>
  237. </tr>
  238. </thead>
  239. <tbody></tbody>
  240. </table>
  241. </div>
  242. <div class="pager">
  243. <button id="userPrevPage" class="btn">上一页</button>
  244. <span id="userPageInfo" class="muted"></span>
  245. <button id="userNextPage" class="btn">下一页</button>
  246. </div>
  247. </section>
  248. <section id="sec-download-logs" class="content-section" style="display:none">
  249. <div class="toolbar">
  250. <input id="dlQ" class="input" placeholder="搜索手机号/资源/Ref/IP" />
  251. <select id="dlTypeFilter" class="input">
  252. <option value="">全部类型</option>
  253. <option value="FREE">免费</option>
  254. <option value="VIP">VIP</option>
  255. </select>
  256. <select id="dlStateFilter" class="input">
  257. <option value="">全部状态</option>
  258. <option value="ONLINE">资源在线</option>
  259. <option value="OFFLINE">资源下架</option>
  260. <option value="DELETED">资源已删除</option>
  261. </select>
  262. <button id="dlSearchBtn" type="button" class="btn">搜索</button>
  263. </div>
  264. <div class="table-wrap">
  265. <table class="table" id="downloadLogTable">
  266. <colgroup>
  267. <col style="width:6%" />
  268. <col style="width:12%" />
  269. <col style="width:14%" />
  270. <col style="width:26%" />
  271. <col style="width:8%" />
  272. <col style="width:8%" />
  273. <col style="width:8%" />
  274. <col style="width:10%" />
  275. <col style="width:8%" />
  276. </colgroup>
  277. <thead>
  278. <tr>
  279. <th>ID</th><th>下载时间</th><th>用户</th><th>资源</th><th>下载时</th><th>当前</th><th>状态</th><th>IP</th><th>操作</th>
  280. </tr>
  281. </thead>
  282. <tbody></tbody>
  283. </table>
  284. </div>
  285. <div class="pager">
  286. <button id="dlPrevPage" class="btn">上一页</button>
  287. <span id="dlPageInfo" class="muted"></span>
  288. <button id="dlNextPage" class="btn">下一页</button>
  289. </div>
  290. </section>
  291. <section id="sec-messages" class="content-section" style="display:none">
  292. <div class="toolbar">
  293. <input id="msgQ" class="input" placeholder="搜索手机号/标题" />
  294. <select id="msgReadFilter" class="input">
  295. <option value="">全部状态</option>
  296. <option value="unread">未读</option>
  297. <option value="read">已读</option>
  298. </select>
  299. <select id="msgSenderFilter" class="input">
  300. <option value="">全部来源</option>
  301. <option value="ADMIN">管理员</option>
  302. <option value="SYSTEM">系统</option>
  303. </select>
  304. <button id="msgSearchBtn" type="button" class="btn">搜索</button>
  305. <button id="msgSendBtn" type="button" class="btn btn-primary">发送消息</button>
  306. <button id="msgBroadcastBtn" type="button" class="btn">群发</button>
  307. </div>
  308. <div class="table-wrap">
  309. <table class="table" id="msgTable">
  310. <colgroup>
  311. <col style="width:6%" />
  312. <col style="width:14%" />
  313. <col style="width:26%" />
  314. <col style="width:16%" />
  315. <col style="width:10%" />
  316. <col style="width:10%" />
  317. <col style="width:18%" />
  318. </colgroup>
  319. <thead>
  320. <tr>
  321. <th>ID</th><th>用户</th><th>标题</th><th>发送时间</th><th>已读</th><th>来源</th><th>操作</th>
  322. </tr>
  323. </thead>
  324. <tbody></tbody>
  325. </table>
  326. </div>
  327. <div class="pager">
  328. <button id="msgPrevPage" class="btn">上一页</button>
  329. <span id="msgPageInfo" class="muted"></span>
  330. <button id="msgNextPage" class="btn">下一页</button>
  331. </div>
  332. </section>
  333. <section id="sec-settings" class="content-section" style="display:none">
  334. <div class="toolbar">
  335. <button id="settingsRefreshBtn" type="button" class="btn">刷新</button>
  336. <button id="settingsSaveBtn" type="button" class="btn btn-primary">保存</button>
  337. </div>
  338. <div class="card settings-card">
  339. <div class="toolbar settings-toolbar" style="margin:0 0 12px 0">
  340. <input id="cfgSearch" class="input settings-search" placeholder="搜索配置项(例如:gogs / token / mysql)" />
  341. </div>
  342. <div id="cfgGroupNav" class="segmented nowrap settings-nav" style="margin:0 0 12px 0">
  343. <button type="button" class="btn active" data-target="#cfgGroupGogs">Gogs</button>
  344. <button type="button" class="btn" data-target="#cfgGroupPay">支付</button>
  345. <button type="button" class="btn" data-target="#cfgGroupLlm">大模型</button>
  346. <button type="button" class="btn" data-target="#cfgGroupCache">缓存</button>
  347. <button type="button" class="btn" data-target="#cfgGroupStorage">存储</button>
  348. <button type="button" class="btn" data-target="#cfgGroupDb">数据库</button>
  349. </div>
  350. <div id="settingsGroups">
  351. <div id="cfgGroupGogs" class="collapse settings-group" data-open="1">
  352. <button type="button" class="collapse-head">
  353. <div class="collapse-head-left">
  354. <div class="settings-group-title">Gogs</div>
  355. <div class="muted settings-group-desc">仓库读取、分支/标签查询</div>
  356. </div>
  357. <i class="ri-arrow-down-s-line collapse-icon"></i>
  358. </button>
  359. <div class="collapse-body">
  360. <div class="toolbar settings-group-toolbar">
  361. <button id="cfgGogsSaveBtn" type="button" class="btn btn-primary">保存本组</button>
  362. <button id="cfgGogsResetBtn" type="button" class="btn">重置本组</button>
  363. </div>
  364. <div class="form-grid">
  365. <div style="grid-column: 1 / -1">
  366. <div class="label">Base URL</div>
  367. <input id="cfgGogsBaseUrl" class="input" placeholder="例如:https://gogs.example.com" />
  368. </div>
  369. <div style="grid-column: 1 / -1">
  370. <div class="label">Token</div>
  371. <input id="cfgGogsToken" class="input" type="password" placeholder="留空保持不变" />
  372. <label class="muted checkbox-row settings-checkbox">
  373. <input id="cfgClearGogsToken" type="checkbox" />
  374. 清除 Token
  375. </label>
  376. </div>
  377. </div>
  378. </div>
  379. </div>
  380. <div id="cfgGroupPay" class="collapse settings-group" data-open="0">
  381. <button type="button" class="collapse-head">
  382. <div class="collapse-head-left">
  383. <div class="settings-group-title">支付</div>
  384. <div class="muted settings-group-desc">支持 Mock 与支付宝真实支付</div>
  385. </div>
  386. <i class="ri-arrow-down-s-line collapse-icon"></i>
  387. </button>
  388. <div class="collapse-body">
  389. <div class="toolbar settings-group-toolbar">
  390. <button id="cfgPaySaveBtn" type="button" class="btn btn-primary">保存本组</button>
  391. <button id="cfgPayResetBtn" type="button" class="btn">重置本组</button>
  392. </div>
  393. <div class="form-grid">
  394. <div>
  395. <div class="label">Provider</div>
  396. <select id="cfgPayProvider" class="input">
  397. <option value="MOCK">MOCK</option>
  398. <option value="ALIPAY">ALIPAY</option>
  399. <option value="WECHAT">WECHAT</option>
  400. </select>
  401. <label class="muted checkbox-row settings-checkbox">
  402. <input id="cfgEnableMockPay" type="checkbox" />
  403. 启用 Mock 支付
  404. </label>
  405. </div>
  406. <div>
  407. <div class="label">API Key</div>
  408. <input id="cfgPayApiKey" class="input" type="password" placeholder="留空保持不变" />
  409. <label class="muted checkbox-row settings-checkbox">
  410. <input id="cfgClearPayApiKey" type="checkbox" />
  411. 清除 API Key
  412. </label>
  413. </div>
  414. </div>
  415. <div id="cfgAlipayFields" style="margin-top: 12px; display: none;">
  416. <div class="form-grid">
  417. <div>
  418. <div class="label">App ID</div>
  419. <input id="cfgAlipayAppId" class="input" placeholder="例如:2021000123456789" />
  420. </div>
  421. <div>
  422. <div class="label">Gateway</div>
  423. <input id="cfgAlipayGateway" class="input" placeholder="https://openapi.alipay.com/gateway.do" />
  424. </div>
  425. <div style="grid-column: 1 / -1">
  426. <div class="label" style="display:flex; align-items:center; justify-content: space-between; gap: 8px;">
  427. <span>Notify URL</span>
  428. <button id="cfgAlipayUseCurrentNotify" type="button" class="btn btn-ghost">使用当前域名</button>
  429. </div>
  430. <input id="cfgAlipayNotifyUrl" class="input" placeholder="必须公网可达,例如:https://example.com/pay/callback" />
  431. </div>
  432. <div style="grid-column: 1 / -1">
  433. <div class="label" style="display:flex; align-items:center; justify-content: space-between; gap: 8px;">
  434. <span>Return URL</span>
  435. <button id="cfgAlipayUseCurrentReturn" type="button" class="btn btn-ghost">使用当前域名</button>
  436. </div>
  437. <input id="cfgAlipayReturnUrl" class="input" placeholder="可选,例如:https://example.com/ui/me" />
  438. </div>
  439. <div style="grid-column: 1 / -1">
  440. <div class="label">应用私钥(PKCS8 / RSA2)</div>
  441. <textarea id="cfgAlipayPrivateKey" class="input secret-textarea" rows="6" placeholder="留空保持不变"></textarea>
  442. <label class="muted checkbox-row settings-checkbox">
  443. <input id="cfgClearAlipayPrivateKey" type="checkbox" />
  444. 清除私钥
  445. </label>
  446. <label class="muted checkbox-row settings-checkbox">
  447. <input id="cfgShowAlipayPrivateKey" type="checkbox" />
  448. 显示私钥
  449. </label>
  450. </div>
  451. <div style="grid-column: 1 / -1">
  452. <div class="label">支付宝公钥</div>
  453. <textarea id="cfgAlipayPublicKey" class="input secret-textarea" rows="6" placeholder="留空保持不变"></textarea>
  454. <label class="muted checkbox-row settings-checkbox">
  455. <input id="cfgClearAlipayPublicKey" type="checkbox" />
  456. 清除公钥
  457. </label>
  458. <label class="muted checkbox-row settings-checkbox">
  459. <input id="cfgShowAlipayPublicKey" type="checkbox" />
  460. 显示公钥
  461. </label>
  462. </div>
  463. </div>
  464. </div>
  465. </div>
  466. </div>
  467. <div id="cfgGroupLlm" class="collapse settings-group" data-open="0">
  468. <button type="button" class="collapse-head">
  469. <div class="collapse-head-left">
  470. <div class="settings-group-title">大模型</div>
  471. <div class="muted settings-group-desc">智能摘要/检索等能力预留</div>
  472. </div>
  473. <i class="ri-arrow-down-s-line collapse-icon"></i>
  474. </button>
  475. <div class="collapse-body">
  476. <div class="toolbar settings-group-toolbar">
  477. <button id="cfgLlmSaveBtn" type="button" class="btn btn-primary">保存本组</button>
  478. <button id="cfgLlmResetBtn" type="button" class="btn">重置本组</button>
  479. </div>
  480. <div class="form-grid">
  481. <div>
  482. <div class="label">Provider</div>
  483. <input id="cfgLlmProvider" class="input" placeholder="例如:OpenAI / Azure / DeepSeek" />
  484. </div>
  485. <div>
  486. <div class="label">Model</div>
  487. <input id="cfgLlmModel" class="input" placeholder="例如:gpt-4.1-mini" />
  488. </div>
  489. <div style="grid-column: 1 / -1">
  490. <div class="label">Base URL</div>
  491. <input id="cfgLlmBaseUrl" class="input" placeholder="例如:https://api.example.com" />
  492. </div>
  493. <div style="grid-column: 1 / -1">
  494. <div class="label">API Key</div>
  495. <input id="cfgLlmApiKey" class="input" type="password" placeholder="留空保持不变" />
  496. <label class="muted checkbox-row settings-checkbox">
  497. <input id="cfgClearLlmApiKey" type="checkbox" />
  498. 清除 API Key
  499. </label>
  500. </div>
  501. </div>
  502. </div>
  503. </div>
  504. <div id="cfgGroupCache" class="collapse settings-group" data-open="0">
  505. <button type="button" class="collapse-head">
  506. <div class="collapse-head-left">
  507. <div class="settings-group-title">缓存</div>
  508. <div class="muted settings-group-desc">可选 Redis 共享缓存(例如:Gogs 相关接口)</div>
  509. </div>
  510. <i class="ri-arrow-down-s-line collapse-icon"></i>
  511. </button>
  512. <div class="collapse-body">
  513. <div class="toolbar settings-group-toolbar">
  514. <button id="cfgCacheSaveBtn" type="button" class="btn btn-primary">保存本组</button>
  515. <button id="cfgCacheResetBtn" type="button" class="btn">重置本组</button>
  516. </div>
  517. <div class="form-grid">
  518. <div style="grid-column: 1 / -1">
  519. <div class="label">Redis URL</div>
  520. <input id="cfgRedisUrl" class="input" placeholder="例如:redis://:password@127.0.0.1:6379/0" />
  521. <label class="muted checkbox-row settings-checkbox">
  522. <input id="cfgClearRedisUrl" type="checkbox" />
  523. 清除 Redis URL
  524. </label>
  525. </div>
  526. <div style="grid-column: 1 / -1">
  527. <div class="toolbar" style="margin: 0">
  528. <button id="cfgRedisTestBtn" type="button" class="btn">测试连接</button>
  529. </div>
  530. <div id="cfgCacheMsg" class="muted" style="margin-top:8px"></div>
  531. </div>
  532. </div>
  533. </div>
  534. </div>
  535. <div id="cfgGroupStorage" class="collapse settings-group" data-open="0">
  536. <button type="button" class="collapse-head">
  537. <div class="collapse-head-left">
  538. <div class="settings-group-title">存储</div>
  539. <div class="muted settings-group-desc">可选阿里云 OSS,用于后台上传文件管理</div>
  540. </div>
  541. <i class="ri-arrow-down-s-line collapse-icon"></i>
  542. </button>
  543. <div class="collapse-body">
  544. <div class="toolbar settings-group-toolbar">
  545. <button id="cfgStorageSaveBtn" type="button" class="btn btn-primary">保存本组</button>
  546. <button id="cfgStorageResetBtn" type="button" class="btn">重置本组</button>
  547. </div>
  548. <div class="form-grid">
  549. <div>
  550. <div class="label">Provider</div>
  551. <select id="cfgStorageProvider" class="input">
  552. <option value="AUTO">AUTO</option>
  553. <option value="LOCAL">LOCAL</option>
  554. <option value="OSS">OSS</option>
  555. </select>
  556. </div>
  557. <div></div>
  558. <div style="grid-column: 1 / -1">
  559. <div class="label">OSS Endpoint</div>
  560. <input id="cfgOssEndpoint" class="input" placeholder="例如:https://oss-cn-hangzhou.aliyuncs.com" />
  561. </div>
  562. <div>
  563. <div class="label">Bucket</div>
  564. <input id="cfgOssBucket" class="input" placeholder="例如:my-bucket" />
  565. </div>
  566. <div>
  567. <div class="label">AccessKeyId</div>
  568. <input id="cfgOssAccessKeyId" class="input" placeholder="例如:LTAI..." />
  569. </div>
  570. <div style="grid-column: 1 / -1">
  571. <div class="label">AccessKeySecret</div>
  572. <input id="cfgOssAccessKeySecret" class="input" type="password" placeholder="留空保持不变" />
  573. <label class="muted checkbox-row settings-checkbox">
  574. <input id="cfgClearOssAccessKeySecret" type="checkbox" />
  575. 清除 Secret
  576. </label>
  577. </div>
  578. <div style="grid-column: 1 / -1">
  579. <div class="label">Upload Prefix</div>
  580. <input id="cfgOssUploadPrefix" class="input" placeholder="例如:uploads/" />
  581. </div>
  582. <div style="grid-column: 1 / -1">
  583. <div class="label">Public Base URL</div>
  584. <input id="cfgOssPublicBaseUrl" class="input" placeholder="例如:https://cdn.example.com 或 https://bucket.oss-cn-hangzhou.aliyuncs.com" />
  585. </div>
  586. </div>
  587. </div>
  588. </div>
  589. <div id="cfgGroupDb" class="collapse settings-group" data-open="1">
  590. <button type="button" class="collapse-head">
  591. <div class="collapse-head-left">
  592. <div class="settings-group-title">数据库</div>
  593. <div id="cfgDbActive" class="muted settings-group-desc">当前连接:-</div>
  594. </div>
  595. <i class="ri-arrow-down-s-line collapse-icon"></i>
  596. </button>
  597. <div class="collapse-body">
  598. <div class="toolbar settings-group-toolbar">
  599. <button id="cfgDbSaveBtn" type="button" class="btn btn-primary">保存本组</button>
  600. <button id="cfgDbResetBtn" type="button" class="btn">重置本组</button>
  601. </div>
  602. <div class="form-grid">
  603. <div style="grid-column: 1 / -1">
  604. <div class="label">MySQL Host</div>
  605. <input id="cfgMysqlHost" class="input" placeholder="例如:localhost / 127.0.0.1 / mysql.internal" />
  606. </div>
  607. <div>
  608. <div class="label">MySQL Port</div>
  609. <input id="cfgMysqlPort" class="input" placeholder="例如:3306" />
  610. </div>
  611. <div>
  612. <div class="label">MySQL User</div>
  613. <input id="cfgMysqlUser" class="input" placeholder="例如:root" />
  614. </div>
  615. <div style="grid-column: 1 / -1">
  616. <div class="label">MySQL Password</div>
  617. <input id="cfgMysqlPassword" class="input" type="password" placeholder="留空保持不变" />
  618. <label class="muted checkbox-row settings-checkbox">
  619. <input id="cfgClearMysqlPassword" type="checkbox" />
  620. 清除 Password
  621. </label>
  622. </div>
  623. <div style="grid-column: 1 / -1">
  624. <div class="label">MySQL Database</div>
  625. <input id="cfgMysqlDatabase" class="input" placeholder="例如:sourceshare" />
  626. </div>
  627. <div style="grid-column: 1 / -1">
  628. <div class="toolbar" style="margin: 0">
  629. <button id="cfgMysqlTestBtn" type="button" class="btn">测试连接</button>
  630. <button id="cfgDbSwitchMysqlBtn" type="button" class="btn btn-primary">切换到 MySQL(迁移)</button>
  631. <button id="cfgDbSwitchSqliteBtn" type="button" class="btn">切换到 SQLite(迁移)</button>
  632. </div>
  633. <div id="settingsMsg" class="muted" style="margin-top:8px"></div>
  634. </div>
  635. </div>
  636. </div>
  637. </div>
  638. </div>
  639. </div>
  640. </section>
  641. </section>
  642. </div>
  643. <div id="adminModalBackdrop" class="modal-backdrop" style="display:none">
  644. <div class="modal">
  645. <div class="modal-header">
  646. <div id="adminModalTitle" class="modal-title"></div>
  647. <div class="modal-header-right">
  648. <div id="adminModalHeaderActions"></div>
  649. <button id="adminModalClose" type="button" class="btn btn-ghost" style="padding: 4px; min-width: auto; width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center;"><i class="ri-close-line" style="font-size: 1.25rem;"></i></button>
  650. </div>
  651. </div>
  652. <div id="adminModalBody"></div>
  653. <div id="adminModalFooter" class="modal-footer"></div>
  654. </div>
  655. </div>
  656. {% endblock %}
  657. {% block scripts %}
  658. <script src="{{ url_for('static', filename='app_common.js') }}"></script>
  659. <script src="{{ url_for('static', filename='app_admin.js') }}"></script>
  660. {% endblock %}