refactor(@vben/web-antd): 优化 word 模块功能和界面

- 移除 authentication.json 中的冗余文本
- 新增 getMessages 接口用于获取消息列表
- 重构 word-history-view 和 word-work-view 组件
- 优化文档预览样式
- 修复聊天窗口的滚动问题
- 增加项目名称验证和错误提示
This commit is contained in:
vertoryao 2025-05-07 17:05:42 +08:00
parent 4518ef74eb
commit 62f1343c3b
11 changed files with 74 additions and 42 deletions

View File

@ -15,6 +15,13 @@ export namespace ChatflowApi {
files: []; files: [];
} }
export interface MessagesRequest {
conversationId: string;
userId: string;
firstId: string;
limit: number;
}
export interface ChatListBody { export interface ChatListBody {
userId: string; userId: string;
lastId: string; lastId: string;
@ -57,9 +64,12 @@ export async function getChatList(
}); });
} }
// export function stopChatflow(data){ export async function getMessages(
// return requestClient.post('/v1/chat/stopMessagesStream', data); appId: string,
// }; data: ChatflowApi.MessagesRequest,
) {
return requestClient.post(`/v1/chat/messages/${appId}`, data);
}
// //
// export function getChatflowList(data){ // export function getChatflowList(data){
// return requestClient.post('/v1/chat/messages', data); // return requestClient.post('/v1/chat/messages', data);

View File

@ -1,13 +1,13 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { WordTempItem } from '@vben/common-ui'; import type { WordHistoryItem, WordTempItem } from '@vben/common-ui';
import { onMounted, reactive, ref } from 'vue'; import { onMounted, reactive, ref } from 'vue';
import { WordHistoryView, WordListView, WordWorkView } from '@vben/common-ui'; import { WordHistoryView, WordListView, WordWorkView } from '@vben/common-ui';
import { getChatList, sendChatflow } from '#/api'; import { getChatList, getMessages, sendChatflow } from '#/api';
let temp = reactive<WordTempItem>({ const temp = reactive<WordTempItem>({
id: 'baca08c1-e92b-4dc9-a445-3584803f54d4', id: 'baca08c1-e92b-4dc9-a445-3584803f54d4',
name: '职业创新申报书', name: '职业创新申报书',
}); });
@ -28,17 +28,15 @@ const getLogs = async (appid: string) => {
limit: '5', limit: '5',
}, },
); );
// const res = await getChatList({
// appid,
// limit: 5,
// page: 1,
// });
hitsory.value = res.data; hitsory.value = res.data;
loading.value = false; loading.value = false;
}; };
function handleClick(item: WordTempItem) { async function handleClick(item: WordHistoryItem) {
temp = item; await getMessages(temp.id, {
conversationId: item.id,
userId: '1562',
});
} }
onMounted(() => { onMounted(() => {

View File

@ -45,6 +45,7 @@
"@vueuse/integrations": "catalog:", "@vueuse/integrations": "catalog:",
"ant-design-vue": "catalog:", "ant-design-vue": "catalog:",
"ant-design-x-vue": "^1.1.2", "ant-design-x-vue": "^1.1.2",
"dayjs": "catalog:",
"qrcode": "catalog:", "qrcode": "catalog:",
"tippy.js": "catalog:", "tippy.js": "catalog:",
"vue": "catalog:", "vue": "catalog:",

View File

@ -11,7 +11,7 @@ import VueOfficePptx from '@vue-office/pptx';
const pptx = ref('/pptx/66f3cfd95e364a239d8036390db658ae.pptx'); const pptx = ref('/pptx/66f3cfd95e364a239d8036390db658ae.pptx');
const pptStyle = ref({ const pptStyle = ref({
height: 'calc(100vh - 100px)', height: 'calc(100vh - 100px)',
width: '100%', width: 'auto',
margin: 'auto', margin: 'auto',
background: '#ffffff', background: '#ffffff',
}); });
@ -40,7 +40,7 @@ const [Drawer, drawerApi] = useVbenDrawer({
}); });
</script> </script>
<template> <template>
<Drawer title="文档预览" :footer="false"> <Drawer class="w-[880px]" title="文档预览" :footer="false">
<VueOfficePptx <VueOfficePptx
:src="pptx" :src="pptx"
:style="pptStyle" :style="pptStyle"
@ -52,6 +52,6 @@ const [Drawer, drawerApi] = useVbenDrawer({
<style scoped> <style scoped>
.pptx-preview-wrapper { .pptx-preview-wrapper {
background: #fff; background: #fff !important;
} }
</style> </style>

View File

@ -286,10 +286,12 @@ watch(
</script> </script>
<template> <template>
<div> <PreviewDrawer />
<PreviewDrawer /> <div class="flex h-[910px] flex-col">
<div style="height: calc(67vh - 120px); margin: 20px; overflow-y: auto"> <div class="flex-1 overflow-y-auto">
<BubbleList :roles="roles" :items="resultItems" /> <div style="margin: 20px; overflow-y: auto">
<BubbleList :auto-scroll="true" :roles="roles" :items="resultItems" />
</div>
</div> </div>
<Card class="w-full"> <Card class="w-full">
<Sender <Sender

View File

@ -76,6 +76,7 @@ const startFetching = async () => {
); );
// //
fetchResult.value = res.data.outputs.result; fetchResult.value = res.data.outputs.result;
downloadDisable.value = false;
} catch (error) { } catch (error) {
console.error(error); console.error(error);
} }
@ -109,6 +110,7 @@ const downloadFile = () => {
}; };
const isFetching = ref(false); const isFetching = ref(false);
const downloadDisable = ref(true);
const fetchResult = ref(''); const fetchResult = ref('');
const fetchStatus = ref(''); const fetchStatus = ref('');
</script> </script>
@ -126,11 +128,7 @@ const fetchStatus = ref('');
<Button :disabled="!item" @click="startFetching"> <Button :disabled="!item" @click="startFetching">
{{ isFetching ? '抓取中...' : '开始抓取' }} {{ isFetching ? '抓取中...' : '开始抓取' }}
</Button> </Button>
<Button <Button class="mx-2" :disabled="downloadDisable" @click="downloadFile">
class="mx-2"
:disabled="fetchStatus !== 'completed'"
@click="downloadFile"
>
下载文件 下载文件
</Button> </Button>
</CardFooter> </CardFooter>

View File

@ -5,13 +5,11 @@ interface WordTempItem {
interface WordHistoryItem { interface WordHistoryItem {
id: string; id: string;
workflowRun: { inputs: {
id: string; projectName: string;
};
createdByEndUser: {
id: string;
sessionId: string;
}; };
name: string;
createdAt: number;
} }
export type { WordHistoryItem, WordTempItem }; export type { WordHistoryItem, WordTempItem };

View File

@ -3,6 +3,8 @@ import type { WordHistoryItem } from '../word';
import { Card, CardContent, CardHeader, CardTitle } from '@vben-core/shadcn-ui'; import { Card, CardContent, CardHeader, CardTitle } from '@vben-core/shadcn-ui';
import dayjs from 'dayjs';
interface Props { interface Props {
items?: WordHistoryItem[]; items?: WordHistoryItem[];
title: string; title: string;
@ -35,7 +37,10 @@ defineEmits(['click']);
@click="$emit('click', item)" @click="$emit('click', item)"
class="flex cursor-pointer justify-between gap-x-6 py-5" class="flex cursor-pointer justify-between gap-x-6 py-5"
> >
{{ item.id }} <span>{{ item.name }}</span>
<span>{{
dayjs.unix(item.createdAt).format('YYYY-MM-DD HH:mm:ss')
}}</span>
</li> </li>
</ul> </ul>
</CardContent> </CardContent>

View File

@ -12,7 +12,7 @@ import { useVbenDrawer } from '@vben/common-ui';
import { Card } from '@vben-core/shadcn-ui'; import { Card } from '@vben-core/shadcn-ui';
import { UserOutlined } from '@ant-design/icons-vue'; import { UserOutlined } from '@ant-design/icons-vue';
import { Button, Flex } from 'ant-design-vue'; import { Button, Flex, notification } from 'ant-design-vue';
import { Attachments, BubbleList, Sender } from 'ant-design-x-vue'; import { Attachments, BubbleList, Sender } from 'ant-design-x-vue';
import WordPreview from './word-preview.vue'; import WordPreview from './word-preview.vue';
@ -75,7 +75,16 @@ function openPreviewDrawer(
previewDrawerApi.setState({ placement }).setData(fileData).open(); previewDrawerApi.setState({ placement }).setData(fileData).open();
} }
const inputStatus = ref<string>('');
const startFetching = async () => { const startFetching = async () => {
if (!projectName.value) {
inputStatus.value = 'error';
notification.error({
duration: 3,
message: '请填写项目名称',
});
return;
}
isFetching.value = true; isFetching.value = true;
fetchStatus.value = 'fetching'; fetchStatus.value = 'fetching';
resultItems.value.push({ resultItems.value.push({
@ -272,13 +281,21 @@ const resultItems = ref<ResultItem[]>([]);
</script> </script>
<template> <template>
<div> <PreviewDrawer />
<PreviewDrawer /> <div class="flex h-[910px] flex-col">
<a-space class="w-full" direction="vertical"> <div class="flex-1 overflow-y-auto">
<a-input v-model:value="projectName" required placeholder="项目名称" /> <a-space class="w-full" direction="vertical">
</a-space> <a-input
<div style="height: calc(67vh - 120px); margin: 20px; overflow-y: auto"> size="large"
<BubbleList :roles="roles" :items="resultItems" /> v-model:value="projectName"
:status="inputStatus"
required
placeholder="项目名称(必填)"
/>
</a-space>
<div style="margin: 20px; overflow-y: auto">
<BubbleList :auto-scroll="true" :roles="roles" :items="resultItems" />
</div>
</div> </div>
<Card class="w-full"> <Card class="w-full">
<Sender <Sender

View File

@ -1,7 +1,7 @@
{ {
"welcomeBack": "欢迎回来", "welcomeBack": "欢迎回来",
"pageTitle": "开箱即用的大型中后台管理系统", "pageTitle": "",
"pageDesc": "工程化、高性能、跨组件库的前端模版", "pageDesc": "",
"loginSuccess": "登录成功", "loginSuccess": "登录成功",
"loginSuccessDesc": "欢迎回来", "loginSuccessDesc": "欢迎回来",
"loginSubtitle": "请输入您的帐户信息以开始管理您的项目", "loginSubtitle": "请输入您的帐户信息以开始管理您的项目",

View File

@ -1344,6 +1344,9 @@ importers:
ant-design-x-vue: ant-design-x-vue:
specifier: ^1.1.2 specifier: ^1.1.2
version: 1.1.2(ant-design-vue@4.2.6(vue@3.5.13(typescript@5.8.3)))(vue@3.5.13(typescript@5.8.3)) version: 1.1.2(ant-design-vue@4.2.6(vue@3.5.13(typescript@5.8.3)))(vue@3.5.13(typescript@5.8.3))
dayjs:
specifier: 'catalog:'
version: 1.11.13
qrcode: qrcode:
specifier: 'catalog:' specifier: 'catalog:'
version: 1.5.4 version: 1.5.4