提交 3c87033e 编写于 作者: DCloud_JSON's avatar DCloud_JSON

1.3.2

上级 1115f80b
<template>
<template>
<view @click="onClick" :style="{width,height}">
<image v-if="cSrc" :style="{width,height}" :src="cSrc" :mode="mode"></image>
</view>
</template>
<image v-if="cSrc" :style="{width,height}" :src="cSrc" :mode="mode"></image>
</view>
</template>
<script>
/**
* cloud-image
......@@ -13,11 +13,11 @@
* @property {String} width 图片的宽,默认为:100rpx
* @property {String} height 图片的高,默认为:100rpx
* @event {Function} click 点击 cloud-image 触发事件
*/
export default {
*/
export default {
name: "cloud-image",
emits:['click'],
props: {
emits:['click'],
props: {
mode: {
type:String,
default () {
......@@ -25,10 +25,10 @@
}
},
src: {
// type:String,
default () {
return ""
}
// type:String,
default () {
return ""
}
},
width: {
type:String,
......@@ -41,7 +41,7 @@
default () {
return '100rpx'
}
}
}
},
watch: {
src:{
......@@ -53,9 +53,7 @@
fileList: [src]
}).then(res=>{
// console.log(res);
// 兼容uniCloud私有化部署
let fileList = res.fileList || res.result.fileList
this.cSrc = fileList[0].tempFileURL
this.cSrc = res.fileList[0].tempFileURL
})
}else{
this.cSrc = src
......@@ -72,10 +70,10 @@
this.$emit('click')
}
},
data() {
return {
cSrc:false
};
}
}
data() {
return {
cSrc:false
};
}
}
</script>
\ No newline at end of file
## 1.3.2(2022-12-05)
- 修复 因vue2与vue3下 :key 的位置要求不同 引起的chat页面报错问题
## 1.3.1(2022-12-05)
- 修复 1.3.0版引起的截图粘贴发送失败的问题
- 修复 集成到 uni-admin 中样式设置失败的问题
## 1.3.0(2022-12-02)
- 修复 APP端当消息未满半屏时,弹出的键盘会将消息顶出界面外
- 新增 消息类型支持代码模式
......
......@@ -169,7 +169,7 @@ export default {
},
async initConversationData(context){
getConversationDatasPage = 0
getApp().globalData.uniIm = {"msgManagers":{}}
getApp().globalData.uniIm.msgManagers = {}
await context.commit('clearConversationDatas')
await context.dispatch('loadMoreConversation')
},
......
......@@ -12,7 +12,10 @@ export default {
init(){
setTimeout(()=>{
// 初始化uniIm依赖的全局变量
getApp().globalData.uniIm = {"msgManagers":{}}
getApp().globalData.uniIm = {
"msgManagers":{},
audioContext:uni.createInnerAudioContext()
}
},0)
//监听im消息
......@@ -59,11 +62,23 @@ export default {
listenImMsg(){
uni.onPushMessage(async res => {
const {currentConversationId} = $store.state.uniIm
// console.log('收到消息 onPushMessage===================',res.type, res.data,currentConversationId );
console.log('收到消息 onPushMessage===================',res.type, res.data,currentConversationId );
const {payload} = res.data
if (payload.type == 'im') {
const msg = payload.data
// console.log({msg});
const {msg_id} = payload
if(msg_id){
const db = uniCloud.database();
let res = await db.collection('uni-im-msg').doc(msg_id).get()
console.error(res);
if(res.result.code == 0){
payload.data.body = res.result.data[0].body
}
}
if(res.type =='receive'){
// console.log(777);
const {conversation_id} = msg
......
/*!
Theme: Default
Description: Original highlight.js style
Author: (c) Ivan Sagalaev <maniac@softwaremaniacs.org>
Maintainer: @highlightjs/core-team
Website: https://highlightjs.org/
License: see project LICENSE
Touched: 2021
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{background:#f3f3f3;color:#444}.hljs-comment{color:#697070}.hljs-punctuation,.hljs-tag{color:#444a}.hljs-tag .hljs-attr,.hljs-tag .hljs-name{color:#444}.hljs-attribute,.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-name,.hljs-selector-tag{font-weight:700}.hljs-deletion,.hljs-number,.hljs-quote,.hljs-selector-class,.hljs-selector-id,.hljs-string,.hljs-template-tag,.hljs-type{color:#800}.hljs-section,.hljs-title{color:#800;font-weight:700}.hljs-link,.hljs-operator,.hljs-regexp,.hljs-selector-attr,.hljs-selector-pseudo,.hljs-symbol,.hljs-template-variable,.hljs-variable{color:#ab5656}.hljs-literal{color:#695}.hljs-addition,.hljs-built_in,.hljs-bullet,.hljs-code{color:#397300}.hljs-meta{color:#1f7199}.hljs-meta .hljs-string{color:#38a}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}
\ No newline at end of file
{
"name": "uni-im-code-view",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "uni-im-code-view",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"highlight.js": "^11.7.0"
}
},
"node_modules/highlight.js": {
"version": "11.7.0",
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.7.0.tgz",
"integrity": "sha512-1rRqesRFhMO/PRF+G86evnyJkCgaZFOI+Z6kdj15TA18funfoqJXvgPCLSf0SWq3SRfg1j3HlDs8o4s3EGq1oQ==",
"engines": {
"node": ">=12.0.0"
}
}
},
"dependencies": {
"highlight.js": {
"version": "11.7.0",
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.7.0.tgz",
"integrity": "sha512-1rRqesRFhMO/PRF+G86evnyJkCgaZFOI+Z6kdj15TA18funfoqJXvgPCLSf0SWq3SRfg1j3HlDs8o4s3EGq1oQ=="
}
}
}
{
"name": "uni-im-code-view",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"highlight.js": "^11.7.0"
}
}
<template>
<view class="code-view">
<rich-text :class="{'narrow':showFullBtn}" v-if="nodes.length" space="nbsp" :nodes="nodes" class="text-box"></rich-text>
<view v-if="showFullBtn" class="showFullBtn" @click="showFull">
<text class="tip">- 展开</text>
<uni-im-icons color="#ccc" code="e6a8" size="30" class="icon"></uni-im-icons>
</view>
</view>
</template>
<script>
import hljs from 'highlight.js';
import parseHtml from '@/uni_modules/uni-im/components/uni-im-msg/html-parser.js';
export default {
data() {
return {
htmlString:"",
nodes:[],
}
},
props: {
showFullBtn:{
type:Boolean,
default:true
},
code: {
type: String,
default(){
return `
// demo
if(this.msg.body == this.htmlString){
return 123
}
try{
let nodes = parseHtml(this.htmlString)
nodes.map(item=>{
// console.log('item',item);
if(item.attrs && item.attrs.class){
item.attrs.class += " msg-text"
}else{
item.attrs = {class:"msg-text"}
}
return item
})
return nodes
}catch(e){
//TODO handle the exception
console.error(e);
return ""
}
`
}
},
},
mounted() {
//非全屏模式截取3行
let code = this.code
if(this.showFullBtn && code.split("\n").length > 3){
code = code.split("\n").slice(0,3).join("\n")
}
let res = hljs.highlightAuto(code)
this.htmlString = res.value
// console.log('this.htmlString',JSON.stringify(this.htmlString));
// #ifdef APP-NVUE
// //添加空格
this.htmlString = this.htmlString.replace(/\t/g,'<text class="nbsp">__</text>')
this.htmlString = this.htmlString.replace(/\n/g,'<p>')
this.htmlString = this.htmlString.replace(/&#x27;/g,'\'')
// #endif
// #ifndef APP-NVUE
this.htmlString = `<pre><code>${this.htmlString}</code></pre>`
// #endif
this.nodes = parseHtml(this.htmlString)
// console.log(JSON.stringify(this.nodes));
},
methods:{
showFull(){
uni.navigateTo({
url:'/uni_modules/uni-im/pages/common/uni-im-code-pages/uni-im-code-pages?code=' + encodeURIComponent(this.code),
animationType:'slide-in-bottom',
animationDuration:300
})
}
}
}
</script>
<style lang="scss">
/* #ifndef APP-NVUE */
@import './default.css';
/* #endif */
.text-box{
background-color: #fffae5 !important;
/* background-color: #21231c; */
width: 500rpx;
color: #1e7800;
font-size: 14px;
border-radius: 10px;
}
.code-view{
position: relative;
background-color: #fffae5 !important;
border: solid 10px #fffae5;
/* #ifndef APP-NVUE */
word-break: break-all;
tab-size: 2;
user-select: text;
cursor: text !important;
overflow: auto;
/* #endif */
}
.showFullBtn{
width: 500rpx;
margin-top: 3px;
flex-direction: row;
justify-content: center;
align-items: center;
}
.tip{
color: #ccc;
font-size: 12px;
margin-right: -8px;
}
.nbsp{
color: #fffae5;
width: 2px;
}
.hljs-built_in{
color: #293dc3;
}
.hljs-string{
color: #008b7e;
}
.hljs-name,
.hljs-title {
color: #f0c674
}
.hljs-comment,
.hljs-meta{
color: #9aabab;
}
.hljs-deletion,
.hljs-link,
.hljs-literal,
.hljs-number,
.hljs-symbol {
color: #c66
}
.hljs-addition,
.hljs-doctag,
.hljs-regexp,
.hljs-selector-attr,
.hljs-selector-pseudo,
.hljs-string {
color: #b5bd68
}
.hljs-attribute,
.hljs-code,
.hljs-selector-id {
color: #b294bb
}
.hljs-bullet,
.hljs-keyword,
.hljs-selector-tag,
.hljs-tag {
color: #81a2be
}
.hljs-subst,
.hljs-template-tag,
.hljs-template-variable,
.hljs-variable {
color: #8abeb7
}
.hljs-built_in,
.hljs-quote,
.hljs-section,
.hljs-selector-class,
.hljs-type {
color: #de935f
}
.hljs-emphasis {
font-style: italic
}
.hljs-strong {
font-weight: 700
}
.hljs-keyword{
color: #8ba400;
}
.narrow{
// height: 15px;
/* #ifndef APP-NVUE */
overflow: hidden;
/* #endif */
}
</style>
<template>
<view>
<text :style="{ color: color, 'font-size': iconSize }" @click="_onClick" class="uni-im-icons">{{unicode}}</text>
</view>
</template>
<script>
const getVal = (val) => {
const reg = /^[0-9]*$/g
return (typeof val === 'number' || reg.test(val) )? val + 'px' : val;
}
// #ifdef APP-NVUE
// import iconUrl from './uni-im-icons.ttf'
const domModule = uni.requireNativePlugin('dom')
domModule.addRule('fontFace', {
'fontFamily': "uni-im-icons",
// 'src': "url('"+iconUrl+"')"
'src': "url('https://at.alicdn.com/t/c/font_3726059_ve7fv3q2ya.ttf?t=1670230205644')"
});
// #endif
export default {
emits:['click'],
data() {
return {
}
},
props: {
code: {
type: String,
default(){
return ''
}
},
color: {
type: String,
default: '#333333'
},
size: {
type: [Number, String],
default: 16
},
},
computed:{
unicode(){
return unescape(`%u${this.code}`)
},
iconSize(){
return getVal(this.size)
}
},
methods:{
_onClick(e) {
this.$emit('click',e)
}
}
}
</script>
<style>
@font-face {
font-family: "uni-im-icons"; /* Project id 3726059 */
src: url('https://at.alicdn.com/t/c/font_3726059_ve7fv3q2ya.ttf?t=1670230205644') format('truetype');
}
.uni-im-icons {
font-family: uni-im-icons !important;
font-size: 16px;
font-style: normal;
}
/* #ifndef APP-NVUE */
.uni-im-share:before {
content: "\e6c4";
}
.uni-im-copy:before {
content: "\e67e";
}
.uni-im-delete:before {
content: "\e63d";
}
/* #endif */
</style>
......@@ -6,12 +6,19 @@
<view class="msg-content" @longpress.prevent="showControl" ref="msg-content">
<uni-icons @click="retries" :color="msg.state===0?'#999':'#d22'" :type="msgStateIcon" class="msgStateIcon">
</uni-icons>
<cloud-image width="200rpx" height="200rpx" @click="previewImage(msg.body)" v-if="msg.type == 'image'"
:src="msg.body" mode="aspectFill" />
<view @click="playVoice(msg.body)" v-if="msg.type == 'sound'" class="text selfText">
<uni-icons :type="msgStateIcon" size="25" color="#FFFFFF"></uni-icons>
<cloud-image width="200rpx" height="200rpx" @click="previewImage(msg.body.url||msg.body)" v-if="msg.type == 'image'"
:src="msg.body.url||msg.body" mode="aspectFill" />
<!-- msg.body.url||msg.body 这个写法是为了兼容老版的设计,新版直接 msg.body.url即可-->
<view @click="playSound(msg.body.url)" v-if="msg.type == 'sound'" class="text selfText sound-box"
:style="{width:soundBoxWidth}">
<text class="sound-time">{{msg.body.time}}''</text>
<view class="sound-icon-box" style="width: 18px;height: 18px;">
<image v-if="soundPlayState" src="@/uni_modules/uni-im/static/sound-ing.gif" style="width: 18px;height: 18px;"
mode="widthFix"></image>
<uni-im-icons v-else :class="{'sound-icon-active':soundPlayState}" code="e6f5" size="18px"
color="#000000"></uni-im-icons>
</view>
</view>
<template v-if="msg.type == 'text'">
<!-- #ifdef APP-NVUE -->
<view class="rich-text-box" :class="msgClass">
......@@ -27,21 +34,33 @@
<template v-else>
<template v-for="(item,index) in nodes">
<text :key="index" class="msg-text" v-if="item.type == 'text'">{{ item.text }}</text>
<text :key="index" v-if="item.name == 'a'" @click="clickLink(item.attrs.href)" class="link msg-text">{{item.attrs.href}}</text>
<text :key="index" v-if="item.name == 'a'" @click="clickLink(item.attrs.href)"
class="link msg-text">{{item.attrs.href}}</text>
</template>
</template>
</view>
<!-- #endif -->
</template>
<!-- <uni-link href="https://ext.dcloud.net.cn/" text="https://ext.dcloud.net.cn/"></uni-link> -->
<template v-if="msg.type == 'video'">
<img @click="playVideo" :src="msg.body+'?x-oss-process=video/snapshot,t_1000,f_jpg,w_200,h_200,m_fast'">
<uni-icons type="paly"></uni-icons>
<template v-if="msg.type == 'code'">
<uni-im-code-view :code="msg.body"></uni-im-code-view>
</template>
<!-- <uni-link href="https://ext.dcloud.net.cn/" text="https://ext.dcloud.net.cn/"></uni-link> -->
<view @click="playVideo" class="video-box" v-if="msg.type == 'video'">
<image class="video-img" mode="aspectFill"
:src="videoUrl+'?x-oss-process=video/snapshot,t_1000,f_jpg,w_200,m_fast'"></image>
<view class="video-box-mark"></view>
<uni-im-icons code="e650" size="35" color="#FFF" class="play-video-icon"></uni-im-icons>
</view>
<template v-if="msg.type == 'file'">
<uni-icons size="50" color="#aaa" type="paperclip"></uni-icons>
<view class="file-msg-box" @click="downLoadFile">
<view class="file-msg-info">
<text class="file-msg-info-name">{{fileName}}</text>
<text class="file-msg-info-size">{{fileSize}}</text>
</view>
<uni-im-icons code="e858" size="50" color="#EEEEEE" class="file-icon"></uni-im-icons>
</view>
</template>
</view>
</view>
......@@ -51,46 +70,54 @@
import {
store as uniIdStore,
} from '@/uni_modules/uni-id-pages/common/store'
import parseHtml from './html-parser.js';
import parseHtml from './html-parser.js';
let audioContext
setTimeout(()=> {
audioContext = getApp().globalData.uniIm.audioContext
}, 0);
export default {
data() {
return {
username: "用户名"
username: "用户名",
videoUrl: '',
soundPlayState: 0
};
},
mounted() {
if(this.msg.type == 'video'){
this.videoUrl = this.msg.body.url
// return
// uniCloud.getTempFileURL({
// fileList: [this.msg.body]
// }).then(res => {
// console.log(999999, res);
// // 兼容uniCloud私有化部署
// let fileList = res.fileList || res.result.fileList
// this.videoUrl = fileList[0].tempFileURL
// console.log('this.videoUrl', this.videoUrl);
// }).catch(e => {
// this.videoUrl = this.msg.body
// })
}else if(this.msg.type == 'sound'){
audioContext.onPlay(() => {
// console.log('soundPlayStart------------------');
let src = getApp().globalData.uniIm.audioContext.src
if(src == this.msg.body.url){
this.soundPlayState = 1
}
});
let soundPlayEnd = () => {
// console.log('soundPlayEnd------------------');
this.soundPlayState = 0
}
audioContext.onPause(soundPlayEnd);
audioContext.onStop(soundPlayEnd);
audioContext.onEnded(soundPlayEnd);
audioContext.onError(soundPlayEnd);
}
mounted() {
if(this.msg.type == 'video'){
this.videoUrl = this.msg.body.url
// return
// uniCloud.getTempFileURL({
// fileList: [this.msg.body]
// }).then(res => {
// console.log(999999, res);
// // 兼容uniCloud私有化部署
// let fileList = res.fileList || res.result.fileList
// this.videoUrl = fileList[0].tempFileURL
// console.log('this.videoUrl', this.videoUrl);
// }).catch(e => {
// this.videoUrl = this.msg.body
// })
}else if(this.msg.type == 'sound'){
audioContext.onPlay(() => {
// console.log('soundPlayStart------------------');
let src = getApp().globalData.uniIm.audioContext.src
if(src == this.msg.body.url){
this.soundPlayState = 1
}
});
let soundPlayEnd = () => {
// console.log('soundPlayEnd------------------');
this.soundPlayState = 0
}
audioContext.onPause(soundPlayEnd);
audioContext.onStop(soundPlayEnd);
audioContext.onEnded(soundPlayEnd);
audioContext.onError(soundPlayEnd);
}
},
props: {
msg: {
......@@ -144,10 +171,13 @@
},
msgClass() {
var msgClass = ''
let textLength = this.msg.body.replace(/[\u0000-\u007f]/g, "a").replace(/[\u0080-\u07ff]/g, "aa").replace(
/[\u0800-\uffff]/g, "aa").length
if (textLength > 30) {
msgClass += ' exceed'
if (this.msg.type == 'text') {
let textLength = this.msg.body.replace(/[\u0000-\u007f]/g, "a").replace(/[\u0080-\u07ff]/g, "aa")
.replace(
/[\u0800-\uffff]/g, "aa").length
if (textLength > 30) {
msgClass += ' exceed'
}
}
if (this.self) {
msgClass += ' self-text-box'
......@@ -162,61 +192,96 @@
return this.avatar_file?.url
}
},
soundBoxWidth() {
return uni.upx2px(750 / 60 * this.msg.body.time) + 50 + 'px'
},
htmlString() {
let content = this.msg.body//.replace(/</g, "< ");
if(/</g.test(content)){
if (this.msg.type != 'text') {
return "";
}
let content = this.msg.body //.replace(/</g, "< ");
if (/</g.test(content)) {
return content
}
if (!content) {
return "";
}
// 找网址
let urlPattern = /(https?:\/\/|www\.)[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]/g;
content = content.replace(urlPattern, function(match) {
var href = match;
if (match.indexOf("http") == -1) {
//如果不带http://开头就带上
href = "http://" + match;
}
return '<a class="link" target="_blank" href="' + href + '">' + match + "</a> ";
});
/*
// 手机号正则
const regPhone = /(13[0-9]|14[5-9]|15[012356789]|166|17[0-8]|18[0-9]|19[8-9])[0-9]{8}/g;
content = content.replace(regPhone, " <a href='tel:$&'>$&</a>")
// 固定电话正则
const regTel = /(([0\+]\d{2,3}-)?(0\d{2,3})-)(\d{7,8})(-(\d{3,}))?/g;
content = content.replace(regTel, " <a href='tel:$&'>$&</a>")
// 邮箱正则
const regMail = /([a-z0-9._-]+@[a-z0-9.-]+\.[a-z]{2,4})/ig;
content = content.replace(regMail, " <a href='mailto:$&'>$&</a>")
*/
return content
}
// 找网址
let urlPattern = /(https?:\/\/|www\.)[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]/g;
content = content.replace(urlPattern, function(match) {
var href = match;
if (match.indexOf("http") == -1) {
//如果不带http://开头就带上
href = "http://" + match;
}
return '<a class="link" target="_blank" href="' + href + '">' + match + "</a> ";
});
/*
// 手机号正则
const regPhone = /(13[0-9]|14[5-9]|15[012356789]|166|17[0-8]|18[0-9]|19[8-9])[0-9]{8}/g;
content = content.replace(regPhone, " <a href='tel:$&'>$&</a>")
// 固定电话正则
const regTel = /(([0\+]\d{2,3}-)?(0\d{2,3})-)(\d{7,8})(-(\d{3,}))?/g;
content = content.replace(regTel, " <a href='tel:$&'>$&</a>")
// 邮箱正则
const regMail = /([a-z0-9._-]+@[a-z0-9.-]+\.[a-z]{2,4})/ig;
content = content.replace(regMail, " <a href='mailto:$&'>$&</a>")
*/
return content
},
nodes() {
if(this.msg.body == this.htmlString){
return
if (this.msg.body == this.htmlString) {
return
}
try{
let nodes = parseHtml(this.htmlString)
try {
let nodes = parseHtml(this.htmlString)
// console.log('nodes',nodes);
nodes.map(item=>{
nodes.map(item => {
// console.log('item',item);
if(item.attrs&&item.attrs.class){
if (item.attrs && item.attrs.class) {
item.attrs.class += " msg-text"
}else{
item.attrs = {class:"msg-text"}
} else {
item.attrs = {
class: "msg-text"
}
}
return item
})
return nodes
}catch(e){
console.error('htmlString error:',e);
} catch (e) {
console.error('htmlString error:', e);
return ''
//TODO handle the exception
}
},
fileSize() {
if (this.msg.type == 'file') {
let size = this.msg.body.size
if(size < Math.pow(1024,1) ){
return parseInt(size * 10)/10 + 'B'
}else if(size < Math.pow(1024,2) ){
return parseInt(size/Math.pow(1024,1) * 10) / 10 + 'KB'
}else if(size < Math.pow(1024,3) ){
return parseInt(size/Math.pow(1024,2) * 10) / 10 + 'MB'
}else {
return 'err'
}
}
},
fileName(){
if (this.msg.type == 'file') {
let name = this.msg.body.name
if(name.length < 30){
return name
}else{
return name.slice(0,15) + '...'+name.slice(-15)
}
}
}
},
methods: {
......@@ -237,21 +302,22 @@
});
// #endif
},
playSound(url) {
// console.log("playSound", url);
audioContext.src = url;
// console.log(78998797,audioContext);
if(this.soundPlayState === 1){
// console.log('播放中,执行关闭');
audioContext.stop()
}else{
audioContext.stop()
audioContext.play();
}
playSound(url) {
// console.log("playSound", url);
audioContext.src = url;
// console.log(78998797,audioContext);
if(this.soundPlayState === 1){
// console.log('播放中,执行关闭');
audioContext.stop()
}else{
audioContext.stop()
audioContext.play();
}
},
previewImage(url) {
uni.showLoading();
if (url.includes('://') && !url.includes('https://img-cdn-tc.dcloud.net.cn/uploads/avatar')&& !url.includes('https://ask.dcloud.net.cn/uploads/avatar')) {
if (url.includes('://') && !url.includes('https://img-cdn-tc.dcloud.net.cn/uploads/avatar') && !url
.includes('https://ask.dcloud.net.cn/uploads/avatar')) {
uniCloud.getTempFileURL({
fileList: [url]
}).then(res => {
......@@ -275,7 +341,9 @@
},
playVideo() {
uni.navigateTo({
url: "/pages/common/webview/webview?url=" + this.msg.body
url: "/uni_modules/uni-im/pages/common/video/video?url=" + this.videoUrl,
animationDuration: 300,
animationType: "fade-in"
})
},
async showControl() {
......@@ -333,34 +401,33 @@
// }
this.$emit('retries', this.msg)
},
downLoadFile() {
// #ifdef H5
return window.open(this.msg.body.url)
// #endif
downLoadFile() {
// #ifdef H5
return window.open(this.msg.body.url)
// #endif
// #ifndef H5
uni.downloadFile({
url: this.msg.body.url,
success: (res) => {
if (res.statusCode === 200) {
// console.log('下载成功');
// console.log(res.tempFilePath);
uni.saveFile({
tempFilePath: res.tempFilePath,
success: (res)=> {
// console.log('res',res);
uni.openDocument({filePath:res.savedFilePath})
}
});
}
}
});
// #ifndef H5
uni.downloadFile({
url: this.msg.body.url,
success: (res) => {
if (res.statusCode === 200) {
// console.log('下载成功');
// console.log(res.tempFilePath);
uni.saveFile({
tempFilePath: res.tempFilePath,
success: (res)=> {
// console.log('res',res);
uni.openDocument({filePath:res.savedFilePath})
}
});
}
}
});
// #endif
}
}
}
</script>
<style lang="scss">
/* #ifndef APP-NVUE */
view {
......@@ -388,6 +455,7 @@
.msg-box * {
cursor: default;
}
/* #endif */
.msg-content {
......@@ -401,8 +469,8 @@
color: #666666;
margin: 8rpx 0;
}
.text-box{
.text-box {
/* #ifndef APP-NVUE */
display: block;
/* #endif */
......@@ -414,14 +482,18 @@
justify-content: flex-start;
line-height: 20px;
}
.rich-text-box{
.rich-text-box {
padding: 18rpx;
border-radius: 5px;
background-color: #FFFFFF;
}
.rich-text{
.rich-text {
background-color: transparent;
width: 500rpx;
}
.msg-text {
font-size: 16px;
justify-content: space-between;
......@@ -431,10 +503,13 @@
cursor: text;
/* #endif */
}
.link{
.link {
// font-size: 16px;
color: #007fff;
/* #ifdef H5 */
cursor: pointer;
/* #endif */
}
.self-text-box {
......@@ -456,4 +531,83 @@
.msgStateIcon {
margin-right: 10rpx;
}
</style>
.video-box {
width: 200rpx;
height: 200rpx;
position: relative;
}
.video-img {
width: 200rpx;
height: 200rpx;
}
.play-video-icon {
position: absolute;
width: 60rpx;
height: 60rpx;
top: 70rpx;
left: 70rpx;
}
.video-box-mark {
position: absolute;
top: 0;
left: 0;
background-color: rgba(0, 0, 0, 0.1);
}
.sound-box {
flex-direction: row;
background-color: #94EB6A;
height: 44px;
padding: 10px;
width: 66px;
border-radius: 5px;
justify-content: flex-end;
align-items: center;
}
.sound-time {
font-size: 14px;
margin-right: 2px;
}
.sound-icon-active {
transform: option;
opacity: 10;
background-color: #007AFF;
transition-property: background-color;
transition-duration: 0.3s;
transition-delay: 0.1s;
transition-timing-function: cubic-bezier(0.25, 0.1, 0.25, 1.0);
}
.file-msg-box {
background-color: #FFFFFF;
width: 500rpx;
padding: 20rpx;
border-radius: 8px;
flex-direction: row;
justify-content: space-between;
}
.file-msg-info {
width: 300rpx;
flex-direction: column;
justify-content: space-around;
}
.file-msg-info-name {
/* #ifndef APP-NVUE */
word-wrap: break-word;
/* #endif */
font-size: 16px;
}
.file-msg-info-size {
font-size: 12px;
color: #666;
}
</style>
<template>
<view>
<view :style="{'height':soundState?'':0}" class="mark"></view>
<view @touchmove="touchmove" @touchstart="soundStart" @touchend="soundEnd" @touchcancel="soundEnd"
class="sound-buttom" :class="{soundState}">
<view v-if="soundProgress" class="sound-progress" :style="{'width':soundProgress}"></view>
<text class="sound-text">{{soundState?'录音中('+time+'s)':'按住 说话'}}</text>
<view class="sound-tip" v-if="soundState">
<text class="sound-tip-text" :style="{color:cancel?'#f70000':'#FFFFFF'}">{{cancel?'松手取消':'松手发送,上划取消'}}</text>
<view class="closeIcon" :style="{'backgroundColor':cancel?'#f70000':'EEEEEE'}">
<uni-im-icons code="e61a" size="10px" color="#FFFFFF"></uni-im-icons>
</view>
</view>
</view>
</view>
</template>
<script>
// #ifndef H5
const recorderManager = uni.getRecorderManager();
// #endif
const innerAudioContext = uni.createInnerAudioContext();
innerAudioContext.autoplay = true;
let soundInterval,soundPath,startTime;
const windowInfo = uni.getWindowInfo()
export default {
emits: ['success'],
data() {
return {
soundState:0,
soundProgress:0,
cancel:false,
time:0
}
},
computed:{
},
created() {
// #ifndef H5
recorderManager.onStop((res)=> {
console.log('recorderManager.onStop',{res});
if(!this.cancel){
if(this.time < 2){
return uni.showToast({
title: '语音时间过短',
icon: 'none'
});
}
uni.showLoading({
title: '上传中',
mask: false
});
uniCloud.uploadFile({
filePath:res.tempFilePath,
cloudPath:'uni-im/' + uniCloud.getCurrentUserInfo().uid + '/sound/' + Date.now(),
success: (e) => {
console.log('uniCloud.uploadFile-success',e,'success',{"url":e.fileID,time:this.time});
try{
this.$emit('success',{"url":e.fileID,time:this.time})
}catch(e){
console.log(e);
//TODO handle the exception
}
uni.hideLoading()
},
fail: (e) =>{
console.log(e);
uni.showModal({
content: JSON.stringify(e),
showCancel: false,
confirmText: '知道了'
});
},
complete: (e) =>{
console.log('complete',e);
uni.hideLoading()
}
})
}else{
console.log('用户取消了录音功能','this.time:'+this.time);
}
});
// #endif
},
methods: {
touchmove(e){
let y = (e.touches[0].screenY - windowInfo.screenTop) || e.touches[0].clientY
if(windowInfo.windowHeight - y > 50){
this.cancel = true
}else{
this.cancel = false
}
},
soundStart(e){
// 关闭正在播放的sound
getApp().globalData.uniIm.audioContext.stop()
// #ifdef H5
// 防止H5端 调试出现鼠标右键菜单
window.oncontextmenu = function () { return false; }
// #endif
// #ifdef H5
return uni.showToast({
title: 'h5端不支持语音功能',
icon: 'none'
});
// #endif
recorderManager.start({
sampleRate:16000,
numberOfChannels:2,
format:"mp3"
});
startTime = Date.now()
// console.log('soundStart');
//进度条
this.soundState = 1
soundInterval = setInterval(()=>{
this.soundProgress = parseInt(this.soundProgress) + uni.upx2px(450/60) +'px'
// console.log('this.soundProgress',this.soundProgress);
this.time = parseInt((Date.now() - startTime) / 1000)
},1000)
// e.preventDefault();
},
soundEnd(){
// #ifdef H5
return
// #endif
recorderManager.stop();
// console.log('soundEnd');
clearInterval(soundInterval)
setTimeout(()=> {
this.soundState = 0
this.soundProgress = 0
this.cancel = false
}, 300);
}
}
}
</script>
<style lang="scss">
.sound-buttom {
background-color: #ffffff;
padding: 10px;
width: 450rpx;
height: 46px;
// border-radius: 10px;
font-size: 16px;
align-items: flex-start;
justify-content: center;
/* #ifndef APP-NVUE */
overflow:hidden;
/* #endif */
}
.sound-text{
position: relative;
left: -20rpx;
width: 450rpx;
font-size: 14px;
text-align: center;
}
.sound-tip{
position: fixed;
left: 0;
bottom: 80px;
width: 750rpx;
text-align: center;
justify-content: center;
align-items: center;
}
.sound-tip-text{
margin-bottom: 10px;
color: #999999;
font-size: 14px;
}
.closeIcon{
width: 30px;
height: 30px;
background-color: #DDDDDD;
border-radius: 100px;
justify-content: center;
align-items: center;
}
.sound-progress {
// border-radius: 10px;
height: 44px;
position: absolute;
left: 0;
top: 0;
padding: 0;
transition: width 0.2s linear;
background-color: #2faf4c;
opacity: 0.3;
}
.soundState{
background-color: #efefef;
}
.mark{
width: 750rpx;
position: fixed;
top: 0;
left: 0;
bottom: 57px;
right: 0;
background:rgba(0,0,0,0.7);
flex: 1;
}
</style>
{
"id": "uni-im",
"displayName": "uni-im",
"version": "1.3.0",
"version": "1.3.2",
"description": "uni-im是云端一体的、全平台的、免费的、开源即时通讯系统",
"keywords": [
"uni-im,即时通讯,客服,聊天"
"im,即时通讯,客服,聊天"
],
"repository": "https://gitcode.net/dcloud/hello-uni-im",
"engines": {
......
<template>
<view class="code-view" :class="{isRotate}">
<uni-im-code-view :code="code" :showFullBtn="false"></uni-im-code-view>
<!-- <uni-im-icons id="rotate" @click="rotate" code="e664"></uni-im-icons> -->
</view>
</template>
<script>
export default {
data() {
return {
code:"",
isRotate:false
}
},
onLoad({
code
}) {
this.code = decodeURIComponent(code)
},
methods:{
rotate(){
this.isRotate = !this.isRotate
}
}
}
</script>
<style lang="scss">
.text-box,
.code-view {
background-color: #fffae5 !important;
flex: 1;
width: 750rpx;
/* #ifndef APP-NVUE */
width: 100vw;
/* #endif */
height: 100vh;
}
#rotate{
position: fixed;
right: 10px;
top: 60px;
z-index: 999;
}
.isRotate{}
</style>
<template>
<view class="video-box">
<video @click="showCloseBtnFn" v-if="url" :src="url" :autoplay="true" :page-gesture="true" :show-fullscreen-btn="false" class="video"></video>
<uni-icons v-if="showCloseBtn" @click="close" size="30px" color="#FFFFFF" type="closeempty" class="close-icon"></uni-icons>
</view>
</template>
<script>
export default {
data() {
return {
url:"",
showCloseBtn:true
};
},
onLoad({url}) {
// console.log({url});
this.url = url
setTimeout(()=> {
this.showCloseBtn = false
}, 1000);
},
methods:{
close(){
uni.navigateBack()
},
showCloseBtnFn(){
// console.log('showCloseBtnFn');
this.showCloseBtn = true
setTimeout(()=> {
this.showCloseBtn = false
}, 5000);
}
}
}
</script>
<style lang="scss">
.video-box,.video{
width: 750rpx;
/* #ifndef APP-NVUE */
height: 100vh;
/* #endif */
flex: 1;
}
.close-icon{
position: fixed;
top: 80rpx;
left: 30rpx;
}
</style>
......@@ -126,7 +126,7 @@
wHeight: 'auto',
isWidescreen: false,
userInfo: {},
scrollTop: 0
scrollTop: 0
};
},
async onShow() {
......@@ -151,8 +151,11 @@
// #ifdef H5
uni.$on('uni-im-showLast', e => {
// console.log('uni-im-showLast');
this.scrollTop = document.querySelector('#chat-view .uni-scroll-view-content').scrollHeight
// console.log('uni-im-showLast');
let dom = document.querySelector('#chat-view .uni-scroll-view-content')
if(dom){
this.scrollTop = dom.scrollHeight
}
})
// #endif
},
......@@ -163,7 +166,7 @@
conversation_id
}) {
// 发布新版本后,清理旧版本下的storage避免脏数据引发问题
let version = '2022.11.23.01'
let version = '2022.12.01.01'
if (uni.getStorageSync('uni-im-storage-version') != version) {
let data = uni.getStorageInfoSync();
// console.log('data.keys', JSON.stringify(data.keys));
......@@ -171,7 +174,6 @@
if (item.includes('uni-im-msg:') || item.includes('uni-im-conversation')) {
// console.log(item);
uni.removeStorageSync(item);
console.log(uni.getStorageSync(item));
}
});
uni.setStorageSync('uni-im-storage-version',version)
......@@ -192,28 +194,31 @@
let res = await uniImCo.login(token)
await uniIdMutations.updateUserInfo()
} else {
if (!uniCloud.getCurrentUserInfo().uid) {
if (!uniCloud.getCurrentUserInfo().uid) {
return uni.redirectTo({
url: '/uni_modules/uni-id-pages/pages/login/login-withpwd'
})
}
}
this.init({
user_id,
goods,
conversation_id
})
uni.$on('uni-id-pages-login-success', async () => {
this.init({
user_id,
goods,
conversation_id
})
})
},
onUnload() {
uni.$off('uni-id-pages-login-success')
}
}
this.$nextTick(()=>{
this.init({
user_id,
goods,
conversation_id
})
})
uni.$on('uni-id-pages-login-success', async () => {
this.init({
user_id,
goods,
conversation_id
})
})
},
onUnload() {
uni.$off('uni-id-pages-login-success')
},
onHide() {},
methods: {
......@@ -232,8 +237,9 @@
conversation_id,
user_id,
goods
}) {
}) {
// 初始化会话列表
// console.log('初始化会话列表');
await this.initConversationData()
if (conversation_id) {
console.log('conversation_id', conversation_id);
......@@ -274,7 +280,7 @@
if (name && url) {
this.$refs['chat-view'].chatText = '【' + name + ':' + url + '】'
}
}
}
},
search(e) {
// console.log("search-e: " + JSON.stringify(e));
......@@ -310,9 +316,9 @@
// console.log('toChat',{conversation_id,'isWidescreen':this.isWidescreen});
this.setCurrentConversationId(conversation_id);
if (this.isWidescreen) { //若为宽屏,则触发右侧详情页的自定义事件,通知右侧窗体刷新详情
if(this.$refs['chat-view']){
this.$refs['chat-view'].load(conversation_id)
}
if(this.$refs['chat-view']){
this.$refs['chat-view'].load(conversation_id)
}
} else { // 若为窄屏,则打开新窗体,在新窗体打开详情页面
uni.navigateTo({
url: '/uni_modules/uni-im/pages/chat/chat?conversation_id=' + conversation_id,
......@@ -345,17 +351,36 @@
return
}
const oldClassName = 'uni-body uni_modules-uni-im-pages-index-index'
if (this.isWidescreen) {
conversationDom.querySelector('uni-page-body').style.background = 'none'
conversationDom.querySelector('.uni-page-head').style.display = 'none'
conversationDom.querySelector('.uni-placeholder').style.display = 'none'
conversationDom.querySelector('uni-page').style.transform = 'scale(0.86) translateY(-30px)';
const oldClassName = 'uni-body uni_modules-uni-im-pages-index-index'
let uniPageBodyDom = conversationDom.querySelector('uni-page-body'),
uniPageHeadDom = conversationDom.querySelector('.uni-page-head'),
uniPlaceholderDom = conversationDom.querySelector('.uni-placeholder'),
uniPageDom = conversationDom.querySelector('uni-page')
if (this.isWidescreen) {
if(uniPageBodyDom){
uniPageBodyDom.style.background = 'none'
}
if(uniPageHeadDom){
uniPageHeadDom.style.display = 'none'
}
if(uniPlaceholderDom){
uniPlaceholderDom.style.display = 'none'
}
if(uniPageDom){
uniPageDom.style.transform = 'scale(0.86) translateY(-30px)';
}
conversationDom.className = oldClassName + ' uni-im-dark'
} else {
conversationDom.querySelector('.uni-page-head').style.display = 'block'
conversationDom.querySelector('.uni-placeholder').style.display = 'block'
conversationDom.querySelector('uni-page').style.transform = 'scale(1)';
} else {
if(uniPageHeadDom){
uniPageHeadDom.style.display = 'block'
}
if(uniPlaceholderDom){
uniPlaceholderDom.style.display = 'block'
}
if(uniPageDom){
uniPageDom.style.transform = 'scale(1)';
}
conversationDom.className = oldClassName
}
// #endif
......@@ -394,6 +419,9 @@
<style lang="scss" scoped>
/* #ifndef APP-NVUE */
#page {
justify-content: center;
}
#page,
view {
display: flex;
......@@ -410,7 +438,9 @@
/* #ifdef H5 */
#conversation {
flex: 1;
/* #ifdef VUE2 */
flex: 1;
/* #endif */
// background-color: #f6f6f6;
border-right: solid 1px #dededd;
}
......@@ -527,7 +557,7 @@
font-size: 10px;
}
#chat-view ::v-deep .input-box {
#chat-view ::v-deep .chat-foot {
border-radius: 0 0 10px 0;
}
......
......@@ -110,7 +110,17 @@ module.exports = {
last_msg_note = body.toString()
last_msg_note = last_msg_note.replace(/[\r\n]/g, "");
last_msg_note = last_msg_note.slice(0, 30)
}
}
let typeObj = {
"image":"[图片]",
"sound":"语音",
"video":"[视频]",
"file":"文件",
"location":"位置"
}
last_msg_note = typeObj[type]
//发送者身份id
const from_uid = res.uid
let admin_uid = uniImConfig.config('admin_uid')
......@@ -197,35 +207,42 @@ module.exports = {
console.log({
...msgData,
conversation_id
});
});
let msg_id = false;
if(!isRetries){
res = await msgTable.add({
...msgData,
conversation_id
})
})
if(msgData.body.length > 250){
msgData.body = msgData.body.slice(0,50)
msg_id = res.id
}
console.log('msgTable msgData:', res);
}
res = await db.collection('uni-id-users').doc(from_uid)
.field({
'username': true ,
'_id': true ,
'nickname': true ,
'nickname': true,
'avatar_file': true
}).get()
let {username,nickname,avatar_file} = res.data[0]
let title = username||nickname
let content = msgData.body
let param = {
let title = (username||nickname).slice(0,20)
let content = msgData.type == 'text' ? msgData.body : '[多媒体]'
console.log(content);
let param = {
"user_id": msgData.to_uid,
"payload": {
"type": "im",
"data":msgData,
title,// "收到im消息,在线时显示的标题",
content,// "在线时显示的副标题",
avatar_file//头像文件对象
avatar_file,//头像文件对象
msg_id
},
title,// "收到im消息,离线时显示的标题",
content,//"离线时显示的内容"
title:title.slice(0,20),// "收到im消息,离线时显示的标题",
content:content.slice(0,50),//"离线时显示的内容"
settings:{
//-1表示不设离线,因为离线后重新打开数据统一从数据库中拉取。否则会重复
ttl:-1
......@@ -233,7 +250,8 @@ module.exports = {
channel:{
"HW":"NORMAL"
}
}
}
console.log({param});
if (msgData.to_uid) {
//单聊
param.user_id = msgData.to_uid
......
// 本文件中的内容将在云对象【运行】时解析为运行参数
// 配置教程参考:https://uniapp.dcloud.net.cn/uniCloud/rundebug.html#run-obj-param
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册