This commit is contained in:
@zuopngfei 2025-11-06 14:07:51 +08:00
parent 8250bb2877
commit d5239d0654
7 changed files with 100 additions and 61 deletions

1
components.d.ts vendored
View File

@ -41,6 +41,7 @@ declare module 'vue' {
ElSelect: typeof import('element-plus/es')['ElSelect']
ElSelectV2: typeof import('element-plus/es')['ElSelectV2']
ElSkeleton: typeof import('element-plus/es')['ElSkeleton']
ElSpace: typeof import('element-plus/es')['ElSpace']
ElTable: typeof import('element-plus/es')['ElTable']
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
ElTabPane: typeof import('element-plus/es')['ElTabPane']

View File

@ -19,10 +19,11 @@ export const addApp = (data) => {
})
}
export const deleteRobot = (id) => {
export const deleteRobot = (data) => {
return request({
url: `admin/app/${id}`,
method: 'delete',
url: `admin/app/delete`,
method: 'post',
data
})
}
export const editRobot = (id, data) => {

View File

@ -12,11 +12,11 @@
<!-- <span v-if="element.sender_id != sendeInfo.userInfo.user_id" class="robot-name">{{ sendeInfo.robotInfo.name }}</span>
<span v-if="element.sender_id == sendeInfo.userInfo.user_id" class="robot-name">{{ sendeInfo.userInfo.nickname }}</span> -->
<div class="text" v-if="element.msg_type == 1">
<pre>{{ element.content.messages }}</pre>
<pre>{{ element.content.message }}</pre>
</div>
<div class="image" v-if="element.msg_type == 2">
<el-image :src="element.content.messages" fit="cover"
:preview-src-list="[element.content.messages]" preview-teleported>
<el-image :src="element.content.message" fit="cover"
:preview-src-list="[element.content.message]" preview-teleported>
<template #placeholder>
<div class="image-slot">Loading<span class="dot">...</span></div>
</template>

View File

@ -104,11 +104,13 @@ const formatLastMessage = (user) => {
try {
// JSONcontent
const contentObj = JSON.parse(user.content)
const contentObj = {
message: JSON.parse(user.content).message || JSON.parse(user.content).messages
}
// messages
if (contentObj.messages) {
const content = String(contentObj.messages).slice(0, 30)
if (contentObj.message) {
const content = String(contentObj.message).slice(0, 30)
return content.length > 30 ? content + '...' : content
}

View File

@ -209,7 +209,7 @@ const sortMessagesByTime = (messages) => {
id: m.id || m._id || m.message_id,
send_time: m.send_time,
content: typeof m.content === 'object' ?
(m.content.messages || JSON.stringify(m.content)) :
(m.content.message || JSON.stringify(m.content)) :
String(m.content).slice(0, 20) + '...'
})))
@ -248,10 +248,13 @@ const getMessages = async (isHistory = true, pageOverride = null) => {
const newMessages = list.map(item => {
// ChatRecord
try {
item.content = JSON.parse(item.content)
const text = JSON.parse(item.content)
item.content = {
message: text.message || text.messages
}
} catch (e) {
//
item.content = { messages: item.content }
item.content = { message: item.content }
}
return item
})
@ -301,13 +304,13 @@ const getMessages = async (isHistory = true, pageOverride = null) => {
if (existingMsg.msg_type === 1) {
//
const existingContent = existingMsg._tempContent ||
(typeof existingMsg.content === 'object' ? existingMsg.content.messages : existingMsg.content)
const newContent = typeof newMsg.content === 'object' ? newMsg.content.messages : newMsg.content
(typeof existingMsg.content === 'object' ? existingMsg.content.message : existingMsg.content)
const newContent = typeof newMsg.content === 'object' ? newMsg.content.message : newMsg.content
contentMatch = existingContent === newContent
} else if (existingMsg.msg_type === 2) {
//
if (existingMsg._tempImageFile) {
const newContent = typeof newMsg.content === 'object' ? newMsg.content.messages : newMsg.content
const newContent = typeof newMsg.content === 'object' ? newMsg.content.message : newMsg.content
//
if (typeof newContent === 'string' && newContent.includes(existingMsg._tempImageFile.name.split('.')[0])) {
contentMatch = true
@ -345,10 +348,10 @@ const getMessages = async (isHistory = true, pageOverride = null) => {
// ID使
const existingContentStr = typeof existingMsg.content === 'object' ?
(existingMsg.content.messages || JSON.stringify(existingMsg.content)) :
(existingMsg.content.message || JSON.stringify(existingMsg.content)) :
String(existingMsg.content)
const newContentStr = typeof newMsg.content === 'object' ?
(newMsg.content.messages || JSON.stringify(newMsg.content)) :
(newMsg.content.message || JSON.stringify(newMsg.content)) :
String(newMsg.content)
const compositeMatch = existingMsg.sender_id === newMsg.sender_id &&
@ -363,7 +366,7 @@ const getMessages = async (isHistory = true, pageOverride = null) => {
// 3.
console.log('发现新消息:', {
id: newMsg.id || newMsg._id || newMsg.message_id,
content: typeof newMsg.content === 'object' ? newMsg.content.messages : newMsg.content
content: typeof newMsg.content === 'object' ? newMsg.content.message : newMsg.content
})
currentMessages.push(newMsg)
hasUpdates = true
@ -481,7 +484,7 @@ const send = async () => {
msg.sender_id === '888888' &&
msg.msg_type === 1 &&
typeof msg.content === 'object' &&
msg.content.messages === content &&
msg.content.message === content &&
(now - (msg._timestamp || 0)) < 5000
)
@ -503,7 +506,7 @@ const send = async () => {
sender_id: '888888',
sender_name: '平台',
msg_type: 1,
content: { messages: content },
content: { message: content },
send_time: '刚刚',
_timestamp: now,
_tempContent: content //
@ -520,7 +523,7 @@ const send = async () => {
send_message({
app_id: route.query.app_id,
content: JSON.stringify({
messages: content
message: content
}),
msg_type: 1,
to_user_id: activeUser.value.sender_id
@ -590,7 +593,7 @@ const handleImageChange = (e) => {
sender_id: '888888',
sender_name: '平台',
msg_type: 2,
content: { messages: url },
content: { message: url },
send_time: '刚刚',
_timestamp: now,
_tempImageFile: file //
@ -615,7 +618,7 @@ const handleImageChange = (e) => {
send_message({
app_id: route.query.app_id,
msg_type: 2,
content: JSON.stringify({ messages: imageUrl }),
content: JSON.stringify({ message: imageUrl }),
to_user_id: activeUser.value.sender_id
}).then(() => {
//

View File

@ -11,10 +11,9 @@
@selection-change="handleSelectionChange" row-key="id">
<template #empty>
<span v-if="tableLoading">加载中...</span>
<span v-if="!tableLoading && query.robot_id">暂无数据</span>
<span v-if="!query.robot_id && !tableLoading" style="font-weight: bold;">请选择一个客服</span>
<span v-if="!tableLoading">暂无数据</span>
</template>
<el-table-column type="selection" width="55" :reserve-selection="true" />
<!-- <el-table-column type="selection" width="55" :reserve-selection="true" /> -->
<el-table-column prop="avatar" label="头像" align="center">
<template #default="scoped">
<el-image style="width: 30px;display: block;margin: auto;border-radius: 4px;"
@ -28,7 +27,7 @@
<el-table-column prop="created_at" label="添加时间" align="center"
min-width="160"></el-table-column>
<el-table-column prop="" label="操作" width="100" align="center" fixed="right">
<el-table-column prop="" label="操作" align="center" fixed="right" width="220">
<template #default="scoped">
<div class="mht-operations">
@ -104,12 +103,12 @@
<div class="dialog-box">
<el-table ref="appTableRef" :data="logList" style="width: 100%" max-height="500px" row-key="id"
@selection-change="appSelectionChange">
@selection-change="appSelectionChange" v-loading="tableLoading">
<template #empty>
<span v-if="tableLoading">加载中...</span>
<span v-if="!tableLoading">暂无数据</span>
</template>
<el-table-column type="selection" width="55" :reserve-selection="true" :selectable="isSelectable" />
<el-table-column type="selection" width="55" :reserve-selection="true" />
<el-table-column prop="avatar" label="头像" align="center">
<template #default="scoped">
<el-image style="width: 30px;display: block;margin: auto;border-radius: 4px;"
@ -214,9 +213,14 @@ const query = reactive({
const total = ref(0)
const mpTable = ref([])
const getTable = async () => {
const res = await robotList(query)
robotCards.value = res.list
total.value = res.total
tableLoading.value = true
const res = await robotList(query).then(res => {
robotCards.value = res.list
total.value = res.total
tableLoading.value = false
}).catch(() => {
tableLoading.value = false
})
}
const listLoad = () => {
@ -329,16 +333,16 @@ const handleDelete = (item, index) => {
}
)
.then(async () => {
ElNotification({
message: '删除中,请稍等',
type: 'success',
duration: 2000
})
await deleteRobot({
ids: String(item.id)
})
// getGroups()
robotCards.value.splice(index, 1)
ElNotification({
message: '删除成功',
type: 'success',
duration: 2000
})
})
.catch(() => {
@ -381,7 +385,6 @@ const openLog = async () => {
dialogLog.value = true
tableLoading.value = true
const res = await appList(logQuery)
tableLoading.value = false
logList.value = res.list
total.value = res.total
@ -392,6 +395,8 @@ const openLog = async () => {
page: 1,
page_size: 100
})
tableLoading.value = false
bandAppIds.value = res2.list.map(item => item.id)
// appSelects
appSelects = [...bandAppIds.value]

View File

@ -11,10 +11,9 @@
@selection-change="handleSelectionChange" row-key="user_id">
<template #empty>
<span v-if="tableLoading">加载中...</span>
<span v-if="!tableLoading && query.robot_id">暂无数据</span>
<span v-if="!query.robot_id && !tableLoading" style="font-weight: bold;">请选择一个小程序</span>
<span v-if="!tableLoading">暂无数据</span>
</template>
<el-table-column type="selection" width="55" :reserve-selection="true" />
<!-- <el-table-column type="selection" width="55" :reserve-selection="true" /> -->
<el-table-column prop="avatar" label="头像" align="center">
<template #default="scoped">
<el-image style="width: 30px;display: block;margin: auto;border-radius: 4px;"
@ -26,6 +25,14 @@
<el-table-column prop="app_secret" label="AppSecret" />
<el-table-column prop="template_id" label="模版ID" />
<el-table-column prop="description" label="描述" />
<el-table-column prop="message_total" label="会话量" />
<el-table-column prop="check_status_text" label="状态">
<template #default="scoped">
<el-tag v-if="scoped.row.check_status_text"
:type="scoped.row.check_status_text === '正常' ? 'success' : 'danger'">{{
scoped.row.check_status_text }}</el-tag>
</template>
</el-table-column>
<el-table-column label="意图关键字" align="center">
<template #default="scoped">
<div class="mht-operations">
@ -36,7 +43,7 @@
<el-table-column prop="created_at" label="添加时间" align="center"
min-width="160"></el-table-column>
<el-table-column prop="" label="操作" width="100" align="center" fixed="right">
<el-table-column prop="" label="操作" align="center" fixed="right" width="280">
<template #default="scoped">
<div class="mht-operations">
@ -49,7 +56,7 @@
</el-button>
<el-button type="primary" link @click="handleDetail(scoped.row)">
详情
进入会话
</el-button>
<el-button type="danger" link @click="handeleDelete(scoped.row)">
@ -89,11 +96,11 @@
<el-input v-model="ruleForm.template_id" placeholder="请输入模板ID" size="large" />
</el-form-item>
<el-form-item label="头像" prop="avatar">
<el-form-item label="头像">
<Upload v-model="ruleForm.avatar" type="image" accept="image/*" :action="robotHost"
@change="changeFile" @success="uploadSuccess" @error="uploadError"></Upload>
</el-form-item>
<el-form-item label="小程序描述" prop="description">
<el-form-item label="小程序描述">
<el-input type="textarea" row="3" v-model="ruleForm.description" placeholder="请输入小程序描述"
size="large" />
</el-form-item>
@ -145,9 +152,15 @@
</template>
</el-dialog>
<el-dialog v-model="qrDialog" title="小程序二维码" width="500px" align-center :before-close="handleClose">
<div class="dialog-box" style="text-align: center;">
<img :src="qrCode" style="width: 200px;" alt="">
<el-dialog v-model="qrDialog" title="小程序二维码" width="610px" align-center :before-close="handleClose">
<div class="dialog-box">
<div>小程序路径</div>
<el-space style="margin: 20px 0">
<el-input v-model="qrPath" style="width: 400px;margin-right: 10px;" placeholder="请输入小程序路径" />
<el-button type="primary" @click="getQrCode">获取二维码</el-button>
</el-space>
<img :src="qrCode" style="width: 200px;margin: auto;display: block;" alt="">
</div>
<template #footer>
@ -292,9 +305,14 @@ const query = reactive({
let robtoTotal = 0
const mpTable = ref([])
const getTable = async () => {
const res = await appList(query)
robotCards.value = res.list
total.value = res.total
tableLoading.value = true
const res = await appList(query).then(res => {
robotCards.value = res.list
total.value = res.total
tableLoading.value = false
}).catch(() => {
tableLoading.value = false
})
}
@ -395,15 +413,17 @@ const handeleDelete = (item, index) => {
}
)
.then(async () => {
await deleteRobot({
ids: String(item.id)
})
// getGroups()
robotCards.value.splice(index, 1)
ElNotification({
message: '删除中,请稍等',
message: '删除成功',
type: 'success',
duration: 2000
})
await deleteRobot(item.id)
// getGroups()
robotCards.value.splice(index, 1)
})
.catch(() => {
@ -489,13 +509,20 @@ const handleDetail = (row) => {
const qrCode = ref('')
const qrDialog = ref(false)
const qrPath = ref('pages/contact/index')
let qrRow = {}
const handleqr = (row) => {
qrCode.value = ''
qrDialog.value = true
qrRow = row
}
const getQrCode = () => {
getQr({
"app_id": row.app_id,
"app_secret": row.app_secret,
"path": "pages/contact/index"
"app_id": qrRow.app_id,
"app_secret": qrRow.app_secret,
"path": qrPath.value
}).then((res => {
qrDialog.value = true
qrCode.value = `data:image/png;base64,${res.data}`
}))
}