This commit is contained in:
@zuopngfei 2025-10-20 18:54:15 +08:00
parent 1dbf6ffa5a
commit c48931dd31
10 changed files with 60 additions and 32 deletions

12
components.d.ts vendored
View File

@ -12,10 +12,13 @@ declare module 'vue' {
ElButton: typeof import('element-plus/es')['ElButton']
ElCard: typeof import('element-plus/es')['ElCard']
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
ElCol: typeof import('element-plus/es')['ElCol']
ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
ElContainer: typeof import('element-plus/es')['ElContainer']
ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
ElDialog: typeof import('element-plus/es')['ElDialog']
ElDrawer: typeof import('element-plus/es')['ElDrawer']
ElForm: typeof import('element-plus/es')['ElForm']
ElFormItem: typeof import('element-plus/es')['ElFormItem']
ElHeader: typeof import('element-plus/es')['ElHeader']
@ -23,21 +26,30 @@ declare module 'vue' {
ElImage: typeof import('element-plus/es')['ElImage']
ElInput: typeof import('element-plus/es')['ElInput']
ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
ElLink: typeof import('element-plus/es')['ElLink']
ElMain: typeof import('element-plus/es')['ElMain']
ElMenu: typeof import('element-plus/es')['ElMenu']
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
ElOption: typeof import('element-plus/es')['ElOption']
ElPagination: typeof import('element-plus/es')['ElPagination']
ElPopover: typeof import('element-plus/es')['ElPopover']
ElProgress: typeof import('element-plus/es')['ElProgress']
ElRadio: typeof import('element-plus/es')['ElRadio']
ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
ElRow: typeof import('element-plus/es')['ElRow']
ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
ElSelect: typeof import('element-plus/es')['ElSelect']
ElSelectV2: typeof import('element-plus/es')['ElSelectV2']
ElSkeleton: typeof import('element-plus/es')['ElSkeleton']
ElTable: typeof import('element-plus/es')['ElTable']
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
ElTabPane: typeof import('element-plus/es')['ElTabPane']
ElTabs: typeof import('element-plus/es')['ElTabs']
ElTag: typeof import('element-plus/es')['ElTag']
ElTimePicker: typeof import('element-plus/es')['ElTimePicker']
ElTooltip: typeof import('element-plus/es')['ElTooltip']
ElTour: typeof import('element-plus/es')['ElTour']
ElTourStep: typeof import('element-plus/es')['ElTourStep']
IndexUser: typeof import('./src/components/TagClass/indexUser.vue')['default']
KeyWords: typeof import('./src/components/KeyWords/index.vue')['default']
MaterialPublic: typeof import('./src/components/MaterialPublic/index.vue')['default']

View File

@ -3,14 +3,20 @@ import request from '@/utils/request'
// export const getUserList = (params) => {
// return request({
// url: `admin/app/users`,
// method: 'get',
// params
// })
// }
export const getUserList = (params) => {
return request({
url: `admin/app/users`,
url: `admin/messages/latest`,
method: 'get',
params
})
}
export const send_message = (data) => {
return request({
url: `admin/send_message`,

View File

@ -1,12 +1,12 @@
<template>
<div v-for="(element, index) in list">
<div class="materia-element" :class="{ robotSend : element.sender_id != sendeInfo.userInfo.user_id }">
<el-image v-if="element.sender_id == sendeInfo.robotInfo.wx_id" class="tobot-image" :src="sendeInfo.robotInfo.head_url"></el-image>
<template v-else>
<!-- <el-image v-if="element.sender_id == sendeInfo.robotInfo.wx_id" class="tobot-image" :src="sendeInfo.robotInfo.head_url"></el-image>
<template v-else> -->
<el-image v-if="sendeInfo.userInfo.user_id != element.sender_id" class="tobot-image" :src="robot_avatar"></el-image>
<el-image v-if="sendeInfo.userInfo.user_id == element.sender_id" class="tobot-image" :src="sendeInfo.userInfo.user_avatar"></el-image>
<!-- <span class="tobot-image text-logo" v-else> {{ element.sender_name.charAt(0) }} </span> -->
</template>
<!-- </template> -->
<div class="materia-info">
<!-- <span class="robot-name">{{ element.sender_name }}</span> -->
<!-- <span v-if="element.sender_id != sendeInfo.userInfo.user_id" class="robot-name">{{ sendeInfo.robotInfo.name }}</span>

View File

@ -2,10 +2,10 @@
<div style="width: 100%;">
<el-input v-model="centent" suffix-icon="Search" @input="inputSearch" placeholder="搜索"></el-input>
<ul v-infinite-scroll="load" class="infinite-list" style="overflow: auto" :style="'height:' + height" :infinite-scroll-immediate="false" infinite-scroll-distance="5">
<li v-for="item in cardlist" :key="item.user_id" class="infinite-list-item" :class="{ active: item.active }"
<li v-for="item in cardlist" :key="item.sender_id" class="infinite-list-item" :class="{ active: item.active }"
@click="handleItem(item)">
<el-image class="user-avatar" :src="item.user_avatar"></el-image>
<span class="nickname">{{ item.user_name }}</span>
<el-image class="user-avatar" :src="item.sender_avatar"></el-image>
<span class="nickname">{{ item.sender_name }}</span>
<span class="sex">
<!-- <el-icon v-if="item.sex == '男'" style="color: rgb(121.3, 187.1, 255);">
<svg class="icon" aria-hidden="true">
@ -67,7 +67,7 @@ const handleItem = (row) => {
let arr = []
props.cardlist.forEach((el) => {
if (el.active === true) {
arr.push(el.user_id)
arr.push(el.sender_id)
}
})
setTimeout(() => {
@ -81,8 +81,8 @@ const handleItem = (row) => {
// true
row.active = true
// emitcardlistactive
emits('change', row.user_id)
emits("update:modelValue", row.user_id)
emits('change', row.sender_id)
emits("update:modelValue", row.sender_id)
}
}

View File

@ -14,7 +14,7 @@ const goHome = () => {
<template>
<div class="logo">
SCRM
小程序聊天管理
</div>
</template>

View File

@ -1,3 +1,3 @@
export default {
title: '猕猴桃 Scrm', //项目名称
title: '小程序聊天管理', //项目名称
}

View File

@ -69,7 +69,7 @@ const sendeInfo = reactive({
//
const msgQuery = reactive({
page: 1,
page_size: 190,
page_size: 100,
app_id: route.query.app_id,
user_id: ''
})
@ -81,22 +81,24 @@ const isAutoScroll = ref(true) // 是否自动滚动到底部
const messageTimer = ref(null) //
//
const onSelectUser = (id) => {
const u = userList.value.find((it) => it.user_id == id)
const onSelectUser = async (id) => {
const u = userList.value.find((it) => it.sender_id == id)
if (u) {
userList.value.forEach((it) => (it.active = it.user_id === id))
userList.value.forEach((it) => (it.active = it.sender_id === id))
activeUser.value = u
sendeInfo.userInfo = { user_id: u.user_id, user_name: u.user_name, user_avatar: u.user_avatar }
sendeInfo.userInfo = { user_id: u.sender_id, user_name: u.sender_name, user_avatar: u.sender_avatar }
sendeInfo.robotInfo = { wx_id: 'robot', head_url: mihoutai }
//
messages.value = []
msgQuery.page = 1
msgQuery.user_id = u.user_id
msgQuery.user_id = u.sender_id
noMoreMessages.value = false
// await
scrollToBottom()
// await scrollToBottom()
getMessages()
//
@ -225,7 +227,7 @@ const loadMoreMessages = () => {
//
const send = () => {
if (!activeUser.value.user_id) {
if (!activeUser.value.sender_id) {
ElMessage({ type: 'warning', message: '请先选择一个联系人' })
return
}
@ -259,7 +261,7 @@ const send = () => {
messages: content
}),
msg_type: 1,
to_user_id: activeUser.value.user_id
to_user_id: activeUser.value.sender_id
}).then(() => {
msg._sending = false
msg._failed = false
@ -312,13 +314,13 @@ const handleImageChange = (e) => {
form.append('file', file)
form.append('app_id', route.query.app_id)
form.append('msg_type', 2)
form.append('to_user_id', activeUser.value.user_id)
form.append('to_user_id', activeUser.value.sender_id)
uploadFile(form, import.meta.env.VITE_APP_BASE_API + 'admin/upload/image').then((resp) => {
send_message({
app_id: route.query.app_id,
content: JSON.stringify({ messages: import.meta.env.VITE_APP_BASE_API + resp.preview_image_url }),
msg_type: 2,
to_user_id: activeUser.value.user_id
to_user_id: activeUser.value.sender_id
}).then(() => {
msg._sending = false
msg._failed = false
@ -343,7 +345,7 @@ const handleRetry = (id) => {
app_id: route.query.app_id,
content: msg.content.content,
msg_type: 1,
to_user_id: activeUser.value.user_id
to_user_id: activeUser.value.sender_id
}).then(() => {
msg._sending = false
}).catch(() => {
@ -356,7 +358,7 @@ const handleRetry = (id) => {
form.append('file', msg.content.file)
form.append('app_id', route.query.app_id)
form.append('msg_type', 2)
form.append('to_user_id', activeUser.value.user_id)
form.append('to_user_id', activeUser.value.sender_id)
send_message(form).then(() => {
msg._sending = false
}).catch(() => {
@ -399,8 +401,8 @@ const getUsers = (append = false) => {
userList.value = res.list || []
}
//
if (!append && userList.value.length && !activeUser.value.user_id) {
onSelectUser(userList.value[0].user_id)
if (!append && userList.value.length && !activeUser.value.sender_id) {
onSelectUser(userList.value[0].sender_id)
}
})
}
@ -459,7 +461,7 @@ onUnmounted(() => {
//
watch(activeUser, (newVal) => {
if (newVal.user_id) {
if (newVal.sender_id) {
restartMessageTimer()
} else {
stopMessageTimer()

View File

@ -12,7 +12,7 @@ import { getTime } from '@/utils/time';
<div class="box">
<div class="bottom">
<h3 class="title">尊敬的用户{{ getTime() }} </h3>
<p class="subtitle">欢迎使用 猕猴桃 SCRM 系统</p>
<p class="subtitle">欢迎使用 小程序聊天管理 系统</p>
</div>
</div>
</el-card>

View File

@ -40,7 +40,7 @@
<el-col :span="12">
<div class="row-login">
<div class="login-form">
<h2>SCRM 登录</h2>
<h2>小程序聊天管理 登录</h2>
<el-form ref="ruleFormRef" :model="ruleForm" :rules="rules" label-width="0">
<el-form-item label="" prop="username" style="margin-bottom: 30px;">
<el-input v-model="ruleForm.username" placeholder="用户名" prefix-icon="User" size="large" />

View File

@ -94,7 +94,9 @@
<el-form-item label="小程序ID" prop="app_id">
<el-input v-model="ruleForm.app_id" placeholder="请输入小程序ID" size="large" />
</el-form-item>
<el-form-item label="App_Secret" prop="app_secret">
<el-input v-model="ruleForm.app_secret" placeholder="请输入app_secret" size="large" />
</el-form-item>
<el-form-item label="头像" prop="avatar">
<Upload v-model="ruleForm.avatar" type="image" accept="image/*" :action="robotHost"
@ -206,6 +208,11 @@ const rules = ref({
required: true,
message: '请上传小程序头像',
trigger: 'change',
}],
app_secret: [{
required: true,
message: '请上传小程序头像',
trigger: 'change',
}]
})
const query = reactive({
@ -260,7 +267,8 @@ const submitRobot = async () => {
description: ruleForm.value.description,
name: ruleForm.value.name,
app_id: ruleForm.value.app_id,
avatar: ruleForm.value.avatar
avatar: ruleForm.value.avatar,
app_secret: ruleForm.value.app_secret
})
// editItem = ruleForm.value
// robotCards.value[editIndex] = editItem