Files
im-demo-server/resources/views/chat.blade.php
lq c16edb77f1
Some checks failed
Tests / PHP 8.2 (push) Has been cancelled
Tests / PHP 8.3 (push) Has been cancelled
Tests / PHP 8.4 (push) Has been cancelled
图片发送、视频发送(写死的)
2025-06-27 07:53:13 +08:00

1029 lines
35 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>奶酪云聊天室</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.3.5/axios.min.js"></script>
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<!-- 添加 Vue.js CDN -->
<script src="https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/vue/2.6.14/vue.min.js"></script>
<style>
/* 原有样式保持不变 */
:root {
--bg-dark: #121212;
--bg-darker: #0a0a0a;
--bg-light: #1e1e1e;
--accent: #6a55fa;
--accent-hover: #7d6dfa;
--text-primary: #f0f0f0;
--text-secondary: #a0a0a0;
--success: #4ade80;
--warning: #fbbf24;
--error: #f87171;
--border: #2d2d2d;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
background: var(--bg-dark);
color: var(--text-primary);
height: 100vh;
overflow: hidden;
}
.connection-status {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 16px;
border-radius: 20px;
background: rgba(255, 255, 255, 0.05);
position: absolute;
top: 20px;
left: 50%;
transform: translateX(-50%);
font-size: 0.9rem;
backdrop-filter: blur(10px);
z-index: 5;
}
.status-indicator {
width: 10px;
height: 10px;
border-radius: 50%;
background: var(--text-secondary);
}
.status-indicator.connected {
background: var(--success);
}
.status-indicator.disconnected {
background: var(--error);
}
#chat-container {
height: 100vh;
display: flex;
flex-direction: column;
background: var(--bg-dark);
}
.chat-header {
padding: 1rem 1.5rem;
border-bottom: 1px solid var(--border);
background: rgba(30, 30, 30, 0.6);
backdrop-filter: blur(10px);
display: flex;
align-items: center;
justify-content: space-between;
position: sticky;
top: 0;
z-index: 2;
}
.chat-title {
display: flex;
align-items: center;
gap: 0.8rem;
}
.chat-title h2 {
font-size: 1.2rem;
font-weight: 600;
}
.user-avatar {
width: 38px;
height: 38px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
flex-shrink: 0;
}
#logout-btn {
background: rgba(255, 255, 255, 0.08);
border: none;
color: var(--text-secondary);
padding: 8px 16px;
border-radius: 6px;
font-size: 0.9rem;
cursor: pointer;
transition: all 0.3s;
}
#logout-btn:hover {
background: rgba(255, 255, 255, 0.12);
color: var(--text-primary);
}
.chat-content {
display: flex;
flex: 1;
height: calc(100vh - 140px);
}
.user-list {
width: 260px;
border-right: 1px solid var(--border);
background: var(--bg-darker);
overflow-y: auto;
padding: 1rem 0;
}
.section-title {
padding: 0 1.5rem 1rem;
color: var(--text-secondary);
font-size: 0.8rem;
text-transform: uppercase;
letter-spacing: 1px;
}
.user-item {
display: flex;
align-items: center;
gap: 0.8rem;
padding: 0.8rem 1.5rem;
cursor: pointer;
transition: all 0.2s;
}
.user-item:hover {
background: rgba(255, 255, 255, 0.05);
}
.user-item.me {
background: rgba(255, 255, 255, 0.05);
}
.user-item.active {
background: rgba(106, 85, 250, 0.15);
border-left: 3px solid var(--accent);
}
.user-item .status-indicator {
margin-left: auto;
}
.chat-area {
flex: 1;
display: flex;
flex-direction: column;
}
.messages-container {
flex: 1;
overflow-y: auto;
padding: 1.5rem;
display: flex;
flex-direction: column;
}
.message-container {
display: flex;
margin-bottom: 1.5rem;
animation: fadeIn 0.3s ease-out;
}
.message-container.sent {
align-self: flex-end;
flex-direction: row-reverse;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.message-avatar {
width: 36px;
height: 36px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
flex-shrink: 0;
margin: 0 12px;
}
.message-body {
max-width: 70%;
display: flex;
flex-direction: column;
}
.message-name {
font-size: 0.8rem;
font-weight: bold;
margin-bottom: 4px;
color: var(--text-secondary);
}
.message-bubble {
padding: 12px 16px;
border-radius: 12px;
position: relative;
}
.message-container.received .message-bubble {
background: var(--bg-light);
border-bottom-left-radius: 4px;
align-self: flex-start;
}
.message-container.sent .message-bubble {
background: var(--accent);
color: white;
border-bottom-right-radius: 4px;
align-self: flex-end;
}
.message-info {
display: flex;
justify-content: flex-end;
margin-top: 5px;
}
.timestamp {
font-size: 0.7rem;
color: var(--text-secondary);
}
.message-container.sent .timestamp {
color: rgba(255, 255, 255, 0.7);
}
.message-content {
line-height: 1.5;
word-wrap: break-word;
font-size: 1rem;
}
.message-input-area {
padding: 1.5rem;
border-top: 1px solid var(--border);
background: rgba(30, 30, 30, 0.7);
position: relative;
}
.input-toolbar {
display: flex;
gap: 12px;
margin-bottom: 12px;
}
.toolbar-btn {
width: 36px;
height: 36px;
border-radius: 8px;
background: rgba(255, 255, 255, 0.07);
display: flex;
align-items: center;
justify-content: center;
color: var(--text-secondary);
font-size: 16px;
cursor: pointer;
transition: all 0.2s;
}
.toolbar-btn:hover {
background: rgba(255, 255, 255, 0.15);
color: var(--text-primary);
}
.input-container {
position: relative;
background: var(--bg-light);
border-radius: 12px;
display: flex;
padding: 4px;
}
#message-input {
flex: 1;
border: none;
background: transparent;
padding: 12px 16px;
color: var(--text-primary);
min-height: 50px;
max-height: 150px;
overflow-y: auto;
resize: none;
outline: none;
font-size: 1rem;
}
.input-actions {
display: flex;
align-items: center;
padding: 0 8px;
}
.emoji-btn {
width: 36px;
height: 36px;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
color: var(--text-secondary);
transition: all 0.3s;
}
.emoji-btn:hover {
background: rgba(255, 255, 255, 0.1);
color: var(--text-primary);
}
#send-btn {
padding: 8px 20px;
border-radius: 8px;
background: var(--accent);
color: white;
border: none;
font-weight: bold;
cursor: pointer;
transition: all 0.3s;
margin-left: 8px;
}
#send-btn:hover {
background: var(--accent-hover);
}
.emoji-picker {
position: absolute;
bottom: 70px;
right: 50px;
width: 280px;
height: 260px;
background: var(--bg-light);
border-radius: 12px;
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.5);
padding: 1rem;
overflow-y: auto;
display: none;
flex-wrap: wrap;
gap: 6px;
z-index: 10;
}
.emoji-picker.show {
display: flex;
}
.emoji-item {
font-size: 1.4rem;
width: 36px;
height: 36px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 6px;
cursor: pointer;
transition: all 0.2s;
}
.emoji-item:hover {
background: rgba(255, 255, 255, 0.1);
transform: scale(1.2);
}
.system-message {
align-self: center;
background: rgba(255, 255, 255, 0.1);
padding: 8px 16px;
border-radius: 8px;
font-size: 0.85rem;
color: var(--text-secondary);
margin: 10px 0;
text-align: center;
}
.no-messages {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
color: var(--text-secondary);
text-align: center;
}
.no-messages i {
font-size: 4rem;
margin-bottom: 1.5rem;
color: var(--accent);
opacity: 0.3;
}
/* 滚动条样式 */
::-webkit-scrollbar {
width: 6px;
height: 6px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: var(--bg-light);
border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--accent);
}
/* 语音录制按钮样式 */
#voice-btn {
transition: all 0.3s;
color: var(--accent);
}
#voice-btn.recording {
animation: pulse 1s infinite;
}
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.1); box-shadow: 0 0 10px var(--accent); }
100% { transform: scale(1); }
}
/* 新增样式:媒体消息样式 */
.media-message {
max-width: 300px;
margin: 5px 0;
border-radius: 8px;
overflow: hidden;
}
.media-message img {
max-width: 100%;
max-height: 300px;
display: block;
border-radius: 8px;
}
.media-message video {
max-width: 100%;
max-height: 300px;
display: block;
border-radius: 8px;
}
.upload-indicator {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 16px;
background: rgba(30, 30, 30, 0.8);
border-radius: 20px;
position: fixed;
top: 70px;
left: 50%;
transform: translateX(-50%);
z-index: 100;
backdrop-filter: blur(10px);
box-shadow: 0 4px 12px rgba(0,0,0,0.5);
}
</style>
</head>
<body>
<div id="app">
<!-- 上传状态指示器 -->
<div class="upload-indicator" v-if="uploadStatus.show">
<i :class="uploadStatus.icon" :style="{ color: uploadStatus.color }"></i>
<span>@{{ uploadStatus.message }}</span>
</div>
<!-- 连接状态提示 -->
<div class="connection-status">
<div class="status-indicator" :class="connectionStatus"></div>
<span id="status-text">@{{ statusText }}@{{ selectUsers.nick_name }}</span>
</div>
<!-- 聊天主界面 -->
<div id="chat-container">
<div class="chat-header">
<div class="chat-title">
<div class="user-avatar" id="user-avatar" :style="{ background: currentUser.avatarColor }">
@{{ currentUser.name.charAt(0).toUpperCase() }}
</div>
<h2 id="current-username">@{{ currentUser.name }} 的接诊室</h2>
</div>
<button id="logout-btn" @click="handleLogout">退出登录</button>
</div>
<div class="chat-content">
<div class="user-list">
<div class="section-title">用户列表 <span id="online-count">(@{{ users.length }})</span></div>
<div id="user-list-container">
<!-- 当前用户显示在顶部 -->
<div class="user-item me">
<div class="user-avatar" :style="{ background: currentUser.avatarColor }">
@{{ currentUser.name.charAt(0).toUpperCase() }}
</div>
<div class="user-name">@{{ currentUser.name }} ()</div>
<div class="status-indicator connected"></div>
</div>
<!-- 其他用户列表 -->
<div class="user-item"
v-for="user in users"
:key="user.id"
v-if="user.id != currentUser.id"
@click="selectUser(user)"
:class="{
active: selectUsers.id === user.id
}"
>
<div class="user-avatar" :style="{ background: user.avatar || '#6a55fa' }">
@{{ user.nick_name.charAt(0).toUpperCase() }}
</div>
<div class="user-name">@{{ user.nick_name }}</div>
<div class="status-indicator" :class="{ connected: user.is_uid_online === true }"></div>
</div>
</div>
</div>
<div class="chat-area">
<div class="messages-container" id="messages-container">
<div class="no-messages" v-if="messages.length === 0">
<i class="fas fa-comment-alt"></i>
<p>开始聊天吧!您发送的消息将在这里显示</p>
</div>
<!-- 聊天消息 -->
<div class="message-container" :class="msg.type" v-for="msg in messages" :key="msg.timestamp">
<div class="message-avatar" :style="{ background: msg.avatarColor }">
@{{ msg.name.charAt(0).toUpperCase() }}
</div>
<div class="message-body">
<div class="message-name">@{{ msg.name }}</div>
<div class="message-bubble">
<!-- 文本消息 -->
<div class="message-content" v-if="msg.messageType === 'text'">
@{{ msg.text }}
</div>
<!-- 图片消息 -->
<div class="media-message" v-else-if="msg.messageType === 'image'">
<img :src="msg.text" alt="Image">
</div>
<!-- 视频消息 -->
<div class="media-message" v-else-if="msg.messageType === 'video'">
<video :src="msg.text" controls></video>
</div>
</div>
<div class="message-info">
<span class="timestamp">@{{ formatTime(msg.timestamp) }}</span>
</div>
</div>
</div>
</div>
<div class="message-input-area">
<!-- 工具栏 -->
<div class="input-toolbar">
<div class="toolbar-btn" id="image-btn" @click="showImageUpload">
<i class="fas fa-image"></i>
</div>
<div class="toolbar-btn" id="voice-btn" :class="{ recording: isRecording }" @click="toggleVoiceRecording">
<i :class="isRecording ? 'fas fa-square' : 'fas fa-microphone'"></i>
</div>
<div class="toolbar-btn" id="attach-btn" @click="showAttachmentUpload">
<i class="fas fa-paperclip"></i>
</div>
</div>
<div class="input-container">
<textarea id="message-input" v-model="messageInput" placeholder="输入消息..."
autocomplete="off" @keydown.enter.exact.prevent="sendChatMessage"></textarea>
<div class="input-actions">
<div class="emoji-btn" id="emoji-btn" @click="toggleEmojiPicker">
<i class="far fa-smile"></i>
</div>
<button id="send-btn" @click="sendChatMessage">发送</button>
</div>
</div>
<!-- Emoji选择器 -->
<div class="emoji-picker" :class="{ show: showEmojiPicker }" id="emoji-picker">
<div class="emoji-item" v-for="(emoji, index) in emojis" :key="index" @click="addEmoji(emoji)">
@{{ emoji }}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
// 常见的emoji
const EMOJIS = [
'😀', '😃', '😄', '😁', '😆', '😅', '😂', '🤣',
'😊', '😇', '🙂', '🙃', '😉', '😌', '😍', '🥰',
'😘', '😗', '😋', '😛', '😜', '🤪', '😝', '🤑',
'🤗', '🤭', '🤫', '🤔', '🤐', '🤨', '😐', '😑',
'😶', '😏', '😒', '🙄', '😬', '🤥', '😲', '😮',
'😦', '😧', '😳', '😵', '😖', '😫', '😩', '🥺',
'😢', '😭', '😤', '😠', '😡', '🤬', '🤯', '😳',
'🥵', '🥶', '😨', '😰', '😥', '😓', '🤗', '🤔',
'🫣', '🤭', '🤫', '🫢', '🫠', '😶', '‍🌫', '🌫️', '😐', '😑',
'🙈', '🙉', '🙊', '❤️', '💛', '💚', '💙', '💜',
'💔', '💋', '💯', '💢', '💥', '💫', '💦', '💨',
'👍', '👎', '👌', '✌️', '🤞', '🤟', '🤘', '🤙',
'👋', '🤚', '🖐️', '✋', '🖖', '👏', '🙌', '👐',
'🤲', '🤝', '🙏', '💪', '🦾', '🦿', '🦵', '🦶'
];
// 头像颜色
const AVATAR_COLORS = [
'#6a55fa', '#f87171', '#4ade80', '#fbbf24',
'#60a5fa', '#c084fc', '#fb923c', '#34d399'
];
// 模拟上传的媒体URL
const MOCK_IMAGE_URL = 'http://d-jy.nailaoyun.cn/storage/image//20250509/e2e107d3776542eea1c454d84e9bff0c.png';
const MOCK_VIDEO_URL = 'http://d-jy.nailaoyun.cn/storage/video//20250327/2cc1abf9bd69410ce7c69660daf54260.mp4';
new Vue({
el: '#app',
data: {
currentUser: {
id: '',
name: '',
username: '',
avatarColor: ''
},
selectUsers: [],
users: [],
messages: [],
messageInput: '',
token: '',
showEmojiPicker: false,
emojis: EMOJIS,
isRecording: false,
socket: null,
statusText: '未连接',
connectionStatus: '',
serverUrl: "{{ config('gateway.ws_address') }}",
uploadStatus: {
show: false,
message: '',
icon: '',
color: '#ffffff'
}
},
created() {
this.token = sessionStorage.getItem('token');
this.initializeUser();
this.connectWebSocket();
let selectUserLocalStorage = localStorage.getItem('selectUser')
if (selectUserLocalStorage) {
this.selectUser(JSON.parse(selectUserLocalStorage))
}
},
methods: {
initializeUser() {
const storedUser = sessionStorage.getItem('currentUser');
if (!storedUser) {
window.location.href = '/login';
return;
}
const userData = JSON.parse(storedUser);
this.currentUser.id = userData.id;
this.currentUser.username = userData.username;
this.currentUser.name = userData.name;
// 为用户生成头像颜色
this.currentUser.avatarColor = userData.avatarColor;
},
connectWebSocket() {
this.updateStatus('连接中...', 'connecting');
this.socket = new WebSocket(this.serverUrl);
this.socket.onopen = () => {
this.updateStatus('已连接', 'connected');
// 发送登录信息
this.socket.send(JSON.stringify({
type: 'login',
userId: this.currentUser.id,
userName: this.currentUser.name,
avatarColor: this.currentUser.avatarColor
}));
};
this.socket.onmessage = (event) => {
try {
const message = JSON.parse(event.data);
this.handleIncomingMessage(message);
} catch (e) {
console.error('消息解析错误:', e);
}
};
this.socket.onerror = (error) => {
console.error('WebSocket错误:', error);
this.updateStatus('连接出错', 'error');
};
this.socket.onclose = () => {
this.updateStatus('连接已关闭', 'disconnected');
};
},
handleIncomingMessage(message) {
switch(message.type) {
case 'system':
// this.addSystemMessage(message.content);
break;
case 'login_success':
this.handleLoginSuccess(message);
break;
case 'chat':
this.addMessage({
userId: message.userId,
name: message.userName,
avatarColor: message.avatarColor,
text: message.content,
timestamp: new Date(message.timestamp),
type: message.userId === this.currentUser.id ? 'sent' : 'received',
messageType: 'text' // 默认文本类型
});
break;
case 'user_list':
this.updateUserList(message.users);
break;
default:
console.log('未知消息类型:', message);
}
},
handleLoginSuccess(message) {
let token = sessionStorage.getItem('token');
axios.post('/api/b', {
client_id: message.client_id,
user_id: token
}).then(response => {
console.log('请求成功:', response.data);
}).catch(error => {
console.error('请求出错:', error);
});
this.addSystemMessage(message.content);
},
sendChatMessage() {
const text = this.messageInput.trim();
if (!text) return;
const message = {
type: 'chat',
userId: this.currentUser.id,
userName: this.currentUser.name,
avatarColor: this.currentUser.avatarColor,
content: text,
timestamp: Date.now(),
messageType: 'text' // 文本消息
};
let token = sessionStorage.getItem('token');
if (this.socket && this.socket.readyState === WebSocket.OPEN) {
axios.post('/api/im/send-message', {
message_type: 0,
data: message,
to_user_id: this.selectUsers.id,
chat_room_id: this.selectUsers.chat_room_id
}, {
headers: {
'token': `${token}`,
'Content-Type': 'application/json'
}
})
.then(response => {
console.log('请求成功:', response.data);
let res = response.data;
if (res.code === 0) {
// 添加消息到UI自己的消息
this.addMessage({
userId: this.currentUser.id,
name: this.currentUser.name,
avatarColor: this.currentUser.avatarColor,
text: text,
timestamp: new Date(),
type: 'sent',
messageType: 'text'
});
// 清空输入框
this.messageInput = '';
}
})
.catch(error => {
console.error('请求出错:', error);
});
}
},
updateStatus(text, status) {
this.statusText = text;
this.connectionStatus = status === 'connected' ? 'connected' : '';
},
addSystemMessage(text) {
// this.messages.push({
// content: text,
// timestamp: new Date()
// });
// this.scrollToBottom();
},
addMessage(msg) {
this.messages.push(msg);
this.scrollToBottom();
},
updateUserList(users) {
console.log('更新用户列表:', users);
let token = sessionStorage.getItem('token');
axios.get('/api/user/user-list', {
headers: {
'token': `${token}`,
'Content-Type': 'application/json'
}
})
.then(response => {
console.log('请求成功:', response.data);
let res = response.data;
if (res.code === 0) {
this.users = res.result;
}
})
.catch(error => {
console.error('请求出错:', error);
});
},
formatTime(date) {
if (!(date instanceof Date)) {
date = new Date(date);
}
const hours = date.getHours().toString().padStart(2, '0');
const minutes = date.getMinutes().toString().padStart(2, '0');
return `${hours}:${minutes}`;
},
scrollToBottom() {
this.$nextTick(() => {
const container = document.getElementById('messages-container');
container.scrollTop = container.scrollHeight;
});
},
handleLogout() {
if (this.socket && this.socket.readyState === WebSocket.OPEN) {
this.socket.close();
}
sessionStorage.removeItem('currentUser');
window.location.href = '/login';
},
toggleVoiceRecording() {
if (!this.isRecording) {
// 开始录制
this.isRecording = true;
document.getElementById('voice-btn').style.backgroundColor = 'rgba(248, 113, 113, 0.2)';
// 模拟3秒后停止录制
setTimeout(() => {
this.isRecording = false;
document.getElementById('voice-btn').style.backgroundColor = '';
}, 3000);
} else {
// 停止录制
this.isRecording = false;
document.getElementById('voice-btn').style.backgroundColor = '';
}
},
toggleEmojiPicker() {
this.showEmojiPicker = !this.showEmojiPicker;
},
addEmoji(emoji) {
this.messageInput += emoji;
this.showEmojiPicker = false;
},
selectUser(user) {
localStorage.setItem('selectUser', JSON.stringify(user));
console.log('Selected user:', user);
// 这里可以添加选择用户后的逻辑
this.selectUsers = user;
this.messages = [];
axios.get('/api/im/get-message-by-chat-room-id', {
params: {
chat_room_id: user.chat_room_id
},
headers: {
'token': `${this.token}`,
'Content-Type': 'application/json'
}
})
.then(response => {
console.log('请求成功:', response.data);
let res = response.data;
let result = res.result;
if (res.code === 0) {
result.forEach(item => {
this.addMessage({
userId: item.userId,
name: item.nick_name,
avatarColor: item.avatar,
text: item.content,
timestamp: item.timestamp,
type: item.type,
messageType: 'text' // 默认为文本类型
});
});
}
})
},
// 显示图片上传状态
showUploadStatus(message, icon, color) {
this.uploadStatus = {
show: true,
message: message,
icon: icon,
color: color
};
// 3秒后自动隐藏
setTimeout(() => {
this.uploadStatus.show = false;
}, 3000);
},
// 模拟图片上传功能
showImageUpload() {
// 显示上传状态
this.showUploadStatus('图片上传中...', 'fas fa-spinner fa-spin', '#4ade80');
// 模拟上传过程
setTimeout(() => {
// 上传成功
this.showUploadStatus('图片上传成功', 'fas fa-check-circle', '#4ade80');
// 添加到消息列表
this.addMessage({
userId: this.currentUser.id,
name: this.currentUser.name,
avatarColor: this.currentUser.avatarColor,
text: MOCK_IMAGE_URL,
timestamp: new Date(),
type: 'sent',
messageType: 'image' // 图片类型
});
// 实际开发中应通过API发送到服务器
}, 2000);
},
// 模拟视频上传功能
showAttachmentUpload() {
// 显示上传状态
this.showUploadStatus('视频上传中...', 'fas fa-spinner fa-spin', '#60a5fa');
// 模拟上传过程
setTimeout(() => {
// 上传成功
this.showUploadStatus('视频上传成功', 'fas fa-check-circle', '#60a5fa');
// 添加到消息列表
this.addMessage({
userId: this.currentUser.id,
name: this.currentUser.name,
avatarColor: this.currentUser.avatarColor,
text: MOCK_VIDEO_URL,
timestamp: new Date(),
type: 'sent',
messageType: 'video' // 视频类型
});
// 实际开发中应通过API发送到服务器
}, 2000);
}
}
});
</script>
</body>
</html>