feat: lighten ai agent admin frontend

This commit is contained in:
2026-06-22 09:52:31 +08:00
parent 76ea0b9cde
commit 6f872bbbc6
9 changed files with 201 additions and 743 deletions
@@ -35,24 +35,6 @@ import { ChatBox } from '#/components/ChatBox';
import { useChatApi } from './composables/useChatApi';
import { useEventHandler } from './composables/useEventHandler';
const AppDesignPanel = defineAsyncComponent(() =>
import('#/components/form-editor/AppDesignPanel.vue'),
);
const AppSettingsPanel = defineAsyncComponent(() =>
import('#/components/form-editor/AppSettingsPanel.vue'),
);
const DashboardBasicInfoConfirmPanel = defineAsyncComponent(() =>
import('#/components/form-editor/DashboardBasicInfoConfirmPanel.vue'),
);
const DashboardDesignConfirmPanel = defineAsyncComponent(() =>
import('#/components/form-editor/DashboardDesignConfirmPanel.vue'),
);
const DashboardPublishConfirmPanel = defineAsyncComponent(() =>
import('#/components/form-editor/DashboardPublishConfirmPanel.vue'),
);
const DesignEditorPanel = defineAsyncComponent(() =>
import('#/components/form-editor/DesignEditorPanel.vue'),
);
const SystemSummaryConfirmPanel = defineAsyncComponent(() =>
import('#/components/form-editor/SystemSummaryConfirmPanel.vue'),
);
@@ -206,25 +188,7 @@ const variablesDialogVisible = ref(false);
const variablesForm = ref<Record<string, any>>({});
const pendingMessage = ref('');
// ==================== 设计预览面板状态 ====================
const showDesignPanel = ref(false);
const currentDesign = ref<DesignPreviewData | undefined>(undefined);
const showAppDesignPanel = ref(false);
const currentAppDesign = ref<DesignPreviewData | undefined>(undefined);
const showAppSettingsPanel = ref(false);
const currentAppSettings = ref<DesignPreviewData | undefined>(undefined);
const showDashboardBasicInfoPanel = ref(false);
const currentDashboardBasicInfo = ref<DesignPreviewData | undefined>(undefined);
const showDashboardDesignPanel = ref(false);
const currentDashboardDesign = ref<DesignPreviewData | undefined>(undefined);
const showDashboardPublishPanel = ref(false);
const currentDashboardPublish = ref<DesignPreviewData | undefined>(undefined);
// ==================== 轻量版设计预览面板状态 ====================
const showSystemSummaryPanel = ref(false);
const currentSystemSummary = ref<DesignPreviewData | undefined>(undefined);
@@ -234,15 +198,7 @@ const loadingAnimationTitle = ref('AI 正在开发...');
// 是否有任何设计面板打开
const hasAnyDesignPanelOpen = computed(
() =>
showDesignPanel.value ||
showAppDesignPanel.value ||
showAppSettingsPanel.value ||
showDashboardBasicInfoPanel.value ||
showDashboardDesignPanel.value ||
showDashboardPublishPanel.value ||
showSystemSummaryPanel.value ||
showLoadingAnimation.value,
() => showSystemSummaryPanel.value || showLoadingAnimation.value,
);
// ==================== 工作流变量 ====================
@@ -290,43 +246,15 @@ const handleDesignPreview = (data: DesignPreviewData) => {
// 关闭加载动画
showLoadingAnimation.value = false;
switch (data.type) {
case 'app_design': {
currentAppDesign.value = data;
showAppDesignPanel.value = true;
break;
}
case 'app_settings': {
currentAppSettings.value = data;
showAppSettingsPanel.value = true;
break;
}
case 'dashboard_basic_info': {
currentDashboardBasicInfo.value = data;
showDashboardBasicInfoPanel.value = true;
break;
}
case 'dashboard_design': {
currentDashboardDesign.value = data;
showDashboardDesignPanel.value = true;
break;
}
case 'dashboard_publish': {
currentDashboardPublish.value = data;
showDashboardPublishPanel.value = true;
break;
}
case 'system_summary': {
currentSystemSummary.value = data;
showSystemSummaryPanel.value = true;
break;
}
default: {
currentDesign.value = data;
showDesignPanel.value = true;
break;
}
if (data.type === 'system_summary') {
currentSystemSummary.value = data;
showSystemSummaryPanel.value = true;
return undefined;
}
waitingForInput.value = false;
waitingConfig.value = null;
return `**${data.title || '设计预览'}**\n\n轻量版已移除在线开发设计确认面板。请将该流程改为 LLM、对话、条件、并行、子流程或知识库检索等 AI 协作节点后再运行。`;
};
const { handleStreamEvent, updateAssistantMessage } = useEventHandler({
@@ -810,78 +738,6 @@ const createDesignCloseHandler = (
};
};
const handleDesignConfirm = createDesignConfirmHandler(
showDesignPanel,
currentDesign,
'确认设计',
);
const handleDesignClose = createDesignCloseHandler(
showDesignPanel,
currentDesign,
);
const handleAppDesignConfirm = createDesignConfirmHandler(
showAppDesignPanel,
currentAppDesign,
'确认应用设计',
);
const handleAppDesignClose = createDesignCloseHandler(
showAppDesignPanel,
currentAppDesign,
);
const handleAppSettingsConfirm = createDesignConfirmHandler(
showAppSettingsPanel,
currentAppSettings,
'确认应用设置',
);
const handleAppSettingsClose = createDesignCloseHandler(
showAppSettingsPanel,
currentAppSettings,
);
const handleDashboardBasicInfoConfirm = createDesignConfirmHandler(
showDashboardBasicInfoPanel,
currentDashboardBasicInfo,
'确认仪表盘基础信息',
);
const handleDashboardBasicInfoClose = createDesignCloseHandler(
showDashboardBasicInfoPanel,
currentDashboardBasicInfo,
);
const handleDashboardDesignConfirm = createDesignConfirmHandler(
showDashboardDesignPanel,
currentDashboardDesign,
'确认仪表盘设计',
);
const handleDashboardDesignClose = createDesignCloseHandler(
showDashboardDesignPanel,
currentDashboardDesign,
);
const handleDashboardPublishConfirm = (data: Record<string, any>) => {
showDashboardPublishPanel.value = false;
currentDashboardPublish.value = undefined;
const userMsg: ChatMessage = {
id: generateId(),
role: 'user',
content: `发布到菜单:${data.menu_name}`,
timestamp: new Date(),
};
messages.value.push(userMsg);
waitingForInput.value = false;
waitingConfig.value = null;
resumeExecution(JSON.stringify(data));
};
const handleDashboardPublishClose = createDesignCloseHandler(
showDashboardPublishPanel,
currentDashboardPublish,
);
const handleSystemSummaryConfirm = createDesignConfirmHandler(
showSystemSummaryPanel,
currentSystemSummary,
@@ -1017,66 +873,6 @@ onUnmounted(() => {
class="ml-3 h-full min-h-[400px] flex-1 rounded-lg"
/>
<!-- 设计编辑面板 -->
<DesignEditorPanel
v-if="showDesignPanel"
:visible="showDesignPanel"
:design="currentDesign as any"
@update:visible="showDesignPanel = $event"
@confirm="handleDesignConfirm"
@close="handleDesignClose"
/>
<!-- 应用设计面板 -->
<AppDesignPanel
v-if="showAppDesignPanel"
:visible="showAppDesignPanel"
:design="currentAppDesign as any"
@update:visible="showAppDesignPanel = $event"
@confirm="handleAppDesignConfirm"
@close="handleAppDesignClose"
/>
<!-- 应用设置面板 -->
<AppSettingsPanel
v-if="showAppSettingsPanel"
:visible="showAppSettingsPanel"
:settings="currentAppSettings as any"
@update:visible="showAppSettingsPanel = $event"
@confirm="handleAppSettingsConfirm"
@close="handleAppSettingsClose"
/>
<!-- 仪表盘基础信息面板 -->
<DashboardBasicInfoConfirmPanel
v-if="showDashboardBasicInfoPanel"
:visible="showDashboardBasicInfoPanel"
:basic-info="currentDashboardBasicInfo as any"
@update:visible="showDashboardBasicInfoPanel = $event"
@confirm="handleDashboardBasicInfoConfirm"
@close="handleDashboardBasicInfoClose"
/>
<!-- 仪表盘设计面板 -->
<DashboardDesignConfirmPanel
v-if="showDashboardDesignPanel"
:visible="showDashboardDesignPanel"
:design="currentDashboardDesign as any"
@update:visible="showDashboardDesignPanel = $event"
@confirm="handleDashboardDesignConfirm"
@close="handleDashboardDesignClose"
/>
<!-- 仪表盘发布面板 -->
<DashboardPublishConfirmPanel
v-if="showDashboardPublishPanel"
:visible="showDashboardPublishPanel"
:publish-data="currentDashboardPublish as any"
@update:visible="showDashboardPublishPanel = $event"
@confirm="handleDashboardPublishConfirm"
@close="handleDashboardPublishClose"
/>
<!-- 系统总结面板 -->
<SystemSummaryConfirmPanel
v-if="showSystemSummaryPanel"
@@ -1090,60 +886,6 @@ onUnmounted(() => {
<!-- 侧边栏布局时的设计面板(保持原有行为) -->
<template v-if="layout === 'sidebar'">
<DesignEditorPanel
v-if="showDesignPanel"
:visible="showDesignPanel"
:design="currentDesign as any"
@update:visible="showDesignPanel = $event"
@confirm="handleDesignConfirm"
@close="handleDesignClose"
/>
<AppDesignPanel
v-if="showAppDesignPanel"
:visible="showAppDesignPanel"
:design="currentAppDesign as any"
@update:visible="showAppDesignPanel = $event"
@confirm="handleAppDesignConfirm"
@close="handleAppDesignClose"
/>
<AppSettingsPanel
v-if="showAppSettingsPanel"
:visible="showAppSettingsPanel"
:settings="currentAppSettings as any"
@update:visible="showAppSettingsPanel = $event"
@confirm="handleAppSettingsConfirm"
@close="handleAppSettingsClose"
/>
<DashboardBasicInfoConfirmPanel
v-if="showDashboardBasicInfoPanel"
:visible="showDashboardBasicInfoPanel"
:basic-info="currentDashboardBasicInfo as any"
@update:visible="showDashboardBasicInfoPanel = $event"
@confirm="handleDashboardBasicInfoConfirm"
@close="handleDashboardBasicInfoClose"
/>
<DashboardDesignConfirmPanel
v-if="showDashboardDesignPanel"
:visible="showDashboardDesignPanel"
:design="currentDashboardDesign as any"
@update:visible="showDashboardDesignPanel = $event"
@confirm="handleDashboardDesignConfirm"
@close="handleDashboardDesignClose"
/>
<DashboardPublishConfirmPanel
v-if="showDashboardPublishPanel"
:visible="showDashboardPublishPanel"
:publish-data="currentDashboardPublish as any"
@update:visible="showDashboardPublishPanel = $event"
@confirm="handleDashboardPublishConfirm"
@close="handleDashboardPublishClose"
/>
<SystemSummaryConfirmPanel
v-if="showSystemSummaryPanel"
:visible="showSystemSummaryPanel"
@@ -28,7 +28,7 @@ interface EventHandlerConfig {
running: Ref<boolean>;
conversationId: Ref<null | string>;
// 设计预览回调
onDesignPreview?: (data: DesignPreviewData) => void;
onDesignPreview?: (data: DesignPreviewData) => string | void;
}
/** 生成消息 ID */
@@ -104,10 +104,12 @@ export function useEventHandler(config: EventHandlerConfig) {
};
// 调用设计预览回调
onDesignPreview?.(previewData);
const customWaitingContent = onDesignPreview?.(previewData);
// 显示提示消息
const waitingContent = `**${configData.title}**\n\n${configData.message || '请在右侧面板中确认或编辑设计'}`;
const waitingContent =
customWaitingContent ||
`**${configData.title}**\n\n${configData.message || '请在右侧面板中确认或编辑设计'}`;
const initialMsg = messages.value.find((m) => m.id === msgId);
if (initialMsg && !initialMsg.content?.trim()) {
updateAssistantMessage(msgId, {
@@ -39,79 +39,22 @@ const widgetComponents: Record<
string,
ReturnType<typeof defineAsyncComponent>
> = {
'stat-card': defineAsyncComponent(() => import('./widgets/StatCard.vue')),
'progress-card': defineAsyncComponent(
() => import('./widgets/ProgressCard.vue'),
),
'chart-line': defineAsyncComponent(() => import('./widgets/ChartLine.vue')),
'chart-bar': defineAsyncComponent(() => import('./widgets/ChartBar.vue')),
'chart-pie': defineAsyncComponent(() => import('./widgets/ChartPie.vue')),
'chart-gauge': defineAsyncComponent(() => import('./widgets/ChartGauge.vue')),
'chart-area': defineAsyncComponent(() => import('./widgets/ChartArea.vue')),
'chart-radar': defineAsyncComponent(() => import('./widgets/ChartRadar.vue')),
'chart-funnel': defineAsyncComponent(
() => import('./widgets/ChartFunnel.vue'),
),
'chart-scatter': defineAsyncComponent(
() => import('./widgets/ChartScatter.vue'),
),
'chart-ring': defineAsyncComponent(() => import('./widgets/ChartRing.vue')),
'chart-heatmap': defineAsyncComponent(
() => import('./widgets/ChartHeatmap.vue'),
),
'chart-kline': defineAsyncComponent(() => import('./widgets/ChartKline.vue')),
'chart-sankey': defineAsyncComponent(
() => import('./widgets/ChartSankey.vue'),
),
'todo-list': defineAsyncComponent(() => import('./widgets/TodoList.vue')),
'notice-list': defineAsyncComponent(() => import('./widgets/NoticeList.vue')),
'ranking-list': defineAsyncComponent(
() => import('./widgets/RankingList.vue'),
),
'announcement-list': defineAsyncComponent(
() => import('./widgets/AnnouncementList.vue'),
),
'approval-center': defineAsyncComponent(
() => import('./widgets/ApprovalCenter.vue'),
),
'quick-links': defineAsyncComponent(() => import('./widgets/QuickLinks.vue')),
'welcome-card': defineAsyncComponent(
() => import('./widgets/WelcomeCard.vue'),
),
calendar: defineAsyncComponent(() => import('./widgets/CalendarWidget.vue')),
countdown: defineAsyncComponent(
() => import('./widgets/CountdownWidget.vue'),
),
clock: defineAsyncComponent(() => import('./widgets/ClockWidget.vue')),
weather: defineAsyncComponent(() => import('./widgets/WeatherWidget.vue')),
'image-carousel': defineAsyncComponent(
() => import('./widgets/ImageCarousel.vue'),
),
'data-table': defineAsyncComponent(() => import('./widgets/DataTable.vue')),
'form-render': defineAsyncComponent(
() => import('./widgets/FormRenderWidget.vue'),
),
iframe: defineAsyncComponent(() => import('./widgets/IframeWidget.vue')),
'video-player': defineAsyncComponent(
() => import('./widgets/VideoPlayer.vue'),
),
image: defineAsyncComponent(() => import('./widgets/ImageWidget.vue')),
'approval-center': defineAsyncComponent(
() => import('./widgets/ApprovalCenter.vue'),
),
'my-apps': defineAsyncComponent(() => import('./widgets/MyApps.vue')),
'server-monitor': defineAsyncComponent(
() => import('./widgets/ServerMonitor.vue'),
),
'filter-input': defineAsyncComponent(
() => import('./widgets/FilterInput.vue'),
),
'filter-select': defineAsyncComponent(
() => import('./widgets/FilterSelect.vue'),
),
'filter-date': defineAsyncComponent(
() => import('./widgets/FilterDate.vue'),
),
'filter-date-range': defineAsyncComponent(
() => import('./widgets/FilterDateRange.vue'),
),
};
const store = useDashboardDesignStore();
@@ -15,6 +15,15 @@ const props = defineProps<{
widget: DashboardWidget;
}>();
type StaticAppItem = {
code?: string;
icon?: string;
id: string;
name?: string;
path?: string;
title?: string;
};
// 应用列表
const appList = ref<ApplicationListItem[]>([]);
const loading = ref(false);
@@ -22,11 +31,22 @@ const loading = ref(false);
// 最大显示数量
const maxCount = computed(() => props.widget.props.maxCount || 8);
const configuredApps = computed<StaticAppItem[]>(() => {
const apps = props.widget.props.apps;
return Array.isArray(apps) ? apps.filter(Boolean) : [];
});
// 显示的应用列表
const displayApps = computed(() => appList.value.slice(0, maxCount.value));
const displayApps = computed(() => {
const source =
configuredApps.value.length > 0 ? configuredApps.value : appList.value;
return source.slice(0, maxCount.value);
});
// 加载已发布的应用列表
const loadApps = async () => {
if (configuredApps.value.length > 0) return;
loading.value = true;
try {
const res = await getApplicationListApi({
@@ -43,8 +63,18 @@ const loadApps = async () => {
};
// 点击应用
const handleClick = (app: ApplicationListItem) => {
window.open(`${window.location.origin}/app/${app.code}`, '_blank');
const handleClick = (app: ApplicationListItem | StaticAppItem) => {
const path = 'path' in app ? app.path : '';
const target =
path ||
('code' in app && app.code ? `/app/${app.code}` : '');
if (!target) return;
if (/^https?:\/\//.test(target)) {
window.open(target, '_blank');
return;
}
window.open(`${window.location.origin}${target}`, '_blank');
};
// 点击更多
@@ -52,6 +82,11 @@ const handleMore = () => {
window.open(`${window.location.origin}/application`, '_blank');
};
const getAppName = (app: ApplicationListItem | StaticAppItem) => {
if ('title' in app && app.title) return app.title;
return app.name || app.code || '';
};
onMounted(() => {
loadApps();
});
@@ -96,7 +131,9 @@ onMounted(() => {
/>
<AppWindow v-else class="h-6 w-6 text-white" />
</div>
<span class="text-muted-foreground w-full truncate text-center text-xs">{{ app.name }}</span>
<span class="text-muted-foreground w-full truncate text-center text-xs">{{
getAppName(app)
}}</span>
</div>
</div>
<ElEmpty