index.html 74 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091
  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8"/>
  5. <link rel="icon" type="image/svg+xml" href="/wails.png"/>
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"/>
  7. <link rel="stylesheet" href="/style.css"/>
  8. <title>腾图工具箱</title>
  9. <!-- 首屏前置应用主题,避免暗色/亮色切换时闪烁 -->
  10. <script>document.documentElement.dataset.theme = localStorage.getItem('tengtu-theme') || 'dark';</script>
  11. </head>
  12. <body data-file-drop-target>
  13. <!-- 窗口收拢时居中显示的还原圆点:双击还原窗口大小 -->
  14. <div id="compact-restore" title="双击还原窗口"><span></span></div>
  15. <div class="tab-container">
  16. <!-- 标签栏(兼作标题栏):左侧 tab,右侧窗口关闭按钮 -->
  17. <div class="tab-buttons">
  18. <!-- 左侧拖动手柄:圆点提示,留出距离,便于拖动窗口 -->
  19. <div class="tab-drag-handle" title="拖动窗口"><span class="tab-drag-dot"></span></div>
  20. <button class="tab-btn active" data-tab="links">网址</button>
  21. <button class="tab-btn" data-tab="news">新闻</button>
  22. <button class="tab-btn" data-tab="github">Github</button>
  23. <button class="tab-btn" data-tab="stock">股市</button>
  24. <button class="tab-btn" data-tab="todo">待办</button>
  25. <button class="tab-btn" data-tab="record">记录</button>
  26. <button class="tab-btn" data-tab="tools">工具</button>
  27. <button class="tab-btn" data-tab="host">服务</button>
  28. <button class="tab-btn" data-tab="settings">设置</button>
  29. <div class="win-spacer"></div>
  30. <button class="win-close" id="win-close" title="关闭到托盘">×</button>
  31. </div>
  32. <!-- 内容面板 -->
  33. <div class="tab-content">
  34. <!-- 常用网址:设置中配置,点击卡片在浏览器打开 -->
  35. <div class="tab-panel active" id="tab-links">
  36. <div class="card-grid" id="links-grid"></div>
  37. </div>
  38. <!-- 新闻:煎蛋 + 头条热榜,命中关键词的排在前面并高亮 -->
  39. <div class="tab-panel" id="tab-news">
  40. <div class="panel-head">
  41. <div>
  42. <h2>新闻</h2>
  43. </div>
  44. <div class="panel-head-actions">
  45. <span class="github-refresh-time" id="news-refresh-time" title="最后一次成功刷新的时间"></span>
  46. <button class="btn-ghost" id="news-read" title="朗读未点击过的新闻标题">阅读</button>
  47. <button class="btn-ghost" id="news-refresh">刷新</button>
  48. </div>
  49. </div>
  50. <div class="news-list" id="news-list">
  51. <div class="empty-state">
  52. <div class="empty-mark">◈</div>
  53. <div class="empty-title">正在获取新闻…</div>
  54. <div class="empty-text">首次加载需要几秒</div>
  55. </div>
  56. </div>
  57. </div>
  58. <!-- Github:监听设置中仓库的最新提交 -->
  59. <div class="tab-panel" id="tab-github">
  60. <div class="panel-head">
  61. <div class="panel-head-actions">
  62. <span class="github-refresh-time" id="github-refresh-time" title="最后一次成功刷新的时间"></span>
  63. <button class="btn-ghost" id="github-refresh">刷新</button>
  64. </div>
  65. </div>
  66. <div class="repo-list" id="repo-list">
  67. <div class="empty-state">
  68. <div class="empty-mark">◈</div>
  69. <div class="empty-title">正在获取仓库动态…</div>
  70. <div class="empty-text">通过 GitHub API 拉取提交与最新版本</div>
  71. </div>
  72. </div>
  73. <div class="trending-block">
  74. <div class="trending-head">
  75. <h3 class="trending-title">热门仓库 <span class="trending-sub">GitHub Trending</span></h3>
  76. <span class="github-refresh-time" id="trending-refresh-time" title="最后一次成功刷新的时间"></span>
  77. <button class="btn-ghost" id="trending-refresh">刷新</button>
  78. </div>
  79. <div class="trending-list" id="trending-list">
  80. <div class="empty-state">
  81. <div class="empty-mark">◈</div>
  82. <div class="empty-title">正在获取热门仓库…</div>
  83. <div class="empty-text">抓取 github.com/trending,英文简介自动翻译为中文</div>
  84. </div>
  85. </div>
  86. </div>
  87. </div>
  88. <!-- 股市:按设置的代码展示行情 -->
  89. <div class="tab-panel" id="tab-stock">
  90. <div class="panel-head">
  91. <div class="panel-head-actions">
  92. <span class="market-status" id="market-status"><span class="dot"></span>加载中…</span>
  93. <span class="github-refresh-time" id="stock-refresh-time" title="最后一次成功刷新的时间"></span>
  94. <button class="btn-ghost" id="stock-refresh">刷新</button>
  95. </div>
  96. </div>
  97. <div class="stock-list" id="stock-list">
  98. <div class="empty-state">
  99. <div class="empty-mark">◈</div>
  100. <div class="empty-title">正在获取行情…</div>
  101. <div class="empty-text">首次加载需要几秒</div>
  102. </div>
  103. </div>
  104. </div>
  105. <!-- 待办:每行记录一个待完成任务,可勾选完成 / 编辑 / 删除 -->
  106. <div class="tab-panel panel-todo" id="tab-todo">
  107. <div class="panel-head">
  108. <div class="todo-path-desc" id="todo-path-desc"></div>
  109. <button class="btn-ghost" id="todo-save">保存</button>
  110. </div>
  111. <div class="todo-list" id="todo-list"></div>
  112. <div class="todo-actions">
  113. <button class="btn-ghost" id="todo-add">添加任务</button>
  114. </div>
  115. <div class="todo-status" id="todo-status"></div>
  116. </div>
  117. <!-- 记录:每行一条「姓名|名称|值」,保存到 SQLite 数据库;姓名/名称输入可自动补全历史值 -->
  118. <div class="tab-panel panel-record" id="tab-record">
  119. <div class="panel-head">
  120. <div class="record-path-desc" id="record-path-desc"></div>
  121. <button class="btn-ghost" id="record-save">保存</button>
  122. </div>
  123. <div class="record-toolbar">
  124. <label class="record-label">姓名
  125. <select class="input record-select" id="record-name-filter"><option value="">全部</option></select>
  126. </label>
  127. <label class="record-label">名称
  128. <select class="input record-select" id="record-item-filter"><option value="">全部</option></select>
  129. </label>
  130. <label class="record-label">从
  131. <input class="input record-date" id="record-date-from" type="date">
  132. </label>
  133. <label class="record-label">到
  134. <input class="input record-date" id="record-date-to" type="date">
  135. </label>
  136. <button class="btn-ghost" id="record-filter-clear" title="清除时间过滤">清除</button>
  137. <span class="record-count" id="record-count"></span>
  138. </div>
  139. <div class="record-chart-wrap">
  140. <canvas class="record-chart" id="record-chart"></canvas>
  141. <div class="record-chart-tooltip" id="record-chart-tooltip" hidden></div>
  142. <div class="record-chart-empty" id="record-chart-empty">请先选择姓名,才显示柱状图(可选名称进一步筛选)</div>
  143. </div>
  144. <!-- 自动补全候选:姓名/名称输入框通过 list 属性引用;随数据库历史值刷新。
  145. 必须放在 record-list 容器之外,避免 loadRecords() 的 innerHTML='' 把它们清空 -->
  146. <datalist id="record-names-dl"></datalist>
  147. <datalist id="record-items-dl"></datalist>
  148. <div class="record-list" id="record-list"></div>
  149. <div class="record-actions">
  150. <button class="btn-ghost" id="record-add">添加记录</button>
  151. </div>
  152. <div class="record-status" id="record-status"></div>
  153. </div>
  154. <!-- 工具:本地开发/运维辅助工具集 -->
  155. <div class="tab-panel" id="tab-tools">
  156. <!-- 工具 1:Web 服务——选择目录,开启本地浏览服务 -->
  157. <div class="tool-card is-collapsed" data-tool="websvc">
  158. <div class="tool-card-head" role="button" tabindex="0" aria-expanded="false">
  159. <span class="tool-card-title"><span class="tool-arrow">▸</span><span class="dot"></span>Web 服务</span>
  160. <span class="tool-status" id="websvc-status"></span>
  161. <span class="tool-order-btns"><button class="tool-order-btn tool-up" type="button" title="上移">↑</button><button class="tool-order-btn tool-down" type="button" title="下移">↓</button></span>
  162. </div>
  163. <div class="tool-card-body">
  164. <p class="tool-desc">选择任意目录,在本机开启浏览服务,默认页为 <code>index.html</code> 或 <code>readme.md</code>。</p>
  165. <div class="tool-row">
  166. <input class="input tool-dir" id="websvc-dir" type="text" placeholder="未选择目录" readonly>
  167. <button class="btn-ghost" id="websvc-pick">选择目录</button>
  168. </div>
  169. <div class="tool-row tool-actions">
  170. <button class="btn-primary" id="websvc-toggle">开启浏览服务</button>
  171. <span class="tool-hint" id="websvc-hint"></span>
  172. </div>
  173. <div class="websvc-preview" id="websvc-preview" hidden>
  174. <iframe id="websvc-frame" title="Web 服务预览"></iframe>
  175. </div>
  176. </div>
  177. </div>
  178. <!-- 工具 2:翻译——中文→英文 / 英文→中文,自动检测 -->
  179. <div class="tool-card is-collapsed" data-tool="translate">
  180. <div class="tool-card-head" role="button" tabindex="0" aria-expanded="false">
  181. <span class="tool-card-title"><span class="tool-arrow">▸</span><span class="dot"></span>翻译</span>
  182. <span class="tool-status" id="tr-status"></span>
  183. <span class="tool-order-btns"><button class="tool-order-btn tool-up" type="button" title="上移">↑</button><button class="tool-order-btn tool-down" type="button" title="下移">↓</button></span>
  184. </div>
  185. <div class="tool-card-body">
  186. <p class="tool-desc">输入中文自动翻译为英文,输入英文自动翻译为中文。免费接口有每日配额,超额请稍后再试。</p>
  187. <textarea class="input tr-input" id="tr-source" rows="3" placeholder="输入要翻译的中文或英文……"></textarea>
  188. <div class="tool-row tool-actions">
  189. <button class="btn-primary" id="tr-go">翻译</button>
  190. <span class="tool-hint" id="tr-hint"></span>
  191. </div>
  192. <div class="tr-result" id="tr-result" hidden></div>
  193. </div>
  194. </div>
  195. <!-- 工具 3:二维码生成——输入字符串生成二维码图片 -->
  196. <div class="tool-card is-collapsed" data-tool="qrcode">
  197. <div class="tool-card-head" role="button" tabindex="0" aria-expanded="false">
  198. <span class="tool-card-title"><span class="tool-arrow">▸</span><span class="dot"></span>二维码生成</span>
  199. <span class="tool-status" id="qr-status"></span>
  200. <span class="tool-order-btns"><button class="tool-order-btn tool-up" type="button" title="上移">↑</button><button class="tool-order-btn tool-down" type="button" title="下移">↓</button></span>
  201. </div>
  202. <div class="tool-card-body">
  203. <p class="tool-desc">输入任意字符串,即时生成二维码图片。可用于网址、文本、联系方式等。</p>
  204. <textarea class="input tr-input" id="qr-input" rows="3" placeholder="输入要生成二维码的内容……"></textarea>
  205. <div class="tool-row tool-actions">
  206. <button class="btn-primary" id="qr-go">生成二维码</button>
  207. <span class="tool-hint" id="qr-hint"></span>
  208. </div>
  209. <div class="qr-box" id="qr-box" hidden>
  210. <img id="qr-img" alt="二维码" title="点击下载 PNG">
  211. <button class="btn-ghost" id="qr-save">下载 PNG</button>
  212. </div>
  213. </div>
  214. </div>
  215. <!-- 工具 4:发送 ntfy 消息——输入主题 / 标题 / 内容,推送到 ntfy 频道 -->
  216. <div class="tool-card is-collapsed" data-tool="ntfy">
  217. <div class="tool-card-head" role="button" tabindex="0" aria-expanded="false">
  218. <span class="tool-card-title"><span class="tool-arrow">▸</span><span class="dot"></span>发送 ntfy 消息</span>
  219. <span class="tool-status" id="ntfy-status"></span>
  220. <span class="tool-order-btns"><button class="tool-order-btn tool-up" type="button" title="上移">↑</button><button class="tool-order-btn tool-down" type="button" title="下移">↓</button></span>
  221. </div>
  222. <div class="tool-card-body">
  223. <p class="tool-desc">向 ntfy 服务推送通知,用于手机 / 浏览器 / 其他设备即时提醒。主题(Topic)为监听频道名,输入过的主题会自动记忆。</p>
  224. <div class="tool-row">
  225. <input class="input" id="ntfy-topic" type="text" placeholder="主题(Topic),如 my-alerts" list="ntfy-topic-list" autocomplete="off">
  226. <datalist id="ntfy-topic-list"></datalist>
  227. </div>
  228. <input class="input" id="ntfy-title" type="text" placeholder="标题(可留空)">
  229. <textarea class="input tr-input" id="ntfy-message" rows="3" placeholder="输入要发送的消息内容……"></textarea>
  230. <div class="tool-row tool-actions">
  231. <button class="btn-primary" id="ntfy-go">发送</button>
  232. <span class="tool-hint" id="ntfy-hint"></span>
  233. </div>
  234. </div>
  235. </div>
  236. <!-- 工具 5:ntfy 聊天室——输入昵称与主题,订阅并实时收发消息(QQ 气泡风格) -->
  237. <div class="tool-card is-collapsed" data-tool="chat">
  238. <div class="tool-card-head" role="button" tabindex="0" aria-expanded="false">
  239. <span class="tool-card-title"><span class="tool-arrow">▸</span><span class="dot"></span>ntfy 聊天室</span>
  240. <span class="tool-status" id="chat-status"></span>
  241. <span class="tool-order-btns"><button class="tool-order-btn tool-up" type="button" title="上移">↑</button><button class="tool-order-btn tool-down" type="button" title="下移">↓</button></span>
  242. </div>
  243. <div class="tool-card-body">
  244. <p class="tool-desc">输入昵称(作为发送方标识,记忆上次使用)与聊天室名称(ntfy 主题)后开始监听,像 QQ 一样左右气泡收发消息。</p>
  245. <div class="tool-row">
  246. <input class="input" id="chat-nickname" type="text" placeholder="昵称(作为发送方标题)" list="ntfy-nickname-list" autocomplete="off">
  247. <input class="input" id="chat-topic" type="text" placeholder="聊天室名称(ntfy 主题),留空则不监听" list="ntfy-topic-list" autocomplete="off">
  248. <button class="btn-ghost" id="chat-toggle">开始监听</button>
  249. </div>
  250. <div class="chat-box" id="chat-box" hidden>
  251. <div class="chat-list" id="chat-list"></div>
  252. <div class="chat-input-row">
  253. <input class="input" id="chat-message" type="text" placeholder="输入消息,回车发送" autocomplete="off">
  254. <button class="btn-ghost" id="chat-send">发送</button>
  255. </div>
  256. </div>
  257. </div>
  258. </div>
  259. <!-- 工具 6:古诗词——显示 footer 最近获取的古诗,可刷新获取新诗 -->
  260. <div class="tool-card is-collapsed" data-tool="poem">
  261. <div class="tool-card-head" role="button" tabindex="0" aria-expanded="false">
  262. <span class="tool-card-title"><span class="tool-arrow">▸</span><span class="dot"></span>古诗词</span>
  263. <span class="tool-status" id="poem-status"></span>
  264. <span class="tool-order-btns"><button class="tool-order-btn tool-up" type="button" title="上移">↑</button><button class="tool-order-btn tool-down" type="button" title="下移">↓</button></span>
  265. </div>
  266. <div class="tool-card-body">
  267. <p class="tool-desc">显示主窗口 footer 最近获取到的古诗词内容,可手动刷新获取新的一首。数据来自古诗词网随机接口。</p>
  268. <div class="tool-row tool-actions">
  269. <button class="btn-primary" id="poem-tool-refresh">刷新获取</button>
  270. <button class="btn-ghost" id="poem-tool-read">朗读</button>
  271. <span class="tool-hint" id="poem-tool-hint"></span>
  272. </div>
  273. <div class="poem-tool" id="poem-tool-box" hidden>
  274. <div class="poem-tool-title" id="poem-tool-title"></div>
  275. <div class="poem-tool-author" id="poem-tool-author"></div>
  276. <div class="poem-tool-content" id="poem-tool-content"></div>
  277. </div>
  278. </div>
  279. </div>
  280. <!-- 工具 7:屏幕截图——隐藏本程序后截取全屏,完成后重新显示 -->
  281. <div class="tool-card is-collapsed" data-tool="screenshot">
  282. <div class="tool-card-head" role="button" tabindex="0" aria-expanded="false">
  283. <span class="tool-card-title"><span class="tool-arrow">▸</span><span class="dot"></span>屏幕截图</span>
  284. <span class="tool-status" id="shot-status"></span>
  285. <span class="tool-order-btns"><button class="tool-order-btn tool-up" type="button" title="上移">↑</button><button class="tool-order-btn tool-down" type="button" title="下移">↓</button></span>
  286. </div>
  287. <div class="tool-card-body">
  288. <p class="tool-desc">点击截屏后自动隐藏本程序窗口,截取整个屏幕(全部显示器),完成后重新显示并预览。截到的画面不含本程序自身。</p>
  289. <div class="tool-row tool-actions">
  290. <button class="btn-primary" id="shot-capture">截屏</button>
  291. <span class="tool-hint" id="shot-hint"></span>
  292. </div>
  293. <div class="screenshot-box" id="screenshot-box" hidden>
  294. <div class="screenshot-head">
  295. <span class="card-title"><span class="dot"></span>屏幕截图</span>
  296. <span class="screenshot-hint" id="screenshot-hint"></span>
  297. </div>
  298. <img id="screenshot-img" alt="屏幕截图预览">
  299. </div>
  300. </div>
  301. </div>
  302. <!-- 工具 8:延时关机——输入多少分钟后关机,交给系统倒计时 -->
  303. <div class="tool-card is-collapsed" data-tool="shutdown">
  304. <div class="tool-card-head" role="button" tabindex="0" aria-expanded="false">
  305. <span class="tool-card-title"><span class="tool-arrow">▸</span><span class="dot"></span>延时关机</span>
  306. <span class="tool-status" id="sd-status"></span>
  307. <span class="tool-order-btns"><button class="tool-order-btn tool-up" type="button" title="上移">↑</button><button class="tool-order-btn tool-down" type="button" title="下移">↓</button></span>
  308. </div>
  309. <div class="tool-card-body">
  310. <p class="tool-desc">输入多少分钟后关机,确认后交给系统倒计时(即使本程序退出仍会执行),也可随时取消。</p>
  311. <div class="tool-row">
  312. <input class="input" id="sd-minutes" type="number" min="1" max="1440" step="1" placeholder="分钟数" style="width:120px">
  313. <button class="btn-primary" id="sd-go">延时关机</button>
  314. <button class="btn-ghost" id="sd-cancel">取消</button>
  315. <span class="tool-hint" id="sd-hint"></span>
  316. </div>
  317. </div>
  318. </div>
  319. <!-- 工具 9:MD5 加密——输入字符串,生成 32 位 MD5 摘要 -->
  320. <div class="tool-card is-collapsed" data-tool="md5">
  321. <div class="tool-card-head" role="button" tabindex="0" aria-expanded="false">
  322. <span class="tool-card-title"><span class="tool-arrow">▸</span><span class="dot"></span>MD5 加密</span>
  323. <span class="tool-status" id="md5-status"></span>
  324. <span class="tool-order-btns"><button class="tool-order-btn tool-up" type="button" title="上移">↑</button><button class="tool-order-btn tool-down" type="button" title="下移">↓</button></span>
  325. </div>
  326. <div class="tool-card-body">
  327. <p class="tool-desc">输入任意字符串,计算其 32 位小写十六进制 MD5 摘要。常用于文件/字符串校验,注意 MD5 已不适合密码存储。</p>
  328. <textarea class="input tr-input" id="md5-input" rows="3" placeholder="输入要计算 MD5 的字符串……"></textarea>
  329. <div class="tool-row tool-actions">
  330. <button class="btn-primary" id="md5-go">计算 MD5</button>
  331. <span class="tool-hint" id="md5-hint"></span>
  332. </div>
  333. <div class="hash-result" id="md5-result" hidden></div>
  334. </div>
  335. </div>
  336. <!-- 工具 10:SHA256 编码——输入字符串,生成 SHA256 摘要 -->
  337. <div class="tool-card is-collapsed" data-tool="sha256">
  338. <div class="tool-card-head" role="button" tabindex="0" aria-expanded="false">
  339. <span class="tool-card-title"><span class="tool-arrow">▸</span><span class="dot"></span>SHA256 编码</span>
  340. <span class="tool-status" id="sha-status"></span>
  341. <span class="tool-order-btns"><button class="tool-order-btn tool-up" type="button" title="上移">↑</button><button class="tool-order-btn tool-down" type="button" title="下移">↓</button></span>
  342. </div>
  343. <div class="tool-card-body">
  344. <p class="tool-desc">输入任意字符串,计算其 64 位小写十六进制 SHA256 摘要。适用于校验、签名与安全存储。</p>
  345. <textarea class="input tr-input" id="sha-input" rows="3" placeholder="输入要计算 SHA256 的字符串……"></textarea>
  346. <div class="tool-row tool-actions">
  347. <button class="btn-primary" id="sha-go">计算 SHA256</button>
  348. <span class="tool-hint" id="sha-hint"></span>
  349. </div>
  350. <div class="hash-result" id="sha-result" hidden></div>
  351. </div>
  352. </div>
  353. <!-- 工具 11:LED 滚动文字——输入文字(可汉字),转换为 LED 点阵独立窗口滚动显示 -->
  354. <div class="tool-card is-collapsed" data-tool="led">
  355. <div class="tool-card-head" role="button" tabindex="0" aria-expanded="false">
  356. <span class="tool-card-title"><span class="tool-arrow">▸</span><span class="dot"></span>LED 滚动文字</span>
  357. <span class="tool-status" id="led-status"></span>
  358. <span class="tool-order-btns"><button class="tool-order-btn tool-up" type="button" title="上移">↑</button><button class="tool-order-btn tool-down" type="button" title="下移">↓</button></span>
  359. </div>
  360. <div class="tool-card-body">
  361. <p class="tool-desc">输入文字(支持中文),转换为 LED 点阵,在独立的无边框置顶透明窗口中横向滚动显示。窗口可拖动、可关闭。</p>
  362. <input class="input" id="led-text" type="text" placeholder="输入要滚动的文字,如 你好 世界">
  363. <div class="tool-row tool-actions">
  364. <label class="color-field" title="点阵颜色">
  365. <input type="color" id="led-color" value="#ff4d4d">
  366. <span>颜色</span>
  367. </label>
  368. <label class="speed-field" title="滚动速度(像素/秒)">
  369. <input type="number" id="led-speed" value="60" min="10" max="600" step="10">
  370. <span>速度</span>
  371. </label>
  372. <button class="btn-primary" id="led-go">打开 LED 窗口</button>
  373. <button class="btn-ghost" id="led-close">关闭窗口</button>
  374. <span class="tool-hint" id="led-hint"></span>
  375. </div>
  376. </div>
  377. </div>
  378. <!-- 工具 12:定时提醒——输入提醒信息与间隔分钟数,每 xx 分钟提醒一次直到取消 -->
  379. <div class="tool-card is-collapsed" data-tool="reminder">
  380. <div class="tool-card-head" role="button" tabindex="0" aria-expanded="false">
  381. <span class="tool-card-title"><span class="tool-arrow">▸</span><span class="dot"></span>定时提醒</span>
  382. <span class="tool-status" id="remind-status"></span>
  383. <span class="tool-order-btns"><button class="tool-order-btn tool-up" type="button" title="上移">↑</button><button class="tool-order-btn tool-down" type="button" title="下移">↓</button></span>
  384. </div>
  385. <div class="tool-card-body">
  386. <p class="tool-desc">输入提醒信息与间隔分钟数,每 xx 分钟弹出一次提醒,直到手动取消。适合定时喝水、休息、吃药等。</p>
  387. <input class="input" id="remind-message" type="text" placeholder="提醒信息,如:该喝水了">
  388. <div class="tool-row tool-actions">
  389. <input class="input" id="remind-minutes" type="number" min="1" max="1440" step="1" placeholder="间隔(分钟)" style="width:120px">
  390. <button class="btn-primary" id="remind-go">开始提醒</button>
  391. <button class="btn-ghost" id="remind-stop">取消提醒</button>
  392. <span class="tool-hint" id="remind-hint"></span>
  393. </div>
  394. </div>
  395. </div>
  396. <!-- 工具 13:LocalSend 文件互传——组播发现设备,HTTPS 接收文件 -->
  397. <div class="tool-card is-collapsed" data-tool="localsend">
  398. <div class="tool-card-head" role="button" tabindex="0" aria-expanded="false">
  399. <span class="tool-card-title" title="与局域网内的 LocalSend 客户端(手机 / 电脑)互相发现并互传文件。启动后:其他设备可发送文件到本机(按设置中的「接收模式」自动或手动接收);也可从本机选择文件发送给发现的设备。本机名、接收位置、接收模式在「设置 → LocalSend」中配置。"><span class="tool-arrow">▸</span><span class="dot"></span>LocalSend 互传</span>
  400. <span class="tool-status" id="localsend-status"></span>
  401. <span class="tool-order-btns"><button class="tool-order-btn tool-up" type="button" title="上移">↑</button><button class="tool-order-btn tool-down" type="button" title="下移">↓</button></span>
  402. </div>
  403. <div class="tool-card-body">
  404. <div class="tool-row">
  405. <button class="btn-primary" id="localsend-toggle">启动服务</button>
  406. <span class="tool-hint" id="localsend-hint"></span>
  407. </div>
  408. <div class="localsend-devices" id="localsend-devices" hidden>
  409. <div class="card-title"><span class="dot"></span>发现设备</div>
  410. <span class="tool-hint" id="localsend-send-hint"></span>
  411. <ul class="localsend-device-list" id="localsend-device-list"></ul>
  412. </div>
  413. </div>
  414. </div>
  415. <!-- 工具 14:Croc 传送——自动检测 PATH 中的 croc CLI,点对点加密传输文件 -->
  416. <div class="tool-card is-collapsed" data-tool="croc" id="croc-card" style="display:none">
  417. <div class="tool-card-head" role="button" tabindex="0" aria-expanded="false">
  418. <span class="tool-card-title" title="通过 croc 命令行工具在任意两台电脑间点对点加密传输文件(自动检测系统 PATH 中的 croc)。点击「启动」用设置中的密码作为传输码开始接收,再点一次停止;点击「发送」选择文件后发送,密码同样作为传输码。密码与接收目录在「设置 → 工具」中配置。"><span class="tool-arrow">▸</span><span class="dot"></span>Croc 传送</span>
  419. <span class="tool-status" id="croc-status"></span>
  420. <span class="tool-order-btns"><button class="tool-order-btn tool-up" type="button" title="上移">↑</button><button class="tool-order-btn tool-down" type="button" title="下移">↓</button></span>
  421. </div>
  422. <div class="tool-card-body">
  423. <div class="tool-row tool-actions">
  424. <button class="btn-ghost" id="croc-toggle" type="button">启动</button>
  425. <button class="btn-primary" id="croc-send" type="button">发送</button>
  426. <span class="tool-hint" id="croc-hint"></span>
  427. </div>
  428. <pre class="croc-log" id="croc-log" hidden></pre>
  429. </div>
  430. </div>
  431. <!-- 工具 15:视频下载——自动检测 PATH 中的 yt-dlp,监视剪贴板中的 B 站链接 -->
  432. <div class="tool-card is-collapsed" data-tool="ytdlp" id="ytdlp-card" style="display:none">
  433. <div class="tool-card-head" role="button" tabindex="0" aria-expanded="false">
  434. <span class="tool-card-title" title="自动检测系统 PATH 中的 yt-dlp(未安装时隐藏本工具)。运行时自动读取剪贴板,发现 B 站链接(bilibili.com / b23.tv)就列在下方,点「下载」即可用 yt-dlp 下载到「设置 → 工具」中配置的目录。"><span class="tool-arrow">▸</span><span class="dot"></span>视频下载</span>
  435. <span class="tool-status" id="ytdlp-status"></span>
  436. <span class="tool-order-btns"><button class="tool-order-btn tool-up" type="button" title="上移">↑</button><button class="tool-order-btn tool-down" type="button" title="下移">↓</button></span>
  437. </div>
  438. <div class="tool-card-body">
  439. <div class="tool-row tool-actions">
  440. <label class="ytdlp-select-all"><input type="checkbox" id="ytdlp-select-all">全选</label>
  441. <button class="btn-primary" id="ytdlp-batch-download" type="button" disabled>批量下载</button>
  442. <button class="btn-ghost" id="ytdlp-batch-mp3" type="button" style="display:none" disabled>批量转 mp3</button>
  443. </div>
  444. <div class="ytdlp-list" id="ytdlp-list"></div>
  445. <pre class="croc-log" id="ytdlp-log" hidden></pre>
  446. </div>
  447. </div>
  448. <!-- 工具 16:Memos 速记——把内容一键发送到 Memos 实例 -->
  449. <div class="tool-card is-collapsed" data-tool="memos">
  450. <div class="tool-card-head" role="button" tabindex="0" aria-expanded="false">
  451. <span class="tool-card-title" title="写内容后点「发送」即创建一条私有 Memos 备忘(支持 Markdown 与 #标签,Ctrl+Enter 快捷发送)。实例地址与访问令牌在「设置 → 工具」中配置;未配置前输入框不可编辑。"><span class="tool-arrow">▸</span><span class="dot"></span>Memos 速记</span>
  452. <span class="tool-status" id="memos-status"></span>
  453. <span class="tool-order-btns"><button class="tool-order-btn tool-up" type="button" title="上移">↑</button><button class="tool-order-btn tool-down" type="button" title="下移">↓</button></span>
  454. </div>
  455. <div class="tool-card-body">
  456. <textarea class="input tr-input" id="memos-input" rows="5" placeholder="请先到「设置 → 工具」填写 Memos 地址与访问令牌" spellcheck="false" readonly></textarea>
  457. <div class="tool-row tool-actions">
  458. <button class="btn-primary" id="memos-send" type="button" disabled>发送</button>
  459. <span class="tool-hint" id="memos-hint"></span>
  460. </div>
  461. </div>
  462. </div>
  463. </div>
  464. <div class="tab-panel" id="tab-host">
  465. <div class="host-cards">
  466. <div class="card">
  467. <div class="card-title-row">
  468. <span class="card-title"><span class="dot"></span>API 服务</span>
  469. <button class="btn-ghost" id="api-toggle">停止服务</button>
  470. </div>
  471. <p id="api-status">检查中…</p>
  472. </div>
  473. <!-- 文件上传:需密码,上传成功显示二维码 -->
  474. <div class="card" id="upload-card">
  475. <div class="card-title-row">
  476. <span class="card-title"><span class="dot"></span>文件上传</span>
  477. </div>
  478. <div>
  479. <p class="tool-hint">手机等设备访问 http://&lt;服务地址&gt;/upload 上传页,输入密码即可上传文件。</p>
  480. </div>
  481. <div class="upload-box">
  482. <div class="upload-row">
  483. <button class="btn-ghost" id="upload-btn">选择文件并上传</button>
  484. <span class="upload-name" id="upload-name"></span>
  485. </div>
  486. <div class="upload-progress" id="upload-progress" hidden><div class="upload-bar"></div></div>
  487. <div class="upload-result" id="upload-result" hidden>
  488. <div class="upload-qr" id="upload-qr"></div>
  489. <div class="upload-meta">
  490. <div class="upload-name" id="upload-name2"></div>
  491. <a class="upload-link" id="upload-link" href="#" target="_blank">下载地址</a>
  492. </div>
  493. </div>
  494. </div>
  495. </div>
  496. <div class="card">
  497. <div class="card-title"><span class="dot"></span>电源命令</div>
  498. <p id="pc-status">暂无请求</p>
  499. </div>
  500. </div>
  501. <h3 class="section-title">提供的功能</h3>
  502. <ul class="api-list" id="api-list">
  503. <li><code>GET /health</code>健康检查</li>
  504. <li><code>POST /api/notify</code>弹出系统通知</li>
  505. <li><code>POST /api/window/show</code>显示主窗口</li>
  506. <li><code>POST /api/mouse/alert</code>系统级鼠标提醒(闪烁光标+提示文字)</li>
  507. <li><code>POST /api/handle/flash</code>拖动手柄圆点闪烁(颜色+大小变化,?count= 次数)</li>
  508. <li><code>GET /api/settings</code>读取配置</li>
  509. <li><code>POST /api/settings</code>保存配置</li>
  510. <li><code>GET /api/stocks</code>股票行情(?codes= 可临时指定)</li>
  511. <li><code>GET /api/screenshot</code>屏幕截图(?display= 指定显示器)</li>
  512. <li><code>POST /api/upload</code>上传文件(字段 password+file,密码正确才保存)</li>
  513. <li><code>GET /api/download/:filename</code>下载已上传文件(?password= 校验密码)</li>
  514. <li><code>GET /api/pc/poweroff</code>30 秒后关机</li>
  515. <li><code>GET /api/pc/restart</code>30 秒后重启</li>
  516. <li><code>GET /api/pc/sleep</code>30 秒后休眠</li>
  517. <li><code>GET /api/pc/lock</code>立即锁屏</li>
  518. <li><code>GET /api/pc/cancel</code>取消待执行命令</li>
  519. <li><code>GET /api/pc/status</code>查询命令状态</li>
  520. <li><code>GET /api/pc/timesync</code>同步系统时间</li>
  521. </ul>
  522. <div class="section-title section-title-row">
  523. <span>Gin 日志</span>
  524. <button class="btn-ghost" id="log-clear">清空日志</button>
  525. </div>
  526. <pre class="log-view" id="log-view">暂无日志</pre>
  527. </div>
  528. <!-- 设置 -->
  529. <div class="tab-panel" id="tab-settings">
  530. <h2>设置</h2>
  531. <div class="setting-list">
  532. <!-- 界面样式:暗色 / 亮色 -->
  533. <div class="setting-row">
  534. <div class="setting-info">
  535. <div class="setting-title">界面样式</div>
  536. <div class="setting-hint">在暗色与亮色主题之间切换</div>
  537. </div>
  538. <div class="segmented" id="theme-seg">
  539. <button class="seg-btn active" data-theme-value="dark">暗色</button>
  540. <button class="seg-btn" data-theme-value="light">亮色</button>
  541. </div>
  542. </div>
  543. <!-- 界面字号:全局 +- 调整 -->
  544. <div class="setting-row">
  545. <div class="setting-info">
  546. <div class="setting-title">界面字号</div>
  547. <div class="setting-hint">统一调整全部文字大小,范围 +-3</div>
  548. </div>
  549. <div class="stepper">
  550. <button class="step-btn" id="font-minus" title="减小字号">−</button>
  551. <span class="step-value" id="font-delta-value">0</span>
  552. <button class="step-btn" id="font-plus" title="增大字号">+</button>
  553. </div>
  554. </div>
  555. <!-- 系统启动时运行:默认勾选 -->
  556. <div class="setting-row">
  557. <div class="setting-info">
  558. <div class="setting-title">系统启动时运行</div>
  559. <div class="setting-hint">开机后自动启动腾图工具箱(默认开启)</div>
  560. </div>
  561. <label class="switch">
  562. <input type="checkbox" id="autostart" checked>
  563. <span class="switch-track"></span>
  564. </label>
  565. </div>
  566. <!-- 窗口置顶 -->
  567. <div class="setting-row">
  568. <div class="setting-info">
  569. <div class="setting-title">窗口置顶</div>
  570. <div class="setting-hint">主窗口始终显示在其他窗口之上</div>
  571. </div>
  572. <label class="switch">
  573. <input type="checkbox" id="always-on-top">
  574. <span class="switch-track"></span>
  575. </label>
  576. </div>
  577. <!-- 启动时缩小 -->
  578. <div class="setting-row">
  579. <div class="setting-info">
  580. <div class="setting-title">启动时缩小</div>
  581. <div class="setting-hint">启动后直接收拢为圆点,双击圆点或拖动手柄即可还原窗口</div>
  582. </div>
  583. <label class="switch">
  584. <input type="checkbox" id="start-compact">
  585. <span class="switch-track"></span>
  586. </label>
  587. </div>
  588. <!-- 呼出窗口热键 -->
  589. <div class="setting-row">
  590. <div class="setting-info">
  591. <div class="setting-title">呼出窗口热键</div>
  592. <div class="setting-hint">点击输入框后按下组合键,例如 Ctrl+Shift+G</div>
  593. </div>
  594. <input class="input hotkey-input" id="hotkey" readonly placeholder="按下组合键">
  595. </div>
  596. <!-- 指定浏览器:留空则用系统默认浏览器打开网址 -->
  597. <div class="setting-row">
  598. <div class="setting-info">
  599. <div class="setting-title">指定浏览器</div>
  600. <div class="setting-hint">点击网址时用该浏览器打开;留空则使用系统默认浏览器</div>
  601. </div>
  602. <div class="browser-path-group">
  603. <input class="input" id="browser-path" type="text" placeholder="留空=系统默认浏览器" spellcheck="false">
  604. <button class="btn-ghost" id="browser-pick" type="button" title="选择浏览器可执行文件">选择…</button>
  605. <button class="btn-ghost" id="browser-clear" type="button" title="恢复系统默认浏览器">清除</button>
  606. </div>
  607. </div>
  608. <!-- Tab 显示顺序(归入「系统」组) -->
  609. <div class="setting-row" data-tab-group="system">
  610. <div class="setting-info">
  611. <div class="setting-title">Tab 显示顺序</div>
  612. <div class="setting-hint">用逗号分隔 Tab 名称,从左到右依次显示;未列出的追加到末尾</div>
  613. </div>
  614. <input class="input" id="tab-order" type="text" placeholder="网址, 新闻, Github, 股市, 待办, 工具, 服务">
  615. </div>
  616. <!-- 自定义 Tab 页面(归入「系统」组) -->
  617. <div class="setting-row setting-row-col" data-tab-group="system">
  618. <div class="setting-info">
  619. <div class="setting-title">自定义 Tab 页面</div>
  620. <div class="setting-hint">每行一条,格式:页面名称|地址|备注(备注可空)。地址以 http:// 或 https:// 开头则内嵌网页;否则按本地文件路径读取,Markdown 自动渲染。名称用于 Tab 显示顺序,备注显示为 Tab 说明</div>
  621. </div>
  622. <textarea class="input textarea" id="custom-tabs" rows="3" placeholder="文档|D:\My\notes\readme.md|个人笔记&#10;示例|https://example.com"></textarea>
  623. </div>
  624. <!-- 股市代码 -->
  625. <div class="setting-row" data-tab-group="stock">
  626. <div class="setting-info">
  627. <div class="setting-title">股市代码</div>
  628. <div class="setting-hint">多个代码用逗号分隔,纯数字会自动补市场前缀</div>
  629. </div>
  630. <input class="input" id="stock-codes" type="text" placeholder="600519, 000001">
  631. </div>
  632. <!-- 涨跌颜色 -->
  633. <div class="setting-row" data-tab-group="stock">
  634. <div class="setting-info">
  635. <div class="setting-title">涨跌颜色</div>
  636. <div class="setting-hint">上涨 / 下跌在列表、图表与滚动条中的显示颜色</div>
  637. </div>
  638. <div class="ticker-controls">
  639. <span class="num-unit">涨</span>
  640. <input class="input-color" id="stock-up-color" type="color" title="上涨颜色">
  641. <span class="num-unit">跌</span>
  642. <input class="input-color" id="stock-down-color" type="color" title="下跌颜色">
  643. </div>
  644. </div>
  645. <!-- 股市刷新间隔 -->
  646. <div class="setting-row" data-tab-group="stock">
  647. <div class="setting-info">
  648. <div class="setting-title">股市刷新间隔</div>
  649. <div class="setting-hint">自动刷新行情的间隔,默认 30 秒</div>
  650. </div>
  651. <div class="num-group">
  652. <input class="input input-num" id="stock-refresh-secs" type="number" min="5" max="3600">
  653. <span class="num-unit">秒</span>
  654. </div>
  655. </div>
  656. <!-- 休市刷新间隔 -->
  657. <div class="setting-row" data-tab-group="stock">
  658. <div class="setting-info">
  659. <div class="setting-title">休市刷新间隔</div>
  660. <div class="setting-hint">休市时自动刷新行情的间隔,默认 2 小时</div>
  661. </div>
  662. <div class="num-group">
  663. <input class="input input-num" id="stock-closed-refresh-secs" type="number" min="60" max="86400">
  664. <span class="num-unit">秒</span>
  665. </div>
  666. </div>
  667. <!-- 常用网址 -->
  668. <div class="setting-row setting-row-col" data-tab-group="links">
  669. <div class="setting-info">
  670. <div class="setting-title">常用网址</div>
  671. <div class="setting-hint">每行一条,格式:名称|网址,例如 煎蛋|https://jandan.net/</div>
  672. </div>
  673. <textarea class="input textarea" id="links-text" rows="4" placeholder="名称|网址,每行一条"></textarea>
  674. </div>
  675. <!-- 新闻关键词 -->
  676. <div class="setting-row" data-tab-group="news">
  677. <div class="setting-info">
  678. <div class="setting-title">新闻关键词</div>
  679. <div class="setting-hint">逗号分隔;命中关键词的新闻在「新闻」页置顶高亮</div>
  680. </div>
  681. <input class="input" id="news-keywords" type="text" placeholder="AI, 芯片, 苹果">
  682. </div>
  683. <!-- B站登录 cookie -->
  684. <div class="setting-row setting-row-col" data-tab-group="news">
  685. <div class="setting-info">
  686. <div class="setting-title">B站 cookie</div>
  687. <div class="setting-hint">登录 bilibili.com 后从浏览器 Cookie 复制 SESSDATA=xxx(整个 cookie 串)。用于在「新闻」页展示你关注的人的最新动态;为空或失效时回退热门视频。cookie 会过期,需定期更新。</div>
  688. </div>
  689. <input class="input" id="bili-cookie" type="text" placeholder="SESSDATA=xxxxxxxx; bili_jct=xxxx" spellcheck="false">
  690. </div>
  691. <!-- 新闻刷新间隔 -->
  692. <div class="setting-row" data-tab-group="news">
  693. <div class="setting-info">
  694. <div class="setting-title">新闻刷新间隔</div>
  695. <div class="setting-hint">自动抓取新闻的间隔,默认 2 小时</div>
  696. </div>
  697. <div class="num-group">
  698. <input class="input input-num" id="news-refresh-mins" type="number" min="5" max="1440">
  699. <span class="num-unit">分钟</span>
  700. </div>
  701. </div>
  702. <!-- 新闻显示条数 -->
  703. <div class="setting-row" data-tab-group="news">
  704. <div class="setting-info">
  705. <div class="setting-title">新闻显示条数</div>
  706. <div class="setting-hint">「新闻」页最多显示的条目数,默认 30 条</div>
  707. </div>
  708. <div class="num-group">
  709. <input class="input input-num" id="news-count" type="number" min="5" max="200">
  710. <span class="num-unit">条</span>
  711. </div>
  712. </div>
  713. <!-- Github 项目 -->
  714. <div class="setting-row setting-row-col" data-tab-group="github">
  715. <div class="setting-info">
  716. <div class="setting-title">Github 项目</div>
  717. <div class="setting-hint">每行一条,格式:仓库地址|项目说明|本地版本(版本可选,用于提示更新)</div>
  718. </div>
  719. <textarea class="input textarea" id="github-repos" rows="4" placeholder="https://github.com/wailsapp/wails|Wails 框架|3.0.0"></textarea>
  720. </div>
  721. <!-- Github 刷新间隔 -->
  722. <div class="setting-row" data-tab-group="github">
  723. <div class="setting-info">
  724. <div class="setting-title">Github 刷新间隔</div>
  725. <div class="setting-hint">自动监听仓库更新的间隔,默认 2 小时</div>
  726. </div>
  727. <div class="num-group">
  728. <input class="input input-num" id="github-refresh-mins" type="number" min="5" max="1440">
  729. <span class="num-unit">分钟</span>
  730. </div>
  731. </div>
  732. <!-- 服务自动启动:应用启动时自动开启内置 API 服务(默认勾选) -->
  733. <div class="setting-row" data-tab-group="host">
  734. <div class="setting-info">
  735. <div class="setting-title">服务自动启动</div>
  736. <div class="setting-hint">启动腾图工具箱时自动开启内置 API 服务(默认开启)</div>
  737. </div>
  738. <label class="switch">
  739. <input type="checkbox" id="api-auto-start" checked>
  740. <span class="switch-track"></span>
  741. </label>
  742. </div>
  743. <!-- API 监听地址 -->
  744. <div class="setting-row" data-tab-group="host">
  745. <div class="setting-info">
  746. <div class="setting-title">API 监听地址</div>
  747. <div class="setting-hint">内置 API 服务监听地址,保存后自动重启服务</div>
  748. </div>
  749. <input class="input" id="api-addr" type="text" placeholder="127.0.0.1:17890">
  750. </div>
  751. <!-- 上传密码 -->
  752. <div class="setting-row" data-tab-group="host">
  753. <div class="setting-info">
  754. <div class="setting-title">上传密码</div>
  755. <div class="setting-hint">服务页文件上传需输入该密码;留空则不启用上传/下载接口</div>
  756. </div>
  757. <input class="input" id="upload-password" type="password" placeholder="留空=不启用上传">
  758. </div>
  759. <!-- 上传保存目录 -->
  760. <div class="setting-row" data-tab-group="host">
  761. <div class="setting-info">
  762. <div class="setting-title">上传保存目录</div>
  763. <div class="setting-hint">上传文件的保存目录,留空则保存到用户配置目录/uploads</div>
  764. </div>
  765. <input class="input" id="upload-dir" type="text" placeholder="D:\My\腾图\上传">
  766. </div>
  767. <!-- 上传大小上限 -->
  768. <div class="setting-row" data-tab-group="host">
  769. <div class="setting-info">
  770. <div class="setting-title">上传大小上限</div>
  771. <div class="setting-hint">单个上传文件允许的最大大小(MB),超出会被拒绝</div>
  772. </div>
  773. <input class="input" id="upload-max-size" type="number" min="1" step="1" placeholder="默认 512MB">
  774. </div>
  775. <!-- LocalSend 本机名称 -->
  776. <div class="setting-row" data-tab-group="tools">
  777. <div class="setting-info">
  778. <div class="setting-title">LocalSend 本机名称</div>
  779. <div class="setting-hint">局域网内其他 LocalSend 设备看到的名称;留空则随机生成,如「工具箱-3F8A」</div>
  780. </div>
  781. <input class="input" id="localsend-alias" type="text" placeholder="留空=随机生成" autocomplete="off">
  782. </div>
  783. <!-- LocalSend 接收模式 -->
  784. <div class="setting-row" data-tab-group="tools">
  785. <div class="setting-info">
  786. <div class="setting-title">LocalSend 接收模式</div>
  787. <div class="setting-hint">自动接收:直接保存到接收位置;手动确认:收到文件请求时弹窗由你决定</div>
  788. </div>
  789. <label class="radio-field"><input type="radio" name="localsend-mode" id="localsend-auto" value="auto"><span>自动接收</span></label>
  790. <label class="radio-field"><input type="radio" name="localsend-mode" id="localsend-manual" value="manual" checked><span>手动确认</span></label>
  791. </div>
  792. <!-- LocalSend 接收位置 -->
  793. <div class="setting-row" data-tab-group="tools">
  794. <div class="setting-info">
  795. <div class="setting-title">LocalSend 接收位置</div>
  796. <div class="setting-hint">接收文件保存目录,留空则保存到用户配置目录/TengTuToolbox/LocalSend接收</div>
  797. </div>
  798. <div class="browser-path-group">
  799. <input class="input" id="localsend-recvdir" type="text" placeholder="留空=默认接收目录" spellcheck="false">
  800. <button class="btn-ghost" id="localsend-pickdir" type="button" title="选择接收目录">选择目录</button>
  801. </div>
  802. </div>
  803. <!-- Croc 传送密码(发送/接收共用) -->
  804. <div class="setting-row croc-setting-row" data-tab-group="tools">
  805. <div class="setting-info">
  806. <div class="setting-title">Croc 传送密码</div>
  807. <div class="setting-hint">发送与接收共用同一密码(至少 6 个字符):设置后作为固定传输码(croc send --code),双方密码一致即可传输;留空则由 croc 生成随机传输码。需本机 PATH 中存在 croc 才会显示「Croc 传送」工具</div>
  808. </div>
  809. <input class="input" id="croc-password" type="password" placeholder="发送/接收共用密码" autocomplete="new-password" spellcheck="false">
  810. </div>
  811. <!-- Croc 接收保存目录 -->
  812. <div class="setting-row croc-setting-row" data-tab-group="tools">
  813. <div class="setting-info">
  814. <div class="setting-title">Croc 接收保存目录</div>
  815. <div class="setting-hint">接收到的文件保存位置;留空则保存到程序当前工作目录</div>
  816. </div>
  817. <div class="browser-path-group">
  818. <input class="input" id="croc-recvdir" type="text" placeholder="留空=当前目录" spellcheck="false">
  819. <button class="btn-ghost" id="croc-pickdir" type="button" title="选择接收目录">选择目录</button>
  820. </div>
  821. </div>
  822. <!-- 视频下载保存目录 -->
  823. <div class="setting-row ytdlp-setting-row" data-tab-group="tools">
  824. <div class="setting-info">
  825. <div class="setting-title">视频下载保存目录</div>
  826. <div class="setting-hint">「视频下载」工具用 yt-dlp 下载视频的保存位置;留空则保存到程序当前工作目录。需本机 PATH 中存在 yt-dlp 才会显示该工具</div>
  827. </div>
  828. <div class="browser-path-group">
  829. <input class="input" id="ytdlp-dir" type="text" placeholder="留空=当前目录" spellcheck="false">
  830. <button class="btn-ghost" id="ytdlp-pickdir" type="button" title="选择下载目录">选择目录</button>
  831. </div>
  832. </div>
  833. <!-- mp3 转换质量 -->
  834. <div class="setting-row ytdlp-setting-row" data-tab-group="tools">
  835. <div class="setting-info">
  836. <div class="setting-title">mp3 转换质量</div>
  837. <div class="setting-hint">「下载转 mp3」「批量转 mp3」使用的音频质量;VBR 数字越小质量越高,也可指定固定码率</div>
  838. </div>
  839. <select class="input" id="ytdlp-mp3-quality">
  840. <option value="0">最佳(VBR 0)</option>
  841. <option value="2">较好(VBR 2)</option>
  842. <option value="5">一般(VBR 5)</option>
  843. <option value="128K">128 kbps</option>
  844. <option value="192K">192 kbps</option>
  845. <option value="320K">320 kbps</option>
  846. </select>
  847. </div>
  848. <!-- Memos 地址 -->
  849. <div class="setting-row" data-tab-group="tools">
  850. <div class="setting-info">
  851. <div class="setting-title">Memos 实例地址</div>
  852. <div class="setting-hint">「Memos 速记」发送的目标实例,例如 https://m.scwy.net</div>
  853. </div>
  854. <input class="input" id="memos-url" type="text" placeholder="https://m.scwy.net" spellcheck="false">
  855. </div>
  856. <!-- Memos 访问令牌 -->
  857. <div class="setting-row" data-tab-group="tools">
  858. <div class="setting-info">
  859. <div class="setting-title">Memos 访问令牌</div>
  860. <div class="setting-hint">在 Memos 网页端「设置 → 访问令牌」中创建后填入,仅保存在本机</div>
  861. </div>
  862. <input class="input" id="memos-token" type="password" placeholder="粘贴个人访问令牌" spellcheck="false">
  863. </div>
  864. <div class="setting-row" data-tab-group="todo">
  865. <div class="setting-info">
  866. <div class="setting-title">待办文件路径</div>
  867. <div class="setting-hint">「待办」标签每行一个任务,保存到该文本文件</div>
  868. </div>
  869. <input class="input" id="todo-path" type="text" placeholder="D:\My\腾图\待办.txt">
  870. </div>
  871. <!-- 记录数据库路径 -->
  872. <div class="setting-row" data-tab-group="record">
  873. <div class="setting-info">
  874. <div class="setting-title">记录数据库路径</div>
  875. <div class="setting-hint">「记录」标签全部「姓名|名称|值」保存到该 SQLite 数据库文件;姓名/名称输入自动补全历史值,选择姓名与名称后按值绘柱状图</div>
  876. </div>
  877. <input class="input" id="record-db-path" type="text" placeholder="D:\My\腾图\记录.db">
  878. </div>
  879. <!-- 文本备份目录 -->
  880. <div class="setting-row">
  881. <div class="setting-info">
  882. <div class="setting-title">文本备份目录</div>
  883. <div class="setting-hint">文件类自定义 Tab 的「备份」按钮按当前时间备份文件到该目录,文件名带时间戳</div>
  884. </div>
  885. <input class="input" id="backup-dir" type="text" placeholder="D:\My\腾图\备份">
  886. </div>
  887. <!-- 股票滚动条 -->
  888. <div class="setting-row" data-tab-group="stock">
  889. <div class="setting-info">
  890. <div class="setting-title">股票滚动条</div>
  891. <div class="setting-hint">屏幕顶部一行置顶滚动显示实时行情,可拖动位置</div>
  892. </div>
  893. <div class="ticker-controls">
  894. <label class="switch" title="显示滚动条">
  895. <input type="checkbox" id="stock-ticker-enabled">
  896. <span class="switch-track"></span>
  897. </label>
  898. <label class="mini-label" title="背景透明"><input type="checkbox" id="stock-ticker-transparent">透明</label>
  899. <input class="input input-num" id="stock-ticker-width" type="number" min="200" max="6000" title="宽度 px">
  900. <input class="input input-num" id="stock-ticker-size" type="number" min="10" max="40" title="字号 px">
  901. <input class="input-color" id="stock-ticker-color" type="color" title="文字颜色">
  902. <input class="input input-num" id="stock-ticker-speed" type="number" min="20" max="400" title="滚动速度 px/s">
  903. </div>
  904. </div>
  905. <!-- 新闻滚动条 -->
  906. <div class="setting-row" data-tab-group="news">
  907. <div class="setting-info">
  908. <div class="setting-title">新闻滚动条</div>
  909. <div class="setting-hint">屏幕顶部一行置顶滚动显示新闻标题,点击标题打开详情</div>
  910. </div>
  911. <div class="ticker-controls">
  912. <label class="switch" title="显示滚动条">
  913. <input type="checkbox" id="news-ticker-enabled">
  914. <span class="switch-track"></span>
  915. </label>
  916. <label class="mini-label" title="背景透明"><input type="checkbox" id="news-ticker-transparent">透明</label>
  917. <input class="input input-num" id="news-ticker-width" type="number" min="200" max="6000" title="宽度 px">
  918. <input class="input input-num" id="news-ticker-size" type="number" min="10" max="40" title="字号 px">
  919. <input class="input-color" id="news-ticker-color" type="color" title="文字颜色">
  920. <input class="input input-num" id="news-ticker-speed" type="number" min="20" max="400" title="滚动速度 px/s">
  921. </div>
  922. </div>
  923. <!-- 随机古诗(归入「系统」组) -->
  924. <div class="setting-row" data-tab-group="system">
  925. <div class="setting-info">
  926. <div class="setting-title">随机古诗</div>
  927. <div class="setting-hint">footer 版本后面水平滚动显示一首随机古诗,可点击换一首、朗读(TTS)</div>
  928. </div>
  929. <div class="ticker-controls">
  930. <label class="switch" title="显示古诗">
  931. <input type="checkbox" id="poem-enabled">
  932. <span class="switch-track"></span>
  933. </label>
  934. <input class="input-color" id="poem-color" type="color" title="文字颜色">
  935. <input class="input input-num" id="poem-size" type="number" min="12" max="48" title="字号 px">
  936. <label class="mini-label" title="滚动速度(秒/轮),数值越小滚动越快"><input type="number" id="poem-speed" class="input input-num" min="5" max="120" title="滚动速度(秒/轮)">速度</label>
  937. <label class="mini-label" title="显示朗读按钮"><input type="checkbox" id="poem-tts">朗读</label>
  938. </div>
  939. </div>
  940. <!-- 鼠标提醒(系统级气泡) -->
  941. <div class="setting-row" data-tab-group="host">
  942. <div class="setting-info">
  943. <div class="setting-title">鼠标提醒</div>
  944. <div class="setting-hint">触发提醒时在鼠标旁浮出透明气泡文字,可调字号、宽度、滚动速度、颜色与描边(描边形成反差,避免背景看不清)</div>
  945. </div>
  946. <div class="ticker-controls">
  947. <input class="input input-num" id="mouse-alert-size" type="number" min="10" max="48" title="字号 px">
  948. <input class="input input-num" id="mouse-alert-width" type="number" min="120" max="1200" title="窗口宽度 px">
  949. <input class="input input-num" id="mouse-alert-speed" type="number" min="5" max="300" title="滚动速度 px/s">
  950. <input class="input-color" id="mouse-alert-color" type="color" title="文字颜色">
  951. <input class="input input-num" id="mouse-alert-outline-width" type="number" min="0" max="6" title="文字描边宽度 px(0 关闭)">
  952. <input class="input-color" id="mouse-alert-outline-color" type="color" title="文字描边颜色(与文字形成反差)">
  953. <input class="input input-num" id="mouse-alert-duration" type="number" min="2" max="60" title="显示时长(秒)">
  954. </div>
  955. </div>
  956. </div>
  957. <!-- 保存栏 -->
  958. <div class="save-bar">
  959. <button class="btn-primary" id="save-settings">保存设置</button>
  960. <span class="save-status" id="save-status"></span>
  961. </div>
  962. </div>
  963. </div>
  964. </div>
  965. <!-- 股票图表弹窗:点击股市行打开,可切换分时图 / 日K图 -->
  966. <div class="chart-modal" id="chart-modal" hidden>
  967. <div class="chart-mask" id="chart-mask"></div>
  968. <div class="chart-dialog" role="dialog" aria-modal="true" aria-label="股票图表">
  969. <div class="chart-head">
  970. <div class="chart-title-wrap">
  971. <div class="chart-title" id="chart-title">--</div>
  972. <div class="chart-sub" id="chart-sub"></div>
  973. </div>
  974. <div class="segmented" id="chart-kind">
  975. <button class="seg-btn active" data-chart-kind="minute">分时</button>
  976. <button class="seg-btn" data-chart-kind="kline">日K</button>
  977. </div>
  978. <button class="chart-close" id="chart-close" title="关闭">×</button>
  979. </div>
  980. <canvas id="chart-canvas"></canvas>
  981. <div class="chart-legend" id="chart-legend"></div>
  982. </div>
  983. </div>
  984. <!-- 待办提醒弹窗:到点时弹出,置顶显示 -->
  985. <div class="remind-modal" id="remind-modal" hidden>
  986. <div class="remind-mask" id="remind-mask"></div>
  987. <div class="remind-dialog" role="alertdialog" aria-modal="true" aria-label="待办提醒">
  988. <div class="remind-icon">⏰</div>
  989. <div class="remind-title">待办提醒</div>
  990. <div class="remind-text" id="remind-text"></div>
  991. <div class="remind-time" id="remind-time"></div>
  992. <div class="remind-actions">
  993. <button class="btn-primary" id="remind-ok">知道了</button>
  994. </div>
  995. </div>
  996. </div>
  997. <!-- LocalSend 文件接收确认弹窗(手动接收模式) -->
  998. <div class="ls-offer-mask" id="ls-offer-mask" hidden>
  999. <div class="ls-offer-dialog">
  1000. <div class="ls-offer-title">收到文件发送请求</div>
  1001. <div class="ls-offer-sender" id="ls-offer-sender"></div>
  1002. <ul class="ls-offer-files" id="ls-offer-files"></ul>
  1003. <div class="ls-offer-actions">
  1004. <button class="btn-ghost" id="ls-offer-reject">拒绝</button>
  1005. <button class="btn-primary" id="ls-offer-accept">接受</button>
  1006. </div>
  1007. </div>
  1008. </div>
  1009. <footer class="footer">
  1010. <span class="footer-version"><span class="dot"></span>腾图工具箱 <span id="footer-version-text"></span></span>
  1011. <div class="footer-desc" id="footer-desc">
  1012. <span class="footer-marquee" id="footer-marquee"></span>
  1013. <button class="poem-read" id="poem-read" title="朗读古诗" hidden>🔊</button>
  1014. </div>
  1015. <span class="footer-time" id="time">--:--:--</span>
  1016. <a class="footer-docs" data-wml-openURL="https://v3.wails.io" aria-label="Wails documentation">官方文档</a>
  1017. </footer>
  1018. <script type="module" src="/src/main.js"></script>
  1019. </body>
  1020. </html>