微信修改
This commit is contained in:
@@ -0,0 +1,229 @@
|
||||
.page {
|
||||
min-height: 100vh;
|
||||
background: linear-gradient(180deg, #fff 0%, #f0f1f6 60%, #f0f1f6 100%);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.nav {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 176rpx;
|
||||
padding-top: 88rpx;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 24rpx;
|
||||
padding-right: 24rpx;
|
||||
box-sizing: border-box;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.nav-back {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.back-arrow {
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
border-left: 4rpx solid #222;
|
||||
border-bottom: 4rpx solid #222;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
flex: 1;
|
||||
font-size: 30rpx;
|
||||
font-weight: 600;
|
||||
color: #222;
|
||||
margin-left: 16rpx;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.nav-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
padding: 12rpx 20rpx;
|
||||
background: rgba(255,255,255,0.9);
|
||||
border-radius: 32rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
.action-text {
|
||||
font-size: 26rpx;
|
||||
font-weight: 600;
|
||||
color: #173294;
|
||||
}
|
||||
|
||||
.meeting-btn {
|
||||
background: linear-gradient(90deg, #52c41a 0%, #73d13d 100%);
|
||||
}
|
||||
|
||||
.meeting-btn .action-text {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.chat-area {
|
||||
flex: 1;
|
||||
margin-top: 176rpx;
|
||||
padding: 24rpx;
|
||||
padding-bottom: 180rpx;
|
||||
}
|
||||
|
||||
.message-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.msg {
|
||||
display: flex;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.msg.ai {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.msg.user {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.message-row {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.other-row {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.self-row {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 72rpx;
|
||||
height: 72rpx;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(145deg, #e8f7ff 0%, #c5e4ff 100%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.self-avatar {
|
||||
background: linear-gradient(145deg, #e9f1ff 0%, #c5d9ff 100%);
|
||||
}
|
||||
|
||||
.avatar-text {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #173294;
|
||||
}
|
||||
|
||||
.message-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-width: 480rpx;
|
||||
}
|
||||
|
||||
.self-row .message-content {
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.sender-name {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.bubble {
|
||||
max-width: 480rpx;
|
||||
padding: 18rpx 20rpx;
|
||||
border-radius: 18rpx;
|
||||
font-size: 28rpx;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.other-bubble {
|
||||
background: #fff;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
.self-bubble {
|
||||
background: #e9f1ff;
|
||||
color: #173294;
|
||||
}
|
||||
|
||||
.message-text {
|
||||
font-size: 28rpx;
|
||||
line-height: 1.6;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.message-time {
|
||||
font-size: 22rpx;
|
||||
color: #999;
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
|
||||
.footer {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: #f0f1f6;
|
||||
padding: 20rpx 24rpx 40rpx;
|
||||
z-index: 50;
|
||||
}
|
||||
|
||||
.input-row {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: #fff;
|
||||
border-radius: 50rpx;
|
||||
padding: 10rpx 96rpx 10rpx 18rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.04);
|
||||
}
|
||||
|
||||
.chat-input {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
.send-btn {
|
||||
position: absolute;
|
||||
right: 12rpx;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
border-radius: 30rpx;
|
||||
border: 2rpx solid #8dbbff;
|
||||
background: #e9f1ff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.send-text {
|
||||
font-size: 24rpx;
|
||||
color: #4b87ff;
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
<template>
|
||||
<!-- #ifdef APP -->
|
||||
<scroll-view style="flex:1">
|
||||
<!-- #endif -->
|
||||
<view class="page">
|
||||
<!-- 自定义导航栏 -->
|
||||
<view class="nav" :style="{ paddingTop: headerPaddingTop + 'px', height: headerTotalHeight + 'px' }">
|
||||
<view class="nav-back" @tap="goBack">
|
||||
<text class="nav-back-icon">←</text>
|
||||
</view>
|
||||
<text class="nav-title">{{ roomName }}</text>
|
||||
<view class="nav-actions">
|
||||
<view class="action-btn" @tap="handleWorkcaseAction">
|
||||
<text class="action-text">{{ workcaseId ? '查看工单' : '创建工单' }}</text>
|
||||
</view>
|
||||
<view class="action-btn meeting-btn" @tap="startMeeting">
|
||||
<text class="action-text">发起会议</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 聊天消息区域 -->
|
||||
<scroll-view class="chat-area" scroll-y="true" :scroll-top="scrollTop"
|
||||
:style="{ marginTop: headerTotalHeight + 'px' }">
|
||||
<view class="message-list">
|
||||
<view class="message-item" v-for="(msg, index) in messages" :key="index"
|
||||
:class="msg.senderType === 'guest' ? 'self' : 'other'">
|
||||
<!-- 对方消息(左侧) -->
|
||||
<view class="message-row other-row" v-if="msg.senderType !== 'guest'">
|
||||
<view class="avatar">
|
||||
<text class="avatar-text">{{ msg.senderName?.charAt(0) || '客' }}</text>
|
||||
</view>
|
||||
<view class="message-content">
|
||||
<text class="sender-name">{{ msg.senderName || '客服' }}</text>
|
||||
<view class="bubble other-bubble">
|
||||
<text class="message-text">{{ msg.content }}</text>
|
||||
</view>
|
||||
<text class="message-time">{{ formatTime(msg.sendTime) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 自己消息(右侧) -->
|
||||
<view class="message-row self-row" v-else>
|
||||
<view class="message-content">
|
||||
<view class="bubble self-bubble">
|
||||
<text class="message-text">{{ msg.content }}</text>
|
||||
</view>
|
||||
<text class="message-time">{{ formatTime(msg.sendTime) }}</text>
|
||||
</view>
|
||||
<view class="avatar self-avatar">
|
||||
<text class="avatar-text">我</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 底部输入区 -->
|
||||
<view class="footer">
|
||||
<view class="input-row">
|
||||
<input class="chat-input" v-model="inputText" placeholder="输入消息..."
|
||||
@confirm="sendMessage" />
|
||||
<view class="send-btn" @tap="sendMessage">
|
||||
<text class="send-text">发送</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 工单创建弹窗 -->
|
||||
<WorkcaseCreator v-if="showWorkcaseCreator" :show="showWorkcaseCreator"
|
||||
@close="hideCreator" @success="onWorkcaseCreated" />
|
||||
</view>
|
||||
<!-- #ifdef APP -->
|
||||
</scroll-view>
|
||||
<!-- #endif -->
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, nextTick, onMounted } from 'vue'
|
||||
import WorkcaseCreator from '@/components/WorkcaseCreator/WorkcaseCreator.uvue'
|
||||
import type { ChatRoomMessageVO } from '@/types/workcase'
|
||||
|
||||
// 响应式数据
|
||||
const headerPaddingTop = ref<number>(44)
|
||||
const headerTotalHeight = ref<number>(88)
|
||||
const roomId = ref<string>('')
|
||||
const workcaseId = ref<string>('')
|
||||
const roomName = ref<string>('聊天室')
|
||||
const inputText = ref<string>('')
|
||||
const scrollTop = ref<number>(0)
|
||||
const showWorkcaseCreator = ref<boolean>(false)
|
||||
|
||||
// 消息列表
|
||||
const messages = ref<ChatRoomMessageVO[]>([
|
||||
{
|
||||
messageId: '1',
|
||||
roomId: 'room001',
|
||||
senderId: 'agent001',
|
||||
senderType: 'agent',
|
||||
senderName: '客服小张',
|
||||
content: '您好,我是客服小张,请问有什么可以帮助您的?',
|
||||
sendTime: '2024-12-17 16:00:00'
|
||||
},
|
||||
{
|
||||
messageId: '2',
|
||||
roomId: 'room001',
|
||||
senderId: 'guest001',
|
||||
senderType: 'guest',
|
||||
senderName: '李经理',
|
||||
content: '我们的设备出现了控制系统故障,无法正常启动',
|
||||
sendTime: '2024-12-17 16:02:00'
|
||||
},
|
||||
{
|
||||
messageId: '3',
|
||||
roomId: 'room001',
|
||||
senderId: 'agent001',
|
||||
senderType: 'agent',
|
||||
senderName: '客服小张',
|
||||
content: '好的,请问是哪个型号的设备?能否提供一下设备序列号?',
|
||||
sendTime: '2024-12-17 16:03:00'
|
||||
},
|
||||
{
|
||||
messageId: '4',
|
||||
roomId: 'room001',
|
||||
senderId: 'guest001',
|
||||
senderType: 'guest',
|
||||
senderName: '李经理',
|
||||
content: '型号是TH-500GF,序列号是TH20230501001',
|
||||
sendTime: '2024-12-17 16:05:00'
|
||||
},
|
||||
{
|
||||
messageId: '5',
|
||||
roomId: 'room001',
|
||||
senderId: 'agent001',
|
||||
senderType: 'agent',
|
||||
senderName: '客服小张',
|
||||
content: '好的,我已经记录了您的问题。建议您创建一个工单,我们会安排工程师尽快上门处理。',
|
||||
sendTime: '2024-12-17 16:08:00'
|
||||
}
|
||||
])
|
||||
|
||||
// 生命周期
|
||||
onMounted(() => {
|
||||
uni.getSystemInfo({
|
||||
success: (res) => {
|
||||
// #ifdef MP-WEIXIN
|
||||
try {
|
||||
const menuButtonInfo = uni.getMenuButtonBoundingClientRect()
|
||||
headerPaddingTop.value = menuButtonInfo.top
|
||||
headerTotalHeight.value = menuButtonInfo.bottom + 8
|
||||
} catch (e) {
|
||||
headerPaddingTop.value = res.statusBarHeight || 44
|
||||
headerTotalHeight.value = (res.statusBarHeight || 44) + 44
|
||||
}
|
||||
// #endif
|
||||
// #ifndef MP-WEIXIN
|
||||
headerPaddingTop.value = res.statusBarHeight || 44
|
||||
headerTotalHeight.value = (res.statusBarHeight || 44) + 44
|
||||
// #endif
|
||||
}
|
||||
})
|
||||
|
||||
// 获取页面参数
|
||||
const pages = getCurrentPages()
|
||||
const currentPage = pages[pages.length - 1] as any
|
||||
if (currentPage && currentPage.options) {
|
||||
roomId.value = currentPage.options.roomId || ''
|
||||
workcaseId.value = currentPage.options.workcaseId || ''
|
||||
}
|
||||
|
||||
loadChatRoom()
|
||||
scrollToBottom()
|
||||
})
|
||||
|
||||
// 加载聊天室
|
||||
function loadChatRoom() {
|
||||
console.log('加载聊天室:', roomId.value)
|
||||
// TODO: 调用 workcaseChatAPI.getChatRoomById() 获取聊天室信息
|
||||
// TODO: 调用 workcaseChatAPI.getChatMessagePage() 获取消息列表
|
||||
}
|
||||
|
||||
// 格式化时间
|
||||
function formatTime(time?: string): string {
|
||||
if (!time) return ''
|
||||
const date = new Date(time)
|
||||
return `${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`
|
||||
}
|
||||
|
||||
// 发送消息
|
||||
function sendMessage() {
|
||||
const text = inputText.value.trim()
|
||||
if (!text) return
|
||||
|
||||
const newMsg: ChatRoomMessageVO = {
|
||||
messageId: Date.now().toString(),
|
||||
roomId: roomId.value,
|
||||
senderId: 'guest001',
|
||||
senderType: 'guest',
|
||||
senderName: '我',
|
||||
content: text,
|
||||
sendTime: new Date().toISOString()
|
||||
}
|
||||
|
||||
messages.value.push(newMsg)
|
||||
inputText.value = ''
|
||||
|
||||
nextTick(() => {
|
||||
scrollToBottom()
|
||||
})
|
||||
|
||||
// TODO: 调用 workcaseChatAPI.sendMessage() 发送消息
|
||||
}
|
||||
|
||||
// 滚动到底部
|
||||
function scrollToBottom() {
|
||||
scrollTop.value = 999999
|
||||
}
|
||||
|
||||
// 处理工单操作
|
||||
function handleWorkcaseAction() {
|
||||
if (workcaseId.value) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/workcase/workcaseDetail/workcaseDetail?workcaseId=${workcaseId.value}`
|
||||
})
|
||||
} else {
|
||||
showWorkcaseCreator.value = true
|
||||
}
|
||||
}
|
||||
|
||||
// 隐藏工单创建器
|
||||
function hideCreator() {
|
||||
showWorkcaseCreator.value = false
|
||||
}
|
||||
|
||||
// 工单创建成功
|
||||
function onWorkcaseCreated(data: any) {
|
||||
hideCreator()
|
||||
workcaseId.value = data.workcaseId || 'new-workcase'
|
||||
uni.showToast({
|
||||
title: '工单创建成功',
|
||||
icon: 'success'
|
||||
})
|
||||
}
|
||||
|
||||
// 发起会议
|
||||
function startMeeting() {
|
||||
uni.navigateTo({
|
||||
url: `/pages/meeting/Meeting/Meeting?roomId=${roomId.value}&workcaseId=${workcaseId.value}`
|
||||
})
|
||||
}
|
||||
|
||||
// 返回上一页
|
||||
function goBack() {
|
||||
uni.navigateBack()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "./chatRoom.scss";
|
||||
</style>
|
||||
@@ -0,0 +1,229 @@
|
||||
.page {
|
||||
min-height: 100vh;
|
||||
background: #f4f5f7;
|
||||
}
|
||||
|
||||
.nav {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 176rpx;
|
||||
padding-top: 88rpx;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
padding-left: 24rpx;
|
||||
padding-right: 24rpx;
|
||||
box-sizing: border-box;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.nav-back {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.back-arrow {
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
border-left: 4rpx solid #222;
|
||||
border-bottom: 4rpx solid #222;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
font-size: 34rpx;
|
||||
font-weight: 600;
|
||||
color: #222;
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
padding-right: 174rpx;
|
||||
}
|
||||
|
||||
.nav-capsule {
|
||||
width: 174rpx;
|
||||
height: 64rpx;
|
||||
border-radius: 32rpx;
|
||||
}
|
||||
|
||||
.list {
|
||||
margin-top: 176rpx;
|
||||
padding: 20rpx 24rpx;
|
||||
padding-bottom: 60rpx;
|
||||
}
|
||||
|
||||
.room-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 24rpx;
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.room-avatar {
|
||||
width: 96rpx;
|
||||
height: 96rpx;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(145deg, #e8f7ff 0%, #c5e4ff 100%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.avatar-text {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
color: #173294;
|
||||
}
|
||||
|
||||
.room-info {
|
||||
flex: 1;
|
||||
margin-left: 20rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.room-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.room-name {
|
||||
font-size: 30rpx;
|
||||
font-weight: 600;
|
||||
color: #222;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.room-time {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
flex-shrink: 0;
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
|
||||
.room-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.last-message {
|
||||
font-size: 26rpx;
|
||||
color: #999;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.unread-badge {
|
||||
min-width: 36rpx;
|
||||
height: 36rpx;
|
||||
padding: 0 12rpx;
|
||||
background: #ff4d4f;
|
||||
border-radius: 18rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
|
||||
.badge-text {
|
||||
font-size: 22rpx;
|
||||
color: #fff;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.room-status {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
margin-left: 20rpx;
|
||||
padding: 8rpx 16rpx;
|
||||
border-radius: 8rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.status-dot {
|
||||
width: 12rpx;
|
||||
height: 12rpx;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.status-text {
|
||||
font-size: 22rpx;
|
||||
}
|
||||
|
||||
.status-active {
|
||||
background: #e7f7ea;
|
||||
}
|
||||
|
||||
.status-active .status-dot {
|
||||
background: #3abe59;
|
||||
}
|
||||
|
||||
.status-active .status-text {
|
||||
color: #3abe59;
|
||||
}
|
||||
|
||||
.status-waiting {
|
||||
background: #fff7e6;
|
||||
}
|
||||
|
||||
.status-waiting .status-dot {
|
||||
background: #faad14;
|
||||
}
|
||||
|
||||
.status-waiting .status-text {
|
||||
color: #faad14;
|
||||
}
|
||||
|
||||
.status-closed {
|
||||
background: #f0f0f0;
|
||||
}
|
||||
|
||||
.status-closed .status-dot {
|
||||
background: #999;
|
||||
}
|
||||
|
||||
.status-closed .status-text {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 160rpx 40rpx;
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
font-size: 96rpx;
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 32rpx;
|
||||
color: #222;
|
||||
font-weight: 500;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.empty-hint {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
<template>
|
||||
<!-- #ifdef APP -->
|
||||
<scroll-view style="flex:1">
|
||||
<!-- #endif -->
|
||||
<view class="page">
|
||||
<!-- 自定义导航栏 -->
|
||||
<view class="nav" :style="{ paddingTop: headerPaddingTop + 'px', height: headerTotalHeight + 'px' }">
|
||||
<view class="nav-back" @tap="goBack">
|
||||
<text class="nav-back-icon">←</text>
|
||||
</view>
|
||||
<text class="nav-title">我的聊天室</text>
|
||||
<view class="nav-capsule"></view>
|
||||
</view>
|
||||
|
||||
<!-- 聊天室列表 -->
|
||||
<scroll-view class="list" scroll-y="true" :style="{ marginTop: headerTotalHeight + 'px' }">
|
||||
<view class="room-card" v-for="(room, index) in chatRooms" :key="index" @tap="enterRoom(room)">
|
||||
<view class="room-avatar">
|
||||
<text class="avatar-text">{{ room.guestName?.charAt(0) || '客' }}</text>
|
||||
</view>
|
||||
<view class="room-info">
|
||||
<view class="room-header">
|
||||
<text class="room-name">{{ room.roomName || '聊天室' }}</text>
|
||||
<text class="room-time">{{ formatTime(room.lastMessageTime) }}</text>
|
||||
</view>
|
||||
<view class="room-footer">
|
||||
<text class="last-message">{{ room.lastMessage || '暂无消息' }}</text>
|
||||
<view class="unread-badge" v-if="room.unreadCount && room.unreadCount > 0">
|
||||
<text class="badge-text">{{ room.unreadCount > 99 ? '99+' : room.unreadCount }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="room-status" :class="getStatusClass(room.status)">
|
||||
<text class="status-dot"></text>
|
||||
<text class="status-text">{{ getStatusText(room.status) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<view class="empty-state" v-if="chatRooms.length === 0">
|
||||
<text class="empty-icon">💬</text>
|
||||
<text class="empty-text">暂无聊天室</text>
|
||||
<text class="empty-hint">点击"联系人工"创建新聊天室</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<!-- #ifdef APP -->
|
||||
</scroll-view>
|
||||
<!-- #endif -->
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import type { ChatRoomVO } from '@/types/workcase'
|
||||
|
||||
// 响应式数据
|
||||
const headerPaddingTop = ref<number>(44)
|
||||
const headerTotalHeight = ref<number>(88)
|
||||
|
||||
// 聊天室列表
|
||||
const chatRooms = ref<ChatRoomVO[]>([
|
||||
{
|
||||
roomId: 'room001',
|
||||
roomName: '控制系统故障咨询',
|
||||
guestId: '1',
|
||||
guestName: '李经理',
|
||||
status: 'active',
|
||||
lastMessage: '好的,工程师会尽快联系您',
|
||||
lastMessageTime: '2024-12-17 16:30:00',
|
||||
unreadCount: 2,
|
||||
workcaseId: 'TH20241217001'
|
||||
},
|
||||
{
|
||||
roomId: 'room002',
|
||||
roomName: '设备维修咨询',
|
||||
guestId: '2',
|
||||
guestName: '王工',
|
||||
status: 'closed',
|
||||
lastMessage: '问题已解决,感谢您的咨询',
|
||||
lastMessageTime: '2024-12-16 14:20:00',
|
||||
unreadCount: 0
|
||||
},
|
||||
{
|
||||
roomId: 'room003',
|
||||
roomName: '新设备安装咨询',
|
||||
guestId: '3',
|
||||
guestName: '张总',
|
||||
status: 'waiting',
|
||||
lastMessage: '您好,请问有什么可以帮助您的?',
|
||||
lastMessageTime: '2024-12-17 10:15:00',
|
||||
unreadCount: 0
|
||||
}
|
||||
])
|
||||
|
||||
// 生命周期
|
||||
onMounted(() => {
|
||||
uni.getSystemInfo({
|
||||
success: (res) => {
|
||||
// #ifdef MP-WEIXIN
|
||||
try {
|
||||
const menuButtonInfo = uni.getMenuButtonBoundingClientRect()
|
||||
headerPaddingTop.value = menuButtonInfo.top
|
||||
headerTotalHeight.value = menuButtonInfo.bottom + 8
|
||||
} catch (e) {
|
||||
headerPaddingTop.value = res.statusBarHeight || 44
|
||||
headerTotalHeight.value = (res.statusBarHeight || 44) + 44
|
||||
}
|
||||
// #endif
|
||||
// #ifndef MP-WEIXIN
|
||||
headerPaddingTop.value = res.statusBarHeight || 44
|
||||
headerTotalHeight.value = (res.statusBarHeight || 44) + 44
|
||||
// #endif
|
||||
}
|
||||
})
|
||||
|
||||
loadChatRooms()
|
||||
})
|
||||
|
||||
// 加载聊天室列表
|
||||
function loadChatRooms() {
|
||||
console.log('加载聊天室列表')
|
||||
// TODO: 调用 workcaseChatAPI.getChatRoomPage() 获取数据
|
||||
}
|
||||
|
||||
// 格式化时间
|
||||
function formatTime(time?: string): string {
|
||||
if (!time) return ''
|
||||
const date = new Date(time)
|
||||
const now = new Date()
|
||||
const diff = now.getTime() - date.getTime()
|
||||
|
||||
if (diff < 60000) return '刚刚'
|
||||
if (diff < 3600000) return Math.floor(diff / 60000) + '分钟前'
|
||||
if (diff < 86400000) return Math.floor(diff / 3600000) + '小时前'
|
||||
if (diff < 172800000) return '昨天'
|
||||
|
||||
return `${date.getMonth() + 1}/${date.getDate()}`
|
||||
}
|
||||
|
||||
// 获取状态样式类
|
||||
function getStatusClass(status?: string): string {
|
||||
switch (status) {
|
||||
case 'active': return 'status-active'
|
||||
case 'waiting': return 'status-waiting'
|
||||
case 'closed': return 'status-closed'
|
||||
default: return 'status-waiting'
|
||||
}
|
||||
}
|
||||
|
||||
// 获取状态文本
|
||||
function getStatusText(status?: string): string {
|
||||
switch (status) {
|
||||
case 'active': return '进行中'
|
||||
case 'waiting': return '等待中'
|
||||
case 'closed': return '已关闭'
|
||||
default: return '未知'
|
||||
}
|
||||
}
|
||||
|
||||
// 进入聊天室
|
||||
function enterRoom(room: ChatRoomVO) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/chatRoom/chatRoom/chatRoom?roomId=${room.roomId}&workcaseId=${room.workcaseId || ''}`
|
||||
})
|
||||
}
|
||||
|
||||
// 返回上一页
|
||||
function goBack() {
|
||||
uni.navigateBack()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "./chatRoomList.scss";
|
||||
</style>
|
||||
Reference in New Issue
Block a user