improve auto-connect loading states
This commit is contained in:
@@ -1149,16 +1149,37 @@ async function ensureAutoSession(options = {}) {
|
|||||||
return Boolean(appState.session);
|
return Boolean(appState.session);
|
||||||
}
|
}
|
||||||
appState.autoConnectAttempted = true;
|
appState.autoConnectAttempted = true;
|
||||||
|
renderAll();
|
||||||
try {
|
try {
|
||||||
await loginWithAutoSession(backendUrl);
|
await loginWithAutoSession(backendUrl);
|
||||||
return true;
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
appState.autoConnectError = formatActionErrorMessage(error, "自动连接失败");
|
appState.autoConnectError = formatActionErrorMessage(error, "自动连接失败");
|
||||||
persistSession(null);
|
persistSession(null);
|
||||||
|
renderAll();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isAutoConnectionPending() {
|
||||||
|
return !appState.session
|
||||||
|
&& appState.autoConnectAttempted
|
||||||
|
&& !appState.autoConnectSuppressed
|
||||||
|
&& !appState.autoConnectError;
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderAutoConnectingScreen(screenTitle, nextStepText) {
|
||||||
|
return screenShell(
|
||||||
|
screenTitle,
|
||||||
|
"正在自动连接工作区,成功后会自动替换成真实内容。",
|
||||||
|
`${button("连接状态", "open-auth", "primary")}`,
|
||||||
|
renderEmptyState(
|
||||||
|
"正在自动连接工作区",
|
||||||
|
nextStepText || "如果超过几秒仍未进入真实页面,可以点右上角查看连接状态。"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
async function refreshFromAuthModal() {
|
async function refreshFromAuthModal() {
|
||||||
const modal = document.querySelector(".auth-modal-backdrop");
|
const modal = document.querySelector(".auth-modal-backdrop");
|
||||||
const visible = modal && !modal.classList.contains("hidden");
|
const visible = modal && !modal.classList.contains("hidden");
|
||||||
@@ -3878,6 +3899,9 @@ function renderAdminWorkbenchScreen() {
|
|||||||
|
|
||||||
function renderDashboardScreen() {
|
function renderDashboardScreen() {
|
||||||
if (!appState.session) {
|
if (!appState.session) {
|
||||||
|
if (isAutoConnectionPending()) {
|
||||||
|
return renderAutoConnectingScreen("项目总台", "会话签发成功后,这里会自动切成真实项目总台。");
|
||||||
|
}
|
||||||
return screenShell(
|
return screenShell(
|
||||||
"项目总台",
|
"项目总台",
|
||||||
"先自动连接工作区,再加载项目、对标、Agent 和生产状态。",
|
"先自动连接工作区,再加载项目、对标、Agent 和生产状态。",
|
||||||
@@ -3907,6 +3931,9 @@ function renderDashboardScreen() {
|
|||||||
|
|
||||||
function renderProjectsScreen() {
|
function renderProjectsScreen() {
|
||||||
if (!appState.dashboard) {
|
if (!appState.dashboard) {
|
||||||
|
if (isAutoConnectionPending()) {
|
||||||
|
return renderAutoConnectingScreen("我的项目", "工作区就绪后,这里会自动加载真实项目和导入队列。");
|
||||||
|
}
|
||||||
return screenShell("我的项目", "先完成工作区自动连接,再加载项目。", `${button("自动连接", "open-auth", "primary")}`, renderEmptyState("项目未加载", "自动连接成功后,这里会显示真实项目和导入队列。"));
|
return screenShell("我的项目", "先完成工作区自动连接,再加载项目。", `${button("自动连接", "open-auth", "primary")}`, renderEmptyState("项目未加载", "自动连接成功后,这里会显示真实项目和导入队列。"));
|
||||||
}
|
}
|
||||||
const projects = safeArray(appState.dashboard.projects);
|
const projects = safeArray(appState.dashboard.projects);
|
||||||
@@ -4109,6 +4136,9 @@ function renderDiscoveryRelationsSection(linkedAccounts, similarCandidates) {
|
|||||||
|
|
||||||
function renderDiscoveryScreen() {
|
function renderDiscoveryScreen() {
|
||||||
if (!appState.dashboard) {
|
if (!appState.dashboard) {
|
||||||
|
if (isAutoConnectionPending()) {
|
||||||
|
return renderAutoConnectingScreen("找对标", "工作区就绪后,这里会自动显示当前平台的账号列表和详情。");
|
||||||
|
}
|
||||||
return screenShell("找对标", "完成工作区自动连接后才能加载真实对标账号。", `${button("自动连接", "open-auth", "primary")}`, renderEmptyState("对标库未加载", "自动连接成功后,这里会显示当前平台的账号列表和详情。"));
|
return screenShell("找对标", "完成工作区自动连接后才能加载真实对标账号。", `${button("自动连接", "open-auth", "primary")}`, renderEmptyState("对标库未加载", "自动连接成功后,这里会显示当前平台的账号列表和详情。"));
|
||||||
}
|
}
|
||||||
const query = appState.discoveryQuery.toLowerCase();
|
const query = appState.discoveryQuery.toLowerCase();
|
||||||
@@ -4282,6 +4312,9 @@ function renderDiscoveryScreen() {
|
|||||||
|
|
||||||
function renderTrackingScreen() {
|
function renderTrackingScreen() {
|
||||||
if (!appState.dashboard) {
|
if (!appState.dashboard) {
|
||||||
|
if (isAutoConnectionPending()) {
|
||||||
|
return renderAutoConnectingScreen("跟踪账号", "工作区就绪后,这里会自动加载真实跟踪对象和日报。");
|
||||||
|
}
|
||||||
return screenShell("跟踪账号", "完成工作区自动连接后才能生成真实日报。", `${button("自动连接", "open-auth", "primary")}`, renderEmptyState("日报未加载", "当前还没有可用的对标账号数据。"));
|
return screenShell("跟踪账号", "完成工作区自动连接后才能生成真实日报。", `${button("自动连接", "open-auth", "primary")}`, renderEmptyState("日报未加载", "当前还没有可用的对标账号数据。"));
|
||||||
}
|
}
|
||||||
const currentPlatform = getCurrentPlatformValue();
|
const currentPlatform = getCurrentPlatformValue();
|
||||||
@@ -4428,6 +4461,9 @@ function renderAutomationScreen() {
|
|||||||
|
|
||||||
function renderOwnedScreen() {
|
function renderOwnedScreen() {
|
||||||
if (!appState.dashboard) {
|
if (!appState.dashboard) {
|
||||||
|
if (isAutoConnectionPending()) {
|
||||||
|
return renderAutoConnectingScreen("我的账号", "工作区就绪后,这里会自动显示当前账号和建议动作。");
|
||||||
|
}
|
||||||
return screenShell("我的账号", "先自动连接工作区。", `${button("自动连接", "open-auth", "primary")}`, renderEmptyState("我的账号未加载", "自动连接成功后,这里会展示当前账号和建议动作。"));
|
return screenShell("我的账号", "先自动连接工作区。", `${button("自动连接", "open-auth", "primary")}`, renderEmptyState("我的账号未加载", "自动连接成功后,这里会展示当前账号和建议动作。"));
|
||||||
}
|
}
|
||||||
const me = appState.me || appState.session?.account || {};
|
const me = appState.me || appState.session?.account || {};
|
||||||
@@ -4507,6 +4543,9 @@ function renderOwnedScreen() {
|
|||||||
|
|
||||||
function renderPlaybookScreen() {
|
function renderPlaybookScreen() {
|
||||||
if (!appState.dashboard) {
|
if (!appState.dashboard) {
|
||||||
|
if (isAutoConnectionPending()) {
|
||||||
|
return renderAutoConnectingScreen("Agent", "工作区就绪后,这里会自动加载真实 Agent 列表和模型。");
|
||||||
|
}
|
||||||
return screenShell("Agent", "先自动连接工作区。", `${button("自动连接", "open-auth", "primary")}`, renderEmptyState("Agent 未加载", "自动连接成功后,这里会展示真实 Agent 列表和模型。"));
|
return screenShell("Agent", "先自动连接工作区。", `${button("自动连接", "open-auth", "primary")}`, renderEmptyState("Agent 未加载", "自动连接成功后,这里会展示真实 Agent 列表和模型。"));
|
||||||
}
|
}
|
||||||
const assistants = safeArray(appState.dashboard.assistants);
|
const assistants = safeArray(appState.dashboard.assistants);
|
||||||
@@ -4681,6 +4720,9 @@ function renderPlaybookScreen() {
|
|||||||
|
|
||||||
function renderProductionScreen() {
|
function renderProductionScreen() {
|
||||||
if (!appState.dashboard) {
|
if (!appState.dashboard) {
|
||||||
|
if (isAutoConnectionPending()) {
|
||||||
|
return renderAutoConnectingScreen("生产中心", "工作区就绪后,这里会自动加载真实任务和作品。");
|
||||||
|
}
|
||||||
return screenShell("生产中心", "先自动连接工作区。", `${button("自动连接", "open-auth", "primary")}`, renderEmptyState("生产中心未加载", "自动连接成功后,这里会展示真实任务和作品。"));
|
return screenShell("生产中心", "先自动连接工作区。", `${button("自动连接", "open-auth", "primary")}`, renderEmptyState("生产中心未加载", "自动连接成功后,这里会展示真实任务和作品。"));
|
||||||
}
|
}
|
||||||
const jobs = safeArray(appState.dashboard.recent_jobs);
|
const jobs = safeArray(appState.dashboard.recent_jobs);
|
||||||
@@ -4822,6 +4864,9 @@ function renderProductionScreen() {
|
|||||||
|
|
||||||
function renderReviewScreen() {
|
function renderReviewScreen() {
|
||||||
if (!appState.dashboard) {
|
if (!appState.dashboard) {
|
||||||
|
if (isAutoConnectionPending()) {
|
||||||
|
return renderAutoConnectingScreen("发布与复盘", "工作区就绪后,这里会自动生成复盘入口和最近完成任务。");
|
||||||
|
}
|
||||||
return screenShell("发布与复盘", "先自动连接工作区。", `${button("自动连接", "open-auth", "primary")}`, renderEmptyState("复盘未加载", "自动连接成功后,这里会先用最近任务生成一版复盘入口。"));
|
return screenShell("发布与复盘", "先自动连接工作区。", `${button("自动连接", "open-auth", "primary")}`, renderEmptyState("复盘未加载", "自动连接成功后,这里会先用最近任务生成一版复盘入口。"));
|
||||||
}
|
}
|
||||||
if (!backendSupports("/v2/reviews")) {
|
if (!backendSupports("/v2/reviews")) {
|
||||||
@@ -4889,6 +4934,9 @@ function renderReviewScreen() {
|
|||||||
|
|
||||||
function renderCreditsScreen() {
|
function renderCreditsScreen() {
|
||||||
if (!appState.dashboard) {
|
if (!appState.dashboard) {
|
||||||
|
if (isAutoConnectionPending()) {
|
||||||
|
return renderAutoConnectingScreen("额度", "工作区就绪后,这里会自动展示真实额度和运营看板。");
|
||||||
|
}
|
||||||
return screenShell("额度", "先自动连接工作区。", `${button("自动连接", "open-auth", "primary")}`, renderEmptyState("额度未加载", "自动连接成功后,这里会展示真实额度和运营看板。"));
|
return screenShell("额度", "先自动连接工作区。", `${button("自动连接", "open-auth", "primary")}`, renderEmptyState("额度未加载", "自动连接成功后,这里会展示真实额度和运营看板。"));
|
||||||
}
|
}
|
||||||
const jobs = safeArray(appState.dashboard.recent_jobs);
|
const jobs = safeArray(appState.dashboard.recent_jobs);
|
||||||
|
|||||||
@@ -55,3 +55,23 @@ test("projects screen uses an adaptive project grid instead of a fixed three-col
|
|||||||
assert.match(CSS, /\.project-status-grid\s*\{[\s\S]*repeat\(auto-fit,\s*minmax\(260px,\s*1fr\)\)/);
|
assert.match(CSS, /\.project-status-grid\s*\{[\s\S]*repeat\(auto-fit,\s*minmax\(260px,\s*1fr\)\)/);
|
||||||
assert.match(CSS, /\.entity-card\.pad\s*\{[\s\S]*padding:\s*15px/);
|
assert.match(CSS, /\.entity-card\.pad\s*\{[\s\S]*padding:\s*15px/);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("dashboard and project screens distinguish auto-connecting from truly disconnected", () => {
|
||||||
|
const dashboard = extractBetween(APP, "function renderDashboardScreen()", "function renderProjectsScreen()");
|
||||||
|
const projects = extractBetween(APP, "function renderProjectsScreen()", "function getActiveDetailTab(");
|
||||||
|
const helper = extractBetween(APP, "function isAutoConnectionPending()", "async function refreshFromAuthModal()");
|
||||||
|
|
||||||
|
assert.match(APP, /function isAutoConnectionPending\(\)/);
|
||||||
|
assert.match(APP, /function renderAutoConnectingScreen\(/);
|
||||||
|
assert.match(helper, /正在自动连接工作区/);
|
||||||
|
assert.match(dashboard, /isAutoConnectionPending\(\)/);
|
||||||
|
assert.match(dashboard, /renderAutoConnectingScreen\("项目总台"/);
|
||||||
|
assert.match(projects, /isAutoConnectionPending\(\)/);
|
||||||
|
assert.match(projects, /renderAutoConnectingScreen\("我的项目"/);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("ensureAutoSession re-renders immediately when auto-connect starts", () => {
|
||||||
|
const source = extractBetween(APP, "async function ensureAutoSession(options = {})", "async function refreshFromAuthModal()");
|
||||||
|
assert.match(source, /appState\.autoConnectAttempted = true;/);
|
||||||
|
assert.match(source, /renderAll\(\);/);
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user