1002 lines
21 KiB
Plaintext
1002 lines
21 KiB
Plaintext
<!-- 客服端首页 - UTS Android 兼容 -->
|
|
<template>
|
|
<view class="service-container">
|
|
<!-- 头部工作状态栏 -->
|
|
<view class="header">
|
|
<view class="agent-info">
|
|
<image :src="agentInfo.avatar_url || '/static/default-avatar.png'" class="avatar" mode="aspectFit" />
|
|
<view class="agent-details">
|
|
<text class="agent-name">{{ agentInfo.name }}</text>
|
|
<view class="status-info">
|
|
<text class="status-badge" :class="getStatusClass()">{{ getStatusText() }}</text>
|
|
<text class="work-time">工作时长: {{ workDuration }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<view class="status-controls">
|
|
<switch :checked="isOnline" @change="toggleWorkStatus" color="#4CAF50" />
|
|
<text class="status-label">{{ isOnline ? '在线服务' : '离线休息' }}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 今日工作统计 -->
|
|
<view class="stats-section">
|
|
<text class="section-title">今日工作统计</text>
|
|
<view class="stats-grid">
|
|
<view class="stat-item">
|
|
<text class="stat-value">{{ todayStats.handled_conversations }}</text>
|
|
<text class="stat-label">处理会话</text>
|
|
</view>
|
|
<view class="stat-item">
|
|
<text class="stat-value">{{ todayStats.resolved_issues }}</text>
|
|
<text class="stat-label">解决问题</text>
|
|
</view>
|
|
<view class="stat-item">
|
|
<text class="stat-value">{{ todayStats.avg_response_time }}s</text>
|
|
<text class="stat-label">平均响应</text>
|
|
</view>
|
|
<view class="stat-item">
|
|
<text class="stat-value">{{ todayStats.satisfaction_rate }}%</text>
|
|
<text class="stat-label">满意度</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 当前会话队列 -->
|
|
<view class="queue-section">
|
|
<view class="section-header">
|
|
<text class="section-title">会话队列 ({{ conversations.length }})</text>
|
|
<text class="queue-status" :class="getQueueStatusClass()">{{ getQueueStatusText() }}</text>
|
|
</view>
|
|
|
|
<view v-if="conversations.length === 0" class="empty-queue">
|
|
<text class="empty-icon">💬</text>
|
|
<text class="empty-text">当前没有待处理会话</text>
|
|
<text class="empty-subtitle">{{ isOnline ? '请保持在线,等待用户咨询' : '请上线接受用户咨询' }}</text>
|
|
</view>
|
|
|
|
<view v-for="conversation in conversations" :key="conversation.id" class="conversation-item" @click="openConversation(conversation.id)">
|
|
<view class="conversation-header">
|
|
<view class="user-info">
|
|
<image :src="conversation.user_avatar || '/static/default-avatar.png'" class="user-avatar" mode="aspectFit" />
|
|
<view class="user-details">
|
|
<text class="user-name">{{ conversation.user_name }}</text>
|
|
<text class="conversation-type">{{ getConversationTypeText(conversation.type) }}</text>
|
|
</view>
|
|
</view>
|
|
<view class="conversation-meta">
|
|
<text class="priority-badge" :class="getPriorityClass(conversation.priority)">{{ getPriorityText(conversation.priority) }}</text>
|
|
<text class="wait-time">等待 {{ formatWaitTime(conversation.created_at) }}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="conversation-preview">
|
|
<text class="last-message">{{ conversation.last_message }}</text>
|
|
<text class="message-time">{{ formatTime(conversation.last_message_time) }}</text>
|
|
</view>
|
|
|
|
<view class="conversation-actions">
|
|
<button class="action-btn primary" @click.stop="acceptConversation(conversation.id)">接受</button>
|
|
<button class="action-btn secondary" @click.stop="viewUserProfile(conversation.user_id)">用户信息</button>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 快速处理工具 -->
|
|
<view class="tools-section">
|
|
<text class="section-title">快速处理</text>
|
|
<view class="tools-grid">
|
|
<view class="tool-item" @click="goToOrderInquiry">
|
|
<text class="tool-icon">📋</text>
|
|
<text class="tool-text">订单查询</text>
|
|
</view>
|
|
<view class="tool-item" @click="goToRefundProcess">
|
|
<text class="tool-icon">💰</text>
|
|
<text class="tool-text">退款处理</text>
|
|
</view>
|
|
<view class="tool-item" @click="goToComplaintHandle">
|
|
<text class="tool-icon">⚠️</text>
|
|
<text class="tool-text">投诉处理</text>
|
|
</view>
|
|
<view class="tool-item" @click="goToKnowledgeBase">
|
|
<text class="tool-icon">📚</text>
|
|
<text class="tool-text">知识库</text>
|
|
</view>
|
|
<view class="tool-item" @click="goToQuickReplies">
|
|
<text class="tool-icon">💬</text>
|
|
<text class="tool-text">快捷回复</text>
|
|
</view>
|
|
<view class="tool-item" @click="goToEscalation">
|
|
<text class="tool-icon">⬆️</text>
|
|
<text class="tool-text">问题升级</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 待办事项 -->
|
|
<view class="todo-section">
|
|
<view class="section-header">
|
|
<text class="section-title">待办事项</text>
|
|
<text class="todo-count">{{ todoItems.length }}项</text>
|
|
</view>
|
|
|
|
<view v-if="todoItems.length === 0" class="empty-todo">
|
|
<text class="empty-text">暂无待办事项</text>
|
|
</view>
|
|
|
|
<view v-for="todo in todoItems" :key="todo.id" class="todo-item" @click="handleTodoItem(todo)">
|
|
<view class="todo-content">
|
|
<text class="todo-title">{{ todo.title }}</text>
|
|
<text class="todo-description">{{ todo.description }}</text>
|
|
<text class="todo-deadline">截止: {{ formatDeadline(todo.deadline) }}</text>
|
|
</view>
|
|
<view class="todo-actions">
|
|
<text class="todo-priority" :class="getTodoPriorityClass(todo.priority)">{{ getTodoPriorityText(todo.priority) }}</text>
|
|
<button class="todo-btn" @click.stop="completeTodo(todo.id)">完成</button>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 常用功能快捷入口 -->
|
|
<view class="shortcuts-section">
|
|
<text class="section-title">常用功能</text>
|
|
<view class="shortcuts-list">
|
|
<view class="shortcut-item" @click="goToConversationHistory">
|
|
<text class="shortcut-icon">📝</text>
|
|
<text class="shortcut-text">会话记录</text>
|
|
</view>
|
|
<view class="shortcut-item" @click="goToPerformanceReport">
|
|
<text class="shortcut-icon">📊</text>
|
|
<text class="shortcut-text">绩效报表</text>
|
|
</view>
|
|
<view class="shortcut-item" @click="goToTrainingCenter">
|
|
<text class="shortcut-icon">🎓</text>
|
|
<text class="shortcut-text">培训中心</text>
|
|
</view>
|
|
<view class="shortcut-item" @click="goToFeedback">
|
|
<text class="shortcut-icon">💡</text>
|
|
<text class="shortcut-text">意见反馈</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script lang="uts">
|
|
type AgentInfoType = {
|
|
id: string
|
|
name: string
|
|
avatar_url: string | null
|
|
status: number
|
|
department: string
|
|
}
|
|
|
|
type TodayStatsType = {
|
|
handled_conversations: number
|
|
resolved_issues: number
|
|
avg_response_time: number
|
|
satisfaction_rate: number
|
|
}
|
|
|
|
type ConversationType = {
|
|
id: string
|
|
user_id: string
|
|
user_name: string
|
|
user_avatar: string | null
|
|
type: number
|
|
priority: number
|
|
last_message: string
|
|
last_message_time: string
|
|
created_at: string
|
|
}
|
|
|
|
type TodoItemType = {
|
|
id: string
|
|
title: string
|
|
description: string
|
|
priority: number
|
|
deadline: string
|
|
created_at: string
|
|
}
|
|
|
|
export default {
|
|
data() {
|
|
return {
|
|
isOnline: false,
|
|
workDuration: '0小时0分钟',
|
|
|
|
agentInfo: {
|
|
id: '',
|
|
name: '客服代表',
|
|
avatar_url: '',
|
|
status: 0,
|
|
department: '客服部'
|
|
} as AgentInfoType,
|
|
|
|
todayStats: {
|
|
handled_conversations: 0,
|
|
resolved_issues: 0,
|
|
avg_response_time: 0,
|
|
satisfaction_rate: 0
|
|
} as TodayStatsType,
|
|
|
|
conversations: [] as Array<ConversationType>,
|
|
todoItems: [] as Array<TodoItemType>
|
|
}
|
|
},
|
|
|
|
onLoad() {
|
|
this.loadAgentInfo()
|
|
this.loadTodayStats()
|
|
this.loadConversations()
|
|
this.loadTodoItems()
|
|
this.startWorkTimer()
|
|
},
|
|
|
|
onShow() {
|
|
this.refreshData()
|
|
},
|
|
|
|
methods: {
|
|
// 加载客服信息
|
|
loadAgentInfo() {
|
|
// TODO: 调用API获取客服信息
|
|
this.agentInfo.name = '张小美'
|
|
this.agentInfo.department = '在线客服部'
|
|
},
|
|
|
|
// 加载今日统计
|
|
loadTodayStats() {
|
|
// TODO: 调用API获取今日统计
|
|
this.todayStats = {
|
|
handled_conversations: 25,
|
|
resolved_issues: 23,
|
|
avg_response_time: 45,
|
|
satisfaction_rate: 96
|
|
}
|
|
},
|
|
|
|
// 加载会话列表
|
|
loadConversations() {
|
|
if (!this.isOnline) {
|
|
this.conversations = []
|
|
return
|
|
}
|
|
|
|
// TODO: 调用API获取待处理会话
|
|
this.conversations = [
|
|
{
|
|
id: '1',
|
|
user_id: '1',
|
|
user_name: '张先生',
|
|
user_avatar: '/static/user1.jpg',
|
|
type: 1,
|
|
priority: 2,
|
|
last_message: '我的订单什么时候能发货?',
|
|
last_message_time: '2025-01-08T15:30:00Z',
|
|
created_at: '2025-01-08T15:28:00Z'
|
|
},
|
|
{
|
|
id: '2',
|
|
user_id: '2',
|
|
user_name: '李女士',
|
|
user_avatar: '/static/user2.jpg',
|
|
type: 2,
|
|
priority: 3,
|
|
last_message: '我要申请退款,商品有质量问题',
|
|
last_message_time: '2025-01-08T15:25:00Z',
|
|
created_at: '2025-01-08T15:20:00Z'
|
|
}
|
|
]
|
|
},
|
|
|
|
// 加载待办事项
|
|
loadTodoItems() {
|
|
// TODO: 调用API获取待办事项
|
|
this.todoItems = [
|
|
{
|
|
id: '1',
|
|
title: '处理投诉单 #CS001',
|
|
description: '用户反馈配送延迟问题,需要跟进处理',
|
|
priority: 3,
|
|
deadline: '2025-01-08T18:00:00Z',
|
|
created_at: '2025-01-08T14:00:00Z'
|
|
}
|
|
]
|
|
},
|
|
|
|
// 刷新数据
|
|
refreshData() {
|
|
this.loadConversations()
|
|
this.loadTodoItems()
|
|
this.loadTodayStats()
|
|
},
|
|
|
|
// 开始工作计时
|
|
startWorkTimer() {
|
|
// TODO: 实现工作时长计时器
|
|
this.workDuration = '2小时15分钟'
|
|
},
|
|
|
|
// 切换工作状态
|
|
toggleWorkStatus(event: UniSwitchChangeEvent) {
|
|
this.isOnline = event.detail.value
|
|
|
|
if (this.isOnline) {
|
|
this.goOnline()
|
|
} else {
|
|
this.goOffline()
|
|
}
|
|
},
|
|
|
|
// 上线
|
|
goOnline() {
|
|
// TODO: 调用API上线
|
|
this.loadConversations()
|
|
uni.showToast({
|
|
title: '已上线接受咨询',
|
|
icon: 'success'
|
|
})
|
|
},
|
|
|
|
// 下线
|
|
goOffline() {
|
|
// TODO: 调用API下线
|
|
this.conversations = []
|
|
uni.showToast({
|
|
title: '已下线休息',
|
|
icon: 'none'
|
|
})
|
|
},
|
|
|
|
// 获取状态样式
|
|
getStatusClass(): string {
|
|
return this.isOnline ? 'status-online' : 'status-offline'
|
|
},
|
|
|
|
// 获取状态文本
|
|
getStatusText(): string {
|
|
return this.isOnline ? '在线' : '离线'
|
|
},
|
|
|
|
// 获取队列状态样式
|
|
getQueueStatusClass(): string {
|
|
if (this.conversations.length === 0) return 'queue-empty'
|
|
if (this.conversations.length > 5) return 'queue-busy'
|
|
return 'queue-normal'
|
|
},
|
|
|
|
// 获取队列状态文本
|
|
getQueueStatusText(): string {
|
|
if (this.conversations.length === 0) return '空闲'
|
|
if (this.conversations.length > 5) return '繁忙'
|
|
return '正常'
|
|
},
|
|
|
|
// 获取会话类型文本
|
|
getConversationTypeText(type: number): string {
|
|
switch (type) {
|
|
case 1: return '订单咨询'
|
|
case 2: return '退款申请'
|
|
case 3: return '商品咨询'
|
|
case 4: return '投诉建议'
|
|
default: return '一般咨询'
|
|
}
|
|
},
|
|
|
|
// 获取优先级样式
|
|
getPriorityClass(priority: number): string {
|
|
switch (priority) {
|
|
case 3: return 'priority-high'
|
|
case 2: return 'priority-medium'
|
|
default: return 'priority-low'
|
|
}
|
|
},
|
|
|
|
// 获取优先级文本
|
|
getPriorityText(priority: number): string {
|
|
switch (priority) {
|
|
case 3: return '紧急'
|
|
case 2: return '重要'
|
|
default: return '普通'
|
|
}
|
|
},
|
|
|
|
// 获取待办优先级样式
|
|
getTodoPriorityClass(priority: number): string {
|
|
switch (priority) {
|
|
case 3: return 'todo-high'
|
|
case 2: return 'todo-medium'
|
|
default: return 'todo-low'
|
|
}
|
|
},
|
|
|
|
// 获取待办优先级文本
|
|
getTodoPriorityText(priority: number): string {
|
|
switch (priority) {
|
|
case 3: return '高'
|
|
case 2: return '中'
|
|
default: return '低'
|
|
}
|
|
},
|
|
|
|
// 格式化等待时间
|
|
formatWaitTime(timeStr: string): string {
|
|
const date = new Date(timeStr)
|
|
const now = new Date()
|
|
const diff = now.getTime() - date.getTime()
|
|
const minutes = Math.floor(diff / (1000 * 60))
|
|
|
|
if (minutes < 60) {
|
|
return `${minutes}分钟`
|
|
} else {
|
|
return `${Math.floor(minutes / 60)}小时${minutes % 60}分钟`
|
|
}
|
|
},
|
|
|
|
// 格式化时间
|
|
formatTime(timeStr: string): string {
|
|
const date = new Date(timeStr)
|
|
const now = new Date()
|
|
const diff = now.getTime() - date.getTime()
|
|
const minutes = Math.floor(diff / (1000 * 60))
|
|
|
|
if (minutes < 60) {
|
|
return `${minutes}分钟前`
|
|
} else {
|
|
return `${Math.floor(minutes / 60)}小时前`
|
|
}
|
|
},
|
|
|
|
// 格式化截止时间
|
|
formatDeadline(timeStr: string): string {
|
|
const date = new Date(timeStr)
|
|
return `${date.getMonth() + 1}月${date.getDate()}日 ${date.getHours()}:${date.getMinutes().toString().padStart(2, '0')}`
|
|
},
|
|
|
|
// 会话操作
|
|
openConversation(conversationId: string) {
|
|
uni.navigateTo({
|
|
url: `/pages/mall/service/conversation?id=${conversationId}`
|
|
})
|
|
},
|
|
|
|
acceptConversation(conversationId: string) {
|
|
// TODO: 调用API接受会话
|
|
uni.showToast({
|
|
title: '已接受会话',
|
|
icon: 'success'
|
|
})
|
|
this.openConversation(conversationId)
|
|
},
|
|
|
|
viewUserProfile(userId: string) {
|
|
uni.navigateTo({
|
|
url: `/pages/mall/service/user-profile?id=${userId}`
|
|
})
|
|
},
|
|
|
|
// 待办事项操作
|
|
handleTodoItem(todo: TodoItemType) {
|
|
uni.navigateTo({
|
|
url: `/pages/mall/service/todo-detail?id=${todo.id}`
|
|
})
|
|
},
|
|
|
|
completeTodo(todoId: string) {
|
|
// TODO: 调用API完成待办
|
|
uni.showToast({
|
|
title: '待办已完成',
|
|
icon: 'success'
|
|
})
|
|
this.loadTodoItems()
|
|
},
|
|
|
|
// 导航方法
|
|
goToOrderInquiry() {
|
|
uni.navigateTo({
|
|
url: '/pages/mall/service/order-inquiry'
|
|
})
|
|
},
|
|
|
|
goToRefundProcess() {
|
|
uni.navigateTo({
|
|
url: '/pages/mall/service/refund-process'
|
|
})
|
|
},
|
|
|
|
goToComplaintHandle() {
|
|
uni.navigateTo({
|
|
url: '/pages/mall/service/complaint-handle'
|
|
})
|
|
},
|
|
|
|
goToKnowledgeBase() {
|
|
uni.navigateTo({
|
|
url: '/pages/mall/service/knowledge-base'
|
|
})
|
|
},
|
|
|
|
goToQuickReplies() {
|
|
uni.navigateTo({
|
|
url: '/pages/mall/service/quick-replies'
|
|
})
|
|
},
|
|
|
|
goToEscalation() {
|
|
uni.navigateTo({
|
|
url: '/pages/mall/service/escalation'
|
|
})
|
|
},
|
|
|
|
goToConversationHistory() {
|
|
uni.navigateTo({
|
|
url: '/pages/mall/service/conversation-history'
|
|
})
|
|
},
|
|
|
|
goToPerformanceReport() {
|
|
uni.navigateTo({
|
|
url: '/pages/mall/service/performance-report'
|
|
})
|
|
},
|
|
|
|
goToTrainingCenter() {
|
|
uni.navigateTo({
|
|
url: '/pages/mall/service/training-center'
|
|
})
|
|
},
|
|
|
|
goToFeedback() {
|
|
uni.navigateTo({
|
|
url: '/pages/mall/service/feedback'
|
|
})
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style>
|
|
.service-container {
|
|
background-color: #f5f5f5;
|
|
min-height: 100vh;
|
|
padding-bottom: 40rpx;
|
|
}
|
|
|
|
.header {
|
|
background: linear-gradient(135deg, #36D1DC 0%, #5B86E5 100%);
|
|
padding: 30rpx;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
|
|
.agent-info {
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.avatar {
|
|
width: 80rpx;
|
|
height: 80rpx;
|
|
border-radius: 40rpx;
|
|
margin-right: 20rpx;
|
|
}
|
|
|
|
.agent-details {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.agent-name {
|
|
font-size: 32rpx;
|
|
font-weight: bold;
|
|
color: #fff;
|
|
margin-bottom: 8rpx;
|
|
}
|
|
|
|
.status-info {
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.status-badge {
|
|
font-size: 20rpx;
|
|
padding: 6rpx 12rpx;
|
|
border-radius: 12rpx;
|
|
margin-right: 15rpx;
|
|
}
|
|
|
|
.status-online {
|
|
background-color: rgba(76, 175, 80, 0.2);
|
|
color: #4CAF50;
|
|
}
|
|
|
|
.status-offline {
|
|
background-color: rgba(255, 152, 0, 0.2);
|
|
color: #FF9800;
|
|
}
|
|
|
|
.work-time {
|
|
font-size: 20rpx;
|
|
color: rgba(255, 255, 255, 0.8);
|
|
}
|
|
|
|
.status-controls {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
}
|
|
|
|
.status-label {
|
|
font-size: 22rpx;
|
|
color: rgba(255, 255, 255, 0.9);
|
|
margin-top: 8rpx;
|
|
}
|
|
|
|
.stats-section {
|
|
background-color: #fff;
|
|
margin: 20rpx;
|
|
padding: 30rpx;
|
|
border-radius: 16rpx;
|
|
}
|
|
|
|
.section-title {
|
|
font-size: 32rpx;
|
|
font-weight: bold;
|
|
color: #333;
|
|
margin-bottom: 30rpx;
|
|
}
|
|
|
|
.stats-grid {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
.stat-item {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
flex: 1;
|
|
}
|
|
|
|
.stat-value {
|
|
font-size: 36rpx;
|
|
font-weight: bold;
|
|
color: #36D1DC;
|
|
margin-bottom: 10rpx;
|
|
}
|
|
|
|
.stat-label {
|
|
font-size: 24rpx;
|
|
color: #666;
|
|
}
|
|
|
|
.queue-section {
|
|
margin: 20rpx;
|
|
}
|
|
|
|
.section-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 20rpx;
|
|
}
|
|
|
|
.queue-status {
|
|
font-size: 24rpx;
|
|
padding: 8rpx 16rpx;
|
|
border-radius: 20rpx;
|
|
}
|
|
|
|
.queue-empty {
|
|
background-color: #E8F5E8;
|
|
color: #4CAF50;
|
|
}
|
|
|
|
.queue-normal {
|
|
background-color: #E3F2FD;
|
|
color: #2196F3;
|
|
}
|
|
|
|
.queue-busy {
|
|
background-color: #FFEBEE;
|
|
color: #F44336;
|
|
}
|
|
|
|
.empty-queue {
|
|
background-color: #fff;
|
|
padding: 80rpx 30rpx;
|
|
border-radius: 16rpx;
|
|
text-align: center;
|
|
}
|
|
|
|
.empty-icon {
|
|
font-size: 64rpx;
|
|
margin-bottom: 20rpx;
|
|
}
|
|
|
|
.empty-text {
|
|
font-size: 32rpx;
|
|
color: #999;
|
|
margin-bottom: 15rpx;
|
|
}
|
|
|
|
.empty-subtitle {
|
|
font-size: 24rpx;
|
|
color: #ccc;
|
|
}
|
|
|
|
.conversation-item {
|
|
background-color: #fff;
|
|
border-radius: 12rpx;
|
|
padding: 20rpx;
|
|
margin-bottom: 15rpx;
|
|
}
|
|
|
|
.conversation-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 15rpx;
|
|
}
|
|
|
|
.user-info {
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.user-avatar {
|
|
width: 60rpx;
|
|
height: 60rpx;
|
|
border-radius: 30rpx;
|
|
margin-right: 15rpx;
|
|
}
|
|
|
|
.user-details {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.user-name {
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
margin-bottom: 5rpx;
|
|
}
|
|
|
|
.conversation-type {
|
|
font-size: 22rpx;
|
|
color: #666;
|
|
}
|
|
|
|
.conversation-meta {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: flex-end;
|
|
}
|
|
|
|
.priority-badge {
|
|
font-size: 20rpx;
|
|
padding: 4rpx 8rpx;
|
|
border-radius: 8rpx;
|
|
margin-bottom: 8rpx;
|
|
}
|
|
|
|
.priority-high {
|
|
background-color: #FFEBEE;
|
|
color: #F44336;
|
|
}
|
|
|
|
.priority-medium {
|
|
background-color: #FFF3E0;
|
|
color: #FF9800;
|
|
}
|
|
|
|
.priority-low {
|
|
background-color: #F3E5F5;
|
|
color: #9C27B0;
|
|
}
|
|
|
|
.wait-time {
|
|
font-size: 20rpx;
|
|
color: #999;
|
|
}
|
|
|
|
.conversation-preview {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 15rpx;
|
|
padding: 15rpx;
|
|
background-color: #f8f9fa;
|
|
border-radius: 8rpx;
|
|
}
|
|
|
|
.last-message {
|
|
font-size: 26rpx;
|
|
color: #333;
|
|
flex: 1;
|
|
margin-right: 15rpx;
|
|
}
|
|
|
|
.message-time {
|
|
font-size: 20rpx;
|
|
color: #999;
|
|
}
|
|
|
|
.conversation-actions {
|
|
display: flex;
|
|
gap: 15rpx;
|
|
}
|
|
|
|
.action-btn {
|
|
flex: 1;
|
|
height: 70rpx;
|
|
border-radius: 8rpx;
|
|
font-size: 26rpx;
|
|
border: none;
|
|
}
|
|
|
|
.primary {
|
|
background-color: #36D1DC;
|
|
color: #fff;
|
|
}
|
|
|
|
.secondary {
|
|
background-color: #f0f0f0;
|
|
color: #333;
|
|
}
|
|
|
|
.tools-section {
|
|
background-color: #fff;
|
|
margin: 20rpx;
|
|
padding: 30rpx;
|
|
border-radius: 16rpx;
|
|
}
|
|
|
|
.tools-grid {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
.tool-item {
|
|
width: 30%;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
margin-bottom: 30rpx;
|
|
}
|
|
|
|
.tool-icon {
|
|
font-size: 48rpx;
|
|
margin-bottom: 15rpx;
|
|
}
|
|
|
|
.tool-text {
|
|
font-size: 22rpx;
|
|
color: #333;
|
|
text-align: center;
|
|
}
|
|
|
|
.todo-section {
|
|
background-color: #fff;
|
|
margin: 20rpx;
|
|
padding: 30rpx;
|
|
border-radius: 16rpx;
|
|
}
|
|
|
|
.todo-count {
|
|
font-size: 24rpx;
|
|
color: #666;
|
|
background-color: #f0f0f0;
|
|
padding: 8rpx 16rpx;
|
|
border-radius: 20rpx;
|
|
}
|
|
|
|
.empty-todo {
|
|
text-align: center;
|
|
padding: 40rpx;
|
|
}
|
|
|
|
.todo-item {
|
|
border: 1rpx solid #e5e5e5;
|
|
border-radius: 12rpx;
|
|
padding: 20rpx;
|
|
margin-bottom: 15rpx;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
|
|
.todo-content {
|
|
display: flex;
|
|
flex-direction: column;
|
|
flex: 1;
|
|
}
|
|
|
|
.todo-title {
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
margin-bottom: 8rpx;
|
|
}
|
|
|
|
.todo-description {
|
|
font-size: 24rpx;
|
|
color: #666;
|
|
margin-bottom: 8rpx;
|
|
}
|
|
|
|
.todo-deadline {
|
|
font-size: 22rpx;
|
|
color: #999;
|
|
}
|
|
|
|
.todo-actions {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: flex-end;
|
|
}
|
|
|
|
.todo-priority {
|
|
font-size: 20rpx;
|
|
padding: 4rpx 8rpx;
|
|
border-radius: 8rpx;
|
|
margin-bottom: 10rpx;
|
|
}
|
|
|
|
.todo-high {
|
|
background-color: #FFEBEE;
|
|
color: #F44336;
|
|
}
|
|
|
|
.todo-medium {
|
|
background-color: #FFF3E0;
|
|
color: #FF9800;
|
|
}
|
|
|
|
.todo-low {
|
|
background-color: #E8F5E8;
|
|
color: #4CAF50;
|
|
}
|
|
|
|
.todo-btn {
|
|
background-color: #36D1DC;
|
|
color: #fff;
|
|
border: none;
|
|
padding: 10rpx 20rpx;
|
|
border-radius: 6rpx;
|
|
font-size: 22rpx;
|
|
}
|
|
|
|
.shortcuts-section {
|
|
background-color: #fff;
|
|
margin: 20rpx;
|
|
padding: 30rpx;
|
|
border-radius: 16rpx;
|
|
}
|
|
|
|
.shortcuts-list {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
.shortcut-item {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
flex: 1;
|
|
}
|
|
|
|
.shortcut-icon {
|
|
font-size: 48rpx;
|
|
margin-bottom: 15rpx;
|
|
}
|
|
|
|
.shortcut-text {
|
|
font-size: 24rpx;
|
|
color: #333;
|
|
text-align: center;
|
|
}
|
|
</style>
|