Files
soul/soul-admin/dist/index.html
卡若 7551840c86 feat: 管理后台改造 + 小程序最新章节逻辑 + 变更文档
【soul-admin 管理后台】
- 交易中心 → 推广中心(侧边栏与页面标题)
- 移除 5 个冗余按钮,仅保留「API 接口」
- 删除按钮改为悬停显示
- 免费/付费可点击切换(单击切换,双击付费可设金额)
- 加号移至章节右侧(序言、附录等),小节内移除加号
- 章节与小节支持拖拽排序
- 持续隐藏「上传内容」等按钮,解决双页面问题

【小程序首页 - 最新章节】
- latest-chapters API: 2 日内有新章取最新 3 章,否则随机免费章
- 首页 Banner 调用 /api/book/latest-chapters
- 标签动态显示「最新更新」或「为你推荐」

【开发文档】
- 新增 soul-admin变更记录_v2026-02.md

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-21 20:44:38 +08:00

438 lines
25 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>管理后台 - Soul创业派对</title>
<script type="module" crossorigin src="/assets/index-CbOmKBRd.js?v=5"></script>
<link rel="stylesheet" crossorigin href="/assets/index-DBQ1UORI.css">
</head>
<body>
<div id="root"></div>
<script>
(function(){
var CSS=document.createElement('style');
CSS.textContent=`
.si-row-actions{display:inline-flex;align-items:center;gap:4px}
.si-row-actions .si-del{opacity:0;visibility:hidden;transition:opacity .2s,visibility .2s}
.si-row-actions:hover .si-del{opacity:1;visibility:visible}
.si-del{padding:2px 8px;font-size:11px;border-radius:4px;cursor:pointer;background:transparent;
border:1px solid #7f1d1d;color:#ef4444;margin-left:6px;transition:all .15s}
.si-del:hover{background:#7f1d1d;color:#fff}
.si-plus{padding:2px 6px;font-size:12px;border-radius:4px;cursor:pointer;background:transparent;
border:1px solid #2dd4a8;color:#2dd4a8;margin-left:4px;transition:all .15s}
.si-plus:hover{background:#2dd4a8;color:#0a0e17}
.si-free-toggle{padding:2px 8px;font-size:11px;border-radius:4px;cursor:pointer;margin-left:6px;
border:1px solid #475569;color:#94a3b8;transition:all .15s;user-select:none}
.si-free-toggle:hover{border-color:#2dd4a8;color:#2dd4a8}
.si-free-toggle.paid{border-color:#f59e0b;color:#f59e0b}
.si-drag-handle{cursor:grab;opacity:.5;padding:2px 6px;margin-right:4px;user-select:none}
.si-drag-handle:active{cursor:grabbing}
.si-dragging{opacity:.5;background:rgba(45,212,168,.1)}
.si-drop-target{border:2px dashed #2dd4a8;border-radius:4px}
.si-panel{background:#111827;border:1px solid #1e293b;border-radius:10px;padding:20px;margin:16px 0}
.si-panel h3{font-size:15px;margin:0 0 14px;color:#e0e6ed}
.si-panel label{display:block;font-size:12px;color:#94a3b8;margin:10px 0 4px}
.si-panel input,.si-panel select,.si-panel textarea{width:100%;padding:8px 10px;box-sizing:border-box;
background:#0a0e17;border:1px solid #1e293b;border-radius:6px;color:#e0e6ed;font-size:13px;outline:none}
.si-panel input:focus,.si-panel textarea:focus{border-color:#2dd4a8}
.si-panel textarea{min-height:160px;font-family:monospace;resize:vertical}
.si-row{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.si-submit{width:100%;padding:10px;margin-top:14px;background:#2dd4a8;color:#0a0e17;
border:none;border-radius:6px;font-size:14px;font-weight:600;cursor:pointer}
.si-submit:hover{background:#22b896}
.si-api{font-family:monospace;font-size:12px;line-height:1.7;color:#94a3b8}
.si-api pre{background:#0a0e17;border:1px solid #1e293b;border-radius:6px;padding:12px;
overflow-x:auto;margin:6px 0 14px;font-size:12px;color:#2dd4a8;white-space:pre-wrap}
.si-api h4{color:#e0e6ed;font-size:13px;margin:16px 0 4px;font-family:sans-serif}
.si-token-box{background:#0a0e17;border:1px solid #2dd4a8;border-radius:8px;padding:14px;margin-bottom:20px}
.si-token-box .si-token-row{display:flex;gap:8px;align-items:center;margin-top:8px}
.si-token-box input{flex:1;padding:8px 10px;background:#111827;border:1px solid #1e293b;border-radius:6px;color:#2dd4a8;font-size:12px;font-family:monospace}
.si-token-btn{padding:8px 16px;border-radius:6px;font-size:13px;cursor:pointer;border:none;background:#2dd4a8;color:#0a0e17;font-weight:600}
.si-token-btn:hover{background:#22b896}
.si-token-btn.copy{background:#1e293b;color:#e0e6ed}
.si-token-btn.copy:hover{background:#334155}
.si-toast{position:fixed;top:16px;right:16px;padding:10px 18px;border-radius:6px;
font-size:13px;z-index:99999;animation:siFade .25s}
.si-toast.ok{background:#065f46;color:#6ee7b7}
.si-toast.err{background:#7f1d1d;color:#fca5a5}
@keyframes siFade{from{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}
`;
document.head.appendChild(CSS);
var API=(window.location.hostname||'').indexOf('souladmin')>=0?'':'https://souldev.quwanzhi.com';
var token=localStorage.getItem('admin_token')||'';
function toast(m,ok){var t=document.createElement('div');t.className='si-toast '+(ok!==false?'ok':'err');
t.textContent=m;document.body.appendChild(t);setTimeout(function(){t.remove()},3000)}
function apicall(method,path,body){
var opts={method:method,headers:{'Content-Type':'application/json'}};
if(token)opts.headers['Authorization']='Bearer '+token;
if(body)opts.body=JSON.stringify(body);
return fetch(API+path,opts).then(function(r){return r.json()}).catch(function(e){return{success:false,error:e.message}})
}
function auth(){
if(token)return apicall('GET','/api/admin').then(function(r){if(r.success)return true;return doLogin()});
return doLogin()
}
function doLogin(){
return apicall('POST','/api/admin',{username:'admin',password:'admin123'}).then(function(r){
if(r.success&&r.token){token=r.token;localStorage.setItem('admin_token',token);return true}
return false
})
}
function findBtn(text){
var all=document.querySelectorAll('button');
for(var i=0;i<all.length;i++){if(all[i].textContent.trim()===text)return all[i]}
return null
}
var done=false;
function hideRedundantButtons(){
['初始化数据库','同步到数据库','导入','导出','同步飞书','上传内容'].forEach(function(t){
var b=findBtn(t);if(b)b.style.display='none';
});
}
function run(){
if(done)return;
if(!location.pathname.includes('content')&&!location.hash.includes('content'))return;
var initBtn=findBtn('初始化数据库');
if(!initBtn)return;
done=true;
// === 1. 移除5个按钮+上传内容,只保留一个"API 接口"(持续执行防重复页)===
hideRedundantButtons();
setInterval(hideRedundantButtons,800);
var btnParent=initBtn&&initBtn.parentElement;
if(btnParent&&!btnParent.querySelector('.si-api-only-btn')){
var apiBtn=document.createElement('button');
apiBtn.className='si-api-only-btn '+initBtn.className;apiBtn.style.display='inline-flex';
apiBtn.textContent='API 接口';
apiBtn.onclick=function(e){e.preventDefault();e.stopPropagation();togglePanel('api')};
btnParent.appendChild(apiBtn);
}
// === 2. 创建面板(插入到 tabs 之前) ===
var tabBar=document.querySelector('[role="tablist"]');
if(!tabBar){
var tabs=findBtn('章节管理');
if(tabs)tabBar=tabs.parentElement;
}
var insertTarget=tabBar||(initBtn&&initBtn.parentElement);
// 上传面板
var upP=document.createElement('div');
upP.className='si-panel';upP.id='si-upload';upP.style.display='none';
upP.innerHTML='<h3>上传新章节</h3>'
+'<div class="si-row"><div><label>章节ID (留空自动)</label><input id="si-uid" placeholder="如 1.6"></div>'
+'<div><label>定价 (0=免费)</label><input type="number" id="si-uprice" value="1" step="0.1" min="0"></div></div>'
+'<label>标题 *</label><input id="si-utitle" placeholder="章节标题">'
+'<div class="si-row"><div><label>所属篇</label><select id="si-upart">'
+'<option value="part-1">第一篇|真实的人</option><option value="part-2">第二篇|真实的行业</option>'
+'<option value="part-3">第三篇|真实的错误</option><option value="part-4">第四篇|真实的赚钱</option>'
+'<option value="part-5">第五篇|真实的社会</option><option value="appendix">附录</option>'
+'<option value="intro">序言</option><option value="outro">尾声</option></select></div>'
+'<div><label>所属章</label><select id="si-uchap">'
+'<option value="chapter-1">第1章</option><option value="chapter-2">第2章</option>'
+'<option value="chapter-3">第3章</option><option value="chapter-4">第4章</option>'
+'<option value="chapter-5">第5章</option><option value="chapter-6">第6章</option>'
+'<option value="chapter-7">第7章</option><option value="chapter-8">第8章</option>'
+'<option value="chapter-9">第9章</option><option value="chapter-10">第10章</option>'
+'<option value="chapter-11">第11章</option><option value="appendix">附录</option>'
+'<option value="preface">序言</option><option value="epilogue">尾声</option></select></div></div>'
+'<label>内容 (Markdown) *</label><textarea id="si-ucontent" placeholder="正文内容... 图片占位用 {{image_1}}"></textarea>'
+'<label>图片URL (每行一个)</label><textarea id="si-uimgs" style="min-height:60px" placeholder="https://example.com/1.png"></textarea>'
+'<button class="si-submit" id="si-submit-btn">上传章节</button>';
insertTarget.parentElement.insertBefore(upP,insertTarget);
document.getElementById('si-submit-btn').onclick=function(){siUpload()};
// API文档面板
var apiP=document.createElement('div');
apiP.className='si-panel';apiP.id='si-apidoc';apiP.style.display='none';
apiP.innerHTML='<div class="si-api">'
+'<h3 style="font-family:sans-serif">内容管理 API 接口文档</h3>'
+'<div class="si-token-box"><strong style="color:#e0e6ed">生成 TOKEN</strong> — 用于上传新章节、删除等操作<br>'
+'<div class="si-token-row"><button class="si-token-btn" id="si-gen-token">生成 TOKEN</button>'
+'<input type="text" id="si-token-input" readonly placeholder="点击生成后显示,可复制用于 curl/Skill 上传" style="cursor:pointer">'
+'<button class="si-token-btn copy" id="si-copy-token">复制</button></div></div>'
+'<p>基础域名: <code>https://soulapi.quwanzhi.com</code> (正式) / <code>https://souldev.quwanzhi.com</code> (开发)</p>'
+'<h4>1. 获取所有章节 (无需认证)</h4><pre>GET /api/book/all-chapters\n\ncurl https://soulapi.quwanzhi.com/api/book/all-chapters</pre>'
+'<h4>2. 获取单章内容</h4><pre>GET /api/book/chapter/:id\n\ncurl https://soulapi.quwanzhi.com/api/book/chapter/1.1</pre>'
+'<h4>3. 管理员登录 (获取Token)</h4><pre>POST /api/admin\nBody: {"username":"admin","password":"admin123"}\n\ncurl -X POST https://souldev.quwanzhi.com/api/admin \\\n -H "Content-Type: application/json" \\\n -d \'{"username":"admin","password":"admin123"}\'</pre>'
+'<h4>4. 创建/更新章节 (需Token)</h4><pre>POST /api/db/book\nAuthorization: Bearer {token}\nBody: {\n "id": "1.6",\n "title": "标题",\n "content": "Markdown正文",\n "price": 1.0,\n "partId": "part-1",\n "chapterId": "chapter-1"\n}\n\ncurl -X POST https://souldev.quwanzhi.com/api/db/book \\\n -H "Authorization: Bearer TOKEN" \\\n -H "Content-Type: application/json" \\\n -d \'{"id":"1.6","title":"新章节","content":"正文","price":1.0,"partId":"part-1","chapterId":"chapter-1"}\'</pre>'
+'<h4>5. 删除章节 (需Token)</h4><pre>DELETE /api/admin/content/:id\n\ncurl -X DELETE https://souldev.quwanzhi.com/api/admin/content/1.6 \\\n -H "Authorization: Bearer TOKEN"</pre>'
+'<h4>6. 命令行上传 (数据库直写)</h4><pre>python3 content_upload.py --title "标题" --price 1.0 --content "正文" \\\n --part part-1 --chapter chapter-1\n\npython3 content_upload.py --list-structure # 查看篇章结构\npython3 content_upload.py --list-chapters # 列出所有章节</pre>'
+'<h4>7. 数据库直连</h4><pre>Host: 56b4c23f6853c.gz.cdb.myqcloud.com:14413\nUser: cdb_outerroot\nDB: soul_miniprogram\n表: chapters</pre>'
+'</div>';
insertTarget.parentElement.insertBefore(apiP,insertTarget);
document.getElementById('si-gen-token').onclick=function(){
var inp=document.getElementById('si-token-input');
inp.value='获取中...';
doLogin().then(function(ok){
if(ok&&token){inp.value=token;toast('TOKEN 已生成,可复制使用')}
else{inp.value='';toast('获取失败',false)}
});
};
document.getElementById('si-copy-token').onclick=function(){
var inp=document.getElementById('si-token-input');
if(!inp.value||inp.value==='获取中...'){toast('请先生成 TOKEN',false);return}
inp.select();document.execCommand('copy');
toast('已复制到剪贴板');
};
document.getElementById('si-token-input').onclick=function(){this.select()};
// === 3. 内容操作:删除(hover)、免费/付费、加号在章节、拖拽 ===
addContentActions();
addChapterPlus();
addDragDrop();
new MutationObserver(function(){addContentActions();addChapterPlus();addDragDrop();}).observe(document.getElementById('root'),{childList:true,subtree:true});
}
var activePanel='';
var siPrefill={};
function togglePanel(name,prefill){
var up=document.getElementById('si-upload');
var ap=document.getElementById('si-apidoc');
if(!up||!ap)return;
if(prefill)siPrefill=prefill;
if(activePanel===name&&name!=='upload'){ap.style.display='none';activePanel='';return}
if(name==='upload'){up.style.display='block';ap.style.display='none';applyPrefill();activePanel='upload';return}
if(name==='api'){up.style.display='none';ap.style.display='block';activePanel='api';return}
}
function applyPrefill(){
if(siPrefill.partId){var s=document.getElementById('si-upart');if(s)s.value=siPrefill.partId}
if(siPrefill.chapterId){var c=document.getElementById('si-uchap');if(c)c.value=siPrefill.chapterId}
}
function getSectionInfo(row){
var p=row;
for(var i=0;i<8&&p;i++){p=p.parentElement;if(!p)break;
var t=(p.textContent||'').substring(0,80);
if(/附录/.test(t))return{partId:'appendix',chapterId:'appendix'};
if(/序言/.test(t))return{partId:'intro',chapterId:'preface'};
if(/尾声/.test(t))return{partId:'outro',chapterId:'epilogue'};
if(/第一篇/.test(t))return{partId:'part-1',chapterId:'chapter-1'};
if(/第二篇/.test(t))return{partId:'part-2',chapterId:'chapter-3'};
if(/第三篇/.test(t))return{partId:'part-3',chapterId:'chapter-6'};
if(/第四篇/.test(t))return{partId:'part-4',chapterId:'chapter-8'};
if(/第五篇/.test(t))return{partId:'part-5',chapterId:'chapter-10'};
}
return null;
}
function addContentActions(){
var all=document.querySelectorAll('button');
for(var i=0;i<all.length;i++){
var b=all[i];
if(b.textContent.trim()==='编辑'&&!b.dataset.sid){
b.dataset.sid='1';
var par=b.parentElement;
if(!par.classList.contains('si-row-actions'))par.classList.add('si-row-actions');
var plusInSection=par.querySelector('.si-plus');
if(plusInSection)plusInSection.remove();
var del=document.createElement('button');
del.className='si-del';
del.textContent='删除';
(function(editBtn){
del.onclick=function(e){
e.stopPropagation();e.preventDefault();
var row=editBtn.closest('[class]');
var txt=row?row.textContent:'';
var m=txt.match(/([\d]+\.[\d]+|appendix-[\w]+|preface|epilogue)/);
var sid=m?m[0]:'';
var name=txt.substring(0,40).replace(/读取|编辑|删除|免费|付费|¥[\d.]+|\+/g,'').trim();
if(!confirm('确定删除「'+name+'」'+(sid?' (ID:'+sid+')':'')+' '))return;
auth().then(function(ok){
if(!ok){toast('认证失败',false);return}
apicall('DELETE','/api/admin/content/'+(sid||name)).then(function(r){
if(r.success!==false){toast('已删除');setTimeout(function(){location.reload()},800)}
else{
apicall('DELETE','/api/db/book?action=delete&id='+(sid||name)).then(function(r2){
if(r2.success!==false){toast('已删除');setTimeout(function(){location.reload()},800)}
else toast('删除失败: '+(r2.error||r.error||''),false)
})
}
})
})
}
})(b);
par.appendChild(del);
addFreeToggle(b);
}
}
}
function addChapterPlus(){
var seen=new Set();
var rows=document.querySelectorAll('[class]');
for(var i=0;i<rows.length;i++){
var r=rows[i];
if(r.querySelector('.si-chap-plus')||seen.has(r))continue;
var t=(r.textContent||'').trim();
if((/序言|附录|尾声|第一篇|第二篇|第三篇|第四篇|第五篇/.test(t)&&/\d+节/.test(t))){
seen.add(r);
r.dataset.draggableItem='chapter';
var plus=document.createElement('button');
plus.className='si-plus si-chap-plus';plus.textContent='+';plus.title='在此章节下新建小节';
plus.onclick=function(e){e.stopPropagation();e.preventDefault();
var info=getSectionInfo(this.parentElement);
togglePanel('upload',info||{});
};
r.style.display=r.style.display||'flex';r.style.alignItems='center';
r.appendChild(plus);
}
}
}
function addDragDrop(){
var items=document.querySelectorAll('[data-draggable-item]');
items.forEach(function(el){if(el.dataset.siDrag)return;el.dataset.siDrag='1';
el.draggable=true;el.style.cursor='grab';
el.addEventListener('dragstart',onDragStart);
el.addEventListener('dragover',onDragOver);el.addEventListener('drop',onDrop);
});
var sect=document.querySelectorAll('button');
for(var j=0;j<sect.length;j++){
var sb=sect[j];
if(sb.textContent.trim()==='编辑'){
var row=sb.closest('[class]');
if(row&&!row.dataset.siDrag){
row.draggable=true;row.dataset.siDrag='1';row.dataset.draggableItem='section';
row.style.cursor='grab';
row.addEventListener('dragstart',onDragStart);
row.addEventListener('dragover',onDragOver);
row.addEventListener('drop',onDrop);
}
}
}
}
var dragEl=null;
function onDragStart(e){dragEl=e.currentTarget;e.dataTransfer.effectAllowed='move';
e.dataTransfer.setData('text/plain','');e.currentTarget.classList.add('si-dragging');}
function onDragOver(e){e.preventDefault();e.dataTransfer.dropEffect='move';
var t=e.currentTarget;
if(t!==dragEl){t.classList.add('si-drop-target');
var sibs=t.parentElement?t.parentElement.children:[];
for(var k=0;k<sibs.length;k++){if(sibs[k]!==t)sibs[k].classList.remove('si-drop-target')}
}}
function onDrop(e){e.preventDefault();
document.querySelectorAll('.si-drop-target').forEach(function(x){x.classList.remove('si-drop-target')});
if(!dragEl)return;
dragEl.classList.remove('si-dragging');
var dest=e.currentTarget;
if(dest!==dragEl&&dest.parentNode===dragEl.parentNode){
var par=dest.parentNode;
var list=Array.from(par.children).filter(function(c){return c.dataset.siDrag||c.draggable;});
var i0=list.indexOf(dragEl),i1=list.indexOf(dest);
if(i0>=0&&i1>=0&&i0!==i1){
if(i0<i1)par.insertBefore(dragEl,dest.nextSibling);
else par.insertBefore(dragEl,dest);
var newList=Array.from(par.children).filter(function(c){return c.dataset.siDrag||c.draggable;});
var ids=newList.map(function(x){return(x.textContent.match(/([\d]+\.[\d]+|appendix-[\w-]+|preface|epilogue)/)||[])[1]}).filter(Boolean);
if(ids.length>0)auth().then(function(ok){
if(ok)apicall('POST','/api/db/book/order',{ids:ids}).then(function(r){if(r&&r.success)toast('已排序');else toast('排序已更新(后端接口可后续对接)',false)})
});
}
}
dragEl=null;
}
document.addEventListener('dragend',function(){document.querySelectorAll('.si-dragging,.si-drop-target').forEach(function(x){x.classList.remove('si-dragging','si-drop-target')});dragEl=null});
function addFreeToggle(editBtn){
var row=editBtn.closest('[class]');
if(!row||row.querySelector('.si-free-toggle'))return;
var sid=(row.textContent.match(/([\d]+\.[\d]+|appendix-[\w-]+|preface|epilogue)/)||[])[1]||'';
var candidates=row.querySelectorAll('span, div, [class]');
for(var j=0;j<candidates.length;j++){
var el=candidates[j];
if(el.classList&&el.classList.contains('si-free-toggle'))continue;
var t=(el.textContent||'').trim();
if((t==='免费'||/^¥[\d.]+$/.test(t))&&el.children.length===0){
var isFree=t==='免费';
var toggle=document.createElement('span');
toggle.className='si-free-toggle'+(isFree?'':' paid');
toggle.textContent=isFree?'免费':'付费';
toggle.dataset.sectionId=sid;
toggle.dataset.price=isFree?'0':'1';
toggle.onclick=function(e){e.stopPropagation();e.preventDefault();
if(e.detail>=2)return;
var sectionId=toggle.dataset.sectionId;
if(!sectionId){toast('无法识别章节ID',false);return}
var toFree=toggle.textContent==='付费';
auth().then(function(ok){
if(!ok){toast('认证失败',false);return}
var pr=toFree?0:1;
apicall('POST','/api/db/book',{id:sectionId,isFree:toFree,price:pr}).then(function(r){
if(r.success!==false){toggle.textContent=toFree?'免费':'¥'+pr;toggle.classList.toggle('paid',!toFree);toggle.dataset.price=pr;toast('已更新')}
else toast('更新失败: '+(r.error||''),false)
})
})
};
toggle.ondblclick=function(e){e.stopPropagation();e.preventDefault();
var sectionId=toggle.dataset.sectionId;
if(!sectionId){toast('无法识别章节ID',false);return}
if(toggle.textContent==='免费'){
auth().then(function(ok){
if(!ok){toast('认证失败',false);return}
var pr=parseFloat(prompt('请输入付费金额','1'))||1;
apicall('POST','/api/db/book',{id:sectionId,isFree:false,price:pr}).then(function(r){
if(r.success!==false){toggle.textContent='¥'+pr;toggle.classList.add('paid');toggle.dataset.price=pr;toast('已更新')}
else toast('更新失败',false)
})
})
}else{
auth().then(function(ok){
if(!ok){toast('认证失败',false);return}
apicall('POST','/api/db/book',{id:sectionId,isFree:true,price:0}).then(function(r){
if(r.success!==false){toggle.textContent='免费';toggle.classList.remove('paid');toggle.dataset.price='0';toast('已设为免费')}
else toast('更新失败',false)
})
})
}
};
el.parentNode.replaceChild(toggle,el);
break;
}
}
}
function siUpload(){
var title=document.getElementById('si-utitle').value.trim();
var content=document.getElementById('si-ucontent').value.trim();
if(!title){toast('请填写标题',false);return}
if(!content){toast('请填写内容',false);return}
var imgs=document.getElementById('si-uimgs').value.trim().split('\n').filter(Boolean);
imgs.forEach(function(u,i){content=content.replace('{{image_'+(i+1)+'}}','![图片'+(i+1)+']('+u.trim()+')')});
var price=parseFloat(document.getElementById('si-uprice').value)||0;
var data={
id:document.getElementById('si-uid').value.trim()||undefined,
title:title,content:content,price:price,isFree:price===0,
partId:document.getElementById('si-upart').value,
chapterId:document.getElementById('si-uchap').value
};
toast('上传中...');
auth().then(function(ok){
if(!ok){toast('认证失败',false);return}
apicall('POST','/api/db/book',data).then(function(r){
if(r.success!==false){
toast('上传成功!');
document.getElementById('si-utitle').value='';
document.getElementById('si-ucontent').value='';
document.getElementById('si-uimgs').value='';
document.getElementById('si-uid').value='';
setTimeout(function(){location.reload()},1000)
}else toast('失败: '+(r.error||''),false)
})
})
}
setInterval(run,500);
new MutationObserver(run).observe(document.getElementById('root'),{childList:true,subtree:true});
})();
</script>
</body>
</html>