feat: Conversations封装、首页开发
This commit is contained in:
3
src/assets/svg/svg-pushpin.svg
Normal file
3
src/assets/svg/svg-pushpin.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 14 14" fill="none">
|
||||
<path d="M6.10963 5.99245L5.88754 6.00922L2.72457 6.2548L7.74479 11.275L7.99037 8.11205L8.00714 7.88996L10.5716 5.3255L8.67409 3.42799L6.10963 5.99245ZM9.17397 8.42741L8.8472 12.6525C8.80683 13.1737 8.17358 13.4078 7.80384 13.0383L4.80861 10.0431L1.9355 12.9162C1.85964 12.9921 1.7363 12.992 1.6604 12.9162L1.08404 12.3399C1.00814 12.264 1.00814 12.1407 1.08404 12.0648L3.95715 9.19165L0.961248 6.19575C0.592209 5.82604 0.826163 5.19293 1.34706 5.15239L5.57218 4.82562L7.82196 2.57585L6.9356 1.68949C6.86001 1.61358 6.86048 1.49086 6.93627 1.41506L7.51264 0.838698C7.58845 0.763107 7.71122 0.7625 7.78706 0.838028L13.1616 6.21253C13.2374 6.28835 13.2373 6.41172 13.1616 6.48763L12.5852 7.06399C12.5093 7.13989 12.386 7.13989 12.3101 7.06399L11.4237 6.17764L9.17397 8.42741Z" fill="currentColor"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 901 B |
@ -1,6 +1,11 @@
|
||||
<template>
|
||||
<a-tooltip :disabled="isShowBtn || (!isShowBtn && disabled)" :placement="props.placement">
|
||||
<template #content>
|
||||
<Tooltip
|
||||
:disabled="isShowBtn || (!isShowBtn && disabled)"
|
||||
:placement="props.placement"
|
||||
:mouseEnterDelay="props.mouseEnterDelay"
|
||||
:mouseLeaveDelay="props.mouseLeaveDelay"
|
||||
>
|
||||
<template #title>
|
||||
<div :style="contentStyle" class="tip-content">{{ props.context }}</div>
|
||||
</template>
|
||||
<div v-bind="$attrs" ref="Text" :class="`${isShow ? '' : `line-${props.line}`} `" class="overflow-text">
|
||||
@ -18,11 +23,23 @@
|
||||
{{ isShow ? '收起' : '展开' }}
|
||||
<icon-up size="16" :class="{ active: isShow }" class="ml-2px color-#8C8C8C" />
|
||||
</div>
|
||||
</a-tooltip>
|
||||
</Tooltip>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, toRefs, onBeforeMount, onMounted, watchEffect, computed, watch, nextTick, defineProps } from 'vue';
|
||||
import { Tooltip } from 'ant-design-vue';
|
||||
import {
|
||||
ref,
|
||||
reactive,
|
||||
toRefs,
|
||||
onBeforeMount,
|
||||
onMounted,
|
||||
watchEffect,
|
||||
computed,
|
||||
watch,
|
||||
nextTick,
|
||||
defineProps,
|
||||
} from 'vue';
|
||||
import elementResizeDetectorMaker from 'element-resize-detector';
|
||||
|
||||
const props = defineProps({
|
||||
@ -38,6 +55,14 @@ const props = defineProps({
|
||||
type: Number,
|
||||
default: 1,
|
||||
},
|
||||
mouseEnterDelay: {
|
||||
type: Number,
|
||||
default: 0.01,
|
||||
},
|
||||
mouseLeaveDelay: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
maxHeight: {
|
||||
type: [String, Number],
|
||||
default: '',
|
||||
|
||||
173
src/components/xt-chat/conversations/index.vue
Normal file
173
src/components/xt-chat/conversations/index.vue
Normal file
@ -0,0 +1,173 @@
|
||||
<script lang="tsx">
|
||||
import { ref, defineComponent, computed } from 'vue';
|
||||
import { Input, Dropdown, Menu } from 'ant-design-vue';
|
||||
import type { MenuProps } from 'ant-design-vue';
|
||||
|
||||
import type { VNode } from 'vue';
|
||||
import SvgIcon from '@/components/svg-icon';
|
||||
import TextoverTips from '@/components/text-over-tips';
|
||||
|
||||
// 定义对话项类型
|
||||
interface ConversationItem {
|
||||
key: string;
|
||||
label: string | VNode;
|
||||
icon?: string | VNode;
|
||||
disabled?: boolean;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
const DEFAULT_MENU_CONFIG = [
|
||||
{
|
||||
label: '置顶',
|
||||
key: 'pin',
|
||||
icon: () => <SvgIcon name="svg-pushpin" size={14} class="color-#737478 hover:color-#6D4CFE" />,
|
||||
},
|
||||
{
|
||||
label: '重命名',
|
||||
key: 'rename',
|
||||
icon: <icon-edit size={14} class="color-#737478" />,
|
||||
},
|
||||
{
|
||||
label: '删除',
|
||||
key: 'delete',
|
||||
icon: <icon-delete size={14} class="color-#F64B31" />,
|
||||
status: 'danger',
|
||||
},
|
||||
] as ConversationItem[];
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Conversations',
|
||||
props: {
|
||||
dataSource: {
|
||||
type: Array as () => ConversationItem[],
|
||||
default: () => [],
|
||||
},
|
||||
activeKey: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
defaultActiveKey: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
menu: {
|
||||
type: Array as () => ConversationItem[],
|
||||
default: () => DEFAULT_MENU_CONFIG,
|
||||
},
|
||||
},
|
||||
emits: ['activeChange', 'menuClick', 'update:dataSource', 'update:modelValue', 'rename'],
|
||||
setup(props, { emit, expose }) {
|
||||
const activeKey = ref(props.activeKey || props.defaultActiveKey || '');
|
||||
const localDataSource = ref<ConversationItem[]>([]);
|
||||
const inputRef = ref(null);
|
||||
const menuConfigs = ref<ConversationItem[]>(props.menu ?? DEFAULT_MENU_CONFIG);
|
||||
|
||||
// 处理选中变更
|
||||
const handleActiveChange = (value: string) => {
|
||||
activeKey.value = value;
|
||||
emit('update:modelValue', value);
|
||||
emit('activeChange', value);
|
||||
};
|
||||
const onMenuItemClick = ({ menuInfo, item }) => {
|
||||
const { key } = menuInfo;
|
||||
emit('menuClick', menuInfo);
|
||||
|
||||
switch (key) {
|
||||
case 'rename':
|
||||
item.editing = true;
|
||||
nextTick(() => {
|
||||
inputRef.value.focus();
|
||||
});
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
const changeItems = () => {
|
||||
emit('update:dataSource', localDataSource.value);
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.dataSource,
|
||||
(newItems) => {
|
||||
if (newItems) {
|
||||
localDataSource.value = cloneDeep(newItems);
|
||||
}
|
||||
},
|
||||
{ deep: true, immediate: true },
|
||||
);
|
||||
|
||||
const renderItems = () => {
|
||||
return localDataSource.value.map((item, index) => (
|
||||
<div
|
||||
class={`group flex justify-between cursor-pointer items-center p-8px h-40px rounded-8px hover:bg-#F2F3F5 ${
|
||||
activeKey.value === item.key ? 'bg-#F2F3F5' : ''
|
||||
}`}
|
||||
onClick={() => handleActiveChange(item.key)}
|
||||
>
|
||||
{item.editing ? (
|
||||
<Input
|
||||
ref={inputRef}
|
||||
v-model:value={item.label}
|
||||
onBlur={() => {
|
||||
item.editing = false;
|
||||
changeItems();
|
||||
emit('rename', item);
|
||||
}}
|
||||
onPressEnter={() => {
|
||||
item.editing = false;
|
||||
}}
|
||||
class="flex-1"
|
||||
/>
|
||||
) : (
|
||||
<TextoverTips context={item.label} class="flex-1" placement="bottom" />
|
||||
)}
|
||||
<Dropdown
|
||||
class="p-0"
|
||||
overlayClassName="xt-conversations-dropdown"
|
||||
placement="bottomRight"
|
||||
v-slots={{
|
||||
overlay: () => (
|
||||
<Menu onClick={(menuInfo: MenuProps) => onMenuItemClick({ menuInfo, item })}>
|
||||
{menuConfigs.value.map((menuItem) => (
|
||||
<Menu.Item key={menuItem.key} icon={menuItem.icon} class={`${menuItem.status || ''}`}>
|
||||
{menuItem.label}
|
||||
</Menu.Item>
|
||||
))}
|
||||
</Menu>
|
||||
),
|
||||
}}
|
||||
>
|
||||
<icon-more size={16} class="color-#737478 cursor-pointer ml-8px opacity-0 group-hover:opacity-100" />
|
||||
</Dropdown>
|
||||
</div>
|
||||
));
|
||||
};
|
||||
|
||||
return () => <div className="xt-conversations-container">{renderItems()}</div>;
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import './style.scss';
|
||||
</style>
|
||||
<style lang="scss">
|
||||
.xt-conversations-dropdown {
|
||||
.ant-dropdown-menu {
|
||||
padding: 4px 0;
|
||||
.ant-dropdown-menu-item {
|
||||
padding: 0 12px;
|
||||
min-width: 124px;
|
||||
height: 36px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
&:hover {
|
||||
background: var(--BG-200, #f2f3f5);
|
||||
}
|
||||
&.danger {
|
||||
color: var(--RED-600, #f64b31);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
13
src/components/xt-chat/conversations/style.scss
Normal file
13
src/components/xt-chat/conversations/style.scss
Normal file
@ -0,0 +1,13 @@
|
||||
.xt-conversations-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
:deep(.overflow-text) {
|
||||
color: var(--Text-1, #211f24);
|
||||
font-family: $font-family-regular;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 22px;
|
||||
}
|
||||
}
|
||||
@ -27,13 +27,16 @@ const showSider = computed(() => {
|
||||
return !route.meta?.hideSidebar;
|
||||
});
|
||||
|
||||
const isHomeRoute = computed(() => {
|
||||
return route.name === 'Home';
|
||||
const layoutPageClass = computed(() => {
|
||||
if (!showSider.value) {
|
||||
return 'pb-8px pr-8px';
|
||||
}
|
||||
return 'pb-24px pr-24px';
|
||||
});
|
||||
|
||||
const layoutPageClass = computed(() => {
|
||||
return isHomeRoute.value ? 'pb-8px pr-8px' : 'pb-24px pr-24px'
|
||||
})
|
||||
const siderWidth = computed(() => {
|
||||
return showSider.value ? sidebarStore.sidebarWidth : 0;
|
||||
});
|
||||
|
||||
const collapsed = computed(() => {
|
||||
return sidebarStore.menuCollapse;
|
||||
@ -53,7 +56,6 @@ const checkHasInviteCode = () => {
|
||||
joinModalRef.value?.getEnterprise?.();
|
||||
}
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -66,7 +68,7 @@ const checkHasInviteCode = () => {
|
||||
<Layout.Sider
|
||||
v-if="showSider"
|
||||
v-model="collapsed"
|
||||
:width="sidebarStore.sidebarWidth"
|
||||
:width="siderWidth"
|
||||
collapsible
|
||||
trigger
|
||||
@collapse="setCollapsed"
|
||||
@ -74,18 +76,18 @@ const checkHasInviteCode = () => {
|
||||
>
|
||||
<SiderBar />
|
||||
</Layout.Sider>
|
||||
<Layout.Content
|
||||
<Layout
|
||||
class="layout-content"
|
||||
:style="{
|
||||
paddingLeft: sidebarStore.sidebarWidth + 'px',
|
||||
paddingLeft: `${siderWidth}px`,
|
||||
}"
|
||||
>
|
||||
<div :class="layoutPageClass">
|
||||
<Layout.Content :class="layoutPageClass">
|
||||
<layout-page />
|
||||
</div>
|
||||
</Layout.Content>
|
||||
</Layout>
|
||||
</Layout>
|
||||
</Layout>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@ -102,7 +104,7 @@ const checkHasInviteCode = () => {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 9999;
|
||||
z-index: 999;
|
||||
width: 100%;
|
||||
}
|
||||
.layout-content-wrap {
|
||||
@ -118,7 +120,7 @@ const checkHasInviteCode = () => {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 9999;
|
||||
z-index: 999;
|
||||
height: 100%;
|
||||
transition: all 0.2s cubic-bezier(0.34, 0.69, 0.1, 1);
|
||||
.ant-layout-sider-trigger {
|
||||
|
||||
@ -1,12 +1,14 @@
|
||||
<script lang="jsx">
|
||||
import { Sender } from 'ant-design-x-vue';
|
||||
import { Input } from 'ant-design-vue';
|
||||
import { handleUserHome } from '@/utils/user.ts';
|
||||
|
||||
export default {
|
||||
setup(props, { emit, expose }) {
|
||||
const keyWord = ref('');
|
||||
|
||||
const handleSearch = () => {
|
||||
console.log('handleSearch', keyWord.value);
|
||||
handleUserHome({ keyWord: keyWord.value });
|
||||
keyWord.value = '';
|
||||
};
|
||||
return () => (
|
||||
<div class="middle-wrap h-100% flex-1 flex items-center justify-center px-24px">
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<img src="@/assets/img/icon-logo.png" alt="" width="96" height="24" />
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<MiddleSide />
|
||||
<MiddleSide v-if="!isHomeRoute" />
|
||||
</div>
|
||||
<RightSide :isAgentRoute="isAgentRoute" v-if="userStore.isLogin" />
|
||||
</div>
|
||||
@ -24,6 +24,10 @@ const userStore = useUserStore();
|
||||
const isAgentRoute = computed(() => {
|
||||
return route.meta?.isAgentRoute;
|
||||
});
|
||||
|
||||
const isHomeRoute = computed(() => {
|
||||
return route.name === 'Home';
|
||||
});
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.navbar-wrap {
|
||||
|
||||
20
src/stores/modules/share-data/index.ts
Normal file
20
src/stores/modules/share-data/index.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { defineStore } from 'pinia';
|
||||
|
||||
interface SharedDataState {
|
||||
routeParams: Record<string, any> | null;
|
||||
}
|
||||
|
||||
export const useSharedDataStore = defineStore('sharedData', {
|
||||
state: (): SharedDataState => ({
|
||||
routeParams: null,
|
||||
}),
|
||||
|
||||
actions: {
|
||||
setRouteParams(params: Record<string, any>) {
|
||||
this.routeParams = params;
|
||||
},
|
||||
clearRouteParams() {
|
||||
this.routeParams = null;
|
||||
},
|
||||
},
|
||||
});
|
||||
@ -1,7 +1,3 @@
|
||||
/*
|
||||
* @Author: RenXiaoDong
|
||||
* @Date: 2025-06-19 01:45:53
|
||||
*/
|
||||
import { defineStore } from 'pinia';
|
||||
import type { TabBarState, TagProps, RouteLocationNormalized } from './types';
|
||||
|
||||
|
||||
37
src/styles/components/chat-sender.scss
Normal file
37
src/styles/components/chat-sender.scss
Normal file
@ -0,0 +1,37 @@
|
||||
.ant-sender {
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--Border-2, #e6e6e8);
|
||||
background: var(--BG-White, #fff);
|
||||
box-shadow: none;
|
||||
transition: all 0.3s;
|
||||
&::after {
|
||||
display: none;
|
||||
}
|
||||
.ant-sender-content {
|
||||
height: 100%;
|
||||
padding: 14px 8px 8px 16px;
|
||||
.ant-input {
|
||||
font-family: $font-family-regular;
|
||||
color: #211f24;
|
||||
height: 100% !important;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 22px;
|
||||
&::placeholder {
|
||||
color: #939499;
|
||||
}
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
border: 1px solid var(--Brand-6, #6d4cfe);
|
||||
box-shadow: 0 8px 16px 0 rgba(109, 76, 254, 0.15);
|
||||
}
|
||||
&:focus-within {
|
||||
border-color: #6d4cfe;
|
||||
box-shadow: 0 8px 16px 0 rgba(109, 76, 254, 0.15);
|
||||
.ant-input {
|
||||
caret-color: #6d4cfe;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -10,3 +10,4 @@
|
||||
@import "./button.scss";
|
||||
@import "./steps.scss";
|
||||
@import "./form.scss";
|
||||
@import "./chat-sender.scss";
|
||||
|
||||
@ -7,6 +7,7 @@ import router from '@/router';
|
||||
import { useUserStore } from '@/stores';
|
||||
import { useEnterpriseStore } from '@/stores/modules/enterprise';
|
||||
import { useSidebarStore } from '@/stores/modules/side-bar';
|
||||
import { useSharedDataStore } from '@/stores/modules/share-data';
|
||||
|
||||
// 登录
|
||||
export function goUserLogin(query?: any) {
|
||||
@ -36,8 +37,12 @@ export async function handleUserLogin() {
|
||||
}
|
||||
|
||||
// 首页
|
||||
export function handleUserHome() {
|
||||
router.push({ name: 'Home' });
|
||||
export function handleUserHome(params?: any) {
|
||||
if (params) {
|
||||
const sharedDataStore = useSharedDataStore();
|
||||
sharedDataStore.setRouteParams(params);
|
||||
}
|
||||
router.push({ name: 'Home', params });
|
||||
}
|
||||
|
||||
// 登出处理
|
||||
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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>
|
||||
|
||||
@ -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% */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user