开发完成聊天页面功能
This commit is contained in:
parent
2cc55b44c5
commit
4ff482bbbf
@ -1,3 +1,4 @@
|
|||||||
NODE_ENV='development'
|
NODE_ENV='development'
|
||||||
VITE_APP_TITLE='开发环境'
|
VITE_APP_TITLE='开发环境'
|
||||||
VITE_APP_BASE_API='http://114.132.197.85:8099'
|
VITE_APP_BASE_API='http://114.132.197.85:8099'
|
||||||
|
VITE_APP_SCOKET='ws://114.132.197.85:8099/ws/asset/'
|
||||||
@ -1,3 +1,4 @@
|
|||||||
NODE_ENV='production'
|
NODE_ENV='production'
|
||||||
VITE_APP_TITLE='生产环境'
|
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/'
|
||||||
@ -94,3 +94,21 @@ export const appMaxCatgIdApi = (catgName) => {
|
|||||||
export const articlePageApi = (params) => {
|
export const articlePageApi = (params) => {
|
||||||
return request.get('/web/newsPageList', {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)
|
||||||
|
}
|
||||||
@ -1,15 +1,143 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="pages">
|
<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>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onLoad } from '@dcloudio/uni-app';
|
import { onLoad, onUnload } from '@dcloudio/uni-app';
|
||||||
import { ref } from 'vue';
|
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>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<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>
|
</style>
|
||||||
@ -173,7 +173,7 @@
|
|||||||
<view @click="tabsChange(2)">
|
<view @click="tabsChange(2)">
|
||||||
{{$t('common.sendInquiry')}}
|
{{$t('common.sendInquiry')}}
|
||||||
</view>
|
</view>
|
||||||
<view>
|
<view @click="goOnline">
|
||||||
{{$t('common.chatNow')}}
|
{{$t('common.chatNow')}}
|
||||||
</view>
|
</view>
|
||||||
</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'}
|
{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) => {
|
onLoad((options) => {
|
||||||
id.value = options.id
|
id.value = options.id
|
||||||
getInfo()
|
getInfo()
|
||||||
|
|||||||
BIN
src/assets/images/icon/send.png
Normal file
BIN
src/assets/images/icon/send.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 764 B |
@ -2,15 +2,28 @@
|
|||||||
<view>
|
<view>
|
||||||
<view class="anchor"></view>
|
<view class="anchor"></view>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
<SuspensionBtn @ClickTop="ClickTop" @clickMsg="onlineModalShow=true"/>
|
<template v-if="noModal">
|
||||||
<OnlineModal v-if="onlineModalShow" @close="onlineModalShow=false" />
|
<SuspensionBtn @ClickTop="ClickTop" @clickMsg="onlineModalShow=true"/>
|
||||||
|
<OnlineModal v-if="onlineModalShow" @close="onlineModalShow=false" />
|
||||||
|
</template>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue';
|
import { ref, watch, computed } from 'vue';
|
||||||
import { useScroll } from '@/stores/index.js';
|
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 pageRef = ref()
|
||||||
const onlineModalShow = ref(false)
|
const onlineModalShow = ref(false)
|
||||||
const onlineModalRef = ref()
|
const onlineModalRef = ref()
|
||||||
|
|||||||
@ -124,6 +124,10 @@
|
|||||||
"footer": {
|
"footer": {
|
||||||
"contactUs": "Contact us"
|
"contactUs": "Contact us"
|
||||||
},
|
},
|
||||||
|
"online": {
|
||||||
|
"placeholder": "Send your requiremen",
|
||||||
|
"Retry": "Please try again later"
|
||||||
|
},
|
||||||
"seo": {
|
"seo": {
|
||||||
"news": {
|
"news": {
|
||||||
"title": "China National Heavy Duty Truck Group Co., Ltd. - News List",
|
"title": "China National Heavy Duty Truck Group Co., Ltd. - News List",
|
||||||
|
|||||||
@ -124,6 +124,10 @@
|
|||||||
"footer": {
|
"footer": {
|
||||||
"contactUs": "联系我们"
|
"contactUs": "联系我们"
|
||||||
},
|
},
|
||||||
|
"online": {
|
||||||
|
"placeholder": "Send your requiremen",
|
||||||
|
"Retry": "请稍后重试"
|
||||||
|
},
|
||||||
"seo": {
|
"seo": {
|
||||||
"news": {
|
"news": {
|
||||||
"title": "中国重汽豪沃销售有限公司 - 新闻列表",
|
"title": "中国重汽豪沃销售有限公司 - 新闻列表",
|
||||||
|
|||||||
@ -112,7 +112,7 @@
|
|||||||
"navigationStyle": "custom",
|
"navigationStyle": "custom",
|
||||||
"navigationBarTextStyle": "black",
|
"navigationBarTextStyle": "black",
|
||||||
"navigationBarTitleText": "China Trailer, Truck, Trailer Parts, Truck Parts Manufacturers and Factory - Price - SINOTRUCK",
|
"navigationBarTitleText": "China Trailer, Truck, Trailer Parts, Truck Parts Manufacturers and Factory - Price - SINOTRUCK",
|
||||||
"navigationBarBackgroundColor": "#F8F8F8",
|
"navigationBarBackgroundColor": "#ffffff",
|
||||||
"backgroundColor": "#F8F8F8"
|
"backgroundColor": "#F8F8F8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { ref } from 'vue';
|
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',()=>{
|
export const useIndex = defineStore('index',()=>{
|
||||||
const routeMap = {
|
const routeMap = {
|
||||||
@ -60,3 +62,94 @@ export const useScroll = defineStore('scroll', () => {
|
|||||||
sendCallback
|
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
|
||||||
|
}
|
||||||
|
})
|
||||||
Loading…
Reference in New Issue
Block a user