feat(portal/t53): 進站完成安裝清單(leo 07-25:金鑰與 daemon 要在站內做,不然安裝沒完成)——常駐三項清單(下載小幫手/下載 config.json 站內生成/貼 Gemini 金鑰即時啟用)+新端點 POST /portal/admin/chat-key(改寫 tenant rag_chat 的 x-goog-api-key,admin 閘、金鑰不落 log)+session 回 email 供 config 生成
This commit is contained in:
@@ -590,27 +590,10 @@ function taipeiMonthDay(ms) { var d = new Date(ms + TAIPEI_OFFSET_MS); return {
|
||||
$('v-firstsetup').classList.remove('on');
|
||||
$('shell').classList.add('on');
|
||||
$('tabbar').classList.add('on');
|
||||
// t49 一次性歡迎引導(首次設定完成那一刻才出現;關掉就不再出現):
|
||||
// 下一步只有兩件——裝同步小幫手(資料自動進來)、想問答就設金鑰。連去 installer /setup。
|
||||
try {
|
||||
if (localStorage.getItem('arcrun_onboarding') === '1' && !document.getElementById('onboard-card')) {
|
||||
var setupUrl = (window.ARCRUN_CONFIG && window.ARCRUN_CONFIG.installerBase
|
||||
? String(window.ARCRUN_CONFIG.installerBase).replace(/\/+$/, '')
|
||||
: 'https://arcrun-installer.youlin-hsieh-dev.workers.dev') + '/setup';
|
||||
var el = document.createElement('div');
|
||||
el.id = 'onboard-card';
|
||||
el.style.cssText = 'position:fixed;left:50%;bottom:24px;transform:translateX(-50%);z-index:60;max-width:560px;width:calc(100% - 32px);padding:18px 20px;border-radius:14px;background:rgba(var(--amber-rgb),.10);border:1px solid rgba(var(--amber-rgb),.45);backdrop-filter:blur(6px);font-size:14.5px;line-height:1.7';
|
||||
el.innerHTML = '<b>🎉 你的知識庫開張了!</b>接下來只有一件事:'
|
||||
+ '<a href="' + setupUrl + '" target="_blank" rel="noopener">下載同步小幫手設定</a>'
|
||||
+ '——把你的資料夾連上來,檔案就會自動變成可搜尋的知識(想用 AI 問答,金鑰也在同一頁設定)。'
|
||||
+ '<button id="onboard-close" style="margin-left:10px;border:none;background:none;color:inherit;cursor:pointer;font-size:13px;text-decoration:underline">知道了</button>';
|
||||
document.body.appendChild(el);
|
||||
document.getElementById('onboard-close').addEventListener('click', function () {
|
||||
try { localStorage.removeItem('arcrun_onboarding'); } catch (e) { /* noop */ }
|
||||
el.remove();
|
||||
});
|
||||
}
|
||||
} catch (e) { /* 引導卡失敗不擋主流程 */ }
|
||||
// t53(leo 07-25:「進站要做的事——給金鑰、下載 daemon——不然這個安裝沒完成」):
|
||||
// 常駐「完成安裝」清單卡,三件做完才消失(localStorage 記進度;admin 才看得到——
|
||||
// 金鑰與 daemon 設定是裝機者的事,同事帳號不顯示)。
|
||||
try { renderSetupChecklist(); } catch (e) { /* 清單卡失敗不擋主流程 */ }
|
||||
var p = S.profile || {};
|
||||
$('side-foot').innerHTML = esc(p.display_name || '') + '<br>' + esc(location.host);
|
||||
$('nav-workflows').classList.toggle('hide', !p.workflows_visible);
|
||||
@@ -678,6 +661,88 @@ function taipeiMonthDay(ms) { var d = new Date(ms + TAIPEI_OFFSET_MS); return {
|
||||
dropSession();
|
||||
});
|
||||
|
||||
// ── t53 完成安裝清單(進站必見,三件做完才消失)─────────────────────────────
|
||||
function setupSteps() {
|
||||
try { return JSON.parse(localStorage.getItem('arcrun_setup_steps') || '{}'); } catch (e) { return {}; }
|
||||
}
|
||||
function markStep(k) {
|
||||
var s = setupSteps(); s[k] = 1;
|
||||
try { localStorage.setItem('arcrun_setup_steps', JSON.stringify(s)); } catch (e) { /* noop */ }
|
||||
renderSetupChecklist();
|
||||
}
|
||||
function renderSetupChecklist() {
|
||||
var old = document.getElementById('setup-checklist');
|
||||
if (old) old.remove();
|
||||
var p = S.profile || {};
|
||||
if (p.role !== 'admin') return;
|
||||
var s = setupSteps();
|
||||
if (s.daemon && s.config && s.key) return; // 三件齊=安裝真的完成,不再打擾
|
||||
var cfg = window.ARCRUN_CONFIG || {};
|
||||
var daemonUrl = cfg.daemonDownload || 'https://raw.githubusercontent.com/youlinhsieh/arcrun-rag-bundles/main/daemon/ArcrunRAG-mac-unsigned.zip';
|
||||
var row = function (done, id, html) {
|
||||
return '<div style="display:flex;gap:10px;align-items:baseline;margin-top:10px">'
|
||||
+ '<span>' + (done ? '✅' : '⬜') + '</span><div style="flex:1">' + html + '</div></div>';
|
||||
};
|
||||
var el = document.createElement('div');
|
||||
el.id = 'setup-checklist';
|
||||
el.style.cssText = 'position:fixed;right:20px;bottom:20px;z-index:60;max-width:400px;width:calc(100% - 40px);padding:18px 20px;border-radius:14px;background:rgba(var(--amber-rgb),.10);border:1px solid rgba(var(--amber-rgb),.45);backdrop-filter:blur(8px);font-size:14px;line-height:1.65';
|
||||
el.innerHTML = '<b>還差 ' + (3 - (s.daemon?1:0) - (s.config?1:0) - (s.key?1:0)) + ' 步,安裝就真的完成了</b>'
|
||||
+ row(s.daemon, 'daemon',
|
||||
'<b>下載同步小幫手</b>(把資料夾變成知識庫)<br>'
|
||||
+ '<a href="' + esc(daemonUrl) + '" id="sc-daemon">下載 Mac 版</a>'
|
||||
+ '<span class="muted" style="font-size:12.5px">(封測版未簽章,第一次請右鍵→打開)</span>')
|
||||
+ row(s.config, 'config',
|
||||
'<b>下載設定檔</b> 放到 <code style="font-size:12px">~/.arcrun-rag/config.json</code><br>'
|
||||
+ '<a href="#" id="sc-config">下載 config.json</a>')
|
||||
+ row(s.key, 'key',
|
||||
'<b>啟用 AI 問答</b>(<a href="https://aistudio.google.com" target="_blank" rel="noopener">aistudio.google.com</a> 免費申請)<br>'
|
||||
+ '<input id="sc-key" type="password" placeholder="貼上 Google AI 金鑰" style="width:60%;padding:6px 8px;border-radius:8px;border:1px solid rgba(var(--ink-rgb),.25);background:rgba(var(--ink-rgb),.04);color:var(--ink)"> '
|
||||
+ '<button class="btn3" id="sc-key-save" style="padding:6px 12px;border-radius:8px;cursor:pointer">啟用</button>'
|
||||
+ '<div id="sc-key-msg" style="font-size:12.5px;min-height:1.1em"></div>')
|
||||
+ '<div style="margin-top:10px;text-align:right"><button id="sc-later" style="border:none;background:none;color:inherit;cursor:pointer;font-size:12.5px;text-decoration:underline;opacity:.65">稍後再說</button></div>';
|
||||
document.body.appendChild(el);
|
||||
var dl = document.getElementById('sc-daemon');
|
||||
if (dl) dl.addEventListener('click', function () { markStep('daemon'); });
|
||||
var cb = document.getElementById('sc-config');
|
||||
if (cb) cb.addEventListener('click', function (ev) {
|
||||
ev.preventDefault();
|
||||
var conf = {
|
||||
watch_folders: [],
|
||||
manifest: '~/.arcrun-rag/manifest.json',
|
||||
cypher_url: cfg.apiBase || '',
|
||||
namespace: cfg.tenant || '',
|
||||
library: 'kb',
|
||||
extractor: 'claude',
|
||||
email: (S.profile && S.profile.email) || ''
|
||||
};
|
||||
var a = document.createElement('a');
|
||||
a.href = 'data:application/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(conf, null, 2));
|
||||
a.download = 'config.json';
|
||||
document.body.appendChild(a); a.click(); a.remove();
|
||||
markStep('config');
|
||||
});
|
||||
var kb = document.getElementById('sc-key-save');
|
||||
if (kb) kb.addEventListener('click', function () {
|
||||
var k = (document.getElementById('sc-key').value || '').trim();
|
||||
var m = document.getElementById('sc-key-msg');
|
||||
if (!k) { m.textContent = '請先貼上金鑰'; return; }
|
||||
kb.disabled = true; m.textContent = '啟用中…';
|
||||
fetch(API_BASE + '/portal/admin/chat-key', {
|
||||
method: 'POST',
|
||||
headers: Object.assign({ 'Content-Type': 'application/json' }, authHeaders()),
|
||||
body: JSON.stringify({ key: k })
|
||||
}).then(function (r) { return r.json().then(function (d) { return { ok: r.ok, d: d }; }); })
|
||||
.then(function (x) {
|
||||
kb.disabled = false;
|
||||
if (!x.ok || !x.d.success) { m.textContent = x.d.error || '啟用失敗,請再試一次'; return; }
|
||||
markStep('key');
|
||||
})
|
||||
.catch(function () { kb.disabled = false; m.textContent = '網路好像有問題,請再試一次'; });
|
||||
});
|
||||
var later = document.getElementById('sc-later');
|
||||
if (later) later.addEventListener('click', function () { el.remove(); }); // 只藏本次,下次進站再提醒
|
||||
}
|
||||
|
||||
// ── t49 首次設定(leo 07-25):console/setup → portal/admin/bootstrap → 預設庫登記 → portal/login
|
||||
// 四發全是既有端點,一顆按鈕做完;用戶感受=「建一組帳密就進來了」。
|
||||
$('fs-submit').addEventListener('click', doFirstSetup);
|
||||
|
||||
Reference in New Issue
Block a user