|
|
@@ -110,20 +110,21 @@
|
|
|
<div class="agent-name">{{ agent.name }}</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div class="pagination-dots" v-if="totalPages > 1">
|
|
|
- <span
|
|
|
- v-for="page in totalPages"
|
|
|
- :key="page"
|
|
|
- class="dot"
|
|
|
- :class="{ active: currentPage === page - 1 }"
|
|
|
- @click="currentPage = page - 1"
|
|
|
- ></span>
|
|
|
- </div>
|
|
|
</div>
|
|
|
<div class="agents-footer">
|
|
|
- <el-button type="primary" round size="large" class="start-btn" @click="startChat">
|
|
|
- 开始对话
|
|
|
- </el-button>
|
|
|
+ <div class="footer-input">
|
|
|
+ <el-input
|
|
|
+ v-model="customerPhone"
|
|
|
+ placeholder="请输入客户电话号码(可选)"
|
|
|
+ class="customer-phone-input"
|
|
|
+ clearable
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class="footer-actions">
|
|
|
+ <el-button type="primary" round size="large" class="start-btn" @click="startChat">
|
|
|
+ 开始对话
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</main>
|
|
|
|
|
|
@@ -214,6 +215,7 @@ const basicExpanded = ref(true)
|
|
|
const otherExpanded = ref(false)
|
|
|
const currentPage = ref(0)
|
|
|
const chatContent = ref(null)
|
|
|
+const customerPhone = ref('')
|
|
|
|
|
|
// 语音识别
|
|
|
const { isRecording, currentTranscription, tempTranscription, startRecording, stopRecording } = useVoiceRecognition()
|
|
|
@@ -595,44 +597,47 @@ const fetchTtsVcnList = async () => {
|
|
|
// 获取客服列表
|
|
|
const fetchAgents = async (silent = false) => {
|
|
|
try {
|
|
|
- const response = await fetch(API_ENDPOINTS.agentList, {
|
|
|
+ const response = await fetch(API_ENDPOINTS.agentMy, {
|
|
|
headers: getHeaders()
|
|
|
})
|
|
|
const result = await response.json()
|
|
|
- if (result.code === 200 && result.rows) {
|
|
|
+ if (result.code === 200 && result.data) {
|
|
|
+ const agent = result.data
|
|
|
// 只显示状态为0(空闲中)或2(工作中)的客服
|
|
|
- const previousSelectedAgent = selectedAgent.value
|
|
|
- agents.value = result.rows
|
|
|
- .filter(agent => agent.status === '0' || agent.status === '2')
|
|
|
- .map(agent => ({
|
|
|
- id: agent.id,
|
|
|
- name: agent.name,
|
|
|
- gender: agent.gender === '0' ? 'male' : 'female',
|
|
|
- avatarUrl: agent.avatarUrl,
|
|
|
- greetingMessage: agent.greetingMessage,
|
|
|
- ttsVcn: agent.ttsVcn,
|
|
|
- ttsSpeed: agent.ttsSpeed,
|
|
|
- ttsPitch: agent.ttsPitch,
|
|
|
- ttsVolume: agent.ttsVolume,
|
|
|
- ttsBgs: agent.ttsBgs,
|
|
|
- status: agent.status
|
|
|
- }))
|
|
|
-
|
|
|
- // 如果之前选中的客服不在列表中,清除选择
|
|
|
- if (previousSelectedAgent && !agents.value.find(a => a.id === previousSelectedAgent)) {
|
|
|
+ if (agent.status === '0' || agent.status === '2') {
|
|
|
+ agents.value = [{
|
|
|
+ id: agent.id,
|
|
|
+ name: agent.name,
|
|
|
+ gender: agent.gender === '0' ? 'male' : 'female',
|
|
|
+ avatarUrl: agent.avatarUrl,
|
|
|
+ greetingMessage: agent.greetingMessage,
|
|
|
+ ttsVcn: agent.ttsVcn,
|
|
|
+ ttsSpeed: agent.ttsSpeed,
|
|
|
+ ttsPitch: agent.ttsPitch,
|
|
|
+ ttsVolume: agent.ttsVolume,
|
|
|
+ ttsBgs: agent.ttsBgs,
|
|
|
+ status: agent.status
|
|
|
+ }]
|
|
|
+ selectedAgent.value = agent.id
|
|
|
+ console.log('自动匹配到当前用户的客服:', agent.name)
|
|
|
+ } else {
|
|
|
+ agents.value = []
|
|
|
selectedAgent.value = null
|
|
|
+ if (!silent) {
|
|
|
+ ElMessage.warning('您的客服当前不可用')
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
- // 如果没有选中客服且列表不为空,选择第一个可用的客服
|
|
|
- if (!selectedAgent.value && agents.value.length > 0) {
|
|
|
- const availableAgent = agents.value.find(a => a.status === '0')
|
|
|
- selectedAgent.value = availableAgent ? availableAgent.id : agents.value[0].id
|
|
|
+ } else {
|
|
|
+ agents.value = []
|
|
|
+ selectedAgent.value = null
|
|
|
+ if (!silent) {
|
|
|
+ ElMessage.warning('未找到对应的客服')
|
|
|
}
|
|
|
}
|
|
|
} catch (error) {
|
|
|
- console.error('获取客服列表失败:', error)
|
|
|
+ console.error('获取客服失败:', error)
|
|
|
if (!silent) {
|
|
|
- ElMessage.error('获取客服列表失败')
|
|
|
+ ElMessage.error('获取客服失败')
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -726,7 +731,10 @@ const startChat = async () => {
|
|
|
// 调用对话前端的开始对话接口(带并发控制)
|
|
|
const response = await fetch(API_ENDPOINTS.agentStart(selectedAgent.value), {
|
|
|
method: 'POST',
|
|
|
- headers: getHeaders()
|
|
|
+ headers: getHeaders(),
|
|
|
+ body: JSON.stringify({
|
|
|
+ customerPhone: customerPhone.value
|
|
|
+ })
|
|
|
})
|
|
|
|
|
|
const result = await response.json()
|
|
|
@@ -994,7 +1002,7 @@ const handleWheel = (e) => {
|
|
|
flex-direction: column;
|
|
|
align-items: stretch;
|
|
|
justify-content: flex-start;
|
|
|
- padding: 0;
|
|
|
+ padding: 20px;
|
|
|
background: #f9fafb;
|
|
|
border-radius: 8px;
|
|
|
height: 100%;
|
|
|
@@ -1016,8 +1024,8 @@ const handleWheel = (e) => {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
align-items: center;
|
|
|
- padding-top: 36px;
|
|
|
- padding-bottom: 0;
|
|
|
+ justify-content: flex-start;
|
|
|
+ padding: 72px 40px 28px;
|
|
|
overflow: visible;
|
|
|
min-height: 0;
|
|
|
position: relative;
|
|
|
@@ -1035,32 +1043,46 @@ const handleWheel = (e) => {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
align-items: center;
|
|
|
- padding: 0;
|
|
|
+ width: 100%;
|
|
|
+ max-width: 520px;
|
|
|
+ margin-left: auto;
|
|
|
+ margin-right: auto;
|
|
|
+ gap: 14px;
|
|
|
flex-shrink: 0;
|
|
|
- position: absolute;
|
|
|
- left: 50%;
|
|
|
- transform: translateX(-50%);
|
|
|
- top: calc(36px + 220px + 16px + 220px + 24px + 40px);
|
|
|
+ margin-top: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.footer-input {
|
|
|
+ width: 100%;
|
|
|
+ padding: 0;
|
|
|
+ background: transparent;
|
|
|
+ border: none;
|
|
|
+ border-radius: 0;
|
|
|
+ box-shadow: none;
|
|
|
+}
|
|
|
+
|
|
|
+.footer-actions {
|
|
|
+ width: 100%;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
}
|
|
|
|
|
|
.agents-list {
|
|
|
- display: grid;
|
|
|
- grid-template-columns: repeat(3, 220px);
|
|
|
- gap: 16px;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
width: 100%;
|
|
|
max-width: 100%;
|
|
|
- padding: 0 12px;
|
|
|
- margin-top: 0;
|
|
|
- margin-bottom: 0;
|
|
|
- justify-content: center;
|
|
|
+ padding: 0 20px;
|
|
|
+ margin-bottom: 28px;
|
|
|
}
|
|
|
|
|
|
.agent-card {
|
|
|
- width: 220px;
|
|
|
- height: 220px;
|
|
|
- padding: 10px;
|
|
|
+ width: 280px;
|
|
|
+ height: 280px;
|
|
|
+ padding: 20px;
|
|
|
border: 2px solid #e5e7eb;
|
|
|
- border-radius: 12px;
|
|
|
+ border-radius: 16px;
|
|
|
text-align: center;
|
|
|
cursor: pointer;
|
|
|
position: relative;
|
|
|
@@ -1171,18 +1193,18 @@ const handleWheel = (e) => {
|
|
|
}
|
|
|
|
|
|
.avatar {
|
|
|
- width: 120px;
|
|
|
- height: 120px;
|
|
|
+ width: 150px;
|
|
|
+ height: 150px;
|
|
|
border-radius: 50%;
|
|
|
- margin: 20px auto 12px;
|
|
|
+ margin: 20px auto 16px;
|
|
|
border: 3px solid #e5e7eb;
|
|
|
}
|
|
|
|
|
|
.avatar-img {
|
|
|
- width: 120px;
|
|
|
- height: 120px;
|
|
|
+ width: 150px;
|
|
|
+ height: 150px;
|
|
|
border-radius: 50%;
|
|
|
- margin: 20px auto 12px;
|
|
|
+ margin: 20px auto 16px;
|
|
|
object-fit: cover;
|
|
|
border: 3px solid #e5e7eb;
|
|
|
background: #f9fafb;
|
|
|
@@ -1249,17 +1271,58 @@ const handleWheel = (e) => {
|
|
|
}
|
|
|
|
|
|
.agent-name {
|
|
|
- font-size: 14px;
|
|
|
+ font-size: 18px;
|
|
|
color: #1f2937;
|
|
|
font-weight: 600;
|
|
|
margin-top: 8px;
|
|
|
}
|
|
|
|
|
|
.start-btn {
|
|
|
+ width: 100%;
|
|
|
+ height: 44px;
|
|
|
font-size: 16px;
|
|
|
- padding: 12px 48px;
|
|
|
+ font-weight: 600;
|
|
|
+ padding: 0 18px;
|
|
|
align-self: center;
|
|
|
- margin: 0;
|
|
|
+ border: none;
|
|
|
+ background: linear-gradient(135deg, #3b82f6, #2563eb);
|
|
|
+ box-shadow: 0 10px 18px rgba(37, 99, 235, 0.25);
|
|
|
+ transition: transform 0.15s ease, box-shadow 0.15s ease, filter 0.15s ease;
|
|
|
+}
|
|
|
+
|
|
|
+.start-btn:hover {
|
|
|
+ filter: brightness(1.02);
|
|
|
+ transform: translateY(-1px);
|
|
|
+ box-shadow: 0 14px 24px rgba(37, 99, 235, 0.32);
|
|
|
+}
|
|
|
+
|
|
|
+.start-btn:active {
|
|
|
+ transform: translateY(0);
|
|
|
+ box-shadow: 0 10px 18px rgba(37, 99, 235, 0.25);
|
|
|
+}
|
|
|
+
|
|
|
+.customer-phone-input {
|
|
|
+ width: 100%;
|
|
|
+ max-width: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+.customer-phone-input :deep(.el-input__wrapper) {
|
|
|
+ height: 44px;
|
|
|
+ border-radius: 9999px;
|
|
|
+ padding: 0 16px;
|
|
|
+ border: 1px solid rgba(229, 231, 235, 1);
|
|
|
+ background: rgba(255, 255, 255, 0.98);
|
|
|
+ box-shadow: 0 6px 16px rgba(15, 23, 42, 0.06);
|
|
|
+ transition: box-shadow 0.15s ease, border-color 0.15s ease;
|
|
|
+}
|
|
|
+
|
|
|
+.customer-phone-input :deep(.el-input__inner) {
|
|
|
+ font-size: 14px;
|
|
|
+}
|
|
|
+
|
|
|
+.customer-phone-input :deep(.el-input__wrapper.is-focus) {
|
|
|
+ border-color: rgba(59, 130, 246, 0.9);
|
|
|
+ box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.16), 0 10px 20px rgba(37, 99, 235, 0.10);
|
|
|
}
|
|
|
|
|
|
.pagination-dots {
|