feat: Conversations封装、首页开发

This commit is contained in:
rd
2025-08-19 18:01:30 +08:00
parent b717c7629f
commit c0fbf501e1
19 changed files with 594 additions and 29 deletions

View File

@ -0,0 +1,51 @@
<template>
<a-modal v-model:visible="visible" title="删除对话" width="400px" @close="onClose">
<div class="flex items-center">
<img :src="icon1" width="20" height="20" class="mr-12px" />
<span>确认删除对话吗删除后聊天记录将不可恢复</span>
</div>
<template #footer>
<a-button size="large" @click="onClose">取消</a-button>
<a-button type="primary" class="ml-16px !bg-#f64b31 !border-none" status="danger" size="large" @click="onDelete"
>确定</a-button
>
</template>
</a-modal>
</template>
<script setup>
import { ref } from 'vue';
import { deleteTask, deleteBatchTasks } from '@/api/all/common';
import icon1 from '@/assets/img/media-account/icon-warn-1.png';
const emits = defineEmits(['update', 'close', 'batchUpdate']);
const visible = ref(false);
const chatId = ref(null);
const isBatch = computed(() => Array.isArray(taskId.value));
function onClose() {
visible.value = false;
chatId.value = null;
emits('close');
}
const open = (record) => {
const { id = null } = record;
chatId.value = id;
visible.value = true;
};
async function onDelete() {
const { code } = await deleteTask(chatId.value);
if (code === 200) {
AMessage.success('删除成功');
emits('delete', chatId.value);
onClose();
}
}
defineExpose({ open });
</script>

View File

@ -0,0 +1,74 @@
<script lang="jsx">
import { Drawer } from 'ant-design-vue';
import TextoverTips from '@/components/text-over-tips';
import Conversations from '@/components/xt-chat/conversations';
import SvgIcon from '@/components/svg-icon';
import { Button, Flex, Input } from 'ant-design-vue';
import DeleteChatModal from './delete-chat-modal.vue';
export default {
setup(props, { emit, expose }) {
const open = ref(false);
const dataSource = ref([]);
const activeKey = ref('');
const deleteChatModalRef = ref(null);
const showDrawer = () => {
getData();
open.value = true;
};
const getData = () => {
dataSource.value = Array.from({ length: 4 }).map((conversation, index) => ({
key: `item${index + 1}`,
label: `Conversation Item ${index + 1}Conversation Item 1`,
}));
};
const onClose = () => {
open.value = false;
};
const handleMenuClick = (menuInfo) => {
const { item, key } = menuInfo;
switch (key) {
case 'pin':
console.log('置顶');
break;
case 'rename':
item.editing = true;
break;
case 'delete':
deleteChatModalRef.value.open(item);
break;
}
};
const handleRename = (item) => {
console.log('handleRename', item);
};
expose({
showDrawer,
});
return () => (
<Drawer width={240} rootClassName="ct-history-conversation-drawer" v-model:open={open.value} onClose={onClose}>
<header class="header h-40px px-12px flex justify-between items-center">
<span class="s1">历史对话</span>
<icon-close size={16} class="color-#211F24 cursor-pointer" onClick={onClose} />
</header>
<section class="flex-1 overflow-y-auto content p-12px">
<Conversations
v-model={activeKey.value}
dataSource={dataSource.value}
onMenuClick={handleMenuClick}
onRename={handleRename}
/>
</section>
<DeleteChatModal ref={deleteChatModalRef} />
</Drawer>
);
},
};
</script>
<style lang="scss">
@import './style.scss';
</style>

View File

@ -0,0 +1,37 @@
.ct-history-conversation-drawer {
border-radius: 8px;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.1);
.ant-drawer-content {
.ant-drawer-header {
display: none;
}
.ant-drawer-body {
padding: 0;
display: flex;
flex-direction: column;
.header {
position: relative;
&::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 1px;
margin: 0 16px;
background: #f2f3f5;
}
}
.content {
.ant-conversations {
gap: 0;
padding: 0;
.ant-conversations-item {
gap: 0;
padding: 8px;
}
}
}
}
}
}

View File

@ -1,7 +1,75 @@
<script lang="jsx">
import HistoryConversationDrawer from './components/history-conversation-drawer';
import { Sender } from 'ant-design-x-vue';
import { message } from 'ant-design-vue';
import { useSharedDataStore } from '@/stores/modules/share-data';
export default {
setup(props, { emit, expose }) {
return () => <div>home</div>;
const historyConversationDrawerRef = ref(null);
const searchValue = ref('');
const sharedDataStore = useSharedDataStore();
const handleSubmit = () => {
handleSearch();
searchValue.value = '';
};
const handleSearch = () => {
message.info('handleSearch');
};
onMounted(() => {
const params = sharedDataStore.routeParams;
if (params) {
searchValue.value = params.keyWord;
sharedDataStore.clearRouteParams();
handleSubmit();
}
});
return () => (
<div class="home-wrap rounded-12px w-full h-full">
<div class="w-full h-full flex justify-center ">
<div class="main-chat-wrap w-600px pt-120px">
<p class="title mb-16px">
<span>营小智7x24小时</span>
<span class="s1">AI营销</span>
<span>团队</span>
</p>
<p class="cts text-center mb-104px">AI 辅助账号托管账号 自动生成爆款内容 定时任务发布</p>
<Sender
v-model:value={searchValue.value}
onSubmit={handleSubmit}
class="h-120px w-full mb-24px"
placeholder="随时告诉我你想做什么,比如查数据、发任务、写内容,我会立刻帮你完成。"
actions={() => (
<div
onClick={handleSubmit}
class={`submit-btn w-32px h-32px p-6px flex justify-center items-center rounded-50% cursor-pointer ${
!searchValue.value ? 'opacity-50' : ''
}`}
>
<icon-arrow-right size={20} class="color-#FFFFFF" />
</div>
)}
/>
<p class="cts">可以试试这样下发任务</p>
</div>
</div>
{/**历史对话入口 */}
<div
class="history-conversation-btn cursor-pointer bg-#fff flex flex-col justify-center w-28px px-10px py-8px"
onClick={() => historyConversationDrawerRef.value.showDrawer()}
>
<span class="s1">历史对话</span>
</div>
<HistoryConversationDrawer ref={historyConversationDrawerRef} />
</div>
);
},
};
</script>

View File

@ -0,0 +1,54 @@
.home-wrap {
border: 1px solid rgba(255, 255, 255, 0.1);
backdrop-filter: blur(20px);
background: rgba(255, 255, 255, 0.9);
.cts {
color: var(--Text-1, #737478);
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 22px;
}
.main-chat-wrap {
.title {
color: var(--Text-1, #211f24);
text-align: center;
font-family: $font-family-medium;
font-size: 32px;
font-style: normal;
font-weight: 700;
line-height: 48px;
.s1 {
background: linear-gradient(90deg, #6d4cfe 38.12%, #b93bf0 100%);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
}
:deep(.ant-sender) {
.submit-btn {
background: linear-gradient(125deg, #6d4cfe 32.25%, #3ba1f0 72.31%),
linear-gradient(113deg, #6d4cfe 0%, #b93bf0 100%);
}
}
}
.history-conversation-btn {
border-radius: 8px 0 0 8px;
border-top: 1px solid #eabaff;
border-bottom: 1px solid #eabaff;
border-left: 1px solid #eabaff;
position: absolute;
top: 50%;
right: 0;
transform: translateY(-50%);
.s1 {
color: var(--Text-1, #211f24);
font-family: $font-family-regular;
font-size: 10px;
font-style: normal;
font-weight: 400;
line-height: 18px; /* 180% */
}
}
}