feat: chat
parent
e6a9dd0e4c
commit
e3f8a3a94b
|
@ -1,5 +1,6 @@
|
||||||
<script lang="tsx">
|
<script lang="tsx">
|
||||||
import { defineComponent, computed } from 'vue'
|
import { defineComponent, computed } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
import { Message } from '@/layout/components//Message'
|
import { Message } from '@/layout/components//Message'
|
||||||
import { Collapse } from '@/layout/components/Collapse'
|
import { Collapse } from '@/layout/components/Collapse'
|
||||||
import { UserInfo } from '@/layout/components/UserInfo'
|
import { UserInfo } from '@/layout/components/UserInfo'
|
||||||
|
@ -9,6 +10,7 @@ import { SizeDropdown } from '@/layout/components/SizeDropdown'
|
||||||
import { LocaleDropdown } from '@/layout/components/LocaleDropdown'
|
import { LocaleDropdown } from '@/layout/components/LocaleDropdown'
|
||||||
import { useAppStore } from '@/store/modules/app'
|
import { useAppStore } from '@/store/modules/app'
|
||||||
import { useDesign } from '@/hooks/web/useDesign'
|
import { useDesign } from '@/hooks/web/useDesign'
|
||||||
|
import { Icon } from '@/components/Icon'
|
||||||
|
|
||||||
const { getPrefixCls, variables } = useDesign()
|
const { getPrefixCls, variables } = useDesign()
|
||||||
|
|
||||||
|
@ -37,6 +39,10 @@ const locale = computed(() => appStore.getLocale)
|
||||||
// 消息图标
|
// 消息图标
|
||||||
const message = computed(() => appStore.getMessage)
|
const message = computed(() => appStore.getMessage)
|
||||||
|
|
||||||
|
const goToChat = () => {
|
||||||
|
window.open(window.location.host + '/chat', '_blank')
|
||||||
|
}
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'ToolHeader',
|
name: 'ToolHeader',
|
||||||
setup() {
|
setup() {
|
||||||
|
@ -58,6 +64,13 @@ export default defineComponent({
|
||||||
</div>
|
</div>
|
||||||
) : undefined}
|
) : undefined}
|
||||||
<div class="h-full flex items-center">
|
<div class="h-full flex items-center">
|
||||||
|
<div onClick={goToChat}>
|
||||||
|
<Icon
|
||||||
|
icon="ep:chat-dot-round"
|
||||||
|
color="var(--top-header-text-color)"
|
||||||
|
class="custom-hover"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
{screenfull.value ? (
|
{screenfull.value ? (
|
||||||
<Screenfull class="custom-hover" color="var(--top-header-text-color)"></Screenfull>
|
<Screenfull class="custom-hover" color="var(--top-header-text-color)"></Screenfull>
|
||||||
) : undefined}
|
) : undefined}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { Layout } from '@/utils/routerHelper'
|
import { Layout } from '@/utils/routerHelper'
|
||||||
|
import ChatPage from '../../views/chat/ChatPage/Index.vue'
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
/**
|
/**
|
||||||
|
@ -460,6 +461,12 @@ const remainingRouter: AppRouteRecordRaw[] = [
|
||||||
component: () => import('@/views/pay/cashier/index.vue')
|
component: () => import('@/views/pay/cashier/index.vue')
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/chat',
|
||||||
|
component: ChatPage,
|
||||||
|
name: 'chat',
|
||||||
|
meta: { hidden: false }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
<template>
|
||||||
|
<view class="flex h-full flex-1">
|
||||||
|
<ToolSection />
|
||||||
|
<Session />
|
||||||
|
<view class="flex w-full flex-col">
|
||||||
|
<ChatHeader />
|
||||||
|
<ChatMessage />
|
||||||
|
<InputSection />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
/**
|
||||||
|
* TODO: Replace me with comment, and tell the main subject of this page
|
||||||
|
*/
|
||||||
|
|
||||||
|
import ToolSection from '../components/ToolSection/Index.vue'
|
||||||
|
import Session from '../components/Session/Index.vue'
|
||||||
|
import ChatHeader from '../components/ChatHeader/Index.vue'
|
||||||
|
import ChatMessage from '../components/ChatMessage/Index.vue'
|
||||||
|
import InputSection from '../components/InputSection/index.vue'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define Data Structure of this page, then initialize it with reactive object
|
||||||
|
*/
|
||||||
|
interface State {}
|
||||||
|
|
||||||
|
defineOptions({ name: 'ChatPage' })
|
||||||
|
</script>
|
|
@ -0,0 +1,18 @@
|
||||||
|
<template>
|
||||||
|
<view
|
||||||
|
class="flex items-center w-full border-b-1 border-b-gray border-b-solid"
|
||||||
|
style="height: 60px"
|
||||||
|
>
|
||||||
|
<label class="text-black text-size-xl font-medium mx-4">{{
|
||||||
|
chatStore.currentSession?.name
|
||||||
|
}}</label>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { useChatStore } from '../../store/chatstore'
|
||||||
|
|
||||||
|
defineOptions({ name: 'ChatHeader' })
|
||||||
|
|
||||||
|
const chatStore = useChatStore()
|
||||||
|
</script>
|
|
@ -0,0 +1,21 @@
|
||||||
|
<template>
|
||||||
|
<view
|
||||||
|
class="flex flex-col items-start w-full border-b-1 border-b-gray border-b-solid flex-1 border-b-1 border-b-gray border-b-solid py-2"
|
||||||
|
>
|
||||||
|
<template v-for="item in chatStore.currentSession?.msgList">
|
||||||
|
<TextMessage v-if="item.messageType === MessageType.TEXT" :key="item.id" :message="item" />
|
||||||
|
<ImageMessage v-if="item.messageType === MessageType.IMAGE" :key="item.id" :message="item" />
|
||||||
|
</template>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { useChatStore } from '../../store/chatstore'
|
||||||
|
import TextMessage from '@/views/chat/components/Message/TextMessage.vue'
|
||||||
|
import ImageMessage from '@/views/chat/components/Message/ImageMessage.vue'
|
||||||
|
import { MessageType } from '../../types/index.d.ts'
|
||||||
|
|
||||||
|
defineOptions({ name: 'ChatMessage' })
|
||||||
|
|
||||||
|
const chatStore = useChatStore()
|
||||||
|
</script>
|
|
@ -0,0 +1,58 @@
|
||||||
|
<template>
|
||||||
|
<view
|
||||||
|
class="flex flex-col items-center w-full border-b-1 border-b-gray border-b-solid"
|
||||||
|
style="height: 248px"
|
||||||
|
>
|
||||||
|
<view class="flex p-2 w-full" style="height: 20px">
|
||||||
|
<Icon icon="ep:apple" color="var(--top-header-text-color)" class="custom-hover" />
|
||||||
|
<Icon icon="ep:folder" color="var(--top-header-text-color)" class="custom-hover" />
|
||||||
|
<Icon icon="ep:chat-line-square" color="var(--top-header-text-color)" class="custom-hover" />
|
||||||
|
</view>
|
||||||
|
<ElInput
|
||||||
|
type="textarea"
|
||||||
|
class="h-full"
|
||||||
|
clearable
|
||||||
|
v-model="chatStore.inputText"
|
||||||
|
input-style="border: none !important; box-shadow: none !important"
|
||||||
|
:autosize="{ minRows: 10, maxRows: 11 }"
|
||||||
|
placeholder="Press Enter to send"
|
||||||
|
@keydown.enter="onEnter"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import TextMessage from '../../model/TextMessage'
|
||||||
|
import { useChatStore } from '../../store/chatstore'
|
||||||
|
import { SendStatus, MessageRole, MessageType } from '../../types/index.d.ts'
|
||||||
|
|
||||||
|
defineOptions({ name: 'InputSection' })
|
||||||
|
|
||||||
|
const chatStore = useChatStore()
|
||||||
|
const onEnter = () => {
|
||||||
|
console.log('enter pressed')
|
||||||
|
const msg = createTextMessage(chatStore.inputText)
|
||||||
|
chatStore.addMessageToCurrentSession(msg)
|
||||||
|
chatStore.setInputText('')
|
||||||
|
}
|
||||||
|
|
||||||
|
const createTextMessage = (content: string): TextMessage => {
|
||||||
|
console.log('====>>>>', content)
|
||||||
|
const _localId = `${new Date().getTime()}`
|
||||||
|
// 部分信息从account信息里面获取
|
||||||
|
const msg = new TextMessage(
|
||||||
|
_localId,
|
||||||
|
'https://img0.baidu.com/it/u=1121635512,1294972039&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=889',
|
||||||
|
'Dylan May',
|
||||||
|
new Date().getTime(),
|
||||||
|
false,
|
||||||
|
content,
|
||||||
|
MessageRole.SELF,
|
||||||
|
SendStatus.SUCCESS,
|
||||||
|
MessageType.TEXT,
|
||||||
|
chatStore.currentSession?.id || ''
|
||||||
|
)
|
||||||
|
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,26 @@
|
||||||
|
<template>
|
||||||
|
<view
|
||||||
|
class="flex w-full"
|
||||||
|
:class="props.message.role === MessageRole.SELF ? 'flex-row-reverse' : 'flex-row'"
|
||||||
|
>
|
||||||
|
<el-avatar shape="square" size="default" class="mx-2" :src="props.message.avatar" />
|
||||||
|
<view class="flex flex-col">
|
||||||
|
<label class="text-xs text-gray-4 mb-1">{{ props.message.nickname }}</label>
|
||||||
|
<slot name="content"></slot>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { PropType } from 'vue'
|
||||||
|
import { MessageModelType, MessageRole } from '../../types/index.d.ts'
|
||||||
|
|
||||||
|
defineOptions({ name: 'BaseMessage' })
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
message: {
|
||||||
|
type: Object as PropType<MessageModelType>,
|
||||||
|
default: () => {}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
|
@ -0,0 +1,28 @@
|
||||||
|
<template>
|
||||||
|
<BaseMesageLayout>
|
||||||
|
<template #content>
|
||||||
|
<view>
|
||||||
|
<label>{{ props.message.content }}</label>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</BaseMesageLayout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { PropType } from 'vue'
|
||||||
|
import { useChatStore } from '../../store/chatstore'
|
||||||
|
import { onMounted } from 'vue'
|
||||||
|
import { MessageModelType } from '../../types'
|
||||||
|
import BaseMesageLayout from '../Message/BaseMessage.vue'
|
||||||
|
|
||||||
|
defineOptions({ name: 'ImageMessage' })
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
message: {
|
||||||
|
type: Object as PropType<MessageModelType>,
|
||||||
|
default: () => {}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const { sessionList, setCurrentConversation, setCurrentSessionIndex } = useChatStore()
|
||||||
|
</script>
|
|
@ -0,0 +1,27 @@
|
||||||
|
<template>
|
||||||
|
<BaseMesageLayout :message="props.message">
|
||||||
|
<template #content>
|
||||||
|
<view class="p-3 bg-gray-2 rounded">
|
||||||
|
<label>{{ props.message.content }}</label>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</BaseMesageLayout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { PropType } from 'vue'
|
||||||
|
import { useChatStore } from '../../store/chatstore'
|
||||||
|
import BaseMesageLayout from '../Message/BaseMessage.vue'
|
||||||
|
import { MessageModelType } from '../../types/index'
|
||||||
|
|
||||||
|
defineOptions({ name: 'TextMessage' })
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
message: {
|
||||||
|
type: Object as PropType<MessageModelType>,
|
||||||
|
default: () => {}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const { sessionList, setCurrentConversation, setCurrentSessionIndex } = useChatStore()
|
||||||
|
</script>
|
|
@ -0,0 +1,33 @@
|
||||||
|
<template>
|
||||||
|
<view class="flex flex-col items-center h-full py-2 b-1 b-gray b-solid" style="width: 248px">
|
||||||
|
<view class="flex flex-col w-full">
|
||||||
|
<SessionItem
|
||||||
|
v-for="(item, index) in sessionList"
|
||||||
|
:key="item.id"
|
||||||
|
:index="index"
|
||||||
|
:conversation="item"
|
||||||
|
@click="() => onSessionItemClick(index)"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import SessionItem from '../SessionItem/Index.vue'
|
||||||
|
import { useChatStore } from '../../store/chatstore'
|
||||||
|
import { onMounted } from 'vue'
|
||||||
|
|
||||||
|
defineOptions({ name: 'Session' })
|
||||||
|
|
||||||
|
const { sessionList, setCurrentConversation, setCurrentSessionIndex } = useChatStore()
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
// set default conversation
|
||||||
|
setCurrentConversation()
|
||||||
|
})
|
||||||
|
|
||||||
|
const onSessionItemClick = (index: number) => {
|
||||||
|
setCurrentSessionIndex(index)
|
||||||
|
setCurrentConversation()
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,47 @@
|
||||||
|
<template>
|
||||||
|
<view class="flex py-2 border-b-gray-3 border-b-solid items-center px-2" :class="bgColor()">
|
||||||
|
<el-avatar shape="square" size="default" class="mr-2" />
|
||||||
|
<view class="flex flex-col flex-1">
|
||||||
|
<label
|
||||||
|
class="text-black-c text-size-sm font-medium text-ellipsis text-nowrap"
|
||||||
|
:class="fontColor()"
|
||||||
|
>{{ props.conversation.name }}</label
|
||||||
|
>
|
||||||
|
<label class="text-gray-f text-size-sm text-ellipsis text-nowrap mr-1" :class="fontColor()">{{
|
||||||
|
props.conversation.description
|
||||||
|
}}</label>
|
||||||
|
</view>
|
||||||
|
<view class="flex items-end h-full">
|
||||||
|
<label class="text-gray-f text-size-sm text-nowrap" :class="fontColor()">{{
|
||||||
|
formatPast(new Date(props.conversation.updateTime))
|
||||||
|
}}</label>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { PropType } from 'vue'
|
||||||
|
import { ConversationModelType } from '../../types'
|
||||||
|
import { formatPast } from '@/utils/formatTime'
|
||||||
|
import { useChatStore } from '../../store/chatstore'
|
||||||
|
|
||||||
|
defineOptions({ name: 'SessionItem' })
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
conversation: {
|
||||||
|
type: Object as PropType<ConversationModelType>,
|
||||||
|
default: () => {}
|
||||||
|
},
|
||||||
|
index: Number
|
||||||
|
})
|
||||||
|
|
||||||
|
const chatStore = useChatStore()
|
||||||
|
|
||||||
|
const bgColor = () => {
|
||||||
|
return props.index === chatStore.currentSessionIndex ? 'bg-blue' : 'bg-white'
|
||||||
|
}
|
||||||
|
|
||||||
|
const fontColor = () => {
|
||||||
|
return props.index === chatStore.currentSessionIndex ? 'text-white' : 'text-gray-f'
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<template>
|
||||||
|
<view class="flex flex-col items-center bg-gray h-full py-2" style="width: 80px">
|
||||||
|
<el-avatar shape="square" />
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
defineOptions({ name: 'ToolSection' })
|
||||||
|
</script>
|
|
@ -0,0 +1,32 @@
|
||||||
|
import { MessageModelType } from '../types'
|
||||||
|
|
||||||
|
export default class BaseConversation {
|
||||||
|
public id: string
|
||||||
|
public avatar: string
|
||||||
|
public name: string
|
||||||
|
public description: string
|
||||||
|
public createTime: number
|
||||||
|
public updateTime: number
|
||||||
|
public unreadCount: number
|
||||||
|
public msgList: Array<MessageModelType>
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
id: string,
|
||||||
|
avatar: string,
|
||||||
|
name: string,
|
||||||
|
descrition: string,
|
||||||
|
createTime: number,
|
||||||
|
updateTime: number,
|
||||||
|
unreadCount: number,
|
||||||
|
msgList: Array<MessageModelType>
|
||||||
|
) {
|
||||||
|
this.id = id
|
||||||
|
this.avatar = avatar
|
||||||
|
this.name = name
|
||||||
|
this.description = descrition
|
||||||
|
this.createTime = createTime
|
||||||
|
this.updateTime = updateTime
|
||||||
|
this.unreadCount = unreadCount
|
||||||
|
this.msgList = msgList
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
import { MessageRole, MessageType, SendStatus } from '../types'
|
||||||
|
|
||||||
|
export default class BaseMessage {
|
||||||
|
id: string
|
||||||
|
avatar: string
|
||||||
|
nickname: string
|
||||||
|
createTime: number
|
||||||
|
isRead: boolean
|
||||||
|
role: MessageRole
|
||||||
|
sendStatus: SendStatus
|
||||||
|
messageType: MessageType
|
||||||
|
conversationId: string
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
id: string,
|
||||||
|
avatar: string,
|
||||||
|
nickname: string,
|
||||||
|
createTime: number,
|
||||||
|
isRead: boolean,
|
||||||
|
role: MessageRole,
|
||||||
|
sendStauts: SendStatus,
|
||||||
|
messageType: MessageType,
|
||||||
|
conversationId: string
|
||||||
|
) {
|
||||||
|
this.id = id
|
||||||
|
this.avatar = avatar
|
||||||
|
this.nickname = nickname
|
||||||
|
this.createTime = createTime
|
||||||
|
this.isRead = isRead
|
||||||
|
this.role = role
|
||||||
|
this.sendStatus = sendStauts
|
||||||
|
this.messageType = messageType
|
||||||
|
this.conversationId = conversationId
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
import BaseConversation from './BaseConversation'
|
||||||
|
import BaseMessage from './BaseMessage'
|
||||||
|
|
||||||
|
export class ChatConversation extends BaseConversation {
|
||||||
|
constructor(
|
||||||
|
id: string,
|
||||||
|
avatar: string,
|
||||||
|
name: string,
|
||||||
|
descrition: string,
|
||||||
|
createTime: number,
|
||||||
|
updateTime: number,
|
||||||
|
unreadCount: number,
|
||||||
|
msgList: Array<BaseMessage>
|
||||||
|
) {
|
||||||
|
super(id, avatar, name, descrition, createTime, updateTime, unreadCount, msgList)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { MessageRole, MessageType, SendStatus } from '../types'
|
||||||
|
import BaseMessage from './BaseMessage'
|
||||||
|
|
||||||
|
export default class ImageMessage extends BaseMessage {
|
||||||
|
content: string
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
id: string,
|
||||||
|
avatar: string,
|
||||||
|
nickname: string,
|
||||||
|
createTime: number,
|
||||||
|
isRead: boolean,
|
||||||
|
content: string,
|
||||||
|
role: MessageRole,
|
||||||
|
sendStatus: SendStatus,
|
||||||
|
messageType: MessageType,
|
||||||
|
conversationId: string
|
||||||
|
) {
|
||||||
|
super(id, avatar, nickname, createTime, isRead, role, sendStatus, messageType, conversationId)
|
||||||
|
this.content = content
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { MessageRole, MessageType, SendStatus } from '../types'
|
||||||
|
import BaseMessage from './BaseMessage'
|
||||||
|
|
||||||
|
export default class TextMessage extends BaseMessage {
|
||||||
|
content: string
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
id: string,
|
||||||
|
avatar: string,
|
||||||
|
nickname: string,
|
||||||
|
createTime: number,
|
||||||
|
isRead: boolean,
|
||||||
|
content: string,
|
||||||
|
role: MessageRole,
|
||||||
|
sendStatus: SendStatus,
|
||||||
|
messageType: MessageType,
|
||||||
|
conversationId: string
|
||||||
|
) {
|
||||||
|
super(id, avatar, nickname, createTime, isRead, role, sendStatus, messageType, conversationId)
|
||||||
|
this.content = content
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,135 @@
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
import BaseConversation from '../model/BaseConversation'
|
||||||
|
import BaseMessage from '../model/BaseMessage'
|
||||||
|
import { ConversationModelType, MessageRole, MessageType, SendStatus } from '../types/index.d.ts'
|
||||||
|
|
||||||
|
interface ChatStoreModel {
|
||||||
|
sessionList: Array<ConversationModelType>
|
||||||
|
currentSession: ConversationModelType | null
|
||||||
|
currentSessionIndex: number
|
||||||
|
inputText: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useChatStore = defineStore('chatStore', {
|
||||||
|
state: (): ChatStoreModel => ({
|
||||||
|
sessionList: [
|
||||||
|
{
|
||||||
|
id: '11111',
|
||||||
|
name: '张三',
|
||||||
|
avatar:
|
||||||
|
'https://img.zcool.cn/community/019fb65925bc32a801216a3ef77f7b.png@1280w_1l_2o_100sh.png',
|
||||||
|
description: 'sss',
|
||||||
|
createTime: 1693970987760,
|
||||||
|
updateTime: 1693970987760,
|
||||||
|
unreadCount: 1,
|
||||||
|
msgList: [
|
||||||
|
{
|
||||||
|
avatar:
|
||||||
|
'https://img0.baidu.com/it/u=1121635512,1294972039&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=889',
|
||||||
|
nickname: 'Dylan May',
|
||||||
|
id: '222221111',
|
||||||
|
isRead: false,
|
||||||
|
messageType: MessageType.TEXT,
|
||||||
|
sendStatus: SendStatus.SUCCESS,
|
||||||
|
role: MessageRole.SELF,
|
||||||
|
createTime: 1693970987760,
|
||||||
|
conversationId: '11111',
|
||||||
|
content: 'hello MUSK'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
avatar:
|
||||||
|
'https://img0.baidu.com/it/u=4211304696,1059959254&fm=253&fmt=auto&app=120&f=JPEG?w=800&h=1174',
|
||||||
|
nickname: 'Elon Musk',
|
||||||
|
id: '2222222222',
|
||||||
|
isRead: false,
|
||||||
|
messageType: MessageType.TEXT,
|
||||||
|
sendStatus: SendStatus.SUCCESS,
|
||||||
|
role: MessageRole.OTHER,
|
||||||
|
createTime: 1693970987760,
|
||||||
|
conversationId: '11111',
|
||||||
|
content: 'hello DYLAN'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '22222',
|
||||||
|
name: '搞笑的一家人',
|
||||||
|
avatar:
|
||||||
|
'https://img.zcool.cn/community/019fb65925bc32a801216a3ef77f7b.png@1280w_1l_2o_100sh.png',
|
||||||
|
description: '今天晚上吃啥',
|
||||||
|
createTime: 1693970987760,
|
||||||
|
updateTime: 1693970987760,
|
||||||
|
unreadCount: 1,
|
||||||
|
msgList: [
|
||||||
|
{
|
||||||
|
avatar:
|
||||||
|
'https://img.zcool.cn/community/019fb65925bc32a801216a3ef77f7b.png@1280w_1l_2o_100sh.png',
|
||||||
|
nickname: '小艳',
|
||||||
|
id: '22222',
|
||||||
|
isRead: false,
|
||||||
|
messageType: MessageType.TEXT,
|
||||||
|
sendStatus: SendStatus.SUCCESS,
|
||||||
|
role: MessageRole.OTHER,
|
||||||
|
createTime: 1693970987760,
|
||||||
|
conversationId: '22222',
|
||||||
|
content: 'what your name'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
currentSession: null,
|
||||||
|
currentSessionIndex: 0,
|
||||||
|
inputText: ''
|
||||||
|
}),
|
||||||
|
|
||||||
|
getters: {
|
||||||
|
getSessionList(state: ChatStoreModel): Array<ConversationModelType> {
|
||||||
|
return state.sessionList
|
||||||
|
},
|
||||||
|
|
||||||
|
getCurrentSession(state: ChatStoreModel): ConversationModelType | null {
|
||||||
|
return state.currentSession
|
||||||
|
},
|
||||||
|
|
||||||
|
getCurrentSessionIndex(state: ChatStoreModel): number {
|
||||||
|
return state.currentSessionIndex
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
addSession(session: BaseConversation) {
|
||||||
|
this.sessionList.push(session)
|
||||||
|
},
|
||||||
|
|
||||||
|
setCurrentConversation() {
|
||||||
|
this.currentSession = this.sessionList[this.currentSessionIndex]
|
||||||
|
},
|
||||||
|
|
||||||
|
setCurrentSessionIndex(index: number) {
|
||||||
|
this.currentSessionIndex = index
|
||||||
|
},
|
||||||
|
|
||||||
|
setInputText(content: string) {
|
||||||
|
this.inputText = content
|
||||||
|
},
|
||||||
|
|
||||||
|
addMessageToCurrentSession<T extends BaseMessage>(message: T): void {
|
||||||
|
this.currentSession?.msgList.push(message)
|
||||||
|
},
|
||||||
|
|
||||||
|
addMessageToSesstion<T extends BaseMessage>(message: T): void {
|
||||||
|
// get the conversation from list
|
||||||
|
const conversationIndex = this.sessionList.findIndex((item) => {
|
||||||
|
return item.id === message.conversationId
|
||||||
|
})
|
||||||
|
|
||||||
|
const msgConversation = this.sessionList[conversationIndex]
|
||||||
|
|
||||||
|
// add the message
|
||||||
|
msgConversation?.msgList.push(message)
|
||||||
|
|
||||||
|
// replace the old Conversation
|
||||||
|
this.sessionList.splice(conversationIndex, 1, msgConversation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
|
@ -0,0 +1,27 @@
|
||||||
|
import BaseConversation from '../model/BaseConversation'
|
||||||
|
import BaseMessage from '../model/BaseMessage'
|
||||||
|
import { ChatConversation } from '../model/ChatConversation'
|
||||||
|
import ImageMessage from '../model/ImageMessage'
|
||||||
|
import TextMessage from '../model/TextMessage'
|
||||||
|
|
||||||
|
export enum MessageRole {
|
||||||
|
SELF = 1,
|
||||||
|
SYSTEM = 2,
|
||||||
|
OTHER = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum SendStatus {
|
||||||
|
FAILURE = 1,
|
||||||
|
SENDING = 2,
|
||||||
|
SUCCESS = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum MessageType {
|
||||||
|
TEXT = 1,
|
||||||
|
IMAGE = 2,
|
||||||
|
AUDIO = 3,
|
||||||
|
SYSTEM = 4
|
||||||
|
}
|
||||||
|
|
||||||
|
export type MessageModelType = BaseMessage | TextMessage | ImageMessage
|
||||||
|
export type ConversationModelType = BaseConversation | ChatConversation
|
Loading…
Reference in New Issue