This commit is contained in:
parent
0084fe8aa1
commit
b1b68d68ef
|
@ -7,6 +7,8 @@ const config = {
|
|||
// #endif
|
||||
// #ifndef H5
|
||||
host: 'http://91f.xyz:8080',
|
||||
// host: 'https://b433d23.r24.cpolar.top/',
|
||||
// host: 'http://hvw2rn.natappfree.cc',
|
||||
// #endif
|
||||
// 支付方式配置
|
||||
payType: {
|
||||
|
|
|
@ -1766,6 +1766,12 @@ const util = {
|
|||
success: (res) => {
|
||||
if (res && res.result) {
|
||||
let result = JSON.parse(res.result)
|
||||
if (result.type == 'ADDFRIEND') {
|
||||
uni.navigateTo({
|
||||
url: `/pages/news/addFriend?account=${result.account}`
|
||||
});
|
||||
return
|
||||
}
|
||||
if (result.key == 'user') {
|
||||
// 跳转申请添加好友界面
|
||||
uni.navigateTo({
|
||||
|
|
|
@ -99,7 +99,6 @@ function toCustomer() {
|
|||
|
||||
util.toChat(param)
|
||||
|
||||
|
||||
uni.navigateTo({
|
||||
url: util.setUrl('/pages/news/chat/chat', param)
|
||||
})
|
||||
|
@ -131,10 +130,10 @@ function toCustomer() {
|
|||
</view>
|
||||
</view>
|
||||
|
||||
<!-- <view class="option ver" @click="toCustomer">
|
||||
<view class="option ver" @click="toCustomer">
|
||||
<image class="wh30" src="/static/customer-service.png" mode="aspectFit" />
|
||||
<text class="text mt10">客服</text>
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 下单 -->
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
import {
|
||||
useStore,
|
||||
} from 'vuex'
|
||||
// api
|
||||
import api from '@/api/index.js'
|
||||
// 工具库
|
||||
import util from '@/common/js/util';
|
||||
// 代理
|
||||
|
|
|
@ -1,57 +1,71 @@
|
|||
<script setup>
|
||||
/**
|
||||
* 个人中心 商城
|
||||
*/
|
||||
// 底部菜单
|
||||
import {
|
||||
ref,
|
||||
computed,
|
||||
} from 'vue'
|
||||
import {
|
||||
onReachBottom,
|
||||
onPullDownRefresh,
|
||||
onShow,
|
||||
onLoad,
|
||||
onPageScroll
|
||||
} from '@dcloudio/uni-app';
|
||||
import {
|
||||
useStore
|
||||
} from 'vuex'
|
||||
// 顶部状态栏
|
||||
import statusBar from '@/components/header/statusBar'
|
||||
/**
|
||||
* 个人中心 商城
|
||||
*/
|
||||
// 底部菜单
|
||||
import {
|
||||
ref,
|
||||
computed,
|
||||
} from 'vue'
|
||||
import {
|
||||
onReachBottom,
|
||||
onPullDownRefresh,
|
||||
onShow,
|
||||
onLoad,
|
||||
onPageScroll
|
||||
} from '@dcloudio/uni-app';
|
||||
import {
|
||||
useStore
|
||||
} from 'vuex'
|
||||
// 顶部状态栏
|
||||
import statusBar from '@/components/header/statusBar'
|
||||
|
||||
// 产品列表
|
||||
import productList from '@/components/shop/productList/productList';
|
||||
// 底部导航
|
||||
import footerMneu from '@/components/footerMenu/footerMenu'
|
||||
//
|
||||
import util from '@/common/js/util';
|
||||
//
|
||||
const store = useStore()
|
||||
// 用户信息
|
||||
const userinfo = computed(() => {
|
||||
let result = store.state.userinfo || {}
|
||||
return result
|
||||
// 产品列表
|
||||
import productList from '@/components/shop/productList/productList';
|
||||
// 底部导航
|
||||
import footerMneu from '@/components/footerMenu/footerMenu'
|
||||
//
|
||||
import util from '@/common/js/util';
|
||||
//
|
||||
const store = useStore()
|
||||
// 用户信息
|
||||
const userinfo = computed(() => {
|
||||
let result = store.state.userinfo || {}
|
||||
return result
|
||||
})
|
||||
// 是否显示顶部
|
||||
const showHeader = ref(false)
|
||||
|
||||
onPageScroll((ev) => {
|
||||
if (ev.scrollTop > 44) showHeader.value = true
|
||||
else showHeader.value = false
|
||||
})
|
||||
|
||||
// 跳转
|
||||
function link(url) {
|
||||
uni.navigateTo({
|
||||
url,
|
||||
})
|
||||
// 是否显示顶部
|
||||
const showHeader = ref(false)
|
||||
}
|
||||
function toCustomer() {
|
||||
let param = {};
|
||||
param.type = 'C2C'
|
||||
param.name = `${props.detail.merName}`
|
||||
param.msgId = `${rs.data.serviceId}`
|
||||
param.isCustomer = true
|
||||
|
||||
onPageScroll((ev) => {
|
||||
if (ev.scrollTop > 44) showHeader.value = true
|
||||
else showHeader.value = false
|
||||
util.toChat(param)
|
||||
|
||||
|
||||
uni.navigateTo({
|
||||
url: util.setUrl('/pages/news/chat/chat', param)
|
||||
})
|
||||
|
||||
// 跳转
|
||||
function link(url) {
|
||||
uni.navigateTo({
|
||||
url,
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="app">
|
||||
<view class="apex" :class="{'active': showHeader}">
|
||||
<view class="apex" :class="{ 'active': showHeader }">
|
||||
<statusBar />
|
||||
<view class="head rows">
|
||||
<view class=""></view>
|
||||
|
@ -80,8 +94,7 @@
|
|||
|
||||
<view class="df">
|
||||
<!-- 客服 -->
|
||||
<image class="ml20 wh40" @click="link('customer_service')" src="@/static/mine-kefu.png"
|
||||
mode="aspectFill" />
|
||||
<image class="ml20 wh40" @click="toCustomer" src="@/static/mine-kefu.png" mode="aspectFill" />
|
||||
<!-- 设置 -->
|
||||
<image class="ml20 wh40" @click="link('/pages/mine/setting/setting')" src="@/static/mine-shezhi.png"
|
||||
mode="aspectFill" />
|
||||
|
@ -202,55 +215,55 @@
|
|||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
//
|
||||
.apex {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 10;
|
||||
opacity: 0;
|
||||
transition: .2s;
|
||||
//
|
||||
.apex {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 10;
|
||||
opacity: 0;
|
||||
transition: .2s;
|
||||
|
||||
&.active {
|
||||
opacity: 1;
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
// 头部个人资料卡
|
||||
.header {
|
||||
.avatar {
|
||||
background: #D8D8D8;
|
||||
}
|
||||
}
|
||||
|
||||
// 我的钱包
|
||||
.wallet {
|
||||
position: relative;
|
||||
|
||||
.right {
|
||||
|
||||
text {
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 模块
|
||||
.container {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
margin: 20rpx 20rpx;
|
||||
padding: 0 20rpx;
|
||||
&.active {
|
||||
opacity: 1;
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.main {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
// 头部个人资料卡
|
||||
.header {
|
||||
.avatar {
|
||||
background: #D8D8D8;
|
||||
}
|
||||
}
|
||||
|
||||
// 我的钱包
|
||||
.wallet {
|
||||
position: relative;
|
||||
|
||||
.right {
|
||||
|
||||
text {
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 模块
|
||||
.container {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
margin: 20rpx 20rpx;
|
||||
padding: 0 20rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
|
||||
.main {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
}
|
||||
}
|
||||
</style>
|
File diff suppressed because it is too large
Load Diff
|
@ -3,7 +3,9 @@ import {
|
|||
} from 'vite';
|
||||
import uni from '@dcloudio/vite-plugin-uni';
|
||||
|
||||
let target = 'http://91f.xyz:8080'
|
||||
// let target = 'http://91f.xyz:8080'
|
||||
let target = 'https://b433d23.r24.cpolar.top/'
|
||||
// let target = 'http://hvw2rn.natappfree.cc'
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [uni()],
|
||||
|
|
|
@ -8,7 +8,7 @@ export default {
|
|||
// 登录令牌
|
||||
const token = uni.getStorageSync('token')
|
||||
// 用户信息
|
||||
const userinfo = JSON.parse(uni.getStorageSync('userinfo'))
|
||||
const userinfo = JSON.parse(uni.getStorageSync('userinfo'))
|
||||
|
||||
// 如果登录保活
|
||||
if (token) {
|
||||
|
@ -19,8 +19,7 @@ export default {
|
|||
value: userinfo
|
||||
})
|
||||
|
||||
|
||||
// 登录腾讯IM
|
||||
// 登录腾讯IM
|
||||
// util.loginTencent(userinfo)
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -1759,11 +1759,11 @@ const util = {
|
|||
*/
|
||||
toChat(option) {
|
||||
uni.navigateTo({
|
||||
url: util.setUrl('/pages/news/chat/chat', {
|
||||
url: util.setUrl('/pages/chat/chat', {
|
||||
name: option.name,
|
||||
msgId: option.msgId,
|
||||
type: option.type,
|
||||
num: option.num,
|
||||
// num: option.num,
|
||||
})
|
||||
})
|
||||
},
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
// 状态栏高度
|
||||
export const statusBarHeight = (isUnit) => {
|
||||
let h = uni.getSystemInfoSync().statusBarHeight
|
||||
h = h ? h : 0
|
||||
return isUnit ? h : `${h}px`
|
||||
}
|
||||
// 底部安全区域高度
|
||||
export const bottomSafeAreaHeight = (isUnit) => {
|
||||
let b = uni.getSystemInfoSync().safeAreaInsets.bottom
|
||||
b = b ? b : 0
|
||||
return isUnit ? b : `${b}px`
|
||||
}
|
||||
// 获取屏幕宽
|
||||
export const screenWidth = (isUnit) => {
|
||||
let w = uni.getSystemInfoSync().screenWidth
|
||||
w = w ? w : 0
|
||||
return isUnit ? w : `${w}px`
|
||||
}
|
||||
// 顶部导航栏的高度
|
||||
export const windowTop = (isUnit) => {
|
||||
let h = uni.getSystemInfoSync().windowTop
|
||||
h = h ? h : 0
|
||||
return isUnit ? h : `${h}px`
|
||||
}
|
||||
// 获取屏幕高 x 小数
|
||||
export const screenHeight = (isUnit) => {
|
||||
let h = uni.getSystemInfoSync().screenHeight
|
||||
h = h ? h : 0
|
||||
return isUnit ? h : `${h}px`
|
||||
}
|
||||
// 判断是否有上一页 返回上一页 否则跳转首页
|
||||
export const goBack = (url) => {
|
||||
// 获取当前页面栈
|
||||
const pages = getCurrentPages();
|
||||
|
||||
// 判断是否存在上一页
|
||||
if (pages.length > 1) {
|
||||
return uni.navigateBack({
|
||||
delta: 1
|
||||
})
|
||||
} else {
|
||||
return uni.reLaunch({
|
||||
url: url
|
||||
})
|
||||
}
|
||||
}
|
|
@ -0,0 +1,187 @@
|
|||
<!-- 页面描述 -->
|
||||
<template>
|
||||
<view class="commodity-information" @click="emit('click', orderInfo)">
|
||||
<uni-section>
|
||||
<template v-slot:decoration>
|
||||
<!-- 商品图 -->
|
||||
<image class="shop-image" :src="orderInfo.productImage" mode="aspectFill"></image>
|
||||
</template>
|
||||
<template v-slot:content>
|
||||
<!-- 订单 | 聊天-->
|
||||
<template v-if="showType == 1 || showType == 4">
|
||||
<view class="commodity-name commodity-name-1">
|
||||
<text class="commodity-name-title t2hd">{{ orderInfo.productName }}</text>
|
||||
<text class="commodity-name-ks thd">{{ orderInfo.status_text }}</text>
|
||||
<text v-if="showType == 4">{{ orderInfo.status }}</text>
|
||||
</view>
|
||||
</template>
|
||||
<!-- 历史浏览 | 收藏 -->
|
||||
<template v-if="showType == 2 || showType == 3">
|
||||
<view class="commodity-name commodity-name-2">
|
||||
<text class="t2hd">耳钉耳钉耳钉耳钉耳钉耳钉耳钉耳钉耳钉耳钉耳钉</text>
|
||||
<view class="df aic" v-if="showType == 2">
|
||||
<view class="df aic price mr10">
|
||||
<text class="f20 jg">¥</text>
|
||||
<text class="f28">{{ orderInfo.price }}</text>
|
||||
</view>
|
||||
<view class="df xl">
|
||||
<text>销量</text> <text>{{ orderInfo.sales }}</text> <text>+</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="df aic" v-if="showType == 3">
|
||||
<view class="df xl thd">
|
||||
<text>店铺名称</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<!-- 店铺管理 -->
|
||||
<template v-if="showType == 5">
|
||||
<view class="df fdc jcsb hohp">
|
||||
<text class="t2hd c333 f28 fw600">耳钉耳钉耳钉耳钉耳钉耳钉耳钉耳钉耳钉耳钉耳钉</text>
|
||||
<text class="c333 f24">销量:156151</text>
|
||||
<view class="df aic">
|
||||
<text class="f24 cFF9B27">价格:¥123</text>
|
||||
<text class="f24 ml40 c999">库存:x1</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</template>
|
||||
<template v-slot:right v-if="showType != 3 && right">
|
||||
<template v-if="showType == 1 || showType == 4">
|
||||
<view class="df fdc jcsb aife" style="height: 100%;align-items: flex-end">
|
||||
<!-- 价格 -->
|
||||
<view class="price-num">
|
||||
<view class="df aic price">
|
||||
<text class="f20 jg">¥</text>
|
||||
<text class="f28">{{ orderInfo.productPrice }}</text>
|
||||
</view>
|
||||
<!-- 数量 -->
|
||||
<text class="c999 f24">x{{ orderInfo.totalNum }}</text>
|
||||
</view>
|
||||
<!-- 发送到聊天 -->
|
||||
<view @click.stop="emit('consult', orderInfo)" class="go-buy" v-if="showType == 4">
|
||||
<uni-tag :inverted="true" text="去咨询" type="warning" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<template v-if="showType == 2">
|
||||
<view class="go-buy" @click.stop="emit('buy', orderInfo)">
|
||||
<uni-tag :inverted="true" text="去购买" type="warning" />
|
||||
</view>
|
||||
</template>
|
||||
</template>
|
||||
</uni-section>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, defineEmits } from 'vue'
|
||||
const emit = defineEmits(['consult', 'click', 'buy'])
|
||||
const props = defineProps({
|
||||
// 订单信息
|
||||
orderInfo: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {
|
||||
shop_logo: '',
|
||||
shop_name: '123',
|
||||
order_status_text: 6,
|
||||
}
|
||||
},
|
||||
},
|
||||
// 1是订单模式
|
||||
// 2是历史浏览
|
||||
// 3是收藏
|
||||
// 4是聊天
|
||||
showType: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
// 在4的模式下是否显示销量
|
||||
right: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.commodity-information {
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
|
||||
$h : 164rpx;
|
||||
|
||||
.shop-image {
|
||||
height: $h;
|
||||
width: 164rpx;
|
||||
background-color: #D8D8D8;
|
||||
border-radius: 10rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
::v-deep .uni-section-header {
|
||||
padding: 0 !important;
|
||||
|
||||
.uni-section-header__content {
|
||||
height: $h;
|
||||
}
|
||||
|
||||
.uni-section-header__slot-right {
|
||||
height: $h;
|
||||
}
|
||||
}
|
||||
|
||||
.commodity-name {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
&-title {
|
||||
color: #333333;
|
||||
font-size: 28rpx;
|
||||
font-weight: normal;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
&-ks {
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
|
||||
.commodity-name-2 {
|
||||
justify-content: space-between;
|
||||
|
||||
}
|
||||
|
||||
.commodity-name-1 {
|
||||
justify-content: flex-start;
|
||||
|
||||
}
|
||||
|
||||
.go-buy {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
|
||||
.price-num {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
margin-left: 20rpx;
|
||||
|
||||
.price {
|
||||
color: #3D3D3D;
|
||||
}
|
||||
}
|
||||
|
||||
.jg {
|
||||
margin-right: 4rpx;
|
||||
}
|
||||
|
||||
.xl {
|
||||
color: #8C8C8C;
|
||||
}
|
||||
</style>
|
|
@ -19,6 +19,12 @@
|
|||
"navigationBarTitleText": "订单"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/chat/chat",
|
||||
"style": {
|
||||
"navigationBarTitleText": "聊天"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/index/article",
|
||||
"style": {
|
||||
|
|
|
@ -0,0 +1,712 @@
|
|||
<script setup>
|
||||
/**
|
||||
* 聊天页面
|
||||
*/
|
||||
// 腾讯云聊天
|
||||
import TencentCloudChat from '@tencentcloud/chat';
|
||||
import {
|
||||
ref,
|
||||
reactive,
|
||||
nextTick,
|
||||
onUnmounted,
|
||||
onMounted,
|
||||
computed,
|
||||
getCurrentInstance,
|
||||
watch,
|
||||
} from 'vue'
|
||||
// api
|
||||
import api from '@/api/index.js'
|
||||
// 工具库
|
||||
import util from '@/common/js/util.js'
|
||||
import {
|
||||
onLoad,
|
||||
onReady,
|
||||
onPageScroll,
|
||||
onUnload
|
||||
} from "@dcloudio/uni-app"
|
||||
|
||||
// 单条消息
|
||||
import newsTemplate from './components/news-temp'
|
||||
// 表情
|
||||
import emoji from './emoji.vue'
|
||||
// 语音条
|
||||
import JyVoice from './jy-voice.vue'
|
||||
// 加号菜单
|
||||
import JyPlus from './jy-plus.vue'
|
||||
|
||||
import {
|
||||
useStore
|
||||
} from 'vuex'
|
||||
const {
|
||||
proxy
|
||||
} = getCurrentInstance()
|
||||
const store = useStore()
|
||||
|
||||
// 聊天对象
|
||||
const msg = reactive({
|
||||
// 聊天对象
|
||||
id: '',
|
||||
// 聊天类型 C2C单聊 GROUP群聊
|
||||
type: '',
|
||||
// 群人数
|
||||
num: '',
|
||||
// 是否客服聊天
|
||||
isCustomer: false,
|
||||
})
|
||||
// 输入的内容
|
||||
const content = ref('')
|
||||
// 加载
|
||||
const loading = ref(false)
|
||||
// 用户信息
|
||||
const userinfo = computed(() => {
|
||||
let result = store.state.userinfo
|
||||
return result
|
||||
})
|
||||
// 列表数据
|
||||
const list = reactive({
|
||||
// 列表条数
|
||||
limit: 20,
|
||||
//显示的数据
|
||||
data: [],
|
||||
//
|
||||
total: 0,
|
||||
})
|
||||
// 滚动条位置
|
||||
const top = ref(0)
|
||||
// 工具条的高度
|
||||
const toolHeight = ref(0)
|
||||
// 当前操作的元素
|
||||
const messageItem = ref({})
|
||||
// 工具栏状态 voice录音 input输入框 emoji表情 plus加号菜单
|
||||
const toolStatus = ref('input')
|
||||
// video路径
|
||||
const videoUrl = ref('')
|
||||
// 视频上下文
|
||||
const videoContext = ref(null)
|
||||
// 红包对象
|
||||
const redPacket = reactive({})
|
||||
|
||||
onLoad(option => {
|
||||
// 标题
|
||||
let title = ''
|
||||
// 聊天类型
|
||||
if (option.type) msg.type = option.type
|
||||
// 标题
|
||||
if (option.name) title = option.name
|
||||
// 用户id
|
||||
if (option.msgId) msg.id = option.msgId
|
||||
// 如果是群组
|
||||
if (option.type == 'GROUP') {
|
||||
msg.num = option.num
|
||||
title = `(${option.num})${option.name}`
|
||||
}
|
||||
// 标题
|
||||
if (title) uni.setNavigationBarTitle({
|
||||
title,
|
||||
})
|
||||
// 是否客服
|
||||
if (option.isCustomer) msg.isCustomer = option.isCustomer
|
||||
|
||||
// 开启消息监听
|
||||
addListener()
|
||||
// 获取历史消息
|
||||
getHistory({
|
||||
callback: scrollToBottom
|
||||
})
|
||||
// #ifdef APP
|
||||
uni.onKeyboardHeightChange((rs) => {
|
||||
ghostBox.value.height = rs.height + 'px'
|
||||
nextTick(() => {
|
||||
scrollToBottom()
|
||||
})
|
||||
})
|
||||
// #endif
|
||||
})
|
||||
|
||||
onReady(() => {
|
||||
uni.createSelectorQuery().in(proxy).select('#tool').boundingClientRect((rect) => {
|
||||
toolHeight.value = rect.height
|
||||
}).exec();
|
||||
//
|
||||
videoContext.value = uni.createVideoContext('video')
|
||||
})
|
||||
|
||||
onPageScroll((ev) => {
|
||||
onContentScroll(ev)
|
||||
})
|
||||
|
||||
onUnload(() => {
|
||||
// #ifdef APP
|
||||
uni.offKeyboardHeightChange(() => { })
|
||||
// #endif
|
||||
videoContext.value.stop()
|
||||
})
|
||||
|
||||
// 开启监听消息
|
||||
function addListener() {
|
||||
let onMessageReceived = function (event) {
|
||||
console.log('TencentCloudChat.EVENT.MESSAGE_RECEIVED', event)
|
||||
setTimeout(() => {
|
||||
// 获取历史记录
|
||||
getHistory({
|
||||
msgId: '',
|
||||
limit: 1,
|
||||
})
|
||||
}, 200)
|
||||
}
|
||||
|
||||
uni.$chat.on(TencentCloudChat.EVENT.MESSAGE_RECEIVED, onMessageReceived);
|
||||
}
|
||||
|
||||
// 移除监听消息
|
||||
function removeListener() {
|
||||
uni.$chat.on(TencentCloudChat.EVENT.MESSAGE_RECEIVED);
|
||||
}
|
||||
|
||||
// 获取更多消息记录
|
||||
function getMoreHistroy() {
|
||||
// 获取第一条消息记录
|
||||
if (list.total <= list.data.length) return
|
||||
getHistory({
|
||||
msgId: list.data[0].id
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取历史记录
|
||||
* @param {Object} param
|
||||
*/
|
||||
function getHistory(param = {}) {
|
||||
// 验证sdk是否准备完毕
|
||||
let isReady = uni.$chat.isReady();
|
||||
//
|
||||
if (!isReady && userinfo.value.id) {
|
||||
setTimeout(function () {
|
||||
getHistory(param)
|
||||
}, 200);
|
||||
return
|
||||
}
|
||||
//
|
||||
loading.value = true
|
||||
|
||||
// 获取单聊聊天记录
|
||||
let request = api.news.getUserMsgHistory
|
||||
// // 如果是群聊 获取群聊聊天记录
|
||||
// if (msg.type == 'GROUP') request = api.news.getGroupMsgHistory
|
||||
|
||||
// 获取历史记录
|
||||
request({
|
||||
query: {
|
||||
msgId: param.msgId || '',
|
||||
fromId: userinfo.value.serviceId,
|
||||
toId: msg.id,
|
||||
// groupId: msg.id,
|
||||
limit: param.limit || list.limit,
|
||||
},
|
||||
}).then(res => {
|
||||
if (res.code === 200) {
|
||||
// 结果
|
||||
const result = res.data
|
||||
|
||||
// 如果是最新消息
|
||||
if (param.limit == 1) {
|
||||
list.data.push(...result.list.map(item => {
|
||||
item.callbackData = JSON.parse(item.callbackJson)
|
||||
return item
|
||||
}))
|
||||
} else {
|
||||
// 追加
|
||||
list.data.unshift(...result.list.map(item => {
|
||||
item.callbackData = JSON.parse(item.callbackJson)
|
||||
return item
|
||||
}))
|
||||
}
|
||||
console.log('getHostory', list.data)
|
||||
// 总数
|
||||
list.total = result.total
|
||||
nextTick(() => {
|
||||
param.callback && param.callback()
|
||||
})
|
||||
return
|
||||
}
|
||||
util.alert({
|
||||
content: res.msg,
|
||||
showCancel: false,
|
||||
})
|
||||
}).catch(rs => {
|
||||
console.log('err', rs)
|
||||
}).finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
// 滚动至底部
|
||||
function scrollToBottom() {
|
||||
uni.createSelectorQuery().in(proxy).select('#scroll-content').boundingClientRect((res) => {
|
||||
top.value = res.height
|
||||
|
||||
uni.pageScrollTo({
|
||||
scrollTop: top.value,
|
||||
duration: 0
|
||||
})
|
||||
// console.log('top.value', top.value)
|
||||
}).exec();
|
||||
}
|
||||
|
||||
// 防抖
|
||||
function debounce(func, wait = 500) {
|
||||
let timeout = null;
|
||||
return function (...args) {
|
||||
clearTimeout(timeout)
|
||||
timeout = setTimeout(() => {
|
||||
func.apply(this, args)
|
||||
}, wait);
|
||||
}
|
||||
}
|
||||
|
||||
// 监听内容滚动
|
||||
function onContentScroll(ev) {
|
||||
if (ev.scrollTop == 50) getMoreHistroy()
|
||||
debounce(() => {
|
||||
top.value = ev.detail.scrollTop
|
||||
})
|
||||
}
|
||||
|
||||
// 点击发送
|
||||
function handleSend() {
|
||||
// 发送消息
|
||||
sendMsg({
|
||||
query: {
|
||||
formId: userinfo.value.id,
|
||||
toUserId: msg.id,
|
||||
msgType: TencentCloudChat.TYPES.MSG_TEXT,
|
||||
},
|
||||
data: {
|
||||
text: content.value
|
||||
},
|
||||
success: () => {
|
||||
// 清空已发送的消息
|
||||
content.value = ''
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 加号菜单发送
|
||||
* @param {Object} message 消息对象
|
||||
*/
|
||||
function handlePlusSend(message) {
|
||||
sendMsg(message)
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送消息
|
||||
* @param {Object} param
|
||||
*/
|
||||
function sendMsg(param) {
|
||||
//
|
||||
let request = api.news.sendUserMsg
|
||||
//
|
||||
if (msg.type == 'GROUP') request = api.news.sendGroupMsg
|
||||
|
||||
// 发送消息
|
||||
request({
|
||||
query: param.query,
|
||||
data: param.data,
|
||||
}).then((rs) => {
|
||||
if (rs.code == 200) {
|
||||
param.success ? param.success() : ''
|
||||
return
|
||||
}
|
||||
util.alert({
|
||||
content: rs.msg,
|
||||
showCancel: false,
|
||||
})
|
||||
}).catch((rs) => {
|
||||
console.log('sendMsg error:', rs);
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开红包详情
|
||||
* @param {Object} ev
|
||||
*/
|
||||
function handleRedPacket(ev) {
|
||||
messageItem.value = ev
|
||||
api.news.getRedPacketInfo({
|
||||
query: {
|
||||
// 红包id
|
||||
redPacketId: ev.callbackData.callback_json[0].businessId
|
||||
}
|
||||
}).then(rs => {
|
||||
if (rs.code == 200) {
|
||||
proxy.$refs.RedPacketRef.open()
|
||||
Object.assign(redPacket, rs.data)
|
||||
return
|
||||
}
|
||||
util.alert({
|
||||
content: rs.msg,
|
||||
showCancel: false,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 领取红包
|
||||
function handleOpenReadPacket() {
|
||||
// 如果不能领取
|
||||
if (redPacket.redStatus == false) return
|
||||
// 红包过期
|
||||
// if (redPacket.isStale == 1) return
|
||||
|
||||
|
||||
// 抢红包
|
||||
api.news.getRedPacket({
|
||||
query: {
|
||||
// 红包id
|
||||
redPacketId: redPacket.id,
|
||||
// 领取人id
|
||||
userId: userinfo.value.id,
|
||||
// 群聊类型
|
||||
sendType: {
|
||||
'C2C': '1',
|
||||
'GROUP': '2',
|
||||
}[msg.type],
|
||||
}
|
||||
}).then(rs => {
|
||||
if (rs.code == 200) {
|
||||
// 修改领取状态
|
||||
redPacket.redStatus = false
|
||||
// 获取金额
|
||||
redPacket.amount = rs.data
|
||||
return
|
||||
}
|
||||
util.alert({
|
||||
content: rs.msg,
|
||||
showCancel: false,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 选择的emoji
|
||||
function emojiTap(val) {
|
||||
content.value = content.value + val
|
||||
}
|
||||
|
||||
// 点击工具栏
|
||||
function handleTool(val) {
|
||||
if (toolStatus.value === val) {
|
||||
toolStatus.value = 'input'
|
||||
return
|
||||
}
|
||||
toolStatus.value = val
|
||||
}
|
||||
|
||||
// 输入框聚焦
|
||||
function onFocus() {
|
||||
handleTool('input')
|
||||
}
|
||||
|
||||
// 输入语音
|
||||
function voiceSend(message) {
|
||||
console.log('handlePlusSend', message)
|
||||
sendMsg({
|
||||
message,
|
||||
})
|
||||
}
|
||||
|
||||
// 监听滚动
|
||||
const handleScroll = (e) => {
|
||||
if (e.detail.scrollTop === 0) {
|
||||
getHistory()
|
||||
}
|
||||
}
|
||||
|
||||
// 撑起键盘的高度 打开该元素
|
||||
const showGhost = ref(false)
|
||||
// 给元素加高度
|
||||
const ghostBox = ref({
|
||||
height: '0px',
|
||||
duration: '0.25s'
|
||||
})
|
||||
|
||||
// 监听键盘高度变化
|
||||
function keyboardheightchange(res) {
|
||||
ghostBox.value = res.detail
|
||||
nextTick(() => {
|
||||
showGhost.value = res.detail.height > 0 ? true : false
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 看视频
|
||||
* @param {Object} item 聊天消息对象
|
||||
*/
|
||||
function handleViewVideo(item) {
|
||||
videoUrl.value = item.payload.videoUrl
|
||||
// 进入全屏
|
||||
videoContext.value.requestFullScreen()
|
||||
}
|
||||
|
||||
// 监听视频是否全屏
|
||||
function onScreenChange(ev) {
|
||||
console.log('onScreenChange', ev)
|
||||
if (!ev.fullScreen) videoContext.value.pause()
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="app">
|
||||
<scroll-view class="scroll-view" scroll-y :scroll-with-animation="true" :scroll-top="top"
|
||||
@scroll="onContentScroll" @scrolltoupper="getMoreHistroy">
|
||||
<view id="scroll-content" style="padding: 30rpx 30rpx">
|
||||
<view v-for="(item, index) in list.data" :key="index">
|
||||
<!-- 普通消息 -->
|
||||
<view class="message"
|
||||
:class="[(item.From_Account || item.fromId) == userinfo.id ? 'self' : 'friend']">
|
||||
<!-- 如果是我自己 -->
|
||||
<view v-if="msg.type == 'C2C'">
|
||||
<image :src="list.faceUrl" class="avatar wh80" mode="aspectFill" />
|
||||
</view>
|
||||
<view v-else>
|
||||
<image :src="item.fromFaceUrl" class="avatar wh80" mode="aspectFill" />
|
||||
</view>
|
||||
|
||||
<view class="df fdc mlr20">
|
||||
<!-- 昵称 -->
|
||||
<view class="df fdc" v-if="item.from != userinfo.userId">
|
||||
<view class="name">{{ item.callbackData.from_name }}</view>
|
||||
</view>
|
||||
<!-- 消息 -->
|
||||
<newsTemplate :item="item" :msg="msg" @openRedBag="handleRedPacket"
|
||||
@viewVideo="handleViewVideo" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="showGhost" :style="{ height: `${ghostBox.height}px`, transition: `${ghostBox.duration}s` }">
|
||||
</view>
|
||||
<view class="ghost" :style="{ height: toolHeight + 'px' }"></view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<view class="tool" id="tool">
|
||||
<view class="tool-group" style="background: #F6F6F6;">
|
||||
<!-- 语音 -->
|
||||
<image src="/static/news-voice.png" mode="widthFix" class="thumb" @click="handleTool('voice')"></image>
|
||||
<!-- 摁住说话 -->
|
||||
<template v-if="toolStatus == 'voice'">
|
||||
<JyVoice @send="voiceSend" :msg="msg" />
|
||||
</template>
|
||||
<!-- 输入框 -->
|
||||
<template v-if="toolStatus != 'voice'">
|
||||
<uni-easyinput @focus="onFocus" type="text" v-model="content" :clearable="false" class="input"
|
||||
:adjust-position="false" @keyboardheightchange="keyboardheightchange" placeholder="请输入你的问题"
|
||||
confirmType="发送" />
|
||||
</template>
|
||||
<!-- 表情 -->
|
||||
<image src="/static/news-emoji.png" mode="widthFix" class="thumb" @click="handleTool('emoji')"></image>
|
||||
<!-- 加号 -->
|
||||
<template v-if="!content">
|
||||
<image src="/static/news-plus.png" mode="widthFix" class="thumb" @click="handleTool('plus')" />
|
||||
</template>
|
||||
<!-- 文本发送按钮 -->
|
||||
<template v-else>
|
||||
<view class="send" @click="handleSend">发送</view>
|
||||
</template>
|
||||
</view>
|
||||
<view v-if="showGhost" :style="{ height: `${ghostBox.height}px`, transition: `${ghostBox.duration}s` }"></view>
|
||||
<!-- 表情 -->
|
||||
<template v-if="toolStatus == 'emoji'">
|
||||
<emoji @setEmoj="emojiTap"></emoji>
|
||||
</template>
|
||||
<!-- 加号 -->
|
||||
<template v-if="toolStatus == 'plus'">
|
||||
<JyPlus @send="handlePlusSend" :msg="msg"></JyPlus>
|
||||
</template>
|
||||
</view>
|
||||
|
||||
<!-- 视频 -->
|
||||
<video :src="videoUrl" id="video" @fullscreenchange="onScreenChange" />
|
||||
|
||||
<!-- 红包封面 -->
|
||||
<uni-popup ref="RedPacketRef" type="center">
|
||||
<view class="red-bag br20" @touchmove.stop.prevent="">
|
||||
<view class="rbag_top">
|
||||
<view class="user fmid">
|
||||
<view class="avatar">
|
||||
<image class="wh80 cir" :src="redPacket.fromUrl" mode="scaleToFill" />
|
||||
</view>
|
||||
<view class="ml15 f32">{{ redPacket.fromName }}的红包</view>
|
||||
</view>
|
||||
<view class="app_name mt15 mlr30 tac f40">{{ redPacket.blessing }}</view>
|
||||
<!-- -->
|
||||
<view class="cfff f32 tac mt50" v-if="redPacket.isStale == 1">红包已过期</view>
|
||||
<view class="cfff f32 tac mt50" v-else-if="redPacket.remainingCount == 0">来晚啦,红包已被抢完</view>
|
||||
|
||||
<!-- redPacket.redStatus true可以领取 false不可领取 -->
|
||||
<view class="amount f32" v-if="!redPacket.redStatus">
|
||||
<text class="">已领取</text>
|
||||
<text class="value">{{ redPacket.amount }}</text>
|
||||
<text class="unit" v-if="redPacket.payType == 1">余额</text>
|
||||
<text class="unit" v-else-if="redPacket.payType == 2">积分</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="open_rbag_btn pr fmid" @click="handleOpenReadPacket">
|
||||
<text v-if="redPacket.amount">已</text>
|
||||
<text>开</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="tac mt35" @click.stop="$refs.RedPacketRef.close()">
|
||||
<uni-icons type="close" color="#fbd977" size="32" />
|
||||
</view>
|
||||
</uni-popup>
|
||||
</template>
|
||||
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import './index.scss';
|
||||
|
||||
//
|
||||
#video {
|
||||
position: fixed;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
//
|
||||
.red-bag {
|
||||
position: relative;
|
||||
width: 528rpx;
|
||||
height: 60vh;
|
||||
color: #ECCD97;
|
||||
background-color: #e0534a;
|
||||
box-shadow: 0 0 20rpx #00000033;
|
||||
|
||||
.rbag_top {
|
||||
padding-top: 60rpx;
|
||||
height: 70%;
|
||||
background-color: #e0534a;
|
||||
border-radius: 0 0 500rpx 500rpx / 0 0 200rpx 200rpx;
|
||||
box-shadow: 0 5rpx 5rpx rgba(0, 0, 0, 0.2);
|
||||
|
||||
.amount {
|
||||
margin-top: 120rpx;
|
||||
text-align: center;
|
||||
letter-spacing: 1rpx;
|
||||
|
||||
.value {
|
||||
font-size: 60rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.open_rbag_btn {
|
||||
width: 180rpx;
|
||||
height: 180rpx;
|
||||
margin: -90rpx auto 0;
|
||||
color: #fef5e8;
|
||||
font-size: 74rpx;
|
||||
font-weight: bold;
|
||||
background-color: #ffd287;
|
||||
box-shadow: 2rpx 2rpx 6rpx rgba(0, 0, 0, 0.2);
|
||||
border-radius: 50%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
// 打开红包
|
||||
.open_rbag_model {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
z-index: 1000;
|
||||
|
||||
.rbag_conbg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 80%;
|
||||
height: 840rpx;
|
||||
margin: auto;
|
||||
z-index: 1001;
|
||||
}
|
||||
|
||||
.open_rbag_con {
|
||||
z-index: 1002;
|
||||
|
||||
.open_title {
|
||||
height: 120rpx;
|
||||
line-height: 120rpx;
|
||||
text-align: center;
|
||||
font-size: 38rpx;
|
||||
letter-spacing: 2rpx;
|
||||
color: #e46965;
|
||||
}
|
||||
|
||||
.rbag_detail {
|
||||
margin-top: 90rpx;
|
||||
|
||||
.open_money {
|
||||
text-align: center;
|
||||
font-size: 80rpx;
|
||||
color: #c95948;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
.danwei {
|
||||
font-size: 30rpx;
|
||||
margin-left: 16rpx;
|
||||
margin-top: 24rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.open_tips {
|
||||
text-align: center;
|
||||
font-size: 30rpx;
|
||||
color: #d26762;
|
||||
margin-top: 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.lookbag_box {
|
||||
margin-top: 300rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
.lookbag_btn {
|
||||
width: 70%;
|
||||
height: 90rpx;
|
||||
line-height: 90rpx;
|
||||
text-align: center;
|
||||
font-size: 32rpx;
|
||||
color: #c95948;
|
||||
letter-spacing: 2rpx;
|
||||
background-color: #ffd356;
|
||||
border-radius: 50rpx;
|
||||
box-shadow: 0rpx 0rpx 4rpx rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
.hide_btn {
|
||||
position: absolute;
|
||||
bottom: -110rpx;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
text-align: center;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,223 @@
|
|||
<script setup>
|
||||
/**
|
||||
* 聊天框内容
|
||||
*/
|
||||
// 聊天
|
||||
import TencentCloudChat from '@tencentcloud/chat';
|
||||
|
||||
import {
|
||||
nextTick,
|
||||
watch,
|
||||
computed,
|
||||
defineEmits,
|
||||
} from 'vue'
|
||||
import NewsAudio from '@/static/audio.png'
|
||||
import JyCommodityInformation from '@/components/public/jy-commodity-information'
|
||||
const props = defineProps({
|
||||
item: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
{}
|
||||
}
|
||||
},
|
||||
msg: {
|
||||
type: Object,
|
||||
}
|
||||
})
|
||||
import {
|
||||
useStore
|
||||
} from 'vuex'
|
||||
const store = useStore()
|
||||
const emit = defineEmits(['openRedBag', 'viewVideo'])
|
||||
// 格式化
|
||||
const formatData = computed(() => props.item.callbackData.callback_json[0])
|
||||
//音频
|
||||
const innerAudioContext = uni.createInnerAudioContext();
|
||||
// 播放语音
|
||||
const payAudio = (item) => {
|
||||
innerAudioContext.src = item.payload.url
|
||||
nextTick(() => {
|
||||
innerAudioContext.play();
|
||||
})
|
||||
}
|
||||
// 用户信息
|
||||
const userinfo = computed(() => {
|
||||
let result = store.state.userinfo
|
||||
return result
|
||||
})
|
||||
|
||||
// 拨打电话
|
||||
function handleCall() {
|
||||
uni.$TUICallKit.call({
|
||||
userID: props.msg.id,
|
||||
callMediaType: formatData.value.data.call_type,
|
||||
}, res => {
|
||||
console.log('[TUICallKit] call params: ', JSON.stringify(res));
|
||||
});
|
||||
}
|
||||
|
||||
// 开红包
|
||||
function handleOpenRedBag() {
|
||||
emit('openRedBag', props.item)
|
||||
}
|
||||
|
||||
// 看视频
|
||||
function handleViewVideo(item) {
|
||||
emit('viewVideo', item)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="content pr">
|
||||
<!-- 图片 -->
|
||||
<template v-if="item.callbackData.MsgType === TencentCloudChat.TYPES.MSG_IMAGE">
|
||||
<image class="br10" :src="formatData.MsgContent.ImageInfoArray[0].URL" mode="widthFix" />
|
||||
</template>
|
||||
<!-- 文字 -->
|
||||
<template v-else-if="item.callbackData.MsgType === TencentCloudChat.TYPES.MSG_TEXT">
|
||||
<view class="p25">
|
||||
{{ formatData.MsgContent.Text }}
|
||||
</view>
|
||||
</template>
|
||||
<!-- 自定义消息 -->
|
||||
<template v-else-if="item.callbackData.MsgType === TencentCloudChat.TYPES.MSG_CUSTOM">
|
||||
<!-- 判断业务字段 -->
|
||||
<template v-if="formatData.businessType">
|
||||
<!-- 音视频通话 -->
|
||||
<template v-if="formatData.businessType == 1">
|
||||
<!-- 拨打电话 -->
|
||||
<view class="p25" @click="handleCall">
|
||||
<template v-if="formatData.actionType == TencentCloudChat.TSignaling.ACTION_TYPE_INVITE">
|
||||
<text>[ </text>
|
||||
<uni-icons type="videocam" color="#333" size="32rpx"
|
||||
v-if="formatData.data.call_type == 1" />
|
||||
<uni-icons type="phone" color="#333" size="32rpx"
|
||||
v-else-if="formatData.data.call_type == 2" />
|
||||
<text>发起</text>
|
||||
<text v-if="formatData.data.call_type == 1">语音</text>
|
||||
<text v-else-if="formatData.data.call_type == 2">视频</text>
|
||||
<text>通话</text>
|
||||
<text> ]</text>
|
||||
</template>
|
||||
<template v-if="formatData.actionType == TencentCloudChat.TSignaling.ACTION_TYPE_CANCEL_INVITE">
|
||||
<text>[</text>
|
||||
<uni-icons type="videocam" color="#333" size="32rpx"
|
||||
v-if="formatData.data.call_type == 1" />
|
||||
<uni-icons type="phone" color="#333" size="32rpx"
|
||||
v-else-if="formatData.data.call_type == 2" />
|
||||
<text>已取消通话 ]</text>
|
||||
</template>
|
||||
<template v-if="formatData.actionType == TencentCloudChat.TSignaling.ACTION_TYPE_ACCEPT_INVITE">
|
||||
<text>[ </text>
|
||||
<uni-icons type="videocam" color="#333" size="32rpx"
|
||||
v-if="formatData.data.call_type == 1" />
|
||||
<uni-icons type="phone" color="#333" size="32rpx"
|
||||
v-else-if="formatData.data.call_type == 2" />
|
||||
<text>已接通 ]</text>
|
||||
<!-- <text>[ 通话时长 {{formatData.data.call_end}} ]</text> -->
|
||||
</template>
|
||||
<template v-if="formatData.actionType == TencentCloudChat.TSignaling.ACTION_TYPE_REJECT_INVITE">
|
||||
<text>[ </text>
|
||||
<uni-icons type="videocam" color="#333" size="32rpx"
|
||||
v-if="formatData.data.call_type == 1" />
|
||||
<uni-icons type="phone" color="#333" size="32rpx"
|
||||
v-else-if="formatData.data.call_type == 2" />
|
||||
<text>已拒绝通话 ]</text>
|
||||
</template>
|
||||
<template
|
||||
v-if="formatData.actionType == TencentCloudChat.TSignaling.ACTION_TYPE_INVITE_TIMEOUT">
|
||||
<text>[ </text>
|
||||
<uni-icons type="videocam" color="#333" size="32rpx"
|
||||
v-if="formatData.data.call_type == 1" />
|
||||
<uni-icons type="phone" color="#333" size="32rpx"
|
||||
v-else-if="formatData.data.call_type == 2" />
|
||||
<text>超时未接听 ]</text>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
<!-- 红包消息 -->
|
||||
<template v-else-if="formatData.businessType == 'redPacket'">
|
||||
<!-- 红包 -->
|
||||
<view class="redPacket br10" :class="{'disabled': 0}"
|
||||
@click="handleOpenRedBag">
|
||||
<view class="df aic">
|
||||
<image class="img fs0 mr10" src="/static/image/red-envelope.png" />
|
||||
<view class="red-packet-text cfff">{{ formatData.data.blessing }}</view>
|
||||
</view>
|
||||
<!-- 分割线 -->
|
||||
<view class="line"></view>
|
||||
<view class="f20" style="color:#FBD3A4">{{ formatData.data.payType == 1 ? '余额红包' : '积分红包' }}</view>
|
||||
</view>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<!-- 音频文件 -->
|
||||
<template v-if="item.callbackData.MsgType == TencentCloudChat.TYPES.MSG_AUDIO">
|
||||
<div class="df aic p25" style="width: 100rpx" @click="payAudio(item)">
|
||||
<image class="mr20" style="width: 30rpx;height: 30rpx;z-index: 1;" :src="NewsAudio" />
|
||||
<text>{{ item.payload.downloadFlag }}''</text>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 视频消息 -->
|
||||
<template v-if="item.callbackData.MsgType == TencentCloudChat.TYPES.MSG_VIDEO">
|
||||
<image :src="item.payload.snapshotUrl" mode="widthFix" />
|
||||
<view class="window pfull" @click="handleViewVideo(item)">
|
||||
<image class="pause pmid wh40" src="/static/pause.png" mode="aspectFit" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<!-- 咨询订单 -->
|
||||
<template v-if="item.callbackData.MsgType === 'order'">
|
||||
<JyCommodityInformation :showType="4" :right="false"></JyCommodityInformation>
|
||||
</template>
|
||||
<!-- 咨询商品-->
|
||||
<template v-if="item.callbackData.MsgType === 'shop'">
|
||||
<JyCommodityInformation :showType="3"></JyCommodityInformation>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.content {
|
||||
box-sizing: border-box;
|
||||
min-height: 80rpx;
|
||||
max-width: 60vw;
|
||||
font-size: 28rpx;
|
||||
|
||||
image {
|
||||
width: 200rpx;
|
||||
}
|
||||
}
|
||||
|
||||
// 红包消息
|
||||
.redPacket {
|
||||
width: 360rpx;
|
||||
padding: 24rpx;
|
||||
background-color: rgb(248, 162, 60);
|
||||
color: #FCFEFD;
|
||||
|
||||
&.disabled {
|
||||
opacity: .6;
|
||||
}
|
||||
|
||||
.img {
|
||||
width: 50rpx;
|
||||
height: 60rpx;
|
||||
}
|
||||
|
||||
.line {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
background: #EF9B45;
|
||||
margin: 10rpx 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 遮罩
|
||||
.window {
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,33 @@
|
|||
export default [
|
||||
"😀", "😁", "😃", "😄", "😅", "😆", "😉", "😊", "😋", "😎", "😍",
|
||||
"😘", "😗", "😙", "😚", "☺", "😇", "😐", "😑", "😶", "😏", "😣", "😥", "😮", "😯", "😪",
|
||||
"😫", "😴", "😌", "😛", "😜", "😝", "😒", "😓", "😔", "😕", "😲", "😷", "😖", "😞", "😟",
|
||||
"😤", "😢", "😭", "😦", "😧", "😨", "😬", "😰", "😱", "😳", "😵", "😡", "😠",
|
||||
"👦", "👧", "👨", "👩", "👴", "👵", "👶", "👱", "👮", "👲", "👳", "👷", "👸", "💂", "🎅", "👰", "👼",
|
||||
"💆", "💇", "🙍", "🙎", "🙅", "🙆", "💁", "🙋", "🙇", "🙌", "🙏", "👤", "👥", "🚶", "🏃", "👯",
|
||||
"💃", "👫", "👬", "👭", "💏", "💑", "👪", "💪", "👈", "👉", "☝", "👆", "👇", "✌", "✋", "👌",
|
||||
"👍", "👎", "✊", "👊", "👋", "👏", "👐", "✍", "👣", "👀", "👂", "👃", "👅", "👄", "💋", "👓",
|
||||
"👔", "👙", "👛", "👜", "👝", "🎒", "💼", "👞", "👟", "👠", "👡", "👢", "👑",
|
||||
"👒", "🎩", "🎓", "💄", "💅", "💍", "🌂", "📶", "📳", "📴", "♻", "🏧","🚮", "🚰", "♿", "🚹", "🚺",
|
||||
"🚻", "🚼", "🚾", "⚠", "🚸", "⛔", "🚫", "🚳", "🚭", "🚯", "🚱", "🚷", "🔞", "💈",
|
||||
"🙈", "🐒", "🐶", "🐕", "🐩", "🐺", "🐱","🐈", "🐯", "🐅", "🐆", "🐴", "🐎", "🐮", "🐂",
|
||||
"🐃","🐄","🐷","🐖","🐗","🐽","🐏","🐑","🐐","🐪","🐫","🐘","🐭",
|
||||
"🐁","🐀","🐹","🐰","🐇","🐻","🐨","🐼","🐾","🐔","🐓","🐣","🐤","🐥",
|
||||
"🐦", "🐧", "🐸", "🐊","🐢", "🐍", "🐲", "🐉", "🐳", "🐋", "🐬", "🐟", "🐠", "🐡",
|
||||
"🐙", "🐚", "🐌", "🐛", "🐜", "🐝", "🐞", "🦋", "💐", "🌸", "💮", "🌹", "🌺",
|
||||
"🌻", "🌼", "🌷", "🌱", "🌲", "🌳", "🌴", "🌵", "🌾", "🌿", "🍀", "🍁", "🍂", "🍃",
|
||||
"🌍","🌎","🌏","🌐","🌑","🌒","🌓","🌔","🌕","🌖","🌗","🌘","🌙","🌚",
|
||||
"🌛","🌜","☀","🌝","🌞","⭐","🌟","🌠","☁","⛅","☔","⚡","❄","🔥","💧","🌊",
|
||||
"🏀", "🏈", "🏉", "🎾", "🎱", "🎳", "⛳", "🎣", "🎽", "🎿",
|
||||
"😈", "👿", "👹", "👺", "💀", "☠", "👻", "👽", "👾", "💣",
|
||||
"🌋", "🗻", "🏠", "🏡", "🏢", "🏣", "🏤", "🏥", "🏦", "🏨",
|
||||
"⛲", "🌁", "🌃", "🌆", "🌇", "🎠", "🎡", "🎢", "🚂",
|
||||
"🚌", "🚍", "🚎", "🚏", "🚐", "🚑", "🚒", "🚓", "🚔", "🚕", "🚖", "🚗", "🚘",
|
||||
"💌", "💎", "🔪", "💈", "🚪", "🚽", "🚿", "🛁", "⌛", "⏳", "⌚", "⏰", "🎈", "🎉",
|
||||
"💤", "💢", "💬", "💭", "♨", "🌀", "🔔", "🔕", "✡", "✝", "🔯", "📛", "🔰", "🔱", "⭕", "✅",
|
||||
"☑", "✔", "✖", "❌", "❎", "➕", "➖", "➗", "➰", "➿", "〽", "✳", "✴", "❇", "‼", "⁉", "❓", "❔", "❕", "❗",
|
||||
"🕛", "🕧", "🕐", "🕜", "🕑", "🕝", "🕒", "🕞", "🕓", "🕟", "🕔", "🕠", "🕕", "🕡",
|
||||
"🕖", "🕢", "🕗", "🕣", "🕘", "🕤", "🕙", "🕥", "🕚", "🕦", "⏱", "⏲", "🕰",
|
||||
"💘", "❤", "💓", "💔", "💕", "💖", "💗", "💙", "💚", "💛", "💜", "💝", "💞", "💟❣",
|
||||
"🍇", "🍈", "🍉", "🍊", "🍋", "🍌", "🍍", "🍎", "🍏", "🍐", "🍑", "🍒", "🍓",
|
||||
]
|
|
@ -0,0 +1,42 @@
|
|||
<template>
|
||||
<view class="NewsPlus">
|
||||
<scroll-view scroll-y scroll-with-animation>
|
||||
<view append="tree" class="emoj_box">
|
||||
<template v-for="(item, index) in emojiList" :key="index">
|
||||
<text @click="emit('setEmoj', item)" class="emoj_box_img">{{ item }}</text>
|
||||
</template>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
<script setup>
|
||||
import {
|
||||
defineEmits
|
||||
} from 'vue'
|
||||
import emojiList from './emoji.js'
|
||||
const emit = defineEmits(['setEmoj'])
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.NewsPlus {
|
||||
background-color: #f6f6f6;
|
||||
}
|
||||
|
||||
.scroller {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.emoj_box {
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.emoj_box_img {
|
||||
font-size: 45rpx;
|
||||
width: 83rpx;
|
||||
height: 83rpx;
|
||||
text-align: center;
|
||||
line-height: 83rpx;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,30 @@
|
|||
// 获取历史记录
|
||||
// C2C${userID}(单聊)
|
||||
// GROUP${groupID}(群聊)
|
||||
// GROUP${topicID}(话题)
|
||||
// @TIM#SYSTEM(系统通知会话)
|
||||
/**
|
||||
* 获取历史记录
|
||||
* @param {String} option 聊天属性
|
||||
* @param {String} option.chatType C2C单聊 GROUP群聊/话题 @TIM#SYSTEM系统通知会话
|
||||
* @param {String} option.msgId 聊天对象id 单聊/群聊/话题
|
||||
* @param {String} option.nextReqMessageID 用于分页续拉的消息 ID。第一次拉取时不要传入 nextReqMessageID,续拉时填入上次调用 getMessageList 接口返回的该字段的值
|
||||
*/
|
||||
|
||||
export const getHistoryMsg = async (option) => {
|
||||
let options = {
|
||||
// 对方的用户 ID 或者群组 ID 或聊天室 ID。
|
||||
conversationID: `${option.chatType}${option.msgId}`,
|
||||
nextReqMessageID: option.nextReqMessageID,
|
||||
}
|
||||
|
||||
console.log('options', options);
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.$chat.getMessageList(options).then((res) => {
|
||||
resolve(res)
|
||||
}).catch((e) => {
|
||||
console.log('Promise reject', e);
|
||||
reject(e)
|
||||
});
|
||||
})
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
|
||||
|
||||
.scroll-view {
|
||||
box-sizing: border-box;
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.message {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
flex-direction: row;
|
||||
margin-bottom: 40rpx;
|
||||
|
||||
.avatar {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
|
||||
.content {
|
||||
min-height: 80rpx;
|
||||
max-width: 60vw;
|
||||
font-size: 28rpx;
|
||||
|
||||
image {
|
||||
width: 200rpx;
|
||||
}
|
||||
}
|
||||
|
||||
// 我自己
|
||||
&.self {
|
||||
flex-direction: row-reverse;
|
||||
// justify-content: flex-end;
|
||||
|
||||
.content {
|
||||
background: #d9e1ff;
|
||||
border-radius: 24rpx 0rpx 24rpx 24rpx;
|
||||
}
|
||||
}
|
||||
|
||||
// 对方
|
||||
&.friend {
|
||||
.name {
|
||||
font-size: 20rpx;
|
||||
color: '#000000';
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.content {
|
||||
border-radius: 0rpx 24rpx 24rpx 24rpx;
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tool {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
padding-bottom: constant(safe-area-inset-bottom);
|
||||
padding-bottom: calc(0 + env(safe-area-inset-bottom));
|
||||
z-index: 1;
|
||||
|
||||
.tool-group {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
&-group {
|
||||
height: 120rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
::v-deep .uni-easyinput__content {
|
||||
border-radius: 192rpx;
|
||||
}
|
||||
|
||||
.xf-for {
|
||||
height: 80rpx;
|
||||
padding-bottom: 12rpx;
|
||||
background: #eee;
|
||||
|
||||
.xfBtn {
|
||||
box-sizing: border-box;
|
||||
border: 2px solid #dcdcdc;
|
||||
background: #ffffff;
|
||||
padding: 12rpx 32rpx;
|
||||
font-size: 28rpx;
|
||||
color: rgba(0, 0, 0, 0.9);
|
||||
border-radius: 200rpx;
|
||||
width: fit-content;
|
||||
margin: 10rpx 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.NewsPlus {
|
||||
width: 100%;
|
||||
height: 486rpx;
|
||||
}
|
||||
|
||||
.thumb {
|
||||
width: 44rpx;
|
||||
height: 44rpx;
|
||||
margin: 0 10rpx;
|
||||
}
|
||||
|
||||
.send {
|
||||
border-radius: 10rpx;
|
||||
margin: 0 10rpx;
|
||||
padding: 10rpx 20rpx;
|
||||
background: #ff3737;
|
||||
color: #fff;
|
||||
font-size: small;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,344 @@
|
|||
<script setup>
|
||||
// + 页面
|
||||
// 腾讯云聊天
|
||||
import TencentCloudChat from '@tencentcloud/chat';
|
||||
import {
|
||||
ref,
|
||||
reactive,
|
||||
nextTick,
|
||||
computed,
|
||||
} from 'vue'
|
||||
import {
|
||||
screenHeight
|
||||
} from '@/components/public/Mixins'
|
||||
import JyCommodityInformation from '@/components/public/jy-commodity-information'
|
||||
// api
|
||||
import api from '@/api/index.js'
|
||||
// 工具库
|
||||
import util from '@/common/js/util.js'
|
||||
import { inject } from 'vue'
|
||||
|
||||
const { checkLink } = inject('util');
|
||||
//
|
||||
const props = defineProps({
|
||||
msg: {
|
||||
type: Object,
|
||||
},
|
||||
})
|
||||
|
||||
// 调用父级方法
|
||||
const emit = defineEmits(['plusClick', 'send'])
|
||||
// 加号菜单
|
||||
const plusList = computed(() => {
|
||||
let result = [
|
||||
{
|
||||
type: 'picture.png',
|
||||
label: '照片',
|
||||
value: 'chooseImage',
|
||||
}, {
|
||||
type: 'photograph.png',
|
||||
label: '拍摄',
|
||||
value: 'takePhoto',
|
||||
}, {
|
||||
type: 'red-envelope.png',
|
||||
label: '红包',
|
||||
value: 'redEnvelope',
|
||||
}
|
||||
]
|
||||
|
||||
const isCustomer = props.msg.isCustomer;
|
||||
|
||||
// 单聊
|
||||
if (props.msg.type == 'C2C' && !isCustomer) result.push({
|
||||
type: 'news-voice.png',
|
||||
label: '音视频',
|
||||
value: 'voice'
|
||||
})
|
||||
// 客服
|
||||
if (isCustomer) result.unshift({
|
||||
type: 'order.png',
|
||||
label: '订单',
|
||||
value: 'chooseOrder',
|
||||
}, {
|
||||
type: 'shop.png',
|
||||
label: '商品',
|
||||
value: 'chooseShop',
|
||||
})
|
||||
return result
|
||||
})
|
||||
|
||||
const popupRef = ref(null)
|
||||
const popupRE = ref(null)
|
||||
const formData = reactive({
|
||||
name: ''
|
||||
})
|
||||
const popupData = reactive({
|
||||
show: false,
|
||||
title: '选择订单'
|
||||
})
|
||||
|
||||
// 订单列表
|
||||
const list = reactive([])
|
||||
|
||||
// 加号方法对象
|
||||
const plusClickObj = {
|
||||
voice: () => {
|
||||
// 菜单
|
||||
const menu = [{
|
||||
name: '语音通话',
|
||||
type: 1,
|
||||
},
|
||||
{
|
||||
nanme: '视频通话',
|
||||
type: 2,
|
||||
}
|
||||
]
|
||||
|
||||
uni.showActionSheet({
|
||||
itemList: ['语音通话', '视频通话'],
|
||||
success: rs => {
|
||||
uni.$TUICallKit.call({
|
||||
userID: props.msg.id,
|
||||
callMediaType: menu[rs.tapIndex].type,
|
||||
// callParams: {
|
||||
// roomID: 234,
|
||||
// strRoomID: '2323423',
|
||||
// timeout: 30
|
||||
// },
|
||||
}, res => {
|
||||
console.log('[TUICallKit] call params: ', JSON.stringify(res));
|
||||
});
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 选择订单
|
||||
chooseOrder: () => {
|
||||
let param = {
|
||||
pageSize: 10,
|
||||
pageNum: 1,
|
||||
merId: props.msg.id,
|
||||
}
|
||||
api.shop.getShopOrderList(param).then(rs => {
|
||||
if (rs.code == 200) {
|
||||
list.length = 0
|
||||
list.push(...rs.rows.map(item => {
|
||||
// 状态
|
||||
item.status = Number(item.status)
|
||||
// 编辑订单状态文字
|
||||
item.status_text = {
|
||||
'0': '待支付',
|
||||
'1': '待发货',
|
||||
'4': '待收货',
|
||||
'5': '已收货',
|
||||
'6': '已完成',
|
||||
'9': '已取消',
|
||||
}[item.status]
|
||||
return item
|
||||
}))
|
||||
|
||||
|
||||
nextTick().then(() => {
|
||||
popupRef.value.open()
|
||||
});
|
||||
return
|
||||
}
|
||||
|
||||
util.alert({
|
||||
content: rs.msg,
|
||||
showCancel: false,
|
||||
})
|
||||
})
|
||||
|
||||
},
|
||||
|
||||
// 选择商品
|
||||
chooseShop: () => {
|
||||
uni.navigateTo({
|
||||
url: `/pages/news/goodsList/index?merId=${props.msg.id}`
|
||||
});
|
||||
},
|
||||
|
||||
// 发送红包
|
||||
redEnvelope() {
|
||||
uni.navigateTo({
|
||||
url: util.setUrl('/pages/news/redPacket', {
|
||||
// 聊天对象
|
||||
msgId: props.msg.id,
|
||||
// 发送方式
|
||||
sendType: {
|
||||
'C2C': 1,
|
||||
'GROUP': 2,
|
||||
}[props.msg.type],
|
||||
num: props.msg.num,
|
||||
})
|
||||
})
|
||||
// popupRE.value.open()
|
||||
},
|
||||
|
||||
//拍照
|
||||
takePhoto: () => {
|
||||
console.log('takePhoto')
|
||||
sendMsgImg({
|
||||
sourceType: ['album'],
|
||||
})
|
||||
},
|
||||
|
||||
//选择图片
|
||||
chooseImage: () => {
|
||||
console.log('chooseImage')
|
||||
sendMsgImg({
|
||||
sourceType: ['album'],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 发送图片消息
|
||||
function sendMsgImg(option) {
|
||||
util.upload_image({
|
||||
count: 1,
|
||||
type: 1,
|
||||
success: rs => {
|
||||
emit('send', {
|
||||
query: {
|
||||
toUserId: props.msg.id,
|
||||
msgType: TencentCloudChat.TYPES.MSG_IMAGE,
|
||||
},
|
||||
data: {
|
||||
imgUrl: rs.value
|
||||
},
|
||||
})
|
||||
}
|
||||
})
|
||||
return
|
||||
// 选择图片
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
sourceType: option.sourceType, // 从相册选择
|
||||
success: (res) => {
|
||||
let message = uni.$chat.createImageMessage({
|
||||
to: props.msg.id,
|
||||
conversationType: props.msg.type,
|
||||
payload: {
|
||||
file: res
|
||||
},
|
||||
onProgress: function (event) {
|
||||
console.log('file uploading:', event)
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 咨询订单
|
||||
const consult = (content) => {
|
||||
let obj = {
|
||||
content,
|
||||
type: 'order'
|
||||
}
|
||||
popupRef.value.close()
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="jy-plus">
|
||||
<view class="NewsPlus ptb20" style="background: #F6F6F6;">
|
||||
<view class="df fdc aic" v-for="(item, index) in plusList" :key="index" @click="plusClickObj[item.value]">
|
||||
<view class="imageBox fmid wh100">
|
||||
<image class="image wh50" :src="`/static/new-${item.type}`" mode="aspectFit" />
|
||||
</view>
|
||||
<text class="mt20">{{ item.label }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 咨询订单的弹窗 -->
|
||||
<uni-popup ref="popupRef" type="bottom">
|
||||
<view class="jy-popup bfff" :style="{ height: `${screenHeight(true) * 0.7}px` }">
|
||||
<view class="title">
|
||||
<text>咨询订单</text>
|
||||
</view>
|
||||
<view class="close-btn" @click="popupRef.close()">×</view>
|
||||
<view class="input-view">
|
||||
<uni-easyinput class="easyinput" placeholder="搜索你要查询的订单">
|
||||
<template v-slot:left>
|
||||
<uni-icons class="ml20" type="search" size="20"></uni-icons>
|
||||
</template>
|
||||
</uni-easyinput>
|
||||
</view>
|
||||
<scroll-view scroll-y scroll-with-animation>
|
||||
<view v-for="(item, index) in list" :key="index">
|
||||
<view class="time">
|
||||
下单时间:{{ item.createTime }}
|
||||
</view>
|
||||
<JyCommodityInformation :showType="4" :orderInfo="item" @consult="consult"></JyCommodityInformation>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.NewsPlus {
|
||||
// 一行四个
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
grid-gap: 20rpx;
|
||||
|
||||
.imageBox {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.jy-popup {
|
||||
width: 100%;
|
||||
border-radius: 20px 20px 0px 0px;
|
||||
|
||||
.title {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
// 底部边框显示
|
||||
color: #3D3D3D;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.close-btn {
|
||||
position: absolute;
|
||||
top: 40rpx;
|
||||
right: 40rpx;
|
||||
height: 52rpx;
|
||||
line-height: 52rpx;
|
||||
width: 52rpx;
|
||||
background: #D8D8D8;
|
||||
color: #999999;
|
||||
font-size: 30rpx;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
transform: translate(50%, -50%);
|
||||
}
|
||||
|
||||
.input-view {
|
||||
// 只显示上下边框不显示左右
|
||||
border-top: 1px solid #E5E5E5;
|
||||
border-bottom: 1px solid #E5E5E5;
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.easyinput {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.time {
|
||||
padding: 24rpx 20rpx 0 20rpx;
|
||||
font-size: 22rpx;
|
||||
color: #3D3D3D;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,280 @@
|
|||
<!-- 语音 -->
|
||||
<template>
|
||||
<view class="voice_box" @touchstart="sv.touchstartVoice" @touchmove.stop.prevent="sv.touchmoveVoice"
|
||||
@touchend="sv.touchendVoice" @touchcancel="sv.touchcancelVoice">
|
||||
<text class="voice_text c000">{{ voiceText }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 语音状态显示 -->
|
||||
<template v-if="voiceFlg">
|
||||
<!-- 录音UI效果 -->
|
||||
<view class="record" :class="voiceFlg ? '' : 'hidden'">
|
||||
<uni-icons :class="[voiceStop ? 'cancel' : 'ing']" :type="voiceStop ? 'micoff' : 'mic'" size="100" />
|
||||
<view class="tis" :class="voiceStop ? 'change' : ''">{{ voiceTis }}</view>
|
||||
</view>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
defineEmits
|
||||
} from 'vue'
|
||||
// 腾讯云聊天
|
||||
import TencentCloudChat from '@tencentcloud/chat';
|
||||
const props = defineProps({
|
||||
msg: {
|
||||
type: Object
|
||||
},
|
||||
})
|
||||
const emit = defineEmits(['send'])
|
||||
//录音
|
||||
// #ifdef APP-PLUS
|
||||
const recorderManager = uni.getRecorderManager();
|
||||
// #endif
|
||||
// 录音时长
|
||||
const voiceLength = ref(0);
|
||||
// 录音定时器
|
||||
const voiceTimer = ref(null);
|
||||
// 录音文本
|
||||
const voiceText = ref('按住 说话');
|
||||
// 录音提示
|
||||
const voiceTis = ref('手指上滑 取消发送');
|
||||
// 录音图标显示
|
||||
const voiceFlg = ref(false);
|
||||
// 录音开始Y坐标
|
||||
const voicePageY = ref(0);
|
||||
// 录音结束
|
||||
const voiceStop = ref(false);
|
||||
const str = '';
|
||||
// 录音相关
|
||||
const sv = {
|
||||
// 按下触发
|
||||
touchstartVoice: (e) => {
|
||||
voicePageY.value = (e.changedTouches[0].pageY).toFixed(2);
|
||||
recorderManager.start({
|
||||
duration: 60000, // 录音的时长,单位 ms,最大值 600000(10 分钟)
|
||||
sampleRate: 44100, // 采样率
|
||||
numberOfChannels: 1, // 录音通道数
|
||||
encodeBitRate: 192000, // 编码码率
|
||||
format: "mp3"
|
||||
});
|
||||
voiceLength.value = 0;
|
||||
voiceFlg.value = true
|
||||
console.log('recorder start success');
|
||||
//录音开始,
|
||||
voiceTimer.value = setInterval(() => {
|
||||
voiceLength.value += 0.1;
|
||||
}, 100);
|
||||
|
||||
console.log('touchstartVoice', voicePageY.value);
|
||||
},
|
||||
// 滑动触发
|
||||
touchmoveVoice: (e) => {
|
||||
// 没有展示UI不触发
|
||||
if (!voiceFlg.value) {
|
||||
return;
|
||||
}
|
||||
let numTemp = voicePageY.value - ((e.changedTouches[0].pageY).toFixed(2));
|
||||
if (numTemp >= 60) {
|
||||
console.log('取消发送');
|
||||
voiceStop.value = true
|
||||
voiceTis.value = '松开手指 取消发送'
|
||||
} else {
|
||||
console.log('继续发送');
|
||||
voiceStop.value = false
|
||||
voiceTis.value = '手指上滑 取消发送'
|
||||
}
|
||||
},
|
||||
// 松开触发
|
||||
touchendVoice: () => {
|
||||
// 没有展示UI不触发
|
||||
if (!voiceFlg.value) {
|
||||
return;
|
||||
}
|
||||
clearInterval(voiceTimer.value);
|
||||
voiceText.value = '按住 说话'
|
||||
voiceTis.value = "手指上滑 取消发送"
|
||||
console.log('touchendVoice');
|
||||
sv.stop();
|
||||
},
|
||||
// 打断触发
|
||||
touchcancelVoice: () => {
|
||||
clearInterval(voiceTimer.value);
|
||||
// 关闭UI
|
||||
voiceText.value = '按住 说话'
|
||||
voiceTis.value = "手指上滑 取消发送"
|
||||
// 不发送语音
|
||||
voiceStop.value = true
|
||||
console.log('touchcancelVoice');
|
||||
sv.stop();
|
||||
},
|
||||
stop: () => {
|
||||
voiceTimer.value = null;
|
||||
voiceFlg.value = false
|
||||
recorderManager.stop(); // 录音结束
|
||||
console.log('录音结束');
|
||||
}
|
||||
};
|
||||
// #ifdef APP-PLUS
|
||||
// 监听录音停止事件
|
||||
recorderManager.onStop((res) => {
|
||||
// 被打断等情况不发送
|
||||
if (voiceStop.value) {
|
||||
return
|
||||
}
|
||||
// 正常情况
|
||||
if (voiceStop.value) {
|
||||
uni.showToast({
|
||||
icon: "none",
|
||||
title: "取消发送",
|
||||
duration: 2000
|
||||
})
|
||||
return
|
||||
}
|
||||
if (voiceLength.value < 1) {
|
||||
uni.showToast({
|
||||
icon: "none",
|
||||
title: "语音时长过短",
|
||||
duration: 2000
|
||||
})
|
||||
return
|
||||
}
|
||||
if (voiceLength.value > 60) {
|
||||
uni.showToast({
|
||||
icon: "none",
|
||||
title: "语音时长过长",
|
||||
duration: 2000
|
||||
})
|
||||
return
|
||||
}
|
||||
console.log('file', res)
|
||||
|
||||
try {
|
||||
let message = uni.$chat.createAudioMessage({
|
||||
to: props.msg.id,
|
||||
conversationType: props.msg.type,
|
||||
payload: {
|
||||
file: res
|
||||
},
|
||||
// 音频上传进度回调
|
||||
onProgress: function(event) {
|
||||
console.log('file uploading:', event)
|
||||
}
|
||||
})
|
||||
emit('send', message)
|
||||
} catch (e) {
|
||||
console.log('message catch', e)
|
||||
}
|
||||
//
|
||||
|
||||
})
|
||||
// #endif
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.voice_box {
|
||||
padding: 20rpx 0;
|
||||
margin: 0 20rpx;
|
||||
border-radius: 50rpx;
|
||||
background: #fff;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.record {
|
||||
width: 40vw;
|
||||
height: 40vw;
|
||||
position: fixed;
|
||||
top: 55%;
|
||||
left: 30%;
|
||||
background-color: rgba(0, 0, 0, .6);
|
||||
border-radius: 20rpx;
|
||||
|
||||
.ing {
|
||||
width: 100%;
|
||||
height: 30vw;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
// 模拟录音音效动画
|
||||
@keyframes volatility {
|
||||
0% {
|
||||
background-position: 0% 130%;
|
||||
}
|
||||
|
||||
20% {
|
||||
background-position: 0% 150%;
|
||||
}
|
||||
|
||||
30% {
|
||||
background-position: 0% 155%;
|
||||
}
|
||||
|
||||
40% {
|
||||
background-position: 0% 150%;
|
||||
}
|
||||
|
||||
50% {
|
||||
background-position: 0% 145%;
|
||||
}
|
||||
|
||||
70% {
|
||||
background-position: 0% 150%;
|
||||
}
|
||||
|
||||
80% {
|
||||
background-position: 0% 155%;
|
||||
}
|
||||
|
||||
90% {
|
||||
background-position: 0% 140%;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-position: 0% 135%;
|
||||
}
|
||||
}
|
||||
|
||||
background-image: linear-gradient(to bottom, #f09b37, #fff 50%);
|
||||
background-size: 100% 200%;
|
||||
animation: volatility 1.5s ease-in-out -1.5s infinite alternate;
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
font-size: 150rpx;
|
||||
color: #f09b37;
|
||||
|
||||
}
|
||||
|
||||
.cancel {
|
||||
width: 100%;
|
||||
height: 30vw;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
color: #fff;
|
||||
font-size: 150rpx;
|
||||
|
||||
}
|
||||
|
||||
.tis {
|
||||
width: 100%;
|
||||
height: 10vw;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
font-size: 28rpx;
|
||||
color: #fff;
|
||||
|
||||
&.change {
|
||||
color: #f09b37;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -73,7 +73,7 @@ function getList() {
|
|||
if (rs.code == 200) {
|
||||
chatList.push(...rs.data.map(item => {
|
||||
item.callbackData = JSON.parse(item.callbackJson)
|
||||
|
||||
|
||||
if (item.callbackData.callback_json.length) {
|
||||
let msgType = item.callbackData.callback_json[0].MsgType;
|
||||
if (msgType == TencentCloudChat.TYPES.MSG_TEXT) {
|
||||
|
@ -143,20 +143,15 @@ function handleLogout() {
|
|||
* @param {Object} item
|
||||
*/
|
||||
function handleChat(item) {
|
||||
let param = {};
|
||||
// 单聊
|
||||
if (item.groupId == null) {
|
||||
param.type = 'C2C'
|
||||
param.name = `${item.callbackJson.from_name}`
|
||||
param.msgId = `${item.callbackJson.from_id}`
|
||||
} else {
|
||||
// 群聊
|
||||
param.type = 'GROUP'
|
||||
param.name = `${item.groupChatDTO.name}`
|
||||
param.msgId = `${item.groupId}`
|
||||
param.num = `${item.groupChatDTO.memberCount}`
|
||||
}
|
||||
//
|
||||
console.log(111111111, item);
|
||||
|
||||
let param = {
|
||||
type: 'C2C',
|
||||
name: `${item.callbackData.from_name}`,
|
||||
msgId: `${item.callbackData.from_id}`
|
||||
};
|
||||
console.log(22222222, param);
|
||||
|
||||
util.toChat(param)
|
||||
}
|
||||
/**
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 3.6 KiB |
Loading…
Reference in New Issue