合并linfangfang

linfangfang_branch
psnci6hgk 2 months ago
parent 13867065d3
commit 37dc01141f

@ -1,31 +1,272 @@
<template>
<div class="phone-page">
<h2>手机</h2>
<el-alert title="这是独立的手机页面(也可在社区中以弹窗形式使用)" type="info" show-icon />
<div class="widget">
<PhoneWidget v-model="open" />
<el-button type="primary" @click="open = true">打开手机</el-button>
<el-dialog
v-model="modelValueLocal"
title="手机通信"
width="900px"
destroy-on-close
append-to-body
>
<div class="chat-layout">
<div class="left">
<div class="left-header">
<img class="me-avatar" :src="selfAvatar" alt="me" />
<div class="me-meta">
<div class="me-name"></div>
<div class="me-sub">在线</div>
</div>
<el-button size="small" type="info" @click="showMyProfile" style="margin-left:auto;">我的资料</el-button>
</div>
<el-tabs v-model="leftTab" class="left-tabs">
<el-tab-pane label="聊天" name="chat" />
<el-tab-pane label="联系人" name="contacts" />
</el-tabs>
<ContactsList v-model="activeContactId" :contacts="contacts" :simple-mode="true" v-show="leftTab === 'contacts'" />
<div v-show="leftTab === 'chat'" class="chat-list">
<div
v-for="c in contacts"
:key="c.id"
class="contact-item"
:class="{ active: c.id === activeContactId }"
@click="selectContact(c.id)"
>
<img class="avatar" :src="c.avatar" alt="avatar" />
<div class="meta">
<div class="name">{{ c.name }}</div>
<div class="last">{{ c.lastMessage || '...' }}</div>
</div>
<div class="time" v-if="c.lastTime">{{ formatTime(c.lastTime) }}</div>
<el-badge v-if="c.unread" :value="c.unread" class="unread" />
</div>
</div>
</div>
<div class="right">
<ChatWindow
:active-contact="activeContact"
v-model="activeMessages"
:self-id="selfId"
:self-avatar="selfAvatar"
@send="handleSend"
@open-info="showInfoDialog"
/>
</div>
</div>
</div>
<template #footer>
<el-button @click="close"></el-button>
</template>
<!-- OC信息弹窗 -->
<OCInfoDialog
v-model="infoDialogVisible"
:oc="infoDialogOC"
/>
<!-- 我的资料弹窗 -->
<UserCenterDialog v-model="myProfileVisible" />
</el-dialog>
</template>
<script setup>
import { ref } from 'vue'
import PhoneWidget from './PhoneWidget.vue'
import { computed, ref, watch } from 'vue'
import ContactsList from './ContactsList.vue'
import ChatWindow from './ChatWindow.vue'
import { ocList } from '../stores/ocStore'
import { currentUser } from '../stores/userStore'
const open = ref(true)
import OCInfoDialog from './OCInfoDialog.vue'
import UserCenterDialog from './UserCenterDialog.vue'
const props = defineProps({
modelValue: {
type: Boolean,
default: false
}
})
const emit = defineEmits(['update:modelValue'])
const modelValueLocal = computed({
get: () => props.modelValue,
set: value => emit('update:modelValue', value)
})
// 使OC
const selfId = currentUser.value.username || 'me'
const selfAvatar = currentUser.value.avatar || 'https://avatars.githubusercontent.com/u/9919?v=4'
const contacts = ocList
// OC
const messagesByContact = ref({})
const activeContactId = ref(contacts.value.length > 0 ? contacts.value[0].id : '')
const activeContact = computed(() => contacts.value.find(c => c.id === activeContactId.value) || null)
// OC
const infoDialogVisible = ref(false)
const infoDialogOC = computed(() => activeContact.value)
const showInfoDialog = () => {
//
if (!activeContact.value && contacts.value.length > 0) {
activeContactId.value = contacts.value[0].id
}
if (activeContact.value) {
infoDialogVisible.value = true
} else {
ElMessage.warning('暂无可查看的OC信息')
}
}
//
const myProfileVisible = ref(false)
const showMyProfile = () => {
myProfileVisible.value = true
}
const leftTab = ref('chat')
const activeMessages = computed({
get: () => messagesByContact.value[activeContactId.value] || [],
set: val => {
messagesByContact.value[activeContactId.value] = val
}
})
const close = () => {
modelValueLocal.value = false
}
const selectContact = (contactId) => {
activeContactId.value = contactId
}
const formatTime = (ts) => {
try {
const d = new Date(ts)
const h = String(d.getHours()).padStart(2, '0')
const m = String(d.getMinutes()).padStart(2, '0')
return `${h}:${m}`
} catch (e) {
return ''
}
}
const handleSend = async ({ contact, message }) => {
const idx = contacts.value.findIndex(c => c.id === contact.id)
if (idx !== -1) {
contacts.value[idx] = {
...contacts.value[idx],
lastMessage: message.text,
lastTime: message.timestamp
}
}
// AIChatWindowAI
}
// clear unread when switching to a contact
watch(activeContactId, id => {
const i = contacts.value.findIndex(c => c.id === id)
if (i !== -1) {
contacts.value[i] = { ...contacts.value[i], unread: 0 }
}
})
</script>
<!-- OC信息弹窗 -->
<OCInfoDialog
v-model="infoDialogVisible"
:oc="infoDialogOC"
/>
<style scoped>
.phone-page {
.chat-layout {
display: flex;
flex-direction: column;
gap: 12px;
padding: 16px;
height: 600px;
background: #f5f7fa;
}
.left {
width: 280px;
height: 100%;
}
.widget {
margin-top: 8px;
.left-header {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 12px;
background: #fff;
border-bottom: 1px solid #ebeef5;
}
.me-avatar {
width: 32px;
height: 32px;
border-radius: 50%;
}
.me-name {
font-weight: 600;
}
.me-sub {
font-size: 12px;
color: #909399;
}
.left-tabs {
background: #fff;
border-bottom: 1px solid #ebeef5;
}
.right {
flex: 1;
height: 100%;
}
.chat-list {
height: 100%;
overflow-y: auto;
background: #fff;
}
.contact-item {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 12px;
cursor: pointer;
border-bottom: 1px solid #f0f0f0;
}
.contact-item:hover {
background: #f5f7fa;
}
.contact-item.active {
background: #ecf5ff;
}
.avatar {
width: 36px;
height: 36px;
border-radius: 8px;
}
.meta {
flex: 1;
min-width: 0;
}
.name {
font-weight: 600;
font-size: 14px;
}
.last {
font-size: 12px;
color: #909399;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.time {
font-size: 12px;
color: #909399;
}
</style>

Loading…
Cancel
Save