feat(@vben/web-antd): 新增新建会话功能并优化界面展示
This commit is contained in:
parent
8d17c6eb9f
commit
e4349221b2
@ -16,7 +16,7 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
items: () => [],
|
||||
temp: () => [],
|
||||
});
|
||||
const emit = defineEmits(['click', 'clickMode']);
|
||||
const emit = defineEmits(['click', 'clickMode', 'newConversation']);
|
||||
const defaultConversationsItems = computed(() => {
|
||||
return props.items.map((item) => {
|
||||
return {
|
||||
@ -51,6 +51,10 @@ const handleMenuClick = (item: { key: string }) => {
|
||||
}
|
||||
};
|
||||
|
||||
const handleNewConversation = () => {
|
||||
emit('newConversation');
|
||||
};
|
||||
|
||||
const onConversationClick: ConversationsProps['onActiveChange'] = (key) => {
|
||||
activeKey.value = key;
|
||||
|
||||
@ -73,6 +77,17 @@ watch(
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
watch(
|
||||
() => itemsData.value,
|
||||
(newVal) => {
|
||||
if (newVal && newVal.length > 0) {
|
||||
selectedKeys.value = [newVal[0].key]; // 默认选中第一个菜单项
|
||||
handleMenuClick(newVal[0]);
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -88,6 +103,10 @@ watch(
|
||||
/>
|
||||
|
||||
<div class="addBtn">会话</div>
|
||||
|
||||
<Button type="submit" class="newBtn" @click="handleNewConversation">
|
||||
新建会话
|
||||
</Button>
|
||||
<!-- 🌟 会话管理 -->
|
||||
<Conversations
|
||||
:items="conversationsItems"
|
||||
@ -182,4 +201,13 @@ watch(
|
||||
width: calc(100% - 24px);
|
||||
margin: 12px 12px 24px 12px;
|
||||
}
|
||||
|
||||
.newBtn {
|
||||
float: left;
|
||||
width: calc(100% - 24px);
|
||||
margin: 12px 12px 12px 12px;
|
||||
padding: 5px;
|
||||
border-radius: 5px;
|
||||
background-color: rgba(19, 118, 163, 0.1);
|
||||
}
|
||||
</style>
|
||||
|
@ -110,6 +110,7 @@ const handleFileChange: AttachmentsProps['onChange'] = (info) =>
|
||||
// }
|
||||
|
||||
const startFetching = async () => {
|
||||
resultItems.value = [];
|
||||
agentRequestLoading.value = true;
|
||||
fetchStatus.value = 'fetching';
|
||||
resultItems.value.push({
|
||||
@ -192,6 +193,7 @@ watch(
|
||||
() => props.itemMessage,
|
||||
(newVal) => {
|
||||
resultItems.value = [];
|
||||
content.value = '';
|
||||
if (newVal && newVal.length > 0) {
|
||||
newVal.forEach((msg) => {
|
||||
if (msg.role === 'user') {
|
||||
@ -272,7 +274,7 @@ watch(
|
||||
:typing="true"
|
||||
:items="resultItems"
|
||||
:roles="roles"
|
||||
style="flex: 1"
|
||||
style="flex: 1; padding: 10px 10px 0"
|
||||
/>
|
||||
|
||||
<!-- 🌟 输入框 -->
|
||||
|
@ -60,6 +60,11 @@ async function handleClick(item: PPTTempItem) {
|
||||
}
|
||||
}
|
||||
|
||||
function handleNewConversation() {
|
||||
// 清空对话内容
|
||||
itemMessage.value = [];
|
||||
}
|
||||
|
||||
const currentTemp = ref<null | PPTTempItem>(null);
|
||||
|
||||
async function handleClickMode(item: PPTTempItem) {
|
||||
@ -87,6 +92,7 @@ onMounted(() => {
|
||||
:loading="loading"
|
||||
@click-mode="handleClickMode"
|
||||
@click="handleClick"
|
||||
@new-conversation="handleNewConversation"
|
||||
/>
|
||||
</div>
|
||||
<PptWorkView
|
||||
|
@ -40,6 +40,7 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
id: '',
|
||||
name: '',
|
||||
url: '',
|
||||
description: '',
|
||||
}),
|
||||
runSpider: () => async () => ({
|
||||
msg: '',
|
||||
@ -372,7 +373,7 @@ watch(
|
||||
<CardTitle class="text-lg">{{ title }}</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent class="flex flex-wrap pt-0">
|
||||
{{ item ? item.url : '请选择左侧列表' }}
|
||||
{{ props.item ? props.item.description : '请选择左侧列表' }}
|
||||
</CardContent>
|
||||
<CardFooter class="flex justify-end">
|
||||
<RangePicker
|
||||
|
@ -30,6 +30,7 @@ const transformItems = computed(() => {
|
||||
key: item.id,
|
||||
label: item.name,
|
||||
title: item.name,
|
||||
description: item.description,
|
||||
}));
|
||||
});
|
||||
|
||||
@ -43,6 +44,7 @@ const handleMenuClick = (item: { key: string }) => {
|
||||
name: selectedItem.title,
|
||||
id: selectedItem.key,
|
||||
url: selectedItem.url,
|
||||
description: selectedItem.description,
|
||||
};
|
||||
emit('clickMode', transformedItem); // 发送转换后的数据
|
||||
}
|
||||
@ -66,6 +68,16 @@ watch(
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
watch(
|
||||
() => itemsData.value,
|
||||
(newVal) => {
|
||||
if (newVal && newVal.length > 0) {
|
||||
selectedKeys.value = [newVal[0].key]; // 默认选中第一个菜单项
|
||||
openKeys.value = [newVal[0].key]; // 默认展开第一个菜单项
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -33,6 +33,7 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
id: '',
|
||||
name: '',
|
||||
url: '',
|
||||
description: '',
|
||||
}),
|
||||
runSpiderGz: () => async () => ({
|
||||
outputs: {
|
||||
@ -292,7 +293,7 @@ watch(
|
||||
<CardTitle class="text-lg">{{ title }}</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent class="flex flex-wrap pt-0">
|
||||
{{ item ? item.url : '请选择左侧列表' }}
|
||||
{{ props.item ? props.item.description : '请选择左侧列表' }}
|
||||
</CardContent>
|
||||
<CardFooter class="flex justify-end">
|
||||
<Button :disabled="!item" type="primary" @click="startFetching">
|
||||
|
@ -36,7 +36,11 @@ const getTemp = async () => {
|
||||
const res = await getAppListByType(3);
|
||||
if (Array.isArray(res) && res.length > 0) {
|
||||
// 提取 id 和 name 并赋值给 temp
|
||||
temp.value = res.map(({ id, name }) => ({ id, name }));
|
||||
temp.value = res.map(({ id, name, description }) => ({
|
||||
id,
|
||||
name,
|
||||
description,
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
@ -58,6 +62,7 @@ async function handleClick(item: WordFlowItem) {
|
||||
const currentTemp = ref<TempItem>({
|
||||
id: '77c068fd-d5b6-4c33-97d8-db5511a09b26',
|
||||
name: '全国公共资源交易平台_信息爬取',
|
||||
description: 'https://ygp.gdzwfw.gov.cn/',
|
||||
});
|
||||
|
||||
async function handleClickMode(item: TempItem) {
|
||||
|
@ -2,6 +2,7 @@ interface TempItem {
|
||||
id: string;
|
||||
name: string;
|
||||
url?: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
interface ResultItem {
|
||||
|
@ -18,7 +18,7 @@ const props = withDefaults(defineProps<PropsHistory>(), {
|
||||
items: () => [],
|
||||
temp: () => [],
|
||||
});
|
||||
const emit = defineEmits(['click', 'clickMode', 'delete']);
|
||||
const emit = defineEmits(['click', 'clickMode', 'delete', 'newConversation']);
|
||||
const defaultConversationsItems = computed(() => {
|
||||
return props.items.map((item) => {
|
||||
return {
|
||||
@ -58,6 +58,10 @@ const onConversationClick: ConversationsProps['onActiveChange'] = (key) => {
|
||||
emit('click', key);
|
||||
};
|
||||
|
||||
const handleNewConversation = () => {
|
||||
emit('newConversation');
|
||||
};
|
||||
|
||||
const menuConfig: ConversationsProps['menu'] = (conversation) => ({
|
||||
items: [
|
||||
{
|
||||
@ -83,6 +87,17 @@ watch(
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
watch(
|
||||
() => itemsData.value,
|
||||
(newVal) => {
|
||||
if (newVal && newVal.length > 0) {
|
||||
selectedKeys.value = [newVal[0].key]; // 默认选中第一个菜单项
|
||||
handleMenuClick(newVal[0]);
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -99,8 +114,10 @@ watch(
|
||||
<!-- 🌟 添加会话 -->
|
||||
<!-- <Button type="link" class="addBtn">会话</Button>-->
|
||||
<div class="addBtn">会话</div>
|
||||
<!-- 🌟 添加会话 -->
|
||||
|
||||
<!-- 🌟 新增:新建会话按钮 -->
|
||||
<Button type="submit" class="newBtn" @click="handleNewConversation">
|
||||
新建会话
|
||||
</Button>
|
||||
<!-- 🌟 会话管理 -->
|
||||
<Conversations
|
||||
:items="conversationsItems"
|
||||
@ -199,4 +216,12 @@ watch(
|
||||
width: calc(100% - 24px);
|
||||
margin: 12px 12px 24px 12px;
|
||||
}
|
||||
.newBtn {
|
||||
float: left;
|
||||
width: calc(100% - 24px);
|
||||
margin: 12px 12px 12px 12px;
|
||||
padding: 5px;
|
||||
border-radius: 5px;
|
||||
background-color: rgba(19, 118, 163, 0.1);
|
||||
}
|
||||
</style>
|
||||
|
@ -58,6 +58,12 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
},
|
||||
},
|
||||
}),
|
||||
projectInfo: () => ({
|
||||
projectName: '',
|
||||
projectContext: '',
|
||||
projectKeyAvoidTechOrKeyword: '',
|
||||
userInitialInnovationPoint: '',
|
||||
}),
|
||||
});
|
||||
|
||||
// 初始化 markdown 解析器
|
||||
@ -148,12 +154,7 @@ const content = ref('');
|
||||
// const conversationsItems = ref(defaultConversationsItems);
|
||||
const attachedFiles = ref<AttachmentsProps['items']>([]);
|
||||
const agentRequestLoading = ref(false);
|
||||
const projectInfo = ref({
|
||||
projectName: '',
|
||||
projectContext: '',
|
||||
projectKeyAvoidTechOrKeyword: '',
|
||||
userInitialInnovationPoint: '',
|
||||
});
|
||||
const projectInfo = ref({ ...props.projectInfo });
|
||||
const open = ref(false);
|
||||
// const inputStatus = ref<string>('');
|
||||
const fetchStatus = ref('');
|
||||
@ -178,20 +179,6 @@ function openPreviewDrawer(
|
||||
}
|
||||
|
||||
// ==================== Event ====================
|
||||
|
||||
// 判断是否是以 .docx 结尾的 URL
|
||||
// function isDocxURL(str: string): boolean {
|
||||
// return str.endsWith('.docx');
|
||||
// }
|
||||
|
||||
// 使用正则提取 /static/ 后面的文件名部分
|
||||
// function extractDocxFilename(url: string): null | string {
|
||||
// const match = url.match(/\/static\/([a-f0-9-]+\.docx)$/i);
|
||||
// if (match) {
|
||||
// return match[1]; // 返回类似:9e1c421e-991c-411f-8176-6350a97e70f3.docx
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
function extractDocxInfo(
|
||||
markdownLink: string,
|
||||
): null | { filename: string; url: string } {
|
||||
@ -310,6 +297,7 @@ watch(
|
||||
() => props.itemMessage,
|
||||
(newVal) => {
|
||||
resultItems.value = [];
|
||||
content.value = '';
|
||||
if (newVal && newVal.length > 0) {
|
||||
newVal.forEach((msg) => {
|
||||
if (msg.role === 'user') {
|
||||
@ -372,6 +360,14 @@ watch(
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.projectInfo,
|
||||
(newVal) => {
|
||||
projectInfo.value = { ...newVal };
|
||||
},
|
||||
{ deep: true, immediate: true },
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -429,7 +425,7 @@ watch(
|
||||
v-else
|
||||
:items="resultItems"
|
||||
:roles="roles"
|
||||
style="flex: 1"
|
||||
style="flex: 1; padding: 10px"
|
||||
:message-render="renderMarkdown"
|
||||
/>
|
||||
|
||||
@ -445,12 +441,13 @@ watch(
|
||||
:value="content"
|
||||
class="sender"
|
||||
:loading="agentRequestLoading"
|
||||
:disabled="agentRequestLoading"
|
||||
@submit="startFetching"
|
||||
@change="(value) => (content = value)"
|
||||
>
|
||||
<template #prefix>
|
||||
<Badge :dot="attachedFiles.length > 0 && !headerOpen">
|
||||
<Button type="text" @click="() => (open = !open)">
|
||||
<Button @click="() => (open = !open)">
|
||||
<template #icon>
|
||||
<EditOutlined />
|
||||
</template>
|
||||
|
@ -23,6 +23,7 @@ const temp = ref([]);
|
||||
const hitsory = ref([]);
|
||||
const loading = ref(true);
|
||||
const params = ref({});
|
||||
const projectInfo = ref({});
|
||||
|
||||
const getLogs = async (appid: string) => {
|
||||
loading.value = true;
|
||||
@ -68,17 +69,30 @@ function handleClickMode(item: WordTempItem) {
|
||||
getParameters(item.id);
|
||||
}
|
||||
|
||||
function handleNewConversation() {
|
||||
// 清空项目信息
|
||||
projectInfo.value = {
|
||||
projectName: '',
|
||||
projectContext: '',
|
||||
projectKeyAvoidTechOrKeyword: '',
|
||||
userInitialInnovationPoint: '',
|
||||
};
|
||||
|
||||
// 清空对话内容
|
||||
itemMessage.value = [];
|
||||
}
|
||||
|
||||
const itemMessage = ref<ResultItem[]>([]);
|
||||
|
||||
async function deleteLog(item: any) {
|
||||
const res = await deleteChatflow({
|
||||
appId: temp.value.id,
|
||||
appId: currentTemp.value.id,
|
||||
conversationId: item,
|
||||
userId: '1562',
|
||||
});
|
||||
if (res.code === 0) {
|
||||
if (res.message === '删除成功') {
|
||||
message.success('删除成功');
|
||||
getLogs(temp.value.id);
|
||||
getLogs(currentTemp.value.id);
|
||||
} else {
|
||||
message.error('删除失败');
|
||||
}
|
||||
@ -96,6 +110,7 @@ async function handleClick(item: string) {
|
||||
conversationId: item,
|
||||
limit: '',
|
||||
});
|
||||
projectInfo.value = res.data[0].inputs;
|
||||
itemMessage.value = [];
|
||||
if (res.data.length > 0) {
|
||||
res.data.forEach((msg) => {
|
||||
@ -120,6 +135,7 @@ async function handleClick(item: string) {
|
||||
|
||||
onMounted(() => {
|
||||
getTemp();
|
||||
handleNewConversation();
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -134,6 +150,7 @@ onMounted(() => {
|
||||
@click-mode="handleClickMode"
|
||||
@click="handleClick"
|
||||
@delete="deleteLog"
|
||||
@new-conversation="handleNewConversation"
|
||||
/>
|
||||
</div>
|
||||
<WordWorkView
|
||||
@ -141,6 +158,7 @@ onMounted(() => {
|
||||
:params-data="params"
|
||||
:run-chatflow="sendWord"
|
||||
:item-message="itemMessage"
|
||||
:project-info="projectInfo"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -48,6 +48,7 @@ interface Props {
|
||||
appId: any,
|
||||
context: WorkflowContext,
|
||||
) => Promise<WorkflowResult>;
|
||||
projectInfo: object;
|
||||
}
|
||||
|
||||
interface PropsHistory {
|
||||
|
@ -11,8 +11,8 @@ export default defineConfig(async () => {
|
||||
rewrite: (path) => path.replace(/^\/api/, ''),
|
||||
// mock代理目标地址
|
||||
// target: 'http://172.16.35.190:9090/api',
|
||||
// target: 'http://43.139.10.64:8082/api',
|
||||
target: 'http://localhost:8081/api',
|
||||
target: 'http://43.139.10.64:8082/api',
|
||||
// target: 'http://localhost:8081/api',
|
||||
// target: 'http://192.168.3.238:8081/api',
|
||||
ws: true,
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user