feat: v1.5.0 — GitHub 账号添加/编辑改为弹窗式(带✏️编辑按钮)
- 「添加 GitHub 账号」改为卡片里的按钮,点击弹出填写弹窗
(模态:备注/用户名/Token/私有,含取消/验证并添加/ESC/点背景关闭)
- 表格每行新增 ✏️ 编辑按钮:弹出编辑弹窗,预填当前值
(Token 字段空着+占位符显示当前掩码,留空则保留原 Token,
只改备注/私有时无需重新输入 Token)
- 后端新增 /api/accounts/edit 端点(按 id 改备注/私有/Token),
add 改为严格新增(gh_user 重复则拒绝并引导用编辑功能)
- 顶部横幅「去添加 Token」直接打开当前账号的编辑弹窗并聚焦 Token
- 移除了原来表内的「添加 Token」按钮(编辑弹窗已覆盖该流程)
- manifest 1.4.1 → 1.5.0
This commit is contained in:
@@ -956,6 +956,29 @@ h2 .h2sub{font-size:12px;font-weight:400;color:#8a919e;margin-left:10px}
|
|||||||
.saved-tip{font-size:12px;font-weight:600;white-space:nowrap}
|
.saved-tip{font-size:12px;font-weight:600;white-space:nowrap}
|
||||||
.saved-tip.ok{color:#0a7d34}
|
.saved-tip.ok{color:#0a7d34}
|
||||||
.saved-tip.err{color:#b91c1c}
|
.saved-tip.err{color:#b91c1c}
|
||||||
|
input[readonly]{background:#f6f8fa;color:#646a73;cursor:not-allowed}
|
||||||
|
.b-icon{padding:5px 9px;min-width:auto;font-size:13px}
|
||||||
|
/* ---------- 模态弹窗 ---------- */
|
||||||
|
.modal{display:none;position:fixed;inset:0;background:rgba(15,23,42,.45);z-index:1000;align-items:center;justify-content:center;padding:20px}
|
||||||
|
.modal.show{display:flex}
|
||||||
|
.modal-box{background:#fff;border-radius:14px;width:100%;max-width:480px;box-shadow:0 20px 60px rgba(0,0,0,.25);max-height:90vh;overflow:auto;animation:modalIn .15s ease-out}
|
||||||
|
@keyframes modalIn{from{transform:translateY(-8px);opacity:.6}to{transform:translateY(0);opacity:1}}
|
||||||
|
.modal-head{display:flex;align-items:center;justify-content:space-between;padding:18px 22px;border-bottom:1px solid #eef0f3}
|
||||||
|
.modal-head h3{font-size:17px;margin:0}
|
||||||
|
.modal-close{background:none;border:none;font-size:24px;color:#646a73;cursor:pointer;padding:2px 10px;border-radius:6px;line-height:1}
|
||||||
|
.modal-close:hover{background:#f0f2f5;color:#1f2329}
|
||||||
|
.modal-body{padding:22px;display:flex;flex-direction:column;gap:8px}
|
||||||
|
.modal-body input[type=text],.modal-body input[type=password]{
|
||||||
|
border:1px solid #d0d5dd;border-radius:10px;padding:11px 14px;font-size:14px;outline:none;width:100%;box-sizing:border-box;font-family:inherit}
|
||||||
|
.modal-body input:focus{border-color:#7c3aed}
|
||||||
|
.modal-foot{padding:14px 22px;border-top:1px solid #eef0f3;display:flex;align-items:center;gap:10px;flex-wrap:wrap}
|
||||||
|
.modal-msg{font-size:13px;flex:1;min-width:0;word-break:break-word}
|
||||||
|
.modal-msg.ok{color:#0a7d34}
|
||||||
|
.modal-msg.err{color:#b91c1c}
|
||||||
|
.modal-msg:empty{display:none}
|
||||||
|
@media (max-width:760px){
|
||||||
|
.modal-box{max-width:none}
|
||||||
|
}
|
||||||
table.hover tbody tr:hover{background:#f8fafc}
|
table.hover tbody tr:hover{background:#f8fafc}
|
||||||
td.ops{white-space:nowrap}
|
td.ops{white-space:nowrap}
|
||||||
td.ops button,td.ops .pill{margin:2px 4px 2px 0}
|
td.ops button,td.ops .pill{margin:2px 4px 2px 0}
|
||||||
@@ -1219,21 +1242,9 @@ PAGE_SETTINGS = """
|
|||||||
</div>
|
</div>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h2>添加 / 更新 GitHub 账号<span class="h2sub">Token 验证通过后自动识别用户名</span></h2>
|
<h2>添加 / 更新 GitHub 账号<span class="h2sub">Token 验证通过后自动识别用户名</span></h2>
|
||||||
<label class="flabel">备注名<span class="sub">方便自己识别,可留空</span></label>
|
<p style="color:#646a73;margin-bottom:14px">添加多个账号后可随时切换推送目标,每个账号独立记录同步进度。已存在的账号可点表格行右边的 ✏️ 编辑。</p>
|
||||||
<div class="addrow"><input id="accLabel" placeholder="如:我的主账号"></div>
|
<button class="b-add" onclick="openAddModal()" style="font-size:15px;padding:12px 24px">➕ 添加 GitHub 账号</button>
|
||||||
<label class="flabel">GitHub 用户名<span class="sub">留空则按 Token 自动识别</span></label>
|
<div class="tip" style="margin-top:16px">
|
||||||
<div class="addrow"><input id="accUser" placeholder="如 cbb2625274797"></div>
|
|
||||||
<label class="flabel">Personal Access Token</label>
|
|
||||||
<div class="addrow"><input id="accToken" type="password" placeholder="ghp_ 开头"></div>
|
|
||||||
<label class="flabel">自动创建的仓库设为</label>
|
|
||||||
<div class="addrow" style="align-items:center">
|
|
||||||
<label class="chk"><input type="checkbox" id="accPrivate" checked> 私有(推荐)</label>
|
|
||||||
</div>
|
|
||||||
<div class="btns" style="margin-top:14px">
|
|
||||||
<button class="b-add" id="btnAccAdd" onclick="addAccount()">✓ 验证并添加</button>
|
|
||||||
</div>
|
|
||||||
<div class="msg" id="msgAcc"></div>
|
|
||||||
<div class="tip">
|
|
||||||
Token 获取:GitHub → Settings → Developer settings → Personal access tokens →
|
Token 获取:GitHub → Settings → Developer settings → Personal access tokens →
|
||||||
<b>Tokens (classic)</b> → Generate new token,勾选 <b>repo</b> 权限(即可自动创建仓库并推送)。<br>
|
<b>Tokens (classic)</b> → Generate new token,勾选 <b>repo</b> 权限(即可自动创建仓库并推送)。<br>
|
||||||
链接:<a href="https://github.com/settings/tokens" target="_blank">github.com/settings/tokens</a> ·
|
链接:<a href="https://github.com/settings/tokens" target="_blank">github.com/settings/tokens</a> ·
|
||||||
@@ -1352,15 +1363,16 @@ async function refresh(){
|
|||||||
?`<div class="banner warn"><span class="ic">⚠️</span><div><b>当前账号「${esc(cur.label)}」通过 SSH 私钥推送,暂时无法自动创建仓库。</b>
|
?`<div class="banner warn"><span class="ic">⚠️</span><div><b>当前账号「${esc(cur.label)}」通过 SSH 私钥推送,暂时无法自动创建仓库。</b>
|
||||||
<br>GitHub 的创建仓库接口只认 Token 认证,SSH 私钥只能推送<b>已存在</b>的仓库——这是 GitHub 的限制,不是软件没做。
|
<br>GitHub 的创建仓库接口只认 Token 认证,SSH 私钥只能推送<b>已存在</b>的仓库——这是 GitHub 的限制,不是软件没做。
|
||||||
<br>给这个账号配上 Token 即可解锁(推送也会改走 HTTPS,更稳更快):
|
<br>给这个账号配上 Token 即可解锁(推送也会改走 HTTPS,更稳更快):
|
||||||
<button class="b-mini" style="margin-left:6px" onclick="upgradeAcc('${esc(cur.id)}','${esc(cur.gh_user)}')">去添加 Token</button></div></div>`
|
<button class="b-mini" style="margin-left:6px" onclick="upgradeAcc('${esc(cur.id)}')">去添加 Token</button></div></div>`
|
||||||
:'';
|
:'';
|
||||||
|
allAccounts=s.accounts||[];
|
||||||
document.getElementById('tbAcc').innerHTML=(s.accounts||[]).map(a=>{
|
document.getElementById('tbAcc').innerHTML=(s.accounts||[]).map(a=>{
|
||||||
const isCur=a.id===s.active;
|
const isCur=a.id===s.active;
|
||||||
const ops=isCur
|
const ops=isCur
|
||||||
? '<span class="pill on">当前使用</span>'
|
? '<span class="pill on">当前使用</span>'
|
||||||
: `<button class="b-mini" onclick="switchAcc('${esc(a.id)}')">切换到此账号</button>`;
|
: `<button class="b-mini" onclick="switchAcc('${esc(a.id)}')">切换到此账号</button>`;
|
||||||
const verify=a.has_token?`<button class="b-mini" onclick="verifyAcc('${esc(a.id)}')">验证</button>`:'';
|
const verify=a.has_token?`<button class="b-mini" onclick="verifyAcc('${esc(a.id)}')">验证</button>`:'';
|
||||||
const upgrade=a.has_token?'':`<button class="b-mini" onclick="upgradeAcc('${esc(a.id)}','${esc(a.gh_user)}')">添加 Token</button>`;
|
const edit=`<button class="b-mini b-icon" title="编辑" onclick="openEditModal('${esc(a.id)}')">✏️</button>`;
|
||||||
const del=(a.has_token||(s.accounts||[]).length>1)
|
const del=(a.has_token||(s.accounts||[]).length>1)
|
||||||
? `<button class="b-del" onclick="delAcc('${esc(a.id)}')">删除</button>`:'';
|
? `<button class="b-del" onclick="delAcc('${esc(a.id)}')">删除</button>`:'';
|
||||||
const method=a.has_token
|
const method=a.has_token
|
||||||
@@ -1373,33 +1385,78 @@ async function refresh(){
|
|||||||
+`<td data-label="Token" class="mono">${esc(a.token||'(未配置)')}</td>`
|
+`<td data-label="Token" class="mono">${esc(a.token||'(未配置)')}</td>`
|
||||||
+`<td data-label="推送方式">${method}</td>`
|
+`<td data-label="推送方式">${method}</td>`
|
||||||
+`<td data-label="自动建库">${create}</td>`
|
+`<td data-label="自动建库">${create}</td>`
|
||||||
+`<td data-label="操作" class="ops">${ops} ${verify} ${upgrade} ${del}</td></tr>`;
|
+`<td data-label="操作" class="ops">${ops} ${edit} ${verify} ${del}</td></tr>`;
|
||||||
}).join('')||'<tr><td colspan="6" style="color:#646a73">暂无账号</td></tr>';
|
}).join('')||'<tr><td colspan="6" style="color:#646a73">暂无账号</td></tr>';
|
||||||
}catch(e){showMsg('msgAcc','刷新失败: '+e,false)}
|
}catch(e){showMsg('msgAcc','刷新失败: '+e,false)}
|
||||||
}
|
}
|
||||||
function upgradeAcc(id,ghUser){
|
// ---- GitHub 账号:弹窗式添加/编辑 ----
|
||||||
// 预填「添加/更新账号」表单并滚动过去,引导给旧账号补 Token
|
let allAccounts=[];
|
||||||
document.getElementById('accLabel').value='';
|
function showModalMsg(id,t,ok){
|
||||||
document.getElementById('accUser').value=ghUser||'';
|
const m=document.getElementById(id);
|
||||||
document.getElementById('accToken').value='';
|
m.textContent=t||''; m.className='modal-msg'+(ok===true?' ok':(ok===false?' err':''));
|
||||||
document.getElementById('accToken').focus();
|
|
||||||
document.getElementById('accToken').scrollIntoView({behavior:'smooth',block:'center'});
|
|
||||||
showMsg('msgAcc','已为你填好用户名 '+ghUser+',把 Token 粘贴进去点「验证并添加」即可(会更新原账号)',true);
|
|
||||||
}
|
}
|
||||||
async function addAccount(){
|
function closeModal(id){ document.getElementById(id).classList.remove('show'); }
|
||||||
const label=document.getElementById('accLabel').value.trim();
|
function openAddModal(){
|
||||||
const gh_user=document.getElementById('accUser').value.trim();
|
document.getElementById('addLabel').value='';
|
||||||
const token=document.getElementById('accToken').value.trim();
|
document.getElementById('addUser').value='';
|
||||||
const priv=document.getElementById('accPrivate').checked;
|
document.getElementById('addToken').value='';
|
||||||
if(!token){showMsg('msgAcc','请填写 Personal Access Token',false);return;}
|
document.getElementById('addPrivate').checked=true;
|
||||||
const b=document.getElementById('btnAccAdd');b.disabled=true;b.textContent='⏳ 验证中…';
|
showModalMsg('addMsg','',null);
|
||||||
|
document.getElementById('modalAdd').classList.add('show');
|
||||||
|
setTimeout(()=>document.getElementById('addLabel').focus(),50);
|
||||||
|
}
|
||||||
|
function openEditModal(id, focusToken){
|
||||||
|
const acc=allAccounts.find(a=>a.id===id);
|
||||||
|
if(!acc)return;
|
||||||
|
document.getElementById('modalEdit').dataset.id=id;
|
||||||
|
document.getElementById('editLabel').value=acc.label||'';
|
||||||
|
document.getElementById('editUser').value=acc.gh_user||'';
|
||||||
|
document.getElementById('editToken').value='';
|
||||||
|
document.getElementById('editToken').placeholder=acc.token?'当前:'+acc.token:'(未配置)';
|
||||||
|
document.getElementById('editPrivate').checked=!!acc.private;
|
||||||
|
showModalMsg('editMsg','',null);
|
||||||
|
document.getElementById('modalEdit').classList.add('show');
|
||||||
|
setTimeout(()=>{
|
||||||
|
const el=focusToken?document.getElementById('editToken'):document.getElementById('editLabel');
|
||||||
|
el.focus();
|
||||||
|
},50);
|
||||||
|
}
|
||||||
|
function upgradeAcc(id){
|
||||||
|
// 顶部横幅「去添加 Token」:直接打开当前账号的编辑弹窗,聚焦 Token
|
||||||
|
openEditModal(id, true);
|
||||||
|
}
|
||||||
|
async function saveAdd(){
|
||||||
|
const body={
|
||||||
|
label: document.getElementById('addLabel').value.trim(),
|
||||||
|
gh_user: document.getElementById('addUser').value.trim(),
|
||||||
|
token: document.getElementById('addToken').value.trim(),
|
||||||
|
private: document.getElementById('addPrivate').checked,
|
||||||
|
};
|
||||||
|
if(!body.token){ showModalMsg('addMsg','请填写 Personal Access Token',false); return; }
|
||||||
|
const b=document.getElementById('btnAddSave'); b.disabled=true; b.textContent='⏳ 验证中…';
|
||||||
try{
|
try{
|
||||||
const r=await (await fetch('api/accounts/add',{method:'POST',headers:{'Content-Type':'application/json'},
|
const r=await (await fetch('api/accounts/add',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(body)})).json();
|
||||||
body:JSON.stringify({label,gh_user,token,private:priv})})).json();
|
showModalMsg('addMsg', r.msg||'', !!r.ok);
|
||||||
showMsg('msgAcc',r.msg||JSON.stringify(r),!!r.ok);
|
if(r.ok){ setTimeout(()=>{ closeModal('modalAdd'); refresh(); }, 700); }
|
||||||
if(r.ok){document.getElementById('accLabel').value='';document.getElementById('accUser').value='';document.getElementById('accToken').value='';}
|
}catch(e){ showModalMsg('addMsg','请求失败: '+e, false); }
|
||||||
}catch(e){showMsg('msgAcc','请求失败: '+e,false)}
|
finally{ b.disabled=false; b.textContent='✓ 验证并添加'; }
|
||||||
finally{b.disabled=false;b.textContent='✓ 验证并添加';refresh();}
|
}
|
||||||
|
async function saveEdit(){
|
||||||
|
const id=document.getElementById('modalEdit').dataset.id;
|
||||||
|
if(!id){ showModalMsg('editMsg','内部错误:未选中账号',false); return; }
|
||||||
|
const body={
|
||||||
|
id,
|
||||||
|
label: document.getElementById('editLabel').value.trim(),
|
||||||
|
token: document.getElementById('editToken').value.trim(), // 空 = 不改
|
||||||
|
private: document.getElementById('editPrivate').checked,
|
||||||
|
};
|
||||||
|
const b=document.getElementById('btnEditSave'); b.disabled=true; b.textContent='⏳ 保存中…';
|
||||||
|
try{
|
||||||
|
const r=await (await fetch('api/accounts/edit',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(body)})).json();
|
||||||
|
showModalMsg('editMsg', r.msg||'', !!r.ok);
|
||||||
|
if(r.ok){ setTimeout(()=>{ closeModal('modalEdit'); refresh(); }, 700); }
|
||||||
|
}catch(e){ showModalMsg('editMsg','请求失败: '+e, false); }
|
||||||
|
finally{ b.disabled=false; b.textContent='保存'; }
|
||||||
}
|
}
|
||||||
async function switchAcc(id){
|
async function switchAcc(id){
|
||||||
const r=await (await fetch('api/accounts/switch',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id})})).json();
|
const r=await (await fetch('api/accounts/switch',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id})})).json();
|
||||||
@@ -1437,6 +1494,64 @@ function fmtInterval(s){
|
|||||||
}
|
}
|
||||||
refresh();
|
refresh();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
// ---- 模态弹窗:添加 ----
|
||||||
|
<div class="modal" id="modalAdd">
|
||||||
|
<div class="modal-box">
|
||||||
|
<div class="modal-head">
|
||||||
|
<h3>添加 GitHub 账号</h3>
|
||||||
|
<button class="modal-close" onclick="closeModal('modalAdd')" aria-label="关闭">×</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<label class="flabel" style="margin-top:0">备注名<span class="sub">方便自己识别,可留空</span></label>
|
||||||
|
<input id="addLabel" placeholder="如:我的主账号" autocomplete="off">
|
||||||
|
<label class="flabel">GitHub 用户名<span class="sub">留空则按 Token 自动识别</span></label>
|
||||||
|
<input id="addUser" placeholder="如 cbb2625274797" autocomplete="off">
|
||||||
|
<label class="flabel">Personal Access Token</label>
|
||||||
|
<input id="addToken" type="password" placeholder="ghp_ 开头" autocomplete="off">
|
||||||
|
<label class="chk" style="margin-top:8px"><input type="checkbox" id="addPrivate" checked> 自动创建的仓库设为私有(推荐)</label>
|
||||||
|
</div>
|
||||||
|
<div class="modal-foot">
|
||||||
|
<div class="modal-msg" id="addMsg"></div>
|
||||||
|
<button class="b-mini" onclick="closeModal('modalAdd')">取消</button>
|
||||||
|
<button class="b-add" id="btnAddSave" onclick="saveAdd()">✓ 验证并添加</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
// ---- 模态弹窗:编辑 ----
|
||||||
|
<div class="modal" id="modalEdit">
|
||||||
|
<div class="modal-box">
|
||||||
|
<div class="modal-head">
|
||||||
|
<h3>编辑 GitHub 账号</h3>
|
||||||
|
<button class="modal-close" onclick="closeModal('modalEdit')" aria-label="关闭">×</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<label class="flabel" style="margin-top:0">备注名</label>
|
||||||
|
<input id="editLabel" autocomplete="off">
|
||||||
|
<label class="flabel">GitHub 用户名<span class="sub">账号标识,不可修改</span></label>
|
||||||
|
<input id="editUser" readonly tabindex="-1">
|
||||||
|
<label class="flabel">Personal Access Token<span class="sub">留空则保留当前 Token</span></label>
|
||||||
|
<input id="editToken" type="password" placeholder="ghp_ 开头(留空不修改)" autocomplete="off">
|
||||||
|
<label class="chk" style="margin-top:8px"><input type="checkbox" id="editPrivate"> 自动创建的仓库设为私有(推荐)</label>
|
||||||
|
</div>
|
||||||
|
<div class="modal-foot">
|
||||||
|
<div class="modal-msg" id="editMsg"></div>
|
||||||
|
<button class="b-mini" onclick="closeModal('modalEdit')">取消</button>
|
||||||
|
<button class="b-add" id="btnEditSave" onclick="saveEdit()">保存</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// 弹窗:点遮罩关闭 + ESC 关闭
|
||||||
|
document.querySelectorAll('.modal').forEach(m=>{
|
||||||
|
m.addEventListener('click',e=>{ if(e.target===m) m.classList.remove('show'); });
|
||||||
|
});
|
||||||
|
document.addEventListener('keydown',e=>{
|
||||||
|
if(e.key==='Escape') document.querySelectorAll('.modal.show').forEach(m=>m.classList.remove('show'));
|
||||||
|
});
|
||||||
|
</script>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
@@ -1633,6 +1748,7 @@ class Handler(BaseHTTPRequestHandler):
|
|||||||
notes.append(f"注意:在新地址上找不到用户 {cfg['gitea_user']},请检查")
|
notes.append(f"注意:在新地址上找不到用户 {cfg['gitea_user']},请检查")
|
||||||
self._json({"ok": True, "msg": "已保存(" + ";".join(notes) + ")"})
|
self._json({"ok": True, "msg": "已保存(" + ";".join(notes) + ")"})
|
||||||
elif path == "/api/accounts/add":
|
elif path == "/api/accounts/add":
|
||||||
|
# 严格新增:Token 对应的 gh_user 若已存在则拒绝,引导用户用编辑功能
|
||||||
token = (data.get("token") or "").strip()
|
token = (data.get("token") or "").strip()
|
||||||
label = (data.get("label") or "").strip()
|
label = (data.get("label") or "").strip()
|
||||||
gh_user = (data.get("gh_user") or "").strip()
|
gh_user = (data.get("gh_user") or "").strip()
|
||||||
@@ -1647,16 +1763,9 @@ class Handler(BaseHTTPRequestHandler):
|
|||||||
if gh_user and gh_user != login:
|
if gh_user and gh_user != login:
|
||||||
self._json({"ok": False, "msg": f"Token 对应的账号是 {login},与填写的 {gh_user} 不一致"})
|
self._json({"ok": False, "msg": f"Token 对应的账号是 {login},与填写的 {gh_user} 不一致"})
|
||||||
return
|
return
|
||||||
existing = next((a for a in accounts if a["gh_user"] == login), None)
|
if next((a for a in accounts if a["gh_user"] == login), None):
|
||||||
if existing:
|
self._json({"ok": False,
|
||||||
existing["token"] = token
|
"msg": f"GitHub 账号 {login} 已存在,请用编辑功能(每行右边的✏️)更新 Token/备注"})
|
||||||
existing["private"] = private
|
|
||||||
if label:
|
|
||||||
existing["label"] = label
|
|
||||||
active_id = existing["id"]
|
|
||||||
save_accounts()
|
|
||||||
log(f"GitHub 账号 {login} 的 Token 已更新")
|
|
||||||
self._json({"ok": True, "msg": f"账号 {login} 已存在,Token 已更新并切换为当前账号"})
|
|
||||||
return
|
return
|
||||||
acc = {"id": uuid.uuid4().hex[:8], "label": label or login,
|
acc = {"id": uuid.uuid4().hex[:8], "label": label or login,
|
||||||
"gh_user": login, "token": token, "private": private,
|
"gh_user": login, "token": token, "private": private,
|
||||||
@@ -1670,6 +1779,34 @@ class Handler(BaseHTTPRequestHandler):
|
|||||||
log(f"新增 GitHub 账号 {login}({'私有' if private else '公开'}仓库)")
|
log(f"新增 GitHub 账号 {login}({'私有' if private else '公开'}仓库)")
|
||||||
self._json({"ok": True, "msg": f"账号 {login} 验证通过,已添加"
|
self._json({"ok": True, "msg": f"账号 {login} 验证通过,已添加"
|
||||||
+ ("并切换为当前账号" if active_id == acc["id"] else "")})
|
+ ("并切换为当前账号" if active_id == acc["id"] else "")})
|
||||||
|
elif path == "/api/accounts/edit":
|
||||||
|
# 按 id 编辑已有账号:token 留空则保留,可改 label / private
|
||||||
|
aid = (data.get("id") or "").strip()
|
||||||
|
acc = find_account(aid)
|
||||||
|
if not acc:
|
||||||
|
self._json({"ok": False, "msg": "账号不存在"})
|
||||||
|
return
|
||||||
|
new_token = (data.get("token") or "").strip()
|
||||||
|
if new_token:
|
||||||
|
ok, login, err = gh_verify_token(new_token)
|
||||||
|
if not ok:
|
||||||
|
self._json({"ok": False, "msg": f"Token 验证失败: {err}"})
|
||||||
|
return
|
||||||
|
if login != acc["gh_user"]:
|
||||||
|
self._json({"ok": False,
|
||||||
|
"msg": f"Token 对应的账号是 {login},与当前账号 {acc['gh_user']} 不一致"})
|
||||||
|
return
|
||||||
|
acc["token"] = new_token
|
||||||
|
log(f"GitHub 账号 {acc['gh_user']} 的 Token 已通过编辑更新")
|
||||||
|
if "private" in data:
|
||||||
|
acc["private"] = bool(data.get("private"))
|
||||||
|
if "label" in data:
|
||||||
|
label = (data.get("label") or "").strip()
|
||||||
|
if label:
|
||||||
|
acc["label"] = label
|
||||||
|
save_accounts()
|
||||||
|
self._json({"ok": True,
|
||||||
|
"msg": f"账号 {acc['gh_user']} 已保存" + ("(Token 已更新)" if new_token else "")})
|
||||||
elif path == "/api/accounts/switch":
|
elif path == "/api/accounts/switch":
|
||||||
aid = (data.get("id") or "").strip()
|
aid = (data.get("id") or "").strip()
|
||||||
if not find_account(aid):
|
if not find_account(aid):
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
appname = GiteaHubSync
|
appname = GiteaHubSync
|
||||||
version = 1.4.1
|
version = 1.5.0
|
||||||
display_name = Gitea→GitHub 同步助手
|
display_name = Gitea→GitHub 同步助手
|
||||||
desc = 每次推送到飞牛 Gitea 的代码,10 秒内自动镜像到 GitHub 的 7 个私有仓库。内置控制面板:自动同步开关、立即同步、仓库状态、同步日志,一键打开 Gitea。数据全部保存在 NAS 本地。
|
desc = 每次推送到飞牛 Gitea 的代码,10 秒内自动镜像到 GitHub 的 7 个私有仓库。内置控制面板:自动同步开关、立即同步、仓库状态、同步日志,一键打开 Gitea。数据全部保存在 NAS 本地。
|
||||||
platform = all
|
platform = all
|
||||||
|
|||||||
Reference in New Issue
Block a user