refactor(@vben/web-antd): 重构爬虫页面组件和样式

- 移除了不必要的导入和未使用的代码
- 优化了爬虫列表和工作视图的结构- 添加了项目信息表单模态框
- 调整了布局和样式,提高了页面的可读性和可用性
This commit is contained in:
Kven 2025-05-17 17:34:27 +08:00
parent ad79e5113e
commit e4a74a5f8c
7 changed files with 83 additions and 214 deletions

View File

@ -1,6 +1,4 @@
<script lang="ts" setup>
import type { PPTTempItem } from '@vben/common-ui';
import { ref } from 'vue';
import { SpiderListView, SpiderWorkView } from '@vben/common-ui';
@ -9,6 +7,12 @@ import { notification } from 'ant-design-vue';
import { getWorkflowInfo, getWorkflowList, runSpider } from '#/api';
// sendWorkflow
interface TempItem {
id: string;
name: string;
url: string;
}
interface ResultItem {
key: number;
role: 'ai' | 'user';
@ -53,7 +57,7 @@ async function handleClick(item: WordFlowItem) {
}
}
async function handleClickMode(item: PPTTempItem) {
async function handleClickMode(item: TempItem) {
notification.success({
message: `${item.name}`,
description: '已选取',

View File

@ -203,7 +203,7 @@ const startFetching = async () => {
}
// url http://47.112.173.8:6802/static/66f3cfd95e364a239d8036390db658ae.pptx
fetchResult.value = `/static/${filename.value}`;
fetchResult.value = `/pptx/${filename.value}`;
resultItems.value.push({
key: resultItems.value.length + 1,
role: 'ai',
@ -252,50 +252,6 @@ const startFetching = async () => {
};
// ==================== Nodes ====================
// const placeholderNode = computed(() =>
// h(
// Space,
// { direction: 'vertical', size: 16, style: value.placeholder },
// [
// h(Welcome, {
// variant: 'borderless',
// icon: 'https://mdn.alipayobjects.com/huamei_iwk9zp/afts/img/A*s5sNRo5LjfQAAAAAAAAAAAAADgCCAQ/fmt.webp',
// title: "Hello, I'm Ant Design X",
// description:
// 'Base on Ant Design, AGI product interface solution, create a better intelligent vision~',
// extra: h(Space, {}, [
// h(Button, { icon: h(ShareAltOutlined) }),
// h(Button, { icon: h(EllipsisOutlined) }),
// ]),
// }),
// h(Prompts, {
// title: 'Do you want?',
// items: placeholderPromptsItems,
// styles: {
// list: {
// width: '100%',
// },
// item: {
// flex: 1,
// },
// },
// onItemClick: onPromptsItemClick,
// }),
// ],
// ),
// );
// const items = computed<BubbleListProps['items']>(() => {
// // if (messages.value.length === 0) {
// // return [{ content: placeholderNode, variant: 'borderless' }];
// // }
// return messages.value.map(({ id, message, status }) => ({
// key: id,
// loading: status === 'loading',
// role: status === 'local' ? 'local' : 'ai',
// content: message,
// }));
// });
// itemMessage resultItems
watch(

View File

@ -5,6 +5,7 @@ interface PPTTempItem {
appId?: string;
userId?: string;
taskId?: string;
url?: string;
}
interface PptHistoryItem {

View File

@ -40,11 +40,13 @@ const itemsData = ref([
key: '77c068fd-d5b6-4c33-97d8-db5511a09b26',
label: '全国公共资源交易平台_信息爬取',
title: '全国公共资源交易平台_信息爬取',
url: 'https://ygp.gdzwfw.gov.cn/',
},
{
key: 'c736edd0-925d-4877-9223-56aab7342311',
label: '广州公共资源交易中心_信息获取',
title: '全国公共资源交易平台_信息爬取',
url: 'https://www.gzggzy.cn',
},
]);
@ -55,6 +57,7 @@ const handleMenuClick = (item: { key: string }) => {
const transformedItem = {
name: selectedItem.title,
id: selectedItem.key,
url: selectedItem.url,
};
emit('clickMode', transformedItem); //
}

View File

@ -373,7 +373,7 @@ watch(
<CardTitle class="text-lg">{{ title }}</CardTitle>
</CardHeader>
<CardContent class="flex flex-wrap pt-0">
{{ item ? item.name : '请选择右侧爬虫' }}
{{ item ? item.url : '请选择左侧列表' }}
</CardContent>
<CardFooter class="flex justify-end">
<RangePicker
@ -383,17 +383,11 @@ watch(
/>
<Button
:disabled="!item || selectedDateRange.length < 2"
type="primary"
@click="startFetching"
>
{{ isFetching ? '抓取中...' : '开始抓取' }}
</Button>
<!-- <Button-->
<!-- class="mx-2"-->
<!-- :disabled="fetchStatus !== 'completed'"-->
<!-- @click="downloadFile"-->
<!-- >-->
<!-- 下载文件-->
<!-- </Button>-->
</CardFooter>
</Card>
</div>

View File

@ -1,6 +1,7 @@
interface SpiderItem {
id: string;
name: string;
url: string;
}
export type { SpiderItem };

View File

@ -11,8 +11,7 @@ import type { WordTempItem } from './typing';
import { computed, h, ref, watch } from 'vue';
import { useVbenForm } from '@vben-core/form-ui';
import { useVbenDrawer, useVbenModal } from '@vben-core/popup-ui';
import { useVbenDrawer } from '@vben-core/popup-ui';
import {
CloudUploadOutlined,
@ -24,8 +23,12 @@ import {
Badge,
Button,
Flex,
message,
Form,
FormItem,
Input,
Modal,
Space,
Textarea,
Typography,
} from 'ant-design-vue';
import {
@ -164,11 +167,6 @@ const roles: BubbleListProps['roles'] = {
h(Typography, [
h('div', {
innerHTML: md.render(content),
style: {
// padding: '8px',
lineHeight: '1.6',
whiteSpace: 'break-spaces',
},
}),
]),
},
@ -194,12 +192,22 @@ const content = ref('');
const activeKey = ref(defaultConversationsItems[0].key);
const attachedFiles = ref<AttachmentsProps['items']>([]);
const agentRequestLoading = ref(false);
const projectName = ref<string>('');
const inputStatus = ref<string>('');
const projectInfo = ref({
projectName: '',
projectContext: '',
projectKeyAvoidTechOrKeyword: '',
userInitialInnovationPoint: '',
});
const open = ref(false);
// const inputStatus = ref<string>('');
const fetchStatus = ref('');
const resultItems = ref<ResultItem[]>([]);
const conversationId = ref('');
const fetchResult = ref('');
const layout = {
labelCol: { span: 6 },
wrapperCol: { span: 16 },
};
// ==================== Runtime ====================
const [agent] = useXAgent({
request: async ({ message }, { onSuccess }) => {
@ -252,15 +260,11 @@ function extractDocxFilename(url: string): null | string {
}
return null;
}
const showModal = () => {
open.value = true;
};
const startFetching = async () => {
//
if (!projectName.value.trim()) {
inputStatus.value = 'error';
message.error('请输入项目名称');
return;
}
open.value = false;
agentRequestLoading.value = true;
fetchStatus.value = 'fetching';
resultItems.value.push({
@ -279,10 +283,11 @@ const startFetching = async () => {
conversationId: conversationId.value,
files: [],
inputs: {
projectName: projectName.value,
projectContext: '无',
keyAvoidTechOrKeyword: '无',
userInitialInnovationPoint: '无',
projectName: projectInfo.value.projectName,
projectContext: projectInfo.value.projectContext,
keyAvoidTechOrKeyword: projectInfo.value.projectKeyAvoidTechOrKeyword,
userInitialInnovationPoint:
projectInfo.value.userInitialInnovationPoint,
},
content: content.value || '',
},
@ -351,79 +356,6 @@ const startFetching = async () => {
fetchStatus.value = 'completed';
};
function openFormModal() {
formModalApi
.setData({
//
values: {
projectName: 'abc',
projectContext: '123',
keyAvoidTechOrKeyWord: 'abc',
userInitialInnovationPoint: 'abc',
},
})
.open();
}
const [Form, formApi] = useVbenForm({
handleSubmit: startFetching,
schema: [
{
component: 'Input',
componentProps: {
placeholder: '请输入',
},
fieldName: 'projectName',
label: '项目名称',
},
{
component: 'Input',
componentProps: {
placeholder: '请输入',
},
fieldName: 'projectContext',
label: '项目背景',
},
{
component: 'Input',
componentProps: {
placeholder: '请输入',
},
fieldName: 'keyAvoidTechOrKeyWord',
label: '规避关键词',
},
{
component: 'Input',
componentProps: {
placeholder: '请输入',
},
fieldName: 'userInitialInnovationPoint',
label: '初步创新点',
},
],
showDefaultActions: false,
});
const [Modal, formModalApi] = useVbenModal({
fullscreenButton: false,
onCancel() {
formModalApi.close();
},
onConfirm: async () => {
await formApi.validateAndSubmitForm();
// modalApi.close();
},
onOpenChange(isOpen: boolean) {
if (isOpen) {
const { values } = formModalApi.getData<Record<string, any>>();
if (values) {
formApi.setValues(values);
}
}
},
title: '内嵌表单示例',
});
const onPromptsItemClick: PromptsProps['onItemClick'] = (info) => {
content.value = info.data.description;
};
@ -506,8 +438,42 @@ watch(
<template>
<div class="layout">
<PreviewDrawer />
<Modal>
<Form />
<Modal v-model:open="open" title="项目信息" :footer="null">
<Form :model="projectInfo" v-bind="layout" @finish="startFetching">
<FormItem label="项目名称" name="projectName" required>
<Input
v-model:value="projectInfo.projectName"
placeholder="请输入项目名称"
/>
</FormItem>
<FormItem label="项目背景" name="projectContext" required>
<Textarea
v-model:value="projectInfo.projectContext"
placeholder="请输入项目背景"
/>
</FormItem>
<FormItem
label="规避关键词"
name="projectKeyAvoidTechOrKeyword"
required
>
<Textarea
v-model:value="projectInfo.projectKeyAvoidTechOrKeyword"
placeholder="规避关键词"
/>
</FormItem>
<FormItem label="创新点" name="userInitialInnovationPoint" required>
<Textarea
v-model:value="projectInfo.userInitialInnovationPoint"
placeholder="请输入创新点"
/>
</FormItem>
<FormItem label="" :wrapper-col="{ span: 14, offset: 8 }">
<Button type="primary" html-type="submit" style="float: right">
提交
</Button>
</FormItem>
</Form>
</Modal>
<div class="chat">
<Space
@ -523,15 +489,6 @@ watch(
description="请选择模板列表中需要生成文件的模板,输入参数后开始生成生成内容或文件。"
/>
</Space>
<!-- <a-space class="w-full" direction="vertical" style="padding-top: 20px">-->
<!-- <a-input-->
<!-- v-model:value="projectName"-->
<!-- required-->
<!-- placeholder="项目名称"-->
<!-- :status="inputStatus"-->
<!-- />-->
<!-- </a-space>-->
<!-- 🌟 消息列表 -->
<Bubble.List
v-else
@ -553,7 +510,7 @@ watch(
:value="content"
class="sender"
:loading="agentRequestLoading"
@submit="openFormModal"
@submit="showModal"
@change="(value) => (content = value)"
>
<template #prefix>
@ -615,32 +572,19 @@ watch(
.layout {
width: 100%;
min-width: 1400px;
height: 100%;
max-height: 100vh;
display: flex;
flex-direction: column;
background: hsl(216deg 21.74% 95.49%);
font-family: AlibabaPuHuiTi, v-deep(var(--ant-font-family)), sans-serif;
border-radius: v-deep(var(--ant-border-radius));
}
.menu {
background: #ffffff;
width: 280px;
height: 100%;
display: flex;
flex-direction: column;
}
.conversations {
padding: 0 12px;
flex: 1;
overflow-y: auto;
}
.chat {
height: 100%;
width: 100%;
height: 100%;
max-height: 88vh;
max-width: 1000px;
max-height: 900px;
margin: 0 auto;
box-sizing: border-box;
display: flex;
@ -649,10 +593,6 @@ watch(
gap: 16px;
}
//.messages {
// flex: 1;
//}
.placeholder {
padding-top: 32px;
text-align: left;
@ -664,34 +604,4 @@ watch(
width: 100%;
box-shadow: v-deep(var(--ant-box-shadow));
}
.logo {
display: flex;
height: 72px;
align-items: center;
justify-content: start;
padding: 0 24px;
box-sizing: border-box;
}
.logo-img {
width: 24px;
height: 24px;
display: inline-block;
}
.logo-span {
display: inline-block;
margin: 0 8px;
font-weight: bold;
color: v-deep(var(--ant-color-text));
font-size: 16px;
}
.addBtn {
background: #1677ff0f;
border: 1px solid #1677ff34;
width: calc(100% - 24px);
margin: 12px 12px 24px 12px;
}
</style>