开发完成聊天页面功能

This commit is contained in:
hejin 2025-08-24 01:46:22 +08:00
parent 2cc55b44c5
commit 4ff482bbbf
11 changed files with 280 additions and 12 deletions

View File

@ -1,3 +1,4 @@
NODE_ENV='development'
VITE_APP_TITLE='开发环境'
VITE_APP_BASE_API='http://114.132.197.85:8099'
VITE_APP_SCOKET='ws://114.132.197.85:8099/ws/asset/'

View File

@ -1,3 +1,4 @@
NODE_ENV='production'
VITE_APP_TITLE='生产环境'
VITE_APP_BASE_API=''
VITE_APP_BASE_API='http://114.132.197.85:8099'
VITE_APP_SCOKET='ws://114.132.197.85:8099/ws/asset/'

View File

@ -94,3 +94,21 @@ export const appMaxCatgIdApi = (catgName) => {
export const articlePageApi = (params) => {
return request.get('/web/newsPageList', {params})
}
/**
* @function 获取聊天窗口信息
* @param {string} cusCode 设备唯一值
* @param {string} prodId 产品ID
**/
export const msgListApi = (data) => {
return request.post('/web/chatMain',data)
}
/**
* @function 保存消息
* @param {string} id
* @param {array} jsonArray 最新的消息列表
**/
export const saveMsg = (data) => {
return request.post('/web/saveMessage', data)
}

View File

@ -1,15 +1,143 @@
<template>
<view class="pages">
在线聊天
<scroll-view
class="scroll-box"
:scroll-y="true"
:scroll-top="msgScroll"
>
<view
class="msg"
:class="item.dataFrom === 'customer' ? 'oneself' : 'opposite'"
v-for="(item,index) in useScoketMsg().msgList"
:key="index"
>
{{item.content}}
</view>
</scroll-view
>
<view class="footer">
<view class="send-box">
<uni-easyinput
:inputBorder="false"
:clearable="false"
:focus="inputFocus"
v-model="sendVal"
trim="both"
:placeholder="$t('online.placeholder')"
type="search"
@confirm="send"
>
<template #right>
<image
class="search-icon"
src="@/assets/images/icon/send.png"
@click="send"
>
</image>
</template>
</uni-easyinput>
</view>
</view>
</view>
</template>
<script setup>
import { onLoad } from '@dcloudio/uni-app';
import { ref } from 'vue';
import { onLoad, onUnload } from '@dcloudio/uni-app';
import { ref, nextTick } from 'vue';
import { useScoketMsg } from '@/stores/index.js';
const inputFocus = ref(true)
const sendVal = ref('')
const send = () => {
if (!sendVal.value) {
return
}
useScoketMsg().send(`customer,${sendVal.value}`).then(() => {
sendVal.value = ''
inputFocus.value = false
nextTick(() => {
inputFocus.value = true
})
})
}
const msgScroll = ref(9999)
const scrollJump = () => {
nextTick(() => {
msgScroll.value += 99
})
}
useScoketMsg().msgCallback = scrollJump
const prodId = ref('')
onUnload(() => {
useScoketMsg().closeScoket()
})
onLoad(async(options) => {
prodId.value = options.prodId
await useScoketMsg().getMsgList(prodId.value)
useScoketMsg().scoketInit()
scrollJump()
})
</script>
<style lang="scss" scoped>
.pages {
/* #ifdef H5 */
min-height: calc(100vh - 44px);
/* #endif */
background: #f8f9fa;
.scroll-box {
width: 100%;
height: calc(100vh - 160rpx);
/* #ifdef H5 */
height: calc(100vh - 160rpx - 44px);
/* #endif */
padding: 38rpx 28rpx;
box-sizing: border-box;
.msg {
width: max-content;
max-width: 80%;
height: min-content;
margin-bottom: 46rpx;
padding: 23rpx 34rpx;
word-break: break-word;
border-radius: 8rpx;
border: 2rpx solid #eeeeef;
font-size: 28rpx;
}
.opposite {
color: #0d0e0e;
background-color: #fff;
}
.oneself {
margin-left: auto;
color: #ffffff;
background-color: #6b98fe;
}
}
.footer {
width: 100%;
height: 160rpx;
padding: 16rpx;
background-color: #eaecf1;
.send-box {
::v-deep .uni-easyinput {
border-radius: 12rpx;
border: 2rpx solid #015fe8;
overflow: hidden;
.uni-easyinput__content {
padding: 0 15rpx;
}
}
.search-icon {
width: 40rpx;
height: 40rpx;
margin-right: 16rpx;
}
}
}
}
</style>

View File

@ -173,7 +173,7 @@
<view @click="tabsChange(2)">
{{$t('common.sendInquiry')}}
</view>
<view>
<view @click="goOnline">
{{$t('common.chatNow')}}
</view>
</view>
@ -312,6 +312,12 @@
{id:121113123,title: 'SINOTRUK HOWO Tractor Truck Head',mainPic:'https://dianliang123.oss-cn-qingdao.aliyuncs.com/user/2025/07/09/55979a0deee24031a38e934c6b06ca20.jpg'}
])
const goOnline = () => {
uni.navigateTo({
url: `/application/online?prodId=${info.value.id}`
})
}
onLoad((options) => {
id.value = options.id
getInfo()

Binary file not shown.

After

Width:  |  Height:  |  Size: 764 B

View File

@ -2,15 +2,28 @@
<view>
<view class="anchor"></view>
<slot></slot>
<SuspensionBtn @ClickTop="ClickTop" @clickMsg="onlineModalShow=true"/>
<OnlineModal v-if="onlineModalShow" @close="onlineModalShow=false" />
<template v-if="noModal">
<SuspensionBtn @ClickTop="ClickTop" @clickMsg="onlineModalShow=true"/>
<OnlineModal v-if="onlineModalShow" @close="onlineModalShow=false" />
</template>
</view>
</template>
<script setup>
import { ref } from 'vue';
import { ref, watch, computed } from 'vue';
import { useScroll } from '@/stores/index.js';
const currentPage = computed(() => {
let arr = getCurrentPages()
return arr[arr.length - 1]
})
const noModalPage = [
'application/online'
]
const noModal = computed(() => {
return noModalPage.indexOf(currentPage.value.route) === -1
})
const pageRef = ref()
const onlineModalShow = ref(false)
const onlineModalRef = ref()

View File

@ -124,6 +124,10 @@
"footer": {
"contactUs": "Contact us"
},
"online": {
"placeholder": "Send your requiremen",
"Retry": "Please try again later"
},
"seo": {
"news": {
"title": "China National Heavy Duty Truck Group Co., Ltd. - News List",

View File

@ -124,6 +124,10 @@
"footer": {
"contactUs": "联系我们"
},
"online": {
"placeholder": "Send your requiremen",
"Retry": "请稍后重试"
},
"seo": {
"news": {
"title": "中国重汽豪沃销售有限公司 - 新闻列表",

View File

@ -112,7 +112,7 @@
"navigationStyle": "custom",
"navigationBarTextStyle": "black",
"navigationBarTitleText": "China Trailer, Truck, Trailer Parts, Truck Parts Manufacturers and Factory - Price - SINOTRUCK",
"navigationBarBackgroundColor": "#F8F8F8",
"navigationBarBackgroundColor": "#ffffff",
"backgroundColor": "#F8F8F8"
}
}

View File

@ -1,6 +1,8 @@
import { defineStore } from 'pinia';
import { ref } from 'vue';
import { menuCategoryApi } from '@/api/index.js';
import { useI18n } from 'vue-i18n';
import { menuCategoryApi, msgListApi, saveMsg } from '@/api/index.js';
import { getUuid } from '@/utils/tool.js';
export const useIndex = defineStore('index',()=>{
const routeMap = {
@ -60,3 +62,94 @@ export const useScroll = defineStore('scroll', () => {
sendCallback
}
})
export const useScoketMsg = defineStore('scoketMsg', () => {
const { t } = useI18n()
const msgCallback = ref(null)
const onlyId = ref(uni.getStorageSync('onlyId'))
if (!onlyId.value) {
onlyId.value = getUuid()
uni.setStorageSync('onlyId', onlyId.value)
}
const scoket = ref(null)
const count = ref(0)
const msgList = ref([])
const notices = ref([])
const chatMain = ref({})
const getMsgList = (prodId) => {
const data = {
cusCode: onlyId.value,
prodId
}
return msgListApi(data).then(({data:res}) => {
chatMain.value = res.data
if (res.data.jsonArray) {
msgList.value = res.data.jsonArray
}
})
}
const scoketInit = () => {
scoket.value = uni.connectSocket({
url: `${import.meta.env.VITE_APP_SCOKET}${onlyId.value}`,
success: () => {
console.log('创建链接成功')
},
fail: (err) => {
console.log('创建失败',err)
}
})
scoket.value.onMessage((e) => {
if (e.data.startsWith("C")) {
count.value = e.data;
}
else if (e.data.startsWith("系统通知")){
notices.value.push(e.data);
}else if (e.data.startsWith("close")){
console.log(e.data)
} else {
msgList.value.push(JSON.parse(e.data))
msgCallback.value && msgCallback.value()
saveMsg({id:chatMain.value.id,jsonArray:msgList.value})
}
})
scoket.value.onError((err) => {
console.log('链接错误',err)
})
}
const send = (text) => {
return new Promise((reslove,reject) => {
scoket.value.send({
data: text,
success: () => {
reslove()
console.log('发送成功')
},
fail: (err) => {
uni.$showTost(t('online.Retry'))
reject(err)
}
})
})
}
const closeScoket = () => {
if (scoket.value) {
scoket.value.close()
scoket.value = null
}
}
return {
scoket,
scoketInit,
closeScoket,
msgList,
getMsgList,
chatMain,
send,
msgCallback
}
})