332 lines
33 KiB
HTML
332 lines
33 KiB
HTML
<!doctype html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
<title>Bangumi 保管库</title>
|
||
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1024 1024' fill='%23FF6CB8'><path d='M228.115268 615.399298a12.300795 12.300795 0 0 0 11.35458 7.569719 12.471113 12.471113 0 0 0 4.749999-0.965139l147.609537-61.882459a12.300795 12.300795 0 0 0 0.26494-22.557765l-147.609537-66.235049a12.300795 12.300795 0 1 0-10.067727 22.444219l121.740019 54.634453-121.456155 50.906366a12.300795 12.300795 0 0 0-6.585656 16.085655zM399.020617 627.965033H239.469848a12.300795 12.300795 0 0 0 0 24.601589h159.550769a12.300795 12.300795 0 0 0 0-24.601589zM399.020617 667.460046H239.469848a12.300795 12.300795 0 0 0 0 24.601589h159.550769a12.300795 12.300795 0 0 0 0-24.601589zM872.941851 476.892349l-133.283841 58.381464a12.300795 12.300795 0 0 0-0.397411 22.349598l133.302766 64.058754a12.073703 12.073703 0 0 0 5.317729 1.23008 12.300795 12.300795 0 0 0 5.336652-23.390435l-109.15536-52.42031L882.896033 499.469038a12.300795 12.300795 0 1 0-9.954182-22.576689zM877.881094 627.965033h-148.101569a12.300795 12.300795 0 0 0 0 24.601589h148.101569a12.300795 12.300795 0 0 0 0-24.601589zM877.881094 667.460046h-148.101569a12.300795 12.300795 0 0 0 0 24.601589h148.101569a12.300795 12.300795 0 0 0 0-24.601589zM644.866193 537.128395h-162.919295a12.28187 12.28187 0 0 0-10.711153 18.318722l81.374488 145.130453a12.300795 12.300795 0 0 0 21.460155 0l81.374489-145.130453a12.300795 12.300795 0 0 0-10.730078-18.318722z m-81.374488 132.299778l-60.444213-107.698189h120.888426z'/><path d='M891.411968 334.960102H648.405037c-6.812748-15.13944-19.813742-28.386449-36.864535-38.018917L803.092262 19.283861a12.300795 12.300795 0 0 0-20.249001-13.966133L588.566402 286.873457a147.723082 147.723082 0 0 0-45.418319-7.001991 151.507942 151.507942 0 0 0-31.887445 3.368526L239.980804 4.712151A12.300795 12.300795 0 0 0 222.437978 21.87649l262.726051 269.803739c-22.14143 9.821711-39.116527 25.112546-47.310749 43.242025H132.547555A91.763929 91.763929 0 0 0 40.764702 426.705107v414.44216A91.763929 91.763929 0 0 0 132.547555 932.967969h268.024855l-19.908363 46.989036c-12.641432 29.881469 22.614538 57.094612 48.294812 37.299794L538.473781 932.967969h352.938187a91.763929 91.763929 0 0 0 91.782853-91.782853v-414.442161a91.763929 91.763929 0 0 0-91.782853-91.782853z m34.839635 463.815658a60.709153 60.709153 0 0 1-60.709153 60.709153H585.670984L487.870204 932.967969l-77.002975 57.851583 24.412346-57.851583 31.016927-73.483056H198.082405A60.728077 60.728077 0 0 1 137.27863 798.737912V440.330602a60.728077 60.728077 0 0 1 60.728077-60.728077h667.460046a60.709153 60.709153 0 0 1 60.709153 60.728077z'/></svg>" />
|
||
<meta name="description" content="Bangumi 本地保险箱:收藏、标签、吐槽、评分、进度、历史版本与离线导出。" />
|
||
<link rel="stylesheet" href="css/fonts.css" />
|
||
<link rel="stylesheet" href="css/styles.css" />
|
||
</head>
|
||
<body>
|
||
<div id='loadingScreen'><div class='ld-inner'><div class='bangumi-logo'><svg viewBox='0 0 1024 1024' fill='#FF6CB8' aria-hidden='true'><path d='M228.115268 615.399298a12.300795 12.300795 0 0 0 11.35458 7.569719 12.471113 12.471113 0 0 0 4.749999-0.965139l147.609537-61.882459a12.300795 12.300795 0 0 0 0.26494-22.557765l-147.609537-66.235049a12.300795 12.300795 0 1 0-10.067727 22.444219l121.740019 54.634453-121.456155 50.906366a12.300795 12.300795 0 0 0-6.585656 16.085655zM399.020617 627.965033H239.469848a12.300795 12.300795 0 0 0 0 24.601589h159.550769a12.300795 12.300795 0 0 0 0-24.601589zM399.020617 667.460046H239.469848a12.300795 12.300795 0 0 0 0 24.601589h159.550769a12.300795 12.300795 0 0 0 0-24.601589zM872.941851 476.892349l-133.283841 58.381464a12.300795 12.300795 0 0 0-0.397411 22.349598l133.302766 64.058754a12.073703 12.073703 0 0 0 5.317729 1.23008 12.300795 12.300795 0 0 0 5.336652-23.390435l-109.15536-52.42031L882.896033 499.469038a12.300795 12.300795 0 1 0-9.954182-22.576689zM877.881094 627.965033h-148.101569a12.300795 12.300795 0 0 0 0 24.601589h148.101569a12.300795 12.300795 0 0 0 0-24.601589zM877.881094 667.460046h-148.101569a12.300795 12.300795 0 0 0 0 24.601589h148.101569a12.300795 12.300795 0 0 0 0-24.601589zM644.866193 537.128395h-162.919295a12.28187 12.28187 0 0 0-10.711153 18.318722l81.374488 145.130453a12.300795 12.300795 0 0 0 21.460155 0l81.374489-145.130453a12.300795 12.300795 0 0 0-10.730078-18.318722z m-81.374488 132.299778l-60.444213-107.698189h120.888426z'></path><path d='M891.411968 334.960102H648.405037c-6.812748-15.13944-19.813742-28.386449-36.864535-38.018917L803.092262 19.283861a12.300795 12.300795 0 0 0-20.249001-13.966133L588.566402 286.873457a147.723082 147.723082 0 0 0-45.418319-7.001991 151.507942 151.507942 0 0 0-31.887445 3.368526L239.980804 4.712151A12.300795 12.300795 0 0 0 222.437978 21.87649l262.726051 269.803739c-22.14143 9.821711-39.116527 25.112546-47.310749 43.242025H132.547555A91.763929 91.763929 0 0 0 40.764702 426.705107v414.44216A91.763929 91.763929 0 0 0 132.547555 932.967969h268.024855l-19.908363 46.989036c-12.641432 29.881469 22.614538 57.094612 48.294812 37.299794L538.473781 932.967969h352.938187a91.763929 91.763929 0 0 0 91.782853-91.782853v-414.442161a91.763929 91.763929 0 0 0-91.782853-91.782853z m34.839635 463.815658a60.709153 60.709153 0 0 1-60.709153 60.709153H585.670984L487.870204 932.967969l-77.002975 57.851583 24.412346-57.851583 31.016927-73.483056H198.082405A60.728077 60.728077 0 0 1 137.27863 798.737912V440.330602a60.728077 60.728077 0 0 1 60.728077-60.728077h667.460046a60.709153 60.709153 0 0 1 60.709153 60.728077z'></path></svg></div><div class='ld-title'>Bangumi 保管库</div><div class='ld-dots'><span></span><span></span><span></span></div></div></div>
|
||
<div class="login-shell" id="loginShell">
|
||
<form class="login-card" id="loginForm">
|
||
<div class="field"><label>管理员密码</label><input id="adminPasswordInput" type="password" autocomplete="current-password" autofocus /></div>
|
||
<button class="btn primary" id="loginSubmitBtn" type="submit" style="width:100%">登录</button>
|
||
<div class="auth-status" id="loginStatus"></div>
|
||
</form>
|
||
</div>
|
||
<div class="side-backdrop" id="sideBackdrop"></div>
|
||
<div class="app" id="appRoot">
|
||
<aside class="side">
|
||
<div class="brand">
|
||
<a class="bangumi-logo" href="https://bgm.tv" target="_blank" rel="noopener" title="Bangumi 番组计划">
|
||
<svg viewBox="0 0 1024 1024" fill="#FF6CB8" aria-label="Bangumi" role="img"><path d="M228.115268 615.399298a12.300795 12.300795 0 0 0 11.35458 7.569719 12.471113 12.471113 0 0 0 4.749999-0.965139l147.609537-61.882459a12.300795 12.300795 0 0 0 0.26494-22.557765l-147.609537-66.235049a12.300795 12.300795 0 1 0-10.067727 22.444219l121.740019 54.634453-121.456155 50.906366a12.300795 12.300795 0 0 0-6.585656 16.085655zM399.020617 627.965033H239.469848a12.300795 12.300795 0 0 0 0 24.601589h159.550769a12.300795 12.300795 0 0 0 0-24.601589zM399.020617 667.460046H239.469848a12.300795 12.300795 0 0 0 0 24.601589h159.550769a12.300795 12.300795 0 0 0 0-24.601589zM872.941851 476.892349l-133.283841 58.381464a12.300795 12.300795 0 0 0-0.397411 22.349598l133.302766 64.058754a12.073703 12.073703 0 0 0 5.317729 1.23008 12.300795 12.300795 0 0 0 5.336652-23.390435l-109.15536-52.42031L882.896033 499.469038a12.300795 12.300795 0 1 0-9.954182-22.576689zM877.881094 627.965033h-148.101569a12.300795 12.300795 0 0 0 0 24.601589h148.101569a12.300795 12.300795 0 0 0 0-24.601589zM877.881094 667.460046h-148.101569a12.300795 12.300795 0 0 0 0 24.601589h148.101569a12.300795 12.300795 0 0 0 0-24.601589zM644.866193 537.128395h-162.919295a12.28187 12.28187 0 0 0-10.711153 18.318722l81.374488 145.130453a12.300795 12.300795 0 0 0 21.460155 0l81.374489-145.130453a12.300795 12.300795 0 0 0-10.730078-18.318722z m-81.374488 132.299778l-60.444213-107.698189h120.888426z"></path><path d="M891.411968 334.960102H648.405037c-6.812748-15.13944-19.813742-28.386449-36.864535-38.018917L803.092262 19.283861a12.300795 12.300795 0 0 0-20.249001-13.966133L588.566402 286.873457a147.723082 147.723082 0 0 0-45.418319-7.001991 151.507942 151.507942 0 0 0-31.887445 3.368526L239.980804 4.712151A12.300795 12.300795 0 0 0 222.437978 21.87649l262.726051 269.803739c-22.14143 9.821711-39.116527 25.112546-47.310749 43.242025H132.547555A91.763929 91.763929 0 0 0 40.764702 426.705107v414.44216A91.763929 91.763929 0 0 0 132.547555 932.967969h268.024855l-19.908363 46.989036c-12.641432 29.881469 22.614538 57.094612 48.294812 37.299794L538.473781 932.967969h352.938187a91.763929 91.763929 0 0 0 91.782853-91.782853v-414.442161a91.763929 91.763929 0 0 0-91.782853-91.782853z m34.839635 463.815658a60.709153 60.709153 0 0 1-60.709153 60.709153H585.670984L487.870204 932.967969l-77.002975 57.851583 24.412346-57.851583 31.016927-73.483056H198.082405A60.728077 60.728077 0 0 1 137.27863 798.737912V440.330602a60.728077 60.728077 0 0 1 60.728077-60.728077h667.460046a60.709153 60.709153 0 0 1 60.709153 60.728077z"></path></svg>
|
||
</a>
|
||
<div><h1>Bangumi 保管库</h1><p>本地收藏备份</p></div>
|
||
</div>
|
||
<div class="stats">
|
||
<div class="stat"><b id="statTotal">0</b><span>本地条目</span></div>
|
||
<div class="stat"><b id="statMissing">0</b><span>疑似消失</span></div>
|
||
<div class="stat stat-clickable" id="statCommentsCard" role="button" tabindex="0" title="点击只看有吐槽的条目(再点取消)"><b id="statComments">0</b><span>有吐槽</span></div>
|
||
<div class="stat"><b id="statTags">0</b><span>标签数</span></div>
|
||
</div>
|
||
<div class="nav-title">收藏状态</div>
|
||
<div class="nav" id="statusNav"></div>
|
||
<div class="nav-title tag-head"><span>标签筛选</span><button class="tag-search-toggle" id="tagSearchToggle" type="button" aria-label="搜索标签"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><circle cx="11" cy="11" r="7"/><line x1="20.5" y1="20.5" x2="16.5" y2="16.5"/></svg></button></div>
|
||
<div class="tag-filter" id="tagFilter">
|
||
<svg class="tag-filter-ico" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><circle cx="11" cy="11" r="7"/><line x1="20.5" y1="20.5" x2="16.5" y2="16.5"/></svg>
|
||
<input id="tagFilterInput" class="tag-filter-input" type="text" autocomplete="off" spellcheck="false" aria-label="过滤标签" />
|
||
</div>
|
||
<div class="tag-list" id="tagList"></div>
|
||
<button class="tag-list-more" id="tagListMore" type="button">展开更多</button>
|
||
<div class="drawer-actions" id="drawerActions">
|
||
<div class="nav-title">操作</div>
|
||
<button class="btn" id="mSettings" type="button">设置</button>
|
||
<button class="btn primary" id="mSyncRecent" type="button">同步最近</button>
|
||
<button class="btn warn" id="mFullSync" type="button">完整同步</button>
|
||
<button class="btn" id="mExport" type="button">导出备份</button>
|
||
<button class="btn" id="mImport" type="button">导入备份</button>
|
||
<button class="btn" id="mCacheCovers" type="button">缓存当前封面</button>
|
||
<button class="btn" id="mEnrichTags" type="button">刷新公共标签</button>
|
||
</div>
|
||
<div class="footer-note">
|
||
<div id="lastSyncText">尚未同步</div>
|
||
<div style="margin-top:8px">Powered by <a href="https://git.stdm.moe/Stardream/Bangumi-Vault" target="_blank" rel="noopener" style="color:inherit;text-decoration:none">Bangumi-Vault</a></div>
|
||
<div style="margin-top:8px">Copyright © 2026 AKISATO · MIT License</div>
|
||
</div>
|
||
</aside>
|
||
|
||
<main class="main">
|
||
<div class="top">
|
||
<div class="row">
|
||
<button class="btn menu-btn" id="menuBtn" type="button" aria-label="菜单">☰</button>
|
||
<div class="title">目录</div>
|
||
<span class="pill" id="accountPill">未登录</span>
|
||
<span class="pill" id="countPill">0 条</span>
|
||
<div id="syncMiniBar" title="点击展开同步进度">
|
||
<div class="smi-ring"></div>
|
||
<div class="smi-body"><div class="smi-label" id="syncMiniLabel">同步中…</div><div class="smi-track"><div class="smi-fill" id="syncMiniFill"></div></div></div>
|
||
</div>
|
||
<div class="grow"></div>
|
||
<button class="btn primary" id="syncBtn" title="只扫描最近自定义月份内更新过的收藏;不会触发安全箱删除判断,适合日常同步。">同步最近</button>
|
||
<button class="btn warn" id="fullSyncBtn" title="完整分页核对全部收藏;只有这个模式会做远端缺失检查并把疑似消失条目放入安全箱。">完整同步</button>
|
||
<button class="btn" id="exportBtn">导出备份</button>
|
||
<button class="btn" id="settingsBtn">设置</button>
|
||
<button class="btn small theme-toggle" id="themeBtnTop" type="button" aria-label="切换明暗"></button>
|
||
</div>
|
||
<div class="row" style="margin-top:14px">
|
||
<div class="search"><input id="searchInput" placeholder="搜索标题、吐槽、简介、年份…" /></div>
|
||
<div class="selectish" id="typeDropdown">
|
||
<button class="btn select-trigger" id="typeDropdownBtn" type="button"><span id="typeDropdownLabel">全部分类</span><span class="chev" aria-hidden="true"></span></button>
|
||
<div class="select-menu" role="menu">
|
||
<button data-value="0" class="active">全部分类</button><button data-value="2">动画</button><button data-value="1">书籍</button><button data-value="4">游戏</button><button data-value="3">音乐</button><button data-value="6">三次元</button>
|
||
</div>
|
||
</div>
|
||
<select class="hidden" id="typeFilter" aria-label="条目分类"><option value="0">全部分类</option><option value="2">动画</option><option value="1">书籍</option><option value="4">游戏</option><option value="3">音乐</option><option value="6">三次元</option></select>
|
||
<div class="selectish" id="sortDropdown">
|
||
<button class="btn select-trigger" id="sortDropdownBtn" type="button"><span id="sortDropdownLabel">按更新时间新到旧</span><span class="chev" aria-hidden="true"></span></button>
|
||
<div class="select-menu" role="menu">
|
||
<button data-value="updated_desc" class="active">按更新时间新到旧</button><button data-value="updated_asc">按更新时间旧到新</button><button data-value="rate_desc">按我的评分高到低</button><button data-value="name_asc">按标题 A-Z</button><button data-value="first_seen_desc">按首次备份新到旧</button>
|
||
</div>
|
||
</div>
|
||
<select class="hidden" id="sortSelect" aria-label="排序"><option value="updated_desc">按更新时间新到旧</option><option value="updated_asc">按更新时间旧到新</option><option value="rate_desc">按我的评分高到低</option><option value="name_asc">按标题 A-Z</option><option value="first_seen_desc">按首次备份新到旧</option></select>
|
||
<button class="btn theme-toggle" id="themeBtn" type="button" aria-label="切换明暗"></button>
|
||
</div>
|
||
</div>
|
||
<div class="filters">
|
||
<div class="filters-left">
|
||
<span class="pill" id="filterSummary">全部条目</span>
|
||
<span class="pill sync-explain" id="syncModePill" title="显示上次同步的触发方式和模式">最近同步 · 手动增量</span>
|
||
</div>
|
||
<div class="filters-right">
|
||
<button class="btn small" id="nsfwBtn" title="点击循环切换:全部显示 → 屏蔽 NSFW → 仅 NSFW">NSFW</button>
|
||
<button class="btn small" id="cacheCoversBtn">缓存当前封面到目录</button>
|
||
<button class="btn small" id="enrichTagsBtn" title="为当前筛选结果刷新条目的公共标签;会覆盖旧的公共标签缓存。">刷新公共标签</button>
|
||
<button class="btn small" id="importBtn">导入备份</button>
|
||
</div>
|
||
</div>
|
||
<div class="content" id="content"></div>
|
||
</main>
|
||
</div>
|
||
|
||
<div class="drawer-mask" id="drawerMask"></div>
|
||
<section class="drawer" id="drawer"></section>
|
||
|
||
<div class='modal-mask' id='settingsModal'>
|
||
<div class='modal-card settings-card'>
|
||
<div class='row'><h2 style='margin:0'>设置</h2><div class='grow'></div><button class='btn small' data-close='settingsModal'>关闭</button></div>
|
||
<div class='settings-tabs'>
|
||
<button class='settings-tab active' data-tab='stab-account'>账户</button>
|
||
<button class='settings-tab' data-tab='stab-sync'>同步</button>
|
||
<button class='settings-tab' data-tab='stab-appearance'>外观</button>
|
||
<button class='settings-tab' data-tab='stab-advanced'>高级</button>
|
||
<button class='settings-tab hidden' data-tab='stab-login'>管理员登录</button>
|
||
</div>
|
||
<div class='settings-pane active' id='stab-account'>
|
||
<div class='split'>
|
||
<div class='field'><label>Access Token</label><textarea id='tokenInput' rows='4' placeholder='粘贴 Bangumi Access Token' class='masked-input'></textarea></div>
|
||
<div class='field'><label>用户名</label><input id='usernameInput' placeholder='可留空,点击测试登录自动读取' /><div class='help'>用户名用于读取 /v0/users/{username}/collections。</div></div>
|
||
</div>
|
||
<div class='row' style='margin-top:16px'>
|
||
<button class='btn' id='openTokenBtn'>获取 Access Token</button>
|
||
<button class='btn good' id='testLoginBtn'>测试登录</button>
|
||
</div>
|
||
<div class='sync-log' id='loginLog' style='margin-top:14px' aria-live='polite'></div>
|
||
</div>
|
||
<div class='settings-pane' id='stab-sync'>
|
||
<div class='sync-master'>
|
||
<div>
|
||
<div class='setting-title' style='margin-bottom:2px'>自动同步</div>
|
||
<div class='setting-help' style='margin-top:0'>按设定的调度频率在后台自动同步收藏。</div>
|
||
</div>
|
||
<label style='flex:none;cursor:pointer;display:inline-flex;align-items:center'><input type='checkbox' id='autoSyncEnabledInput' class='switch-input' /><span class='switch'></span></label>
|
||
</div>
|
||
<div id='autoSyncOptions'>
|
||
<div class='setting-card'>
|
||
<div class='setting-title'>同步方式</div>
|
||
<div class='segmented' data-segment='autoSyncMode' style='width:max-content;margin-top:6px'>
|
||
<button data-value='recent'>增量</button>
|
||
<button data-value='full'>完整</button>
|
||
</div>
|
||
<div class='setting-help'>增量只读取最近更新的收藏;完整会核对全部收藏并触发安全箱判断。</div>
|
||
</div>
|
||
|
||
<div class='setting-card'>
|
||
<div class='setting-title'>同步范围</div>
|
||
<div class='row' style='gap:8px;align-items:center;flex-wrap:nowrap;margin-top:6px;max-width:440px'>
|
||
<input id='recentMonthsInput' type='number' min='1' max='999' step='1' placeholder='例如 3' style='flex:1;min-width:0' />
|
||
<div class='selectish' id='autoSyncRangeUnitDropdown' style='flex:none'>
|
||
<button class='btn select-trigger' type='button' style='min-width:84px;padding-left:12px'><span id='autoSyncRangeUnitLabel'>月</span><span class='chev' aria-hidden='true'></span></button>
|
||
<div class='select-menu' role='menu' style='min-width:120px'>
|
||
<button data-value='minute'>分钟</button>
|
||
<button data-value='hour'>小时</button>
|
||
<button data-value='day'>天</button>
|
||
<button data-value='month'>月</button>
|
||
</div>
|
||
</div>
|
||
<select class='hidden' id='autoSyncRangeUnit'><option value='minute'>分钟</option><option value='hour'>小时</option><option value='day'>天</option><option value='month'>月</option></select>
|
||
<button class='btn small' id='autoSyncRangeBtn' type='button' style='flex:none'>跟随调度频率</button>
|
||
</div>
|
||
<div class='setting-help' id='autoSyncRangeHelp'>仅用于自动同步:从每个分类/状态读取最近 N 个月更新的条目。手动“同步最近”的范围在它的弹窗里单独设置。</div>
|
||
</div>
|
||
|
||
<div class='setting-card'>
|
||
<div class='setting-title'>调度频率</div>
|
||
<div class='segmented' id='cronFreqRow' style='flex-wrap:wrap;width:max-content;max-width:100%;margin-top:6px'>
|
||
<button data-freq='minutes'>每隔分钟</button>
|
||
<button data-freq='hours'>每隔小时</button>
|
||
<button data-freq='daily'>每天</button>
|
||
<button data-freq='weekly'>每周</button>
|
||
<button data-freq='custom'>自定义</button>
|
||
</div>
|
||
<div id='cronFreqMinutes' style='margin-top:10px;display:none;align-items:center;gap:10px'>
|
||
<span>每隔</span><input id='cronEveryMinutes' type='number' min='1' max='59' step='1' value='30' class='btn' style='width:84px' /><span>分钟</span>
|
||
</div>
|
||
<div id='cronFreqHours' style='margin-top:10px;display:none;align-items:center;gap:10px;flex-wrap:wrap'>
|
||
<span>每隔</span><input id='cronEveryHours' type='number' min='1' max='23' step='1' value='4' class='btn' style='width:84px' /><span>小时,第</span><input id='cronHourMinute' type='number' min='0' max='59' step='1' value='0' class='btn' style='width:84px' /><span>分</span>
|
||
</div>
|
||
<div id='cronFreqDaily' style='margin-top:10px;display:none;align-items:center;gap:10px'>
|
||
<span>每天</span><input id='cronDailyTime' type='time' value='02:00' class='btn' style='padding:8px 12px;border-radius:14px;width:auto;cursor:pointer' />
|
||
</div>
|
||
<div id='cronFreqWeekly' style='margin-top:10px;display:none'>
|
||
<div class='segmented' id='cronWeeklyDaysRow'>
|
||
<button data-day='1'>周一</button>
|
||
<button data-day='2'>周二</button>
|
||
<button data-day='3'>周三</button>
|
||
<button data-day='4'>周四</button>
|
||
<button data-day='5'>周五</button>
|
||
<button data-day='6'>周六</button>
|
||
<button data-day='0'>周日</button>
|
||
</div>
|
||
<div style='margin-top:8px;display:flex;align-items:center;gap:6px'><span>时间</span><input id='cronWeeklyTime' type='time' value='08:00' class='btn' style='padding:8px 12px;border-radius:14px;width:auto;cursor:pointer' /></div>
|
||
</div>
|
||
<div id='cronFreqCustom' style='margin-top:10px;display:none'>
|
||
<input id='cronCustomInput' type='text' placeholder='分 时 日 月 周,例如 0 */4 * * *' class='btn' style='width:100%;max-width:320px;font-family:monospace' />
|
||
<div class='setting-help' style='margin-top:4px'>5 字段标准 cron:分 时 日 月 周(周 0–6,0=周日)。</div>
|
||
</div>
|
||
<div class='cron-summary'>
|
||
<div class='setting-help' id='autoSyncHelp' style='margin-top:0;color:var(--soft)'></div>
|
||
<div class='setting-help' id='cronNextText' style='margin-top:3px'></div>
|
||
<div class='setting-help' style='margin-top:3px;opacity:.7'>cron <code id='cronExprText' style='font-family:monospace'></code></div>
|
||
</div>
|
||
</div>
|
||
|
||
<label class='setting-card sync-cover' style='cursor:pointer'>
|
||
<div>
|
||
<div class='setting-title' style='margin-bottom:2px'>同步后缓存封面</div>
|
||
<div class='setting-help' style='margin-top:0'>自动同步时把封面下载到本地文件卷。</div>
|
||
</div>
|
||
<input type='checkbox' id='autoCacheCoversInput' class='switch-input' />
|
||
<span class='switch'></span>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
<div class='settings-pane' id='stab-appearance'>
|
||
<div class='settings-grid split'>
|
||
<div class='setting-card'><div class='setting-title'>主题模式</div><div class='segmented' data-segment='themeMode'><button data-value='system'>跟随系统</button><button data-value='dark'>深色</button><button data-value='light'>浅色</button></div><div class='setting-help'>点击切换时会用扩散动画过渡;跟随系统会随系统明暗变化。</div></div>
|
||
<div class='setting-card'><div class='setting-title'>字体风格</div><div class='segmented' data-segment='fontFamily'><button data-value='system'>系统默认</button><button data-value='rounded'>圆润</button><button data-value='jp'>日系</button><button data-value='wenkai'>文楷</button><button data-value='mono'>等宽</button></div><div class='setting-help'>使用本机已安装字体;没有对应字体时自动回退。</div></div>
|
||
<div class='setting-card'><div class='setting-title'>海报卡片</div><div class='segmented' data-segment='cardSize'><button data-value='compact'>紧凑</button><button data-value='standard'>标准</button><button data-value='large'>大卡</button></div><div class='setting-help'>卡片文字区固定高度,悬停时弹起展开,不再把整行撑乱。</div></div>
|
||
<div class='setting-card'><div class='setting-title'>动效强度</div><div class='segmented' data-segment='motion'><button data-value='full'>完整</button><button data-value='soft'>轻量</button><button data-value='off'>关闭</button></div><div class='setting-help'>页面卡顿时可改成轻量或关闭;不会影响备份数据。</div></div>
|
||
<div class='setting-card'><div class='setting-title'>主题配色</div><div class='segmented accent-buttons' data-segment='accentColor'><button data-value='pink'>樱粉</button><button data-value='wisteria'>紫藤</button><button data-value='cyan'>青蓝</button><button data-value='amber'>暖黄</button><button data-value='mint'>薄荷</button></div><div class='setting-help'>影响背景、边框、选中态、按钮与动效光晕的强调色。</div></div>
|
||
</div>
|
||
<div class='number-grid' style='margin-top:14px'>
|
||
<div class='field'><label>每次显示条数</label><input id='pageSizeInput' type='number' min='40' max='360' step='20' placeholder='例如 120' /><div class='help'>越小越顺滑;越大越少点”再显示”。</div></div>
|
||
<div class='field'><label>卡片吐槽预览行数</label><input id='commentLinesInput' type='number' min='0' max='6' step='1' placeholder='例如 3' /><div class='help'>设为 0 可基本隐藏预览,只在详情里看完整吐槽。</div></div>
|
||
<div class='field'><label>UI 白边粗细(px)</label><input id='borderWidthInput' type='number' min='0' max='4' step='0.5' placeholder='0 到 4' /><div class='help'>控制卡片、弹窗、按钮等玻璃边框;设为 0 可关闭大部分白边。</div></div>
|
||
</div>
|
||
</div>
|
||
<div class='settings-pane' id='stab-advanced'>
|
||
<div class='advanced-grid'>
|
||
<div class='setting-card'>
|
||
<div class='setting-title'>修改管理员密码</div>
|
||
<div class='split'>
|
||
<div class='field'><label>当前密码</label><input id='currentAdminPasswordInput' type='password' autocomplete='current-password' /></div>
|
||
<div class='field'><label>新密码</label><input id='newAdminPasswordInput' type='password' autocomplete='new-password' minlength='10' /></div>
|
||
</div>
|
||
<button class='btn warn' id='changePasswordBtn' type='button' style='margin-top:12px'>修改密码</button>
|
||
</div>
|
||
<div class='setting-card'>
|
||
<div class='setting-title'>公开访问</div>
|
||
<label class='pill'>公开保管库(访客无需密码即可浏览)<input type='checkbox' id='publicModeInput' class='switch-input' /><span class='switch'></span></label>
|
||
<label class='pill'>允许访客查看 NSFW 条目<input type='checkbox' id='publicNsfwInput' class='switch-input' /><span class='switch'></span></label>
|
||
</div>
|
||
<details class='setting-card net-collapse'>
|
||
<summary class='setting-title'>网络与镜像</summary>
|
||
<div class='field'><label>自定义 API 地址</label><input id='bgmApiBaseInput' type='text' placeholder='https://api.bgm.tv' /><div class='help'>留空用默认 api.bgm.tv。<b>自定义会把 Access Token 发往该地址,只填可信镜像。</b></div></div>
|
||
<div class='field'><label>图片反代 / 镜像</label><input id='imageProxyInput' type='text' placeholder='留空不代理;可含 {url} 占位' /><div class='help'>未缓存的在线封面走此代理;含 <code>{url}</code> 时替换原图地址,否则前缀拼接。</div></div>
|
||
<div class='field'><label>Bangumi 站点地址</label><input id='siteBaseInput' type='text' placeholder='https://bgm.tv' /><div class='help'>打开条目/标签页用;留空用 bgm.tv。例:https://bgmmi.anibt.net</div></div>
|
||
</details>
|
||
</div>
|
||
</div>
|
||
<div class='settings-pane' id='stab-login'>
|
||
<div class='field'><label>管理员密码</label><input id='publicLoginPasswordInput' type='password' autocomplete='current-password' /></div>
|
||
<button class='btn primary' id='publicLoginSubmitBtn' type='button' style='width:100%'>登录</button>
|
||
<div class='auth-status' id='publicLoginStatus' style='margin-top:10px'></div>
|
||
</div>
|
||
<div class='settings-footer row'>
|
||
<button class='btn primary' id='saveSettingsBtn'>保存设置</button>
|
||
<button class='btn bad' id='logoutBtn' type='button'>退出登录</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="modal-mask" id="syncConfirmModal">
|
||
<div class="modal-card">
|
||
<div class="row"><h2 style="margin:0" id="syncConfirmTitle">同步最近</h2><div class="grow"></div><button class="btn small" data-close="syncConfirmModal">取消</button></div>
|
||
<p class="help" id="syncConfirmHelp"></p>
|
||
<div class="field" id="syncConfirmMonthsRow" style="max-width:280px;margin-top:4px">
|
||
<label>最近同步范围(月)</label>
|
||
<input id="syncConfirmMonthsInput" type="number" min="1" max="120" step="1" placeholder="例如 3" />
|
||
<div class="help">只读取最近 N 个月更新过的收藏;确认后该范围会保存为默认值,自动增量同步也会沿用。</div>
|
||
</div>
|
||
<label class="pill" style="cursor:pointer;margin-top:12px;display:flex;align-items:center;justify-content:space-between;gap:10px">刷新缓存封面到本地<input type="checkbox" id="syncConfirmCoversInput" class="switch-input" /><span class="switch"></span></label>
|
||
<div id="syncConfirmSubjectsRow">
|
||
<label class="pill" style="cursor:pointer;margin-top:8px;display:flex;align-items:center;justify-content:space-between;gap:10px">刷新条目数据(NSFW / 平台 / 公共标签等)<input type="checkbox" id="syncConfirmSubjectsInput" class="switch-input" /><span class="switch"></span></label>
|
||
<div class="help" style="margin-top:8px">关闭“刷新条目数据”可大幅加快同步;已备份条目的元数据会保留,新条目稍后再刷新即可补全。</div>
|
||
</div>
|
||
<div class="row" style="margin-top:16px"><button class="btn primary" id="syncConfirmStartBtn">开始同步</button></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="modal-mask" id="syncModal">
|
||
<div class="modal-card">
|
||
<div class="row"><h2 style="margin:0" id="syncTitle">同步中</h2><div class="grow"></div><button class="btn small" id="cancelSyncBtn">停止显示</button></div>
|
||
<p class="help" id="syncHelp">日常同步只读取最近几个月的更新并增量写入;完整同步才做全量核对和安全箱判断。</p>
|
||
<div class="progress"><div class="bar" id="syncBar"></div></div>
|
||
<div class="sync-log" id="syncLog" style="margin-top:14px"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="modal-mask" id="exportModal">
|
||
<div class="modal-card">
|
||
<div class="row"><h2 style="margin:0">导出与导入</h2><div class="grow"></div><button class="btn small" data-close="exportModal">关闭</button></div>
|
||
<p class="help">完整 ZIP 包含 JSON、CSV、离线 HTML、Word、XLSX 表格、历史版本、同步记录与 images 封面目录。为避免大量 Base64 导致浏览器卡死,完整 ZIP 使用真实图片文件;请先解压 ZIP,再打开 offline-poster-wall.html。</p>
|
||
<div class="row">
|
||
<button class="btn primary" id="exportZipBtn">导出完整 ZIP(快速)</button>
|
||
<button class="btn" id="exportJsonBtn">导出 JSON</button>
|
||
<button class="btn" id="exportCsvBtn">导出 CSV</button>
|
||
<button class="btn" id="exportHtmlBtn">导出单文件 HTML(慢)</button>
|
||
<button class="btn" id="exportDocxBtn">导出文档 .docx</button>
|
||
<button class="btn" id="exportXlsxBtn">导出表格 .xlsx</button>
|
||
</div>
|
||
<div class="notice" style="margin-top:14px">封面离线取决于是否已缓存。完整 ZIP 会把服务端文件卷里的封面作为 images/ 文件夹打包,速度更快、不会塞满 HTML;请解压后打开 offline-poster-wall.html。单文件 HTML 会把封面内嵌成 Base64,条目很多时会很慢,只建议少量条目使用。</div>
|
||
<input type="file" id="importFile" accept="application/json,.json" class="hidden" />
|
||
</div>
|
||
</div>
|
||
|
||
<div class="toast" id="toast"></div>
|
||
|
||
<script src="js/core.js"></script>
|
||
<script src="js/model.js"></script>
|
||
<script src="js/view.js"></script>
|
||
<script src="js/cron.js"></script>
|
||
<script src="js/sync.js"></script>
|
||
<script src="js/covers.js"></script>
|
||
<script src="js/exports.js"></script>
|
||
<script src="js/main.js"></script>
|
||
</body>
|
||
</html>
|