首页工作空间适配新结构并支持加载失败重试、切换独立删除接口

- 工作空间结果树适配 createDate→flows→items 两级结构(flows 下文件平铺,兼容旧平铺结构)
- 删除接口切换:工作空间树删除改走 session 域独立接口 resultDelete(deleteWorkspaceResult),不依赖内容创作域
- 会话记录/工作空间列表加载失败:区分失败态与空态,提供重试按钮;工作空间懒加载失败后切回 tab 自动重试

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-08-20 14:01:30 +08:00
co-authored by Claude
parent 63ac39cd4a
commit abc5b47f72
3 changed files with 123 additions and 23 deletions
+52 -6
View File
@@ -47,12 +47,20 @@
</div>
</div>
<div v-else-if="historyFailed" class="panel-error">
<span class="panel-error-text">加载失败</span>
<button class="panel-retry-btn" @click="emit('retry-history')">重试</button>
</div>
<div v-else class="panel-empty">暂无会话记录</div>
</div>
<!-- 工作空间面板 -->
<div v-show="activeTab === 'workspace'" class="panel" v-loading="treeLoading">
<el-empty v-if="!treeLoading && treeNodes.length === 0" :image-size="48" description="暂无内容" />
<div v-if="!treeLoading && treeNodes.length === 0 && workspaceFailed" class="panel-error">
<span class="panel-error-text">加载失败</span>
<button class="panel-retry-btn" @click="emit('retry-workspace')">重试</button>
</div>
<el-empty v-else-if="!treeLoading && treeNodes.length === 0" :image-size="48" description="暂无内容" />
<div v-else class="panel-list">
<div v-for="dateNode in treeNodes" :key="dateNode.id" class="tree-date-group">
<div class="tree-date-label">{{ dateNode.label }}</div>
@@ -98,6 +106,11 @@ interface Props {
activeMenu: string;
activeHistoryId: string | null;
historyList: HistoryItem[];
// 会话记录 / 工作空间加载失败标记:失败时显示「加载失败 + 重试」错误态
historyFailed?: boolean;
workspaceFailed?: boolean;
// 工作空间是否已成功加载:懒加载成功后才不再触发;失败保持 false → 切回 tab 自动重试
workspaceLoaded?: boolean;
treeNodes: TreeNode[];
treeLoading: boolean;
}
@@ -111,18 +124,23 @@ interface Emits {
(e: 'download-node', data: TreeNode): void;
(e: 'delete-node', data: TreeNode): void;
(e: 'load-workspace'): void;
(e: 'retry-history'): void;
(e: 'retry-workspace'): void;
}
const props = defineProps<Props>();
const props = withDefaults(defineProps<Props>(), {
historyFailed: false,
workspaceFailed: false,
workspaceLoaded: false,
});
const emit = defineEmits<Emits>();
const activeTab = ref<'history' | 'workspace'>('history');
// 工作空间懒加载标记:首次切换到「工作空间」tab 时才通知父组件加载结果树,避免进入页面即拉取
const workspaceLoaded = ref(false);
const handleTabChange = (tab: 'history' | 'workspace') => {
activeTab.value = tab;
if (tab === 'workspace' && !workspaceLoaded.value) {
workspaceLoaded.value = true;
// 懒加载:仅在「工作空间」tab 且尚未成功加载过时通知父组件拉取结果树,避免进入页面即请求;
// 失败时父组件不置 workspaceLoaded,切回 tab 自动重试
if (tab === 'workspace' && !props.workspaceLoaded) {
emit('load-workspace');
}
};
@@ -282,6 +300,34 @@ const handleDeleteNode = (data: TreeNode) => emit('delete-node', data);
padding: 32px 0;
}
/* 加载失败错误态:可区分「失败」与「空数据」,并提供重试入口 */
.panel-error {
padding: 32px 0;
text-align: center;
}
.panel-error-text {
font-size: 12px;
color: #94a3b8;
margin-right: 8px;
}
.panel-retry-btn {
border: 1px solid #dbeafe;
background: #eff6ff;
color: #2563eb;
font-size: 12px;
padding: 4px 14px;
border-radius: 8px;
cursor: pointer;
transition: background 0.15s;
outline: none;
&:hover {
background: #dbeafe;
}
}
/* 历史记录条目 */
.history-item {
display: flex;