vue-vben-admin/apps/web-antd/src/views/spider/index.vue
Kven 7020672e57 feat(@vben/web-antd): 新增聊天流和数据抓取功能
- 添加聊天流 API 和相关组件,实现 PPT 模板生成工具界面
- 新增数据抓取工具列表和抓取功能
- 优化模板选择和会话管理逻辑
- 实现消息列表和输入框功能
- 添加文件上传和下载支持
2025-05-04 18:45:03 +08:00

212 lines
5.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="js">
import { onMounted, ref } from 'vue';
import { getAppList, sendWorkflow } from '#/api';
// 数据爬取工具列表
const tools = ref([
{
id: 1,
name: '工具一',
description: '这是一个用于抓取网页数据的工具',
content: '工具一的具体内容:支持多种网页抓取规则配置。',
path: '/tools/tool1',
},
{
id: 2,
name: '工具二',
description: '这是一个用于分析文本数据的工具',
content: '工具二的具体内容:支持自然语言处理和文本分析功能。',
path: '/tools/tool2',
},
{
id: 3,
name: '工具三',
description: '这是一个用于数据清洗的工具',
content: '工具三的具体内容:支持数据去重、格式化等操作。',
path: '/tools/tool3',
},
]);
// 当前选中的工具
const selectedTool = ref(null);
// 抓取状态相关变量
const isFetching = ref(false);
const fetchStatus = ref('idle'); // idle | fetching | completed
// 保存抓取结果
const fetchResult = ref(null);
// 点击工具项时触发
const selectTool = (tool) => {
selectedTool.value = tool;
fetchStatus.value = 'idle'; // 重置抓取状态
};
const getChatflowList = async () => {
try {
const res = await getAppList({
mode: '',
name: '',
});
tools.value = res.data;
} catch (error) {
console.error(error);
}
};
// 开始抓取逻辑
const startFetching = async () => {
if (!selectedTool.value) return;
// 更新状态为“抓取中”
isFetching.value = true;
fetchStatus.value = 'fetching';
try {
const res = await sendWorkflow(
{
appid: 'c736edd0-925d-4877-9223-56aab7342311',
},
{
userId: '1562',
conversationId: '',
files: [],
inputs: {},
},
);
// 保存抓取结果
fetchResult.value = res.data.data.outputs.result;
} catch (error) {
console.error(error);
}
// 模拟抓取完成
isFetching.value = false;
fetchStatus.value = 'completed';
};
// 下载文件逻辑
const downloadFile = () => {
if (!fetchResult.value) return;
// 使用抓取结果作为文件内容
const fileName = `${selectedTool.value.name}.txt`;
const fileContent = fetchResult.value;
// 创建 Blob 对象
const blob = new Blob([fileContent], { type: 'text/plain' });
// 创建下载链接
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = fileName;
// 触发下载
link.click();
// 释放 URL 对象
URL.revokeObjectURL(link.href);
};
onMounted(() => {
getChatflowList();
});
</script>
<template>
<a-layout>
<!-- 右侧部分开始 -->
<a-layout :style="{ height: '100vh' }">
<!-- 右侧页面主体开始 -->
<a-layout-content
:style="{
margin: '12px 10px',
padding: '18px',
background: '#fff',
minHeight: '280px',
borderRadius: '4px',
}"
>
<!-- 左右布局容器 -->
<a-row
:gutter="16"
:style="{ height: 'calc(100vh - 100px)', overflow: 'hidden' }"
>
<!-- 左边数据爬取工具列表 -->
<a-col
:span="6"
:style="{
height: '100%',
overflowY: 'auto',
borderRight: '1px solid #e8e8e8',
}"
>
<a-card
title="数据爬取工具列表"
:bordered="false"
:style="{ height: '100%' }"
>
<a-list item-layout="horizontal" :data-source="tools">
<template #renderItem="{ item }">
<a-list-item @click="selectTool(item)">
<a-list-item-meta>
<template #title>
<span>{{ item.name }}</span>
</template>
</a-list-item-meta>
</a-list-item>
</template>
</a-list>
</a-card>
</a-col>
<!-- 右边所选工具的内容 -->
<a-col
:span="18"
:style="{
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-end',
height: '100%',
}"
>
<a-card
v-if="selectedTool"
title="工具"
:bordered="false"
:style="{ marginBottom: '20px' }"
>
<p>{{ selectedTool.name }}</p>
<!-- 抓取按钮和状态 -->
<div style="float: right; margin-top: 20px">
<a-button
type="primary"
style="margin-right: 12px"
:loading="isFetching"
@click="startFetching"
>
开始抓取
</a-button>
<a-button
type="primary"
@click="downloadFile"
v-if="fetchStatus === 'completed'"
>
下载文件
</a-button>
</div>
</a-card>
<a-empty v-else description="请选择一个工具" />
</a-col>
</a-row>
</a-layout-content>
<!-- 右侧页面主体结束 -->
</a-layout>
<!-- 右侧部分结束 -->
</a-layout>
</template>